Merge pull request #47 from eaglerforge/main

Version v2.3.4
This commit is contained in:
ZXMushroom63 2024-12-24 20:20:39 +08:00 committed by GitHub
commit 46b57d109a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 241 additions and 55 deletions

View File

@ -63,9 +63,6 @@
} }
ModAPI.reflect.prototypeStack(itemClass, nmi_ItemPistol); ModAPI.reflect.prototypeStack(itemClass, nmi_ItemPistol);
nmi_ItemPistol.prototype.$onItemRightClick = function ($itemstack, $world, $player) { nmi_ItemPistol.prototype.$onItemRightClick = function ($itemstack, $world, $player) {
DamageSourceClass.staticMethods.$callClinit.method();
//Noticed that the gun only worked after an entity in the world takes damage XD
//TeaVM is very optimised. Using $callClinit tells it to hurry up pretty much lol
var cactus = DamageSourceClass.staticVariables.cactus; var cactus = DamageSourceClass.staticVariables.cactus;
var world = ModAPI.util.wrap($world); var world = ModAPI.util.wrap($world);
var entityplayer = ModAPI.util.wrap($player); var entityplayer = ModAPI.util.wrap($player);

View File

@ -63,9 +63,6 @@
} }
ModAPI.reflect.prototypeStack(itemClass, nmi_ItemPistol); ModAPI.reflect.prototypeStack(itemClass, nmi_ItemPistol);
nmi_ItemPistol.prototype.$onItemRightClick = function ($itemstack, $world, $player) { nmi_ItemPistol.prototype.$onItemRightClick = function ($itemstack, $world, $player) {
DamageSourceClass.staticMethods.$callClinit.method();
//Noticed that the gun only worked after an entity in the world takes damage XD
//TeaVM is very optimised. Using $callClinit tells it to hurry up pretty much lol
var cactus = DamageSourceClass.staticVariables.cactus; var cactus = DamageSourceClass.staticVariables.cactus;
var world = ModAPI.util.wrap($world); var world = ModAPI.util.wrap($world);
var entityplayer = ModAPI.util.wrap($player); var entityplayer = ModAPI.util.wrap($player);

47
examplemods/sliders.js Normal file
View File

@ -0,0 +1,47 @@
(function Sliders() {
ModAPI.meta.title("Sliders");
ModAPI.meta.description("Remove the clamping on sliders.");
ModAPI.meta.credits("By ZXMushroom63");
const MathHelper_clamp_float = ModAPI.util.getMethodFromPackage("net.minecraft.util.MathHelper", "clamp_float");
const GuiOptionSlider_mouseDragged = ModAPI.util.getMethodFromPackage("net.minecraft.client.gui.GuiOptionSlider", "mouseDragged");
const GuiOptionSlider_mousePressed = ModAPI.util.getMethodFromPackage("net.minecraft.client.gui.GuiOptionSlider", "mousePressed");
const GameSetting$Options_normalizeValue = ModAPI.util.getMethodFromPackage("net.minecraft.client.settings.GameSettings$Options", "normalizeValue");
const GameSetting$Options_snapToStepClamp = ModAPI.util.getMethodFromPackage("net.minecraft.client.settings.GameSettings$Options", "snapToStepClamp");
const GuiOptionSlider_mouseDragged_fn = ModAPI.hooks.methods[GuiOptionSlider_mouseDragged];
const GuiOptionSlider_mousePressed_fn = ModAPI.hooks.methods[GuiOptionSlider_mousePressed];
const GameSetting$Options_normalizeValue_fn = ModAPI.hooks.methods[GameSetting$Options_normalizeValue];
const GameSetting$Options_snapToStepClamp_fn = ModAPI.hooks.methods[GameSetting$Options_snapToStepClamp];
const MathHelper_clamp_float_fn = ModAPI.hooks.methods[MathHelper_clamp_float];
const fakeClampMethod = (x)=>x;
ModAPI.hooks.methods[GuiOptionSlider_mouseDragged] = function (...args) {
ModAPI.hooks.methods[MathHelper_clamp_float] = fakeClampMethod;
var ret = GuiOptionSlider_mouseDragged_fn.apply(this, args);
ModAPI.hooks.methods[MathHelper_clamp_float] = MathHelper_clamp_float_fn;
return ret;
}
ModAPI.hooks.methods[GuiOptionSlider_mousePressed] = function (...args) {
ModAPI.hooks.methods[MathHelper_clamp_float] = fakeClampMethod;
var ret = GuiOptionSlider_mousePressed_fn.apply(this, args);
ModAPI.hooks.methods[MathHelper_clamp_float] = MathHelper_clamp_float_fn;
return ret;
}
ModAPI.hooks.methods[GameSetting$Options_normalizeValue] = function (...args) {
ModAPI.hooks.methods[MathHelper_clamp_float] = fakeClampMethod;
var ret = GameSetting$Options_normalizeValue_fn.apply(this, args);
ModAPI.hooks.methods[MathHelper_clamp_float] = MathHelper_clamp_float_fn;
return ret;
}
// ModAPI.hooks.methods[GameSetting$Options_snapToStepClamp] = function (...args) {
// ModAPI.hooks.methods[MathHelper_clamp_float] = fakeClampMethod;
// var ret = GameSetting$Options_snapToStepClamp_fn.apply(this, args);
// ModAPI.hooks.methods[MathHelper_clamp_float] = MathHelper_clamp_float_fn;
// return ret;
// }
})();

138
examplemods/waypoints.js Normal file
View File

@ -0,0 +1,138 @@
(function Waypoints() {
ModAPI.meta.title("Waypoints Mod");
ModAPI.meta.description("Use /setwp <name> to make a waypoint, and /wp <name> to go to it. /remwp <name> to delete a waypoint. /listwp to list all waypoints.");
ModAPI.meta.credits("By blizz828, Block_2222 & ZXMushroom63");
ModAPI.dedicatedServer.appendCode(async ()=>{ //The mods should probably be running on the server
function initDB(dbName, storeName) {
return new Promise((resolve, reject) => {
const request = indexedDB.open(dbName, 2);
request.onupgradeneeded = (event) => {
const db = event.target.result;
if (!db.objectStoreNames.contains(storeName)) {
db.createObjectStore(storeName);
}
resolve(db);
};
request.onsuccess = (event) => {
const db = event.target.result;
resolve(db);
};
request.onerror = (event) => {
reject('Error opening database: ' + event.target.errorCode);
};
});
}
function storeString(dbName, storeName, key, value) {
return initDB(dbName, storeName).then((db) => {
return new Promise((resolve, reject) => {
const transaction = db.transaction(storeName, 'readwrite');
const store = transaction.objectStore(storeName);
const putRequest = store.put(value, key);
putRequest.onsuccess = () => {
resolve('String stored successfully.');
};
putRequest.onerror = (event) => {
reject('Error storing string: ' + event.target.errorCode);
};
});
});
}
function retrieveString(dbName, storeName, key) {
return initDB(dbName, storeName).then((db) => {
return new Promise((resolve, reject) => {
const transaction = db.transaction(storeName, 'readonly');
const store = transaction.objectStore(storeName);
const getRequest = store.get(key);
getRequest.onsuccess = () => {
if (getRequest.result !== undefined) {
resolve(getRequest.result);
} else {
resolve('');
}
};
getRequest.onerror = (event) => {
resolve('');
};
});
});
}
var data = {};
try {
data = JSON.parse(await retrieveString("waypoints_db", "waypoints", "waypoints"));
} catch(e) {
//didn't ask
}
async function saveData() {
await storeString("waypoints_db", "waypoints", "waypoints", JSON.stringify(data));
}
ModAPI.addEventListener("processcommand", (e)=>{
if (!ModAPI.reflect.getClassById("net.minecraft.entity.player.EntityPlayerMP").instanceOf(e.sender.getRef())) {
return;
}
if (e.command.toLowerCase().startsWith("/setwp ") && e.sender.canCommandSenderUseCommand(2, ModAPI.util.str("setwp"))) {
e.preventDefault = true;
var pos = e.sender.getPosition();
var name = ModAPI.util.unstring(e.sender.getName().getRef());
var waypointId = e.command.split(" ")[1] || "waypoint";
waypointId = waypointId.replace(/[^a-zA-Z0-9_]/gm, "_");
if (!data[name]) {
data[name] = {};
}
data[name][waypointId] = [pos.x,pos.y,pos.z,e.sender.dimension];
saveData();
e.sender.addChatMessage(ModAPI.reflect.getClassById("net.minecraft.util.ChatComponentText").constructors[0](ModAPI.util.str("Set waypoint "+waypointId+".")));
}
if (e.command.toLowerCase().startsWith("/wp ") && e.sender.canCommandSenderUseCommand(2, ModAPI.util.str("wp"))) {
e.preventDefault = true;
var name = ModAPI.util.unstring(e.sender.getName().getRef());
var waypointId = e.command.split(" ")[1];
if (waypointId && Array.isArray(data?.[name]?.[waypointId])) {
// Wildly important! regular setPosition triggers minecraft's built in anti-cheat and teleports you back in the same tick.
if (data?.[name]?.[waypointId]?.[3] && (data?.[name]?.[waypointId]?.[3] !== e.sender.dimension)) {
e.sender.travelToDimension(data?.[name]?.[waypointId]?.[3]);
}
e.sender.setPositionAndUpdate(...data?.[name]?.[waypointId]);
e.sender.addChatMessage(ModAPI.reflect.getClassById("net.minecraft.util.ChatComponentText").constructors[0](ModAPI.util.str("Teleported to waypoint " + waypointId + ".")));
} else {
e.sender.addChatMessage(ModAPI.reflect.getClassById("net.minecraft.util.ChatComponentText").constructors[0](ModAPI.util.str("No such waypoint.")));
}
}
if (e.command.toLowerCase().startsWith("/remwp ") && e.sender.canCommandSenderUseCommand(2, ModAPI.util.str("remwp"))) {
e.preventDefault = true;
var name = ModAPI.util.unstring(e.sender.getName().getRef());
var waypointId = e.command.split(" ")[1] || "waypoint";
if (!data[name]) {
data[name] = {};
}
delete data[name][waypointId];
saveData();
e.sender.addChatMessage(ModAPI.reflect.getClassById("net.minecraft.util.ChatComponentText").constructors[0](ModAPI.util.str("Removed waypoint "+waypointId+".")));
}
if ((e.command.toLowerCase() === "/listwp") && e.sender.canCommandSenderUseCommand(2, ModAPI.util.str("listwp"))) {
e.preventDefault = true;
var name = ModAPI.util.unstring(e.sender.getName().getRef());
if (!data[name]) {
data[name] = {};
}
e.sender.addChatMessage(ModAPI.reflect.getClassById("net.minecraft.util.ChatComponentText").constructors[0](ModAPI.util.str("Your waypoints: " + Object.keys(data[name]).join(", "))));
}
});
});
})();

View File

@ -90,9 +90,8 @@
>Choose .html file...</label >Choose .html file...</label
> >
<br /> <br />
<span><label>Minify:&nbsp;</label><input type="checkbox" oninput="globalThis.doShronk = this.checked">&nbsp;&nbsp;&nbsp; <span><label>Minify:&nbsp;</label><input type="checkbox" oninput="globalThis.doShronk = this.checked">
<label>EaglerForge:&nbsp;</label><input checked type="checkbox" oninput="globalThis.doEaglerforge = this.checked">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<label>EaglerForge:&nbsp;</label><input checked type="checkbox" oninput="globalThis.doEaglerforge = this.checked">
<label>Optimize π:&nbsp;</label><input checked type="checkbox" oninput="globalThis.optimizePi= this.checked">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code id="status">Awaiting input...</code></span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<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>

View File

@ -1,5 +1,4 @@
globalThis.doEaglerforge = true; globalThis.doEaglerforge = true;
globalThis.optimizePi = true;
function wait(ms) { function wait(ms) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
setTimeout(() => { resolve(); }, ms); setTimeout(() => { resolve(); }, ms);
@ -8,12 +7,19 @@ function wait(ms) {
function _status(x) { function _status(x) {
document.querySelector("#status").innerText = x; document.querySelector("#status").innerText = x;
} }
function entriesToStaticVariableProxy(entries, prefix) { function entriesToStaticVariableProxy(entries, prefix, clinitList) {
prefix = prefix.replace(
"var ",
""
);
if (entries.length === 0) { if (entries.length === 0) {
return `ModAPI.hooks._rippedStaticProperties[\`${prefix.replace( return `ModAPI.hooks._rippedStaticProperties[\`${prefix}\`]={};`;
"var ", }
"" if (clinitList.includes(prefix + "_$callClinit")) {
)}\`]={};`; entries.push({
name: "$callClinit",
variable: prefix + "_$callClinit"
});
} }
var getComponents = ""; var getComponents = "";
entries.forEach((entry) => { entries.forEach((entry) => {
@ -126,6 +132,10 @@ var main;(function(){`
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...");
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);
@ -159,28 +169,6 @@ var main;(function(){`
} }
); );
if(globalThis.optimizePi){
patchedFile = patchedFile.replaceAll(
"3.1415927410125732 / 180.0",
"0.01745"
);
patchedFile = patchedFile.replaceAll(
"180.0 / 3.1415927410125732",
"57.2958"
);
patchedFile = patchedFile.replaceAll(
"3.1415927410125732",
"3.14159"
);
patchedFile = patchedFile.replaceAll(
"0.01745329238474369",
"0.01745"
);
}
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
@ -189,7 +177,8 @@ var main;(function(){`
(match) => { (match) => {
if ( if (
match.includes("__init_") || match.includes("__init_") ||
match.includes("__clinit_") match.includes("__clinit_") ||
match.includes("_$callClinit")
) { ) {
return match; return match;
} }
@ -236,7 +225,7 @@ var main;(function(){`
} }
}); });
var proxy = entriesToStaticVariableProxy(entries, prefix); var proxy = entriesToStaticVariableProxy(entries, prefix, clinitList);
return match + proxy; return match + proxy;
} }
@ -266,7 +255,7 @@ var main;(function(){`
} }
}); });
var proxy = entriesToStaticVariableProxy(entries, prefix); var proxy = entriesToStaticVariableProxy(entries, prefix, clinitList);
return proxy + "\n" + match; return proxy + "\n" + match;
} }

View File

@ -63,7 +63,11 @@ globalThis.modapi_modloader = "(" + (() => {
globalThis.addFileMod = async function addFileMod(mod, textContents) { globalThis.addFileMod = async function addFileMod(mod, textContents) {
const mods = await getMods(); const mods = await getMods();
mods.push(mod); if (mods.includes(mod)) {
await removeMod(mods.indexOf(mod));
} else {
mods.push(mod);
}
await saveMods(mods); await saveMods(mods);
const db = await getDatabase(); const db = await getDatabase();

View File

@ -1,4 +1,4 @@
globalThis.ModAPIVersion = "v2.3.3"; globalThis.ModAPIVersion = "v2.3.4";
globalThis.modapi_postinit = "(" + (() => { globalThis.modapi_postinit = "(" + (() => {
//EaglerForge post initialization code. //EaglerForge post initialization code.
//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.
@ -42,7 +42,7 @@ globalThis.modapi_postinit = "(" + (() => {
if (!document.currentScript.hasAttribute("data-hash")) { if (!document.currentScript.hasAttribute("data-hash")) {
return console.log("[ModAPIMeta] Script does not have a hashcode."); return console.log("[ModAPIMeta] Script does not have a hashcode.");
} }
ModAPI.meta._titleMap[document.currentScript.getAttribute("data-hash")] = limitSize(title, 16); ModAPI.meta._titleMap[document.currentScript.getAttribute("data-hash")] = limitSize(title, 36);
} }
ModAPI.meta.icon = function (iconSrc) { ModAPI.meta.icon = function (iconSrc) {
if (!document.currentScript || document.currentScript.getAttribute("data-isMod") !== "true") { if (!document.currentScript || document.currentScript.getAttribute("data-isMod") !== "true") {
@ -60,7 +60,7 @@ globalThis.modapi_postinit = "(" + (() => {
if (!document.currentScript.hasAttribute("data-hash")) { if (!document.currentScript.hasAttribute("data-hash")) {
return console.log("[ModAPIMeta] Script does not have a hashcode."); return console.log("[ModAPIMeta] Script does not have a hashcode.");
} }
ModAPI.meta._developerMap[document.currentScript.getAttribute("data-hash")] = limitSize(cd, 36); ModAPI.meta._developerMap[document.currentScript.getAttribute("data-hash")] = limitSize(cd, 128);
} }
ModAPI.meta.description = function (desc) { ModAPI.meta.description = function (desc) {
if (!document.currentScript || document.currentScript.getAttribute("data-isMod") !== "true") { if (!document.currentScript || document.currentScript.getAttribute("data-isMod") !== "true") {
@ -78,7 +78,7 @@ globalThis.modapi_postinit = "(" + (() => {
if (!document.currentScript.hasAttribute("data-hash")) { if (!document.currentScript.hasAttribute("data-hash")) {
return console.log("[ModAPIMeta] Script does not have a hashcode."); return console.log("[ModAPIMeta] Script does not have a hashcode.");
} }
ModAPI.meta._versionMap[document.currentScript.getAttribute("data-hash")] = limitSize(ver, 6); ModAPI.meta._versionMap[document.currentScript.getAttribute("data-hash")] = limitSize(ver, 7);
} }
ModAPI.reflect ||= {}; ModAPI.reflect ||= {};
ModAPI.server = ModAPI.serverInstance = null; ModAPI.server = ModAPI.serverInstance = null;
@ -208,6 +208,16 @@ globalThis.modapi_postinit = "(" + (() => {
return ModAPI.hooks._teavm.$rt_createDoubleArray(size); return ModAPI.hooks._teavm.$rt_createDoubleArray(size);
} }
//Proxy to make sure static variables are initialized before access.
function makeClinitProxy(staticVariables, clinit) {
return new Proxy(staticVariables, {
get: function (a, b, c) {
clinit();
return Reflect.get(a, b, c);
}
});
}
ModAPI.hooks.regenerateClassMap = function () { ModAPI.hooks.regenerateClassMap = function () {
ModAPI.hooks._rippedConstructorKeys = Object.keys(ModAPI.hooks._rippedConstructors); ModAPI.hooks._rippedConstructorKeys = Object.keys(ModAPI.hooks._rippedConstructors);
ModAPI.hooks._rippedInternalConstructorKeys = Object.keys(ModAPI.hooks._rippedInternalConstructors); ModAPI.hooks._rippedInternalConstructorKeys = Object.keys(ModAPI.hooks._rippedInternalConstructors);
@ -265,7 +275,11 @@ globalThis.modapi_postinit = "(" + (() => {
"class": item || null, "class": item || null,
"hasMeta": !!item, "hasMeta": !!item,
"instanceOf": function (object) { "instanceOf": function (object) {
return ModAPI.hooks._teavm.$rt_isInstance(object, item || null); try {
return ModAPI.hooks._teavm.$rt_isInstance(object, item || null);
} catch {
return false;
}
}, },
"compiledName": compiledName "compiledName": compiledName
} }
@ -278,9 +292,6 @@ globalThis.modapi_postinit = "(" + (() => {
ModAPI.hooks._classMap[compiledName].superclassName = null; ModAPI.hooks._classMap[compiledName].superclassName = null;
} }
ModAPI.hooks._classMap[compiledName].staticVariables = ModAPI.hooks._rippedStaticProperties[compiledName];
ModAPI.hooks._classMap[compiledName].staticVariableNames = Object.keys(ModAPI.hooks._classMap[compiledName].staticVariables || {});
if (item?.["$$constructor$$"]) { if (item?.["$$constructor$$"]) {
//Class does not have any hand written constructors //Class does not have any hand written constructors
//Eg: class MyClass {} //Eg: class MyClass {}
@ -320,6 +331,10 @@ globalThis.modapi_postinit = "(" + (() => {
} }
} }
}); });
ModAPI.hooks._classMap[compiledName].staticVariables = makeClinitProxy(ModAPI.hooks._rippedStaticProperties[compiledName] || {}, (()=>{
(ModAPI.hooks._rippedStaticProperties[compiledName].$callClinit ?? (()=>{}))();
}));
ModAPI.hooks._classMap[compiledName].staticVariableNames = Object.keys(ModAPI.hooks._classMap[compiledName].staticVariables);
}); });
ModAPI.reflect.classes = Object.values(ModAPI.hooks._classMap); ModAPI.reflect.classes = Object.values(ModAPI.hooks._classMap);
console.log("[ModAPI] Regenerated hook classmap."); console.log("[ModAPI] Regenerated hook classmap.");
@ -336,7 +351,7 @@ globalThis.modapi_postinit = "(" + (() => {
//Magical function for making a subclass with a custom constructor that you can easily use super(...) on. //Magical function for making a subclass with a custom constructor that you can easily use super(...) on.
ModAPI.reflect.getSuper = function getSuper(reflectClass, filter) { ModAPI.reflect.getSuper = function getSuper(reflectClass, filter) {
filter ||= ()=>true; filter ||= () => true;
var initialiser = reflectClass.internalConstructors.find(filter); var initialiser = reflectClass.internalConstructors.find(filter);
return function superFunction(thisArg, ...extra_args) { return function superFunction(thisArg, ...extra_args) {
reflectClass.class.call(thisArg); reflectClass.class.call(thisArg);
@ -471,7 +486,7 @@ globalThis.modapi_postinit = "(" + (() => {
} }
ModAPI.events.listeners[name].push(callback); ModAPI.events.listeners[name].push(callback);
} }
console.log("[ModAPI] Added new library listener."); console.log("[ModAPI] Added new library listener: " + name);
return; return;
} }
if (!callback || typeof callback !== "function") { if (!callback || typeof callback !== "function") {
@ -482,7 +497,7 @@ globalThis.modapi_postinit = "(" + (() => {
ModAPI.events.listeners[name] = []; ModAPI.events.listeners[name] = [];
} }
ModAPI.events.listeners[name].push(callback); ModAPI.events.listeners[name].push(callback);
console.log("[ModAPI] Added new event listener."); console.log("[ModAPI] Added new event listener: " + name);
} else { } else {
throw new Error("[ModAPI] This event does not exist!"); throw new Error("[ModAPI] This event does not exist!");
} }