From 48653ec89538f1650106a5e77463412cad4684c2 Mon Sep 17 00:00:00 2001 From: Soopyboo32 <49228220+Soopyboo32@users.noreply.github.com> Date: Sun, 31 Oct 2021 09:49:42 +0800 Subject: first commit --- class.js | 139 ++++++++ featureClass/class.js | 139 ++++++++ featureClass/featureManager.js | 384 ++++++++++++++++++++ featureClass/forgeEvents.js | 93 +++++ featureManager.js | 384 ++++++++++++++++++++ features/agentlaiThings/hiddenRequirement.js | 8 + features/agentlaiThings/index.js | 194 +++++++++++ features/agentlaiThings/metadata.json | 8 + features/betterGuis/index.js | 197 +++++++++++ features/betterGuis/metadata.json | 8 + features/changeLogGUI/index.js | 210 +++++++++++ features/changeLogGUI/metadata.json | 8 + features/dataLoader/index.js | 128 +++++++ features/dataLoader/metadata.json | 8 + features/dungeonMap/index.js | 299 ++++++++++++++++ features/dungeonMap/metadata.json | 8 + features/dungeonSolvers/index.js | 153 ++++++++ features/dungeonSolvers/metadata.json | 8 + features/events/index.js | 463 +++++++++++++++++++++++++ features/events/metadata.json | 8 + features/featureBase/index.js | 24 ++ features/featureBase/metadata.json | 8 + features/fragBot/index.js | 84 +++++ features/fragBot/metadata.json | 8 + features/friendsGUI/index.js | 154 ++++++++ features/friendsGUI/metadata.json | 8 + features/globalSettings/index.js | 51 +++ features/globalSettings/metadata.json | 8 + features/hud/HudTextElement.js | 77 ++++ features/hud/index.js | 315 +++++++++++++++++ features/hud/metadata.json | 8 + features/improvements/index.js | 36 ++ features/improvements/metadata.json | 8 + features/mining/index.js | 201 +++++++++++ features/mining/metadata.json | 8 + features/settings/index.js | 249 +++++++++++++ features/settings/metadata.json | 8 + features/settings/settingThings/button.js | 18 + features/settings/settingThings/location.js | 332 ++++++++++++++++++ features/settings/settingThings/settingBase.js | 106 ++++++ features/settings/settingThings/textSetting.js | 33 ++ features/settings/settingThings/toggle.js | 58 ++++ features/settings/settingsCommunicator.js | 29 ++ features/slayers/index.js | 359 +++++++++++++++++++ features/slayers/metadata.json | 8 + features/soopyGui/GuiPage.js | 46 +++ features/soopyGui/index.js | 192 ++++++++++ features/soopyGui/metadata.json | 8 + features/spamHider/index.js | 175 ++++++++++ features/spamHider/metadata.json | 8 + features/stat_next_to_name/index.js | 19 + features/stat_next_to_name/metadata.json | 8 + forgeEvents.js | 93 +++++ index.js | 12 + logger.js | 28 ++ metadata.js | 5 + metadata.json | 16 + utils/numberUtils.js | 50 +++ utils/renderLib2d.js | 147 ++++++++ utils/renderUtils.js | 291 ++++++++++++++++ utils/stringUtils.js | 11 + utils/utils.js | 116 +++++++ 62 files changed, 6270 insertions(+) create mode 100644 class.js create mode 100644 featureClass/class.js create mode 100644 featureClass/featureManager.js create mode 100644 featureClass/forgeEvents.js create mode 100644 featureManager.js create mode 100644 features/agentlaiThings/hiddenRequirement.js create mode 100644 features/agentlaiThings/index.js create mode 100644 features/agentlaiThings/metadata.json create mode 100644 features/betterGuis/index.js create mode 100644 features/betterGuis/metadata.json create mode 100644 features/changeLogGUI/index.js create mode 100644 features/changeLogGUI/metadata.json create mode 100644 features/dataLoader/index.js create mode 100644 features/dataLoader/metadata.json create mode 100644 features/dungeonMap/index.js create mode 100644 features/dungeonMap/metadata.json create mode 100644 features/dungeonSolvers/index.js create mode 100644 features/dungeonSolvers/metadata.json create mode 100644 features/events/index.js create mode 100644 features/events/metadata.json create mode 100644 features/featureBase/index.js create mode 100644 features/featureBase/metadata.json create mode 100644 features/fragBot/index.js create mode 100644 features/fragBot/metadata.json create mode 100644 features/friendsGUI/index.js create mode 100644 features/friendsGUI/metadata.json create mode 100644 features/globalSettings/index.js create mode 100644 features/globalSettings/metadata.json create mode 100644 features/hud/HudTextElement.js create mode 100644 features/hud/index.js create mode 100644 features/hud/metadata.json create mode 100644 features/improvements/index.js create mode 100644 features/improvements/metadata.json create mode 100644 features/mining/index.js create mode 100644 features/mining/metadata.json create mode 100644 features/settings/index.js create mode 100644 features/settings/metadata.json create mode 100644 features/settings/settingThings/button.js create mode 100644 features/settings/settingThings/location.js create mode 100644 features/settings/settingThings/settingBase.js create mode 100644 features/settings/settingThings/textSetting.js create mode 100644 features/settings/settingThings/toggle.js create mode 100644 features/settings/settingsCommunicator.js create mode 100644 features/slayers/index.js create mode 100644 features/slayers/metadata.json create mode 100644 features/soopyGui/GuiPage.js create mode 100644 features/soopyGui/index.js create mode 100644 features/soopyGui/metadata.json create mode 100644 features/spamHider/index.js create mode 100644 features/spamHider/metadata.json create mode 100644 features/stat_next_to_name/index.js create mode 100644 features/stat_next_to_name/metadata.json create mode 100644 forgeEvents.js create mode 100644 index.js create mode 100644 logger.js create mode 100644 metadata.js create mode 100644 metadata.json create mode 100644 utils/numberUtils.js create mode 100644 utils/renderLib2d.js create mode 100644 utils/renderUtils.js create mode 100644 utils/stringUtils.js create mode 100644 utils/utils.js diff --git a/class.js b/class.js new file mode 100644 index 0000000..1cfdd8b --- /dev/null +++ b/class.js @@ -0,0 +1,139 @@ +/// + +import logger from "../logger" + +/// + +class Feature { + constructor(){ + this.FeatureManager = undefined + this.events = {} + this.customEvents = {} + this.forgeEvents = {} + this.soopyEvents = {} + + this.id = undefined + + this.enabled = false + } + + setId(id){ + this.id = id + } + getId(){ + return this.id + } + + _onDisable(){ + Object.values(this.events).forEach(e=>this.FeatureManager.unregisterEvent(e)) //calling parent unregister to avoid the set in unregister event + Object.values(this.customEvents).forEach(e=>this.FeatureManager.unregisterCustom(e)) //calling parent unregister to avoid the set in unregister event + + this.onDisable() + + this.events = {} + this.customEvents = {} + this.enabled = false + } + + _onEnable(parent){ + this.FeatureManager = parent + + this.enabled = true + + this.onEnable() + } + + onDisable(){} + onEnable(){} + + registerEvent(event, func){ + let theEvent = this.FeatureManager.registerEvent(event, func, this) + + this.events[theEvent.id] = theEvent + + return theEvent + } + + unregisterEvent(event){ + this.FeatureManager.unregisterEvent(event) + + delete this.events[event.id] + } + registerSoopy(event, func){ + let theEvent = this.FeatureManager.registerSoopy(event, func, this) + + this.soopyEvents[theEvent.id] = theEvent + + return theEvent + } + + unregisterSoopy(event){ + this.FeatureManager.unregisterSoopy(event) + + delete this.soopyEvents[event.id] + } + + registerForge(event, func){ + let theEvent = this.FeatureManager.registerForge(event, func, this) + + this.forgeEvents[theEvent.id] = theEvent + + return theEvent + } + + unregisterForge(event){ + this.FeatureManager.unregisterForge(event) + + delete this.forgeEvents[event.id] + } + + registerChat(criteria, func){ + let theEvent = this.FeatureManager.registerChat(criteria, func, this) + + this.customEvents[theEvent.id] = theEvent + + return theEvent + } + registerStep(isFps, interval, func){ + let theEvent = this.FeatureManager.registerStep(isFps, interval, func, this) + + this.customEvents[theEvent.id] = theEvent + + return theEvent + } + + registerCustom(event, func){ + let theEvent = this.FeatureManager.registerCustom(event, func, this) + + this.customEvents[theEvent.id] = theEvent + + return theEvent + } + + registerCommand(name, func){ + this.FeatureManager.commandFuncs[name] = func + + this.FeatureManager.registerCommand(name, (...args)=>{ + if(this.FeatureManager.commandFuncs[name]){ + this.FeatureManager.commandFuncs[name].call(this, ...(args || [])) + }else{ + ChatLib.chat("&cThis command is not available atm") + } + }, this) + } + unregisterCommand(name){ + delete this.FeatureManager.commandFuncs[name] + } + + unregisterCustom(event){ + this.FeatureManager.unregisterCustom(event) + + delete this.customEvents[event.id] + } + + createCustomEvent(eventId){ + return this.FeatureManager.createCustomEvent(eventId) + } +} + +export default Feature \ No newline at end of file diff --git a/featureClass/class.js b/featureClass/class.js new file mode 100644 index 0000000..1cfdd8b --- /dev/null +++ b/featureClass/class.js @@ -0,0 +1,139 @@ +/// + +import logger from "../logger" + +/// + +class Feature { + constructor(){ + this.FeatureManager = undefined + this.events = {} + this.customEvents = {} + this.forgeEvents = {} + this.soopyEvents = {} + + this.id = undefined + + this.enabled = false + } + + setId(id){ + this.id = id + } + getId(){ + return this.id + } + + _onDisable(){ + Object.values(this.events).forEach(e=>this.FeatureManager.unregisterEvent(e)) //calling parent unregister to avoid the set in unregister event + Object.values(this.customEvents).forEach(e=>this.FeatureManager.unregisterCustom(e)) //calling parent unregister to avoid the set in unregister event + + this.onDisable() + + this.events = {} + this.customEvents = {} + this.enabled = false + } + + _onEnable(parent){ + this.FeatureManager = parent + + this.enabled = true + + this.onEnable() + } + + onDisable(){} + onEnable(){} + + registerEvent(event, func){ + let theEvent = this.FeatureManager.registerEvent(event, func, this) + + this.events[theEvent.id] = theEvent + + return theEvent + } + + unregisterEvent(event){ + this.FeatureManager.unregisterEvent(event) + + delete this.events[event.id] + } + registerSoopy(event, func){ + let theEvent = this.FeatureManager.registerSoopy(event, func, this) + + this.soopyEvents[theEvent.id] = theEvent + + return theEvent + } + + unregisterSoopy(event){ + this.FeatureManager.unregisterSoopy(event) + + delete this.soopyEvents[event.id] + } + + registerForge(event, func){ + let theEvent = this.FeatureManager.registerForge(event, func, this) + + this.forgeEvents[theEvent.id] = theEvent + + return theEvent + } + + unregisterForge(event){ + this.FeatureManager.unregisterForge(event) + + delete this.forgeEvents[event.id] + } + + registerChat(criteria, func){ + let theEvent = this.FeatureManager.registerChat(criteria, func, this) + + this.customEvents[theEvent.id] = theEvent + + return theEvent + } + registerStep(isFps, interval, func){ + let theEvent = this.FeatureManager.registerStep(isFps, interval, func, this) + + this.customEvents[theEvent.id] = theEvent + + return theEvent + } + + registerCustom(event, func){ + let theEvent = this.FeatureManager.registerCustom(event, func, this) + + this.customEvents[theEvent.id] = theEvent + + return theEvent + } + + registerCommand(name, func){ + this.FeatureManager.commandFuncs[name] = func + + this.FeatureManager.registerCommand(name, (...args)=>{ + if(this.FeatureManager.commandFuncs[name]){ + this.FeatureManager.commandFuncs[name].call(this, ...(args || [])) + }else{ + ChatLib.chat("&cThis command is not available atm") + } + }, this) + } + unregisterCommand(name){ + delete this.FeatureManager.commandFuncs[name] + } + + unregisterCustom(event){ + this.FeatureManager.unregisterCustom(event) + + delete this.customEvents[event.id] + } + + createCustomEvent(eventId){ + return this.FeatureManager.createCustomEvent(eventId) + } +} + +export default Feature \ No newline at end of file diff --git a/featureClass/featureManager.js b/featureClass/featureManager.js new file mode 100644 index 0000000..92b9cd8 --- /dev/null +++ b/featureClass/featureManager.js @@ -0,0 +1,384 @@ +/// +/// +import LocationSetting from "../features/settings/settingThings/location"; +import logger from "../logger"; +const File = Java.type("java.io.File") +import metadata from "../metadata.js" +import { registerForge as registerForgeBase, unregisterForge as unregisterForgeBase} from "./forgeEvents.js" + +class FeatureManager { + constructor(){ + + this.enabled = true //make triggers work with this context + + this.features = {}; + this.events = {} + this.eventObjects = {} + this.soopyEventHandlers = {} + + this.parent = undefined + + this.commandFuncs = {} + + this.lastEventId = 0 + + this.customEvents = {} + this.lastChatEventId = 0 + + this.forgeEvents = {} + this.lastForgeEventId = 0 + + this.lastSoopyEventId = 0 + + this.featureSettingsDataLastUpdated = false + + this.featureMetas = {} + + this.featureSettingsData = {} + + new Thread(()=>{ + this.loadFeatureMetas() + + this.loadFeatureSettings() + + Object.keys(this.featureMetas).forEach((feature)=>{ + if(this.featureSettingsData[feature] && this.featureSettingsData[feature].enabled){ + this.loadFeature(feature) + } + }) + }).start() + + this.registerStep(false, 30, ()=>{ + if(this.featureSettingsDataLastUpdated){ + new Thread(()=>{ + this.saveFeatureSettings() + }).start() + } + }, this) + + this.registerEvent("worldUnload", this.saveFeatureSettings, this) + this.registerEvent("gameUnload", this.saveFeatureSettings, this) + + this.registerCommand("soopyunloadfeature", (args)=>{ + new Thread(()=>{ + this.unloadFeature(args) + }).start() + }, this) + this.registerCommand("soopyloadfeature", (args)=>{ + new Thread(()=>{ + this.loadFeature(args) + }).start() + }, this) + this.registerCommand("soopyreloadfeature", (args)=>{ + new Thread(()=>{ + this.unloadFeature(args) + + this.loadFeature(args) + }).start() + }, this) + } + + loadFeatureSettings(){ + logger.logMessage("Loading settings", 4) + + let data = FileLib.read("soopyAddonsData", "soopyaddonsbetafeaturesdata.json") + + if(!data){ + this.loadDefaultFeatureSettings(); + return; + } + + data = JSON.parse(data) + + this.featureSettingsData = data + + this.ensureNewSettingsExist() + } + + saveFeatureSettings(){ + if(!this.featureSettingsDataLastUpdated) return + + FileLib.write("soopyAddonsData", "soopyaddonsbetafeaturesdata.json", JSON.stringify(this.featureSettingsData)) + + this.featureSettingsDataLastUpdated = false + + logger.logMessage("Saved settings", 4) + } + + loadDefaultFeatureSettings(){ + Object.keys(this.featureMetas).forEach((feature)=>{ + this.featureSettingsData[feature] = { + enabled: this.featureMetas[feature].defaultEnabled, + subSettings: {} + } + }) + + this.featureSettingsDataLastUpdated= true + + logger.logMessage("Loaded default settings", 4) + } + + ensureNewSettingsExist(){ + Object.keys(this.featureMetas).forEach((feature)=>{ + if(!this.featureSettingsData[feature]){ + this.featureSettingsData[feature] = { + enabled: this.featureMetas[feature].defaultEnabled, + subSettings: {} + } + this.featureSettingsDataLastUpdated= true + logger.logMessage("Loaded default settings for " + feature, 4) + } + }) + } + + startCatchingEvent(event){ + if(this.eventObjects[event]) return + + //SBA compatability or something (removed) + // if(event === "renderOverlay"){ + // let lastPartialTick = undefined + // this.eventObjects[event] = register(event, (...args)=>{ + // let pTicks = Tessellator.getPartialTicks() + // if(pTicks !== lastPartialTick){ + // lastPartialTick = pTicks + // this.triggerEvent(event, args) + // } + // }) + // }else{ + this.eventObjects[event] = register(event, (...args)=>{ + this.triggerEvent(event, args) + }) + //} + + logger.logMessage("Registered " + event + " event", 4) + } + + triggerEvent(event, args){ + if(this.events[event]) + try{ + for(Event of Object.values(this.events[event])){ + if(Event.context.enabled) Event.func.call(Event.context, ...args) + } + }catch(e){ + logger.logMessage("Error in " + event + " event: " + JSON.stringify(e, undefined, 2), 2) + } + } + triggerSoopy(event, args){ + if(this.soopyEventHandlers[event]) + try{ + for(Event of Object.values(this.soopyEventHandlers[event])){ + if(Event.context.enabled) Event.func.call(Event.context, ...args) + } + }catch(e){ + logger.logMessage("Error in soopy " + event + " event: " + JSON.stringify(e, undefined, 2), 2) + } + } + + stopCatchingEvent(event){ + if(!this.eventObjects[event]) return + + this.eventObjects[event].unregister() + delete this.eventObjects[event] + delete this.events[event] + logger.logMessage("Unregistered " + event + " event", 4) + } + + registerEvent(event, func, context){ + if(!this.events[event]){ + this.events[event] = [] + this.startCatchingEvent(event) + } + + let theEvent = { + func: func, + context: context, + id: this.lastEventId++, + event: event + } + this.events[event].push(theEvent) + + return theEvent + } + registerSoopy(event, func, context){ + if(!this.soopyEventHandlers[event]){ + this.soopyEventHandlers[event] = [] + } + + let theEvent = { + func: func, + context: context, + id: this.lastSoopyEventId++, + event: event + } + this.soopyEventHandlers[event].push(theEvent) + + return theEvent + } + + registerChat(criteria, func, context){ + + let event = this.registerCustom("chat", func, context) + + event.trigger.setChatCriteria(criteria) + + return event + } + registerCommand(commandName, func, context){ + + let event = this.registerCustom("command", func, context) + + event.trigger.setName(commandName) + + return event + } + registerStep(isFps, interval, func, context){ + + let event = this.registerCustom("step", func, context) + + event.trigger[isFps?"setFps":"setDelay"](interval) //TODO: make this group events similar to registerEvent() + + return event + } + + registerCustom(type, func, context){ + + let id = this.lastChatEventId++ + + this.customEvents[id] = { + func: func, + context: context, + trigger: register(type, (...args)=>{ + try{ + if(context.enabled) func.call(context, ...(args || [])) + }catch(e){ + logger.logMessage("Error in " + type + " event: " + JSON.stringify(e, undefined, 2), 2) + } + }), + id: id + } + + return this.customEvents[id] + } + + registerForge(event, func, context){ + let id = this.lastForgeEventId++ + + this.forgeEvents[id] = { + func: func, + context: context, + trigger: registerForgeBase(event, (...args)=>{ + try{ + if(context.enabled) func.call(context, ...args) + }catch(e){ + logger.logMessage("Error in " + event.class.toString() + " (forge) event: " + JSON.stringify(e, undefined, 2), 2) + } + }), + id: id + } + + return this.forgeEvents[id] + } + + unregisterForge(event){ + unregisterForgeBase(this.forgeEvents[event.id].trigger) + delete this.forgeEvents[event.id] + } + + unregisterCustom(event){ + event.trigger.unregister() + + delete this.customEvents[event.id] + } + + unregisterEvent(event){ + if(!this.events[event.event]) return + + this.events[event.event] = this.events[event.event].filter((e)=>{ + return e.id !== event.id + }) + + if(this.events[event.event].length === 0){ + this.stopCatchingEvent(event.event) + delete this.events[event.event] + } + } + + unregisterSoopy(event){ + if(!this.soopyEventHandlers[event.event]) return + + this.soopyEventHandlers[event.event] = this.soopyEventHandlers[event.event].filter((e)=>{ + return e.id !== event.id + }) + + if(this.soopyEventHandlers[event.event].length === 0){ + delete this.events[event.event] + } + } + + loadFeatureMetas(){ + featuresDir = new File("./config/ChatTriggers/modules/" + metadata.name + "/features") + + featuresDir.list().forEach((pathName)=>{ + if(pathName.includes(".")) return; + + try{ + let data = JSON.parse(FileLib.read( metadata.name + "/features/" + pathName,"metadata.json")) + if(data === null){ + return; + } + data.id = pathName + this.featureMetas[pathName] = data + }catch(_){} + }) + } + + loadFeature(feature){ //run in seperate thread so onenable can do network requests + if(this.features[feature]) return + + let LoadedFeature = require("../features/" + feature + "/index.js") + + this.features[feature] = LoadedFeature + + LoadedFeature.class.setId(feature) + + LoadedFeature.class._onEnable(this) + + logger.logMessage("Loaded feature " + feature, 3) + + return this + } + + unloadFeature(feature){ //run in seperate thread so ondisable can do network requests + if(!this.features[feature]) return + + this.features[feature].class._onDisable() + + delete this.features[feature] + + logger.logMessage("Unloaded feature " + feature, 3) + + return this + } + + isFeatureLoaded(feature){ + return !!this.features[feature] + } + + getLoadedFeatures(){ + return Object.keys(this.features) + } + + createCustomEvent(eventId){ + logger.logMessage("Registered custom " + eventId + " event", 4) + + return { + trigger: (...args)=>{ + this.triggerSoopy(eventId, args) + } + } + } +} + +const featureManager = new FeatureManager(); + +export default featureManager; \ No newline at end of file diff --git a/featureClass/forgeEvents.js b/featureClass/forgeEvents.js new file mode 100644 index 0000000..e852c49 --- /dev/null +++ b/featureClass/forgeEvents.js @@ -0,0 +1,93 @@ +importClass(net.minecraftforge.common.MinecraftForge) //i would have used the ct module but it is broken (line 78) (this is fixed verison) +importPackage(net.minecraftforge.fml.common.eventhandler) +importPackage(org.objectweb.asm) +importClass(java.lang.ClassLoader) +importClass(org.apache.commons.lang3.RandomStringUtils) +importClass(java.util.function.Consumer) + +const L = s => `L${s};` + +const LoadedInsts = [] + +function defineClassBytes(name, bytes) { + const classLoader = Packages.com.chattriggers.ctjs.CTJS.class.getClassLoader() + + const defClass = ClassLoader.class.getDeclaredMethods()[23] // defineClass() + + defClass.setAccessible(true) + + const n = new java.lang.String(name) + const o = new java.lang.Integer(0) + const s = new java.lang.Integer(bytes.length) + return defClass.invoke(classLoader, n, bytes, o, s) +} + +const registerForge = (e, cb) => { + const cw = new ClassWriter(0) + + const event = Type.getType(e.class).internalName + const name = RandomStringUtils.randomAlphabetic(7) + + const consumer = Type.getType(Consumer.class).internalName + const mcForge = Type.getType(MinecraftForge.class).internalName + const eventBus = Type.getType(EventBus.class).internalName + const subscribeEvent = Type.getType(SubscribeEvent.class).internalName + const obj = Type.getType(java.lang.Object.class).internalName + + cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, name, null, obj, null) + // cw.visitInnerClass("net/minecraftforge/event/entity/player/PlayerEvent$BreakSpeed", "net/minecraftforge/event/entity/player/PlayerEvent", "BreakSpeed", ACC_PUBLIC + ACC_STATIC); + { + cw.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL, "callback", L(consumer), L(consumer + "<" + L(event) + ">"), null).visitEnd() + } + { + const con = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "(" + L(consumer) + ")V", "(" + L(consumer + "<" + L(event) + ">") + ")V", null) + con.visitCode() + con.visitVarInsn(Opcodes.ALOAD, 0) + con.visitMethodInsn(Opcodes.INVOKESPECIAL, obj, "", "()V", false) + + con.visitVarInsn(Opcodes.ALOAD, 0) + con.visitVarInsn(Opcodes.ALOAD, 1) + con.visitFieldInsn(Opcodes.PUTFIELD, name, "callback", L(consumer)) + con.visitFieldInsn(Opcodes.GETSTATIC, mcForge, "EVENT_BUS", L(eventBus)) + con.visitVarInsn(Opcodes.ALOAD, 0) + con.visitMethodInsn(Opcodes.INVOKEVIRTUAL, eventBus, "register", "(" + L(obj) + ")V", false) + con.visitInsn(Opcodes.RETURN) + con.visitMaxs(2, 2) + con.visitEnd() + } + { + const mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "on", "(" + L(event) + ")V", null, null) + { + const av = mv.visitAnnotation(L(subscribeEvent), true) + av.visitEnd() + } + mv.visitCode() + mv.visitVarInsn(Opcodes.ALOAD, 0) + mv.visitFieldInsn(Opcodes.GETFIELD, name, "callback", L(consumer)) + mv.visitVarInsn(Opcodes.ALOAD, 1) + mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, consumer, "accept", "(" + L(obj) + ")V", true) + mv.visitInsn(Opcodes.RETURN) + mv.visitMaxs(2, 2) + mv.visitEnd() + } + cw.visitEnd() + + const inst = defineClassBytes(name, cw.toByteArray()) + .getDeclaredConstructor(Consumer.class) + .newInstance(new java.util.function.Consumer({ + accept: function (t) { cb(t) } + })) + LoadedInsts.push(inst) + return inst; +} + +const unregisterForge = inst => { + MinecraftForge.EVENT_BUS.unregister(inst) +} + +register("gameUnload", () => { + LoadedInsts.forEach(unregisterForge) + LoadedInsts.length = 0 +}) + +export { registerForge, unregisterForge } diff --git a/featureManager.js b/featureManager.js new file mode 100644 index 0000000..92b9cd8 --- /dev/null +++ b/featureManager.js @@ -0,0 +1,384 @@ +/// +/// +import LocationSetting from "../features/settings/settingThings/location"; +import logger from "../logger"; +const File = Java.type("java.io.File") +import metadata from "../metadata.js" +import { registerForge as registerForgeBase, unregisterForge as unregisterForgeBase} from "./forgeEvents.js" + +class FeatureManager { + constructor(){ + + this.enabled = true //make triggers work with this context + + this.features = {}; + this.events = {} + this.eventObjects = {} + this.soopyEventHandlers = {} + + this.parent = undefined + + this.commandFuncs = {} + + this.lastEventId = 0 + + this.customEvents = {} + this.lastChatEventId = 0 + + this.forgeEvents = {} + this.lastForgeEventId = 0 + + this.lastSoopyEventId = 0 + + this.featureSettingsDataLastUpdated = false + + this.featureMetas = {} + + this.featureSettingsData = {} + + new Thread(()=>{ + this.loadFeatureMetas() + + this.loadFeatureSettings() + + Object.keys(this.featureMetas).forEach((feature)=>{ + if(this.featureSettingsData[feature] && this.featureSettingsData[feature].enabled){ + this.loadFeature(feature) + } + }) + }).start() + + this.registerStep(false, 30, ()=>{ + if(this.featureSettingsDataLastUpdated){ + new Thread(()=>{ + this.saveFeatureSettings() + }).start() + } + }, this) + + this.registerEvent("worldUnload", this.saveFeatureSettings, this) + this.registerEvent("gameUnload", this.saveFeatureSettings, this) + + this.registerCommand("soopyunloadfeature", (args)=>{ + new Thread(()=>{ + this.unloadFeature(args) + }).start() + }, this) + this.registerCommand("soopyloadfeature", (args)=>{ + new Thread(()=>{ + this.loadFeature(args) + }).start() + }, this) + this.registerCommand("soopyreloadfeature", (args)=>{ + new Thread(()=>{ + this.unloadFeature(args) + + this.loadFeature(args) + }).start() + }, this) + } + + loadFeatureSettings(){ + logger.logMessage("Loading settings", 4) + + let data = FileLib.read("soopyAddonsData", "soopyaddonsbetafeaturesdata.json") + + if(!data){ + this.loadDefaultFeatureSettings(); + return; + } + + data = JSON.parse(data) + + this.featureSettingsData = data + + this.ensureNewSettingsExist() + } + + saveFeatureSettings(){ + if(!this.featureSettingsDataLastUpdated) return + + FileLib.write("soopyAddonsData", "soopyaddonsbetafeaturesdata.json", JSON.stringify(this.featureSettingsData)) + + this.featureSettingsDataLastUpdated = false + + logger.logMessage("Saved settings", 4) + } + + loadDefaultFeatureSettings(){ + Object.keys(this.featureMetas).forEach((feature)=>{ + this.featureSettingsData[feature] = { + enabled: this.featureMetas[feature].defaultEnabled, + subSettings: {} + } + }) + + this.featureSettingsDataLastUpdated= true + + logger.logMessage("Loaded default settings", 4) + } + + ensureNewSettingsExist(){ + Object.keys(this.featureMetas).forEach((feature)=>{ + if(!this.featureSettingsData[feature]){ + this.featureSettingsData[feature] = { + enabled: this.featureMetas[feature].defaultEnabled, + subSettings: {} + } + this.featureSettingsDataLastUpdated= true + logger.logMessage("Loaded default settings for " + feature, 4) + } + }) + } + + startCatchingEvent(event){ + if(this.eventObjects[event]) return + + //SBA compatability or something (removed) + // if(event === "renderOverlay"){ + // let lastPartialTick = undefined + // this.eventObjects[event] = register(event, (...args)=>{ + // let pTicks = Tessellator.getPartialTicks() + // if(pTicks !== lastPartialTick){ + // lastPartialTick = pTicks + // this.triggerEvent(event, args) + // } + // }) + // }else{ + this.eventObjects[event] = register(event, (...args)=>{ + this.triggerEvent(event, args) + }) + //} + + logger.logMessage("Registered " + event + " event", 4) + } + + triggerEvent(event, args){ + if(this.events[event]) + try{ + for(Event of Object.values(this.events[event])){ + if(Event.context.enabled) Event.func.call(Event.context, ...args) + } + }catch(e){ + logger.logMessage("Error in " + event + " event: " + JSON.stringify(e, undefined, 2), 2) + } + } + triggerSoopy(event, args){ + if(this.soopyEventHandlers[event]) + try{ + for(Event of Object.values(this.soopyEventHandlers[event])){ + if(Event.context.enabled) Event.func.call(Event.context, ...args) + } + }catch(e){ + logger.logMessage("Error in soopy " + event + " event: " + JSON.stringify(e, undefined, 2), 2) + } + } + + stopCatchingEvent(event){ + if(!this.eventObjects[event]) return + + this.eventObjects[event].unregister() + delete this.eventObjects[event] + delete this.events[event] + logger.logMessage("Unregistered " + event + " event", 4) + } + + registerEvent(event, func, context){ + if(!this.events[event]){ + this.events[event] = [] + this.startCatchingEvent(event) + } + + let theEvent = { + func: func, + context: context, + id: this.lastEventId++, + event: event + } + this.events[event].push(theEvent) + + return theEvent + } + registerSoopy(event, func, context){ + if(!this.soopyEventHandlers[event]){ + this.soopyEventHandlers[event] = [] + } + + let theEvent = { + func: func, + context: context, + id: this.lastSoopyEventId++, + event: event + } + this.soopyEventHandlers[event].push(theEvent) + + return theEvent + } + + registerChat(criteria, func, context){ + + let event = this.registerCustom("chat", func, context) + + event.trigger.setChatCriteria(criteria) + + return event + } + registerCommand(commandName, func, context){ + + let event = this.registerCustom("command", func, context) + + event.trigger.setName(commandName) + + return event + } + registerStep(isFps, interval, func, context){ + + let event = this.registerCustom("step", func, context) + + event.trigger[isFps?"setFps":"setDelay"](interval) //TODO: make this group events similar to registerEvent() + + return event + } + + registerCustom(type, func, context){ + + let id = this.lastChatEventId++ + + this.customEvents[id] = { + func: func, + context: context, + trigger: register(type, (...args)=>{ + try{ + if(context.enabled) func.call(context, ...(args || [])) + }catch(e){ + logger.logMessage("Error in " + type + " event: " + JSON.stringify(e, undefined, 2), 2) + } + }), + id: id + } + + return this.customEvents[id] + } + + registerForge(event, func, context){ + let id = this.lastForgeEventId++ + + this.forgeEvents[id] = { + func: func, + context: context, + trigger: registerForgeBase(event, (...args)=>{ + try{ + if(context.enabled) func.call(context, ...args) + }catch(e){ + logger.logMessage("Error in " + event.class.toString() + " (forge) event: " + JSON.stringify(e, undefined, 2), 2) + } + }), + id: id + } + + return this.forgeEvents[id] + } + + unregisterForge(event){ + unregisterForgeBase(this.forgeEvents[event.id].trigger) + delete this.forgeEvents[event.id] + } + + unregisterCustom(event){ + event.trigger.unregister() + + delete this.customEvents[event.id] + } + + unregisterEvent(event){ + if(!this.events[event.event]) return + + this.events[event.event] = this.events[event.event].filter((e)=>{ + return e.id !== event.id + }) + + if(this.events[event.event].length === 0){ + this.stopCatchingEvent(event.event) + delete this.events[event.event] + } + } + + unregisterSoopy(event){ + if(!this.soopyEventHandlers[event.event]) return + + this.soopyEventHandlers[event.event] = this.soopyEventHandlers[event.event].filter((e)=>{ + return e.id !== event.id + }) + + if(this.soopyEventHandlers[event.event].length === 0){ + delete this.events[event.event] + } + } + + loadFeatureMetas(){ + featuresDir = new File("./config/ChatTriggers/modules/" + metadata.name + "/features") + + featuresDir.list().forEach((pathName)=>{ + if(pathName.includes(".")) return; + + try{ + let data = JSON.parse(FileLib.read( metadata.name + "/features/" + pathName,"metadata.json")) + if(data === null){ + return; + } + data.id = pathName + this.featureMetas[pathName] = data + }catch(_){} + }) + } + + loadFeature(feature){ //run in seperate thread so onenable can do network requests + if(this.features[feature]) return + + let LoadedFeature = require("../features/" + feature + "/index.js") + + this.features[feature] = LoadedFeature + + LoadedFeature.class.setId(feature) + + LoadedFeature.class._onEnable(this) + + logger.logMessage("Loaded feature " + feature, 3) + + return this + } + + unloadFeature(feature){ //run in seperate thread so ondisable can do network requests + if(!this.features[feature]) return + + this.features[feature].class._onDisable() + + delete this.features[feature] + + logger.logMessage("Unloaded feature " + feature, 3) + + return this + } + + isFeatureLoaded(feature){ + return !!this.features[feature] + } + + getLoadedFeatures(){ + return Object.keys(this.features) + } + + createCustomEvent(eventId){ + logger.logMessage("Registered custom " + eventId + " event", 4) + + return { + trigger: (...args)=>{ + this.triggerSoopy(eventId, args) + } + } + } +} + +const featureManager = new FeatureManager(); + +export default featureManager; \ No newline at end of file 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 @@ +/// +/// +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 @@ +/// +/// +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 @@ +/// +/// +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); +