GUI COMPLETE

This commit is contained in:
ZXMushroom63 2024-08-31 17:32:03 +08:00
parent 133b6081af
commit fa9e0220b8
4 changed files with 196 additions and 191 deletions

View File

@ -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 = \`<div id="modapi_gui_container">
(() => {
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 = \`<div id="modapi_gui_container">
<header>
<h1 class="title">EaglerForge Mod Manager</h1>
<h4>
@ -158,38 +158,85 @@ globalThis.modapi_guikit = `// ModAPI GUI made by TheIdiotPlays
}
</style>
</div>\`;
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();
}
})();`;

133
modgui.js
View File

@ -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 = `<div id="modapi_gui_container">
(() => {
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 = `<div id="modapi_gui_container">
<header>
<h1 class="title">EaglerForge Mod Manager</h1>
<h4>
@ -158,38 +158,85 @@
}
</style>
</div>`;
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();
}
})();

View File

@ -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);
}

View File

@ -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);
}