mirror of
https://github.com/eaglerforge/EaglerForgeInjector
synced 2025-07-23 06:01:38 -09:00
2.2 beta
This commit is contained in:
parent
8743dd983f
commit
541f9b4af3
@ -49,6 +49,10 @@ Can only be used in the context of the dedicated server. More: [DedicatedServerD
|
||||
- `serverstart`:
|
||||
- Called when the dedicated server starts.
|
||||
- Event object is blank.
|
||||
- `bootstrap`:
|
||||
- Called when the dedicated server registers blocks, items, materials, enchantments, etc.
|
||||
- This is when you should register cstom blocks and items.
|
||||
- Event object is blank.
|
||||
- `serverstop`:
|
||||
- Called when the dedicated server stops.
|
||||
- Event object is blank.
|
||||
|
@ -44,7 +44,9 @@ Each `ReflectClass` has the following properties:
|
||||
- List of all the static variable names for the class.
|
||||
- `staticVariables: Map<String, *>`
|
||||
- key-value dictionary of all the static variables in a class.
|
||||
- `superclass: String?`
|
||||
- `superclass: Class?`
|
||||
- The raw teavm class of the superclass.
|
||||
- `superclassName: String?`
|
||||
- The class id of the class's superclass. Eg: `net.minecraft.client.entity.AbstractClientPlayer`
|
||||
- Will be `null` if `hasMeta` is equal to `false`
|
||||
|
||||
|
@ -40,6 +40,7 @@ ModAPI.meta.credits("By ZXMushroom63");
|
||||
|
||||
// @type Map<string, ArrayBuffer>
|
||||
AsyncSink.FS = new Map();
|
||||
AsyncSink.L10N = new Map();
|
||||
AsyncSink.FSOverride = new Set();
|
||||
AsyncSink.MIDDLEWARE = [];
|
||||
AsyncSink.setFile = function setFile(path, data) {
|
||||
@ -149,7 +150,27 @@ ModAPI.meta.credits("By ZXMushroom63");
|
||||
return originalFileExists.apply(this, args);
|
||||
};
|
||||
|
||||
const L10NRead = ModAPI.util.getMethodFromPackage("net.minecraft.util.StatCollector", "translateToLocal");
|
||||
const originalL10NRead = ModAPI.hooks.methods[L10NRead];
|
||||
ModAPI.hooks.methods[L10NRead] = function (...args) {
|
||||
var key = ModAPI.util.ustr(args[0]);
|
||||
if (AsyncSink.L10N.has(key)) {
|
||||
return ModAPI.util.str(AsyncSink.L10N.get(key));
|
||||
}
|
||||
return originalL10NRead.apply(this, args);
|
||||
};
|
||||
|
||||
const L10NCheck = ModAPI.util.getMethodFromPackage("net.minecraft.util.StatCollector", "canTranslate");
|
||||
const originalL10NCheck = ModAPI.hooks.methods[L10NRead];
|
||||
ModAPI.hooks.methods[L10NCheck] = function (...args) {
|
||||
if (AsyncSink.L10N.has(ModAPI.util.ustr(args[0]))) {
|
||||
return 1;
|
||||
}
|
||||
return originalL10NCheck.apply(this, args);
|
||||
};
|
||||
|
||||
globalThis.AsyncSink = AsyncSink;
|
||||
ModAPI.events.newEvent("lib:asyncsink");
|
||||
ModAPI.events.callEvent("lib:asyncsink", {});
|
||||
console.log("[AsyncSink] Loaded!");
|
||||
}
|
||||
@ -225,6 +246,7 @@ ModAPI.meta.credits("By ZXMushroom63");
|
||||
ModAPI.addEventListener("sendchatmessage", (e) => {
|
||||
if (e.message.toLowerCase().startsWith(".reload_tex")) {
|
||||
e.preventDefault = true;
|
||||
ModAPI.mc.renderItem.itemModelMesher.simpleShapesCache.clear();
|
||||
ModAPI.promisify(ModAPI.mc.refreshResources)();
|
||||
}
|
||||
});
|
||||
|
117
examplemods/block_of_steve.js
Normal file
117
examplemods/block_of_steve.js
Normal file
@ -0,0 +1,117 @@
|
||||
//nice little utility function to fix the block identity map
|
||||
function fixupBlockIds() {
|
||||
var blockRegistry = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.blockRegistry).getCorrective();
|
||||
var BLOCK_STATE_IDS = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.BLOCK_STATE_IDS).getCorrective();
|
||||
blockRegistry.registryObjects.hashTableKToV.forEach(entry => {
|
||||
if (entry) {
|
||||
var block = entry.value;
|
||||
var validStates = block.getBlockState().getValidStates();
|
||||
var stateArray = validStates.array || [validStates.element];
|
||||
stateArray.forEach(iblockstate => {
|
||||
var i = blockRegistry.getIDForObject(block.getRef()) << 4 | block.getMetaFromState(iblockstate.getRef());
|
||||
BLOCK_STATE_IDS.put(iblockstate.getRef(), i);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
function makeSteveBlock() {
|
||||
var blockClass = ModAPI.reflect.getClassById("net.minecraft.block.Block");
|
||||
var iproperty = ModAPI.reflect.getClassById("net.minecraft.block.properties.IProperty").class;
|
||||
var makeBlockState = ModAPI.reflect.getClassById("net.minecraft.block.state.BlockState").constructors.find(x => x.length === 2);
|
||||
var blockSuper = ModAPI.reflect.getSuper(blockClass, (x) => x.length === 2);
|
||||
var nmb_BlockSteve = function nmb_BlockSteve() {
|
||||
blockSuper(this, ModAPI.materials.rock.getRef());
|
||||
}
|
||||
ModAPI.reflect.prototypeStack(blockClass, nmb_BlockSteve);
|
||||
nmb_BlockSteve.prototype.$isOpaqueCube = function () {
|
||||
return 1;
|
||||
}
|
||||
nmb_BlockSteve.prototype.$createBlockState = function () {
|
||||
return makeBlockState(this, ModAPI.array.object(iproperty, 0));
|
||||
}
|
||||
globalThis.nmb_BlockSteve = nmb_BlockSteve;
|
||||
}
|
||||
function registerSteveClientSide() {
|
||||
var itemClass = ModAPI.reflect.getClassById("net.minecraft.item.Item");
|
||||
var blockClass = ModAPI.reflect.getClassById("net.minecraft.block.Block");
|
||||
var block_of_steve = (new nmb_BlockSteve()).$setHardness(-1.0).$setStepSound(blockClass.staticVariables.soundTypeGravel).$setUnlocalizedName(
|
||||
ModAPI.util.str("steve")
|
||||
);
|
||||
blockClass.staticMethods.registerBlock0.method(
|
||||
198,
|
||||
ModAPI.util.str("steve"),
|
||||
block_of_steve
|
||||
);
|
||||
itemClass.staticMethods.registerItemBlock0.method(block_of_steve);
|
||||
ModAPI.addEventListener("lib:asyncsink", async () => {
|
||||
AsyncSink.L10N.set("tile.steve.name", "Block Of Steve");
|
||||
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/models/block/steve.json", JSON.stringify(
|
||||
{
|
||||
"parent": "block/cube_all",
|
||||
"textures": {
|
||||
"all": "blocks/steve"
|
||||
}
|
||||
}
|
||||
));
|
||||
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/models/item/steve.json", JSON.stringify(
|
||||
{
|
||||
"parent": "block/steve",
|
||||
"display": {
|
||||
"thirdperson": {
|
||||
"rotation": [10, -45, 170],
|
||||
"translation": [0, 1.5, -2.75],
|
||||
"scale": [0.375, 0.375, 0.375]
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/blockstates/steve.json", JSON.stringify(
|
||||
{
|
||||
"variants": {
|
||||
"normal": [
|
||||
{ "model": "steve" },
|
||||
]
|
||||
}
|
||||
}
|
||||
));
|
||||
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/textures/blocks/steve.png", await (await fetch(
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE0SURBVDhPpdO9S8NAHMbxy3sVfJmMg6h7FRXXkkUUX0addSjo4OAfIDqLIoiLi3+BRRx0EIQOnV0EcVAIWkR0KIFgrcEktX6vcXD0nuE+5Afhnhw5bWy4qylaidOfVQhT0zFKYozjBHVdzi3TwCZvteaS/0fLD8oGf5OzTeyxNUyE3Ln2HmGctpuxKuS3wd76CgPHsrEj142NeojCkHsFry+4c3aJ6g1OtlZp0Ok4DD4i+Y2GIZ+DMMAhtw+fHu8xi3IDM9t5YfMQF71dLHo+ZjsfXbh4WtnH0vYaqp/BcXGGM3D7BxiYTi+el8uYZWm2gM/VB/Tfaqje4GB5iga2Jv+sUuUa5/ITmOXq7gbnC+MY1r9QvcHG9AgN0lRex1u/ilr7ehqWvBNZvMlRbESfqNhAiG/Pb1bHXpMbFgAAAABJRU5ErkJggg=="
|
||||
)).arrayBuffer());
|
||||
});
|
||||
}
|
||||
function registerSteveServerSide() {
|
||||
function fixupBlockIds() {
|
||||
var blockRegistry = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.blockRegistry).getCorrective();
|
||||
var BLOCK_STATE_IDS = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.BLOCK_STATE_IDS).getCorrective();
|
||||
blockRegistry.registryObjects.hashTableKToV.forEach(entry => {
|
||||
if (entry) {
|
||||
var block = entry.value;
|
||||
var validStates = block.getBlockState().getValidStates();
|
||||
var stateArray = validStates.array || [validStates.element];
|
||||
stateArray.forEach(iblockstate => {
|
||||
var i = blockRegistry.getIDForObject(block.getRef()) << 4 | block.getMetaFromState(iblockstate.getRef());
|
||||
BLOCK_STATE_IDS.put(iblockstate.getRef(), i);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
var blockClass = ModAPI.reflect.getClassById("net.minecraft.block.Block");
|
||||
var itemClass = ModAPI.reflect.getClassById("net.minecraft.item.Item");
|
||||
ModAPI.addEventListener("bootstrap", () => {
|
||||
var block_of_steve = (new nmb_BlockSteve()).$setHardness(-1.0).$setStepSound(blockClass.staticVariables.soundTypeGravel).$setUnlocalizedName(
|
||||
ModAPI.util.str("steve")
|
||||
);
|
||||
blockClass.staticMethods.registerBlock0.method(
|
||||
198,
|
||||
ModAPI.util.str("steve"),
|
||||
block_of_steve
|
||||
);
|
||||
itemClass.staticMethods.registerItemBlock0.method(block_of_steve);
|
||||
fixupBlockIds();
|
||||
});
|
||||
}
|
||||
ModAPI.dedicatedServer.appendCode(makeSteveBlock);
|
||||
makeSteveBlock();
|
||||
registerSteveClientSide();
|
||||
fixupBlockIds();
|
||||
ModAPI.dedicatedServer.appendCode(registerSteveServerSide);
|
@ -167,6 +167,7 @@
|
||||
ModAPI.hooks._rippedData ||= [];
|
||||
ModAPI.hooks._teavm ||= {};
|
||||
ModAPI.hooks._rippedConstructors ||= {};
|
||||
ModAPI.hooks._rippedInternalConstructors ||= {};
|
||||
ModAPI.hooks.methods ||= {};
|
||||
ModAPI.hooks._rippedMethodTypeMap ||= {};
|
||||
ModAPI.hooks._postInit ||= ()=>{};
|
||||
|
14
injector.js
14
injector.js
@ -136,6 +136,20 @@ var main;(function(){`
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
const extractInternalConstructorRegex =
|
||||
/^\s*function (\S*?)__init_\d*?\(\$this/gm; //same as extract constructor regex, but only allow $this as first argument
|
||||
patchedFile = patchedFile.replaceAll(
|
||||
extractInternalConstructorRegex,
|
||||
(match) => {
|
||||
var fullName = match.match(extractConstructorFullNameRegex);
|
||||
fullName = fullName[0].replace("function ", "");
|
||||
return (
|
||||
`ModAPI.hooks._rippedInternalConstructors[\`${fullName}\`] = ${fullName};
|
||||
` + match
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
if(globalThis.optimizePi){
|
||||
patchedFile = patchedFile.replaceAll(
|
||||
|
@ -35,4 +35,4 @@ PatchesRegistry.addPatch(function (input) {
|
||||
if (!$this.$renderHand)`
|
||||
);
|
||||
return output;
|
||||
})
|
||||
});
|
44
postinit.js
44
postinit.js
@ -149,7 +149,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
||||
}
|
||||
if (xOut && typeof xOut === "object" && !Array.isArray(xOut)) {
|
||||
if (corrective) {
|
||||
return new Proxy(outputValue.data, CorrectiveRecursive);
|
||||
return new Proxy(xOut, CorrectiveRecursive);
|
||||
}
|
||||
return new Proxy(xOut, ModAPI.util.TeaVM_to_Recursive_BaseData_ProxyConf);
|
||||
}
|
||||
@ -209,6 +209,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
||||
|
||||
ModAPI.hooks.regenerateClassMap = function () {
|
||||
ModAPI.hooks._rippedConstructorKeys = Object.keys(ModAPI.hooks._rippedConstructors);
|
||||
ModAPI.hooks._rippedInternalConstructorKeys = Object.keys(ModAPI.hooks._rippedInternalConstructors);
|
||||
ModAPI.hooks._rippedMethodKeys = Object.keys(ModAPI.hooks._rippedMethodTypeMap);
|
||||
|
||||
var compiledNames = new Set();
|
||||
@ -255,6 +256,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
||||
"id": classId,
|
||||
"binaryName": item?.$meta?.binaryName || null,
|
||||
"constructors": [],
|
||||
"internalConstructors": [],
|
||||
"methods": {},
|
||||
"staticMethods": {},
|
||||
"staticVariables": {},
|
||||
@ -268,9 +270,11 @@ globalThis.modapi_postinit = "(" + (() => {
|
||||
}
|
||||
}
|
||||
if (typeof item?.$meta?.superclass === "function" && item?.$meta?.superclass?.$meta) {
|
||||
ModAPI.hooks._classMap[compiledName].superclass = item.$meta.superclass.$meta.name;
|
||||
ModAPI.hooks._classMap[compiledName].superclassName = item.$meta.superclass.$meta.name;
|
||||
ModAPI.hooks._classMap[compiledName].superclass = item.$meta.superclass;
|
||||
} else {
|
||||
ModAPI.hooks._classMap[compiledName].superclass = null;
|
||||
ModAPI.hooks._classMap[compiledName].superclassName = null;
|
||||
}
|
||||
ModAPI.hooks._classMap[compiledName].staticVariableNames = ModAPI.hooks._rippedStaticIndexer[compiledName];
|
||||
ModAPI.hooks._classMap[compiledName].staticVariables = ModAPI.hooks._rippedStaticProperties[compiledName];
|
||||
@ -286,6 +290,13 @@ globalThis.modapi_postinit = "(" + (() => {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ModAPI.hooks._rippedInternalConstructorKeys.forEach(initialiser => { // Find internal constructors/initialisers. Used for calling super() on custom classes. (They are the different implementations of a classes constructor, that don't automatically create an object. Thus, it is identical to calling super)
|
||||
if (initialiser.startsWith(compiledName + "__init_") && !initialiser.includes("$lambda$")) {
|
||||
ModAPI.hooks._classMap[compiledName].internalConstructors.push(ModAPI.hooks._rippedInternalConstructors[initialiser]);
|
||||
}
|
||||
});
|
||||
|
||||
ModAPI.hooks._rippedMethodKeys.forEach((method) => {
|
||||
if (method.startsWith(compiledName + "_") && !method.includes("$lambda$")) {
|
||||
var targetMethodMap = ModAPI.hooks._classMap[compiledName].methods;
|
||||
@ -319,6 +330,31 @@ globalThis.modapi_postinit = "(" + (() => {
|
||||
var key = classKeys.filter(k => { return ModAPI.hooks._classMap[k].name === className })[0];
|
||||
return key ? ModAPI.hooks._classMap[key] : null;
|
||||
}
|
||||
|
||||
//Magical function for making a subclass with a custom constructor that you can easily use super(...) on.
|
||||
ModAPI.reflect.getSuper = function getSuper(reflectClass, filter) {
|
||||
filter ||= ()=>true;
|
||||
var initialiser = reflectClass.internalConstructors.find(filter);
|
||||
return function superFunction(thisArg, ...extra_args) {
|
||||
reflectClass.class.call(thisArg);
|
||||
initialiser(thisArg, ...extra_args);
|
||||
}
|
||||
}
|
||||
|
||||
//Iteratively load the superclasses' prototype methods.
|
||||
ModAPI.reflect.prototypeStack = function prototypeStack(reflectClass, classFn) {
|
||||
var stack = [reflectClass.class.prototype];
|
||||
var currentSuperclass = reflectClass.superclass;
|
||||
while (currentSuperclass) {
|
||||
stack.push(currentSuperclass.prototype);
|
||||
currentSuperclass = currentSuperclass?.$meta?.superclass;
|
||||
}
|
||||
stack.reverse();
|
||||
stack.forEach(proto => {
|
||||
Object.assign(classFn.prototype, proto);
|
||||
});
|
||||
}
|
||||
|
||||
var reloadDeprecationWarnings = 0;
|
||||
const TeaVMArray_To_Recursive_BaseData_ProxyConf = {
|
||||
get(target, prop, receiver) {
|
||||
@ -556,7 +592,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
||||
|
||||
//Function used for running @Async / @Async-dependent TeaVM methods.
|
||||
ModAPI.promisify = function promisify(fn) {
|
||||
return function promisifiedJavaMethpd(...inArguments) {
|
||||
return function promisifiedJavaMethod(...inArguments) {
|
||||
return new Promise((res, rej) => {
|
||||
Promise.resolve().then( //queue microtask
|
||||
() => {
|
||||
@ -850,10 +886,12 @@ globalThis.modapi_postinit = "(" + (() => {
|
||||
ModAPI.enchantments = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.enchantment.Enchantment")].staticVariables, StaticProps_ProxyConf);
|
||||
}
|
||||
|
||||
ModAPI.events.newEvent("bootstrap", "server");
|
||||
const originalBootstrap = ModAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.init.Bootstrap", "register")];
|
||||
ModAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.init.Bootstrap", "register")] = function (...args) {
|
||||
var x = originalBootstrap.apply(this, args);
|
||||
ModAPI.util.bootstrap();
|
||||
ModAPI.events.callEvent("bootstrap", {});
|
||||
console.log("[ModAPI] Hooked into bootstrap. .blocks, .items, .materials and .enchantments are now accessible.");
|
||||
return x;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user