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 ████████████████████████████████████████████████████