Merge pull request #64 from eaglerforge/main

site overhaul
This commit is contained in:
ZXMushroom63 2025-03-13 16:30:22 +08:00 committed by GitHub
commit 7ebaf4d5ef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 85 additions and 30 deletions

32
backgroundLogger.js Normal file
View 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...");

View File

@ -90,8 +90,12 @@
>Choose .html file...</label
>
<br />
<span><label>Minify:&nbsp;</label><input type="checkbox" oninput="globalThis.doShronk = this.checked">
&nbsp;&nbsp;&nbsp;<label>EaglerForge:&nbsp;</label><input checked type="checkbox" oninput="globalThis.doEaglerforge = this.checked">
<span>
<label>Minify:&nbsp;</label><input type="checkbox" oninput="globalThis.doShronk = this.checked">
&nbsp;&nbsp;&nbsp;
<label>MinifyExtras:&nbsp;</label><input type="checkbox" oninput="globalThis.doShronkPlus = this.checked">
&nbsp;&nbsp;&nbsp;
<label>EaglerForge:&nbsp;</label><input checked type="checkbox" oninput="globalThis.doEaglerforge = this.checked">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code id="status">Awaiting input...</code></span>
<br /><br />
<button class="btn btn-primary" id="giveme">Make modded client</button>
@ -163,6 +167,7 @@
`;
var freezeCallstack = `if(ModAPI.hooks.freezeCallstack){return false};`;
</script>
<script src="backgroundLogger.js"></script>
<script src="patches.js"></script>
<script src="injector.minify.js"></script>
<script src="injector.js"></script>

View File

@ -8,6 +8,7 @@ function wait(ms) {
});
}
function _status(x) {
backgroundLog(x, true);
document.querySelector("#status").innerText = x;
}
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.")) {
return;
}
backgroundLog("[MINIFY] Minify warning bypassed.");
}
_status("Beginning patch process...");
await wait(50);
@ -101,6 +103,7 @@ var main;(function(){`
"var main;\n(function() {",
modapi_preinit + "var main;\n(function() {"
);
backgroundLog("[JSPATCH] Adding pre-init script");
patchedFile = patchedFile.replace(
/function \$rt_metadata\(data\)( ?){/gm,
`function $rt_metadata(data) {
@ -108,20 +111,21 @@ var main;(function(){`
ModAPI.hooks._rippedData.push(data);
/*/EaglerForge Client Patch/*/`
);
backgroundLog("[JSPATCH] Redirecting $rt_metadata to ModAPI.hooks._rippedData");
patchedFile = patchedFile.replaceAll(
`return thread != null && thread.isResuming()`,
(match) => {
return freezeCallstack + match;
}
);
backgroundLog("[JSPATCH] Freeze-callstack patch on TeaVMThread.isResuming()");
patchedFile = patchedFile.replaceAll(
`return thread != null && thread.isSuspending();`,
(match) => {
return freezeCallstack + match;
}
);
backgroundLog("[JSPATCH] Freeze-callstack patch on TeaVMThread.isSuspending()");
patchedFile = patchedFile.replaceAll(
`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(");
_status("Getting clinit list...");
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...");
await wait(50);
@ -158,6 +162,8 @@ var main;(function(){`
}
);
backgroundLog("-> Extract contructor 1");
const extractInternalConstructorRegex =
/^\s*function (\S*?)__init_\d*?\(\$this/gm; //same as extract constructor regex, but only allow $this as first argument
patchedFile = patchedFile.replaceAll(
@ -172,6 +178,8 @@ var main;(function(){`
}
);
backgroundLog("-> Extract contructor 2");
const extractInstanceMethodRegex =
/^[\t ]*function \S+?_\S+?_\S+?\((\$this)?/gm; // /^[\t ]*function \S+?_\S+?_\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 = [
...patchedFile.matchAll(/var \S+?_\S+?_\S+? = /gm),
].flatMap((x) => {
@ -205,6 +217,7 @@ var main;(function(){`
}).filter(x => {
return (!x.includes("$_clinit_$")) && (!x.includes("$lambda$"))
});
backgroundLog("-> Extract static variables");
//Also stores classes from $rt_classWithoutFields(0)
patchedFile = patchedFile.replaceAll(
/var \S+?_\S+? = \$rt_classWithoutFields\(\S*?\);/gm,
@ -240,6 +253,7 @@ var main;(function(){`
);
//Edge cases. sigh
//Done: add support for static properties on classes with constructors like this: function nmcg_GuiMainMenu() {
backgroundLog("-> Expose static variables");
patchedFile = patchedFile.replaceAll(
@ -307,10 +321,13 @@ var main;(function(){`
\<script id="libserverside"\>{"._|_libserverside_|_."}\<\/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) => {
return match.replace("main();", "main();ModAPI.hooks._postInit();");
});
backgroundLog("[HTML] Injecting main function");
_status("Done, awaiting input...");
await wait(50);
@ -334,7 +351,8 @@ document.querySelector("#giveme").addEventListener("click", () => {
if (globalThis.doEaglerforge) {
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);
} else if (globalThis.doShronk) {
@ -344,6 +362,7 @@ document.querySelector("#giveme").addEventListener("click", () => {
patchedFile.replace(`{"._|_libserverside_|_."}`, "");
var blob = new Blob([patchedFile], { type: file.type });
saveAs(blob, "processed." + fileType);
backgroundLog("Saving file...", true);
});
});

View File

@ -1,23 +1,17 @@
// Babel plugin to transform functions and calls
const ASYNC_PLUGIN_1 = function ({ types: t }) {
const MINIFY = function () {
return {
visitor: {
FunctionDeclaration(path) {
console.log(path);
path.node.async = true;
},
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)
);
Identifier(path) {
if (path.node.name === "$ptr") {
path.node.name = "r";
}
}
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>`;
}
_status("[ASYNC_PLUGIN_1] Parsing html...");
_status("[MINIFY] Parsing html...");
await wait(50);
const parser = new DOMParser();
const doc = parser.parseFromString(inputHtml, 'text/html');
@ -40,18 +34,20 @@ async function shronk(input) {
for (let i = 0; i < scriptTags.length; i++) {
const scriptTag = scriptTags[i];
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);
const output = Babel.transform(code, {
plugins: []
plugins: globalThis.doShronkPlus ? [
MINIFY()
] : []
});
scriptTag.textContent = output.code;
await wait(10);
}
_status("[ASYNC_PLUGIN_1] Job complete!");
_status("[MINIFY] Job complete!");
await wait(50);
if (isHtml) {

View File

@ -10,7 +10,9 @@ globalThis.modapi_guikit = "(" + (() => {
"hey you should check out https://github.com/ZXMushroom63/scratch-gui",
"99% of people stop gambling before they win big.",
"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">
<header>
@ -184,7 +186,8 @@ globalThis.modapi_guikit = "(" + (() => {
cb ||= document.querySelector("#modapi_gui_container")._cb;
document.querySelector("#modapi_gui_container").remove();
}
var element = document.createElement("div");
element.innerHTML = gui.replace("{splash_msg}", splashes[Math.floor(Math.random() * splashes.length)]);