mirror of
https://github.com/eaglerforge/EaglerForgeInjector
synced 2025-07-26 23:39:25 -09:00
Merge branch 'main' of https://github.com/eaglerforge/EaglerForgeInjector
This commit is contained in:
commit
f21266f57f
32
backgroundLogger.js
Normal file
32
backgroundLogger.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
var backgroundLogs = document.createElement("div");
|
||||||
|
backgroundLogs.style = `
|
||||||
|
color: lime;
|
||||||
|
opacity: 0.1;
|
||||||
|
font-family: monospace;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
z-index: -1;
|
||||||
|
pointer-events: none;
|
||||||
|
overflow: none;
|
||||||
|
user-select: none;
|
||||||
|
`;
|
||||||
|
const bgLogsList = [];
|
||||||
|
document.documentElement.appendChild(backgroundLogs);
|
||||||
|
var dirty = true;
|
||||||
|
function backgroundLog(text, unSuppress) {
|
||||||
|
var linesExcess = backgroundLogs.scrollHeight - window.innerHeight;
|
||||||
|
for (i = 0; i < linesExcess; i++) {
|
||||||
|
bgLogsList.shift();
|
||||||
|
}
|
||||||
|
bgLogsList.push(text);
|
||||||
|
dirty = true;
|
||||||
|
if (!unSuppress) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dirty = false;
|
||||||
|
backgroundLogs.innerText = bgLogsList.join("\n");
|
||||||
|
}
|
||||||
|
backgroundLog("Awaiting input...");
|
@ -99,7 +99,10 @@ The ModAPI object has the following methods:
|
|||||||
- Gets the frames per second of the game
|
- Gets the frames per second of the game
|
||||||
- `promisify(asyncJavaMethod: Method | Constructor) : PromisifiedJavaRunner`
|
- `promisify(asyncJavaMethod: Method | Constructor) : PromisifiedJavaRunner`
|
||||||
- Allows running java methods that are @Async/@Async dependent.
|
- Allows running java methods that are @Async/@Async dependent.
|
||||||
- More [PromisifyDocumentation](promisify.md)
|
- More: [PromisifyDocumentation](promisify.md)
|
||||||
|
- `addCredit(category: String, contributor: String, contents: String)`
|
||||||
|
- Lets you easily add credits to Eaglercraft's credits.txt
|
||||||
|
- eg: `ModAPI.addCredit("My Cool Mod", "Username", " - Coded the mod\n - Wrote somne credits")`
|
||||||
|
|
||||||
|
|
||||||
## Handling strings, numbers and booleans to and from java.
|
## Handling strings, numbers and booleans to and from java.
|
||||||
|
@ -11,3 +11,7 @@ Methods:
|
|||||||
- `ModAPI.meta.icon(iconURL: String)`
|
- `ModAPI.meta.icon(iconURL: String)`
|
||||||
- Sets the icon of the mod.
|
- Sets the icon of the mod.
|
||||||
- It can be extremely low res, it will not appear blurry.
|
- It can be extremely low res, it will not appear blurry.
|
||||||
|
- `ModAPI.meta.version(versionCode: String)`
|
||||||
|
- Sets the version of the mod. Appended after the title.
|
||||||
|
- `ModAPI.meta.config(configFn: Function)`
|
||||||
|
- Once the client is fully loaded, creates a button in the mod manager GUI that runs the specified function when pressed.
|
@ -31,7 +31,7 @@ var asyncDownloadRemoteURI = ModAPI.promisify(ModAPI.hooks.methods.nlevi_Platfor
|
|||||||
console.log(typeof asyncDownloadRemoteURI); //Logs function
|
console.log(typeof asyncDownloadRemoteURI); //Logs function
|
||||||
```
|
```
|
||||||
|
|
||||||
When it is called, like any other asyncronoush function, it returns a `Promise` object.
|
When it is called, like any other asyncronous function, it returns a `Promise` object.
|
||||||
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
|
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
|
||||||
|
|
||||||
You can replace the argument with any other method or constructor, including non asynchronous ones.
|
You can replace the argument with any other method or constructor, including non asynchronous ones.
|
@ -90,8 +90,12 @@
|
|||||||
>Choose .html file...</label
|
>Choose .html file...</label
|
||||||
>
|
>
|
||||||
<br />
|
<br />
|
||||||
<span><label>Minify: </label><input type="checkbox" oninput="globalThis.doShronk = this.checked">
|
<span>
|
||||||
<label>EaglerForge: </label><input checked type="checkbox" oninput="globalThis.doEaglerforge = this.checked">
|
<label>Minify: </label><input type="checkbox" oninput="globalThis.doShronk = this.checked">
|
||||||
|
|
||||||
|
<label>MinifyExtras: </label><input type="checkbox" oninput="globalThis.doShronkPlus = this.checked">
|
||||||
|
|
||||||
|
<label>EaglerForge: </label><input checked type="checkbox" oninput="globalThis.doEaglerforge = this.checked">
|
||||||
<code id="status">Awaiting input...</code></span>
|
<code id="status">Awaiting input...</code></span>
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<button class="btn btn-primary" id="giveme">Make modded client</button>
|
<button class="btn btn-primary" id="giveme">Make modded client</button>
|
||||||
@ -163,6 +167,7 @@
|
|||||||
`;
|
`;
|
||||||
var freezeCallstack = `if(ModAPI.hooks.freezeCallstack){return false};`;
|
var freezeCallstack = `if(ModAPI.hooks.freezeCallstack){return false};`;
|
||||||
</script>
|
</script>
|
||||||
|
<script src="backgroundLogger.js"></script>
|
||||||
<script src="patches.js"></script>
|
<script src="patches.js"></script>
|
||||||
<script src="injector.minify.js"></script>
|
<script src="injector.minify.js"></script>
|
||||||
<script src="injector.js"></script>
|
<script src="injector.js"></script>
|
||||||
|
31
injector.js
31
injector.js
@ -1,4 +1,4 @@
|
|||||||
globalThis.ModAPIVersion = "v2.7";
|
globalThis.ModAPIVersion = "v2.7.3";
|
||||||
globalThis.doEaglerforge = true;
|
globalThis.doEaglerforge = true;
|
||||||
document.querySelector("title").innerText = `EaglerForge Injector ${ModAPIVersion}`;
|
document.querySelector("title").innerText = `EaglerForge Injector ${ModAPIVersion}`;
|
||||||
document.querySelector("h1").innerText = `EaglerForge Injector ${ModAPIVersion}`;
|
document.querySelector("h1").innerText = `EaglerForge Injector ${ModAPIVersion}`;
|
||||||
@ -8,6 +8,7 @@ function wait(ms) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
function _status(x) {
|
function _status(x) {
|
||||||
|
backgroundLog(x, true);
|
||||||
document.querySelector("#status").innerText = x;
|
document.querySelector("#status").innerText = x;
|
||||||
}
|
}
|
||||||
function entriesToStaticVariableProxy(entries, prefix, clinitList) {
|
function entriesToStaticVariableProxy(entries, prefix, clinitList) {
|
||||||
@ -77,6 +78,7 @@ async function processClasses(string) {
|
|||||||
if (!confirm("The minify step is extremely slow, especially on lower-end devices, and can take upwards of 15 minutes.")) {
|
if (!confirm("The minify step is extremely slow, especially on lower-end devices, and can take upwards of 15 minutes.")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
backgroundLog("[MINIFY] Minify warning bypassed.");
|
||||||
}
|
}
|
||||||
_status("Beginning patch process...");
|
_status("Beginning patch process...");
|
||||||
await wait(50);
|
await wait(50);
|
||||||
@ -101,6 +103,7 @@ var main;(function(){`
|
|||||||
"var main;\n(function() {",
|
"var main;\n(function() {",
|
||||||
modapi_preinit + "var main;\n(function() {"
|
modapi_preinit + "var main;\n(function() {"
|
||||||
);
|
);
|
||||||
|
backgroundLog("[JSPATCH] Adding pre-init script");
|
||||||
patchedFile = patchedFile.replace(
|
patchedFile = patchedFile.replace(
|
||||||
/function \$rt_metadata\(data\)( ?){/gm,
|
/function \$rt_metadata\(data\)( ?){/gm,
|
||||||
`function $rt_metadata(data) {
|
`function $rt_metadata(data) {
|
||||||
@ -108,20 +111,21 @@ var main;(function(){`
|
|||||||
ModAPI.hooks._rippedData.push(data);
|
ModAPI.hooks._rippedData.push(data);
|
||||||
/*/EaglerForge Client Patch/*/`
|
/*/EaglerForge Client Patch/*/`
|
||||||
);
|
);
|
||||||
|
backgroundLog("[JSPATCH] Redirecting $rt_metadata to ModAPI.hooks._rippedData");
|
||||||
patchedFile = patchedFile.replaceAll(
|
patchedFile = patchedFile.replaceAll(
|
||||||
`return thread != null && thread.isResuming()`,
|
`return thread != null && thread.isResuming()`,
|
||||||
(match) => {
|
(match) => {
|
||||||
return freezeCallstack + match;
|
return freezeCallstack + match;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
backgroundLog("[JSPATCH] Freeze-callstack patch on TeaVMThread.isResuming()");
|
||||||
patchedFile = patchedFile.replaceAll(
|
patchedFile = patchedFile.replaceAll(
|
||||||
`return thread != null && thread.isSuspending();`,
|
`return thread != null && thread.isSuspending();`,
|
||||||
(match) => {
|
(match) => {
|
||||||
return freezeCallstack + match;
|
return freezeCallstack + match;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
backgroundLog("[JSPATCH] Freeze-callstack patch on TeaVMThread.isSuspending()");
|
||||||
|
|
||||||
patchedFile = patchedFile.replaceAll(
|
patchedFile = patchedFile.replaceAll(
|
||||||
`return $rt_currentNativeThread;`,
|
`return $rt_currentNativeThread;`,
|
||||||
@ -132,12 +136,12 @@ var main;(function(){`
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
backgroundLog("[JSPATCH] Freeze-callstack patch thread getter");
|
||||||
|
|
||||||
patchedFile = patchedFile.replaceAll("function TeaVMThread(", "globalThis.ModAPI.hooks.TeaVMThread = TeaVMThread;\nfunction TeaVMThread(");
|
patchedFile = patchedFile.replaceAll("function TeaVMThread(", "globalThis.ModAPI.hooks.TeaVMThread = TeaVMThread;\nfunction TeaVMThread(");
|
||||||
|
|
||||||
_status("Getting clinit list...");
|
_status("Getting clinit list...");
|
||||||
var clinitList = [...patchedFile.matchAll(/^[\t ]*function \S+?_\S+?_\$callClinit\(/gm)].map(x => x[0].replaceAll("function ", "").replaceAll("(", "").trim());
|
var clinitList = [...patchedFile.matchAll(/^[\t ]*function \S+?_\S+?_\$callClinit\(/gm)].map(x => x[0].replaceAll("function ", "").replaceAll("(", "").trim());
|
||||||
console.log(clinitList);
|
|
||||||
|
|
||||||
_status("Extracting constructors and methods...");
|
_status("Extracting constructors and methods...");
|
||||||
await wait(50);
|
await wait(50);
|
||||||
@ -158,6 +162,8 @@ var main;(function(){`
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
backgroundLog("-> Extract contructor 1");
|
||||||
|
|
||||||
const extractInternalConstructorRegex =
|
const extractInternalConstructorRegex =
|
||||||
/^\s*function (\S*?)__init_\d*?\(\$this/gm; //same as extract constructor regex, but only allow $this as first argument
|
/^\s*function (\S*?)__init_\d*?\(\$this/gm; //same as extract constructor regex, but only allow $this as first argument
|
||||||
patchedFile = patchedFile.replaceAll(
|
patchedFile = patchedFile.replaceAll(
|
||||||
@ -172,6 +178,8 @@ var main;(function(){`
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
backgroundLog("-> Extract contructor 2");
|
||||||
|
|
||||||
const extractInstanceMethodRegex =
|
const extractInstanceMethodRegex =
|
||||||
/^[\t ]*function \S+?_\S+?_\S+?\((\$this)?/gm; // /^[\t ]*function \S+?_\S+?_\S+?\(\$this/gm
|
/^[\t ]*function \S+?_\S+?_\S+?\((\$this)?/gm; // /^[\t ]*function \S+?_\S+?_\S+?\(\$this/gm
|
||||||
const extractInstanceMethodFullNameRegex = /function (\S*?)\(/gm; // /function (\S*?)\(\$this/gm
|
const extractInstanceMethodFullNameRegex = /function (\S*?)\(/gm; // /function (\S*?)\(\$this/gm
|
||||||
@ -198,6 +206,10 @@ var main;(function(){`
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
backgroundLog("-> Extract instance methods");
|
||||||
|
backgroundLog("-> Expose instance methods");
|
||||||
|
|
||||||
var staticVariables = [
|
var staticVariables = [
|
||||||
...patchedFile.matchAll(/var \S+?_\S+?_\S+? = /gm),
|
...patchedFile.matchAll(/var \S+?_\S+?_\S+? = /gm),
|
||||||
].flatMap((x) => {
|
].flatMap((x) => {
|
||||||
@ -205,6 +217,7 @@ var main;(function(){`
|
|||||||
}).filter(x => {
|
}).filter(x => {
|
||||||
return (!x.includes("$_clinit_$")) && (!x.includes("$lambda$"))
|
return (!x.includes("$_clinit_$")) && (!x.includes("$lambda$"))
|
||||||
});
|
});
|
||||||
|
backgroundLog("-> Extract static variables");
|
||||||
//Also stores classes from $rt_classWithoutFields(0)
|
//Also stores classes from $rt_classWithoutFields(0)
|
||||||
patchedFile = patchedFile.replaceAll(
|
patchedFile = patchedFile.replaceAll(
|
||||||
/var \S+?_\S+? = \$rt_classWithoutFields\(\S*?\);/gm,
|
/var \S+?_\S+? = \$rt_classWithoutFields\(\S*?\);/gm,
|
||||||
@ -240,6 +253,7 @@ var main;(function(){`
|
|||||||
);
|
);
|
||||||
//Edge cases. sigh
|
//Edge cases. sigh
|
||||||
//Done: add support for static properties on classes with constructors like this: function nmcg_GuiMainMenu() {
|
//Done: add support for static properties on classes with constructors like this: function nmcg_GuiMainMenu() {
|
||||||
|
backgroundLog("-> Expose static variables");
|
||||||
|
|
||||||
|
|
||||||
patchedFile = patchedFile.replaceAll(
|
patchedFile = patchedFile.replaceAll(
|
||||||
@ -307,10 +321,13 @@ var main;(function(){`
|
|||||||
\<script id="libserverside"\>{"._|_libserverside_|_."}\<\/script\>
|
\<script id="libserverside"\>{"._|_libserverside_|_."}\<\/script\>
|
||||||
\<script id="__eaglerforgeinjector_installation_flag__"\>console.log("Thank you for using EaglerForge!");\<\/script\>`
|
\<script id="__eaglerforgeinjector_installation_flag__"\>console.log("Thank you for using EaglerForge!");\<\/script\>`
|
||||||
);
|
);
|
||||||
patchedFile = patchedFile.replace(`<title>EaglercraftX 1.8</title>`, `<title>EFI ${globalThis.ModAPIVersion}</title>`);
|
backgroundLog("[HTML] Injecting script files");
|
||||||
|
patchedFile = patchedFile.replace(`<title>EaglercraftX`, `<title>EFI ${globalThis.ModAPIVersion} on`);
|
||||||
|
backgroundLog("[HTML] Injecting title");
|
||||||
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();");
|
||||||
});
|
});
|
||||||
|
backgroundLog("[HTML] Injecting main function");
|
||||||
|
|
||||||
_status("Done, awaiting input...");
|
_status("Done, awaiting input...");
|
||||||
await wait(50);
|
await wait(50);
|
||||||
@ -334,7 +351,8 @@ document.querySelector("#giveme").addEventListener("click", () => {
|
|||||||
|
|
||||||
if (globalThis.doEaglerforge) {
|
if (globalThis.doEaglerforge) {
|
||||||
if (string.includes("__eaglerforgeinjector_installation_flag__")) {
|
if (string.includes("__eaglerforgeinjector_installation_flag__")) {
|
||||||
return alert("this file already has eaglerforge injected in it, you nonce.\nif you're trying to update, you need a vanilla file.");
|
backgroundLog("Detected input containing EFI installation flag.", true);
|
||||||
|
return alert("this file already has EaglerForge injected in it, you nonce.\nif you're trying to update, you need a vanilla file.");
|
||||||
}
|
}
|
||||||
patchedFile = await processClasses(patchedFile);
|
patchedFile = await processClasses(patchedFile);
|
||||||
} else if (globalThis.doShronk) {
|
} else if (globalThis.doShronk) {
|
||||||
@ -344,6 +362,7 @@ document.querySelector("#giveme").addEventListener("click", () => {
|
|||||||
patchedFile.replace(`{"._|_libserverside_|_."}`, "");
|
patchedFile.replace(`{"._|_libserverside_|_."}`, "");
|
||||||
var blob = new Blob([patchedFile], { type: file.type });
|
var blob = new Blob([patchedFile], { type: file.type });
|
||||||
saveAs(blob, "processed." + fileType);
|
saveAs(blob, "processed." + fileType);
|
||||||
|
backgroundLog("Saving file...", true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,23 +1,17 @@
|
|||||||
// Babel plugin to transform functions and calls
|
const MINIFY = function () {
|
||||||
const ASYNC_PLUGIN_1 = function ({ types: t }) {
|
|
||||||
return {
|
return {
|
||||||
visitor: {
|
visitor: {
|
||||||
FunctionDeclaration(path) {
|
Identifier(path) {
|
||||||
console.log(path);
|
if (path.node.name === "$ptr") {
|
||||||
path.node.async = true;
|
path.node.name = "r";
|
||||||
},
|
|
||||||
ArrowFunctionExpression(path) {
|
|
||||||
console.log(path);
|
|
||||||
path.node.async = true;
|
|
||||||
},
|
|
||||||
CallExpression(path) {
|
|
||||||
console.log(path);
|
|
||||||
if (path.parent.type !== 'AwaitExpression') {
|
|
||||||
path.replaceWith(
|
|
||||||
t.awaitExpression(path.node)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
if (path.node.name === "$tmp") {
|
||||||
|
path.node.name = "m";
|
||||||
|
}
|
||||||
|
if (path.node.name === "$thread") {
|
||||||
|
path.node.name = "t";
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -31,7 +25,7 @@ async function shronk(input) {
|
|||||||
inputHtml = `<script>${input}</script>`;
|
inputHtml = `<script>${input}</script>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
_status("[ASYNC_PLUGIN_1] Parsing html...");
|
_status("[MINIFY] Parsing html...");
|
||||||
await wait(50);
|
await wait(50);
|
||||||
const parser = new DOMParser();
|
const parser = new DOMParser();
|
||||||
const doc = parser.parseFromString(inputHtml, 'text/html');
|
const doc = parser.parseFromString(inputHtml, 'text/html');
|
||||||
@ -40,18 +34,20 @@ async function shronk(input) {
|
|||||||
for (let i = 0; i < scriptTags.length; i++) {
|
for (let i = 0; i < scriptTags.length; i++) {
|
||||||
const scriptTag = scriptTags[i];
|
const scriptTag = scriptTags[i];
|
||||||
const code = scriptTag.textContent;
|
const code = scriptTag.textContent;
|
||||||
_status("[ASYNC_PLUGIN_1] Transpiling script #" + (i + 1) + " of length " + Math.round(code.length / 1000) + "k...");
|
_status("[MINIFY] Transpiling script #" + (i + 1) + " of length " + Math.round(code.length / 1000) + "k...");
|
||||||
await wait(150);
|
await wait(150);
|
||||||
|
|
||||||
|
|
||||||
const output = Babel.transform(code, {
|
const output = Babel.transform(code, {
|
||||||
plugins: []
|
plugins: globalThis.doShronkPlus ? [
|
||||||
|
MINIFY()
|
||||||
|
] : []
|
||||||
});
|
});
|
||||||
scriptTag.textContent = output.code;
|
scriptTag.textContent = output.code;
|
||||||
await wait(10);
|
await wait(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
_status("[ASYNC_PLUGIN_1] Job complete!");
|
_status("[MINIFY] Job complete!");
|
||||||
await wait(50);
|
await wait(50);
|
||||||
|
|
||||||
if (isHtml) {
|
if (isHtml) {
|
||||||
|
30
modgui.js
30
modgui.js
@ -10,7 +10,9 @@ globalThis.modapi_guikit = "(" + (() => {
|
|||||||
"hey you should check out https://github.com/ZXMushroom63/scratch-gui",
|
"hey you should check out https://github.com/ZXMushroom63/scratch-gui",
|
||||||
"99% of people stop gambling before they win big.",
|
"99% of people stop gambling before they win big.",
|
||||||
"Now with free estradiol!",
|
"Now with free estradiol!",
|
||||||
"Now with H.I.V (Hyper Injected Virtual-debugger)"
|
"Now with H.I.V (Hyper Injected Virtual-debugger)",
|
||||||
|
"asdasd",
|
||||||
|
"Star us on GitHub to support us! https://github.com/EaglerForge/EaglerForgeInjector"
|
||||||
];
|
];
|
||||||
var gui = `<div id="modapi_gui_container">
|
var gui = `<div id="modapi_gui_container">
|
||||||
<header>
|
<header>
|
||||||
@ -185,6 +187,7 @@ globalThis.modapi_guikit = "(" + (() => {
|
|||||||
document.querySelector("#modapi_gui_container").remove();
|
document.querySelector("#modapi_gui_container").remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var element = document.createElement("div");
|
var element = document.createElement("div");
|
||||||
|
|
||||||
element.innerHTML = gui.replace("{splash_msg}", splashes[Math.floor(Math.random() * splashes.length)]);
|
element.innerHTML = gui.replace("{splash_msg}", splashes[Math.floor(Math.random() * splashes.length)]);
|
||||||
@ -245,15 +248,28 @@ globalThis.modapi_guikit = "(" + (() => {
|
|||||||
spacer.classList.add("nothing");
|
spacer.classList.add("nothing");
|
||||||
var controls = document.createElement("td");
|
var controls = document.createElement("td");
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var deleteBtn = document.createElement("button");
|
||||||
button.innerText = "Delete";
|
deleteBtn.innerText = "Delete";
|
||||||
button.style.height = "3rem";
|
deleteBtn.style.height = "3rem";
|
||||||
button.addEventListener("click", async () => {
|
deleteBtn.addEventListener("click", async () => {
|
||||||
await removeMod(i);
|
await removeMod(i);
|
||||||
window.modapi_displayModGui();
|
window.modapi_displayModGui();
|
||||||
});
|
});
|
||||||
button.classList.add("button");
|
deleteBtn.classList.add("button");
|
||||||
controls.appendChild(button);
|
controls.appendChild(deleteBtn);
|
||||||
|
|
||||||
|
if (typeof ModAPI.meta._configMap[hash] === "function") {
|
||||||
|
var configBtn = document.createElement("button");
|
||||||
|
configBtn.innerText = "Config";
|
||||||
|
configBtn.style.height = "3rem";
|
||||||
|
configBtn.style.marginLeft = "1rem";
|
||||||
|
configBtn.addEventListener("click", async () => {
|
||||||
|
ModAPI.meta._configMap[hash]();
|
||||||
|
});
|
||||||
|
configBtn.classList.add("button");
|
||||||
|
controls.appendChild(configBtn);
|
||||||
|
}
|
||||||
|
|
||||||
tr.appendChild(mod);
|
tr.appendChild(mod);
|
||||||
tr.appendChild(spacer);
|
tr.appendChild(spacer);
|
||||||
tr.appendChild(controls);
|
tr.appendChild(controls);
|
||||||
|
92
postinit.js
92
postinit.js
@ -3,6 +3,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
//This script cannot contain backticks, escape characters, or backslashes in order to inject into the dedicated server code.
|
//This script cannot contain backticks, escape characters, or backslashes in order to inject into the dedicated server code.
|
||||||
var startedModLoader = false;
|
var startedModLoader = false;
|
||||||
var BACKSLASH = String.fromCharCode(92);
|
var BACKSLASH = String.fromCharCode(92);
|
||||||
|
var LF = String.fromCharCode(10);
|
||||||
var STRIP_COMMENTS = new RegExp(atob("KChcL1wvLiokKXwoXC9cKltcc1xTXSo/XCpcLykp"), "gm");
|
var STRIP_COMMENTS = new RegExp(atob("KChcL1wvLiokKXwoXC9cKltcc1xTXSo/XCpcLykp"), "gm");
|
||||||
var ARGUMENT_NAMES = new RegExp(atob("KFteXHMsXSsp"), "g");
|
var ARGUMENT_NAMES = new RegExp(atob("KFteXHMsXSsp"), "g");
|
||||||
|
|
||||||
@ -21,17 +22,66 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
ModAPI.meta = {};
|
ModAPI.meta = {};
|
||||||
ModAPI.meta._titleMap = {};
|
ModAPI.meta._titleMap = {};
|
||||||
ModAPI.meta._descriptionMap = {};
|
ModAPI.meta._descriptionMap = {};
|
||||||
|
ModAPI.meta._configMap = {};
|
||||||
ModAPI.meta._developerMap = {};
|
ModAPI.meta._developerMap = {};
|
||||||
ModAPI.meta._iconMap = {};
|
ModAPI.meta._iconMap = {};
|
||||||
ModAPI.meta._versionMap = {};
|
ModAPI.meta._versionMap = {};
|
||||||
|
const credits = {};
|
||||||
|
ModAPI.addCredit = function (category, name, contents) {
|
||||||
|
if (!credits[category]) {
|
||||||
|
credits[category] = [];
|
||||||
|
}
|
||||||
|
credits[category].push(LF + LF + " " + name + ": " + LF + LF + contents);
|
||||||
|
}
|
||||||
|
function getCreditsString() {
|
||||||
|
return Object.entries(credits).map((entry) => {
|
||||||
|
return " "+entry[0] + LF + " " + (new Array(entry[0].length)).fill("~").join("") + entry[1].join("") + LF + LF + LF;
|
||||||
|
}).join("");
|
||||||
|
}
|
||||||
ModAPI.array = {};
|
ModAPI.array = {};
|
||||||
|
|
||||||
ModAPI.version = "__modapi_version_code__";
|
ModAPI.version = "__modapi_version_code__";
|
||||||
ModAPI.flavour = "injector";
|
ModAPI.flavour = "injector";
|
||||||
ModAPI.GNU = "terry pratchett";
|
ModAPI.GNU = "terry pratchett";
|
||||||
ModAPI.credits = ["ZXMushroom63", "radmanplays", "Murturtle", "OtterCodes101", "TheIdiotPlays", "OeildeLynx31", "Stpv22"];
|
|
||||||
|
ModAPI.addCredit("EaglerForge Devs", "ZXMushroom63",
|
||||||
|
" - Built the original PluginAPI for EaglerReborn" + LF +
|
||||||
|
" - Built EaglerForgeInjector as a procedural replacement for EaglerForge clients" + LF +
|
||||||
|
" - Made the mod loader and gui loader" + LF +
|
||||||
|
" - Added singleplayer support" + LF +
|
||||||
|
" - Made the AsyncSink corelib");
|
||||||
|
|
||||||
|
ModAPI.addCredit("EaglerForge Devs", "radmanplays",
|
||||||
|
" - Ported and maintained EaglerReborn's PluginAPI to modern version of eaglercrafts (u22+)" + LF +
|
||||||
|
" - Rebranded PluginAPI to ModAPI" + LF +
|
||||||
|
" - Added various new features to ModAPI" + LF +
|
||||||
|
" - Made the worldedit mod + a few other mods");
|
||||||
|
|
||||||
|
ModAPI.addCredit("EaglerForge Devs", "LeahOnBrainrot / OtterCodes101 / OtterDev",
|
||||||
|
" - Created EaglerReborn" + LF +
|
||||||
|
" - EaglerForge developer" + LF +
|
||||||
|
" - Helped update the client to newer versions" + LF +
|
||||||
|
" - Made signed clients work" + LF +
|
||||||
|
" - Maintainer nowadays" + LF +
|
||||||
|
" - Various bug fixes for EaglerForgeInjector");
|
||||||
|
|
||||||
|
ModAPI.addCredit("EaglerForge Devs", "Murturtle",
|
||||||
|
" - Added the render event to EaglerForgeInjector" + LF +
|
||||||
|
" - Added pi optimiser to the injector (now removed)");
|
||||||
|
|
||||||
|
ModAPI.addCredit("EaglerForge Devs", "TheIdiotPlays",
|
||||||
|
" - Made the mod manager GUI");
|
||||||
|
|
||||||
|
ModAPI.addCredit("EaglerForge Devs", "OeildeLynx31",
|
||||||
|
" - Work on the worldedit mod");
|
||||||
|
|
||||||
|
ModAPI.addCredit("EaglerForge Devs", "Stpv22",
|
||||||
|
" - Made the mod gui open before the client starts");
|
||||||
|
|
||||||
function limitSize(x, n) {
|
function limitSize(x, n) {
|
||||||
|
if (!x) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
if (x.length > n) {
|
if (x.length > n) {
|
||||||
return x.substring(0, n) + "…";
|
return x.substring(0, n) + "…";
|
||||||
} else {
|
} else {
|
||||||
@ -41,12 +91,12 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
function arraysAreSame(arr1, arr2) {
|
function arraysAreSame(arr1, arr2) {
|
||||||
if (!arr1 || !arr2)
|
if (!arr1 || !arr2)
|
||||||
return false;
|
return false;
|
||||||
if(arr1 === arr2)
|
if (arr1 === arr2)
|
||||||
return true;
|
return true;
|
||||||
if (arr1.length !== arr2.length)
|
if (arr1.length !== arr2.length)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (var i = 0, l=arr1.length; i < l; i++) {
|
for (var i = 0, l = arr1.length; i < l; i++) {
|
||||||
if (arr1[i] instanceof Array && arr2[i] instanceof Array) {
|
if (arr1[i] instanceof Array && arr2[i] instanceof Array) {
|
||||||
if (!arr1[i].equals(arr2[i]))
|
if (!arr1[i].equals(arr2[i]))
|
||||||
return false;
|
return false;
|
||||||
@ -115,6 +165,18 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
}
|
}
|
||||||
ModAPI.meta._descriptionMap[document.currentScript.getAttribute("data-hash")] = limitSize(desc, 160);
|
ModAPI.meta._descriptionMap[document.currentScript.getAttribute("data-hash")] = limitSize(desc, 160);
|
||||||
}
|
}
|
||||||
|
ModAPI.meta.config = function (conf) {
|
||||||
|
if (typeof conf !== "function") {
|
||||||
|
return console.log("[ModAPIMeta] Config value was not a function");
|
||||||
|
}
|
||||||
|
if (!document.currentScript || document.currentScript.getAttribute("data-isMod") !== "true") {
|
||||||
|
return console.log("[ModAPIMeta] Cannot set meta for non-mod script.");
|
||||||
|
}
|
||||||
|
if (!document.currentScript.hasAttribute("data-hash")) {
|
||||||
|
return console.log("[ModAPIMeta] Script does not have a hashcode.");
|
||||||
|
}
|
||||||
|
ModAPI.meta._configMap[document.currentScript.getAttribute("data-hash")] = conf;
|
||||||
|
}
|
||||||
ModAPI.meta.version = function (ver) {
|
ModAPI.meta.version = function (ver) {
|
||||||
if (!document.currentScript || document.currentScript.getAttribute("data-isMod") !== "true") {
|
if (!document.currentScript || document.currentScript.getAttribute("data-isMod") !== "true") {
|
||||||
return console.log("[ModAPIMeta] Cannot set meta for non-mod script.");
|
return console.log("[ModAPIMeta] Cannot set meta for non-mod script.");
|
||||||
@ -343,7 +405,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
"getConstructorByArgs": function (...argNames) {
|
"getConstructorByArgs": function (...argNames) {
|
||||||
if (!argumentCache) {
|
if (!argumentCache) {
|
||||||
argumentCache = [];
|
argumentCache = [];
|
||||||
this.internalConstructors.forEach(x=>{
|
this.internalConstructors.forEach(x => {
|
||||||
argumentCache.push(getParamNames(x).slice(1).map(y => y.substring(1)));
|
argumentCache.push(getParamNames(x).slice(1).map(y => y.substring(1)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -771,7 +833,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
if (!object) {
|
if (!object) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (prop in object) {
|
if ((prop in object) && Object.keys(object).includes(prop)) {
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
var possibleKeys = Object.keys(object).filter(x => { return x.startsWith(prop) });
|
var possibleKeys = Object.keys(object).filter(x => { return x.startsWith(prop) });
|
||||||
@ -780,7 +842,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
})
|
})
|
||||||
return possibleKeys.sort((a, b) => {
|
return possibleKeys.sort((a, b) => {
|
||||||
return a.length - b.length;
|
return a.length - b.length;
|
||||||
})[0] || null;
|
})[0] || prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModAPI.util.modifyFunction = function (fn, patcherFn) {
|
ModAPI.util.modifyFunction = function (fn, patcherFn) {
|
||||||
@ -821,6 +883,22 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
return originalUpdate.apply(this, args);
|
return originalUpdate.apply(this, args);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getCreditsName = ModAPI.util.getMethodFromPackage("net.lax1dude.eaglercraft.v1_8.EagRuntime", "getResourceString");
|
||||||
|
const originalGetCredits = ModAPI.hooks.methods[getCreditsName];
|
||||||
|
ModAPI.hooks.methods[getCreditsName] = function ($path) {
|
||||||
|
if (!$path) {
|
||||||
|
return originalGetCredits.apply(this, [$path]);
|
||||||
|
}
|
||||||
|
if (ModAPI.util.ustr($path).toLowerCase().endsWith("credits.txt")) {
|
||||||
|
var out = originalGetCredits.apply(this, [$path]);
|
||||||
|
out = ModAPI.util.ustr(out);
|
||||||
|
out = getCreditsString() + out;
|
||||||
|
out = ModAPI.util.str(out);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
return originalGetCredits.apply(this, [$path]);
|
||||||
|
};
|
||||||
|
|
||||||
const initMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.client.Minecraft", "startGame");
|
const initMethodName = ModAPI.util.getMethodFromPackage("net.minecraft.client.Minecraft", "startGame");
|
||||||
const originalInit = ModAPI.hooks.methods[initMethodName];
|
const originalInit = ModAPI.hooks.methods[initMethodName];
|
||||||
ModAPI.hooks.methods[initMethodName] = function (...args) {
|
ModAPI.hooks.methods[initMethodName] = function (...args) {
|
||||||
@ -1105,7 +1183,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
}
|
}
|
||||||
ModAPI.keygen.entity = function (entity) {
|
ModAPI.keygen.entity = function (entity) {
|
||||||
var hashMap = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.entity.EntityList").staticVariables.idToClassMapping).getCorrective();
|
var hashMap = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.entity.EntityList").staticVariables.idToClassMapping).getCorrective();
|
||||||
var values = hashMap.keys.getRef().data.filter(x=>hashMap.get(x));
|
var values = hashMap.keys.getRef().data.filter(x => hashMap.get(x));
|
||||||
return qhash(entity, values, 127);
|
return qhash(entity, values, 127);
|
||||||
}
|
}
|
||||||
}).toString() + ")();";
|
}).toString() + ")();";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user