This commit is contained in:
ZXMushroom63 2024-08-29 18:31:55 +08:00
parent 36d87d1a56
commit 3dc920c144
3 changed files with 418 additions and 198 deletions

View File

@ -12,13 +12,13 @@
} }
PluginAPI.javaClient.$timer.$timerSpeed = speed; PluginAPI.javaClient.$timer.$timerSpeed = speed;
} }
PluginAPI.displayToChat("[Timescale] Set world timescale to " + speed + "."); PluginAPI.displayToChat("[Timescale] Set world timescale to " + speed.toFixed(2) + ".");
} }
}); });
PluginAPI.dedicatedServer.appendCode(function () { PluginAPI.dedicatedServer.appendCode(function () {
globalThis.timeScale = 1n; globalThis.timeScale = 1n;
globalThis.timeScaleDividing = false; globalThis.timeScaleDividing = false;
PluginAPI.addEventListener("handleslashcommand", (event) => { PluginAPI.addEventListener("processcommand", (event) => {
if (event.command.toLowerCase().startsWith("/timescale")) { if (event.command.toLowerCase().startsWith("/timescale")) {
var speed = parseFloat(event.command.split(" ")[1]); var speed = parseFloat(event.command.split(" ")[1]);
if (!speed) { if (!speed) {
@ -45,5 +45,4 @@
} }
}; };
}); });
})(); })();

View File

@ -26,8 +26,7 @@
<h1>EaglerForge Injector</h1> <h1>EaglerForge Injector</h1>
<h4> <h4>
Adds ModAPI with more functionality (adds hooking into functions, exposes Adds ModAPI with more functionality (adds hooking into functions, exposes
all classes, etc) to unminified unobfuscated EaglercraftX all classes, etc) to unminified unobfuscated EaglercraftX builds.
builds.
</h4> </h4>
<br /> <br />
<input type="file" accept=".html,.js" /><br /><br /> <input type="file" accept=".html,.js" /><br /><br />
@ -248,17 +247,29 @@ var main;(function(){`
/*/EaglerForge Client Patch/*/` /*/EaglerForge Client Patch/*/`
); );
patchedFile = patchedFile.replaceAll(`return thread != null && thread.isResuming()`, (match)=>{ patchedFile = patchedFile.replaceAll(
`return thread != null && thread.isResuming()`,
(match) => {
return freezeCallstack + match; return freezeCallstack + match;
}); }
);
patchedFile = patchedFile.replaceAll(`return thread != null && thread.isSuspending();`, (match)=>{ patchedFile = patchedFile.replaceAll(
`return thread != null && thread.isSuspending();`,
(match) => {
return freezeCallstack + match; return freezeCallstack + match;
}); }
);
patchedFile = patchedFile.replaceAll(`return $rt_currentNativeThread;`, (match)=>{ patchedFile = patchedFile.replaceAll(
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; `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( patchedFile = patchedFile.replace(
` id="game_frame">`, ` id="game_frame">`,
@ -302,9 +313,7 @@ var main;(function(){`
return ModAPI.hooks.methods[\`${fullName}\`].apply(this, args); return ModAPI.hooks.methods[\`${fullName}\`].apply(this, args);
} }
ModAPI.hooks._rippedMethodTypeMap[\`${fullName}\`] = \`${ ModAPI.hooks._rippedMethodTypeMap[\`${fullName}\`] = \`${
match.endsWith("($this") match.endsWith("($this") ? "instance" : "static"
? "instance"
: "static"
}\`; }\`;
ModAPI.hooks.methods[\`${fullName}\`]=` + ModAPI.hooks.methods[\`${fullName}\`]=` +
match.replace(fullName + "(", "(") match.replace(fullName + "(", "(")
@ -312,41 +321,68 @@ var main;(function(){`
return match; return match;
} }
); );
var staticVariables = [...patchedFile.matchAll(/var \S+?_\S+?_\S+? = null;/gm)].flatMap(x => {return x[0]}); var staticVariables = [
...patchedFile.matchAll(/var \S+?_\S+?_\S+? = null;/gm),
].flatMap((x) => {
return x[0];
});
//Todo: add support for static properties on classes with constructors like this: function nmcg_GuiMainMenu() { //Todo: add support for static properties on classes with constructors like this: function nmcg_GuiMainMenu() {
patchedFile = patchedFile.replaceAll(/var \S+?_\S+? = \$rt_classWithoutFields\(\S*?\);/gm, function (match) { patchedFile = patchedFile.replaceAll(
var prefix = match.replaceAll(/ = \$rt_classWithoutFields\(\S*?\);/gm, ""); /var \S+?_\S+? = \$rt_classWithoutFields\(\S*?\);/gm,
function (match) {
var prefix = match.replaceAll(
/ = \$rt_classWithoutFields\(\S*?\);/gm,
""
);
var entries = []; var entries = [];
staticVariables.forEach(entry => { staticVariables.forEach((entry) => {
if (entry.startsWith(prefix)) { if (entry.startsWith(prefix)) {
var variableName = entry.replace("var ", "").replace(" = null;", ""); var variableName = entry
.replace("var ", "")
.replace(" = null;", "");
var segments = variableName.split("_"); var segments = variableName.split("_");
segments.splice(0, 2); segments.splice(0, 2);
var name = segments.join("_"); var name = segments.join("_");
entries.push({ entries.push({
"name": name, name: name,
"variable": variableName, variable: variableName,
}); });
} }
}); });
var getComponents = ""; var getComponents = "";
entries.forEach(entry => { entries.forEach((entry) => {
getComponents += ` getComponents += `
case \`${entry.name}\`: case \`${entry.name}\`:
return ${entry.variable}; return ${entry.variable};
break;` break;`;
}); });
var setComponents = ""; var setComponents = "";
entries.forEach(entry => { entries.forEach((entry) => {
setComponents += ` setComponents += `
case \`${entry.name}\`: case \`${entry.name}\`:
${entry.variable} = c; ${entry.variable} = c;
break;`; break;`;
}); });
var proxy = ` var proxy = `
ModAPI.hooks._rippedStaticIndexer[\`${prefix.replace("var ", "")}\`] = [${entries.flatMap((x)=>{return "\"" + x.name + "\""}).join(",")}]; ModAPI.hooks._rippedStaticIndexer[\`${prefix.replace(
ModAPI.hooks._rippedStaticProperties[\`${prefix.replace("var ", "")}\`] = new Proxy({}, { "var ",
""
)}\`] = [${entries
.flatMap((x) => {
return '"' + x.name + '"';
})
.join(",")}];
ModAPI.hooks._rippedStaticProperties[\`${prefix.replace(
"var ",
""
)}\`] = new Proxy({${
entries
.flatMap((x) => {
return '"' + x.name + '"';
})
.join(":null,") + (entries.length > 0 ? ":null" : "")
}}, {
get: function (a,b,c) { get: function (a,b,c) {
switch (b) { switch (b) {
${getComponents} ${getComponents}
@ -359,13 +395,19 @@ var main;(function(){`
} }
});`; });`;
return match + proxy; return match + proxy;
}); }
patchedFile = patchedFile.replaceAll(/function \$rt_\S+?\(/gm, (match)=>{ );
patchedFile = patchedFile.replaceAll(
/function \$rt_\S+?\(/gm,
(match) => {
var name = match.replace("function ", ""); var name = match.replace("function ", "");
name = name.substring(0, name.length - 1); name = name.substring(0, name.length - 1);
return `ModAPI.hooks._teavm[\`${name}\`]=${name}; return (
` + match; `ModAPI.hooks._teavm[\`${name}\`]=${name};
}); ` + match
);
}
);
patchedFile = patchedFile.replaceAll(/main\(\);\s*?}/gm, (match) => { patchedFile = patchedFile.replaceAll(/main\(\);\s*?}/gm, (match) => {
return match.replace("main();", "main();ModAPI.hooks._postInit();"); return match.replace("main();", "main();ModAPI.hooks._postInit();");
}); });
@ -411,7 +453,7 @@ var main;(function(){`
name += "_" + methodName; name += "_" + methodName;
return name; return name;
} }
ModAPI.util.getCompiledNameFromPackage = function (classId) { ModAPI.util.getCompiledNameFromPackage = ModAPI.util.getCompiledName = function (classId) {
var name = ""; var name = "";
var classStuff = classId.split("."); var classStuff = classId.split(".");
classStuff.forEach((component, i) => { classStuff.forEach((component, i) => {
@ -425,57 +467,84 @@ var main;(function(){`
} }
ModAPI.version = "v2.0"; ModAPI.version = "v2.0";
ModAPI.flavour = "injector"; ModAPI.flavour = "injector";
ModAPI.GNU = "terry pratchett";
ModAPI.credits = ["ZXMushroom63", "radmanplays", "OtterCodes101", "TheIdiotPlays"]; ModAPI.credits = ["ZXMushroom63", "radmanplays", "OtterCodes101", "TheIdiotPlays"];
ModAPI.hooks.regenerateClassMap = function () { ModAPI.hooks.regenerateClassMap = function () {
ModAPI.hooks._rippedConstructorKeys = Object.keys(ModAPI.hooks._rippedConstructors); ModAPI.hooks._rippedConstructorKeys = Object.keys(ModAPI.hooks._rippedConstructors);
ModAPI.hooks._rippedMethodKeys = Object.keys(ModAPI.hooks._rippedMethodTypeMap); ModAPI.hooks._rippedMethodKeys = Object.keys(ModAPI.hooks._rippedMethodTypeMap);
var compiledNames = new Set();
var metaMap = {};
//Loop through ripped metadata passes. Classes obtained through this method have full metadata (superclasses, full names, binary names, actual class)
ModAPI.hooks._rippedData.forEach(block => { ModAPI.hooks._rippedData.forEach(block => {
block.forEach(item => { block.forEach(item => {
if (typeof item === "function") { if (typeof item === "function") {
if (!item.$meta || typeof item.$meta.name !== "string") { if (!item.$meta || typeof item.$meta.name !== "string") {
return; return;
} }
var compiledName = ModAPI.util.getCompiledNameFromPackage(item.$meta.name);
compiledNames.add(compiledName);
metaMap[compiledName] = item;
}
});
});
var classId = item.$meta.name; ModAPI.hooks._rippedConstructorKeys.forEach(constructor => {
var compiledName = ModAPI.util.getCompiledNameFromPackage(classId); if (typeof constructor === "string" && constructor.length > 0) {
//Constructor names are phrased as aaa_Apple__init_3 or similar, the separator is __init_
var constructorData = constructor.split("__init_");
if (constructorData[0] && constructorData[0].includes("_")) {
compiledNames.add(constructorData[0]);
}
}
});
if (!ModAPI.hooks._classMap[classId]) { //Initialise all compiled names into the class map
ModAPI.hooks._classMap[classId] = { compiledNames.forEach(compiledName => {
"name": classId.split(".")[classId.split(".").length - 1], var item = metaMap[compiledName];
var classId = item?.$meta?.name || null;
if (!ModAPI.hooks._classMap[compiledName]) {
ModAPI.hooks._classMap[compiledName] = {
"name": compiledName.split("_")[1],
"id": classId, "id": classId,
"binaryName": item.$meta.binaryName, "binaryName": item?.$meta?.binaryName || null,
"constructors": [], "constructors": [],
"methods": {}, "methods": {},
"staticMethods": {}, "staticMethods": {},
"staticVariables": {}, "staticVariables": {},
"staticVariableNames": [], "staticVariableNames": [],
"class": item, "class": item || null,
"hasMeta": !!item,
"compiledName": compiledName "compiledName": compiledName
} }
} }
if (typeof item.$meta.superclass === "function" && item.$meta.superclass.$meta) { if (typeof item?.$meta?.superclass === "function" && item?.$meta?.superclass?.$meta) {
ModAPI.hooks._classMap[classId].superclass = item.$meta.superclass.$meta.name; ModAPI.hooks._classMap[compiledName].superclass = item.$meta.superclass.$meta.name;
} else {
ModAPI.hooks._classMap[compiledName].superclass = null;
} }
ModAPI.hooks._classMap[classId].staticVariableNames = ModAPI.hooks._rippedStaticIndexer[compiledName]; ModAPI.hooks._classMap[compiledName].staticVariableNames = ModAPI.hooks._rippedStaticIndexer[compiledName];
ModAPI.hooks._classMap[classId].staticVariables = ModAPI.hooks._rippedStaticProperties[compiledName]; ModAPI.hooks._classMap[compiledName].staticVariables = ModAPI.hooks._rippedStaticProperties[compiledName];
if (item["$$constructor$$"]) { if (item?.["$$constructor$$"]) {
//Class does not have any hand written constructors //Class does not have any hand written constructors
//Eg: class MyClass {} //Eg: class MyClass {}
ModAPI.hooks._classMap[classId].constructors.push(item["$$constructor$$"]); ModAPI.hooks._classMap[compiledName].constructors.push(item["$$constructor$$"]);
} else { } else {
//Class has hand written constructors, we need to search in the stash //Class has hand written constructors, we need to search in the stash
ModAPI.hooks._rippedConstructorKeys.forEach(constructor => { ModAPI.hooks._rippedConstructorKeys.forEach(constructor => {
if (constructor.startsWith(compiledName + "__init_") && !constructor.includes("$lambda$")) { if (constructor.startsWith(compiledName + "__init_") && !constructor.includes("$lambda$")) {
ModAPI.hooks._classMap[classId].constructors.push(ModAPI.hooks._rippedConstructors[constructor]); ModAPI.hooks._classMap[compiledName].constructors.push(ModAPI.hooks._rippedConstructors[constructor]);
} }
}); });
} }
ModAPI.hooks._rippedMethodKeys.forEach((method) => { ModAPI.hooks._rippedMethodKeys.forEach((method) => {
if (method.startsWith(compiledName + "_") && !method.includes("$lambda$")) { if (method.startsWith(compiledName + "_") && !method.includes("$lambda$")) {
var targetMethodMap = ModAPI.hooks._classMap[classId].methods; var targetMethodMap = ModAPI.hooks._classMap[compiledName].methods;
if (ModAPI.hooks._rippedMethodTypeMap[method] === "static") { if (ModAPI.hooks._rippedMethodTypeMap[method] === "static") {
targetMethodMap = ModAPI.hooks._classMap[classId].staticMethods; targetMethodMap = ModAPI.hooks._classMap[compiledName].staticMethods;
} }
targetMethodMap[method.replace(compiledName + "_", "")] = { targetMethodMap[method.replace(compiledName + "_", "")] = {
method: ModAPI.hooks.methods[method], method: ModAPI.hooks.methods[method],
@ -486,14 +555,18 @@ var main;(function(){`
}; };
} }
}); });
}
});
}); });
console.log("[ModAPI] Regenerated hook classmap.");
} }
ModAPI.hooks.regenerateClassMap(); ModAPI.hooks.regenerateClassMap();
var reloadDeprecationWarnings = 0; var reloadDeprecationWarnings = 0;
const TeaVM_to_BaseData_ProxyConf = { const TeaVM_to_BaseData_ProxyConf = {
get(target, prop, receiver) { get(target, prop, receiver) {
if (prop === "getRef") {
return function () {
return target;
}
}
if (prop === "reload") { if (prop === "reload") {
return function () { return function () {
if (reloadDeprecationWarnings < 10) { if (reloadDeprecationWarnings < 10) {
@ -527,6 +600,11 @@ var main;(function(){`
if (outputValue && typeof outputValue === "object" && !Array.isArray(outputValue)) { if (outputValue && typeof outputValue === "object" && !Array.isArray(outputValue)) {
return new Proxy(outputValue, TeaVM_to_Recursive_BaseData_ProxyConf); return new Proxy(outputValue, TeaVM_to_Recursive_BaseData_ProxyConf);
} }
if (prop === "getRef") {
return function () {
return target;
}
}
return outputValue; return outputValue;
}, },
set(object, prop, value) { set(object, prop, value) {
@ -536,6 +614,11 @@ var main;(function(){`
} }
const TeaVM_to_Recursive_BaseData_ProxyConf = { const TeaVM_to_Recursive_BaseData_ProxyConf = {
get(target, prop, receiver) { get(target, prop, receiver) {
if (prop === "getRef") {
return function () {
return target;
}
}
if (prop === "reload") { if (prop === "reload") {
return function () { return function () {
if (reloadDeprecationWarnings < 10) { if (reloadDeprecationWarnings < 10) {
@ -566,25 +649,44 @@ var main;(function(){`
return true; return true;
}, },
}; };
const StaticProps_ProxyConf = {
get(target, prop, receiver) {
var outProp = prop;
var outputValue = Reflect.get(target, outProp, receiver);
if (outputValue && typeof outputValue === "object" && Array.isArray(outputValue.data) && typeof outputValue.type === "function") {
return new Proxy(outputValue.data, TeaVMArray_To_Recursive_BaseData_ProxyConf);
}
if (outputValue && typeof outputValue === "object" && !Array.isArray(outputValue)) {
return new Proxy(outputValue, TeaVM_to_Recursive_BaseData_ProxyConf);
}
return outputValue;
},
set(object, prop, value) {
var outProp = prop;
object[outProp] = value;
return true;
},
};
ModAPI.util.TeaVM_to_BaseData_ProxyConf = TeaVM_to_BaseData_ProxyConf; ModAPI.util.TeaVM_to_BaseData_ProxyConf = TeaVM_to_BaseData_ProxyConf;
ModAPI.util.TeaVMArray_To_Recursive_BaseData_ProxyConf = TeaVMArray_To_Recursive_BaseData_ProxyConf; ModAPI.util.TeaVMArray_To_Recursive_BaseData_ProxyConf = TeaVMArray_To_Recursive_BaseData_ProxyConf;
ModAPI.util.TeaVM_to_Recursive_BaseData_ProxyConf = TeaVM_to_Recursive_BaseData_ProxyConf; ModAPI.util.TeaVM_to_Recursive_BaseData_ProxyConf = TeaVM_to_Recursive_BaseData_ProxyConf;
ModAPI.util.StaticProps_ProxyConf = StaticProps_ProxyConf;
ModAPI.required = new Set(); ModAPI.required = new Set();
ModAPI.events = {}; ModAPI.events = {};
ModAPI.events.types = ["event"]; ModAPI.events.types = ["event"];
ModAPI.events.listeners = { "event": [] }; ModAPI.events.listeners = { "event": [] };
ModAPI.addEventListener = function addEventListener(name, callback) { ModAPI.addEventListener = function addEventListener(name, callback) {
if (!callback) { if (!callback || typeof callback !== "function") {
throw new Error("Invalid callback!"); throw new Error("[ModAPI] Invalid callback!");
} }
if (ModAPI.events.types.includes(name)) { if (ModAPI.events.types.includes(name)) {
if (!Array.isArray(ModAPI.events.listeners[name])) { if (!Array.isArray(ModAPI.events.listeners[name])) {
ModAPI.events.listeners[name] = []; ModAPI.events.listeners[name] = [];
} }
ModAPI.events.listeners[name].push(callback); ModAPI.events.listeners[name].push(callback);
console.log("Added new event listener."); console.log("[ModAPI] Added new event listener.");
} else { } else {
throw new Error("This event does not exist!"); throw new Error("[ModAPI] This event does not exist!");
} }
}; };
@ -599,19 +701,20 @@ var main;(function(){`
if (!slow) { if (!slow) {
if (targetArr.indexOf(func) !== -1) { if (targetArr.indexOf(func) !== -1) {
targetArr.splice(targetArr.indexOf(func), 1); targetArr.splice(targetArr.indexOf(func), 1);
console.log("Removed event listener."); console.log("[ModAPI] Removed event listener.");
} }
} else { } else {
var functionString = func.toString(); var functionString = func.toString();
targetArr.forEach((f, i) => { targetArr.forEach((f, i) => {
if (f.toString() === functionString) { if (f.toString() === functionString) {
targetArr.splice(i, 1); targetArr.splice(i, 1);
console.log("Removed event listener."); console.log("[ModAPI] Removed event listener.");
} }
}); });
} }
}; };
ModAPI.events.newEvent = function newEvent(name) { ModAPI.events.newEvent = function newEvent(name, side) {
console.log("[ModAPI] Registered "+side+" event: "+name);
ModAPI.events.types.push(name); ModAPI.events.types.push(name);
}; };
@ -642,7 +745,7 @@ var main;(function(){`
func({ event: name, data: data }); func({ event: name, data: data });
}); });
}; };
ModAPI.events.newEvent("update"); ModAPI.events.newEvent("update", "client");
ModAPI.require = function (module) { ModAPI.require = function (module) {
ModAPI.required.add(module); ModAPI.required.add(module);
@ -690,7 +793,7 @@ var main;(function(){`
var v = typeof param === "object" ? param.msg : (param + ""); var v = typeof param === "object" ? param.msg : (param + "");
v ||= ""; v ||= "";
var jclString = ModAPI.util.string(v); var jclString = ModAPI.util.string(v);
ModAPI.hooks.methods["nmcg_GuiNewChat_printChatMessage"](ModAPI.javaClient.$ingameGUI.$persistantChatGUI, ModAPI.hooks._classMap["net.minecraft.util.ChatComponentText"].constructors[0](jclString)); ModAPI.hooks.methods["nmcg_GuiNewChat_printChatMessage"](ModAPI.javaClient.$ingameGUI.$persistantChatGUI, ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.util.ChatComponentText")].constructors[0](jclString));
} }
const updateMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.client.entity.EntityPlayerSP", "onUpdate"); const updateMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.client.entity.EntityPlayerSP", "onUpdate");
@ -721,7 +824,7 @@ var main;(function(){`
return x; return x;
}; };
ModAPI.events.newEvent("sendchatmessage"); ModAPI.events.newEvent("sendchatmessage", "client");
const sendChatMessageMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.client.entity.EntityPlayerSP", "sendChatMessage"); const sendChatMessageMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.client.entity.EntityPlayerSP", "sendChatMessage");
const sendChatMessage = ModAPI.hooks.methods[sendChatMessageMethodName]; const sendChatMessage = ModAPI.hooks.methods[sendChatMessageMethodName];
ModAPI.hooks.methods[sendChatMessageMethodName] = function ($this, $message) { ModAPI.hooks.methods[sendChatMessageMethodName] = function ($this, $message) {
@ -739,7 +842,7 @@ var main;(function(){`
return sendChatMessage.apply(this, [$this, $message]); return sendChatMessage.apply(this, [$this, $message]);
} }
ModAPI.events.newEvent("tick"); ModAPI.events.newEvent("tick", "server");
const serverTickMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.server.MinecraftServer", "tick"); const serverTickMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.server.MinecraftServer", "tick");
const serverTickMethod = ModAPI.hooks.methods[serverTickMethodName]; const serverTickMethod = ModAPI.hooks.methods[serverTickMethodName];
ModAPI.hooks.methods[serverTickMethodName] = function ($this) { ModAPI.hooks.methods[serverTickMethodName] = function ($this) {
@ -751,7 +854,7 @@ var main;(function(){`
return serverTickMethod.apply(this, [$this]); return serverTickMethod.apply(this, [$this]);
} }
ModAPI.events.newEvent("serverstart"); ModAPI.events.newEvent("serverstart", "server");
const serverStartMethodName = ModAPI.util.getMethodFromPackage("net.lax1dude.eaglercraft.v1_8.sp.server.EaglerMinecraftServer", "startServer"); const serverStartMethodName = ModAPI.util.getMethodFromPackage("net.lax1dude.eaglercraft.v1_8.sp.server.EaglerMinecraftServer", "startServer");
const serverStartMethod = ModAPI.hooks.methods[serverStartMethodName]; const serverStartMethod = ModAPI.hooks.methods[serverStartMethodName];
ModAPI.hooks.methods[serverStartMethodName] = function ($this) { ModAPI.hooks.methods[serverStartMethodName] = function ($this) {
@ -762,7 +865,7 @@ var main;(function(){`
return x; return x;
} }
ModAPI.events.newEvent("serverstop"); ModAPI.events.newEvent("serverstop", "server");
const serverStopMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.server.MinecraftServer", "stopServer"); const serverStopMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.server.MinecraftServer", "stopServer");
const serverStopMethod = ModAPI.hooks.methods[serverStopMethodName]; const serverStopMethod = ModAPI.hooks.methods[serverStopMethodName];
ModAPI.hooks.methods[serverStopMethodName] = function ($this) { ModAPI.hooks.methods[serverStopMethodName] = function ($this) {
@ -771,11 +874,52 @@ var main;(function(){`
ModAPI.events.callEvent("serverstop", {}); ModAPI.events.callEvent("serverstop", {});
return x; return x;
} }
ModAPI.events.newEvent("receivechatmessage", "server");
const receiveChatMessageMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.network.play.client.C01PacketChatMessage", "processPacket");
const receiveChatMessageMethod = ModAPI.hooks.methods[receiveChatMessageMethodName];
ModAPI.hooks.methods[receiveChatMessageMethodName] = function (...args) {
var $this = args[0];
var data = {
preventDefault: false,
message: ModAPI.util.jclStrToJsStr($this.$message3)
}
ModAPI.events.callEvent("sendchatmessage", data);
if (data.preventDefault) {
return;
}
if (typeof data.message === "string") {
ModAPI.util.setStringContent($this.$message3, data.message)
}
var x = receiveChatMessageMethod.apply(this, args);
return x;
}
ModAPI.events.newEvent("processcommand", "server");
const processCommandMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.command.CommandHandler", "executeCommand");
const processCommandMethod = ModAPI.hooks.methods[processCommandMethodName];
ModAPI.hooks.methods[processCommandMethodName] = function ($this, $sender, $rawCommand) {
var data = {
preventDefault: false,
sender: new Proxy($sender, TeaVM_to_Recursive_BaseData_ProxyConf),
command: ModAPI.util.jclStrToJsStr($rawCommand)
}
ModAPI.events.callEvent("processcommand", data);
if (data.preventDefault) {
return;
}
if (typeof data.command === "string") {
ModAPI.util.setStringContent($rawCommand, data.command)
}
var x = processCommandMethod.apply(this, [$this, $sender, $rawCommand]);
return x;
}
ModAPI.items = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.init.Items")].staticVariables, StaticProps_ProxyConf);
ModAPI.blocks = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.init.Blocks")].staticVariables, StaticProps_ProxyConf);
})();`; })();`;
</script> </script>
<script> <script>
globalThis.modapi_guikit = ``; globalThis.modapi_guikit = ``;
</script> </script>

View File

@ -33,7 +33,7 @@
name += "_" + methodName; name += "_" + methodName;
return name; return name;
} }
ModAPI.util.getCompiledNameFromPackage = function (classId) { ModAPI.util.getCompiledNameFromPackage = ModAPI.util.getCompiledName = function (classId) {
var name = ""; var name = "";
var classStuff = classId.split("."); var classStuff = classId.split(".");
classStuff.forEach((component, i) => { classStuff.forEach((component, i) => {
@ -47,57 +47,84 @@
} }
ModAPI.version = "v2.0"; ModAPI.version = "v2.0";
ModAPI.flavour = "injector"; ModAPI.flavour = "injector";
ModAPI.GNU = "terry pratchett";
ModAPI.credits = ["ZXMushroom63", "radmanplays", "OtterCodes101", "TheIdiotPlays"]; ModAPI.credits = ["ZXMushroom63", "radmanplays", "OtterCodes101", "TheIdiotPlays"];
ModAPI.hooks.regenerateClassMap = function () { ModAPI.hooks.regenerateClassMap = function () {
ModAPI.hooks._rippedConstructorKeys = Object.keys(ModAPI.hooks._rippedConstructors); ModAPI.hooks._rippedConstructorKeys = Object.keys(ModAPI.hooks._rippedConstructors);
ModAPI.hooks._rippedMethodKeys = Object.keys(ModAPI.hooks._rippedMethodTypeMap); ModAPI.hooks._rippedMethodKeys = Object.keys(ModAPI.hooks._rippedMethodTypeMap);
var compiledNames = new Set();
var metaMap = {};
//Loop through ripped metadata passes. Classes obtained through this method have full metadata (superclasses, full names, binary names, actual class)
ModAPI.hooks._rippedData.forEach(block => { ModAPI.hooks._rippedData.forEach(block => {
block.forEach(item => { block.forEach(item => {
if (typeof item === "function") { if (typeof item === "function") {
if (!item.$meta || typeof item.$meta.name !== "string") { if (!item.$meta || typeof item.$meta.name !== "string") {
return; return;
} }
var compiledName = ModAPI.util.getCompiledNameFromPackage(item.$meta.name);
compiledNames.add(compiledName);
metaMap[compiledName] = item;
}
});
});
var classId = item.$meta.name; ModAPI.hooks._rippedConstructorKeys.forEach(constructor => {
var compiledName = ModAPI.util.getCompiledNameFromPackage(classId); if (typeof constructor === "string" && constructor.length > 0) {
//Constructor names are phrased as aaa_Apple__init_3 or similar, the separator is __init_
var constructorData = constructor.split("__init_");
if (constructorData[0] && constructorData[0].includes("_")) {
compiledNames.add(constructorData[0]);
}
}
});
if (!ModAPI.hooks._classMap[classId]) { //Initialise all compiled names into the class map
ModAPI.hooks._classMap[classId] = { compiledNames.forEach(compiledName => {
"name": classId.split(".")[classId.split(".").length - 1], var item = metaMap[compiledName];
var classId = item?.$meta?.name || null;
if (!ModAPI.hooks._classMap[compiledName]) {
ModAPI.hooks._classMap[compiledName] = {
"name": compiledName.split("_")[1],
"id": classId, "id": classId,
"binaryName": item.$meta.binaryName, "binaryName": item?.$meta?.binaryName || null,
"constructors": [], "constructors": [],
"methods": {}, "methods": {},
"staticMethods": {}, "staticMethods": {},
"staticVariables": {}, "staticVariables": {},
"staticVariableNames": [], "staticVariableNames": [],
"class": item, "class": item || null,
"hasMeta": !!item,
"compiledName": compiledName "compiledName": compiledName
} }
} }
if (typeof item.$meta.superclass === "function" && item.$meta.superclass.$meta) { if (typeof item?.$meta?.superclass === "function" && item?.$meta?.superclass?.$meta) {
ModAPI.hooks._classMap[classId].superclass = item.$meta.superclass.$meta.name; ModAPI.hooks._classMap[compiledName].superclass = item.$meta.superclass.$meta.name;
} else {
ModAPI.hooks._classMap[compiledName].superclass = null;
} }
ModAPI.hooks._classMap[classId].staticVariableNames = ModAPI.hooks._rippedStaticIndexer[compiledName]; ModAPI.hooks._classMap[compiledName].staticVariableNames = ModAPI.hooks._rippedStaticIndexer[compiledName];
ModAPI.hooks._classMap[classId].staticVariables = ModAPI.hooks._rippedStaticProperties[compiledName]; ModAPI.hooks._classMap[compiledName].staticVariables = ModAPI.hooks._rippedStaticProperties[compiledName];
if (item["$$constructor$$"]) { if (item?.["$$constructor$$"]) {
//Class does not have any hand written constructors //Class does not have any hand written constructors
//Eg: class MyClass {} //Eg: class MyClass {}
ModAPI.hooks._classMap[classId].constructors.push(item["$$constructor$$"]); ModAPI.hooks._classMap[compiledName].constructors.push(item["$$constructor$$"]);
} else { } else {
//Class has hand written constructors, we need to search in the stash //Class has hand written constructors, we need to search in the stash
ModAPI.hooks._rippedConstructorKeys.forEach(constructor => { ModAPI.hooks._rippedConstructorKeys.forEach(constructor => {
if (constructor.startsWith(compiledName + "__init_") && !constructor.includes("$lambda$")) { if (constructor.startsWith(compiledName + "__init_") && !constructor.includes("$lambda$")) {
ModAPI.hooks._classMap[classId].constructors.push(ModAPI.hooks._rippedConstructors[constructor]); ModAPI.hooks._classMap[compiledName].constructors.push(ModAPI.hooks._rippedConstructors[constructor]);
} }
}); });
} }
ModAPI.hooks._rippedMethodKeys.forEach((method) => { ModAPI.hooks._rippedMethodKeys.forEach((method) => {
if (method.startsWith(compiledName + "_") && !method.includes("$lambda$")) { if (method.startsWith(compiledName + "_") && !method.includes("$lambda$")) {
var targetMethodMap = ModAPI.hooks._classMap[classId].methods; var targetMethodMap = ModAPI.hooks._classMap[compiledName].methods;
if (ModAPI.hooks._rippedMethodTypeMap[method] === "static") { if (ModAPI.hooks._rippedMethodTypeMap[method] === "static") {
targetMethodMap = ModAPI.hooks._classMap[classId].staticMethods; targetMethodMap = ModAPI.hooks._classMap[compiledName].staticMethods;
} }
targetMethodMap[method.replace(compiledName + "_", "")] = { targetMethodMap[method.replace(compiledName + "_", "")] = {
method: ModAPI.hooks.methods[method], method: ModAPI.hooks.methods[method],
@ -108,9 +135,8 @@
}; };
} }
}); });
}
});
}); });
console.log("[ModAPI] Regenerated hook classmap.");
} }
ModAPI.hooks.regenerateClassMap(); ModAPI.hooks.regenerateClassMap();
var reloadDeprecationWarnings = 0; var reloadDeprecationWarnings = 0;
@ -131,9 +157,6 @@
} }
var outProp = "$" + prop; var outProp = "$" + prop;
if (target["__modapi_noprefix__"]) {
outProp = prop;
}
var outputValue = Reflect.get(target, outProp, receiver); var outputValue = Reflect.get(target, outProp, receiver);
if (outputValue && typeof outputValue === "object" && Array.isArray(outputValue.data) && typeof outputValue.type === "function") { if (outputValue && typeof outputValue === "object" && Array.isArray(outputValue.data) && typeof outputValue.type === "function") {
return outputValue.data; return outputValue.data;
@ -147,9 +170,6 @@
}, },
set(object, prop, value) { set(object, prop, value) {
var outProp = "$" + prop; var outProp = "$" + prop;
if (target["__modapi_noprefix__"]) {
outProp = prop;
}
object[outProp] = value; object[outProp] = value;
return true; return true;
}, },
@ -189,9 +209,6 @@
} }
var outProp = "$" + prop; var outProp = "$" + prop;
if (target["__modapi_noprefix__"]) {
outProp = prop;
}
var outputValue = Reflect.get(target, outProp, receiver); var outputValue = Reflect.get(target, outProp, receiver);
if (outputValue && typeof outputValue === "object" && Array.isArray(outputValue.data) && typeof outputValue.type === "function") { if (outputValue && typeof outputValue === "object" && Array.isArray(outputValue.data) && typeof outputValue.type === "function") {
return new Proxy(outputValue.data, TeaVMArray_To_Recursive_BaseData_ProxyConf); return new Proxy(outputValue.data, TeaVMArray_To_Recursive_BaseData_ProxyConf);
@ -208,9 +225,24 @@
}, },
set(object, prop, value) { set(object, prop, value) {
var outProp = "$" + prop; var outProp = "$" + prop;
if (target["__modapi_noprefix__"]) { object[outProp] = value;
outProp = prop; return true;
},
};
const StaticProps_ProxyConf = {
get(target, prop, receiver) {
var outProp = prop;
var outputValue = Reflect.get(target, outProp, receiver);
if (outputValue && typeof outputValue === "object" && Array.isArray(outputValue.data) && typeof outputValue.type === "function") {
return new Proxy(outputValue.data, TeaVMArray_To_Recursive_BaseData_ProxyConf);
} }
if (outputValue && typeof outputValue === "object" && !Array.isArray(outputValue)) {
return new Proxy(outputValue, TeaVM_to_Recursive_BaseData_ProxyConf);
}
return outputValue;
},
set(object, prop, value) {
var outProp = prop;
object[outProp] = value; object[outProp] = value;
return true; return true;
}, },
@ -218,22 +250,23 @@
ModAPI.util.TeaVM_to_BaseData_ProxyConf = TeaVM_to_BaseData_ProxyConf; ModAPI.util.TeaVM_to_BaseData_ProxyConf = TeaVM_to_BaseData_ProxyConf;
ModAPI.util.TeaVMArray_To_Recursive_BaseData_ProxyConf = TeaVMArray_To_Recursive_BaseData_ProxyConf; ModAPI.util.TeaVMArray_To_Recursive_BaseData_ProxyConf = TeaVMArray_To_Recursive_BaseData_ProxyConf;
ModAPI.util.TeaVM_to_Recursive_BaseData_ProxyConf = TeaVM_to_Recursive_BaseData_ProxyConf; ModAPI.util.TeaVM_to_Recursive_BaseData_ProxyConf = TeaVM_to_Recursive_BaseData_ProxyConf;
ModAPI.util.StaticProps_ProxyConf = StaticProps_ProxyConf;
ModAPI.required = new Set(); ModAPI.required = new Set();
ModAPI.events = {}; ModAPI.events = {};
ModAPI.events.types = ["event"]; ModAPI.events.types = ["event"];
ModAPI.events.listeners = { "event": [] }; ModAPI.events.listeners = { "event": [] };
ModAPI.addEventListener = function addEventListener(name, callback) { ModAPI.addEventListener = function addEventListener(name, callback) {
if (!callback) { if (!callback || typeof callback !== "function") {
throw new Error("Invalid callback!"); throw new Error("[ModAPI] Invalid callback!");
} }
if (ModAPI.events.types.includes(name)) { if (ModAPI.events.types.includes(name)) {
if (!Array.isArray(ModAPI.events.listeners[name])) { if (!Array.isArray(ModAPI.events.listeners[name])) {
ModAPI.events.listeners[name] = []; ModAPI.events.listeners[name] = [];
} }
ModAPI.events.listeners[name].push(callback); ModAPI.events.listeners[name].push(callback);
console.log("Added new event listener."); console.log("[ModAPI] Added new event listener.");
} else { } else {
throw new Error("This event does not exist!"); throw new Error("[ModAPI] This event does not exist!");
} }
}; };
@ -248,19 +281,20 @@
if (!slow) { if (!slow) {
if (targetArr.indexOf(func) !== -1) { if (targetArr.indexOf(func) !== -1) {
targetArr.splice(targetArr.indexOf(func), 1); targetArr.splice(targetArr.indexOf(func), 1);
console.log("Removed event listener."); console.log("[ModAPI] Removed event listener.");
} }
} else { } else {
var functionString = func.toString(); var functionString = func.toString();
targetArr.forEach((f, i) => { targetArr.forEach((f, i) => {
if (f.toString() === functionString) { if (f.toString() === functionString) {
targetArr.splice(i, 1); targetArr.splice(i, 1);
console.log("Removed event listener."); console.log("[ModAPI] Removed event listener.");
} }
}); });
} }
}; };
ModAPI.events.newEvent = function newEvent(name) { ModAPI.events.newEvent = function newEvent(name, side) {
console.log("[ModAPI] Registered "+side+" event: "+name);
ModAPI.events.types.push(name); ModAPI.events.types.push(name);
}; };
@ -291,7 +325,7 @@
func({ event: name, data: data }); func({ event: name, data: data });
}); });
}; };
ModAPI.events.newEvent("update"); ModAPI.events.newEvent("update", "client");
ModAPI.require = function (module) { ModAPI.require = function (module) {
ModAPI.required.add(module); ModAPI.required.add(module);
@ -339,7 +373,7 @@
var v = typeof param === "object" ? param.msg : (param + ""); var v = typeof param === "object" ? param.msg : (param + "");
v ||= ""; v ||= "";
var jclString = ModAPI.util.string(v); var jclString = ModAPI.util.string(v);
ModAPI.hooks.methods["nmcg_GuiNewChat_printChatMessage"](ModAPI.javaClient.$ingameGUI.$persistantChatGUI, ModAPI.hooks._classMap["net.minecraft.util.ChatComponentText"].constructors[0](jclString)); ModAPI.hooks.methods["nmcg_GuiNewChat_printChatMessage"](ModAPI.javaClient.$ingameGUI.$persistantChatGUI, ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.util.ChatComponentText")].constructors[0](jclString));
} }
const updateMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.client.entity.EntityPlayerSP", "onUpdate"); const updateMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.client.entity.EntityPlayerSP", "onUpdate");
@ -370,7 +404,7 @@
return x; return x;
}; };
ModAPI.events.newEvent("sendchatmessage"); ModAPI.events.newEvent("sendchatmessage", "client");
const sendChatMessageMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.client.entity.EntityPlayerSP", "sendChatMessage"); const sendChatMessageMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.client.entity.EntityPlayerSP", "sendChatMessage");
const sendChatMessage = ModAPI.hooks.methods[sendChatMessageMethodName]; const sendChatMessage = ModAPI.hooks.methods[sendChatMessageMethodName];
ModAPI.hooks.methods[sendChatMessageMethodName] = function ($this, $message) { ModAPI.hooks.methods[sendChatMessageMethodName] = function ($this, $message) {
@ -388,7 +422,7 @@
return sendChatMessage.apply(this, [$this, $message]); return sendChatMessage.apply(this, [$this, $message]);
} }
ModAPI.events.newEvent("tick"); ModAPI.events.newEvent("tick", "server");
const serverTickMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.server.MinecraftServer", "tick"); const serverTickMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.server.MinecraftServer", "tick");
const serverTickMethod = ModAPI.hooks.methods[serverTickMethodName]; const serverTickMethod = ModAPI.hooks.methods[serverTickMethodName];
ModAPI.hooks.methods[serverTickMethodName] = function ($this) { ModAPI.hooks.methods[serverTickMethodName] = function ($this) {
@ -400,7 +434,7 @@
return serverTickMethod.apply(this, [$this]); return serverTickMethod.apply(this, [$this]);
} }
ModAPI.events.newEvent("serverstart"); ModAPI.events.newEvent("serverstart", "server");
const serverStartMethodName = ModAPI.util.getMethodFromPackage("net.lax1dude.eaglercraft.v1_8.sp.server.EaglerMinecraftServer", "startServer"); const serverStartMethodName = ModAPI.util.getMethodFromPackage("net.lax1dude.eaglercraft.v1_8.sp.server.EaglerMinecraftServer", "startServer");
const serverStartMethod = ModAPI.hooks.methods[serverStartMethodName]; const serverStartMethod = ModAPI.hooks.methods[serverStartMethodName];
ModAPI.hooks.methods[serverStartMethodName] = function ($this) { ModAPI.hooks.methods[serverStartMethodName] = function ($this) {
@ -411,7 +445,7 @@
return x; return x;
} }
ModAPI.events.newEvent("serverstop"); ModAPI.events.newEvent("serverstop", "server");
const serverStopMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.server.MinecraftServer", "stopServer"); const serverStopMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.server.MinecraftServer", "stopServer");
const serverStopMethod = ModAPI.hooks.methods[serverStopMethodName]; const serverStopMethod = ModAPI.hooks.methods[serverStopMethodName];
ModAPI.hooks.methods[serverStopMethodName] = function ($this) { ModAPI.hooks.methods[serverStopMethodName] = function ($this) {
@ -420,4 +454,47 @@
ModAPI.events.callEvent("serverstop", {}); ModAPI.events.callEvent("serverstop", {});
return x; return x;
} }
ModAPI.events.newEvent("receivechatmessage", "server");
const receiveChatMessageMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.network.play.client.C01PacketChatMessage", "processPacket");
const receiveChatMessageMethod = ModAPI.hooks.methods[receiveChatMessageMethodName];
ModAPI.hooks.methods[receiveChatMessageMethodName] = function (...args) {
var $this = args[0];
var data = {
preventDefault: false,
message: ModAPI.util.jclStrToJsStr($this.$message3)
}
ModAPI.events.callEvent("sendchatmessage", data);
if (data.preventDefault) {
return;
}
if (typeof data.message === "string") {
ModAPI.util.setStringContent($this.$message3, data.message)
}
var x = receiveChatMessageMethod.apply(this, args);
return x;
}
ModAPI.events.newEvent("processcommand", "server");
const processCommandMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.command.CommandHandler", "executeCommand");
const processCommandMethod = ModAPI.hooks.methods[processCommandMethodName];
ModAPI.hooks.methods[processCommandMethodName] = function ($this, $sender, $rawCommand) {
var data = {
preventDefault: false,
sender: new Proxy($sender, TeaVM_to_Recursive_BaseData_ProxyConf),
command: ModAPI.util.jclStrToJsStr($rawCommand)
}
ModAPI.events.callEvent("processcommand", data);
if (data.preventDefault) {
return;
}
if (typeof data.command === "string") {
ModAPI.util.setStringContent($rawCommand, data.command)
}
var x = processCommandMethod.apply(this, [$this, $sender, $rawCommand]);
return x;
}
ModAPI.items = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.init.Items")].staticVariables, StaticProps_ProxyConf);
ModAPI.blocks = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.init.Blocks")].staticVariables, StaticProps_ProxyConf);
})(); })();