mirror of
https://github.com/eaglerforge/EaglerForgeInjector
synced 2025-07-26 15:29:26 -09:00
commit
a07c3207cf
@ -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.
|
||||
|
@ -16,7 +16,12 @@ Methods:
|
||||
- This method is used to find a class by its id.
|
||||
- For example, to get the `Minecraft` class, you can use `ModAPI.reflect.getClassById("Minecraft")`
|
||||
- This runs slower than `getClassById` because it has to filter through all classes. Make sure to cache the result rather than calling it over and over again.
|
||||
|
||||
- `ModAPI.reflect.getSuper(rClass: ReflectClass, filter: Function) : Function`
|
||||
- Gets a super function from a reflect class. This is used to extend built in classes, like `Block`.
|
||||
- For an example, see lines [29](https://github.com/eaglerforge/EaglerForgeInjector/blob/6e8598c180f96a65c0c101be72e6d0fa53195404/examplemods/unlucky_blocks.js#L29) and [33](https://github.com/eaglerforge/EaglerForgeInjector/blob/6e8598c180f96a65c0c101be72e6d0fa53195404/examplemods/unlucky_blocks.js#L33) in unlucky_blocks.js
|
||||
- `ModAPI.reflect.prototypeStack(rClass: ReflectClass, target: Class/ConstructorFunction) : void`
|
||||
- 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.
|
||||
- [Example usage](https://github.com/eaglerforge/EaglerForgeInjector/blob/6e8598c180f96a65c0c101be72e6d0fa53195404/examplemods/unlucky_blocks.js#L37)
|
||||
### ReflectClass Definition
|
||||
|
||||
Each `ReflectClass` has the following properties:
|
||||
@ -44,7 +49,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`
|
||||
|
||||
|
@ -37,6 +37,8 @@ Methods:
|
||||
- `ModAPI.util.isCritical() : boolean`
|
||||
- Checks wether the thread is in a critical state.
|
||||
- When patching methods, it is good practice to allow the method to resume as usual if this is `true`, to avoid stack implosions. (yes, those are real)
|
||||
- `ModAPI.util.bootstrap() : void`
|
||||
- Regenerate proxies for ModAPI.items, .blocks, .materials, .enchantments
|
||||
- `ModAPI.util.createArray(class, jsArray) : Object[]`
|
||||
- Makes a java array from a class and a javascript array.
|
||||
- The class parameter can be retrieved via reflect: `ModAPI.reflect.getClassById("net.minecraft.util.BlockPos").class`
|
||||
|
1
docs/tutorials/comingsoon.md
Normal file
1
docs/tutorials/comingsoon.md
Normal file
@ -0,0 +1 @@
|
||||
# Coming Soon
|
@ -1,10 +1,11 @@
|
||||
ModAPI.meta.title("AsyncSink");
|
||||
ModAPI.meta.description("Library for patching and hooking into asynchronous filesystem requests for EaglercraftX.");
|
||||
ModAPI.meta.icon("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAL9JREFUOE9jZGBg+M9ABcAIMsgtPo3hzZ2zYONEVIxJZu9aOIsBbJCRtTHcEJAgLgBSh82ic0fPIgyCKQAJXrx4EcUsfX19sBiIRrYU5gu4Qchew2cQyHSQYehBgdNruFwEcybMZci+gIcRIa+hhxu6LzBiDZvX0A1BDyuivYbLIJK8pqevjze5GlsbMxAdayCT/PQwDRS2gaQror2m36KH4SqjZybwxEl0gsQWRkM01ogpVQh6jaJihBgXEFIDAAIQ9AFDJlrxAAAAAElFTkSuQmCC");
|
||||
const asyncSinkIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAL9JREFUOE9jZGBg+M9ABcAIMsgtPo3hzZ2zYONEVIxJZu9aOIsBbJCRtTHcEJAgLgBSh82ic0fPIgyCKQAJXrx4EcUsfX19sBiIRrYU5gu4Qchew2cQyHSQYehBgdNruFwEcybMZci+gIcRIa+hhxu6LzBiDZvX0A1BDyuivYbLIJK8pqevjze5GlsbMxAdayCT/PQwDRS2gaQror2m36KH4SqjZybwxEl0gsQWRkM01ogpVQh6jaJihBgXEFIDAAIQ9AFDJlrxAAAAAElFTkSuQmCC";
|
||||
ModAPI.meta.icon(asyncSinkIcon);
|
||||
ModAPI.meta.credits("By ZXMushroom63");
|
||||
(function AsyncSinkFn() {
|
||||
//AsyncSink is a plugin to debug and override asynchronous methods in EaglercraftX
|
||||
function runtimeComponent() {
|
||||
async function runtimeComponent() {
|
||||
const booleanResult = (b) => ModAPI.hooks.methods.nlevit_BooleanResult__new(b * 1);
|
||||
const wrap = ModAPI.hooks.methods.otji_JSWrapper_wrap;
|
||||
const unwrap = ModAPI.hooks.methods.otji_JSWrapper_unwrap;
|
||||
@ -39,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) {
|
||||
@ -147,10 +149,107 @@ 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!");
|
||||
}
|
||||
runtimeComponent();
|
||||
ModAPI.dedicatedServer.appendCode(runtimeComponent);
|
||||
|
||||
|
||||
async function assureAsyncSinkResources() {
|
||||
const dec = new TextDecoder("utf-8");
|
||||
const enc = new TextEncoder("utf-8");
|
||||
var resourcePackKey = (await indexedDB.databases()).find(x => x?.name?.endsWith("_resourcePacks")).name;
|
||||
const dbRequest = indexedDB.open(resourcePackKey);
|
||||
const db = await promisifyIDBRequest(dbRequest);
|
||||
const transaction = db.transaction(["filesystem"], "readonly");
|
||||
const objectStore = transaction.objectStore("filesystem");
|
||||
var object = (await promisifyIDBRequest(objectStore.get(["resourcepacks/manifest.json"])))?.data;
|
||||
var resourcePackList = object ? JSON.parse(dec.decode(object)) : { resourcePacks: [] };
|
||||
if (!resourcePackList.resourcePacks.find(x => x.name === "AsyncSinkLib")) {
|
||||
resourcePackList.resourcePacks.push({
|
||||
domains: ["minecraft"],
|
||||
folder: "AsyncSinkLib",
|
||||
name: "AsyncSinkLib",
|
||||
timestamp: Date.now()
|
||||
});
|
||||
const writeableTransaction = db.transaction(["filesystem"], "readwrite");
|
||||
const writeableObjectStore = writeableTransaction.objectStore("filesystem");
|
||||
await promisifyIDBRequest(writeableObjectStore.put({
|
||||
path: "resourcepacks/manifest.json",
|
||||
data: enc.encode(JSON.stringify(resourcePackList)).buffer
|
||||
}));
|
||||
await promisifyIDBRequest(writeableObjectStore.put({
|
||||
path: "resourcepacks/AsyncSinkLib/pack.mcmeta",
|
||||
data: enc.encode(JSON.stringify({
|
||||
"pack": {
|
||||
"pack_format": 1,
|
||||
"description": "AsyncSink Library Resources"
|
||||
}
|
||||
})).buffer
|
||||
}));
|
||||
|
||||
var icon = {
|
||||
path: "resourcepacks/AsyncSinkLib/pack.png",
|
||||
data: await (await fetch(asyncSinkIcon)).arrayBuffer()
|
||||
};
|
||||
|
||||
const imageTransaction = db.transaction(["filesystem"], "readwrite");
|
||||
const imageObjectStore = imageTransaction.objectStore("filesystem");
|
||||
|
||||
await promisifyIDBRequest(imageObjectStore.put(icon));
|
||||
}
|
||||
}
|
||||
|
||||
// Client side reminders to enable the AsyncSink Resource Pack
|
||||
var asyncSinkInstallStatus = false;
|
||||
var installMessage = document.createElement("span");
|
||||
installMessage.innerText = "Please enable the AsyncSink resource pack\nIn game, use the .reload_tex command to load textures for modded blocks and items.";
|
||||
installMessage.style = "background-color: rgba(0,0,0,0.7); color: red; position: fixed; top: 0; left: 0; font-family: sans-serif; pointer-events: none; user-select: none;";
|
||||
document.body.appendChild(installMessage);
|
||||
|
||||
assureAsyncSinkResources();
|
||||
setInterval(() => {
|
||||
var resourcePackEntries = ModAPI.mc.mcResourcePackRepository.getRepositoryEntries().getCorrective();
|
||||
var array = resourcePackEntries.array || [resourcePackEntries.element];
|
||||
asyncSinkInstallStatus = array.find(x => ModAPI.util.ustr(x.reResourcePack.resourcePackFile.getRef()) === "AsyncSinkLib") ? true : false;
|
||||
assureAsyncSinkResources();
|
||||
if (asyncSinkInstallStatus) {
|
||||
installMessage.style.display = "none";
|
||||
} else {
|
||||
installMessage.style.display = "initial";
|
||||
}
|
||||
}, 8000);
|
||||
ModAPI.events.newEvent("custom:asyncsink_reloaded");
|
||||
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)().then(()=>{
|
||||
ModAPI.events.callEvent("custom:asyncsink_reloaded", {});
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
127
examplemods/block_of_steve_advanced.js
Normal file
127
examplemods/block_of_steve_advanced.js
Normal file
@ -0,0 +1,127 @@
|
||||
//THIS IS A DEMO MOD
|
||||
|
||||
|
||||
//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 creativeBlockTab = ModAPI.reflect.getClassById("net.minecraft.creativetab.CreativeTabs").staticVariables.tabBlock;
|
||||
var nmb_BlockSteve = function nmb_BlockSteve() {
|
||||
blockSuper(this, ModAPI.materials.rock.getRef());
|
||||
this.$defaultBlockState = this.$blockState.$getBaseState();
|
||||
this.$setCreativeTab(creativeBlockTab);
|
||||
}
|
||||
ModAPI.reflect.prototypeStack(blockClass, nmb_BlockSteve);
|
||||
nmb_BlockSteve.prototype.$isOpaqueCube = function () {
|
||||
return 1;
|
||||
}
|
||||
nmb_BlockSteve.prototype.$createBlockState = function (t) {
|
||||
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, //use blockid 198
|
||||
ModAPI.util.str("steve"),
|
||||
block_of_steve
|
||||
);
|
||||
itemClass.staticMethods.registerItemBlock0.method(block_of_steve);
|
||||
ModAPI.mc.renderItem.registerBlock(block_of_steve, ModAPI.util.str("steve"));
|
||||
ModAPI.addEventListener("lib:asyncsink", async () => {
|
||||
ModAPI.addEventListener("custom:asyncsink_reloaded", ()=>{
|
||||
ModAPI.mc.renderItem.registerBlock(block_of_steve, ModAPI.util.str("steve"));
|
||||
});
|
||||
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);
|
111
examplemods/block_of_steve_simple.js
Normal file
111
examplemods/block_of_steve_simple.js
Normal file
@ -0,0 +1,111 @@
|
||||
//THIS IS A DEMO MOD
|
||||
|
||||
|
||||
//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 registerSteveClientSide() {
|
||||
var creativeBlockTab = ModAPI.reflect.getClassById("net.minecraft.creativetab.CreativeTabs").staticVariables.tabBlock;
|
||||
var itemClass = ModAPI.reflect.getClassById("net.minecraft.item.Item");
|
||||
var blockClass = ModAPI.reflect.getClassById("net.minecraft.block.Block");
|
||||
var constructor = blockClass.constructors.find(x=>x.length === 1);
|
||||
var block_of_steve = constructor(ModAPI.materials.rock.getRef()).$setHardness(-1.0).$setStepSound(blockClass.staticVariables.soundTypeGravel).$setUnlocalizedName(
|
||||
ModAPI.util.str("steve")
|
||||
).$setCreativeTab(creativeBlockTab);
|
||||
blockClass.staticMethods.registerBlock0.method(
|
||||
198, //use blockid 198
|
||||
ModAPI.util.str("steve"),
|
||||
block_of_steve
|
||||
);
|
||||
itemClass.staticMethods.registerItemBlock0.method(block_of_steve);
|
||||
ModAPI.mc.renderItem.registerBlock(block_of_steve, ModAPI.util.str("steve"));
|
||||
|
||||
|
||||
ModAPI.addEventListener("lib:asyncsink", async () => {
|
||||
ModAPI.addEventListener("custom:asyncsink_reloaded", ()=>{
|
||||
ModAPI.mc.renderItem.registerBlock(block_of_steve, ModAPI.util.str("steve"));
|
||||
});
|
||||
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 creativeBlockTab = ModAPI.reflect.getClassById("net.minecraft.creativetab.CreativeTabs").staticVariables.tabBlock;
|
||||
var blockClass = ModAPI.reflect.getClassById("net.minecraft.block.Block");
|
||||
var itemClass = ModAPI.reflect.getClassById("net.minecraft.item.Item");
|
||||
var constructor = blockClass.constructors.find(x=>x.length === 1);
|
||||
ModAPI.addEventListener("bootstrap", () => {
|
||||
var block_of_steve = constructor(ModAPI.materials.rock.getRef()).$setHardness(-1.0).$setStepSound(blockClass.staticVariables.soundTypeGravel).$setUnlocalizedName(
|
||||
ModAPI.util.str("steve")
|
||||
).$setCreativeTab(creativeBlockTab);
|
||||
blockClass.staticMethods.registerBlock0.method(
|
||||
198,
|
||||
ModAPI.util.str("steve"),
|
||||
block_of_steve
|
||||
);
|
||||
itemClass.staticMethods.registerItemBlock0.method(block_of_steve);
|
||||
fixupBlockIds();
|
||||
});
|
||||
}
|
||||
registerSteveClientSide();
|
||||
fixupBlockIds();
|
||||
ModAPI.dedicatedServer.appendCode(registerSteveServerSide);
|
@ -92,7 +92,7 @@ function button_utility_script(inputArr, bindingClass, actionBindMode) {
|
||||
{
|
||||
text: "Server Close",
|
||||
click: () => {
|
||||
var CloseWindow = ModAPI.reflect.getClassByName("C0DPacketCloseWindow").constructors.find(x => x.length === 1);
|
||||
var CloseWindow = ModAPI.reflect.getClassByName("C0DPacketCloseWindow").constructors[0];
|
||||
ModAPI.player.sendQueue.addToSendQueue(CloseWindow(ModAPI.player.openContainer.getCorrective().windowId));
|
||||
},
|
||||
x: 0,
|
||||
|
134
examplemods/unlucky_blocks.js
Normal file
134
examplemods/unlucky_blocks.js
Normal file
@ -0,0 +1,134 @@
|
||||
(()=>{
|
||||
const unluckyBlockTexture = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAOhJREFUOE9jnJn2/z8DGvj4koHh9UOIoKg8AwO/OLoKBJ8RZED6LEbcKvDIzEz7z8DY5f//f9lGTANCGTAcxrCaAVUd2IBSg///uy+gSqBr/sJwF+6O7QwqcHaXPxYXgDTDNCArtmXYBtZ4mMELbkCpwX8GjDDwZLjD8IXhFopCkA5s4mAXEBOIMC+BXIbsKnAYEDIAOTywBiI+A0DO5mFQBvsZXTNIjKALQAHHw6CG4mzkZIE3HYAUEjIAHIjY0gGxyRIcjfgMgIUBNv+DLAEbgCspgxTAYgCXAUSnA1xegscCPj8TytoAA5eEOx9BbCgAAAAASUVORK5CYII=";
|
||||
ModAPI.meta.title("Unlucky Blocks");
|
||||
ModAPI.meta.version("v1.0");
|
||||
ModAPI.meta.description("These purple cubes ruined my life. Requires AsyncSink.");
|
||||
ModAPI.meta.credits("By ZXMushroom63");
|
||||
ModAPI.meta.icon(unluckyBlockTexture);
|
||||
|
||||
function UnluckyBlocks() {
|
||||
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 itemClass = ModAPI.reflect.getClassById("net.minecraft.item.Item");
|
||||
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); //Get super function from the block class with a target length of two. ($this (mandatory), material (optional))
|
||||
var creativeBlockTab = ModAPI.reflect.getClassById("net.minecraft.creativetab.CreativeTabs").staticVariables.tabBlock;
|
||||
var breakBlockMethod = blockClass.methods.breakBlock.method;
|
||||
var nmb_BlockUnlucky = function nmb_BlockUnlucky() {
|
||||
blockSuper(this, ModAPI.materials.rock.getRef()); //Use super function to get block properties on this class.
|
||||
this.$defaultBlockState = this.$blockState.$getBaseState();
|
||||
this.$setCreativeTab(creativeBlockTab);
|
||||
}
|
||||
ModAPI.reflect.prototypeStack(blockClass, nmb_BlockUnlucky);
|
||||
nmb_BlockUnlucky.prototype.$isOpaqueCube = function () {
|
||||
return 1;
|
||||
}
|
||||
nmb_BlockUnlucky.prototype.$createBlockState = function () {
|
||||
return makeBlockState(this, ModAPI.array.object(iproperty, 0));
|
||||
}
|
||||
nmb_BlockUnlucky.prototype.$breakBlock = function ($world, $blockpos, $blockstate) {
|
||||
var world = ModAPI.util.wrap($world);
|
||||
var blockpos = ModAPI.util.wrap($blockpos);
|
||||
if (Math.random() < 1) { //was gonna add random events but couldn't be bothered. Enjoy exploding!
|
||||
world.newExplosion(null, blockpos.getX() + 0.5, blockpos.getY() + 0.5,
|
||||
blockpos.getZ() + 0.5, 9, 1, 1);
|
||||
}
|
||||
return breakBlockMethod(this, $world, $blockpos, $blockstate);
|
||||
}
|
||||
|
||||
function internal_reg() {
|
||||
var block_of_unluckiness = (new nmb_BlockUnlucky()).$setHardness(0.0).$setStepSound(blockClass.staticVariables.soundTypePiston).$setUnlocalizedName(
|
||||
ModAPI.util.str("unluckiness")
|
||||
);
|
||||
blockClass.staticMethods.registerBlock0.method(
|
||||
544,
|
||||
ModAPI.util.str("unluckiness"),
|
||||
block_of_unluckiness
|
||||
);
|
||||
itemClass.staticMethods.registerItemBlock0.method(block_of_unluckiness);
|
||||
fixupBlockIds();
|
||||
ModAPI.blocks["unluckiness"] = block_of_unluckiness;
|
||||
|
||||
return block_of_unluckiness;
|
||||
}
|
||||
|
||||
const WorldGenMineable = ModAPI.reflect.getClassById("net.minecraft.world.gen.feature.WorldGenMinable").constructors.find(x=>x.length===2);
|
||||
|
||||
const BiomeDecorator_decorate = ModAPI.util.getMethodFromPackage("net.minecraft.world.biome.BiomeDecorator", "decorate");
|
||||
const oldDecorate = ModAPI.hooks.methods[BiomeDecorator_decorate];
|
||||
ModAPI.hooks.methods[BiomeDecorator_decorate] = function ($this, $world, $random, $biomeGenBase, $blockpos) {
|
||||
if (!$this.$currentWorld) {
|
||||
$this.$unluckyBlockGen = WorldGenMineable(ModAPI.blocks.unluckiness.getDefaultState().getRef(), 4);
|
||||
}
|
||||
return oldDecorate.apply(this, [$this, $world, $random, $biomeGenBase, $blockpos]);
|
||||
}
|
||||
|
||||
const BiomeDecorator_generateOres = ModAPI.util.getMethodFromPackage("net.minecraft.world.biome.BiomeDecorator", "generateOres");
|
||||
const oldGenerateOres = ModAPI.hooks.methods[BiomeDecorator_generateOres];
|
||||
ModAPI.hooks.methods[BiomeDecorator_generateOres] = function ($this) {
|
||||
$this.$genStandardOre1(105, $this.$unluckyBlockGen || null, 0, 256);
|
||||
return oldGenerateOres.apply(this, [$this]);
|
||||
}
|
||||
|
||||
if (ModAPI.materials) {
|
||||
return internal_reg();
|
||||
} else {
|
||||
ModAPI.addEventListener("bootstrap", internal_reg);
|
||||
}
|
||||
}
|
||||
ModAPI.dedicatedServer.appendCode(UnluckyBlocks);
|
||||
var block_of_unluckiness = UnluckyBlocks();
|
||||
ModAPI.addEventListener("lib:asyncsink", async () => {
|
||||
ModAPI.addEventListener("custom:asyncsink_reloaded", ()=>{
|
||||
ModAPI.mc.renderItem.registerBlock(block_of_unluckiness, ModAPI.util.str("unluckiness"));
|
||||
});
|
||||
AsyncSink.L10N.set("tile.unluckiness.name", "Unlucky Block");
|
||||
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/models/block/unluckiness.json", JSON.stringify(
|
||||
{
|
||||
"parent": "block/cube_all",
|
||||
"textures": {
|
||||
"all": "blocks/unluckiness"
|
||||
}
|
||||
}
|
||||
));
|
||||
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/models/item/unluckiness.json", JSON.stringify(
|
||||
{
|
||||
"parent": "block/unluckiness",
|
||||
"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/unluckiness.json", JSON.stringify(
|
||||
{
|
||||
"variants": {
|
||||
"normal": [
|
||||
{ "model": "unluckiness" },
|
||||
]
|
||||
}
|
||||
}
|
||||
));
|
||||
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/textures/blocks/unluckiness.png", await (await fetch(
|
||||
unluckyBlockTexture
|
||||
)).arrayBuffer());
|
||||
});
|
||||
})();
|
@ -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 ||= ()=>{};
|
||||
|
35
injector.js
35
injector.js
@ -9,6 +9,12 @@ function _status(x) {
|
||||
document.querySelector("#status").innerText = x;
|
||||
}
|
||||
function entriesToStaticVariableProxy(entries, prefix) {
|
||||
if (entries.length === 0) {
|
||||
return `ModAPI.hooks._rippedStaticProperties[\`${prefix.replace(
|
||||
"var ",
|
||||
""
|
||||
)}\`]={};`;
|
||||
}
|
||||
var getComponents = "";
|
||||
entries.forEach((entry) => {
|
||||
getComponents += `
|
||||
@ -16,6 +22,9 @@ function entriesToStaticVariableProxy(entries, prefix) {
|
||||
return ${entry.variable};
|
||||
break;`;
|
||||
});
|
||||
getComponents += `
|
||||
default:
|
||||
return Reflect.get(a,b,c);`
|
||||
|
||||
var setComponents = "";
|
||||
entries.forEach((entry) => {
|
||||
@ -24,7 +33,11 @@ function entriesToStaticVariableProxy(entries, prefix) {
|
||||
${entry.variable} = c;
|
||||
break;`;
|
||||
});
|
||||
var proxy = `
|
||||
setComponents += `
|
||||
default:
|
||||
a[b]=c;`
|
||||
/*/
|
||||
|
||||
ModAPI.hooks._rippedStaticIndexer[\`${prefix.replace(
|
||||
"var ",
|
||||
""
|
||||
@ -33,7 +46,8 @@ function entriesToStaticVariableProxy(entries, prefix) {
|
||||
return '"' + x.name + '"';
|
||||
})
|
||||
.join(",")}];
|
||||
ModAPI.hooks._rippedStaticProperties[\`${prefix.replace(
|
||||
/*/
|
||||
var proxy = `ModAPI.hooks._rippedStaticProperties[\`${prefix.replace(
|
||||
"var ",
|
||||
""
|
||||
)}\`] = new Proxy({${entries
|
||||
@ -51,6 +65,7 @@ function entriesToStaticVariableProxy(entries, prefix) {
|
||||
switch (b) {
|
||||
${setComponents}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});`;
|
||||
return proxy;
|
||||
@ -137,6 +152,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(
|
||||
"3.1415927410125732 / 180.0",
|
||||
@ -224,7 +253,7 @@ var main;(function(){`
|
||||
|
||||
|
||||
patchedFile = patchedFile.replaceAll(
|
||||
/function [a-z]+?_([a-zA-Z\$]+?)\(\) \{/gm,
|
||||
/function [a-z]+?_([a-zA-Z0-9\$]+?)\(\) \{/gm,
|
||||
(match) => {
|
||||
var prefix = "var " + match.replace("function ", "").replace("() {", "");
|
||||
var entries = [];
|
||||
|
@ -35,4 +35,4 @@ PatchesRegistry.addPatch(function (input) {
|
||||
if (!$this.$renderHand)`
|
||||
);
|
||||
return output;
|
||||
})
|
||||
});
|
60
postinit.js
60
postinit.js
@ -22,7 +22,7 @@ globalThis.modapi_postinit = "(" + (() => {
|
||||
ModAPI.meta._versionMap = {};
|
||||
ModAPI.array = {};
|
||||
|
||||
ModAPI.version = "v2.1.2";
|
||||
ModAPI.version = "v2.2";
|
||||
ModAPI.flavour = "injector";
|
||||
ModAPI.GNU = "terry pratchett";
|
||||
ModAPI.credits = ["ZXMushroom63", "radmanplays", "Murturtle", "OtterCodes101", "TheIdiotPlays", "OeildeLynx31", "Stpv22"];
|
||||
@ -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,12 +270,16 @@ 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];
|
||||
ModAPI.hooks._classMap[compiledName].staticVariableNames = Object.keys(ModAPI.hooks._classMap[compiledName].staticVariables || {});
|
||||
|
||||
if (item?.["$$constructor$$"]) {
|
||||
//Class does not have any hand written constructors
|
||||
//Eg: class MyClass {}
|
||||
@ -286,6 +292,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 +332,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 +594,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
|
||||
() => {
|
||||
@ -843,13 +881,19 @@ globalThis.modapi_postinit = "(" + (() => {
|
||||
return x;
|
||||
}
|
||||
|
||||
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 = function () {
|
||||
ModAPI.items = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.init.Items")].staticVariables, StaticProps_ProxyConf);
|
||||
ModAPI.blocks = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.init.Blocks")].staticVariables, StaticProps_ProxyConf);
|
||||
ModAPI.materials = new Proxy(ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.block.material.Material")].staticVariables, StaticProps_ProxyConf);
|
||||
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;
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
*/*/ ZXMushroom63's rather large to do list */*/
|
||||
|
||||
Add makeItemStack to LCI [Todo]
|
||||
Fix blocklook.js [In progress]
|
||||
Fix setblocktest.js [In progress]
|
Loading…
x
Reference in New Issue
Block a user