diff --git a/examplemods/timescale_command.js b/examplemods/timescale_command.js
index 2839eec..4e45e37 100644
--- a/examplemods/timescale_command.js
+++ b/examplemods/timescale_command.js
@@ -12,13 +12,13 @@
}
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 () {
globalThis.timeScale = 1n;
globalThis.timeScaleDividing = false;
- PluginAPI.addEventListener("handleslashcommand", (event) => {
+ PluginAPI.addEventListener("processcommand", (event) => {
if (event.command.toLowerCase().startsWith("/timescale")) {
var speed = parseFloat(event.command.split(" ")[1]);
if (!speed) {
@@ -45,5 +45,4 @@
}
};
});
-
})();
\ No newline at end of file
diff --git a/injector.html b/injector.html
index ec3c62b..c2c59e1 100644
--- a/injector.html
+++ b/injector.html
@@ -26,8 +26,7 @@
EaglerForge Injector
Adds ModAPI with more functionality (adds hooking into functions, exposes
- all classes, etc) to unminified unobfuscated EaglercraftX
- builds.
+ all classes, etc) to unminified unobfuscated EaglercraftX builds.
@@ -208,7 +207,7 @@ ModAPI.hooks._postInit ||= ()=>{};
ModAPI.hooks._rippedStaticProperties ||= {};
ModAPI.hooks._rippedStaticIndexer ||= {};
`;
-var freezeCallstack = `if(ModAPI.hooks.freezeCallstack){return false};`;
+ var freezeCallstack = `if(ModAPI.hooks.freezeCallstack){return false};`;
document.querySelector("#giveme").addEventListener("click", () => {
if (
!document.querySelector("input").files ||
@@ -248,17 +247,29 @@ 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.isResuming()`,
+ (match) => {
+ return freezeCallstack + match;
+ }
+ );
- patchedFile = patchedFile.replaceAll(`return thread != null && thread.isSuspending();`, (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.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">`,
@@ -302,9 +313,7 @@ var main;(function(){`
return ModAPI.hooks.methods[\`${fullName}\`].apply(this, args);
}
ModAPI.hooks._rippedMethodTypeMap[\`${fullName}\`] = \`${
- match.endsWith("($this")
- ? "instance"
- : "static"
+ match.endsWith("($this") ? "instance" : "static"
}\`;
ModAPI.hooks.methods[\`${fullName}\`]=` +
match.replace(fullName + "(", "(")
@@ -312,41 +321,68 @@ var main;(function(){`
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() {
- patchedFile = patchedFile.replaceAll(/var \S+?_\S+? = \$rt_classWithoutFields\(\S*?\);/gm, function (match) {
- var prefix = match.replaceAll(/ = \$rt_classWithoutFields\(\S*?\);/gm, "");
- var entries = [];
- staticVariables.forEach(entry => {
- if (entry.startsWith(prefix)) {
- var variableName = entry.replace("var ", "").replace(" = null;", "");
- var segments = variableName.split("_");
- segments.splice(0, 2);
- var name = segments.join("_");
- entries.push({
- "name": name,
- "variable": variableName,
- });
- }
- });
- var getComponents = "";
- entries.forEach(entry => {
- getComponents+= `
+ patchedFile = patchedFile.replaceAll(
+ /var \S+?_\S+? = \$rt_classWithoutFields\(\S*?\);/gm,
+ function (match) {
+ var prefix = match.replaceAll(
+ / = \$rt_classWithoutFields\(\S*?\);/gm,
+ ""
+ );
+ var entries = [];
+ staticVariables.forEach((entry) => {
+ if (entry.startsWith(prefix)) {
+ var variableName = entry
+ .replace("var ", "")
+ .replace(" = null;", "");
+ var segments = variableName.split("_");
+ segments.splice(0, 2);
+ var name = segments.join("_");
+ entries.push({
+ name: name,
+ variable: variableName,
+ });
+ }
+ });
+ var getComponents = "";
+ entries.forEach((entry) => {
+ getComponents += `
case \`${entry.name}\`:
return ${entry.variable};
- break;`
- });
+ break;`;
+ });
- var setComponents = "";
- entries.forEach(entry => {
- setComponents+= `
+ var setComponents = "";
+ entries.forEach((entry) => {
+ setComponents += `
case \`${entry.name}\`:
${entry.variable} = c;
break;`;
- });
- var proxy = `
- ModAPI.hooks._rippedStaticIndexer[\`${prefix.replace("var ", "")}\`] = [${entries.flatMap((x)=>{return "\"" + x.name + "\""}).join(",")}];
- ModAPI.hooks._rippedStaticProperties[\`${prefix.replace("var ", "")}\`] = new Proxy({}, {
+ });
+ var proxy = `
+ ModAPI.hooks._rippedStaticIndexer[\`${prefix.replace(
+ "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) {
switch (b) {
${getComponents}
@@ -359,13 +395,19 @@ var main;(function(){`
}
});`;
return match + proxy;
- });
- patchedFile = patchedFile.replaceAll(/function \$rt_\S+?\(/gm, (match)=>{
- var name = match.replace("function ", "");
- name = name.substring(0, name.length - 1);
- return `ModAPI.hooks._teavm[\`${name}\`]=${name};
- ` + match;
- });
+ }
+ );
+ patchedFile = patchedFile.replaceAll(
+ /function \$rt_\S+?\(/gm,
+ (match) => {
+ var name = match.replace("function ", "");
+ name = name.substring(0, name.length - 1);
+ return (
+ `ModAPI.hooks._teavm[\`${name}\`]=${name};
+ ` + match
+ );
+ }
+ );
patchedFile = patchedFile.replaceAll(/main\(\);\s*?}/gm, (match) => {
return match.replace("main();", "main();ModAPI.hooks._postInit();");
});
@@ -411,7 +453,7 @@ var main;(function(){`
name += "_" + methodName;
return name;
}
- ModAPI.util.getCompiledNameFromPackage = function (classId) {
+ ModAPI.util.getCompiledNameFromPackage = ModAPI.util.getCompiledName = function (classId) {
var name = "";
var classStuff = classId.split(".");
classStuff.forEach((component, i) => {
@@ -425,75 +467,106 @@ var main;(function(){`
}
ModAPI.version = "v2.0";
ModAPI.flavour = "injector";
+ ModAPI.GNU = "terry pratchett";
ModAPI.credits = ["ZXMushroom63", "radmanplays", "OtterCodes101", "TheIdiotPlays"];
ModAPI.hooks.regenerateClassMap = function () {
ModAPI.hooks._rippedConstructorKeys = Object.keys(ModAPI.hooks._rippedConstructors);
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 => {
block.forEach(item => {
if (typeof item === "function") {
if (!item.$meta || typeof item.$meta.name !== "string") {
return;
}
-
- var classId = item.$meta.name;
- var compiledName = ModAPI.util.getCompiledNameFromPackage(classId);
-
-
- if (!ModAPI.hooks._classMap[classId]) {
- ModAPI.hooks._classMap[classId] = {
- "name": classId.split(".")[classId.split(".").length - 1],
- "id": classId,
- "binaryName": item.$meta.binaryName,
- "constructors": [],
- "methods": {},
- "staticMethods": {},
- "staticVariables": {},
- "staticVariableNames": [],
- "class": item,
- "compiledName": compiledName
- }
- }
- if (typeof item.$meta.superclass === "function" && item.$meta.superclass.$meta) {
- ModAPI.hooks._classMap[classId].superclass = item.$meta.superclass.$meta.name;
- }
- ModAPI.hooks._classMap[classId].staticVariableNames = ModAPI.hooks._rippedStaticIndexer[compiledName];
- ModAPI.hooks._classMap[classId].staticVariables = ModAPI.hooks._rippedStaticProperties[compiledName];
- if (item["$$constructor$$"]) {
- //Class does not have any hand written constructors
- //Eg: class MyClass {}
- ModAPI.hooks._classMap[classId].constructors.push(item["$$constructor$$"]);
- } else {
- //Class has hand written constructors, we need to search in the stash
- ModAPI.hooks._rippedConstructorKeys.forEach(constructor => {
- if (constructor.startsWith(compiledName + "__init_") && !constructor.includes("$lambda$")) {
- ModAPI.hooks._classMap[classId].constructors.push(ModAPI.hooks._rippedConstructors[constructor]);
- }
- });
- }
- ModAPI.hooks._rippedMethodKeys.forEach((method) => {
- if (method.startsWith(compiledName + "_") && !method.includes("$lambda$")) {
- var targetMethodMap = ModAPI.hooks._classMap[classId].methods;
- if (ModAPI.hooks._rippedMethodTypeMap[method] === "static") {
- targetMethodMap = ModAPI.hooks._classMap[classId].staticMethods;
- }
- targetMethodMap[method.replace(compiledName + "_", "")] = {
- method: ModAPI.hooks.methods[method],
- proxiedMethod: function (...args) {
- return ModAPI.hooks.methods[method].apply(this, args);
- },
- methodName: method
- };
- }
- });
+ var compiledName = ModAPI.util.getCompiledNameFromPackage(item.$meta.name);
+ compiledNames.add(compiledName);
+ metaMap[compiledName] = item;
}
});
});
+
+ ModAPI.hooks._rippedConstructorKeys.forEach(constructor => {
+ 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]);
+ }
+ }
+ });
+
+
+ //Initialise all compiled names into the class map
+ compiledNames.forEach(compiledName => {
+ 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,
+ "binaryName": item?.$meta?.binaryName || null,
+ "constructors": [],
+ "methods": {},
+ "staticMethods": {},
+ "staticVariables": {},
+ "staticVariableNames": [],
+ "class": item || null,
+ "hasMeta": !!item,
+ "compiledName": compiledName
+ }
+ }
+ if (typeof item?.$meta?.superclass === "function" && item?.$meta?.superclass?.$meta) {
+ ModAPI.hooks._classMap[compiledName].superclass = item.$meta.superclass.$meta.name;
+ } else {
+ ModAPI.hooks._classMap[compiledName].superclass = null;
+ }
+ ModAPI.hooks._classMap[compiledName].staticVariableNames = ModAPI.hooks._rippedStaticIndexer[compiledName];
+ ModAPI.hooks._classMap[compiledName].staticVariables = ModAPI.hooks._rippedStaticProperties[compiledName];
+ if (item?.["$$constructor$$"]) {
+ //Class does not have any hand written constructors
+ //Eg: class MyClass {}
+ ModAPI.hooks._classMap[compiledName].constructors.push(item["$$constructor$$"]);
+ } else {
+ //Class has hand written constructors, we need to search in the stash
+ ModAPI.hooks._rippedConstructorKeys.forEach(constructor => {
+ if (constructor.startsWith(compiledName + "__init_") && !constructor.includes("$lambda$")) {
+ ModAPI.hooks._classMap[compiledName].constructors.push(ModAPI.hooks._rippedConstructors[constructor]);
+ }
+ });
+ }
+ ModAPI.hooks._rippedMethodKeys.forEach((method) => {
+ if (method.startsWith(compiledName + "_") && !method.includes("$lambda$")) {
+ var targetMethodMap = ModAPI.hooks._classMap[compiledName].methods;
+ if (ModAPI.hooks._rippedMethodTypeMap[method] === "static") {
+ targetMethodMap = ModAPI.hooks._classMap[compiledName].staticMethods;
+ }
+ targetMethodMap[method.replace(compiledName + "_", "")] = {
+ method: ModAPI.hooks.methods[method],
+ proxiedMethod: function (...args) {
+ return ModAPI.hooks.methods[method].apply(this, args);
+ },
+ methodName: method
+ };
+ }
+ });
+ });
+ console.log("[ModAPI] Regenerated hook classmap.");
}
ModAPI.hooks.regenerateClassMap();
var reloadDeprecationWarnings = 0;
const TeaVM_to_BaseData_ProxyConf = {
get(target, prop, receiver) {
+ if (prop === "getRef") {
+ return function () {
+ return target;
+ }
+ }
if (prop === "reload") {
return function () {
if (reloadDeprecationWarnings < 10) {
@@ -527,6 +600,11 @@ var main;(function(){`
if (outputValue && typeof outputValue === "object" && !Array.isArray(outputValue)) {
return new Proxy(outputValue, TeaVM_to_Recursive_BaseData_ProxyConf);
}
+ if (prop === "getRef") {
+ return function () {
+ return target;
+ }
+ }
return outputValue;
},
set(object, prop, value) {
@@ -536,6 +614,11 @@ var main;(function(){`
}
const TeaVM_to_Recursive_BaseData_ProxyConf = {
get(target, prop, receiver) {
+ if (prop === "getRef") {
+ return function () {
+ return target;
+ }
+ }
if (prop === "reload") {
return function () {
if (reloadDeprecationWarnings < 10) {
@@ -566,25 +649,44 @@ var main;(function(){`
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.TeaVMArray_To_Recursive_BaseData_ProxyConf = TeaVMArray_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.events = {};
ModAPI.events.types = ["event"];
ModAPI.events.listeners = { "event": [] };
ModAPI.addEventListener = function addEventListener(name, callback) {
- if (!callback) {
- throw new Error("Invalid callback!");
+ if (!callback || typeof callback !== "function") {
+ throw new Error("[ModAPI] Invalid callback!");
}
if (ModAPI.events.types.includes(name)) {
if (!Array.isArray(ModAPI.events.listeners[name])) {
ModAPI.events.listeners[name] = [];
}
ModAPI.events.listeners[name].push(callback);
- console.log("Added new event listener.");
+ console.log("[ModAPI] Added new event listener.");
} 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 (targetArr.indexOf(func) !== -1) {
targetArr.splice(targetArr.indexOf(func), 1);
- console.log("Removed event listener.");
+ console.log("[ModAPI] Removed event listener.");
}
} else {
var functionString = func.toString();
targetArr.forEach((f, i) => {
if (f.toString() === functionString) {
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);
};
@@ -642,8 +745,8 @@ var main;(function(){`
func({ event: name, data: data });
});
};
- ModAPI.events.newEvent("update");
-
+ ModAPI.events.newEvent("update", "client");
+
ModAPI.require = function (module) {
ModAPI.required.add(module);
};
@@ -690,7 +793,7 @@ var main;(function(){`
var v = typeof param === "object" ? param.msg : (param + "");
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");
@@ -721,7 +824,7 @@ var main;(function(){`
return x;
};
- ModAPI.events.newEvent("sendchatmessage");
+ ModAPI.events.newEvent("sendchatmessage", "client");
const sendChatMessageMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.client.entity.EntityPlayerSP", "sendChatMessage");
const sendChatMessage = ModAPI.hooks.methods[sendChatMessageMethodName];
ModAPI.hooks.methods[sendChatMessageMethodName] = function ($this, $message) {
@@ -739,7 +842,7 @@ var main;(function(){`
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 serverTickMethod = ModAPI.hooks.methods[serverTickMethodName];
ModAPI.hooks.methods[serverTickMethodName] = function ($this) {
@@ -751,7 +854,7 @@ var main;(function(){`
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 serverStartMethod = ModAPI.hooks.methods[serverStartMethodName];
ModAPI.hooks.methods[serverStartMethodName] = function ($this) {
@@ -762,7 +865,7 @@ var main;(function(){`
return x;
}
- ModAPI.events.newEvent("serverstop");
+ ModAPI.events.newEvent("serverstop", "server");
const serverStopMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.server.MinecraftServer", "stopServer");
const serverStopMethod = ModAPI.hooks.methods[serverStopMethodName];
ModAPI.hooks.methods[serverStopMethodName] = function ($this) {
@@ -771,11 +874,52 @@ var main;(function(){`
ModAPI.events.callEvent("serverstop", {});
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);
})();`;
-
-
diff --git a/postinit.js b/postinit.js
index 0bd49a2..c3d3ae9 100644
--- a/postinit.js
+++ b/postinit.js
@@ -33,7 +33,7 @@
name += "_" + methodName;
return name;
}
- ModAPI.util.getCompiledNameFromPackage = function (classId) {
+ ModAPI.util.getCompiledNameFromPackage = ModAPI.util.getCompiledName = function (classId) {
var name = "";
var classStuff = classId.split(".");
classStuff.forEach((component, i) => {
@@ -47,70 +47,96 @@
}
ModAPI.version = "v2.0";
ModAPI.flavour = "injector";
+ ModAPI.GNU = "terry pratchett";
ModAPI.credits = ["ZXMushroom63", "radmanplays", "OtterCodes101", "TheIdiotPlays"];
ModAPI.hooks.regenerateClassMap = function () {
ModAPI.hooks._rippedConstructorKeys = Object.keys(ModAPI.hooks._rippedConstructors);
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 => {
block.forEach(item => {
if (typeof item === "function") {
if (!item.$meta || typeof item.$meta.name !== "string") {
return;
}
-
- var classId = item.$meta.name;
- var compiledName = ModAPI.util.getCompiledNameFromPackage(classId);
-
-
- if (!ModAPI.hooks._classMap[classId]) {
- ModAPI.hooks._classMap[classId] = {
- "name": classId.split(".")[classId.split(".").length - 1],
- "id": classId,
- "binaryName": item.$meta.binaryName,
- "constructors": [],
- "methods": {},
- "staticMethods": {},
- "staticVariables": {},
- "staticVariableNames": [],
- "class": item,
- "compiledName": compiledName
- }
- }
- if (typeof item.$meta.superclass === "function" && item.$meta.superclass.$meta) {
- ModAPI.hooks._classMap[classId].superclass = item.$meta.superclass.$meta.name;
- }
- ModAPI.hooks._classMap[classId].staticVariableNames = ModAPI.hooks._rippedStaticIndexer[compiledName];
- ModAPI.hooks._classMap[classId].staticVariables = ModAPI.hooks._rippedStaticProperties[compiledName];
- if (item["$$constructor$$"]) {
- //Class does not have any hand written constructors
- //Eg: class MyClass {}
- ModAPI.hooks._classMap[classId].constructors.push(item["$$constructor$$"]);
- } else {
- //Class has hand written constructors, we need to search in the stash
- ModAPI.hooks._rippedConstructorKeys.forEach(constructor => {
- if (constructor.startsWith(compiledName + "__init_") && !constructor.includes("$lambda$")) {
- ModAPI.hooks._classMap[classId].constructors.push(ModAPI.hooks._rippedConstructors[constructor]);
- }
- });
- }
- ModAPI.hooks._rippedMethodKeys.forEach((method) => {
- if (method.startsWith(compiledName + "_") && !method.includes("$lambda$")) {
- var targetMethodMap = ModAPI.hooks._classMap[classId].methods;
- if (ModAPI.hooks._rippedMethodTypeMap[method] === "static") {
- targetMethodMap = ModAPI.hooks._classMap[classId].staticMethods;
- }
- targetMethodMap[method.replace(compiledName + "_", "")] = {
- method: ModAPI.hooks.methods[method],
- proxiedMethod: function (...args) {
- return ModAPI.hooks.methods[method].apply(this, args);
- },
- methodName: method
- };
- }
- });
+ var compiledName = ModAPI.util.getCompiledNameFromPackage(item.$meta.name);
+ compiledNames.add(compiledName);
+ metaMap[compiledName] = item;
}
});
});
+
+ ModAPI.hooks._rippedConstructorKeys.forEach(constructor => {
+ 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]);
+ }
+ }
+ });
+
+
+ //Initialise all compiled names into the class map
+ compiledNames.forEach(compiledName => {
+ 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,
+ "binaryName": item?.$meta?.binaryName || null,
+ "constructors": [],
+ "methods": {},
+ "staticMethods": {},
+ "staticVariables": {},
+ "staticVariableNames": [],
+ "class": item || null,
+ "hasMeta": !!item,
+ "compiledName": compiledName
+ }
+ }
+ if (typeof item?.$meta?.superclass === "function" && item?.$meta?.superclass?.$meta) {
+ ModAPI.hooks._classMap[compiledName].superclass = item.$meta.superclass.$meta.name;
+ } else {
+ ModAPI.hooks._classMap[compiledName].superclass = null;
+ }
+ ModAPI.hooks._classMap[compiledName].staticVariableNames = ModAPI.hooks._rippedStaticIndexer[compiledName];
+ ModAPI.hooks._classMap[compiledName].staticVariables = ModAPI.hooks._rippedStaticProperties[compiledName];
+ if (item?.["$$constructor$$"]) {
+ //Class does not have any hand written constructors
+ //Eg: class MyClass {}
+ ModAPI.hooks._classMap[compiledName].constructors.push(item["$$constructor$$"]);
+ } else {
+ //Class has hand written constructors, we need to search in the stash
+ ModAPI.hooks._rippedConstructorKeys.forEach(constructor => {
+ if (constructor.startsWith(compiledName + "__init_") && !constructor.includes("$lambda$")) {
+ ModAPI.hooks._classMap[compiledName].constructors.push(ModAPI.hooks._rippedConstructors[constructor]);
+ }
+ });
+ }
+ ModAPI.hooks._rippedMethodKeys.forEach((method) => {
+ if (method.startsWith(compiledName + "_") && !method.includes("$lambda$")) {
+ var targetMethodMap = ModAPI.hooks._classMap[compiledName].methods;
+ if (ModAPI.hooks._rippedMethodTypeMap[method] === "static") {
+ targetMethodMap = ModAPI.hooks._classMap[compiledName].staticMethods;
+ }
+ targetMethodMap[method.replace(compiledName + "_", "")] = {
+ method: ModAPI.hooks.methods[method],
+ proxiedMethod: function (...args) {
+ return ModAPI.hooks.methods[method].apply(this, args);
+ },
+ methodName: method
+ };
+ }
+ });
+ });
+ console.log("[ModAPI] Regenerated hook classmap.");
}
ModAPI.hooks.regenerateClassMap();
var reloadDeprecationWarnings = 0;
@@ -131,9 +157,6 @@
}
var outProp = "$" + prop;
- if (target["__modapi_noprefix__"]) {
- outProp = prop;
- }
var outputValue = Reflect.get(target, outProp, receiver);
if (outputValue && typeof outputValue === "object" && Array.isArray(outputValue.data) && typeof outputValue.type === "function") {
return outputValue.data;
@@ -147,9 +170,6 @@
},
set(object, prop, value) {
var outProp = "$" + prop;
- if (target["__modapi_noprefix__"]) {
- outProp = prop;
- }
object[outProp] = value;
return true;
},
@@ -189,9 +209,6 @@
}
var outProp = "$" + prop;
- if (target["__modapi_noprefix__"]) {
- 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);
@@ -208,9 +225,24 @@
},
set(object, prop, value) {
var outProp = "$" + prop;
- if (target["__modapi_noprefix__"]) {
- outProp = prop;
+ object[outProp] = value;
+ 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;
},
@@ -218,22 +250,23 @@
ModAPI.util.TeaVM_to_BaseData_ProxyConf = TeaVM_to_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.StaticProps_ProxyConf = StaticProps_ProxyConf;
ModAPI.required = new Set();
ModAPI.events = {};
ModAPI.events.types = ["event"];
ModAPI.events.listeners = { "event": [] };
ModAPI.addEventListener = function addEventListener(name, callback) {
- if (!callback) {
- throw new Error("Invalid callback!");
+ if (!callback || typeof callback !== "function") {
+ throw new Error("[ModAPI] Invalid callback!");
}
if (ModAPI.events.types.includes(name)) {
if (!Array.isArray(ModAPI.events.listeners[name])) {
ModAPI.events.listeners[name] = [];
}
ModAPI.events.listeners[name].push(callback);
- console.log("Added new event listener.");
+ console.log("[ModAPI] Added new event listener.");
} 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 (targetArr.indexOf(func) !== -1) {
targetArr.splice(targetArr.indexOf(func), 1);
- console.log("Removed event listener.");
+ console.log("[ModAPI] Removed event listener.");
}
} else {
var functionString = func.toString();
targetArr.forEach((f, i) => {
if (f.toString() === functionString) {
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);
};
@@ -291,8 +325,8 @@
func({ event: name, data: data });
});
};
- ModAPI.events.newEvent("update");
-
+ ModAPI.events.newEvent("update", "client");
+
ModAPI.require = function (module) {
ModAPI.required.add(module);
};
@@ -339,7 +373,7 @@
var v = typeof param === "object" ? param.msg : (param + "");
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");
@@ -370,7 +404,7 @@
return x;
};
- ModAPI.events.newEvent("sendchatmessage");
+ ModAPI.events.newEvent("sendchatmessage", "client");
const sendChatMessageMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.client.entity.EntityPlayerSP", "sendChatMessage");
const sendChatMessage = ModAPI.hooks.methods[sendChatMessageMethodName];
ModAPI.hooks.methods[sendChatMessageMethodName] = function ($this, $message) {
@@ -388,7 +422,7 @@
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 serverTickMethod = ModAPI.hooks.methods[serverTickMethodName];
ModAPI.hooks.methods[serverTickMethodName] = function ($this) {
@@ -400,7 +434,7 @@
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 serverStartMethod = ModAPI.hooks.methods[serverStartMethodName];
ModAPI.hooks.methods[serverStartMethodName] = function ($this) {
@@ -411,7 +445,7 @@
return x;
}
- ModAPI.events.newEvent("serverstop");
+ ModAPI.events.newEvent("serverstop", "server");
const serverStopMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.server.MinecraftServer", "stopServer");
const serverStopMethod = ModAPI.hooks.methods[serverStopMethodName];
ModAPI.hooks.methods[serverStopMethodName] = function ($this) {
@@ -420,4 +454,47 @@
ModAPI.events.callEvent("serverstop", {});
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);
})();
\ No newline at end of file