mirror of
https://github.com/eaglerforge/EaglerForgeInjector
synced 2025-07-23 06:01:38 -09:00
commit
e09077fbeb
@ -24,7 +24,7 @@ Download this repository as a .zip, and extract it. Open index.html with your pr
|
||||
- Run `npx efi /help` for use instructions.
|
||||
|
||||
#### How does it work?
|
||||
This tool matches patterns in eaglercraft builds and adds patching code to let you modify how the code works at runtime. It then adds a [corelib](./postinit.js) that initialises the `ModAPI` object.
|
||||
This tool matches patterns in eaglercraft builds and adds patching code to let you modify how the code works at runtime. It then adds a [corelib](./core/postinit.js) that initialises the `ModAPI` object.
|
||||
|
||||
#### History
|
||||
EaglerForgeInjector is a replacement for the `ModAPI` in the [old eaglerforge](https://github.com/EaglerForge/EaglerForge-old), which was maintained by @radmanplays. The legacy eaglerforge was a port of [Leah Anderson's EaglerReborn (dmca'd)](https://github.com/EaglerReborn/reborn)'s `PluginAPI` (created by me, @ZXMushroom63) to run on newer versions of Eaglercraft, with a few improvements and new features. Unlike EaglerForgeInjector, both legacy eaglerforge and eaglerreborn manually exposed properties and methods one by one.
|
||||
|
@ -37,7 +37,7 @@ var modapi_preinit = `globalThis.ModAPI ||= {};
|
||||
`;
|
||||
var freezeCallstack = `if(ModAPI.hooks.freezeCallstack){return false};`;
|
||||
const EFIConfig = {
|
||||
ModAPIVersion: "v2.7.92", //also change in package.json
|
||||
ModAPIVersion: "v2.7.93", //also change in package.json
|
||||
doEaglerforge: true,
|
||||
verbose: false,
|
||||
doServerExtras: false,
|
||||
|
@ -27,6 +27,7 @@ const modapi_postinit = "(" + (() => {
|
||||
ModAPI.meta._developerMap = {};
|
||||
ModAPI.meta._iconMap = {};
|
||||
ModAPI.meta._versionMap = {};
|
||||
ModAPI.isServer = false;
|
||||
const credits = {};
|
||||
ModAPI.addCredit = function (category, name, contents) {
|
||||
if (!credits[category]) {
|
||||
@ -36,7 +37,7 @@ const modapi_postinit = "(" + (() => {
|
||||
}
|
||||
function getCreditsString() {
|
||||
return Object.entries(credits).map((entry) => {
|
||||
return " "+entry[0] + LF + " " + (new Array(entry[0].length)).fill("~").join("") + entry[1].join("") + LF + LF + LF;
|
||||
return " " + entry[0] + LF + " " + (new Array(entry[0].length)).fill("~").join("") + entry[1].join("") + LF + LF + LF;
|
||||
}).join("");
|
||||
}
|
||||
ModAPI.array = {};
|
||||
@ -140,6 +141,9 @@ const modapi_postinit = "(" + (() => {
|
||||
}
|
||||
});
|
||||
}
|
||||
function easyStaticPropAlias(clsId, real, alias) {
|
||||
easyAlias(ModAPI.reflect.getClassById(clsId).staticVariables, real, alias);
|
||||
}
|
||||
ModAPI.meta.title = function (title) {
|
||||
if (!document.currentScript || document.currentScript.getAttribute("data-isMod") !== "true") {
|
||||
return console.log("[ModAPIMeta] Cannot set meta for non-mod script.");
|
||||
@ -216,6 +220,7 @@ const modapi_postinit = "(" + (() => {
|
||||
ModAPI.util.getMethodFromPackage = function (classId, methodName) {
|
||||
if (ModAPI.is_1_12) {
|
||||
classId = classId.replace(".eaglercraft.v1_8", ".eaglercraft"); //why peyton why must you do this. you couldve changed it to v1_12 too, that would've worked
|
||||
classId = classId.replace(".entity.RenderItem", ".RenderItem");
|
||||
}
|
||||
var name = "";
|
||||
var classStuff = classId.split(".");
|
||||
@ -571,6 +576,24 @@ const modapi_postinit = "(" + (() => {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
if (prop === "getCorrective") {
|
||||
return function () {
|
||||
return new Proxy(target, patchProxyConfToCorrective(TeaVMArray_To_Recursive_BaseData_ProxyConf));
|
||||
}
|
||||
}
|
||||
if (prop === "isCorrective") {
|
||||
return function () {
|
||||
return corrective;
|
||||
}
|
||||
}
|
||||
if (prop === "reload") {
|
||||
return function () {
|
||||
if (reloadDeprecationWarnings < 10) {
|
||||
console.warn("ModAPI/PluginAPI reload() is obsolete, please stop using it in code.")
|
||||
reloadDeprecationWarnings++;
|
||||
}
|
||||
}
|
||||
}
|
||||
var outputValue = Reflect.get(target, prop, receiver);
|
||||
var wrapped = ModAPI.util.wrap(outputValue, target, corrective, true);
|
||||
if (wrapped) {
|
||||
@ -839,7 +862,11 @@ const modapi_postinit = "(" + (() => {
|
||||
var v = typeof param === "object" ? param.msg : (param + "");
|
||||
v ||= "";
|
||||
var jclString = ModAPI.util.string(v);
|
||||
ModAPI.hooks.methods["nmcg_GuiNewChat_printChatMessage"](ModAPI.javaClient.$ingameGUI.$persistantChatGUI, ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.util.ChatComponentText")].constructors[0](jclString));
|
||||
if (ModAPI.is_1_12) {
|
||||
ModAPI.hooks.methods["nmcg_GuiNewChat_printChatMessage"](ModAPI.javaClient.$ingameGUI.$persistantChatGUI, ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.util.text.TextComponentString")].constructors[0](jclString));
|
||||
} else {
|
||||
ModAPI.hooks.methods["nmcg_GuiNewChat_printChatMessage"](ModAPI.javaClient.$ingameGUI.$persistantChatGUI, ModAPI.hooks._classMap[ModAPI.util.getCompiledName("net.minecraft.util.ChatComponentText")].constructors[0](jclString));
|
||||
}
|
||||
}
|
||||
|
||||
ModAPI.util.makeArray = function makeArray(arrayClass, arrayContents = []) {
|
||||
@ -959,7 +986,7 @@ const modapi_postinit = "(" + (() => {
|
||||
inlineIntegratedServerStartup = ModAPI.hooks._rippedMethodKeys.filter(key => { return key.startsWith(inlineIntegratedServerStartup); })[0];
|
||||
const inlineIntegratedServerStartupMethod = ModAPI.hooks.methods[inlineIntegratedServerStartup];
|
||||
ModAPI.hooks.methods[inlineIntegratedServerStartup] = function (worker, bootstrap) {
|
||||
var x = inlineIntegratedServerStartupMethod.apply(this, [worker, bootstrap + ";" + globalThis.modapi_postinit + ";" + ModAPI.dedicatedServer._data.join(";")]);
|
||||
var x = inlineIntegratedServerStartupMethod.apply(this, [worker, bootstrap + ";" + globalThis.modapi_postinit + ";ModAPI.isServer=true;" + ModAPI.dedicatedServer._data.join(";")]);
|
||||
ModAPI.dedicatedServer._data = [];
|
||||
ModAPI.dedicatedServer._wasUsed = true;
|
||||
console.log("[ModAPI] Hooked into inline integrated server.");
|
||||
@ -1112,6 +1139,11 @@ const modapi_postinit = "(" + (() => {
|
||||
} else {
|
||||
ModAPI.enchantments = new Proxy(ModAPI.reflect.getClassById("net.minecraft.enchantment.Enchantment").staticVariables, StaticProps_ProxyConf);
|
||||
}
|
||||
|
||||
if (ModAPI.is_1_12) {
|
||||
//1.12 specific globals
|
||||
ModAPI.blockSounds = new Proxy(ModAPI.reflect.getClassById("net.minecraft.block.SoundType").staticVariables, StaticProps_ProxyConf);
|
||||
}
|
||||
}
|
||||
|
||||
ModAPI.events.newEvent("bootstrap", "server");
|
||||
@ -1193,11 +1225,16 @@ const modapi_postinit = "(" + (() => {
|
||||
|
||||
// 1.12 utility junk
|
||||
if (ModAPI.is_1_12) {
|
||||
var Block = ModAPI.reflect.getClassById("net.minecraft.block.Block").class;
|
||||
var NonNullList = ModAPI.reflect.getClassById("net.minecraft.util.NonNullList").class;
|
||||
var ArrayAsList = ModAPI.reflect.getClassById("java.util.Arrays$ArrayAsList").class;
|
||||
easyStaticPropAlias("net.minecraft.block.Block", "REGISTRY", "blockRegistry");
|
||||
easyStaticPropAlias("net.minecraft.item.Item", "REGISTRY", "itemRegistry");
|
||||
}
|
||||
|
||||
|
||||
function qhash(txt, arr, interval) {
|
||||
arr ||= [];
|
||||
interval ||= 32767;
|
||||
// var interval = 4095; //used to be 4095 - arr.length, but that increases incompatibility based on load order and other circumstances
|
||||
if (arr.length >= interval) {
|
||||
console.error("[ModAPI.keygen] Ran out of IDs while generating for " + txt);
|
||||
@ -1216,6 +1253,7 @@ const modapi_postinit = "(" + (() => {
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
ModAPI.util.qhash = qhash;
|
||||
|
||||
|
||||
ModAPI.keygen = {};
|
||||
@ -1226,11 +1264,19 @@ const modapi_postinit = "(" + (() => {
|
||||
return registryNamespaceMethod.apply(this, args);
|
||||
}
|
||||
ModAPI.keygen.item = function (item) {
|
||||
var values = [...ModAPI.reflect.getClassById("net.minecraft.item.Item").staticVariables.itemRegistry.$modapi_specmap.values()];
|
||||
if (ModAPI.is_1_12) {
|
||||
var values = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.item.Item").staticVariables.REGISTRY).getCorrective().underlyingIntegerMap.identityMap.elementData.filter(x => !!x).map(y => y.value.value);
|
||||
} else {
|
||||
var values = [...ModAPI.reflect.getClassById("net.minecraft.item.Item").staticVariables.itemRegistry.$modapi_specmap.values()];
|
||||
}
|
||||
return qhash(item, values, 4095);
|
||||
}
|
||||
ModAPI.keygen.block = function (block) {
|
||||
var values = [...ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.blockRegistry.$modapi_specmap.values()];
|
||||
if (ModAPI.is_1_12) {
|
||||
var values = ModAPI.util.wrap(ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.REGISTRY).getCorrective().underlyingIntegerMap.identityMap.elementData.filter(x => !!x).map(y => y.value.value);
|
||||
} else {
|
||||
var values = [...ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.blockRegistry.$modapi_specmap.values()];
|
||||
}
|
||||
return qhash(block, values, 4095);
|
||||
}
|
||||
ModAPI.keygen.entity = function (entity) {
|
||||
@ -1248,10 +1294,27 @@ const modapi_postinit = "(" + (() => {
|
||||
}
|
||||
return qhash(entity, values, 127);
|
||||
}
|
||||
ModAPI.keygen.sound = function (soundId) {
|
||||
if (!ModAPI.is_1_12) {
|
||||
return -1;
|
||||
}
|
||||
const SoundEvent = ModAPI.reflect.getClassByName("SoundEvent")
|
||||
const values = ModAPI.util.wrap(SoundEvent.staticVariables.REGISTRY).getCorrective().underlyingIntegerMap.identityMap.elementData.filter(x => !!x).map(y => y.value.value);
|
||||
return qhash(soundId, values, 4095);
|
||||
}
|
||||
ModAPI.keygen.enchantment = function (enchantment) {
|
||||
const Enchantment = ModAPI.reflect.getClassByName("Enchantment");
|
||||
if (ModAPI.is_1_12) {
|
||||
const values = ModAPI.util.wrap(Enchantment.staticVariables.REGISTRY).getCorrective().underlyingIntegerMap.identityMap.elementData.filter(x => !!x).map(y => y.value.value);
|
||||
return qhash(enchantment, values, 4095);
|
||||
}
|
||||
const values = ModAPI.util.wrap(Enchantment.staticVariables.enchantmentsList).getCorrective().filter(x => !!x).map(y => y.effectId);
|
||||
return qhash(enchantment, values, 4095);
|
||||
}
|
||||
}).toString() + ")();";
|
||||
|
||||
if (globalThis.process) {
|
||||
module.exports = {
|
||||
modapi_postinit: modapi_postinit
|
||||
}
|
||||
}
|
||||
}
|
@ -34,6 +34,8 @@ The global object has the following properties:
|
||||
- This is a key-value dictionary of all of the enchantments in the game. It is generated upon init from the static variables of the `Enchantment` class.
|
||||
- For example, to access the enchantment class for `knockback`, you can use `ModAPI.enchantments["knockback"]`
|
||||
- As the enchantment class has other static variables, `Object.keys` will also return non-enchantment keys such as `enchantmentsBookList`.
|
||||
- `ModAPI.blockSounds: Map<String, SoundType>` (1.12 only)
|
||||
- This is a key-value dictionary of `SoundType`s. Used in `.setSoundType(soundType)` when registering custom blocks in 1.12.
|
||||
- `ModAPI.minecraft: Minecraft`
|
||||
- This is the minecraft instance for the client, generated upon init.
|
||||
- It can also be accessed using `ModAPI.mc`
|
||||
@ -81,6 +83,8 @@ The global object has the following properties:
|
||||
- The version of ModAPI.
|
||||
- `ModAPI.is_1_12: Boolean`
|
||||
- Property defining wether or not ModAPI thinks the current version is 1.12-based.
|
||||
- `ModAPI.isServer: Boolean`
|
||||
- Property defining wether or not ModAPI thinks it is running on the dedicated server.
|
||||
- `ModAPI.flavour: String`
|
||||
- The flavour of ModAPI. Hardcoded to be `"injector"`.
|
||||
|
||||
|
@ -7,4 +7,8 @@ Methods:
|
||||
- `ModAPI.keygen.block(blockId: String) : number`
|
||||
- Example usage is: `var id = ModAPI.keygen.block("my_example_block");`
|
||||
- `ModAPI.keygen.entity(entityId: String) : number`
|
||||
- Example usage is: `var id = ModAPI.keygen.entity("my_example_entity");`
|
||||
- Example usage is: `var id = ModAPI.keygen.entity("my_example_entity");`
|
||||
- `ModAPI.keygen.sound(soundId: String) : number`
|
||||
- Example usage is: `var id = ModAPI.keygen.sound("my.example.sound");`
|
||||
- `ModAPI.keygen.enchantment(enchantmentId: String) : number`
|
||||
- Example usage is: `var id = ModAPI.keygen.enchantment("sharpness_v2");`
|
@ -11,7 +11,7 @@ ModAPI.meta.credits("By ZXMushroom63");
|
||||
|
||||
if (ModAPI.is_1_12) {
|
||||
const _boolRes = ModAPI.reflect.getClassById("net.lax1dude.eaglercraft.internal.teavm.BooleanResult").constructors[0];
|
||||
booleanResult = (b) => _boolRes(b*1);
|
||||
booleanResult = (b) => _boolRes(b * 1);
|
||||
} else {
|
||||
booleanResult = (b) => ModAPI.hooks.methods.nlevit_BooleanResult__new(b * 1);
|
||||
}
|
||||
@ -196,6 +196,26 @@ ModAPI.meta.credits("By ZXMushroom63");
|
||||
return originalL18NFormat.apply(this, args);
|
||||
};
|
||||
|
||||
const LanguageMapTranslate = ModAPI.util.getMethodFromPackage("net.minecraft.util.text.translation.LanguageMap", "tryTranslateKey");
|
||||
const originalLanguageMapTranslate = ModAPI.hooks.methods[LanguageMapTranslate];
|
||||
ModAPI.hooks.methods[LanguageMapTranslate] = function (...args) {
|
||||
var key = ModAPI.util.ustr(args[1]);
|
||||
if (AsyncSink.L10N.has(key)) {
|
||||
args[1] = ModAPI.util.str(AsyncSink.L10N.get(key));
|
||||
}
|
||||
return originalLanguageMapTranslate.apply(this, args);
|
||||
};
|
||||
|
||||
const LanguageMapCheckTranslate = ModAPI.util.getMethodFromPackage("net.minecraft.util.text.translation.LanguageMap", "isKeyTranslated");
|
||||
const originalLanguageMapCheckTranslate = ModAPI.hooks.methods[LanguageMapCheckTranslate];
|
||||
ModAPI.hooks.methods[LanguageMapCheckTranslate] = function (...args) {
|
||||
var key = ModAPI.util.ustr(args[1]);
|
||||
if (AsyncSink.L10N.has(key)) {
|
||||
return 1;
|
||||
}
|
||||
return originalLanguageMapTranslate.apply(this, args);
|
||||
};
|
||||
|
||||
const L10NCheck = ModAPI.util.getMethodFromPackage("net.minecraft.util.StatCollector", "canTranslate");
|
||||
const originalL10NCheck = ModAPI.hooks.methods[L10NCheck];
|
||||
ModAPI.hooks.methods[L10NCheck] = function (...args) {
|
||||
@ -217,7 +237,7 @@ ModAPI.meta.credits("By ZXMushroom63");
|
||||
async function assureAsyncSinkResources() {
|
||||
const dec = new TextDecoder("utf-8");
|
||||
const enc = new TextEncoder("utf-8");
|
||||
var resourcePackKey = ModAPI.is_1_12 ? "_net_lax1dude_eaglercraft_v1_8_internal_PlatformFilesystem_1_12_2_" :(await indexedDB.databases()).find(x => x?.name?.endsWith("_resourcePacks")).name;
|
||||
var resourcePackKey = ModAPI.is_1_12 ? "_net_lax1dude_eaglercraft_v1_8_internal_PlatformFilesystem_1_12_2_" : (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");
|
||||
@ -326,8 +346,8 @@ ModAPI.meta.credits("By ZXMushroom63");
|
||||
// values = SoundEntry[]
|
||||
// category: AsyncSink.Audio.Category.*
|
||||
// SoundEntry = {path: String, pitch: 1, volume: 1, streaming: false}
|
||||
const EaglercraftRandom = ModAPI.reflect.getClassByName("EaglercraftRandom").constructors.find(x=>x.length===0);
|
||||
|
||||
const EaglercraftRandom = ModAPI.reflect.getClassByName("EaglercraftRandom").constructors.find(x => x.length === 0);
|
||||
|
||||
function makeSoundEventAccessor(soundpoolentry, weight) {
|
||||
const SoundEventAccessorClass = ModAPI.reflect.getClassByName("SoundEventAccessor").class;
|
||||
var object = new SoundEventAccessorClass;
|
||||
@ -336,7 +356,7 @@ ModAPI.meta.credits("By ZXMushroom63");
|
||||
wrapped.weight = weight;
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
function makeSoundEventAccessorComposite(rKey, pitch, volume, category) {
|
||||
const SoundEventAccessorCompositeClass = ModAPI.reflect.getClassByName("SoundEventAccessorComposite").class;
|
||||
var object = new SoundEventAccessorCompositeClass;
|
||||
@ -349,12 +369,12 @@ ModAPI.meta.credits("By ZXMushroom63");
|
||||
wrapped.rnd = EaglercraftRandom();
|
||||
return object;
|
||||
}
|
||||
function makeSoundEventAccessor112(rKey) {
|
||||
function makeSoundEventAccessor112(rKey, subttl) {
|
||||
const SoundEventAccessorClass = ModAPI.reflect.getClassByName("SoundEventAccessor").class;
|
||||
var object = new SoundEventAccessorClass;
|
||||
var wrapped = ModAPI.util.wrap(object).getCorrective();
|
||||
wrapped.location = rKey;
|
||||
wrapped.subtitle = null;
|
||||
wrapped.subtitle = ModAPI.util.str(subttl);
|
||||
wrapped.accessorList = ModAPI.hooks.methods.cgcc_Lists_newArrayList0();
|
||||
wrapped.rnd = EaglercraftRandom();
|
||||
return object;
|
||||
@ -362,32 +382,44 @@ ModAPI.meta.credits("By ZXMushroom63");
|
||||
if (ModAPI.is_1_12) {
|
||||
const soundType = ModAPI.reflect.getClassById("net.minecraft.client.audio.Sound$Type").staticVariables.FILE;
|
||||
const mkSound = ModAPI.reflect.getClassById("net.minecraft.client.audio.Sound").constructors[0];
|
||||
|
||||
AsyncSink.Audio.register = function addSfx(key, category, values) {
|
||||
if (!category) {
|
||||
throw new Error("[AsyncSink] Invalid audio category provided: "+category);
|
||||
const SoundEvent = ModAPI.reflect.getClassById("net.minecraft.util.SoundEvent");
|
||||
const SoundEvents = ModAPI.reflect.getClassById("net.minecraft.init.SoundEvents");
|
||||
|
||||
AsyncSink.Audio.register = function addSfx(key, unused, values, subtitle) {
|
||||
subtitle ||= "(AsyncSink Sound)";
|
||||
if (unused) {
|
||||
console.log("Category is not a property of the sound in 1.12, category for " + key + " will be unused.");
|
||||
}
|
||||
|
||||
const rKey = ResourceLocation(ModAPI.util.str(key));
|
||||
|
||||
const ev = new SoundEvent.class;
|
||||
ev.$soundName = rKey;
|
||||
ModAPI.util.wrap(SoundEvent.staticVariables.REGISTRY).register(ModAPI.keygen.sound(key), rKey, ev);
|
||||
const outObj = SoundEvents.staticMethods.getRegisteredSoundEvent.method(ModAPI.util.str(key));
|
||||
|
||||
var snd = ModAPI.mc.mcSoundHandler.getCorrective();
|
||||
var registry = snd.soundRegistry.soundRegistry;
|
||||
var rKey = ResourceLocation(ModAPI.util.str(key));
|
||||
|
||||
|
||||
var soundPool = values.map(se => {
|
||||
return mkSound(ModAPI.util.str(se.path), se.volume, se.pitch, 1, soundType, 1 * se.streaming);
|
||||
return mkSound(ModAPI.util.str(se.path.replace("sounds/", "").replace(".ogg", "")), se.volume, se.pitch, 1, soundType, 1 * se.streaming);
|
||||
});
|
||||
var eventAccessor = makeSoundEventAccessor112(rKey);
|
||||
var eventAccessor = makeSoundEventAccessor112(rKey, subtitle);
|
||||
var eventAccessorWrapped = ModAPI.util.wrap(eventAccessor);
|
||||
soundPool.forEach(sound => {
|
||||
eventAccessorWrapped.accessorList.add(sound);
|
||||
});
|
||||
AsyncSink.Audio.Objects.push([rKey, eventAccessor]);
|
||||
registry.put(rKey, eventAccessor);
|
||||
values.map(x=>"resourcepacks/AsyncSinkLib/assets/minecraft/" + x.path + ".mcmeta").forEach(x=>AsyncSink.setFile(x, new ArrayBuffer(0)));
|
||||
return soundPool;
|
||||
values.map(x => "resourcepacks/AsyncSinkLib/assets/minecraft/" + x.path + ".mcmeta").forEach(x => AsyncSink.setFile(x, new ArrayBuffer(0)));
|
||||
return outObj;
|
||||
}
|
||||
} else {
|
||||
const SoundPoolEntry = ModAPI.reflect.getClassByName("SoundPoolEntry").constructors.find(x => x.length === 4);
|
||||
AsyncSink.Audio.register = function addSfx(key, category, values) {
|
||||
if (!category) {
|
||||
throw new Error("[AsyncSink] Invalid audio category provided: "+category);
|
||||
throw new Error("[AsyncSink] Invalid audio category provided: " + category);
|
||||
}
|
||||
var snd = ModAPI.mc.mcSoundHandler;
|
||||
var registry = snd.sndRegistry.soundRegistry;
|
||||
@ -405,7 +437,7 @@ ModAPI.meta.credits("By ZXMushroom63");
|
||||
});
|
||||
AsyncSink.Audio.Objects.push([rKey, compositeSound]);
|
||||
registry.put(rKey, compositeSound);
|
||||
values.map(x=>"resourcepacks/AsyncSinkLib/assets/minecraft/" + x.path + ".mcmeta").forEach(x=>AsyncSink.setFile(x, new ArrayBuffer(0)));
|
||||
values.map(x => "resourcepacks/AsyncSinkLib/assets/minecraft/" + x.path + ".mcmeta").forEach(x => AsyncSink.setFile(x, new ArrayBuffer(0)));
|
||||
return soundPool;
|
||||
}
|
||||
}
|
||||
|
122
examplemods/custom_block_112.js
Normal file
122
examplemods/custom_block_112.js
Normal file
@ -0,0 +1,122 @@
|
||||
//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 blockSuper = ModAPI.reflect.getSuper(blockClass, (x) => x.length === 2);
|
||||
var creativeBlockTab = ModAPI.reflect.getClassById("net.minecraft.creativetab.CreativeTabs").staticVariables.tabBlock;
|
||||
function nmb_BlockSteve() {
|
||||
blockSuper(this, ModAPI.materials.rock.getRef());
|
||||
//this.$defaultBlockState = this.$blockState.$getBaseState(); built-in in 1.12
|
||||
this.$setCreativeTab(creativeBlockTab);
|
||||
}
|
||||
ModAPI.reflect.prototypeStack(blockClass, nmb_BlockSteve);
|
||||
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).$setSoundType(ModAPI.blockSounds.PLANT.getRef()).$setUnlocalizedName(
|
||||
ModAPI.util.str("steve")
|
||||
);
|
||||
blockClass.staticMethods.registerBlock0.method(
|
||||
ModAPI.keygen.block("steve"),
|
||||
ModAPI.util.str("steve"),
|
||||
block_of_steve
|
||||
);
|
||||
itemClass.staticMethods.registerItemBlock0.method(block_of_steve);
|
||||
ModAPI.addEventListener("lib:asyncsink", async () => {
|
||||
ModAPI.addEventListener("lib:asyncsink:registeritems", (renderItem)=>{
|
||||
console.log("registered!!");
|
||||
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());
|
||||
});
|
||||
ModAPI.blocks["steve"] = block_of_steve;
|
||||
}
|
||||
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).$setSoundType(ModAPI.blockSounds.PLANT.getRef()).$setUnlocalizedName(
|
||||
ModAPI.util.str("steve")
|
||||
);
|
||||
blockClass.staticMethods.registerBlock0.method(
|
||||
ModAPI.keygen.block("steve"), //MAXIMUM BLOCK ID IS 4095. keygen method accounts for this
|
||||
ModAPI.util.str("steve"),
|
||||
block_of_steve
|
||||
);
|
||||
itemClass.staticMethods.registerItemBlock0.method(block_of_steve);
|
||||
fixupBlockIds();
|
||||
ModAPI.blocks["steve"] = block_of_steve;
|
||||
});
|
||||
}
|
||||
ModAPI.dedicatedServer.appendCode(makeSteveBlock);
|
||||
makeSteveBlock();
|
||||
registerSteveClientSide();
|
||||
fixupBlockIds();
|
||||
|
||||
ModAPI.dedicatedServer.appendCode(registerSteveServerSide);
|
@ -2,20 +2,28 @@
|
||||
ModAPI.meta.title("Timescale Command");
|
||||
ModAPI.meta.description("/timescale 0.5 to halve the speed of time");
|
||||
ModAPI.meta.credits("By ZXMushroom63");
|
||||
globalThis.timeScale = 1n;
|
||||
globalThis.timeScaleDividing = false;
|
||||
PluginAPI.addEventListener("sendchatmessage", (event) => {
|
||||
if (event.message.toLowerCase().startsWith("/timescale")) {
|
||||
var speed = parseFloat(event.message.split(" ")[1]);
|
||||
if (!speed) {
|
||||
speed = 1;
|
||||
globalThis.timeScale = 1n;
|
||||
globalThis.timeScaleDividing = false;
|
||||
PluginAPI.mc.timer.timerSpeed = 1;
|
||||
} else {
|
||||
if (speed < 1) {
|
||||
speed = 1 / Math.round(1 / speed);
|
||||
globalThis.timeScaleDividing = true;
|
||||
globalThis.timeScale = BigInt(Math.round(1 / speed));
|
||||
} else {
|
||||
speed = Math.round(speed);
|
||||
globalThis.timeScaleDividing = false;
|
||||
globalThis.timeScale = BigInt(Math.round(speed));
|
||||
}
|
||||
PluginAPI.mc.timer.timerSpeed = speed;
|
||||
}
|
||||
PluginAPI.mc.systemTime = PluginAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.client.Minecraft", "getSystemTime")]();
|
||||
PluginAPI.mc.debugUpdateTime = PluginAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.client.Minecraft", "getSystemTime")]() - 1000n;
|
||||
PluginAPI.mc.timer.lastSyncSysClock = PluginAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.client.Minecraft", "getSystemTime")]();
|
||||
PluginAPI.displayToChat("[Timescale] Set world timescale to " + speed.toFixed(2) + ".");
|
||||
}
|
||||
});
|
||||
@ -52,4 +60,12 @@
|
||||
}
|
||||
};
|
||||
});
|
||||
const original_getSystemTime = ModAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.client.Minecraft", "getSystemTime")];
|
||||
PluginAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.client.Minecraft", "getSystemTime")] = function () {
|
||||
if (globalThis.timeScaleDividing) {
|
||||
return original_getSystemTime() / globalThis.timeScale;
|
||||
} else {
|
||||
return original_getSystemTime() * globalThis.timeScale;
|
||||
}
|
||||
};
|
||||
})();
|
69
examplemods/useless_item_example_mod_112.js
Normal file
69
examplemods/useless_item_example_mod_112.js
Normal file
@ -0,0 +1,69 @@
|
||||
// This is an example mod on how to register an item.
|
||||
(()=>{
|
||||
const itemTexture = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAKZJREFUOE9j/P//PxMDBIBoEP6HREOl4PLIciA2AyPIgMcM//7KgvWSDJjBBpx9/+YvJzc3Sbq12DhB6sEGsJ19/+YnmQawYhigzc7FcPXnN4KugbqAHWQAy9n3b34T4wJkw6EGYLqAoNVQBWS5ANlwZBfAvUCs/0EGkW0AzBKqGoCSDgh5A80F2KMRpAgfAKUT6kcjsfEPUycmKMQgy8AETkgUZWcAS3CPIf4oSPsAAAAASUVORK5CYII=";
|
||||
//this texture is REALLY bad, so the item appears 2d in game. (it uses partially transparent pixels around the edges in some spots ;-;)
|
||||
ModAPI.meta.title("Adding items demo.");
|
||||
ModAPI.meta.version("v1.0");
|
||||
ModAPI.meta.icon(itemTexture);
|
||||
ModAPI.meta.description("Requires AsyncSink.");
|
||||
|
||||
function ExampleItem() {
|
||||
var creativeMiscTab = ModAPI.reflect.getClassById("net.minecraft.creativetab.CreativeTabs").staticVariables.MISC;
|
||||
var itemClass = ModAPI.reflect.getClassById("net.minecraft.item.Item");
|
||||
var itemSuper = ModAPI.reflect.getSuper(itemClass, (x) => x.length === 1);
|
||||
function nmi_ItemExample() {
|
||||
itemSuper(this); //Use super function to get block properties on this class.
|
||||
this.$setCreativeTab(creativeMiscTab);
|
||||
}
|
||||
ModAPI.reflect.prototypeStack(itemClass, nmi_ItemExample);
|
||||
|
||||
function internal_reg() {
|
||||
var example_item = (new nmi_ItemExample()).$setUnlocalizedName(
|
||||
ModAPI.util.str("exampleitem")
|
||||
);
|
||||
itemClass.staticMethods.registerItem.method(ModAPI.keygen.item("exampleitem"), ModAPI.util.str("exampleitem"), example_item);
|
||||
ModAPI.items["exampleitem"] = example_item;
|
||||
|
||||
return example_item;
|
||||
}
|
||||
|
||||
if (ModAPI.items) {
|
||||
return internal_reg();
|
||||
} else {
|
||||
ModAPI.addEventListener("bootstrap", internal_reg);
|
||||
}
|
||||
}
|
||||
|
||||
ModAPI.dedicatedServer.appendCode(ExampleItem);
|
||||
var example_item = ExampleItem();
|
||||
|
||||
ModAPI.addEventListener("lib:asyncsink", async () => {
|
||||
ModAPI.addEventListener("lib:asyncsink:registeritems", (renderItem)=>{
|
||||
renderItem.registerItem(example_item, ModAPI.util.str("exampleitem"));
|
||||
});
|
||||
AsyncSink.L10N.set("item.exampleitem.name", "Example Item");
|
||||
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/models/item/exampleitem.json", JSON.stringify(
|
||||
{
|
||||
"parent": "builtin/generated",
|
||||
"textures": {
|
||||
"layer0": "items/exampleitem"
|
||||
},
|
||||
"display": {
|
||||
"thirdperson": {
|
||||
"rotation": [ -90, 0, 0 ],
|
||||
"translation": [ 0, 1, -3 ],
|
||||
"scale": [ 0.55, 0.55, 0.55 ]
|
||||
},
|
||||
"firstperson": {
|
||||
"rotation": [ 0, -135, 25 ],
|
||||
"translation": [ 0, 4, 2 ],
|
||||
"scale": [ 1.7, 1.7, 1.7 ]
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
AsyncSink.setFile("resourcepacks/AsyncSinkLib/assets/minecraft/textures/items/exampleitem.png", await (await fetch(
|
||||
itemTexture
|
||||
)).arrayBuffer());
|
||||
});
|
||||
})();
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eaglerforgeinjector",
|
||||
"version": "2.7.92",
|
||||
"version": "2.7.93",
|
||||
"description": "Advanced modding API injector for unminified, unobfuscated, unsigned eaglercraft builds.",
|
||||
"main": "node.js",
|
||||
"directories": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user