///
///
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"
import soopyV2Server from "../socketConnection"
class FeatureManager {
constructor(){
this.messagePrefix = "&6[SOOPY V2]&7 "
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)=>{
// let start = Date.now()
this.triggerEvent(event, args)
// this.eventTimingData[event] = (this.eventTimingData[event] || 0)+(Date.now()-start)
})
//}
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
}
registerActionBar(criteria, func, context){
let event = this.registerCustom("actionBar", 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
try{
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)
}catch(e){
logger.logMessage("Error loading feature " + feature, 1)
console.log(JSON.stringify(e, undefined, 2))
ChatLib.chat(this.messagePrefix + "Error loading feature " + feature)
}
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;