Fix memleak

This commit is contained in:
ZXMushroom63 2024-08-28 16:23:56 +08:00
parent 58b83230bd
commit 2e700760ca
4 changed files with 139 additions and 43 deletions

View File

@ -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;
};`);
})();

View File

@ -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;
}
};
});
})();

View File

@ -198,8 +198,9 @@
<script>
var modapi_preinit = `globalThis.ModAPI ||= {};
ModAPI.hooks ||= {};
ModAPI.hooks.freezeCallstack = false;
ModAPI.hooks._rippedData ||= [];
ModAPI.hooks._teavmMethods ||= {};
ModAPI.hooks._teavm ||= {};
ModAPI.hooks._rippedConstructors ||= {};
ModAPI.hooks.methods ||= {};
ModAPI.hooks._rippedMethodTypeMap ||= {};
@ -207,6 +208,7 @@ ModAPI.hooks._postInit ||= ()=>{};
ModAPI.hooks._rippedStaticProperties ||= {};
ModAPI.hooks._rippedStaticIndexer ||= {};
`;
var freezeCallstack = `if(ModAPI.hooks.freezeCallstack){return false};`;
document.querySelector("#giveme").addEventListener("click", () => {
if (
!document.querySelector("input").files ||
@ -246,6 +248,18 @@ var main;(function(){`
/*/EaglerForge Client Patch/*/`
);
patchedFile = patchedFile.replaceAll(`return thread != null && thread.isResuming()`, (match)=>{
return freezeCallstack + match;
});
patchedFile = patchedFile.replaceAll(`return thread != null && thread.isSuspending();`, (match)=>{
return freezeCallstack + match;
});
patchedFile = patchedFile.replaceAll(`return $rt_currentNativeThread;`, (match)=>{
return `if(ModAPI.hooks.freezeCallstack){return {push: (a)=>{console.log("Data pushed to stack: ") + a}, pop: ()=>{console.warn("Frozen stack was popped, context is now unstable.")}}};` + match;
});
patchedFile = patchedFile.replace(
` id="game_frame">`,
` id="game_frame">
@ -349,7 +363,7 @@ var main;(function(){`
patchedFile = patchedFile.replaceAll(/function \$rt_\S+?\(/gm, (match)=>{
var name = match.replace("function ", "");
name = name.substring(0, name.length - 1);
return `ModAPI.hooks._teavmMethods[\`${name}\`]=${name};
return `ModAPI.hooks._teavm[\`${name}\`]=${name};
` + match;
});
patchedFile = patchedFile.replaceAll(/main\(\);\s*?}/gm, (match) => {
@ -369,10 +383,19 @@ var main;(function(){`
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) {
@ -647,25 +670,21 @@ var main;(function(){`
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.setStringContent = function (jclString) {
ModAPI.util.string = ModAPI.util.str = ModAPI.hooks._teavm.$rt_str;
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 + "");
@ -697,6 +716,8 @@ var main;(function(){`
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;
};
@ -712,7 +733,10 @@ var main;(function(){`
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");
@ -733,9 +757,20 @@ var main;(function(){`
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;
}
})();`;
</script>

View File

@ -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.setStringContent = function (jclString) {
ModAPI.util.string = ModAPI.util.str = ModAPI.hooks._teavm.$rt_str;
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;
}
})();