diff --git a/examplemods/minecraft_on_3x_speed.js b/examplemods/minecraft_on_3x_speed.js deleted file mode 100644 index 5e3269d..0000000 --- a/examplemods/minecraft_on_3x_speed.js +++ /dev/null @@ -1,9 +0,0 @@ -//Very much WIP, still firguring out how to poke the dedicated server. -(()=>{ - PluginAPI.javaClient.$timer.$timerSpeed = 3; - ModAPI.dedicatedServer.appendCode(` - const original_getCurrentTime = ModAPI.hooks.methods.nms_MinecraftServer_getCurrentTimeMillis; - ModAPI.hooks.methods.nms_MinecraftServer_getCurrentTimeMillis = function () { - return original_getCurrentTime() * 3n; - };`); -})(); \ No newline at end of file diff --git a/examplemods/timescale_command.js b/examplemods/timescale_command.js new file mode 100644 index 0000000..2839eec --- /dev/null +++ b/examplemods/timescale_command.js @@ -0,0 +1,49 @@ +(() => { + PluginAPI.addEventListener("sendchatmessage", (event) => { + if (event.message.toLowerCase().startsWith("/timescale")) { + var speed = parseFloat(event.message.split(" ")[1]); + if (!speed) { + PluginAPI.javaClient.$timer.$timerSpeed = 1; + } else { + if (speed < 1) { + speed = 1 / Math.round(1 / speed); + } else { + speed = Math.round(speed); + } + PluginAPI.javaClient.$timer.$timerSpeed = speed; + } + PluginAPI.displayToChat("[Timescale] Set world timescale to " + speed + "."); + } + }); + PluginAPI.dedicatedServer.appendCode(function () { + globalThis.timeScale = 1n; + globalThis.timeScaleDividing = false; + PluginAPI.addEventListener("handleslashcommand", (event) => { + if (event.command.toLowerCase().startsWith("/timescale")) { + var speed = parseFloat(event.command.split(" ")[1]); + if (!speed) { + globalThis.timeScale = 1n; + globalThis.timeScaleDividing = false; + } else { + if (speed < 1) { + globalThis.timeScaleDividing = true; + globalThis.timeScale = BigInt(Math.round(1 / speed)); + } else { + globalThis.timeScaleDividing = false; + globalThis.timeScale = BigInt(Math.round(speed)); + } + } + event.preventDefault = true; + } + }); + const original_getCurrentTime = ModAPI.hooks.methods.nms_MinecraftServer_getCurrentTimeMillis; + PluginAPI.hooks.methods.nms_MinecraftServer_getCurrentTimeMillis = function () { + if (globalThis.timeScaleDividing) { + return original_getCurrentTime() / globalThis.timeScale; + } else { + return original_getCurrentTime() * globalThis.timeScale; + } + }; + }); + +})(); \ No newline at end of file diff --git a/injector.html b/injector.html index 4e0a935..ec3c62b 100644 --- a/injector.html +++ b/injector.html @@ -198,8 +198,9 @@

diff --git a/postinit.js b/postinit.js index 084e32b..6625278 100644 --- a/postinit.js +++ b/postinit.js @@ -5,10 +5,19 @@ globalThis.PluginAPI ||= ModAPI; ModAPI.mcinstance ||= {}; ModAPI.javaClient ||= {}; + ModAPI.server = ModAPI.serverInstance = null; ModAPI.dedicatedServer ||= {}; ModAPI.dedicatedServer._data ||= []; + ModAPI.dedicatedServer._wasUsed = false; ModAPI.dedicatedServer.appendCode = function (code) { - ModAPI.dedicatedServer._data.push(code); + if (ModAPI.dedicatedServer._wasUsed) { + return console.warn("The dedicated server has already launched, ModAPI.dedicatedServer.appendCode() is useless."); + } + if (typeof code === "function") { + ModAPI.dedicatedServer._data.push("(" + code.toString() + ")()"); + } else if (typeof code === "string") { + ModAPI.dedicatedServer._data.push(code); + } } ModAPI.util ||= {}; ModAPI.util.getMethodFromPackage = function (classId, methodName) { @@ -283,25 +292,21 @@ return uint16Array; } - var stringDefaultConstructor = ModAPI.hooks._classMap["java.lang.String"].constructors.filter(x => { return x.length === 0 })[0]; - ModAPI.util.string = ModAPI.util.str = function (string) { - var jclString = stringDefaultConstructor(); - jclString.$characters.data = ModAPI.util.stringToUint16Array(string); - return jclString; + //Overrides $rt_resuming, $rt_suspending, $rt_currentThread. Experimental, but should be used if call stack leaks occur as a result of running internal code. + ModAPI.freezeCallstack = function () { + ModAPI.hooks.freezeCallstack = true; } + ModAPI.unfreezeCallstack = function () { + ModAPI.hooks.freezeCallstack = false; + } + + ModAPI.util.string = ModAPI.util.str = ModAPI.hooks._teavm.$rt_str; - ModAPI.util.setStringContent = function (jclString) { + ModAPI.util.setStringContent = function (jclString, string) { jclString.$characters.data = ModAPI.util.stringToUint16Array(string); } - ModAPI.util.jclStrToJsStr = function (jclString) { - var uint16Array = jclString.$characters.data; - let str = ''; - for (let i = 0; i < uint16Array.length; i++) { - str += String.fromCharCode(uint16Array[i]); - } - return str; - } + ModAPI.util.jclStrToJsStr = ModAPI.util.unstr = ModAPI.util.unstring = ModAPI.util.ustr = ModAPI.hooks._teavm.$rt_ustr; ModAPI.displayToChat = function (param) { var v = typeof param === "object" ? param.msg : (param + ""); @@ -333,6 +338,8 @@ const integratedServerStartupMethod = ModAPI.hooks.methods[integratedServerStartup]; ModAPI.hooks.methods[integratedServerStartup] = function (worker, bootstrap) { var x = integratedServerStartupMethod.apply(this, [worker, bootstrap + ";" + globalThis.modapi_postinit + ";" + ModAPI.dedicatedServer._data.join(";")]); + ModAPI.dedicatedServer._data = []; + ModAPI.dedicatedServer._wasUsed = true; return x; }; @@ -348,7 +355,10 @@ if (data.preventDefault) { return; } - return sendChatMessage.apply(this, [$this, ModAPI.util.str(data.message) || $message]); + if (typeof data.message === "string") { + ModAPI.util.setStringContent($message, data.message) + } + return sendChatMessage.apply(this, [$this, $message]); } ModAPI.events.newEvent("tick"); @@ -369,7 +379,18 @@ ModAPI.hooks.methods[serverStartMethodName] = function ($this) { var x = serverStartMethod.apply(this, [$this]); ModAPI.server = ModAPI.serverInstance = new Proxy($this, ModAPI.util.TeaVM_to_Recursive_BaseData_ProxyConf); + ModAPI.rawServer = $this; ModAPI.events.callEvent("serverstart", {}); return x; } + + ModAPI.events.newEvent("serverstop"); + const serverStopMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.server.MinecraftServer", "stopServer"); + const serverStopMethod = ModAPI.hooks.methods[serverStopMethodName]; + ModAPI.hooks.methods[serverStopMethodName] = function ($this) { + var x = serverStopMethod.apply(this, [$this]); + ModAPI.server = ModAPI.serverInstance = null; + ModAPI.events.callEvent("serverstop", {}); + return x; + } })(); \ No newline at end of file