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);
+