diff options
author | Soopyboo32 <49228220+Soopyboo32@users.noreply.github.com> | 2021-10-31 09:49:42 +0800 |
---|---|---|
committer | Soopyboo32 <49228220+Soopyboo32@users.noreply.github.com> | 2021-10-31 09:49:42 +0800 |
commit | 48653ec89538f1650106a5e77463412cad4684c2 (patch) | |
tree | 09687cd579462e04d539fd4615369fa6dae13902 /features | |
download | SoopyV2-48653ec89538f1650106a5e77463412cad4684c2.tar.gz SoopyV2-48653ec89538f1650106a5e77463412cad4684c2.tar.bz2 SoopyV2-48653ec89538f1650106a5e77463412cad4684c2.zip |
first commit
Diffstat (limited to 'features')
47 files changed, 4362 insertions, 0 deletions
diff --git a/features/agentlaiThings/hiddenRequirement.js b/features/agentlaiThings/hiddenRequirement.js new file mode 100644 index 0000000..3c0408d --- /dev/null +++ b/features/agentlaiThings/hiddenRequirement.js @@ -0,0 +1,8 @@ +let allowedUUIDS = [ + "f2bcfe6aa54c4eb9b37156b4f1d20beb", + "dc8c39647b294e03ae9ed13ebd65dd29" +] + +export default ()=>{ + return !allowedUUIDS.includes(Player.getUUID().toString().replace(/-/g, "")) +}
\ No newline at end of file diff --git a/features/agentlaiThings/index.js b/features/agentlaiThings/index.js new file mode 100644 index 0000000..aa3fdc3 --- /dev/null +++ b/features/agentlaiThings/index.js @@ -0,0 +1,194 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +import { SoopyGui, SoopyRenderEvent } from "../../../guimanager"; +import SoopyBoxElement from "../../../guimanager/GuiElement/SoopyBoxElement"; +import SoopyGuiElement from "../../../guimanager/GuiElement/SoopyGuiElement"; +import renderLibs from "../../../guimanager/renderLibs"; +import Feature from "../../featureClass/class"; +import ToggleSetting from "../settings/settingThings/toggle"; + +class AgentThings extends Feature { + constructor() { + super() + } + + onEnable(){ + this.initVariables() + + this.nearPlayerData = [] + while(this.nearPlayerData.length < 100){this.nearPlayerData.push({})} + + this.recordNearestPlayers = new ToggleSetting("Record nearby players", "You can then view this data with /nearplayers", true, "record_near_players", this) + + this.registerStep(false, 1, this.step) + + this.nearPlayersGui = new SoopyGui().setOpenCommand("nearplayers") + + this.nearPlayersGuiBox = new SoopyBoxElement().setLocation(0.25, 0.25, 0.5, 0.5) + this.nearPlayersGui.element.addChild(this.nearPlayersGuiBox) + + this.nearPlayersRenderElement = new SoopyGuiElement() + this.nearPlayersGuiBox.addChild(this.nearPlayersRenderElement) + + + let selected = undefined + let selectedDist = undefined + let lastXY = 0 + this.nearPlayersRenderElement.addEvent(new SoopyRenderEvent().setHandler((mouseX, mouseY)=>{ + let moved = lastXY !== mouseX+mouseY + lastXY = mouseX+mouseY + + let x = this.nearPlayersRenderElement.location.getXExact() + let y = this.nearPlayersRenderElement.location.getYExact() + let width = this.nearPlayersRenderElement.location.getWidthExact() + let height = this.nearPlayersRenderElement.location.getHeightExact() + + x+=width*0.125 + y+=height*0.125 + width*=0.75 + height*=0.75 + + Renderer.drawLine(Renderer.color(0, 0, 0), x, y+height, x+width, y+height, 2)//bottom axis line + Renderer.drawLine(Renderer.color(0, 0, 0), x, y, x, y+height, 2)//left axis line + + renderLibs.drawStringCentered("&0100s ago", x, y+height+6, Renderer.screen.getWidth()/1000) + renderLibs.drawStringCentered("&050s ago", x+width/2, y+height+6, Renderer.screen.getWidth()/1000) + renderLibs.drawStringCentered("&0Now", x+width, y+height+6, Renderer.screen.getWidth()/1000) //bottom axis markers + + + renderLibs.drawStringCenteredVertically("&025m away", x+3-Renderer.getStringWidth("&025m away")*Renderer.screen.getWidth()/1000, y, Renderer.screen.getWidth()/1000) + renderLibs.drawStringCenteredVertically("&020m away", x+3-Renderer.getStringWidth("&020m away")*Renderer.screen.getWidth()/1000, y+height/5*1, Renderer.screen.getWidth()/1000) + renderLibs.drawStringCenteredVertically("&010m away", x+3-Renderer.getStringWidth("&010m away")*Renderer.screen.getWidth()/1000, y+height/5*3, Renderer.screen.getWidth()/1000) + renderLibs.drawStringCenteredVertically("&00m away", x+3-Renderer.getStringWidth("&00m away")*Renderer.screen.getWidth()/1000, y+height-6, Renderer.screen.getWidth()/1000) + + if(moved){ + selected = undefined + selectedDist = undefined + } + let lastUuids = [] + this.nearPlayerData.forEach((data, i)=>{ + let newLastUuids = [] + Object.keys(data).forEach(uuid=>{ + newLastUuids.push(uuid) + lastUuids = lastUuids.filter(a=>a!==uuid) + + let dist = data[uuid].distance + let oldDist = this.nearPlayerData[i-1]?.[uuid]?.distance || 25 + + let thisX = x+(i)/100*width + let thisY = y+height-(dist/25)*height + + if(moved && (thisX-mouseX)**2 + (thisY-mouseY)**2 < 3){ + selected = uuid + selectedDist = dist + } + + if(i !== 0){ + Renderer.drawLine(Renderer.color(0, 0, 0), x+(i-1)/100*width, y+height-(oldDist/25)*height, thisX, thisY, 1) + } + + Renderer.drawRect(Renderer.color(0, 0, 0), thisX-1, thisY-1, 3, 3) + }) + + lastUuids.forEach(uuid=>{ + let dist = 25 + let oldDist = this.nearPlayerData[i-1]?.[uuid]?.distance || 25 + + let thisX = x+(i)/100*width + let thisY = y+height-(dist/25)*height + + if(i !== 0){ + Renderer.drawLine(Renderer.color(0, 0, 0), x+(i-1)/100*width, y+height-(oldDist/25)*height, thisX, thisY, 1) + } + }) + + lastUuids = newLastUuids + }) + + if(selected){ + width = this.nearPlayersRenderElement.location.getWidthExact() + height = this.nearPlayersRenderElement.location.getHeightExact() + + width*=0.75 + height*=0.75 + + renderLibs.scizzorFast(0,0,Renderer.screen.getWidth(), Renderer.screen.getHeight()) + let selectedIgn = undefined + let lastRenderedSelected = false + this.nearPlayerData.forEach((data, i)=>{ + if(data[selected]){ + lastRenderedSelected = true + + selectedIgn = data[selected].name + + let dist = data[selected].distance + let oldDist = this.nearPlayerData[i-1]?.[selected]?.distance || 25 + + let thisX = x+(i)/100*width + let thisY = y+height-(dist/25)*height + + if(i !== 0){ + Renderer.drawLine(Renderer.color(255, 0, 0), x+(i-1)/100*width, y+height-(oldDist/25)*height, thisX, thisY, 3) + } + }else{ + if(lastRenderedSelected){ + lastRenderedSelected = false + + let dist = 25 + let oldDist = this.nearPlayerData[i-1]?.[selected]?.distance || 25 + + let thisX = x+(i)/100*width + let thisY = y+height-(dist/25)*height + + if(i !== 0){ + Renderer.drawLine(Renderer.color(255, 0, 0), x+(i-1)/100*width, y+height-(oldDist/25)*height, thisX, thisY, 3) + } + } + } + }) + + let width = Math.max(Renderer.getStringWidth(selectedIgn)*2, Renderer.getStringWidth("Distance: " + selectedDist.toFixed(1)))+8 + let height = 32 + renderLibs.drawBox([255, 255, 255], mouseX+10, mouseY-height/2, width,height, 3) + renderLibs.drawString("&0" + selectedIgn, mouseX+14, mouseY-height/2+3, 2) + renderLibs.drawString("&0Distance: &7" + selectedDist.toFixed(1) , mouseX+14, mouseY-height/2+21, 1) + } + + })) + } + + step(){ + if(!this.recordNearestPlayers.getValue()) return + + let thisSecondPlayerData = {} + World.getAllPlayers().forEach(p=>{ + let distSq = (p.getX()-Player.getX())**2+(p.getY()-Player.getY())**2+(p.getZ()-Player.getZ())**2 + + if(distSq < 25*25 && distSq !== 0){ + thisSecondPlayerData[p.getUUID().toString()] = {name: p.getName(), distance: Math.sqrt(distSq)} + } + }) + + this.nearPlayerData.push(thisSecondPlayerData) + + if(this.nearPlayerData.length > 100) this.nearPlayerData.shift() + } + + initVariables(){ + this.recordNearestPlayers = undefined + this.nearPlayerData = undefined + this.nearPlayersGui = undefined + this.nearPlayersGuiBox = undefined + this.nearPlayersRenderElement = undefined + } + + onDisable(){ + this.nearPlayersGui.delete() + + this.initVariables() + } +} + +module.exports = { + class: new AgentThings() +}
\ No newline at end of file diff --git a/features/agentlaiThings/metadata.json b/features/agentlaiThings/metadata.json new file mode 100644 index 0000000..e44e8fa --- /dev/null +++ b/features/agentlaiThings/metadata.json @@ -0,0 +1,8 @@ +{ + "name": "Agentlai Settings", + "description": "Settings only avalible to agentlai", + "isHidden": "hiddenRequirement.js", + "isTogglable": true, + "defaultEnabled": false, + "sortA": 0 +}
\ No newline at end of file diff --git a/features/betterGuis/index.js b/features/betterGuis/index.js new file mode 100644 index 0000000..8600499 --- /dev/null +++ b/features/betterGuis/index.js @@ -0,0 +1,197 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +import Feature from "../../featureClass/class"; +import { drawBoxAtBlockNotVisThruWalls } from "../../utils/renderUtils"; +import ToggleSetting from "../settings/settingThings/toggle"; + +class BetterGuis extends Feature { + constructor() { + super() + } + + onEnable(){ + this.initVariables() + + 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 may add back 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.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" + ] + 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.registerEvent("guiMouseClick", this.guiClicked) + this.registerStep(true, 10, this.step) + } + + guiClicked(mouseX, mouseY, button, gui, event){ + if(gui.class.toString()==="class net.minecraft.client.gui.inventory.GuiChest" && button===0 && this.replaceSbMenuClicks.getValue()){ + + let hoveredSlot = gui.getSlotUnderMouse() + if(!hoveredSlot) return + + let hoveredSlotId = hoveredSlot.field_75222_d + // console.log(hoveredSlotId) + if(this.guiSlotClicked(ChatLib.removeFormatting(Player.getOpenedInventory().getName()), hoveredSlotId)){ + cancel(event) + } + } + } + + step(){ + if(this.replaceSbMenuClicks.getValue()){ + if(Player.getOpenedInventory().getName()==="SkyBlock Menu"){ + if(this.lastWindowId === 0){ + this.lastWindowId = Player.getOpenedInventory().getWindowId() + return; + } + if(Player.getOpenedInventory().getWindowId()!==this.lastWindowId){ + this.lastWindowId = Player.getOpenedInventory().getWindowId() + this.shouldHold+= 10 + if(Date.now()-this.clickSlotTime >1000){ + this.clickSlot = -1 + } + if(this.clickSlot && this.clickSlot != -1){ + Player.getOpenedInventory().click(this.clickSlot, false, "MIDDLE") + this.clickSlot = -1 + } + }else{ + this.shouldHold-- + } + }else{ + this.lastWindowId =0 + } + } + } + + guiSlotClicked(inventoryName, slotId){ + 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.getOpenedInventory().click(slotId, false, "MIDDLE") + } + break; + } + return true + break + default: + if(this.middleClickGuis.includes(inventoryName)){ + Player.getOpenedInventory().click(slotId, false, "MIDDLE") + return true + } + for(let thing of this.middleClickStartsWith){ + if(inventoryName.startsWith(thing)){ + Player.getOpenedInventory().click(slotId, false, "MIDDLE") + return true + } + } + for(let thing of this.middleClickEndsWith){ + if(inventoryName.endsWith(thing)){ + Player.getOpenedInventory().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 + } + + onDisable(){ + this.initVariables() + } +} + +module.exports = { + class: new BetterGuis() +}
\ No newline at end of file diff --git a/features/betterGuis/metadata.json b/features/betterGuis/metadata.json new file mode 100644 index 0000000..6aeed27 --- /dev/null +++ b/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/features/changeLogGUI/index.js b/features/changeLogGUI/index.js new file mode 100644 index 0000000..f6595b0 --- /dev/null +++ b/features/changeLogGUI/index.js @@ -0,0 +1,210 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +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" +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"); + +class ChangeLogGui extends Feature { + constructor() { + super() + } + + onEnable(){ + this.initVariables() + + this.ChangelogPage = new ChangelogPage() + } + + 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 = 0 + + 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 SoopyAddons ").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(`# NOTE +Updating SoopyAddons through this method is downloading the code from _§cmy server_ +This means that there is _§cno_ third party that is double checking the code to ensure there is no virus in it. +This is fine if you trust me to not put a virus in it, but if you dont you should instead wait for the update to be checked and verified by the chattriggers people.`) + this.updatingSidebarConfirmPage.addChild(this.warningMessage) + + this.updateButton = new ButtonWithArrow().setText("§0Update").setLocation(0.3, 0.3+this.warningMessage.getHeight(), 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+this.warningMessage.getHeight(),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() + } + + onOpen(){ + new Thread(()=>{ + let data = JSON.parse(FileLib.getUrlContent("http://soopymc.my.to/api/soopyv2/changelog.json")) + + this.changelogData = data.changelog.reverse() + + this.downloadableVersion = data.downloadableVersion + + this.updateText() + }).start() + } + + 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 SoopyAddons " + version) + + this.updateButton.location.location.y.set(0.3+this.warningMessage.getHeight(),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://soopymc.my.to/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" : "") + "\n" + data.description) + + height += changes.getHeight() + + height += 0.1 + }) + } +} + +module.exports = { + class: new ChangeLogGui() +}
\ No newline at end of file diff --git a/features/changeLogGUI/metadata.json b/features/changeLogGUI/metadata.json new file mode 100644 index 0000000..8dfbe4b --- /dev/null +++ b/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/features/dataLoader/index.js b/features/dataLoader/index.js new file mode 100644 index 0000000..41f0c61 --- /dev/null +++ b/features/dataLoader/index.js @@ -0,0 +1,128 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +import Feature from "../../featureClass/class"; + +class DataLoader extends Feature { + constructor() { + super() + } + + onEnable(){ + this.initVariables() + + this.stats = {} + + this.area = undefined + + this.isInSkyblock = false + + this.registerStep(true, 2, this.step) + + this.registerEvent("worldLoad", this.worldLoad) + + this.api_loaded_event = this.createCustomEvent("apiLoad") + + this.lastApiData = { + "skyblock": undefined, + "player": undefined, + "skyblock_raw": undefined, //the _raw is loaded from hypixel api instead of soopy api + "player_raw": undefined + } + + this.loadApi() + } + + worldLoad(){ + this.area = undefined + } + + loadApi(){ + let data = JSON.parse(FileLib.getUrlContent("http://soopymc.my.to/api/v2/player_skyblock/" + Player.getUUID().replace(/-/g, ""))) + + if(!data.success) return + + this.api_loaded_event.trigger(data, "skyblock", true, true) + this.lastApiData.skyblock = data + } + + loadApiData(type, soopyServer){ + while(this.FeatureManager.features["globalSettings"] === undefined){ + Thread.sleep(100) + } + let key = this.FeatureManager.features["globalSettings"].class.apiKeySetting.getValue() + if(!key) return + + if(soopyServer){ + + }else{ + if(type === "skyblock"){ + let data = JSON.parse(FileLib.getUrlContent("https://api.hypixel.net/skyblock/profiles?key=" + key + "&uuid=" + Player.getUUID().replace(/-/g, ""))) + + if(!data.success) return + + this.api_loaded_event.trigger(data, "skyblock", false, true) + this.lastApiData.skyblock_raw = data + } + } + } + + step(){ //2fps + this.stats["Area"] = undefined + this.stats["Dungeon"] = undefined + TabList.getNames().forEach(n=>{ + n = ChatLib.removeFormatting(n) + if(n.includes(": ")){ + 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.dungeonFloor = 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]) + } + }) + + this.isInSkyblock = Scoreboard.getTitle()?.removeFormatting().endsWith("SKYBLOCK") + this.area = this.stats["Area"] + } + + 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/features/dataLoader/metadata.json b/features/dataLoader/metadata.json new file mode 100644 index 0000000..4953f99 --- /dev/null +++ b/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/features/dungeonMap/index.js b/features/dungeonMap/index.js new file mode 100644 index 0000000..12bd471 --- /dev/null +++ b/features/dungeonMap/index.js @@ -0,0 +1,299 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +import Feature from "../../featureClass/class"; +const BufferedImage = Java.type("java.awt.image.BufferedImage") + +class DungeonMap extends Feature { + constructor() { + super() + } + + isInDungeon(){ + return this.FeatureManager.features["dataLoader"].class.isInDungeon + } + + onEnable(){ + this.initVariables() + + this.defaultPlayerImage = new Image("skull-steve","https://cravatar.eu/avatar/dc8c39647b294e03ae9ed13ebd65dd29") + this.playerImages = {} + this.mapDataPlayers = {} + this.offset = [] + this.mapScale = 1 + this.puzzles = [] + this.puzzlesTab = [] + this.newPuzzlesTab = [] + + // this.registerEvent("tick", this.tick) + this.registerStep(true, 5, this.step) + this.registerEvent("renderOverlay", this.renderOverlay) + this.registerEvent("worldLoad", this.worldLoad) + } + + worldLoad(){ + this.mortLocation = undefined + this.playerImages = {} + this.mapDataPlayers = {} + this.offset = [] + this.mapScale = 1 + this.puzzles = [] + this.puzzlesTab = [] + this.newPuzzlesTab = [] + } + + renderOverlay(){ + if(this.isInDungeon()){ + if(this.mapImage){ + this.mapImage.draw(50,50) + + this.drawPlayersLocations() + } + } + } + + drawPlayersLocations(){ + + let uuidToPlayer = {} + World.getAllPlayers().forEach(player=>{ + uuidToPlayer[player.getUUID().toString()] = player + }) + + Object.keys(this.mapDataPlayers).forEach((uuid)=>{ + let player = uuidToPlayer[uuid] + if(player){ + this.mapDataPlayers[uuid] = { + x: player.getX()/this.mapScale, + y: player.getZ()/this.mapScale, + rot: player.getYaw()+180 + } + } + + Renderer.translate(this.mapDataPlayers[uuid].x+50+this.offset[0], this.mapDataPlayers[uuid].y+50+this.offset[1]) + Renderer.rotate(this.mapDataPlayers[uuid].rot) + this.getImageForPlayer(uuid).draw(-5,-5, 10, 10) + }) + } + + step(){ + TabList.getNames().forEach(name=>{ + name = ChatLib.removeFormatting(name).split() + if(name[1].trim() === "[✦]" && !name[0].includes("???") && !this.puzzlesTab.includes(name[0].trim())){ + this.newPuzzlesTab.push(name[0].trim()) + this.puzzlesTab.push(name[0].trim()) + } + }) + + if(this.isInDungeon()){ + this.updateMapImage() + }else{ + this.mapImage = undefined + } + } + + updateMapImage(){ + + World.getAllPlayers().forEach(player=>{ + this.mapDataPlayers[Player.getUUID().toString()] = { + x: player.getX()/this.mapScale, + y: player.getZ()/this.mapScale, + rot: player.getYaw()+180 + } + }) + if(!this.mortLocation){ + World.getAllEntities().forEach(entity=>{ + if(ChatLib.removeFormatting(entity.getName()) === ("Mort")){ + this.mortLocation = [ + entity.getX(), + entity.getZ() + ] + } + }) + } + + let IMAGE_SIZE = 128 + let newImage = new BufferedImage(IMAGE_SIZE,IMAGE_SIZE, BufferedImage.TYPE_INT_RGB) + let graphics = newImage.getGraphics() + + graphics.fillRect(0,0,IMAGE_SIZE,IMAGE_SIZE) + + let mapImage = new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB) + let mapData + try { + let item = Player.getInventory().getStackInSlot(8) + mapData = item.getItem().func_77873_a(item.getItemStack(), World.getWorld()); // ItemStack.getItem().getMapData() + } catch (error) { + } + if(mapData){ + mapData.field_76203_h.forEach((icon, vec4b) => { + let x = vec4b.func_176112_b() + let y = vec4b.func_176113_c() + let rot = vec4b.func_176111_d() + + //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 + } + }) + + this.mapDataPlayers[closestP].x = x + this.mapDataPlayers[closestP].y = y + this.mapDataPlayers[closestP].rot = rot + }); + + // console.log("has map data poggies") + let bytes = mapData.field_76198_e + + let x = 0 + let y = 0 + for(let i = 0; i < bytes.length; i++){ + // console.log(bytes[i]/4) + + if(bytes[i] !== 0){ + let j = bytes[i]&255 + let color = net.minecraft.block.material.MapColor.field_76281_a[j>>2].func_151643_b(j & 3); + mapImage.setRGB(x, y, color) + newImage.setRGB(x, y, color) + } + x++ + if(x >= 128){ + x=0 + y++ + + if(y>128) break + } + + // mapImage.getRGB() + } + + // newImage.setRGB(0,0,128,128, ints, 0, 1) + + // graphics. () + //room size is 18 + //4 inbetween + + //finding room offsets + let roomOffsets + let mortLocationOnMap = undefined + let roomWidth = 0 + for(let x = 0;x<128;x++){ + for(let y = 0;y<128;y++){ + if(bytes[x+y*128] === 30 && bytes[(x-1)+(y-1)*128] === 0){ + roomWidth++ + } + } + if(roomWidth > 0) break; + } + + roomWidth = Math.floor(roomWidth*5/4) + this.mapScale = 32/roomWidth + for(let x = 0;x<128;x++){ + for(let y = 0;y<128;y++){ + if(bytes[x+y*128] === 30 && bytes[(x-1)+(y-1)*128] === 0){ + if(roomOffsets) break; + roomOffsets = [x%roomWidth-3, y%roomWidth-3] + + let dir = roomWidth/2-5/this.mapScale + + //top + for(let i = 0;i<roomWidth;i++){ + if(bytes[(i+x-3)+(y-3)*128] !== 0){ + mortLocationOnMap = [x-2+roomWidth/2, y-2+roomWidth/2-dir] + break + } + } + if(mortLocationOnMap) break + //bottom + for(let i = 0;i<roomWidth;i++){ + if(bytes[(i+x-3)+(y+roomWidth-3)*128] !== 0){ + mortLocationOnMap = [x-2+roomWidth/2, y-2+roomWidth/2+dir] + break + } + } + //left + for(let i = 0;i<roomWidth;i++){ + if(bytes[(x-3)+(i+y-3)*128] !== 0){ + mortLocationOnMap = [x-2+roomWidth/2-dir, y-2+roomWidth/2] + break + } + } + //right + for(let i = 0;i<roomWidth;i++){ + if(bytes[(x+roomWidth-3)+(i+y-3)*128] !== 0){ + mortLocationOnMap = [x-2+roomWidth/2+dir, y-2+roomWidth/2] + } + } + + break + } + if(bytes[x+y*128] === 66 && bytes[(x-1)+(y)*128] === 0 && bytes[(x)+(y-1)*128] === 0){ + if(!this.puzzles[x+y*128]){ + this.puzzles[x+y*128] = this.newPuzzlesTab.shift() + } + } + } + + } + + 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){ + newImage.setRGB(x, y, 0) + } + } + } + + if(mortLocationOnMap && this.mortLocation){ + this.offset = [mortLocationOnMap[0]-this.mortLocation[0]/this.mapScale, mortLocationOnMap[1]-this.mortLocation[1]/this.mapScale] + newImage.setRGB(mortLocationOnMap[0], mortLocationOnMap[1], Renderer.color(255, 0, 0)) + } + } + + // console.log(bytes[Math.floor(Player.getX()/this.mapScale+this.offset[0])+Math.floor(Player.getZ()/this.mapScale + this.offset[1])*128]) + + } + + + + this.mapImage = new Image(newImage) + } + + getImageForPlayer(uuid){ + uuid = uuid.replace(/-/g, "") + if(this.playerImages[uuid] === "Loading") return this.defaultPlayerImage + if(this.playerImages[uuid]) return this.playerImages[uuid] + + this.playerImages[uuid]= "Loading" + new Thread(()=>{ + this.playerImages[uuid] = new Image("skull-" + uuid,"https://cravatar.eu/helmavatar/" + uuid) + }).start() + return this.defaultPlayerImage + } + + initVariables(){ + this.mapImage = undefined + this.defaultPlayerImage = undefined + this.mortLocation = undefined + this.playerImages = undefined + this.offset = undefined + this.puzzles = undefined + this.puzzlesTab = undefined + this.mapScale = undefined + this.newPuzzlesTab = undefined + } + + onDisable(){ + this.initVariables() + } +} + +module.exports = { + class: new DungeonMap() +}
\ No newline at end of file diff --git a/features/dungeonMap/metadata.json b/features/dungeonMap/metadata.json new file mode 100644 index 0000000..2d0df77 --- /dev/null +++ b/features/dungeonMap/metadata.json @@ -0,0 +1,8 @@ +{ + "name": "Dungeon Map", + "description": "A really good dungeon map", + "isHidden": false, + "isTogglable": true, + "defaultEnabled": true, + "sortA": 1 +}
\ No newline at end of file diff --git a/features/dungeonSolvers/index.js b/features/dungeonSolvers/index.js new file mode 100644 index 0000000..5ca1ed5 --- /dev/null +++ b/features/dungeonSolvers/index.js @@ -0,0 +1,153 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +import Feature from "../../featureClass/class"; +import * as renderUtils from "../../utils/renderUtils"; +import HudTextElement from "../hud/HudTextElement"; +import LocationSetting from "../settings/settingThings/location"; +import ToggleSetting from "../settings/settingThings/toggle"; + +class DungeonSolvers extends Feature { + constructor() { + super() + } + + onEnable(){ + this.initVariables() + + this.lividData = {} + this.lividData.lividColor = { + "Vendetta": "&f", + "Crossed": "&d", + "Hockey": "&c", + "Doctor": "&7", + "Frog": "&2", + "Smile": "&a", + "Scream": "&1", + "Purple": "&5", + "Arcade": "&e" + } + this.onWorldLoad() + + 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.lividFindChat = new ToggleSetting("Say correct livid in chat", "Sends the correct livid in chat", false, "livid_chat_enabled", this).requires(this.lividFindEnabled) + 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.hudElements.push(this.lividHpElement) + + this.registerStep(true, 2, this.step) + this.registerEvent("worldLoad", this.onWorldLoad) + + this.registerEvent("renderOverlay", this.renderHud) + this.registerEvent("renderWorld", this.renderWorld) + this.registerEvent("renderEntity", this.renderEntity) + } + + renderWorld(ticks){ + if(this.lividFindBox.getValue()){ + if(this.lividData.correctLividEntity){ + renderUtils.drawBoxAtEntity(this.lividData.correctLividEntity, 255, 0, 0, 0.75, -2, ticks) + } + } + } + + 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) + } + } + } + } + + renderHud(){ + for(let element of this.hudElements){ + element.render() + } + } + + onWorldLoad(){ + this.lividData.correctLividColor = undefined + this.lividData.correctLividColorHP = undefined + this.lividData.sayLividColors = [] + this.lividData.sayLividColors2 = [] + this.lividData.correctLividEntity = undefined + this.lividHpElement && this.lividHpElement.setText("") + } + + step(){ //2fps + if(this.lividFindEnabled.getValue() && (this.FeatureManager.features["dataLoader"].class.dungeonFloor === "F5")){ //TODO: fix on M5 + World.getAllEntities().forEach(entity => { + let entityName = entity.getName() + if (/(?:Vendetta|Crossed|Hockey|Doctor|Frog|Smile|Scream|Purple|Arcade) Livid/g.test(entityName)) { + let lividName = entityName.replace(" Livid", "") + + if (!this.lividData.sayLividColors2.includes(lividName)) { + this.lividData.sayLividColors2.push(lividName) + if (this.lividData.sayLividColors2.length === 1) { + this.lividData.correctLividColor = lividName + } + if (this.lividData.sayLividColors2.length === 9) { + if(this.lividFindChat.getValue()){ + ChatLib.chat("Correct livid is: " + this.lividData.lividColor[lividName] + lividName) + } + this.lividData.correctLividColor = lividName + } + } + return; + } + if (entityName.includes("Livid") && entityName.includes("❤")) { + if (!this.lividData.sayLividColors.includes(entityName.substr(0, 3))) { + this.lividData.sayLividColors.push(entityName.substr(0, 3)) + if (this.lividData.sayLividColors.length === 9) { + this.lividData.correctLividColorHP = entityName.substr(0, 3) + } + if (this.lividData.sayLividColors.length === 1) { + this.lividData.correctLividColorHP = entityName.substr(0, 3) + } + } + + if (this.lividData.sayLividColors.length === 1) { + if (entityName.includes("Livid") && entityName.includes("❤")) { + this.lividHpElement.setText(entityName) + } + } else { + if (this.lividData.correctLividColorHP !== undefined) { + // if (this.lividData.correctLividColor === "Arcade") { + // this.lividHpElement.setText("Unknown Health (Yellow Livid)") + // } else { + if (entityName.includes(this.lividData.correctLividColorHP)) { + this.lividHpElement.setText(entityName) + this.lividData.correctLividEntity = entity + } + // } + } + } + + } + }) + } + } + + initVariables(){ + this.lividFindEnabled = undefined + this.lividData = undefined + this.hudElements = [] + } + + onDisable(){ + this.initVariables() + } +} + +module.exports = { + class: new DungeonSolvers() +}
\ No newline at end of file diff --git a/features/dungeonSolvers/metadata.json b/features/dungeonSolvers/metadata.json new file mode 100644 index 0000000..6467a3a --- /dev/null +++ b/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/features/events/index.js b/features/events/index.js new file mode 100644 index 0000000..24615e4 --- /dev/null +++ b/features/events/index.js @@ -0,0 +1,463 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +import Feature from "../../featureClass/class"; +import { drawBoxAtBlock, drawBoxAtBlockNotVisThruWalls, drawLine } from "../../utils/renderUtils"; +import { calculateDistance, calculateDistanceQuick, fastestPathThrough } from "../../utils/utils"; +import HudTextElement from "../hud/HudTextElement"; +import LocationSetting from "../settings/settingThings/location"; +import ToggleSetting from "../settings/settingThings/toggle"; + +class Events extends Feature { + constructor() { + super() + } + + onEnable(){ + this.initVariables() + + this.burrialData = { + points: [], + locations: [], + historicalLocations: [] + } + this.lastRequestTime = 0 + this.nextUpdateApprox = -1 + this.lastRequest = 0 + this.potentialParticleLocs = {} + this.showingWaypoints = false + this.lastPath = [] + this.updatingPath = false + this.hudElements = [] + this.lastPathCords = undefined + + this.burrialWaypointsEnabled = new ToggleSetting("Burrial waypoints", "Show waypoints for burrials during the diana event", true, "burrial_waypoints", this) + this.burrialWaypointsPath = new ToggleSetting("Pathfind waypoints", "Calculate a path thru all the waypoints", true, "burrial_waypoints_path", this).requires(this.burrialWaypointsEnabled) + this.burrialWaypointsNearest = new ToggleSetting("Show nearest using pathfinding", "Use pathfinding to highlight the next burrial instead of disance", true, "burrial_nearest_path", this).requires(this.burrialWaypointsEnabled) + + this.updateTimerEnabled = new ToggleSetting("Show API update timer", "Shows a countdown till the burrial waypoints will be next updated", true, "burrial_timer", this).requires(this.burrialWaypointsEnabled) + this.updateTimer = new HudTextElement() + .setToggleSetting(this.updateTimerEnabled) + .setLocationSetting(new LocationSetting("Timer Location", "Allows you to edit the location of the timer", "burrial_timer_location", this, [10, 50, 1, 1]) + .requires(this.burrialWaypointsEnabled) + .editTempText("&6Update&7> &f100s")) + this.hudElements.push(this.updateTimer) + + this.registerEvent("worldLoad", this.worldLoad) + this.registerEvent("spawnParticle", this.spawnParticle) + this.registerEvent("renderWorld", this.renderWorld) + this.registerEvent("renderOverlay", this.renderOverlay) + this.registerStep(true, 2, this.step) + this.registerStep(false, 5, this.step_5s) + this.registerSoopy("apiLoad", this.apiLoad) + } + + renderOverlay(){ + for(let element of this.hudElements){ + element.render() + } + } + + renderWorld(ticks){ + if(this.showingWaypoints && this.lastPathCords && this.burrialWaypointsPath.getValue()){ + let startPoint = [Player.getPlayer().field_70142_S+Player.getPlayer().field_70159_w*ticks, + Player.getPlayer().field_70137_T+Player.getPlayer().field_70181_x*ticks, + Player.getPlayer().field_70136_U+Player.getPlayer().field_70179_y*ticks] + + let lastPoint = startPoint || [0,0,0] + + this.lastPathCords.forEach((point)=>{ + drawLine(...lastPoint,...point,255,255,0) + + lastPoint = point + }) + } + if(this.showingWaypoints){ + 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 + }) + sorted.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 + } + drawBoxAtBlock(loc.x, loc.y,loc.z,0,blue?100:255,blue?255:0) + } + if(loc.fromApi){ + Tessellator.drawString( + "(" + (loc.chain+1) + "/4) " + typeReplace[loc.type] + " BURRIAL (" + Math.round(calculateDistance([Player.getX(),Player.getY(),Player.getZ()],[loc.x+0.5,loc.y+2.5,loc.z+0.5])) + "m)", + loc.x+0.5, + loc.y+1.5, + loc.z+0.5, + loc.clicked? 65280:(loc.nearest?16711680:6579300), true, loc.clicked? 0.04:(loc.nearest?1:0.5), !loc.clicked + ); + }else{ + Tessellator.drawString( + typeReplace[loc.type] + " BURRIAL (" + Math.round(calculateDistance([Player.getX(),Player.getY(),Player.getZ()],[loc.x+0.5,loc.y+2.5,loc.z+0.5])) + "m)", + loc.x+0.5, + loc.y+1.5, + loc.z+0.5, + loc.clicked? 65280:(loc.nearest?16711680:6579300), true, loc.clicked? 0.04:(loc.nearest?1:0.5), !loc.clicked + ); + } + }) + } + } + + step(){ + + hasDianaShovle = false + let slots = [0, 1, 2, 3, 4, 5, 6, 7, 8] + + slots.forEach(a=>{ + item = Player.getInventory().getStackInSlot(a) + if(ChatLib.removeFormatting(item.getName()) === "Ancestral Spade"){ + hasDianaShovle = true + } + }) + + let showingWaypointsNew = hasDianaShovle && this.FeatureManager.features["dataLoader"].class.area === "Hub" && this.burrialWaypointsEnabled.getValue() + + if(!this.showingWaypoints && showingWaypointsNew){ + this.loadApi() + }else{ + if(Date.now()-this.nextUpdateApprox > 0 && this.nextUpdateApprox > 0 && Date.now()-this.lastRequest>5000){ + this.nextUpdateApprox = -2 + this.loadApi() + } + } + + this.showingWaypoints = showingWaypointsNew + + if(this.showingWaypoints){ + + this.updateTimer.setText("&6Update&7> &f" + (this.nextUpdateApprox===-1?"Updating...":(this.nextUpdateApprox===-2?"Loading...":Math.ceil((this.nextUpdateApprox-Date.now())/1000) + "s"))) + }else{ + this.updateTimer.setText("") + } + + } + step_5s(){ + if(this.showingWaypoints){ + if(this.burrialWaypointsPath.getValue() || this.burrialWaypointsNearest.getValue()){ + new Thread(()=>{ + this.updateBurrialPath() + }).start() + } + } + } + + worldLoad(){ + this.burrialData.points = [] + this.burrialData.locations = [] + this.burrialData.historicalLocations = [] + + this.showingWaypoints = false + } + + loadApi(){ + new Thread(()=>{ + this.FeatureManager.features["dataLoader"].class.loadApiData("skyblock", false) + }).start() + } + + apiLoad(data, dataType, isSoopyServer, isLatest){ + if(!this.showingWaypoints) return; + if(isSoopyServer || dataType !== "skyblock" || !isLatest) return + this.lastRequest = Date.now() + + let profileData = data.profiles[0].members[Player.getUUID().toString().replace(/-/g,"")] + + data.profiles.forEach((prof)=>{ + if((prof.members[Player.getUUID().toString().replace(/-/g,"")].last_save || 0) > (profileData.last_save || 0)){ + profileData = prof.members[Player.getUUID().toString().replace(/-/g,"")] + } + }) + this.nextUpdateApprox = profileData.last_save+173000 + this.nextUpdateApprox += 2000 //incase ur pc time is behind + if(profileData.last_save === this.lastRequestTime){ + return + } + this.lastRequestTime = profileData.last_save + + let locsAccessed = [] + let newLocs = [] + profileData.griffin.burrows.forEach((burrow)=>{ + let pushed = false + this.burrialData.locations.forEach((loc, i)=>{ + if((loc.fromApi || loc.clicked) && loc.x + "," + loc.y + "," + loc.z === burrow.x + "," + burrow.y + "," + burrow.z){ + newLocs.push(loc) + pushed = true + locsAccessed.push(i) + } + }) + this.burrialData.historicalLocations.forEach((loc)=>{ + if(loc.x + "," + loc.y + "," + loc.z === burrow.x + "," + burrow.y + "," + burrow.z){ + pushed = true + } + }) + if(!pushed){ + burrow.clicked = false + burrow.fromApi = true + newLocs.push(burrow) + } + }) + + this.burrialData.locations.forEach((loc)=>{ + if(!loc.fromApi){ + let found = false + newLocs.forEach((burrow)=>{ + if(loc.x + "," + loc.y + "," + loc.z === burrow.x + "," + burrow.y + "," + burrow.z){ + found = true + } + }) + + if(!found){ + newLocs.push(loc) + } + } + }) + + this.burrialData.locations = newLocs + this.updateBurrialPath() + } + + + spawnParticle(particle, type, event){ + if(this.showingWaypoints){ + 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 + + this.lastPathCords.shift() + } + }) + 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; + + 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 = true + loc.lastPing = Date.now() + } + if((loc.x+1) + "," + loc.y + "," + loc.z === locstr){ + found = true + loc.lastPing = Date.now() + } + if((loc.x-1) + "," + loc.y + "," + loc.z === locstr){ + found = true + loc.lastPing = Date.now() + } + if(loc.x + "," + loc.y + "," + (loc.z+1) === locstr){ + found = true + loc.lastPing = Date.now() + } + if(loc.x + "," + loc.y + "," + (loc.z-1) === locstr){ + found = true + loc.lastPing = Date.now() + } + }) + if(this.burrialData.historicalLocations){ + this.burrialData.historicalLocations.forEach((loc)=>{ + if(loc.x + "," + loc.y + "," + loc.z === locstr){ + found = true + } + }) + } + + if(found) return; + + + if (!this.potentialParticleLocs[locstr])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 > 2 && this.potentialParticleLocs[locstr].step > 5){ + 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 + }) + new Thread(()=>{ + this.updateBurrialPath() + }).start() + } + } + } + + burrialClicked(){ + 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() + this.lastPathCords.shift() + new Thread(()=>{ + this.updateBurrialPath() + }).start() + } + updateBurrialPath(){ + if(this.burrialWaypointsPath.getValue() || this.burrialWaypointsNearest.getValue()){ + let startPoint = [Player.getX(),Player.getY(),Player.getZ()] + + let points = this.burrialData.locations.filter((a)=>{return !a.clicked}).map((a)=>{return [a.x+0.5,a.y+1.3,a.z+0.5]}) + + if(points.length !== 0){ + + if(points.length >= 10){ + this.lastPath = undefined + this.lastPathCords = undefined + }else{ + this.lastPath = fastestPathThrough(startPoint,points) + + this.lastPathCords = [] + this.lastPath.forEach(a=>{ + this.lastPathCords.push(points[a]) + }) + } + + if(this.lastPath.length === 0){ + this.lastPath = undefined + this.lastPathCords = undefined + } + + }else{ + this.lastPath = undefined + this.lastPathCords = undefined + } + } + + + if(this.showingWaypoints){ + if(this.burrialWaypointsNearest.getValue()){ + let trueI = 0 + this.burrialData.locations.forEach((loc,i)=>{ + if(!loc.clicked && trueI === this.lastPath[0]){ + this.burrialData.locations[i].nearest = true + }else{ + this.burrialData.locations[i].nearest = false + } + + if(!loc.clicked) trueI++ + }) + }else{ + let closestBurrialI = 0 + let closestBurrialDist = Infinity + + this.burrialData.locations.forEach((loc,i)=>{ + let dist = calculateDistanceQuick([loc.x,loc.y,loc.z],[Player.getX(),Player.getY(),Player.getZ()]) + if(dist < closestBurrialDist){ + closestBurrialDist = dist + closestBurrialI = i + } + this.burrialData.locations[i].nearest = false + }) + + this.burrialData.locations[closestBurrialI].nearest = true + } + } + } + + initVariables(){ + this.burrialData = undefined + this.lastRequestTime = undefined + this.nextUpdateApprox = undefined + this.lastRequest = undefined + this.potentialParticleLocs = undefined + this.showingWaypoints = undefined + this.lastPath = undefined + this.updatingPath = undefined + this.hudElements = undefined + this.lastPathCords = undefined + } + + onDisable(){ + this.initVariables() + } +} + +module.exports = { + class: new Events() +}
\ No newline at end of file diff --git a/features/events/metadata.json b/features/events/metadata.json new file mode 100644 index 0000000..363625f --- /dev/null +++ b/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/features/featureBase/index.js b/features/featureBase/index.js new file mode 100644 index 0000000..7a11945 --- /dev/null +++ b/features/featureBase/index.js @@ -0,0 +1,24 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +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/features/featureBase/metadata.json b/features/featureBase/metadata.json new file mode 100644 index 0000000..a6b411d --- /dev/null +++ b/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/features/fragBot/index.js b/features/fragBot/index.js new file mode 100644 index 0000000..67bb9a3 --- /dev/null +++ b/features/fragBot/index.js @@ -0,0 +1,84 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +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) + + 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) + this.registerStep(true, 2, this.step2) + + 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("&aFragbot has been disabled") + }else{ + this.hostingFragBot = true + ChatLib.chat("&aNow 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/features/fragBot/metadata.json b/features/fragBot/metadata.json new file mode 100644 index 0000000..5aaa6a9 --- /dev/null +++ b/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/features/friendsGUI/index.js b/features/friendsGUI/index.js new file mode 100644 index 0000000..c7a370e --- /dev/null +++ b/features/friendsGUI/index.js @@ -0,0 +1,154 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +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"; + +class FriendsGui extends Feature { + constructor() { + super() + } + + onEnable(){ + this.initVariables() + + this.GuiPage = new SettingPage() + + this.registerChat("&9-----------------------------------------------------&r&9${*}&r&9 ${*} &6Friends (Page ${pagenum} of ${maxpages})${friendslist}&r&9-----------------------------------------------------&r", (...args)=>{this.GuiPage.friendListMessageEvent.call(this.GuiPage, ...args)}) + this.registerStep(true, 5, ()=>{this.GuiPage.regenGuiElements.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.pageCount = undefined + + this.heightPerFriend = 0.2 + this.loadingElement = new BoxWithLoading().setLocation(0,0, 1, 0.175) + this.lastLoadedPage = 0 + this.maxLoadedPage = 0 + + this.loadingElement.addEvent(new SoopyRenderEvent().setHandler(()=>{ + if(Date.now()-this.lastLoadedPage > 1000){ + this.loadFriendPage(this.maxLoadedPage+1) + } + })) + + + this.finaliseLoading() + } + + friendListMessageEvent(pagenum, maxpages, friendslist, event){ + if(Date.now()-this.lastRender < 1000){ + cancel(event) + // console.log("Canceling") + }else{ + return + } + + this.maxLoadedPage = parseInt(pagenum) + + this.pageCount = parseInt(maxpages) + + 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)].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, + 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")) + } + this.loadedFriends[ChatLib.removeFormatting(name)].element.location.location.y.set(this.heightPerFriend*Object.keys(this.loadedFriends).length-this.heightPerFriend, 500+100*i) + } + } + }); + + this.regenGuiElements() + } + + 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)=>{ + if(this.loadedFriends[ign].element.location.location.y.get() > minY && this.loadedFriends[ign].element.location.location.y.get() < maxY){ + this.friendsArea.addChild(this.loadedFriends[ign].element) + } + }) + + if(this.maxLoadedPage !== this.pageCount){ + this.loadingElement.location.location.y.set(this.heightPerFriend*Object.keys(this.loadedFriends).length, 500) + this.friendsArea.addChild(this.loadingElement) + } + } + } + + loadFriendPage(page){ + ChatLib.command("friends list " + page) + this.lastLoadedPage = Date.now() + } + + onOpen(){ + this.loadedFriends = {} + this.pageCount = undefined + this.lastLoadedPage = 0 + this.maxLoadedPage = 0 + + this.regenGuiElements() + + this.loadFriendPage(1) + } +} + +module.exports = { + class: new FriendsGui() +}
\ No newline at end of file diff --git a/features/friendsGUI/metadata.json b/features/friendsGUI/metadata.json new file mode 100644 index 0000000..b7b1f6f --- /dev/null +++ b/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/features/globalSettings/index.js b/features/globalSettings/index.js new file mode 100644 index 0000000..5b459f9 --- /dev/null +++ b/features/globalSettings/index.js @@ -0,0 +1,51 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +import Feature from "../../featureClass/class"; +import ButtonSetting from "../settings/settingThings/button"; +import TextSetting from "../settings/settingThings/textSetting"; + +class Hud extends Feature { + constructor() { + super() + + this.initVariables() + } + + initVariables(){ + + this.apiKeySetting = 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.verifyKey, undefined) + + this.registerChat("&aYour new API key is &r&b${key}&r", this.newKey) + } + + verifyKey(){ + if(this.module.apiKeySetting.getValue() == ""){ + ChatLib.chat("&c[SOOPY V2] You need to set an api key first!") + return + } + + var url = "https://api.hypixel.net/key?key=" + this.module.apiKeySetting.getValue() + + ChatLib.chat("&c[SOOPY V2] The rest of checking is yet to be coded!") + } + + newKey(key){ + ChatLib.chat("&c[SOOPY V2] Copied api key!") + this.apiKeySetting.setValue(key) + } + + onDisable(){ + this.fpsEnabledSetting.delete() + + this.initVariables() + } +} + +module.exports = { + class: new Hud() +}
\ No newline at end of file diff --git a/features/globalSettings/metadata.json b/features/globalSettings/metadata.json new file mode 100644 index 0000000..801716f --- /dev/null +++ b/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/features/hud/HudTextElement.js b/features/hud/HudTextElement.js new file mode 100644 index 0000000..582b778 --- /dev/null +++ b/features/hud/HudTextElement.js @@ -0,0 +1,77 @@ +class HudTextElement{ + constructor(){ + this.text = "" + + this.toggleSetting = undefined + this.locationSetting = undefined + + this.blackText = "&0" + ChatLib.removeFormatting(this.text) + + this.editTempTimeV = 0 + this.editTempTextV = undefined + + this.tempDisableTime = 0 + } + + setText(text){ + this.text = text + + if(this.locationSetting.shadowType === 2){ + this.blackText = "&0" + ChatLib.removeFormatting(text) + } + return this + } + setToggleSetting(setting){ + this.toggleSetting = setting + return this + } + setLocationSetting(setting){ + this.locationSetting = setting + setting.setParent(this) + return this + } + + render(){ + if(this.toggleSetting && !this.toggleSetting.getValue() || !this.locationSetting) return + if(Date.now()-this.tempDisableTime < 100) return + + this.renderRaw() + } + + getText(){ + let text = this.text + let blackText = this.blackText + if(this.editTempTextV && Date.now()-this.editTempTimeV < 100){ + text = this.editTempTextV + blackText = "&0" + ChatLib.removeFormatting(text) + } + return [text.split("\n"), blackText.split("\n")] + } + + renderRaw(){ + let [text, blackText] = this.getText() + + text.forEach((line, 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; + case 2: + Renderer.drawString(blackText[i], (this.locationSetting.x+1)/this.locationSetting.scale, this.locationSetting.y/this.locationSetting.scale +9*i) + Renderer.drawString(blackText[i], (this.locationSetting.x-1)/this.locationSetting.scale, this.locationSetting.y/this.locationSetting.scale +9*i) + Renderer.drawString(blackText[i], this.locationSetting.x/this.locationSetting.scale, (this.locationSetting.y+1)/this.locationSetting.scale +9*i) + Renderer.drawString(blackText[i], this.locationSetting.x/this.locationSetting.scale, (this.locationSetting.y-1)/this.locationSetting.scale +9*i) + + Renderer.drawString(line, this.locationSetting.x/this.locationSetting.scale, this.locationSetting.y/this.locationSetting.scale +9*i) + break; + } + }) + Renderer.scale(1, 1) + } +} + +export default HudTextElement
\ No newline at end of file diff --git a/features/hud/index.js b/features/hud/index.js new file mode 100644 index 0000000..b6db8c6 --- /dev/null +++ b/features/hud/index.js @@ -0,0 +1,315 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +import SoopyNumber from "../../../guimanager/Classes/SoopyNumber"; +import Feature from "../../featureClass/class"; +import LocationSetting from "../settings/settingThings/location"; +import ToggleSetting from "../settings/settingThings/toggle"; +import HudTextElement from "./HudTextElement"; + +class Hud extends Feature { + constructor() { + super() + + this.initVariables() + } + + 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 + } + + onEnable(){ + + 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)) + this.hudElements.push(this.petElement) + + this.soulflowEnabledSetting = new ToggleSetting("Show Soulflow", "Whether the soulflow count is rendered onto the screen", true, "soulflow_enabled", this) + this.soulflowShowWarningSetting = new ToggleSetting("Show no Talisman Warning", "Shows a warning if you dont have a soulflow talis in ur inv", true, "soulflow_notalis_warning", this).requires(this.soulflowEnabledSetting) + 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)) + this.hudElements.push(this.soulflowElement) + + // 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).requires(this.soulflowEnabledSetting) + // 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("Test Line 1\nTest line 2\nTest line 3\nTest line 4 (longer KEKW)")) + // this.hudElements.push(this.dragonDamageElement) + + this.step_5second() + + this.lastTickTime = 0 + this.framesSince = 0 + this.lastframe = 0 + this.slowestFrameTime = 0 + + 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) + this.registerStep(true, 5, this.step) + this.registerStep(false, 5, this.step_5second) + this.registerEvent("renderWorld", this.renderWorld) + + this.petLevels = {} + 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.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.registerChat("&r&aYou despawned your &r${*}&r&a!&r", ()=>{ + this.petElement.setText("&6Pet&7> &cNone") + this.petText = "&6Pet&7> &cNone" + }) + this.registerChat("&r&aYour &r${pet} &r&alevelled up to level &r&9${level}&r&a!&r", (pet, level)=>{ + this.petElement.setText("&6Pet&7> &7[Lvl " + level +"] "+pet) + this.petText = "&6Pet&7> &7[Lvl " + level +"] "+pet + }) + + 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) + } + } + + onDisable(){ + this.fpsEnabledSetting.delete() + this.fpsFastSetting.delete() + this.cpsEnabledSetting.delete() + + this.initVariables() + } + + renderHud(){ + + 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())) + } + } + + for(let element of this.hudElements){ + element.render() + } + } + + renderWorld(){ + if(!this.fpsEnabledSetting.getValue() ||!this.fpsFastSetting.getValue()) return + this.framesSince++ + + let instant = this.Instant.now() + let time = instant.getEpochSecond() + (instant.getNano() / 1000000000); + + let thisframeTime = time - this.lastFrame + + if(thisframeTime > this.slowestFrameTime){ + this.slowestFrameTime = thisframeTime + } + + this.lastFrame = time + } + + step(){ + 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(Player && Player.getOpenedInventory().getName().includes(") Pets")){ + let inv = Player.getOpenedInventory().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 + } + } + } + } + + step_5second(){ + if(!this.soulflowEnabledSetting.getValue()) return + if(!Player.getPlayer()) return + if(!Player.getInventory()) return + + if(!this.FeatureManager.features["dataLoader"].class.isInSkyblock){ + this.soulflowElement.setText("") + this.petElement.setText("") + return + }else{ + this.petElement.setText(this.petText) + } + + let soulflowCount = 0 + let hasSoulflowItem = false + Player.getInventory().getItems().forEach(i=>{ + + let id; + try{ + id = i.getNBT().getCompoundTag("tag").getCompoundTag("ExtraAttributes").getString("id") + }catch(e){} + + if(id === "SOULFLOW_PILE" || id=== "SOULFLOW_BATTERY" || id === "SOULFLOW_SUPERCELL"){ + //soulflowCount + i.getLore().forEach(line=>{ + if(line.startsWith("§5§o§7Internalized:")){ + hasSoulflowItem = true + soulflowCount = parseInt(ChatLib.removeFormatting(line).substr("Internalized: ".length).split("⸎")[0].replace(/,/g,"")) + } + }) + } + }) + if(!hasSoulflowItem){ + if(this.soulflowShowWarningSetting.getValue()){ + this.soulflowElement.setText("&6Soulflow&7> &cNO TALISMAN") + }else{ + this.soulflowElement.setText("") + } + return; + } + if(soulflowCount > 0 && !this.soulflowShowWhen0Setting.getValue()){ + this.soulflowElement.setText("") + return; + } + + this.soulflowElement.setText("&6Soulflow&7> &f" + this.numberUtils.numberWithCommas(soulflowCount)) + } + + apiLoad(data, dataType, isSoopyServer, isLatest){ + 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 + } +} + +module.exports = { + class: new Hud() +}
\ No newline at end of file diff --git a/features/hud/metadata.json b/features/hud/metadata.json new file mode 100644 index 0000000..67f5671 --- /dev/null +++ b/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/features/improvements/index.js b/features/improvements/index.js new file mode 100644 index 0000000..4d003f3 --- /dev/null +++ b/features/improvements/index.js @@ -0,0 +1,36 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +import Feature from "../../featureClass/class"; +import ToggleSetting from "../settings/settingThings/toggle"; + +class Improvements extends Feature { + constructor() { + super() + } + + onEnable(){ + this.initVariables() + + this.betterLineBreaks = new ToggleSetting("Better line breaks", "Changes all dashed lines (-------) in chat into solid lines", true, "better_line_breaks", this) + + this.registerChat("${color}-----------------------------------------------------&r", (color, event)=>{ + if(this.betterLineBreaks.getValue()){ + cancel(event) + ChatLib.chat(color + "&m" + ChatLib.getChatBreak(" ") + "&r"); + } + }).trigger.triggerIfCanceled(false) + } + + + initVariables(){ + this.betterLineBreaks = undefined + } + + onDisable(){ + this.initVariables() + } +} + +module.exports = { + class: new Improvements() +}
\ No newline at end of file diff --git a/features/improvements/metadata.json b/features/improvements/metadata.json new file mode 100644 index 0000000..4e147f6 --- /dev/null +++ b/features/improvements/metadata.json @@ -0,0 +1,8 @@ +{ + "name": "Improvements", + "description": "A bunch of random features that improve aspects of the game", + "isHidden": false, + "isTogglable": true, + "defaultEnabled": true, + "sortA": 1 +}
\ No newline at end of file diff --git a/features/mining/index.js b/features/mining/index.js new file mode 100644 index 0000000..457ab84 --- /dev/null +++ b/features/mining/index.js @@ -0,0 +1,201 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +import Feature from "../../featureClass/class"; +import { drawBoxAtBlockNotVisThruWalls } from "../../utils/renderUtils"; +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"; + +class Mining extends Feature { + constructor() { + super() + } + + 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.seenBalDamages = [] + this.balHP = 250 + this.lastBalAlive = 0 + this.balDespawnDebounce = 0 + this.armourstandClass = Java.type("net.minecraft.entity.item.EntityArmorStand").class + + this.registerEvent("renderOverlay", this.renderOverlay) + this.registerEvent("tick", this.tick) + this.registerEvent("itemTooltip", this.itemTooltipEvent) + this.registerEvent("renderWorld", this.renderWorld) + + 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 + }) + } + + itemTooltipEvent(lore, item, event){ + this.addLore(item) + } + + /** + * @param {Item} item + */ + addLore(item){ + 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.func_74745_c() === 0){ + utils.addLore(item, ChatLib.addColor("&d&lGemstones Unlocked: &f"), ChatLib.addColor("&cNone!")) + }else{ + let gemstoneString = "" + + for(let i = 0; i < unlockedGems.func_74745_c(); i++){ + let gem = String(unlockedGems.func_150307_f(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()) + } + } + + tick(){ + 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().func_70809_q() > 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("") + } + } + + renderOverlay(){ + for(let element of this.hudElements){ + element.render() + } + } + + 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.initVariables() + } +} + +module.exports = { + class: new Mining() +}
\ No newline at end of file diff --git a/features/mining/metadata.json b/features/mining/metadata.json new file mode 100644 index 0000000..ce9ed40 --- /dev/null +++ b/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/features/settings/index.js b/features/settings/index.js new file mode 100644 index 0000000..6d41754 --- /dev/null +++ b/features/settings/index.js @@ -0,0 +1,249 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +import Feature from "../../featureClass/class"; +import * as GuiManager from "../../../guimanager/index.js" +import SoopyGuiElement from "../../../guimanager/GuiElement/SoopyGuiElement"; +import SoopyTextElement from "../../../guimanager/GuiElement/SoopyTextElement"; +import SoopyBoxElement from "../../../guimanager/GuiElement/SoopyBoxElement"; +import TextWithArrow from "../../../guimanager/GuiElement/TextWithArrow"; +import ButtonWithArrow from "../../../guimanager/GuiElement/ButtonWithArrow"; +import BoxWithToggleAndDescription from "../../../guimanager/GuiElement/BoxWithToggleAndDescription"; +import ButtonWithArrowAndDescription from "../../../guimanager/GuiElement/ButtonWithArrowAndDescription"; +import SoopyMouseClickEvent from "../../../guimanager/EventListener/SoopyMouseClickEvent"; +import SoopyContentChangeEvent from "../../../guimanager/EventListener/SoopyContentChangeEvent"; +import SoopyOpenGuiEvent from "../../../guimanager/EventListener/SoopyOpenGuiEvent"; +import settingsCommunicator from "./settingsCommunicator"; +import GuiPage from "../soopyGui/GuiPage" + + +class SettingsRenderer extends Feature { + constructor() { + super() + + this.gui = undefined + + this.pages = [] + this.currentPage = 0 + this.backButton = undefined + this.settingsCategoryArea = undefined + this.settingsTitle = undefined + this.settingsArea = undefined + this.modifyingFeature = false + this.featureLoadedTextBox = undefined + + this.SettingPage = undefined + } + + onEnable(){ + + this.SettingPage = new SettingPage() + this.SettingPage.FeatureManager = this.FeatureManager + + return; + } + + onDisable(){ + this.SettingPage = undefined + return; + this.gui.delete() + + this.pages = [] + this.currentPage = 0 + this.backButton = undefined + this.settingsArea = undefined + this.settingsTitle = undefined + this.settingsCategoryArea = undefined + this.modifyingFeature = false + this.featureLoadedTextBox = undefined + } + + clickedOpenSettings(){ + + + this.goToPage(1) + } + + clickedBackButton(){ + this.goToPage(this.currentPage-1) + } + + goToPage(pageNum, animate=true){ + pageNum = Math.max(0, Math.min(pageNum, this.pages.length-1)) + + if(pageNum == this.currentPage){ + return + } + + this.currentPage = pageNum + + this.pages.forEach((p, i)=>{ + p.forEach(e=>{ + e.location.location.x.set(i-pageNum, animate?1000:0) + }) + }) + + this.backButton.location.location.y.set(pageNum === 0?-0.2:0, animate?1000:0) + } +} + +class SettingPage extends GuiPage { + constructor(){ + super(10) + + this.name = "Settings" + + this.pages = [this.newPage(), this.newPage()] + + this.settingsCategoryArea = undefined + this.settingsTitle = undefined + this.settingsArea = undefined + this.modifyingFeature = false + this.featureLoadedTextBox = undefined + + this.SettingPage = undefined + + this.pages[0].addEvent(new GuiManager.SoopyRenderEvent().setHandler(()=>{this.updateLocs()})) + + //############################################################################################### + // Settings Category Page + //############################################################################################### + + + + let settingsCategoryTitle = new SoopyTextElement().setText("§0Settings").setMaxTextScale(3).setLocation(0.1, 0.05, 0.8, 0.1) + this.pages[0].addChild(settingsCategoryTitle) + + this.settingsCategoryArea = new SoopyGuiElement().setLocation(0.1, 0.2, 0.8, 0.8).setScrollable(true) + this.pages[0].addChild(this.settingsCategoryArea) + + + //############################################################################################### + // Settings Page + //############################################################################################### + + this.settingsTitle = new SoopyTextElement().setMaxTextScale(3).setLocation(0.1, 0.05, 0.8, 0.1) + this.pages[1].addChild(this.settingsTitle) + + this.settingsArea = new SoopyGuiElement().setLocation(0.1, 0.2, 0.8, 0.8).setScrollable(true) + this.pages[1].addChild(this.settingsArea) + + + this.finaliseLoading() + } + + onOpen(){ + this.updateSettingCategories() + this.settingsCategoryArea.location.scroll.x.set(0, 0) + this.settingsCategoryArea.location.scroll.y.set(0, 0) + } + + updateSettingCategories(){ + this.settingsCategoryArea.children = [] + + let i = 0 + + Object.keys(this.FeatureManager.featureMetas).sort((a, b)=>{return a.sortA-b.sortA}).forEach((f)=>{ + let meta = this.FeatureManager.featureMetas[f] + + let isHidden = meta.isHidden + if(typeof isHidden === "string"){ + isHidden = require("../" + f + "/" + isHidden).default() + } + if(isHidden) return + + let category = new ButtonWithArrowAndDescription().setText("&0" + meta.name).setDesc("&0" +meta.description).setLocation(0, 0.225*i, 1, 0.2) + category.addEvent(new SoopyMouseClickEvent().setHandler(()=>{this.clickedOpenCategory(f)})) + + this.settingsCategoryArea.addChild(category) + + i++ + }) + // this.FeatureManager.features = {}; enabled features + } + + updateSettings(category){ + let meta = this.FeatureManager.featureMetas[category] + + this.settingsArea.children = [] + + this.settingsTitle.setText("&0" + this.FeatureManager.featureMetas[category].name) + + let height = 0 + + if(meta.isTogglable){ + let toggle = new BoxWithToggleAndDescription().setLocation(0, height, 1, 0.2).setText("&0Main toggle").setDesc("&0This is the main toggle for the whole category") + this.settingsArea.addChild(toggle) + + toggle.toggle.setValue(this.FeatureManager.isFeatureLoaded(category), 0) + + toggle.toggle.addEvent(new SoopyContentChangeEvent().setHandler((newVal, oldVal, resetFun)=>{ + //dont allow editing if currenately loading/unloading it + if(this.modifyingFeature){ + resetFun() + return + } + + //toggle the feature + this.modifyingFeature = true + new Thread(()=>{ + this.FeatureManager.featureSettingsData[category].enabled = newVal + this.FeatureManager.featureSettingsDataLastUpdated = true + + if(!newVal && this.FeatureManager.isFeatureLoaded(category)){ + this.FeatureManager.unloadFeature(category) + } + if(newVal && !this.FeatureManager.isFeatureLoaded(category)){ + this.FeatureManager.loadFeature(category) + } + + Thread.sleep(100) + + this.modifyingFeature = false + + this.updateSettings(category) + }).start() + })) + height += toggle.location.size.y.get()+0.045 + } + + if(!this.FeatureManager.isFeatureLoaded(category)){ + + //only show if feature issnt loaded + + let textBox = new SoopyBoxElement().setLocation(0, height, 1, 0.2) + .addChild(new SoopyTextElement().setText("&0Feature not loaded").setLocation(0, 0, 1, 0.5)) + .addChild(new SoopyTextElement().setText("&0Load feature to access settings").setLocation(0, 0.5, 1, 0.5)) + this.settingsArea.addChild(textBox) + return; + } + + settingsCommunicator.getModuleSettings(category).forEach(setting=>{ + setting.location.location.y.set(height, 0) + this.settingsArea.addChild(setting) + + height += 0.045+setting.location.size.y.get() + }) + } + + updateLocs(){ + let totalHeight = 0 + + this.settingsArea.children.forEach(e=>{ + e.location.location.y.set(totalHeight, 0) + + totalHeight += e.location.size.y.get()+Math.min(0.045,e.location.size.y.get()) + }) + } + + clickedOpenCategory(category){ + this.updateSettings(category) + this.goToPage(2) + + this.settingsArea.location.scroll.x.set(0, 0) + this.settingsArea.location.scroll.y.set(0, 0) + } +} + +module.exports = { + class: new SettingsRenderer() +}
\ No newline at end of file diff --git a/features/settings/metadata.json b/features/settings/metadata.json new file mode 100644 index 0000000..8f2ace4 --- /dev/null +++ b/features/settings/metadata.json @@ -0,0 +1,8 @@ +{ + "name": "Settings", + "description": "Adds a settings gui with toggles for all the modules, also renders each individual module's settings", + "isHidden": true, + "isTogglable": false, + "defaultEnabled": true, + "sortA": 0 +}
\ No newline at end of file diff --git a/features/settings/settingThings/button.js b/features/settings/settingThings/button.js new file mode 100644 index 0000000..77ba4b8 --- /dev/null +++ b/features/settings/settingThings/button.js @@ -0,0 +1,18 @@ +import SoopyMouseClickEvent from "../../../../guimanager/EventListener/SoopyMouseClickEvent"; +import ButtonWithArrow from "../../../../guimanager/GuiElement/ButtonWithArrow"; +import SettingBase from "./settingBase"; + +class ButtonSetting extends SettingBase { + constructor(name, description, settingId, module, buttonText, buttonFunction, defaultValue=null){ + super(name, description, defaultValue, settingId, module) + + this.buttonObject = new ButtonWithArrow().setLocation(0, 0.3, 0.8, 0.4).setText("§0"+buttonText) + this.settingObject.addChild(this.buttonObject) + + this.buttonObject.addEvent(new SoopyMouseClickEvent().setHandler(()=>{ + buttonFunction.call(this) + })) + } +} + +export default ButtonSetting
\ No newline at end of file diff --git a/features/settings/settingThings/location.js b/features/settings/settingThings/location.js new file mode 100644 index 0000000..69d1a43 --- /dev/null +++ b/features/settings/settingThings/location.js @@ -0,0 +1,332 @@ +import { SoopyGui } from "../../../../guimanager" +import SoopyBoxElement from "../../../../guimanager/GuiElement/SoopyBoxElement" +import SoopyTextElement from "../../../../guimanager/GuiElement/SoopyTextElement" +import ButtonSetting from "./button" +import BoxWithText from "../../../../guimanager/GuiElement/BoxWithText" +import ButtonWithArrow from "../../../../guimanager/GuiElement/ButtonWithArrow" +import SoopyMouseClickEvent from "../../../../guimanager/EventListener/SoopyMouseClickEvent" +import NumberTextBox from "../../../../guimanager/GuiElement/NumberTextBox" +import SoopyContentChangeEvent from "../../../../guimanager/EventListener/SoopyContentChangeEvent" + +let allLocations = [] + +class LocationSetting extends ButtonSetting { + constructor(name, description, settingId, module, defaultLocation){ + super(name, description, settingId, module, "Edit Position", this.editPosition, defaultLocation) + + this.x = this.getValue()[0] + this.y = this.getValue()[1] + this.scale = this.getValue()[2] + this.shadowType = this.getValue()[3] //0-none, 1-vanilla, 2-border + + this.editTempTextV = undefined + + this.dragging = false + this.dragOffset = [0, 0] + this.resisizing = false + this.resizePoint = 0 + this.resizeInitialPos=[0, 0, 0, 0, 0, 0] + + this.parent = undefined + + this.soopyGui = new SoopyGui() + this.soopyGui._renderBackground = ()=>{} //remove background darkening + + this.elmSettings = new SoopyBoxElement().setLocation(0, 0, 0.25, 0.25) + + let scaleText = new SoopyTextElement().setText("&0Scale: ").setLocation(3, 0.025, 1, 0.15) + scaleText.location.location.setRelative(false, true) + scaleText.centeredX = false + this.elmSettings.addChild(scaleText) + + this.scaleInput = new NumberTextBox().setText(this.scale.toFixed(2)).setLocation(Renderer.getStringWidth("Scale: ")+3, 0.025, -(Renderer.getStringWidth("Scale: ")+6), 0.15) + this.scaleInput.location.location.setRelative(false, true) + this.scaleInput.location.size.setRelative(false, true) + this.elmSettings.addChild(this.scaleInput) + this.scaleInput.text.addEvent(new SoopyContentChangeEvent().setHandler((newVal, oldVal, resetFun)=>{ + try{ + newVal = parseFloat(newVal) + if(!isNaN(newVal)){ + this.scale = newVal + this._updateValue() + } + }catch(e){} + })) + this.lastScaleRender = this.scale.toFixed(2) + + let xText = new SoopyTextElement().setText("&0X: ").setLocation(3, 0.225, 1, 0.15) + xText.location.location.setRelative(false, true) + xText.centeredX = false + this.elmSettings.addChild(xText) + this.xInput = new NumberTextBox().setText(this.x.toFixed(0)).setLocation(Renderer.getStringWidth("X: ")+3, 0.225, -(Renderer.getStringWidth("X: ")+6), 0.15) + this.xInput.location.location.setRelative(false, true) + this.xInput.location.size.setRelative(false, true) + this.elmSettings.addChild(this.xInput) + this.xInput.text.addEvent(new SoopyContentChangeEvent().setHandler((newVal, oldVal, resetFun)=>{ + try{ + newVal = parseFloat(newVal) + if(!isNaN(newVal)){ + this.x = newVal + this._updateValue() + } + }catch(e){} + })) + this.lastXRender = this.x.toFixed(0) + + let yText = new SoopyTextElement().setText("&0Y: ").setLocation(3, 0.425, 1, 0.15) + yText.location.location.setRelative(false, true) + yText.centeredX = false + this.elmSettings.addChild(yText) + this.yInput = new NumberTextBox().setText(this.y.toFixed(0)).setLocation(Renderer.getStringWidth("Y: ")+3, 0.425, -(Renderer.getStringWidth("Y: ")+6), 0.15) + this.yInput.location.location.setRelative(false, true) + this.yInput.location.size.setRelative(false, true) + this.elmSettings.addChild(this.yInput) + this.yInput.text.addEvent(new SoopyContentChangeEvent().setHandler((newVal, oldVal, resetFun)=>{ + try{ + newVal = parseFloat(newVal) + if(!isNaN(newVal)){ + this.y = newVal + this._updateValue() + } + }catch(e){} + })) + this.lastYRender = this.y.toFixed(0) + + this.soopyGui.element.addChild(this.elmSettings) + + let button = new ButtonWithArrow().setText("&0Reset").setLocation(0.125, 0.625, 0.75, 0.15) + button.addEvent(new SoopyMouseClickEvent().setHandler(()=>{ + this.x = defaultLocation[0] + this.y = defaultLocation[1] + this.scale = defaultLocation[2] + this.shadowType = defaultLocation[3] + })) + this.elmSettings.addChild(button) + + let button2 = new ButtonWithArrow().setText("&0Back").setLocation(0.125, 0.825, 0.75, 0.15) + button2.addEvent(new SoopyMouseClickEvent().setHandler(()=>{ + this.soopyGui.close() + this.guiObject.main.ctGui.open() + })) + this.elmSettings.addChild(button2) + + this.editGui = this.soopyGui.ctGui + + this.editGui.registerDraw((mouseX, mouseY, partialTicks)=>{ + this.renderGui(mouseX, mouseY) + this.soopyGui._render(mouseX, mouseY, partialTicks) + }) + this.editGui.registerClicked((mouseX, mouseY, button)=>{ + this.clicked(mouseX, mouseY) + this.soopyGui._onClick(mouseX, mouseY, button) + }) + this.editGui.registerMouseReleased((mouseX, mouseY)=>{ + this.released(mouseX, mouseY) + }) + + allLocations.push(this) + } + + requires(toggleSetting){ + this.requiresO = toggleSetting + + toggleSetting.toggleObject.addEvent(new SoopyContentChangeEvent().setHandler((newVal, oldVal, resetFun)=>{ + if(newVal){ + this.guiObject.location.size.y.set(0.2, 500) + }else{ + this.guiObject.location.size.y.set(0, 500) + } + })) + let newVal = this.requiresO.getValue() + if(!newVal){ + this.guiObject.location.size.y.set(0, 0) + } + + return this + } + + _updateValue(){ + this.setValue([this.x, this.y, this.scale, this.shadowType]) + } + + editTempText(text){ + this.editTempTextV = text + return this; + } + + setParent(parent){ + this.parent = parent + } + + editPosition(){ + this.guiObject.main.ctGui.close() + + this.soopyGui.open() + } + + clicked(mouseX, mouseY){ + let width = this.getWidth() + let height = 9*this.parent.getText()[0].length + + let locations = [[this.x, this.y], [this.x+width*this.scale, this.y], [this.x, this.y+height*this.scale], [this.x+width*this.scale, this.y+height*this.scale]] + + locations.forEach((loc, i)=>{ + if(mouseX >= loc[0]-1*Math.max(1, this.scale) && mouseX <= loc[0]+1*Math.max(1, this.scale) + && mouseY >= loc[1]-1*Math.max(1, this.scale) && mouseY <= loc[1]+1*Math.max(1, this.scale)){ + this.resisizing= true + this.resizePoint = i + this.resizeInitialPos = [mouseX, mouseY, this.x, this.y, width*this.scale, height*this.scale] + } + }) + if(this.resisizing) return; + + if(mouseX > this.x && mouseX < this.x+width*this.scale + && mouseY>this.y && mouseY<this.y+height*this.scale){ + this.dragging = true; + this.dragOffset = [this.x-mouseX, this.y-mouseY] + } + } + released(mouseX, mouseY){ + this.updateLocation(mouseX, mouseY) + this.dragging = false + this.resisizing = false + + this._updateValue() + } + + getWidth(){ + return Math.max(...(this.parent.getText()[0].map(a=>Renderer.getStringWidth(ChatLib.removeFormatting(a))))) + } + + updateLocation(mouseX, mouseY, drawCollidingBox){ + let width = this.getWidth() + let height = 9*this.parent.getText()[0].length + + if(this.dragging){ + this.x = mouseX+this.dragOffset[0] + this.y = mouseY+this.dragOffset[1] + + let snapPoints = [] + allLocations.forEach(loc=>{ + if(loc === this) return; + snapPoints.push([loc.x, loc.y]) + snapPoints.push([loc.x+loc.getWidth()*loc.scale, loc.y]) + snapPoints.push([loc.x+loc.getWidth()*loc.scale, loc.y+height*loc.scale]) + snapPoints.push([loc.x, loc.y+height*loc.scale]) + }) + + snapPoints.forEach(point=>{ + //top left + if(Math.abs(this.x-point[0]) < 5 && Math.abs(this.y-point[1]) < 5){ + this.x = point[0] + this.y = point[1] + } + + //top right + if(Math.abs(this.x+width*this.scale-point[0]) < 5 && Math.abs(this.y-point[1]) < 5){ + this.x = point[0]-width*this.scale + this.y = point[1] + } + + //bottom left + if(Math.abs(this.x-point[0]) < 5 && Math.abs(this.y+height*this.scale-point[1]) < 5){ + this.x = point[0] + this.y = point[1]-height*this.scale + } + + //bottom right + if(Math.abs(this.x+width*this.scale-point[0]) < 5 && Math.abs(this.y+height*this.scale-point[1]) < 5){ + this.x = point[0]-width*this.scale + this.y = point[1]-height*this.scale + } + }) + } + if(this.resisizing){ + if(this.resizePoint === 3){ + this.scale=(mouseX-this.x)/width + this.scale = Math.max(0.25, this.scale) + } + if(this.resizePoint === 1){ + + let [oMouseX, oMouseY, oX, oY, ow, oh] = this.resizeInitialPos + + this.scale=(mouseX-this.x)/width + this.scale = Math.max(0.25, this.scale) + this.y=oY+oh-height*this.scale + } + if(this.resizePoint===0){ + let [oMouseX, oMouseY, oX, oY, ow, oh] = this.resizeInitialPos + + this.scale=(oX+ow-mouseX)/width + this.scale = Math.max(0.25, this.scale) + this.x=oX+ow-width*this.scale + this.y=oY+oh-height*this.scale + } + if(this.resizePoint === 2){ + let [oMouseX, oMouseY, oX, oY, ow, oh] = this.resizeInitialPos + + this.scale=(oX+ow-mouseX)/width + this.scale = Math.max(0.25, this.scale) + this.x=oX+ow-width*this.scale + } + } + } + + renderGui(mouseX, mouseY){ + + if(this.parent){ + this.parent.editTempTextV = this.editTempTextV + this.parent.editTempTimeV = Date.now() + + this.parent.tempDisableTime = Date.now() + this.parent.renderRaw() + } + + let width = this.getWidth() + let height = 9*this.parent.getText()[0].length + + this.updateLocation(mouseX, mouseY, true) + + this.renderBox(true) + + if(this.x+width*this.scale/2 > Renderer.screen.getWidth()/2){ + this.elmSettings.location.location.x.set(Math.min(Math.max(this.x/Renderer.screen.getWidth()-0.25-0.03, 0.02), 0.73)) + }else{ + this.elmSettings.location.location.x.set(Math.min(Math.max((this.x+width*this.scale)/Renderer.screen.getWidth()+0.03, 0.02), 0.73)) + } + this.elmSettings.location.location.y.set(Math.min(Math.max((this.y+height*this.scale/2)/Renderer.screen.getHeight() - this.elmSettings.location.size.y.get()/2, 0.02), 0.73)) + + + if(this.lastScaleRender !== this.scale.toFixed(2) && !this.scaleInput.text.selected){ + this.lastScaleRender = this.scale.toFixed(2) + this.scaleInput.setText(this.scale.toFixed(2)) + } + if(this.lastXRender !== this.x.toFixed(0) && !this.xInput.text.selected){ + this.lastXRender = this.x.toFixed(0) + this.xInput.setText(this.x.toFixed(0)) + } + if(this.lastYRender !== this.y.toFixed(0) && !this.yInput.text.selected){ + this.lastYRender = this.y.toFixed(0) + this.yInput.setText(this.y.toFixed(0)) + } + } + + renderBox(drawHandles){ + let width = this.getWidth() + let height = 9*this.parent.getText()[0].length + + Renderer.drawRect(Renderer.color(255, 255, 255), this.x, this.y, width*this.scale, 1) + Renderer.drawRect(Renderer.color(255, 255, 255), this.x, this.y, 1, height*this.scale) + Renderer.drawRect(Renderer.color(255, 255, 255), this.x, this.y+height*this.scale, width*this.scale, 1) + Renderer.drawRect(Renderer.color(255, 255, 255), this.x+width*this.scale, this.y, 1, height*this.scale) + + if(drawHandles){ + Renderer.drawRect(Renderer.color(255, 255, 255), this.x-1*Math.max(1, this.scale)+width*this.scale, this.y-1*Math.max(1, this.scale), 2*Math.max(1, this.scale)+1, 2*Math.max(1, this.scale)+1) + Renderer.drawRect(Renderer.color(255, 255, 255), this.x-1*Math.max(1, this.scale), this.y-1*Math.max(1, this.scale)+height*this.scale, 2*Math.max(1, this.scale)+1, 2*Math.max(1, this.scale)+1) + Renderer.drawRect(Renderer.color(255, 255, 255), this.x-1*Math.max(1, this.scale)+width*this.scale, this.y-1*Math.max(1, this.scale)+height*this.scale, 2*Math.max(1, this.scale)+1, 2*Math.max(1, this.scale)+1) + Renderer.drawRect(Renderer.color(255, 255, 255), this.x-1*Math.max(1, this.scale), this.y-1*Math.max(1, this.scale), 2*Math.max(1, this.scale)+1, 2*Math.max(1, this.scale)+1) + } + } +} + +export default LocationSetting
\ No newline at end of file diff --git a/features/settings/settingThings/settingBase.js b/features/settings/settingThings/settingBase.js new file mode 100644 index 0000000..fbee5bf --- /dev/null +++ b/features/settings/settingThings/settingBase.js @@ -0,0 +1,106 @@ +import SoopyContentChangeEvent from "../../../../guimanager/EventListener/SoopyContentChangeEvent"; +import BoxWithTextAndDescription from "../../../../guimanager/GuiElement/BoxWithTextAndDescription" +import SoopyGuiElement from "../../../../guimanager/GuiElement/SoopyGuiElement"; +import settingsCommunicator from "../settingsCommunicator"; + +class SettingBase { + constructor(name, description, defaultVal, settingId, module){ + this.name = name; + this.description = description; + this.defaultVal = defaultVal; + this.settingId = settingId + this.module = module + this.moduleId = module.getId() + + this.val = defaultVal; + + this.guiObject = new BoxWithTextAndDescription().setDesc("§0"+this.description).setText("§0"+this.name).setLocation(0, 0, 1, 0.175) + + this.settingObject = new SoopyGuiElement().setLocation(0.8, 0, 0.2, 1) + + this.guiObject.addChild(this.settingObject) + + settingsCommunicator.addSetting(this.moduleId, settingId, this.getGuiObject()) + + if(!module.FeatureManager.featureSettingsData[this.moduleId]){ + module.FeatureManager.featureSettingsData[this.moduleId] = {} + } + if(!module.FeatureManager.featureSettingsData[this.moduleId].subSettings)module.FeatureManager.featureSettingsData[this.moduleId].subSettings = {} + if(!module.FeatureManager.featureSettingsData[this.moduleId].subSettings[settingId]){ + module.FeatureManager.featureSettingsData[this.moduleId].subSettings[settingId] = { + value: this.getDefaultValue(), + temp_val: this.getDefaultValue() + } + + module.FeatureManager.featureSettingsDataLastUpdated = true + } + let temp_val_temp =module.FeatureManager.featureSettingsData[this.moduleId].subSettings[settingId].temp_val + this.setValue(module.FeatureManager.featureSettingsData[this.moduleId].subSettings[settingId].value) + this.temp_val = temp_val_temp + + this.requiresO = undefined + } + + getValue(){ + return this.val; + } + + setValue(val){ + this.val = val; + + if(!this.requiresO || this.requiresO.getValue()){ + this.temp_val = val + } + + if(this.module.FeatureManager.featureSettingsData[this.moduleId].subSettings[this.settingId].value !== val){ + this.module.FeatureManager.featureSettingsData[this.moduleId].subSettings[this.settingId].value = val + + this.module.FeatureManager.featureSettingsDataLastUpdated = true + } + if(this.module.FeatureManager.featureSettingsData[this.moduleId].subSettings[this.settingId].temp_val !== this.temp_val){ + this.module.FeatureManager.featureSettingsData[this.moduleId].subSettings[this.settingId].temp_val = this.temp_val + + this.module.FeatureManager.featureSettingsDataLastUpdated = true + } + } + + getName(){ + return this.name; + } + + getDescription(){ + return this.description; + } + + getDefaultValue(){ + return this.defaultVal; + } + + getGuiObject(){ + return this.guiObject; + } + + requires(toggleSetting){ + this.requiresO = toggleSetting + + toggleSetting.toggleObject.addEvent(new SoopyContentChangeEvent().setHandler((newVal, oldVal, resetFun)=>{ + if(newVal){ + this.guiObject.location.size.y.set(0.2, 500) + }else{ + this.guiObject.location.size.y.set(0, 500) + } + })) + let newVal = this.requiresO.getValue() + if(!newVal){ + this.guiObject.location.size.y.set(0, 0) + } + + return this + } + + delete(){ + settingsCommunicator.removeSetting(this.module, this.settingId) + } +} + +export default SettingBase
\ No newline at end of file diff --git a/features/settings/settingThings/textSetting.js b/features/settings/settingThings/textSetting.js new file mode 100644 index 0000000..4960461 --- /dev/null +++ b/features/settings/settingThings/textSetting.js @@ -0,0 +1,33 @@ + +import SoopyContentChangeEvent from "../../../../guimanager/EventListener/SoopyContentChangeEvent"; +import TextBox from "../../../../guimanager/GuiElement/TextBox"; +import PasswordInput from "../../../../guimanager/GuiElement/PasswordInput" +import SettingBase from "./settingBase"; + +class TextSetting extends SettingBase { + constructor(name, description, defaultVal, settingId, module, placeholder, isSecret){ + super(name, description, defaultVal, settingId, module) + + this.textObject = (isSecret?new PasswordInput():new TextBox()).setLocation(0, 0.2, 0.9, 0.6).setText(this.getValue()).setPlaceholder(placeholder) + this.settingObject.addChild(this.textObject) + + this.settingObject.setLocation(0.6, 0, 0.4, 1) + this.guiObject.text.setLocation(0, 0, 0.6, 0.6) + this.guiObject.description.setLocation(0, 0.6, 0.55, 0.4) + + this.textObject.addEvent(new SoopyContentChangeEvent().setHandler((newVal, oldVal, resetFun)=>{ + this.setValue(newVal) + })) + + } + + setValue(newVal){ + super.setValue(newVal) + + this.textObject.setText(newVal) + + return this + } +} + +export default TextSetting
\ No newline at end of file diff --git a/features/settings/settingThings/toggle.js b/features/settings/settingThings/toggle.js new file mode 100644 index 0000000..d839b8f --- /dev/null +++ b/features/settings/settingThings/toggle.js @@ -0,0 +1,58 @@ +import Enum from "../../../../guimanager/Enum"; +import SoopyContentChangeEvent from "../../../../guimanager/EventListener/SoopyContentChangeEvent"; +import Toggle from "../../../../guimanager/GuiElement/Toggle"; +import SettingBase from "./settingBase"; + +class ToggleSetting extends SettingBase { + constructor(name, description, defaultVal, settingId, module){ + super(name, description, defaultVal, settingId, module) + + this.toggleObject = new Toggle().setLocation(0, 0.3, 0.8, 0.4).setValue(this.getValue()) + this.settingObject.addChild(this.toggleObject) + + this.toggleObject.addEvent(new SoopyContentChangeEvent().setHandler((newVal, oldVal, resetFun)=>{ + this.setValue(newVal) + })) + + } + + setValue(newVal){ + super.setValue(newVal) + + this.toggleObject.setValue(newVal) + + return this + } + + requires(toggleSetting){ + this.requiresO = toggleSetting + + toggleSetting.toggleObject.addEvent(new SoopyContentChangeEvent().setHandler((newVal, oldVal, resetFun)=>{ + if(newVal){ + this.setValue(this.temp_val) + + this.toggleObject.triggerEvent(Enum.EVENT.CONTENT_CHANGE, [this.temp_val, false, ()=>{}]) + + this.guiObject.location.size.y.set(0.2, 500) + }else{ + this.temp_val = this.getValue() + this.setValue(false) + + this.toggleObject.triggerEvent(Enum.EVENT.CONTENT_CHANGE, [false, this.temp_val, ()=>{}]) + + this.guiObject.location.size.y.set(0, 500) + } + })) + let newVal = this.requiresO.getValue() + if(!newVal){ + let temp_val = this.temp_val + this.setValue(false) + this.temp_val = temp_val + this.guiObject.location.size.y.set(0, 0) + } + + return this + } +} + +export default ToggleSetting
\ No newline at end of file diff --git a/features/settings/settingsCommunicator.js b/features/settings/settingsCommunicator.js new file mode 100644 index 0000000..b54b1c1 --- /dev/null +++ b/features/settings/settingsCommunicator.js @@ -0,0 +1,29 @@ +//So features can add settings by adding to this class, then the gui will load data from this class +//this makes it so i can add settings before the settings gui is loaded +//and so that settings gui can still be dynamicly reloaded and not break things + +class SettingsCommunicator { + constructor(){ + this.settings = {} + } + + addSetting(module, settingID, settingObject){ + if(!this.settings[module]) this.settings[module] = {} + + this.settings[module][settingID] = settingObject + } + removeSetting(module, settingID){ + if(!this.settings[module]) return; + delete this.settings[module][settingID] + } + getSetting(module, settingID){ + return this.settings[module][settingID] + } + getModuleSettings(module){ + return Object.values(this.settings[module] || []) + } +} + +const settingsCommunicator = new SettingsCommunicator() + +export default settingsCommunicator
\ No newline at end of file diff --git a/features/slayers/index.js b/features/slayers/index.js new file mode 100644 index 0000000..3599996 --- /dev/null +++ b/features/slayers/index.js @@ -0,0 +1,359 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +import Feature from "../../featureClass/class"; +import { numberWithCommas } from "../../utils/numberUtils"; +import { drawBoxAtBlock, drawBoxAtEntity, drawFilledBox, drawLine } from "../../utils/renderUtils"; +import HudTextElement from "../hud/HudTextElement"; +import LocationSetting from "../settings/settingThings/location"; +import ToggleSetting from "../settings/settingThings/toggle"; + +class Slayers extends Feature { + constructor() { + super() + } + + onEnable(){ + this.initVariables() + + this.expOnKill = new ToggleSetting("Show slayer exp on boss kill", "Says your slayer exp in chat when you kill a boss", true, "slayer_xp", this) + this.slainAlert = new ToggleSetting("Show boss slain alert", "This helps you to not kill mobs for ages with an inactive quest", true, "boss_slain_alert", this) + this.spawnAlert = new ToggleSetting("Show boss spawned alert", "This helps you to not miss your boss when you spawn it", true, "boss_spawn_alert", this) + + + this.boxAroundEmanBoss = new ToggleSetting("Box around enderman slayer boss", "This helps to know what boss it yours", true, "eman_box", this) + this.boxToEmanBeacon = new ToggleSetting("Box and line to the enderman beacon", "This will help to find the beacon when the boss throws it", true, "eman_beacon", this) + this.emanBeaconDinkDonk = new ToggleSetting("DinkDonk when beacon is spawned", "This will help to notice when the beacon is spawned", true, "eman_beacon_dinkdink", this) + this.emanEyeThings = new ToggleSetting("Put box around the enderman eye things", "This will help to find them", true, "eman_eye_thing", this) + this.emanHpGuiElement = new ToggleSetting("Render the enderman hp on your screen", "This will help you to know what stage u are in ect", true, "eman_hp", this) + + this.emanHpElement = new HudTextElement() + .setToggleSetting(this.emanHpGuiElement) + .setLocationSetting(new LocationSetting("Eman Hp Location", "Allows you to edit the location of the enderman hp", "eman_location", this, [10, 50, 1, 1]) + .requires(this.emanHpGuiElement) + .editTempText("&6Enderman&7> &f&l30 Hits")) + this.hudElements.push(this.emanHpElement) + + this.slayerExp = {} + this.slayerExpLoaded = false + + this.lastSlayerType = "" + this.lastSlayerExp = 0 + this.registerChat("&r &r&a&lSLAYER QUEST COMPLETE!&r",(e)=>{ + this.slayerExp[this.lastSlayerType] = this.lastSlayerExp + (this.slayerExp[this.lastSlayerType] || 0) + if(this.expOnKill.getValue()){ + cancel(e) + ChatLib.chat("&r &r&a&lSLAYER QUEST COMPLETE!&r") + ChatLib.chat("&r &r&aYou have &d" + numberWithCommas(this.slayerExp[this.lastSlayerType]) + " " + this.lastSlayerType + " XP&r&7!&r") + ChatLib.chat("&r &r&aYou have &d" + numberWithCommas(Object.values(this.slayerExp).reduce((a, t)=>t+a, 0)) + " total XP&r&7!&r") + } + }) + + this.bossSlainMessage = false + this.bossSpawnedMessage = false + this.lastBossNotSpawnedTime = 0 + + this.registerEvent("renderOverlay", this.renderOverlay) + + + 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.todoE = [] + this.beaconPoints = {} + this.beaconE = [] + this.deadE = [] + this.beaconLocations = {} + this.eyeE = [] + this.todoE2 = [] + this.emanBoss = undefined + this.nextIsBoss = 0 + + this.registerForge(net.minecraftforge.event.entity.EntityJoinWorldEvent, this.entityJoinWorldEvent) + this.registerForge(net.minecraftforge.event.entity.living.LivingAttackEvent, this.entityAttackEvent) //TODO: Use CT event when ct 2.0 because they fixed + this.registerEvent("tick", this.tick) + this.registerEvent("renderWorld", this.renderWorld) + this.registerEvent("worldLoad", this.worldLoad) + this.registerEvent("renderOverlay", this.renderHud) + } + + renderHud(){ + for(let element of this.hudElements){ + element.render() + } + } + + worldLoad(){ + this.todoE = [] + this.beaconPoints = {} + this.beaconE = [] + this.deadE = [] + this.todoE2 = [] + this.beaconLocations = {} + this.eyeE = [] + this.emanBoss = undefined + } + + entityAttackEvent(event){ + if(event.source.func_76346_g() === Player.getPlayer()){ + if(event.entity instanceof net.minecraft.entity.monster.EntityEnderman){ + World.getAllEntitiesOfType(net.minecraft.entity.item.EntityArmorStand).forEach(e=>{ + if(e.getName().includes("Voidgloom Seraph")){ + //if distance from e to event.entity < 5 + if((e.getX() - event.entity.field_70165_t)**2 + (e.getY() - event.entity.field_70163_u)**2 + (e.getZ() - event.entity.field_70161_v)**2 < 25){ + this.emanBoss = e + } + } + }) + } + } + } + + renderWorld(ticks){ + Object.values(this.beaconPoints).forEach(line=>{ + let lastPoint = undefined + line.forEach(p=>{ + if(lastPoint){ + drawLine(lastPoint[0], lastPoint[1], lastPoint[2], p[0], p[1], p[2], 0, 0, 255, 3) + } + lastPoint = p + }) + }) + + this.eyeE.forEach(e=>{ + let x = e.getX() + ((e.getX()-e.getLastX())*ticks) + let y = e.getY() + ((e.getY()-e.getLastY())*ticks) + let z = e.getZ() + ((e.getZ()-e.getLastZ())*ticks) + + drawBoxAtBlock(x-0.5, y+0.7, z-0.5, 255, 0, 0) + }) + + if(this.emanBoss) drawBoxAtEntity(this.emanBoss, 0, 255, 0, 1, -3, ticks, 4, false) + + Object.values(this.beaconLocations).forEach(loc=>{ + drawFilledBox(loc[0]+0.5, loc[1], loc[2]+0.5, 1.01, 1.01, 0, 0, 1, 1, true) + }) + } + + entityJoinWorldEvent(event){ + this.todoE2.push(event.entity) + } + + tick(){ + this.bossSlainMessage = false + let dis1 = false + Scoreboard.getLines().forEach((line, i) => { + if(ChatLib.removeFormatting(line.getName()).includes("Slayer Quest")){ + let slayerInfo = ChatLib.removeFormatting(Scoreboard.getLines()[i-1].getName().replace(/§/g,"&")) + let levelString = slayerInfo.split(" ").pop().trim() + let slayerLevelToExp = { + "I": 5, + "II": 25, + "III": 100, + "IV": 500, + "V": 1500 + } + this.lastSlayerExp = slayerLevelToExp[levelString] + let slayerStrToType = { + "revenant": "zombie", + "tarantula": "spider", + "sven": "wolf", + "voidgloom":"enderman" + } + this.lastSlayerType = slayerStrToType[slayerInfo.split(" ")[0].toLowerCase()] + //slayerExp[lastSlayerType] += lastSlayerExp + } + if (line.getName().includes('Boss slain!')) { + this.bossSlainMessage = true + } + + if (line.getName().includes('Slay the boss!')) { + + if(!this.bossSpawnedMessage && !this.emanBoss){ + this.nextIsBoss = Date.now() + } + + dis1 = true + this.bossSpawnedMessage = true + } + }) + if (!dis1) { + this.lastBossNotSpawnedTime = Date.now() + this.bossSpawnedMessage = false + } + + + this.todoE.forEach(e=>{ + try{ + if(e instanceof net.minecraft.entity.item.EntityArmorStand && e.func_71124_b(4)){ + if(e.func_71124_b(4).func_82833_r() === "Beacon"){ + + let closestEIsGaming = false + let closestDist = Infinity + World.getAllEntitiesOfType(net.minecraft.entity.item.EntityArmorStand).forEach(e2=>{ + if(e2.getName().includes("Voidgloom Seraph")){ + if((e2.getX() - e.field_70165_t)**2 + (e2.getY() - e.field_70163_u)**2 + (e2.getZ() - e.field_70161_v)**2 < closestDist){ + closestDist = (e2.getX() - e.field_70165_t)**2 + (e2.getY() - e.field_70163_u)**2 + (e2.getZ() - e.field_70161_v)**2 + closestEIsGaming = this.emanBoss?e2.getUUID().toString()===this.emanBoss.getUUID().toString():false + } + } + }) + if(closestEIsGaming){ + this.beaconE.push(e) + } + } + if(e.func_71124_b(4).func_82833_r().startsWith("§a")){ + + let closestEIsGaming = false + let closestDist = Infinity + World.getAllEntitiesOfType(net.minecraft.entity.item.EntityArmorStand).forEach(e2=>{ + if(e2.getName().includes("Voidgloom Seraph")){ + if((e2.getX() - e.field_70165_t)**2 + (e2.getY() - e.field_70163_u)**2 + (e2.getZ() - e.field_70161_v)**2 < closestDist){ + closestDist = (e2.getX() - e.field_70165_t)**2 + (e2.getY() - e.field_70163_u)**2 + (e2.getZ() - e.field_70161_v)**2 + closestEIsGaming = this.emanBoss?e2.getUUID().toString()===this.emanBoss.getUUID().toString():false + } + } + }) + + if(closestEIsGaming && new Item(e.func_71124_b(4)).getNBT().getCompoundTag("tag").getCompoundTag("SkullOwner").getCompoundTag("Properties").getRawNBT().func_150295_c("textures", 10).func_150305_b(0).func_74779_i("Value") === "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWIwNzU5NGUyZGYyNzM5MjFhNzdjMTAxZDBiZmRmYTExMTVhYmVkNWI5YjIwMjllYjQ5NmNlYmE5YmRiYjRiMyJ9fX0="){ + this.eyeE.push(new Entity(e)) + } + // console.log(":" + new Item(e.func_71124_b(4)).getNBT().getCompoundTag("tag").getCompoundTag("SkullOwner").getCompoundTag("Properties").getRawNBT().func_150295_c("textures", 10).func_150305_b(0).func_74779_i("Value")) + } + } + + if(e.func_95999_t() && e.func_95999_t().includes("Voidgloom Seraph")){ + if(Date.now()-this.nextIsBoss < 3000){ + this.emanBoss = new Entity(e) + this.nextIsBoss = false + } + } + }catch(_){console.log(JSON.stringify(_, undefined, 2))} + }) + this.todoE = this.todoE2 + this.todoE2 = [] + + if(this.emanBoss && this.emanBoss.getEntity().field_70128_L) this.emanBoss = undefined + this.eyeE = this.eyeE.filter(e=>!e.getEntity().field_70128_L) + this.beaconE = this.beaconE.filter((e)=>{ + if(e.field_70128_L){ + this.deadE.push([Date.now(), e.func_110124_au().toString()]) + + let pos = [e.field_70165_t+0.5, e.field_70163_u+0.7, e.field_70161_v+0.5] + //check for a beacon block within 5 blocks of pos + for(let x = pos[0] - 5; x <= pos[0] + 5; x++){ + for(let y = pos[1] - 5; y <= pos[1] + 5; y++){ + for(let z = pos[2] - 5; z <= pos[2] + 5; z++){ + if(World.getBlockAt(Math.floor(x), Math.floor(y), Math.floor(z)).getID() === 138){ + this.beaconLocations[e.func_110124_au().toString()] = [Math.floor(x), Math.floor(y), Math.floor(z)] + } + } + } + } + + // if(!this.beaconLocations[e.func_110124_au().toString()]){ + // console.log("Diddnt find beacon wtf?????") + // } + + return false + } + return true + }) + + this.beaconE.forEach((e)=>{ + if(!this.beaconPoints[e.func_110124_au().toString()])this.beaconPoints[e.func_110124_au().toString()] = [] + + this.beaconPoints[e.func_110124_au().toString()].push([e.field_70165_t+0.5, e.field_70163_u+0.7, e.field_70161_v+0.5])//x, y, z + }) + + this.deadE = this.deadE.filter(e=>{ + if(Date.now()-e[0] > 5000){ + delete this.beaconPoints[e[1]] + delete this.beaconLocations[e[1]] + return false + } + + let location = this.beaconLocations[e[1]] + if(!location){ + delete this.beaconPoints[e[1]] + delete this.beaconLocations[e[1]] + return false + } + + if(World.getBlockAt(location[0], location[1], location[2]).getID() === 138){ + Client.showTitle("&cGO TO BEACON!","&c" + (Math.max(0,5000-(Date.now()-e[0]))/1000).toFixed(1) + "s",0,20,10) + World.playSound("note.pling",1,1) + }else{ + delete this.beaconPoints[e[1]] + delete this.beaconLocations[e[1]] + return false + } + return true + }) + + if(this.emanBoss){ + this.emanHpElement.setText("&6Enderman&7> " + this.emanBoss.getName().split("Voidgloom Seraph")[1].trim()) + }else{ + this.emanHpElement.setText("") + } + } + + apiLoad(data, dataType, isSoopyServer, isLatest){ + if(!isSoopyServer || !isLatest) return + if(dataType !== "skyblock") return + + this.slayerExp.zombie = data.data.profiles[data.data.stats.currentProfileId].members[Player.getUUID().replace(/-/g, "")].slayer.zombie.xp + this.slayerExp.spider = data.data.profiles[data.data.stats.currentProfileId].members[Player.getUUID().replace(/-/g, "")].slayer.spider.xp + this.slayerExp.wolf = data.data.profiles[data.data.stats.currentProfileId].members[Player.getUUID().replace(/-/g, "")].slayer.wolf.xp + this.slayerExp.enderman = data.data.profiles[data.data.stats.currentProfileId].members[Player.getUUID().replace(/-/g, "")].slayer.enderman.xp + } + + renderOverlay(){ + if(this.slainAlert.getValue() && this.bossSlainMessage){ + let scale = Renderer.getStringWidth(ChatLib.removeFormatting("BOSS SLAIN"))/(Renderer.screen.getWidth()*0.75) + + Renderer.scale(1/scale, 1/scale) + Renderer.drawString("&4BOSS SLAIN", (Renderer.screen.getWidth()*0.125)*scale, (Renderer.screen.getHeight()/2-9/scale)*scale) + Renderer.scale(1, 1) + } + if(this.spawnAlert.getValue() && this.bossSpawnedMessage && Date.now()-this.lastBossNotSpawnedTime<3000){ + let scale = Renderer.getStringWidth(ChatLib.removeFormatting("BOSS SPAWNED"))/(Renderer.screen.getWidth()*0.75) + + Renderer.scale(1/scale, 1/scale) + Renderer.drawString("&4BOSS SPAWNED", (Renderer.screen.getWidth()*0.125)*scale, (Renderer.screen.getHeight()/2-9/scale)*scale) + Renderer.scale(1, 1) + } + } + + initVariables(){ + this.expOnKill = undefined + this.slainAlert = undefined + this.spawnAlert = undefined + this.slayerExp = undefined + this.slayerExpLoaded = undefined + this.lastSlayerType = undefined + this.lastSlayerExp = undefined + this.bossSpawnedMessage = undefined + this.lastBossNotSpawnedTime = undefined + this.bossSlainMessage = undefined + this.todoE = undefined + this.beaconPoints = undefined + this.beaconE = undefined + this.deadE = undefined + this.beaconLocations = undefined + this.emanBoss = undefined + this.eyeE = undefined + this.nextIsBoss = undefined + this.hudElements = [] + this.todoE2 = undefined + } + + onDisable(){ + this.initVariables() + } +} + +module.exports = { + class: new Slayers() +}
\ No newline at end of file diff --git a/features/slayers/metadata.json b/features/slayers/metadata.json new file mode 100644 index 0000000..b186b29 --- /dev/null +++ b/features/slayers/metadata.json @@ -0,0 +1,8 @@ +{ + "name": "Slayer", + "description": "Slayer features", + "isHidden": false, + "isTogglable": true, + "defaultEnabled": true, + "sortA": 1 +}
\ No newline at end of file diff --git a/features/soopyGui/GuiPage.js b/features/soopyGui/GuiPage.js new file mode 100644 index 0000000..09142d0 --- /dev/null +++ b/features/soopyGui/GuiPage.js @@ -0,0 +1,46 @@ +import SoopyGuiElement from '../../../guimanager/GuiElement/SoopyGuiElement.js'; + +class GuiPage{ + constructor(priority){ + this.currentPageId = 0; + this.priority = priority + + this.soopyGui = require('./index.js').class; + this.name = "" + + this.pages = {} + } + + finaliseLoading(){ + this.soopyGui.addCategory(this); + } + + newPage(){ + this.currentPageId++ + let page = new SoopyGuiElement().setLocation(1*this.currentPageId,0,1,1) + + page._soopyAddonsPageId = this.currentPageId + + this.pages[this.currentPageId] = page + + return page + } + + goToPage(page, anim){ + this.soopyGui.goToPageNum(page, anim) + } + + openSidebarPage(child){ + this.soopyGui.openSidebarPage(child) + } + closeSidebarPage(){ + this.soopyGui.closeSidebarPage() + } + + //Override me :D + onOpen(){ + + } +} + +export default GuiPage;
\ No newline at end of file diff --git a/features/soopyGui/index.js b/features/soopyGui/index.js new file mode 100644 index 0000000..428bbf1 --- /dev/null +++ b/features/soopyGui/index.js @@ -0,0 +1,192 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +import Feature from "../../featureClass/class"; +import * as GuiManager from "../../../guimanager/index.js" +import SoopyGuiElement from "../../../guimanager/GuiElement/SoopyGuiElement"; +import SoopyTextElement from "../../../guimanager/GuiElement/SoopyTextElement"; +import SoopyBoxElement from "../../../guimanager/GuiElement/SoopyBoxElement"; +import TextWithArrow from "../../../guimanager/GuiElement/TextWithArrow"; +import ButtonWithArrow from "../../../guimanager/GuiElement/ButtonWithArrow"; +import SoopyMouseClickEvent from "../../../guimanager/EventListener/SoopyMouseClickEvent"; +import SoopyOpenGuiEvent from "../../../guimanager/EventListener/SoopyOpenGuiEvent"; + + +class SoopyGui extends Feature { + constructor() { + super() + + this.gui = undefined + + this.pages = [] + this.currentPage = 0 + this.backButton = undefined + + this.categoryPage = undefined + this.currCategory = undefined + this.activePages = [] + this.lastClickedOpen = undefined + } + + onEnable(){ + this.gui = new GuiManager.SoopyGui() + + // this.gui.isDebugEnabled = true + + this.gui.setOpenCommand("soopyv2") + + this.mainWindowElement = new SoopyBoxElement().setLocation(0.25, 0.2, 0.5, 0.6) + + this.mainWindowElement.addEvent(new SoopyOpenGuiEvent().setHandler(()=>{this.goToPageNum(0, false)})) + + //############################################################################################### + // Category Page + //############################################################################################### + + this.categoryPage = new SoopyGuiElement().setLocation(0, 0, 1, 1) + + let title = new SoopyTextElement().setText("§0Soopy Addons!").setMaxTextScale(3).setLocation(0.1, 0.05, 0.8, 0.1) + this.categoryPage.addChild(title) + + this.buttonListElm = new SoopyGuiElement().setLocation(0.1, 0.2, 0.8, 0.8).setScrollable(true) + this.categoryPage.addChild(this.buttonListElm) + + //############################################################################################### + // Back button for all second pages + //############################################################################################### + + this.backButton = new TextWithArrow().setText("§0Back").setLocation(0.01, -0.2, 0.1, 0.1).setDirectionRight(false) + let backButtonEvent = new SoopyMouseClickEvent().setHandler(()=>{this.clickedBackButton()}) + this.backButton.addEvent(backButtonEvent) + + this.mainWindowElement.addChild(this.categoryPage) + this.mainWindowElement.addChild(this.backButton) + + this.sidebarPage = new SoopyBoxElement().setLocation(0.3, 0.2, 0.3, 0.6) + // this.sidebarPage.visable = false + + this.gui.element.addChild(this.sidebarPage) + this.gui.element.addChild(this.mainWindowElement) + + this.updateButtons() + } + + addCategory(category){ + this.pages.push(category) + this.sortPages() + + this.updateButtons() + } + + updateButtons(){ + if(!this.buttonListElm) return; + + this.buttonListElm.children = [] + + this.pages.forEach((p, i)=>{ + let settingsButton = new ButtonWithArrow().setText("§0" + p.name).setLocation(0, 0.25*i, 1, 0.2) + settingsButton.addEvent(new SoopyMouseClickEvent().setHandler(()=>{this.clickedOpen(p)})) + this.buttonListElm.addChild(settingsButton) + }) + } + + clickedOpen(category){ + if(!this.lastClickedOpen)this.lastClickedOpen = 0 + if(Date.now()-this.lastClickedOpen < 100) return //Stopping infinite loop where button getting reset causes click event to get fired again + this.lastClickedOpen = Date.now() + + let theParent = this.mainWindowElement.innerObjectPaddingThing || this.mainWindowElement + theParent.children = [] + + this.mainWindowElement.addChild(this.categoryPage) + this.mainWindowElement.addChild(this.backButton) + + this.activePages = category.pages + + Object.values(this.activePages).forEach(p=>{ + this.mainWindowElement.addChild(p) + }) + + this.goToPageNum(1, true) + + category.onOpen() + } + + sortPages(){ + this.pages = this.pages.sort((a, b)=>{ + return b.priority - a.priority + }) + } + + onDisable(){ + this.gui.delete() + + this.gui = undefined + + this.pages = [] + this.currentPage = 0 + this.backButton = undefined + this.activePages = [] + this.currCategory = undefined + this.lastClickedOpen = undefined + } + + clickedBackButton(){ + this.goToPageNum(this.currentPage-1) + } + + goToPage(page, animate=true){ + let pageNum = page._soopyAddonsPageId + + if(pageNum == this.currentPage){ + return + } + + this.currentPage = pageNum + + this.pages.forEach((p)=>{ + Object.values(p.pages).forEach((e, i)=>{ + e.location.location.x.set(i-pageNum+1, animate?1000:0) + }) + }) + this.categoryPage.location.location.x.set(-pageNum, animate?1000:0) + + this.backButton.location.location.y.set(pageNum === 0?-0.2:0, animate?1000:0) + } + goToPageNum(pageNum, animate=true){ + if(pageNum<0) return; + + this.currentPage = pageNum + if(pageNum===0){ + this.currCategory = undefined + this.closeSidebarPage() + } + + this.pages.forEach((p)=>{ + Object.values(p.pages).forEach((e, i)=>{ + e.location.location.x.set(i-pageNum+1, animate?1000:0) + }) + }) + this.categoryPage.location.location.x.set(-pageNum, animate?1000:0) + + this.backButton.location.location.y.set(pageNum === 0?-0.2:0, animate?1000:0) + } + openSidebarPage(child){ + this.sidebarPage.location.location.x.set(0.625, 500) + this.mainWindowElement.location.location.x.set(0.075, 500) + + // this.sidebarPage.visable = true + this.sidebarPage.addChild(child) + } + + closeSidebarPage(){ + this.sidebarPage.location.location.x.set(0.3, 500) + this.mainWindowElement.location.location.x.set(0.25, 500) + + this.sidebarPage.clearChildren() + // this.sidebarPage.visable = false + } +} + +module.exports = { + class: new SoopyGui() +}
\ No newline at end of file diff --git a/features/soopyGui/metadata.json b/features/soopyGui/metadata.json new file mode 100644 index 0000000..8f2ace4 --- /dev/null +++ b/features/soopyGui/metadata.json @@ -0,0 +1,8 @@ +{ + "name": "Settings", + "description": "Adds a settings gui with toggles for all the modules, also renders each individual module's settings", + "isHidden": true, + "isTogglable": false, + "defaultEnabled": true, + "sortA": 0 +}
\ No newline at end of file diff --git a/features/spamHider/index.js b/features/spamHider/index.js new file mode 100644 index 0000000..37c964f --- /dev/null +++ b/features/spamHider/index.js @@ -0,0 +1,175 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +import Feature from "../../featureClass/class"; +import { newSideMessage, setLocation } from "../../../soopyApis"; + +class SpamHider extends Feature { + constructor() { + super() + } + + onEnable(){ + this.initVariables() + + this.hideMessages = [] + this.hideMessagesRexex = [] + this.moveMessages = [] + this.moveMessagesRexex = [] + + this.SpamHiderMessagesRenderer = new SpamHiderMessagesRenderer() + + this.loadSpamMessages() + + this.registerChat("${*}", this.onChat) + + this.registerEvent("renderOverlay", this.renderOverlay) + } + + onChat(e){ + let msg = ChatLib.getChatMessage(e, true).replace(/§/g, "&").replace(/(?:^&r)|(?:&r$)/g, "") + + this.hideMessagesRexex.forEach(regex => { + if(regex.test(msg)){ + cancel(e) + return + } + }) + + this.moveMessagesRexex.forEach(regex => { + if(regex.test(msg)){ + this.SpamHiderMessagesRenderer.addMessage(msg) + cancel(e) + return + } + }) + } + renderOverlay(){ + this.SpamHiderMessagesRenderer.render(100,100,1, 1) + } + + loadSpamMessages(){ + let messages = JSON.parse(FileLib.getUrlContent("http://soopymc.my.to/api/soopyv2/spamHiderMessages.json")) + this.hideMessages = messages.hideMessages + this.moveMessages = messages.moveMessages + + this.hideMessagesRexex = [] + this.hideMessages.forEach(message=>{ + let regex = new RegExp(message.replace(/[\\^$*+?.()|[\]{}]/g, '\$&') + .replace(/\$\{\*\}/g, "(?:.+)")) + this.hideMessagesRexex.push(regex) + }) + + this.moveMessagesRexex = [] + this.moveMessages.forEach(message=>{ + let regex = new RegExp(message.replace(/[\\^$*+?.()|[\]{}]/g, '\$&') + .replace(/\$\{\*\}/g, "(?:.+)")) + + this.moveMessagesRexex.push(regex) + }) + } + + initVariables(){ + this.hideMessages = undefined + this.hideMessagesRexex = undefined + this.moveMessages = undefined + this.moveMessagesRexex = undefined + this.SpamHiderMessagesRenderer = undefined + } + + onDisable(){ + this.initVariables() + } +} + +class SpamHiderMessagesRenderer{ + constructor(){ + this.messages = [] + this.x = 0 //offset from corner, not absolute location + this.y = 0 //offset from corner, not absolute location + this.scale = 1 + this.corner = 2 + + this.lastRender = 0 + } + + addMessage(str){ + this.messages.push([str, Date.now(), this.y]) + } + + render(){ + Renderer.drawString("", -100, -100)//Fixes skytils issue //idk if this is still needed, it was in old code and imma just leave it ig + + let now = Date.now() + let animDiv = (now-this.lastRender) / 1000 + this.lastRender = now + let swidth = Renderer.screen.getWidth() + let sheight = Renderer.screen.getHeight() + + //loop over all messages backwards + for(let i = this.messages.length - 1; i >= 0; i--){ + let message = this.messages[i] + + let [str, time, height] = message + + time = now-time + + let messageWidth = Renderer.getStringWidth(ChatLib.removeFormatting(str)) + + let x = 0; + let y = 0; + if (this.corner === 0) { //top left + x = 20 + this.messages[i][2] = height + (((this.messages.length-i) * -10) - height) * (animDiv * 5) + } + if (this.corner === 1) { //top right + x = swidth - 20 - messageWidth + this.messages[i][2] = height + (((this.messages.length-i) * -10) - height) * (animDiv * 5) + } + if (this.corner === 2) { //bottom right + x = swidth - 20 - messageWidth + this.messages[i][2] = height + (((this.messages.length-i) * 10) - height) * (animDiv * 5) + } + + let animOnOff = 0 + if (time < 500) { + animOnOff = 1 - (time / 500) + } + if (time > 3500) { + animOnOff = ((time - 3500) / 500) + } + + animOnOff *= 90 + animOnOff += 90 + + animOnOff = animOnOff * Math.PI / 180; + + animOnOff = Math.sin(animOnOff) + + animOnOff *= -1 + animOnOff += 1 + + if (this.corner === 0) { //top left + x += ((animOnOff * -1) * (messageWidth + 30)) + y = 30 - (height) + } + if (this.corner === 1) { //top right + x += (animOnOff * (messageWidth + 30)) + y = 30 - (height) + } + if (this.corner === 2) { //bottom right + x += (animOnOff * (messageWidth + 30)) + y = sheight - 30 - (height) + } + + Renderer.drawString(str, x + this.x, y + this.y); + + if (time > 4000) { + this.messages.shift() + } + } + } +} + +module.exports = { + class: new SpamHider() +}
\ No newline at end of file diff --git a/features/spamHider/metadata.json b/features/spamHider/metadata.json new file mode 100644 index 0000000..7e8e2b1 --- /dev/null +++ b/features/spamHider/metadata.json @@ -0,0 +1,8 @@ +{ + "name": "Spam Hider", + "description": "A couple of features to help clean up your chat", + "isHidden": false, + "isTogglable": true, + "defaultEnabled": true, + "sortA": 1 +}
\ No newline at end of file diff --git a/features/stat_next_to_name/index.js b/features/stat_next_to_name/index.js new file mode 100644 index 0000000..b7addb9 --- /dev/null +++ b/features/stat_next_to_name/index.js @@ -0,0 +1,19 @@ +/// <reference types="../../../CTAutocomplete" /> +/// <reference lib="es2015" /> +import Feature from "../../featureClass/class"; + +class StatNextToName extends Feature { + constructor() { + super() + } + + onEnable(){ + } + + onDisable(){ + } +} + +module.exports = { + class: new StatNextToName() +}
\ No newline at end of file diff --git a/features/stat_next_to_name/metadata.json b/features/stat_next_to_name/metadata.json new file mode 100644 index 0000000..cd2f79c --- /dev/null +++ b/features/stat_next_to_name/metadata.json @@ -0,0 +1,8 @@ +{ + "name": "Stat next to name", + "description": "Shows a players skyblock stat next to their name in the world", + "isHidden": false, + "isTogglable": true, + "defaultEnabled": true, + "sortA": 0 +}
\ No newline at end of file |