diff --git a/modgui.injector.js b/modgui.injector.js
index d2d64e2..fda999f 100644
--- a/modgui.injector.js
+++ b/modgui.injector.js
@@ -1,15 +1,15 @@
globalThis.modapi_guikit = `// ModAPI GUI made by TheIdiotPlays
// https://github.com/TheIdiotPlays
-(()=>{
- var splashes = [
- "Now with A.I.D.S (automatically injected dedicated server)",
- "Only causes death 90% of the time!",
- "HTML is better.",
- "https://github.com/EaglerForge",
- "hey you should check out https://github.com/ZXMushroom63/scratch-gui",
- "99% of people stop gambling before they win big."
- ];
- var gui = \`
+(() => {
+ var splashes = [
+ "Now with A.I.D.S (automatically injected dedicated server)",
+ "Only causes death 90% of the time!",
+ "HTML is better.",
+ "https://github.com/EaglerForge",
+ "hey you should check out https://github.com/ZXMushroom63/scratch-gui",
+ "99% of people stop gambling before they win big."
+ ];
+ var gui = \`
EaglerForge Mod Manager
@@ -158,38 +158,85 @@ globalThis.modapi_guikit = `// ModAPI GUI made by TheIdiotPlays
}
\`;
- window.modapi_displayModGui = async function () {
- if (!getMods) {
- return;
- }
- if (document.querySelector("#modapi_gui_container")) {
- document.querySelector("#modapi_gui_container").remove();
- }
- var element = document.createElement("div");
-
- element.innerHTML = gui.replace("{splash_msg}", splashes[Math.floor(Math.random() * splashes.length)]);
-
- document.body.appendChild(element);
-
- var modsList = await getMods();
- var tbody = document.querySelector("#modapi_gui_container .modTable tbody");
- tbody.innerHTML = "";
- modsList.forEach((modtxt, i) => {
- var tr = document.createElement("tr");
- var mod = document.createElement("td");
- mod.innerText = modtxt;
- var spacer = document.createElement("td");
- spacer.appendChild("nothing");
- var controls = document.createElement("td");
-
- var button = document.createElement("button");
- button.classList.add("button");
- controls.appendChild(button);
- tr.appendChild(mod);
- tr.appendChild(spacer);
- tr.appendChild(button);
- tbody.appendChild(tr);
- });
-
+ async function fileToDataURI(file) {
+ return new Promise((res, rej) => {
+ var fr = new FileReader();
+ fr.addEventListener("error", (e) => { rej(e); });
+ fr.addEventListener("load", (e) => { res(fr.result); });
+ fr.readAsDataURL(file);
+ });
+ }
+ window.modapi_displayModGui = async function () {
+ if (!getMods) {
+ return;
}
+ if (document.querySelector("#modapi_gui_container")) {
+ document.querySelector("#modapi_gui_container").remove();
+ }
+ var element = document.createElement("div");
+
+ element.innerHTML = gui.replace("{splash_msg}", splashes[Math.floor(Math.random() * splashes.length)]);
+
+ document.body.appendChild(element);
+
+ var modsList = await getMods();
+ var tbody = document.querySelector("#modapi_gui_container .modTable tbody");
+ tbody.innerHTML = "";
+ modsList.forEach((modtxt, i) => {
+ if (!modtxt) { return }
+ var tr = document.createElement("tr");
+ var mod = document.createElement("td");
+ if (modtxt.length > 125) {
+ try {
+ mod.innerText = modtxt.match(/data:text\\/\\S+?;fs=\\S+;/m)[0]
+ } catch (error) {
+ mod.innerText = "Unknown Mod.";
+ }
+ } else { mod.innerText = modtxt; }
+ var spacer = document.createElement("td");
+ spacer.classList.add("nothing");
+ var controls = document.createElement("td");
+
+ var button = document.createElement("button");
+ button.innerText = "Delete";
+ button.addEventListener("click", async () => {
+ await removeMod(i);
+ window.modapi_displayModGui();
+ });
+ button.classList.add("button");
+ controls.appendChild(button);
+ tr.appendChild(mod);
+ tr.appendChild(spacer);
+ tr.appendChild(button);
+ tbody.appendChild(tr);
+ });
+ }
+ window.modapi_clearmods = async () => {
+ await resetMods();
+ window.modapi_displayModGui();
+ }
+ window.modapi_addmod = async () => {
+ var mod = window.prompt("Paste in the URL of the mod you wish to add: ");
+ if (!mod || mod.length === 0) {
+ return;
+ }
+ await addMod("web@" + mod);
+ window.modapi_displayModGui();
+ }
+ window.modapi_uploadmod = async () => {
+ var f = document.createElement("input");
+ f.type = "file";
+ f.accept = "text/javascript";
+ f.multiple = true;
+ f.addEventListener("input", async () => {
+ if (f.files.length < 1) {
+ return;
+ }
+ for (let i = 0; i < f.files.length; i++) {
+ await addMod("web@" + (await fileToDataURI(f.files[i])).replaceAll(";base64", ";fs=" + f.files[i].name + ";base64"));
+ }
+ window.modapi_displayModGui();
+ });
+ f.click();
+ }
})();`;
\ No newline at end of file
diff --git a/modgui.js b/modgui.js
index 2e5c7b9..b3df844 100644
--- a/modgui.js
+++ b/modgui.js
@@ -1,15 +1,15 @@
// ModAPI GUI made by TheIdiotPlays
// https://github.com/TheIdiotPlays
-(()=>{
- var splashes = [
- "Now with A.I.D.S (automatically injected dedicated server)",
- "Only causes death 90% of the time!",
- "HTML is better.",
- "https://github.com/EaglerForge",
- "hey you should check out https://github.com/ZXMushroom63/scratch-gui",
- "99% of people stop gambling before they win big."
- ];
- var gui = `
+(() => {
+ var splashes = [
+ "Now with A.I.D.S (automatically injected dedicated server)",
+ "Only causes death 90% of the time!",
+ "HTML is better.",
+ "https://github.com/EaglerForge",
+ "hey you should check out https://github.com/ZXMushroom63/scratch-gui",
+ "99% of people stop gambling before they win big."
+ ];
+ var gui = `
EaglerForge Mod Manager
@@ -158,38 +158,85 @@
}
`;
- window.modapi_displayModGui = async function () {
- if (!getMods) {
- return;
- }
- if (document.querySelector("#modapi_gui_container")) {
- document.querySelector("#modapi_gui_container").remove();
- }
- var element = document.createElement("div");
-
- element.innerHTML = gui.replace("{splash_msg}", splashes[Math.floor(Math.random() * splashes.length)]);
-
- document.body.appendChild(element);
-
- var modsList = await getMods();
- var tbody = document.querySelector("#modapi_gui_container .modTable tbody");
- tbody.innerHTML = "";
- modsList.forEach((modtxt, i) => {
- var tr = document.createElement("tr");
- var mod = document.createElement("td");
- mod.innerText = modtxt;
- var spacer = document.createElement("td");
- spacer.appendChild("nothing");
- var controls = document.createElement("td");
-
- var button = document.createElement("button");
- button.classList.add("button");
- controls.appendChild(button);
- tr.appendChild(mod);
- tr.appendChild(spacer);
- tr.appendChild(button);
- tbody.appendChild(tr);
- });
-
+ async function fileToDataURI(file) {
+ return new Promise((res, rej) => {
+ var fr = new FileReader();
+ fr.addEventListener("error", (e) => { rej(e); });
+ fr.addEventListener("load", (e) => { res(fr.result); });
+ fr.readAsDataURL(file);
+ });
+ }
+ window.modapi_displayModGui = async function () {
+ if (!getMods) {
+ return;
}
+ if (document.querySelector("#modapi_gui_container")) {
+ document.querySelector("#modapi_gui_container").remove();
+ }
+ var element = document.createElement("div");
+
+ element.innerHTML = gui.replace("{splash_msg}", splashes[Math.floor(Math.random() * splashes.length)]);
+
+ document.body.appendChild(element);
+
+ var modsList = await getMods();
+ var tbody = document.querySelector("#modapi_gui_container .modTable tbody");
+ tbody.innerHTML = "";
+ modsList.forEach((modtxt, i) => {
+ if (!modtxt) { return }
+ var tr = document.createElement("tr");
+ var mod = document.createElement("td");
+ if (modtxt.length > 125) {
+ try {
+ mod.innerText = modtxt.match(/data:text\/\S+?;fs=\S+;/m)[0]
+ } catch (error) {
+ mod.innerText = "Unknown Mod.";
+ }
+ } else { mod.innerText = modtxt; }
+ var spacer = document.createElement("td");
+ spacer.classList.add("nothing");
+ var controls = document.createElement("td");
+
+ var button = document.createElement("button");
+ button.innerText = "Delete";
+ button.addEventListener("click", async () => {
+ await removeMod(i);
+ window.modapi_displayModGui();
+ });
+ button.classList.add("button");
+ controls.appendChild(button);
+ tr.appendChild(mod);
+ tr.appendChild(spacer);
+ tr.appendChild(button);
+ tbody.appendChild(tr);
+ });
+ }
+ window.modapi_clearmods = async () => {
+ await resetMods();
+ window.modapi_displayModGui();
+ }
+ window.modapi_addmod = async () => {
+ var mod = window.prompt("Paste in the URL of the mod you wish to add: ");
+ if (!mod || mod.length === 0) {
+ return;
+ }
+ await addMod("web@" + mod);
+ window.modapi_displayModGui();
+ }
+ window.modapi_uploadmod = async () => {
+ var f = document.createElement("input");
+ f.type = "file";
+ f.accept = "text/javascript";
+ f.multiple = true;
+ f.addEventListener("input", async () => {
+ if (f.files.length < 1) {
+ return;
+ }
+ for (let i = 0; i < f.files.length; i++) {
+ await addMod("web@" + (await fileToDataURI(f.files[i])).replaceAll(";base64", ";fs=" + f.files[i].name + ";base64"));
+ }
+ window.modapi_displayModGui();
+ });
+ f.click();
+ }
})();
\ No newline at end of file
diff --git a/modloader.injector.js b/modloader.injector.js
index 325866b..3106c34 100644
--- a/modloader.injector.js
+++ b/modloader.injector.js
@@ -28,8 +28,7 @@ async function getMods() {
const transaction = db.transaction(["filesystem"], "readonly");
const objectStore = transaction.objectStore("filesystem");
const object = await promisifyIDBRequest(objectStore.get("mods.txt"));
- const decoder = new TextDecoder("utf-8");
- return object ? decoder.decode(object).split("|") : [];
+ return object ? (await object.text()).split("|") : [];
}
async function saveMods(mods) {
@@ -46,26 +45,21 @@ async function addMod(mod) {
const mods = await getMods();
mods.push(mod);
await saveMods(mods);
- console.log("Mod added: " + mod);
}
async function removeMod(index) {
const mods = await getMods();
if (index >= 0 && index < mods.length) {
- const removedMod = mods.splice(index, 1);
+ mods.splice(index, 1);
await saveMods(mods);
- console.log("Mod removed: " + removedMod);
- } else {
- console.log("Invalid index");
}
}
async function resetMods() {
await saveMods([]);
- console.log("Mods reset");
}
-window.modLoader = async function modLoader(modsArr) {
+window.modLoader = async function modLoader(modsArr = []) {
if (!window.eaglerMLoaderMainRun) {
var searchParams = new URLSearchParams(location.search);
searchParams.getAll("mod").forEach((modToAdd) => {
@@ -94,52 +88,13 @@ window.modLoader = async function modLoader(modsArr) {
});
}
- // Reverse engineer eaglercraftx virtual file system to gain external access to mod store WITHOUT messing with java teavm nonsense
- var StoreId = "EF_MODS";
- var decoder = new TextDecoder("utf-8");
console.log("[EaglerML] Searching in iDB");
try {
- var database = await promisifyIDBRequest(indexedDB.open(StoreId));
- var storeIsValid = !!database.objectStoreNames[0];
- if (!storeIsValid) {
- throw new Error("Invalid object store");
- }
- var key = database.objectStoreNames[0].length === 0 ? "filesystem" : database.objectStoreNames[0];
- var transaction = database.transaction([key], "readwrite");
- var objectStore = transaction.objectStore("filesystem");
- var object = await promisifyIDBRequest(objectStore.get(["mods.txt"]));
- if (!object) {
- throw new Error("No mods.txt found");
- }
- var mods = decoder.decode(object.data);
- if (mods.length === 0) {
- throw new Error("No mods found");
- }
- var modsArr = mods.split("|");
- for (var modFilePath of modsArr) {
- if (modFilePath.length === 0) {
- continue;
- }
- var modUrl = null;
- if (modFilePath.startsWith("web@")) {
- modUrl = modFilePath.replace("web@", "");
- } else {
- var modFile = await promisifyIDBRequest(objectStore.get(["mods/" + modFilePath]));
- if (!modFile) {
- continue;
- }
- var modData = decoder.decode(modFile.data);
- var modBlob = new Blob([modData], {
- type: 'text/javascript'
- });
- modUrl = URL.createObjectURL(modBlob);
- }
- if (!modUrl) {
- continue;
- }
- modsArr.push(modUrl);
- console.log("Loaded iDB mod: " + modFilePath);
- }
+ var idbMods = await getMods();
+ modsArr.concat(idbMods
+ .filter(x => { return x && x.length > 0 })
+ .flatMap(x => { if (x.startsWith("web@")) { return x.replace("web@", "") } return x })
+ );
} catch (error) {
console.error(error);
}
diff --git a/modloader.js b/modloader.js
index 4423bcb..e149676 100644
--- a/modloader.js
+++ b/modloader.js
@@ -28,8 +28,7 @@ async function getMods() {
const transaction = db.transaction(["filesystem"], "readonly");
const objectStore = transaction.objectStore("filesystem");
const object = await promisifyIDBRequest(objectStore.get("mods.txt"));
- const decoder = new TextDecoder("utf-8");
- return object ? decoder.decode(object).split("|") : [];
+ return object ? (await object.text()).split("|") : [];
}
async function saveMods(mods) {
@@ -46,17 +45,13 @@ async function addMod(mod) {
const mods = await getMods();
mods.push(mod);
await saveMods(mods);
- console.log("Mod added: " + mod);
}
async function removeMod(index) {
const mods = await getMods();
if (index >= 0 && index < mods.length) {
- const removedMod = mods.splice(index, 1);
+ mods.splice(index, 1);
await saveMods(mods);
- console.log("Mod removed: " + removedMod);
- } else {
- console.log("Invalid index");
}
}
@@ -65,7 +60,7 @@ async function resetMods() {
console.log("Mods reset");
}
-window.modLoader = async function modLoader(modsArr) {
+window.modLoader = async function modLoader(modsArr = []) {
if (!window.eaglerMLoaderMainRun) {
var searchParams = new URLSearchParams(location.search);
searchParams.getAll("mod").forEach((modToAdd) => {
@@ -94,52 +89,13 @@ window.modLoader = async function modLoader(modsArr) {
});
}
- // Reverse engineer eaglercraftx virtual file system to gain external access to mod store WITHOUT messing with java teavm nonsense
- var StoreId = "EF_MODS";
- var decoder = new TextDecoder("utf-8");
console.log("[EaglerML] Searching in iDB");
try {
- var database = await promisifyIDBRequest(indexedDB.open(StoreId));
- var storeIsValid = !!database.objectStoreNames[0];
- if (!storeIsValid) {
- throw new Error("Invalid object store");
- }
- var key = database.objectStoreNames[0].length === 0 ? "filesystem" : database.objectStoreNames[0];
- var transaction = database.transaction([key], "readwrite");
- var objectStore = transaction.objectStore("filesystem");
- var object = await promisifyIDBRequest(objectStore.get(["mods.txt"]));
- if (!object) {
- throw new Error("No mods.txt found");
- }
- var mods = decoder.decode(object.data);
- if (mods.length === 0) {
- throw new Error("No mods found");
- }
- var modsArr = mods.split("|");
- for (var modFilePath of modsArr) {
- if (modFilePath.length === 0) {
- continue;
- }
- var modUrl = null;
- if (modFilePath.startsWith("web@")) {
- modUrl = modFilePath.replace("web@", "");
- } else {
- var modFile = await promisifyIDBRequest(objectStore.get(["mods/" + modFilePath]));
- if (!modFile) {
- continue;
- }
- var modData = decoder.decode(modFile.data);
- var modBlob = new Blob([modData], {
- type: 'text/javascript'
- });
- modUrl = URL.createObjectURL(modBlob);
- }
- if (!modUrl) {
- continue;
- }
- modsArr.push(modUrl);
- console.log("Loaded iDB mod: " + modFilePath);
- }
+ var idbMods = await getMods();
+ modsArr.concat(idbMods
+ .filter(x => { return x && x.length > 0 })
+ .flatMap(x => { if (x.startsWith("web@")) { return x.replace("web@", "") } return x })
+ );
} catch (error) {
console.error(error);
}