Merge pull request #37 from eaglerforge/main

keygen module
This commit is contained in:
ZXMushroom63 2024-12-01 19:11:05 +08:00 committed by GitHub
commit 403d41d6d9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 346 additions and 47 deletions

View File

@ -42,8 +42,10 @@ Events broadcast data for use in mods.
- `frame`:
- Called just when a frame is rendered on the client.
- Event object is blank.
- `render`:
- Called when 3D is rendered.
- Event object is has one property:
- `partialTicks`: number representing the fraction of ticks passed at this frame.
### Server Side Events
Can only be used in the context of the dedicated server. More: [DedicatedServerDocumentation](dedicatedserver.md)
- `serverstart`:

View File

@ -65,13 +65,16 @@ The global object has the following properties:
- Once the dedicated server worker has started, it is unuseable.
- More: [DedicatedServerDocumentation](dedicatedserver.md)
- `ModAPI.meta`
- This object is used to register metadata for mods such as their title, credits, icon and description.
- This module is used to register metadata for mods such as their title, credits, icon and description.
- More: [MetaDocumentation](meta.md)
- `ModAPI.array`
- This object is used to interact and create arrays easily.
- This module is used to interact and create arrays easily.
- More: [ArrayDocumentation](array.md)
- `ModAPI.keygen`
- This module is used to get IDs for registering blocks and items without hardcoding an ID.
- More: [KeygenDocumentation](keygen.md)
- `ModAPI.resolution`
- This object is used to query information about GUI dimensions, to make drawing to the screen easier, generated when the `frame` event is fired.
- This module is used to query information about GUI dimensions, to make drawing to the screen easier, generated when the `frame` event is fired.
- Deprecated alias (please do not use): `ModAPI.ScaledResolution`
- More: [ArrayDocumentation](array.md)
- `ModAPI.version: String`

8
docs/apidoc/keygen.md Normal file
View File

@ -0,0 +1,8 @@
## ModAPI.keygen
ModAPI.keygen contains the API for getting item and block IDs from a string. It looks at the registries for items and blocks to derive the IDs, so IDs will not be automatically reserved until a block/item is actually registered. Ideally, you'd want to call a keygen method just before registering your block.
Methods:
- `ModAPI.keygen.item(itemId: String) : number`
- Example usage is: `var id = ModAPI.keygen.item("my_example_item");`
- `ModAPI.keygen.block(blockId: String) : number`
- Example usage is: `var id = ModAPI.keygen.block("my_example_block");`

View File

@ -1,10 +1,38 @@
## Mod tutorials with ModAPI
### Beginner
Prerequisites:
- Basic knowledge of JavaScript
- A good code editor (recommended: https://vscode.dev)
### Beginner
Tutorials:
- [Step Hack](step.md)
- [Spider Hack](spider.md)
- [VClip Exploit](comingsoon)
- [VClip Exploit](comingsoon)
### Intermediate
Prerequisites:
- Basic knowledge of JavaScript
- A good code editor (recommended: https://vscode.dev)
- A copy of the eaglercraft workspace (optional, get it at: https://git.eaglercraft.rip/eaglercraft/eaglercraft-1.8-workspace)
Tutorials:
- [Disable All Particles](comingsoon)
- [/hat mod](comingsoon)
- [/spawnxp command](comingsoon)
- [Slippery Mod](comingsoon)
### Advanced
Prerequisites:
- Basic knowledge of JavaScript
- A good code editor (recommended: https://vscode.dev)
- A copy of the eaglercraft workspace (get it at: https://git.eaglercraft.rip/eaglercraft/eaglercraft-1.8-workspace)
- Your EaglerForgeInjector processed.html opened in an editor (optional)
Tutorials:
- [Custom Blocks](comingsoon)
- [Custom Items](comingsoon)
- [Timescale Command](comingsoon)

View File

@ -188,39 +188,47 @@ ModAPI.meta.credits("By ZXMushroom63");
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));
var pack = {
domains: ["minecraft", "eagler"],
folder: "AsyncSinkLib",
name: "AsyncSinkLib",
timestamp: Date.now()
};
if (!Array.isArray(resourcePackList.resourcePacks)) {
resourcePackList.resourcePacks = [];
}
if (resourcePackList.resourcePacks.find(x => x.name === "AsyncSinkLib")) {
var idx = resourcePackList.resourcePacks.indexOf(resourcePackList.resourcePacks.find(x => x.name === "AsyncSinkLib"));
resourcePackList.resourcePacks[idx] = pack;
} else {
resourcePackList.resourcePacks.push(pack);
}
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
@ -235,7 +243,7 @@ ModAPI.meta.credits("By ZXMushroom63");
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();
//assureAsyncSinkResources();
if (asyncSinkInstallStatus) {
installMessage.style.display = "none";
} else {

File diff suppressed because one or more lines are too long

View File

@ -44,7 +44,7 @@ function registerSteveClientSide() {
ModAPI.util.str("steve")
);
blockClass.staticMethods.registerBlock0.method(
198, //use blockid 198. MAKE SURE TO CHANGE IF YOU ARE MAKING A MOD USING THIS, MAXIMUM BLOCK ID IS 4095.
ModAPI.keygen.block("steve"),
ModAPI.util.str("steve"),
block_of_steve
);
@ -112,7 +112,7 @@ function registerSteveServerSide() {
ModAPI.util.str("steve")
);
blockClass.staticMethods.registerBlock0.method(
198, //use blockid 198. MAKE SURE TO CHANGE IF YOU ARE MAKING A MOD USING THIS, MAXIMUM BLOCK ID IS 4095.
ModAPI.keygen.block("steve"), //use blockid 198. MAKE SURE TO CHANGE IF YOU ARE MAKING A MOD USING THIS, MAXIMUM BLOCK ID IS 4095.
ModAPI.util.str("steve"),
block_of_steve
);

View File

@ -26,7 +26,7 @@ function registerSteveClientSide() {
ModAPI.util.str("steve")
).$setCreativeTab(creativeBlockTab);
blockClass.staticMethods.registerBlock0.method(
198, //use blockid 198. MAKE SURE TO CHANGE IF YOU ARE MAKING A MOD USING THIS, MAXIMUM BLOCK ID IS 4095.
ModAPI.keygen.block("steve"), //use blockid 198. MAKE SURE TO CHANGE IF YOU ARE MAKING A MOD USING THIS, MAXIMUM BLOCK ID IS 4095.
ModAPI.util.str("steve"),
block_of_steve
);
@ -97,7 +97,7 @@ function registerSteveServerSide() {
ModAPI.util.str("steve")
).$setCreativeTab(creativeBlockTab);
blockClass.staticMethods.registerBlock0.method(
198, //use blockid 198. MAKE SURE TO CHANGE IF YOU ARE MAKING A MOD USING THIS, MAXIMUM BLOCK ID IS 4095.
ModAPI.keygen.block("steve"), //use blockid 198. MAKE SURE TO CHANGE IF YOU ARE MAKING A MOD USING THIS, MAXIMUM BLOCK ID IS 4095.
ModAPI.util.str("steve"),
block_of_steve
);

42
examplemods/jenny_skin.js Normal file

File diff suppressed because one or more lines are too long

36
examplemods/microphone.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -56,7 +56,7 @@
ModAPI.util.str("unluckiness")
);
blockClass.staticMethods.registerBlock0.method(
544, //use blockid 544. MAKE SURE TO CHANGE IF YOU ARE MAKING A MOD USING THIS, MAXIMUM BLOCK ID IS 4095.
ModAPI.keygen.block("unluckiness"),
ModAPI.util.str("unluckiness"),
block_of_unluckiness
);

View File

@ -24,7 +24,7 @@
var example_item = (new nmi_ItemExample()).$setUnlocalizedName(
ModAPI.util.str("exampleitem")
);
itemClass.staticMethods.registerItem0.method(432, ModAPI.util.str("exampleitem"), example_item);
itemClass.staticMethods.registerItem0.method(ModAPI.keygen.item("exampleitem"), ModAPI.util.str("exampleitem"), example_item);
ModAPI.items["exampleitem"] = example_item;
return example_item;

View File

@ -22,7 +22,7 @@ globalThis.modapi_postinit = "(" + (() => {
ModAPI.meta._versionMap = {};
ModAPI.array = {};
ModAPI.version = "v2.2";
ModAPI.version = "v2.3";
ModAPI.flavour = "injector";
ModAPI.GNU = "terry pratchett";
ModAPI.credits = ["ZXMushroom63", "radmanplays", "Murturtle", "OtterCodes101", "TheIdiotPlays", "OeildeLynx31", "Stpv22"];
@ -952,4 +952,37 @@ globalThis.modapi_postinit = "(" + (() => {
ModAPI.events.newEvent(eventName, "patcher");
});
}
function qhash(txt, arr) {
var interval = 4095 - arr.length;
var x = 1;
for (let i = 0; i < txt.length; i++) {
x += txt.charCodeAt(i);
x = x << txt.charCodeAt(i);
x = Math.abs(x);
x = x % interval;
}
var hash = x + arr.length;
while (arr.includes(hash)) {
hash = (hash + 1) % (interval + arr.length);
}
return hash;
}
ModAPI.keygen = {};
var registryNamespaceMethod = ModAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.util.RegistryNamespaced", "register")];
ModAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.util.RegistryNamespaced", "register")] = function (...args) {
args[0].$modapi_specmap ||= new Map();
args[0].$modapi_specmap.set(args[2], args[1]);
return registryNamespaceMethod.apply(this, args);
}
ModAPI.keygen.item = function (item) {
var values = [...ModAPI.reflect.getClassById("net.minecraft.item.Item").staticVariables.itemRegistry.$modapi_specmap.values()];
return qhash(item, values);
}
ModAPI.keygen.block = function (block) {
var values = [...ModAPI.reflect.getClassById("net.minecraft.block.Block").staticVariables.blockRegistry.$modapi_specmap.values()];
return qhash(block, values);
}
}).toString() + ")();";