From 431e4fc9d1657a50ebc34b8ac24f9bfaea06417f Mon Sep 17 00:00:00 2001
From: Soopyboo32 <49228220+Soopyboo32@users.noreply.github.com>
Date: Sat, 17 Sep 2022 19:39:05 +0800
Subject: Initial move to babel + change fetch to use async/await
---
src/features/bestiary/index.js | 250 ++++
src/features/bestiary/metadata.json | 8 +
src/features/betterGuis/dungeonReadyGui.js | 284 +++++
src/features/betterGuis/index.js | 386 ++++++
src/features/betterGuis/metadata.json | 8 +
src/features/betterGuis/museumGui.js | 1024 ++++++++++++++++
src/features/changeLogGUI/index.js | 255 ++++
src/features/changeLogGUI/metadata.json | 8 +
src/features/cosmetics/cosmetic.js | 29 +
.../cosmetics/cosmetic/dragon/dragonWings.js | 482 ++++++++
src/features/cosmetics/hiddenRequirement.js | 4 +
src/features/cosmetics/index.js | 271 ++++
src/features/cosmetics/metadata.json | 8 +
src/features/dataLoader/index.js | 280 +++++
src/features/dataLoader/metadata.json | 8 +
src/features/dungeonMap/dungeonBossImages/f1.png | Bin 0 -> 4681 bytes
src/features/dungeonMap/index.js | 1186 ++++++++++++++++++
src/features/dungeonMap/map.png | Bin 0 -> 5648 bytes
src/features/dungeonMap/metadata.json | 8 +
src/features/dungeonMap2/DungeonMapData.js | 513 ++++++++
src/features/dungeonMap2/DungeonMapRoom.js | 256 ++++
src/features/dungeonMap2/DungeonRoomStaticData.js | 19 +
src/features/dungeonMap2/index.js | 312 +++++
src/features/dungeonMap2/metadata.json | 8 +
src/features/dungeonRoutes/index.js | 481 ++++++++
src/features/dungeonRoutes/metadata.json | 8 +
src/features/dungeonRoutes/routesData.json | 1296 ++++++++++++++++++++
src/features/dungeonSolvers/f7data.json | 263 ++++
src/features/dungeonSolvers/index.js | 1270 +++++++++++++++++++
src/features/dungeonSolvers/metadata.json | 8 +
src/features/events/index.js | 816 ++++++++++++
src/features/events/metadata.json | 8 +
src/features/eventsGUI/index.js | 287 +++++
src/features/eventsGUI/metadata.json | 8 +
src/features/featureBase/index.js | 24 +
src/features/featureBase/metadata.json | 8 +
src/features/fpsImproveGui/index.js | 49 +
src/features/fpsImproveGui/metadata.json | 8 +
src/features/fragBot/index.js | 84 ++
src/features/fragBot/metadata.json | 8 +
src/features/friendsGUI/index.js | 363 ++++++
src/features/friendsGUI/metadata.json | 8 +
src/features/globalSettings/firstLoadPage.js | 42 +
src/features/globalSettings/firstLoadPages.js | 135 ++
src/features/globalSettings/index.js | 1121 +++++++++++++++++
src/features/globalSettings/metadata.json | 8 +
src/features/globalSettings/warps.json | 41 +
src/features/guild/index.js | 70 ++
src/features/guild/metadata.json | 8 +
src/features/hud/HudTextElement.js | 143 +++
src/features/hud/index.js | 812 ++++++++++++
src/features/hud/metadata.json | 8 +
src/features/lockedFeatures/index.js | 121 ++
src/features/lockedFeatures/metadata.json | 8 +
src/features/mining/coords.json | 202 +++
src/features/mining/index.js | 469 +++++++
src/features/mining/metadata.json | 8 +
src/features/nether/index.js | 406 ++++++
src/features/nether/metadata.json | 8 +
src/features/networthGUI/index.js | 239 ++++
src/features/networthGUI/metadata.json | 8 +
src/features/performance/hiddenRequirement.js | 7 +
src/features/performance/index.js | 128 ++
src/features/performance/metadata.json | 8 +
src/features/senitherGui/index.js | 453 +++++++
src/features/senitherGui/metadata.json | 8 +
src/features/settings/helpDataLoader.js | 50 +
src/features/settings/index.js | 332 +++++
src/features/settings/locationSettingHolder.js | 27 +
src/features/settings/metadata.json | 8 +
.../settings/settingThings/FakeRequireToggle.js | 27 +
src/features/settings/settingThings/button.js | 18 +
.../settings/settingThings/dropdownSetting.js | 41 +
.../settings/settingThings/imageLocation.js | 321 +++++
src/features/settings/settingThings/location.js | 340 +++++
src/features/settings/settingThings/settingBase.js | 162 +++
src/features/settings/settingThings/textSetting.js | 41 +
src/features/settings/settingThings/toggle.js | 62 +
src/features/settings/settingsCommunicator.js | 35 +
src/features/slayers/index.js | 1022 +++++++++++++++
src/features/slayers/metadata.json | 8 +
src/features/soopyGui/GuiPage.js | 68 +
src/features/soopyGui/categoryManager.js | 37 +
src/features/soopyGui/index.js | 215 ++++
src/features/soopyGui/metadata.json | 8 +
src/features/spamHider/index.js | 351 ++++++
src/features/spamHider/metadata.json | 8 +
src/features/specialMining/index.js | 461 +++++++
src/features/specialMining/metadata.json | 8 +
src/features/statHistoryGui/index.js | 189 +++
src/features/statHistoryGui/metadata.json | 8 +
src/features/stat_next_to_name/index.js | 193 +++
src/features/stat_next_to_name/metadata.json | 8 +
src/features/streamsGUI/index.js | 181 +++
src/features/streamsGUI/metadata.json | 8 +
src/features/suggestionsGui/index.js | 217 ++++
src/features/suggestionsGui/metadata.json | 8 +
src/features/waypoints/index.js | 323 +++++
src/features/waypoints/metadata.json | 8 +
src/features/waypoints/minewaypoints_socket.js | 49 +
src/features/waypoints/pathfind.js | 96 ++
101 files changed, 20003 insertions(+)
create mode 100644 src/features/bestiary/index.js
create mode 100644 src/features/bestiary/metadata.json
create mode 100644 src/features/betterGuis/dungeonReadyGui.js
create mode 100644 src/features/betterGuis/index.js
create mode 100644 src/features/betterGuis/metadata.json
create mode 100644 src/features/betterGuis/museumGui.js
create mode 100644 src/features/changeLogGUI/index.js
create mode 100644 src/features/changeLogGUI/metadata.json
create mode 100644 src/features/cosmetics/cosmetic.js
create mode 100644 src/features/cosmetics/cosmetic/dragon/dragonWings.js
create mode 100644 src/features/cosmetics/hiddenRequirement.js
create mode 100644 src/features/cosmetics/index.js
create mode 100644 src/features/cosmetics/metadata.json
create mode 100644 src/features/dataLoader/index.js
create mode 100644 src/features/dataLoader/metadata.json
create mode 100644 src/features/dungeonMap/dungeonBossImages/f1.png
create mode 100644 src/features/dungeonMap/index.js
create mode 100644 src/features/dungeonMap/map.png
create mode 100644 src/features/dungeonMap/metadata.json
create mode 100644 src/features/dungeonMap2/DungeonMapData.js
create mode 100644 src/features/dungeonMap2/DungeonMapRoom.js
create mode 100644 src/features/dungeonMap2/DungeonRoomStaticData.js
create mode 100644 src/features/dungeonMap2/index.js
create mode 100644 src/features/dungeonMap2/metadata.json
create mode 100644 src/features/dungeonRoutes/index.js
create mode 100644 src/features/dungeonRoutes/metadata.json
create mode 100644 src/features/dungeonRoutes/routesData.json
create mode 100644 src/features/dungeonSolvers/f7data.json
create mode 100644 src/features/dungeonSolvers/index.js
create mode 100644 src/features/dungeonSolvers/metadata.json
create mode 100644 src/features/events/index.js
create mode 100644 src/features/events/metadata.json
create mode 100644 src/features/eventsGUI/index.js
create mode 100644 src/features/eventsGUI/metadata.json
create mode 100644 src/features/featureBase/index.js
create mode 100644 src/features/featureBase/metadata.json
create mode 100644 src/features/fpsImproveGui/index.js
create mode 100644 src/features/fpsImproveGui/metadata.json
create mode 100644 src/features/fragBot/index.js
create mode 100644 src/features/fragBot/metadata.json
create mode 100644 src/features/friendsGUI/index.js
create mode 100644 src/features/friendsGUI/metadata.json
create mode 100644 src/features/globalSettings/firstLoadPage.js
create mode 100644 src/features/globalSettings/firstLoadPages.js
create mode 100644 src/features/globalSettings/index.js
create mode 100644 src/features/globalSettings/metadata.json
create mode 100644 src/features/globalSettings/warps.json
create mode 100644 src/features/guild/index.js
create mode 100644 src/features/guild/metadata.json
create mode 100644 src/features/hud/HudTextElement.js
create mode 100644 src/features/hud/index.js
create mode 100644 src/features/hud/metadata.json
create mode 100644 src/features/lockedFeatures/index.js
create mode 100644 src/features/lockedFeatures/metadata.json
create mode 100644 src/features/mining/coords.json
create mode 100644 src/features/mining/index.js
create mode 100644 src/features/mining/metadata.json
create mode 100644 src/features/nether/index.js
create mode 100644 src/features/nether/metadata.json
create mode 100644 src/features/networthGUI/index.js
create mode 100644 src/features/networthGUI/metadata.json
create mode 100644 src/features/performance/hiddenRequirement.js
create mode 100644 src/features/performance/index.js
create mode 100644 src/features/performance/metadata.json
create mode 100644 src/features/senitherGui/index.js
create mode 100644 src/features/senitherGui/metadata.json
create mode 100644 src/features/settings/helpDataLoader.js
create mode 100644 src/features/settings/index.js
create mode 100644 src/features/settings/locationSettingHolder.js
create mode 100644 src/features/settings/metadata.json
create mode 100644 src/features/settings/settingThings/FakeRequireToggle.js
create mode 100644 src/features/settings/settingThings/button.js
create mode 100644 src/features/settings/settingThings/dropdownSetting.js
create mode 100644 src/features/settings/settingThings/imageLocation.js
create mode 100644 src/features/settings/settingThings/location.js
create mode 100644 src/features/settings/settingThings/settingBase.js
create mode 100644 src/features/settings/settingThings/textSetting.js
create mode 100644 src/features/settings/settingThings/toggle.js
create mode 100644 src/features/settings/settingsCommunicator.js
create mode 100644 src/features/slayers/index.js
create mode 100644 src/features/slayers/metadata.json
create mode 100644 src/features/soopyGui/GuiPage.js
create mode 100644 src/features/soopyGui/categoryManager.js
create mode 100644 src/features/soopyGui/index.js
create mode 100644 src/features/soopyGui/metadata.json
create mode 100644 src/features/spamHider/index.js
create mode 100644 src/features/spamHider/metadata.json
create mode 100644 src/features/specialMining/index.js
create mode 100644 src/features/specialMining/metadata.json
create mode 100644 src/features/statHistoryGui/index.js
create mode 100644 src/features/statHistoryGui/metadata.json
create mode 100644 src/features/stat_next_to_name/index.js
create mode 100644 src/features/stat_next_to_name/metadata.json
create mode 100644 src/features/streamsGUI/index.js
create mode 100644 src/features/streamsGUI/metadata.json
create mode 100644 src/features/suggestionsGui/index.js
create mode 100644 src/features/suggestionsGui/metadata.json
create mode 100644 src/features/waypoints/index.js
create mode 100644 src/features/waypoints/metadata.json
create mode 100644 src/features/waypoints/minewaypoints_socket.js
create mode 100644 src/features/waypoints/pathfind.js
(limited to 'src/features')
diff --git a/src/features/bestiary/index.js b/src/features/bestiary/index.js
new file mode 100644
index 0000000..da09463
--- /dev/null
+++ b/src/features/bestiary/index.js
@@ -0,0 +1,250 @@
+///
+///
+import Feature from "../../featureClass/class";
+import { numberWithCommas } from "../../utils/numberUtils";
+import HudTextElement from "../hud/HudTextElement";
+import DropdownSetting from "../settings/settingThings/dropdownSetting";
+import LocationSetting from "../settings/settingThings/location";
+import SettingBase from "../settings/settingThings/settingBase";
+import ToggleSetting from "../settings/settingThings/toggle";
+
+let dontUseApi = new Set()
+dontUseApi.add("arachne")
+dontUseApi.add("barbarian_duke_x")
+dontUseApi.add("bladesoul")
+dontUseApi.add("mage_outlaw")
+dontUseApi.add("ashfang")
+dontUseApi.add("magma_cube_boss")
+dontUseApi.add("headless_horseman")
+dontUseApi.add("dragon")
+
+
+class Bestiary extends Feature {
+ constructor() {
+ super()
+ }
+
+ onEnable() {
+ this.bestiaryData = JSON.parse(FileLib.read("soopyAddonsData", "bestiaryData.json") || "{}")
+ this.bestiaryChanged = false
+
+ this.bestiaryApiTracking = {}
+
+ this.registerStep(true, 5, this.scanInv)
+ this.registerStep(false, 5, this.saveData)
+
+
+ this.bestiaryStatTypes = {
+ "barbarian_duke_x": "Barbarian Duke X"
+ }
+ Object.keys(this.bestiaryData).forEach(k => {
+ if (this.bestiaryData[k].guiName) this.bestiaryStatTypes[k] = this.bestiaryData[k].guiName
+ })
+
+ new SettingBase("NOTE: u need to open ur bestiary menu", "before this will work", true, "info_bestiary", this)
+ this.hudStat = []
+ for (let i = 0; i < 10; i++) {
+ this.hudStat[i] = {}
+ this.hudStat[i].enabled = new ToggleSetting("Bestiary Slot #" + (i + 1), "Allows you to render a custom besiary kills on your hud", false, "bestiary_stat_" + i, this)
+ this.hudStat[i].type = new DropdownSetting("Bestiary Slot #" + (i + 1) + " Type", "The bestiary type", "barbarian_duke_x", "bestiary_stat_" + i + "_type", this, this.bestiaryStatTypes)
+ this.hudStat[i].location = new LocationSetting("Bestiary Slot #" + (i + 1) + " Location", "Allows you to edit the location of the bestiary stat", "bestiary_stat_" + i + "_location", this, [10, 50 + i * 10, 1, 1]).editTempText("&6Bestiary Stat Stat&7> &f12,345")
+ this.hudStat[i].textElement = new HudTextElement().setToggleSetting(this.hudStat[i].enabled).setLocationSetting(this.hudStat[i].location).setText("&6Bestiary Stat&7> &fLoading...")
+ this.hudStat[i].onlySb = new ToggleSetting("Bestiary Slot #" + (i + 1) + " Only SB", "Only render this stat when you are in skyblock", true, "bestiary_stat_" + i + "_only_sb", this).requires(this.hudStat[i].enabled)
+
+ this.hudStat[i].location.requires(this.hudStat[i].enabled)
+ this.hudStat[i].type.requires(this.hudStat[i].enabled)
+ if (this.hudStat[i - 1]) {
+ this.hudStat[i].enabled.requires(this.hudStat[i - 1].enabled)
+ }
+ }
+
+ this.registerStep(false, 5, this.updateHudElements)
+ let lastThing = undefined
+ let lastThingTime = 0
+ this.registerChat("${chat}", (chat) => {
+ let thing
+ switch (chat.trim()) {
+ case "MAGE OUTLAW DOWN!":
+ thing = "mage_outlaw"
+ break;
+ case "BARBARIAN DUKE X DOWN!":
+ thing = "barbarian_duke_x"
+ break;
+ case "BLADESOUL DOWN!":
+ thing = "bladesoul"
+ break;
+ case "ASHFANG DOWN!":
+ thing = "ashfang"
+ break;
+ // case "MAGMA BOSS DOWN!":
+ // thing = "magma_cube_boss"
+ // break;
+ case "ARACHNE DOWN!":
+ lastThing = "arachne"
+ lastThingTime = Date.now()
+ break;
+ case "HORSEMAN DOWN!":
+ lastThing = "arachne"
+ lastThingTime = Date.now()
+ break;
+ default:
+ break;
+ }
+ if (chat.includes("DRAGON")) {
+ lastThing = "dragon"
+ lastThingTime = Date.now()
+ }
+
+ if (chat.trim().startsWith("Your Damage: ")) {
+ let dmg = parseInt(chat.trim().split("Your Damage: ")[1].split(" ")[0])
+ if (dmg > 0 && Date.now() - lastThingTime < 1000) {
+ thing = lastThing
+ lastThing = ""
+ lastThingTime = 0
+ }
+ }
+
+ if (thing) {
+ this.bestiaryData[thing].guessCount++
+ this.bestiaryChanged = true
+ }
+ })
+ this.registerSoopy("apiLoad", this.apiLoad);
+
+ if (this.FeatureManager.features["dataLoader"] && this.FeatureManager.features["dataLoader"].class.lastApiData.skyblock_raw) {
+ this.apiLoad(this.FeatureManager.features["dataLoader"].class.lastApiData.skyblock_raw, "skyblock", false, true);
+ }
+ }
+
+ getBestiaryCount(id) {
+ if (!this.bestiaryData[id]) return "???"
+ let count = this.bestiaryData[id].count
+
+ if (!dontUseApi.has(id)) {
+ let currApiData = this.bestiaryApiTracking[id]
+
+ count += currApiData - this.bestiaryData[id].apiCount
+ }
+
+ count += this.bestiaryData[id].guessCount
+
+ return count
+ }
+
+ updateHudElements() {
+ if (!this.FeatureManager.features["dataLoader"]) return
+
+ let insb = this.FeatureManager.features["dataLoader"].class.isInSkyblock
+
+ this.hudStat.forEach(stat => {
+ if (stat.enabled.getValue()) {
+ if (!insb && stat.onlySb.getValue()) {
+ stat.textElement.setText("")
+ return
+ }
+
+ let type = stat.type.getValue()
+
+ stat.textElement.setText(`&6${this.bestiaryData[type]?.guiName}&7> &f${numberWithCommas(this.getBestiaryCount(type))}`)
+ } else {
+ stat.textElement.setText("")
+ }
+ })
+ }
+
+ apiLoad(data, dataType, isSoopyServer, isLatest) {
+ if (isSoopyServer || !isLatest) return;
+ if (dataType !== "skyblock") return;
+
+ let currentProfile = {}
+ let currentProfileTime = 0
+
+ data.profiles.forEach(p => {
+ if (p.members[Player.getUUID().toString().replace(/-/g, "")].last_save > currentProfileTime) {
+ currentProfileTime = p.members[Player.getUUID().toString().replace(/-/g, "")].last_save
+ currentProfile = p.members[Player.getUUID().toString().replace(/-/g, "")]
+ }
+ })
+
+ Object.keys(currentProfile.stats).forEach(key => {
+ if (key.startsWith("kills_")) {
+ this.bestiaryApiTracking[key.replace("kills_", "")] = currentProfile.stats[key]
+ }
+ })
+ }
+
+ scanInv() {
+ if (!Player.getContainer()) return
+ if (!Player.getContainer().getName().startsWith("Bestiary ➜ ")) return
+ let tempChanged = false
+ let seen = new Set()
+
+ for (let item of Player.getContainer().getItems()) {
+ if (!item) continue
+ let name = ChatLib.removeFormatting(item.getName()).split(" ")
+ name.pop()
+ let apiName = name.join("_").toLowerCase()
+ if (seen.has(apiName)) continue
+ seen.add(apiName)
+
+ if (apiName === "skeletor_prime") continue
+
+ if (this.bestiaryApiTracking[apiName] || dontUseApi.has(apiName)) {
+
+ let count = 0
+
+ for (let l of item.getLore()) {
+ l = ChatLib.removeFormatting(l)
+
+ if (l.startsWith("Kills: ")) {
+ count = parseInt(l.split("Kills: ")[1].replace(/,/g, ""))
+ break;
+ }
+ }
+
+ let needsChange = !this.bestiaryData[apiName] || this.bestiaryData[apiName].guiName !== name.join(" ") || this.bestiaryData[apiName].count !== count || this.bestiaryData[apiName].apiCount !== (this.bestiaryApiTracking[apiName] || 0) || this.bestiaryData[apiName].guessCount !== 0
+ if (needsChange) {
+ this.bestiaryData[apiName] = {
+ guiName: name.join(" "),
+ count,
+ apiCount: this.bestiaryApiTracking[apiName] || 0,
+ guessCount: 0
+ }
+ this.bestiaryChanged = true
+
+ tempChanged = true
+
+ }
+ }
+ }
+
+ if (tempChanged) {
+ this.bestiaryStatTypes = {}
+ Object.keys(this.bestiaryData).forEach(k => {
+ if (this.bestiaryData[k]?.guiName) this.bestiaryStatTypes[k] = this.bestiaryData[k].guiName
+ })
+
+ this.hudStat.forEach(s => {
+ s.type.dropdownObject.setOptions(this.bestiaryStatTypes)
+ })
+
+ this.updateHudElements()
+ }
+ start = Date.now()
+ }
+
+ saveData() {
+ if (this.bestiaryChanged) {
+ FileLib.write("soopyAddonsData", "bestiaryData.json", JSON.stringify(this.bestiaryData))
+ }
+ }
+
+ onDisable() {
+ this.hudStat.forEach(h => h.textElement.delete())
+ this.saveData()
+ }
+
+}
+module.exports = {
+ class: new Bestiary()
+}
diff --git a/src/features/bestiary/metadata.json b/src/features/bestiary/metadata.json
new file mode 100644
index 0000000..3ff9383
--- /dev/null
+++ b/src/features/bestiary/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Bestiary",
+ "description": "Bestiary trackers",
+ "isHidden": false,
+ "isTogglable": true,
+ "defaultEnabled": true,
+ "sortA": 0
+}
\ No newline at end of file
diff --git a/src/features/betterGuis/dungeonReadyGui.js b/src/features/betterGuis/dungeonReadyGui.js
new file mode 100644
index 0000000..ad9a5dd
--- /dev/null
+++ b/src/features/betterGuis/dungeonReadyGui.js
@@ -0,0 +1,284 @@
+import { SoopyGui, SoopyRenderEvent } from "../../../guimanager"
+import SoopyKeyPressEvent from "../../../guimanager/EventListener/SoopyKeyPressEvent"
+import SoopyMouseClickEvent from "../../../guimanager/EventListener/SoopyMouseClickEvent"
+import BoxWithTextAndDescription from "../../../guimanager/GuiElement/BoxWithTextAndDescription"
+import ButtonWithArrow from "../../../guimanager/GuiElement/ButtonWithArrow"
+import SoopyGuiElement from "../../../guimanager/GuiElement/SoopyGuiElement"
+import SoopyTextElement from "../../../guimanager/GuiElement/SoopyTextElement"
+
+
+const ContainerChest = Java.type("net.minecraft.inventory.ContainerChest");
+
+class DungeonReadyGui {
+ constructor() {
+ this.checkMenu = false;
+
+ this.soopyGui = new SoopyGui();
+
+ this.soopyGui.optimisedLocations = true;
+
+ this.mainPage = new SoopyGuiElement().setLocation(0, 0, 1, 1);
+ this.soopyGui.element.addChild(this.mainPage);
+ this.soopyGui.element.addEvent(new SoopyKeyPressEvent().setHandler((...args) =>
+ this.keyPress(...args)
+ ));
+
+
+ this.startButton = new ButtonWithArrow()
+ .setText("§0Start Dungeon")
+ .setLocation(0.25, 0.25, 0.5, 0.5)
+ .addEvent(new SoopyMouseClickEvent().setHandler(() =>
+ this.startDungeon()
+ ));
+ this.soopyGui.element.addChild(this.startButton);
+
+ this.startButton.desc = new SoopyTextElement()
+ .setMaxTextScale(2)
+ .setLocation(0.05, 0.6, 0.7, 0.4)
+ .setText("");
+ this.startButton.addChild(this.startButton.desc);
+
+ this.closeMenu = 0;
+ this.nameToId = {};
+ this.nextId = 0;
+ this.currPlayers = 1;
+ this.readyBoxes = [];
+ this.confirmationCooldown = 0;
+ for (let i = 0; i < 4; i++) {
+ let readyBox = new BoxWithTextAndDescription()
+ .setText("§0")
+ .setDesc("§0")
+ .setLocation(0.1 + 0.2 * i, 0.75, 0.15, 0.15)
+ .setColor(255, 150, 150);
+ this.readyBoxes.push(readyBox);
+
+
+ readyBox.text.setLocation(0, 0, 1, 0.6);
+ readyBox.description.setLocation(0.05, 0.6, 0.9, 0.4);
+ readyBox.visable = false;
+
+
+ this.mainPage.addChild(readyBox);
+ }
+
+ this.classBoxes = [];
+ this.currentPlayerClass = -1;
+ this.classes = {
+ "Healer": new Item("minecraft:potion"),
+ "Mage": new Item("minecraft:blaze_rod"),
+ "Berserker": new Item("minecraft:iron_sword"),
+ "Archer": new Item("minecraft:bow"),
+ "Tank": new Item("minecraft:leather_chestplate")
+ };
+ Object.keys(this.classes).forEach((clas, i) => {
+ let classBox = new BoxWithTextAndDescription()
+ .setText("§0" + clas + "&7 - 0")
+ .setDesc("§0")
+ .setLocation(0.1 + 0.1625 * i, 0.1, 0.15, 0.1);
+ this.classBoxes.push(classBox);
+
+ let classIndex = i;
+
+ classBox.text.setLocation(0, 0, 1, 0.6);
+ classBox.description.setLocation(0.05, 0.6, 0.9, 0.4);
+ classBox.addEvent(new SoopyRenderEvent()
+ .setHandler(() => {
+ let scale = 16 / Math.min(classBox.location.getWidthExact(), classBox.location.getHeightExact() / 2) * 3;
+ this.classes[clas].draw(classBox.location.getXExact() + classBox.location.getWidthExact() / 2 - 16 * scale / 2, classBox.location.getYExact() + classBox.location.getHeightExact() - 16 * scale - 4, scale);
+ })).addEvent(new SoopyMouseClickEvent().setHandler(() =>
+ this.clickedClass(classIndex)
+ ));
+
+ this.mainPage.addChild(classBox)
+ })
+
+ this.playerReadyButton = new ButtonWithArrow()
+ .setText("§0Ready")
+ .setLocation(0.33, 0.33, 0.33, 0.33)
+ .setColor(255, 150, 150)
+ .addEvent(new SoopyMouseClickEvent()
+ .setHandler(() => this.ready()));
+ this.mainPage.addChild(this.playerReadyButton);
+ }
+
+ joinedDungeon(players) {
+ this.currPlayers = players;
+ }
+
+ startDungeon() {
+ if (Player.getContainer().getName() !== "Start Dungeon?") return;
+
+ if (!this.confirmationCooldown && World.getAllPlayers().filter(p => p.getPing() === 1).length !== this.currPlayers && !(World.getAllPlayers().filter(p => p.getPing() === 1).length === 1 && this.currPlayers === 2)) {
+ this.startButton.setText("§0Confirm starting Dungeon? (3s)");
+ this.startButton.desc.setText("§0(" + World.getAllPlayers().filter(p => p.getPing() === 1).length + "/" + this.currPlayers + " in dungeon)");
+ this.confirmationCooldown = Date.now() + 3000;
+ return;
+ }
+ if (Date.now() < this.confirmationCooldown) return;
+
+ this.startButton.visable = false;
+ Player.getContainer().click(13, false, "MIDDLE");
+ }
+
+ ready() {
+ if (!Player.getContainer().getName().startsWith("Catacombs - Floor ")) return;
+ this.playerReadyButton.setColor(150, 150, 150);
+ for (let i = 0; i < 5; i++) {
+ if (ChatLib.removeFormatting(Player.getContainer().getStackInSlot(3 + i).getName().split(" ").pop()) === Player.getName())
+ Player.getContainer().drop(12 + i, false);
+ }
+ }
+
+ clickedClass(classIndex) {
+ if (!Player.getContainer().getName().startsWith("Catacombs - Floor ")) return;
+
+ Player.getContainer().drop(2 + 4 * 9 + classIndex, false);
+
+ this.classBoxes[classIndex].setColor(150, 150, 150);
+
+ if (this.currentPlayerClass !== -1) this.classBoxes[this.currentPlayerClass].setColor(253, 255, 227);
+ }
+
+ reset() {
+ this.startButton.visable = true;
+ this.playerReadyButton.setColor(255, 150, 150);
+
+ this.nameToId = {};
+ this.nextId = 0;
+ this.closeMenu = 0;
+
+ this.startButton.setText("§0Start Dungeon");
+ this.startButton.desc.setText("");
+ this.confirmationCooldown = 0;
+
+ this.readyBoxes.forEach(b => b.visable = false);
+ }
+
+ readyInOneSecond() {
+ this.closeMenu = Date.now() + 1000;
+ }
+
+ tick() {
+ if (!this.soopyGui.ctGui.isOpen()) return;
+
+ if (this.closeMenu > 0 && Date.now() > this.closeMenu) {
+ this.soopyGui.close();
+ Client.currentGui.close();
+ this.closeMenu = 0;
+ return;
+ }
+
+ if (Player.getContainer().getName().startsWith("Catacombs - Floor ")) {
+ this.startButton.visable = false;
+
+ let clickingClassButton = -1;
+
+ for (let i = 0; i < 5; i++) {
+ //ready up buttons
+ if (Player.getContainer().getStackInSlot(3 + i)) {
+ if (ChatLib.removeFormatting(Player.getContainer().getStackInSlot(3 + i).getName().split(" ").pop()) === Player.getName()) {
+ if (Player.getContainer().getStackInSlot(12 + i)) {
+ if (ChatLib.removeFormatting(Player.getContainer().getStackInSlot(12 + i).getName()) === "Ready") {
+ this.playerReadyButton.setColor(150, 255, 150);
+ } else {
+ this.playerReadyButton.setColor(255, 150, 150);
+ }
+ } else {
+ this.playerReadyButton.setColor(150, 150, 150);
+ }
+ } else {
+ let boxId = this.nameToId[ChatLib.removeFormatting(Player.getContainer().getStackInSlot(3 + i).getName().split(" ").pop())];
+
+ if (boxId) {
+ this.readyBoxes[boxId].setColor(255, 150, 150);
+ if (ChatLib.removeFormatting(Player.getContainer().getStackInSlot(12 + i).getName()) === "Ready")
+ this.readyBoxes[boxId].setColor(150, 255, 150);
+
+ this.readyBoxes[boxId].setLore(Player.getContainer().getStackInSlot(3 + i).getLore());
+ this.readyBoxes[boxId].setDesc("§0" + ChatLib.removeFormatting(Player.getContainer().getStackInSlot(3 + i).getLore()[2]));
+ }
+ }
+ }
+
+
+ //select class buttons
+ if (Player.getContainer().getStackInSlot(2 + 4 * 9 + i)) {
+ this.classBoxes[i].setColor(253, 255, 227);
+ if (Player.getContainer().getStackInSlot(2 + 4 * 9 + i).getDamage() === 10)
+ this.classBoxes[i].setColor(250, 255, 150);
+
+ this.classBoxes[i]
+ .setText("§0" + Object.keys(this.classes)[i] + "§7 - " + ChatLib.removeFormatting(Player.getContainer().getStackInSlot(2 + 4 * 9 + i).getName().split(" ")[0]))
+ .setLore(Player.getContainer().getStackInSlot(2 + 4 * 9 + i).getLore());
+
+ let isPlayerClass = false;
+ Player.getContainer().getStackInSlot(2 + 4 * 9 + i).getLore().forEach(line => {
+ if (!ChatLib.removeFormatting(line).startsWith(" - ")) return;
+ if (ChatLib.removeFormatting(line.split(" ").pop()) === Player.getName())
+ isPlayerClass = true;
+ })
+
+ if (isPlayerClass) {
+ this.currentPlayerClass = i;
+ this.classBoxes[i].setColor(150, 255, 150);
+ }
+ } else clickingClassButton = i;
+ }
+
+ if (clickingClassButton !== -1) {
+ this.classBoxes[clickingClassButton].setColor(150, 150, 150);
+ if (this.currentPlayerClass !== -1) this.classBoxes[this.currentPlayerClass].setColor(253, 255, 227);
+ }
+ };
+
+ if (this.confirmationCooldown) {
+ this.startButton.setText("§0Confirm starting Dungeon? (" + Math.ceil(Math.max(0, this.confirmationCooldown - Date.now()) / 1000) + "s)");
+ };
+
+ World.getAllPlayers().filter(p => p.getPing() === 1).forEach(p => {
+ if (p.getUUID().toString() === Player.getUUID().toString()) return;
+
+ if (p.getName() in this.nameToId) return;
+
+ this.nameToId[p.getName()] = this.nextId++;
+
+ this.readyBoxes[this.nameToId[p.getName()]].setText("§0" + p.getName()).visable = true;
+ });
+ }
+
+ guiOpened(event) {
+ let name = "";
+ if (event.gui && event.gui.field_147002_h instanceof ContainerChest)
+ name = event.gui.field_147002_h.func_85151_d().func_145748_c_().func_150260_c();
+
+ if (this.soopyGui.ctGui.isOpen()) {
+ if (!event.gui || !event.gui.field_147002_h) return;
+ Player.getPlayer().field_71070_bA = event.gui.field_147002_h
+
+ if (!Player.getContainer().getName().startsWith("Catacombs - Floor ")) return;
+
+ event.gui = this.soopyGui.ctGui
+ this.soopyGui.ctGui.open();
+ return
+ }
+
+ if (name === "Start Dungeon?" || name.startsWith("Catacombs - Floor ")) {
+ if (event.gui && event.gui.field_147002_h) Player.getPlayer().field_71070_bA = event.gui.field_147002_h;
+
+ this.soopyGui.open();
+ event.gui = this.soopyGui.ctGui;
+ }
+ }
+
+ keyPress(key, keyId) {
+ if (keyId === 1) //escape key
+ // this.dontOpen = 1
+ Client.currentGui.close();
+
+ if (keyId === 18) //'e' key
+ Client.currentGui.close();
+
+ }
+}
+
+export default DungeonReadyGui;
\ No newline at end of file
diff --git a/src/features/betterGuis/index.js b/src/features/betterGuis/index.js
new file mode 100644
index 0000000..dcd8fb9
--- /dev/null
+++ b/src/features/betterGuis/index.js
@@ -0,0 +1,386 @@
+///
+///
+import Feature from "../../featureClass/class";
+import logger from "../../logger";
+import { f, m } from "../../../mappings/mappings";
+import ToggleSetting from "../settings/settingThings/toggle";
+import MuseumGui from "./museumGui.js";
+import DungeonReadyGui from "./dungeonReadyGui";
+import { SoopyGui } from "../../../guimanager";
+import TextBox from "../../../guimanager/GuiElement/TextBox";
+import SoopyNumber from "../../../guimanager/Classes/SoopyNumber";
+
+class BetterGuis extends Feature {
+ constructor() {
+ super();
+ }
+
+ inSkyblock() {
+ return this.FeatureManager.features["dataLoader"] && this.FeatureManager.features["dataLoader"].class.isInSkyblock;
+ }
+
+ onEnable() {
+ this.initVariables();
+
+ this.museumGui = new MuseumGui();
+ this.dungeonReady = new DungeonReadyGui();
+
+ this.replaceSbMenuClicks = new ToggleSetting("Improve Clicks on SBMENU", "This will change clicks to middle clicks, AND use commands where possible (eg /pets)", true, "sbmenu_clicks", this);
+ this.reliableSbMenuClicks = { getValue: () => false }//removed because hypixel fixed, code kept incase hypixel adds back bug later //new ToggleSetting("Make SBMENU clicks reliable", "This will delay clicks on sbmenu to time them so they dont get canceled", true, "sbmenu_time", this)
+
+ this.museumGuiEnabled = new ToggleSetting("Custom Museum GUI", "Custom gui for the Museum", true, "custom_museum_enabled", this);
+ this.dungeonReadyGuiEnabled = new ToggleSetting("Custom Dungeon Ready GUI", "Custom gui for the dungeon ready up menu", false, "custom_dungeon_ready_enabled", this);
+
+ this.chestSearchBar = new ToggleSetting("Inventory Search Bar", "use '&' to make it filter by stuff that contains multiple things", false, "inv_search", this);
+ this.customBars = new ToggleSetting("Custom hp and mana bar", "Also hides stuff like armor bar", false, "custom_bars", this);
+
+ this.lastWindowId = 0;
+ this.shouldHold = 10;
+ this.clickSlot = -1;
+ this.clickSlotTime = 0;
+
+ this.middleClickGuis = [
+ "Your SkyBlock Profile",
+ "Your Skills",
+ "Farming Skill",
+ "Mining Skill",
+ "Heart of the Mountain",
+ "Combat Skill",
+ "Foraging Skill",
+ "Fishing Skill",
+ "Enchanting Skill",
+ "Alchemy Skill",
+ "Carpentry Skill",
+ "Runecrafting Skill",
+ "Social Skill",
+ "Taming Skill",
+ "Dungeoneering",
+ "Your Essence",
+ "Healer Class Perks",
+ "Mage Class Perks",
+ "Beserk Class Perks",
+ "Archer Class Perks",
+ "Tank Class Perks",
+ "Recipe Book",
+ "Trades",
+ "Quest Log",
+ "Quest Log (Completed)",
+ "Fairt Souls Guide",
+ "Dungeon Journals",
+ "Calendar and Events",
+ "Booster Cookie",
+ "Island Management",
+ "Toggle Potion Effects",
+ "Bank",
+ "Bank Account Upgrades",
+ "Co-op Bank Account",
+ "Bank Deposit",
+ "Bank Withdrawal",
+ "Personal Bank Account",
+ "Bazaar Orders",
+ "Co-op Bazaar Orders",
+ "Pets"
+ ]
+ this.middleClickStartsWith = [
+ "Bestiary",
+ "Private Island",
+ "Hub",
+ "Spiders Den",
+ "Blazing Fortress",
+ "The End",
+ "Deep Caverns",
+ "The Park",
+ "Spooky Festival",
+ "Catacombs",
+ "The Catacombs",
+ "Settings",
+ "Bazaar",
+ "Farming",
+ "Mining",
+ "Woods & Fishes",
+ "Oddities"
+ ];
+ this.middleClickEndsWith = [
+ "Recipe",
+ "Recipes",
+ ") Pets",
+ "Collection",
+ "Active Effects"
+ ];
+
+ this.registerChat("&r&aDungeon starts in 1 second.&r", () =>
+ this.dungeonReady.readyInOneSecond.call(this.dungeonReady));
+ this.registerChat("&r&aDungeon starts in 1 second. Get ready!&r", () =>
+ this.dungeonReady.readyInOneSecond.call(this.dungeonReady));
+ this.registerEvent("guiMouseClick", this.guiClicked);
+ this.registerEvent("guiOpened", (event) => {
+ if (this.museumGuiEnabled.getValue()) this.museumGui.guiOpened.call(this.museumGui, event);
+ if (this.dungeonReadyGuiEnabled.getValue()) this.dungeonReady.guiOpened.call(this.dungeonReady, event);
+ });
+ this.registerEvent("worldLoad", () => this.dungeonReady.reset());
+ this.registerChat("&e${*} &r&cThe Catacombs &r&ewith &r&9${players}/5 players &r&eon &r${*}&r", (players) => {
+ if (this.dungeonReadyGuiEnabled.getValue()) this.dungeonReady.joinedDungeon.call(this.dungeonReady, ~~players);
+ })
+ this.registerChat("&eSkyBlock Dungeon Warp &r&7(${players} players)&r", (players) => {
+ if (this.dungeonReadyGuiEnabled.getValue()) this.dungeonReady.joinedDungeon.call(this.dungeonReady, ~~players)
+ })
+ this.registerStep(true, 10, this.step)
+ this.registerEvent("worldUnload", () => this.museumGui.saveMuseumCache.call(this.museumGui));
+ this.registerStep(false, 30, () => this.museumGui.saveMuseumCache.call(this.museumGui));
+
+
+ this.invSearchSoopyGui = new SoopyGui();
+ this.invSearchSoopyGui._renderBackground = () => { };
+
+ this.invSearchTextBox = new TextBox().setPlaceholder("Click to search").setLocation(0.4, 0.05, 0.2, 0.05);
+ this.invSearchSoopyGui.element.addChild(this.invSearchTextBox);
+
+ this.mana = new SoopyNumber(0);
+ this.overflowMana = new SoopyNumber(0);
+ this.maxMana = new SoopyNumber(0);
+ this.lastOverFlow = Date.now();
+
+ this.slotMatches = new Map();
+ this.registerEvent("renderHealth", this.renderHealth).registeredWhen(() => this.inSkyblock() && this.customBars.getValue());
+ this.registerEvent("renderFood", cancel).registeredWhen(() => this.inSkyblock() && this.customBars.getValue());
+ this.registerEvent("renderArmor", this.renderMana).registeredWhen(() => this.inSkyblock() && this.customBars.getValue());
+ let registerActionBar = this.registerCustom("actionbar", this.actionbarMana);
+ registerActionBar.trigger.setCriteria('&b${curr}/${max}✎').setParameter('contains');
+ let registerActionBar2 = this.registerCustom("actionbar", this.actionbarOverflowMana);
+ registerActionBar2.trigger.setCriteria('&3${curr}ʬ').setParameter('contains');
+ //&c2532/2532❤ &a798&a❈ Defense &b2525/2525✎ &31ʬ&r (100)
+ //&c2532/2532❤ &f20&f❂ True Defense &b2414/2414✎ &3600ʬ&r (13)
+ //&c2665/2665❤ &a972&a❈ Defense &b2145/2145✎ &3600ʬ&r
+ //&c2,806/2,806❤ &a1,050&a❈ Defense &b1,945/1,945✎ &3600ʬ&r
+ this.registerEvent("guiRender", this.postGuiRender).registeredWhen(() => this.chestSearchBar.getValue());
+ this.registerEvent("guiMouseClick", this.guiMouseClick).registeredWhen(() => this.chestSearchBar.getValue());
+ this.registerEvent("guiKey", this.guiKey).registeredWhen(() => this.chestSearchBar.getValue());
+ this.registerEvent("renderSlot", this.renderSlot).registeredWhen(() => this.chestSearchBar.getValue());
+ this.registerEvent("guiOpened", this.guiOpened).registeredWhen(() => this.chestSearchBar.getValue());
+ }
+
+ actionbarMana(curr, max) {
+ if (curr.includes("Mana"))
+ curr = curr.split("&b").pop();
+
+ this.mana.set(parseInt(curr.replace(/,/g, "")), 500);
+ this.maxMana.set(parseInt(max.replace(/,/g, "")), 500);
+ if (Date.now() - this.lastOverFlow > 1000) this.overflowMana.set(0, 500);
+ }
+
+ actionbarOverflowMana(curr) {
+ this.overflowMana.set(parseInt(curr.replace(/,/g, "")), 500);
+ this.lastOverFlow = Date.now();
+ }
+
+ renderMana(event) {
+ cancel(event);
+
+ let left = Renderer.screen.getWidth() / 2 + 91 - 80;
+ let top = Renderer.screen.getHeight() - 40;
+
+ Renderer.retainTransforms(true);
+ Renderer.translate(left, top);
+
+ let totalAmt = Math.max(this.maxMana.get(), this.mana.get() + this.overflowMana.get());
+
+ let manaPercent = this.mana.get() / totalAmt;
+ let ofPercent = this.overflowMana.get() / totalAmt;
+
+ Renderer.drawRect(Renderer.color(0, 0, 0), 0, 0, 80, 10);
+ Renderer.drawRect(Renderer.color(50, 50, 50), 2, 2, 76, 6);
+ Renderer.drawRect(Renderer.color(0, 0, 255), 2, 2, manaPercent * 76, 6);
+ Renderer.drawRect(Renderer.color(0, 255, 255), 2 + manaPercent * 76, 2, ofPercent * 76, 6);
+ Renderer.retainTransforms(false);
+ }
+
+ renderHealth(event) {
+ cancel(event);
+
+ let left = Renderer.screen.getWidth() / 2 - 91;
+ let top = Renderer.screen.getHeight() - 40;
+
+ Renderer.retainTransforms(true);
+ Renderer.translate(left, top);
+
+ let totalAmt = Math.max(Player.asPlayerMP().getMaxHP(), Player.getHP() + Player.asPlayerMP().getAbsorption());
+
+ let hpPercent = Player.getHP() / totalAmt;
+ let abPercent = Player.asPlayerMP().getAbsorption() / totalAmt;
+
+
+ Renderer.drawRect(Renderer.color(0, 0, 0), 0, 0, 80, 10);
+ Renderer.drawRect(Renderer.color(50, 50, 50), 2, 2, 76, 6);
+ Renderer.drawRect(Renderer.color(255, 0, 0), 2, 2, hpPercent * 76, 6);
+ Renderer.drawRect(Renderer.color(255, 255, 0), 2 + hpPercent * 76, 2, abPercent * 76, 6);
+
+ Renderer.retainTransforms(false);
+ }
+
+ postGuiRender(x, y, gui) {
+ if (gui instanceof net.minecraft.client.gui.inventory.GuiChest)
+ this.invSearchSoopyGui._render(x, y, 0);
+ }
+ guiMouseClick(x, y, button, gui) {
+ if (gui instanceof net.minecraft.client.gui.inventory.GuiChest)
+ this.invSearchSoopyGui._onClick(x, y, button);
+ }
+ guiKey(char, code, gui, event) {
+ if (!(gui instanceof net.minecraft.client.gui.inventory.GuiChest)) return;
+
+ this.invSearchSoopyGui._onKeyPress(char, code);
+
+ if (this.invSearchTextBox.text.selected) {
+ cancel(event);
+ this.slotMatches.clear();
+ }
+ }
+ guiOpened() {
+ this.slotMatches.clear();
+ }
+
+ renderSlot(slot, gui, event) {
+ if (!(gui instanceof net.minecraft.client.gui.inventory.GuiChest)) return;
+ if (!this.invSearchTextBox.getText()) return;
+
+ let searchText = this.invSearchTextBox.getText().toLowerCase();
+
+ let isMatching = false;
+ let slotMatches = this.slotMatches.get(slot.getIndex());
+ if (slotMatches && Date.now() - slotMatches.timestamp < 500) {
+ if (!slotMatches.isMatching) {
+ Renderer.translate(0, 0, 100);
+ Renderer.drawRect(Renderer.color(0, 0, 0, 200), slot.getDisplayX(), slot.getDisplayY(), 8 * Renderer.screen.getScale(), 8 * Renderer.screen.getScale());
+ }
+ return;
+ }
+ let item = slot.getItem();
+ if (item) {
+ isMatching = !searchText.split("&").map(a => {
+ a = a.trim();
+ let isMatching2 = false;
+ if (ChatLib.removeFormatting(item.getName()).toLowerCase().includes(a)) isMatching2 = true;
+ if (!isMatching2 && item.getLore().some(b => ChatLib.removeFormatting(b).toLowerCase().includes(a))) isMatching2 = true;
+ return isMatching2;
+ }).includes(false);
+ }
+
+ this.slotMatches.set(slot.getIndex(), { isMatching, timestamp: Date.now() });
+
+ if (!isMatching) {
+ Renderer.translate(0, 0, 100);
+ Renderer.drawRect(Renderer.color(0, 0, 0, 200), slot.getDisplayX(), slot.getDisplayY(), 8 * Renderer.screen.getScale(), 8 * Renderer.screen.getScale());
+ }
+ }
+
+ guiClicked(mouseX, mouseY, button, gui, event) {
+ if (!(gui instanceof net.minecraft.client.gui.inventory.GuiChest) || button !== 0 || !this.replaceSbMenuClicks.getValue()) return;
+
+ let hoveredSlot = gui.getSlotUnderMouse();
+ if (!hoveredSlot) return;
+
+ let hoveredSlotId = hoveredSlot[f.slotNumber];
+
+ // logger.logMessage(hoveredSlotId, 4)
+
+ if (this.guiSlotClicked(ChatLib.removeFormatting(Player.getContainer().getName()), hoveredSlotId))
+ cancel(event);
+ }
+
+ step() {
+ if (this.museumGuiEnabled.getValue()) this.museumGui.tick.call(this.museumGui);
+ if (this.dungeonReadyGuiEnabled.getValue()) this.dungeonReady.tick.call(this.dungeonReady);
+
+ if (!this.replaceSbMenuClicks.getValue()) return
+ if (Player.getContainer() && Player.getContainer().getName() !== "SkyBlock Menu") {
+ this.lastWindowId = 0;
+ return;
+ }
+ if (this.lastWindowId === 0) {
+ this.lastWindowId = Player.getContainer().getWindowId();
+ return;
+ }
+ if (Player.getContainer().getWindowId() === this.lastWindowId) {
+ this.shouldHold--
+ return;
+ }
+
+ this.lastWindowId = Player.getContainer().getWindowId();
+ this.shouldHold += 10;
+ if (Date.now() - this.clickSlotTime > 1000) {
+ this.clickSlot = -1;
+ }
+ if (this.clickSlot && this.clickSlot != -1) {
+ Player.getContainer().click(this.clickSlot, false, "MIDDLE");
+ this.clickSlot = -1;
+ }
+ }
+
+ guiSlotClicked(inventoryName, slotId) {
+ if (inventoryName.endsWith(" Sack")) return false
+ switch (inventoryName) {
+ case "SkyBlock Menu":
+ switch (slotId) {
+ case 30:
+ ChatLib.command("pets")
+ break
+ case 25:
+ ChatLib.command("storage")
+ break
+ default:
+ if (this.shouldHold > 0 && this.reliableSbMenuClicks.getValue()) {
+ this.clickSlot = slotId
+ this.clickSlotTime = Date.now()
+ } else {
+ Player.getContainer().click(slotId, false, "MIDDLE")
+ }
+ break;
+ }
+ return true
+ break
+ default:
+ if (this.middleClickGuis.includes(inventoryName)) {
+ Player.getContainer().click(slotId, false, "MIDDLE")
+ return true
+ }
+ for (let thing of this.middleClickStartsWith) {
+ if (inventoryName.startsWith(thing)) {
+ Player.getContainer().click(slotId, false, "MIDDLE")
+ return true
+ }
+ }
+ for (let thing of this.middleClickEndsWith) {
+ if (inventoryName.endsWith(thing)) {
+ Player.getContainer().click(slotId, false, "MIDDLE")
+ return true
+ }
+ }
+ return false
+ break
+ }
+ }
+
+ initVariables() {
+ this.replaceSbMenuClicks = undefined;
+ this.lastWindowId = undefined;
+ this.shouldHold = undefined;
+ this.clickSlot = undefined;
+ this.clickSlotTime = undefined;
+ this.reliableSbMenuClicks = undefined;
+ this.middleClickGuis = undefined;
+ this.middleClickStartsWith = undefined;
+ this.middleClickEndsWith = undefined;
+
+ this.museumGui = undefined;
+ }
+
+ onDisable() {
+ this.initVariables();
+
+ this.invSearchSoopyGui.delete();
+ }
+}
+
+module.exports = {
+ class: new BetterGuis()
+}
\ No newline at end of file
diff --git a/src/features/betterGuis/metadata.json b/src/features/betterGuis/metadata.json
new file mode 100644
index 0000000..6aeed27
--- /dev/null
+++ b/src/features/betterGuis/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Better guis",
+ "description": "Edits to a bunch of guis to make them nicer to use",
+ "isHidden": false,
+ "isTogglable": true,
+ "defaultEnabled": true,
+ "sortA": 1
+}
\ No newline at end of file
diff --git a/src/features/betterGuis/museumGui.js b/src/features/betterGuis/museumGui.js
new file mode 100644
index 0000000..06497af
--- /dev/null
+++ b/src/features/betterGuis/museumGui.js
@@ -0,0 +1,1024 @@
+import { SoopyGui, SoopyRenderEvent } from "../../../guimanager"
+import SoopyContentChangeEvent from "../../../guimanager/EventListener/SoopyContentChangeEvent"
+import SoopyHoverChangeEvent from "../../../guimanager/EventListener/SoopyHoverChangeEvent"
+import SoopyKeyPressEvent from "../../../guimanager/EventListener/SoopyKeyPressEvent"
+import SoopyMouseClickEvent from "../../../guimanager/EventListener/SoopyMouseClickEvent"
+import SoopyOpenGuiEvent from "../../../guimanager/EventListener/SoopyOpenGuiEvent"
+import BoxWithText from "../../../guimanager/GuiElement/BoxWithText"
+import ButtonWithArrow from "../../../guimanager/GuiElement/ButtonWithArrow"
+import ProgressBar from "../../../guimanager/GuiElement/ProgressBar"
+import SoopyBoxElement from "../../../guimanager/GuiElement/SoopyBoxElement"
+import SoopyGuiElement from "../../../guimanager/GuiElement/SoopyGuiElement"
+import SoopyMarkdownElement from "../../../guimanager/GuiElement/SoopyMarkdownElement"
+import SoopyTextElement from "../../../guimanager/GuiElement/SoopyTextElement"
+import TextBox from "../../../guimanager/GuiElement/TextBox"
+import Notification from "../../../guimanager/Notification"
+import renderLibs from "../../../guimanager/renderLibs"
+import { m } from "../../../mappings/mappings"
+import * as utils from "../../utils/utils"
+
+
+const ContainerChest = Java.type("net.minecraft.inventory.ContainerChest")
+
+class MuseumGui {
+ constructor() {
+ this.checkMenu = false
+
+ this.isInMuseum = false
+ this.guiOpenTickThing = false
+ this.dontOpen = 0
+ this.lastClosed = 0
+ this.itemsInPages = JSON.parse(FileLib.read("soopyAddonsData", "museumItemsCache.json") || "{}") || {}
+ this.itemsInPagesSaved = true
+
+ this.soopyGui = new SoopyGui()
+
+ this.soopyGui.optimisedLocations = true
+
+ this.soopyGui.element.addEvent(new SoopyKeyPressEvent().setHandler((...args) => {
+ this.keyPress(...args)
+ }))
+
+ this.mainPage = new SoopyGuiElement().setLocation(0, 0, 1, 1)
+ this.soopyGui.element.addChild(this.mainPage)
+
+ let widthPer = 0.2
+ let leftOffset = (1 - widthPer * 3 - widthPer * 4 / 5) / 2
+
+ this.weaponsIndicator = new SoopyBoxElement().setLocation(leftOffset, 0.05, widthPer * 4 / 5, 0.15)
+ this.weaponsIndicator.addEvent(new SoopyRenderEvent().setHandler(() => {
+ if (this.weaponsIndicator.hovered && ChatLib.removeFormatting(Player.getContainer().getStackInSlot(4).getName()) !== "Weapons") {
+ this.weaponText.location.location.x.set(0.05, 500)
+ this.weaponText.location.size.x.set(0.9, 500)
+ this.weaponText.location.location.y.set(0.025, 500)
+ this.weaponText.location.size.y.set(0.35, 500)
+
+ this.weaponsIndicator.setColorOffset(-20, -20, -20, 100)
+
+ Renderer.translate(0, 0, 100)
+ Renderer.drawRect(Renderer.color(0, 0, 0, 100), this.weaponsIndicator.location.getXExact(), this.weaponsIndicator.location.getYExact(), this.weaponsIndicator.location.getWidthExact(), this.weaponsIndicator.location.getHeightExact())
+ let clicks = Player.getContainer().getName() === "Your Museum" ? "1" : "2"
+ Renderer.translate(0, 0, 100)
+ renderLibs.drawStringCenteredFull(clicks, this.weaponsIndicator.location.getXExact() + this.weaponsIndicator.location.getWidthExact() / 2, this.weaponsIndicator.location.getYExact() + this.weaponsIndicator.location.getHeightExact() / 2, Math.min(this.weaponsIndicator.location.getWidthExact() / Renderer.getStringWidth(clicks) / 4, this.weaponsIndicator.location.getHeightExact() / 4 / 2))
+ } else {
+ this.weaponText.location.location.x.set(0.1, 500)
+ this.weaponText.location.size.x.set(0.8, 500)
+ this.weaponText.location.location.y.set(0.05, 500)
+ this.weaponText.location.size.y.set(0.3, 500)
+
+ this.weaponsIndicator.setColorOffset(0, 0, 0, 100)
+ }
+ })).addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.clickedTopButton("Weapons")
+ }))
+
+ this.weaponText = new SoopyTextElement().setText("§5Weapons").setMaxTextScale(10).setLocation(0.1, 0.05, 0.8, 0.3)
+ this.weaponsIndicator.addChild(this.weaponText)
+ this.weaponsPercentageText = new SoopyTextElement().setLocation(0.1, 0.4, 0.8, 0.2).setText("§0Items Donated: §7Loading...").setMaxTextScale(10)
+ this.weaponsIndicator.addChild(this.weaponsPercentageText)
+ this.weaponsProgressBar = new ProgressBar().setLocation(0.1, 0.6, 0.8, 0.35).showPercentage(true)
+ this.weaponsIndicator.addChild(this.weaponsProgressBar)
+ this.mainPage.addChild(this.weaponsIndicator)
+
+ this.armourIndicator = new SoopyBoxElement().setLocation(leftOffset + widthPer, 0.05, widthPer * 4 / 5, 0.15)
+ this.armourIndicator.addEvent(new SoopyRenderEvent().setHandler(() => {
+ if (this.armourIndicator.hovered && ChatLib.removeFormatting(Player.getContainer().getStackInSlot(4).getName()) !== "Armor Sets") {
+ this.armourText.location.location.x.set(0.05, 500)
+ this.armourText.location.size.x.set(0.9, 500)
+ this.armourText.location.location.y.set(0.025, 500)
+ this.armourText.location.size.y.set(0.35, 500)
+
+ this.armourIndicator.setColorOffset(-20, -20, -20, 100)
+
+ Renderer.translate(0, 0, 100)
+ Renderer.drawRect(Renderer.color(0, 0, 0, 100), this.armourIndicator.location.getXExact(), this.armourIndicator.location.getYExact(), this.armourIndicator.location.getWidthExact(), this.armourIndicator.location.getHeightExact())
+ let clicks = Player.getContainer().getName() === "Your Museum" ? "1" : "2"
+ Renderer.translate(0, 0, 100)
+ renderLibs.drawStringCenteredFull(clicks, this.armourIndicator.location.getXExact() + this.armourIndicator.location.getWidthExact() / 2, this.armourIndicator.location.getYExact() + this.armourIndicator.location.getHeightExact() / 2, Math.min(this.armourIndicator.location.getWidthExact() / Renderer.getStringWidth(clicks) / 4, this.armourIndicator.location.getHeightExact() / 4 / 2))
+ } else {
+ this.armourText.location.location.x.set(0.1, 500)
+ this.armourText.location.size.x.set(0.8, 500)
+ this.armourText.location.location.y.set(0.05, 500)
+ this.armourText.location.size.y.set(0.3, 500)
+
+ this.armourIndicator.setColorOffset(0, 0, 0, 100)
+ }
+ })).addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.clickedTopButton("Armor Sets")
+ }))
+
+ this.armourText = new SoopyTextElement().setText("§5Armor Sets").setMaxTextScale(10).setLocation(0.1, 0.05, 0.8, 0.3)
+ this.armourIndicator.addChild(this.armourText)
+ this.armourPercentageText = new SoopyTextElement().setLocation(0.1, 0.4, 0.8, 0.2).setText("§0Items Donated: §7Loading...").setMaxTextScale(10)
+ this.armourIndicator.addChild(this.armourPercentageText)
+ this.armourProgressBar = new ProgressBar().setLocation(0.1, 0.6, 0.8, 0.35).showPercentage(true)
+ this.armourIndicator.addChild(this.armourProgressBar)
+ this.mainPage.addChild(this.armourIndicator)
+
+ this.raritiesIndicator = new SoopyBoxElement().setLocation(leftOffset + widthPer * 2, 0.05, widthPer * 4 / 5, 0.15)
+ this.raritiesIndicator.addEvent(new SoopyRenderEvent().setHandler(() => {
+ if (this.raritiesIndicator.hovered && ChatLib.removeFormatting(Player.getContainer().getStackInSlot(4).getName()) !== "Rarities") {
+ this.raritiesText.location.location.x.set(0.05, 500)
+ this.raritiesText.location.size.x.set(0.9, 500)
+ this.raritiesText.location.location.y.set(0.025, 500)
+ this.raritiesText.location.size.y.set(0.35, 500)
+
+ this.raritiesIndicator.setColorOffset(-20, -20, -20, 100)
+
+ Renderer.translate(0, 0, 100)
+ Renderer.drawRect(Renderer.color(0, 0, 0, 100), this.raritiesIndicator.location.getXExact(), this.raritiesIndicator.location.getYExact(), this.raritiesIndicator.location.getWidthExact(), this.raritiesIndicator.location.getHeightExact())
+ let clicks = Player.getContainer().getName() === "Your Museum" ? "1" : "2"
+ Renderer.translate(0, 0, 100)
+ renderLibs.drawStringCenteredFull(clicks, this.raritiesIndicator.location.getXExact() + this.raritiesIndicator.location.getWidthExact() / 2, this.raritiesIndicator.location.getYExact() + this.raritiesIndicator.location.getHeightExact() / 2, Math.min(this.raritiesIndicator.location.getWidthExact() / Renderer.getStringWidth(clicks) / 4, this.raritiesIndicator.location.getHeightExact() / 4 / 2))
+ } else {
+ this.raritiesText.location.location.x.set(0.1, 500)
+ this.raritiesText.location.size.x.set(0.8, 500)
+ this.raritiesText.location.location.y.set(0.05, 500)
+ this.raritiesText.location.size.y.set(0.3, 500)
+
+ this.raritiesIndicator.setColorOffset(0, 0, 0, 100)
+ }
+ })).addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.clickedTopButton("Rarities")
+ }))
+
+ this.raritiesText = new SoopyTextElement().setText("§5Rarities").setMaxTextScale(10).setLocation(0.1, 0.05, 0.8, 0.3)
+ this.raritiesIndicator.addChild(this.raritiesText)
+ this.raritiesPercentageText = new SoopyTextElement().setLocation(0.1, 0.4, 0.8, 0.2).setText("§0Items Donated: §7Loading...").setMaxTextScale(10)
+ this.raritiesIndicator.addChild(this.raritiesPercentageText)
+ this.raritiesProgressBar = new ProgressBar().setLocation(0.1, 0.6, 0.8, 0.35).showPercentage(true)
+ this.raritiesIndicator.addChild(this.raritiesProgressBar)
+ this.mainPage.addChild(this.raritiesIndicator)
+
+ this.specialIndicator = new SoopyBoxElement().setLocation(leftOffset + widthPer * 3, 0.05, widthPer * 4 / 5, 0.15)
+ this.specialIndicator.addEvent(new SoopyRenderEvent().setHandler(() => {
+ if (this.specialIndicator.hovered && ChatLib.removeFormatting(Player.getContainer().getStackInSlot(4).getName()) !== "Special Items") {
+ this.specialText.location.location.x.set(0.05, 500)
+ this.specialText.location.size.x.set(0.9, 500)
+ this.specialText.location.location.y.set(0.025, 500)
+ this.specialText.location.size.y.set(0.35, 500)
+
+ this.specialIndicator.setColorOffset(-20, -20, -20, 100)
+
+ Renderer.translate(0, 0, 100)
+ Renderer.drawRect(Renderer.color(0, 0, 0, 100), this.specialIndicator.location.getXExact(), this.specialIndicator.location.getYExact(), this.specialIndicator.location.getWidthExact(), this.specialIndicator.location.getHeightExact())
+ let clicks = Player.getContainer().getName() === "Your Museum" ? "1" : "2"
+ Renderer.translate(0, 0, 100)
+ renderLibs.drawStringCenteredFull(clicks, this.specialIndicator.location.getXExact() + this.specialIndicator.location.getWidthExact() / 2, this.specialIndicator.location.getYExact() + this.specialIndicator.location.getHeightExact() / 2, Math.min(this.specialIndicator.location.getWidthExact() / Renderer.getStringWidth(clicks) / 4, this.specialIndicator.location.getHeightExact() / 4 / 2))
+
+ } else {
+ this.specialText.location.location.x.set(0.1, 500)
+ this.specialText.location.size.x.set(0.8, 500)
+ this.specialText.location.location.y.set(0.05, 500)
+ this.specialText.location.size.y.set(0.3, 500)
+
+ this.specialIndicator.setColorOffset(0, 0, 0, 100)
+ }
+ })).addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.clickedTopButton("Special Items")
+ }))
+
+ this.specialText = new SoopyTextElement().setText("§5Special Items").setMaxTextScale(10).setLocation(0.1, 0.05, 0.8, 0.3)
+ this.specialIndicator.addChild(this.specialText)
+ this.specialPercentageText = new SoopyTextElement().setLocation(0.1, 0.4, 0.8, 0.6).setText("§0Items Donated: §7Loading...").setMaxTextScale(10)
+ this.specialIndicator.addChild(this.specialPercentageText)
+ this.mainPage.addChild(this.specialIndicator)
+
+ let box = new SoopyBoxElement().setLocation(0.5 - widthPer * 0.75, 0.25, widthPer * 2 * 0.75, 0.075).setLore(["Click to search"])
+ this.pageTitle = new SoopyTextElement().setText("§5Your Museum").setMaxTextScale(10).setLocation(0, 0, 1, 1)
+ box.addChild(this.pageTitle)
+ this.mainPage.addChild(box)
+
+ this.searchText = ""
+ let search = new TextBox().setLocation(0.5 - widthPer * 0.75, 0.25, widthPer * 2 * 0.75, 0.075)
+ box.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ box.visable = false
+ search.visable = true
+ search.select()
+ }))
+ search.visable = false
+ search.text.mouseClickG = (mouseX, mouseY) => {
+ if (search.text.selected && !this.searchText) {
+ box.visable = true
+ search.visable = false
+ }
+ search.text.selected = false
+ }
+ search.text.addEvent(new SoopyContentChangeEvent().setHandler((newVal, oldVal, resetFunction) => {
+ this.searchText = newVal
+ this.showSearchItems()
+ }))
+ this.mainPage.addChild(search)
+ this.mainPage.addEvent(new SoopyOpenGuiEvent().setHandler(() => {
+ box.visable = true
+ search.visable = false
+ search.text.selected = false
+ search.setText("")
+ this.searchText = ""
+ }))
+
+ this.nextButton = new ButtonWithArrow().setLocation(0.5 + widthPer * 3 / 2 - widthPer / 2, 0.25, widthPer / 2, 0.075).setText("§0Next Page")
+ this.nextButton.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ if (this.nextButton.visable) this.nextPage()
+ }))
+ this.mainPage.addChild(this.nextButton)
+
+ this.previousButton = new ButtonWithArrow().setLocation(0.5 - widthPer * 3 / 2, 0.25, widthPer / 2, 0.075).setText("§0Previous Page").setDirectionRight(false)
+ this.previousButton.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ if (this.previousButton.visable) this.previousPage()
+ }))
+ this.mainPage.addChild(this.previousButton)
+
+ this.nextButton.visable = false
+ this.previousButton.visable = false
+
+ this.donateTitleBox = new SoopyBoxElement().setLocation(0.5 + widthPer * 3 / 2 + 0.025, 0.25, 0.5 - widthPer * 1.5 - 0.05, 0.075)
+ let donateTitle = new SoopyTextElement().setText("§5Donate").setMaxTextScale(10).setLocation(0, 0, 1, 1)
+
+ this.donateTitleBox.addChild(donateTitle)
+ this.mainPage.addChild(this.donateTitleBox)
+
+ this.donateBox = new SoopyBoxElement().setLocation(0.5 + widthPer * 3 / 2 + 0.025, 0.35, 0.5 - widthPer * 1.5 - 0.05, 0.6).setScrollable(true).enableFrameBuffer()
+ this.mainPage.addChild(this.donateBox)
+
+ this.favoriteTitleBox = new SoopyBoxElement().setLocation(0.025, 0.25, 0.5 - widthPer * 1.5 - 0.05, 0.075)
+ let favoriteTitle = new SoopyTextElement().setText("§5Favourite Items").setMaxTextScale(10).setLocation(0, 0, 1, 1)
+
+ this.favoriteTitleBox.addChild(favoriteTitle)
+ this.mainPage.addChild(this.favoriteTitleBox)
+
+ this.favoriteBox = new SoopyBoxElement().setLocation(0.025, 0.35, 0.5 - widthPer * 1.5 - 0.05, 0.6).setScrollable(true).enableFrameBuffer()
+ this.mainPage.addChild(this.favoriteBox)
+
+ this.itemsBox = new SoopyBoxElement().setLocation(0.5 - widthPer * 3 / 2, 0.35, widthPer * 3, 0.6).enableFrameBuffer()
+ this.mainPage.addChild(this.itemsBox)
+
+ new Array(this.donateBox, this.favoriteBox, this.itemsBox).forEach((box, i) => {
+ box.addEvent(new SoopyHoverChangeEvent().setHandler((hovered) => {
+ if (i === 2) {
+ if (this.searchText) {
+
+ } else {
+ box.enableFrameBuffer()
+ return
+ }
+ }
+ if (hovered) {
+ box.disableFrameBuffer()
+ } else {
+ box.enableFrameBuffer()
+ box.dirtyFrameBuffer(1000)
+ }
+ }))
+ })
+
+ this.donateItems = []
+
+ this.confirm_temp = ""
+
+ this.replacePage = {
+ "Your Museum": "Museum",
+ " Weapons": "Weapons",
+ " Armor Sets": "Armor Sets",
+ " Rarities": "Rarities",
+ " Special Items": "Special Items"
+ }
+
+ this.tickI = 0
+
+ this.lastGuiTitle = ""
+
+ this.favoriteItems = JSON.parse(FileLib.read("soopyAddonsData", "museumFavoriteData.json") || "[]") || []
+ this.favoriteIds = this.favoriteItems.map(a => a.sb_id)
+ this.updatedFavorites(false)
+ }
+
+ saveMuseumCache() {
+ //Called on worldUnload, and ever 30 seconds
+ if (this.itemsInPagesSaved) return
+ this.itemsInPagesSaved = true
+
+ new Thread(() => {
+ FileLib.write("soopyAddonsData", "museumItemsCache.json", JSON.stringify(this.itemsInPages))
+ }).start()
+ }
+
+ clickedTopButton(type) {
+ if (ChatLib.removeFormatting(Player.getContainer().getStackInSlot(4).getName()) === type) return
+
+ if (Player.getContainer().getName() === "Your Museum") {
+ //if on main page can just directly click on it
+ switch (type) {
+ case "Weapons":
+ Player.getContainer().click(19, false, "MIDDLE")
+ break
+ case "Armor Sets":
+ Player.getContainer().click(21, false, "MIDDLE")
+ break
+ case "Rarities":
+ Player.getContainer().click(23, false, "MIDDLE")
+ break
+ case "Special Items":
+ Player.getContainer().click(25, false, "MIDDLE")
+ break
+ }
+ } else {
+ Player.getContainer().click(48, false, "MIDDLE")
+ }
+ }
+
+ nextPage() {
+ let itempages = ["Weapons", "Armor Sets", "Rarities", "Special Items"]
+ if (itempages.includes(this.replacePage[Player.getContainer().getName().split("➜").pop()])) {
+ Player.getContainer().click(53, false, "MIDDLE")
+
+ let [currPage, pageNum] = Player.getContainer().getName().split(")")[0].split("(")[1].split("/").map(a => parseInt(a))
+ this.regenItems(currPage + 1)
+ }
+ }
+
+ previousPage() {
+ let itempages = ["Weapons", "Armor Sets", "Rarities", "Special Items"]
+ if (itempages.includes(this.replacePage[Player.getContainer().getName().split("➜").pop()])) {
+ Player.getContainer().click(45, false, "MIDDLE")
+
+ let [currPage, pageNum] = Player.getContainer().getName().split(")")[0].split("(")[1].split("/").map(a => parseInt(a))
+ this.regenItems(currPage - 1)
+ }
+ }
+
+ tickMenu(first = false) {
+ if (!first && (this.tickI++) % 5 !== 0) {
+ if (this.lastGuiTitle === Player.getContainer().getName()) {
+ return
+ }
+ }
+ this.lastGuiTitle = Player.getContainer().getName()
+
+ if (Player.getContainer().getName() === "Your Museum") {//main page
+ if (!Player.getContainer().getStackInSlot(19)) return
+
+ let lore = Player.getContainer().getStackInSlot(19).getLore()
+ lore.forEach((line, i) => {
+ if (i === 0) return
+
+ if (line.split(" ")?.[1]?.includes("/")) {
+ let data = ChatLib.removeFormatting(line).split(" ")[1].split("/")
+
+ this.weaponsProgressBar.setProgress(parseInt(data[0]) / parseInt(data[1]))
+ this.weaponsPercentageText.setText("§0Items Donated: §7" + data[0] + "/" + data[1])
+ }
+ })
+ this.weaponsIndicator.setLore(lore)
+
+ lore = Player.getContainer().getStackInSlot(21).getLore()
+ lore.forEach((line, i) => {
+ if (i === 0) return
+
+ if (line.split(" ")?.[1]?.includes("/")) {
+ let data = ChatLib.removeFormatting(line).split(" ")[1].split("/")
+
+ this.armourProgressBar.setProgress(parseInt(data[0]) / parseInt(data[1]))
+ this.armourPercentageText.setText("§0Items Donated: §7" + data[0] + "/" + data[1])
+ }
+ })
+ this.armourIndicator.setLore(lore)
+
+ lore = Player.getContainer().getStackInSlot(23).getLore()
+ lore.forEach((line, i) => {
+ if (i === 0) return
+
+ if (line.split(" ")?.[1]?.includes("/")) {
+ let data = ChatLib.removeFormatting(line).split(" ")[1].split("/")
+
+ this.raritiesProgressBar.setProgress(parseInt(data[0]) / parseInt(data[1]))
+ this.raritiesPercentageText.setText("§0Items Donated: §7" + data[0] + "/" + data[1])
+ }
+ })
+ this.raritiesIndicator.setLore(lore)
+
+ lore = Player.getContainer().getStackInSlot(25).getLore()
+ lore.forEach((line, i) => {
+ if (i === 0) return
+
+ if (ChatLib.removeFormatting(line).startsWith("Items Donated: ")) {
+ this.specialPercentageText.setText("§0Items Donated: §7" + ChatLib.removeFormatting(line).split(": ")[1])
+ }
+ })
+ this.specialIndicator.setLore(lore)
+
+ if ((this.pageTitle.text !== ("§5" + Player.getContainer().getName()) || first) && !this.searchText) {
+ this.itemsBox.clearChildren()
+ let rewardsButton = new ButtonWithArrow().setText("§5Rewards").setLocation(0.1, 0.05, 0.8, 0.2)
+ rewardsButton.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ Player.getContainer().click(40, false, "MIDDLE")
+ }))
+ this.itemsBox.addChild(rewardsButton)
+ let browserButton = new ButtonWithArrow().setText("§5Museum Browser").setLocation(0.1, 0.3, 0.8, 0.2)
+ browserButton.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ Player.getContainer().click(50, false, "MIDDLE")
+ }))
+ this.itemsBox.addChild(browserButton)
+
+ this.itemsBox.dirtyFrameBuffer()
+ }
+ }
+
+ this.nextButton.visable = false
+ this.previousButton.visable = false
+
+ this.donateTitleBox.visable = false
+ this.donateBox.visable = false
+
+ let itempages = ["Weapons", "Armor Sets", "Rarities", "Special Items"]
+ if (itempages.includes(this.replacePage[Player.getContainer().getName().split("➜").pop()])) {
+ let page = this.replacePage[Player.getContainer().getName().split("➜").pop()]
+ let currPage = 0
+ let pageNum = Player.getContainer().getStackInSlot(4) ? Math.ceil(ChatLib.removeFormatting(Player.getContainer().getStackInSlot(4).getLore().pop().split("/").pop()) / 28) : 0
+
+ // {
+ // let item = Player.getContainer().getStackInSlot(45)
+ // if (item) {
+ // let lore = item.getLore()
+ // let lastLine = ChatLib.removeFormatting(lore[lore.length - 1]).trim()
+ // let num = lastLine.match(/(\d+)$/g)
+ // currPage = parseInt(num) + 1
+ // }
+ // }
+ // {
+ // let item = Player.getContainer().getStackInSlot(53)
+ // if (item) {
+ // let lore = item.getLore()
+ // let lastLine = ChatLib.removeFormatting(lore[lore.length - 1]).trim()
+ // let num = lastLine.match(/(\d+)$/g)
+ // currPage = parseInt(num) - 1
+ // }
+ // }
+ console.log(currPage, pageNum)
+
+ if (!this.searchText) {
+ if (currPage > 1) {
+ this.previousButton.visable = true
+ if (Player.getContainer().getStackInSlot(45)) this.previousButton.setLore(Player.getContainer().getStackInSlot(45).getLore())
+ }
+ if (currPage < pageNum) {
+ this.nextButton.visable = true
+ if (Player.getContainer().getStackInSlot(53)) this.nextButton.setLore(Player.getContainer().getStackInSlot(53).getLore())
+ }
+ }
+
+ this.donateTitleBox.visable = true
+ this.donateBox.visable = true
+ let oldDonateItems = JSON.stringify(this.donateItems)
+ this.donateItems = []
+ let donateArmorSets = {}
+ let slot = 0
+ for (let item of Player.getContainer().getItems()) {
+ if (!item) continue
+ if (item.getID() === -1) continue
+ let lore = item.itemStack[m.getTooltip](Player.getPlayer(), false)
+ for (let line of lore) {
+ if (ChatLib.removeFormatting(line) === "Click to donate item!") {
+ let sb_id = utils.getSBID(item)
+
+ this.donateItems.push({
+ sb_id: sb_id || "NA",
+ name: item.getName() || "",
+ lore: item.getLore() || [],
+ slot: slot
+ })
+ }
+ if (ChatLib.removeFormatting(line) === "Click to donate armor set!") {
+ let sb_id = utils.getSBID(item)
+
+ let setId = sb_id.split("_")
+ setId.pop()
+ setId = setId.join("_")
+
+ donateArmorSets[setId] = (donateArmorSets[setId] || 0) + 1
+
+ if (donateArmorSets[setId] === 3) {
+ this.donateItems.push({
+ sb_id: sb_id || "NA",
+ name: item.getName() || "",
+ lore: item.getLore() || [],
+ slot: slot
+ })
+ }
+
+ }
+ }
+ slot++
+ }
+ if (oldDonateItems !== JSON.stringify(this.donateItems)) {
+ this.regenDonateItems()
+ }
+
+ if (!this.itemsInPages[page]) this.itemsInPages[page] = []
+
+ //10-16 43
+ let changed = false
+ for (let i = 0; i < 4; i++) {
+ for (let j = 10; j < 17; j++) {
+ let slot = i * 9 + j
+ let item = Player.getContainer().getStackInSlot(slot)
+ let sb_id = utils.getSBID(item)
+ if (!this.itemsInPages[page][currPage]) this.itemsInPages[page][currPage] = []
+
+ if (item && item.getID() !== -1) {
+
+ let itemData = {
+ sb_id: "NA",
+ name: item.getName() || "",
+ lore: item.getLore() || []
+ }
+
+ if (sb_id) {
+ itemData.sb_id = sb_id
+ }
+ if (!this.itemsInPages[page][currPage][slot] || this.itemsInPages[page][currPage][slot].sb_id !== itemData.sb_id) {
+ this.itemsInPages[page][currPage][slot] = itemData
+
+ changed = true
+ this.itemsInPagesSaved = false
+ }
+ } else {
+ if (this.itemsInPages[page][currPage][slot]) {
+ delete this.itemsInPages[page][currPage][slot]
+
+ changed = true
+ this.itemsInPagesSaved = false
+ }
+ }
+ }
+ }
+ if (changed || this.guiUpdated || first) this.regenItems(currPage)
+ }
+
+ if (Player.getContainer().getName() === "Confirm Donation") {
+ let this_confirm_temp_str = (Player.getContainer().getStackInSlot(4)?.getName() || "") + (Player.getContainer().getStackInSlot(2)?.getName() || "") + (Player.getContainer().getStackInSlot(20)?.getName() || "") + (Player.getContainer().getStackInSlot(24)?.getName() || "")//4, 24, 20
+ if (this.confirm_temp !== this_confirm_temp_str || first) {
+ this.confirm_temp = this_confirm_temp_str
+
+ this.itemsBox.clearChildren()
+
+ let isArmour = utils.getSBID(Player.getContainer().getStackInSlot(4)) === null
+ if (isArmour) {
+ let name = Player.getContainer().getStackInSlot(2).getName()
+ let itemBox = new BoxWithText().setText(name.startsWith("§f") ? "&7" + name.substr(2) : name).setLocation(0.1, 0.05, 0.8, 0.2).setLore(Player.getContainer().getStackInSlot(2).getLore())
+
+ this.itemsBox.addChild(itemBox)
+ } else {
+ let name = Player.getContainer().getStackInSlot(4).getName()
+ let itemBox = new BoxWithText().setText(name.startsWith("§f") ? "&7" + name.substr(2) : name).setLocation(0.1, 0.05, 0.8, 0.2).setLore(Player.getContainer().getStackInSlot(4).getLore())
+
+ this.itemsBox.addChild(itemBox)
+ }
+
+ if (Player.getContainer().getStackInSlot(24) && Player.getContainer().getStackInSlot(20)) {
+
+ let cancelButton = new ButtonWithArrow().setText("§cCancel").setLocation(0.1, 0.4, 0.35, 0.2).setDirectionRight(false).setLore(Player.getContainer().getStackInSlot(24).getLore())
+ cancelButton.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ Player.getContainer().click(24, false, "LEFT")
+ }))
+ this.itemsBox.addChild(cancelButton)
+
+ let confirmButton = new ButtonWithArrow().setText("§aConfirm Donation").setLocation(0.55, 0.4, 0.35, 0.2).setLore(Player.getContainer().getStackInSlot(20).getLore())
+ confirmButton.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ Player.getContainer().click(20, false, "LEFT")
+ }))
+ this.itemsBox.addChild(confirmButton)
+ }
+
+ this.itemsBox.dirtyFrameBuffer()
+ }
+
+ this.favoriteBox.visable = false
+ this.favoriteTitleBox.visable = false
+ } else {
+ if (this.confirm_temp && this.searchText) {
+ this.showSearchItems()
+ }
+ this.confirm_temp = ""
+
+ this.favoriteBox.visable = true
+ this.favoriteTitleBox.visable = true
+ }
+
+ this.pageTitle.setText("§5" + Player.getContainer().getName())
+ this.guiUpdated = false
+ }
+
+ regenDonateItems() {
+ this.donateBox.clearChildren()
+ this.donateItems.forEach((item, i) => {
+ let itemButton = new ButtonWithArrow().setText(item.name.startsWith("§f") ? "&7" + item.name.substr(2) : item.name).setLocation(0.05, 0.025 + 0.125 * i, 0.9, 0.1).setLore(item.lore)
+ itemButton.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ Player.getContainer().click(item.slot, false, "LEFT")
+ }))
+ this.donateBox.addChild(itemButton)
+ })
+
+ this.donateBox.dirtyFrameBuffer()
+ }
+
+ showSearchItems() {
+ if (Player.getContainer().getName() === "Confirm Donation") return
+
+ if (!this.searchText) {
+ this.tickMenu(true)
+ return
+ }
+
+
+ this.itemsBox.clearChildren()
+
+ let items = []
+
+ // this.itemsInPages[page][page2]
+ Object.keys(this.itemsInPages).forEach((pageKey) => {
+ let page = this.itemsInPages[pageKey]
+ page.forEach((page2, page2I) => {
+ if (!page2) return
+ if (items.length >= 4 * 7) return
+ page2.forEach((item, slotNum) => {
+ if (!item) return
+ if (items.length >= 4 * 7) return
+ if (item.name.toLowerCase().includes(this.searchText.toLowerCase())) {
+ let loreNew = []
+ Object.values(item.lore).forEach(a => {
+ loreNew.push(a)
+ })
+ item.lore = loreNew
+ item.page = pageKey //category eg: Weapons, armour sets ect
+ item.page2 = page2I //pagenum of category
+ item.slotNum = slotNum //slotnum
+
+ items.push(item)
+ }
+ })
+ })
+ })
+
+ let y = 0.0325
+ let itemNum = 0
+ let width = 3
+ let widthPer = 1 / (width + 1)
+ let offset = 0.0125
+
+ items.forEach((slot, slotNum) => {
+ if (!slot) return
+
+ let child
+
+ if (slot.sb_id === "NA") {
+ child = new BoxWithText().setText(slot.name.startsWith("§f") ? "&7" + slot.name.substr(2) : slot.name).setLore(slot.lore)
+ if (slot.name.startsWith("§c")) {
+ child.setColor(255, 100, 100)
+ child.setText("&0" + slot.name.substr(2))
+ }
+ if (slot.name.startsWith("§e")) {
+ child.setColor(255, 255, 100)
+ child.setText("&0" + slot.name.substr(2))
+ }
+ } else {
+ let fItem = slot
+ child = new ButtonWithArrow().setText(slot.name.startsWith("§f") ? "&7" + slot.name.substr(2) : slot.name).setLore(slot.lore)
+ child.addEvent(new SoopyMouseClickEvent().setHandler((mouseX, mouseY, button) => {
+ if (button === 2) { //middle click -> add item to favorites
+ this.addItemToFavorites(fItem, fItem.page, fItem.page2, fItem.slotNum)
+ return
+ }
+ // Player.getContainer().click(item.slotNum, false,button===1?"RIGHT":"LEFT")
+
+ let currPage, pageNum
+ if (Player.getContainer().getName().includes("/")) {
+ [currPage, pageNum] = Player.getContainer().getName().split(")")[0].split("(")[1].split("/").map(a => parseInt(a))
+ }
+
+ if (this.replacePage[Player.getContainer().getName().split("➜").pop()] === fItem.page) {
+ if (currPage === fItem.page2) {
+ Player.getContainer().click(fItem.slotNum, false, "LEFT")
+ } else {
+ if (currPage < fItem.page2) {
+ Player.getContainer().click(53, false, "MIDDLE")
+ } else {
+ Player.getContainer().click(45, false, "MIDDLE")
+ }
+ }
+ } else {
+ this.clickedTopButton(fItem.page)
+ }
+ })).addEvent(new SoopyRenderEvent().setHandler(() => {
+ if (child.hovered) {
+
+ child.setColorOffset(-20, -20, -20, 100)
+
+ Renderer.translate(0, 0, 100)
+ Renderer.drawRect(Renderer.color(0, 0, 0, 100), child.location.getXExact(), child.location.getYExact(), child.location.getWidthExact(), child.location.getHeightExact())
+
+ let clicks = "?"
+ let currPage, pageNum
+ if (Player.getContainer().getName().includes("/")) {
+ [currPage, pageNum] = Player.getContainer().getName().split(")")[0].split("(")[1].split("/").map(a => parseInt(a))
+ }
+ let pageClicks = Math.abs(currPage - fItem.page2)
+ if (this.replacePage[Player.getContainer().getName().split("➜").pop()] === fItem.page) {
+ clicks = (pageClicks + 1) + ""
+ } else {
+ if (Player.getContainer().getName() === "Your Museum") {
+ clicks = (1 + fItem.page2) + ""
+ } else {
+ clicks = (2 + fItem.page2) + ""
+ }
+ }
+
+ Renderer.translate(0, 0, 100)
+ renderLibs.drawStringCenteredFull(clicks, child.location.getXExact() + child.location.getWidthExact() / 2, child.location.getYExact() + child.location.getHeightExact() / 2, Math.min(child.location.getWidthExact() / Renderer.getStringWidth(clicks) / 4, child.location.getHeightExact() / 4 / 2))
+
+ }
+ }))
+ if (this.favoriteIds.includes(slot.sb_id)) {
+ child.setColor(200, 255, 200)
+ }
+ }
+ child.setLocation(offset + widthPer * itemNum, y, widthPer * 9 / 10, 0.125)
+ this.itemsBox.addChild(child)
+
+ itemNum++
+ if (itemNum > width) {
+ itemNum = 0
+ y += 0.135
+ }
+ })
+
+ this.itemsBox.dirtyFrameBuffer()
+ }
+
+ regenItems(page2) {
+ if (this.searchText) return
+
+ this.itemsBox.clearChildren()
+
+ let page = this.replacePage[Player.getContainer().getName().split("➜").pop()]
+
+ let y = 0.0325
+ let itemNum = 0
+ let width = 3
+ let widthPer = 1 / (width + 1)
+ let offset = 0.0125
+
+ if (!this.itemsInPages[page][page2]) this.itemsInPages[page][page2] = []
+
+ this.itemsInPages[page][page2].forEach((slot, slotNum) => {
+ if (!slot) return
+
+ let child
+
+ if (slot.sb_id === "NA") {
+ child = new BoxWithText().setText(slot.name.startsWith("§f") ? "&7" + slot.name.substr(2) : slot.name).setLore(slot.lore)
+ if (slot.name.startsWith("§c")) {
+ child.setColor(255, 100, 100)
+ child.setText("&0" + slot.name.substr(2))
+ }
+ if (slot.name.startsWith("§e")) {
+ child.setColor(255, 255, 100)
+ child.setText("&0" + slot.name.substr(2))
+ }
+ } else {
+ child = new ButtonWithArrow().setText(slot.name.startsWith("§f") ? "&7" + slot.name.substr(2) : slot.name).setLore(slot.lore)
+ child.addEvent(new SoopyMouseClickEvent().setHandler((mouseX, mouseY, button) => {
+ if (button === 2) { //middle click -> add item to favorites
+ this.addItemToFavorites(slot, page, page2, slotNum)
+ return
+ }
+ // Player.getContainer().click(slotNum, false,button===1?"RIGHT":"LEFT")
+ Player.getContainer().click(slotNum, false, "LEFT") //TODO: add right click support for viewing armour sets
+ }))
+ if (this.favoriteIds.includes(slot.sb_id)) {
+ child.setColor(200, 255, 200)
+ }
+ }
+ child.setLocation(offset + widthPer * itemNum, y, widthPer * 9 / 10, 0.125)
+ this.itemsBox.addChild(child)
+
+ itemNum++
+ if (itemNum > width) {
+ itemNum = 0
+ y += 0.135
+ }
+ })
+
+ this.itemsBox.dirtyFrameBuffer()
+ }
+
+ addItemToFavorites(slot, page, page2, slotNum) {
+ if (page === "Special Items") {
+ new Notification("§cError!", ["You cant add Special Items", ["to favorites"]])
+ return
+ }
+ if (this.favoriteItems.map(a => a.sb_id).includes(slot.sb_id)) {
+ //remove from favorites
+ this.favoriteItems = this.favoriteItems.filter(a => a.sb_id !== slot.sb_id)
+ this.favoriteIds = this.favoriteIds.filter(a => a !== slot.sb_id)
+ this.regenItems(page2)
+ this.updatedFavorites()
+ return
+ }
+ let loreNew = []
+ slot.lore.forEach(a => {
+ loreNew.push(a)
+ })
+ slot.lore = loreNew
+ slot.page = page //category eg: Weapons, armour sets ect
+ slot.page2 = page2 //pagenum of category
+ slot.slotNum = slotNum //slotnum
+ this.favoriteItems.push(slot)
+ this.favoriteIds.push(slot.sb_id)
+ this.regenItems(page2)
+ this.updatedFavorites()
+ }
+
+ updatedFavorites(saveToFile = true) {
+ this.favoriteBox.clearChildren()
+
+ if (this.favoriteItems.length === 0) {
+ let item = new SoopyMarkdownElement().setText("Middle click to add an item to your favorites list").setLocation(0.05, 0.025, 0.9, 0.9)
+
+ this.favoriteBox.addChild(item)
+ }
+
+ this.favoriteItems.forEach((fItem, i) => {
+ let item = new ButtonWithArrow().setText(fItem.name.startsWith("§f") ? "&7" + fItem.name.substr(2) : fItem.name).setLocation(0.05, 0.025 + 0.125 * i, 0.9, 0.1).setLore(fItem.lore)
+
+ item.addEvent(new SoopyMouseClickEvent().setHandler((mouseX, mouseY, button) => {
+ if (button === 2) { //middle click -> remove item from favorites (calling add will remove because it alr exists)
+ this.addItemToFavorites(fItem, fItem.page, fItem.page2, fItem.slotNum)
+ return
+ }
+ // Player.getContainer().click(item.slotNum, false,button===1?"RIGHT":"LEFT")
+
+ let currPage, pageNum
+ if (Player.getContainer().getName().includes("/")) {
+ [currPage, pageNum] = Player.getContainer().getName().split(")")[0].split("(")[1].split("/").map(a => parseInt(a))
+ }
+
+ if (this.replacePage[Player.getContainer().getName().split("➜").pop()] === fItem.page) {
+ if (currPage === fItem.page2) {
+ Player.getContainer().click(fItem.slotNum, false, "LEFT")
+ } else {
+ if (currPage < fItem.page2) {
+ Player.getContainer().click(53, false, "MIDDLE")
+ } else {
+ Player.getContainer().click(45, false, "MIDDLE")
+ }
+ }
+ } else {
+ this.clickedTopButton(fItem.page)
+ }
+ })).addEvent(new SoopyRenderEvent().setHandler(() => {
+ if (item.hovered) {
+
+ item.setColorOffset(-20, -20, -20, 100)
+
+ Renderer.translate(0, 0, 100)
+ Renderer.drawRect(Renderer.color(0, 0, 0, 100), item.location.getXExact(), item.location.getYExact(), item.location.getWidthExact(), item.location.getHeightExact())
+
+ let clicks = "?"
+ let currPage, pageNum
+ if (Player.getContainer().getName().includes("/")) {
+ [currPage, pageNum] = Player.getContainer().getName().split(")")[0].split("(")[1].split("/").map(a => parseInt(a))
+ }
+ let pageClicks = Math.abs(currPage - fItem.page2)
+ if (this.replacePage[Player.getContainer().getName().split("➜").pop()] === fItem.page) {
+ clicks = (pageClicks + 1) + ""
+ } else {
+ if (Player.getContainer().getName() === "Your Museum") {
+ clicks = (1 + fItem.page2) + ""
+ } else {
+ clicks = (2 + fItem.page2) + ""
+ }
+ }
+
+ Renderer.translate(0, 0, 100)
+ renderLibs.drawStringCenteredFull(clicks, item.location.getXExact() + item.location.getWidthExact() / 2, item.location.getYExact() + item.location.getHeightExact() / 2, Math.min(item.location.getWidthExact() / Renderer.getStringWidth(clicks) / 4, item.location.getHeightExact() / 4 / 2))
+
+ }
+ }))
+
+ this.favoriteBox.addChild(item)
+ })
+
+ if (saveToFile) {
+ new Thread(() => {
+ FileLib.write("soopyAddonsData", "museumFavoriteData.json", JSON.stringify(this.favoriteItems))
+ }).start()
+ }
+
+ this.favoriteBox.dirtyFrameBuffer()
+ }
+
+ guiOpened(event) {
+ let name = ""
+ if (event.gui && event.gui.field_147002_h instanceof ContainerChest) {
+ name = event.gui.field_147002_h.func_85151_d().func_145748_c_().func_150260_c()
+ }
+ if (this.dontOpen > 0) {
+ this.dontOpen--
+ }
+ if (this.soopyGui.ctGui.isOpen()) {
+ if (event.gui && event.gui.field_147002_h) {
+ Player.getPlayer().field_71070_bA = event.gui.field_147002_h
+
+ if (Player.getContainer().getName() === "Museum Rewards") {
+ return
+ }
+ if (Player.getContainer().getName().startsWith("Museum Browser")) {
+ return
+ }
+
+ event.gui = this.soopyGui.ctGui
+ this.guiUpdated = true
+ this.soopyGui.ctGui.open()
+
+ this.itemsBox.dirtyFrameBuffer()
+ }
+ return
+ }
+ if (this.isInMuseum) {
+ this.soopyGui.ctGui.open()
+
+ this.itemsBox.dirtyFrameBuffer()
+ } else {
+ if (name === "Your Museum" && !this.isInMuseum) {
+
+ if (event.gui && event.gui.field_147002_h) Player.getPlayer().field_71070_bA = event.gui.field_147002_h
+
+ this.isInMuseum = true
+
+ this.soopyGui.open()
+ event.gui = this.soopyGui.ctGui
+ this.guiOpenTickThing = true
+
+ this.itemsBox.clearChildren()
+ let rewardsButton = new ButtonWithArrow().setText("§5Rewards").setLocation(0.1, 0.05, 0.8, 0.2)
+ rewardsButton.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ Player.getContainer().click(40, false, "MIDDLE")
+ }))
+ this.itemsBox.addChild(rewardsButton)
+ let browserButton = new ButtonWithArrow().setText("§5Museum Browser").setLocation(0.1, 0.3, 0.8, 0.2)
+ browserButton.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ Player.getContainer().click(50, false, "MIDDLE")
+ }))
+ this.itemsBox.addChild(browserButton)
+
+ this.nextButton.visable = false
+ this.previousButton.visable = false
+
+ this.donateTitleBox.visable = false
+ this.donateBox.visable = false
+
+ this.pageTitle.setText("§5" + name)
+
+ this.tickMenu(true)
+
+ this.itemsBox.dirtyFrameBuffer()
+ }
+ }
+ }
+
+ keyPress(key, keyId) {
+ if (keyId === 1) { //escape key
+ this.isInMuseum = false
+ // this.dontOpen = 1
+ Client.currentGui.close()
+ }
+ }
+
+ tick() {
+ if (this.isInMuseum) {
+ if (this.soopyGui.ctGui.isOpen() || this.guiOpenTickThing) {
+ this.tickMenu()
+
+ this.guiOpenTickThing = false
+ } else {
+ // Client.currentGui.close()
+ this.isInMuseum = false
+
+ this.lastClosed = Date.now()
+ }
+ }
+
+ if (!(this.soopyGui.ctGui.isOpen() || this.guiOpenTickThing) && Date.now() - this.lastClosed > 1000) {
+ this.weaponsProgressBar.setProgress(0)
+ this.armourProgressBar.setProgress(0)
+ this.raritiesProgressBar.setProgress(0)
+ }
+
+ if (this.dontOpen > 0) {
+ Client.currentGui.close()
+ }
+ }
+}
+
+export default MuseumGui;
\ No newline at end of file
diff --git a/src/features/changeLogGUI/index.js b/src/features/changeLogGUI/index.js
new file mode 100644
index 0000000..c9c25fe
--- /dev/null
+++ b/src/features/changeLogGUI/index.js
@@ -0,0 +1,255 @@
+///
+///
+import SoopyGuiElement from "../../../guimanager/GuiElement/SoopyGuiElement";
+import SoopyTextElement from "../../../guimanager/GuiElement/SoopyTextElement";
+import Feature from "../../featureClass/class";
+import GuiPage from "../soopyGui/GuiPage";
+import SoopyMarkdownElement from '../../../guimanager/GuiElement/SoopyMarkdownElement.js';
+import metadata from "../../metadata";
+import ButtonWithArrow from "../../../guimanager/GuiElement/ButtonWithArrow";
+import SoopyMouseClickEvent from "../../../guimanager/EventListener/SoopyMouseClickEvent";
+import ProgressBar from "../../../guimanager/GuiElement/ProgressBar"
+import SoopyRenderEvent from "../../../guimanager/EventListener/SoopyRenderEvent"
+import { fetch } from "../../utils/networkUtils";
+import { numberWithCommas } from "../../utils/numberUtils";
+const File = Java.type("java.io.File")
+const URL = Java.type("java.net.URL");
+const PrintStream = Java.type("java.io.PrintStream");
+const Byte = Java.type("java.lang.Byte");
+//global.soopyv2featuremanagerthing.features.changeLogGUI.class.ChangelogPage.downloadUpdate()
+class ChangeLogGui extends Feature {
+ constructor() {
+ super()
+ }
+
+ onEnable() {
+ this.initVariables()
+
+ this.ChangelogPage = new ChangelogPage()
+
+ this.latestAnnouncedVersion = this.ChangelogPage.currVersionId
+
+ this.registerEvent("worldLoad", this.worldLoad)
+
+ this.registerStep(false, 60 * 5, () => {
+ this.ChangelogPage.loadChangeLog()
+ })
+ }
+
+ worldLoad() {
+ if (this.ChangelogPage.downloadableVersion === -1) return
+
+
+ if (this.FeatureManager.features["globalSettings"] === undefined || this.FeatureManager.features["globalSettings"].class.alertAllUpdates === undefined) {
+ return
+ }
+ let alertBeta = this.FeatureManager.features["globalSettings"].class.alertAllUpdates.getValue()
+
+ if (this.latestAnnouncedVersion < (alertBeta ? this.ChangelogPage.downloadableVersion : this.ChangelogPage.importantVersion)) {
+ let version = ""
+ this.ChangelogPage.changelogData.forEach(data => {
+
+ if (this.ChangelogPage.downloadableVersion === data.versionId && this.ChangelogPage.downloadableVersion > this.ChangelogPage.currVersionId) {
+ //add button to download this version
+ version = data.version
+ }
+ })
+
+ ChatLib.chat("§r")
+ ChatLib.chat("&1" + ChatLib.getChatBreak("-").trim())
+ ChatLib.chat(" &6New SoopyV2 Version is avalible (" + version + ")")
+ ChatLib.chat("§r§r")
+ new TextComponent(" &e[CLICK] &7- View changelog and download update").setHover("show_text", "&2Open changelog").setClick("run_command", "/soopyv2 changelog").chat()
+ ChatLib.chat("&1" + ChatLib.getChatBreak("-").trim())
+ ChatLib.chat("§r§r§r")
+
+ this.latestAnnouncedVersion = this.ChangelogPage.downloadableVersion
+ }
+ }
+
+ initVariables() {
+ this.ChangelogPage = undefined
+ }
+
+ onDisable() {
+ this.initVariables()
+ }
+}
+
+
+class ChangelogPage extends GuiPage {
+ constructor() {
+ super(9)
+
+ this.name = "Changelog"
+
+ this.pages = [this.newPage()]
+
+ this.changelogData = []
+ this.downloadableVersion = -1
+
+ this.importantVersion = -1
+
+ let changelogTitle = new SoopyTextElement().setText("§0Changelog").setMaxTextScale(3).setLocation(0.1, 0.05, 0.8, 0.1)
+ this.pages[0].addChild(changelogTitle)
+
+ this.changelogArea = new SoopyGuiElement().setLocation(0.1, 0.2, 0.8, 0.8).setScrollable(true)
+ this.pages[0].addChild(this.changelogArea)
+
+ //Update confirmation page
+ this.updatingSidebar = new SoopyGuiElement().setLocation(0, 0, 1, 1)
+ this.updatingSidebarConfirmPage = new SoopyGuiElement().setLocation(0, 0, 1, 1)
+ this.updatingSidebar.addChild(this.updatingSidebarConfirmPage)
+
+ this.updateTitle = new SoopyTextElement().setText("§0Update to SoopyV2 ").setMaxTextScale(3).setLocation(0.1, 0.05, 0.8, 0.1)
+ this.updatingSidebarConfirmPage.addChild(this.updateTitle)
+
+ // this.warningMessage = new SoopyMarkdownElement().setLocation(0.1, 0.2, 0.8, 0.8)
+ // this.warningMessage.setText(``)
+ // this.updatingSidebarConfirmPage.addChild(this.warningMessage)
+
+ this.updateButton = new ButtonWithArrow().setText("§0Update").setLocation(0.3, 0.3, 0.4, 0.2)
+ this.updatingSidebarConfirmPage.addChild(this.updateButton)
+
+ this.updatingSidebarConfirmPage.setScrollable(true)
+
+ this.updateButton.addEvent(new SoopyRenderEvent().setHandler(() => {
+ this.updateButton.location.location.y.set(0.3, 0)
+ }))
+ this.updateButton.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.downloadUpdate()
+ }))
+
+ this.updatingSidebarLoadingPage = new SoopyGuiElement().setLocation(1, 0, 1, 1)
+ this.updatingSidebar.addChild(this.updatingSidebarLoadingPage)
+
+ let updatingTitle = new SoopyTextElement().setText("§0Updating...").setMaxTextScale(3).setLocation(0.1, 0.05, 0.8, 0.1)
+ this.updatingSidebarLoadingPage.addChild(updatingTitle)
+
+ this.progressBar = new ProgressBar().setLocation(0.1, 0.2, 0.8, 0.1)
+ this.updatingSidebarLoadingPage.addChild(this.progressBar)
+
+ this.currVersionId = metadata.versionId
+
+ this.finaliseLoading()
+
+ this.loadChangeLog()
+ }
+
+ async loadChangeLog() {
+ let data = await fetch("http://soopy.dev/api/soopyv2/changelog.json").json()
+
+ this.changelogData = data.changelog.reverse()
+
+ this.downloadableVersion = data.downloadableVersion
+ this.importantVersion = data.importantVersion
+
+ this.updateText()
+ }
+
+ onOpen() {
+ this.loadChangeLog()
+ }
+
+ showConfirmUpdatePage() {
+ let version = ""
+ this.changelogData.forEach(data => {
+
+ if (this.downloadableVersion === data.versionId && this.downloadableVersion > this.currVersionId) {
+ //add button to download this version
+ version = data.version
+ }
+ })
+ this.updateTitle.setText("§0Update to SoopyV2 " + version)
+
+ this.updateButton.location.location.y.set(0.3, 0)
+
+ this.openSidebarPage(this.updatingSidebar)
+ }
+
+ downloadUpdate() {
+ new Thread(() => {
+ this.updatingSidebarConfirmPage.location.location.x.set(-1, 500)
+ this.updatingSidebarLoadingPage.location.location.x.set(0, 500)
+
+ new File("./config/ChatTriggers/modules/SoopyAddonsTempDownload").mkdir()
+
+ this.progressBar.setProgress(0.1)
+
+ this.urlToFile("http://soopy.dev/api/soopyv2/downloadLatest.zip", "./config/ChatTriggers/modules/SoopyAddonsTempDownload/SoopyAddons.zip", 10000, 20000)
+
+ this.progressBar.setProgress(0.5)
+
+ FileLib.unzip("./config/ChatTriggers/modules/SoopyAddonsTempDownload/SoopyAddons.zip", "./config/ChatTriggers/modules/SoopyAddonsTempDownload/SoopyAddons/")
+
+ this.progressBar.setProgress(0.75)
+
+ FileLib.deleteDirectory(new File("./config/ChatTriggers/modules/SoopyV2"))
+
+ this.progressBar.setProgress(0.9)
+
+ new File("./config/ChatTriggers/modules/SoopyAddonsTempDownload/SoopyAddons/SoopyV2").renameTo(new File("./config/ChatTriggers/modules/SoopyV2"))
+
+ FileLib.deleteDirectory(new File("./config/ChatTriggers/modules/SoopyAddonsTempDownload"))
+
+ this.progressBar.setProgress(1)
+
+ Client.currentGui.close()
+
+ ChatLib.command("ct load", true)
+ }).start()
+ }
+
+ urlToFile(url, destination, connecttimeout, readtimeout) {
+ const d = new File(destination);
+ d.getParentFile().mkdirs();
+ const connection = new URL(url).openConnection();
+ connection.setDoOutput(true);
+ connection.setConnectTimeout(connecttimeout);
+ connection.setReadTimeout(readtimeout);
+ const IS = connection.getInputStream();
+ const FilePS = new PrintStream(destination);
+ let buf = new Packages.java.lang.reflect.Array.newInstance(Byte.TYPE, 65536);
+ let len;
+ while ((len = IS.read(buf)) > 0) {
+ FilePS.write(buf, 0, len);
+ }
+ IS.close();
+ FilePS.close();
+ }
+
+ updateText() {
+ this.changelogArea.children = []
+
+ let height = 0
+
+ this.changelogData.forEach(data => {
+
+ if (this.downloadableVersion === data.versionId && this.downloadableVersion > this.currVersionId) {
+ //add button to download this version
+ let button = new ButtonWithArrow().setText("§0Download this version").setLocation(0.7, height, 0.3, 0.1)
+ this.changelogArea.addChild(button)
+
+ button.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.showConfirmUpdatePage()
+ }))
+
+ height += 0.05
+ }
+
+ let changes = new SoopyMarkdownElement().setLocation(0, height, 1, 0)
+
+ this.changelogArea.addChild(changes)
+
+ changes.setText("# __" + data.version + "__" + (data.versionId === this.currVersionId ? " §7Current (" : " §7(") + numberWithCommas(data.users || 0) + " using)" + "\n" + data.description)
+
+ height += changes.getHeight()
+
+ height += 0.05
+ })
+ }
+}
+
+module.exports = {
+ class: new ChangeLogGui()
+}
\ No newline at end of file
diff --git a/src/features/changeLogGUI/metadata.json b/src/features/changeLogGUI/metadata.json
new file mode 100644
index 0000000..8dfbe4b
--- /dev/null
+++ b/src/features/changeLogGUI/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "ChangeLog gui",
+ "description": "Gui for changelog",
+ "isHidden": true,
+ "isTogglable": false,
+ "defaultEnabled": true,
+ "sortA": 0
+}
\ No newline at end of file
diff --git a/src/features/cosmetics/cosmetic.js b/src/features/cosmetics/cosmetic.js
new file mode 100644
index 0000000..878e425
--- /dev/null
+++ b/src/features/cosmetics/cosmetic.js
@@ -0,0 +1,29 @@
+
+class Cosmetic{
+ constructor(player, parent, id){
+
+ if(player.getUUID().toString() === Player.getUUID().toString()) player = Player
+ /**
+ * @type {PlayerMP | Player}
+ */
+ this.player = player
+
+ this.parent = parent
+
+ this.id = id
+
+ this.settings = this.parent.getPlayerCosmeticSettings(this.player, id)
+
+ this.onTick()
+ }
+
+ onRenderEntity(ticks, isInGui){
+ //override
+ }
+
+ onTick(){
+ //override
+ }
+}
+
+export default Cosmetic;
\ No newline at end of file
diff --git a/src/features/cosmetics/cosmetic/dragon/dragonWings.js b/src/features/cosmetics/cosmetic/dragon/dragonWings.js
new file mode 100644
index 0000000..944ba78
--- /dev/null
+++ b/src/features/cosmetics/cosmetic/dragon/dragonWings.js
@@ -0,0 +1,482 @@
+import renderLibs from "../../../../../guimanager/renderLibs.js";
+import { f, m } from "../../../../../mappings/mappings.js";
+import ToggleSetting from "../../../settings/settingThings/toggle.js";
+import Cosmetic from "../../cosmetic.js";
+
+const ModelDragon = Java.type("net.minecraft.client.model.ModelDragon")
+
+if (!GlStateManager) {
+ // var GL11 = Java.type("org.lwjgl.opengl.GL11"); //using var so it goes to global scope
+ var GlStateManager = Java.type("net.minecraft.client.renderer.GlStateManager");
+}
+const Essential = Java.type("gg.essential.Essential")
+const EssentialCosmeticSlot = Java.type("gg.essential.mod.cosmetics.CosmeticSlot")
+const EssentialBone = Java.type("gg.essential.model.Bone")
+
+const FACING = Java.type("net.minecraft.block.BlockDirectional").field_176387_N
+let dragon = new ModelDragon(0) //too lazy to make my own model so i just yoink it from modelDragon lmfao
+let textures = new Map()
+let loadingTextures = new Set()
+function loadTexture(id) {
+ new Thread(() => {
+ loadingTextures.add(id)
+ textures.set(id, renderLibs.getImage("http://soopy.dev/api/soopyv2/textures/cosmetic/dragon/" + id + "/img.png", true))
+ }).start()
+}
+loadTexture("classic")
+let wing = getField(dragon, f.wing)
+let wingTip = getField(dragon, f.wingTip)
+
+class DragonWings extends Cosmetic {
+ constructor(player, parent) {
+ super(player, parent, "dragon_wings");
+
+ this.animOffset = Math.random() * 20 * Math.PI
+ this.lastRender = Date.now()
+
+ this.lastFlapSound = this.animOffset
+ this.i = 0
+
+ this.flying = false
+
+ if (!textures.has(this.settings.texture) && !loadingTextures.has(this.settings.texture)) {
+ loadTexture(this.settings.texture)
+ }
+ }
+
+ onRenderEntity(ticks, isInGui) {
+
+ if (this.player.getPlayer()[m.isInvisibleToPlayer](Player.getPlayer()) || this.player.getPlayer()[m.isInvisible]()) {
+ return
+ }
+ if (!textures.has("classic")) return
+
+ let isSelfPlayer = this.player.getUUID().toString() === Player.getUUID().toString()
+ let isInInv = isSelfPlayer && ticks === 1
+ let thirdPersonView = Client.getMinecraft()[f.gameSettings.Minecraft][f.thirdPersonView]
+
+ if (!this.parent.firstPersonVisable.getValue() && thirdPersonView === 0 && isSelfPlayer && !isInInv) return
+
+ // return;
+ // wing.func_78785_a(1)
+
+ let timeSince = (Date.now() - this.lastRender) / 1000
+ this.lastRender = Date.now()
+
+ let rotation = isInInv ? 0 : this.player.getPlayer()[f.prevRenderYawOffset] + (this.player.getPlayer()[f.renderYawOffset] - this.player.getPlayer()[f.prevRenderYawOffset]) * ticks
+ // rotation += entity.field_70761_aq+(entity.field_70761_aq-entity.field_70760_ar)*ticks
+ // console.log(rotation, entity.getEntity().field_70761_aq+(entity.getEntity().field_70761_aq-entity.getEntity().field_70760_ar)*ticks)
+ let horisontalSpeed = Math.hypot((this.player.getPlayer()[f.posX.Entity] - this.player.getPlayer()[f.lastTickPosX]), (this.player.getPlayer()[f.posZ.Entity] - this.player.getPlayer()[f.lastTickPosZ]))
+
+ let verticleSpeed = this.player.getPlayer()[f.posY.Entity] - this.player.getPlayer()[f.lastTickPosY]
+
+ this.animOffset += Math.min(1, horisontalSpeed) * 10 * timeSince + 1 * timeSince
+
+ let flapAmountMultiplyerNoEnd = 1
+ let flapAmountMultiplyer = 1
+
+ let wingEndOffsetThing = 0
+
+ flapAmountMultiplyerNoEnd += Math.min(5, (horisontalSpeed * 5))
+ let flapMainOffsetThing = 0
+
+ let wingBackAmount = 0
+
+ let shouldStandStillWingCurve = true
+
+ if (this.player.getPlayer()[f.hurtResistantTime] > 17) { //damage tick
+ this.animOffset += 25 * timeSince
+ }
+
+
+ // if((this.player === Player &&this.player.getPlayer().field_71075_bZ.field_75100_b) || (this.player !== Player && Math.abs(verticleSpeed)<0.2 && !this.player.getPlayer().field_70122_E)){//playerCapabilities.isFlying
+ if (this.flying) { //flying
+ shouldStandStillWingCurve = false
+ this.animOffset += 5 * timeSince //flap in mid air
+
+ flapAmountMultiplyer *= 1.75 //flap harder
+
+ if (isSelfPlayer && thirdPersonView === 0) {
+ if (!this.parent.lessFirstPersonVisable.getValue()) {
+ flapAmountMultiplyerNoEnd += 0.4
+ flapMainOffsetThing = 0.3
+ }
+ } else {
+ flapAmountMultiplyer *= 1.25
+ flapAmountMultiplyer *= 0.9
+ flapMainOffsetThing = 0.1
+ wingEndOffsetThing += -0.1
+ }
+
+ wingEndOffsetThing += -0.75
+
+ if (verticleSpeed > 0) {
+ this.animOffset += verticleSpeed * 25 * timeSince //flap when flying upwards
+ }
+ } else {
+ if (this.lastFlapSound < this.animOffset - this.animOffset % (Math.PI * 2)) {
+ this.lastFlapSound = this.animOffset - this.animOffset % (Math.PI * 2)
+ }
+ }
+ if (verticleSpeed < -0.5) {
+ wingBackAmount = Math.min(1, (verticleSpeed + 0.5) * -1.5) //lift wings back further ur falling
+
+ this.animOffset += (verticleSpeed + 0.5) * -3 * timeSince
+ }
+
+ GlStateManager[m.pushMatrix](); // pushMatrix
+ Tessellator.colorize(this.settings.color.r, this.settings.color.g, this.settings.color.b);
+
+ if (!isSelfPlayer) {
+ Tessellator.translate(
+ (this.player.getPlayer()[f.lastTickPosX] + (this.player.getPlayer()[f.posX.Entity] - this.player.getPlayer()[f.lastTickPosX]) * ticks) - (Player.getPlayer()[f.lastTickPosX] + (Player.getPlayer()[f.posX.Entity] - Player.getPlayer()[f.lastTickPosX]) * ticks),
+ (this.player.getPlayer()[f.lastTickPosY] + (this.player.getPlayer()[f.posY.Entity] - this.player.getPlayer()[f.lastTickPosY]) * ticks) - (Player.getPlayer()[f.lastTickPosY] + (Player.getPlayer()[f.posY.Entity] - Player.getPlayer()[f.lastTickPosY]) * ticks),
+ (this.player.getPlayer()[f.lastTickPosZ] + (this.player.getPlayer()[f.posZ.Entity] - this.player.getPlayer()[f.lastTickPosZ]) * ticks) - (Player.getPlayer()[f.lastTickPosZ] + (Player.getPlayer()[f.posZ.Entity] - Player.getPlayer()[f.lastTickPosZ]) * ticks))
+ }
+
+ if (textures.get(this.settings.texture || "classic")) {
+ Tessellator.bindTexture(textures.get(this.settings.texture || "classic")) //bind texture
+ } else {
+ Tessellator.bindTexture(textures.get("classic")) //bind default texture (classic)
+ }
+
+ if (this.player.getPlayer()[f.ridingEntity.Entity]) {
+ rotation = this.player.getPlayer()[f.rotationYawHead] + (this.player.getPlayer()[f.rotationYawHead] - this.player.getPlayer()[f.prevRotationYawHead]) * ticks
+ }
+ if (!this.player.getPlayer()[m.isPlayerSleeping]()) { //dont rotate when in bed
+ Tessellator.rotate((180 - rotation), 0, 1, 0)
+
+ Tessellator.translate(0, 1.2, 0.13)
+
+ if (this.player.getPlayer()[m.isSneaking.Entity]()) { //isSneaking
+ Tessellator.translate(0, -0.125, 0)
+ Tessellator.rotate(-20, 1, 0, 0)
+
+ Tessellator.translate(0, 0, 0.1)
+ if (isSelfPlayer && thirdPersonView === 0) { } else {
+ Tessellator.translate(0, -0.125, 0)
+ }
+ }
+
+ if (isSelfPlayer && !isInInv && thirdPersonView === 0) {
+ //Make wings less scuffed when in first person looking down/up
+ Tessellator.translate(0, 0.25, 0.003 * (this.player.getPitch()))
+ }
+ }
+
+
+ //Higher = more elytra like
+ wing[f.rotateAngleY] = 0.25; //rotateAngleY
+
+ let shouldStandingStillWingThing = false
+
+ let changeStandingStillWingThing = 0
+
+ if (horisontalSpeed < 0.01) {
+ if (!(this.flying)) { //not flying
+ let amt = (this.animOffset + Math.PI / 2) % (20 * Math.PI)
+ if (amt < 1 * Math.PI) {
+ this.animOffset += 2 * timeSince * Math.min(1, (amt / (1 * Math.PI)) * 2)
+
+ flapAmountMultiplyer += (amt / (1 * Math.PI)) / 2
+ } else if (amt < 2 * Math.PI) {
+ this.animOffset += 2 * timeSince * Math.min(1, (1 - (amt / (1 * Math.PI) - 1)) * 2)
+
+ flapAmountMultiplyer += (1 - (amt / (1 * Math.PI) - 1)) / 2
+ }
+ }
+ if (this.player.getPlayer()[m.isSneaking.Entity]()) { //isSneaking
+ if (this.player.getPlayer()[f.rotationPitch] > 20) {
+ shouldStandingStillWingThing = true
+ shouldStandStillWingCurve = false
+ changeStandingStillWingThing = Math.max(0, this.player.getPlayer()[f.rotationPitch] / 600)
+ }
+ }
+ }
+
+ if (shouldStandingStillWingThing) {
+ wing[f.rotateAngleY] = 0.25 + (changeStandingStillWingThing) * 3
+ }
+ if (this.player.getPlayer()[m.isPlayerSleeping]()) { //player in bed
+
+ try { //try catch incase no bed at that location
+ let facing = World.getWorld().func_180495_p(this.player.getPlayer()[f.playerLocation])[m.getValue.BlockState$StateImplementation](FACING)[m.getHorizontalIndex]() //0-3 is S-W-N-E
+
+ let rotation = 0
+ switch (facing) {
+ case 0:
+ rotation = 180
+ Tessellator.translate(0, 0, -0.5)
+ break
+ case 1:
+ rotation = 90
+ Tessellator.translate(0.5, 0, 0)
+ break
+ case 2:
+ rotation = 0
+ Tessellator.translate(0, 0, 0.5)
+ break
+ case 3:
+ rotation = 270
+ Tessellator.translate(-0.5, 0, 0)
+ break
+ }
+ // console.log(rotation)
+ // console.log(World.getBlockAt(this.player.getX(), this.player.getY(), this.player.getZ()).getState().func_177229_b(FACING))
+ Tessellator.rotate(rotation, 0, 1, 0)
+ } catch (e) { }
+ Tessellator.translate(0, - this.settings.scale * 25, 0)
+
+ wing[f.rotateAngleX] = 0; //rotateAngleX
+
+ wing[f.rotateAngleZ] = (-0.45 + Math.sin(this.animOffset / 5) * 0.03); //rotateAngleZ
+
+
+ wingTip[f.rotateAngleZ] = -2.5 + Math.sin(this.animOffset / 5) * 0.03
+ } else if (wingBackAmount === 0) {
+ //tilt
+
+
+ let wing_goback_amount = 0.15 / (Math.min(1, horisontalSpeed) * 3 + 0.25)
+ let temp_wing_thing = 1
+
+ if (shouldStandingStillWingThing) {
+ wing_goback_amount /= 1 + (changeStandingStillWingThing) / 50
+ flapAmountMultiplyer /= 1 + (changeStandingStillWingThing) / 50
+
+ temp_wing_thing += changeStandingStillWingThing * 50
+ }
+
+ let wing_tilt_offset = -Math.min(0.8, horisontalSpeed * 3) + 0.3 //When go faster tilt wing back so its in direction of wind
+
+
+ if (shouldStandingStillWingThing) {
+ wing_tilt_offset += (changeStandingStillWingThing) * 4
+ }
+
+ wing[f.rotateAngleX] = 0.85 - Math.cos(this.animOffset) * 0.2 + wing_tilt_offset - (flapAmountMultiplyer - 1) / 3; //rotateAngleX
+
+ let temp_horis_wingthing = 0
+ if (shouldStandingStillWingThing) {
+ temp_horis_wingthing = -(changeStandingStillWingThing) * 0.75
+ }
+
+ wing[f.rotateAngleZ] = (Math.sin(this.animOffset) / temp_wing_thing + 0.125) * wing_goback_amount * (1 + (flapAmountMultiplyer - 1) * 1) * flapAmountMultiplyerNoEnd - 0.4 - wing_tilt_offset / 3 + temp_horis_wingthing + flapMainOffsetThing; //rotateAngleZ
+
+ let standStillCurveThing = shouldStandStillWingCurve ? (2 - flapAmountMultiplyer) * 0.5 : 0
+
+ wingTip[f.rotateAngleZ] = standStillCurveThing - ((Math.sin((this.animOffset + 1.5 + (1 - temp_wing_thing) / 8.5)) / (1 + (temp_wing_thing - 1) / 3) + 0.5)) * 0.75 * (1 + (flapAmountMultiplyer - 1) * 1) / (1 + temp_horis_wingthing) - (1 - flapAmountMultiplyer) * 2 - (1 - temp_wing_thing) / 10 + wingEndOffsetThing; //rotateAngleZ
+ } else {
+ //tilt
+ let wing_tilt_offset = -Math.min(0.8, horisontalSpeed * 3) //When go faster tilt wing back so its in direction of wind
+ wing[f.rotateAngleX] = 0.75 - Math.cos(this.animOffset) * 0.2 + wing_tilt_offset - wingBackAmount / 2; //rotateAngleX
+
+
+ wing[f.rotateAngleZ] = -wingBackAmount; //rotateAngleZ
+
+
+ wingTip[f.rotateAngleZ] = -((Math.sin((this.animOffset)) * 0.5 + 0.3))
+ }
+
+ GlStateManager[m.disableCull]() //disable culling
+
+ let wing_center_dist = ((0 - Math.log(1000 * this.settings.scale + 0.01) - 2) - 100000 * this.settings.scale * this.settings.scale) / 1000
+
+ // GL11.glDepthMask(GL11.GL_FALSE);
+ Tessellator.translate(-wing_center_dist, 0, 0)
+ Tessellator.scale(this.settings.scale, this.settings.scale, this.settings.scale)
+ wing[m.renderWithRotation](1) //render left wing
+
+ Tessellator.translate(2 * wing_center_dist / this.settings.scale, 0, 0)
+ Tessellator.scale(-1, 1, 1)
+ wing[m.renderWithRotation](1) //render right wing
+
+
+ if (this.player.getPlayer()[f.hurtTime] > 0) { //damage tick
+ GlStateManager[m.pushMatrix](); // pushMatrix
+ GlStateManager[m.depthFunc](514);
+ GlStateManager[m.disableTexture2D]();
+ GlStateManager[m.enableBlend]();
+ GlStateManager[m.blendFunc](770, 771);
+ GlStateManager.func_179131_c(1, 0, 0, 0.25); //m.color.glstatemanager.ffff
+
+ Tessellator.scale(-1, 1, 1)
+ Tessellator.translate(-2 * wing_center_dist / this.settings.scale, 0, 0)
+ wing[m.renderWithRotation](1) //render left wing
+
+ Tessellator.translate(2 * wing_center_dist / this.settings.scale, 0, 0)
+ Tessellator.scale(-1, 1, 1)
+ wing[m.renderWithRotation](1) //render right wing
+
+ GlStateManager[m.enableTexture2D]();
+ GlStateManager[m.disableBlend]();
+ GlStateManager[m.depthFunc](515);
+ GlStateManager[m.popMatrix](); // popMatrix
+ }
+ Tessellator.colorize(1, 1, 1)
+ GlStateManager[m.enableCull]() //enable culling
+ GlStateManager[m.popMatrix](); // popMatrix
+ }
+
+ testPlaySound() {
+ if (this.player.getPlayer()[m.isInvisibleToPlayer](Player.getPlayer())) {
+ return
+ }
+ if (!this.parent.ownCosmeticAudio.getValue()) {
+ return
+ }
+
+ if (this.player.getPlayer()[m.isPlayerSleeping]()) return
+
+ let horisontalSpeed = Math.hypot((this.player.getPlayer()[f.posX.Entity] - this.player.getPlayer()[f.lastTickPosX]), (this.player.getPlayer()[f.posZ.Entity] - this.player.getPlayer()[f.lastTickPosZ]))
+
+
+ // if((this.player === Player &&this.player.getPlayer().field_71075_bZ.field_75100_b) || (this.player !== Player && Math.abs(verticleSpeed)<0.2 && !this.player.getPlayer().field_70122_E)){//playerCapabilities.isFlying
+ if (this.flying) { //flying
+
+ if (this.animOffset - this.lastFlapSound > 2 * Math.PI) {
+
+ let dist = Math.hypot((Player.getX() - this.player.getX()), (Player.getY() - this.player.getY()), (Player.getZ() - this.player.getZ())) + 1
+
+ World.playSound("mob.enderdragon.wings", (this.settings.scale * 15) * Math.min(1, 50 / (dist * dist)), 1)
+ this.lastFlapSound = this.animOffset - this.animOffset % (Math.PI * 2)
+ }
+ }
+
+ if (horisontalSpeed < 0.01) {
+ if (!(this.flying)) { //not flying
+ let amt = (this.animOffset + Math.PI / 2) % (20 * Math.PI)
+ if (amt < 1 * Math.PI) {
+ if (amt > 0.65 * Math.PI && (2 * Math.PI + this.animOffset) - this.lastFlapSound > 2 * Math.PI) {
+
+ let dist = Math.hypot((Player.getX() - this.player.getX()), (Player.getY() - this.player.getY()), (Player.getZ() - this.player.getZ())) + 1
+
+ World.playSound("mob.enderdragon.wings", (Math.max(0.005, this.settings.scale - 0.005) * 25) * Math.min(1, 50 / Math.min(1, dist * dist)) / 50, 1 - (Math.max(0.005, this.settings.scale - 0.005) * 25))
+ this.lastFlapSound = 2 * Math.PI + (this.animOffset) - this.animOffset % (Math.PI * 2)
+ }
+ }
+ }
+ }
+ }
+
+ onTick() {
+
+ this.updateIfNotRendering()
+
+ this.testPlaySound()
+
+ }
+
+ removeEssentialCosmetics() {
+ if (!this.player.getPlayer() || !this.player.getPlayer().getCosmeticsState || !this.player.getPlayer().getCosmeticsState() || !this.player.getPlayer().getCosmeticsState().getCosmetics || !this.player.getPlayer().getCosmeticsState().getCosmetics()) return
+ //player.()
+ let wingCosmetic = this.player.getPlayer().getCosmeticsState().getCosmetics().get(EssentialCosmeticSlot.WINGS)
+ if (wingCosmetic !== null) {
+ let cosmetic = this.player.getPlayer().getCosmeticsState().getModels().get(Essential.instance.getConnectionManager().getCosmeticsManager().getCosmetic(wingCosmetic))
+ if (cosmetic) {
+ let model = cosmetic.getModel().getModel()
+
+ let bones = model.getBones(model.getRootBone())
+
+ bones.forEach(b => {
+ setField(b, "showModel", false)
+
+ this.parent.hiddenEssentialCosmetics.push(b)
+ })
+ }
+ } else {
+ let fullBodyCosmetic = this.player.getPlayer().getCosmeticsState().getCosmetics().get(EssentialCosmeticSlot.FULL_BODY)
+ if (fullBodyCosmetic === "DRAGON_ONESIE_2") {
+ let cosmetic = this.player.getPlayer().getCosmeticsState().getModels().get(Essential.instance.getConnectionManager().getCosmeticsManager().getCosmetic(fullBodyCosmetic))
+ if (cosmetic) {
+ let model = cosmetic.getModel().getModel()
+
+ let bones = model.getBones(model.getRootBone())
+
+ bones.forEach(b => {
+ if (b.boxName === "wing_left_1" || b.boxName === "wing_right_1") {
+ setField(b, "showModel", false)
+
+ this.parent.hiddenEssentialCosmetics.push(b)
+ }
+ })
+ }
+ }
+ }
+ }
+
+ updateIfNotRendering() {
+ let verticleSpeed = this.player.getPlayer()[f.posY.Entity] - this.player.getPlayer()[f.lastTickPosY]
+
+ this.flying = (verticleSpeed > -0.2) && !this.player.getPlayer()[f.onGround.Entity]
+
+ let timeSince = (Date.now() - this.lastRender) / 1000
+
+ if (timeSince < 0.020) {
+ return
+ }
+
+ this.lastRender = Date.now()
+
+ let horisontalSpeed = Math.hypot((this.player.getPlayer()[f.posX.Entity] - this.player.getPlayer()[f.lastTickPosX]), (this.player.getPlayer()[f.posZ.Entity] - this.player.getPlayer()[f.lastTickPosZ]))
+
+
+ this.animOffset += Math.min(1, horisontalSpeed) * 10 * timeSince + 1 * timeSince
+
+ if (this.player.getPlayer()[f.hurtResistantTime] > 0) { //damage tick
+ this.animOffset += 5 * timeSince
+ }
+
+
+ // if((this.player === Player &&this.player.getPlayer().field_71075_bZ.field_75100_b) || (this.player !== Player && Math.abs(verticleSpeed)<0.2 && !this.player.getPlayer().field_70122_E)){//playerCapabilities.isFlying
+ if (this.flying) { //flying
+ this.animOffset += 5 * timeSince //flap in mid air
+
+ if (verticleSpeed > 0) {
+ this.animOffset += verticleSpeed * 25 * timeSince //flap when flying upwards
+ }
+ }
+ if (verticleSpeed < -0.5) {
+ this.animOffset += (verticleSpeed + 0.5) * -3 * timeSince
+ }
+
+ if (horisontalSpeed < 0.01) {
+ if (!(this.flying)) { //not flying
+ let amt = (this.animOffset + Math.PI / 2) % (20 * Math.PI)
+ if (amt < 1 * Math.PI) {
+ this.animOffset += 2 * timeSince * Math.min(1, (amt / (1 * Math.PI)) * 2)
+ } else if (amt < 2 * Math.PI) {
+ this.animOffset += 2 * timeSince * Math.min(1, (1 - (amt / (1 * Math.PI) - 1)) * 2)
+ }
+ }
+ }
+ }
+}
+
+export default DragonWings;
+
+
+function getField(e, field) {
+
+ let field2 = e.class.getDeclaredField(field);
+
+ field2.setAccessible(true)
+
+ return field2.get(e)
+}
+
+function setField(e, field, value) {
+
+ let field2 = e.class.getDeclaredField(field);
+
+ field2.setAccessible(true)
+
+ return field2.set(e, value)
+}
+
+let a = 0
+
+register("command", (val) => {
+ a = parseFloat(val)
+ ChatLib.chat("Set a to " + a)
+}).setName("seta", true)
\ No newline at end of file
diff --git a/src/features/cosmetics/hiddenRequirement.js b/src/features/cosmetics/hiddenRequirement.js
new file mode 100644
index 0000000..dbc3e06
--- /dev/null
+++ b/src/features/cosmetics/hiddenRequirement.js
@@ -0,0 +1,4 @@
+
+module.exports = {hidden: function(featureManager){
+ return !(featureManager.features.cosmetics?.["class"]?.playerHasACosmeticA || false)
+}}
\ No newline at end of file
diff --git a/src/features/cosmetics/index.js b/src/features/cosmetics/index.js
new file mode 100644
index 0000000..f3deece
--- /dev/null
+++ b/src/features/cosmetics/index.js
@@ -0,0 +1,271 @@
+///
+///
+import Feature from "../../featureClass/class";
+import DragonWings from "./cosmetic/dragon/dragonWings"
+import Toggle from "../settings/settingThings/toggle"
+import { f } from "../../../mappings/mappings";
+import FakeRequireToggle from "../settings/settingThings/FakeRequireToggle";
+import { fetch } from "../../utils/networkUtils";
+
+class Cosmetics extends Feature {
+ constructor() {
+ super()
+ }
+
+ onEnable() {
+ this.initVariables()
+ this.loadedCosmetics = []
+ this.uuidToCosmetic = {}
+ this.uuidToCosmeticDirect = {}
+
+ this.cosmeticsData = {}
+
+ this.hiddenEssentialCosmetics = []
+
+ this.cosmeticsList = {
+ "dragon_wings": DragonWings
+ }
+
+ this.playerHasACosmeticA = false
+
+ this.firstPersonVisable = new Toggle("Cosmetics visable in first person", "", false, "cosmetics_first_person_visable", this)
+ this.lessFirstPersonVisable = new Toggle("Make cosmetics less visable in first person mode", "", true, "cosmetics_first_person_less_visable", this).requires(this.firstPersonVisable)
+ this.ownCosmeticAudio = new Toggle("Audio for own cosmetics", "", false, "cosmetics_own_audio", this)
+
+ this.dragon_wings_enabled = new Toggle("Dragon Wings Toggle", "", true, "cosmetic_dragon_wings_toggle", this).requires(new FakeRequireToggle(false)).onchange(this, () => {
+ global.soopyV2Server.updateCosmeticsData({
+ cosmetic: "dragon_wings",
+ type: this.dragon_wings_enabled.getValue() ? "enable" : "disable"
+ })
+ })
+
+ this.postRenderEntityTrigger = undefined
+
+ this.loadCosmeticsData()
+
+ this.worldLoad()
+
+ this.registerEvent("tick", this.tick)
+ this.registerEvent("renderWorld", this.renderWorld)
+ this.registerEvent("playerJoined", this.playerJoined)
+ this.registerEvent("playerLeft", this.playerLeft)
+ this.registerEvent("worldLoad", this.worldLoad)
+ this.registerStep(false, 2, this.step)
+ this.registerEvent('gameUnload', () => {
+ if (this.postRenderEntityTrigger) {
+ this.postRenderEntityTrigger.unregister()
+ this.postRenderEntityTrigger = undefined
+ }
+ })
+ // this.registerStep(false, 60*10, ()=>{
+ // new Thread(()=>{this.loadCosmeticsData.call(this)}).start()
+ // })
+ // this.registerEvent("renderEntity", this.renderEntity)
+
+ if (global.soopyV2Server && global.soopyV2Server.userCosmeticPermissions) {
+ this.updateUserCosmeticPermissionSettings()
+ }
+ }
+
+ updateUserCosmeticPermissionSettings() {
+ if (!this.enabled) return
+
+ if (global.soopyV2Server.userCosmeticPermissions === "*" || global.soopyV2Server.userCosmeticPermissions.dragon_wings) {
+ this.dragon_wings_enabled.requiresO.set(true)
+ } else {
+ this.dragon_wings_enabled.requiresO.set(false)
+ }
+ }
+
+ renderWorld(ticks) {
+ for (let i = 0; i < this.loadedCosmetics.length; i++) {
+ this.loadedCosmetics[i].onRenderEntity(ticks, false)
+ }
+ }
+
+ async loadCosmeticsData() {
+ let data = await fetch("http://soopy.dev/api/soopyv2/cosmetics.json").json()
+
+ this.cosmeticsData = data
+ this.playerHasACosmeticA = !!data[Player.getUUID().toString().replace(/-/g, "")]
+ if (this.playerHasACosmeticA && !this.postRenderEntityTrigger) {
+ // this.registerEvent("postRenderEntity", this.renderEntity)
+ this.postRenderEntityTrigger = register("postRenderEntity", (entity, pos, ticks, event) => {
+ if (ticks !== 1) return
+ if (this.uuidToCosmeticDirect[entity.getUUID().toString().replace(/-/g, "")]) {
+ let cosmetics = Object.values(this.uuidToCosmeticDirect[entity.getUUID().toString().replace(/-/g, "")])
+ for (let cosmetic of cosmetics) {
+ cosmetic.onRenderEntity(ticks, true)
+ }
+ }
+ })
+ }
+
+ this.scanForNewCosmetics()
+ }
+
+ setUserCosmeticsInformation(uuid, cosmetics) {
+ if (!this.enabled) return
+ uuid = uuid.replace(/-/g, "")
+
+ this.loadedCosmetics = this.loadedCosmetics.filter(cosmetic => {
+ if (cosmetic.player.getUUID().toString().replace(/-/g, "") === uuid) {
+ return false
+ }
+ return true
+ })
+ Object.keys(this.uuidToCosmetic).forEach(cosmeticName => {
+ delete this.uuidToCosmetic[cosmeticName][uuid]
+ })
+
+ delete this.uuidToCosmeticDirect[uuid]
+
+ if (!cosmetics) {
+ delete this.cosmeticsData[uuid]
+ return
+ }
+ this.cosmeticsData[uuid] = cosmetics
+
+ this.scanForNewCosmetics()
+ }
+
+ step() {
+ this.scanForNewCosmetics()
+
+ this.filterUnloadedCosmetics(false)
+
+ this.restoreEssentialCosmetics()
+
+ this.loadedCosmetics.forEach(c => {
+ c.removeEssentialCosmetics()
+ })
+ }
+ scanForNewCosmetics() {
+ this.loadCosmeticsForPlayer(Player)
+ World.getAllPlayers().forEach(p => {
+ if (p.getUUID().toString().replace(/-/g, "") === Player.getUUID().toString().replace(/-/g, "")) return
+ this.loadCosmeticsForPlayer(p)
+ })
+ }
+
+ loadCosmeticsForPlayer(player) {
+ Object.keys(this.cosmeticsList).forEach(cosmeticName => {
+ if (!this.uuidToCosmetic[cosmeticName]) this.uuidToCosmetic[cosmeticName] = {}
+
+ if (this.uuidToCosmetic[cosmeticName][player.getUUID().toString().replace(/-/g, "")]) return
+
+ if (this.shouldPlayerHaveCosmetic(player, cosmeticName)) {
+ let cosmetic = new (this.cosmeticsList[cosmeticName])(player, this)
+ this.loadedCosmetics.push(cosmetic)
+ this.uuidToCosmetic[cosmeticName][player.getUUID().toString().replace(/-/g, "")] = cosmetic
+
+ if (!this.uuidToCosmeticDirect[player.getUUID.toString()]) this.uuidToCosmeticDirect[player.getUUID().toString().replace(/-/g, "")] = {}
+ this.uuidToCosmeticDirect[player.getUUID().toString().replace(/-/g, "")][cosmeticName] = cosmetic
+ }
+ })
+ }
+
+ worldLoad() {
+ this.loadedCosmetics = []
+ this.uuidToCosmetic = {}
+ this.uuidToCosmeticDirect = {}
+
+ this.loadCosmeticsForPlayer(Player)
+ this.scanForNewCosmetics()
+ }
+
+ playerJoined(player) {
+ if (player.getUUID().toString().replace(/-/g, "") === Player.getUUID().toString().replace(/-/g, "")) return
+
+ this.loadCosmeticsForPlayer(player)
+ }
+
+ playerLeft(playerName) {
+ this.loadedCosmetics = this.loadedCosmetics.filter(cosmetic => {
+ if (cosmetic.player.getUUID().toString().replace(/-/g, "") === Player.getUUID().toString().replace(/-/g, "")) return true
+ if (cosmetic.player.getName() === playerName) {
+ this.uuidToCosmetic[cosmetic.id][cosmetic.player.getUUID().toString().replace(/-/g, "")] = undefined
+
+ this.uuidToCosmeticDirect[cosmetic.player.getUUID().toString().replace(/-/g, "")] = undefined
+ return false
+ }
+ return true
+ })
+ }
+
+ shouldPlayerHaveCosmetic(player, cosmetic) {
+ if (this.getPlayerCosmeticSettings(player, cosmetic)) {
+ if (!this.getPlayerCosmeticSettings(player, cosmetic).enabled) return false
+ return true
+ }
+ return false
+ }
+ getPlayerCosmeticSettings(player, cosmetic) {
+ return this.cosmeticsData[player.getUUID().toString().replace(/-/g, "")]?.[cosmetic]
+ }
+
+ filterUnloadedCosmetics(tick = false) {
+ this.loadedCosmetics = this.loadedCosmetics.filter(cosmetic => {
+ if (tick) cosmetic.onTick()
+ if (cosmetic.player.getUUID().toString().replace(/-/g, "") === Player.getUUID().toString().replace(/-/g, "")) return true
+ if (cosmetic.player.getPlayer()[f.isDead]) { //filter out players that are no longer loaded
+ this.uuidToCosmetic[cosmetic.id][cosmetic.player.getUUID().toString().replace(/-/g, "")] = undefined
+
+ this.uuidToCosmeticDirect[cosmetic.player.getUUID().toString().replace(/-/g, "")] = undefined
+ return false
+ }
+ return true
+ })
+ }
+
+ tick() {
+ for (let cosmetic of this.loadedCosmetics) {
+ cosmetic.onTick()
+ }
+ }
+
+ restoreEssentialCosmetics() {
+ this.hiddenEssentialCosmetics.forEach(cosmetic => {
+ setField(cosmetic, "showModel", true)
+ })
+ this.hiddenEssentialCosmetics = []
+ }
+
+ initVariables() {
+ this.loadedCosmetics = undefined
+ this.uuidToCosmetic = undefined
+ this.uuidToCosmeticDirect = {}
+ this.playerHasACosmeticA = undefined
+ this.cosmeticsData = undefined
+ this.hiddenEssentialCosmetics = undefined
+ this.hiddenEssentialCosmetics = undefined
+ this.cosmeticsList = undefined
+ }
+
+ onDisable() {
+
+ if (this.postRenderEntityTrigger) {
+ this.postRenderEntityTrigger.unregister()
+ this.postRenderEntityTrigger = undefined
+ }
+
+ this.restoreEssentialCosmetics()
+
+ this.initVariables()
+ }
+}
+
+let instance = new Cosmetics()
+
+module.exports = {
+ class: instance
+}
+
+function setField(e, field, value) {
+
+ let field2 = e.class.getDeclaredField(field);
+
+ field2.setAccessible(true)
+
+ return field2.set(e, value)
+}
\ No newline at end of file
diff --git a/src/features/cosmetics/metadata.json b/src/features/cosmetics/metadata.json
new file mode 100644
index 0000000..f198cff
--- /dev/null
+++ b/src/features/cosmetics/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Cosmetics",
+ "description": "Cosmetics settings",
+ "isTogglable": false,
+ "defaultEnabled": true,
+ "isHidden": "hiddenRequirement.js",
+ "sortA": 1
+}
\ No newline at end of file
diff --git a/src/features/dataLoader/index.js b/src/features/dataLoader/index.js
new file mode 100644
index 0000000..eccafb4
--- /dev/null
+++ b/src/features/dataLoader/index.js
@@ -0,0 +1,280 @@
+///
+///
+import Feature from "../../featureClass/class";
+import socketConnection from "../../socketConnection";
+import { fetch } from "../../utils/networkUtils";
+
+class DataLoader extends Feature {
+ constructor() {
+ super()
+ }
+
+ onEnable() {
+ this.initVariables()
+
+ this.stats = {}
+
+ this.area = undefined
+ this.areaFine = undefined
+
+ this.isInSkyblock = false
+
+ this.dungeonPercentCleared = 0
+
+ this.registerStep(true, 2, this.step)
+
+ this.registerStep(false, 170, this.loadApiStepThing)
+ this.registerStep(false, 60 * 5, this.step_5min)
+
+ this.registerEvent("worldLoad", this.worldLoad)
+
+ this.api_loaded_event = this.createCustomEvent("apiLoad")
+
+ this.checkingPing = false;
+ this.lastPingCheck = 0;
+ this.lastPings = [undefined, undefined, undefined];
+ this.ping = 0;
+ this.pingI = 0;
+
+ this.registerChat("&b&bYou are currently connected to server &6${*}&r", (e) => {
+ if (this.checkingPing) {
+ this.lastPings[this.pingI % 3] = Date.now() - this.lastPingCheck;
+ cancel(e);
+ this.checkingPing = false;
+
+ if (this.lastPings.includes(undefined)) {
+ this.ping = this.lastPings[this.pingI % 3];
+ } else {
+ this.ping = [...this.lastPings].sort((a, b) => a - b)[1];
+ }
+ this.pingI++;
+ }
+ });
+
+ this.lastServer = undefined
+ this.lastSentServer = 0
+
+ this.currentMayorPerks = new Set()
+
+ this.loadedApiDatas = {}
+
+ this.partyMembers = new Set()
+ this.partyMembers.add(Player.getName())
+
+ this.lastApiData = {
+ "skyblock": undefined,
+ "player": undefined,
+ "skyblock_raw": undefined, //the _raw is loaded from hypixel api instead of soopy api
+ "player_raw": undefined
+ }
+
+ this.worldLoaded = true
+
+ this.loadApi()
+
+ this.step_5min()
+
+ this.firstLoaded = false;
+
+ ["You are not currently in a party.", "You have been kicked from the party by ${*}", "You left the party.", "The party was disbanded because all invites expired and the party was empty", "${*} &r&ehas disbanded the party!&r"].forEach(m => this.registerChat(m, () => {
+ this.partyMembers.clear()
+ this.partyMembers.add(Player.getName())
+ }));
+
+ ["${mem} &r&ejoined the party.&r", "${mem} &r&einvited &r${*} &r&eto the party! They have &r&c60 &r&eseconds to accept.&r", "&dDungeon Finder &r&f> &r${mem} &r&ejoined the dungeon group! (&r&b${*}&r&e)&r"].forEach(m => this.registerChat(m, (mem) => {
+ this.partyMembers.add(ChatLib.removeFormatting(mem.trim().split(" ").pop().trim()))
+ }));
+ ["${mem} &r&ehas been removed from the party.&r", "${mem} &r&ehas left the party.&r", "${mem} &r&ewas removed from your party because they disconnected&r", "Kicked ${mem} because they were offline."].forEach(m => this.registerChat(m, (mem) => {
+ this.partyMembers.delete(ChatLib.removeFormatting(mem.trim().split(" ").pop().trim()))
+ }))
+ this.registerChat("&eYou have joined &r${mem}'s &r&eparty!&r", (mem) => {
+ this.partyMembers.clear()
+ this.partyMembers.add(Player.getName())
+ this.partyMembers.add(ChatLib.removeFormatting(p = mem.trim().split(" ").pop().trim()))
+ })
+ this.registerChat("&eYou have joined &r${mem}' &r&eparty!&r", (mem) => {
+ this.partyMembers.clear()
+ this.partyMembers.add(Player.getName())
+ this.partyMembers.add(ChatLib.removeFormatting(mem).trim())
+ })
+ this.registerChat("&eYou'll be partying with: ${mem}", (mem) => {
+ mem.split(",").forEach(p => {
+ this.partyMembers.add(ChatLib.removeFormatting(p.trim().split(" ").pop().trim()))
+ })
+ })
+ this.registerChat("&eParty ${type}: ${mem}", (type, mem) => {
+ if (type.toLowerCase().includes("leader")) this.partyMembers.clear()
+ ChatLib.removeFormatting(mem).split("●").forEach(p => {
+ if (!p.trim()) return
+ this.partyMembers.add(p.trim().split(" ").pop().trim())
+ })
+ })
+ this.registerCommand("pmembdebug", () => {
+ ChatLib.chat([...this.partyMembers].join(" | "))
+ })
+ }
+
+ getPing() {
+ if (Date.now() - this.lastPingCheck > 60000 * 30 || (Date.now() - this.lastPingCheck > 60000 && this.lastPings.includes(undefined) && this.bloodX !== -1)) {
+ this.lastPingCheck = Date.now();
+ ChatLib.command("whereami");
+ this.checkingPing = true;
+ }
+ return this.ping || 0
+ }
+
+ async step_5min() {
+ let data = await fetch("http://soopy.dev/api/v2/mayor").json()
+
+ if (!data.success) return
+ this.mayorData = data.data
+ this.currentMayorPerks = new Set(data.data.mayor.perks.map(a => a.name))
+ }
+
+ worldLoad() {
+ this.area = undefined
+ this.areaFine = undefined
+ this.dungeonFloor = undefined
+ this.loadApiData("skyblock", false)
+ }
+
+ loadApiStepThing() {
+ this.loadApiData("skyblock", false)
+ }
+ async loadApi() {
+ let data = await fetch("http://soopy.dev/api/v2/player_skyblock/" + Player.getUUID().replace(/-/g, "")).json()
+
+ if (!data.success) return
+
+ this.api_loaded_event.trigger(data, "skyblock", true, true)
+ this.lastApiData.skyblock = data
+ }
+
+ loadApiData(type, soopyServer) {
+ if (this.FeatureManager.features["globalSettings"] === undefined || this.FeatureManager.features["globalSettings"].class.apiKeySetting === undefined) {
+ return
+ }
+ let key = this.FeatureManager.features["globalSettings"].class.apiKeySetting.getValue()
+ if (!key) return
+
+ if (this.loadedApiDatas[type] !== undefined) {
+ if (Date.now() - this.loadedApiDatas[type] < 5000) return
+ }
+
+ this.loadedApiDatas[type] = Date.now()
+
+ if (soopyServer) {
+
+ } else {
+ if (type === "skyblock") {
+ fetch("https://api.hypixel.net/skyblock/profiles?key=" + key + "&uuid=" + Player.getUUID().replace(/-/g, "")).json().then(data => {
+ if (!data.success) return
+
+ this.api_loaded_event.trigger(data, "skyblock", false, true)
+ this.lastApiData.skyblock_raw = data
+ })
+ }
+ }
+ }
+
+ step() { //2fps
+ if (!this.firstLoaded) {
+ if (!(this.FeatureManager.features["globalSettings"] === undefined || this.FeatureManager.features["globalSettings"].class.apiKeySetting === undefined)) {
+ this.loadApiData("skyblock", false)
+ this.firstLoaded = true
+ }
+ }
+ this.isInSkyblock = Scoreboard.getTitle()?.removeFormatting().includes("SKYBLOCK")
+
+ if (!this.isInSkyblock) {
+ this.stats = {}
+ this.isInDungeon = false
+ this.dungeonFloor = undefined
+ return
+ }
+
+ this.stats["Area"] = undefined
+ this.stats["Dungeon"] = undefined
+
+ if (World.isLoaded() && TabList.getNames()) {
+ TabList.getNames().forEach(n => {
+ n = ChatLib.removeFormatting(n)
+ if (n.includes(": ")) {
+ if (n.includes('Secrets Found')) {
+ if (n.includes('%')) {
+ this.stats["Secrets Found%"] = n.split(": ")[1]
+ } else {
+ this.stats["Secrets Found"] = n.split(": ")[1]
+ }
+ } else {
+ this.stats[n.split(": ")[0].trim()] = n.split(": ")[1].trim()
+ }
+ }
+ })
+ }
+
+ if (this.stats["Dungeon"]) {
+ this.stats["Area"] = this.stats["Dungeon"]
+ this.isInDungeon = true
+ } else {
+ this.isInDungeon = false
+ }
+
+ this.slayerXpToSpawn = undefined
+ Scoreboard.getLines().forEach(line => {
+ let name = ChatLib.removeFormatting(line.getName()).replace(/[^A-z0-9 \:\(\)\.]/g, "")
+ if (this.isInDungeon) {
+ if (name.includes("The Catacombs (")) {
+ this.dungeonFloor = name.split("(")[1].split(")")[0].toUpperCase()
+ }
+ }
+ if (ChatLib.removeFormatting(line).startsWith(" ⏣ ")) {
+ this.areaFine = ChatLib.removeFormatting(line).split(" ⏣ ")[1].replace(/[^A-z0-9 \:\(\)\.\-]/g, "")
+ }
+ if (name.startsWith("Purse: ")) {
+ this.purse = parseInt(name.split("Purse: ")[1].split(" ")[0])
+ }
+ if (name.startsWith("Bits: ")) {
+ this.bits = parseInt(name.split("Bits: ")[1].split(" ")[0])
+ }
+ if (name.startsWith("Cleared: ")) {
+ this.dungeonPercentCleared = parseInt(name.split(" ")[1]) / 100
+ }
+
+ if (name.endsWith("Combat XP")) {
+ this.slayerXpToSpawn = ChatLib.removeFormatting(name).split("(")[1].split(")")[0].split("/").map(parseInt)
+ }
+ })
+
+ this.area = this.stats["Area"]
+
+
+ if (this.lastServer !== this.stats.Server || Date.now() - this.lastSentServer > 60000 * 5) {
+ this.lastServer = this.stats.Server;
+ this.lastSentServer = Date.now()
+
+ socketConnection.setServer(this.stats.Server, this.area, this.areaFine);
+ }
+ }
+
+ initVariables() {
+ this.stats = undefined
+ this.isInDungeon = false
+
+ this.dungeonFloor = undefined
+ this.area = undefined
+ this.areaFine = undefined
+ this.bits = undefined
+ this.purse = undefined
+ this.lastApiData = undefined
+ this.isInSkyblock = undefined
+ }
+
+ onDisable() {
+ this.initVariables()
+ }
+}
+
+module.exports = {
+ class: new DataLoader()
+}
\ No newline at end of file
diff --git a/src/features/dataLoader/metadata.json b/src/features/dataLoader/metadata.json
new file mode 100644
index 0000000..4953f99
--- /dev/null
+++ b/src/features/dataLoader/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Data loader",
+ "description": "Loads data",
+ "isHidden": true,
+ "isTogglable": false,
+ "defaultEnabled": true,
+ "sortA": 0
+}
\ No newline at end of file
diff --git a/src/features/dungeonMap/dungeonBossImages/f1.png b/src/features/dungeonMap/dungeonBossImages/f1.png
new file mode 100644
index 0000000..5bc2d08
Binary files /dev/null and b/src/features/dungeonMap/dungeonBossImages/f1.png differ
diff --git a/src/features/dungeonMap/index.js b/src/features/dungeonMap/index.js
new file mode 100644
index 0000000..456dff3
--- /dev/null
+++ b/src/features/dungeonMap/index.js
@@ -0,0 +1,1186 @@
+///
+///
+
+const Color = Java.type("java.awt.Color")
+
+import Feature from "../../featureClass/class";
+import { f, m } from "../../../mappings/mappings";
+import renderLibs from "../../../guimanager/renderLibs";
+import ToggleSetting from "../settings/settingThings/toggle";
+import { drawBoxAtBlock } from "../../utils/renderUtils";
+import { SoopyGui, SoopyRenderEvent } from "../../../guimanager";
+import SoopyGuiElement from "../../../guimanager/GuiElement/SoopyGuiElement";
+import SoopyMouseClickEvent from "../../../guimanager/EventListener/SoopyMouseClickEvent";
+import ButtonWithArrow from "../../../guimanager/GuiElement/ButtonWithArrow";
+import ImageLocationSetting from "../settings/settingThings/imageLocation";
+import socketConnection from "../../socketConnection";
+import SoopyKeyPressEvent from "../../../guimanager/EventListener/SoopyKeyPressEvent";
+import SettingBase from "../settings/settingThings/settingBase";
+import { Box } from "../../utils/renderJavaUtils";
+const BufferedImage = Java.type("java.awt.image.BufferedImage")
+const AlphaComposite = Java.type("java.awt.AlphaComposite")
+
+class DungeonMap extends Feature {
+ constructor() {
+ super()
+ }
+
+ isInDungeon() {
+ if (!this.FeatureManager || !this.FeatureManager.features["dataLoader"]) return false
+ return this.FeatureManager.features["dataLoader"].class.isInDungeon
+ }
+
+ onEnable() {
+ this.initVariables()
+
+ this.mapInfo = new SettingBase("NOTE: The more players in the party with this", "category enabled the more accurate the map will be.", undefined, "map_info", this)
+ this.renderMap = new ToggleSetting("Render Map", "Toggles Rendering the map on the hud", false, "dmap_render", this)
+ this.mapIcons = new ToggleSetting("Icons for puzzles on map", "Toggles Rendering the puzzle icons on map", true, "dmap_icons", this).requires(this.renderMap)
+ this.mapLocation = new ImageLocationSetting("Map Location", "Sets the location of the map on the hud", "dmap_location", this, [10, 10, 1], new Image(javax.imageio.ImageIO.read(new java.io.File("./config/ChatTriggers/modules/SoopyV2/features/dungeonMap/map.png"))), 100, 100).requires(this.renderMap)
+ this.mapBackground = new ToggleSetting("Map Background And Border", "Puts a grey background behind the map + Black border", true, "dmap_background", this)
+ this.showMapInBoss = new ToggleSetting("Keep showing the map in the dungeon boss room", "This will center the map when in boss to still be usefull", true, "dmap_enable_boss", this)
+ this.borderedHeads = new ToggleSetting("Add a black border around heads on map", "", false, "dmap_border_head", this)
+ this.roomsecrets = new ToggleSetting("Shows secretscompleted/total secrets in room", "(works best when all of party is using soopy map)", false, "roomsecrets", this)
+ this.brBox = new ToggleSetting("Box around doors in br", "In map category because it uses map to find location (no esp)", true, "dmap_door", this)
+ this.spiritLeapOverlay = new ToggleSetting("Spirit leap overlay", "Cool overlay for the spirit leap menu", true, "spirit_leap_overlay", this)
+ // this.spiritLeapOverlay = new ToggleSetting("Spirit leap overlay", "Cool overlay for the spirit leap menu", true, "spirit_leap_overlay", this).requires(this.spiritLeapOverlay)
+
+ this.MAP_QUALITY_SCALE = 1
+ this.IMAGE_SIZE = 128 * this.MAP_QUALITY_SCALE
+
+ this.defaultPlayerImage = renderLibs.getImage("https://crafatar.com/avatars/dc8c39647b294e03ae9ed13ebd65dd29?size=8", true)
+ this.mapDataPlayers = {}
+ this.offset = []
+ this.people = []
+ this.mapScale = 1
+ this.puzzles = {}
+ this.puzzlesTab = []
+ this.roomWidth = 1
+ this.nameToUUID = {}
+ this.deadPlayers = new Set()
+ this.newPuzzlesTab = []
+ this.mortLocationOnMap = undefined
+ this.brBoxLoc = undefined
+ this.keys = 0
+
+ this.roomDataStuff = new Map()
+ this.roomDataStuffRender = new Map()
+ // this.invMapImage = new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB)
+ // this.renderImage = new BufferedImage(this.IMAGE_SIZE, this.IMAGE_SIZE, BufferedImage.TYPE_INT_ARGB)
+ this.mapData = undefined
+ this.idToPlayer = {}
+
+ this.barrier_block_item = new Item("minecraft:barrier")
+ this.puzzleItems = {
+ "Water Board": new Item("minecraft:water_bucket"),
+ "Higher Or Lower": new Item("minecraft:blaze_powder"),
+ "Quiz": new Item("minecraft:book"),
+ "Three Weirdos": new Item("minecraft:chest"),
+ "Tic Tac Toe": new Item("minecraft:shears"),
+ "Teleport Maze": new Item("minecraft:end_portal_frame"),
+ "Ice Fill": new Item("minecraft:ice"),
+ "Creeper Beams": new Item("minecraft:sea_lantern"),
+ "Bomb Defuse": new Item("minecraft:tnt"),
+ "Boulder": new Item("minecraft:planks"),
+ "Ice Path": new Item("minecraft:mob_spawner")
+ }
+
+ this.dungeonBossImages = {
+ // "F1": [
+ // {
+ // image: new Image(javax.imageio.ImageIO.read(new java.io.File("./config/ChatTriggers/modules/SoopyV2/features/dungeonMap/dungeonBossImages/f1.png"))),
+ // bounds: [[-65, 70, -3], [-19, 90, 45]],
+ // widthInWorld: 46,
+ // heightInWorld: 48,
+ // topLeftLocation: [-64, -2]
+ // }
+ // ]
+ }
+
+ this.currDungeonBossImage = undefined
+ this.dungeonBrBoxElm = new Box([0, 0, 0], [3, 4, 3], 1, 0, 0, 1, 3, false)
+
+ this.bloodOpened = false
+ this.registerChat("&r&cThe &r&c&lBLOOD DOOR&r&c has been opened!&r", () => {
+ this.bloodOpened = true
+ this.keys--
+ this.dungeonBrBoxElm.setRGBA(1, 0, 0, 1)
+ this.dungeonBrBoxElm.stopRender()
+ })
+
+ this.registerChat("${*} &r&ehas obtained &r&a&r&${*} Key&r&e!&r", () => {
+ this.keys++
+ this.dungeonBrBoxElm.setRGBA(0, 1, 0, 1)
+ })
+ this.registerChat("&r&eA &r&a&r&${*} Key&r&e was picked up!&r", () => {
+ this.keys++
+ this.dungeonBrBoxElm.setRGBA(0, 1, 0, 1)
+ })
+
+ this.lastDoorOpener = undefined
+ this.registerChat("&r&a${player}&r&a opened a &r&8&lWITHER &r&adoor!&r", (player) => {
+ this.lastDoorOpener = ChatLib.removeFormatting(player)
+ this.keys--
+ this.dungeonBrBoxElm.setRGBA(1, 0, 0, 1)
+ })
+
+ this.spiritLeapOverlayGui = new SpiritLeapOverlay(this)
+
+ // this.registerEvent("tick", this.tick)
+ this.registerStep(true, 3, this.step)
+ this.registerStep(true, 10, () => {
+ this.spiritLeapOverlayGui.tick()
+ }).registeredWhen(() => this.isInDungeon())
+ this.registerStep(false, 5, this.step5s).registeredWhen(() => this.isInDungeon())
+ this.registerEvent("renderOverlay", this.renderOverlay).registeredWhen(() => this.isInDungeon())
+ this.registerEvent("worldLoad", this.worldLoad)
+ this.renderingPlayerList = false
+ this.registerEvent("renderPlayerList", () => {
+ this.renderingPlayerList = true
+ })
+ this.registerEvent("renderDebug", () => {
+ this.renderingPlayerList = true
+ })
+
+ this.registerEvent("guiOpened", (event) => {
+ if (this.spiritLeapOverlay.getValue()) this.spiritLeapOverlayGui.guiOpened.call(this.spiritLeapOverlayGui, event)
+ })
+
+ this.boringMap = false
+ this.registerChat("&r&r&r ${*}&r&cThe Catacombs &r&8- &r&eFloor ${*}&r", () => {
+ this.boringMap = true
+ })
+ this.registerChat("&r&r&r ${*}&r&cMaster Mode Catacombs &r&8- &r&eFloor ${*}&r", () => {
+ this.boringMap = true
+ })
+ this.registerChat("&r&aDungeon starts in 1 second.&r", () => {
+ this.boringMap = false
+ })
+ this.registerChat("&r&aDungeon starts in 1 second. Get ready!&r", () => {
+ this.boringMap = false
+ })
+
+ this.running = true
+ this.registerEvent("gameUnload", () => {
+ this.running = false
+ })
+ this.registerChat("&r&c ☠ ${info} and became a ghost&r&7.&r", (info, e) => {
+ let player = ChatLib.removeFormatting(info.split(" ")[0])
+
+ this.deadPlayers.add(this.nameToUUID[player.toLowerCase()])
+ });
+ this.registerChat("&r&a ❣ &r${info} was revived${*}!&r", (info, e) => {
+ let player = ChatLib.removeFormatting(info.split(" ")[0])
+
+ this.deadPlayers.delete(this.nameToUUID[player.toLowerCase()])
+ });
+
+ this.registerStep(true, 3, () => {
+ if (!this.isInDungeon()) return
+
+ this.updateMapImage()
+ }).registeredWhen(() => this.isInDungeon())
+
+ this.registerChat("&r&r&r &r&cThe Catacombs &r&8- &r&eFloor ${*} Stats&r", () => {
+ this.puzzles = {}
+ })
+
+ let lastXY = ""
+ let registerActionBar = this.registerCustom("actionbar", (curr, max) => {
+ let loc = this.getRoomXYWorld()
+
+ if (lastXY !== loc.join(",")) {
+ lastXY = loc.join(",")
+ return
+ }
+ // if (curr === max) curr = "&a" + curr
+ if (!this.roomDataStuff.get(loc.join(",")) || this.roomDataStuff.get(loc.join(","))[0] !== curr + " " + max) {
+ this.roomDataStuff.set(loc.join(","), [curr + " " + max, this.getCurrentRoomId()])
+
+ socketConnection.sendDungeonData2(this.people, [loc.join(","), curr + " " + max, this.getCurrentRoomId()])
+ }
+ })
+ registerActionBar.trigger.setCriteria('&7${curr}/${max} Secrets').setParameter('contains');
+ }
+
+ getCurrentRoomId() {
+ let id = Scoreboard.getLineByIndex(Scoreboard.getLines().length - 1).getName().trim().split(" ").pop()
+
+ return id
+ }
+
+ updateDungeonMapData2(data) {
+ // console.log("Recieved: " + JSON.stringify(data, undefined, 2))
+ this.roomDataStuff.set(data[0], [data[1], data[2]])
+ }
+ worldLoad() {
+ this.dungeonBrBoxElm.stopRender()
+ this.mortLocation = undefined
+ this.mapDataPlayers = {}
+ this.offset = []
+ this.mapScale = 1
+ this.puzzles = {}
+ this.puzzlesTab = []
+ this.brBoxLoc = undefined
+ this.mortLocationOnMap = undefined
+ this.bloodOpened = false
+ this.keys = 0
+ this.idToPlayer = {}
+ this.roomDataStuff.clear()
+ }
+
+ renderOverlay() {
+ if (!this.renderingPlayerList && this.isInDungeon() && this.renderMap.getValue() && !this.spiritLeapOverlayGui.soopyGui.ctGui.isOpen()) {
+ this.drawMap(this.mapLocation.getValue()[0], this.mapLocation.getValue()[1], 100 * this.mapLocation.getValue()[2], 0.5 * this.mapLocation.getValue()[2])
+ }
+ this.renderingPlayerList = false
+ }
+
+ drawMap(x, y, size, scale) {
+ if (this.mapData) {
+ if (this.FeatureManager.features["dataLoader"].class.stats.Time === "Soon!" && Player.getInventory().getStackInSlot(8).getID() !== 358) return
+ if (this.boringMap) {
+ if (this.mapBackground.getValue()) Renderer.drawRect(Renderer.color(0, 0, 0, 100), x, y, size, size)
+
+ if (this.mapBackground.getValue()) Renderer.drawRect(Renderer.color(0, 0, 0), x, y, size, 2)
+ if (this.mapBackground.getValue()) Renderer.drawRect(Renderer.color(0, 0, 0), x, y, 2, size)
+ if (this.mapBackground.getValue()) Renderer.drawRect(Renderer.color(0, 0, 0), x + size - 2, y, 2, size)
+ if (this.mapBackground.getValue()) Renderer.drawRect(Renderer.color(0, 0, 0), x, y + size - 2, size, 2)
+ if (this.currDungeonBossImage) {
+ this.currDungeonBossImage.image.draw(x, y, size, size)
+ } else {
+ GlStateManager.func_179094_E(); //GlStateManager.push()
+ Renderer.translate(x, y, 1)
+ GlStateManager.func_179152_a(size / 128, size / 128, 1); //GlStateManager.scale()
+ GlStateManager.func_179131_c(1.0, 1.0, 1.0, 1.0); // GlStateManager.color()
+ Client.getMinecraft().field_71460_t.func_147701_i().func_148250_a(this.mapData, true);
+ GlStateManager.func_179121_F(); //GlStateManager.pop()
+ }
+
+ return
+ }
+
+ World.getAllPlayers().forEach(player => {
+ if (player.getPing() === -1) return
+ if (!this.people.includes(player.getName())) return
+ this.mapDataPlayers[player.getUUID().toString()] = {
+ x: player.getX(),
+ y: player.getZ(),
+ rot: player.getYaw() + 180,
+ username: player.getName(),
+ uuid: player.getUUID().toString()
+ }
+ })
+ this.mapDataPlayers[Player.getUUID().toString()] = {
+ x: Player.getX(),
+ y: Player.getZ(),
+ rot: Player.getYaw() + 180,
+ username: Player.getName(),
+ uuid: Player.getUUID().toString()
+ }
+
+ let uuid = Player.getUUID().toString()
+ let renderX
+ let renderY
+ let xOff = 0
+ let yOff = 0
+ let disableMap = false
+ if (this.mapDataPlayers[uuid]) {
+
+ if (this.currDungeonBossImage) {
+ renderX = (this.mapDataPlayers[uuid].x - this.currDungeonBossImage.topLeftLocation[0]) / this.currDungeonBossImage.widthInWorld * size
+ renderY = (this.mapDataPlayers[uuid].y - this.currDungeonBossImage.topLeftLocation[1]) / this.currDungeonBossImage.heightInWorld * size
+ } else {
+ renderX = this.mapDataPlayers[uuid].x / this.mapScale / 128 * size + this.offset[0] / 128 * size//*16/this.roomWidth
+ renderY = this.mapDataPlayers[uuid].y / this.mapScale / 128 * size + this.offset[1] / 128 * size//*16/this.roomWidth
+ }
+
+ if (renderX < 0 || renderX > size
+ || renderY < 0 || renderY > size) {
+ xOff = size / 2 - renderX
+ yOff = size / 2 - renderY
+
+ if (!this.showMapInBoss.getValue()) {
+ disableMap = true
+ }
+ }
+ }
+ if (disableMap) return
+
+ if (this.mapBackground.getValue()) Renderer.drawRect(Renderer.color(0, 0, 0, 100), x, y, size, size)
+ renderLibs.scizzor(x + 2, y + 2, size - 4, size - 4)
+
+ if (this.currDungeonBossImage) {
+ this.currDungeonBossImage.image.draw(x + xOff, y + yOff, size, size)
+ } else {
+ GlStateManager.func_179094_E(); //GlStateManager.push()
+ Renderer.translate(x + xOff, y + yOff, 1)
+ GlStateManager.func_179152_a(size / 128, size / 128, 1); //GlStateManager.scale()
+ GlStateManager.func_179131_c(1.0, 1.0, 1.0, 1.0); // GlStateManager.color()
+ Client.getMinecraft().field_71460_t.func_147701_i().func_148250_a(this.mapData, true);
+ GlStateManager.func_179121_F(); //GlStateManager.pop()
+ }
+ try {
+ this.drawOtherMisc(x + xOff, y + yOff, size, scale)
+
+ this.drawPlayersLocations(x + xOff, y + yOff, size, scale)
+
+ this.drawOtherMisc2(x + xOff, y + yOff, size, scale)
+ } catch (e) {
+ console.error(e)
+ console.error(e.stack)
+ }
+ renderLibs.stopScizzor()
+
+ if (this.mapBackground.getValue()) Renderer.drawRect(Renderer.color(0, 0, 0), x, y, size, 2)
+ if (this.mapBackground.getValue()) Renderer.drawRect(Renderer.color(0, 0, 0), x, y, 2, size)
+ if (this.mapBackground.getValue()) Renderer.drawRect(Renderer.color(0, 0, 0), x + size - 2, y, 2, size)
+ if (this.mapBackground.getValue()) Renderer.drawRect(Renderer.color(0, 0, 0), x, y + size - 2, size, 2)
+
+ }
+ }
+
+ drawOtherMisc(x2, y2, size, scale) {
+ if (this.currDungeonBossImage) return
+ if (this.mapIcons.getValue()) {
+ Object.keys(this.puzzles).forEach(loc => {
+ if (!this.puzzles[loc]) return
+ if (this.puzzles[loc][1]) return
+ let y = (loc % 128) / 128 * 100
+ let x = (Math.floor(loc / 128)) / 128 * 100
+
+ let item = this.puzzleItems[this.puzzles[loc][0]] || this.barrier_block_item
+
+ // lines.forEach((l, i)=>{
+ // renderLibs.drawStringCentered("&0&l" + l, x*scale*2+x2-l.length/2*scale*2, y*scale*2+y2-this.roomWidth/3*scale*2+this.roomWidth/3*scale*2+i*6*scale*2-((lines.length-1)*3+4)*scale*2, scale*2)
+ // })
+
+ item.draw(x * scale * 2 + x2 - this.roomWidth / 4 * scale * 2, y * scale * 2 + y2 - this.roomWidth / 4 * scale * 2, 1.5 * scale)
+ })
+ }
+ }
+
+ drawOtherMisc2(x2, y2, size, scale) {
+ if (this.currDungeonBossImage) return
+ if (this.roomsecrets.getValue()) {
+ for (let ent of this.roomDataStuffRender.entries()) {
+ let [loc, [secrets, roomid, color]] = ent
+ let [x, y] = loc.split(",")
+
+ let renderText = color + secrets
+
+ let val2 = ChatLib.removeFormatting(renderText)
+
+ let renderX = (parseInt(x) + 16) / this.mapScale / 128 * size + this.offset[0] / 128 * size
+ let renderY = (parseInt(y) + 16) / this.mapScale / 128 * size + this.offset[1] / 128 * size
+
+ Renderer.translate(0, 0, 1000)
+ renderLibs.drawStringCentered("§0" + val2, x2 + renderX + scale * 1.25, y2 + renderY - 2 * scale * 1.25, scale * 1.25)
+ Renderer.translate(0, 0, 1000)
+ renderLibs.drawStringCentered("§0" + val2, x2 + renderX - scale * 1.25, y2 + renderY - 2 * scale * 1.25, scale * 1.25)
+ Renderer.translate(0, 0, 1000)
+ renderLibs.drawStringCentered("§0" + val2, x2 + renderX, y2 + renderY + scale * 1.25 - 2 * scale * 1.25, scale * 1.25)
+ Renderer.translate(0, 0, 1000)
+ renderLibs.drawStringCentered("§0" + val2, x2 + renderX, y2 + renderY - scale * 1.25 - 2 * scale * 1.25, scale * 1.25)
+ Renderer.translate(0, 0, 1000)
+ renderLibs.drawStringCentered("§f" + renderText, x2 + renderX, y2 + renderY - 2 * scale * 1.25, scale * 1.25)
+ }
+ }
+ }
+
+ drawPlayersLocations(x, y, size, scale) {
+
+ let uuidToPlayer = {}
+ World.getAllPlayers().forEach(player => {
+ if (player.getPing() === -1) return
+ if (!this.people.includes(player.getName())) return
+ uuidToPlayer[player.getUUID().toString()] = player
+ })
+
+ Object.keys(this.mapDataPlayers).forEach((uuid) => {
+ if (this.deadPlayers.has(uuid)) return
+ if (uuid === Player.getUUID().toString()) return
+ let renderX
+ let renderY
+
+ if (this.currDungeonBossImage) {
+ renderX = (this.mapDataPlayers[uuid].x - this.currDungeonBossImage.topLeftLocation[0]) / this.currDungeonBossImage.widthInWorld * size
+ renderY = (this.mapDataPlayers[uuid].y - this.currDungeonBossImage.topLeftLocation[1]) / this.currDungeonBossImage.heightInWorld * size
+ } else {
+ renderX = this.mapDataPlayers[uuid].x / this.mapScale / 128 * size + this.offset[0] / 128 * size//*16/this.roomWidth
+ renderY = this.mapDataPlayers[uuid].y / this.mapScale / 128 * size + this.offset[1] / 128 * size//*16/this.roomWidth
+ }
+
+ if (this.borderedHeads.getValue()) {
+ Renderer.translate(renderX + x, renderY + y, 1000)
+ Renderer.scale(scale * 1.5, scale * 1.5)
+ Renderer.rotate(this.mapDataPlayers[uuid].rot)
+ Renderer.drawRect(Renderer.color(0, 0, 0), -6, -6, 12, 12)
+ }
+ Renderer.translate(renderX + x, renderY + y, 1000)
+ Renderer.scale(scale * 1.5, scale * 1.5)
+ Renderer.rotate(this.mapDataPlayers[uuid].rot)
+ this.getImageForPlayer(uuid).draw(-5, -5, 10, 10)
+ })
+
+ let uuid = Player.getUUID().toString()
+ if (!this.mapDataPlayers[uuid]) return
+ let renderX
+ let renderY
+
+ if (this.currDungeonBossImage) {
+ renderX = (this.mapDataPlayers[uuid].x - this.currDungeonBossImage.topLeftLocation[0]) / this.currDungeonBossImage.widthInWorld * size
+ renderY = (this.mapDataPlayers[uuid].y - this.currDungeonBossImage.topLeftLocation[1]) / this.currDungeonBossImage.heightInWorld * size
+ } else {
+ renderX = this.mapDataPlayers[uuid].x / this.mapScale / 128 * size + this.offset[0] / 128 * size//*16/this.roomWidth
+ renderY = this.mapDataPlayers[uuid].y / this.mapScale / 128 * size + this.offset[1] / 128 * size//*16/this.roomWidth
+ }
+
+
+ if (this.borderedHeads.getValue()) {
+ Renderer.translate(renderX + x, renderY + y, 1000)
+ Renderer.scale(scale * 1.5, scale * 1.5)
+ Renderer.rotate(this.mapDataPlayers[uuid].rot)
+ Renderer.drawRect(Renderer.color(0, 0, 0), -6, -6, 12, 12)
+ }
+ Renderer.translate(renderX + x, renderY + y, 1000)
+ Renderer.scale(scale * 1.5, scale * 1.5)
+ Renderer.rotate(this.mapDataPlayers[uuid].rot)
+ this.getImageForPlayer(uuid).draw(-5, -5, 10, 10)
+ }
+
+ getRoomXYWorld() {
+ let roomData = this.getRoomWorldData()
+ if (roomData.rotation === 4) {
+ return [roomData.x, roomData.y + 32]
+ }
+
+ return [roomData.x, roomData.y]
+ }
+
+ getRotation(x, y, width, height, roofY) {
+ let one = this.getTopBlockAt(x + width / 2 + 1, y + height / 2, roofY)
+ let two = this.getTopBlockAt(x + width / 2 - 1, y + height / 2, roofY)
+ let three = this.getTopBlockAt(x + width / 2, y + height / 2 + 1, roofY)
+ let four = this.getTopBlockAt(x + width / 2, y + height / 2 - 1, roofY)
+
+ if (one === 0 && three === 0) return 1
+ if (two === 0 && three === 0) return 2
+ if (one === 0 && four === 0) return 3
+ if (two === 0 && four === 0) return 4 //4 IS SO TOXIK HGOLY HEL I HATE L SHAPE ROOMS WHY DO THIS TO ME
+
+ return -1
+ }
+
+ getRoomWorldData() {
+ let x = Math.floor((Player.getX() + 8) / 32) * 32 - 8
+ let y = Math.floor((Player.getZ() + 8) / 32) * 32 - 8
+ let width = 30
+ let height = 30
+
+ let roofY = this.getRoofAt(x, y)
+
+ while (World.getBlockStateAt(new BlockPos(x - 1, roofY, y)).getBlockId() !== 0) {
+ x -= 32
+ width += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x, roofY, y - 1)).getBlockId() !== 0) {
+ y -= 32
+ height += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x - 1, roofY, y)).getBlockId() !== 0) { //second iteration incase of L shape
+ x -= 32
+ width += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x + width + 1, roofY, y)).getBlockId() !== 0) {
+ width += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x, roofY, y + height + 1)).getBlockId() !== 0) {
+ height += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x + width, roofY, y + height + 1)).getBlockId() !== 0) { //second iteration incase of L shape
+ height += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x + width + 1, roofY, y + height)).getBlockId() !== 0) { //second iteration incase of L shape
+ width += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x + width, roofY, y - 1)).getBlockId() !== 0) {//second iteration incase of L shape
+ y -= 32
+ height += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x - 1, roofY, y + height)).getBlockId() !== 0) { //third iteration incase of L shape
+ x -= 32
+ width += 32
+ }
+
+
+ return {
+ x,
+ y,
+ width,
+ height,
+ cx: x + width / 2,
+ cy: y + height / 2,
+ rotation: this.getRotation(x, y, width, height, roofY)
+ }
+ }
+
+ getRoofAt(x, z) {
+ let y = 255
+ while (y > 0 && World.getBlockStateAt(new BlockPos(x, y, z)).getBlockId() === 0) y--
+
+ return y
+ }
+
+ getTopBlockAt(x, z, y) {
+ if (!y) y = this.getHeightAt(x, z)
+
+ return World.getBlockStateAt(new BlockPos(x, y, z)).getBlockId()
+ }
+
+ step() {
+ if (!World.getWorld()) return
+ if (!this.isInDungeon()) return
+ if (Player.getContainer().getName().startsWith("Catacombs - Floor ")) {
+ this.nameToUUID = {}
+ World.getAllPlayers().forEach(p => {
+ this.nameToUUID[p.getName().toLowerCase()] = p.getUUID().toString()
+ })
+ let playerI = 0
+ for (let i = 0; i < 5; i++) {
+ let name = ChatLib.removeFormatting(Player.getContainer().getStackInSlot(3 + i)?.getName()?.split(" ")?.pop() || "")
+ if (this.nameToUUID[name.toLowerCase()] && this.nameToUUID[name.toLowerCase()] !== Player.getUUID().toString()) {
+ this.idToPlayer[playerI] = this.nameToUUID[name.toLowerCase()]
+ if (name) playerI++
+ }
+ }
+ this.idToPlayer[playerI] = Player.getUUID().toString()
+ playerI++
+ if (playerI !== World.getAllPlayers().filter(p => p.getPing() === 1).length) this.idToPlayer = {}
+ }
+ // console.log("asjbfoasbgp")
+ this.people = []
+ this.puzzlesTab = []
+ TabList.getNames().forEach(nameo => {
+
+
+ // Party (2) | Soopyboo32 (Mage XXXVI) | Ultimate: Ready | Revive Stones: 1 | | zZzJAKE ♲ (DEAD) | Ultimate: 00m 45s | Revive Stones: 0 | | | | | | | | | | | | | Player Stats | Downed: zZzJAKE | Time: 00m 47s | Revive: 01m 40s | | Deaths: (2) | Damage Dealt: 4.7M❤ | Healing Done: 718❤ | Milestone: ☠❸ | | Discoveries: (0) | Secrets Found: 0 | Crypts: 0 | | | | | | | | Dungeon Stats | Dungeon: Catacombs | Opened Rooms: 13 | Completed Rooms: 12 | Secrets Found: 0% | Time: 01m 51s | | Puzzles: (3) | ???: [✦] | ???: [✦] | ???: [✦] | | | | | | | | | | Account Info | Profile: Pomegranate | Pet Sitter: N/A | Bank: 57M/11M | Interest: 04h 19m 10s | | Skills: Combat 60: MAX | Speed: ✦457 | Strength: ❁859 | Crit Chance: ☣62 | Crit Damage: ☠1479 | Attack Speed: ⚔92 | | Event: Election Over! | Starts In: 2h 39m 10s | | Election: 0d 2h 39m 10s | Aatrox: |||||||||| (79%) | Marina: |||||||||| (7%) | Cole: |||||||||| (6%) | Soopyboo32
+ let line = ChatLib.removeFormatting(nameo).trim().replace("♲ ", "") //TODO: Remove bingo symbol
+ if (line.endsWith(")") && line.includes(" (") && line.split(" (").length === 2 && line.split(" (")[0].split(" ").length === 1 && line.split(" (")[1].length > 5) {
+ this.people.push(line.split(" ")[0])
+ }
+
+ name = ChatLib.removeFormatting(nameo).trim().split(" ")
+ let end = name.pop()
+ // console.log(end) Water Board: [✔]
+ if (end !== "[✦]" && end !== "[✔]") return
+ name = name.join(" ").trim().replace(":", "")
+ if (name.length > 1 && !name.includes("?")) {
+ this.puzzlesTab.push([name, end === "[✔]"])
+ }
+ // console.log(name)
+ })
+ let puzzlesTab2 = this.puzzlesTab.map(a => a)
+ // console.log(this.puzzlesTab.length)
+ // Object.keys(this.puzzles).forEach(key=>{
+ // let y = (key%128)
+ // let x = (Math.floor(key/128))
+
+ // if(x>100&&y>100){
+ // this.puzzles[key] = puzzlesTab2.shift()
+ // }
+ // })
+ Object.keys(this.puzzles).forEach(key => {
+ // let y = (key%128)
+ // let x = (Math.floor(key/128))
+
+ // if(x>100&&y>100){
+ // return
+ // }
+ this.puzzles[key] = puzzlesTab2.shift()
+ // console.log(key, this.puzzles[key], this.puzzlesTab.length)
+ })
+ }
+
+ updateMapImage() {
+ if (!this.mortLocation) {
+ try {
+ World.getAllEntities().forEach(entity => {
+ if (ChatLib.removeFormatting(entity.getName()) === ("Mort")) {
+ this.mortLocation = [
+ entity.getX(),
+ entity.getZ()
+ ]
+ }
+ })
+ } catch (e) { }
+ }
+
+ // let graphics = this.renderImage.getGraphics()
+
+ // graphics.setComposite(AlphaComposite.Clear);
+ // graphics.fillRect(0, 0, this.IMAGE_SIZE, this.IMAGE_SIZE)
+ // graphics.setComposite(AlphaComposite.SrcOver);
+
+ let mapData
+ try {
+ let item = Player.getInventory().getStackInSlot(8)
+ mapData = item.getItem()[m.getMapData](item.getItemStack(), World.getWorld()); // ItemStack.getItem().getMapData()
+ } catch (error) {
+ }
+ if (mapData && !this.boringMap) {
+ this.mapData = mapData
+
+
+ // console.log("has map data poggies")
+ let bytes = mapData[f.colors.MapData]
+
+ // let newArr = java.lang.reflect.Array.newInstance(java.lang.Integer.TYPE, bytes.length)
+ // for (let i = 0; i < bytes.length; i++) {
+ // // console.log(bytes[i]/4)
+
+ // if (bytes[i] !== 0) {
+ // let j = bytes[i] & 255
+ // newArr[i] = net.minecraft.block.material.MapColor[f.mapColorArray][j >> 2][m.getMapColor.MapColor](j & 3)
+ // // graphics.setColor(color)
+ // // graphics.fillRect(x * this.MAP_QUALITY_SCALE, y * this.MAP_QUALITY_SCALE, this.MAP_QUALITY_SCALE, this.MAP_QUALITY_SCALE)
+ // }
+ // // x++
+ // // if (x >= 128) {
+ // // x = 0
+ // // y++
+
+ // // if (y > 128) break
+ // // }
+
+ // // mapImage.getRGB()
+ // }
+ // this.renderImage.setRGB(0, 0, 128, 128, newArr, 0, 128)
+
+ // newImage.setRGB(0,0,128,128, ints, 0, 1)
+
+ // graphics. ()
+ //room size is 18
+ //4 inbetween
+
+ //finding room offsets
+ let brBoxTemp = undefined
+ let roomOffsets
+ let roomWidth1 = 0
+ let roomWidth2 = 0
+ let rx = 0
+ let ry = 0
+ for (let x = 0; x < 128; x += 5) {
+ for (let y = 0; y < 128; y += 5) {
+ if (bytes[x + y * 128] === 30
+ && bytes[x + 1 + y * 128] === 30
+ && bytes[x + 2 + y * 128] === 30
+ && bytes[x + 3 + y * 128] === 30
+ && bytes[x + 5 + y * 128] === 30
+ && bytes[x + 10 + y * 128] === 30) {
+ rx = x
+ ry = y
+ while (bytes[(rx - 1) + ry * 128] === 30) {
+ rx--
+ }
+ while (bytes[(rx) + (ry - 1) * 128] === 30) {
+ ry--
+ }
+ break;
+ }
+ }
+ if (rx) break;
+ }
+ let x = rx
+ while (bytes[x + ry * 128] === 30) {
+ x++
+ roomWidth2++
+ }
+ let y = ry
+ while (bytes[rx + y * 128] === 30) {
+ y++
+ roomWidth1++
+ }
+
+ let roomWidth = Math.floor(Math.max(roomWidth1, roomWidth2) * 5 / 4)
+
+ this.mapScale = 32 / roomWidth
+ let mortLocationOnMap
+ roomOffsets = [rx % roomWidth - 3, ry % roomWidth - 3]
+
+ let dir = roomWidth / 2 - 5 / this.mapScale
+
+ //top
+ for (let i = 0; i < roomWidth; i++) {
+ if (bytes[(i + rx - 3) + (ry - 3) * 128] !== 0) {
+ mortLocationOnMap = [rx - 2 + roomWidth / 2, ry - 2 + roomWidth / 2 - dir]
+ break
+ }
+ }
+ // if(mortLocationOnMap) break
+ //bottom
+ for (let i = 0; i < roomWidth; i++) {
+ if (bytes[(i + rx - 3) + (ry + roomWidth - 3) * 128] !== 0) {
+ mortLocationOnMap = [rx - 2 + roomWidth / 2, ry - 2 + roomWidth / 2 + dir]
+ break
+ }
+ }
+ //left
+ for (let i = 0; i < roomWidth; i++) {
+ if (bytes[(rx - 3) + (i + ry - 3) * 128] !== 0) {
+ mortLocationOnMap = [rx - 2 + roomWidth / 2 - dir, ry - 2 + roomWidth / 2]
+ break
+ }
+ }
+ //right
+ for (let i = 0; i < roomWidth; i++) {
+ if (bytes[(rx + roomWidth - 3) + (i + ry - 3) * 128] !== 0) {
+ mortLocationOnMap = [rx - 2 + roomWidth / 2 + dir, ry - 2 + roomWidth / 2]
+ }
+ }
+
+ if (mortLocationOnMap && this.mortLocation) {
+
+ for (let x = roomOffsets[0]; x < 128; x += roomWidth) {
+ for (let y = roomOffsets[1]; y < 128; y += roomWidth) {
+ let testLocs = [[x, y + roomWidth / 2, false], [x + roomWidth / 2, y, true]]
+ testLocs.forEach(([ux, uy, isX]) => {
+
+ // console.log(bytes[~~ux+~~uy*128])
+ if (bytes[~~ux + ~~uy * 128] === 119 || bytes[~~ux + ~~uy * 128] === 18) {
+
+ brBoxTemp = [
+ (ux - mortLocationOnMap[0]) / roomWidth * 32 + this.mortLocation[0],
+ (uy - mortLocationOnMap[1]) / roomWidth * 32 + this.mortLocation[1]
+ ]
+
+ if (isX) {
+ brBoxTemp[0] = Math.floor(brBoxTemp[0] / 32 + 0.5) * 32 + 16
+ brBoxTemp[1] = Math.floor(brBoxTemp[1] / 32 + 0.5) * 32
+ } else {
+ brBoxTemp[0] = Math.floor(brBoxTemp[0] / 32 + 0.5) * 32
+ brBoxTemp[1] = Math.floor(brBoxTemp[1] / 32 + 0.5) * 32 + 16
+ }
+
+ brBoxTemp = [
+ (~~brBoxTemp[0]) - 8.5,
+ (~~brBoxTemp[1]) - 8.5
+ ]
+ }
+ })
+
+ let [tx, ty] = [~~(x + roomWidth / 2), ~~(y + roomWidth / 2)]
+
+ if (bytes[tx + ty * 128] === 66) {
+
+ if (!this.puzzles[(tx) * 128 + ty] && Object.keys(this.puzzles).length < 10) {
+ this.puzzles[(tx) * 128 + ty] = ["Loading", false]
+ }
+ }
+ }
+ }
+ }
+
+ this.brBoxLoc = brBoxTemp
+
+
+ if (this.brBox.getValue() && !this.bloodOpened) this.dungeonBrBoxElm.startRender()
+
+ if (this.brBoxLoc) this.dungeonBrBoxElm.setLocationSize([this.brBoxLoc[0] - 1.5, 69, this.brBoxLoc[1] - 1.5], [3, 4, 3])
+
+ if (roomOffsets) {
+ // for(let x = 0;x<128;x++){
+ // for(let y = 0;y<128;y++){
+ // if((x-roomOffsets[0])%roomWidth===0 || (y-roomOffsets[1])%roomWidth===0){
+ // this.renderImage.setRGB(x*this.MAP_QUALITY_SCALE, y*this.MAP_QUALITY_SCALE, Renderer.color(0,0,0))
+ // }
+ // }
+ // }
+
+ // for(let x = roomOffsets[0];x<128;x+=roomWidth){
+ // for(let y = roomOffsets[1];y<128;y+=roomWidth){
+ // let testLocs = [[x, y+roomWidth/2],[x+roomWidth/2, y]]
+ // testLocs.forEach(([ux, uy])=>{
+ // ux = ~~ux
+ // uy = ~~uy
+
+ // try{
+ // this.renderImage.setRGB(ux*this.MAP_QUALITY_SCALE, uy*this.MAP_QUALITY_SCALE, Renderer.color(255,0,0))
+ // }catch(e){}
+ // })
+ // }
+
+ // }
+
+ if (mortLocationOnMap && this.mortLocation) {
+ this.offset = [mortLocationOnMap[0] - this.mortLocation[0] / this.mapScale, mortLocationOnMap[1] - this.mortLocation[1] / this.mapScale]
+ // this.renderImage.setRGB(mortLocationOnMap[0], mortLocationOnMap[1], Renderer.color(255, 0, 0))
+ // ChatLib.chat(roomWidth + " " + this.offset.join(", "))
+ }
+ }
+
+ // console.log(bytes[Math.floor(Player.getX()/this.mapScale+this.offset[0])+Math.floor(Player.getZ()/this.mapScale + this.offset[1])*128])
+ this.roomWidth = roomWidth
+
+ this.mortLocationOnMap = mortLocationOnMap
+
+ if (this.mortLocation && mortLocationOnMap && roomWidth) {
+ let deco = mapData[f.mapDecorations]
+ this.extraDeco = []
+ try {
+ let i = 0
+ deco.forEach((icon, vec4b) => {
+ let x = vec4b.func_176112_b()
+ let y = vec4b.func_176113_c()
+ let rot = vec4b.func_176111_d()
+ x = x / 2 + 64
+ y = y / 2 + 64
+ rot = rot * 360 / 16 + 180
+
+
+ x = (x - mortLocationOnMap[0]) / roomWidth * 32 + this.mortLocation[0]
+ y = (y - mortLocationOnMap[1]) / roomWidth * 32 + this.mortLocation[1]
+
+
+ //wtf is this
+
+ //vec4b.func_176110_a()
+
+
+ let closestP = undefined
+ let closestDistance = Infinity
+ Object.keys(this.mapDataPlayers).forEach((uuid) => {
+ if ((x - this.mapDataPlayers[uuid].x) ** 2 + (y - this.mapDataPlayers[uuid].y) ** 2 < closestDistance) {
+ closestDistance = (x - this.mapDataPlayers[uuid].x) ** 2 + (y - this.mapDataPlayers[uuid].y) ** 2
+ closestP = uuid
+ }
+ })
+ while (this.idToPlayer[i] && this.deadPlayers.has(this.idToPlayer[i])) i++
+ if (this.idToPlayer[i]) closestP = this.idToPlayer[i]
+ if (closestP && closestP !== Player.getUUID().toString()) {
+ // console.log(closestP, x, y)
+ this.mapDataPlayers[closestP].x = x
+ this.mapDataPlayers[closestP].y = y
+ this.mapDataPlayers[closestP].rot = rot
+ }
+ i++
+ });
+ } catch (e) { }
+ }
+
+
+ if (this.offset && this.offset.length === 2) {
+ this.roomDataStuffRender.clear()
+ for (let ent of this.roomDataStuff.entries()) {
+ let [loc] = ent
+ let [x, y] = loc.split(",")
+
+ let renderX = Math.round((parseInt(x) + 16) / this.mapScale + this.offset[0]) // / 128 * size
+ let renderY = Math.round((parseInt(y) + 16) / this.mapScale + this.offset[1])// / 128 * size
+ // console.log(renderX, renderY)
+ let isGreen = false
+ let color = "&8"
+ for (let i = 0; i < 10; i++) {
+ if (bytes[renderX + i + (renderY + i) * 128] === 30
+ || bytes[renderX + i + 1 + (renderY + i) * 128] === 30) {
+ isGreen = true
+ color = "&a"
+ }
+ if (bytes[renderX + i + (renderY + i) * 128] === 34
+ || bytes[renderX + i + 1 + (renderY + i) * 128] === 34) {
+ color = "&f"
+ }
+ }
+ if (isGreen) {
+ let total = ent[1][0].split(" ")[1]
+ let data = this.roomDataStuff.get(loc)
+ data[0] = total + " " + total
+ this.roomDataStuff.set(loc, data)
+ }
+
+ let setData = [...this.roomDataStuff.get(loc)]
+ setData.push(color)
+ this.roomDataStuffRender.set(loc, setData)
+ }
+ }
+ // if (!this.renderImage) return
+
+ // let newMapImageThing = new Image(this.renderImage)
+ this.currDungeonBossImage = undefined
+ } else {
+ //no map data, check to see if should render boss image
+
+ if (this.dungeonBossImages[this.FeatureManager.features["dataLoader"].class.dungeonFloor]) this.dungeonBossImages[this.FeatureManager.features["dataLoader"].class.dungeonFloor].forEach(data => {
+ if (data.bounds[0][0] <= Player.getX() && data.bounds[0][1] <= Player.getY() && data.bounds[0][2] <= Player.getZ() && data.bounds[1][0] >= Player.getX() && data.bounds[1][1] >= Player.getY() && data.bounds[1][2] >= Player.getZ()) {
+ this.currDungeonBossImage = data
+ }
+ })
+ }
+
+
+ // this.mapImage.setImage(this.renderImage)
+ }
+
+ step5s() {
+ if (!this.FeatureManager.features["dataLoader"].class.isInDungeon) return
+ if (this.people.length < 1) return
+
+ let data = []
+
+ World.getAllPlayers().forEach(player => {
+ if (player.getPing() === -1) return
+ if (!this.people.includes(player.getName())) return
+ data.push({
+ x: player.getX(),
+ y: player.getZ(),
+ rot: player.getYaw() + 180,
+ username: player.getName(),
+ uuid: player.getUUID().toString()
+ })
+ this.nameToUUID[player.getName().toLowerCase()] = player.getUUID().toString()
+ })
+ // console.log("Sending: " + JSON.stringify(this.people, undefined, 2)+JSON.stringify(data, undefined, 2))
+ socketConnection.sendDungeonData(this.people, data)
+ }
+ updateDungeonMapData(data) {
+ // console.log("Recieved: " + JSON.stringify(data, undefined, 2))
+ data.forEach(p => {
+ this.mapDataPlayers[p.uuid] = p
+ })
+ }
+
+ getImageForPlayer(uuid) {
+ let img = renderLibs.getImage("https://crafatar.com/avatars/" + uuid.replace(/-/g, "") + "?size=8&overlay")
+ if (!img) return this.defaultPlayerImage
+
+ return img
+ }
+
+ initVariables() {
+ this.mapImage = undefined
+ this.defaultPlayerImage = undefined
+ this.mortLocation = undefined
+ this.offset = undefined
+ this.puzzles = undefined
+ this.puzzlesTab = undefined
+ this.mapScale = undefined
+ this.newPuzzlesTab = undefined
+ this.renderImage = undefined
+ }
+
+ onDisable() {
+ this.dungeonBrBoxElm.stopRender()
+ this.initVariables()
+ this.running = false
+ this.roomDataStuff.clear()
+ }
+}
+
+module.exports = {
+ class: new DungeonMap()
+}
+
+const ContainerChest = Java.type("net.minecraft.inventory.ContainerChest")
+class SpiritLeapOverlay {
+ constructor(parent) {
+ this.parent = parent
+
+ this.soopyGui = new SoopyGui()
+
+ let renderThing = new soopyGuiMapRendererThing(this).setLocation(0, 0, 1, 1)
+ this.soopyGui.element.addChild(renderThing)
+
+ this.soopyGui.element.addEvent(new SoopyKeyPressEvent().setHandler((key, keyId) => {
+ if (keyId === 18) {
+ this.soopyGui.close()
+ }
+ }))
+
+ this.buttonsContainer = new SoopyGuiElement().setLocation(0.2, 0.2, 0.6, 0.3)
+ this.soopyGui.element.addChild(this.buttonsContainer)
+
+ this.items = {}
+
+ this.players = {}
+ }
+
+ guiOpened(event) {
+ if (event.gui && event.gui.field_147002_h instanceof ContainerChest) {
+ name = event.gui.field_147002_h.func_85151_d().func_145748_c_().func_150260_c()
+ if (name === "Spirit Leap") {
+ this.soopyGui.open()
+ }
+ }
+ }
+
+ tick() {
+ let itemsNew = {}
+
+ if (Player.getContainer()?.getName() === "Spirit Leap") {
+
+ this.players = {}
+ Scoreboard.getLines().forEach(line => {
+ let name = ChatLib.removeFormatting(line.getName()).replace(/[^A-z0-9 \:\(\)\.\[\]]/g, "")
+ if (name.startsWith("[M] ")) this.players[name.split(" ")[1]] = "M"
+ if (name.startsWith("[A] ")) this.players[name.split(" ")[1]] = "A"
+ if (name.startsWith("[B] ")) this.players[name.split(" ")[1]] = "B"
+ if (name.startsWith("[H] ")) this.players[name.split(" ")[1]] = "H"
+ if (name.startsWith("[T] ")) this.players[name.split(" ")[1]] = "T"
+ })
+
+ for (let i = 1; i < 9 * 3; i++) {
+ let item = Player.getContainer().getStackInSlot(i)
+ if (item && item.getID() !== 160) {
+ itemsNew[item.getName()] = i
+ }
+ }
+
+ if (JSON.stringify(this.items) !== JSON.stringify(itemsNew)) {
+ this.items = itemsNew
+ this.buttonsContainer.clearChildren()
+
+ getClass = (name) => {
+ let pClass = (this.players[name] || "?")
+ if (pClass === "?") {
+ Object.keys(this.players).forEach(n => {
+ if (name.startsWith(n)) {
+ pClass = this.players[n]
+ }
+ })
+ }
+ return pClass
+ }
+
+ Object.keys(this.items).sort((a, b) => {
+ return getClass(ChatLib.removeFormatting(a)).codePointAt(0) - getClass(ChatLib.removeFormatting(b)).codePointAt(0)
+ }).forEach((name, i) => {
+
+ let name2 = ChatLib.removeFormatting(name)
+ let pClass = getClass(name2)
+
+ let button = new ButtonWithArrow().setText((name2 === this.parent.lastDoorOpener ? "&4" : "&2") + "[" + pClass + "] " + name2).addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ Player.getContainer().click(itemsNew[name])
+ ChatLib.chat("Leaping to " + name)
+ })).setLocation((i % 2) * 0.5, Math.floor(i / 2) * 0.5, 0.5, 0.5)
+ button.text.setLocation(0.5, 0, 0.4, 1)
+ button.addEvent(new SoopyRenderEvent().setHandler(() => {
+ if (!this.parent.nameToUUID[name2.toLowerCase()]) return
+ let img = this.parent.getImageForPlayer(this.parent.nameToUUID[name2.toLowerCase()])
+
+ if (!img) return
+
+ let x = button.location.getXExact()
+ let y = button.location.getYExact()
+ let h = button.location.getHeightExact()
+
+ img.draw(x + h / 5, y + h / 10, 8 * h / 10, 8 * h / 10)
+
+ }))
+ this.buttonsContainer.addChild(button)
+ })
+ }
+ }
+ }
+}
+
+class soopyGuiMapRendererThing extends SoopyGuiElement {
+ constructor(parent) {
+ super()
+
+ this.parentE = parent
+
+ this.addEvent(new SoopyRenderEvent().setHandler((mouseX, mouseY) => {
+ let size2 = Math.min(Renderer.screen.getWidth() / 2, Renderer.screen.getHeight() / 2)
+
+ let [x, y, size, scale] = [Renderer.screen.getWidth() / 2 - size2 / 2, 2 * Renderer.screen.getHeight() / 3 - size2 / 3, size2, size2 / this.parentE.parent.IMAGE_SIZE]
+
+ this.parentE.parent.drawMap(x, y, size, scale)
+
+ let closestPlayer
+ if (mouseY > y) {
+ closestPlayer = this.getClosestPlayerTo(x, y, size, scale, mouseX, mouseY)
+
+ if (closestPlayer) {
+ let renderX = closestPlayer.x / this.parentE.parent.mapScale / 128 * size//*16/this.roomWidth
+ let renderY = closestPlayer.y / this.parentE.parent.mapScale / 128 * size//*16/this.roomWidth
+
+ Renderer.translate(renderX + x + this.parentE.parent.offset[0] / 128 * size, renderY + y + this.parentE.parent.offset[1] / 128 * size, 1000)
+ Renderer.scale(scale * 3, scale * 3)
+ Renderer.rotate(closestPlayer.rot)
+ this.parentE.parent.getImageForPlayer(closestPlayer.uuid).draw(-5, -5, 10, 10)
+ }
+ }
+ Object.keys(this.parentE.parent.mapDataPlayers).forEach(uuid => {
+ let player = this.parentE.parent.mapDataPlayers[uuid]
+
+ let renderX = player.x / this.parentE.parent.mapScale / 128 * size//*16/this.roomWidth
+ let renderY = player.y / this.parentE.parent.mapScale / 128 * size//*16/this.roomWidth
+
+ Renderer.translate(renderX + x + this.parentE.parent.offset[0] / 128 * size, renderY + y + this.parentE.parent.offset[1] / 128 * size, 1000)
+ renderLibs.drawStringCenteredShadow((player.uuid === closestPlayer?.uuid ? "&c" : "&a") + "[" + (this.parentE.players[player.username] || "?") + "] " + player.username, 0, -7 * scale * 3, 2)
+ /*
+ {
+ x: player.getX(),
+ y: player.getZ(),
+ rot: player.getYaw()+180,
+ username: player.getName(),
+ uuid: player.getUUID().toString()
+ }
+ */
+ })
+
+ if (closestPlayer) {
+ let renderX = closestPlayer.x / this.parentE.parent.mapScale / 128 * size//*16/this.roomWidth
+ let renderY = closestPlayer.y / this.parentE.parent.mapScale / 128 * size//*16/this.roomWidth
+
+ Renderer.translate(renderX + x + this.parentE.parent.offset[0] / 128 * size, renderY + y + this.parentE.parent.offset[1] / 128 * size)
+ renderLibs.drawStringCenteredShadow("&c" + "[" + (this.parentE.players[closestPlayer.username] || "?") + "] " + closestPlayer.username, 0, -7 * scale * 3, 2)
+ }
+ }))
+ this.addEvent(new SoopyMouseClickEvent().setHandler((mouseX, mouseY) => {
+ let size2 = Math.min(Renderer.screen.getWidth() / 2, Renderer.screen.getHeight() / 2)
+
+ let [x, y, size, scale] = [Renderer.screen.getWidth() / 2 - size2 / 2, 2 * Renderer.screen.getHeight() / 3 - size2 / 3, size2, size2 / this.parentE.parent.IMAGE_SIZE]
+
+ if (mouseY < y) return
+
+ let closestPlayer = this.getClosestPlayerTo(x, y, size, scale, mouseX, mouseY)
+
+ if (closestPlayer) {
+ if (Player.getContainer()?.getName() === "Spirit Leap") {
+ for (let i = 1; i < 9 * 3; i++) {
+ let item = Player.getContainer().getStackInSlot(i)
+ if (item && item.getID() !== 160) {
+ if (ChatLib.removeFormatting(item.getName()) === closestPlayer.username) {
+ Player.getContainer().click(i)
+ ChatLib.chat("Leaping to " + closestPlayer.username)
+ }
+ }
+ }
+ }
+ }
+ }))
+ }
+
+ getClosestPlayerTo(x, y, size, scale, scanX, scanY) {
+
+ let closest = null
+ let closestD = Infinity
+ Object.keys(this.parentE.parent.mapDataPlayers).forEach((uuid) => {
+
+ if (uuid === Player.getUUID()) return
+
+ let renderX = this.parentE.parent.mapDataPlayers[uuid].x / this.parentE.parent.mapScale / 128 * size//*16/this.roomWidth
+ let renderY = this.parentE.parent.mapDataPlayers[uuid].y / this.parentE.parent.mapScale / 128 * size//*16/this.roomWidth
+
+ let distance = (renderX + x + this.parentE.parent.offset[0] / 128 * size - scanX) ** 2 + (renderY + y + this.parentE.parent.offset[1] / 128 * size - scanY) ** 2
+
+ if (distance < closestD) {
+ closestD = distance
+ closest = this.parentE.parent.mapDataPlayers[uuid]
+ }
+ })
+
+ return closest
+ }
+}
\ No newline at end of file
diff --git a/src/features/dungeonMap/map.png b/src/features/dungeonMap/map.png
new file mode 100644
index 0000000..ff16aca
Binary files /dev/null and b/src/features/dungeonMap/map.png differ
diff --git a/src/features/dungeonMap/metadata.json b/src/features/dungeonMap/metadata.json
new file mode 100644
index 0000000..beef50e
--- /dev/null
+++ b/src/features/dungeonMap/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Dungeon Map",
+ "description": "Cool dungeon map and related features",
+ "isHidden": false,
+ "isTogglable": true,
+ "defaultEnabled": false,
+ "sortA": 1
+}
\ No newline at end of file
diff --git a/src/features/dungeonMap2/DungeonMapData.js b/src/features/dungeonMap2/DungeonMapData.js
new file mode 100644
index 0000000..1b50c67
--- /dev/null
+++ b/src/features/dungeonMap2/DungeonMapData.js
@@ -0,0 +1,513 @@
+import { f, m } from "../../../mappings/mappings"
+import DungeonMapRoom from "./DungeonMapRoom"
+import DungeonRoomStaticData from "./DungeonRoomStaticData"
+
+const Color = Java.type("java.awt.Color")
+const BufferedImage = Java.type("java.awt.image.BufferedImage")
+
+let DEFAULT_DOOR_COLOR = new Color(Renderer.color(114, 67, 27, 255))
+let PUZZLE_DOOR_COLOR = new Color(Renderer.color(178, 76, 216, 255))
+let MINIBOSS_DOOR_COLOR = new Color(Renderer.color(229, 229, 51, 255))
+let BLOOD_DOOR_COLOR = new Color(Renderer.color(255, 0, 0, 255))
+let TRAP_DOOR_COLOR = new Color(Renderer.color(216, 127, 51, 255))
+let WITHER_DOOR_COLOR = new Color(Renderer.color(0, 0, 0, 255))
+
+let mapDataScale = {
+ "E": 22,
+ "1": 22,
+ "2": 22,
+ "3": 22,
+ "4": 20,
+ "5": 20,
+ "6": 20,
+ "7": 20
+}
+
+// let TabOverlayListField = Java.type("net.minecraft.client.gui.GuiPlayerTabOverlay").class.getDeclaredField("field_175252_a")
+// TabOverlayListField.setAccessible(true)
+// let TabOverlayList = TabOverlayListField.get(null)
+let PlayerComparator = Java.type("net.minecraft.client.gui.GuiPlayerTabOverlay").PlayerComparator
+let c = PlayerComparator.class.getDeclaredConstructor()
+c.setAccessible(true);
+let sorter = c.newInstance()
+let nethandlerplayclient = Player.getPlayer()[f.sendQueue.EntityPlayerSP]
+
+class DungeonMapData {
+ constructor(floor) {
+ this.floor = floor
+
+ this.roomScaleMap = mapDataScale[floor[floor.length - 1]] //how many pixels on the map is 32 blocks
+ this.roomOffsetMap = [0, 0] //How offset is the map
+
+ /**
+ * @type {Map}
+ */
+ this.rooms = new Map()
+ /**
+ * @type {Map}
+ */
+ this.doors = new Map()
+
+ this.greenRoomCoords = undefined
+
+ this.image = undefined
+ this.oldImage = undefined
+
+ this.renderTicks = false
+
+ this.players = []
+ this.playersNameToId = {}
+ }
+
+ updatePlayers() {
+ let pl = nethandlerplayclient[m.getPlayerInfoMap]().sort((a, b) => sorter.compare(a, b))
+ let i = 0
+ for (let p of pl) {
+ if (!p[m.getDisplayName.NetworkPlayerInfo]()) continue
+ let line = p[m.getDisplayName.NetworkPlayerInfo]()[m.getUnformattedText]().trim().replace("♲ ", "") //TODO: Remove bingo symbol
+ if (line.endsWith(")") && line.includes(" (") && line.split(" (").length === 2 && line.split(" (")[0].split(" ").length === 1 && line.split(" (")[1].length > 5) {
+ let name = line.split(" ")[0]
+
+ if (!this.players[i]) {
+ this.players[i] = {
+ name: "",
+ x: 0,
+ y: 0,
+ rotate: 0,
+ skin: undefined
+ }
+ }
+ this.players[i].name = name
+ this.players[i].skin = p[m.getLocationSkin.NetworkPlayerInfo]()
+ this.playersNameToId[name] = i
+
+ i++
+ }
+ }
+ }
+
+ updatePlayersFast() {
+ World.getAllPlayers().forEach(player => {
+ let p = this.players[this.playersNameToId[ChatLib.removeFormatting(player.getName()).trim()]]
+ if (!p) return
+
+ p.x = player.getX()
+ p.y = player.getZ()
+ p.rotate = player.getYaw() + 180
+ })
+ }
+
+ loadPlayersFromDecoration(deco) {
+
+ let i = 0
+ deco.forEach((icon, vec4b) => {
+
+ if (!this.players[i]) return
+
+ let x = vec4b.func_176112_b()
+ let y = vec4b.func_176113_c()
+ let rot = vec4b.func_176111_d()
+ x = x / 2 + this.roomScaleMap
+ y = y / 2 + this.roomScaleMap
+ rot = rot * 360 / 16 + 180
+
+ this.players[i].rotate = rot
+ this.players[i].x = (x) / this.roomScaleMap * 32 - this.roomOffsetMap[0]
+ this.players[i].y = (y) / this.roomScaleMap * 32 - this.roomOffsetMap[1]
+
+ i++
+ });
+ }
+
+ updateHotbarData() {
+ let mapData
+ try {
+ let item = Player.getInventory().getStackInSlot(8)
+ mapData = item.getItem()[m.getMapData](item.getItemStack(), World.getWorld()); // ItemStack.getItem().getMapData()
+ } catch (error) {
+ }
+ if (mapData) {
+ this.loadPlayersFromDecoration(mapData[f.mapDecorations])
+
+ let bytes = mapData[f.colors.MapData]
+ if (!this.greenRoomCoords) return
+ //30 = green
+ //0 = transparent
+ //66 = puzzle
+ //34 = white
+
+ let rx = 0
+ let ry = 0
+ for (let x = 0; x < 128; x += 5) {
+ for (let y = 0; y < 128; y += 5) {
+ if (bytes[x + y * 128] === 30
+ && bytes[x + 1 + y * 128] === 30
+ && bytes[x + 2 + y * 128] === 30
+ && bytes[x + 3 + y * 128] === 30) {
+ rx = x
+ ry = y
+ while (bytes[(rx - 1) + ry * 128] === 30) {
+ rx--
+ }
+ while (bytes[(rx) + (ry - 1) * 128] === 30) {
+ ry--
+ }
+ break;
+ }
+ }
+ if (rx) break;
+ }
+ rx += (this.roomScaleMap / 4 * 5) / 2 - this.roomScaleMap
+ ry += (this.roomScaleMap / 4 * 5) / 2 - this.roomScaleMap
+ this.roomOffsetMap[0] = -((this.greenRoomCoords[0]) / 32 * this.roomScaleMap + 2 * this.roomScaleMap - rx) / this.roomScaleMap * 32
+ this.roomOffsetMap[1] = -((this.greenRoomCoords[1]) / 32 * this.roomScaleMap + 2 * this.roomScaleMap - ry) / this.roomScaleMap * 32
+
+ console.log(this.roomOffsetMap.join(","))
+
+
+ let toMap = (x2, y2) => {
+ return Math.round(((x2 + this.roomOffsetMap[0]) / 32 * this.roomScaleMap + 2 * this.roomScaleMap)) + Math.round(((y2 + this.roomOffsetMap[1]) / 32 * this.roomScaleMap + 2 * this.roomScaleMap)) * 128
+ }
+
+ console.log(bytes[toMap(Player.getX(), Player.getZ())])
+
+ let loadRoomAt = (x, y) => {
+ x = Math.floor((x + 8) / 32) * 32 - 8
+ y = Math.floor((y + 8) / 32) * 32 - 8
+
+ if (bytes[toMap(x + 16, y + 16)] === 30) {
+ this.setRoomFull(x, y, 0, DungeonMapRoom.TYPE_SPAWN, DungeonMapRoom.SHAPE_1X1, 0)
+ }
+ if (bytes[toMap(x + 16, y + 16)] === 66) {
+ this.setRoomFull(x, y, 0, DungeonMapRoom.TYPE_PUZZLE, DungeonMapRoom.SHAPE_1X1, 0)
+ }
+ if (bytes[toMap(x + 16, y + 16)] === 82) {
+ this.setRoomFull(x, y, 0, DungeonMapRoom.TYPE_FAIRY, DungeonMapRoom.SHAPE_1X1, 0)
+ }
+ if (bytes[toMap(x + 16, y + 16)] === 18) {
+ this.setRoomFull(x, y, 0, DungeonMapRoom.TYPE_BLOOD, DungeonMapRoom.SHAPE_1X1, 0)
+ }
+ if (bytes[toMap(x + 16, y + 16)] === 64) {
+ this.setRoomFull(x, y, 0, DungeonMapRoom.TYPE_TRAP, DungeonMapRoom.SHAPE_1X1, 0)
+ }
+ if (bytes[toMap(x + 16, y + 16)] === 63) {
+ let width = 32
+ let height = 32
+ while (bytes[toMap(x, y + 5)] === 63) {
+ x -= 32
+ width += 32
+ }
+ while (bytes[toMap(x + 5, y)] === 63) {
+ y -= 32
+ height += 32
+ }
+ while (bytes[toMap(x + width, y + 5)] === 63) {
+ width += 32
+ }
+ while (bytes[toMap(x + 5, y + height)] === 63) {
+ height += 32
+ }
+
+ let shape = DungeonMapRoom.SHAPE_1X1
+ let rotation = 0
+
+ if (width === height) {
+ if (width === 64) {
+ shape = DungeonMapRoom.SHAPE_2X2
+ }
+ }
+ if (width > height) {
+ if (width === 64) {
+ shape = DungeonMapRoom.SHAPE_1X2
+ }
+ if (width === 96) {
+ shape = DungeonMapRoom.SHAPE_1X3
+ }
+ if (width === 128) {
+ shape = DungeonMapRoom.SHAPE_1X4
+ }
+ }
+ if (width < height) {
+ rotation = 1
+ if (height === 64) {
+ shape = DungeonMapRoom.SHAPE_1X2
+ }
+ if (height === 96) {
+ shape = DungeonMapRoom.SHAPE_1X3
+ }
+ if (height === 128) {
+ shape = DungeonMapRoom.SHAPE_1X4
+ }
+ }
+
+ this.setRoomFull(x, y, rotation, DungeonMapRoom.TYPE_NORMAL, shape, 0)
+ }
+ }
+ for (let x = -200; x < 100; x += 32) {
+ for (let y = -200; y < 100; y += 32) {
+ loadRoomAt(x, y)
+ }
+ }
+ }
+ }
+
+ setRenderTicks(val) {
+ if (this.renderTicks !== val) {
+ this.mapChanged()
+ }
+ this.renderTicks = val
+ }
+
+ setDoor(x, y, doorType, rotation) {//doorType 0=normal, 1=wither, 2=blood
+ if (doorType === -1) {
+ let id = World.getBlockStateAt(new BlockPos(x, 69, y)).getBlockId()
+ if (id === 0) doorType = 0
+ else if (id === 97) doorType = 0
+ else if (id === 173) doorType = 1
+ else if (id === 159) doorType = 2
+ else return
+ }
+ if (this.doors.get(x + "," + y)?.join(",") !== doorType + "," + rotation) {
+ this.doors.set(x + "," + y, [doorType, rotation])
+ this.mapChanged()
+ }
+ }
+
+ setRoomFull(x, y, rotation, roomType, shape, checkedState) {
+ let locstr = x + "," + y
+
+ if (shape === DungeonMapRoom.SHAPE_L && rotation === 2) {
+ locstr = x + "," + (y + 32)
+ }
+
+ if (this.rooms.get(locstr) && this.rooms.get(locstr).type !== roomType) {
+ this.rooms.get(locstr).type = roomType
+ this.mapChanged()
+ return
+ }
+ if (this.rooms.get(locstr) && this.rooms.get(locstr).checkedState !== checkedState) {
+ this.rooms.get(locstr).setCheckedState(checkedState)
+ this.mapChanged()
+ return
+ }
+ if (this.rooms.get(locstr) && this.rooms.get(locstr).shape !== shape) {
+ this.rooms.get(locstr).shape = shape
+ this.mapChanged()
+ return
+ }
+ if (this.rooms.get(locstr) && this.rooms.get(locstr).rotation !== rotation) {
+ this.rooms.get(locstr).rotation = rotation
+ this.mapChanged()
+ return
+ }
+ if (this.rooms.get(locstr)) {
+ return
+ }
+
+ let room = new DungeonMapRoom(roomType, shape, rotation, x, y, undefined)
+
+ this.rooms.set(locstr, room)
+
+ this.mapChanged()
+ }
+
+ setRoom(x, y, rotation, id) {
+ let locstr = x + "," + y
+
+ if (DungeonRoomStaticData.getDataFromId(id).shape === 'L' && rotation === 2) {
+ locstr = x + "," + (y + 32)
+ }
+
+ if (this.rooms.get(locstr) && this.rooms.get(locstr).roomId !== id) {
+ this.rooms.get(locstr).setId(id)
+ this.mapChanged()
+ return
+ }
+ if (this.rooms.get(locstr)) {
+ return
+ }
+
+ let room = DungeonMapRoom.fromId(id, x, y, rotation)
+
+ if (room.type === DungeonMapRoom.TYPE_SPAWN) {
+ this.greenRoomCoords = [x, y]
+ }
+
+ this.rooms.set(locstr, room)
+
+ this.mapChanged()
+ }
+
+ getPlayers() {
+ return this.players
+ }
+
+ roomSecrets(x, y, rotation, id, curr, max) {
+ let locstr = x + "," + y
+
+ if (DungeonRoomStaticData.getDataFromId(id).shape === 'L' && rotation === 2) {
+ locstr = x + "," + (y - 32)
+ }
+
+ if (this.rooms.get(locstr)) {
+ this.rooms.get(locstr).setSecrets(curr, max)
+ }
+ }
+
+ destroy() {
+ this.oldImage.getTexture()[m.deleteGlTexture]()
+ this.image.getTexture()[m.deleteGlTexture]()
+ this.oldImage = undefined
+ this.image = undefined
+ }
+
+ mapChanged() {
+ if (this.image) {
+ if (this.oldImage) this.oldImage.getTexture()[m.deleteGlTexture]()
+ this.oldImage = this.image
+ this.image = undefined
+ }
+ }
+
+ /**
+ * @returns {Image}
+ */
+ getImage() {
+ if (!this.image) {
+ this.image = new Image(this.render())
+ this.image.draw(0, 0, 0, 0)
+ if (this.oldImage) return this.oldImage
+ }
+
+ return this.image
+ }
+
+ renderSecrets(size) {
+ for (let data of this.rooms.entries()) {
+ let room = data[1]
+
+ if (room.maxSecrets === 0) continue
+
+ let text = room.getSecrets()
+ let text2 = "&0" + ChatLib.removeFormatting(text)
+ let width = Renderer.getStringWidth(text) - 6
+
+ let location = room.getIconLocation()
+
+ Renderer.drawString(text2, this.toImageX(location[0]) * size - width / 2 - 1, this.toImageY(location[1]) * size)
+ Renderer.drawString(text2, this.toImageX(location[0]) * size - width / 2 + 1, this.toImageY(location[1]) * size)
+ Renderer.drawString(text2, this.toImageX(location[0]) * size - width / 2, this.toImageY(location[1]) * size - 1)
+ Renderer.drawString(text2, this.toImageX(location[0]) * size - width / 2, this.toImageY(location[1]) * size + 1)
+ Renderer.drawString(text, this.toImageX(location[0]) * size - width / 2, this.toImageY(location[1]) * size)
+ }
+ }
+
+ /**
+ * @returns {BufferedImage}
+ */
+ render() {
+ //create 256x256 image
+ let image = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB)
+
+ //create graphics rendering context
+ let graphics = image.createGraphics()
+
+ graphics.translate(256 - 32, 256 - 32)
+
+ //render doors
+ for (let data of this.doors.entries()) {
+ let [location, [type, rotation]] = data
+ location = location.split(",")
+ let x = parseInt(location[0])
+ let y = parseInt(location[1])
+
+ let doorColor = type === 0 ? DEFAULT_DOOR_COLOR : (type === 1 ? WITHER_DOOR_COLOR : BLOOD_DOOR_COLOR)
+
+ if (rotation === 0) {
+ if (this.rooms.get((x - 15) + "," + (y + 1))?.type === DungeonMapRoom.TYPE_BLOOD) {
+ doorColor = BLOOD_DOOR_COLOR
+ }
+ if (this.rooms.get((x - 15) + "," + (y + 1))?.type === DungeonMapRoom.TYPE_PUZZLE) {
+ doorColor = PUZZLE_DOOR_COLOR
+ }
+ if (this.rooms.get((x - 15) + "," + (y + 1))?.type === DungeonMapRoom.TYPE_TRAP) {
+ doorColor = TRAP_DOOR_COLOR
+ }
+ if (this.rooms.get((x - 15) + "," + (y + 1))?.type === DungeonMapRoom.TYPE_MINIBOSS) {
+ doorColor = MINIBOSS_DOOR_COLOR
+ }
+ if (this.rooms.get((x - 15) + "," + (y - 31))?.type === DungeonMapRoom.TYPE_BLOOD) {
+ doorColor = BLOOD_DOOR_COLOR
+ }
+ if (this.rooms.get((x - 15) + "," + (y - 31))?.type === DungeonMapRoom.TYPE_PUZZLE) {
+ doorColor = PUZZLE_DOOR_COLOR
+ }
+ if (this.rooms.get((x - 15) + "," + (y - 31))?.type === DungeonMapRoom.TYPE_TRAP) {
+ doorColor = TRAP_DOOR_COLOR
+ }
+ if (this.rooms.get((x - 15) + "," + (y - 31))?.type === DungeonMapRoom.TYPE_MINIBOSS) {
+ doorColor = MINIBOSS_DOOR_COLOR
+ }
+ }
+ if (rotation === 1) {
+ if (this.rooms.get((x - 31) + "," + (y - 15))?.type === DungeonMapRoom.TYPE_BLOOD) {
+ doorColor = BLOOD_DOOR_COLOR
+ }
+ if (this.rooms.get((x - 31) + "," + (y - 15))?.type === DungeonMapRoom.TYPE_PUZZLE) {
+ doorColor = PUZZLE_DOOR_COLOR
+ }
+ if (this.rooms.get((x - 31) + "," + (y - 15))?.type === DungeonMapRoom.TYPE_TRAP) {
+ doorColor = TRAP_DOOR_COLOR
+ }
+ if (this.rooms.get((x - 31) + "," + (y - 15))?.type === DungeonMapRoom.TYPE_MINIBOSS) {
+ doorColor = MINIBOSS_DOOR_COLOR
+ }
+ if (this.rooms.get((x + 1) + "," + (y - 15))?.type === DungeonMapRoom.TYPE_BLOOD) {
+ doorColor = BLOOD_DOOR_COLOR
+ }
+ if (this.rooms.get((x + 1) + "," + (y - 15))?.type === DungeonMapRoom.TYPE_PUZZLE) {
+ doorColor = PUZZLE_DOOR_COLOR
+ }
+ if (this.rooms.get((x + 1) + "," + (y - 15))?.type === DungeonMapRoom.TYPE_TRAP) {
+ doorColor = TRAP_DOOR_COLOR
+ }
+ if (this.rooms.get((x + 1) + "," + (y - 15))?.type === DungeonMapRoom.TYPE_MINIBOSS) {
+ doorColor = MINIBOSS_DOOR_COLOR
+ }
+ }
+
+ graphics.setColor(doorColor)
+
+ graphics.fillRect(x + (rotation === 0 ? 0 : 1), y + (rotation === 1 ? 0 : 1), rotation === 0 ? 8 : 6, rotation === 1 ? 8 : 6)
+
+ if (rotation === 0) {
+ DungeonMapRoom.drawUnknownRoom(graphics, x - 15, y + 1)
+ DungeonMapRoom.drawUnknownRoom(graphics, x - 15, y - 31)
+ }
+ if (rotation === 1) {
+ DungeonMapRoom.drawUnknownRoom(graphics, x - 31, y - 15)
+ DungeonMapRoom.drawUnknownRoom(graphics, x + 1, y - 15)
+ }
+ }
+
+ //render rooms
+ for (let data of this.rooms.entries()) {
+ let room = data[1]
+ room.draw(graphics, this.renderTicks)
+ }
+
+ graphics.translate(-256 + 32, -256 + 32)
+
+ return image
+ }
+
+ toImageX(x) {
+ return (x + 255 - 32) / 256
+ }
+
+ toImageY(y) {
+ return (y + 255 - 32) / 256
+ }
+}
+
+export default DungeonMapData
\ No newline at end of file
diff --git a/src/features/dungeonMap2/DungeonMapRoom.js b/src/features/dungeonMap2/DungeonMapRoom.js
new file mode 100644
index 0000000..d6ee014
--- /dev/null
+++ b/src/features/dungeonMap2/DungeonMapRoom.js
@@ -0,0 +1,256 @@
+import DungeonRoomStaticData from "./DungeonRoomStaticData"
+
+const Color = Java.type("java.awt.Color")
+
+class DungeonMapRoom {
+
+ static TYPE_SPAWN = 0
+ static TYPE_NORMAL = 1
+ static TYPE_PUZZLE = 2
+ static TYPE_MINIBOSS = 3
+ static TYPE_FAIRY = 4
+ static TYPE_BLOOD = 5
+ static TYPE_TRAP = 7
+ static TYPE_UNKNOWN = 6
+
+ static SHAPE_1X1 = 0
+ static SHAPE_1X2 = 1
+ static SHAPE_1X3 = 2
+ static SHAPE_1X4 = 3
+ static SHAPE_2X2 = 4
+ static SHAPE_L = 5
+
+ static fromId(roomId, x, y, rotation) {
+ let data = DungeonRoomStaticData.getDataFromId(roomId)
+ let type = DungeonMapRoom.TYPE_NORMAL
+ switch (data.type) {
+ case "mobs":
+ type = DungeonMapRoom.TYPE_NORMAL
+ break
+ case "miniboss":
+ type = DungeonMapRoom.TYPE_NORMAL
+ break
+ case "spawn":
+ type = DungeonMapRoom.TYPE_SPAWN
+ break
+ case "puzzle":
+ type = DungeonMapRoom.TYPE_PUZZLE
+ break
+ case "gold":
+ type = DungeonMapRoom.TYPE_MINIBOSS
+ break
+ case "fairy":
+ type = DungeonMapRoom.TYPE_FAIRY
+ break
+ case "blood":
+ type = DungeonMapRoom.TYPE_BLOOD
+ break
+ case "trap":
+ type = DungeonMapRoom.TYPE_TRAP
+ break
+ }
+
+ let shape = DungeonMapRoom.SHAPE_1X1
+ switch (data.shape) {
+ case "1x1":
+ shape = DungeonMapRoom.SHAPE_1X1
+ break
+ case "1x2":
+ shape = DungeonMapRoom.SHAPE_1X2
+ break
+ case "1x3":
+ shape = DungeonMapRoom.SHAPE_1X3
+ break
+ case "1x4":
+ shape = DungeonMapRoom.SHAPE_1X4
+ break
+ case "2x2":
+ shape = DungeonMapRoom.SHAPE_2X2
+ break
+ case "L":
+ shape = DungeonMapRoom.SHAPE_L
+ break
+ }
+ return new DungeonMapRoom(type, shape, rotation, x, y, roomId)
+ }
+
+ /**
+ *
+ * @param {Number} type
+ * @param {Number} shape
+ * @param {Number} rotation 0-3
+ * @param {Number} x
+ * @param {Number} y
+ * @param {String} roomId
+ */
+ constructor(type, shape, rotation, x, y, roomId) {
+ this.type = type
+ this.shape = shape
+ this.rotation = rotation
+ this.roomId = roomId
+ this.maxSecrets = roomId ? DungeonRoomStaticData.getDataFromId(roomId).secrets : 0
+ this.secrets = 0
+
+ this.checkedState = 0
+
+ this.location = [x, y]
+ }
+
+ setSecrets(curr, max) {
+ if (this.maxSecrets === 0) return
+ this.maxSecrets = max
+ this.secrets = curr
+ }
+
+ getSecrets() {
+ let checkColor = "&8"
+ if (this.checkedState === 1) checkColor = "&f"
+ if (this.checkedState === 2) checkColor = "&a"
+ return checkColor + this.secrets + "/" + this.maxSecrets
+ }
+
+ setId(id) {
+ if (this.roomId !== id) {
+ this.roomId = id
+
+ let newRoomData = DungeonMapRoom.fromId(id)
+ this.type = newRoomData.type
+ this.shape = newRoomData.shape
+ this.maxSecrets = newRoomData.maxSecrets
+ }
+ }
+
+ setCheckedState(state) { }
+
+ /**
+ * Renders this room onto the given Graphics2D
+ * @param {Graphics2D} graphics
+ */
+ draw(graphics, renderTicks) {
+
+ let [roomWidth, roomHeight] = this.getRoomWidthHeight()
+
+ let translateX = this.location[0] + 3 + roomWidth / 2
+ let translateY = this.location[1] + 3 + roomHeight / 2
+
+ graphics.translate(translateX, translateY)
+
+ graphics.setColor(this.getRoomRenderColor())
+
+ switch (this.shape) {
+ case DungeonMapRoom.SHAPE_1X1:
+ case DungeonMapRoom.SHAPE_1X2:
+ case DungeonMapRoom.SHAPE_1X3:
+ case DungeonMapRoom.SHAPE_1X4:
+ case DungeonMapRoom.SHAPE_2X2:
+ graphics.fillRect(-roomWidth / 2 + 3, -roomHeight / 2 + 3, roomWidth - 6, roomHeight - 6)
+ break;
+ case DungeonMapRoom.SHAPE_L:
+ graphics.rotate(this.rotation * Math.PI / 2)
+ graphics.fillRect(-(26 + 32) / 2, -(26 + 32) / 2, 26, 26 + 32)
+ graphics.fillRect(-(26 + 32) / 2, -(26 + 32) / 2, 26 + 32, 26)
+ graphics.rotate(-this.rotation * Math.PI / 2)
+ break;
+ }
+
+ graphics.translate(-translateX, -translateY)
+
+ if (renderTicks || this.maxSecrets === 0) {
+ if (this.checkedState === 1) {
+ let loc = this.getIconLocation()
+ graphics.drawImage(whiteCheck, loc[0] - 2, loc[1] - 2, 10, 10, null)
+ }
+ if (this.checkedState === 2) {
+ let loc = this.getIconLocation()
+ graphics.drawImage(greenCheck, loc[0] - 2, loc[1] - 2, 10, 10, null)
+ }
+ }
+ }
+
+ getRoomWidthHeight() {
+ let roomWidth = 32
+ let roomHeight = 32
+
+ switch (this.shape) {
+ case DungeonMapRoom.SHAPE_1X2:
+ roomWidth = 64
+ break;
+ case DungeonMapRoom.SHAPE_1X3:
+ roomWidth = 96
+ break;
+ case DungeonMapRoom.SHAPE_1X4:
+ roomWidth = 128
+ break;
+ case DungeonMapRoom.SHAPE_2X2:
+ case DungeonMapRoom.SHAPE_L:
+ roomWidth = 64
+ roomHeight = 64
+ break;
+ }
+
+ if (this.rotation === 1 || this.rotation === 3) {
+ let tmp = roomWidth
+ roomWidth = roomHeight
+ roomHeight = tmp
+ }
+
+ return [roomWidth, roomHeight]
+ }
+
+ getRoomRenderColor() {
+ return roomColorMap.get(this.type)
+ }
+
+ getIconLocation() {
+ let [width, height] = this.getRoomWidthHeight()
+ if (this.shape === DungeonMapRoom.SHAPE_L && this.rotation === 0) {
+ return [this.location[0] + 16, this.location[1] + 16]
+ }
+ if (this.shape === DungeonMapRoom.SHAPE_L && this.rotation === 1) {
+ return [this.location[0] + 16 + 32, this.location[1] + 16]
+ }
+ if (this.shape === DungeonMapRoom.SHAPE_L && this.rotation === 2) {
+ return [this.location[0] + 16 + 31, this.location[1] + 16 + 31]
+ }
+ if (this.shape === DungeonMapRoom.SHAPE_L && this.rotation === 2) {
+ return [this.location[0] + 16, this.location[1] + 16 + 32]
+ }
+
+ return [this.location[0] + width / 2, this.location[1] + height / 2]
+ }
+
+ static drawUnknownRoom(graphics, x, y) {
+ let roomWidth = 32
+ let roomHeight = 32
+
+ let translateX = x + 3 + roomWidth / 2
+ let translateY = y + 3 + roomHeight / 2
+
+ graphics.translate(translateX, translateY)
+
+ graphics.setColor(roomColorMap.get(DungeonMapRoom.TYPE_UNKNOWN))
+
+ graphics.fillRect(-13, -13, 26, 26)
+
+ graphics.drawImage(questionMark, -4, -7, 8, 14, null)
+
+ graphics.translate(-translateX, -translateY)
+ }
+}
+
+let roomColorMap = new Map()
+roomColorMap.set(DungeonMapRoom.TYPE_SPAWN, new Color(Renderer.color(0, 124, 0, 255)))
+roomColorMap.set(DungeonMapRoom.TYPE_NORMAL, new Color(Renderer.color(114, 67, 27, 255)))
+roomColorMap.set(DungeonMapRoom.TYPE_PUZZLE, new Color(Renderer.color(178, 76, 216, 255)))
+roomColorMap.set(DungeonMapRoom.TYPE_MINIBOSS, new Color(Renderer.color(229, 229, 51, 255)))
+roomColorMap.set(DungeonMapRoom.TYPE_FAIRY, new Color(Renderer.color(242, 127, 165, 255)))
+roomColorMap.set(DungeonMapRoom.TYPE_BLOOD, new Color(Renderer.color(255, 0, 0, 255)))
+roomColorMap.set(DungeonMapRoom.TYPE_TRAP, new Color(Renderer.color(216, 127, 51, 255)))
+roomColorMap.set(DungeonMapRoom.TYPE_UNKNOWN, new Color(Renderer.color(65, 65, 65, 255)))
+
+const greenCheck = new Image("greenCheckVanilla.png", "https://i.imgur.com/h2WM1LO.png").image
+const whiteCheck = new Image("whiteCheckVanilla.png", "https://i.imgur.com/hwEAcnI.png").image
+const failedRoom = new Image("failedRoomVanilla.png", "https://i.imgur.com/WqW69z3.png").image
+const questionMark = new Image("questionMarkVanilla.png", "https://i.imgur.com/1jyxH9I.png").image
+
+export default DungeonMapRoom
\ No newline at end of file
diff --git a/src/features/dungeonMap2/DungeonRoomStaticData.js b/src/features/dungeonMap2/DungeonRoomStaticData.js
new file mode 100644
index 0000000..75d5b1e
--- /dev/null
+++ b/src/features/dungeonMap2/DungeonRoomStaticData.js
@@ -0,0 +1,19 @@
+class DungeonRoomStaticData {
+ constructor() {
+ this.fullRoomData = JSON.parse(FileLib.read("SoopyV2", "data/roomdata.json"))
+
+ this.idMap = new Map()
+ this.fullRoomData.forEach((d, i) => {
+ d.id.forEach(id => {
+ this.idMap.set(id, i)
+ })
+ this.idMap.set(d.index, i)
+ })
+ }
+
+ getDataFromId(id) {
+ return this.fullRoomData[this.idMap.get(id)]
+ }
+}
+
+export default new DungeonRoomStaticData()
\ No newline at end of file
diff --git a/src/features/dungeonMap2/index.js b/src/features/dungeonMap2/index.js
new file mode 100644
index 0000000..199bc05
--- /dev/null
+++ b/src/features/dungeonMap2/index.js
@@ -0,0 +1,312 @@
+///
+///
+
+import Feature from "../../featureClass/class";
+import renderLibs from "../../../guimanager/renderLibs";
+import DungeonMapData from "./DungeonMapData";
+import DungeonRoomStaticData from "./DungeonRoomStaticData";
+import ImageLocationSetting from "../settings/settingThings/imageLocation";
+import ToggleSetting from "../settings/settingThings/toggle";
+import { f, m } from "../../../mappings/mappings";
+
+const DefaultVertexFormats = Java.type("net.minecraft.client.renderer.vertex.DefaultVertexFormats")
+const MCTessellator = Java.type("net.minecraft.client.renderer.Tessellator")
+
+class DungeonMap extends Feature {
+ constructor() {
+ super()
+ }
+
+ onEnable() {
+ if (Player.getUUID().toString() !== "dc8c3964-7b29-4e03-ae9e-d13ebd65dd29") {
+ new SettingBase("not Coming soontm", "maby", undefined, "coming_soontm", this)
+ return
+ }
+ this.mapLocation = new ImageLocationSetting("Map Location", "Sets the location of the map on the hud", "dmap_location", this, [10, 10, 1], new Image(javax.imageio.ImageIO.read(new java.io.File("./config/ChatTriggers/modules/SoopyV2/features/dungeonMap/map.png"))), 150, 150)
+ this.mapSecrets = new ToggleSetting("Show secret count instead of tick", "Syncs between soopyv2 users", true, "dmap_secrets", this)
+
+ this.lastRoomId = undefined
+
+ /**@type {DungeonMapData} */
+ this.currentDungeon = undefined
+ this.lastChange = 0
+
+ this.roomXY = this.getRoomXYWorld().join(",")
+ this.lastXY = undefined
+
+ let registerActionBar = this.registerCustom("actionbar", (curr, max) => {
+
+ let roomid = this.getCurrentRoomId()
+ let roomWorldData = this.getRoomWorldData()
+
+ let rotation = roomWorldData.width > roomWorldData.height ? 0 : 1
+
+ if (this.getCurrentRoomData().shape === "L") rotation = roomWorldData.rotation
+ if (this.getCurrentRoomData().type === "spawn") {
+ roomWorldData.x = x + 1
+ roomWorldData.y = y + 1
+ }
+
+ this.currentDungeon.roomSecrets(roomWorldData.x, roomWorldData.y, rotation, roomid, curr, max)
+ })
+ registerActionBar.trigger.setCriteria('&7${curr}/${max} Secrets').setParameter('contains');
+
+ this.registerStep(true, 5, this.update)
+
+ this.registerEvent("renderOverlay", this.renderOverlay)
+ this.registerEvent("worldLoad", this.worldLoad)
+
+ }
+
+ update() {
+ if (!this.isInDungeon()) {
+ if (this.currentDungeon) {
+ this.currentDungeon.destroy()
+ this.lastRoomId = undefined
+ this.currentDungeon = undefined
+ }
+ return
+ }
+
+ if (!this.currentDungeon) {
+ this.currentDungeon = new DungeonMapData(this.FeatureManager.features["dataLoader"].class.dungeonFloor)
+ }
+ this.currentDungeon.setRenderTicks(!this.mapSecrets.getValue())
+
+ this.currentDungeon.updatePlayers()
+ this.currentDungeon.updateHotbarData()
+
+ let roomid = this.getCurrentRoomId()
+ if (!roomid.includes(",")) return
+ if (this.roomXY !== this.getRoomXYWorld().join(",")) {
+ this.roomXY = this.getRoomXYWorld().join(",")
+ this.lastChange = Date.now()
+ }
+
+ let x = Math.floor((Player.getX() + 8) / 32) * 32 - 9
+ let y = Math.floor((Player.getZ() + 8) / 32) * 32 - 9
+
+ if (roomid !== this.lastRoomId && Date.now() - this.lastChange > 500) {
+ this.lastRoomId = roomid
+
+ let roomWorldData = this.getRoomWorldData()
+
+ let rotation = roomWorldData.width > roomWorldData.height ? 0 : 1
+
+ if (this.getCurrentRoomData().shape === "L") rotation = roomWorldData.rotation
+ if (this.getCurrentRoomData().type === "spawn") {
+ roomWorldData.x = x + 1
+ roomWorldData.y = y + 1
+ }
+
+ this.currentDungeon.setRoom(roomWorldData.x, roomWorldData.y, rotation, roomid)
+ }
+
+
+ if (this.lastXY !== x + "," + y) {
+ this.lastXY = x + "," + y
+ if (this.getBlockAt(x + 16, 73, y) !== 0) {
+ this.currentDungeon.setDoor(x + 16, y, -1, 0)
+ }
+ if (this.getBlockAt(x, 73, y + 16) !== 0) {
+ this.currentDungeon.setDoor(x, y + 16, -1, 1)
+ }
+ if (this.getBlockAt(x + 16, 73, y + 32) !== 0) {
+ this.currentDungeon.setDoor(x + 16, y + 32, -1, 0)
+ }
+ if (this.getBlockAt(x + 32, 73, y + 16) !== 0) {
+ this.currentDungeon.setDoor(x + 32, y + 16, -1, 1)
+ }
+ }
+ }
+
+ renderOverlay() {
+ if (this.currentDungeon) {
+ this.currentDungeon.updatePlayersFast()
+
+ let x = this.mapLocation.getValue()[0]
+ let y = this.mapLocation.getValue()[1]
+ let size = 150 * this.mapLocation.getValue()[2]
+ Renderer.drawRect(Renderer.color(0, 0, 0, 100), x, y, size, size)
+
+ this.currentDungeon.getImage().draw(x, y, size, size)
+
+ Renderer.drawRect(Renderer.color(0, 0, 0), x, y, size, 2)
+ Renderer.drawRect(Renderer.color(0, 0, 0), x, y, 2, size)
+ Renderer.drawRect(Renderer.color(0, 0, 0), x + size - 2, y, 2, size)
+ Renderer.drawRect(Renderer.color(0, 0, 0), x, y + size - 2, size, 2)
+
+ for (let player of this.currentDungeon.getPlayers()) {
+ let x2 = this.currentDungeon.toImageX(player.x) * size + x
+ let y2 = this.currentDungeon.toImageY(player.y) * size + y
+ let rx = -6
+ let ry = -6
+ let rw = 12
+ let rh = 12
+
+ Renderer.translate(x2, y2)
+ Renderer.rotate(player.rotate)
+ GlStateManager[m.enableBlend]()
+ GlStateManager[m.scale](1, 1, 50)
+ Client.getMinecraft()[m.getTextureManager]()[m.bindTexture.TextureManager](player.skin)
+ GlStateManager[m.enableTexture2D]()
+
+ let tessellator = MCTessellator[m.getInstance.Tessellator]()
+ let worldRenderer = tessellator[m.getWorldRenderer]()
+ worldRenderer[m.begin](7, DefaultVertexFormats[f.POSITION_TEX])
+
+ worldRenderer[m.pos](rx, ry + rh, 0.0)[m.tex](8 / 64, 16 / 64)[m.endVertex]()
+ worldRenderer[m.pos](rx + rw, ry + rh, 0.0)[m.tex](16 / 64, 16 / 64)[m.endVertex]()
+ worldRenderer[m.pos](rx + rw, ry, 0.0)[m.tex](16 / 64, 8 / 64)[m.endVertex]()
+ worldRenderer[m.pos](rx, ry, 0.0)[m.tex](8 / 64, 8 / 64)[m.endVertex]()
+ tessellator[m.draw.Tessellator]()
+
+ Tessellator.popMatrix()
+ Tessellator.pushMatrix()
+ }
+
+ if (this.mapSecrets.getValue()) {
+ Renderer.retainTransforms(true)
+ Renderer.translate(x, y)
+ this.currentDungeon.renderSecrets(size)
+ Renderer.translate(-x, -y)
+ Renderer.retainTransforms(false)
+ }
+ }
+ }
+
+ worldLoad() {
+ if (this.currentDungeon) this.currentDungeon.destroy()
+ this.lastRoomId = undefined
+ this.currentDungeon = undefined
+ }
+
+ getCurrentRoomId() {
+ if (Scoreboard.getLines().length === 0) return undefined
+ let id = Scoreboard.getLineByIndex(Scoreboard.getLines().length - 1).getName().trim().split(" ").pop()
+
+ return id
+ }
+
+ isInDungeon() {
+ if (!this.FeatureManager || !this.FeatureManager.features["dataLoader"]) return false
+ return this.FeatureManager.features["dataLoader"].class.isInDungeon
+ }
+
+ getRoomXYWorld() {
+ let roomData = this.getRoomWorldData()
+ if (roomData.rotation === 4) {
+ return [roomData.x, roomData.y + 32]
+ }
+
+ return [roomData.x, roomData.y]
+ }
+
+ getCurrentRoomData() {
+ return DungeonRoomStaticData.getDataFromId(this.getCurrentRoomId())
+ }
+
+ getRotation(x, y, width, height, roofY) {
+ let currRoomData = this.getCurrentRoomData()
+ if (!currRoomData) return -1
+
+ if (currRoomData.shape !== "L") {
+ if (this.getTopBlockAt(x, y, roofY) === 11) return 0
+ if (this.getTopBlockAt(x + width, y, roofY) === 11) return 1
+ if (this.getTopBlockAt(x + width, y + height, roofY) === 11) return 2
+ if (this.getTopBlockAt(x, y + height, roofY) === 11) return 3
+ } else {
+ let one = this.getTopBlockAt2(x + width / 2 + 1, y + height / 2, roofY)
+ let two = this.getTopBlockAt2(x + width / 2 - 1, y + height / 2, roofY)
+ let three = this.getTopBlockAt2(x + width / 2, y + height / 2 + 1, roofY)
+ let four = this.getTopBlockAt2(x + width / 2, y + height / 2 - 1, roofY)
+
+ if (one === 0 && three === 0) return 0
+ if (two === 0 && three === 0) return 1
+ if (one === 0 && four === 0) return 3
+ if (two === 0 && four === 0) return 2//3 IS SO TOXIK HGOLY HEL I HATE L SHAPE ROOMS WHY DO THIS TO ME
+ }
+
+ return -1
+ }
+
+ getRoomWorldData() {
+ let x = Math.floor((Player.getX() + 8) / 32) * 32 - 8
+ let y = Math.floor((Player.getZ() + 8) / 32) * 32 - 8
+ let width = 30
+ let height = 30
+
+ let roofY = this.getRoofAt(x, y)
+
+ while (World.getBlockStateAt(new BlockPos(x - 1, roofY, y)).getBlockId() !== 0) {
+ x -= 32
+ width += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x, roofY, y - 1)).getBlockId() !== 0) {
+ y -= 32
+ height += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x - 1, roofY, y)).getBlockId() !== 0) { //second iteration incase of L shape
+ x -= 32
+ width += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x + width + 1, roofY, y)).getBlockId() !== 0) {
+ width += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x, roofY, y + height + 1)).getBlockId() !== 0) {
+ height += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x + width, roofY, y + height + 1)).getBlockId() !== 0) { //second iteration incase of L shape
+ height += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x + width + 1, roofY, y + height)).getBlockId() !== 0) { //second iteration incase of L shape
+ width += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x + width, roofY, y - 1)).getBlockId() !== 0) {//second iteration incase of L shape
+ y -= 32
+ height += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x - 1, roofY, y + height)).getBlockId() !== 0) { //third iteration incase of L shape
+ x -= 32
+ width += 32
+ }
+
+
+ return {
+ x,
+ y,
+ width,
+ height,
+ cx: x + width / 2,
+ cy: y + height / 2,
+ rotation: this.getRotation(x, y, width, height, roofY)
+ }
+ }
+
+ getRoofAt(x, z) {
+ let y = 255
+ while (y > 0 && World.getBlockStateAt(new BlockPos(x, y, z)).getBlockId() === 0) y--
+
+ return y
+ }
+
+ getTopBlockAt(x, z, y) {
+ if (!y) y = this.getHeightAt(x, z)
+
+ return World.getBlockStateAt(new BlockPos(x, y, z)).getMetadata()
+ }
+ getBlockAt(x, y, z) {
+ return World.getBlockStateAt(new BlockPos(x, y, z)).getBlockId()
+ }
+ getTopBlockAt2(x, z, y) {
+ if (!y) y = this.getHeightAt(x, z)
+
+ return World.getBlockStateAt(new BlockPos(x, y, z)).getBlockId()
+ }
+ onDisable() {
+ }
+}
+
+module.exports = {
+ class: new DungeonMap()
+}
\ No newline at end of file
diff --git a/src/features/dungeonMap2/metadata.json b/src/features/dungeonMap2/metadata.json
new file mode 100644
index 0000000..53e7e03
--- /dev/null
+++ b/src/features/dungeonMap2/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Dungeon Map 2",
+ "description": "WIP",
+ "isHidden": true,
+ "isTogglable": true,
+ "defaultEnabled": false,
+ "sortA": 1
+}
\ No newline at end of file
diff --git a/src/features/dungeonRoutes/index.js b/src/features/dungeonRoutes/index.js
new file mode 100644
index 0000000..e59e908
--- /dev/null
+++ b/src/features/dungeonRoutes/index.js
@@ -0,0 +1,481 @@
+///
+///
+import { m } from "../../../mappings/mappings";
+import Feature from "../../featureClass/class";
+import { drawBoxAtBlock, drawBoxAtBlock2, drawFilledBox, drawLine, drawLinePoints } from "../../utils/renderUtils";
+import { calculateDistanceQuick } from "../../utils/utils";
+import SettingBase from "../settings/settingThings/settingBase";
+
+const EntityItem = Java.type("net.minecraft.entity.item.EntityItem")
+
+const EnumParticleTypes = Java.type('net.minecraft.util.EnumParticleTypes');
+
+class DungeonRoutes extends Feature {
+ constructor() {
+ super()
+ }
+
+ onEnable() {
+ if (Player.getUUID().toString() !== "dc8c3964-7b29-4e03-ae9e-d13ebd65dd29") {
+ new SettingBase("Coming soontm", "maby", undefined, "coming_soontm", this)
+ return
+ }
+
+ this.recordingData = []
+ this.currentActionIndex = 0
+ this.lastLocationUpdatedTime = Date.now()
+
+ this.registerEvent("soundPlay", this.playSound)
+ this.registerEvent("worldLoad", this.worldLoad)
+ this.registerEvent("playerInteract", this.playerInteract)
+ this.registerForge(net.minecraftforge.event.entity.EntityJoinWorldEvent, this.entityJoinWorldEvent)
+ let packetRecieved = this.registerCustom("packetReceived", this.pickupItem)
+
+ try {
+ packetRecieved.trigger.setPacketClasses([net.minecraft.network.play.server.S0DPacketCollectItem])
+ } catch (e) { }//older ct version
+
+ this.registerStep(true, 5, () => {
+ let roomId = this.getCurrentRoomId()
+ if (this.lastRoomId !== roomId) {
+ this.lastRoomId = roomId
+ this.recordingData = []
+
+ this.currRoomData = this.getRoomWorldData()
+
+ this.currentRouteDisplay = this.routesIndexMap.get(this.fullRoomData[this.idMap.get(roomId)].index)?.data
+ ChatLib.chat(JSON.stringify(this.currentRouteDisplay, undefined, 2))
+ }
+
+ if (!this.recordRoute) return
+ if (!this.recordingData[this.recordingData.length - 1]) return
+ let locs = this.recordingData[this.recordingData.length - 1].locations
+ if (locs.length === 0
+ || Math.ceil(Player.getX()) !== locs[locs.length - 1][0]
+ || Math.ceil(Player.getY()) !== locs[locs.length - 1][1]
+ || Math.ceil(Player.getZ()) !== locs[locs.length - 1][2]) {
+
+ this.addRecordingPoint("locations", [Math.ceil(Player.getX()), Math.ceil(Player.getY()), Math.ceil(Player.getZ())])
+ }
+ })
+
+ this.registerEvent("renderWorld", () => {
+ if (this.recordingData && this.recordingData[this.recordingData.length - 1]) {
+ this.recordingData[this.recordingData.length - 1].etherwarps.forEach((loc) => {
+ drawFilledBox(loc[0], loc[1] - 1, loc[2], 1, 1, 1, 0, 0, 50 / 255, true)
+ drawBoxAtBlock(loc[0] - 0.5, loc[1] - 1, loc[2] - 0.5, 1, 0, 0, 1, 1, 1)
+ })
+ this.recordingData[this.recordingData.length - 1].mines.forEach((loc) => {
+ drawFilledBox(loc[0], loc[1] - 0.5, loc[2], 1, 1, 0, 1, 0, 50 / 255, true)
+ })
+ this.recordingData[this.recordingData.length - 1].tnts.forEach((loc) => {
+ drawFilledBox(loc[0], loc[1] - 0.5, loc[2], 1, 1, 1, 0, 0, 50 / 255, true)
+ })
+ this.recordingData[this.recordingData.length - 1].interacts.forEach((data) => {
+ let loc = data.loc
+ drawFilledBox(loc[0], loc[1], loc[2], 1, 1, 0, 0, 1, 50 / 255, true)
+ drawBoxAtBlock(loc[0] - 0.5, loc[1], loc[2] - 0.5, 0, 0, 1, 1, 1, 1)
+ })
+ let locs = this.recordingData[this.recordingData.length - 1].locations
+ if (locs.length >= 2) drawLinePoints(locs.map(a => [a[0] - 0.5, a[1] + 0.1, a[2] - 0.5]), 0, 0, 255, 2, false)
+ }
+
+ if (this.currRoomData) {
+ if (this.currentRouteDisplay) {
+ this.currentRouteDisplay[this.currentActionIndex].etherwarps.forEach(loc => {
+ let coords = this.toRoomCoordinates(loc[0], loc[1] - 1, loc[2])
+ drawFilledBox(coords[0], coords[1], coords[2], 1, 1, 1, 0, 0, 50 / 255, true)
+ drawBoxAtBlock(coords[0] - 0.5, coords[1], coords[2] - 0.5, 1, 0, 0, 1, 1, 1)
+ })
+ this.currentRouteDisplay[this.currentActionIndex].mines.forEach(loc => {
+ let coords = this.toRoomCoordinates(loc[0], loc[1] - 0.5, loc[2])
+ drawBoxAtBlock(coords[0] - 0.5, coords[1], coords[2] - 0.5, 1, 1, 0, 1, 1, 50 / 255)
+ })
+ this.currentRouteDisplay[this.currentActionIndex].tnts.forEach(loc => {
+ let coords = this.toRoomCoordinates(loc[0], loc[1] - 1, loc[2])
+ drawBoxAtBlock(coords[0] - 0.5, coords[1] + 0.5, coords[2] - 0.5, 1, 1, 255, 1, 1, 50 / 255)
+ })
+ this.currentRouteDisplay[this.currentActionIndex].interacts.forEach((data) => {
+ let coords = this.toRoomCoordinates(data.loc[0], data.loc[1], data.loc[2])
+ drawFilledBox(coords[0], coords[1], coords[2], 1, 1, 0, 0, 1, 50 / 255, true)
+ drawBoxAtBlock(coords[0] - 0.5, coords[1], coords[2] - 0.5, 0, 0, 1, 1, 1, 1)
+ })
+
+ // if (this.currentRouteDisplay.locations.length >= 2) drawLinePoints(this.currentRouteDisplay.locations.map(a => this.toRoomCoordinates(...a)).map(a => [a[0] - 0.5, a[1] + 0.1, a[2] - 0.5]), 0, 0, 255, 2, false)
+
+ }
+ }
+
+ })
+
+ this.tempItemIdLocs = new Map()
+
+ this.idMap = new Map()
+ this.routesIndexMap = new Map()
+ this.fullRoomData = JSON.parse(FileLib.read("SoopyV2", "data/roomdata.json"))
+ this.fullRoutesData = JSON.parse(FileLib.read("SoopyV2", "features/dungeonRoutes/routesData.json"))
+ this.fullRoomData.forEach((d, i) => {
+ d.id.forEach(id => {
+ this.idMap.set(id, i)
+ })
+ this.idMap.set(d.index, i)
+ })
+ this.fullRoutesData.forEach((d, i) => {
+ this.routesIndexMap.set(d.index, d)
+ })
+ this.lastRoomId = undefined
+
+ this.currRoomData = undefined
+ this.currentRouteDisplay = undefined
+
+ this.registerCommand("roomid", (...name) => {
+ ChatLib.chat(JSON.stringify(this.getCurrentRoomData(), undefined, 2))
+ ChatLib.chat(JSON.stringify(this.getRoomWorldData(), undefined, 2))
+ })
+ this.recordRoute = false
+
+ this.registerCommand("startroute", (...name) => {
+ this.recordRoute = true
+ this.recordingData = []
+ this.addRecordingPoint()
+ ChatLib.chat(this.FeatureManager.messagePrefix + "Started recording route!")
+ })
+
+ this.registerCommand("saveroute", () => {
+ let data = {
+ index: this.fullRoomData[this.idMap.get(this.lastRoomId)].index,
+ data: this.recordingData.map(a => {
+ a.etherwarps = a.etherwarps.map(a => this.fromRoomCoordinates(a[0], a[1], a[2]))
+ a.mines = a.mines.map(a => this.fromRoomCoordinates(a[0], a[1], a[2]))
+ a.locations = a.locations.map(a => this.fromRoomCoordinates(...a))
+ a.interacts = a.interacts.map(b => {
+ b.loc = this.fromRoomCoordinates(...b.loc)
+ return b
+ })
+ a.tnts = a.tnts.map(a => this.fromRoomCoordinates(a[0], a[1], a[2]))
+
+ return a
+ })
+ }
+ // this.recordingData.push({
+ // etherwarps: [],
+ // mines: [],
+ // locations: [],
+ // interacts: [],
+ // tnts: []
+ // })
+
+ ChatLib.chat(JSON.stringify(data, undefined, 4))
+ ChatLib.chat(this.FeatureManager.messagePrefix + "Saved route!")
+ this.recordRoute = false
+ })
+
+ this.registerStep(true, 5, () => {
+ if (this.currRoomData) {
+ if (this.currentRouteDisplay) {
+
+ if (this.currentRouteDisplay[this.currentActionIndex].locations.length >= 2) this.drawLineMultipleParticles(this.currentRouteDisplay[this.currentActionIndex].locations.map(a => this.toRoomCoordinates(a[0], a[1], a[2])))
+
+ }
+ }
+ })
+ }
+
+ addRecordingPoint(type, point) {
+ if (type) {
+ this.recordingData[this.recordingData.length - 1][type].push(point)
+ }
+ if (!type || type === "interacts") {
+ this.recordingData.push({
+ etherwarps: [],
+ mines: [],
+ locations: [],
+ interacts: [],
+ tnts: []
+ })
+ }
+ }
+ drawLineMultipleParticles(locations) {
+ let lastLoc = undefined
+ locations.forEach(loc => {
+ if (!lastLoc) {
+ lastLoc = loc
+ return
+ }
+
+ this.drawLineParticles(lastLoc, loc)
+ lastLoc = loc
+ })
+ }
+
+ drawLineParticles(loc1, loc2) {
+ let distance = Math.hypot(...loc1.map((a, i) => a - loc2[i]))
+ let maxPoints = Math.ceil(distance * 1)
+ for (let i = 0; i < maxPoints; i++) {
+ let actualI = i + Math.random()
+ let a = actualI / maxPoints
+ let loc = [loc1[0] * a + loc2[0] * (1 - a) - 0.5, loc1[1] * a + loc2[1] * (1 - a) + 0.1, loc1[2] * a + loc2[2] * (1 - a) - 0.5]
+
+ let a2 = (actualI + 0.02) / maxPoints
+ let loc3 = [loc1[0] * a2 + loc2[0] * (1 - a2) - 0.5, loc1[1] * a2 + loc2[1] * (1 - a2) + 0.1, loc1[2] * a2 + loc2[2] * (1 - a2) - 0.5]
+ loc3 = loc3.map((a, i) => loc[i] - a)
+
+ this.spawnParticleAtLocation(loc, loc3, "FLAME")
+ }
+ }
+
+ spawnParticleAtLocation(loc, velo, particle) {
+ let particleType = EnumParticleTypes.valueOf(particle);
+ let idField = particleType.getClass().getDeclaredField('field_179372_R');
+ idField.setAccessible(true);
+ let id = idField.get(particleType);
+
+ Client.getMinecraft().field_71438_f.func_174974_b(
+ id, // particleID
+ true, // shouldIgnoreRange
+ loc[0], // x
+ loc[1], // y
+ loc[2], // z
+ velo[0], // speedX
+ velo[1], // speedY
+ velo[2], // speedZ
+ );
+ }
+
+ toRoomCoordinates(x, y, z) { //From relative coords to world coords
+ if (!this.currRoomData) return null
+
+ if (this.currRoomData.rotation === 2) {
+ z *= -1;
+ [x, z] = [z, x]
+ } else if (this.currRoomData.rotation === 3) {
+ x *= -1
+ z *= -1
+ } else if (this.currRoomData.rotation === 4) {
+ x *= -1;
+ [x, z] = [z, x]
+ }
+
+ return [this.currRoomData.cx + x, y, this.currRoomData.cy + z]
+ }
+ fromRoomCoordinates(x, y, z) { //from world coords to relative coords
+ if (!this.currRoomData) return null
+
+ x -= this.currRoomData.cx
+ z -= this.currRoomData.cy
+
+ if (this.currRoomData.rotation === 2) {
+ [x, z] = [z, x]
+ z *= -1
+ } else if (this.currRoomData.rotation === 3) {
+ x *= -1
+ z *= -1
+ } else if (this.currRoomData.rotation === 4) {
+ [x, z] = [z, x]
+ x *= -1
+ }
+
+ return [x, y, z]
+ }
+
+ getRotation(x, y, width, height, roofY) {
+ let currRoomData = this.getCurrentRoomData()
+ if (!currRoomData) return -1
+
+ if (currRoomData.shape !== "L") {
+ if (this.getTopBlockAt(x, y, roofY) === 11) return 1
+ if (this.getTopBlockAt(x + width, y, roofY) === 11) return 2
+ if (this.getTopBlockAt(x + width, y + height, roofY) === 11) return 3
+ if (this.getTopBlockAt(x, y + height, roofY) === 11) return 4
+ } else {
+ let one = this.getTopBlockAt2(x + width / 2 + 1, y + height / 2, roofY)
+ let two = this.getTopBlockAt2(x + width / 2 - 1, y + height / 2, roofY)
+ let three = this.getTopBlockAt2(x + width / 2, y + height / 2 + 1, roofY)
+ let four = this.getTopBlockAt2(x + width / 2, y + height / 2 - 1, roofY)
+
+ if (one === 0 && three === 0) return 1
+ if (two === 0 && three === 0) return 2
+ if (one === 0 && four === 0) return 3
+ if (two === 0 && four === 0) return 4
+ }
+
+ return -1
+ }
+
+ getRoomWorldData() {
+ let x = Math.floor((Player.getX() + 8) / 32) * 32 - 8
+ let y = Math.floor((Player.getZ() + 8) / 32) * 32 - 8
+ let width = 30
+ let height = 30
+
+ let roofY = this.getRoofAt(x, y)
+
+ while (World.getBlockStateAt(new BlockPos(x - 1, roofY, y)).getBlockId() !== 0) {
+ x -= 32
+ width += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x, roofY, y - 1)).getBlockId() !== 0) {
+ y -= 32
+ height += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x - 1, roofY, y)).getBlockId() !== 0) { //second iteration incase of L shape
+ x -= 32
+ width += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x + width + 1, roofY, y)).getBlockId() !== 0) {
+ width += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x, roofY, y + height + 1)).getBlockId() !== 0) {
+ height += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x + width, roofY, y + height + 1)).getBlockId() !== 0) { //second iteration incase of L shape
+ height += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x + width + 1, roofY, y + height)).getBlockId() !== 0) { //second iteration incase of L shape
+ width += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x + width, roofY, y - 1)).getBlockId() !== 0) {//second iteration incase of L shape
+ y -= 32
+ height += 32
+ }
+ while (World.getBlockStateAt(new BlockPos(x - 1, roofY, y + height)).getBlockId() !== 0) { //third iteration incase of L shape
+ x -= 32
+ width += 32
+ }
+
+
+ return {
+ x,
+ y,
+ width,
+ height,
+ cx: x + width / 2,
+ cy: y + height / 2,
+ rotation: this.getRotation(x, y, width, height, roofY)
+ }
+ }
+
+ getRoofAt(x, z) {
+ let y = 255
+ while (y > 0 && World.getBlockStateAt(new BlockPos(x, y, z)).getBlockId() === 0) y--
+
+ return y
+ }
+
+ getTopBlockAt(x, z, y) {
+ if (!y) y = this.getHeightAt(x, z)
+
+ return World.getBlockStateAt(new BlockPos(x, y, z)).getMetadata()
+ }
+ getTopBlockAt2(x, z, y) {
+ if (!y) y = this.getHeightAt(x, z)
+
+ return World.getBlockStateAt(new BlockPos(x, y, z)).getBlockId()
+ }
+
+ getCurrentRoomData() {
+ let roomId = this.idMap.get(this.getCurrentRoomId())
+ if (roomId === undefined) return null
+
+ return this.fullRoomData[roomId]
+ }
+
+ getCurrentRoomId() {
+ let id = Scoreboard.getLineByIndex(Scoreboard.getLines().length - 1).getName().trim().split(" ").pop()
+
+ return id
+ }
+
+ worldLoad() {
+
+ }
+
+ entityJoinWorldEvent(event) {
+ if (event.entity instanceof EntityItem) {
+ // console.log("Blaze joined world")
+ let e = new Entity(event.entity)
+ let pos = [e.getX(), e.getY(), e.getZ()]
+
+ this.tempItemIdLocs.set(event.entity[m.getEntityId.Entity](), pos)
+ // console.log(event.entity[m.getEntityId.Entity]())
+ }
+ }
+
+ pickupItem(packet) {
+ let packetType = new String(packet.class.getSimpleName()).valueOf()
+ if (packetType === "S0DPacketCollectItem") {
+ let pos = this.tempItemIdLocs.get(packet[m.getCollectedItemEntityID]())
+
+ let data = this.currentRouteDisplay[this.currentActionIndex].interacts[0]
+ if (data && data.type === "item") {
+ let coords = this.toRoomCoordinates(data.loc[0], data.loc[1], data.loc[2])
+ if (calculateDistanceQuick(pos, coords) < 2) {
+ if (this.currentRouteDisplay.length >= this.currentActionIndex) {
+ this.currentActionIndex++
+ }
+ }
+ }
+
+ if (!this.recordRoute) return
+ if (pos) this.addRecordingPoint("interacts", { loc: pos, type: "item" })
+ }
+ }
+
+ playerInteract(action, position, event) {
+ if (action.toString() !== "RIGHT_CLICK_BLOCK") return
+
+ let pos = [Player.lookingAt().getX() + 0.5, Player.lookingAt().getY(), Player.lookingAt().getZ() + 0.5]
+
+ let id = Player.lookingAt().getType().getID()
+ if (id !== 54 && id !== 144 && id !== 69) return
+
+
+ let data = this.currentRouteDisplay[this.currentActionIndex].interacts[0]
+ if (data && data.type === "interact") {
+ let coords = this.toRoomCoordinates(data.loc[0], data.loc[1], data.loc[2])
+ console.log(coords.join(","), pos.join(","))
+ if (coords.join(",") === pos.join(",")) {
+ if (this.currentRouteDisplay.length > this.currentActionIndex) {
+ this.currentActionIndex++
+ }
+ }
+ }
+
+ if (!this.recordRoute) return
+ this.addRecordingPoint("interacts", { loc: pos, type: "interact" })
+ }
+
+ playSound(pos, name, volume, pitch, categoryName, event) {
+ if (!this.recordRoute) return
+
+ let loc = [pos.x, pos.y, pos.z]
+ let nameSplitted = name.split(".")
+ if (name === "mob.enderdragon.hit") { //etherwarp
+ this.addRecordingPoint("etherwarps", loc)
+ }
+ if (name === "random.explode" && pitch !== 1) { //tnt OR MIGHT BE spirit scepter
+ this.addRecordingPoint("tnts", loc)
+ }
+ if (name === "mob.bat.death") {
+ this.addRecordingPoint("interacts", { loc: loc, type: "bat" })
+ }
+ if (nameSplitted[0] === "dig") { //mining block
+ if (!this.recordingData[this.recordingData.length - 1].mines.some(a =>
+ a[0] === pos[0]
+ && a[1] === pos[1]
+ && a[2] === pos[2]
+ )) {
+ this.addRecordingPoint("mines", loc)
+ }
+ }
+ }
+
+ onDisable() {
+
+ }
+
+}
+
+module.exports = {
+ class: new DungeonRoutes()
+}
diff --git a/src/features/dungeonRoutes/metadata.json b/src/features/dungeonRoutes/metadata.json
new file mode 100644
index 0000000..c2f2a63
--- /dev/null
+++ b/src/features/dungeonRoutes/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Dungeon Routes",
+ "description": "Routes for dungeons (Coming soontm maby)",
+ "isHidden": false,
+ "isTogglable": true,
+ "defaultEnabled": true,
+ "sortA": 0
+}
\ No newline at end of file
diff --git a/src/features/dungeonRoutes/routesData.json b/src/features/dungeonRoutes/routesData.json
new file mode 100644
index 0000000..d701fc7
--- /dev/null
+++ b/src/features/dungeonRoutes/routesData.json
@@ -0,0 +1,1296 @@
+[
+ {
+ "index": 84,
+ "data": [
+ {
+ "etherwarps": [
+ [
+ 23.5,
+ 83,
+ 12.5
+ ]
+ ],
+ "mines": [],
+ "locations": [
+ [
+ -4,
+ 68,
+ 16
+ ],
+ [
+ 23,
+ 83,
+ 13
+ ],
+ [
+ 24,
+ 84,
+ 13
+ ],
+ [
+ 24,
+ 85,
+ 13
+ ],
+ [
+ 25,
+ 85,
+ 13
+ ],
+ [
+ 25,
+ 84,
+ 12
+ ],
+ [
+ 25,
+ 84,
+ 11
+ ],
+ [
+ 26,
+ 84,
+ 11
+ ],
+ [
+ 27,
+ 84,
+ 9
+ ],
+ [
+ 26,
+ 84,
+ 6
+ ],
+ [
+ 23,
+ 84,
+ 5
+ ],
+ [
+ 19,
+ 84,
+ 5
+ ],
+ [
+ 19,
+ 85,
+ 5
+ ]
+ ],
+ "interacts": [
+ {
+ "loc": [
+ 17.5,
+ 84,
+ 5.5
+ ],
+ "type": "interact"
+ }
+ ],
+ "tnts": []
+ },
+ {
+ "etherwarps": [
+ [
+ -1.5,
+ 85,
+ 23.5
+ ]
+ ],
+ "mines": [
+ [
+ -2.5,
+ 84.5,
+ 23.5
+ ]
+ ],
+ "locations": [
+ [
+ 19,
+ 85,
+ 5
+ ],
+ [
+ 21,
+ 85,
+ 5
+ ],
+ [
+ 22,
+ 84,
+ 5
+ ],
+ [
+ 25,
+ 84,
+ 7
+ ],
+ [
+ 26,
+ 84,
+ 10
+ ],
+ [
+ 25,
+ 84,
+ 13
+ ],
+ [
+ 24,
+ 85,
+ 13
+ ],
+ [
+ 24,
+ 84,
+ 14
+ ],
+ [
+ 23,
+ 83,
+ 14
+ ],
+ [
+ -2,
+ 85,
+ 24
+ ],
+ [
+ -2,
+ 84,
+ 24
+ ],
+ [
+ -3,
+ 84,
+ 24
+ ],
+ [
+ -6,
+ 84,
+ 24
+ ],
+ [
+ -8,
+ 83,
+ 24
+ ],
+ [
+ -8,
+ 81,
+ 24
+ ],
+ [
+ -8,
+ 84,
+ 24
+ ],
+ [
+ -11,
+ 83,
+ 24
+ ],
+ [
+ -15,
+ 83,
+ 24
+ ],
+ [
+ -18,
+ 83,
+ 24
+ ],
+ [
+ -21,
+ 83,
+ 25
+ ]
+ ],
+ "interacts": [
+ {
+ "loc": [
+ -21.5,
+ 83,
+ 25.5
+ ],
+ "type": "interact"
+ }
+ ],
+ "tnts": []
+ },
+ {
+ "etherwarps": [
+ [
+ -18.5,
+ 91,
+ 24.5
+ ],
+ [
+ -9.5,
+ 83,
+ 2.5
+ ]
+ ],
+ "mines": [],
+ "locations": [
+ [
+ -21,
+ 83,
+ 25
+ ],
+ [
+ -19,
+ 92,
+ 25
+ ],
+ [
+ -19,
+ 91,
+ 25
+ ],
+ [
+ -17,
+ 91,
+ 22
+ ],
+ [
+ -17,
+ 91,
+ 21
+ ],
+ [
+ -15,
+ 91,
+ 18
+ ],
+ [
+ -16,
+ 91,
+ 21
+ ],
+ [
+ -16,
+ 91,
+ 19
+ ],
+ [
+ -15,
+ 90,
+ 17
+ ],
+ [
+ -15,
+ 88,
+ 16
+ ],
+ [
+ -14,
+ 86,
+ 13
+ ],
+ [
+ -15,
+ 86,
+ 10
+ ],
+ [
+ -15,
+ 84,
+ 8
+ ],
+ [
+ -15,
+ 83,
+ 6
+ ],
+ [
+ -16,
+ 83,
+ 4
+ ],
+ [
+ -10,
+ 84,
+ 3
+ ],
+ [
+ -10,
+ 83,
+ 3
+ ],
+ [
+ -8,
+ 83,
+ 3
+ ]
+ ],
+ "interacts": [
+ {
+ "loc": [
+ -4.5,
+ 84,
+ 1.5
+ ],
+ "type": "interact"
+ }
+ ],
+ "tnts": []
+ },
+ {
+ "etherwarps": [
+ [
+ -4.5,
+ 88,
+ 1.5
+ ],
+ [
+ -4.5,
+ 92,
+ 1.5
+ ]
+ ],
+ "mines": [],
+ "locations": [
+ [
+ -8,
+ 83,
+ 3
+ ],
+ [
+ -5,
+ 89,
+ 2
+ ],
+ [
+ -5,
+ 88,
+ 2
+ ],
+ [
+ -5,
+ 92,
+ 2
+ ]
+ ],
+ "interacts": [
+ {
+ "loc": [
+ -4.5,
+ 93,
+ 1.5
+ ],
+ "type": "interact"
+ }
+ ],
+ "tnts": []
+ },
+ {
+ "etherwarps": [],
+ "mines": [],
+ "locations": [
+ [
+ -5,
+ 92,
+ 2
+ ],
+ [
+ -8,
+ 92,
+ 2
+ ],
+ [
+ -11,
+ 92,
+ 1
+ ],
+ [
+ -11,
+ 96,
+ 1
+ ],
+ [
+ -11,
+ 97,
+ 1
+ ],
+ [
+ -13,
+ 96,
+ 1
+ ],
+ [
+ -13,
+ 97,
+ 1
+ ],
+ [
+ -13,
+ 96,
+ 1
+ ],
+ [
+ -13,
+ 92,
+ 1
+ ],
+ [
+ -13,
+ 92,
+ 2
+ ],
+ [
+ -13,
+ 92,
+ 1
+ ],
+ [
+ -13,
+ 93,
+ 1
+ ],
+ [
+ -13,
+ 92,
+ 1
+ ]
+ ],
+ "interacts": [
+ {
+ "loc": [
+ -16.5,
+ 92,
+ 0.5
+ ],
+ "type": "interact"
+ }
+ ],
+ "tnts": []
+ },
+ {
+ "etherwarps": [
+ [
+ -6.5,
+ 91,
+ 8.5
+ ]
+ ],
+ "mines": [],
+ "locations": [
+ [
+ -13,
+ 92,
+ 1
+ ],
+ [
+ -13,
+ 93,
+ 1
+ ],
+ [
+ -13,
+ 93,
+ 2
+ ],
+ [
+ -14,
+ 92,
+ 2
+ ],
+ [
+ -15,
+ 92,
+ 2
+ ],
+ [
+ -16,
+ 92,
+ 2
+ ],
+ [
+ -18,
+ 92,
+ 3
+ ],
+ [
+ -18,
+ 92,
+ 4
+ ],
+ [
+ -18,
+ 92,
+ 5
+ ],
+ [
+ -18,
+ 93,
+ 5
+ ],
+ [
+ -18,
+ 94,
+ 5
+ ],
+ [
+ -18,
+ 93,
+ 8
+ ],
+ [
+ -18,
+ 92,
+ 9
+ ],
+ [
+ -18,
+ 90,
+ 10
+ ],
+ [
+ -18,
+ 87,
+ 11
+ ],
+ [
+ -18,
+ 84,
+ 11
+ ],
+ [
+ -18,
+ 83,
+ 11
+ ],
+ [
+ -7,
+ 91,
+ 9
+ ],
+ [
+ -8,
+ 91,
+ 8
+ ],
+ [
+ -8,
+ 93,
+ 8
+ ],
+ [
+ -8,
+ 92,
+ 8
+ ],
+ [
+ -10,
+ 92,
+ 10
+ ],
+ [
+ -10,
+ 90,
+ 10
+ ],
+ [
+ -10,
+ 87,
+ 11
+ ],
+ [
+ -8,
+ 86,
+ 11
+ ],
+ [
+ -7,
+ 85,
+ 12
+ ],
+ [
+ -7,
+ 83,
+ 12
+ ],
+ [
+ -5,
+ 83,
+ 10
+ ],
+ [
+ -1,
+ 83,
+ 11
+ ],
+ [
+ 3,
+ 83,
+ 12
+ ],
+ [
+ 7,
+ 83,
+ 12
+ ],
+ [
+ 9,
+ 82,
+ 12
+ ],
+ [
+ 11,
+ 80,
+ 13
+ ],
+ [
+ 12,
+ 77,
+ 13
+ ],
+ [
+ 13,
+ 73,
+ 14
+ ],
+ [
+ 14,
+ 68,
+ 14
+ ],
+ [
+ 15,
+ 62,
+ 15
+ ],
+ [
+ 15,
+ 55,
+ 15
+ ],
+ [
+ 15,
+ 48,
+ 16
+ ],
+ [
+ 13,
+ 46,
+ 16
+ ],
+ [
+ 10,
+ 46,
+ 17
+ ],
+ [
+ 7,
+ 46,
+ 17
+ ],
+ [
+ 3,
+ 46,
+ 17
+ ],
+ [
+ -1,
+ 46,
+ 16
+ ],
+ [
+ -6,
+ 46,
+ 16
+ ],
+ [
+ -9,
+ 45,
+ 15
+ ],
+ [
+ -12,
+ 45,
+ 14
+ ],
+ [
+ -17,
+ 47,
+ 13
+ ],
+ [
+ -20,
+ 48,
+ 11
+ ],
+ [
+ -23,
+ 48,
+ 10
+ ],
+ [
+ -24,
+ 49,
+ 10
+ ],
+ [
+ -24,
+ 48,
+ 10
+ ],
+ [
+ -24,
+ 47,
+ 10
+ ],
+ [
+ -25,
+ 48,
+ 10
+ ],
+ [
+ -25,
+ 47,
+ 10
+ ],
+ [
+ -25,
+ 36,
+ 10
+ ],
+ [
+ -25,
+ 35,
+ 10
+ ],
+ [
+ -25,
+ 34,
+ 10
+ ],
+ [
+ -25,
+ 33,
+ 10
+ ],
+ [
+ -14,
+ 29,
+ 10
+ ],
+ [
+ -14,
+ 28,
+ 10
+ ]
+ ],
+ "interacts": [
+ {
+ "loc": [
+ -9.5,
+ 28,
+ 9.5
+ ],
+ "type": "interact"
+ }
+ ],
+ "tnts": []
+ },
+ {
+ "etherwarps": [],
+ "mines": [],
+ "locations": [
+ [
+ -14,
+ 28,
+ 10
+ ],
+ [
+ -25,
+ 34,
+ 10
+ ],
+ [
+ -25,
+ 35,
+ 10
+ ],
+ [
+ -25,
+ 36,
+ 10
+ ],
+ [
+ -25,
+ 47,
+ 10
+ ],
+ [
+ -25,
+ 48,
+ 10
+ ],
+ [
+ -24,
+ 48,
+ 10
+ ],
+ [
+ -24,
+ 49,
+ 10
+ ],
+ [
+ -23,
+ 48,
+ 10
+ ],
+ [
+ -21,
+ 48,
+ 10
+ ],
+ [
+ -20,
+ 47,
+ 10
+ ],
+ [
+ -19,
+ 47,
+ 11
+ ],
+ [
+ -20,
+ 47,
+ 10
+ ],
+ [
+ -20,
+ 47,
+ 9
+ ],
+ [
+ -14,
+ 48,
+ 1
+ ],
+ [
+ -13,
+ 48,
+ 0
+ ],
+ [
+ -14,
+ 49,
+ -3
+ ],
+ [
+ -15,
+ 49,
+ -7
+ ],
+ [
+ -15,
+ 49,
+ -11
+ ],
+ [
+ -14,
+ 49,
+ -15
+ ],
+ [
+ -13,
+ 49,
+ -19
+ ],
+ [
+ -13,
+ 49,
+ -23
+ ],
+ [
+ -13,
+ 50,
+ -24
+ ],
+ [
+ -13,
+ 50,
+ -26
+ ],
+ [
+ -13,
+ 50,
+ -28
+ ],
+ [
+ -11,
+ 50,
+ -27
+ ],
+ [
+ -9,
+ 50,
+ -27
+ ]
+ ],
+ "interacts": [
+ {
+ "loc": [
+ -3.5,
+ 50,
+ -26.5
+ ],
+ "type": "interact"
+ }
+ ],
+ "tnts": []
+ },
+ {
+ "etherwarps": [],
+ "mines": [],
+ "locations": [
+ [
+ -9,
+ 50,
+ -27
+ ],
+ [
+ -10,
+ 50,
+ -28
+ ],
+ [
+ -11,
+ 50,
+ -29
+ ],
+ [
+ -13,
+ 50,
+ -26
+ ],
+ [
+ -13,
+ 50,
+ -24
+ ],
+ [
+ -14,
+ 50,
+ -22
+ ],
+ [
+ -16,
+ 50,
+ -20
+ ],
+ [
+ -18,
+ 49,
+ -19
+ ],
+ [
+ -21,
+ 50,
+ -16
+ ],
+ [
+ -23,
+ 52,
+ -14
+ ],
+ [
+ -25,
+ 53,
+ -10
+ ],
+ [
+ -26,
+ 55,
+ -8
+ ],
+ [
+ -26,
+ 55,
+ -5
+ ],
+ [
+ -26,
+ 55,
+ -3
+ ],
+ [
+ -24,
+ 55,
+ -3
+ ],
+ [
+ -20,
+ 55,
+ -3
+ ],
+ [
+ -17,
+ 55,
+ -2
+ ],
+ [
+ -13,
+ 55,
+ -2
+ ],
+ [
+ -10,
+ 55,
+ -3
+ ],
+ [
+ -9,
+ 55,
+ -2
+ ],
+ [
+ -9,
+ 67,
+ -7
+ ],
+ [
+ -9,
+ 66,
+ -7
+ ],
+ [
+ -9,
+ 68,
+ -9
+ ],
+ [
+ -9,
+ 69,
+ -12
+ ],
+ [
+ -10,
+ 69,
+ -16
+ ],
+ [
+ -14,
+ 69,
+ -17
+ ],
+ [
+ -16,
+ 69,
+ -17
+ ],
+ [
+ -17,
+ 69,
+ -17
+ ],
+ [
+ -18,
+ 69,
+ -16
+ ]
+ ],
+ "interacts": [],
+ "tnts": []
+ }
+ ]
+ },
+ {
+ "index": 12,
+ "data": [
+ {
+ "etherwarps": [
+ [
+ 2.5,
+ 80,
+ -1.5
+ ]
+ ],
+ "mines": [
+ [
+ 1.5,
+ 83.5,
+ -0.5
+ ]
+ ],
+ "locations": [
+ [
+ -7,
+ 69,
+ 3
+ ],
+ [
+ -6,
+ 69,
+ 3
+ ],
+ [
+ -3,
+ 69,
+ 0
+ ],
+ [
+ -1,
+ 69,
+ -2
+ ],
+ [
+ 0,
+ 69,
+ -4
+ ],
+ [
+ 1,
+ 69,
+ -5
+ ],
+ [
+ 3,
+ 69,
+ -7
+ ],
+ [
+ 3,
+ 69,
+ -10
+ ],
+ [
+ 5,
+ 69,
+ -12
+ ],
+ [
+ 8,
+ 69,
+ -12
+ ],
+ [
+ 11,
+ 69,
+ -10
+ ],
+ [
+ 11,
+ 69,
+ -8
+ ],
+ [
+ 11,
+ 69,
+ -9
+ ],
+ [
+ 10,
+ 69,
+ -12
+ ],
+ [
+ 7,
+ 69,
+ -12
+ ],
+ [
+ 3,
+ 69,
+ -11
+ ],
+ [
+ 2,
+ 69,
+ -8
+ ],
+ [
+ 1,
+ 69,
+ -4
+ ],
+ [
+ 1,
+ 69,
+ -3
+ ],
+ [
+ 2,
+ 69,
+ -3
+ ],
+ [
+ 2,
+ 80,
+ -1
+ ],
+ [
+ 1,
+ 80,
+ 0
+ ],
+ [
+ 1,
+ 80,
+ 1
+ ],
+ [
+ 1,
+ 80,
+ 0
+ ],
+ [
+ 1,
+ 80,
+ 1
+ ],
+ [
+ 0,
+ 80,
+ 3
+ ],
+ [
+ -1,
+ 78,
+ 5
+ ],
+ [
+ -2,
+ 76,
+ 5
+ ],
+ [
+ -3,
+ 75,
+ 5
+ ],
+ [
+ -4,
+ 73,
+ 5
+ ],
+ [
+ -4,
+ 70,
+ 5
+ ],
+ [
+ -5,
+ 69,
+ 5
+ ]
+ ],
+ "interacts": [],
+ "tnts": [
+ [
+ 3.5,
+ 70.5,
+ -7.5
+ ]
+ ]
+ }
+ ]
+ }
+]
\ No newline at end of file
diff --git a/src/features/dungeonSolvers/f7data.json b/src/features/dungeonSolvers/f7data.json
new file mode 100644
index 0000000..72e3ec6
--- /dev/null
+++ b/src/features/dungeonSolvers/f7data.json
@@ -0,0 +1,263 @@
+[
+ {
+ "type": "device",
+ "location": [
+ 110,
+ 118,
+ 91
+ ],
+ "phase": 0
+ },
+ {
+ "type": "terminal",
+ "location": [
+ 110,
+ 112,
+ 73
+ ],
+ "phase": 0
+ },
+ {
+ "type": "terminal",
+ "location": [
+ 110,
+ 118,
+ 79
+ ],
+ "phase": 0
+ },
+ {
+ "type": "terminal",
+ "location": [
+ 90,
+ 111,
+ 92
+ ],
+ "phase": 0
+ },
+ {
+ "type": "terminal",
+ "location": [
+ 90,
+ 121,
+ 101
+ ],
+ "phase": 0
+ },
+ {
+ "type": "lever",
+ "location": [
+ 106,
+ 124,
+ 113
+ ],
+ "phase": 0
+ },
+ {
+ "type": "lever",
+ "location": [
+ 94,
+ 124,
+ 113
+ ],
+ "phase": 0
+ },
+ {
+ "type": "terminal",
+ "location": [
+ 68,
+ 108,
+ 122
+ ],
+ "phase": 1
+ },
+ {
+ "type": "terminal",
+ "location": [
+ 59,
+ 119,
+ 123
+ ],
+ "phase": 1
+ },
+ {
+ "type": "device",
+ "location": [
+ 60,
+ 131,
+ 142
+ ],
+ "phase": 1
+ },
+ {
+ "type": "terminal",
+ "location": [
+ 47,
+ 108,
+ 122
+ ],
+ "phase": 1
+ },
+ {
+ "type": "lever",
+ "location": [
+ 27,
+ 124,
+ 127
+ ],
+ "phase": 1
+ },
+ {
+ "type": "terminal",
+ "location": [
+ 40,
+ 123,
+ 123
+ ],
+ "phase": 1
+ },
+ {
+ "type": "terminal",
+ "location": [
+ 39,
+ 107,
+ 142
+ ],
+ "phase": 1
+ },
+ {
+ "type": "lever",
+ "location": [
+ 23,
+ 132,
+ 138
+ ],
+ "phase": 1
+ },
+ {
+ "type": "terminal",
+ "location": [
+ -1,
+ 108,
+ 112
+ ],
+ "phase": 2
+ },
+ {
+ "type": "terminal",
+ "location": [
+ 18,
+ 122,
+ 93
+ ],
+ "phase": 2
+ },
+ {
+ "type": "terminal",
+ "location": [
+ -1,
+ 118,
+ 93
+ ],
+ "phase": 2
+ },
+ {
+ "type": "terminal",
+ "location": [
+ -1,
+ 108,
+ 77
+ ],
+ "phase": 2
+ },
+ {
+ "type": "device",
+ "location": [
+ -3,
+ 120,
+ 77
+ ],
+ "phase": 2
+ },
+ {
+ "type": "lever",
+ "location": [
+ 14,
+ 122,
+ 55
+ ],
+ "phase": 2
+ },
+ {
+ "type": "lever",
+ "location": [
+ 2,
+ 122,
+ 55
+ ],
+ "phase": 2
+ },
+ {
+ "type": "terminal",
+ "location": [
+ 44,
+ 120,
+ 30
+ ],
+ "phase": 3
+ },
+ {
+ "type": "device",
+ "location": [
+ 63,
+ 126,
+ 34
+ ],
+ "phase": 3
+ },
+ {
+ "type": "terminal",
+ "location": [
+ 72,
+ 114,
+ 47
+ ],
+ "phase": 3
+ },
+ {
+ "type": "lever",
+ "location": [
+ 86,
+ 128,
+ 46
+ ],
+ "phase": 3
+ },
+ {
+ "type": "lever",
+ "location": [
+ 84,
+ 121,
+ 34
+ ],
+ "phase": 3
+ },
+ {
+ "type": "terminal",
+ "location": [
+ 41,
+ 108,
+ 30
+ ],
+ "phase": 3
+ },
+ {
+ "type": "terminal",
+ "location": [
+ 67,
+ 108,
+ 30
+ ],
+ "phase": 3
+ }
+]
\ No newline at end of file
diff --git a/src/features/dungeonSolvers/index.js b/src/features/dungeonSolvers/index.js
new file mode 100644
index 0000000..a959a66
--- /dev/null
+++ b/src/features/dungeonSolvers/index.js
@@ -0,0 +1,1270 @@
+///
+///
+import { f, m } from "../../../mappings/mappings";
+import Feature from "../../featureClass/class";
+import { addNotation, numberWithCommas } from "../../utils/numberUtils";
+import * as renderUtils from "../../utils/renderUtils";
+import HudTextElement from "../hud/HudTextElement";
+import LocationSetting from "../settings/settingThings/location";
+import ToggleSetting from "../settings/settingThings/toggle";
+import TextSetting from "../settings/settingThings/textSetting";
+import { fetch } from "../../utils/networkUtils";
+import { delay } from "../../utils/delayUtils";
+import { Waypoint } from "../../utils/renderJavaUtils";
+import { calculateDistanceQuick } from "../../utils/utils";
+import { drawLinePoints } from "../../utils/renderUtils";
+
+const entityGuardian = Java.type("net.minecraft.entity.monster.EntityGuardian")
+
+const MCBlock = Java.type("net.minecraft.block.Block");
+const EntityBlaze = Java.type("net.minecraft.entity.monster.EntityBlaze");
+let translate;
+try {
+ translate = net.minecraft.util.StringTranslate.func_74808_a();
+} catch (e) {
+ //player doesent have translate (using english default)
+}
+let wrongColorList = {
+ "light grey": "silver",
+ "wool": "white wool",
+ "ink": "black ink",
+ "lapis": "blue lapis",
+ "cocoa": "brown cocoa"
+}
+
+class DungeonSolvers extends Feature {
+ constructor() {
+ super();
+ }
+
+ isInDungeon() {
+ if (!this.FeatureManager || !this.FeatureManager.features["dataLoader"]) return false
+ return this.FeatureManager.features["dataLoader"].class.isInDungeon
+ }
+
+ onEnable() {
+ this.initVariables();
+
+ this.lividData = {};
+ this.lividData.lividColor = {
+ Vendetta: "&f",
+ Crossed: "&d",
+ Hockey: "&c",
+ Doctor: "&7",
+ Frog: "&2",
+ Smile: "&a",
+ Scream: "&9",
+ Purple: "&5",
+ Arcade: "&e",
+ };
+
+ this.bonzoMaskTimer = 0;
+ this.fraggedBonzoMaskTimer = 0;
+ this.spiritMaskTimer = 0;
+ this.eraseBonzoTimer = true;
+ this.bonzoMaskCooldown = 0;
+
+ this.lastWorldload = Date.now()
+ this.lividFindEnabled = new ToggleSetting("Correct livid finder", "Finds the real livid to kill in the f5 boss fight", true, "livid_find_enabled", this);
+ this.lividFindHud = new ToggleSetting("Show Livid Hp", "Shows the nametag of the correct livid", true, "livid_hud_enabled", this).requires(this.lividFindEnabled);
+ this.lividHpElement = new HudTextElement().setToggleSetting(this.lividFindHud).setLocationSetting(new LocationSetting("Correct Livid Hp Location", "Allows you to edit the location of the correct livid hp text", "livid_hp_location", this, [10, 50, 1, 1]).requires(this.lividFindHud).editTempText("§r§e﴾ §c§lLivid§r §a7M§c❤ §e﴿§r"));
+
+ this.hudElements.push(this.lividHpElement);
+
+ this.lividFindBox = new ToggleSetting("Put a box around the correct livid", "This helps to locate it in the group", true, "livid_box_enabled", this).requires(this.lividFindEnabled);
+ this.lividFindNametags = new ToggleSetting("Hide the nametags of incorrect livids", "This helps to locate it in the group", true, "livid_nametags_enabled", this).requires(this.lividFindEnabled);
+
+ this.spiritBowDestroyTimer = new ToggleSetting("Timer for when the spirit bow will self destruct", "", true, "spirit_bow_destroy_timer", this);
+ this.spiritBowDestroyElement = new HudTextElement().setToggleSetting(this.spiritBowDestroyTimer).setLocationSetting(new LocationSetting("Spirit bow destroy timer location", "Allows you to edit the location of the timer", "spirit_destroy_location", this, [10, 70, 3, 1]).requires(this.spiritBowDestroyTimer).editTempText("&dBow Destroyed in: &c15s"));
+
+ this.spiritBearSpawnTimer = new ToggleSetting("Timer for when the spirit bear will spawn", "", true, "spirit_bear_spawn_timer", this);
+ this.spiritBearSpawnElement = new HudTextElement().setToggleSetting(this.spiritBearSpawnTimer).setLocationSetting(new LocationSetting("Spirit bear spawn timer location", "Allows you to edit the location of the timer", "spirit_bear_spawn_location", this, [10, 70, 3, 1]).requires(this.spiritBearSpawnTimer).editTempText("&dBear spawned in: &c1.57s"));
+
+ this.fireFreezeTimer = new ToggleSetting("Timer for when to fire freeze in m3/f3", "", true, "ff_timer", this);
+ this.fireFreezeTimerElement = new HudTextElement().setToggleSetting(this.fireFreezeTimer).setLocationSetting(new LocationSetting("Fire freeze timer location", "Allows you to edit the location of the timer", "fire_freeze_location", this, [10, 80, 3, 1]).requires(this.fireFreezeTimer).editTempText("&dFire freeze in: &c1.57s"));
+
+ this.hudElements.push(this.spiritBearSpawnElement);
+ this.hudElements.push(this.fireFreezeTimerElement);
+ this.hudElements.push(this.spiritBowDestroyElement);
+
+ this.bloodCampAssist = new ToggleSetting("Assist blood camp", "Helps guess where and when blood mobs will spawn", true, "blood_camp_assist", this);
+
+ this.runSpeedRates = new ToggleSetting("Show run speed and exp rates", "(Run speed includes downtime inbetween runs, only shows while doing dungeon runs)", true, "run_speed_rates", this);
+ this.runSpeedRatesElement = new HudTextElement()
+ .setText("&6Run speed&7> &fLoading...\n&6Exp/hour&7> &fLoading...\n&6Runs/hour&7> &fLoading...")
+ .setToggleSetting(this.runSpeedRates)
+ .setLocationSetting(new LocationSetting("Run speed and exp rates location", "Allows you to edit the location of the information", "run_speed_rates_location", this, [10, 100, 1, 1]).requires(this.runSpeedRates).editTempText("&6Run speed&7> &f4:30\n&6Exp/hour&7> &f1,234,567\n&6Runs/hour&7> &f17"));
+
+ this.scoreCalculation = new ToggleSetting("Show score calculation", "", true, "run_score_calc", this);
+ this.scoreElement = new HudTextElement().setToggleSetting(this.scoreCalculation).setLocationSetting(new LocationSetting("Score calculation location", "Allows you to edit the location of the score calc", "score_calc_location", this, [10, 130, 1, 1]).requires(this.scoreCalculation).editTempText("&dScore: 120\n&aS+ ??\n&aS ??"));
+
+ this.hudElements.push(this.runSpeedRatesElement);
+ this.hudElements.push(this.scoreElement);
+
+ this.blazeSolver = new ToggleSetting("Blaze Puzzle Solver", "Shows what order to kill the blazes in", true, "blaze_solver", this);
+ this.respawnTimerTerra = new ToggleSetting("Terracotter respawn timer", "", true, "f6_timer_thing", this);
+
+ this.lastDungFinishes = [];
+ this.lastDungExps = [];
+ this.registerChat("${start}+&r&3${exp} Catacombs Experience&r", (start, exp) => {
+ if (ChatLib.removeFormatting(start).replace(/ /gi, "").length > 0) return;
+ this.lastDungExps.push(parseFloat(exp.replace(/,/gi, "")));
+ if (this.lastDungExps.length > 5) {
+ this.lastDungExps.shift();
+ }
+
+ this.lastDungFinishes.push(Date.now());
+ if (this.lastDungFinishes.length > 5) {
+ this.lastDungFinishes.shift();
+ }
+
+ this.bonzoMaskTimer = 0;
+ this.fraggedBonzoMaskTimer = 0;
+ this.spiritMaskTimer = 0;
+ this.eraseBonzoTimer = true;
+ });
+ this.registerStep(false, 30, this.getBonzoMaskCooldown);
+ this.bonzoSpiritMaskTimer = new ToggleSetting("Timer for when bonzo/spirit mask will be ready", "works for both bonzo masks, hides bonzo masks' timers after you leave the run", false, "bonzo_mask_timer", this);
+ this.bonzoSpiritMaskTimerElement = new HudTextElement().setToggleSetting(this.bonzoSpiritMaskTimer).setLocationSetting(new LocationSetting("Bonzo/Spirit Mask timer location", "Allows you to edit the location of the timer", "bonzo_mask_timer_location", this, [10, 100, 1, 1]).requires(this.bonzoSpiritMaskTimer).editTempText("&9Bonzo's Mask: &c157s"));
+ this.hudElements.push(this.bonzoSpiritMaskTimerElement);
+ this.spiritMaskOutsideDungeon = new ToggleSetting("Spirit Mask Timer Outside Dungeons", "should spirit mask timer be shown outside dungeon?", false, "spirit_mask_timer", this).requires(this.bonzoSpiritMaskTimer);
+
+ this.normalBonzoMask = new ToggleSetting("Bonzo Mask Proc'ed Alert", "Enable this to change the message", true, "bonzo_mask_alert", this).requires(this.bonzoSpiritMaskTimer);
+ this.normalBonzoMaskMessage = new TextSetting("Bonzo Mask Proc'ed Message", "change bonzo mask proc message here", "&cBonzo Mask Used", "bonzo_mask_alert_message", this, "&cBonzo Mask Used", false).requires(this.normalBonzoMask);
+ this.fraggedBonzoMask = new ToggleSetting("⚚ Bonzo Mask Proc'ed Alert", "Enable this to change the message", true, "fragged_bonzo_mask_alert", this).requires(this.bonzoSpiritMaskTimer);
+ this.fraggedBonzoMaskMessage = new TextSetting("⚚ Bonzo Mask Proc'ed Message", "change bonzo mask proc message here", "&c⚚ Bonzo Mask Used", "fragged_bonzo_mask_alert_message", this, "&c⚚ Bonzo Mask Used", false).requires(this.fraggedBonzoMask);
+ this.spiritMask = new ToggleSetting("Spirit Mask Proc'ed Alert", "Enable this to change the message", true, "spirit_mask_alert", this).requires(this.bonzoSpiritMaskTimer);
+ this.spiritMaskMessage = new TextSetting("Spirit Mask Proc'ed Message", "change spirit mask proc message here", "&cSpirit Mask Used", "spirit_mask_alert_message", this, "&cSpirit Mask Used", false).requires(this.spiritMask);
+
+ this.registerChat("&r&aYour &r&9Bonzo's Mask &r&asaved your life!&r", () => {
+ this.eraseBonzoTimer = false;
+ if (this.bonzoSpiritMaskTimer.getValue()) {
+ this.bonzoMaskTimer = Date.now() + this.bonzoMaskCooldown * 1000;
+ }
+ if (this.normalBonzoMask.getValue()) {
+ let m = this.normalBonzoMaskMessage.getValue()
+ Client.showTitle(m ? m : "&cBonzo Mask Used", "", 0, 60, 10)
+ }
+ })
+
+ this.registerChat("&r&aYour &r&9⚚ Bonzo's Mask &r&asaved your life!&r", () => {
+ this.eraseBonzoTimer = false;
+ if (this.bonzoSpiritMaskTimer.getValue()) {
+ this.fraggedBonzoMaskTimer = Date.now() + this.bonzoMaskCooldown * 1000;
+ }
+ if (this.fraggedBonzoMask.getValue()) {
+ let m = this.fraggedBonzoMaskMessage.getValue()
+ Client.showTitle(m ? m : "&c⚚ Bonzo Mask Used", "", 0, 60, 10)
+ }
+ })
+
+ this.registerChat("&r&6Second Wind Activated&r&a! &r&aYour Spirit Mask saved your life!&r", () => {
+ if (this.bonzoSpiritMaskTimer.getValue()) {
+ if (this.spiritMaskOutsideDungeon.getValue() ? true : !this.eraseBonzoTimer) {
+ this.spiritMaskTimer = Date.now() + 30 * 1000;
+ }
+ }
+ if (this.fraggedBonzoMask.getValue()) {
+ let m = this.spiritMaskMessage.getValue()
+ Client.showTitle((m ? m : "&cSpirit Mask Used"), "", 0, 60, 10)
+ }
+ })
+
+ this.registerStep(true, 10, () => {
+ if (!this.bonzoSpiritMaskTimer.getValue()) return
+ let timerText = ""
+ if (this.spiritMaskOutsideDungeon.getValue() ? true : !this.eraseBonzoTimer) {
+ if (this.spiritMask.getValue()) {
+ let timer1 = Math.round((this.spiritMaskTimer - Date.now()) / 100) / 10
+ timerText += "&5Spirit Mask: " + (timer1 > 0 ? "&c" + timer1 + "&6s" : "&6READY") + "\n"
+ }
+ }
+ if (!this.eraseBonzoTimer) {
+ if (this.normalBonzoMask.getValue()) {
+ let timer2 = Math.round((this.bonzoMaskTimer - Date.now()) / 100) / 10
+ timerText += "&9Bonzo's Mask: " + (timer2 > 0 ? "&c" + timer2 + "&6s" : "&6READY") + "\n"
+ }
+ if (this.fraggedBonzoMask.getValue()) {
+ let timer3 = Math.round((this.fraggedBonzoMaskTimer - Date.now()) / 100) / 10
+ timerText += "&9⚚ Bonzo's Mask: " + (timer3 > 0 ? "&c" + timer3 + "&6s" : "&6READY")
+ }
+ }
+ this.bonzoSpiritMaskTimerElement.setText(timerText)
+ })
+ this.forgorEnabled = new ToggleSetting("Change withermancer death message to forgor ", "", true, "withermancer_forgor", this);
+ this.f7waypoints = new ToggleSetting("Waypoints for P3 F7/M7", "(Only shows unfinished ones)", true, "f7_waypoints", this);
+
+ this.IceSprayWarn = new ToggleSetting("Ice Spray Drop Ping", "Renders a big title so you don't miss ice spray wands", false, "ice_spray_ping", this).contributor("EmeraldMerchant");
+
+ this.guardianHp = new ToggleSetting("m3/f3 guardian hp", "", true, "guardian_hp", this);
+
+ this.registerChat("&r&c ☠ &r${player} were killed by Withermancer&r&7 and became a ghost&r&7.&r", (player, e) => {
+ if (this.forgorEnabled.getValue()) {
+ cancel(e);
+ ChatLib.chat(player + " forgor ☠");
+ }
+ });
+ this.registerChat("&r&c ☠ &r${player} was killed by Withermancer&r&7 and became a ghost&r&7.&r", (player, e) => {
+ if (this.forgorEnabled.getValue()) {
+ cancel(e);
+ ChatLib.chat(player + " forgor ☠");
+ }
+ });
+
+ this.registerChat("&r&c ☠ ${info} and became a ghost&r&7.&r", (info, e) => {
+ let player = ChatLib.removeFormatting(info.split(" ")[0])
+
+ this.scanFirstDeathForSpiritPet(player)
+ });
+
+ this.spiritBowPickUps = [];
+ this.registerChat("&r&aYou picked up the &r&5Spirit Bow&r&a! Use it to attack &r&cThorn&r&a!&r", () => {
+ this.spiritBowPickUps.push(Date.now());
+ });
+
+ this.bearSpawning = 0;
+ this.registerChat("&r&a&lThe &r&5&lSpirit Bow &r&a&lhas dropped!&r", () => {
+ this.bearSpawning = -Date.now();
+ });
+
+ this.todoE = [];
+ this.eMovingThing = {};
+ this.nameToUuid = {
+ "you": Player.getUUID().toString()
+ }
+ this.bloodX = -1;
+ this.bloodY = -1;
+ this.startSpawningTime = 0;
+ this.spawnIdThing = 0;
+
+ this.failedPuzzleCount = 0;
+ this.totalPuzzleCount = 0;
+ this.completedPuzzleCount = 0;
+
+ this.ezpz = false
+
+ this.arrows = [];
+ this.blazes = [];
+ this.blazeX = -1;
+ this.blazeY = -1;
+ this.timersData = []
+
+ this.dungeonSecretRquired = {
+ 1: 0.3,
+ 2: 0.4,
+ 3: 0.5,
+ 4: 0.6,
+ 5: 0.7,
+ 6: 0.85,
+ 7: 1,
+ };
+ this.floorSecondMod = {
+ 1: 120,
+ 2: 120,
+ 3: 120,
+ 4: 120,
+ 5: 240,
+ 6: 120,
+ 7: 360,
+ };
+ this.renderEntityEvent = this.registerEvent("renderEntity", this.renderEntity);
+
+ this.registerStep(true, 2, this.stepNotDung).registeredWhen(() => !this.isInDungeon());
+ this.registerStep(true, 2, this.step).registeredWhen(() => this.isInDungeon());
+ this.registerStep(false, 60, this.step)
+ this.registerStep(true, 10, this.step2).registeredWhen(() => this.isInDungeon());
+ this.registerStep(true, 1, this.step_1fps).registeredWhen(() => this.isInDungeon());
+ this.registerStep(false, 60 * 5, this.step_5min)
+ this.registerEvent("worldLoad", this.onWorldLoad);
+
+ this.registerEvent("renderWorld", this.renderWorld).registeredWhen(() => this.isInDungeon());
+
+ this.bloodOpenedBonus = false;
+ this.goneInBonus = false;
+ this.mimicDead = false
+ this.inBoss = false
+ this.registerChat("&r&cThe &r&c&lBLOOD DOOR&r&c has been opened!&r", () => {
+ this.bloodOpenedBonus = true;
+ this.goneInBonus = true;
+ });
+ this.registerChat("[BOSS] The Watcher: You have proven yourself. You may pass.", () => {
+ delay(5000, () => {
+ this.bloodOpenedBonus = false;
+ this.goneInBonus = true;
+ })
+ });
+ let enteredBossMessages = ["[BOSS] Maxor: WELL WELL WELL LOOK WHO’S HERE!", "[BOSS] Livid: Welcome, you arrive right on time. I am Livid, the Master of Shadows.", "[BOSS] Thorn: Welcome Adventurers! I am Thorn, the Spirit! And host of the Vegan Trials!", "[BOSS] The Professor: I was burdened with terrible news recently...", "[BOSS] Scarf: This is where the journey ends for you, Adventurers.", "[BOSS] Bonzo: Gratz for making it this far, but I’m basically unbeatable.", "[BOSS] Sadan: So you made it all the way here...and you wish to defy me? Sadan?!"]
+ enteredBossMessages.forEach(msg => {
+ this.registerChat(msg, () => {
+ this.goneInBonus = false;
+ this.bloodOpenedBonus = false;
+ this.inBoss = true
+ });
+ })
+ this.registerEvent("entityDeath", (entity) => {
+ if (entity.getClassName() === "EntityZombie") {
+ if (entity.getEntity().func_70631_g_()) {
+ if (entity.getEntity().func_82169_q(0) === null && entity.getEntity().func_82169_q(1) === null && entity.getEntity().func_82169_q(2) === null && entity.getEntity().func_82169_q(3) === null) {
+ this.mimicDead = true
+ }
+ }
+ }
+ })
+ let mimicDeadMessages = ["$SKYTILS-DUNGEON-SCORE-MIMIC$", "Mimic Killed!", "Mimic Dead!", "Mimic dead!"]
+ this.registerChat("&r&9Party &8> ${msg}", (msg) => {
+ mimicDeadMessages.forEach(dmsg => {
+ if (msg.includes(dmsg)) this.mimicDead = true
+ })
+ })
+
+ this.registerChat("&r&aDungeon starts in 1 second.&r", () => {
+ this.goneInBonus = false;
+ this.bloodOpenedBonus = false;
+
+ this.firstDeath = false
+ this.firstDeathHadSpirit = false
+ })
+
+ this.registerChat("&r&aDungeon starts in 1 second. Get ready!&r", () => {
+ this.goneInBonus = false;
+ this.bloodOpenedBonus = false;
+
+ this.firstDeath = false
+ this.firstDeathHadSpirit = false
+ })
+
+ this.firstDeath = false
+ this.firstDeathHadSpirit = false
+
+
+ this.registerForge(net.minecraftforge.event.entity.EntityJoinWorldEvent, this.entityJoinWorldEvent).registeredWhen(() => this.isInDungeon() && !this.inBoss);
+
+
+ this.onWorldLoad();
+
+ this.registerEvent("tick", () => {
+ this.terminals.forEach(w => w.update())
+ this.levers.forEach(w => w.update())
+ this.devices.forEach(w => w.update())
+ }).registeredWhen(() => this.f7waypoints.getValue())
+ this.terminals = []
+ this.levers = []
+ this.devices = []
+ this.data = []
+ this.area = -1
+ this.registerChat("[BOSS] Goldor: You have done it, you destroyed the factory…", () => {
+ this.area = -1
+ this.areaUpdated()
+ })
+ this.registerEvent("worldLoad", () => {
+ if (this.area !== -1) {
+ this.area = -1
+ this.areaUpdated()
+ }
+ })
+ this.registerChat("[BOSS] Goldor: Who dares trespass into my domain?", () => {
+ this.area = 0
+ this.areaUpdated()
+ })
+
+ this.loadf7data()
+
+ this.ffCountdownTo = 0
+ this.registerChat("[BOSS] The Professor: Oh? You found my Guardians one weakness?", () => {
+ this.ffCountdownTo = Date.now() + 5000
+
+ delay(5000, () => {
+ this.ffCountdownTo = 0
+ })
+ })
+
+ this.registerChat("${name} activated a lever! (${start}/${end})", (name, start, end) => {
+ let player = World.getPlayerByName(ChatLib.removeFormatting(name))
+
+ if (!player) return
+
+ let closestDist = calculateDistanceQuick([this.levers[0].params.x, this.levers[0].params.y, this.levers[0].params.z], [player.getX(), player.getY(), player.getZ()])
+ let closest = this.levers[0]
+ this.levers.forEach(l => {
+ if (!l.rendering) return
+ let dist = calculateDistanceQuick([l.params.x, l.params.y, l.params.z], [player.getX(), player.getY(), player.getZ()])
+ if (dist < closestDist) {
+ closestDist = dist
+ closest = l
+ }
+ })
+ closest.stopRender()
+
+
+ if (start == "0" || start == end) {
+ this.area++
+ this.areaUpdated()
+ }
+ }).registeredWhen(() => this.f7waypoints.getValue())
+
+ this.registerChat("${name} completed a device! (${start}/${end})", (name, start, end) => {
+
+ let closest = this.devices[0]
+
+ closest.stopRender()
+
+ if (start == "0" || start == end) {
+ this.area++
+ this.areaUpdated()
+ }
+ }).registeredWhen(() => this.f7waypoints.getValue())
+
+ this.registerChat("${name} activated a terminal! (${start}/${end})", (name, start, end) => {
+ let player = World.getPlayerByName(ChatLib.removeFormatting(name))
+
+ if (!player) return
+
+ let closestDist = calculateDistanceQuick([this.terminals[0].params.x, this.terminals[0].params.y, this.terminals[0].params.z], [player.getX(), player.getY(), player.getZ()])
+ let closest = this.terminals[0]
+ this.terminals.forEach(l => {
+ if (!l.rendering) return
+ let dist = calculateDistanceQuick([l.params.x, l.params.y, l.params.z], [player.getX(), player.getY(), player.getZ()])
+ if (dist < closestDist) {
+ closestDist = dist
+ closest = l
+ }
+ })
+ closest.stopRender()
+
+
+ if (start == "0" || start == end) {
+ this.area++
+ this.areaUpdated()
+ }
+ }).registeredWhen(() => this.f7waypoints.getValue())
+ //§r§6Soopyboo32§r§a activated a lever! (§r§c8§r§a/8)§r
+ //§r§6Soopyboo32§r§a completed a device! (§r§c3§r§a/8)§r
+ //§r§bBossmanLeo§r§a activated a terminal! (§r§c2§r§a/8)§r
+
+ this.inf6boss = false
+ this.registerStep(true, 1, () => {
+ this.inf6boss = this.getCurrentRoomId() === "sadan"
+ })
+
+ let packetRecieved = this.registerCustom("packetReceived", this.packetReceived).registeredWhen(() => this.inf6boss && this.respawnTimerTerra.getValue())
+
+ try {
+ packetRecieved.trigger.setPacketClasses([net.minecraft.network.play.server.S23PacketBlockChange, net.minecraft.network.play.server.S22PacketMultiBlockChange])
+ } catch (e) { }//older ct version
+
+ }
+ getBonzoMaskCooldown() {
+ [...Player.getInventory().getItems()].forEach(i => {
+ if (!i) return
+ let itemName = i.getName()
+ if (itemName.removeFormatting().includes("Bonzo's Mask")) {
+ i.getLore().forEach(line => {
+ if (line.includes("Cooldown:")) {
+ this.bonzoMaskCooldown = Number(line.removeFormatting().split("n: ")[1].replace("s", ""))
+ }
+ })
+ }
+ })
+ }
+ getCurrentRoomId() {
+ if (Scoreboard.getLines().length === 0) return
+ let id = ChatLib.removeFormatting(Scoreboard.getLineByIndex(Scoreboard.getLines().length - 1).getName()).trim().split(" ").pop()
+
+ return id
+ }
+ getBlockIdFromState(state) {
+ return MCBlock[m.getStateId](state)
+ }
+
+ packetReceived(packet, event) {
+ if (!this.inf6boss || !this.respawnTimerTerra.getValue()) return
+
+ let packetType = new String(packet.class.getSimpleName()).valueOf()
+ if (packetType === "S23PacketBlockChange") {
+ let position = new BlockPos(packet[m.getBlockPosition.S23PacketBlockChange]())
+ let blockState = this.getBlockIdFromState(packet[m.getBlockState.S23PacketBlockChange]())
+ let oldBlockState = this.getBlockIdFromState(World.getBlockStateAt(position))
+
+ if (oldBlockState === 0 && blockState === 4240 && this.inf6boss) {
+ this.timerThing(position)
+ }
+ }
+ if (packetType === "S22PacketMultiBlockChange") {
+ packet[m.getChangedBlocks]().forEach(b => {
+ let position = new BlockPos(b[m.getPos.S22PacketMultiBlockChange$BlockUpdateData]())
+ let blockState = this.getBlockIdFromState(b[m.getBlockState.S22PacketMultiBlockChange$BlockUpdateData]())
+ let oldBlockState = this.getBlockIdFromState(World.getBlockStateAt(position))
+
+ if (oldBlockState === 0 && blockState === 4240 && this.inf6boss) {
+ this.timerThing(position)
+ }
+ })
+ }
+ }
+
+ timerThing(position) {
+ this.timersData.push([position, Date.now() + (this.FeatureManager.features["dataLoader"].class.dungeonFloor[0] === "M" ? 3500 : 5000)])
+ }
+
+ areaUpdated() {
+ this.terminals.forEach(w => w.stopRender())
+ this.levers.forEach(w => w.stopRender())
+ this.devices.forEach(w => w.stopRender())
+
+ this.terminals = []
+ this.levers = []
+ this.devices = []
+
+ if (!this.f7waypoints.getValue()) return
+
+ this.data.forEach(term => {
+ if (term.phase !== this.area) return
+
+ if (term.type === "lever") {
+ this.levers.push(new Waypoint(term.location[0], term.location[1], term.location[2], 1, 0, 0, { name: "Lever" }).startRender())
+ }
+ if (term.type === "terminal") {
+ this.terminals.push(new Waypoint(term.location[0], term.location[1], term.location[2], 1, 0, 0, { name: "Terminal" }).startRender())
+ }
+ if (term.type === "device") {
+ this.devices.push(new Waypoint(term.location[0], term.location[1], term.location[2], 1, 0, 0, { name: "Device" }).startRender())
+ }
+ })
+ }
+
+ loadf7data() {
+ this.unloadf7data()
+
+ let data = FileLib.read("SoopyV2", "features/dungeonSolvers/f7data.json")
+ data = JSON.parse(data)
+
+ this.data = data
+ }
+
+ unloadf7data() {
+ this.terminals.forEach(w => w.stopRender())
+ this.levers.forEach(w => w.stopRender())
+ this.devices.forEach(w => w.stopRender())
+
+ this.terminals = []
+ this.levers = []
+ this.devices = []
+ this.data = []
+ this.area = 0
+ }
+
+ step_5min() {
+ this.ezpz = false
+ if (!this.FeatureManager.features["dataLoader"].class.mayorData) return
+ if (this.FeatureManager.features["dataLoader"].class.mayorData.mayor.name === "Paul") {
+ if (this.FeatureManager.features["dataLoader"].class.currentMayorPerks.has("EZPZ")) {
+ this.ezpz = true
+ }
+ }
+ }
+
+ calculateDungeonScore() {
+ if (!this.FeatureManager.features["dataLoader"].class.dungeonFloor) {
+ this.scoreElement.setText("");
+ return;
+ }
+
+ if (!this.FeatureManager.features["dataLoader"].class.stats.Deaths) return
+
+ // Information about the dungeon
+ let deaths = parseInt(this.FeatureManager.features["dataLoader"].class.stats.Deaths.replace("(", "").replace(")", ""));
+
+ let seconds = 0;
+ if (this.FeatureManager.features["dataLoader"].class.stats.Time !== "Soon!") {
+ let data = this.FeatureManager.features["dataLoader"].class.stats.Time.split(" ");
+ seconds += parseInt(data.pop() || 0);
+ seconds += parseInt(data.pop() || 0) * 60;
+ seconds += parseInt(data.pop() || 0) * 60 * 60;
+ }
+ let timeLimit = this.FeatureManager.features["dataLoader"].class.dungeonFloor[0] === "M" ? 480 : this.floorSecondMod[this.FeatureManager.features["dataLoader"].class.dungeonFloor[1]];
+ let inDungeonSeconds = seconds - timeLimit;
+
+ let clearedPercent = this.FeatureManager.features["dataLoader"].class.dungeonPercentCleared;
+
+ let dungeonFloor = this.FeatureManager.features["dataLoader"].class.dungeonFloor[1];
+
+ let secretPercentRequired = this.FeatureManager.features["dataLoader"].class.dungeonFloor[0] === "M" ? 1 : this.dungeonSecretRquired[dungeonFloor];
+
+ let clearedRooms = parseInt(this.FeatureManager.features["dataLoader"].class.stats["Completed Rooms"]);
+
+ let totalRooms = clearedRooms / clearedPercent || 25;
+
+ let currentSecretsFound = parseInt(this.FeatureManager.features["dataLoader"].class.stats["Secrets Found"]);
+ let currentSecretPercent = parseFloat(this.FeatureManager.features["dataLoader"].class.stats["Secrets Found%"].replace("%", "")) / 100;
+
+ let crypts = parseInt(this.FeatureManager.features["dataLoader"].class.stats["Crypts"]);
+
+ let maxSecrets = currentSecretsFound / currentSecretPercent || 50;
+
+ //Actual Score Calculation
+ let skillScore = Math.floor(Math.max(20, (20 - (this.totalPuzzleCount - this.completedPuzzleCount) * 10 + (((80 * (clearedRooms + this.bloodOpenedBonus + this.goneInBonus)) / totalRooms) - deaths * 2 + this.firstDeathHadSpirit))));
+ let exploreScore = (Math.floor((60 * (clearedRooms + this.bloodOpenedBonus + this.goneInBonus)) / totalRooms) + Math.floor(Math.min(40, (40 * currentSecretsFound) / secretPercentRequired / maxSecrets)));
+ let speedScore;
+ if (inDungeonSeconds < 480) {
+ speedScore = 100;
+ } else if (inDungeonSeconds < 600) {
+ speedScore = Math.ceil(140 - inDungeonSeconds / 12);
+ } else if (inDungeonSeconds < 840) {
+ speedScore = Math.ceil(115 - inDungeonSeconds / 24);
+ } else if (inDungeonSeconds < 1140) {
+ speedScore = Math.ceil(108 - inDungeonSeconds / 30);
+ } else if (inDungeonSeconds < 3940) {
+ speedScore = Math.ceil(98.5 - inDungeonSeconds / 40);
+ } else {
+ speedScore = 0;
+ }
+ let bonus = Math.min(5, crypts) + this.mimicDead * 2 + this.ezpz * 10;
+
+ //Calculating secrets for s/s+
+
+ let hypotheticalSkillScore = Math.floor(Math.max(20, (20 - (this.failedPuzzleCount) * 10 + 80 - deaths * 2 + this.firstDeathHadSpirit)));
+ let hypotheticalSpeedScore = speedScore
+
+ //Calculating for S
+ let hypotheticalBonusScoreS = Math.min(5, crypts) + this.mimicDead * 2 + this.ezpz * 10;
+
+ let sNeededSecrets = Math.min(maxSecrets * secretPercentRequired, Math.ceil((270 - hypotheticalSkillScore - hypotheticalBonusScoreS - hypotheticalSpeedScore - 60) * maxSecrets * secretPercentRequired / 40));
+
+ sNeededSecrets = Math.max(currentSecretsFound, sNeededSecrets)
+
+ let hypotheticalScoreGottenS = hypotheticalSkillScore + hypotheticalSpeedScore + hypotheticalBonusScoreS + 60 + Math.floor(Math.min(40, (40 * sNeededSecrets) / secretPercentRequired / maxSecrets));
+ let sCryptsNeeded = Math.max(crypts, Math.min(5, (270 - hypotheticalScoreGottenS)))
+ hypotheticalScoreGottenS -= hypotheticalBonusScoreS
+ hypotheticalBonusScoreS = sCryptsNeeded + this.mimicDead * 2 + this.ezpz * 10
+ hypotheticalScoreGottenS += hypotheticalBonusScoreS
+
+ let sPossible = hypotheticalScoreGottenS >= 270
+
+ //Calculating for S+
+ let hypotheticalBonusScoreSplus = 5 + this.mimicDead * 2 + this.ezpz * 10;
+
+ let splusNeededSecrets = Math.ceil((300 - hypotheticalSkillScore - hypotheticalBonusScoreSplus - hypotheticalSpeedScore - 60) * maxSecrets * secretPercentRequired / 40);
+
+ let splusPossible = splusNeededSecrets <= maxSecrets * secretPercentRequired
+
+ splusNeededSecrets = Math.max(currentSecretsFound, splusNeededSecrets)
+
+ let hypotheticalScoreGottenSPlus = hypotheticalSkillScore + hypotheticalSpeedScore + hypotheticalBonusScoreSplus + 60 + Math.floor(Math.min(40, (40 * splusNeededSecrets) / secretPercentRequired / maxSecrets));
+ let splusCryptsNeeded = Math.max(crypts, 5 - (hypotheticalScoreGottenSPlus - 300))
+ hypotheticalScoreGottenSPlus -= hypotheticalBonusScoreSplus
+ hypotheticalBonusScoreSplus = splusCryptsNeeded + this.mimicDead * 2 + this.ezpz * 10
+ hypotheticalScoreGottenSPlus += hypotheticalBonusScoreSplus
+
+ //Setting hud element
+ let sPlusText = currentSecretsFound === 0 ? "??" : (skillScore + exploreScore + speedScore + bonus) >= 300 ? "✔" : splusPossible ? `(${hypotheticalScoreGottenSPlus}): ${currentSecretsFound}/${splusNeededSecrets} +${crypts}c/${splusCryptsNeeded}` : "✖"
+ let sText = currentSecretsFound === 0 ? " ??" : (skillScore + exploreScore + speedScore + bonus) >= 270 ? " ✔" : sPossible ? ` (${hypotheticalScoreGottenS}): ${currentSecretsFound}/${sNeededSecrets} +${crypts}c/${sCryptsNeeded}` : "✖"
+
+ this.scoreElement.setText(`&dScore: ${skillScore + exploreScore + speedScore + bonus}\n&aS+ ${sPlusText}\n&aS ${sText}`);
+ }
+
+ async scanFirstDeathForSpiritPet(username) {
+ if (this.firstDeath) return
+ this.firstDeath = true
+ if (!this.nameToUuid[username.toLowerCase()]) return
+ let uuid = this.nameToUuid[username.toLowerCase()]?.replace(/-/g, "")
+
+ if (this.FeatureManager.features["globalSettings"] && this.FeatureManager.features["globalSettings"].class.apiKeySetting.getValue()) {
+ let data = await fetch(`https://api.hypixel.net/skyblock/profiles?key=${this.FeatureManager.features["globalSettings"].class.apiKeySetting.getValue()}&uuid=${uuid}`).json()
+ if (!data.success) return
+
+ let latestProfile = [0, undefined]
+
+ data.profiles.forEach(p => {
+ if (p.members[uuid].last_save > latestProfile[0]) {
+ latestProfile = [p.members[uuid].last_save, p.members[uuid].pets.some(pet => pet.type === "SPIRIT" && pet.tier === "LEGENDARY")]
+ }
+ })
+
+ if (latestProfile[1]) {
+ this.firstDeathHadSpirit = true
+ if (this.scoreCalculation.getValue()) ChatLib.chat(this.FeatureManager.messagePrefix + username + " has spirit pet!")
+ } else {
+ if (this.scoreCalculation.getValue()) ChatLib.chat(this.FeatureManager.messagePrefix + username + " does not have spirit pet!")
+ }
+ } else {
+ let data = await fetch(`http://soopy.dev/api/v2/player_skyblock/${uuid}`).json()
+ if (!data.success) return
+
+ if (data.data.profiles[data2.data.stats.currentProfileId].members[uuid].pets.some(pet => pet.type === "SPIRIT" && pet.tier === "LEGENDARY")) {
+ this.firstDeathHadSpirit = true
+ if (this.scoreCalculation.getValue()) ChatLib.chat(this.FeatureManager.messagePrefix + username + " has spirit pet!")
+ } else {
+ if (this.scoreCalculation.getValue()) ChatLib.chat(this.FeatureManager.messagePrefix + username + " does not have spirit pet!")
+ }
+ }
+ }
+
+ entityJoinWorldEvent(event) {
+ if (this.bloodCampAssist.getValue()) this.todoE.push(event.entity);
+
+ // if(event.entity instanceof EntityArrow){
+ // this.arrows.push(new Entity(event.entity))
+ // }
+ if (event.entity instanceof EntityBlaze) {
+ // console.log("Blaze joined world")
+ this.addBlaze(new Entity(event.entity));
+ }
+ }
+
+ renderWorld(ticks) {
+ if (this.lividFindBox.getValue()) {
+ if (this.lividData.correctLividEntity) {
+ renderUtils.drawBoxAtEntity(this.lividData.correctLividEntity, 255, 0, 0, 0.75, -2, ticks);
+ }
+ }
+
+ if (this.bloodCampAssist.getValue() && this.skulls) {
+ for (let skull of this.skulls) {
+ if (this.eMovingThing[skull.getUUID().toString()] && this.eMovingThing[skull.getUUID().toString()].timeTook) {
+ let skullE = skull.getEntity();
+ let startPoint = [skullE[f.posX.Entity], skullE[f.posY.Entity], skullE[f.posZ.Entity]];
+
+ let xSpeed2 = (startPoint[0] - this.eMovingThing[skull.getUUID().toString()].startX) / this.eMovingThing[skull.getUUID().toString()].timeTook;
+ let ySpeed2 = (startPoint[1] - this.eMovingThing[skull.getUUID().toString()].startY) / this.eMovingThing[skull.getUUID().toString()].timeTook;
+ let zSpeed2 = (startPoint[2] - this.eMovingThing[skull.getUUID().toString()].startZ) / this.eMovingThing[skull.getUUID().toString()].timeTook;
+
+ let time = (this.spawnIdThing >= 4 ? 2900 : 4850) - this.eMovingThing[skull.getUUID().toString()].timeTook;
+ let endPoint1 = this.eMovingThing[skull.getUUID().toString()].endPoint;
+ let endPoint2 = this.eMovingThing[skull.getUUID().toString()].endPointLast;
+ let endPointUpdated = Math.min(Date.now() - this.eMovingThing[skull.getUUID().toString()].endPointUpdated, 100);
+ if (!endPoint2) return;
+ let ping = this.FeatureManager.features["dataLoader"].class.getPing()
+ let endPoint = [endPoint2[0] + ((endPoint1[0] - endPoint2[0]) * endPointUpdated) / 100, endPoint2[1] + ((endPoint1[1] - endPoint2[1]) * endPointUpdated) / 100, endPoint2[2] + ((endPoint1[2] - endPoint2[2]) * endPointUpdated) / 100];
+ let pingPoint = [startPoint[0] + xSpeed2 * ping, startPoint[1] + ySpeed2 * ping, startPoint[2] + zSpeed2 * ping];
+
+ renderUtils.drawLineWithDepth(startPoint[0], startPoint[1] + 2, startPoint[2], endPoint[0], endPoint[1] + 2, endPoint[2], 255, 0, 0, 2);
+
+ if (ping < time) {
+ renderUtils.drawBoxAtBlockNotVisThruWalls(pingPoint[0] - 0.5, pingPoint[1] + 1.5, pingPoint[2] - 0.5, 0, 255, 0);
+ renderUtils.drawBoxAtBlockNotVisThruWalls(endPoint[0] - 0.5, endPoint[1] + 1.5, endPoint[2] - 0.5, 255, 0, 0);
+ } else {
+ renderUtils.drawBoxAtBlockNotVisThruWalls(endPoint[0] - 0.5, endPoint[1] + 1.5, endPoint[2] - 0.5, 0, 0, 255);
+ }
+
+ // if(this.eMovingThing[skull.getUUID().toString()] && this.eMovingThing[skull.getUUID().toString()].timeTook){
+ // Tessellator.drawString((time/1000).toFixed(3)+"s", endPoint[0], endPoint[1]+2, endPoint[2])
+ // }
+ }
+ }
+ }
+
+ if (this.blazeX !== -1 && this.blazes.length > 0 && this.blazeSolver.getValue()) {
+ renderUtils.drawBoxAtEntity(this.blazes[0], 255, 0, 0, 1, 2, ticks, 2);
+
+ let lastLoc = [this.blazes[0].getX(), this.blazes[0].getY() + 1.5, this.blazes[0].getZ()];
+ // this.blazes.forEach((blaze, i) => {
+ for (let i = 0, blaze = this.blazes[0]; i < this.blazes.length; i++, blaze = this.blazes[i]) {
+ if (i < 3 && i !== 0) {
+ renderUtils.drawLineWithDepth(lastLoc[0], lastLoc[1], lastLoc[2], blaze.getX(), blaze.getY() + 1.5, blaze.getZ(), i === 1 ? 0 : 255, i === 1 ? 255 : 0, 0, 3 / i);
+
+ lastLoc[0] = blaze.getX();
+ lastLoc[1] = blaze.getY() + 1.5;
+ lastLoc[2] = blaze.getZ();
+ }
+ }
+ }
+
+ let shifts = 0
+ for (let data of this.timersData) {
+ let [position, time] = data
+
+ if (Date.now() > time) {
+ shifts++
+ }
+
+ Tessellator.drawString(((time - Date.now()) / 1000).toFixed(1) + "s", position.getX(), position.getY() + 0.5, position.getZ(), Renderer.color(0, 255, 50), false, 0.025, false)
+ }
+ for (let i = 0; i < shifts; i++) this.timersData.shift()
+
+ if (this.guardianHp.getValue() && this.FeatureManager.features["dataLoader"].class.dungeonFloor?.[1] === "3") {
+ let es = World.getAllEntitiesOfType(entityGuardian)
+
+ for (let e of es) {
+ if (e.getEntity().func_110143_aJ() < 1000) continue //getHealth
+
+ Tessellator.drawString(addNotation("oneLetters", Math.round(e.getEntity().func_110143_aJ())), e.getX(), e.getY() + 0.25, e.getZ(), Renderer.color(0, 255, 0), false, 0.1, false)
+ }
+ }
+ }
+
+ renderEntity(entity, position, ticks, event) {
+ if (this.lividFindNametags.getValue()) {
+ if (this.lividData.correctLividEntity) {
+ if (entity.getName().includes("Livid") && entity.getName().includes("❤") && entity.getUUID() !== this.lividData.correctLividEntity.getUUID()) {
+ cancel(event);
+ }
+ }
+ }
+ }
+
+ /**
+ * TODO: This is code from old soopyaddons, needs almost complete recode.
+ * TODO: Also needs support for the new terminals, namely click at time
+ * TODO: Make click on time scan even when terminal is throttled (update on chat msg)
+ * TODO: Make all terminal solvers track when the server will accept the click and update on that
+ */
+ findNeededClicks() {
+ let itemsHighlight = []
+ if (ChatLib.removeFormatting(Player.getContainer().getName()).startsWith("What starts with: '") && ChatLib.removeFormatting(Player.getContainer().getName()).endsWith("'?")) {
+ let letter = ChatLib.removeFormatting(Player.getContainer().getName()).substr(19, 1).toLowerCase()
+ let i = 0;
+ Player.getContainer().getItems().forEach((item) => {
+ if (ChatLib.removeFormatting(item.getName()).toLowerCase().startsWith(letter) && !item.isEnchanted()) {
+ itemsHighlight.push(i)
+ }
+ i++
+ })
+ }
+ if (ChatLib.removeFormatting(Player.getContainer().getName()).startsWith("Select all the ") && ChatLib.removeFormatting(Player.getContainer().getName()).endsWith(" items!")) {
+ let color = ChatLib.removeFormatting(Player.getContainer().getName()).substr(15).replace(" items!", "").toLowerCase()
+ let i = 0;//silver -> light grey die, white -> wool--
+ Player.getContainer().getItems().forEach((item) => {
+ let name = ChatLib.removeFormatting(item.getName()).toLowerCase()
+ Object.entries(wrongColorList).forEach(([from, to]) => {
+ name.replace(from, to)
+ })
+ if (name.replace("wool", "white wool").includes(color) && !item.isEnchanted()) {
+ itemsHighlight.push(i)
+ }
+ i++
+ })
+ }
+ if (ChatLib.removeFormatting(Player.getContainer().getName()) === "Click in order!") {
+ let i = 0;//silver -> light grey die, white -> wool--
+ let number = 100;
+ Player.getContainer().getItems().forEach((item, i) => {
+ if (parseInt(ChatLib.removeFormatting(item.getName())) < number && item.getMetadata() === 14) {
+ number = parseInt(ChatLib.removeFormatting(item.getName()))
+ }
+ i++
+ })
+ i = 0
+ Player.getContainer().getItems().forEach((item) => {
+ if (parseInt(ChatLib.removeFormatting(item.getName())) === number) {
+ itemsHighlight.push(i)
+ }
+ i++
+ })
+ i = 0
+ Player.getContainer().getItems().forEach((item) => {
+ if (parseInt(ChatLib.removeFormatting(item.getName())) === number + 1) {
+ itemsHighlight2.push(i)
+ }
+ i++
+ })
+ }
+ }
+
+ onWorldLoad() {
+ this.lastWorldload = Date.now()
+ this.goneInBonus = false;
+ this.bloodOpenedBonus = false;
+ this.mimicDead = false
+ this.lividData.correctLividColor = undefined;
+ this.lividData.correctLividColorHP = undefined;
+ this.lividData.sayLividColors = [];
+ this.lividData.sayLividColors2 = [];
+ this.lividData.correctLividEntity = undefined;
+ this.lividHpElement && this.lividHpElement.setText("");
+ this.nameToUuid = {
+ "you": Player.getUUID().toString()
+ }
+ this.spiritBowPickUps = []
+ this.bearSpawning = 0
+ this.ffCountdownTo = 0
+ this.startSpawningTime = 0;
+ this.spawnIdThing = 0;
+ this.eMovingThing = {};
+ this.bloodX = -1;
+ this.bloodY = -1;
+ this.blazeX = -1;
+ this.blazeY = -1;
+ this.skulls = [];
+ this.arrows = [];
+ this.blazes = [];
+ World.getAllEntitiesOfType(net.minecraft.entity.item.EntityArmorStand).forEach((e) => {
+ if (e.getEntity()[m.getEquipmentInSlot](4) && e.getEntity()[m.getEquipmentInSlot](4)[m.getDisplayName.ItemStack]().endsWith(getSkullName())) {
+ this.addSkull(e);
+ }
+ });
+ World.getAllEntitiesOfType(EntityBlaze).forEach((e) => {
+ this.addBlaze(e);
+ });
+ // World.getAllEntitiesOfType(EntityArrow).forEach((e) => {
+ // this.arrows.push(e)
+ // });
+ }
+
+ step2() {
+
+ if (this.ffCountdownTo && this.ffCountdownTo > 0) {
+ this.fireFreezeTimerElement.setText("&dFire freeze in: &c" + (Math.max(0, this.ffCountdownTo - Date.now()) / 1000).toFixed(2) + "s");
+ } else {
+ this.fireFreezeTimerElement.setText("");
+ }
+ if (this.bearSpawning && this.bearSpawning > 0 && this.isInDungeon()) {
+ this.spiritBearSpawnElement.setText("&dBear spawned in: &c" + (Math.max(0, this.bearSpawning - Date.now()) / 1000).toFixed(2) + "s");
+ } else {
+ this.spiritBearSpawnElement.setText("");
+ }
+ if (this.scoreCalculation.getValue()) this.calculateDungeonScore();
+ if (this.bloodCampAssist.getValue() && this.skulls) {
+ this.skulls.forEach((skull) => {
+ let skullE = skull.getEntity();
+ // renderUtils.drawBoxAtEntity(skull, 255, 0, 0, 0.5, 0.5, ticks)
+
+ let xSpeed = skullE[f.posX.Entity] - skullE[f.lastTickPosX];
+ let ySpeed = skullE[f.posY.Entity] - skullE[f.lastTickPosY];
+ let zSpeed = skullE[f.posZ.Entity] - skullE[f.lastTickPosZ];
+
+ if (this.eMovingThing[skull.getUUID().toString()] && Date.now() - this.eMovingThing[skull.getUUID().toString()].startMovingTime > 5000) {
+ this.eMovingThing[skull.getUUID().toString()].logged = true;
+ this.spawnIdThing++;
+
+ delete this.eMovingThing[skull.getUUID().toString()];
+ this.skulls = this.skulls.filter((e) => {
+ if (e.getUUID().toString() === skull.getUUID().toString()) {
+ return false;
+ }
+ return true;
+ });
+ return;
+ }
+
+ if (xSpeed !== 0 || ySpeed !== 0) {
+ if (!this.eMovingThing[skull.getUUID().toString()]) this.eMovingThing[skull.getUUID().toString()] = { startMovingTime: Date.now(), startX: skullE[f.posX.Entity], startY: skullE[f.posY.Entity], startZ: skullE[f.posZ.Entity] };
+
+ if (this.eMovingThing[skull.getUUID().toString()].lastX !== skullE[f.posX.Entity] || this.eMovingThing[skull.getUUID().toString()].lastY !== skullE[f.posY.Entity]) {
+ this.eMovingThing[skull.getUUID().toString()].timeTook = Date.now() - this.eMovingThing[skull.getUUID().toString()].startMovingTime;
+ } else if (!this.eMovingThing[skull.getUUID().toString()].logged && (skullE[f.isDead] || !skullE[m.getEquipmentInSlot](4) || !skullE[m.getEquipmentInSlot](4)[m.getDisplayName.ItemStack]().endsWith(getSkullName()))) {
+ this.eMovingThing[skull.getUUID().toString()].logged = true;
+ this.spawnIdThing++;
+
+ delete this.eMovingThing[skull.getUUID().toString()];
+ this.skulls = this.skulls.filter((e) => {
+ if (e.getUUID().toString() === skull.getUUID().toString()) {
+ return false;
+ }
+ return true;
+ });
+ return;
+ }
+
+ this.eMovingThing[skull.getUUID().toString()].lastX = skullE[f.posX.Entity];
+ this.eMovingThing[skull.getUUID().toString()].lastY = skullE[f.posY.Entity];
+
+ if (!this.startSpawningTime) this.startSpawningTime = Date.now();
+ }
+
+ if (this.eMovingThing[skull.getUUID().toString()] && this.eMovingThing[skull.getUUID().toString()].timeTook) {
+ let startPoint = [skullE[f.posX.Entity], skullE[f.posY.Entity], skullE[f.posZ.Entity]];
+
+ let xSpeed2 = (startPoint[0] - this.eMovingThing[skull.getUUID().toString()].startX) / this.eMovingThing[skull.getUUID().toString()].timeTook;
+ let ySpeed2 = (startPoint[1] - this.eMovingThing[skull.getUUID().toString()].startY) / this.eMovingThing[skull.getUUID().toString()].timeTook;
+ let zSpeed2 = (startPoint[2] - this.eMovingThing[skull.getUUID().toString()].startZ) / this.eMovingThing[skull.getUUID().toString()].timeTook;
+
+ let time = (this.spawnIdThing >= 4 ? 2900 : 4875) - this.eMovingThing[skull.getUUID().toString()].timeTook;
+ let endPoint = [startPoint[0] + xSpeed2 * time, startPoint[1] + ySpeed2 * time, startPoint[2] + zSpeed2 * time];
+
+ this.eMovingThing[skull.getUUID().toString()].endPointLast = this.eMovingThing[skull.getUUID().toString()].endPoint;
+ this.eMovingThing[skull.getUUID().toString()].endPoint = endPoint;
+ this.eMovingThing[skull.getUUID().toString()].endPointUpdated = Date.now();
+
+ // if(this.eMovingThing[skull.getUUID().toString()] && this.eMovingThing[skull.getUUID().toString()].timeTook){
+ // Tessellator.drawString((time/1000).toFixed(3)+"s", endPoint[0], endPoint[1]+2, endPoint[2])
+ // }
+ }
+ });
+ }
+
+ if (this.blazeX !== -1) {
+ this.blazes = this.blazes.filter((e) => !e.getEntity()[f.isDead]);
+
+ this.blazes.sort((a, b) => a.getEntity().func_110143_aJ() - b.getEntity().func_110143_aJ());
+ if (
+ World.getBlockAt(this.blazeX + 17 - 43, 18, this.blazeY + 16 - 43)
+ .getType()
+ .getID() === 9
+ ) {
+ this.blazes = this.blazes.reverse();
+ }
+ }
+
+ // this.arrows = this.arrows.filter(e=>{
+ // let x = e.getX()
+ // let y = e.getY()
+ // let z = e.getZ()
+
+ // let mX = e.getMotionX()
+ // let mY = e.getMotionY()
+ // let mZ = e.getMotionZ()
+
+ // for(let i = 0;i<100;i++){
+ // x+=mX
+ // y+=mY
+ // z+=mZ
+
+ // mX*=0.99
+ // mY*=0.99
+ // mZ*=0.99
+
+ // mY-=0.05
+
+ // this.blazes = this.blazes.filter(e1=>{
+ // let boundingBox = e1.getEntity().func_174813_aQ()
+
+ // if(boundingBox.intersectsWith(new AxisAlignedBB(x-e.getEntity().field_70130_N/2,y,z-e.getEntity().field_70130_N/2,x+e.getEntity().field_70130_N/2,y+e.getEntity().field_70131_O,z+e.getEntity().field_70130_N/2))){
+ // return false
+ // }
+ // return true
+ // })
+
+ // if(World.getBlockAt(x, y, z).getType().getID() !== 0){
+ // break;
+ // }
+ // }
+
+ // return !e.getEntity()[f.isDead]
+ // })
+
+ if (this.spiritBearSpawnTimer.getValue() && (this.FeatureManager.features["dataLoader"].class.dungeonFloor === "F4" || this.FeatureManager.features["dataLoader"].class.dungeonFloor === "M4")) {
+ let id = World.getBlockAt(7, 77, 34).type.getID();
+
+ if ((!this.bearSpawning || (this.bearSpawning < 0 && this.bearSpawning > -Date.now() + 500)) && id === 169) {
+ this.bearSpawning = Date.now() + 3500;
+ }
+ }
+ }
+
+ addSkull(skull) {
+ if (this.bloodX !== -1) {
+ let xA = skull.getX() + 8 - ((skull.getX() + 8) % 32);
+ let yA = skull.getZ() + 8 - ((skull.getZ() + 8) % 32);
+
+ if (xA !== this.bloodX || yA !== this.bloodY) return;
+ } else {
+ if (skull.getEntity()[m.getEquipmentInSlot](4)[m.getDisplayName.ItemStack]().trim() === getPlayerHeadName().replace("%s", Player.getName())) {
+ this.bloodX = skull.getX() + 8 - ((skull.getX() + 8) % 32);
+ this.bloodY = skull.getZ() + 8 - ((skull.getZ() + 8) % 32);
+ this.skulls = [];
+ World.getAllEntitiesOfType(net.minecraft.entity.item.EntityArmorStand).forEach((e) => {
+ if (e.getEntity()[m.getEquipmentInSlot](4) && e.getEntity()[m.getEquipmentInSlot](4)[m.getDisplayName.ItemStack]().endsWith(getSkullName())) {
+ this.addSkull(e);
+ }
+ });
+ }
+ return;
+ }
+ this.skulls.push(skull);
+ }
+
+ addBlaze(blaze) {
+ if (!this.FeatureManager.features["dataLoader"].class.dungeonFloor) return;
+ if (this.blazeX === -1) {
+ this.blazes.push(blaze);
+ let locs = {};
+
+ this.blazes.forEach((b) => {
+ if (!locs[b.getX() + 8 - ((b.getX() + 8) % 32) + "_" + (b.getZ() + 8 - ((b.getZ() + 8) % 32))]) locs[b.getX() + 8 - ((b.getX() + 8) % 32) + "_" + (b.getZ() + 8 - ((b.getZ() + 8) % 32))] = 0;
+ locs[b.getX() + 8 - ((b.getX() + 8) % 32) + "_" + (b.getZ() + 8 - ((b.getZ() + 8) % 32))]++;
+ });
+
+ Object.keys(locs).forEach((k) => {
+ if (locs[k] === 4) {
+ [this.blazeX, this.blazeY] = k.split("_").map((a) => ~~a);
+ }
+ });
+
+ if (this.blazeX !== -1) {
+ this.blazes = [];
+ World.getAllEntitiesOfType(EntityBlaze).forEach((e) => {
+ if (e.getX() + 8 - ((e.getX() + 8) % 32) === this.blazeX && e.getZ() + 8 - ((e.getZ() + 8) % 32) === this.blazeY) {
+ this.blazes.push(e);
+ }
+ });
+ }
+ } else {
+ if (blaze.getX() + 8 - ((blaze.getX() + 8) % 32) === this.blazeX && blaze.getZ() + 8 - ((blaze.getZ() + 8) % 32) === this.blazeY) {
+ this.blazes.push(blaze);
+ this.blazes.sort((a, b) => a.getEntity().func_110143_aJ() - b.getEntity().func_110143_aJ());
+ if (
+ World.getBlockAt(this.blazeX + 17 - 43, 18, this.blazeY + 16 - 43)
+ .getType()
+ .getID() === 9
+ ) {
+ this.blazes = this.blazes.reverse();
+ }
+ }
+ }
+ }
+
+ stepNotDung() {
+ if (Date.now() - this.lastWorldload < 5000) return
+ this.inBoss = false
+ }
+
+ step() {
+
+ if (this.ffCountdownTo && this.ffCountdownTo > 0) {
+ this.fireFreezeTimerElement.setText("&dFire freeze in: &c" + (Math.max(0, this.ffCountdownTo - Date.now()) / 1000).toFixed(2) + "s");
+ } else {
+ this.fireFreezeTimerElement.setText("");
+ }
+
+ if (this.bearSpawning && this.bearSpawning > 0) {
+ this.spiritBearSpawnElement.setText("&dBear spawned in: &c" + (Math.max(0, this.bearSpawning - Date.now()) / 1000).toFixed(2) + "s");
+ } else {
+ this.spiritBearSpawnElement.setText("");
+ }
+ if (!Player.getX()) return
+ World.getAllPlayers().forEach((p) => {
+ this.nameToUuid[p.getName().toLowerCase()] = p.getUUID().toString()
+ })
+ this.failedPuzzleCount = 0;
+ this.totalPuzzleCount = 0;
+ this.completedPuzzleCount = 0;
+ TabList.getNames().forEach((n) => {
+ let name = ChatLib.removeFormatting(n).trim().split(" ");
+ let end = name.pop();
+ // console.log(end) Water Board: [✔]
+ if (end !== "[✦]" && end !== "[✔]" && end !== "[✖]") {
+ end = name.pop();
+ // console.log(end) Water Board: [✔]
+ if (end !== "[✦]" && end !== "[✔]" && end !== "[✖]") return;
+ }
+ this.totalPuzzleCount++;
+ if (end === "[✖]") this.failedPuzzleCount++;
+ if (end === "[✔]") this.completedPuzzleCount++;
+ });
+
+ if (this.lividFindEnabled.getValue() && (this.FeatureManager.features["dataLoader"].class.dungeonFloor === "F5" || this.FeatureManager.features["dataLoader"].class.dungeonFloor === "M5")) {
+ let type = World.getBlockAt(3, 108, 30).getMetadata();
+
+ let typeReplace = {
+ 0: "Vendetta",
+ 2: "Crossed",
+ 4: "Arcade",
+ 5: "Smile",
+ 6: "Crossed",
+ 7: "Doctor",
+ 8: "Doctor",
+ 10: "Purple",
+ 11: "Scream",
+ 13: "Frog",
+ 14: "Hockey",
+ };
+
+ World.getAllEntities().forEach((entity) => {
+ let entityName = entity.getName();
+
+ if (entityName.includes("Livid") && entityName.includes("❤")) {
+ // ChatLib.chat("D: " + entityName.substr(1, 1) + " asd " + this.lividData.lividColor[typeReplace[type]].split("").pop())
+ if (entityName.substr(1, 1) === this.lividData.lividColor[typeReplace[type]].split("").pop()) {
+ this.lividHpElement.setText(entityName);
+ this.lividData.correctLividEntity = entity;
+ }
+ }
+ });
+ }
+
+ if (this.lividData.correctLividEntity) {
+ if (!this.renderEntityEvent.enabled) {
+ this.renderEntityEvent.register()
+ }
+ } else {
+ if (this.renderEntityEvent.enabled) {
+ this.renderEntityEvent.unregister()
+ }
+ }
+
+ this.spiritBowPickUps = this.spiritBowPickUps.filter((pickUp) => Date.now() - pickUp < 20000);
+ if (this.spiritBowPickUps[0] && this.isInDungeon()) {
+ this.spiritBowDestroyElement.setText("&dBow Destroyed in: &c" + Math.round((this.spiritBowPickUps[0] + 20000 - Date.now()) / 1000) + "s");
+ } else {
+ this.spiritBowDestroyElement.setText("");
+ }
+ // this.spiritBowPickUps
+ if (this.bloodCampAssist.getValue()) {
+ this.todoE.forEach((e) => {
+ let en = new Entity(e);
+ // console.log(en.getName())
+ if (en.getName().trim() === getArmorStandName() && e[m.getEquipmentInSlot](4) && e[m.getEquipmentInSlot](4)[m.getDisplayName.ItemStack]().endsWith(getSkullName())) {
+ this.addSkull(en);
+ }
+ });
+
+ this.todoE = [];
+ }
+
+ let averageExp = this.lastDungExps.reduce((a, b) => a + b, 0) / this.lastDungExps.length;
+ let averageLength = (this.lastDungFinishes[this.lastDungFinishes.length - 1] - this.lastDungFinishes[0]) / (this.lastDungFinishes.length - 1);
+ let runsperHour = (60000 * 60) / averageLength;
+ let expPerHour = averageExp * runsperHour;
+
+ if (Date.now() - this.lastDungFinishes[this.lastDungFinishes.length - 1] < 60000 * 5 || this.FeatureManager.features["dataLoader"].class.dungeonFloor) {
+ if (this.lastDungFinishes.length > 1) {
+ this.runSpeedRatesElement.setText("&6Run speed&7> &f" + Math.floor(averageLength / 60000) + ":" + ((Math.floor(averageLength / 1000) % 60 < 10 ? "0" : "") + (Math.floor(averageLength / 1000) % 60)) + "\n&6Exp/hour&7> &f" + numberWithCommas(Math.round(expPerHour)) + "\n&6Runs/hour&7> &f" + Math.floor(runsperHour));
+ } else {
+ this.runSpeedRatesElement.setText("&6Run speed&7> &fLoading...\n&6Exp/hour&7> &fLoading...\n&6Runs/hour&7> &fLoading...");
+ }
+ } else {
+ this.runSpeedRatesElement.setText("");
+ }
+ }
+
+ step_1fps() {
+ if (this.IceSprayWarn.getValue()) {
+ World.getAllEntitiesOfType(net.minecraft.entity.item.EntityArmorStand).forEach((name) => {
+ let MobName = ChatLib.removeFormatting(name.getName())
+ if (MobName.includes("Ice Spray Wand") && name.getTicksExisted() <= 199) {
+ Client.showTitle(`&r&6&l[&b&l&kO&6&l] ${MobName.toUpperCase()} &6&l[&b&l&kO&6&l]`, "", 0, 40, 10);
+ ChatLib.chat(`&6&lRARE DROP! &r${name.getName()}`)
+ }
+ })
+ }
+ }
+
+ initVariables() {
+ this.lividFindEnabled = undefined;
+ this.lividData = undefined;
+ this.hudElements = [];
+ }
+
+ onDisable() {
+ this.hudElements.forEach(h => h.delete())
+ this.unloadf7data()
+ this.initVariables();
+ }
+}
+
+module.exports = {
+ class: new DungeonSolvers(),
+};
+
+function getSkullName() {
+ if (translate) {
+ return translate.func_74805_b("item.skull.char.name");
+ }
+
+ return "Head";
+}
+
+function getPlayerHeadName() {
+ if (translate) {
+ return translate.func_74805_b("item.skull.player.name");
+ }
+
+ return "%s's Head";
+}
+function getArmorStandName() {
+ if (translate) {
+ return translate.func_74805_b("item.armorStand.name");
+ }
+
+ return "Armor Stand";
+}
diff --git a/src/features/dungeonSolvers/metadata.json b/src/features/dungeonSolvers/metadata.json
new file mode 100644
index 0000000..6467a3a
--- /dev/null
+++ b/src/features/dungeonSolvers/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Dungeon Solvers",
+ "description": "Solvers for dungeon things",
+ "isHidden": false,
+ "isTogglable": true,
+ "defaultEnabled": true,
+ "sortA": 1
+}
\ No newline at end of file
diff --git a/src/features/events/index.js b/src/features/events/index.js
new file mode 100644
index 0000000..ea83312
--- /dev/null
+++ b/src/features/events/index.js
@@ -0,0 +1,816 @@
+///
+///
+import { f, m } from "../../../mappings/mappings";
+import Feature from "../../featureClass/class";
+import socketConnection from "../../socketConnection";
+import { drawBoxAtBlock, drawBoxAtBlockNotVisThruWalls, drawCoolWaypoint, drawLine } from "../../utils/renderUtils";
+import { calculateDistance, calculateDistanceQuick } from "../../utils/utils";
+import SettingBase from "../settings/settingThings/settingBase";
+import ToggleSetting from "../settings/settingThings/toggle";
+import HudTextElement from "../hud/HudTextElement";
+import LocationSetting from "../settings/settingThings/location";
+import ButtonSetting from "../settings/settingThings/button";
+import TextSetting from "../settings/settingThings/textSetting";
+
+let warpData = {
+ "castle": [-250, 130, 45],
+ "da": [91, 75, 176],
+ "museum": [-75, 76, 80],
+ "hub": [-2, 70, -69]
+}
+function getKeyBindFromKey(key, description) {
+ var mcKeyBind = undefined //MinecraftVars.getKeyBindFromKey(key);
+
+ if (mcKeyBind == null || mcKeyBind == undefined) {
+ mcKeyBind = new KeyBind(description, key);
+ }
+
+ return mcKeyBind;
+}
+
+class Events extends Feature {
+ constructor() {
+ super()
+ }
+
+ onEnable() {
+ this.initVariables()
+
+ this.burrialData = {
+ points: [],
+ locations: [],
+ historicalLocations: []
+ }
+ this.lastWorldChange = 0
+ this.lastRequest = 0
+ this.potentialParticleLocs = {}
+ this.showingWaypoints = false
+ this.lastPath = []
+ this.updatingPath = false
+ this.lastPathCords = undefined
+ this.openedWarpsMenu = false
+
+
+ this.loadFromParticles = new ToggleSetting("Load burrials from particles", "Will load particles from burrows in the world", true, "burrial_from_partles", this)
+ this.showBurrialGuess = new ToggleSetting("Estimate burrial location from ability", "Will show a line + box where it thinks the burrial is", true, "burrial_guess", this)
+ new ButtonSetting("NOTE: You must have music disabled", "for burrial guessess to work (/togglemusic)", "togglemusis_button", this, "toggle", () => {
+ ChatLib.command("togglemusic")
+ }, false).requires(this.showBurrialGuess)
+
+ this.otherInquisWaypoints = new ToggleSetting("Show other users inquis locations", "If disabled others wont be able to see urs", true, "inquis_location_other", this).requires(this.loadFromParticles)
+ this.otherInquisPing = new ToggleSetting("Show cool title when someone's inquis spawned", "May be usefull for loot share", true, "inquis_ping_other", this).requires(this.loadFromParticles)
+ this.limitPMemb = new ToggleSetting("Only send inquis ping to party members", "If not in a party it works as default", true, "inquis_ping_party", this).requires(this.otherInquisPing)
+ this.limitPMembRecieve = new ToggleSetting("Only RECIEVE inquis ping from party members", "To prevent trolling for streamers", false, "recieve_inquis_ping_party", this).requires(this.otherInquisPing)
+ this.shinyBlocks = []
+ this.glowingMushrooms = []
+
+ this.MythMobsHPGuiElement = new ToggleSetting("Render Mythological Mobs hp on your screen", "This will help you to know their HP.", true, "myth_mobs_hp", this).contributor("EmeraldMerchant");
+ this.MythMobsHP = new HudTextElement().setToggleSetting(this.MythMobsHPGuiElement).setLocationSetting(new LocationSetting("Mythological Mobs Hp Location", "Allows you to edit the location of Mythological Mobs hp", "myth_mobs_location", this, [10, 50, 1, 1]).requires(this.MythMobsHPGuiElement).editTempText("&8[&7Lv750&8] &2Exalted Minos Inquisitor &a40M&f/&a40M&c❤&r"));
+ this.hudElements.push(this.MythMobsHP);
+
+ this.Mobs = []
+ this.lastDing = 0
+ this.lastDingPitch = 0
+ this.firstPitch = 0
+ this.lastParticlePoint = undefined
+ this.firstParticlePoint = undefined
+ this.particlePoint = undefined
+ this.guessPoint = undefined
+ this.distance = undefined
+ this.dingIndex = 0
+ this.dingSlope = []
+
+ this.ignorePlayers = new Set()
+
+ new SettingBase("There is also a hotkey to warp near", "see minecraft controls menu", true, "warp_info_hotkey", this)
+ this.warpBindDefault = new TextSetting("Default warp keybind", "Eg KEY_F", "CHAR_NONE", "inquis_keybind_default", this, "", false)
+
+ try {
+ this.warpBind = getKeyBindFromKey(Keyboard[this.warpBindDefault.getValue()], "Warp to nearest location to burrial guess");
+ } catch (e) {
+ ChatLib.chat(this.FeatureManager.messagePrefix + this.warpBindDefault.getValue() + " is an invalid keyboard key, see https://legacy.lwjgl.org/javadoc/org/lwjgl/input/Keyboard.html")
+ this.warpBind = getKeyBindFromKey(Keyboard.CHAR_NONE, "Warp to nearest location to burrial guess");
+ }
+
+ this.slayerLocationDataH = {}
+ this.todoE = []
+
+ this.hasWarps = new Set()
+
+ this.shinyBlockOverlayEnabled = new ToggleSetting("Shiny blocks highlight", "Will highlight shiny blocks in the end", false, "shiny_blocks_overlay", this)
+ this.showGlowingMushrooms = new ToggleSetting("Glowing mushrooms highlight", "Will highlight glowing mushrooms", false, "glowing_mushrooms_overlay", this)
+
+ this.registerEvent("worldLoad", this.worldLoad)
+ this.registerEvent("spawnParticle", this.spawnParticle).registeredWhen(() => this.showingWaypoints || this.shinyBlockOverlayEnabled.getValue() || this.showGlowingMushrooms.getValue())
+ this.registerEvent("renderWorld", this.renderWorld).registeredWhen(() => this.showingWaypoints || this.shinyBlockOverlayEnabled.getValue() || this.showGlowingMushrooms.getValue())
+ this.registerStep(true, 2, this.step)
+ this.registerStep(false, 5, this.step_5s)
+
+ this.registerEvent("soundPlay", this.playSound).registeredWhen(() => this.showingWaypoints)
+ this.registerForge(net.minecraftforge.event.entity.EntityJoinWorldEvent, this.entityJoinWorldEvent).registeredWhen(() => this.showingWaypoints);
+
+ this.registerChat("&r&eYou dug out a Griffin Burrow! &r&7(${*}/4)&r", this.burrialClicked)
+ this.registerChat("&r&eYou finished the Griffin burrow chain! &r&7(4/4)&r", this.burrialClicked)
+ this.inquisWaypointSpawned = false
+
+ this.registerEvent("tick", () => {
+ if (this.warpBind.isPressed()) {
+
+ if (!this.openedWarpsMenu) {
+ ChatLib.chat(this.FeatureManager.messagePrefix + "Please open the warps menu first (/warp)")
+ ChatLib.chat(this.FeatureManager.messagePrefix + "(So the mod knows what warps u have access to)")
+ }
+ let loc = this.getClosestWarp()
+
+ if (loc) ChatLib.command(loc)
+ }
+ })
+
+ this.registerStep(true, 1, this.step_1fps)
+ this.registerStep(true, 10, this.step_10fps)
+
+
+ this.registerCommand("inqwaypointignoreadd", (player) => {
+ this.ignorePlayers.add(player)
+ ChatLib.chat(this.FeatureManager.messagePrefix + "Added " + player + " to inquis waypoint ignore list, this will be cleared next game start!")
+
+ delete this.slayerLocationDataH[player]
+ })
+ this.registerCommand("cleardianawaypoints", () => {
+ this.burrialData.points = []
+ this.burrialData.locations = []
+ this.burrialData.historicalLocations = []
+ ChatLib.chat(this.FeatureManager.messagePrefix + "Cleared all diana waypoints!")
+ })
+
+ this.locs = []
+ this.predictions = []
+ // this.predictionsOld = []
+ // this.registerEvent("renderWorld", () => {
+ // for (let loc of this.locs) {
+ // drawBoxAtBlock(loc[0], loc[1], loc[2], 255, 0, 0, 0.05, 0.05)
+ // }
+ // for (let loc of this.predictions) {
+ // drawBoxAtBlock(loc[0], loc[1], loc[2], 0, 255, 0, 0.05, 0.05)
+ // }
+ // })
+
+ // this.registerCommand("clearlocs", () => {
+ // this.locs = []
+ // this.predictions = []
+ // // this.predictionsOld = []
+ // ChatLib.chat(this.FeatureManager.messagePrefix + "Cleared all locs!")
+ // })
+ }
+
+ step_1fps() {
+ if (!this.MythMobsHPGuiElement.getValue() || !this.showingWaypoints) return
+ World.getAllEntitiesOfType(net.minecraft.entity.item.EntityArmorStand).forEach((mob) => {
+ let name = mob.getName()
+ if (!this.Mobs?.map(a => a.getUUID().toString()).includes(mob.getUUID().toString())) {
+ if ((name.includes("Exalted") || name.includes("Stalwart")) && !name.split(" ")[2].startsWith("0")) {
+ this.Mobs.push(mob)
+ }
+ }
+ })
+ this.Mobs = this.Mobs.filter((e) => !e.getEntity()[f.isDead]);
+ }
+
+ step_10fps() {
+ if (!this.MythMobsHPGuiElement.getValue()) return
+ let names = []
+ this.Mobs.forEach(nameTag => {
+ names.push(nameTag.getName())
+ })
+ this.MythMobsHP.setText(names.join("\n"))
+ }
+
+ entityJoinWorldEvent(e) {
+ if (this.otherInquisWaypoints.getValue()) this.todoE.push(e.entity);
+ }
+
+ inquisData(loc, user) {
+ if (this.ignorePlayers.has(user) && user !== Player.getName()) return
+ if (!loc) {
+ delete this.slayerLocationDataH[user]
+ return
+ }
+
+ if (this.limitPMembRecieve.getValue()) {
+ if (!this.FeatureManager.features["dataLoader"].class.partyMembers.has(user)) return
+ }
+ this.slayerLocationDataH[user] = [loc, Date.now()]
+ if (this.otherInquisPing.getValue()) {
+ Client.showTitle("&r&6&l[&b&l&kO&6&l] MINOS INQUISITOR [&b&l&kO&6&l]", `${user}'s Inquisitor`, 0, 50, 10);
+ new TextComponent(this.FeatureManager.messagePrefix + `${user} spawned an inquis &7(waypoint added), &cCLICK HERE &7to ignore waypoints from them.`).setClick("run_command", "/inqwaypointignoreadd " + user).chat()
+ }
+ }
+
+ renderWorld(ticks) {
+ this.shinyBlocks.forEach(([loc]) => {
+ drawBoxAtBlockNotVisThruWalls(loc[0], loc[1], loc[2], 0, 255, 0, 0.1, 0.1)
+ })
+ this.glowingMushrooms.forEach(([loc]) => {
+ drawBoxAtBlockNotVisThruWalls(loc[0] - 0.2, loc[1], loc[2] - 0.2, 0, 255, 0, 0.4, 0.4)
+ })
+ if (this.showingWaypoints) {
+ if (this.guessPoint && this.showBurrialGuess.getValue()) {
+ let warpLoc = this.getClosestWarp()
+ if (this.guessPoint2) {
+ let gY = 131
+ while (World.getBlockAt(this.guessPoint2[0], gY, this.guessPoint2[2]).getType().getID() !== 2 && gY > 70) {
+ gY--
+ }
+ drawCoolWaypoint(this.guessPoint2[0], gY + 3, this.guessPoint2[2], 255, 255, 0, { name: "§eGuess" + (warpLoc ? " §7(" + warpLoc + ")" : "") })
+ }
+ // drawCoolWaypoint(this.guessPoint[0], this.guessPoint[1], this.guessPoint[2], 255, 255, 0, { name: "§7OLD Guess" + (warpLoc ? " §7(" + warpLoc + ")" : "") })
+ }
+ this.burrialData.locations.forEach((loc, i) => {
+
+ let typeReplace = [
+ "Start",
+ "Mob",
+ "Treasure",
+ "Finish",
+ "Unknown"
+ ]
+ if (!loc.clicked) {
+ blue = false
+ if (loc.lastPing && Date.now() - loc.lastPing < 500) {
+ blue = true
+ }
+
+ let name = ""
+
+ if (loc.fromApi) {
+ name = (loc.nearest ? "§c" : "§a") + "(" + (loc.chain + 1) + "/4) " + typeReplace[loc.type] + " burrial"
+ } else {
+ name = (loc.nearest ? "§c" : "§a") + typeReplace[loc.type] + " burrial"
+ }
+
+ drawCoolWaypoint(loc.x, loc.y, loc.z, 0, blue ? 100 : 255, blue ? 255 : 0, { name: name })
+ }
+ })
+ }
+
+ if (this.otherInquisWaypoints.getValue()) {
+ Object.keys(this.slayerLocationDataH).forEach(key => {
+ drawCoolWaypoint(this.slayerLocationDataH[key][0][0] || 0, this.slayerLocationDataH[key][0][1] || 0, this.slayerLocationDataH[key][0][2] || 0, 255, 0, 0, { name: "§c" + (key || "ERROR") + "'s inquis" })
+ })
+ }
+ }
+
+ sortBurrialLocations() {
+ let sorted = [...this.burrialData.locations]
+ sorted.sort((a, b) => {
+ let aDist = calculateDistanceQuick([Player.getX(), Player.getY(), Player.getZ()], [a.x + 0.5, a.y + 2.5, a.z + 0.5])
+ let bDist = calculateDistanceQuick([Player.getX(), Player.getY(), Player.getZ()], [b.x + 0.5, b.y + 2.5, b.z + 0.5])
+
+ return bDist - aDist
+ })
+ this.burrialData.locations = sorted
+ }
+
+ step() {
+ if (!Player.getInventory()) return
+
+ hasDianaShovle = false
+ let slots = [0, 1, 2, 3, 4, 5, 6, 7, 8]
+ slots.forEach(a => {
+ item = Player.getInventory().getStackInSlot(a)
+ if (!item) return
+ if (ChatLib.removeFormatting(item.getName()) === "Ancestral Spade") {
+ hasDianaShovle = true
+ }
+ })
+
+ let showingWaypointsNew = (this.lastWorldChange + 5000 < Date.now() ? hasDianaShovle && this.FeatureManager.features["dataLoader"].class.area === "Hub" && (this.loadFromParticles.getValue() || this.showBurrialGuess.getValue()) : this.showingWaypoints || (hasDianaShovle && this.FeatureManager.features["dataLoader"].class.area === "Hub" && (this.loadFromParticles.getValue() || this.showBurrialGuess.getValue())))
+
+ this.showingWaypoints = showingWaypointsNew
+
+ this.shinyBlocks = this.shinyBlocks.filter(([loc, time]) => {
+ return time > Date.now() - 5000
+ })
+ this.glowingMushrooms = this.glowingMushrooms.filter(([loc, time]) => {
+ return time > Date.now() - 1000 && World.getBlockAt(...loc.map(a => Math.floor(a))).type.getID() !== 0
+ })
+
+
+ Object.keys(this.slayerLocationDataH).forEach(n => {
+ if (this.slayerLocationDataH[n][1] + 60000 * 3 < Date.now()) {
+ delete this.slayerLocationDataH[n]
+ }
+ })
+
+ this.todoE.forEach(e => {
+ e = new Entity(e)
+
+ if (e.getName().toLowerCase().includes("inquis") && !e.getName().includes("'") && Math.abs(e.getY() - Player.getY()) < 10 && Math.abs(e.getX() - Player.getX()) < 10 && Math.abs(e.getZ() - Player.getZ()) < 10) {
+ let loc = [e.getX(), e.getY() - 1, e.getZ()]
+ let self = false
+ this.burrialData.locations.forEach(a => {
+ if (calculateDistanceQuick([a.x, a.y, a.z], loc) < 25) {
+ self = true
+ }
+ })
+ if (self) {
+ let pmemb = []
+ this.FeatureManager.features["dataLoader"].class.partyMembers.forEach(a => pmemb.push(a))
+ socketConnection.sendInquisData({ loc: [Math.round(Player.getX()), Math.round(Player.getY()), Math.round(Player.getZ())], pmemb, limitPMemb: pmemb.length > 1 && this.limitPMemb.getValue() });
+ this.inquisWaypointSpawned = true
+ }
+ }
+ })
+ this.todoE = []
+
+ if (Player.getContainer().getName() === "Fast Travel") {
+ this.openedWarpsMenu = true
+ for (let item of Player.getContainer().getItems()) {
+ if (!item) continue
+ if (ChatLib.removeFormatting(item.getLore()[1]).startsWith("/warp") && warpData[ChatLib.removeFormatting(item.getLore()[1]).replace("/warp ", "")]) {
+
+ if (item.getLore().some(a => a.includes("Click to warp!"))) {
+ this.hasWarps.add(ChatLib.removeFormatting(item.getLore()[1]).replace("/warp ", ""))
+ }
+ }
+ }
+ }
+ }
+
+ getClosestWarp() {
+ if (!this.guessPoint) return undefined
+ let warp = undefined
+ let minDist = calculateDistance([Player.getX(), Player.getY(), Player.getZ()], this.guessPoint) - 50
+
+ this.hasWarps.forEach(w => {
+ if (!warpData[w]) return
+ let d = calculateDistance(warpData[w], this.guessPoint2)
+ if (d < minDist) {
+ warp = "warp " + w
+ minDist = d
+ }
+ })
+
+ return warp
+ }
+
+ step_5s() {
+ this.sortBurrialLocations()
+ }
+
+ worldLoad() {
+
+ this.burrialData.points = []
+ this.burrialData.locations = []
+ this.burrialData.historicalLocations = []
+ this.lastDing = 0
+ this.lastDingPitch = 0
+ this.firstPitch = 0
+ this.lastParticlePoint = undefined
+ this.lastParticlePoint2 = undefined
+ this.lastSoundPoint = undefined
+ this.firstParticlePoint = undefined
+ this.particlePoint = undefined
+ this.guessPoint = undefined
+ this.distance = undefined
+ this.dingIndex = 0
+ this.dingSlope = []
+
+ this.lastPath = undefined
+ this.lastPathCords = undefined
+
+ this.lastWorldChange = Date.now()
+ this.Mobs = []
+ }
+
+ playSound(pos, name, volume, pitch, categoryName, event) {
+ if (!this.showBurrialGuess.getValue()) return
+ // if (this.dingIndex > 13) return
+ // if (pos.getX() === Math.floor(Player.getX() * 8) / 8 && pos.getZ() === Math.floor(Player.getZ() * 8) / 8) return
+ if (name !== "note.harp") return
+ if (this.lastDing === 0) {
+ this.firstPitch = pitch
+ }
+ this.lastDing = Date.now()
+ if (pitch < this.lastDingPitch) {
+ this.firstPitch = pitch
+ this.dingIndex = 0
+ this.dingSlope = []
+ this.lastDingPitch = pitch
+ this.lastParticlePoint = undefined
+ this.lastParticlePoint2 = undefined
+ this.lastSoundPoint = undefined
+ this.firstParticlePoint = undefined
+ this.distance = undefined
+ this.locs = []
+ // this.predictionsOld = this.predictions
+ }
+ if (this.lastDingPitch === 0) {
+ this.lastDingPitch = pitch
+ this.distance = undefined
+ this.lastParticlePoint = undefined
+ this.lastParticlePoint2 = undefined
+ this.lastSoundPoint = undefined
+ this.firstParticlePoint = undefined
+ this.locs = []
+ // this.predictionsOld = this.predictions
+ return
+ }
+ this.dingIndex++
+ if (this.dingIndex > 1) this.dingSlope.push(pitch - this.lastDingPitch)
+ if (this.dingSlope.length > 20) this.dingSlope.shift()
+ let slope = this.dingSlope.reduce((a, b) => a + b, 0) / this.dingSlope.length
+ // console.log(this.dingSlope.join(","))
+ this.lastSoundPoint = [pos.getX(), pos.getY(), pos.getZ()]
+ this.lastDingPitch = pitch
+
+ if (!this.lastParticlePoint2 || !this.particlePoint || !this.firstParticlePoint) return
+ this.distance2 = Math.E / slope - Math.hypot(this.firstParticlePoint[0] - pos.getX(), this.firstParticlePoint[1] - pos.getY(), this.firstParticlePoint[2] - pos.getZ())
+ // console.log(this.dingIndex + " " + this.dingSlope / this.dingIndex + " " + pitch + " " + (pitch - this.lastDingPitch))
+
+ if (this.distance2 > 1000) {
+ this.distance2 = undefined
+ this.guessPoint = undefined
+ return
+ }
+
+ let lineDist = Math.hypot(this.lastParticlePoint2[0] - this.particlePoint[0], this.lastParticlePoint2[1] - this.particlePoint[1], this.lastParticlePoint2[2] - this.particlePoint[2])
+ let distance = this.distance2
+ let changes = [this.particlePoint[0] - this.lastParticlePoint2[0], this.particlePoint[1] - this.lastParticlePoint2[1], this.particlePoint[2] - this.lastParticlePoint2[2]]
+ changes = changes.map(a => a / lineDist)
+ this.guessPoint = [this.lastSoundPoint[0] + changes[0] * distance, this.lastSoundPoint[1] + changes[1] * distance, this.lastSoundPoint[2] + changes[2] * distance]
+ // let minD = Infinity
+ // for (let i = 0; i < this.predictions.length; i++) {
+ // let p = this.predictions[i]
+ // let d = (p[0] - this.guessPoint[0]) ** 2 + (p[2] - this.guessPoint[2]) ** 2
+ // if (d < minD) {
+ // minD = d
+ // this.guessPoint2 = [Math.floor(p[0]), 255, Math.floor(p[2])]
+ // }
+ // }
+ }
+
+ /**
+ * Solves the equasion y=b/(x+a)+c
+ * returns [a, b, c]
+ */
+ solveEquasionThing(x, y) {
+ let a = (-y[0] * x[1] * x[0] - y[1] * x[1] * x[2] + y[1] * x[1] * x[0] + x[1] * x[2] * y[2] + x[0] * x[2] * y[0] - x[0] * x[2] * y[2]) / (x[1] * y[0] - x[1] * y[2] + x[0] * y[2] - y[0] * x[2] + y[1] * x[2] - y[1] * x[0])
+ let b = (y[0] - y[1]) * (x[0] + a) * (x[1] + a) / (x[1] - x[0])
+ let c = y[0] - b / (x[0] + a)
+ return [a, b, c]
+ }
+
+ spawnParticle(particle, type, event) {
+ if (this.showingWaypoints && this.showBurrialGuess.getValue() && particle.toString().startsWith("EntityDropParticleFX,")) {
+
+ let run = false
+ if (this.lastSoundPoint && !run && Math.abs(particle.getX() - this.lastSoundPoint[0]) < 2 && Math.abs(particle.getY() - this.lastSoundPoint[1]) < 0.5 && Math.abs(particle.getZ() - this.lastSoundPoint[2]) < 2) {
+ run = true
+ }
+ if (run) {
+
+ if (this.locs.length < 100 && this.locs.length === 0 || particle.getX() + particle.getY() + particle.getZ() !== this.locs[this.locs.length - 1][0] + this.locs[this.locs.length - 1][1] + this.locs[this.locs.length - 1][2]) {
+
+ let currLoc = [particle.getX(), particle.getY(), particle.getZ()]
+ let distMultiplier = 1
+ {
+ if (this.locs.length > 2) {
+
+ let predictedDist = 0.06507 * this.locs.length + 0.259
+
+ let lastPos = this.locs[this.locs.length - 1]
+ let actualDist = Math.hypot(...currLoc.map((l, i) => {
+ return (l - lastPos[i])
+ }))
+
+ distMultiplier = actualDist / predictedDist
+ }
+ // if (this.locs.length > 2 && !this.distance) {
+ // let lastPos = this.locs[this.locs.length - 1]
+ // let dist = Math.hypot(...currLoc.map((l, i) => {
+ // return (l - lastPos[i])
+ // }))
+ // let lastPos2 = this.locs[this.locs.length - 2]
+ // let dist2 = Math.hypot(...currLoc.map((l, i) => {
+ // return (lastPos[i] - lastPos2[i])
+ // }))
+ // // console.log("------")
+ // // console.log(dist - dist2)
+ // this.distance = 20 / (dist - dist2) - (dist - dist2) * 80
+ // console.log(this.distance)
+ // // this.distance -= Math.hypot(this.firstParticlePoint[0] - particle.getX(), this.firstParticlePoint[1] - particle.getY(), this.firstParticlePoint[2] - particle.getZ())
+
+ // // console.log(Math.sqrt((Player.getX() - this.firstParticlePoint[0]) ** 2 + (Player.getZ() - this.firstParticlePoint[2]) ** 2))
+ // }
+ }
+ this.locs.push(currLoc)
+ if (this.locs.length > 5 && this.guessPoint) {
+ let slopeThing = this.locs.map((a, i) => {
+ if (i === 0) return
+ let lastLoc = this.locs[i - 1]
+ let currLoc = a
+ return Math.atan((currLoc[0] - lastLoc[0]) / (currLoc[2] - lastLoc[2]))
+ })
+
+ let [a, b, c] = this.solveEquasionThing([slopeThing.length - 5, slopeThing.length - 3, slopeThing.length - 1], [slopeThing[slopeThing.length - 5], slopeThing[slopeThing.length - 3], slopeThing[slopeThing.length - 1]])
+ // console.log(a, b, c)
+
+ let pr1 = []
+ let pr2 = []
+
+ let start = slopeThing.length - 1
+ let lastPos = [this.locs[start][0], this.locs[start][1], this.locs[start][2]]
+ let lastPos2 = [this.locs[start][0], this.locs[start][1], this.locs[start][2]]
+
+ let distCovered = 0
+ // this.locs.forEach((l, i) => {
+ // if (i === 0) return
+
+ // distCovered += Math.hypot(this.locs[i][0] - this.locs[i - 1][0], this.locs[i][1] - this.locs[i - 1][1], this.locs[i][2] - this.locs[i - 1][2])
+ // })
+
+ let ySpeed = (this.locs[this.locs.length - 1][1] - this.locs[this.locs.length - 2][1]) / Math.hypot(this.locs[this.locs.length - 1][0] - this.locs[this.locs.length - 2][0], this.locs[this.locs.length - 1][2] - this.locs[this.locs.length - 2][2])
+
+ let i = start + 1
+ while (distCovered < this.distance2 && i < 10000) {
+ let y = b / (i + a) + c
+
+ let dist = distMultiplier * (0.06507 * i + 0.259) //This is where the inaccuracy's come from
+ //dist = distance between particles for guessed line
+
+ let xOff = dist * Math.sin(y)
+ let zOff = dist * Math.cos(y)
+
+
+
+ let dencity = 5
+ for (let o = 0; o < dencity; o++) {
+ lastPos[0] += xOff / dencity
+ lastPos[2] += zOff / dencity
+
+ lastPos[1] += ySpeed * dist / dencity
+ lastPos2[1] += ySpeed * dist / dencity
+
+ lastPos2[0] -= xOff / dencity
+ lastPos2[2] -= zOff / dencity
+
+ pr1.push([...lastPos])
+ pr2.push([...lastPos2])
+
+
+ // distCovered += Math.hypot(xOff, zOff) / dencity
+ distCovered = Math.hypot(lastPos[0] - this.lastSoundPoint[0], lastPos[2] - this.lastSoundPoint[2])
+ if (distCovered > this.distance2) break;
+ }
+ i++
+ }
+ this.predictions = [...pr1, ...pr2]
+ // let minD = Infinity
+
+ let p1 = pr1[pr1.length - 1]
+ let p2 = pr2[pr2.length - 1]
+
+ if (!this.guessPoint) return
+
+ let d1 = (p1[0] - this.guessPoint[0]) ** 2 + (p1[2] - this.guessPoint[2]) ** 2
+ let d2 = (p2[0] - this.guessPoint[0]) ** 2 + (p2[2] - this.guessPoint[2]) ** 2
+
+ if (d1 < d2) {
+ this.guessPoint2 = [Math.floor(p1[0]), 255, Math.floor(p1[2])]
+ } else {
+ this.guessPoint2 = [Math.floor(p2[0]), 255, Math.floor(p2[2])]
+ }
+ // for (let i = 0; i < this.predictions.length; i++) {
+ // let p = this.predictions[i]
+ // let d2 = (p[0] - this.guessPoint[0]) ** 2 + (p[2] - this.guessPoint[2]) ** 2
+ // let d = Math.abs(this.distance ** 2 - (p[0] - this.firstParticlePoint[0]) ** 2 + (p[2] - this.firstParticlePoint[2]) ** 2)
+ // if (d < minD && d2 < 50 ** 2) {
+ // minD = d
+ // this.guessPoint2 = [Math.floor(p[0]), 255, Math.floor(p[2])]
+ // }
+ // }
+ // console.log(this.predictions[1].join(" "))
+ }
+
+ }
+ if (this.lastParticlePoint === undefined) {
+ this.firstParticlePoint = [particle.getX(), particle.getY(), particle.getZ()]
+ }
+ this.lastParticlePoint2 = this.lastParticlePoint
+ this.lastParticlePoint = this.particlePoint
+ this.particlePoint = [particle.getX(), particle.getY(), particle.getZ()]
+
+ if (!this.lastParticlePoint2 || !this.particlePoint || !this.firstParticlePoint || !this.distance || !this.lastSoundPoint) return
+
+ let lineDist = Math.hypot(this.lastParticlePoint2[0] - this.particlePoint[0], this.lastParticlePoint2[1] - this.particlePoint[1], this.lastParticlePoint2[2] - this.particlePoint[2])
+ let distance = this.distance2
+ let changes = [this.particlePoint[0] - this.lastParticlePoint2[0], this.particlePoint[1] - this.lastParticlePoint2[1], this.particlePoint[2] - this.lastParticlePoint2[2]]
+ changes = changes.map(a => a / lineDist)
+ this.guessPoint = [this.lastSoundPoint[0] + changes[0] * distance, this.lastSoundPoint[1] + changes[1] * distance, this.lastSoundPoint[2] + changes[2] * distance]
+ }
+ }
+ if (this.shinyBlockOverlayEnabled.getValue() && this.FeatureManager.features["dataLoader"].class.areaFine === "The End") {
+ if (particle.toString().startsWith("EntitySpellParticleFX,")) {
+ if (particle.getUnderlyingEntity().func_70534_d() === particle.getUnderlyingEntity().func_70535_g()) {
+ let arr = [particle.getX(), particle.getY(), particle.getZ()]
+ if (arr.map(a => Math.abs(a % 1)).includes(0.25) || arr.map(a => Math.abs(a % 1)).includes(0.75)) {
+ this.shinyBlocks.push([[particle.getX(), particle.getY(), particle.getZ()], Date.now()])
+ }
+ }
+ }
+ }
+ if (this.showGlowingMushrooms.getValue() && this.FeatureManager.features["dataLoader"].class.areaFine === "Glowing Mushroom Cave") {
+ if (particle.toString().startsWith("EntitySpellParticleFX,")) {
+ // console.log([particle.getX(), particle.getY(), particle.getZ()].map(a => a % 1))
+ if (Math.abs(particle.getX() % 1) === 0.5 && Math.abs(particle.getZ() % 1) === 0.5) {
+ this.glowingMushrooms.push([[particle.getX(), particle.getY(), particle.getZ()], Date.now()])
+ }
+ }
+ }
+ if (this.showingWaypoints && this.loadFromParticles.getValue()) {
+ let foundEnchant = false
+ let foundCrit = false
+ let foundStep = false
+ let isMob = undefined
+
+ if (particle.toString().startsWith('EntityEnchantmentTableParticleFX, ')) {
+ foundEnchant = true
+ }
+ else if (particle.toString().startsWith('EntityCrit2FX, ')) {
+ foundCrit = true
+
+ isMob = particle.getUnderlyingEntity().func_70534_d() > 0.5 //mob)
+ }
+ else if (particle.toString().startsWith('EntityFootStepFX, ')) {
+ foundStep = true
+ }
+ else if (particle.toString().startsWith('EntityCritFX, ')) {
+
+ let locstr = Math.floor(particle.getX()) + "," + Math.floor(particle.getY() - 1) + "," + Math.floor(particle.getZ())
+
+ let removed = false
+ this.burrialData.locations.filter((loc, i) => {
+ if (!loc.clicked && loc.x + "," + loc.y + "," + loc.z === locstr) {
+ loc.clicked = true
+ removed = true
+ }
+ })
+ if (!removed) return;
+ this.burrialData.locations = this.burrialData.locations.filter(a => {
+ if (!a.clicked) return true
+ if (calculateDistanceQuick([a.x, a.y, a.z], [Player.getX(), Player.getY(), Player.getZ()]) < 15 * 15) return true;
+
+ this.burrialData.historicalLocations.unshift(a)
+
+ return false
+ })
+ if (this.burrialData.historicalLocations.length > 10) this.burrialData.historicalLocations.pop()
+
+ return;
+ }
+
+ if (!foundEnchant && !foundCrit && !foundStep) return;
+
+ if (Math.abs(particle.getY() % 1) > 0.1) return
+ if (Math.abs(particle.getX() % 1) < 0.1) return
+ if (Math.abs(particle.getX() % 1) > 0.9) return
+ if (Math.abs(particle.getZ() % 1) < 0.1) return
+ if (Math.abs(particle.getZ() % 1) > 0.9) return
+
+ let locstr = Math.floor(particle.getX()) + "," + Math.floor(particle.getY() - 1) + "," + Math.floor(particle.getZ())
+ let locarr = [Math.floor(particle.getX()), Math.floor(particle.getY() - 1), Math.floor(particle.getZ())]
+
+ let found = false
+
+ this.burrialData.locations.forEach((loc) => {
+ if (loc.x + "," + loc.y + "," + loc.z === locstr) {
+ found = loc
+ loc.lastPing = Date.now()
+ }
+ if ((loc.x + 1) + "," + loc.y + "," + loc.z === locstr) {
+ found = loc
+ loc.lastPing = Date.now()
+ }
+ if ((loc.x + 1) + "," + (loc.y + 1) + "," + loc.z === locstr) {
+ found = loc
+ loc.lastPing = Date.now()
+ }
+ if ((loc.x + 1) + "," + (loc.y - 1) + "," + loc.z === locstr) {
+ found = loc
+ loc.lastPing = Date.now()
+ }
+ if ((loc.x - 1) + "," + (loc.y + 1) + "," + loc.z === locstr) {
+ found = loc
+ loc.lastPing = Date.now()
+ }
+ if ((loc.x - 1) + "," + (loc.y - 1) + "," + loc.z === locstr) {
+ found = loc
+ loc.lastPing = Date.now()
+ }
+ if ((loc.x - 1) + "," + loc.y + "," + loc.z === locstr) {
+ found = loc
+ loc.lastPing = Date.now()
+ }
+ if (loc.x + "," + loc.y + "," + (loc.z + 1) === locstr) {
+ found = loc
+ loc.lastPing = Date.now()
+ }
+ if (loc.x + "," + loc.y + "," + (loc.z - 1) === locstr) {
+ found = loc
+ loc.lastPing = Date.now()
+ }
+ })
+ if (this.burrialData.historicalLocations) {
+ this.burrialData.historicalLocations.forEach((loc) => {
+ if (loc.x + "," + loc.y + "," + loc.z === locstr) {
+ found = loc
+ }
+ })
+ }
+
+ if (!this.potentialParticleLocs[locstr] || Date.now() - this.potentialParticleLocs[locstr].timestamp > 30000) this.potentialParticleLocs[locstr] = { enchant: 0, crit: 0, step: 0, isMob: 0, timestamp: Date.now() }
+
+ if (foundEnchant) this.potentialParticleLocs[locstr].enchant++
+ if (foundCrit) this.potentialParticleLocs[locstr].crit++
+ if (foundStep) this.potentialParticleLocs[locstr].step++
+ if (foundCrit && isMob) this.potentialParticleLocs[locstr].isMob++
+ if (foundCrit && !isMob) this.potentialParticleLocs[locstr].isMob--
+
+ this.potentialParticleLocs[locstr].timestamp = Date.now()
+
+ if (this.potentialParticleLocs[locstr].enchant >= 1 && this.potentialParticleLocs[locstr].step >= 2) {
+ if (found) {
+ found.type = this.potentialParticleLocs[locstr].isMob >= 1 ? 1 : (this.potentialParticleLocs[locstr].crit > this.potentialParticleLocs[locstr].enchant / 20 ? 0 : 2)
+ return
+ }
+ this.burrialData.locations.push({
+ "x": locarr[0],
+ "y": locarr[1],
+ "z": locarr[2],
+ "type": this.potentialParticleLocs[locstr].isMob >= 1 ? 1 : (this.potentialParticleLocs[locstr].crit > this.potentialParticleLocs[locstr].enchant / 20 ? 0 : 2),
+ "tier": -1,
+ "chain": -1,
+ "fromApi": false
+ })
+ World.playSound("note.pling", 100, 2)
+ }
+ }
+ }
+
+ burrialClicked() {
+ this.locs = []
+ this.predictions = []
+ // this.predictionsOld = []
+ if (this.inquisWaypointSpawned) {
+ socketConnection.sendInquisData({ loc: null });
+ this.inquisWaypointSpawned = false
+ }
+ if (!this.showingWaypoints) return
+
+ let nearestBurriali = undefined
+ let nearestBurrialDist = Infinity
+
+ this.burrialData.locations.forEach((loc, i) => {
+ let dist = calculateDistanceQuick([loc.x, loc.y, loc.z], [Player.getX(), Player.getY(), Player.getZ()])
+ if (dist < nearestBurrialDist) {
+ nearestBurrialDist = dist
+ nearestBurriali = i
+ }
+ })
+
+ if (nearestBurriali === undefined) return;
+ this.burrialData.locations[nearestBurriali].clicked = true
+
+ this.burrialData.locations = this.burrialData.locations.filter(a => {
+ if (!a.clicked) return true
+ if (calculateDistanceQuick([a.x, a.y, a.z], [Player.getX(), Player.getY(), Player.getZ()]) < 15 * 15) return true;
+
+ this.burrialData.historicalLocations.unshift(a)
+
+ return false
+ })
+ if (this.burrialData.historicalLocations.length > 10) this.burrialData.historicalLocations.pop()
+ if (this.lastPathCords) this.lastPathCords.shift()
+ }
+
+ initVariables() {
+ this.burrialData = undefined
+ this.potentialParticleLocs = undefined
+ this.showingWaypoints = undefined
+ this.lastPath = undefined
+ this.updatingPath = undefined
+ this.lastPathCords = undefined
+ this.hudElements = [];
+ this.Mobs = []
+ }
+
+ onDisable() {
+ this.hudElements.forEach(h => h.delete())
+ this.initVariables();
+ }
+}
+
+module.exports = {
+ class: new Events()
+}
diff --git a/src/features/events/metadata.json b/src/features/events/metadata.json
new file mode 100644
index 0000000..363625f
--- /dev/null
+++ b/src/features/events/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Events",
+ "description": "Features for various events (eg diana)",
+ "isHidden": false,
+ "isTogglable": true,
+ "defaultEnabled": true,
+ "sortA": 1
+}
\ No newline at end of file
diff --git a/src/features/eventsGUI/index.js b/src/features/eventsGUI/index.js
new file mode 100644
index 0000000..90e6993
--- /dev/null
+++ b/src/features/eventsGUI/index.js
@@ -0,0 +1,287 @@
+///
+///
+import Enum from "../../../guimanager/Enum";
+import SoopyMouseClickEvent from "../../../guimanager/EventListener/SoopyMouseClickEvent";
+import BoxWithLoading from "../../../guimanager/GuiElement/BoxWithLoading";
+import ButtonWithArrow from "../../../guimanager/GuiElement/ButtonWithArrow";
+import SoopyGuiElement from "../../../guimanager/GuiElement/SoopyGuiElement";
+import SoopyMarkdownElement from "../../../guimanager/GuiElement/SoopyMarkdownElement";
+import SoopyTextElement from "../../../guimanager/GuiElement/SoopyTextElement";
+import TextBox from "../../../guimanager/GuiElement/TextBox";
+import Feature from "../../featureClass/class";
+import socketConnection from "../../socketConnection";
+import { numberWithCommas, timeSince } from "../../utils/numberUtils";
+import { firstLetterCapital, firstLetterWordCapital } from "../../utils/stringUtils";
+import GuiPage from "../soopyGui/GuiPage";
+
+class EventsGui extends Feature {
+ constructor() {
+ super()
+ }
+
+ onEnable() {
+ this.initVariables()
+
+ this.GuiPage = new EventsPage()
+
+ // this.registerChat("&9&m-----------------------------------------------------&r&9${*}&r&9 ${*} &6Friends (Page ${pagenum} of ${maxpages})${friendslist}&r&9&m-----------------------------------------------------&r", (...args) => { this.GuiPage.friendListMessageEvent.call(this.GuiPage, ...args) })
+ this.registerStep(true, 5, () => { this.GuiPage.regenGuiElements.call(this.GuiPage) })
+ this.registerStep(false, 10, () => { this.GuiPage.pollData.call(this.GuiPage) })
+ }
+
+ eventsDataUpdated(data) {
+ this.GuiPage.eventsDataUpdated(data)
+ }
+
+ joinEventResult(data) {
+ this.GuiPage.joinEventResult(data)
+ }
+
+ pollEventData(admin) {
+ this.GuiPage.pollEventData(admin)
+ }
+
+ initVariables() {
+ this.GuiPage = undefined
+ }
+
+ onDisable() {
+ this.initVariables()
+ }
+}
+
+
+class EventsPage extends GuiPage {
+ constructor() {
+ super(8)
+
+ this.name = "Events"
+
+ this.pages = [this.newPage()]
+
+ this.leaderboardElm = undefined
+ this.memberData = undefined
+
+ this.lastScroll = 1
+
+ this.leaderboardChildren = []
+
+ this.code = undefined
+
+ this.finaliseLoading()
+ }
+
+ updateNotInEvent() {
+ this.pages[0].clearChildren()
+
+ this.pages[0].addChild(new SoopyTextElement().setText("§0You are not currently in any events").setMaxTextScale(3).setLocation(0.2, 0.1, 0.6, 0.2))
+ this.pages[0].addChild(new SoopyTextElement().setText("§0If you have a join code enter it here").setMaxTextScale(1).setLocation(0.3, 0.4, 0.4, 0.1))
+ let joinBox = new TextBox().setPlaceholder("Code here").setLocation(0.3, 0.5, 0.4, 0.1)
+ this.pages[0].addChild(joinBox)
+
+ this.pages[0].addChild(new ButtonWithArrow().setLocation(0.35, 0.6, 0.3, 0.1).setText("§0Join Event").addEvent(new SoopyMouseClickEvent().setHandler(() => {
+
+ let code = joinBox.getText()
+
+ this.pages[0].clearChildren()
+ this.pages[0].addChild(new BoxWithLoading().setLocation(0.3, 0.3, 0.4, 0.4))
+
+ socketConnection.pollEventCode(code)
+
+ this.code = code
+ })))
+ }
+
+ updateInEvent(data) {
+ //MAIN PAGE
+
+ this.pages[0].clearChildren()
+
+ this.pages[0].addChild(new SoopyTextElement().setText("§0You are curently in an event managed by §6" + data.admin).setMaxTextScale(3).setLocation(0.1, 0.05, 0.8, 0.2))
+
+ if (!data.members[Player.getUUID().toString().replace(/-/g, "")]) {
+ this.pages[0].addChild(new ButtonWithArrow().setText("§0Join").setLocation(0.2, 0.2, 0.6, 0.1).addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.pages[0].clearChildren()
+ this.pages[0].addChild(new BoxWithLoading().setLocation(0.3, 0.3, 0.4, 0.4))
+
+ socketConnection.pollEventCode(data.code)
+
+ this.code = data.code
+ })))
+ }
+
+ let leaderboard = new SoopyGuiElement().setLocation(0.1, 0.3, 0.8, 0.7).setScrollable(true)
+
+ this.pages[0].addChild(leaderboard)
+
+ let playerPosition = -1
+
+ if (this.leaderboardElm) {
+ let scroll = this.leaderboardElm._scrollAmount
+
+ leaderboard._scrollAmount = scroll
+ leaderboard.location.scroll.y.set(scroll, 0)
+ }
+
+ this.leaderboardElm = leaderboard
+
+ Object.values(data.members).sort((a, b) => b.progress - a.progress).forEach((m, i) => {
+ let isPlayer = m.uuid === Player.getUUID().toString().replace(/-/g, "")
+
+ if (isPlayer) playerPosition = i + 1
+
+ let nameLine = new SoopyTextElement().setText(`${isPlayer ? "§d" : "§0"}#${i + 1} ${m.username}`).setLocation(0, i * 0.05, 0.5, 0.05).setLore(["Last updated " + timeSince(m.timestamp) + " ago", "Currently: " + (m.online ? "§aOnline" : "§cOffline")])
+ nameLine.timestamp = m.timestamp
+ nameLine.online = m.online
+ leaderboard.addChild(nameLine)
+
+ let lore = [
+ `TOTAL: §e${numberWithCommas(Math.floor(m.progress))}`,
+ ` `
+ ]
+ Object.keys(m.current.weights).map(w => {
+ let progress = m.current.weights[w] - m.starting.weights[w]
+
+ return [w, progress]
+ }).sort((a, b) => b[1] - a[1]).forEach((l, i) => {
+ if (i > 10) return
+
+ lore.push(firstLetterWordCapital(l[0].replace(/_/g, " ").replace(/^.+? /, "")) + ": §e" + numberWithCommas(Math.floor(l[1])))
+ })
+
+
+ leaderboard.addChild(new SoopyTextElement().setText(`§0+${numberWithCommas(Math.floor(m.progress))}`).setLocation(0.5, i * 0.05, 0.5, 0.05).setLore(lore))
+ })
+
+ this.leaderboardChildren = [...leaderboard.children]
+
+ this.lastScroll = 1
+
+ if (playerPosition >= 0) {
+ this.pages[0].addChild(new SoopyTextElement().setText("§0You are #" + playerPosition + " with +" + Math.floor(data.members[Player.getUUID().toString().replace(/-/g, "")].progress)).setMaxTextScale(2).setLocation(0.2, 0.2, 0.6, 0.1))
+ }
+
+ // SIDEBAR
+
+ let sideBarElm = new SoopyGuiElement().setLocation(0, 0, 1, 1).setScrollable(true)
+
+ sideBarElm.addChild(new SoopyTextElement().setText("§0Event Settings").setMaxTextScale(3).setLocation(0.1, 0, 0.8, 0.2))
+
+ if (Player.getUUID().toString().replace(/-/g, "") === data.admin) {
+ sideBarElm.addChild(new ButtonWithArrow().setText("§0Change").setMaxTextScale(3).setLocation(0.1, 0.2, 0.8, 0.2).addEvent(new SoopyMouseClickEvent().setHandler(() => {
+
+ })))
+ }
+
+ sideBarElm.addChild(new SoopyMarkdownElement().setLocation(0.05, 0.2, 0.9, 1).setText("# Tracking: \n" + data.settings.tracking.map(a => firstLetterCapital(a.replace(/\w+?_/, "").replace(/_/g, " "))).join("\n")))
+
+ this.openSidebarPage(sideBarElm)
+ }
+
+ regenGuiElements() {
+ if (!this.isOpen()) return
+
+ if (this.leaderboardElm) {
+ let scroll = this.leaderboardElm.location.scroll.y.get()
+ if (this.lastScroll !== scroll) {
+ this.lastScroll = scroll
+
+ this.leaderboardElm.children = []
+
+ let min = this.leaderboardElm.location.getYExact() - 100
+ let max = min + 200 + this.leaderboardElm.location.getHeightExact()
+ let lastChildNotAdded = undefined
+ this.leaderboardChildren.forEach(c => {
+ c.setParent(this.leaderboardElm)
+ c.triggerEvent(Enum.EVENT.RESET_FRAME_CACHES)
+
+ let y = c.location.getYExact()
+
+ if (y > min && y < max) {
+ this.leaderboardElm.children.push(c)
+ } else {
+ lastChildNotAdded = c
+ }
+ })
+
+ if (lastChildNotAdded) {
+ this.leaderboardElm.children.push(lastChildNotAdded)
+ }
+ }
+
+
+ this.leaderboardChildren.forEach(c => {
+ if (c.timestamp) {
+ c.setLore(["Last updated " + timeSince(c.timestamp) + " ago", "Currently: " + (c.online ? "§aOnline" : "§cOffline")])
+ }
+ })
+ }
+ }
+
+ eventsDataUpdated(data) {
+ if (!data.inEvent) {
+ this.updateNotInEvent()
+ return
+ }
+
+ this.updateInEvent(data)
+ }
+
+ pollEventData(admin) {
+ if (!admin) {
+ this.updateNotInEvent()
+ this.pages[0].addChild(new SoopyTextElement().setText("§cInvalid code").setMaxTextScale(3).setLocation(0.2, 0.7, 0.6, 0.2))
+ return
+ }
+ this.pages[0].clearChildren()
+ this.pages[0].addChild(new SoopyTextElement().setText("§0Join §6" + admin + "§0's event?").setMaxTextScale(3).setLocation(0.2, 0.2, 0.6, 0.2))
+ this.pages[0].addChild(new ButtonWithArrow().setText("§0Join").setLocation(0.4, 0.4, 0.4, 0.3).addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ socketConnection.joinEvent(this.code)
+ this.pages[0].clearChildren()
+ this.pages[0].addChild(new BoxWithLoading().setLocation(0.3, 0.3, 0.4, 0.4))
+ })))
+ this.pages[0].addChild(new ButtonWithArrow().setText("§0Cancel").setLocation(0.2, 0.4, 0.2, 0.3).setDirectionRight(false).addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.updateNotInEvent()
+ })))
+ }
+
+ joinEventResult(data) {
+ this.pages[0].clearChildren()
+ if (data.success) {
+ this.pages[0].addChild(new SoopyTextElement().setText("§0Joined event!").setMaxTextScale(3).setLocation(0.2, 0.2, 0.6, 0.2))
+ this.pages[0].addChild(new ButtonWithArrow().setText("§0Ok").setLocation(0.3, 0.4, 0.4, 0.4).addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.pages[0].clearChildren()
+ this.pages[0].addChild(new BoxWithLoading().setLocation(0.3, 0.3, 0.4, 0.4))
+
+ socketConnection.pollEventData()
+ })))
+ } else {
+ this.pages[0].addChild(new SoopyTextElement().setText("§0Unable to join event!").setMaxTextScale(3).setLocation(0.2, 0.2, 0.6, 0.1))
+ this.pages[0].addChild(new SoopyTextElement().setText("§0" + data.reason).setMaxTextScale(3).setLocation(0.2, 0.3, 0.6, 0.1))
+ this.pages[0].addChild(new ButtonWithArrow().setText("§0Ok").setLocation(0.3, 0.4, 0.4, 0.4).addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.pages[0].clearChildren()
+ this.pages[0].addChild(new BoxWithLoading().setLocation(0.3, 0.3, 0.4, 0.4))
+
+ socketConnection.pollEventData()
+ })))
+ }
+ }
+
+ pollData() {
+ if (!this.isOpen()) return
+
+ socketConnection.pollEventData()
+ }
+
+ onOpen() {
+ this.pages[0].clearChildren()
+ this.pages[0].addChild(new BoxWithLoading().setLocation(0.3, 0.3, 0.4, 0.4))
+
+ this.leaderboardElm = undefined
+ socketConnection.pollEventData()
+ }
+}
+
+module.exports = {
+ class: new EventsGui()
+}
\ No newline at end of file
diff --git a/src/features/eventsGUI/metadata.json b/src/features/eventsGUI/metadata.json
new file mode 100644
index 0000000..b7b1f6f
--- /dev/null
+++ b/src/features/eventsGUI/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Friends gui",
+ "description": "Gui for friends",
+ "isHidden": true,
+ "isTogglable": false,
+ "defaultEnabled": true,
+ "sortA": 0
+}
\ No newline at end of file
diff --git a/src/features/featureBase/index.js b/src/features/featureBase/index.js
new file mode 100644
index 0000000..2a96a7f
--- /dev/null
+++ b/src/features/featureBase/index.js
@@ -0,0 +1,24 @@
+///
+///
+import Feature from "../../featureClass/class";
+
+class FeatureBase extends Feature {
+ constructor() {
+ super()
+ }
+
+ onEnable() {
+ this.initVariables()
+ }
+
+ initVariables() {
+ }
+
+ onDisable() {
+ this.initVariables()
+ }
+}
+
+module.exports = {
+ class: new FeatureBase()
+}
\ No newline at end of file
diff --git a/src/features/featureBase/metadata.json b/src/features/featureBase/metadata.json
new file mode 100644
index 0000000..a6b411d
--- /dev/null
+++ b/src/features/featureBase/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Feature Base",
+ "description": "Copy paste and edit this to create a new feature",
+ "isHidden": true,
+ "isTogglable": false,
+ "defaultEnabled": false,
+ "sortA": 1
+}
\ No newline at end of file
diff --git a/src/features/fpsImproveGui/index.js b/src/features/fpsImproveGui/index.js
new file mode 100644
index 0000000..416d754
--- /dev/null
+++ b/src/features/fpsImproveGui/index.js
@@ -0,0 +1,49 @@
+///
+///
+import Feature from "../../featureClass/class";
+import GuiPage from "../soopyGui/GuiPage";
+
+class FpsImproveGui extends Feature {
+ constructor() {
+ super()
+ }
+
+ onEnable() {
+ this.initVariables()
+
+ // this.GuiPage = new FpsPage()
+
+ }
+
+ initVariables() {
+ this.GuiPage = undefined
+ }
+
+ onDisable() {
+ this.initVariables()
+ }
+}
+
+
+class FpsPage extends GuiPage {
+ constructor() {
+ super(7)
+
+ this.name = "Fps Improve Tips"
+
+ this.pages = [this.newPage()]
+
+ // this.pages[0].addChild(this.streamsBox)
+
+ this.finaliseLoading()
+ }
+
+ onOpen() {
+ this.updateStreams()
+ }
+}
+
+
+module.exports = {
+ class: new FpsImproveGui()
+}
\ No newline at end of file
diff --git a/src/features/fpsImproveGui/metadata.json b/src/features/fpsImproveGui/metadata.json
new file mode 100644
index 0000000..a292c1d
--- /dev/null
+++ b/src/features/fpsImproveGui/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Fps improvement tips",
+ "description": "May help",
+ "isHidden": true,
+ "isTogglable": false,
+ "defaultEnabled": true,
+ "sortA": 0
+}
\ No newline at end of file
diff --git a/src/features/fragBot/index.js b/src/features/fragBot/index.js
new file mode 100644
index 0000000..2b89203
--- /dev/null
+++ b/src/features/fragBot/index.js
@@ -0,0 +1,84 @@
+///
+///
+import Feature from "../../featureClass/class";
+import SettingBase from "../settings/settingThings/settingBase";
+import ToggleSetting from "../settings/settingThings/toggle";
+
+class FragBot extends Feature {
+ constructor() {
+ super()
+ }
+
+ onEnable() {
+ this.initVariables()
+
+ this.hostingFragBot = false
+ this.fragBotQueue = []
+ this.commandQueue = []
+
+ new SettingBase("To host a fragbot use /fragbot", "", undefined, "host_fragbot_info", this)
+ new SettingBase("NOTE: All this does atm is accept party invites", "More features for this coming soon", true, "stat_next_to_name_description", this)
+
+ // this.uploadToWebsite = new ToggleSetting("Advertise fragbot status", "Will show up as a fragbot in other peoples fragbot lists", true, "advertise_fragbot", this)
+
+ this.registerCommand("fragbot", this.fragbotCommand)
+
+ this.registerStep(false, 5, this.step).registeredWhen(() => this.hostingFragBot)
+ this.registerStep(true, 2, this.step2).registeredWhen(() => this.hostingFragBot)
+
+ this.registerChat("&9&m---------------------------${*}&r&9\n&r${player} &r&ehas invited you to join their party!\n&r&eYou have &r&c60 &r&eseconds to accept. &r&6Click here to join!&r&9\n&r&9&m----------------------------${*}&r", this.recievedPartyInvite)
+ }
+
+ step() {
+ if (!this.hostingFragBot) return
+
+ if (this.fragBotQueue.length > 0) {
+ let player = this.fragBotQueue.shift()
+ if (player) {
+ this.commandQueue.push("/party leave")
+
+ this.commandQueue.push("/party accept " + player)
+ }
+ }
+ }
+ step2() {
+ if (!this.hostingFragBot) return
+
+ if (this.commandQueue.length > 0) {
+ let command = this.commandQueue.shift()
+ if (command) {
+ ChatLib.say(command)
+ }
+ }
+ }
+ recievedPartyInvite(player) {
+ if (!this.hostingFragBot) return
+ player = ChatLib.removeFormatting(player).split(" ").pop()
+
+ this.fragBotQueue.push(player)
+ }
+
+ fragbotCommand(...args) {
+ if (this.hostingFragBot) {
+ this.hostingFragBot = false
+ ChatLib.chat(this.FeatureManager.messagePrefix + "Fragbot has been disabled")
+ } else {
+ this.hostingFragBot = true
+ ChatLib.chat(this.FeatureManager.messagePrefix + "Now acting as a fragbot, run /fragbot again to disable")
+ }
+ }
+
+ initVariables() {
+ this.hostingFragBot = undefined
+ this.fragBotQueue = undefined
+ this.commandQueue = undefined
+ }
+
+ onDisable() {
+ this.initVariables()
+ }
+}
+
+module.exports = {
+ class: new FragBot()
+}
\ No newline at end of file
diff --git a/src/features/fragBot/metadata.json b/src/features/fragBot/metadata.json
new file mode 100644
index 0000000..5aaa6a9
--- /dev/null
+++ b/src/features/fragBot/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Frag Bot",
+ "description": "Features to assist using fragbots, or to host one",
+ "isHidden": false,
+ "isTogglable": true,
+ "defaultEnabled": true,
+ "sortA": 1
+}
\ No newline at end of file
diff --git a/src/features/friendsGUI/index.js b/src/features/friendsGUI/index.js
new file mode 100644
index 0000000..d4ac2f4
--- /dev/null
+++ b/src/features/friendsGUI/index.js
@@ -0,0 +1,363 @@
+///
+///
+import { SoopyRenderEvent } from "../../../guimanager";
+import ButtonWithArrowAndDescription from "../../../guimanager/GuiElement/ButtonWithArrowAndDescription";
+import SoopyGuiElement from "../../../guimanager/GuiElement/SoopyGuiElement";
+import SoopyTextElement from "../../../guimanager/GuiElement/SoopyTextElement";
+import BoxWithLoading from "../../../guimanager/GuiElement/BoxWithLoading";
+import Feature from "../../featureClass/class";
+import GuiPage from "../soopyGui/GuiPage";
+import SoopyMouseClickEvent from "../../../guimanager/EventListener/SoopyMouseClickEvent";
+import ButtonWithArrow from "../../../guimanager/GuiElement/ButtonWithArrow";
+import ProgressBar from "../../../guimanager/GuiElement/ProgressBar";
+import logger from "../../logger";
+import SoopyMarkdownElement from "../../../guimanager/GuiElement/SoopyMarkdownElement";
+
+class FriendsGui extends Feature {
+ constructor() {
+ super()
+ }
+
+ onEnable() {
+ this.initVariables()
+
+ this.GuiPage = new SettingPage()
+
+ this.registerChat("&9&m-----------------------------------------------------&r&9${*}&r&9 ${*} &6Friends (Page ${pagenum} of ${maxpages})${friendslist}&r&9&m-----------------------------------------------------&r", (...args) => { this.GuiPage.friendListMessageEvent.call(this.GuiPage, ...args) })
+ this.registerStep(true, 5, () => { this.GuiPage.regenGuiElements.call(this.GuiPage) })
+
+ this.registerStep(false, 1, () => { this.GuiPage.runComm.call(this.GuiPage) })
+ }
+
+ initVariables() {
+ this.GuiPage = undefined
+ }
+
+ onDisable() {
+ this.initVariables()
+ }
+}
+
+
+class SettingPage extends GuiPage {
+ constructor() {
+ super(7)
+
+ this.name = "Friends"
+
+ this.pages = [this.newPage()]
+
+ this.lastRender = 0
+
+ this.pages[0].addEvent(new SoopyRenderEvent().setHandler(() => { this.lastRender = Date.now() }))
+
+
+ let friendsTitle = new SoopyTextElement().setText("§0Friends").setMaxTextScale(3).setLocation(0.1, 0.05, 0.8, 0.1)
+ this.pages[0].addChild(friendsTitle)
+
+ this.friendsArea = new SoopyGuiElement().setLocation(0.1, 0.2, 0.8, 0.8).setScrollable(true)
+ this.pages[0].addChild(this.friendsArea)
+
+ this.loadedFriends = {}
+
+ this.loadedPages = new Set()
+
+ this.selectedFriends = new Set()
+
+ this.allFriendsLoaded = false
+
+ this.pageCount = undefined
+
+ this.sidebar = new SoopyGuiElement()
+
+ this.sidebarCustomPage = undefined
+
+ this.sidebarMainPage = new SoopyGuiElement().setLocation(0, 0, 1, 1)
+
+ this.heightPerFriend = 0.15
+ this.loadingElement = new BoxWithLoading().setLocation(0, 0, 1, 0.175)
+ this.lastLoadedPage = 0
+ this.maxLoadedPage = 0
+
+ this.unfriendMode = false
+
+ this.loadingElement.addEvent(new SoopyRenderEvent().setHandler(() => {
+ if (Date.now() - this.lastLoadedPage > 1000) {
+ this.loadFriendPage(this.maxLoadedPage + 1)
+ }
+ }))
+
+ this.commandQueue = []
+
+ this.updateSidebar()
+
+ this.finaliseLoading()
+ }
+
+ loadAllFriends() {
+ let commands = []
+ for (let i = this.maxLoadedPage + 1; i < this.pageCount + 1; i++) {
+ commands.push("/friend list " + i)
+ }
+
+ this.runCommandsArray(commands)
+ }
+
+ runCommandsArray(commands, callback) {
+ this.sidebarCustomPage = new SoopyGuiElement().setLocation(0, 0, 1, 1)
+
+
+ this.sidebarCustomPage.addChild(
+ new ButtonWithArrow().setText("§0CANCEL!").setLocation(0.1, 0.20, 0.8, 0.1)
+ .addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.commandQueue = []
+ this.sidebarCustomPage = undefined
+
+ this.updateSidebar()
+
+ if (callback) callback()
+ })))
+
+ this.sidebarCustomPage.addChild(new SoopyTextElement().setText("§0Running commands...").setLocation(0.2, 0.1, 0.6, 0.1).setMaxTextScale(10))
+
+
+ let progressBar = new ProgressBar().setProgress(0).setLocation(0.2, 0.3, 0.6, 0.1)
+
+ let elements = []
+
+ this.sidebarCustomPage.addChild(progressBar)
+ for (let i = 0; i < commands.length; i++) {
+ let i2 = i
+
+ elements.push(new SoopyTextElement().setText("§0" + commands[i]).setLocation(0.2, 0.4 + i * 0.025, 0.6, 0.025))
+
+ this.runCommand(commands[i], () => {
+ progressBar.setProgress((i2 + 1) / (commands.length), 1000)
+
+ let e = elements.shift()
+ this.sidebarCustomPage.removeChild(e)
+
+ elements.forEach((e, i) => {
+ e.location.location.y.set(0.4 + i * 0.025, 500)
+ })
+
+ if (i2 === commands.length - 1) {
+ this.sidebarCustomPage = undefined
+
+ this.updateSidebar()
+
+ if (callback) callback()
+ }
+ })
+ }
+
+ for (let e of elements) {
+ this.sidebarCustomPage.addChild(e)
+ }
+ }
+
+ updateSidebar() {
+ this.sidebar.clearChildren()
+ if (this.sidebarCustomPage) {
+ this.sidebar.addChild(this.sidebarCustomPage)
+ return
+ }
+
+ this.sidebarMainPage.clearChildren()
+ if (this.selectedFriends.size > 0) {
+ this.sidebarMainPage.addChild(
+ new SoopyTextElement().setText("§0" + this.selectedFriends.size + " friends selected").setMaxTextScale(2).setLocation(0.1, 0.05, 0.8, 0.1))
+
+ this.sidebarMainPage.addChild(
+ new ButtonWithArrow().setText("§0Deselect all").setLocation(0.1, 0.15, 0.8, 0.1)
+ .addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.selectedFriends.clear()
+
+ this.regenGuiElements()
+ this.updateSidebar()
+ })))
+ this.sidebarMainPage.addChild(
+ new ButtonWithArrow().setText("§0Unfriend all").setLocation(0.1, 0.25, 0.8, 0.1)
+ .addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ let commands = []
+
+ for (let f of this.selectedFriends) {
+ this.loadedFriends[f].exists = false
+ commands.push("/friend remove " + f)
+ }
+ this.selectedFriends.clear()
+
+ this.runCommandsArray(commands)
+ this.updateSidebar()
+ })))
+
+
+ } else {
+ if (!this.allFriendsLoaded) {
+ this.sidebarMainPage.addChild(
+ new ButtonWithArrow().setText("§0Load all friends").setLocation(0.1, 0.1, 0.8, 0.15)
+ .addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.loadAllFriends()
+
+ this.updateSidebar()
+ })))
+ } else {
+ this.sidebarMainPage.addChild(
+ new ButtonWithArrow().setText("§0Select all").setLocation(0.1, 0.1, 0.8, 0.15)
+ .addEvent(new SoopyMouseClickEvent().setHandler(() => {
+
+ Object.keys(this.loadedFriends).forEach((ign, i) => {
+ if (this.loadedFriends[ign].exists) {
+ this.selectedFriends.add(ign)
+ }
+ })
+
+ this.regenGuiElements()
+ this.updateSidebar()
+ })))
+ }
+ }
+
+ this.sidebar.addChild(this.sidebarMainPage)
+ }
+
+ runCommand(command, callback) {
+ this.commandQueue.push([command, callback])
+ }
+
+ runComm() {
+ if (this.commandQueue.length > 0 && this.isOpen()) {
+ let [c, callback] = this.commandQueue.shift()
+ ChatLib.say(c)
+ logger.logMessage("running command " + c, 3)
+ callback()
+ }
+ }
+
+ friendListMessageEvent(pagenum, maxpages, friendslist, event) {
+ if (Date.now() - this.lastLoadedPage < 3000 || this.isOpen()) {
+ cancel(event)
+ // console.log("Canceling")
+ } else {
+ return
+ }
+
+ this.maxLoadedPage = parseInt(pagenum)
+
+ this.pageCount = parseInt(maxpages)
+
+ this.allFriendsLoaded = this.maxLoadedPage === this.pageCount
+
+ friendslist = friendslist.replace(/\-\>newLine\<\-/g, "\n").split("\n")
+ friendslist.shift()
+
+ friendslist.pop()
+
+ friendslist.forEach((line, i) => {
+ let [name, location] = line.split(" is ")
+
+ if (location) {
+ if (this.loadedFriends[ChatLib.removeFormatting(name)]) {
+ this.loadedFriends[ChatLib.removeFormatting(name)].nameWithFormatting = name
+ this.loadedFriends[ChatLib.removeFormatting(name)].exists = true
+ this.loadedFriends[ChatLib.removeFormatting(name)].currentGame = location.replace("in ", "").replace("currently offline", "&cCurrently offline")
+ this.loadedFriends[ChatLib.removeFormatting(name)].element.setText(name).setDesc("&7" + location.replace("in ", "").replace("currently offline", "&cCurrently offline"))
+ } else {
+ this.loadedFriends[ChatLib.removeFormatting(name)] = {
+ nameWithFormatting: name,
+ exists: true,
+ currentGame: location.replace("in ", "").replace("currently offline", "&cCurrently offline"),
+ element: new ButtonWithArrowAndDescription().setLocation(0, this.heightPerFriend * Object.keys(this.loadedFriends).length + 1, 1, this.heightPerFriend * 0.875).setText(name).setDesc("&7" + location.replace("in ", "").replace("currently offline", "&cCurrently offline")).addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.clickedOn(ChatLib.removeFormatting(name))
+ }))
+ }
+ this.loadedFriends[ChatLib.removeFormatting(name)].element.location.location.y.set(this.heightPerFriend * Object.keys(this.loadedFriends).length - this.heightPerFriend, 500 + 100 * i)
+ }
+ }
+ });
+
+ this.regenGuiElements()
+ }
+
+ clickedOn(name) {
+ if (this.selectedFriends.has(name)) {
+ this.selectedFriends.delete(name)
+ } else {
+ this.selectedFriends.add(name)
+ }
+ // this.commandQueue.push("/friend remove " + ChatLib.removeFormatting(name))
+
+ // this.loadedFriends[ChatLib.removeFormatting(name)].exists = false
+
+ this.regenGuiElements()
+ this.updateSidebar()
+ }
+
+ regenGuiElements() {
+ if (Date.now() - this.lastRender < 1000) {
+ this.friendsArea.children = []
+
+ let scroll = this.friendsArea.location.scroll.y.get() / this.friendsArea.location.getHeightExact()
+
+ let minY = -scroll - this.heightPerFriend * 0.875 - 0.5
+
+ let maxY = -scroll + 1.5
+
+ Object.keys(this.loadedFriends).forEach((ign, i) => {
+ /**@type {ButtonWithArrowAndDescription} */
+ let e = this.loadedFriends[ign].element
+
+ if (this.loadedFriends[ign].exists && e.location.location.y.get() > minY && e.location.location.y.get() < maxY) {
+ this.friendsArea.addChild(e)
+
+ if (this.selectedFriends.has(ign)) {
+ e.setColor(100, 255, 100)
+ } else {
+ e.setColor(253, 255, 227)
+ }
+ }
+ })
+
+ this.loadingElement.location.location.y.set(this.heightPerFriend * Object.keys(this.loadedFriends).length, 500)
+ this.friendsArea.addChild(this.loadingElement)
+
+ if (this.maxLoadedPage !== this.pageCount) {
+ this.loadingElement.visable = true
+ } else {
+ this.loadingElement.visable = false
+ }
+ }
+ }
+
+ loadFriendPage(page, callback) {
+ if (this.loadedPages.has(page)) return
+
+ this.loadedPages.add(page)
+ this.runCommand("/friends list " + page, () => {
+ this.lastLoadedPage = Date.now()
+ if (callback) callback()
+ })
+ }
+
+ onOpen() {
+ this.loadedFriends = {}
+ this.pageCount = undefined
+ this.lastLoadedPage = 0
+ this.maxLoadedPage = 0
+
+ this.sidebarCustomPage = undefined
+ this.commandQueue = []
+
+ this.loadedPages.clear()
+
+ this.regenGuiElements()
+
+ this.loadFriendPage(1)
+ this.openSidebarPage(this.sidebar)
+ this.updateSidebar()
+ }
+}
+
+module.exports = {
+ class: new FriendsGui()
+}
\ No newline at end of file
diff --git a/src/features/friendsGUI/metadata.json b/src/features/friendsGUI/metadata.json
new file mode 100644
index 0000000..b7b1f6f
--- /dev/null
+++ b/src/features/friendsGUI/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Friends gui",
+ "description": "Gui for friends",
+ "isHidden": true,
+ "isTogglable": false,
+ "defaultEnabled": true,
+ "sortA": 0
+}
\ No newline at end of file
diff --git a/src/features/globalSettings/firstLoadPage.js b/src/features/globalSettings/firstLoadPage.js
new file mode 100644
index 0000000..62805f5
--- /dev/null
+++ b/src/features/globalSettings/firstLoadPage.js
@@ -0,0 +1,42 @@
+import SoopyMouseClickEvent from "../../../guimanager/EventListener/SoopyMouseClickEvent"
+import ButtonWithArrow from "../../../guimanager/GuiElement/ButtonWithArrow"
+import SoopyGuiElement from "../../../guimanager/GuiElement/SoopyGuiElement"
+
+class FirstLoadPage extends SoopyGuiElement {
+ constructor() {
+ super()
+
+ this.setLocation(0, 0, 1, 1)
+
+ this.guiPage = undefined
+ }
+
+ setLoc(addBack, addNext) {
+ if (addBack) {
+ let backButton = new ButtonWithArrow().setLocation(0.05, 0.85, 0.2, 0.1).setDirectionRight(false).setText("§0Back")
+
+ backButton.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.guiPage.prevPage()
+ this.guiPage.closeSidebarPage()
+ }))
+
+ this.addChild(backButton)
+ }
+ if (addNext) {
+ let nextButton = new ButtonWithArrow().setLocation(0.75, 0.85, 0.2, 0.1).setText("§0Next")
+
+ nextButton.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.guiPage.nextPage()
+ this.guiPage.closeSidebarPage()
+ }))
+
+ this.addChild(nextButton)
+ }
+ }
+
+ load() {
+
+ }
+}
+
+export default FirstLoadPage
\ No newline at end of file
diff --git a/src/features/globalSettings/firstLoadPages.js b/src/features/globalSettings/firstLoadPages.js
new file mode 100644
index 0000000..2975a69
--- /dev/null
+++ b/src/features/globalSettings/firstLoadPages.js
@@ -0,0 +1,135 @@
+import SoopyMouseClickEvent from "../../../guimanager/EventListener/SoopyMouseClickEvent";
+import ButtonWithArrow from "../../../guimanager/GuiElement/ButtonWithArrow";
+import SoopyGuiElement from "../../../guimanager/GuiElement/SoopyGuiElement";
+import SoopyTextElement from "../../../guimanager/GuiElement/SoopyTextElement";
+import Notification from "../../../guimanager/Notification";
+import FeatureManager from "../../featureClass/featureManager";
+import FirstLoadPage from "./firstLoadPage";
+
+class WelcomePage extends FirstLoadPage {
+ constructor() {
+ super()
+
+ this.addChild(new SoopyTextElement().setText("§0Welcome to SoopyV2!").setLocation(0.1, 0.05, 0.8, 0.1).setMaxTextScale(10));
+
+ this.addChild(new SoopyTextElement().setText("§7This menu will guide you through important settings").setLocation(0.1, 0.15, 0.8, 0.075).setMaxTextScale(10));
+ // this.addChild(new SoopyTextElement().setText("§7First lets get privacy settings out of the way.").setLocation(0.1, 0.15,0.8,0.075).setMaxTextScale(10));
+
+ this.settingsArea = new SoopyGuiElement().setLocation(0.1, 0.25, 0.8, 0.75);
+ this.settingsArea.setScrollable(true)
+
+ this.addChild(this.settingsArea);
+ }
+
+ load() {
+ let y = 0
+
+ this.guiPage.mainThing.firstPageSettings.forEach(setting => {
+ setting = setting.getGuiObject()
+
+ setting.location.location.y.set(y, 0)
+
+ this.settingsArea.addChild(setting);
+
+ y += 0.045 + setting.location.size.y.get()
+ })
+ }
+}
+class ApiKeyPage extends FirstLoadPage {
+ constructor() {
+ super()
+
+ this.addChild(new SoopyTextElement().setText("§0First lets setup your api key!").setLocation(0.1, 0.05, 0.8, 0.1).setMaxTextScale(10));
+
+ this.addChild(new SoopyTextElement().setText("§7You can skip this but some features may not work").setLocation(0.1, 0.15, 0.8, 0.075).setMaxTextScale(10));
+
+ this.settingsArea = new SoopyGuiElement().setLocation(0.1, 0.25, 0.8, 0.75);
+ this.settingsArea.setScrollable(true)
+
+ this.addChild(this.settingsArea);
+ }
+
+ load() {
+ let y = 0
+
+ let settings = [this.guiPage.mainThing.apiKeySetting, this.guiPage.mainThing.verifyApiKey, this.guiPage.mainThing.findApiKey, this.guiPage.mainThing.newApiKey]
+ settings.forEach(setting => {
+ setting = setting.getGuiObject()
+
+ setting.location.location.y.set(y, 0)
+
+ this.settingsArea.addChild(setting);
+
+ y += 0.045 + setting.location.size.y.get()
+ })
+ }
+}
+
+class HowToOpenMenuPage extends FirstLoadPage {
+ constructor() {
+ super()
+
+ this.addChild(new SoopyTextElement().setText("§0Your all set!").setLocation(0.1, 0.1, 0.8, 0.3).setMaxTextScale(10));
+
+ this.addChild(new SoopyTextElement().setText("§7To change any settings, or to access this menu again run §2/soopy§7.").setLocation(0.1, 0.3, 0.8, 0.1).setMaxTextScale(10));
+
+ let openSettingsButton = new ButtonWithArrow().setText("§0Open settings").setLocation(0.1, 0.5, 0.3, 0.2).setDirectionRight(false)
+
+ openSettingsButton.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ ChatLib.command("soopyv2", true)
+ }))
+
+ this.addChild(openSettingsButton);
+
+ let closeButton = new ButtonWithArrow().setText("§0Close").setLocation(0.6, 0.5, 0.3, 0.2)
+
+ closeButton.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ Client.currentGui.close()
+ }))
+
+ this.addChild(closeButton);
+
+ }
+}
+
+class DisableFeatures extends FirstLoadPage {
+ constructor() {
+ super()
+
+ this.addChild(new SoopyTextElement().setText("§0Lastly do you want to disable all features?").setLocation(0.1, 0.1, 0.8, 0.3).setMaxTextScale(10));
+
+ this.addChild(new SoopyTextElement().setText("§7(So you can only enable the ones you want)").setLocation(0.1, 0.3, 0.8, 0.1).setMaxTextScale(10));
+
+ let openSettingsButton = new ButtonWithArrow().setText("§0Disable all features").setLocation(0.35, 0.5, 0.3, 0.2)
+
+ openSettingsButton.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+
+ new Thread(() => {
+ new Notification("Disabling features...", [])
+ Object.keys(FeatureManager.featureMetas).forEach((f) => {
+ let meta = FeatureManager.featureMetas[f]
+
+ let isHidden = meta.isHidden
+ if (typeof isHidden === "string") {
+ return
+ }
+ if (isHidden) return
+ if (!meta.isTogglable) return
+
+ FeatureManager.featureSettingsData[f].enabled = false
+ FeatureManager.featureSettingsDataLastUpdated = true
+
+ if (FeatureManager.isFeatureLoaded(f)) {
+ FeatureManager.unloadFeature(f)
+ }
+ })
+ new Notification("Disabled all features!", [])
+ }).start()
+ }))
+
+ this.addChild(openSettingsButton);
+
+ }
+}
+
+export default [new WelcomePage(), new ApiKeyPage(), new DisableFeatures(), new HowToOpenMenuPage()]
\ No newline at end of file
diff --git a/src/features/globalSettings/index.js b/src/features/globalSettings/index.js
new file mode 100644
index 0000000..b135337
--- /dev/null
+++ b/src/features/globalSettings/index.js
@@ -0,0 +1,1121 @@
+///
+///
+import Feature from "../../featureClass/class";
+import ButtonSetting from "../settings/settingThings/button";
+import TextSetting from "../settings/settingThings/textSetting";
+import ToggleSetting from "../settings/settingThings/toggle";
+import HudTextElement from "../hud/HudTextElement";
+import LocationSetting from "../settings/settingThings/location";
+import firstLoadPages from "./firstLoadPages";
+import GuiPage from "../soopyGui/GuiPage"
+import Notification from "../../../guimanager/Notification";
+import logger from "../../logger";
+import { numberWithCommas } from "../../utils/numberUtils";
+import { firstLetterCapital } from "../../utils/stringUtils";
+import { fetch } from "../../utils/networkUtils";
+import socketConnection from "../../socketConnection";
+import renderLibs from "../../../guimanager/renderLibs";
+import { f, m } from "../../../mappings/mappings";
+import { addLore, getSBUUID, toMessageWithLinks } from "../../utils/utils";
+import { delay } from "../../utils/delayUtils";
+import { SoopyGui } from "../../../guimanager";
+import SoopyImageElement from "../../../guimanager/GuiElement/SoopyImageElement";
+const Files = Java.type("java.nio.file.Files")
+const Paths = Java.type("java.nio.file.Paths")
+const JavaString = Java.type("java.lang.String")
+const JavaLong = Java.type("java.lang.Long")
+
+let hecatombLevels = [2, 5, 10, 20, 30, 40, 60, 80, 100]
+let championLevels = [50000, 100000, 250000, 500000, 1000000, 1500000, 2000000, 2500000, 3000000]
+
+class GlobalSettings extends Feature {
+ constructor() {
+ super()
+
+ this.initVariables()
+ }
+
+ initVariables() {
+ this.apiKeySetting = undefined
+ this.GuiPage = undefined
+ }
+
+ onEnable() {
+ this.apiKeySetting = new TextSetting("Api Key", "Your hypixel api key", "", "api_key", this, "Run /api new to load", true)
+ this.verifyApiKey = new ButtonSetting("Verify api key", "Click this to make sure the api key is working", "verify_key", this, "Click!", this.verifyKey2, undefined)
+ this.newApiKey = new ButtonSetting("Run /api new", "This is here so u dont need to exit and re-enter", "api_new_command", this, "Click!", this.apiNewCommand, undefined)
+ this.findApiKey = new ButtonSetting("Attempt to load api key from other mods", "This will scan other mods configs to attempt to find your key", "find_key", this, "Click!", () => { this.findKey() }, undefined)
+
+ this.alertAllUpdates = new ToggleSetting("Send chat update avalible for all updates", "If disabled itll notify for new updates less", false, "alert_all_updates", this)
+
+ this.fixNeuNetworth = new ToggleSetting("Change networth in NEU pv to soopynw", "This should make it a lot more accurate", true, "neu_nw_override", this)
+ this.darkTheme = new ToggleSetting("Dark theme", "This might be scuffed because guis are still made in light theme", false, "dark_theme", this)
+ // this.linkPreview = new ToggleSetting("Link preview", "Shows a preview of where a link will take you", true, "link_preview", this)
+
+ // this.reportErrorsSetting = new ToggleSetting("Send module errors to soopy server", "This will allow me to more effectivly fix them", false, "privacy_send_errors", this)
+
+ this.hideFallingBlocks = new ToggleSetting("Hide falling blocks", "NOTE: This setting is a bit laggy", false, "hide_falling_sand", this)
+ this.twitchCommands = new ToggleSetting("Ingame twitch bot commands", "Allows u to use twitch bot commands ingame (eg -sa)", true, "twitch_commands_ingame", this)
+ this.handChat = new ToggleSetting("Replace [hand] with ur currently held item", "Idea from Synthesis im only adding cus i dont have D:", true, "hand_chat", this)
+ this.itemWorth = new ToggleSetting("(Approximate) Item worth in lore", "Accounts for stuff like enchants/recombs ect", false, "item_worth", this)
+ this.showHecatomb = new ToggleSetting("Show hecatomb enchant info in lore", "", true, "show_hecatomb", this)
+ this.showChampion = new ToggleSetting("Show champion enchant info in lore", "", true, "show_champion", this)
+
+ this.thunderBottle = new ToggleSetting("Thunder Bottle Progress Display", "shows you the progress of thunder bottle in your inventory", false, "thunder_bottle", this);
+ this.thunderBottleElement = new HudTextElement()
+ .setText("")
+ .setToggleSetting(this.thunderBottle)
+ .setLocationSetting(new LocationSetting("Thunder Bottle Progress location", "Allows you to change location of this display", "thunder_bottle_location", this, [20, 100, 1, 1]).requires(this.thunderBottle).editTempText(`&6Thunder Charge&7> &f49,999&7/&750,000`));
+ this.hudElements.push(this.thunderBottleElement);
+ this.thunderBottleFull = new ToggleSetting("Thunder Bottle Full Alert", "Alert when your thunder bottle is fully charged", false, "thunder_bottle_full", this);
+
+ this.oldMasterStars = new ToggleSetting("Use Old Master Stars", "replaces the ugly new master star on item name with the old fashion one", false, "old_master_star", this)
+ this.sbaItemPickUpLog = new ToggleSetting("Sba Item Pick Up Log", "Same as sba item pick up log, but fixes old master stars making it go brrr", false, "sba_item_log", this);
+ this.sbaItemPickUpLogElement = new HudTextElement()
+ .setText("")
+ .setToggleSetting(this.sbaItemPickUpLog)
+ .setLocationSetting(new LocationSetting("Sba Item Pick Up Log location", "Allows you to change location of this display", "sba_item_log_location", this, [10, 100, 1, 1]).requires(this.sbaItemPickUpLog).editTempText(`&a+ 1x &dHeroic Hyperion &c✪✪✪✪✪\n&c- 1x &dHeroic Hyperion &6✪✪✪✪✪`));
+ this.hudElements.push(this.sbaItemPickUpLogElement);
+ this.maxAmount = new TextSetting("Pickup Log Line Limit", "Basically after this length it doesn't log anymore", "20", "item_log_max_amount", this, "20", false).requires(this.sbaItemPickUpLog);
+
+ this.fancyVanquisherAlert = new ToggleSetting("Fancy Vanquisher Alert", "Alert when a Vanquisher spawned", false, "fancy_vanquisher_alert", this);
+ this.fancySeaCreaturesAlert = new ToggleSetting("Fancy Sea Creatures Alert", "Alert when you caught x creature (this is the main toggle)", false, "fancy_sc_alert", this);
+ this.fancySeaCreaturesAlertThunder = new ToggleSetting("Fancy Thunder Alert", "Alert when you caught Thunder creature", false, "fancy_thunder_alert", this).requires(this.fancySeaCreaturesAlert);
+ this.fancySeaCreaturesAlertJawbus = new ToggleSetting("Fancy Jawbus Alert", "Alert when you caught Lord Jawbus creature", false, "fancy_jawbus_alert", this).requires(this.fancySeaCreaturesAlert);
+
+ this.registerEvent('itemTooltip', (lore, i, e) => {
+ if (!this.oldMasterStars.getValue()) return
+ if (!i) return
+ let itemName = i.getName()
+ let itemNameReformat = itemName.removeFormatting()
+ if (itemNameReformat.endsWith("➊")) {
+ let newItemName = itemName.replace("§6✪§6✪§6✪§6✪§6✪§c➊", "§c✪§6✪✪✪✪")
+ i.setName(newItemName)
+ this.saveItemData(getSBUUID(i), newItemName)
+ return
+ }
+ if (itemNameReformat.endsWith("➋")) {
+ let newItemName = itemName.replace("§6✪§6✪§6✪§6✪§6✪§c➋", "§c✪✪§6✪✪✪")
+ i.setName(newItemName)
+ this.saveItemData(getSBUUID(i), newItemName)
+ return
+ }
+ if (itemNameReformat.endsWith("➌")) {
+ let newItemName = itemName.replace("§6✪§6✪§6✪§6✪§6✪§c➌", "§c✪✪✪§6✪✪")
+ i.setName(newItemName)
+ this.saveItemData(getSBUUID(i), newItemName)
+ return
+ }
+ if (itemNameReformat.endsWith("➍")) {
+ let newItemName = itemName.replace("§6✪§6✪§6✪§6✪§6✪§c➍", "§c✪✪✪✪§6✪")
+ i.setName(newItemName)
+ this.saveItemData(getSBUUID(i), newItemName)
+ return
+ }
+ if (itemNameReformat.endsWith("➎")) {
+ let newItemName = itemName.replace("§6✪§6✪§6✪§6✪§6✪§c➎", "§c✪✪✪✪✪")
+ i.setName(newItemName)
+ this.saveItemData(getSBUUID(i), newItemName)
+ return
+ }
+ })
+
+ this.registerEvent('worldLoad', this.worldLoad)
+
+ this.itemData = {};
+ this.oldItemData = {};
+ this.initOldItemData();
+ this.todoPickUpLog = {};
+ this.clearLog = false;
+
+ this.registerStep(true, 5, this.step5Fps)
+ //4 chat registeries below prevents pickup log to go brrr when warping
+ this.registerChat("&r&c ☠ ${info} and became a ghost&r&7.&r", (info, e) => {
+ if (info.includes("You")) this.preventGoingBrrr();
+ });
+ this.registerChat("${info}You were revived by ${info2}", this.preventGoingBrrr);
+
+ this.registerChat("&r&e> Your bottle of thunder has fully charged!&r", () => {
+ if (this.thunderBottleFull.getValue()) {
+ Client.showTitle("&6Bottle of Thunder Fully Charged", "", 0, 100, 10);
+ }
+ })
+
+ this.warps = JSON.parse(FileLib.read("SoopyV2", "features/globalSettings/warps.json"))
+
+ this.registerCommand("warp", (...name) => {
+ //send command to server
+ ChatLib.command("warp " + (name[0] || ""));
+ }, (args) => {
+ return this.warps.filter(v => v.toLowerCase().startsWith(args[0]))
+ })
+
+ this.registerStep(true, 4, this.mobThings)
+
+ this.firstPageSettings = [this.darkTheme]
+
+ this.firstLoadPageData = JSON.parse(FileLib.read("soopyAddonsData", "soopyv2firstloaddata.json") || "{}") || {}
+
+ this.GuiPage = new FirstLoadingPage(this)
+
+ // soopyV2Server.reportErrorsSetting = this.reportErrorsSetting
+ this.registerEvent("itemTooltip", this.itemTooltipEvent).registeredWhen(() => this.itemWorth.getValue() || this.showChampion.getValue() || this.showHecatomb.getValue())
+
+
+ this.registerChat("&aYour new API key is &r&b${key}&r", this.newKey)
+ const EntityFallingBlock = Java.type("net.minecraft.entity.item.EntityFallingBlock");
+
+ this.registerEvent('renderEntity', (entity, posVec, partialTicks, event) => {
+ if (entity.getEntity() instanceof EntityFallingBlock) {
+ cancel(event);
+ }
+ }).registeredWhen(() => this.hideFallingBlocks.getValue())
+
+ this.ranFirstLoadThing = false
+
+ if (!this.firstLoadPageData.shown) {
+ new Thread(() => {
+ while (!World.isLoaded() || !this.FeatureManager.finishedLoading) {
+ Thread.sleep(100)
+ }
+ Thread.sleep(500)
+ this.showFirstLoadPage.call(this)
+ }).start()
+ }
+
+ if (net.minecraftforge.fml.common.Loader.isModLoaded("notenoughupdates")) {
+ this.GuiProfileViewer = Java.type("io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer")
+ this.currentPlayerOpen = undefined
+ this.currentPlayerNetworth = {}
+ this.registerEvent("tick", this.fixNEU)
+ }
+
+ this.requestingPrices = new Set()
+ this.registerStep(false, 1, this.updateItemLores)
+
+ try { //This enables links from soopy.dev to be shown in patcher image preview
+ let hasHost = false
+
+ for (let host of Java.type("gg.essential.util.TrustedHostsUtil").INSTANCE.getTrustedHosts()) {
+ if (host.getName() === "soopy.dev") {
+ hasHost = true
+ }
+ }
+
+ if (!hasHost) {
+ let TrustedHost = Java.type("gg.essential.api.utils.TrustedHostsUtil").TrustedHost
+ let TreeSet = Java.type("java.util.TreeSet")
+ let hosts = new TreeSet()
+ hosts.add("soopy.dev")
+
+ let host = new TrustedHost(124123, "soopy.dev", hosts)
+
+ Java.type("gg.essential.util.TrustedHostsUtil").INSTANCE.addTrustedHost(host)
+ }
+ } catch (e) { }
+
+ this.registerCommand("soopyweight", (user = Player.getName()) => {
+ this.soopyWeight(user)
+ })
+ this.registerCommand("sweight", (user = Player.getName()) => {
+ this.soopyWeight(user)
+ })
+ this.registerCommand("lobbyday", () => {
+ ChatLib.chat(this.FeatureManager.messagePrefix + "Current lobby is day " + (World.getTime() / 20 / 60 / 20).toFixed(2))
+ })
+ this.registerCommand("tps", (time = "3") => {
+ time = parseInt(time)
+ ChatLib.chat(this.FeatureManager.messagePrefix + "Loading tps... this will take " + time + "s")
+
+ let packetMoves = 0
+ let ticks = 0
+ let packetReceived = register("packetReceived", () => {
+ packetMoves++
+ })
+
+ let tick = register("tick", () => {
+ if (packetMoves > 0) ticks++
+ packetMoves = 0
+ })
+
+ delay(time * 1000, () => {
+ packetReceived.unregister()
+ tick.unregister()
+ ChatLib.chat(this.FeatureManager.messagePrefix + "Tps: " + Math.min(20, ticks / time).toFixed(1))
+ })
+ })
+
+ this.lastCookies = 0
+
+ this.registerEvent("postGuiRender", () => {
+ if (Player.getContainer() && Player.getContainer().getName() === "Cookie Clicker v0.01" && Player.getContainer().getStackInSlot(13)) this.renderCookie()
+ // if (this.linkPreview.getValue() && Client.currentGui && Client.currentGui.get() && Client.currentGui.get().toString().startsWith("net.minecraft.client.gui.GuiConfirmOpenLink")) this.renderWebpage()
+ })
+ this.registerStep(false, 1, () => {
+ if (Player.getContainer() && Player.getContainer().getName() === "Cookie Clicker v0.01" && Player.getContainer().getStackInSlot(13)) this.tickCookie()
+
+ global.guiManagerSoopyGuisSetDarkThemeEnabled(this.darkTheme.getValue())
+ })
+
+ this.registerEvent("guiMouseClick", this.guiClicked)
+
+ this.partyChatEnabled = true
+
+ this.registerChat("&r&9Party &8> ${*}", (e) => {
+ if (!this.partyChatEnabled) {
+ cancel(e)
+ }
+ })
+
+ this.registerEvent("messageSent", (message, event) => {
+ if (this.twitchCommands.getValue() && message.startsWith("-") && message[1].toLowerCase().match(/[a-z]/)) {
+ cancel(event)
+ ChatLib.addToSentMessageHistory(message)
+ fetch("http://soopy.dev/api/soopyv2/botcommand?m=" + encodeURIComponent(message.replace("-", "")) + "&u=" + Player.getName()).text().then(text => {
+ ChatLib.chat(this.FeatureManager.messagePrefix + "&7" + message)
+ toMessageWithLinks(this.FeatureManager.messagePrefix + text, "7").chat()
+ })
+ return;
+ }
+
+ if (this.handChat.getValue() && message.toLowerCase().includes("[hand]")) {
+ cancel(event)
+ ChatLib.addToSentMessageHistory(message)
+
+ fetch("http://soopy.dev/api/soopyv2/itemup", {
+ postData: {
+ name: Player.getHeldItem().getName(),
+ lore: Player.getHeldItem().getLore().join("\n")
+ }
+ }).text().then(text => {
+ if (text.length > 20) {
+ ChatLib.chat(this.FeatureManager.messagePrefix + "There was an error uploading the item data!")
+ return
+ }
+
+ ChatLib.say(message.replace(/\[hand\]/gi, "[ITEM:" + text + "]"))
+ })
+ return;
+ }
+ })
+
+ let ev = this.registerChat("${*}[ITEM:${*}", (event) => {
+ cancel(event)
+ let message = new Message(event)
+
+ let [_] = message.getUnformattedText().match(/\[ITEM:([0-9]+)\]/g)
+ let id = _.replace("[ITEM:", "").replace(/\]$/g, "")
+
+ fetch("http://soopy.dev/api/soopyv2/itemdown/" + id).json().then(([name, lore]) => {
+ for (let i = 0; i < message.getMessageParts().length; i++) {
+ let component = message.getMessageParts()[i]
+
+ if (component.getText().match(/\[ITEM:([0-9]+)\]/g)) {
+ let [_] = component.getText().match(/\[ITEM:([0-9]+)\]/g)
+ let id = _.replace("[ITEM:", "").replace(/\]$/g, "")
+
+ message.setTextComponent(i, new TextComponent(component.getText().replace("[ITEM:" + id + "]", name + "&r")).setHover("show_text", lore))
+ }
+ }
+ message.setRecursive(true)
+ message.chat()
+ }).catch(() => {
+ ChatLib.chat(this.FeatureManager.messagePrefix + "There was an error downloading the item data!")
+ message.chat()
+ })
+
+ })
+ ev.trigger.setPriority(Priority.HIGHEST)
+
+ this.ahAlerts = [
+ // { //TODO: add a command/gui to add these
+ // id: "ATTRIBUTE_SHARD",
+ // maxPrice: 1300000,
+ // nbt: [
+ // "tag.ExtraAttributes.attributes.mana_pool"
+ // ]
+ // }
+ ]
+
+ this.registerStep(false, 60, async () => {
+ if (this.ahAlerts.length === 0) return
+ let data = await fetch("https://moulberry.codes/auction.json").json()//TODO: use https://moulberry.codes/auction.json.gz
+ if (!data.success) return
+
+ data.new_auctions.forEach(a => {
+ let itemData = decompress(a.item_bytes)
+ let itemJSON = itemData.toObject().i[0]
+ let itemId = itemJSON.tag.ExtraAttributes.id
+
+ if (a.bin && this.ahAlerts.some(al => {
+ let ret = al.id === itemId && a.starting_bid <= al.maxPrice
+
+ if (ret && al.nbt) {
+ if (al.nbt.some(nbtr => {
+ let steps = nbtr.split(".")
+ let o = itemJSON
+ steps.forEach(s => {
+ o = o?.[s]
+ })
+
+ return !o
+ })) ret = false
+ }
+
+ return ret
+ })) {
+ Client.showTitle("SNIPE THING", "CHECK CHAT", 20, 60, 20)
+
+ new TextComponent(this.FeatureManager.messagePrefix + "Bin found " + numberWithCommas(a.starting_bid) + " " + a.item_name).setClick("run_command", "/viewauction " + a.uuid).chat()
+ }
+ })
+ })
+
+ this.registerCommand("price", async () => {
+ let json = await fetch("http://soopy.dev/api/soopyv2/itemPriceDetailed", {
+ postData: {
+ item: Player.getHeldItem().getNBT().toObject()
+ }
+ }).json()
+
+ ChatLib.chat(this.FeatureManager.messagePrefix + "PRICE ANALYSIS (Total: $" + numberWithCommas(Math.round(json.price)) + ")")
+ // json.details.sort((a, b) => {
+ // if (typeof (a) === "string") return 1
+ // if (typeof (b) === "string") return -1
+ // return a[1] - b[1]
+ // }).forEach(d => {
+ // if (typeof (d) === "string") {
+ // ChatLib.chat(d)
+ // } else {
+ // ChatLib.chat("&f" + d[0] + "&7: &6" + numberWithCommas(Math.round(d[1])))
+ // }
+ // })
+ // ChatLib.chat(this.FeatureManager.messagePrefix + "Final price: " + numberWithCommas(Math.round(json.price)))
+ json.details.sort((b, a) => {
+ if (typeof (a) === "string") return 1
+ if (typeof (b) === "string") return -1
+ return a.price - b.price
+ }).forEach(d => {
+ if (typeof (d) === "string") {
+ ChatLib.chat(d)
+ } else {
+ if (!d.price) return
+ let lore = []
+ d.items.sort((b, a) => {
+ if (typeof (a) === "string") return 1
+ if (typeof (b) === "string") return -1
+ return a[1] - b[1]
+ }).forEach(d2 => {
+ if (typeof (d2) === "string") {
+ lore.push(d2)
+ } else {
+ lore.push("&f" + d2[0] + "&7: $&6" + numberWithCommas(Math.round(d2[1])))
+ }
+ })
+ new TextComponent("&d" + d.name + "&7: $&6" + numberWithCommas(Math.round(d.price))).setHover("show_text", lore.join("\n")).chat()
+ }
+ })
+ })
+
+ let zoogui = new SoopyGui().setOpenCommand("zoo")
+
+ zoogui.element.addChild(new SoopyImageElement().setImage("https://img.freepik.com/premium-photo/portrait-monkey-wild_397170-44.jpg?w=1380").setLocation(0, 0, 1, 1))
+ }
+
+ worldLoad() {
+ this.requestingPrices.clear();
+ this.initOldItemData();
+ this.preventGoingBrrr();
+ if (!this.oldMasterStars.getValue()) return
+ let j = 0;
+ [...Player.getInventory().getItems()].forEach(i => {
+ j++;
+ if (j > 8) return //only do the 1-8 hot bar slots
+ if (!i) return
+ let itemName = i.getName()
+ let itemNameReformat = itemName.removeFormatting()
+ if (itemNameReformat.endsWith("➊")) {
+ let newItemName = itemName.replace("§6✪§6✪§6✪§6✪§6✪§c➊", "§c✪§6✪✪✪✪")
+ i.setName(newItemName)
+ this.saveItemData(getSBUUID(i), newItemName)
+ return
+ }
+ if (itemNameReformat.endsWith("➋")) {
+ let newItemName = itemName.replace("§6✪§6✪§6✪§6✪§6✪§c➋", "§c✪✪§6✪✪✪")
+ i.setName(newItemName)
+ this.saveItemData(getSBUUID(i), newItemName)
+ return
+ }
+ if (itemNameReformat.endsWith("➌")) {
+ let newItemName = itemName.replace("§6✪§6✪§6✪§6✪§6✪§c➌", "§c✪✪✪§6✪✪")
+ i.setName(newItemName)
+ this.saveItemData(getSBUUID(i), newItemName)
+ return
+ }
+ if (itemNameReformat.endsWith("➍")) {
+ let newItemName = itemName.replace("§6✪§6✪§6✪§6✪§6✪§c➍", "§c✪✪✪✪§6✪")
+ i.setName(newItemName)
+ this.saveItemData(getSBUUID(i), newItemName)
+ return
+ }
+ if (itemNameReformat.endsWith("➎")) {
+ let newItemName = itemName.replace("§6✪§6✪§6✪§6✪§6✪§c➎", "§c✪✪✪✪✪")
+ i.setName(newItemName)
+ this.saveItemData(getSBUUID(i), newItemName)
+ return
+ }
+ })
+ }
+
+ step5Fps() {
+ let old = this.oldMasterStars.getValue();
+ let pick = this.sbaItemPickUpLog.getValue();
+ let thunder = this.thunderBottle.getValue();
+ let max = this.maxAmount.getValue();
+ if (max) {
+ max = Number(max)
+ if (max < 0 || isNaN(max)) this.maxAmount.setValue("0");
+ }
+ let inGui = Client.isInGui()
+ if (!old && !pick && !thunder) return
+ if (inGui) {
+ this.todoPickUpLog = {};
+ }
+ let j = 0;
+ let now = Date.now();
+ let thunderText = [];
+ [...Player.getInventory().getItems()].forEach(i => {
+ j++;
+ if (i) {
+ let uuid = getSBUUID(i)
+ let ItemName = i.getName()
+ if (old) {
+ if (uuid && this.itemData.hasOwnProperty(uuid)) {
+ let newName = this.itemData[uuid]
+ if (ItemName != newName) {
+ i.setName(newName)
+ }
+ }
+ }
+ if (thunder) {
+ if (ItemName.removeFormatting().includes("Empty Thunder Bottle")) {
+ let charges = i?.getNBT()?.getCompoundTag("tag")?.getCompoundTag("ExtraAttributes")?.getDouble("thunder_charge")
+ thunderText.push(`&6Thunder Charge&7> &f${numberWithCommas(charges)}&7/&750,000`)
+ }
+ }
+ }
+ if (pick && !inGui) {
+ let oldItem = this.oldItemData[j]
+ let newItem = i
+ if (!oldItem && !newItem) return //they both are air
+ if (j > 36 || j == 9) return //sbmenu and armors (when switching wardrobe it goes brrr w/o this)
+ let oldItemAmount = oldItem ? oldItem.getNBT().getDouble("Count") : undefined
+ let oldItemName = oldItem ? oldItem.getName().replace(/ §8x\d+$/, "") : ""
+ let newItemAmount = newItem ? newItem.getNBT().getDouble("Count") : undefined
+ let newItemName = newItem ? newItem.getName().replace(/ §8x\d+$/, "") : ""
+ this.oldItemData[j] = newItem
+ if (oldItemName === newItemName) { //only amount is changed
+ if (oldItemAmount === newItemAmount || !newItemAmount || !oldItemAmount) return
+ this.addToTodoPickUpLog(now, oldItemName, newItemAmount - oldItemAmount)
+ return //so it doesn't provide duplicate message
+ }
+ let olduuid = getSBUUID(oldItem)
+ let newuuid = getSBUUID(newItem)
+ if (oldItemAmount == 1 && olduuid == newuuid) return // fixes using old master star making sba go brrr
+ if (oldItemName) { //thing removed from that inventory slot
+ if (!oldItemAmount) return
+ this.addToTodoPickUpLog(now, oldItemName, (-1) * oldItemAmount)
+ }
+ if (newItemName) { //thing being placed into that inventory slot
+ if (!newItemAmount) return
+ this.addToTodoPickUpLog(now, newItemName, newItemAmount)
+ }
+ }
+ })
+ if (thunder) {
+ if (thunderText.length > 0) {
+ this.thunderBottleElement.setText(thunderText.join("\n"))
+ } else {
+ this.thunderBottleElement.setText("")
+ }
+ }
+ let todoText = [];
+ if (pick) {
+ Object.keys(this.todoPickUpLog).forEach((i) => {
+ if (Math.abs(this.todoPickUpLog[i].timeStamp - now) > 5000 || !this.todoPickUpLog[i].Amount || this.todoPickUpLog[i].Amount == 0) {
+ delete this.todoPickUpLog[i]
+ return
+ }
+ //positive and negative prefix colors
+ if (todoText.length < max) todoText.push((this.todoPickUpLog[i].Amount > 0 ? "&r&a+ " : "&r&c- ") + Math.abs(this.todoPickUpLog[i].Amount) + "x &f" + i)
+ })
+ } else {
+ this.todoPickUpLog = {};
+ }
+ // doesn't need to put setText() in if (pick) cuz if (!pick) it clears the todo log list
+ this.sbaItemPickUpLogElement.setText((inGui || this.clearLog) ? "" : (todoText.join("\n")))
+ }
+
+ mobThings() {
+ if (!this.fancyVanquisherAlert.getValue()) return
+ World.getAllEntitiesOfType(net.minecraft.entity.item.EntityArmorStand).forEach(entity => {
+ let name = entity.getName()
+ if (name.includes("'s")) return
+ let LowerName = name.removeFormatting().toLowerCase()
+ let existedTicks = entity.getTicksExisted()
+ if (this.fancyVanquisherAlert.getValue()) {
+ if (LowerName.includes("vanq")) {
+ if (existedTicks <= 20) {
+ Client.showTitle("&r&5&l[&b&l&kO&5&l] VANQUISHER &5[&b&l&kO&5&l]", "", 0, 50, 10);
+ }
+ }
+ }
+ if (this.fancySeaCreaturesAlertThunder.getValue()) {
+ if (LowerName.includes("thunder")) {
+ if (existedTicks <= 20) {
+ Client.showTitle("&r&6&l[&b&l&kO&6&l] THUNDER [&b&l&kO&6&l]", "", 0, 50, 10)
+ }
+ }
+ }
+ if (this.fancySeaCreaturesAlertJawbus.getValue()) {
+ if (LowerName.includes("jawbus")) {
+ if (existedTicks <= 20) {
+ Client.showTitle("&r&6&l[&b&l&kO&6&l] LORD JAWBUS [&b&l&kO&6&l]", "", 0, 50, 10)
+ }
+ }
+ }
+ })
+ }
+
+ preventGoingBrrr() {
+ this.clearLog = true
+ delay(8000, () => {
+ if (this.clearLog) {
+ this.clearLog = false
+ }
+ })
+ }
+
+ itemTooltipEvent(lore, i, event) {
+ let uuid = getSBUUID(i)
+ if (!uuid) return
+
+ if (this.itemWorth.getValue()) {
+ let a = socketConnection.itemPricesCache.get(uuid)
+
+ if (!a && socketConnection.itemPricesCache2.get(uuid)) {
+ a = socketConnection.itemPricesCache2.get(uuid)
+ socketConnection.itemPricesCache.set(uuid, a)
+ }
+
+ if (a) {
+ addLore(i, "§eWorth: ", "§6$" + numberWithCommas(Math.round(a)))
+ }
+ }
+
+ if (this.showChampion.getValue() && i?.getNBT()?.getCompoundTag("tag")?.getCompoundTag("ExtraAttributes")?.getDouble("champion_combat_xp")) {
+ let xp = i?.getNBT()?.getCompoundTag("tag")?.getCompoundTag("ExtraAttributes")?.getDouble("champion_combat_xp")
+
+ let level = 1
+ championLevels.forEach(l => {
+ if (xp >= l) level++
+ })
+ let xpNext = championLevels[level - 1]
+
+ addLore(i, "§eChampion: ", "§d" + level + " §6" + numberWithCommas(Math.round(xp)) + (xpNext ? " §7/ §6" + numberWithCommas(Math.round(xpNext)) : ""))
+ }
+ if (this.showHecatomb.getValue() && i?.getNBT()?.getCompoundTag("tag")?.getCompoundTag("ExtraAttributes")?.getInteger("hecatomb_s_runs")) {
+ let runs = i?.getNBT()?.getCompoundTag("tag")?.getCompoundTag("ExtraAttributes")?.getInteger("hecatomb_s_runs")
+
+ let level = 1
+ hecatombLevels.forEach(l => {
+ if (runs >= l) level++
+ })
+ let xpNext = hecatombLevels[level - 1]
+
+ addLore(i, "§eHecatomb: ", "§d" + level + " §6" + numberWithCommas(Math.round(runs)) + (xpNext ? " §7/ §6" + numberWithCommas(Math.round(xpNext)) : ""))
+ }
+ }
+
+ updateItemLores() {
+ if (!this.itemWorth.getValue()) return;
+
+ if (!Player.getInventory()) return
+
+ let items = [...Player.getInventory().getItems(), ...Player.getContainer().getItems()]
+
+ items.forEach(i => {
+ let uuid = getSBUUID(i)
+ if (!uuid) return
+
+ if (this.itemWorth.getValue()) {
+ let a = socketConnection.itemPricesCache.get(uuid)
+
+ if (!a && socketConnection.itemPricesCache2.get(uuid)) {
+ a = socketConnection.itemPricesCache2.get(uuid)
+ socketConnection.itemPricesCache.set(uuid, a)
+ }
+
+ if (!a) {
+ if (!this.requestingPrices.has(uuid)) {
+ this.requestingPrices.add(uuid)
+
+ let json = i.getNBT().toObject()
+ socketConnection.requestItemPrice(json, uuid)
+ }
+ }
+
+ }
+
+ })
+ }
+
+ addToTodoPickUpLog(timestamp, itemname, amount) {
+ let basicValue = 0
+ if (this.todoPickUpLog[itemname]) {
+ if (this.todoPickUpLog[itemname].Amount != 0) {
+ basicValue = this.todoPickUpLog[itemname].Amount
+ }
+ }
+ this.todoPickUpLog[itemname] = {
+ timeStamp: timestamp,
+ Amount: basicValue + amount
+ }
+ }
+
+ initOldItemData() {
+ let j = 0;
+ [...Player.getInventory().getItems()].forEach(i => {
+ j++;
+ this.oldItemData[j] = i
+ })
+ }
+
+ saveItemData(uuid, newName) {
+ if (!this.itemData[uuid]) {
+ this.itemData[uuid] = newName
+ }
+ }
+
+ // renderWebpage() {
+ // let url = this.getField(Client.currentGui.get(), f.linkText)
+
+ // let image = renderLibs.getImage("https://soopy.dev/api/soopyv2/webpage?webpage=" + url)
+
+ // if (image) {
+ // let scale = Renderer.screen.getHeight() * 0.5 / image.getTextureHeight()
+ // image.draw(Renderer.screen.getWidth() / 2 - image.getTextureWidth() * scale / 2, Renderer.screen.getHeight() / 2, scale * image.getTextureWidth(), scale * image.getTextureHeight())
+ // } else {
+ // Renderer.drawString("Loading website preview...", Renderer.screen.getWidth() / 2 - Renderer.getStringWidth("Loading website preview...") / 2, Renderer.screen.getHeight() * 3 / 4)
+ // }
+ // }
+
+ guiClicked(mouseX, mouseY, button, gui, event) {
+ if (Player.getContainer() && Player.getContainer().getName() === "Cookie Clicker v0.01") {
+
+ let hoveredSlot = gui.getSlotUnderMouse()
+ if (!hoveredSlot) return
+
+ let hoveredSlotId = hoveredSlot[f.slotNumber]
+
+ // logger.logMessage(hoveredSlotId, 4)
+
+ Player.getContainer().click(hoveredSlotId, false, "MIDDLE")
+ cancel(event)
+ }
+ }
+
+ tickCookie() {
+ let cookies = parseInt(ChatLib.removeFormatting(Player.getContainer().getStackInSlot(13).getName().split(" ")[0]))
+
+ let cookiesGained = cookies - this.lastCookies
+ this.lastCookies = cookies
+ if (cookiesGained > 50) cookiesGained = 0
+ if (cookiesGained < 1) cookiesGained = 0
+ if (!cookiesGained) cookiesGained = 0
+
+ socketConnection.cookiesGained(cookiesGained)
+ }
+
+ renderCookie() {
+ let cookies = parseInt(ChatLib.removeFormatting(Player.getContainer().getStackInSlot(13).getName().split(" ")[0]))
+
+ let cookiesGained = cookies - this.lastCookies
+ let cookieCount = socketConnection.cookieCount + ((cookiesGained < 50 && cookiesGained > 0) ? cookiesGained : 0)
+
+ renderLibs.drawString("Lifetime Cookies: " + numberWithCommas(cookieCount), 10, 10, 1)
+
+ if (socketConnection.cookieData) {
+ // this.cookieData = {
+ // cookieLeaderboard: data.cookieLeaderboard,
+ // clickingNow: data.clickingNow
+ // }
+
+ let linesOfText = []
+
+ linesOfText.push("---- CURRENTLY CLICKING ----")
+ for (let data of socketConnection.cookieData.clickingNow) {
+ linesOfText.push(data[0] + ": " + numberWithCommas(data[1]))
+
+ if (linesOfText.length * 10 > Renderer.screen.getHeight() / 2) break
+ }
+ linesOfText.push("------- LEADERBOARD -------")
+ let i = 0
+ for (let data of socketConnection.cookieData.cookieLeaderboard) {
+ i++
+
+ linesOfText.push("#" + i + " " + data[0] + ": " + numberWithCommas(data[1]))
+
+ if (linesOfText.length * 10 > Renderer.screen.getHeight() - 50) break
+ }
+
+ for (let i = 0; i < linesOfText.length; i++) {
+ renderLibs.drawString(linesOfText[i], 10, 20 + 10 * i, 1)
+ }
+ }
+ }
+
+ fixNEU() {
+ if (Client.currentGui && Client.currentGui.get() instanceof (this.GuiProfileViewer) && this.fixNeuNetworth.getValue()) {
+ let guiProfileViewer = Client.currentGui.get()
+ if (!guiProfileViewer.profile || !guiProfileViewer.profile.getHypixelProfile()) return
+ let uuid = guiProfileViewer.profile.getHypixelProfile().get("uuid").getAsString().replace(/-/g, "")
+
+ if (this.currentPlayerOpen != uuid) {
+ this.currentPlayerOpen = uuid
+ this.currentPlayerNetworth = {}
+
+ fetch("http://soopy.dev/api/v2/player_skyblock/" + uuid).json().then(data => {
+ if (!data.success) return
+
+ if (this.currentPlayerOpen === data.data.uuid) {
+ Object.keys(data.data.profiles).forEach(profileId => {
+ if (!data.data.profiles[profileId].members[uuid].soopyNetworth.networth) return
+ this.currentPlayerNetworth[data.data.profiles[profileId].stats.cute_name] = JavaLong.valueOf(data.data.profiles[profileId].members[uuid].soopyNetworth.networth)
+ })
+ }
+ })
+ }
+
+ let map = this.getField(guiProfileViewer.profile, "networth")
+ Object.keys(this.currentPlayerNetworth).forEach(key => {
+ map.put(new JavaString(key), new JavaLong(this.currentPlayerNetworth[key]))
+ })
+ }
+ }
+
+ getField(e, field) {
+ let field2 = e.class.getDeclaredField(field);
+
+ field2.setAccessible(true)
+
+ return field2.get(e)
+ }
+
+ async soopyWeight(user) {
+
+ ChatLib.chat(this.FeatureManager.messagePrefix + "Finding senither weight for " + user)
+
+ let userData = await fetch("http://soopy.dev/api/v2/player/" + user).json()
+ if (!userData.success) {
+ ChatLib.chat(this.FeatureManager.messagePrefix + "&cError loading data: " + userData.error.description)
+ return
+ }
+
+ let sbData = await fetch("http://soopy.dev/api/v2/player_skyblock/" + userData.data.uuid).json()
+
+ if (!sbData.success) {
+ ChatLib.chat(this.FeatureManager.messagePrefix + "&cError loading data: " + sbData.error.description)
+ return
+ }
+
+ ChatLib.chat("&c" + ChatLib.getChatBreak("-"))
+ ChatLib.chat(userData.data.stats.nameWithPrefix + "'s senither weight (best profile):")
+ ChatLib.chat("&aTotal: &b" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.bestProfileId].members[userData.data.uuid].weight.total)))
+ new Message(new TextComponent("&aSkills: &b" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.bestProfileId].members[userData.data.uuid].weight.skill.total)))
+ .setHover("show_text", Object.keys(sbData.data.profiles[sbData.data.stats.bestProfileId].members[userData.data.uuid].weight.skill).map(skill => {
+ if (skill === "total") {
+ return null
+ }
+ return "&a" + firstLetterCapital(skill) + ": &b" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.bestProfileId].members[userData.data.uuid].weight.skill[skill].total)) + " &7(" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.bestProfileId].members[userData.data.uuid].weight.skill[skill].weight)) + " | " + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.bestProfileId].members[userData.data.uuid].weight.skill[skill].overflow)) + ")"
+ }).filter(a => a).join("\n"))).chat()
+ new Message(new TextComponent("&aSlayer: &b" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.bestProfileId].members[userData.data.uuid].weight.slayer.total)))
+ .setHover("show_text", Object.keys(sbData.data.profiles[sbData.data.stats.bestProfileId].members[userData.data.uuid].weight.slayer).map(slayer => {
+ if (slayer === "total") {
+ return null
+ }
+ return "&a" + firstLetterCapital(slayer) + ": &b" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.bestProfileId].members[userData.data.uuid].weight.slayer[slayer].total)) + " &7(" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.bestProfileId].members[userData.data.uuid].weight.slayer[slayer].weight)) + " | " + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.bestProfileId].members[userData.data.uuid].weight.slayer[slayer].overflow)) + ")"
+ }).filter(a => a).join("\n"))).chat()
+ new Message(new TextComponent("&aDungeon: &b" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.bestProfileId].members[userData.data.uuid].weight.dungeons.total)))
+ .setHover("show_text", Object.keys(sbData.data.profiles[sbData.data.stats.bestProfileId].members[userData.data.uuid].weight.dungeons).map(dungeons => {
+ if (dungeons === "total") {
+ return null
+ }
+ return "&a" + firstLetterCapital(dungeons) + ": &b" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.bestProfileId].members[userData.data.uuid].weight.dungeons[dungeons].total)) + " &7(" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.bestProfileId].members[userData.data.uuid].weight.dungeons[dungeons].weight)) + " | " + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.bestProfileId].members[userData.data.uuid].weight.dungeons[dungeons].overflow)) + ")"
+ }).filter(a => a).join("\n"))).chat()
+ if (sbData.data.stats.bestProfileId !== sbData.data.stats.currentProfileId) {
+ ChatLib.chat(userData.data.stats.nameWithPrefix + "'s senither weight (current profile):")
+ ChatLib.chat("&aTotal: &b" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.currentProfileId].members[userData.data.uuid].weight.total)))
+ new Message(new TextComponent("&aSkills: &b" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.currentProfileId].members[userData.data.uuid].weight.skill.total)))
+ .setHover("show_text", Object.keys(sbData.data.profiles[sbData.data.stats.currentProfileId].members[userData.data.uuid].weight.skill).map(skill => {
+ if (skill === "total") {
+ return null
+ }
+ return "&a" + firstLetterCapital(skill) + ": &b" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.currentProfileId].members[userData.data.uuid].weight.skill[skill].total)) + " &7(" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.currentProfileId].members[userData.data.uuid].weight.skill[skill].weight)) + " | " + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.currentProfileId].members[userData.data.uuid].weight.skill[skill].overflow)) + ")"
+ }).filter(a => a).join("\n"))).chat()
+ new Message(new TextComponent("&aSlayer: &b" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.currentProfileId].members[userData.data.uuid].weight.slayer.total)))
+ .setHover("show_text", Object.keys(sbData.data.profiles[sbData.data.stats.currentProfileId].members[userData.data.uuid].weight.slayer).map(slayer => {
+ if (slayer === "total") {
+ return null
+ }
+ return "&a" + firstLetterCapital(slayer) + ": &b" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.currentProfileId].members[userData.data.uuid].weight.slayer[slayer].total)) + " &7(" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.currentProfileId].members[userData.data.uuid].weight.slayer[slayer].weight)) + " | " + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.currentProfileId].members[userData.data.uuid].weight.slayer[slayer].overflow)) + ")"
+ }).filter(a => a).join("\n"))).chat()
+ new Message(new TextComponent("&aDungeon: &b" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.currentProfileId].members[userData.data.uuid].weight.dungeons.total)))
+ .setHover("show_text", Object.keys(sbData.data.profiles[sbData.data.stats.currentProfileId].members[userData.data.uuid].weight.dungeons).map(dungeons => {
+ if (dungeons === "total") {
+ return null
+ }
+ return "&a" + firstLetterCapital(dungeons) + ": &b" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.currentProfileId].members[userData.data.uuid].weight.dungeons[dungeons].total)) + " &7(" + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.currentProfileId].members[userData.data.uuid].weight.dungeons[dungeons].weight)) + " | " + numberWithCommas(Math.round(sbData.data.profiles[sbData.data.stats.currentProfileId].members[userData.data.uuid].weight.dungeons[dungeons].overflow)) + ")"
+ }).filter(a => a).join("\n"))).chat()
+ }
+ ChatLib.chat("&c" + ChatLib.getChatBreak("-"))
+ }
+
+ showFirstLoadPage() {
+ if (!this.ranFirstLoadThing && World.isLoaded() && !this.firstLoadPageData.shown) {
+ ChatLib.chat(this.FeatureManager.messagePrefix + "Opening first load page, if you accidentally close it run /soopyv2 and click the button")
+ ChatLib.command("soopyv2 first_load_thing", true)
+ this.ranFirstLoadThing = true
+ this.firstLoadPageData.shown = true
+ this.firstLoadPageData.version = 1
+ FileLib.write("soopyAddonsData", "soopyv2firstloaddata.json", JSON.stringify(this.firstLoadPageData))
+ }
+ }
+ verifyKey(key) {
+ // console.log(key)
+ if (key) {
+ try {
+ var url = "https://api.hypixel.net/key?key=" + key
+ let data = fetch(url).jsonSync()
+
+ // console.log(data)
+
+ if (data.success) {
+ return true
+ } else {
+ return false
+ }
+ } catch (e) {
+ return false
+ }
+ } else {
+ return false
+ }
+ }
+ findKey() {
+ new Notification("Finding key...", [])
+ new Thread(() => {
+
+ // NEU
+ try {
+ let testKey = JSON.parse(new JavaString(Files.readAllBytes(Paths.get("./config/notenoughupdates/configNew.json")))).apiKey.apiKey
+ if (testKey) {
+ if (this.verifyKey(testKey)) {
+ this.apiKeySetting.setValue(testKey)
+ new Notification("§aSuccess!", ["Found api key in NotEnoughUpdates!"])
+ return;
+ } else {
+ logger.logMessage("Found invalid key in NotEnoughUpdates", 3)
+ }
+ }
+ } catch (_) { }
+
+ // SBE
+ try {
+ let testKey = JSON.parse(new JavaString(Files.readAllBytes(Paths.get("./config/SkyblockExtras.cfg")))).values.apiKey
+ if (testKey) {
+ if (this.verifyKey(testKey)) {
+ this.apiKeySetting.setValue(testKey)
+ new Notification("§aSuccess!", ["Found api key in SkyblockExtras!"])
+ return;
+ } else {
+ logger.logMessage("Found invalid key in SkyblockExtras", 3)
+ }
+ }
+ } catch (_) { }
+ // SKYTILS
+ try {
+ let testKey2 = new JavaString(Files.readAllBytes(Paths.get("./config/skytils/config.toml")))
+ let testKey = undefined
+ testKey2.split("\n").forEach(line => {
+ if (line.startsWith(" hypixel_api_key = \"")) {
+ testKey = line.split("\"")[1]
+ }
+ })
+ if (testKey) {
+ if (this.verifyKey(testKey)) {
+ this.apiKeySetting.setValue(testKey)
+ new Notification("§aSuccess!", ["Found api key in Skytils!"])
+ return;
+ } else {
+ logger.logMessage("Found invalid key in Skytils", 3)
+ }
+ }
+ } catch (_) { }
+
+ // SOOPYADDONS DATA
+ try {
+ let testKey = FileLib.read("soopyAddonsData", "apikey.txt")
+ if (testKey) {
+ if (this.verifyKey(testKey)) {
+ this.apiKeySetting.setValue(testKey)
+ new Notification("§aSuccess!", ["Found api key in old soopyaddons version!"])
+ return;
+ } else {
+ logger.logMessage("Found invalid key in soopyaddonsData", 3)
+ }
+ }
+ } catch (_) { }
+
+ // HypixelApiKeyManager
+ try {
+ let testKey = JSON.parse(FileLib.read("HypixelApiKeyManager", "localdata.json")).key
+ if (testKey) {
+ if (this.verifyKey(testKey)) {
+ this.apiKeySetting.setValue(testKey)
+ new Notification("§aSuccess!", ["Found api key in HypixelApiKeyManager!"])
+ return;
+ } else {
+ logger.logMessage("Found invalid key in HypixelApiKeyManager", 3)
+ }
+ }
+ } catch (_) { }
+
+
+ new Notification("§cUnable to find api key", [])
+ }).start()
+ }
+
+ apiNewCommand() {
+ ChatLib.command("api new")
+ }
+
+ verifyKey2(key) {
+ if (key) {
+ try {
+ var url = "https://api.hypixel.net/key?key=" + key
+ let data = fetch(url).jsonSync()
+
+ if (data.success) {
+ return true
+ } else {
+ return false
+ }
+ } catch (e) {
+ return false
+ }
+ }
+ if (this.module.apiKeySetting.getValue() == "") {
+ new Notification("§cError!", ["You need to set an api key first!"])
+ return
+ }
+
+
+ new Thread(() => {
+ try {
+ var url = "https://api.hypixel.net/key?key=" + this.module.apiKeySetting.getValue()
+ let data = fetch(url).jsonSync()
+
+ if (data.success) {
+ new Notification("§aSuccess!", ["Your api key is valid!"])
+ return
+ } else {
+ new Notification("§cError!", ["Your api key is invalid!"])
+ return
+ }
+ } catch (e) {
+ new Notification("§cError!", ["Your api key is invalid!"])
+ return
+ }
+ }).start()
+ }
+
+ newKey(key, event) {
+ ChatLib.chat(this.FeatureManager.messagePrefix + "Copied api key!")
+ this.apiKeySetting.setValue(key)
+ }
+
+ initVariables() {
+ this.hudElements = [];
+ }
+
+ onDisable() {
+ this.hudElements.forEach(h => h.delete())
+ this.initVariables()
+ }
+}
+
+class FirstLoadingPage extends GuiPage {
+ constructor(mainThing) {
+ super(-10)
+
+ this.showBackButton = false
+
+ this.name = "First load thing"
+
+ this.mainThing = mainThing
+
+ this.pageThings = []
+
+ firstLoadPages.forEach((page, i) => {
+ let newPage = this.newPage()
+
+ newPage.addChild(page)
+
+ page.setLoc(i !== 0, i !== firstLoadPages.length - 1)
+ page.guiPage = this
+
+ this.pageThings.push(newPage)
+ })
+
+ this.pageNum = 0
+
+ this.finaliseLoading()
+ }
+
+ nextPage() {
+ this.pageNum++
+
+ this.goToPage(this.pageNum)
+ }
+
+ prevPage() {
+ this.pageNum--
+
+ this.goToPage(this.pageNum)
+ }
+
+ onOpen() {
+ this.pageNum = 0
+
+ firstLoadPages.forEach((page, i) => {
+ page.load()
+ })
+ }
+}
+
+module.exports = {
+ class: new GlobalSettings()
+}
+
+
+const ByteArrayInputStream = Java.type("java.io.ByteArrayInputStream")
+const Base64 = Java.type("java.util.Base64")
+const CompressedStreamTools = Java.type("net.minecraft.nbt.CompressedStreamTools")
+function decompress(compressed) {
+ if (compressed === null || compressed.length == 0) {
+ return null
+ }
+
+ return new NBTTagCompound(CompressedStreamTools.func_74796_a(new ByteArrayInputStream(Base64.getDecoder().decode(compressed))))
+}
\ No newline at end of file
diff --git a/src/features/globalSettings/metadata.json b/src/features/globalSettings/metadata.json
new file mode 100644
index 0000000..801716f
--- /dev/null
+++ b/src/features/globalSettings/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Global Settings",
+ "description": "Settings that are applied globally",
+ "isHidden": false,
+ "isTogglable": false,
+ "defaultEnabled": true,
+ "sortA": 5
+}
\ No newline at end of file
diff --git a/src/features/globalSettings/warps.json b/src/features/globalSettings/warps.json
new file mode 100644
index 0000000..e84c78c
--- /dev/null
+++ b/src/features/globalSettings/warps.json
@@ -0,0 +1,41 @@
+[
+ "hub",
+ "village",
+ "home",
+ "island",
+ "spider",
+ "spiders",
+ "end",
+ "park",
+ "gold",
+ "deep",
+ "mines",
+ "forge",
+ "crystals",
+ "hollows",
+ "ch",
+ "nucleus",
+ "barn",
+ "desert",
+ "castle",
+ "museum",
+ "da",
+ "crypt",
+ "crypts",
+ "nest",
+ "crimson",
+ "isle",
+ "nether",
+ "dragontail",
+ "scarleton",
+ "skull",
+ "tomb",
+ "smoldering",
+ "void",
+ "drag",
+ "jungle",
+ "howl",
+ "dungeon_hub",
+ "dungeons",
+ "dhub"
+]
\ No newline at end of file
diff --git a/src/features/guild/index.js b/src/features/guild/index.js
new file mode 100644
index 0000000..27b143b
--- /dev/null
+++ b/src/features/guild/index.js
@@ -0,0 +1,70 @@
+///
+///
+import Feature from "../../featureClass/class";
+import { toMessageWithLinks } from "../../utils/utils";
+import { fetch } from "../../utils/networkUtils";
+import ToggleSetting from "../settings/settingThings/toggle";
+import TextSetting from "../settings/settingThings/textSetting";
+
+class Guild extends Feature {
+ constructor() {
+ super()
+ }
+
+ onEnable() {
+
+ this.bridgeBots = new Set()
+ fetch("http://soopy.dev/api/soopyv2/gbots.json").json().then(bots => {
+ bots.forEach(b => this.bridgeBots.add(b))
+ })
+
+ this.shortenPrefix = new ToggleSetting("Shorten guild message prefix", "from Guild > to G > ", false, "shorten_prefix", this)
+ this.guildBot = new TextSetting("Bridge bot ign", "", "", "guild_bot_ign", this, "", false)
+
+ //&r&2Guild > &6[MVP&0++&6] zZzSNOW &e[STAFF]&f: &r@niftynathan7, niftynathan7's weight: 20 087 (#1 198) (Skill: 8 771, Slayer: 1 263, Dungeons: 10 053) ,.,,,..,.,,.,,,....,,,,,,,,,..,,,,,..,,,..,,,.,,.,,.,..,,....,,....,,..,.&r
+ //&r&2Guild > &6[MVP&4++&6] Soopyboo32 &e[STAFF]&f: &rasd&r
+ //&r&2Guild > &6[MVP&1++&6] niftynathan7 &e[E]&f: &r@Soopyboo32, Soopyboo32's networth: $8 424 131 866 (#2 592) ,..,...,....,.,,,....,,,...,,,,,,,..,,.,,..,,.,.,,,.........,.....,,,,.....,..,,...,.,.,...,.,&r
+ let ev = this.registerChat('&r&2Guild > ${player}&f: &r${msg}&r', (player, msg, event) => {
+ if (msg.includes("[ITEM:")) return
+ if (player.includes(":")) return; //stop people sending weard messages to troll using this
+
+ //player = &6[MVP&0++&6] zZzSNOW &e[STAFF]
+ let [_, rank, ign, grank] = player.match(/(&7|&[0-9a-fmnl]\[\w+(?:&[0-9a-fmnl]\+*&[0-9a-fmnl])?\] )(\w+)( &[0-9a-fmnl]\[\w+\])?/)
+
+ cancel(event)
+
+ let message = ""
+ if (this.bridgeBots.has(ign) || ign.toLowerCase() === this.guildBot.getValue().toLowerCase()) {
+ let [name, other] = msg.split(/ ?[\>\:\»] /g)
+
+ if (other) {
+ message = `&2B${this.shortenPrefix.getValue() ? "" : "ridge"} > &b${name.split(" replying to ").reverse().join(" &7⤷&b ").trim()}&f: ${msg.replace(name, "").replace(/^ ?[\>\:\»] /, "").trim()}`
+ } else {
+ if (msg.includes("---------------------------------------------") || msg.includes("You have 60 seconds to accept. Click here to join!")) {
+ return //bridge bot bug
+ }
+ message = `&2B${this.shortenPrefix.getValue() ? "" : "ridge"} > &7⤷&f ${msg.trim()}`
+ }
+ } else {
+ if (msg.match(/^@\w+, [\w\W]+[,.]+$/)) {
+ let [_, name2, reply] = msg.match(/^@(\w+?), ([\w\W]+?)[,.]+$/)
+ message = `&2B${this.shortenPrefix.getValue() ? "" : "ridge"} > &b${name2} &7⤷&f ${reply.trim()}`
+ } else {
+ message = `&2G${this.shortenPrefix.getValue() ? "" : "uild"} > ${rank}${ign}${grank || ""}&f: ${msg}`
+ }
+ }
+
+
+ toMessageWithLinks(message).chat()
+ })
+ ev.trigger.triggerIfCanceled(false)
+ }
+
+ onDisable() {
+
+ }
+}
+
+module.exports = {
+ class: new Guild()
+}
\ No newline at end of file
diff --git a/src/features/guild/metadata.json b/src/features/guild/metadata.json
new file mode 100644
index 0000000..babd19d
--- /dev/null
+++ b/src/features/guild/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Guild features",
+ "description": "Features nice for guilds, eg bridge formatting",
+ "isHidden": false,
+ "isTogglable": true,
+ "defaultEnabled": false,
+ "sortA": 1
+}
\ No newline at end of file
diff --git a/src/features/hud/HudTextElement.js b/src/features/hud/HudTextElement.js
new file mode 100644
index 0000000..cdde6f3
--- /dev/null
+++ b/src/features/hud/HudTextElement.js
@@ -0,0 +1,143 @@
+import { HudText } from "../../utils/renderJavaUtils"
+
+class HudTextElement {
+ constructor() {
+ this.text = ""
+
+ this.toggleSetting = undefined
+ this.locationSetting = undefined
+
+ this.editTempTimeV = 0
+ this.editTempTextV = undefined
+
+ this.editBaseWidth = undefined
+ this.editBaseHeight = undefined
+
+ this.tempDisableTime = 0
+
+ this.renderTextCache = [""]
+ this.textChanged = false
+
+ this.renderingDisabled = false
+
+ this.renderElm = new HudText([""], 0, 0, true).startRender()
+ }
+
+ disableRendering() {
+ this.renderingDisabled = true
+ this.renderElm.stopRender()
+ }
+
+ enableRendering() {
+ this.renderingDisabled = false
+ if (this.toggleSetting.getValue()) {
+ this.renderElm.startRender()
+ }
+ }
+
+ delete() {
+ this.renderElm.stopRender()
+ if (this.locationSetting) this.locationSetting.delete()
+ }
+
+ setBaseEditWidth(width) {
+ this.editBaseWidth = width
+ return this
+ }
+
+ setBaseEditHeight(height) {
+ this.editBaseHeight = height
+ return this
+ }
+
+ setText(text = "") {
+ if (text === this.text) return this
+ this.text = text
+
+ this.renderTextCache = ChatLib.addColor(this.text).split("\n")
+
+ this.renderElm.setText(this.renderTextCache)
+ return this
+ }
+ setToggleSetting(setting) {
+ this.toggleSetting = setting
+ setting.onChange = () => {
+ if (this.toggleSetting.getValue() && !this.renderingDisabled) {
+ this.renderElm.startRender()
+ } else {
+ this.renderElm.stopRender()
+ }
+ }
+ if (this.toggleSetting.getValue() && !this.renderingDisabled) {
+ this.renderElm.startRender()
+ } else {
+ this.renderElm.stopRender()
+ }
+ return this
+ }
+ setLocationSetting(setting) {
+ this.locationSetting = setting
+ setting.setParent(this)
+
+ setting.onChange = () => {
+ this.renderElm.setX(this.locationSetting.x).setY(this.locationSetting.y).setScale(this.locationSetting.scale)
+ }
+ this.renderElm.setX(this.locationSetting.x).setY(this.locationSetting.y).setScale(this.locationSetting.scale)
+ return this
+ }
+
+ isEnabled() {
+ if (!this.toggleSetting) return true
+ return this.locationSetting && this.toggleSetting.getValue()
+ }
+
+ render() {
+ if (this.toggleSetting && !this.toggleSetting.getValue() || !this.locationSetting) return
+ if (Date.now() - this.tempDisableTime < 100) return
+
+ this.renderRaw()
+ }
+
+ getWidth(locationBox = false) {
+ if (locationBox && this.editBaseWidth) return this.editBaseWidth
+ return Math.max(...(this.getText().map(a => Renderer.getStringWidth(ChatLib.removeFormatting(a)))))
+ }
+ getHeight(locationBox = false) {
+ if (locationBox && this.editBaseHeight) return this.editBaseHeight
+ return 9 * this.getText().length
+ }
+
+ getText() {
+ if (Date.now() - this.editTempTimeV < 100) {
+ let text = this.text
+ if (this.editTempTextV) {
+ text = this.editTempTextV
+ }
+
+ if (ChatLib.removeFormatting(text) === "") {
+ text = "&0Empty string"
+ }
+
+ return text.split("\n")
+ }
+ return this.renderTextCache
+ }
+
+ renderRaw() {
+ let text = this.getText()
+
+ for (let i = 0, line = text[0]; i < text.length; i++, line = text[i]) {
+ Renderer.scale(this.locationSetting.scale, this.locationSetting.scale)
+ switch (this.locationSetting.shadowType) {
+ case 0:
+ Renderer.drawString(line, this.locationSetting.x / this.locationSetting.scale, this.locationSetting.y / this.locationSetting.scale + 9 * i)
+ break;
+ case 1:
+ Renderer.drawStringWithShadow(line, this.locationSetting.x / this.locationSetting.scale, this.locationSetting.y / this.locationSetting.scale + 9 * i)
+ break;
+ }
+ }
+ }
+}
+
+export default HudTextElement
\ No newline at end of file
diff --git a/src/features/hud/index.js b/src/features/hud/index.js
new file mode 100644
index 0000000..8805dac
--- /dev/null
+++ b/src/features/hud/index.js
@@ -0,0 +1,812 @@
+///
+///
+import SoopyNumber from "../../../guimanager/Classes/SoopyNumber";
+import Feature from "../../featureClass/class";
+import { m } from "../../../mappings/mappings";
+import LocationSetting from "../settings/settingThings/location";
+import ToggleSetting from "../settings/settingThings/toggle";
+import HudTextElement from "./HudTextElement";
+import DropdownSetting from "../settings/settingThings/dropdownSetting";
+import { getLevelByXp } from "../../utils/statUtils";
+import { firstLetterCapital } from "../../utils/stringUtils";
+import renderLibs from "../../../guimanager/renderLibs";
+import { addNotation, numberWithCommas } from "../../utils/numberUtils.js";
+
+const ProcessBuilder = Java.type("java.lang.ProcessBuilder")
+const Scanner = Java.type("java.util.Scanner")
+
+//TODO: fix messages like [[Frozen Steve]] fell into the pond long ago, never to resurface... until now!
+//TODO: add this feature
+let fishingExp = { "A Squid appeared.": 41, "You caught a Sea Walker.": 68, "Pitch Darkness reveals you've caught a Night Squid.": 270, "You stumbled upon a Sea Guardian.": 101, "It looks like you've disrupted the Sea Witch's brewing session. Watch out, she's furious!": 338, "You reeled in a Sea Archer.": 169, "The Monster of The Deep emerges from the dark depths...": 270, "Huh? A Catfish!": 405, "Gross! A Sea Leech!": 675, "You've discovered a Guardian Defender of the sea.": 1013, "You have awoken the Deep Sea Protector, prepare for a battle!": 1350, "The Water Hydra has come to test your Strength.": 4050, "The Sea Emperor arises from the depths...": 3375, "A Water Worm surfaces!": 240, "A Poisoned Water Worm surfaces!": 270, "A flaming worm surfaces from the depths!": 240, "A Lava Blaze has surfaced from the depths!": 548, "A Lava Pigman arose from the depths!": 568, "A Zombie Miner surfaces!": 770, "From Beneath the lava": 730, "You hear a faint Moo": 950, "A small but fearsome": 1400, "You feel the heat": 1100, "A Lava Flame flies out from beneath the lava.": 2100, "A Fire Eel slithers out": 2200, "Taurus and his steed emerge.": 4300, "You hear a massive rumble as Thunder emerges.": 12000, "You have angered a legendary creature... ": 40000, "WOAH! A Plhlegblast appeared.": 5000, "Phew! It's only a scarecrow.": 420, "You hear trotting from beneath the waves, you caught a Nightmare": 820, "It must be a full moon, it's a Werewolf!": 1235, "The spirit of a long lost Phantom Fisher has come to haunt you.": 2525, "[[Frozen Steve]] fell into the pond long ago, never to resurface... until now!": 101, "Its a Snowman! It looks harmless.": 203, "The Grinch stole [[Jerry]]'s [[Gifts]]...get them back!": 405, "What is this creature!?": 4050, "A tiny fin emerges from the water, you've caught a Nurse Shark.": 405, "You spot a fin as blue as the water it came from, it's a Blue Shark.": 810, "A striped beast bounds from the depths, the wild Tiger Shark!": 1013, "Hide no longer, a Great White Shark has tracked your scent and thirsts for your blood!": 2025 }
+
+class Hud extends Feature {
+ constructor() {
+ super()
+ }
+
+ initVariables() {
+
+ this.hudElements = []
+
+ this.fpsElement = undefined
+ this.cpsElement = undefined
+ this.soulflowElement = undefined
+ this.petElement = undefined
+ this.fpsEnabledSetting = undefined
+ this.cpsEnabledSetting = undefined
+ this.soulflowEnabledSetting = undefined
+ this.soulflowShowWarningSetting = undefined
+ this.soulflowShowWhen0Setting = undefined
+ this.petEnabledSetting = undefined
+ this.fpsFastSetting = undefined
+ this.fpsLowSetting = undefined
+ this.cpsSeperate = undefined
+ this.cpsIncludeRight = undefined
+
+ this.petLevels = undefined
+
+ this.lastTickTime = undefined
+ this.framesSince = undefined
+ this.lastframe = undefined
+ this.Instant = undefined
+
+ this.lastFrameRates = undefined
+
+ this.fps = undefined
+ this.lowFps = undefined
+
+ this.slowestFrameTime = undefined
+ this.lastFrameRatesS = undefined
+ this.numberUtils = undefined
+
+ this.petText = undefined
+
+ this.lastWitherImpact = undefined
+ this.aup = undefined
+ this.lastTickEventEpochTimestamp = undefined
+ this.lastAbsorbtion = undefined
+ this.impactTest = undefined
+ }
+
+ onEnable() {
+ this.initVariables()
+
+ this.numberUtils = require("../../utils/numberUtils.js")
+
+ this.fpsEnabledSetting = new ToggleSetting("Fps enabled", "Whether the fps is rendered onto the screen", true, "fps_enabled", this)
+ this.fpsFastSetting = new ToggleSetting("Fast fps update", "Whether the fps is updated fast instead of once per second", true, "fps_fast", this).requires(this.fpsEnabledSetting)
+ this.fpsLowSetting = new ToggleSetting("Low fps display", "Display the minumum frame time next to fps (usefull for finding framedrops)", true, "fps_low", this).requires(this.fpsFastSetting)
+
+ this.fpsElement = new HudTextElement()
+ .setToggleSetting(this.fpsEnabledSetting)
+ .setLocationSetting(new LocationSetting("Show FPS", "Allows you to edit the location of the fps text", "fps_location", this, [10, 10, 1, 1])
+ .requires(this.fpsEnabledSetting))
+ this.hudElements.push(this.fpsElement)
+
+ this.cpsEnabledSetting = new ToggleSetting("Show CPS", "Whether the cps is rendered onto the screen", true, "cps_enabled", this)
+ this.cpsIncludeRight = new ToggleSetting("CPS include right click", "Whether right clicks are shown in the CPS", true, "cps_right", this).requires(this.cpsEnabledSetting)
+ this.cpsSeperate = new ToggleSetting("CPS seperate right", "Seperates right clicks from left clicks", true, "cps_seperate", this).requires(this.cpsIncludeRight)
+
+ this.cpsElement = new HudTextElement()
+ .setToggleSetting(this.cpsEnabledSetting)
+ .setLocationSetting(new LocationSetting("Cps Location", "Allows you to edit the location of the cps text", "cps_location", this, [10, 20, 1, 1])
+ .requires(this.cpsEnabledSetting))
+ this.hudElements.push(this.cpsElement)
+
+ this.petEnabledSetting = new ToggleSetting("Show Current Pet", "Whether the current pet is rendered onto the screen", true, "pet_enabled", this)
+ this.petElement = new HudTextElement()
+ .setToggleSetting(this.petEnabledSetting)
+ .setLocationSetting(new LocationSetting("Pet Location", "Allows you to edit the location of the pet text", "pet_location", this, [10, 30, 1, 1])
+ .requires(this.petEnabledSetting)
+ .editTempText("&6Pet&7> &7[Lvl 100] &aEnderman"))
+ this.hudElements.push(this.petElement)
+ this.scanGuiForPet = new ToggleSetting("Scan pets menu gui for selected pet", "Only disable if you get a lot of lag in the pets menu", true, "scan_pets_menu", this).requires(this.petEnabledSetting)
+
+ this.soulflowEnabledSetting = new ToggleSetting("Show Soulflow", "Whether the soulflow count is rendered onto the screen", true, "soulflow_enabled", this)
+ this.soulflowShowWhen0Setting = new ToggleSetting("Show When 0 Soulflow", "If this is off it wont render when you have 0 soulflow", true, "soulflow_showwhen_0", this).requires(this.soulflowEnabledSetting)
+ this.soulflowElement = new HudTextElement()
+ .setToggleSetting(this.soulflowEnabledSetting)
+ .setLocationSetting(new LocationSetting("Soulflow Location", "Allows you to edit the location of the soulflow text", "soulflow_location", this, [10, 40, 1, 1])
+ .requires(this.soulflowEnabledSetting)
+ .editTempText("&6Soulflow&7> &f12,345"))
+ this.hudElements.push(this.soulflowElement)
+
+ this.lagEnabled = new ToggleSetting("Show Lobby TPS", "Calculates the TPS of your current lobby (20=no lag)", true, "lobby_lag", this)
+ this.lagElement = new HudTextElement()
+ .setToggleSetting(this.lagEnabled)
+ .setLocationSetting(new LocationSetting("Lobby TPS Location", "Allows you to edit the location of the TPS", "lobby_lag_location", this, [10, 60, 1, 1])
+ .requires(this.lagEnabled)
+ .editTempText("&6Tps&7> &f20.0"))
+ this.hudElements.push(this.lagElement)
+
+ this.witherImpactCooldownSetting = new ToggleSetting("Show Wither Impact Cooldown", "This will render a small cooldown above your crosshair", true, "wither_impact_cooldown_enabled", this)
+
+ // this.guidedSheepCooldownSetting = new ToggleSetting("Show Guided Sheep / Explosive Shot Cooldown", "This will render a small cooldown below your crosshair", true, "guided_sheep_cooldown_enabled", this)
+
+ this.showSpotifyPlaying = new ToggleSetting("Show Current Playing Spotify Song", "(WINDOWS + Spotify Desktop only)", false, "spotify_now_playing", this)
+ this.spotifyElement = new HudTextElement()
+ .setText("&6Spotify&7> ")
+ .setBaseEditWidth(Renderer.getStringWidth("Spotify> ") + 150)
+ .setToggleSetting(this.showSpotifyPlaying)
+ .setLocationSetting(new LocationSetting("Spotify Location", "Allows you to edit the location of the spotify text", "spotify_now_playing_location", this, [10, 80, 1, 1])
+ .requires(this.showSpotifyPlaying)
+ .editTempText("&6Spotify&7> &cNot open"))
+ this.hudElements.push(this.spotifyElement)
+ this.spotifyElement2 = new HudTextElement().setLocationSetting({
+ setParent: () => { },
+ x: this.spotifyElement.locationSetting.x + this.spotifyElement.getWidth(),
+ y: this.spotifyElement.locationSetting.y,
+ scale: this.spotifyElement.locationSetting.scale,
+ shadowType: this.spotifyElement.locationSetting.shadowType
+ })
+ this.spotifyElement2.disableRendering()
+
+ this.showLobbyDay = new ToggleSetting("Show Current Lobby Day", "", true, "lobby_day", this)
+ this.lobbyDayElement = new HudTextElement()
+ .setText("&6Day&7> &fLoading...")
+ .setToggleSetting(this.showLobbyDay)
+ .setLocationSetting(new LocationSetting("Lobby Day Location", "Allows you to edit the location of the lobby day", "lobby_day_location", this, [10, 90, 1, 1])
+ .requires(this.showLobbyDay)
+ .editTempText("&6Day&7> &f5.15"))
+ this.showLobbyDayOnlyUnder30 = new ToggleSetting("Show Current Lobby Day ONLY WHEN under day 30", "", true, "lobby_day_30", this)
+ this.hudElements.push(this.lobbyDayElement)
+
+ let hudStatTypes = {
+ "cata": "Catacombs level + Exp",
+ "totaldeaths": "Total deaths"
+ }
+
+ this.skillLevelCaps = {
+ "experience_skill_combat": 60,
+ "experience_skill_foraging": 50,
+ "experience_skill_farming": 60,
+ "experience_skill_fishing": 50,
+ "experience_skill_alchemy": 50,
+ "experience_skill_enchanting": 60,
+ "experience_skill_mining": 60,
+ "experience_skill_taming": 50,
+ "experience_skill_carpentry": 50,
+ };
+
+ this.lastSkillLevel = {
+ "experience_skill_combat": undefined,
+ "experience_skill_foraging": undefined,
+ "experience_skill_farming": undefined,
+ "experience_skill_fishing": undefined,
+ "experience_skill_alchemy": undefined,
+ "experience_skill_enchanting": undefined,
+ "experience_skill_mining": undefined,
+ "experience_skill_taming": undefined,
+ "experience_skill_carpentry": undefined,
+ }
+
+ this.spotifyProcessId = -1
+
+ Object.keys(this.skillLevelCaps).forEach(skill => {
+ hudStatTypes[skill] = firstLetterCapital(skill.split("_").pop()) + " level + Exp"
+ })
+
+ hudStatTypes.completions_enterance = "Enterance completions"
+ for (let i = 1; i < 8; i++) {
+ hudStatTypes["completions_floor_" + i] = "Floor " + i + " completions"
+ }
+ for (let i = 1; i < 8; i++) {
+ hudStatTypes["completions_master_" + i] = "Master " + i + " completions"
+ }
+ for (let i = 1; i < 8; i++) {
+ hudStatTypes["completions_dungeon_" + i] = "Dungeon " + i + " completions"
+ }
+
+
+ hudStatTypes["mythril_powder"] = "Mithril Powder"
+ hudStatTypes["gemstone_powder"] = "Gemstone Powder"
+
+ this.extendLevelCap = new ToggleSetting("Hud Stat Ignore Skill Level Cap", "level cap goes over 60 requiring 50m xp per level", false, "hud_ignore_level_cap", this).contributor("EmeraldMerchant")
+ this.showLevelUpMessage = new ToggleSetting("Show level-up message", "Shows skyblock skills level-up message over level 60 in chat", true, "skill_o60_level_message", this).requires(this.extendLevelCap).contributor("EmeraldMerchant")
+
+ this.hudStat = []
+ for (let i = 0; i < 5; i++) {
+ this.hudStat[i] = {}
+ this.hudStat[i].enabled = new ToggleSetting("Hud Stat Slot #" + (i + 1), "Allows you to render a custom stat on your hud", false, "hud_stat_" + i, this)
+ this.hudStat[i].type = new DropdownSetting("Hud Stat Slot #" + (i + 1) + " Type", "The type of stat to render", "weight", "hud_stat_" + i + "_type", this, hudStatTypes)
+ this.hudStat[i].location = new LocationSetting("Hud Stat Slot #" + (i + 1) + " Location", "Allows you to edit the location of the hud stat", "hud_stat_" + i + "_location", this, [10, 50 + i * 10, 1, 1]).editTempText("&6Hud Stat&7> &f12,345")
+ this.hudStat[i].textElement = new HudTextElement().setToggleSetting(this.hudStat[i].enabled).setLocationSetting(this.hudStat[i].location).setText("&6Hud Stat&7> &fLoading...")
+ this.hudStat[i].onlySb = new ToggleSetting("Hud Stat Slot #" + (i + 1) + " Only SB", "Only render this stat when you are in skyblock", true, "hud_stat_" + i + "_only_sb", this).requires(this.hudStat[i].enabled)
+
+ this.hudStat[i].location.requires(this.hudStat[i].enabled)
+ this.hudStat[i].type.requires(this.hudStat[i].enabled)
+ if (this.hudStat[i - 1]) {
+ this.hudStat[i].enabled.requires(this.hudStat[i - 1].enabled)
+ }
+ }
+
+
+ this.showDragonDamages = new ToggleSetting("Show dragon damages", "This will render the top 3 damages + your damage during a dragon fight", true, "dragon_dmg_enable", this)
+ this.dragonDamageElement = new HudTextElement()
+ .setToggleSetting(this.showDragonDamages)
+ .setLocationSetting(new LocationSetting("Damage Location", "Allows you to edit the location of the damage leaderboard", "dragon_dmg_location", this, [50, 40, 1, 1])
+ .requires(this.showDragonDamages)
+ .editTempText("&6Old Dragon &7(&f13.4&7M HP)\n&7- &fSoopyboo32&7:&f 13.4&7M\n&7- &fCamCamSatNav&7:&f 12.3&7M\n&7- &fMuffixy&7:&f 3.4&7M"))
+ this.hudElements.push(this.dragonDamageElement)
+
+
+ this.step_5second()
+
+ this.lastTickTime = 0
+ this.framesSince = 0
+ this.lastframe = 0
+ this.slowestFrameTime = 0
+
+ this.lastSwappedPet = 0
+
+ this.lastWitherImpact = 0
+ this.aup = 0
+ this.lastTickEventEpochTimestamp = 0
+ this.lastAbsorbtion = 0
+ this.impactTest = false
+ this.apiSoulflow = false
+
+ this.lastUpdatedStatData = 0
+
+ this.lastStatData = undefined
+
+ this.lastFrameRates = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ this.lastFrameRatesS = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+
+ this.Instant = Java.type("java.time.Instant");
+
+ this.fps = new SoopyNumber(0)
+ this.lowFps = new SoopyNumber(0)
+
+ this.registerEvent("renderOverlay", this.renderHud).registeredWhen(() => this.showSpotifyPlaying.getValue() || this.witherImpactCooldownSetting.getValue())
+ this.registerStep(true, 5, this.step)
+ this.registerStep(false, 5, this.step_5second)
+ this.registerEvent("renderWorld", this.renderWorld).registeredWhen(() => this.fpsEnabledSetting.getValue() && this.fpsFastSetting.getValue())
+ this.registerEvent("worldLoad", this.worldLoad)
+
+
+ this.petLevels = {}
+ this.petText = "&6Pet&7> &fLoading..."
+ this.petElement.setText(this.petText)
+ this.registerChat("&cAutopet &eequipped your ${pet}&e! &a&lVIEW RULE&r", (pet) => {
+ this.petElement.setText("&6Pet&7> " + pet)
+ this.petText = "&6Pet&7> " + pet
+
+ this.lastSwappedPet = Date.now()
+ })
+ this.registerChat("&r&aYou summoned your &r${pet}&r&a!&r", (pet) => {
+ this.petElement.setText("&6Pet&7> &7[Lvl " + (this.petLevels[pet.replace("&", "§")] || "??") + "] " + pet)
+ this.petText = "&6Pet&7> &7[Lvl " + (this.petLevels[pet.replace("&", "§")] || "??") + "] " + pet
+
+ this.lastSwappedPet = Date.now()
+ })
+ this.registerChat("&r&aYou despawned your &r${*}&r&a!&r", () => {
+ this.petElement.setText("&6Pet&7> &cNone")
+ this.petText = "&6Pet&7> &cNone"
+
+ this.lastSwappedPet = Date.now()
+ })
+ this.registerChat("&r&aYour &r${pet} &r&alevelled up to level &r&9${level}&r&a!&r", (pet, level) => {
+ if (ChatLib.removeFormatting(this.petText.split("] ")[1].trim()) === ChatLib.removeFormatting(pet.trim())) {
+ this.petElement.setText("&6Pet&7> &7[Lvl " + (level || "??") + "] " + pet)
+ this.petText = "&6Pet&7> &7[Lvl " + (level || "??") + "] " + pet
+ this.lastSwappedPet = Date.now()
+ }
+ })
+
+ this.registerSoopy("apiLoad", this.apiLoad)
+ if (this.FeatureManager.features["dataLoader"].class.lastApiData.skyblock) {
+ this.apiLoad(this.FeatureManager.features["dataLoader"].class.lastApiData.skyblock, "skyblock", true, true)
+
+ this.lastSwappedPet = Date.now()
+ }
+ if (this.FeatureManager.features["dataLoader"].class.lastApiData.skyblock_raw) {
+ this.apiLoad(this.FeatureManager.features["dataLoader"].class.lastApiData.skyblock_raw, "skyblock", false, true)
+ }
+
+ this.registerStep(false, 5, () => {
+ if (!this.showSpotifyPlaying.getValue()) return
+
+ new Thread(() => {
+ this.updateSpotify()
+ }).start()
+ })
+
+ this.registerActionBar("${m}", this.actionbarMessage)
+
+ this.packetMoves = 0
+ this.secondPackets = 0
+ this.tps = -2
+ this.lastTps = []
+ this.registerEvent("tick", this.tick)
+ this.registerStep(false, 1, this.step_1second)
+ }
+
+ step_1second() {
+ if (World.getTime() / 20 / 60 / 20 > 30 && this.showLobbyDayOnlyUnder30.getValue()) {
+ this.lobbyDayElement.setText("")
+ } else {
+ if (World.getTime() !== 0) this.lobbyDayElement.setText("&6Day&7> &f" + (World.getTime() / 20 / 60 / 20).toFixed(2))
+ }
+
+ if (!this.lagEnabled.getValue()) {
+ if (this.packetReceived) this.packetReceived.unregister()
+ return
+ }
+ if (!this.packetReceived) this.packetReceived = register("packetReceived", () => {
+ this.packetMoves++
+ })
+ this.lastTps.push(this.secondPackets)
+ if (this.lastTps.length > 10) this.lastTps.shift()
+ if (this.tps === -2) {
+ this.tps = -1
+ this.lastTps = []
+ }
+ this.tps = this.lastTps.reduce((a, b) => a + b, 0) / this.lastTps.length
+ this.secondPackets = 0
+
+ if (this.lastTps.length > 1) {
+ this.lagElement.setText("&6Tps&7> &f" + Math.min(20, this.tps).toFixed(1))
+ } else {
+ this.lagElement.setText("&6Tps&7> &fLOADING")
+ }
+ }
+
+ tick() {
+ if (this.fpsFastSetting.getValue()) {
+ if (this.fpsLowSetting.getValue()) {
+ this.fpsElement.setText("&6Fps&7> &f" + Math.round(this.fps.get()) + "&7/" + Math.round(this.lowFps.get()))
+ } else {
+ this.fpsElement.setText("&6Fps&7> &f" + Math.round(this.fps.get()))
+ }
+ }
+
+ if (!this.lagEnabled.getValue()) return
+ if (this.packetMoves > 0) {
+ this.secondPackets++
+ this.packetMoves = 0
+ }
+ }
+
+ onDisable() {
+ this.fpsEnabledSetting.delete()
+ this.fpsFastSetting.delete()
+ this.cpsEnabledSetting.delete()
+
+ this.hudStat.forEach(h => h.textElement.delete())
+ this.hudElements.forEach(h => h.delete())
+
+ this.initVariables()
+
+ if (this.packetReceived) this.packetReceived.unregister()
+ }
+
+ renderHud() {
+ if (this.showSpotifyPlaying.getValue() && Date.now() - this.spotifyElement.tempDisableTime > 100) {
+ let scale = this.spotifyElement.locationSetting.scale
+ let spotifyWidth1 = this.spotifyElement.getWidth() * scale
+ this.spotifyElement2.locationSetting.x = this.spotifyElement.locationSetting.x + spotifyWidth1
+ this.spotifyElement2.locationSetting.y = this.spotifyElement.locationSetting.y
+ this.spotifyElement2.locationSetting.scale = scale
+ this.spotifyElement2.locationSetting.shadowType = this.spotifyElement.locationSetting.shadowType
+
+ let spotifyWidth2 = this.spotifyElement2.getWidth() * scale
+ if (spotifyWidth2 > 150 * scale) {
+ let w2 = spotifyWidth2 / scale - 150
+ let offX = (Date.now() / 50) % (w2 * 2 + 100)
+ offX = Math.max(0, offX - 50)
+ if (offX > w2 + 50) {
+ offX = w2 - (offX - w2 - 50)
+ } else if (offX > w2) {
+ offX = w2
+ }
+ this.spotifyElement2.locationSetting.x = this.spotifyElement.locationSetting.x + spotifyWidth1 - offX * scale
+
+ renderLibs.scizzorFast(this.spotifyElement.locationSetting.x + spotifyWidth1, this.spotifyElement2.locationSetting.y, 150 * scale, this.spotifyElement2.getHeight() * scale)
+ this.spotifyElement2.render()
+ renderLibs.stopScizzor()
+ } else {
+ this.spotifyElement2.render()
+ }
+ }
+
+ if (this.witherImpactCooldownSetting.getValue() && Date.now() - this.lastWitherImpact < 10000) {
+ Renderer.drawString(Math.max(0, Math.ceil((5000 - (Date.now() - this.lastWitherImpact)) / 1000)) + "s", Renderer.screen.getWidth() / 2 - Renderer.getStringWidth(Math.max(0, Math.ceil((5000 - (Date.now() - this.lastWitherImpact)) / 1000)) + "s") / 2, Renderer.screen.getHeight() / 2 - 15)
+ }
+ }
+
+ renderWorld() {
+ this.framesSince++
+
+ let instant = this.Instant.now()
+ let time = instant.getEpochSecond() + (instant.getNano() / 1000000000);
+
+ let thisframeTime = time - this.lastFrame
+ // console.log(thisframeTime * 1000)
+
+ if (thisframeTime > this.slowestFrameTime) {
+ this.slowestFrameTime = thisframeTime
+ }
+
+ this.lastFrame = time
+ }
+
+ actionbarMessage(m) {
+ if (ChatLib.removeFormatting(m).includes("(Wither Impact)")) {
+ if (Date.now() - this.aup < 750) {
+ this.lastWitherImpact = Date.now()
+ this.aup = 0
+ } else {
+ this.impactTest = Date.now()
+ }
+ }
+ }
+
+ step() {
+ if (!Player.getPlayer()) return
+ let fps = 0
+
+ if (this.fpsEnabledSetting.getValue() && this.fpsFastSetting.getValue()) {
+ //set fps to fast fps
+ // console.log(`${this.framesSince} ${this.lastFrame-this.lastTickTime}`)
+ fps = this.framesSince / (this.lastFrame - this.lastTickTime)
+ if (this.lastFrame === this.lastTickTime) fps = 0
+ this.lastTickTime = this.lastFrame
+ this.framesSince = 0
+
+ this.lastFrameRates.push(fps)
+ this.lastFrameRates.shift()
+
+ if (this.slowestFrameTime > 0) {
+ this.lastFrameRatesS.push(1 / this.slowestFrameTime)
+ } else {
+ this.lastFrameRatesS.push(0)
+ }
+ this.lastFrameRatesS.shift()
+ this.slowestFrameTime = 0
+
+ fps = this.lastFrameRates.reduce((a, b) => a + b, 0) / this.lastFrameRates.length
+ this.fps.set(fps, 200)
+ if (this.fpsLowSetting.getValue()) this.lowFps.set(this.lastFrameRatesS.reduce((a, b) => a + b, 0) / this.lastFrameRatesS.length, 200)
+ } else {
+ fps = Client.getFPS()
+ this.fpsElement.setText("&6Fps&7> &f" + fps)
+ }
+
+ let cpsText = CPS.getLeftClicksAverage()
+
+ if (this.cpsIncludeRight.getValue()) {
+ if (this.cpsSeperate.getValue()) {
+ cpsText += "&7 | &f" + CPS.getRightClicksAverage()
+ } else {
+ cpsText += CPS.getRightClicksAverage()
+ }
+ }
+ this.cpsElement.setText("&6Cps&7> &f" + cpsText)
+
+ //Scan opened inventory for all pet levels
+ if (this.scanGuiForPet.getValue() && Player && Player.getContainer() && Player.getContainer().getName().includes(") Pets")) {
+ let inv = Player.getContainer().getItems()
+ for (let i = 0; i < inv.length; i++) {
+ if (inv[i] != null && inv[i].getName().includes("[Lvl ")) {
+ let level = inv[i].getName().split(" ")[1].replace("]", "")
+ if (!this.petLevels[inv[i].getName().split("] ")[1]] || this.petLevels[inv[i].getName().split("] ")[1]] < level) this.petLevels[inv[i].getName().split("] ")[1]] = level
+
+ if (Date.now() - this.lastSwappedPet > 1000) {
+ inv[i].getLore().forEach(line => {
+ if (line.includes("Click to despawn!")) {
+ this.petElement.setText("&6Pet&7> &7" + inv[i].getName().split("(")[0])
+ this.petText = "&6Pet&7> &7" + inv[i].getName().split("(")[0]
+ }
+ })
+ }
+ }
+ }
+ }
+
+ this.dragonDamageElement.setText("")
+
+ if (this.showDragonDamages.getValue()) {
+
+ let playerDamage = -1
+ let dragonHealth = -1
+
+ Scoreboard.getLines().forEach(line => {
+ if (ChatLib.removeFormatting(line).startsWith("Your Damage: ")) {
+ playerDamage = parseInt(ChatLib.removeFormatting(line).replace("Your Damage: ", "").replace(/[^0-9\.]/g, ""))
+ }
+ if (ChatLib.removeFormatting(line).startsWith("Dragon HP: ")) {
+ dragonHealth = parseInt(ChatLib.removeFormatting(line).replace("Dragon HP: ", "").replace(/[^0-9\.]/g, ""))
+ }
+ })
+
+ if (playerDamage > -1) {
+
+ let damages = [[Player.getName(), playerDamage]]
+ let dragonType = ""
+
+ let lbNum = 0
+
+ TabList.getNames().forEach(n => {
+ l = ChatLib.removeFormatting(n)
+
+ if (lbNum > 0) {
+ lbNum--
+
+ // Soopyboo32: 3.2M
+
+ let name = l.split(":")[0].trim()
+
+ if (name === Player.getName()) return
+
+ let damage = l.split(" ").pop()
+
+ let actualDamage = parseFloat(damage)
+
+ if (damage.includes("k")) actualDamage *= 1000
+ if (damage.includes("M")) actualDamage *= 1000000
+
+ damages.push([name, actualDamage])
+ }
+ if (l.startsWith("Dragon Fight: (")) {
+ dragonType = l.split("(")[1].split(")")[0]
+
+ lbNum = 3
+ }
+ })
+
+ let text = `&6${dragonType} Dragon &7(&f${addNotation("oneLetters", dragonHealth, "&7")}&7 HP)`
+
+ damages.sort((a, b) => b[1] - a[1]).forEach(d => {
+ text += `\n&7- &f${d[0]}&7: &f${addNotation("oneLetters", d[1], "&7")}`
+ })
+
+ this.dragonDamageElement.setText(text)
+ }
+
+ }
+
+ if (Player.getPlayer()[m.getAbsorptionAmount]() > this.lastAbsorbtion) {
+ if (Date.now() - this.impactTest < 750) {
+ this.lastWitherImpact = Date.now()
+ this.impactTest = 0
+ } else {
+ this.aup = Date.now()
+ }
+ }
+ this.lastAbsorbtion = Player.getPlayer()[m.getAbsorptionAmount]()
+ }
+
+ step_5second() {
+ this.updateHudThingos()
+
+ if (!this.soulflowEnabledSetting.getValue()) return
+ if (!Player.getPlayer()) return
+ if (!Player.getInventory()) return
+
+ if (this.FeatureManager.features["dataLoader"] && !this.FeatureManager.features["dataLoader"].class.isInSkyblock) {
+ this.soulflowElement.setText("")
+ this.petElement.setText("")
+ return
+ } else {
+ this.petElement.setText(this.petText)
+ }
+
+ if (!this.apiSoulflow) {
+ this.soulflowElement.setText("")
+ return;
+ }
+
+ this.soulflowElement.setText("&6Soulflow&7> &f" + this.numberUtils.numberWithCommas(this.lastStatData.soulflow))
+ }
+
+ statApiLoadThingo(data) {
+ data.profiles.forEach(p => {
+ if (!this.lastStatData || (p.members[Player.getUUID().toString().replace(/-/g, "")] && p.members[Player.getUUID().toString().replace(/-/g, "")].last_save > this.lastStatData.last_save)) {
+ this.lastStatData = p.members[Player.getUUID().toString().replace(/-/g, "")]
+ }
+ })
+
+ if (this.lastStatData) {
+ if (this.lastStatData.soulflow) this.apiSoulflow = true
+
+ if (this.apiSoulflow) this.soulflowElement.setText("&6Soulflow&7> &f" + this.numberUtils.numberWithCommas(this.lastStatData.soulflow))
+ }
+
+ if (this.showLevelUpMessage.getValue()) {
+ Object.keys(this.skillLevelCaps).forEach(skill => {
+ let skillData = getLevelByXp(this.lastStatData[skill], 0, this.extendLevelCap.getValue() ? Infinity : this.skillLevelCaps[skill])
+ if (this.lastSkillLevel[skill] === skillData.level - 1 && (skillData.level > (this.skillLevelCaps[skill] === 50 ? 50 : 60))) {
+ ChatLib.chat(`&r&3&l▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬&r`)
+ ChatLib.chat(` &r&b&lSKILL LEVEL UP &3${firstLetterCapital(skill.split("_").pop())} &8${skillData.level - 1}➜&3${skillData.level}&r`)
+ ChatLib.chat(`&r &r&a&lREWARDS&r\n&r &r&6&lSoopy's Respect\n&r&3&l▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬&r\n`)
+ }
+ this.lastSkillLevel[skill] = skillData.level;
+ })
+ }
+
+ this.updateHudThingos()
+ }
+
+ updateSpotify() {
+ if (!this.showSpotifyPlaying.getValue()) return
+
+ let currentSong = "&cNot open"
+
+ if (this.spotifyProcessId !== -1) {
+ let pid = this.spotifyProcessId
+
+ let process = new ProcessBuilder("tasklist.exe", "/FO", "csv", "/V", "/FI", "\"PID eq " + pid + "\"").start();
+ let sc = new Scanner(process.getInputStream());
+ if (sc.hasNextLine()) sc.nextLine();
+ while (sc.hasNextLine()) {
+ let line = sc.nextLine();
+ let parts = line.replace("\"", "").split("\",\"");
+ let song = parts[parts.length - 1].substr(0, parts[parts.length - 1].length - 1)
+ if (song === "N/A") continue
+
+ if (song === "Spotify Free" || song === "Spotify Premium" || song === "AngleHiddenWindow") {
+ currentSong = "&cPaused"
+ } else {
+ if (song === "Spotify") song = "Advertisement"
+ currentSong = "&a" + song.replace(/&/g, "&⭍").replace(" - ", " &7-&b ")
+ }
+
+ }
+ process.waitFor();
+
+ this.spotifyElement2.setText(currentSong.normalize("NFD").replace(/[\u0300-\u036f]/g, ""))
+ }
+
+ if (currentSong !== "&cNot open") return
+
+ this.spotifyProcessId = -1
+ let spotifyProcesses = []
+ let process = new ProcessBuilder("tasklist.exe", "/fo", "csv", "/nh").start();
+ let sc = new Scanner(process.getInputStream());
+ if (sc.hasNextLine()) sc.nextLine();
+ while (sc.hasNextLine()) {
+ let line = sc.nextLine();
+ let parts = line.replace("\"", "").split("\",\"");
+ let unq = parts[0]
+ let pid = parts[1]
+ if (unq === "Spotify.exe") {
+ spotifyProcesses.push(pid)
+ // console.log(parts.join(" "));
+ }
+ }
+ process.waitFor();
+
+ while (spotifyProcesses.length > 0) {
+ let pid = spotifyProcesses.pop()
+ // console.log("Loading pid " + pid)
+ let process = new ProcessBuilder("tasklist.exe", "/FO", "csv", "/V", "/FI", "\"PID eq " + pid + "\"").start();
+ let sc = new Scanner(process.getInputStream());
+ if (sc.hasNextLine()) sc.nextLine();
+ while (sc.hasNextLine()) {
+ let line = sc.nextLine();
+ let parts = line.replace("\"", "").split("\",\"");
+ let song = parts[parts.length - 1].substr(0, parts[parts.length - 1].length - 1)
+ if (song === "N/A") continue
+
+ this.spotifyProcessId = pid
+
+ if (song === "Spotify Free" || song === "Spotify Premium" || song === "AngleHiddenWindow") {
+ currentSong = "&cPaused"
+ } else {
+ if (song === "Spotify") song = "Advertisement"
+ currentSong = "&a" + song.replace(/&/g, "&⭍").replace(" - ", " &7-&b ")
+ }
+
+ }
+ process.waitFor();
+ }
+
+ this.spotifyElement2.setText(currentSong.normalize("NFD").replace(/[\u0300-\u036f]/g, ""))
+ }
+
+ updateHudThingos() {
+ let insb = !!(this.FeatureManager.features["dataLoader"] && this.FeatureManager.features["dataLoader"].class?.isInSkyblock)
+
+ this.hudStat.forEach(stat => {
+ if (stat.enabled.getValue()) {
+ this.updateHudThing(stat, insb)
+ } else {
+ stat.textElement.setText("")
+ }
+ })
+ }
+
+ updateHudThing(thing, insb) {
+ if (!this.lastStatData) return
+
+ if (!insb && thing.onlySb.getValue()) {
+ thing.textElement.setText("")
+ return
+ }
+
+ let type = thing.type.getValue()
+
+ let string = "Unknown stat"
+ if (type === "totaldeaths") {
+ string = "&6Deaths&7> &f" + this.numberUtils.numberWithCommas(this.lastStatData.death_count)
+ }
+ if (type === "cata") {
+ let cataData = getLevelByXp(this.lastStatData.dungeons.dungeon_types.catacombs.experience, 2, Infinity)
+ string = "&6Cata&7> &f" + (~~((cataData.level + cataData.progress) * 100) / 100).toFixed(2) + " &7(" + this.numberUtils.numberWithCommas(cataData.xpCurrent) + (cataData.level === 50 ? "" : "/" + this.numberUtils.numberWithCommas(cataData.xpForNext)) + ")"
+ }
+ if (type === "mythril_powder") {
+ string = "&6Mithril Powder&7> &f" + numberWithCommas(this.lastStatData.mining_core.powder_mithril_total)
+ }
+ if (type === "gemstone_powder") {
+ string = "&6Gemstone Powder&7> &f" + numberWithCommas(this.lastStatData.mining_core.powder_gemstone_total)
+ }
+
+ Object.keys(this.skillLevelCaps).forEach(skill => {
+ if (type === skill) {
+ let skillData = getLevelByXp(this.lastStatData[skill], 0, this.extendLevelCap.getValue() ? Infinity : this.skillLevelCaps[skill])
+ this.lastSkillLevel[skill] = skillData.level;
+ string = "&6" + firstLetterCapital(skill.split("_").pop()) + "&7> &f" + (skillData.level + skillData.progress).toFixed(2) + " &7(" + this.numberUtils.numberWithCommas(skillData.xpCurrent) + (skillData.level === this.skillLevelCaps[skill] ? "" : "/" + this.numberUtils.numberWithCommas(skillData.xpForNext)) + ")"
+ }
+ })
+
+ if (type === "completions_enterance") {
+ string = "&6E Comps&7> &f" + this.numberUtils.numberWithCommas((this.lastStatData.dungeons?.dungeon_types?.catacombs?.tier_completions?.[0] || 0))
+ }
+ if (type.startsWith("completions_floor_")) {
+ let floor = parseInt(type.split("_").pop())
+ string = "&6F" + floor + " Comps&7> &f" + this.numberUtils.numberWithCommas((this.lastStatData.dungeons?.dungeon_types?.catacombs?.tier_completions?.[floor] || 0))
+ }
+ if (type.startsWith("completions_master_")) {
+ let floor = parseInt(type.split("_").pop())
+ string = "&6M" + floor + " Comps&7> &f" + this.numberUtils.numberWithCommas((this.lastStatData.dungeons?.dungeon_types?.master_catacombs?.tier_completions?.[floor] || 0))
+ }
+ if (type.startsWith("completions_dungeon_")) {
+ let floor = parseInt(type.split("_").pop())
+ string = "&6Dungeon " + floor + " Comps&7> &f" + this.numberUtils.numberWithCommas((this.lastStatData.dungeons?.dungeon_types?.catacombs?.tier_completions?.[floor] || 0) + (this.lastStatData.dungeons?.dungeon_types?.master_catacombs?.tier_completions?.[floor] || 0))
+ }
+
+ thing.textElement.setText(string)
+ }
+
+ apiLoad(data, dataType, isSoopyServer, isLatest) {
+ if (dataType === "skyblock" && !isSoopyServer) {
+ this.statApiLoadThingo(data)
+ }
+ if (!isSoopyServer || !isLatest) return
+ if (dataType !== "skyblock") return
+
+ let pet = data.data.profiles[data.data.stats.currentProfileId].members[Player.getUUID().replace(/-/g, "")].selectedPet
+
+ if (!pet) {
+ this.petElement.setText("&6Pet&7> &cNone")
+ this.petText = "&6Pet&7> &cNone"
+ return;
+ }
+
+ let petTierColor = {
+ "COMMON": "&f",
+ "UNCOMMON": "&a",
+ "RARE": "&9",
+ "EPIC": "&5",
+ "LEGENDARY": "&6",
+ "MYTHIC": "&d"
+ }
+
+ this.petElement.setText("&6Pet&7> &7[Lvl " + (pet.level.level || "??") + "] " + petTierColor[pet.tier] + pet.name)
+ this.petText = "&6Pet&7> &7[Lvl " + (pet.level.level || "??") + "] " + petTierColor[pet.tier] + pet.name
+ }
+
+ worldLoad() {
+ this.lastUpdatedStatData = 0
+ this.packetMoves = 0
+ this.secondPackets = 0
+ this.tps = -2
+ this.lastTps = []
+ this.lagElement.setText("&6Tps&7> &fLOADING")
+ }
+}
+
+module.exports = {
+ class: new Hud()
+}
diff --git a/src/features/hud/metadata.json b/src/features/hud/metadata.json
new file mode 100644
index 0000000..67f5671
--- /dev/null
+++ b/src/features/hud/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Hud",
+ "description": "Adds a HUD with custom gui elements like fps, cps, equipped pet ect",
+ "isHidden": false,
+ "isTogglable": true,
+ "defaultEnabled": true,
+ "sortA": 2
+}
\ No newline at end of file
diff --git a/src/features/lockedFeatures/index.js b/src/features/lockedFeatures/index.js
new file mode 100644
index 0000000..7557619
--- /dev/null
+++ b/src/features/lockedFeatures/index.js
@@ -0,0 +1,121 @@
+///
+///
+import Feature from "../../featureClass/class";
+import ToggleSetting from "../settings/settingThings/toggle";
+import SoopyV2Server from "../../socketConnection"
+import HudTextElement from "../hud/HudTextElement";
+import LocationSetting from "../settings/settingThings/location";
+import { numberWithCommas, timeNumber2, timeSince } from "../../utils/numberUtils";
+import FakeRequireToggle from "../settings/settingThings/FakeRequireToggle";
+
+class LockedFeatures extends Feature {
+ constructor() {
+ super()
+ }
+
+ onEnable() {
+ this.initVariables()
+
+ this.guildEventLbPossible = new FakeRequireToggle(false)
+ this.guildEventLb = new ToggleSetting("Guild event leaderboard", "A gui element for guild leaderboard progress", true, "guild_event_lb", this).requires(this.guildEventLbPossible)
+
+ this.hudElements = []
+ this.guildLbElement = new HudTextElement()
+ .setToggleSetting(this.guildEventLb)
+ .setLocationSetting(new LocationSetting("Guild Lb Location", "Allows you to edit the location of the guild leaderboard", "guild_lb_location", this, [50, 40, 1, 1])
+ .requires(this.guildEventLb))
+ this.hudElements.push(this.guildLbElement)
+
+ this.eventCommand = undefined
+
+ this.registerStep(true, 1, this.step)
+ }
+
+ step() {
+ if (!SoopyV2Server.lbdatathing) {
+ this.guildEventLbPossible.set(false)
+ if (this.eventCommand) {
+ this.eventCommand.unregister()
+ this.eventCommand = undefined
+ }
+ return;
+ }
+
+ this.guildEventLbPossible.set(true)
+
+ if (!this.eventCommand) {
+ this.eventCommand = this.registerCommand("eventlb", () => {
+ SoopyV2Server.lbdatathing.forEach((u, i) => {
+ let text = ""
+ text += "§6#" + (i + 1)
+ text += "§7 - "
+ text += "§e" + u.username
+ text += "&7: §r" + numberWithCommas(Math.round(parseFloat(u.startingAmount)))
+ if (u.progress) text += " §7(" + (u.progress > 0 ? "+" : "-") + Math.abs(Math.round(u.progress)) + "/h)"
+ ChatLib.chat(text)
+ })
+ })
+ }
+
+ if (!this.guildEventLb.getValue()) return
+
+ let text = ""
+
+ let playerPos = 0
+
+ SoopyV2Server.lbdatathing.forEach((u, i) => {
+ if (u.uuid === Player.getUUID().toString().replace(/-/g, "")) playerPos = i
+ })
+
+ let prevProgress
+ let playerProgress
+ let nextProgress
+
+ SoopyV2Server.lbdatathing.forEach((u, i) => {
+ if (i === playerPos - 1) nextProgress = [parseFloat(u.startingAmount), u.progress]
+ if (i === playerPos) playerProgress = [parseFloat(u.startingAmount), u.progress]
+ if (i === playerPos + 1) prevProgress = [parseFloat(u.startingAmount), u.progress]
+ if (i === playerPos - 1 || i === playerPos || i === playerPos + 1 || (playerPos === 0 && i === playerPos + 2)) {
+ text += "§6#" + (i + 1)
+ text += "§7 - "
+ text += "§e" + u.username
+ text += "&7: §f" + numberWithCommas(Math.round(parseFloat(u.startingAmount)))
+ if (u.progress) text += " §7(" + (u.progress > 0 ? "+" : "-") + Math.abs(Math.round(u.progress)) + "/h)"
+ text += "\n"
+ }
+ })
+
+ text += "&dLast updated " + timeSince(SoopyV2Server.lbdatathingupdated) + " ago"
+
+ let timeTillIncrease = Infinity
+ let timeTillDecrease = Infinity
+ if (nextProgress && nextProgress[1] - playerProgress[1] < 0) {
+ timeTillIncrease = ((nextProgress[0] - playerProgress[0]) / (playerProgress[1] - nextProgress[1]) * 60 * 60 * 1000)
+ }
+ if (prevProgress && prevProgress[1] - playerProgress[1] < 0) {
+ timeTillDecrease = ((playerProgress[0] - prevProgress[0]) / (prevProgress[1] - playerProgress[1]) * 60 * 60 * 1000)
+ }
+
+ if ((timeTillIncrease < timeTillDecrease || (timeTillIncrease > 0)) && timeTillDecrease < 0 && timeTillIncrease < 10000000000) {
+ text = "&d ^ in " + timeNumber2(timeTillIncrease) + "\n" + text
+ }
+ if ((timeTillIncrease > timeTillDecrease || (timeTillDecrease > 0)) && timeTillIncrease < 0 && timeTillDecrease < 10000000000) {
+ text = "&d v in " + timeNumber2(timeTillDecrease) + "\n" + text
+ }
+
+ this.guildLbElement.setText(text)
+ }
+
+ initVariables() {
+
+ }
+
+ onDisable() {
+ this.hudElements.forEach(h => h.delete())
+ this.initVariables()
+ }
+}
+
+module.exports = {
+ class: new LockedFeatures()
+}
diff --git a/src/features/lockedFeatures/metadata.json b/src/features/lockedFeatures/metadata.json
new file mode 100644
index 0000000..7506cc2
--- /dev/null
+++ b/src/features/lockedFeatures/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Locked Features",
+ "description": "A bunch of random features that are only accessable to some people\n§0(eg only people in specific guild)",
+ "isHidden": false,
+ "isTogglable": true,
+ "defaultEnabled": true,
+ "sortA": 1
+}
\ No newline at end of file
diff --git a/src/features/mining/coords.json b/src/features/mining/coords.json
new file mode 100644
index 0000000..246731b
--- /dev/null
+++ b/src/features/mining/coords.json
@@ -0,0 +1,202 @@
+[
+ [
+ -7,
+ 26,
+ -2
+ ],
+ [
+ -15,
+ 26,
+ 31
+ ],
+ [
+ -17,
+ 26,
+ 19
+ ],
+ [
+ 47,
+ 25,
+ 33
+ ],
+ [
+ 36,
+ 26,
+ 45
+ ],
+ [
+ 48,
+ 27,
+ 45
+ ],
+ [
+ 45,
+ 27,
+ -13
+ ],
+ [
+ -38,
+ 26,
+ 21
+ ],
+ [
+ 42,
+ 26,
+ 27
+ ],
+ [
+ 29,
+ 27,
+ -7
+ ],
+ [
+ 22,
+ 26,
+ -15
+ ],
+ [
+ -7,
+ 27,
+ -26
+ ],
+ [
+ -2,
+ 26,
+ -6
+ ],
+ [
+ 43,
+ 27,
+ -21
+ ],
+ [
+ 10,
+ 26,
+ -11
+ ],
+ [
+ 17,
+ 26,
+ 49
+ ],
+ [
+ 19,
+ 26,
+ -17
+ ],
+ [
+ -35,
+ 27,
+ 35
+ ],
+ [
+ 25,
+ 27,
+ 5
+ ],
+ [
+ -37,
+ 24,
+ 46
+ ],
+ [
+ -24,
+ 26,
+ 49
+ ],
+ [
+ -7,
+ 26,
+ 48
+ ],
+ [
+ -14,
+ 27,
+ -24
+ ],
+ [
+ -18,
+ 27,
+ 44
+ ],
+ [
+ -1,
+ 26,
+ -23
+ ],
+ [
+ 41,
+ 25,
+ -37
+ ],
+ [
+ 19,
+ 26,
+ -38
+ ],
+ [
+ -7,
+ 27,
+ 27
+ ],
+ [
+ 42,
+ 26,
+ 19
+ ],
+ [
+ 42,
+ 26,
+ 19
+ ],
+ [
+ -33,
+ 27,
+ 31
+ ],
+ [
+ 6,
+ 27,
+ 25
+ ],
+ [
+ -2,
+ 26,
+ -17
+ ],
+ [
+ -15,
+ 27,
+ 5
+ ],
+ [
+ -20,
+ 27,
+ -12
+ ],
+ [
+ -25,
+ 26,
+ 30
+ ],
+ [
+ 28,
+ 27,
+ -35
+ ],
+ [
+ -19,
+ 27,
+ -22
+ ],
+ [
+ 4,
+ 26,
+ -15
+ ],
+ [
+ 36,
+ 26,
+ 17
+ ]
+]
\ No newline at end of file
diff --git a/src/features/mining/index.js b/src/features/mining/index.js
new file mode 100644
index 0000000..0e9c7c0
--- /dev/null
+++ b/src/features/mining/index.js
@@ -0,0 +1,469 @@
+///
+///
+import Feature from "../../featureClass/class";
+import { m } from "../../../mappings/mappings";
+import * as stringUtils from "../../utils/stringUtils";
+import * as utils from "../../utils/utils"
+import HudTextElement from "../hud/HudTextElement";
+import LocationSetting from "../settings/settingThings/location";
+import ToggleSetting from "../settings/settingThings/toggle";
+import { numberWithCommas, timeSince2 } from "../../utils/numberUtils";
+import { fetch } from "../../utils/networkUtils";
+import socketConnection from "../../socketConnection";
+import { drawCoolWaypoint } from "../../utils/renderUtils";
+
+class Mining extends Feature {
+ constructor() {
+ super()
+ }
+
+ isInCH() {
+ if (!this.FeatureManager || !this.FeatureManager.features["dataLoader"]) return false
+ return this.FeatureManager.features["dataLoader"].class.area === "Crystal Hollows"
+ }
+
+ onEnable() {
+ this.initVariables()
+
+ this.hudElements = []
+
+ this.guessBalHp = new ToggleSetting("Show bal hp", "This will attempt to show remaining hp on bal (guessed)", true, "bal_hp", this)
+ this.balRespawnHud = new ToggleSetting("Show bal hp and respawn timer HUD", "This will add a HUD element with bal's hp and respawn timer", true, "bal_hud", this)
+ this.balHudElement = new HudTextElement()
+ .setToggleSetting(this.balRespawnHud)
+ .setLocationSetting(new LocationSetting("HUD Location", "Allows you to edit the location of the bal info", "bal_hud_location", this, [10, 50, 1, 1])
+ .requires(this.balRespawnHud)
+ .editTempText("&6Bal&7> &f172/250"))
+ this.hudElements.push(this.balHudElement)
+ this.balPetAlert = new ToggleSetting("Bal pet alert", "Give a notification on screen + sound when you drop a bal pet", true, "bal_alert", this)
+
+ this.showUnlockedGemstoneSlots = new ToggleSetting("Show unlocked gemstone slots", "This will show the unlocked gemstone slots of an item.", true, "unlocked_gemstones", this)
+ this.showContainedGemstoneSlots = new ToggleSetting("Show contained gemstones", "This will show the gemstones currently on an item.", true, "contained_gemstones", this)
+
+
+ this.compactProgressHud = new ToggleSetting("Show compact blocks in the current session", "This will add a HUD element with the compact progress", true, "compact_progress_hud", this)
+ this.compactHudElement = new HudTextElement()
+ .setToggleSetting(this.compactProgressHud)
+ .setLocationSetting(new LocationSetting("HUD Location", "Allows you to edit the location of the compact progress", "compact_progress_location", this, [10, 50, 1, 1])
+ .requires(this.compactProgressHud)
+ .editTempText("&6Compact Session&7> &f12,345"))
+ this.hudElements.push(this.compactHudElement)
+ this.compactProgressHudOnlyWhenMoreThan0 = new ToggleSetting("Only show compact progress when it is above 0", "So that you dont need to disable it when you start doing something else", true, "compact_progress_disable_0", this).requires(this.compactProgressHud)
+
+ this.gemstoneMoneyHud = new ToggleSetting("Show $/h made from gemstone mining", "This will add a HUD element with the gemstone $/h", true, "gemstone_money_hud", this)
+ this.gemstoneMoneyHudElement = new HudTextElement()
+ .setToggleSetting(this.gemstoneMoneyHud)
+ .setLocationSetting(new LocationSetting("HUD Location", "Allows you to edit the location of the gemstone $/h", "gemstone_money_location", this, [10, 60, 1, 1])
+ .requires(this.gemstoneMoneyHud)
+ .editTempText("&6$/h&7> &f$12,345,678\n&6$ made&7> &f$123,456,789\n&6Time tracked&7> &f123m"))
+ this.gemstoneMoneyHudMoneyOnly = new ToggleSetting("Force npc price", "(Eg if u are ironman)", false, "gemstone_money_hud_npc", this).requires(this.gemstoneMoneyHud)
+ this.hudElements.push(this.gemstoneMoneyHudElement)
+
+ this.nextChEvent = new ToggleSetting("Show the current and next crystal hollows event", "(syncs the data between all users in ch)", true, "chevent_hud", this)
+ this.nextChEventElement = new HudTextElement()
+ .setToggleSetting(this.nextChEvent)
+ .setLocationSetting(new LocationSetting("HUD Location", "Allows you to edit the location of the hud element", "chevent_hud_location", this, [10, 70, 1, 1])
+ .requires(this.nextChEvent)
+ .editTempText("&6Event&7> &fGONE WITH THE WIND &7->&f 2X POWDER"))
+ this.hudElements.push(this.nextChEventElement)
+
+
+ this.metalDetectorSolver = new ToggleSetting("Metal detector solver", "", true, "metal_detector_solver", this).contributor("tenios", ["- idea that chests are in same locations every time", "- locations of chests", "- finding offset of divan mines"])
+ this.alertTools = new ToggleSetting("Alert when all 4 tools in inventory", "", true, "alert_tools", this)
+
+ this.seenBalDamages = []
+ this.balHP = 250
+ this.lastBalAlive = 0
+ this.balDespawnDebounce = 0
+
+ this.predictedChestLocations = []
+
+ this.totalCompact = 0
+ this.compactProgress = 0
+ this.compactItems = 0
+
+ this.armourstandClass = Java.type("net.minecraft.entity.item.EntityArmorStand").class
+
+ this.registerEvent("tick", this.tick)
+ this.registerEvent("itemTooltip", this.itemTooltipEvent).registeredWhen(() => this.showContainedGemstoneSlots.getValue() || this.showUnlockedGemstoneSlots.getValue())
+ this.registerEvent("renderWorld", this.renderWorld).registeredWhen(() => this.guessBalHp.getValue() || this.metalDetectorSolver.getValue())
+
+ this.registerChat("&r&c&o&r&6&lRARE DROP! &r&eA Bal Pet dropped!&r", () => {
+ if (this.balPetAlert.getValue()) {
+ World.playSound("random.orb", 1, 1)
+ Client.showTitle("§r§c§o§r§6§lRARE DROP! §r§eA Bal Pet dropped!§r", "", 20, 50, 20)
+ }
+ })
+ this.registerChat("&r&c&oThe bosses outer shell looks to be weakening!&r", () => {
+ this.balHP = 200
+ })
+ this.registerChat("&r&c&oHalf way there! The boss is starting to become weaker!&r", () => {
+ this.balHP = 125
+ })
+ this.registerChat("&r&c&oNearly there! The boss is shaking it can't last much longer!&r", () => {
+ this.balHP = 75
+ })
+ this.registerChat("&r&c&oThe boss looks weak and tired and retreats into the lava...&r", () => {
+ this.balHP = 0
+ })
+
+ let startingTime = -1
+ let money = 0
+ let gemstoneCosts = {}
+ let lastMined = 0
+ this.registerChat("&r&d&lPRISTINE! &r&fYou found &r${*} &r&aFlawed ${type} Gemstone &r&8x${num}&r&f!&r", (type, num, event) => {
+
+ let id = "FLAWED_" + type.toUpperCase() + "_GEM"
+ let number = parseInt(num)
+
+ lastMined = Date.now()
+
+ if (!this.gemstoneMoneyHud.getValue()) return
+
+ if (startingTime === 0) return
+ if (startingTime === -1) {
+ startingTime = 0
+ fetch("https://api.hypixel.net/skyblock/bazaar").json().then(data => {
+ startingTime = Date.now()
+
+ Object.keys(data.products).forEach(id => {
+ if (id.startsWith("FLAWED_")) {
+ gemstoneCosts[id] = Math.max(240, data.products[id].quick_status.sellPrice)
+ if (this.gemstoneMoneyHudMoneyOnly.getValue()) {
+ gemstoneCosts[id] = 240
+ }
+ // console.log(id + ": " + gemstoneCosts[id])
+ }
+ })
+ })
+ return
+ }
+
+ money += gemstoneCosts[id] * number
+
+ let moneyPerHour = Math.floor(money / ((Date.now() - startingTime) / (1000 * 60 * 60)))
+ let moneyMade = Math.floor(money)
+ let timeTracked = timeSince2(startingTime)
+
+ this.gemstoneMoneyHudElement.setText("&6$/h&7> &f$" + numberWithCommas(moneyPerHour) + "\n&6$ made&7> &f$" + numberWithCommas(moneyMade) + "\n&6Time tracked&7> &f" + timeTracked)
+ })
+ this.registerStep(false, 10, () => {
+ if (lastMined && Date.now() - lastMined > 2 * 60000) {
+ money = 0
+ startingTime = -1
+ lastMined = 0
+ this.gemstoneMoneyHudElement.setText("")
+ }
+
+ this.nextChEventElement.setText("&6Event&7> &f" + socketConnection.chEvent.join(" &7->&f "))
+ })
+
+ let lastWorldChange = 0
+
+ this.registerEvent("worldLoad", () => {
+ lastWorldChange = Date.now()
+ })
+
+ this.registerChat("&r&r&r ${spaces}&r&${color}&l${event} ENDED!&r", (spaces, color, event) => {
+ if (Date.now() - lastWorldChange < 5000) return
+ if (!this.isInCH()) return
+
+ socketConnection.sendCHEventData(event.trim(), false)
+ })
+ this.registerChat("&r&r&r ${spaces}&r&${color}&l${event} STARTED!&r", (spaces, color, event) => {
+ if (Date.now() - lastWorldChange < 5000) return
+ if (!this.isInCH()) return
+
+ socketConnection.sendCHEventData(event.trim(), true)
+ })
+
+ this.chestCoords = JSON.parse(FileLib.read("SoopyV2", "features/mining/coords.json"))
+
+ let lastLoc = [0, 0, 0]
+
+ this.baseCoordinates = undefined
+
+ this.lastSearchedForBase = 0
+
+ let ignoreLocation = undefined
+
+ this.registerEvent("worldLoad", () => {
+ lastLoc = [0, 0, 0]
+
+ this.baseCoordinates = undefined
+
+ this.lastSearchedForBase = 0
+
+ this.predictedChestLocations = []
+
+ ignoreLocation = undefined
+ })
+
+ let registerActionBar = this.registerCustom("actionbar", (dist) => {
+ let lapis = false
+ let diamond = false
+ let emerald = false
+ let gold = false
+ Player.getInventory().getItems().forEach(i => {
+ if (i && i.getName().includes("Scavenged Lapis")) {
+ lapis = true
+ }
+ if (i && i.getName().includes("Scavenged Diamond")) {
+ diamond = true
+ }
+ if (i && i.getName().includes("Scavenged Emerald")) {
+ emerald = true
+ }
+ if (i && i.getName().includes("Scavenged Golden")) {
+ gold = true
+ }
+ })
+
+ if (this.alertTools.getValue() && lapis && diamond && gold && emerald) Client.showTitle("§cALL TOOLS", "", 10, 40, 20)
+
+ if (!this.metalDetectorSolver.getValue()) return
+ let distance = parseFloat(dist)
+ if (!this.baseCoordinates) this.findBaseCoordinates();
+
+ if (lastLoc[0] !== Player.getX() || lastLoc[1] !== Player.getY() || lastLoc[2] !== Player.getZ()) {
+ lastLoc = [Player.getX(), Player.getY(), Player.getZ()]
+ return
+ }
+
+ this.predictedChestLocations = []
+
+ this.chestCoords.forEach((coordinates) => {
+ let currentDistance = Math.hypot(Player.getX() - (this.baseCoordinates[0] - coordinates[0]), Player.getY() - (this.baseCoordinates[1] - coordinates[1] + 1), Player.getZ() - (this.baseCoordinates[2] - coordinates[2]))
+
+ if (Math.round(currentDistance * 10) / 10 === distance) {
+
+ if ([this.baseCoordinates[0] - coordinates[0], this.baseCoordinates[1] - coordinates[1], this.baseCoordinates[2] - coordinates[2]].join(",") === ignoreLocation) {
+ ignoreLocation = undefined
+ return
+ }
+
+ if (this.predictedChestLocations.length === 0) {
+ World.playSound("note.pling", 100, 2)
+ }
+
+ this.predictedChestLocations.push([this.baseCoordinates[0] - coordinates[0], this.baseCoordinates[1] - coordinates[1], this.baseCoordinates[2] - coordinates[2]])
+ }
+ });
+ })
+ registerActionBar.trigger.setCriteria('TREASURE: ${rest}').setParameter('contains');
+
+ this.registerChat("&r&aYou found${*}with your &r&cMetal Detector&r&a!&r", () => {
+ if (this.predictedChestLocations[0]) ignoreLocation = this.predictedChestLocations[0].join(",")
+ this.predictedChestLocations = []
+ })
+ }
+
+ findBaseCoordinates() {
+ if (Date.now() - this.lastSearchedForBase < 15000) return;
+ let x = ~~Player.getX();
+ let y = ~~Player.getY();
+ let z = ~~Player.getZ();
+ for (let i = x - 50; i < x + 50; i++) {
+ for (let j = y + 30; j >= y - 30; j--) {
+ for (let k = z - 50; k < z + 50; k++) {
+ if (World.getBlockAt(i, j, k).getType().getID() === 156 && World.getBlockAt(i, j + 13, k).getType().getID() === 166) {
+ this.baseCoordinates = this.getBaseCoordinates(i, j + 13, k);
+ return;
+ }
+ }
+ }
+ }
+ this.lastSearchedForBase = Date.now();
+ }
+
+ getBaseCoordinates(x, y, z) {
+ let loop = true;
+ let posX = x;
+ let posY = y;
+ let posZ = z;
+ if (World.getBlockAt(x, y, z).getType().getID() !== 166) return [x, y, z];
+ while (loop) {
+ loop = false;
+ if (World.getBlockAt(posX + 1, posY, posZ).getType().getID() == 166) {
+ posX++;
+ loop = true;
+ }
+ if (World.getBlockAt(posX, posY - 1, posZ).getType().getID() == 166) {
+ posY--;
+ loop = true;
+ }
+ if (World.getBlockAt(posX, posY, posZ + 1).getType().getID() == 166) {
+ posZ++;
+ loop = true;
+ }
+ }
+ return [posX, posY, posZ];
+ }
+
+ itemTooltipEvent(lore, item, event) {
+ this.addLore(item)
+ }
+
+ /**
+ * @param {Item} item
+ */
+ addLore(item) {
+ if (!item) return
+ if (this.showUnlockedGemstoneSlots.getValue()) {
+ let gems = item.getNBT().getCompoundTag("tag").getCompoundTag("ExtraAttributes").getCompoundTag("gems")
+ if (gems) {
+ let unlockedGems = gems.getTagMap().get("unlocked_slots")
+
+ if (unlockedGems) {
+
+ if (unlockedGems[m.tagCount]() === 0) {
+ utils.addLore(item, ChatLib.addColor("&d&lGemstones Unlocked: &f"), ChatLib.addColor("&cNone!"))
+ } else {
+ let gemstoneString = ""
+
+ for (let i = 0; i < unlockedGems[m.tagCount](); i++) {
+ let gem = String(unlockedGems[m.getStringTagAt](i)).split("_")
+
+ let name = stringUtils.firstLetterCapital(gem[0].toLowerCase())
+
+ gemstoneString += (gemstoneString === "" ? "" : "&7, &a") + name
+ }
+ utils.addLore(item, ChatLib.addColor("&d&lGemstones Unlocked: &f"), ChatLib.addColor("&a" + gemstoneString))
+ }
+ }
+ }
+ }
+ if (this.showContainedGemstoneSlots.getValue()) {
+ let gems = item.getNBT().getCompoundTag("tag").getCompoundTag("ExtraAttributes").getCompoundTag("gems")
+ if (gems) {
+ let unlockedGems = gems.getTagMap()
+
+ let gemStr = ""
+
+ unlockedGems.keySet().forEach(gem => {
+ if (gem !== "unlocked_slots" && !gem.endsWith("_gem")) {
+ gem = gem.split("_")
+
+ let gemName = stringUtils.firstLetterCapital(gems.getString(gem.join("_") + "_gem").toLowerCase()) || stringUtils.firstLetterCapital(gem[0].toLowerCase())
+
+ let name = stringUtils.firstLetterCapital(gems.getString(gem.join("_")).toLowerCase()) + " " + gemName
+
+
+ gemStr += (gemStr === "" ? "" : "&7, &a") + name
+ }
+ });
+
+ if (gemStr !== "") {
+ utils.addLore(item, ChatLib.addColor("&d&lGemstones: &f"), ChatLib.addColor("&a" + gemStr))
+ }
+ }
+ }
+ }
+
+ renderWorld() {
+ if (this.guessBalHp.getValue()) {
+ if (this.balEntity) Tessellator.drawString(this.balHP + "/250", this.balEntity.getX(), this.balEntity.getY() + 12, this.balEntity.getZ())
+ }
+ if (!this.metalDetectorSolver.getValue()) return
+ this.predictedChestLocations.forEach(loc => {
+ drawCoolWaypoint(loc[0], loc[1], loc[2], 0, 255, 0, { name: "TREASURE", phase: true })
+ })
+ }
+
+ tick() {
+ let oldCompactItems = this.compactItems
+ let oldTotalCompact = this.totalCompact
+ this.totalCompact = 0
+ this.compactItems = 0
+ let slots = [0, 1, 2, 3, 4, 5, 6, 7, 8]
+
+ slots.forEach(a => {
+ item = Player.getInventory().getStackInSlot(a)
+ if (!item) return
+ if (item.getNBT()?.getCompoundTag("tag")?.getCompoundTag("ExtraAttributes")?.getInteger("compact_blocks")) {
+ this.compactItems++
+ this.totalCompact += item.getNBT().getCompoundTag("tag").getCompoundTag("ExtraAttributes").getInteger("compact_blocks")
+ }
+ })
+
+ if (oldCompactItems === this.compactItems) {
+ this.compactProgress += this.totalCompact - oldTotalCompact
+ }
+ if (this.compactItems === 0) {
+ this.compactProgress = 0
+ }
+
+ if (this.compactProgress === 0 && this.compactProgressHudOnlyWhenMoreThan0.getValue()) {
+ this.compactHudElement.setText("")
+ } else {
+ this.compactHudElement.setText("&6Compact Session&7> &f" + numberWithCommas(this.compactProgress))
+ }
+
+
+ if (!this.FeatureManager.features["dataLoader"]) return
+ if (this.guessBalHp.getValue() || this.balRespawnHud.getValue()) {
+ if (this.FeatureManager.features["dataLoader"].class.area === "Crystal Hollows" && this.FeatureManager.features["dataLoader"].class.areaFine === "Khazad-dm") {
+
+ this.balEntity = undefined
+ World.getAllEntities().filter(a => a.getName() === "Magma Cube").filter(a => a.getEntity()[m.getSlimeSize]() > 10).forEach((bal) => {
+ //Bal found
+ this.balEntity = bal
+ })
+ if (this.balEntity) {
+ this.balDespawnDebounce = 0
+ if (this.lastBalAlive !== 0) {
+ this.lastBalAlive = 0
+ }
+ World.getAllEntitiesOfType(this.armourstandClass).forEach(e => {
+ if (Math.abs(e.getX() - this.balEntity.getX()) <= 5 && Math.abs(e.getZ() - this.balEntity.getZ()) <= 5 && Math.abs(e.getY() - (this.balEntity.getY() + 12)) <= 5) {
+ if (!this.seenBalDamages.includes(e.getUUID())) {
+ this.balHP--
+ this.seenBalDamages.push(e.getUUID())
+ }
+ }
+ })
+ } else {
+ this.balDespawnDebounce++
+ if (this.balDespawnDebounce > 10) {
+ this.seenBalDamages = []
+ this.balHP = 250
+ if (this.lastBalAlive === 0) this.lastBalAlive = Date.now()
+ }
+ }
+ }
+ }
+
+ if (this.balRespawnHud.getValue() && this.FeatureManager.features["dataLoader"].class.area === "Crystal Hollows" && this.FeatureManager.features["dataLoader"].class.areaFine === "Khazad-dm") {
+ if (this.balEntity) {
+ this.balHudElement.setText("&6Bal&7> &f" + this.balHP + "/250")
+ } else {
+ this.balHudElement.setText("&6Bal&7> &f" + Math.max(0, Math.floor((290000 - (Date.now() - this.lastBalAlive)) / 1000)) + "s")
+ }
+ } else {
+ this.balHudElement.setText("")
+ }
+ }
+
+ initVariables() {
+ this.hudElements = undefined
+ this.guessBalHp = undefined
+ this.balRespawnHud = undefined
+ this.balHudElement = undefined
+ this.balEntity = undefined
+ this.balDespawnDebounce = undefined
+ this.lastBalAlive = undefined
+ this.balHP = undefined
+ this.seenBalDamages = undefined
+ this.armourstandClass = undefined
+ this.balPetAlert = undefined
+ }
+
+ onDisable() {
+ this.hudElements.forEach(h => h.delete())
+ this.initVariables()
+ }
+}
+
+module.exports = {
+ class: new Mining()
+}
\ No newline at end of file
diff --git a/src/features/mining/metadata.json b/src/features/mining/metadata.json
new file mode 100644
index 0000000..ce9ed40
--- /dev/null
+++ b/src/features/mining/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Mining",
+ "description": "A bunch of features to assist with mining",
+ "isHidden": false,
+ "isTogglable": true,
+ "defaultEnabled": true,
+ "sortA": 1
+}
\ No newline at end of file
diff --git a/src/features/nether/index.js b/src/features/nether/index.js
new file mode 100644
index 0000000..4b14c48
--- /dev/null
+++ b/src/features/nether/index.js
@@ -0,0 +1,406 @@
+///
+///
+import { f, m } from "../../../mappings/mappings";
+import Feature from "../../featureClass/class";
+import socketConnection from "../../socketConnection";
+import { drawBoxAtBlock, drawBoxAtBlockNotVisThruWalls, drawBoxAtEntity, drawCoolWaypoint, drawLine, drawLineWithDepth, renderBeaconBeam } from "../../utils/renderUtils";
+import ToggleSetting from "../settings/settingThings/toggle";
+import HudTextElement from "../hud/HudTextElement";
+import LocationSetting from "../settings/settingThings/location";
+const MCBlock = Java.type("net.minecraft.block.Block");
+const ArmorStand = Java.type("net.minecraft.entity.item.EntityArmorStand")
+const MCItem = Java.type("net.minecraft.item.Item");
+const EntitySkeleton = Java.type("net.minecraft.entity.monster.EntitySkeleton")
+
+let locationData = {
+ barbarian: {
+ "Ⓐ": [16, 148, -929],
+ "Ⓑ": [-37, 122, -1020],
+ "Ⓒ": [-30, 137, -888],
+ "Ⓓ": [-6, 156, -881],
+ },
+ mage: {
+ "Ⓐ": [-664, 124, -981],
+ "Ⓑ": [-635, 160, -1056],
+ "Ⓒ": [-726, 123, -997],
+ "Ⓓ": [-685, 124, -1049],
+ }
+}
+
+let disciplineColors = {
+ "Wood": [196, 100, 0],
+ "Iron": [194, 194, 194],
+ "Gold": [235, 182, 0],
+ "Diamond": [0, 198, 229]
+}
+
+class Nether extends Feature {
+ constructor() {
+ super();
+ }
+
+ isInDojo() {
+ if (!this.FeatureManager || !this.FeatureManager.features["dataLoader"]) return false
+ return this.FeatureManager.features["dataLoader"].class.areaFine === "Dojo" || this.FeatureManager.features["dataLoader"].class.areaFine === "Dojo Arena"
+ }
+
+ isInNether() {
+ if (!this.FeatureManager || !this.FeatureManager.features["dataLoader"]) return false
+ return this.FeatureManager.features["dataLoader"].class.area === "Crimson Isle"
+ }
+
+ onEnable() {
+ this.initVariables();
+
+ this.masteryTimer = new ToggleSetting("Mastery Timer", "Countdown untill a block will turn red", true, "nether_mastery_timer", this)
+ this.speedNextBlock = new ToggleSetting("Show next block to stand on for dojo swiftness", "", true, "dojo_swiftness", this)
+ this.tenacityLine = new ToggleSetting("Show line for fireball in dojo tenacity", "This may help you to dodge the fireballs", false, "dojo_tanacity", this)
+ this.disciplineOverlay = new ToggleSetting("Show overlay for zombies in dojo discipline", "", true, "dojo_discipline", this).contributor("Empa")
+ this.controlHelper = new ToggleSetting("Shows where you actually have to look for", "control dojo task (accounts for ping)", true, "control_helper", this)
+ this.hostageWaypoints = new ToggleSetting("Show hostage waypoints", "Waypoint for location of hostage in rescue missions", true, "hostage_waypoint", this)
+ this.slugfishTimer = new ToggleSetting("Show timer over rod", "This may help with fishing slugfish", false, "slugfish_timer", this)
+
+ this.minibossNametag = new ToggleSetting("Nether Miniboss Nametag Hud", "renders the HP of minibosses on screen (exclude Magma Boss)", false, "nether_mini_nametag_hud", this);
+ this.minibossNametagElement = new HudTextElement()
+ .setText("")
+ .setToggleSetting(this.minibossNametag)
+ .setLocationSetting(new LocationSetting("Nether Miniboss Nametag Hud location", "allows you to change the location of the hud", "nether_mini_nametag_hud_location", this, [10, 100, 1, 1]).requires(this.minibossNametag).editTempText("&5&lMage Outlaw &r&a70M&c❤"));
+ this.hudElements.push(this.minibossNametagElement);
+
+ this.registerStep(true, 5, this.minibossHPHud)
+
+ this.todoE = []
+ this.todoE2 = []
+ this.blocks = []
+
+ this.todoF = []
+ this.todoF2 = []
+ this.todoM = []
+ this.todoM2 = []
+ this.disciplineZombies = {
+ "Wood": [],
+ "Iron": [],
+ "Gold": [],
+ "Diamond": []
+ }
+ this.inDiscipline = false
+
+ this.dojoFireBalls = []
+ this.inSwiftness = false
+ this.rescueMissionDifficulty = undefined
+ this.rescueMissionType = undefined
+ this.lastBlock = undefined
+ this.hookThrown = 0
+ this.controlSkeleton = undefined
+ this.controlLocLast = undefined
+ this.controlLoc = undefined
+ this.registerChat(" Test of Control OBJECTIVES", () => {
+ this.controlSkeleton = undefined
+ this.controlLocLast = undefined
+ this.controlLoc = undefined
+ })
+
+ let packetRecieved = this.registerCustom("packetReceived", this.packetReceived).registeredWhen(() => this.isInDojo())
+
+ try {
+ packetRecieved.trigger.setPacketClasses([net.minecraft.network.play.server.S23PacketBlockChange, net.minecraft.network.play.server.S22PacketMultiBlockChange])
+ } catch (e) { }//older ct version
+
+ this.registerStep(true, 1, this.step1S).registeredWhen(() => this.isInNether())
+ this.registerEvent("renderWorld", this.renderWorld).registeredWhen(() => this.isInNether())
+
+ this.registerForge(net.minecraftforge.event.entity.EntityJoinWorldEvent, this.entityJoinWorldEvent).registeredWhen(() => this.isInDojo() || (this.isInNether() && this.minibossNametag.getValue()));
+ this.registerEvent("tick", this.tick).registeredWhen(() => this.isInNether())
+ this.registerChat("&r&r&r &r&aTest of Swiftness &r&e&lOBJECTIVES&r", () => {
+ if (this.speedNextBlock.getValue()) {
+ this.inSwiftness = true
+ this.lastBlock = [Math.floor(Player.getX()), Math.floor(Player.getY()) - 1, Math.floor(Player.getZ())]
+ }
+ })
+
+ this.registerChat("&r&r&r &r&cTest of Discipline &r&e&lOBJECTIVES&r", () => {
+ if (this.disciplineOverlay.getValue()) {
+ this.inDiscipline = true
+ this.todoF = []
+ this.todoF2 = []
+ }
+ })
+
+ this.registerChat("&r&r&r ${*}&r&6Your Rank: &r${*}&r", () => {
+ this.inSwiftness = false
+ this.lastBlock = undefined
+ this.inDiscipline = false
+
+ this.controlLocLast = undefined
+ this.controlLoc = undefined
+ this.controlSkeleton = undefined
+ })
+ this.registerEvent("worldLoad", () => {
+ this.inSwiftness = false
+ this.lastBlock = undefined
+ this.inDiscipline = false
+
+ this.controlLocLast = undefined
+ this.controlLoc = undefined
+ this.controlSkeleton = undefined
+ this.miniboss = undefined
+ })
+
+ this.registerChat("You completed your rescue quest! Visit the Town Board to claim the rewards,", () => {
+ this.rescueMissionDifficulty = this.rescueMissionType = undefined
+ })
+ this.registerEvent("worldLoad", () => {
+ this.rescueMissionDifficulty = this.rescueMissionType = undefined
+ })
+ }
+
+ tick() {
+
+ let fishHook = Player.getPlayer()[f.fishEntity]
+
+ if (fishHook) {
+ if (!this.hookThrown) this.hookThrown = Date.now()
+ } else {
+ this.hookThrown = 0
+ }
+
+ if (Player.getContainer().getName() === "Rescue" && Player.getContainer().getStackInSlot(22)) {
+ let difficulty = ChatLib.removeFormatting(Player.getContainer().getStackInSlot(22).getName()).trim()[0]
+
+ this.rescueMissionDifficulty = difficulty
+ TabList.getNames().forEach(n => {
+ if (n.toLowerCase().includes("barbarian rep")) this.rescueMissionType = "barbarian"// : "mage"
+ if (n.toLowerCase().includes("mage rep")) this.rescueMissionType = "mage"// : "mage"
+ })
+ }
+
+
+ this.todoF2.forEach(e => {
+ let name = ChatLib.removeFormatting(e.getName())
+ if (!name) return
+ if (!disciplineColors[name]) return
+
+ this.disciplineZombies[name].push(e)
+ })
+
+ this.todoF2 = this.todoF
+ this.todoF = []
+
+ this.todoE2.forEach(e => {
+ let item = e[m.getHeldItem]()
+ if (!item) return
+ if (MCItem[m.getIdFromItem](item[m.getItem.ItemStack]()) !== 173) return
+
+ this.dojoFireBalls.push(e)
+ })
+
+ this.todoE2 = this.todoE
+ this.todoE = []
+
+
+ if (this.controlHelper.getValue() && this.controlSkeleton) {
+ let ping = this.FeatureManager.features["dataLoader"].class.getPing() / 1000
+
+ let e = this.controlSkeleton
+ let x = e.getX() + (e.getX() - e.getLastX()) * (20 * ping)
+ let y = e.getY() + (e.getY() - e.getLastY()) * (20 * ping)
+ let z = e.getZ() + (e.getZ() - e.getLastZ()) * (20 * ping)
+ if (x === e.getX() && y === e.getY() && z === e.getZ()) return
+
+ while (World.getBlockAt(x, y, z).getType().getID() !== 0) { y += 0.2 }
+
+ if (this.controlLoc) this.controlLocLast = [...this.controlLoc]
+ this.controlLoc = [x - 0.5, y, z - 0.5]
+ } else {
+ this.controlLocLast = undefined
+ this.controlLoc = undefined
+ }
+
+ this.todoM2.forEach(e => {
+ let name = e[m.getCustomNameTag]()
+ if (name) {
+ if (name.includes("Ashfang") || name.includes("Barbarian Duke X") || name.includes("Bladesoul") || name.includes("Mage Outlaw")) {
+ this.miniboss = new Entity(e)
+ }
+ }
+ })
+
+ this.todoM2 = this.todoM
+ this.todoM = []
+ }
+
+ entityJoinWorldEvent(event) {
+ if (this.tenacityLine.getValue() && event.entity instanceof ArmorStand) this.todoE.push(event.entity)
+ if (this.disciplineOverlay.getValue() && this.inDiscipline && event.entity instanceof ArmorStand) this.todoF.push(new Entity(event.entity))
+
+ if (event.entity instanceof EntitySkeleton && !this.controlSkeleton) this.controlSkeleton = new Entity(event.entity)
+ if (this.minibossNametag.getValue() && event.entity instanceof ArmorStand) {
+ this.todoM.push(event.entity)
+ }
+ }
+
+ packetReceived(packet, event) {
+ if (!this.masteryTimer.getValue()) return
+ let packetType = new String(packet.class.getSimpleName()).valueOf()
+ if (packetType === "S23PacketBlockChange") {
+ let position = new BlockPos(packet[m.getBlockPosition.S23PacketBlockChange]())
+ let blockState = this.getBlockIdFromState(packet[m.getBlockState.S23PacketBlockChange]())
+ let oldBlockState = this.getBlockIdFromState(World.getBlockStateAt(position))
+ if (oldBlockState === 20515 && blockState === 16419) {
+ if (Math.abs(Player.getX() - position.getX()) <= 20 && Math.abs(Player.getY() - position.getY()) <= 20 && Math.abs(Player.getZ() - position.getZ()) <= 20) {
+ this.blocks.push({ loc: position, time: Date.now() + 3000 })
+ }
+ }
+ if (blockState === 57379) {
+ this.blocks = this.blocks.filter(b => {
+ if (b.loc.x === position.x && b.loc.y === position.y && b.loc.z === position.z) {
+ return false
+ }
+ return true
+ })
+ //air=0
+ //green=20515
+ //yellow=16419
+ //red=57379
+ }
+ if (oldBlockState === 0 && blockState === 20515 && this.inSwiftness) {
+ this.lastBlock = [position.getX(), position.getY(), position.getZ()]
+ }
+ }
+ if (packetType === "S22PacketMultiBlockChange") {
+ packet[m.getChangedBlocks]().forEach(b => {
+ let position = new BlockPos(b[m.getPos.S22PacketMultiBlockChange$BlockUpdateData]())
+ let blockState = this.getBlockIdFromState(b[m.getBlockState.S22PacketMultiBlockChange$BlockUpdateData]())
+ let oldBlockState = this.getBlockIdFromState(World.getBlockStateAt(position))
+ if (oldBlockState === 0 && blockState === 20515 && this.inSwiftness) {
+ this.lastBlock = [position.getX(), position.getY(), position.getZ()]
+ }
+ if (oldBlockState === 20515 && blockState === 16419) {
+ if (Math.abs(Player.getX() - position.getX()) <= 20 && Math.abs(Player.getY() - position.getY()) <= 20 && Math.abs(Player.getZ() - position.getZ()) <= 20) {
+ this.blocks.push({ loc: position, time: Date.now() + 3000 })
+ }
+ }
+ if (blockState === 57379) {
+ this.blocks = this.blocks.filter(b => {
+ if (b.loc.x === position.x && b.loc.y === position.y && b.loc.z === position.z) {
+ return false
+ }
+ return true
+ })
+ //air=0
+ //green=20515
+ //yellow=16419
+ //red=57379
+ }
+ })
+ }
+ }
+
+ renderWorld(ticks) {
+ if (this.masteryTimer.getValue() && this.blocks) {
+ this.blocks.forEach((data, i) => {
+ Tessellator.drawString((i === 0 ? "§1" : "§0") + Math.max(0, (data.time - Date.now()) / 1000).toFixed(1) + "s", data.loc.getX() + 0.5, data.loc.getY() + 0.5, data.loc.getZ() + 0.5, 0, false, 0.05, false)
+ })
+ if (this.blocks.length >= 2) drawLine(this.blocks[0].loc.getX() + 0.5, this.blocks[0].loc.getY(), this.blocks[0].loc.getZ() + 0.5, this.blocks[1].loc.getX() + 0.5, this.blocks[1].loc.getY(), this.blocks[1].loc.getZ() + 0.5, 255, 0, 0)
+ }
+
+ if (this.lastBlock && this.inSwiftness) drawBoxAtBlock(this.lastBlock[0], this.lastBlock[1], this.lastBlock[2], 0, 255, 0, 1, 1)
+
+ if (this.tenacityLine.getValue()) this.dojoFireBalls.forEach(e => {
+ let offset = [e[f.width.Entity] / 2, e[f.height.Entity] / 2, e[f.width.Entity] / 2]
+ let entitylocation = [e[f.posX.Entity], e[f.posY.Entity], e[f.posZ.Entity]]
+ let lastLocation = [e[f.prevPosX], e[f.prevPosY], e[f.prevPosZ]]
+ let change = [entitylocation[0] - lastLocation[0], entitylocation[1] - lastLocation[1], entitylocation[2] - lastLocation[2]]
+ drawLineWithDepth(entitylocation[0] + change[0] * 100 + offset[0], entitylocation[1] + change[1] * 100 + offset[1], entitylocation[2] + change[2] * 100 + offset[2], entitylocation[0] + offset[0], entitylocation[1] + offset[1], entitylocation[2] + offset[2], 255, 0, 0, 2)
+ })
+
+ if (this.disciplineOverlay.getValue() && Player.getHeldItem() && this.disciplineZombies[ChatLib.removeFormatting(Player.getHeldItem().getName().split(" ")[0].replace("en", ""))]) this.disciplineZombies[ChatLib.removeFormatting(Player.getHeldItem().getName().split(" ")[0].replace("en", ""))].forEach(e => {
+ let color = disciplineColors[ChatLib.removeFormatting(e.getName())]
+
+ drawBoxAtEntity(e, color[0] / 255, color[1] / 255, color[2] / 255, 0.7, -2, ticks, 4, false);
+ })
+
+ if (this.rescueMissionDifficulty && this.rescueMissionType && this.hostageWaypoints.getValue()) {
+ let location = locationData[this.rescueMissionType][this.rescueMissionDifficulty]
+ drawCoolWaypoint(location[0], location[1], location[2], 255, 0, 0, { name: "Hostage" })
+ }
+
+ if (this.slugfishTimer.getValue()) {
+ let hook = Player.getPlayer()[f.fishEntity]
+ if (hook && this.hookThrown) {
+ let x = hook[f.posX.Entity]
+ let y = hook[f.posY.Entity]
+ let z = hook[f.posZ.Entity]
+
+ Tessellator.drawString(((Date.now() - this.hookThrown) / 1000).toFixed(1) + "s", x, y + 0.5, z, Renderer.color(0, 255, 50), false, 0.025, false)
+ }
+ }
+
+ if (this.controlLoc && this.controlLocLast) {
+ drawBoxAtBlockNotVisThruWalls(this.controlLoc[0] * ticks + this.controlLocLast[0] * (1 - ticks), this.controlLoc[1] * ticks + this.controlLocLast[1] * (1 - ticks), this.controlLoc[2] * ticks + this.controlLocLast[2] * (1 - ticks), 255, 0, 0, 1, 2)
+ }
+ }
+
+ step1S() {
+ if (this.blocks) this.blocks = this.blocks.filter(state => Date.now() < state.time)
+ if (this.disciplineZombies) Object.keys(this.disciplineZombies).forEach(k => {
+ this.disciplineZombies[k] = this.disciplineZombies[k].filter(e => !e.getEntity()[f.isDead])
+ })
+ if (this.dojoFireBalls) this.dojoFireBalls = this.dojoFireBalls.filter(e => !e[f.isDead])
+ }
+
+ getBlockIdFromState(state) {
+ return MCBlock[m.getStateId](state)
+ }
+
+ minibossHPHud() {
+ if (this.miniboss && this.miniboss.getEntity()[f.isDead]) this.miniboss = undefined
+ if (!this.minibossNametag.getValue() || !this.miniboss) {
+ this.minibossNametagElement.setText("")
+ return
+ }
+ let name = this.miniboss.getName()
+ let nameRemoveFormat = name.removeFormatting()
+ let mobName = ""
+ if (nameRemoveFormat.includes("Ashfang")) mobName = "&dAshfang"
+ if (nameRemoveFormat.includes("Bladesoul")) mobName = "&dBladesoul"
+ if (nameRemoveFormat.includes("Barbarian Duke X")) mobName = "&dBarbarian Duke X"
+ if (nameRemoveFormat.includes("Mage Outlaw")) mobName = "&dMage Outlaw"
+ if (!mobName) {
+ this.minibossNametagElement.setText("")
+ return
+ }
+ let indexOfHP = {
+ "&dAshfang": 3,
+ "&dBladesoul": 3,
+ "&dBarbarian Duke X": 5,
+ "&dMage Outlaw": 4
+ }
+ let HP = `&l${mobName} &r${name.split(" ")[indexOfHP[mobName]].split("/")[0]}&c❤`
+ this.minibossNametagElement.setText(HP)
+ }
+
+ initVariables() {
+ this.hudElements = [];
+ this.miniboss = undefined
+ }
+
+ onDisable() {
+ this.hudElements.forEach(h => h.delete())
+ this.initVariables();
+ }
+}
+
+let nether = new Nether()
+module.exports = {
+ class: nether,
+};
+
+function getField(e, field) {
+
+ let field2 = e.class.getDeclaredField(field);
+
+ field2.setAccessible(true)
+
+ return field2.get(e)
+}
diff --git a/src/features/nether/metadata.json b/src/features/nether/metadata.json
new file mode 100644
index 0000000..2a7c145
--- /dev/null
+++ b/src/features/nether/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Nether",
+ "description": "uga booga nether",
+ "isHidden": false,
+ "isTogglable": true,
+ "defaultEnabled": true,
+ "sortA": 1
+}
\ No newline at end of file
diff --git a/src/features/networthGUI/index.js b/src/features/networthGUI/index.js
new file mode 100644
index 0000000..b1ff5c2
--- /dev/null
+++ b/src/features/networthGUI/index.js
@@ -0,0 +1,239 @@
+///
+///
+import SoopyTextElement from "../../../guimanager/GuiElement/SoopyTextElement";
+import Feature from "../../featureClass/class";
+import GuiPage from "../soopyGui/GuiPage";
+import BoxWithLoading from "../../../guimanager/GuiElement/BoxWithLoading";
+import BoxWithTextAndDescription from "../../../guimanager/GuiElement/BoxWithTextAndDescription";
+import SoopyGuiElement from "../../../guimanager/GuiElement/SoopyGuiElement";
+import TextBox from "../../../guimanager/GuiElement/TextBox";
+import SoopyKeyPressEvent from "../../../guimanager/EventListener/SoopyKeyPressEvent";
+import { numberWithCommas } from "../../utils/numberUtils";
+import { firstLetterWordCapital } from "../../utils/stringUtils";
+import SoopyBoxElement from "../../../guimanager/GuiElement/SoopyBoxElement";
+import SoopyMarkdownElement from "../../../guimanager/GuiElement/SoopyMarkdownElement";
+import SoopyMouseClickEvent from "../../../guimanager/EventListener/SoopyMouseClickEvent";
+import ButtonWithArrow from "../../../guimanager/GuiElement/ButtonWithArrow";
+import { fetch } from "../../utils/networkUtils";
+import Dropdown from "../../../guimanager/GuiElement/Dropdown";
+import SoopyContentChangeEvent from "../../../guimanager/EventListener/SoopyContentChangeEvent";
+
+class NetworthGui extends Feature {
+ constructor() {
+ super()
+ }
+
+ onEnable() {
+ this.initVariables()
+
+ this.GuiPage = new NetworthPage()
+
+ }
+
+ initVariables() {
+ this.GuiPage = undefined
+ }
+
+ onDisable() {
+ this.initVariables()
+ }
+}
+
+
+class NetworthPage extends GuiPage {
+ constructor() {
+ super(7)
+
+ this.name = "Networth"
+
+ this.pages = [this.newPage()]
+
+ this.pages[0].addChild(new SoopyTextElement().setText("§0Networth").setMaxTextScale(3).setLocation(0.1, 0.05, 0.6, 0.1))
+ this.pages[0].addChild(new SoopyTextElement().setText("§0(This is in beta and may be inaccurate)").setMaxTextScale(3).setLocation(0.1, 0.15, 0.8, 0.075))
+ let button = new ButtonWithArrow().setText("§0Open in browser").setLocation(0.7, 0.05, 0.2, 0.1)
+ this.pages[0].addChild(button)
+
+ button.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ java.awt.Desktop.getDesktop().browse(
+ new java.net.URI("https://soopy.dev/networth")
+ );
+ }))
+
+ this.nameInput = new TextBox().setPlaceholder("Click to search").setLocation(0.1, 0.225, 0.8, 0.1)
+ this.pages[0].addChild(this.nameInput)
+
+ this.nameInput.addEvent(new SoopyKeyPressEvent().setHandler((key, keyId) => {
+ if (this.nameInput.text.selected && keyId === 28) {
+ this.playerLoad = this.nameInput.text.text
+ this.nameInput.setText("")
+ this.updateData(this.playerLoad)
+ }
+ }))
+
+ this.statArea = new SoopyGuiElement().setLocation(0.05, 0.325, 0.9, 0.675).setScrollable(true)
+ this.pages[0].addChild(this.statArea)
+
+ this.loadingElm = new BoxWithLoading().setLocation(0.35, 0.4, 0.3, 0.2)
+ this.errorElm = new BoxWithTextAndDescription().setLocation(0.2, 0.3, 0.6, 0.4).setText("Error!").setDesc("An error occured while loading the data!")
+ this.statArea.addChild(this.loadingElm)
+
+ this.playerLoad = undefined
+
+ this.sidebarElement = new SoopyGuiElement().setLocation(0, 0, 1, 1)
+
+ this.sidebarUsernameSearch = new TextBox().setLocation(0.15, 0.05, 0.7, 0.1).setPlaceholder("Click to search")
+ this.sidebarElement.addChild(this.sidebarUsernameSearch)
+
+ this.sidebarUsernameSearch.addEvent(new SoopyKeyPressEvent().setHandler((key, keyId) => {
+ if (this.sidebarUsernameSearch.text.selected && keyId === 28) {
+ let search = this.sidebarUsernameSearch.text.text
+ this.sidebarUsernameSearch.setText("")
+ this.sidebarSearch(search)
+ }
+ }))
+
+ this.lbBackButton = new ButtonWithArrow().setLocation(0.05, 0.05, 0.1, 0.1).setText("§0Back").setDirectionRight(false)
+ this.lbNextButton = new ButtonWithArrow().setLocation(0.85, 0.05, 0.1, 0.1).setText("§0Next")
+ this.sidebarElement.addChild(this.lbBackButton)
+ this.sidebarElement.addChild(this.lbNextButton)
+ this.lbBackButton.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ if (this.currentLbPage > 0) this.goToLeaderboardPage(this.currentLbPage - 1)
+ }))
+ this.lbNextButton.addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.goToLeaderboardPage(this.currentLbPage + 1)
+ }))
+
+ this.leaderboardArea = new SoopyGuiElement().setLocation(0.05, 0.15, 0.9, 0.85).setScrollable(true)
+ this.sidebarElement.addChild(this.leaderboardArea)
+
+ this.currentLbPage = 0
+
+ this.finaliseLoading()
+ }
+
+ async updateData(player, profIn) {
+ this.playerLoad = player
+
+ this.statArea._scrollAmount = 0
+ this.statArea.location.scroll.y.set(0, 100)
+
+ this.statArea.clearChildren()
+ this.statArea.addChild(this.loadingElm)
+
+ let playerData = await fetch("http://soopy.dev/api/v2/player/" + player).json()
+
+ if (player !== this.playerLoad) return
+
+ if (!playerData.success) {
+ this.statArea.clearChildren()
+ this.statArea.addChild(this.errorElm)
+ this.errorElm.setText("§0" + playerData.error.name)
+ this.errorElm.setDesc("§0" + playerData.error.description)
+ return
+ }
+
+ let skyblockData = await fetch("http://soopy.dev/api/v2/player_skyblock/" + playerData.data.uuid).json()
+
+ if (player !== this.playerLoad) return
+
+ this.statArea.clearChildren()
+
+ if (!skyblockData.success) {
+ this.statArea.addChild(this.errorElm)
+ this.errorElm.setText("§0" + skyblockData.error.name)
+ this.errorElm.setDesc("§0" + skyblockData.error.description)
+ return
+ }
+
+ let selectedProf = profIn || skyblockData.data.stats.bestProfileId
+
+ let nwData = skyblockData.data.profiles[selectedProf].members[playerData.data.uuid].soopyNetworth
+ let nameElm = new SoopyTextElement().setText(playerData.data.stats.nameWithPrefix.replace(/§f/g, "§7")).setMaxTextScale(2).setLocation(0.1, 0.05, 0.8, 0.1)
+ this.statArea.addChild(nameElm)
+
+ let profOptions = {}
+ Object.keys(skyblockData.data.profiles).forEach(p => {
+ profOptions[p] = skyblockData.data.profiles[p].stats.cute_name
+ })
+
+ let profileSelect = new Dropdown().setOptions(profOptions).setSelectedOption(selectedProf).setLocation(0.1, 0.15, 0.3, 0.1).addEvent(new SoopyContentChangeEvent().setHandler(newval => {
+ this.updateData(player, newval)
+ }))
+ this.statArea.addChild(profileSelect)
+ this.statArea.addChild(new SoopyTextElement().setText("§0Networth: §2$" + numberWithCommas(Math.round(nwData.networth)).replace(/,/g, "§7,§2")).setMaxTextScale(1.5).setLocation(0.45, 0.15, 0.4, 0.1))
+ this.statArea.addChild(new SoopyTextElement().setText("§0Purse: §2$" + numberWithCommas(Math.round(nwData.purse)).replace(/,/g, "§7,§2") + "§0 | Bank: §2$" + numberWithCommas(Math.round(nwData.bank)).replace(/,/g, "§7,§2") + "§0 | Sack: §2$" + numberWithCommas(Math.round(nwData.sack)).replace(/,/g, "§7,§2")).setMaxTextScale(1.5).setLocation(0.1, 0.25, 0.8, 0.1))
+
+ Object.keys(nwData.categories).sort((a, b) => nwData.categories[b].total - nwData.categories[a].total).forEach((name, i) => {
+ let renderName = firstLetterWordCapital(name.replace(/_/g, " "))
+
+ let data = nwData.categories[name]
+
+ let box = new SoopyBoxElement().setLocation(i % 2 === 0 ? 0 : 0.525, 0.45 + Math.floor(i / 2) * 0.35, 0.475, 0.25)
+
+ box.addChild(new SoopyMarkdownElement().setLocation(0, 0, 1, 1).setText(data.items.filter(i => i.name).splice(0, 5).map(a => {
+ let name = (a.name.startsWith("§f") || a.name.startsWith("§7[Lvl ")) ? a.name.replace("§f", "§7") : a.name
+ return "§0" + name + "§0: §2$" + numberWithCommas(Math.round(a.p)).replace(/,/g, "§7,§2")
+ }).join("\n")))
+
+ let boxName = new SoopyTextElement().setLocation(i % 2 === 0 ? 0 : 0.525, 0.4 + Math.floor(i / 2) * 0.35, 0.475, 0.05).setText("§0" + renderName + "§0: §2$" + numberWithCommas(Math.round(data.total)).replace(/,/g, "§7,§2"))
+
+ this.statArea.addChild(box)
+ this.statArea.addChild(boxName)
+ })
+
+ if (selectedProf === skyblockData.data.stats.bestProfileId) {
+ let leaderboardData = await fetch("http://soopy.dev/api/v2/leaderboard/networth/user/" + playerData.data.uuid).json()
+ if (player !== this.playerLoad) return
+
+ if (leaderboardData.success) nameElm.setText("§0#" + numberWithCommas(leaderboardData.data.data.position + 1) + " " + playerData.data.stats.nameWithPrefix.replace(/§f/g, "§7"))
+
+ }
+ }
+
+ onOpen() {
+ this.playerLoad = Player.getName()
+ this.updateData(Player.getName())
+
+ this.goToLeaderboardPage(0)
+
+ this.openSidebarPage(this.sidebarElement)
+ }
+
+ async sidebarSearch(user) {
+ let data = await fetch("http://soopy.dev/api/v2/leaderboard/networth/user/" + user).json()
+ if (!data.success) {
+ return
+ }
+
+ let position = data.data.data.position
+
+ this.goToLeaderboardPage(Math.floor(position / 100), false)
+
+ this.leaderboardArea._scrollAmount = -((position % 100) * 0.1 - 0.45) * this.leaderboardArea.location.getHeightExact()
+ this.leaderboardArea.location.scroll.y.set(-((position % 100) * 0.1 - 0.45) * this.leaderboardArea.location.getHeightExact(), 100)
+ }
+
+ async goToLeaderboardPage(page, scroll = true) {
+ this.currentLbPage = page
+
+ if (scroll) this.leaderboardArea._scrollAmount = 0
+ if (scroll) this.leaderboardArea.location.scroll.y.set(0, 100)
+
+ let data = await fetch("http://soopy.dev/api/v2/leaderboard/networth/" + page).json()
+ this.leaderboardArea.clearChildren()
+ data.data.data.forEach((user, i) => {
+ this.leaderboardArea.addChild(
+ new SoopyTextElement().setText("§0#" + numberWithCommas(i + 1 + page * 100) + ": " + user.username).setMaxTextScale(1.5).setLocation(0.05, i * 0.05, 0.5, 0.05).setLore(["Click to show detailed stats"]).addEvent(new SoopyMouseClickEvent().setHandler(() => {
+ this.updateData(user.uuid)
+ }))
+ )
+ this.leaderboardArea.addChild(
+ new SoopyTextElement().setText("§2$" + numberWithCommas(Math.round(user.networth)).replace(/,/g, "§7,§2")).setMaxTextScale(1.5).setLocation(0.6, i * 0.05, 0.35, 0.05)
+ )
+ })
+ }
+}
+
+module.exports = {
+ class: new NetworthGui()
+}
\ No newline at end of file
diff --git a/src/features/networthGUI/metadata.json b/src/features/networthGUI/metadata.json
new file mode 100644
index 0000000..26e6f60
--- /dev/null
+++ b/src/features/networthGUI/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Networth gui",
+ "description": "Gui for Networth and Networth leaderboard",
+ "isHidden": true,
+ "isTogglable": false,
+ "defaultEnabled": true,
+ "sortA": 0
+}
\ No newline at end of file
diff --git a/src/features/performance/hiddenRequirement.js b/src/features/performance/hiddenRequirement.js
new file mode 100644
index 0000000..bc74bfc
--- /dev/null
+++ b/src/features/performance/hiddenRequirement.js
@@ -0,0 +1,7 @@
+let allowedUUIDS = [
+ "dc8c39647b294e03ae9ed13ebd65dd29"
+]
+
+module.exports = {hidden: function(featureManager){
+ return !allowedUUIDS.includes(Player.getUUID().toString().replace(/-/g, ""))
+}}
\ No newline at end of file
diff --git a/src/features/performance/index.js b/src/features/performance/index.js
new file mode 100644
index 0000000..634b994
--- /dev/null
+++ b/src/features/performance/index.js
@@ -0,0 +1,128 @@
+///
+///
+import Feature from "../../featureClass/class";
+import SettingBase from "../settings/settingThings/settingBase";
+import ToggleSetting from "../settings/settingThings/toggle";
+
+class Performance extends Feature {
+ constructor() {
+ super()
+ }
+
+ onEnable() {
+ return;
+ new SettingBase("NOTE: If you dont use any of the features, disable this", "Having performance enabled will decrease performance if no features are used\n(this is due to it using the render entity event)", true, "hide_performance_description", this)
+
+ this.armourStandCapSetting = new ToggleSetting("Armorstand render cap", "Limits the max number of armor stands rendered to 50\n(50 closest to player)", true, "armorstand_render_cap", this)
+
+ this.entitysRenderingTemp = {}
+ this.entitysRendering = {}
+
+ this.dontRender = {}
+
+ // this.removeHiddenEnts = []
+
+ this.nextUpdateDontRender = 0
+ this.maxEntsRender = 50
+ this.armourstandClass = Java.type("net.minecraft.entity.item.EntityArmorStand").class
+ this.armourstandClassString = this.armourstandClass.toString()
+
+ this.registerStep(true, 5, this.updateDontRender)
+
+ this.registerEvent("renderEntity", this.renderEntity)
+ this.registerEvent("renderWorld", this.renderWorld)
+
+ // this.registerForge(net.minecraftforge.event.entity.living.LivingAttackEvent, this.entityAttackEvent);
+ }
+
+ // entityAttackEvent(event) { //TODO: maby make an actual feature for this (0ping 1tap)
+ // if (event.source.func_76346_g() === Player.getPlayer()) {
+ // if(event.entity.func_110143_aJ()<800000){
+
+ // let uuid = new Entity(event.entity).getUUID().toString()
+ // this.dontRender[uuid] = "hit"
+ // this.removeHiddenEnts.push([uuid, Date.now()+1000])
+ // }
+ // }
+ // }
+
+ renderWorld() {
+ if (!this.armourStandCapSetting.getValue()) return
+ this.entitysRendering = {}
+ Object.keys(this.entitysRenderingTemp).forEach(a => {
+ this.entitysRendering[a] = true
+ })
+ this.entitysRenderingTemp = {}
+ }
+
+ updateDontRender() {
+ if (!this.armourStandCapSetting.getValue()) return
+
+ // this.removeHiddenEnts = this.removeHiddenEnts.filter(([uuid, time])=>{
+ // if(Date.now()