diff --git a/changelog.json b/changelog.json
index 7b6b937..1a7a940 100644
--- a/changelog.json
+++ b/changelog.json
@@ -9,6 +9,7 @@
" - Bazaar",
" - Composter",
"- Added dungeon chest profit",
+ "- Added max supercraft",
"- Changed rabbit highlight to be selectable",
"- Changed chocolate factory to support 2.0",
"- Changed storage preview to be hoverable",
@@ -17,8 +18,9 @@
"- Fixed enchanted book calc",
"- Fixed lore rendering",
"- Fixed lore 'ed' spam",
+ "- Fixed egg reset",
"- Removed image viewer",
- "= Removed Gurokinetic features",
+ "= Removed Gyrokinetic features",
"- Removed Jacob highlight",
"- Removed Primal Fear highlight",
"- Removed Vanquisher sounds",
diff --git a/docs/_posts/2024-05-24-v2_9_9.md b/docs/_posts/2024-05-24-v2_9_9.md
new file mode 100644
index 0000000..81bb06c
--- /dev/null
+++ b/docs/_posts/2024-05-24-v2_9_9.md
@@ -0,0 +1,46 @@
+---
+layout: post
+title: v2.9.9 `
+gh-repo: zhenga8533/VolcAddons
+gh-badge: [star, fork, follow]
+tags: [release]
+comments: true
+author: Volcaronitee
+---
+
+## [Changelog](https://github.com/zhenga8533/VolcAddons/releases/tag/v2.9.9) (download by clicking [here](https://github.com/zhenga8533/VolcAddons/releases/download/v2.9.9/VolcAddons.zip))
+
+{: .box-note}
+#### New Features
+- Added global toggle
+- Added socket toggle
+- Added additional mining event checks
+- Added `/va [npc, zone]` scraped info
+- Added `/va preview`
+- Added more container value calcs
+ - Auction
+ - Bazaar
+ - Composter
+- Added dungeon chest profit
+- Added max supercraft
+
+{: .box-warning}
+#### Changes/Fixes
+- Changed rabbit highlight to be selectable
+- Changed chocolate factory to support 2.0
+- Changed storage preview to be hoverable
+- Changed chest tracker to hide opened
+- Fixed socket reconnections
+- Fixed enchanted book calc
+- Fixed lore rendering
+- Fixed lore 'ed' spam
+- Fixed egg reset
+
+{: .box-error}
+#### Deprecated
+- Removed image viewer
+= Removed Gyrokinetic features
+- Removed Jacob highlight
+- Removed Primal Fear highlight
+- Removed Vanquisher sounds
+- Removed Imepl enlarger
diff --git a/docs/commands.md b/docs/commands.md
index 0c036f6..daf2978 100644
--- a/docs/commands.md
+++ b/docs/commands.md
@@ -24,12 +24,13 @@ subtitle: List of every non-gui related commands.
- `/va whitelist`: Set player party invites to auto join.
- `/va binds`: Set slot bindings and their presets.
- `/va buttons`: Set container buttons and their presets.
+ - `/va preview`: Set storage preview keys.
- **Waypoints**
- `/va cat`: Controls Montezuma Soul Piece waypoints.
- `/va enigma`: Controls Enigma Soul waypoints.
- `/va fairy`: Controls Fairy Soul waypoints.
- - `/va npc`: Creates waypoints to user inputted rift NPCs.
- - `/va zone`: Creates waypoints to user inputted rift locations.
+ - `/va npc`: Creates waypoints to user inputted NPCs.
+ - `/va zone`: Creates waypoints to user inputted locations.
- `/va waypoint`: Creates waypoints to user inputted coordinates.
- **Economy**
- `/va attribute`: Various calculations that deal with attribute values.
diff --git a/docs/features.md b/docs/features.md
index 04d3e6a..b9ae016 100644
--- a/docs/features.md
+++ b/docs/features.md
@@ -27,7 +27,6 @@ subtitle: List of all features and their related commands.
- Autocorrect Commands
- Custom Emotes (`/va emote`)
- Discord Webhook
- - Image Viewer
### Container Features
- **General**
@@ -43,6 +42,7 @@ subtitle: List of all features and their related commands.
- Armor Display (`/moveArmor`)
- Equipment Display (`/moveEq`)
- Jyrre Timer
+ - Max Supercraft
### Party Features
- **General**
@@ -78,9 +78,6 @@ subtitle: List of all features and their related commands.
- Low Health Alert
- Mana Drain Range
- Ragnarok Detection
-- **Gyrokinetic Wand**
- - Cell Alignment Alert
- - Cell Alignment Timer (`/moveGyro`)
- **Slayer**
- Boss Announce
- Boss Highlight
@@ -110,8 +107,6 @@ subtitle: List of all features and their related commands.
- Composter Display (`/moveCompost`)
- Garden Plot Box
- Garden Visitor Display (`/moveVisitors`)
- - Garden Webhook
- - Jacob Reward Highlight
- **Pests**
- Desk Highlight
- Infestation Alert
@@ -129,7 +124,6 @@ subtitle: List of all features and their related commands.
- **Great Spook**
- Math Teacher Solver
- Primal Fear Alert
- - Primal Feat Highlight
- **Inquisitor**
- Inquisitor Detect
- Inquisitor Announce
@@ -155,8 +149,12 @@ subtitle: List of all features and their related commands.
- Vanquisher Detect (`/moveVanq`)
### Dungeons
+- **Chests**
+ - Croesus Highlight
+ - Dungeon Chest Profit
- **Star Detect**
- Star Mob Highlight
+ - Star Custom Color
### Kuudra
- **General**
@@ -180,6 +178,5 @@ subtitle: List of all features and their related commands.
- **Vampire**
- Announce Mania Phase
- Effigy Waypoints
- - Enlarge Impel Message
- Vampire Attack Display (`/moveVamp`)
- Vampire Hitbox
diff --git a/features/combat/BestiaryDisplay.js b/features/combat/BestiaryDisplay.js
index 65fb439..db36905 100644
--- a/features/combat/BestiaryDisplay.js
+++ b/features/combat/BestiaryDisplay.js
@@ -130,9 +130,9 @@ registerWhen(register("step", () => {
while (tablist[index].startsWith("§r ") && !tablist[index].endsWith("§r§3§lInfo§r")) {
let beData = tablist[index++].removeFormatting().trim().split(' ');
let levelData = beData[beData.length - 1];
- if (levelData === "MAX") continue;
-
let name = beData.slice(0, -2).join(' ');
+ if (levelData === "MAX" || name === '') continue;
+
let count = levelData.split('/');
let now = unformatNumber(count[0]);
let next = unformatNumber(count[1]);
diff --git a/features/combat/SlayerDetect.js b/features/combat/SlayerDetect.js
index 67218e0..bba5b47 100644
--- a/features/combat/SlayerDetect.js
+++ b/features/combat/SlayerDetect.js
@@ -161,7 +161,7 @@ registerWhen(register("step", () => {
// Check mobs
World.getAllEntitiesOfType(mobClass).forEach(mob => {
const hp = mob.getEntity().func_110148_a(SMA.field_111267_a).func_111125_b();
- if (bossHP == hp) bossWaypoints.push([RED + "Boss", mob]);
- else if (miniSet.has(hp)) miniWaypoints.push([RED + "Mini", mob]);
+ if (bossHP == hp && Settings.bossHighlight) bossWaypoints.push([RED + "Boss", mob]);
+ else if (miniSet.has(hp) && Settings.miniHighlight) miniWaypoints.push([RED + "Mini", mob]);
});
}).setFps(2), () => Settings.bossHighlight || Settings.miniHighlight);
diff --git a/features/container/MaxCraft.js b/features/container/MaxCraft.js
new file mode 100644
index 0000000..f8c3cfc
--- /dev/null
+++ b/features/container/MaxCraft.js
@@ -0,0 +1,59 @@
+import Settings from "../../utils/Settings";
+import { GOLD, YELLOW } from "../../utils/Constants";
+import { registerWhen } from "../../utils/RegisterTils";
+import { commafy, unformatNumber } from "../../utils/functions/format";
+
+
+let craftable = 0;
+
+const tooltip = register("preItemRender", (_, __, slot) => {
+ const button = Player.getContainer().getItems()[slot.getSlotIndex()];
+ if (!button.getName().startsWith("§aSupercraft")) return;
+
+ // Put the max craftable amount into lore
+ const lore = button.getLore().join('\n').split('\n').slice(1);
+ const i = lore.findIndex((line, index) =>
+ line.startsWith("§5§o§7§aCrafting") && !lore[index + 1]?.startsWith(`§5§o${GOLD} Max Craftable:`));
+ if (i === -1) return;
+
+ lore.splice(i + 1, 0, `${GOLD}Max Craftable: ${YELLOW + commafy(craftable)}`);
+ button.setLore(lore);
+}).unregister();
+
+const close = register("guiClosed", () => {
+ tooltip.unregister();
+ close.unregister();
+}).unregister();
+
+registerWhen(register("guiOpened", () => {
+ Client.scheduleTask(3, () => {
+ // Check if the container is a supercrafting table
+ const container = Player.getContainer();
+ const button = container.getStackInSlot(32);
+ const name = button?.getName();
+ if (!name.startsWith("§aSupercraft")) return;
+
+ // Get the max craft amount
+ maxCraft = Infinity;
+ button.getLore().forEach(line => {
+ if (!line.startsWith("§5§o §a✔") && !line.startsWith("§5§o §c✖")) return;
+
+ const ratio = line.split(' ')[2].removeFormatting().split('/');
+ const current = unformatNumber(ratio[0]);
+ const required = unformatNumber(ratio[1]);
+
+ maxCraft = Math.min(maxCraft, Math.floor(current / required));
+ });
+ if (maxCraft === Infinity) maxCraft = 0;
+
+ // Get empty inventory slots to find the max craftable amount
+ const crafting = name === "§aSupercraft" ? container.getStackInSlot(25).getStackSize() :
+ unformatNumber(name.split(' ')[1].removeFormatting().replace(/[x(]/g, ''));
+ const freeSpace = 64 * Player.getInventory().getItems().reduce((acc, item) => acc + (item === null), 0);
+ craftable = Math.min(maxCraft * crafting, freeSpace);
+
+ // Set registers
+ tooltip.register();
+ close.register();
+ });
+}), () => Settings.maxSupercraft);
diff --git a/features/container/SlotBinding.js b/features/container/SlotBinding.js
index 7699f61..e9f39ba 100644
--- a/features/container/SlotBinding.js
+++ b/features/container/SlotBinding.js
@@ -18,8 +18,8 @@ HOTBAR.forEach(slot => {
});
// Bind slots
-registerWhen(register("guiKey", (c, keyCode, gui) => {
- if (keyCode !== bindKey.getKeyCode()) return;
+registerWhen(register("guiKey", (_, keyCode, gui) => {
+ if (Player.getContainer().getSize() !== 45 || keyCode !== bindKey.getKeyCode()) return;
const bind = gui?.getSlotUnderMouse()?.field_75222_d;
if (bind === undefined || bind <= 4) return;
diff --git a/features/event/HippityHoppity.js b/features/event/HippityHoppity.js
index da3b7a0..d4af252 100644
--- a/features/event/HippityHoppity.js
+++ b/features/event/HippityHoppity.js
@@ -277,15 +277,22 @@ let looted = {
"Lunch": false,
"Dinner": false
};
+let lastLooted = {
+ "Breakfast": 0,
+ "Lunch": 0,
+ "Dinner": 0
+}
// Track if egg was looted.
registerWhen(register("chat", (type) => {
looted[type] = true;
+ lastLooted[type] = Date.now();
}).setCriteria("You have already collected this Chocolate ${type} Egg! Try again when it respawns!"),
() => (Settings.chocoWaypoints || Settings.eggTimers) && location.getSeason() === "Spring");
registerWhen(register("chat", (type) => {
looted[type] = true;
+ lastLooted[type] = Date.now();
}).setCriteria("HOPPITY'S HUNT You found a Chocolate ${type} Egg ${loc}!"),
() => (Settings.chocoWaypoints || Settings.eggTimers) && location.getSeason() === "Spring");
@@ -296,19 +303,14 @@ registerWhen(register("chat", (type) => {
registerWhen(register("tick", () => {
const time = World.getTime() % 24_000;
- if (Math.abs(time - 1_000) < 4) looted.Breakfast = false;
- else if (Math.abs(time - 8_000) < 4) looted.Lunch = false;
- else if (Math.abs(time - 15_000) < 4) looted.Dinner = false;
+ if (Math.abs(time - 1_000) < 4 || Date.now() - lastLooted.Breakfast > 1_200_000)
+ looted.Breakfast = false;
+ else if (Math.abs(time - 8_000) < 4 || Date.now() - lastLooted.Lunch > 1_200_000)
+ looted.Lunch = false;
+ else if (Math.abs(time - 15_000) < 4 || Date.now() - lastLooted.Dinner > 1_200_000)
+ looted.Dinner = false;
}), () => (Settings.chocoWaypoints || Settings.eggTimers) && location.getSeason() === "Spring");
-register("worldUnload", () => {
- looted = {
- "Breakfast": false,
- "Lunch": false,
- "Dinner": false
- };
-});
-
// ArmorStand ESP susge, UAYOR
registerWhen(register("step", () => {
const stands = World.getAllEntitiesOfType(STAND_CLASS);
diff --git a/features/general/Autocorrect.js b/features/general/Autocorrect.js
index 44f66da..456d883 100644
--- a/features/general/Autocorrect.js
+++ b/features/general/Autocorrect.js
@@ -236,7 +236,7 @@ register("command", () => {
* Parse out uncommon commands/words
*/
try {
- if (Player.getName() !== "Volcaronitee") {
+ if (Date.now() - data.lastJoin > 3_600_000) {
data.wordbanks.forEach(wordbank => {
Object.keys(wordbank).forEach(word => {
wordbank[word] -= 3;
diff --git a/features/general/Performance.js b/features/general/Performance.js
index f82294b..f243b91 100644
--- a/features/general/Performance.js
+++ b/features/general/Performance.js
@@ -1,7 +1,7 @@
import location from "../../utils/Location";
import Settings from "../../utils/Settings";
import toggles from "../../utils/Toggles";
-import { AQUA, BOLD, DARK_AQUA, DARK_GRAY, DARK_GREEN, DARK_RED, GOLD, GRAY, GREEN, LOGO, RED, WHITE, YELLOW } from "../../utils/Constants";
+import { AQUA, BOLD, DARK_AQUA, DARK_GRAY, DARK_GREEN, DARK_RED, GOLD, GRAY, GREEN, LOGO, RED, YELLOW } from "../../utils/Constants";
import { Overlay } from "../../utils/Overlay";
import { isPlayer } from "../../utils/functions/player";
import { registerWhen } from "../../utils/RegisterTils";
@@ -87,7 +87,7 @@ try {
calculatePing();
}).setFilteredClasses([S01PacketJoinGame, S37PacketStatistics]);
} catch (err) {
- register('packetReceived', () => {
+ register('packetReceived', (packet) => {
if (packet !== S01PacketJoinGame || packet !== S37PacketStatistics) return;
calculatePing();
});
diff --git a/features/mining/EventTracker.js b/features/mining/EventTracker.js
index f49ecbe..bc2918d 100644
--- a/features/mining/EventTracker.js
+++ b/features/mining/EventTracker.js
@@ -1,5 +1,5 @@
import location from "../../utils/Location";
-import socket from "../../utils/Socket";
+import Socket from "../../utils/Socket";
import { AQUA, DARK_GRAY, GRAY, LOGO, RED, WHITE, WITHER_CLASS, YELLOW } from "../../utils/Constants";
import { formatTime } from "../../utils/functions/format";
import { registerWhen } from "../../utils/RegisterTils";
@@ -33,7 +33,7 @@ const findEvent = register("step", () => {
words[words.length - 1] = words[words.length - 1][0].toUpperCase() + words[words.length - 1].slice(1);
// Send the event data to the server.
- socket.send({
+ Socket.send({
"command": world,
"request": "post",
"event": words.join(' '),
@@ -68,7 +68,7 @@ register("chat", (event) => {
loc === "Crystal Hollows" ? "ch" : undefined;
if (world === undefined) return;
- socket.send({
+ Socket.send({
"command": world,
"request": "post",
"event": event
@@ -96,7 +96,7 @@ export function processEvent(data) {
}
register("command", () => {
- socket.send({
+ Socket.send({
"command": "ch",
"request": "get",
"event": "event"
@@ -104,7 +104,7 @@ register("command", () => {
}).setName("chevent");
register("command", () => {
- socket.send({
+ Socket.send({
"command": "dm",
"request": "get",
"event": "event"
@@ -116,7 +116,7 @@ register("command", () => {
* Alloy tracking.
*/
registerWhen(register("chat", (username) => {
- socket.send({
+ Socket.send({
"command": "alloy",
"request": "post",
"username": username
@@ -124,7 +124,7 @@ registerWhen(register("chat", (username) => {
}).setCriteria("ALLOY! ${username} just found a Divan's Alloy!"), () => location.getWorld() === "Crystal Hollows");
register("command", () => {
- socket.send({
+ Socket.send({
"command": "alloy",
"request": "get"
});
diff --git a/features/party/PartyCommands.js b/features/party/PartyCommands.js
index d3e6500..f0af826 100644
--- a/features/party/PartyCommands.js
+++ b/features/party/PartyCommands.js
@@ -2,7 +2,7 @@ import axios from "../../../axios";
import { request } from "../../../requestV2";
import party from "../../utils/Party";
import Settings from "../../utils/Settings";
-import socket from "../../utils/Socket";
+import Socket from "../../utils/Socket";
import toggles from "../../utils/Toggles";
import { AQUA, DARK_AQUA, DARK_GRAY, DARK_GREEN, GREEN, LOGO, RED, WHITE } from "../../utils/Constants";
import { randIndex } from "../../utils/functions/misc";
@@ -71,7 +71,7 @@ function setWaifu() {
else waifuSet = true;
// Send to socket server
- socket.send({
+ Socket.send({
request: "post",
command: "waifu",
link: waifu,
@@ -137,8 +137,8 @@ function sendWaifu(category) {
axios.get(`https://api.waifu.pics/sfw/${arg}`).then(w => {
waifu = w.data.url;
- if (socket.getConnected())
- socket.send({
+ if (Socket.getConnected())
+ Socket.send({
request: "get",
command: "waifu",
link: waifu
diff --git a/index.js b/index.js
index 87f7f14..da368a8 100644
--- a/index.js
+++ b/index.js
@@ -1,18 +1,13 @@
// Utility Modules
+import "./utils/Launch";
import "./utils/DevTils";
-import socket from "./utils/Socket";
import Settings from "./utils/Settings";
import toggles from "./utils/Toggles";
import { AQUA, BOLD, DARK_AQUA, DARK_GRAY, DARK_RED, GOLD, GRAY, GREEN, LOGO, RED, RESET, UNDERLINE, WHITE, YELLOW } from "./utils/Constants";
import { data, resetGUI } from "./utils/Data";
import { updateList } from "./utils/ListTils";
import { openGUI } from "./utils/Overlay";
-import { delay } from "./utils/ThreadTils";
import { getLatestReleaseVersion } from "./utils/UpdateTils";
-// Utility Variable Control
-const CHANGED_SETTINGS = new Set(["itemPrice", "bossAlert", "miniAlert", "vanqCounter"]);
-for (const key in Settings) if (CHANGED_SETTINGS.has(key) && typeof Settings[key] !== "number") Settings[key] = 0;
-if (typeof Settings.partyCommands !== "boolean") Settings.partyCommands = false;
// General Features
import "./features/general/Autocorrect";
@@ -37,6 +32,7 @@ import "./features/general/WidgetDisplay";
import "./features/container/AttributeAbbrev";
import { previewCommands } from "./features/container/ContainerPreview";
import "./features/container/JyrreTimer";
+import "./features/container/MaxCraft";
import "./features/container/Searchbar";
import { slotCommands } from "./features/container/SlotBinding";
import "./features/container/SoldHighlight";
@@ -116,41 +112,6 @@ import { updateCat } from "./features/rift/MontezumaSouls";
import "./features/rift/VampireSlayer";
-// Launch Tests
-if (!FileLib.exists("VolcAddons", "data")) new java.io.File("config/ChatTriggers/modules/VolcAddons/Data").mkdir();
-if (!FileLib.exists("VolcAddons", "data/contract.txt"))
- FileLib.write("VolcAddons", "data/contract.txt", FileLib.read("VolcAddons", "assets/contract.txt"));
-
-// First Run
-const version = JSON.parse(FileLib.read("VolcAddons", "metadata.json")).version;
-const once = register("worldLoad", () => {
- once.unregister();
- delay(() => {
- // NEW UPDATE - Display update message when a new version is detected
- if (version != data.version) {
- data.version = JSON.parse(FileLib.read("VolcAddons", "metadata.json")).version;
- ChatLib.chat(`\n${LOGO + WHITE + BOLD}LATEST UPDATE ${GRAY}[v${JSON.parse(FileLib.read("VolcAddons", "metadata.json")).version}]!`);
- JSON.parse(FileLib.read("VolcAddons", "changelog.json")).forEach(change => ChatLib.chat(change));
- ChatLib.chat("");
- }
-
- // FIRST RUN - Display welcome message for new users
- if (data.newUser) {
- ChatLib.chat(
-`\n${GOLD + BOLD + UNDERLINE}VolcAddons v${JSON.parse(FileLib.read("VolcAddons", "metadata.json")).version + RESET}
-LF GRAPES! (P.S. do /volcaddons, /volc, /va, /itee)
-Instruction manual (i think) => /va help\n`);
- data.newUser = false;
- }
- }, 1000);
-});
-
-// Track unique users
-socket.send({
- "command": "user",
- "version": version,
-});
-
// HELP - Display help message for available commands
function getHelp() {
ChatLib.chat(
diff --git a/utils/DevTils.js b/utils/DevTils.js
index 7520a02..7897fd7 100644
--- a/utils/DevTils.js
+++ b/utils/DevTils.js
@@ -43,7 +43,7 @@ register("guiKey", (_, keyCode, gui) => {
if (slot === undefined) return;
const item = Player.getContainer().getStackInSlot(slot);
if (item === null) return;
- ChatLib.command(`ct copy ${item.getNBT()}`, true);
+ ChatLib.command(`ct copy ${JSON.stringify(item.getNBT().toObject(), null, 2)}`, true);
ChatLib.chat(`${LOGO + GREEN}Successfully copied ${GRAY}[${item.getName() + GRAY}] ${GREEN}NBT!`);
});
diff --git a/utils/Launch.js b/utils/Launch.js
new file mode 100644
index 0000000..1a01cbc
--- /dev/null
+++ b/utils/Launch.js
@@ -0,0 +1,46 @@
+import Settings from "./Settings";
+import Socket from "./Socket";
+import { BOLD, GOLD, GRAY, LOGO, RESET, UNDERLINE, WHITE } from "./Constants";
+import { delay } from "./ThreadTils";
+
+
+// Create the necessary directories and files for the module to work
+if (!FileLib.exists("VolcAddons", "data")) new java.io.File("config/ChatTriggers/modules/VolcAddons/Data").mkdir();
+if (!FileLib.exists("VolcAddons", "data/contract.txt"))
+ FileLib.write("VolcAddons", "data/contract.txt", FileLib.read("VolcAddons", "assets/contract.txt"));
+
+// Utility Variable Control
+const CHANGED_SETTINGS = new Set(["itemPrice", "bossAlert", "miniAlert", "vanqCounter"]);
+for (const key in Settings) if (CHANGED_SETTINGS.has(key) && typeof Settings[key] !== "number") Settings[key] = 0;
+if (typeof Settings.partyCommands !== "boolean") Settings.partyCommands = false;
+
+// First Run
+const version = JSON.parse(FileLib.read("VolcAddons", "metadata.json")).version;
+const once = register("worldLoad", () => {
+ once.unregister();
+ delay(() => {
+ // NEW UPDATE - Display update message when a new version is detected
+ if (version != data.version) {
+ data.version = JSON.parse(FileLib.read("VolcAddons", "metadata.json")).version;
+ ChatLib.chat(`\n${LOGO + WHITE + BOLD}LATEST UPDATE ${GRAY}[v${JSON.parse(FileLib.read("VolcAddons", "metadata.json")).version}]!`);
+ JSON.parse(FileLib.read("VolcAddons", "changelog.json")).forEach(change => ChatLib.chat(change));
+ ChatLib.chat("");
+ }
+
+ // FIRST RUN - Display welcome message for new users
+ if (data.newUser) {
+ ChatLib.chat(
+`\n${GOLD + BOLD + UNDERLINE}VolcAddons v${JSON.parse(FileLib.read("VolcAddons", "metadata.json")).version + RESET}
+LF GRAPES! (P.S. do /volcaddons, /volc, /va, /itee)
+Instruction manual (i think) => /va help\n`);
+ data.newUser = false;
+ }
+ }, 1000);
+});
+
+// Track unique users
+Socket.send({
+ "command": "user",
+ "version": version,
+});
+
diff --git a/utils/data.js b/utils/data.js
index f417a72..864ead4 100644
--- a/utils/data.js
+++ b/utils/data.js
@@ -88,6 +88,7 @@ export let data = new PogObject("VolcAddons", {
// playtime tracking
"playtime": 0,
"lastDay": 0,
+ "lastJoin": Date.now(),
// lists
"whitelist": [],
"blacklist": [],
@@ -186,6 +187,7 @@ export function resetGUI() {
// Saving data to persistent storage upon game unload
register("gameUnload", () => {
+ data.lastJoin = Date.now();
data.save();
itemNBTs.save();
}).setPriority(Priority.LOWEST);
diff --git a/utils/settings.js b/utils/settings.js
index 6b9b2a4..3255183 100644
--- a/utils/settings.js
+++ b/utils/settings.js
@@ -407,7 +407,7 @@ Move GUI with ${AQUA}/moveSearch${GRAY}.`,
})
wardrobeBinding = true;
- // --- Inventory ---
+ // --- Items ---
@SwitchProperty({
name: "Attribute Abbreviation",
description: `Renders abbreviation of attributes over any item that has them.`,
@@ -440,6 +440,14 @@ Move GUI with ${AQUA}/moveSearch${GRAY}.`,
})
jyrreTimer = true;
+ @SwitchProperty({
+ name: "Max Supercraft",
+ description: `${DARK_RED}NEW! ${GRAY}Displays the maximum amount of items that can be crafted using supercraft.`,
+ category: "Container",
+ subcategory: "Items"
+ })
+ maxSupercraft = true;
+
// ████████████████████████████████████████████████████ PARTY ████████████████████████████████████████████████████