mirror of
https://github.com/eaglerforge/EaglerForgeInjector
synced 2025-07-23 06:01:38 -09:00
add interfaces and implements
This commit is contained in:
parent
bd4b5b9d39
commit
42a0f3e148
@ -24,6 +24,9 @@ Methods:
|
||||
- Copies methods from a reflect class and it's parents onto a target native JavaScript class. This allows TeaVM to use these objects normally, without you having to manually reimplement every method. In other words, this is the equivalent of extending a class.
|
||||
- Also adds some metadata to make the class work with `ModAPI.util.asClass`
|
||||
- [Example usage](https://github.com/eaglerforge/EaglerForgeInjector/blob/6e8598c180f96a65c0c101be72e6d0fa53195404/examplemods/unlucky_blocks.js#L37)
|
||||
- `ModAPI.reflect.implements(target: Class/ConstructorFunction, interface: ReflectClass)`
|
||||
- Marks the provided interface as a supertype of the target class.
|
||||
- JavaScript equivalent of the `implements` keyword
|
||||
### ReflectClass Definition
|
||||
|
||||
Each `ReflectClass` has the following properties:
|
||||
|
@ -151,6 +151,7 @@
|
||||
ModAPI.hooks ||= {};
|
||||
ModAPI.hooks.freezeCallstack = false;
|
||||
ModAPI.hooks._rippedData ||= [];
|
||||
ModAPI.hooks._rippedInterfaceMap ||= {};
|
||||
ModAPI.hooks._teavm ||= {};
|
||||
ModAPI.hooks._rippedConstructors ||= {};
|
||||
ModAPI.hooks._rippedInternalConstructors ||= {};
|
||||
|
35
injector.js
35
injector.js
@ -50,13 +50,13 @@ function entriesToStaticVariableProxy(entries, prefix, clinitList) {
|
||||
.join(",")}];
|
||||
/*/
|
||||
var proxy = `ModAPI.hooks._rippedStaticProperties[\`${prefix.replace(
|
||||
"var ",
|
||||
""
|
||||
)}\`] = new Proxy({${entries
|
||||
.flatMap((x) => {
|
||||
return '"' + x.name + '"';
|
||||
})
|
||||
.join(":null,") + (entries.length > 0 ? ":null" : "")
|
||||
"var ",
|
||||
""
|
||||
)}\`] = new Proxy({${entries
|
||||
.flatMap((x) => {
|
||||
return '"' + x.name + '"';
|
||||
})
|
||||
.join(":null,") + (entries.length > 0 ? ":null" : "")
|
||||
}}, {
|
||||
get: function (a,b,c) {
|
||||
switch (b) {
|
||||
@ -136,7 +136,7 @@ var main;(function(){`
|
||||
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());
|
||||
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...");
|
||||
@ -171,7 +171,7 @@ var main;(function(){`
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
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
|
||||
@ -205,6 +205,7 @@ var main;(function(){`
|
||||
}).filter(x => {
|
||||
return (!x.includes("$_clinit_$")) && (!x.includes("$lambda$"))
|
||||
});
|
||||
//Also stores classes from $rt_classWithoutFields(0)
|
||||
patchedFile = patchedFile.replaceAll(
|
||||
/var \S+?_\S+? = \$rt_classWithoutFields\(\S*?\);/gm,
|
||||
function (match) {
|
||||
@ -213,6 +214,7 @@ var main;(function(){`
|
||||
""
|
||||
);
|
||||
var entries = [];
|
||||
|
||||
staticVariables.forEach((entry) => {
|
||||
if (entry.startsWith(prefix)) {
|
||||
var variableName = entry
|
||||
@ -229,14 +231,17 @@ var main;(function(){`
|
||||
});
|
||||
|
||||
var proxy = entriesToStaticVariableProxy(entries, prefix, clinitList);
|
||||
|
||||
return match + proxy;
|
||||
var shortPrefix = prefix.replace(
|
||||
"var ",
|
||||
""
|
||||
);
|
||||
return match + `ModAPI.hooks._rippedInterfaceMap[\`${shortPrefix}\`]=${shortPrefix};` + proxy;
|
||||
}
|
||||
);
|
||||
//Edge cases. sigh
|
||||
//Done: add support for static properties on classes with constructors like this: function nmcg_GuiMainMenu() {
|
||||
|
||||
|
||||
|
||||
patchedFile = patchedFile.replaceAll(
|
||||
/function [a-z]+?_([a-zA-Z0-9\$]+?)\(\) \{/gm,
|
||||
(match) => {
|
||||
@ -335,7 +340,7 @@ document.querySelector("#giveme").addEventListener("click", () => {
|
||||
} else if (globalThis.doShronk) {
|
||||
patchedFile = await shronk(patchedFile);
|
||||
}
|
||||
|
||||
|
||||
patchedFile.replace(`{"._|_libserverside_|_."}`, "");
|
||||
var blob = new Blob([patchedFile], { type: file.type });
|
||||
saveAs(blob, "processed." + fileType);
|
||||
@ -356,13 +361,13 @@ document.querySelector("#givemeserver").addEventListener("click", () => {
|
||||
|
||||
file.text().then(async (string) => {
|
||||
var patchedFile = string;
|
||||
|
||||
|
||||
if (globalThis.doEaglerforge) {
|
||||
patchedFile = await processClasses(patchedFile);
|
||||
} else if (globalThis.doShronk) {
|
||||
patchedFile = await shronk(patchedFile);
|
||||
}
|
||||
|
||||
|
||||
patchedFile.replace(`{"._|_libserverside_|_."}`, `(${EFServer.toString()})()`);
|
||||
var blob = new Blob([patchedFile], { type: file.type });
|
||||
saveAs(blob, "efserver." + fileType);
|
||||
|
21
postinit.js
21
postinit.js
@ -269,6 +269,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
||||
ModAPI.hooks._rippedConstructorKeys = Object.keys(ModAPI.hooks._rippedConstructors);
|
||||
ModAPI.hooks._rippedInternalConstructorKeys = Object.keys(ModAPI.hooks._rippedInternalConstructors);
|
||||
ModAPI.hooks._rippedMethodKeys = Object.keys(ModAPI.hooks._rippedMethodTypeMap);
|
||||
ModAPI.hooks._rippedInterfaceKeys = Object.keys(ModAPI.hooks._rippedInterfaceMap);
|
||||
|
||||
var compiledNames = new Set();
|
||||
var metaMap = {};
|
||||
@ -302,10 +303,19 @@ globalThis.modapi_postinit = "(" + (() => {
|
||||
}
|
||||
});
|
||||
|
||||
ModAPI.hooks._rippedInterfaceKeys.forEach(className => {
|
||||
if (typeof className === "string" && className.length > 0) {
|
||||
//Interfaces using $rt_classWithoutFields(0) and no constructors.
|
||||
if (className && className.includes("_")) {
|
||||
compiledNames.add(className);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//Initialise all compiled names into the class map
|
||||
compiledNames.forEach(compiledName => {
|
||||
var item = metaMap[compiledName];
|
||||
var item = metaMap[compiledName] || ModAPI.hooks._rippedInterfaceMap[compiledName];
|
||||
var classId = item?.$meta?.name || null;
|
||||
|
||||
if (!ModAPI.hooks._classMap[compiledName]) {
|
||||
@ -321,7 +331,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
||||
"staticVariables": {},
|
||||
"staticVariableNames": [],
|
||||
"class": item || null,
|
||||
"hasMeta": !!item,
|
||||
"hasMeta": !!(item?.$meta),
|
||||
"instanceOf": function (object) {
|
||||
try {
|
||||
return ModAPI.hooks._teavm.$rt_isInstance(object, item || null);
|
||||
@ -431,6 +441,13 @@ globalThis.modapi_postinit = "(" + (() => {
|
||||
};
|
||||
classFn.classObject = null;
|
||||
}
|
||||
ModAPI.reflect.implements = function implements(classFn, reflectClass) {
|
||||
classFn.$meta ||= {};
|
||||
classFn.$meta.supertypes ||= [];
|
||||
if (reflectClass && reflectClass.class) {
|
||||
classFn.$meta.supertypes.push(reflectClass.class);
|
||||
}
|
||||
}
|
||||
|
||||
var reloadDeprecationWarnings = 0;
|
||||
const TeaVMArray_To_Recursive_BaseData_ProxyConf = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user