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.
|
- 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`
|
- 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)
|
- [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
|
### ReflectClass Definition
|
||||||
|
|
||||||
Each `ReflectClass` has the following properties:
|
Each `ReflectClass` has the following properties:
|
||||||
|
@ -151,6 +151,7 @@
|
|||||||
ModAPI.hooks ||= {};
|
ModAPI.hooks ||= {};
|
||||||
ModAPI.hooks.freezeCallstack = false;
|
ModAPI.hooks.freezeCallstack = false;
|
||||||
ModAPI.hooks._rippedData ||= [];
|
ModAPI.hooks._rippedData ||= [];
|
||||||
|
ModAPI.hooks._rippedInterfaceMap ||= {};
|
||||||
ModAPI.hooks._teavm ||= {};
|
ModAPI.hooks._teavm ||= {};
|
||||||
ModAPI.hooks._rippedConstructors ||= {};
|
ModAPI.hooks._rippedConstructors ||= {};
|
||||||
ModAPI.hooks._rippedInternalConstructors ||= {};
|
ModAPI.hooks._rippedInternalConstructors ||= {};
|
||||||
|
35
injector.js
35
injector.js
@ -50,13 +50,13 @@ function entriesToStaticVariableProxy(entries, prefix, clinitList) {
|
|||||||
.join(",")}];
|
.join(",")}];
|
||||||
/*/
|
/*/
|
||||||
var proxy = `ModAPI.hooks._rippedStaticProperties[\`${prefix.replace(
|
var proxy = `ModAPI.hooks._rippedStaticProperties[\`${prefix.replace(
|
||||||
"var ",
|
"var ",
|
||||||
""
|
""
|
||||||
)}\`] = new Proxy({${entries
|
)}\`] = new Proxy({${entries
|
||||||
.flatMap((x) => {
|
.flatMap((x) => {
|
||||||
return '"' + x.name + '"';
|
return '"' + x.name + '"';
|
||||||
})
|
})
|
||||||
.join(":null,") + (entries.length > 0 ? ":null" : "")
|
.join(":null,") + (entries.length > 0 ? ":null" : "")
|
||||||
}}, {
|
}}, {
|
||||||
get: function (a,b,c) {
|
get: function (a,b,c) {
|
||||||
switch (b) {
|
switch (b) {
|
||||||
@ -136,7 +136,7 @@ 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...");
|
_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);
|
console.log(clinitList);
|
||||||
|
|
||||||
_status("Extracting constructors and methods...");
|
_status("Extracting constructors and methods...");
|
||||||
@ -171,7 +171,7 @@ var main;(function(){`
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
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
|
||||||
@ -205,6 +205,7 @@ var main;(function(){`
|
|||||||
}).filter(x => {
|
}).filter(x => {
|
||||||
return (!x.includes("$_clinit_$")) && (!x.includes("$lambda$"))
|
return (!x.includes("$_clinit_$")) && (!x.includes("$lambda$"))
|
||||||
});
|
});
|
||||||
|
//Also stores classes from $rt_classWithoutFields(0)
|
||||||
patchedFile = patchedFile.replaceAll(
|
patchedFile = patchedFile.replaceAll(
|
||||||
/var \S+?_\S+? = \$rt_classWithoutFields\(\S*?\);/gm,
|
/var \S+?_\S+? = \$rt_classWithoutFields\(\S*?\);/gm,
|
||||||
function (match) {
|
function (match) {
|
||||||
@ -213,6 +214,7 @@ var main;(function(){`
|
|||||||
""
|
""
|
||||||
);
|
);
|
||||||
var entries = [];
|
var entries = [];
|
||||||
|
|
||||||
staticVariables.forEach((entry) => {
|
staticVariables.forEach((entry) => {
|
||||||
if (entry.startsWith(prefix)) {
|
if (entry.startsWith(prefix)) {
|
||||||
var variableName = entry
|
var variableName = entry
|
||||||
@ -229,14 +231,17 @@ var main;(function(){`
|
|||||||
});
|
});
|
||||||
|
|
||||||
var proxy = entriesToStaticVariableProxy(entries, prefix, clinitList);
|
var proxy = entriesToStaticVariableProxy(entries, prefix, clinitList);
|
||||||
|
var shortPrefix = prefix.replace(
|
||||||
return match + proxy;
|
"var ",
|
||||||
|
""
|
||||||
|
);
|
||||||
|
return match + `ModAPI.hooks._rippedInterfaceMap[\`${shortPrefix}\`]=${shortPrefix};` + proxy;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
//Edge cases. sigh
|
//Edge cases. sigh
|
||||||
//Done: add support for static properties on classes with constructors like this: function nmcg_GuiMainMenu() {
|
//Done: add support for static properties on classes with constructors like this: function nmcg_GuiMainMenu() {
|
||||||
|
|
||||||
|
|
||||||
patchedFile = patchedFile.replaceAll(
|
patchedFile = patchedFile.replaceAll(
|
||||||
/function [a-z]+?_([a-zA-Z0-9\$]+?)\(\) \{/gm,
|
/function [a-z]+?_([a-zA-Z0-9\$]+?)\(\) \{/gm,
|
||||||
(match) => {
|
(match) => {
|
||||||
@ -335,7 +340,7 @@ document.querySelector("#giveme").addEventListener("click", () => {
|
|||||||
} else if (globalThis.doShronk) {
|
} else if (globalThis.doShronk) {
|
||||||
patchedFile = await shronk(patchedFile);
|
patchedFile = await shronk(patchedFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
patchedFile.replace(`{"._|_libserverside_|_."}`, "");
|
patchedFile.replace(`{"._|_libserverside_|_."}`, "");
|
||||||
var blob = new Blob([patchedFile], { type: file.type });
|
var blob = new Blob([patchedFile], { type: file.type });
|
||||||
saveAs(blob, "processed." + fileType);
|
saveAs(blob, "processed." + fileType);
|
||||||
@ -356,13 +361,13 @@ document.querySelector("#givemeserver").addEventListener("click", () => {
|
|||||||
|
|
||||||
file.text().then(async (string) => {
|
file.text().then(async (string) => {
|
||||||
var patchedFile = string;
|
var patchedFile = string;
|
||||||
|
|
||||||
if (globalThis.doEaglerforge) {
|
if (globalThis.doEaglerforge) {
|
||||||
patchedFile = await processClasses(patchedFile);
|
patchedFile = await processClasses(patchedFile);
|
||||||
} else if (globalThis.doShronk) {
|
} else if (globalThis.doShronk) {
|
||||||
patchedFile = await shronk(patchedFile);
|
patchedFile = await shronk(patchedFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
patchedFile.replace(`{"._|_libserverside_|_."}`, `(${EFServer.toString()})()`);
|
patchedFile.replace(`{"._|_libserverside_|_."}`, `(${EFServer.toString()})()`);
|
||||||
var blob = new Blob([patchedFile], { type: file.type });
|
var blob = new Blob([patchedFile], { type: file.type });
|
||||||
saveAs(blob, "efserver." + fileType);
|
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._rippedConstructorKeys = Object.keys(ModAPI.hooks._rippedConstructors);
|
||||||
ModAPI.hooks._rippedInternalConstructorKeys = Object.keys(ModAPI.hooks._rippedInternalConstructors);
|
ModAPI.hooks._rippedInternalConstructorKeys = Object.keys(ModAPI.hooks._rippedInternalConstructors);
|
||||||
ModAPI.hooks._rippedMethodKeys = Object.keys(ModAPI.hooks._rippedMethodTypeMap);
|
ModAPI.hooks._rippedMethodKeys = Object.keys(ModAPI.hooks._rippedMethodTypeMap);
|
||||||
|
ModAPI.hooks._rippedInterfaceKeys = Object.keys(ModAPI.hooks._rippedInterfaceMap);
|
||||||
|
|
||||||
var compiledNames = new Set();
|
var compiledNames = new Set();
|
||||||
var metaMap = {};
|
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
|
//Initialise all compiled names into the class map
|
||||||
compiledNames.forEach(compiledName => {
|
compiledNames.forEach(compiledName => {
|
||||||
var item = metaMap[compiledName];
|
var item = metaMap[compiledName] || ModAPI.hooks._rippedInterfaceMap[compiledName];
|
||||||
var classId = item?.$meta?.name || null;
|
var classId = item?.$meta?.name || null;
|
||||||
|
|
||||||
if (!ModAPI.hooks._classMap[compiledName]) {
|
if (!ModAPI.hooks._classMap[compiledName]) {
|
||||||
@ -321,7 +331,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
"staticVariables": {},
|
"staticVariables": {},
|
||||||
"staticVariableNames": [],
|
"staticVariableNames": [],
|
||||||
"class": item || null,
|
"class": item || null,
|
||||||
"hasMeta": !!item,
|
"hasMeta": !!(item?.$meta),
|
||||||
"instanceOf": function (object) {
|
"instanceOf": function (object) {
|
||||||
try {
|
try {
|
||||||
return ModAPI.hooks._teavm.$rt_isInstance(object, item || null);
|
return ModAPI.hooks._teavm.$rt_isInstance(object, item || null);
|
||||||
@ -431,6 +441,13 @@ globalThis.modapi_postinit = "(" + (() => {
|
|||||||
};
|
};
|
||||||
classFn.classObject = null;
|
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;
|
var reloadDeprecationWarnings = 0;
|
||||||
const TeaVMArray_To_Recursive_BaseData_ProxyConf = {
|
const TeaVMArray_To_Recursive_BaseData_ProxyConf = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user