Supporters
Community members who have proven to be competent supporters.
Posts
-
where is the liquidbounce folder in prism launcher -
[Script] PearlBlockThrow ?This is a somewhat faithful transplation of the original source code, which would not work on 1.8.x, this should desync your inventory too.
function __require(path) { if (path.startsWith("@embedded")) { return globalThis } if (path.startsWith("@minecraft-yarn-definitions/types/")) { return { [path.substring(path.lastIndexOf("/") + 1)]: Java.type(path .replaceAll("@minecraft-yarn-definitions/types/", "") .replaceAll("/", ".") ) } } return require(path); } var exports = {} "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // imports /* eslint-disable unused-imports/no-unused-imports */ const _embedded_1 = __require("@embedded"); /* eslint-enable unused-imports/no-unused-imports */ // DO NOT TOUCH ANYTHING ABOVE THIS LINE, also not sure why it didn't work const PlayerInteractItemC2SPacket_1 = __require("@minecraft-yarn-definitions/types/net/minecraft/network/packet/c2s/play/PlayerInteractItemC2SPacket"); const UpdateSelectedSlotC2SPacket_1 = __require("@minecraft-yarn-definitions/types/net/minecraft/network/packet/c2s/play/UpdateSelectedSlotC2SPacket"); const UpdateSelectedSlotS2CPacket_1 = __require("@minecraft-yarn-definitions/types/net/minecraft/network/packet/s2c/play/UpdateSelectedSlotS2CPacket"); const Items_1 = __require("@minecraft-yarn-definitions/types/net/minecraft/item/Items"); const Hand_1 = __require("@minecraft-yarn-definitions/types/net/minecraft/util/Hand"); const script = _embedded_1.registerScript.apply({ name: "no-pearl-use", version: "1.0.0", authors: ["commandblock2"] }); script.registerModule({ name: "no-pearl-use", description: "cancels ender pearl use", category: "Player", }, (mod) => { var slot = 0; mod.on("enable", () => { var _a, _b; slot = (_b = (_a = _embedded_1.mc.player) === null || _a === void 0 ? void 0 : _a.inventory.selectedSlot) !== null && _b !== void 0 ? _b : 0; }); mod.on("packet", (event) => { var _a; if (event.packet instanceof UpdateSelectedSlotS2CPacket_1.UpdateSelectedSlotS2CPacket) { slot = event.packet.slot(); } if (event.packet instanceof UpdateSelectedSlotC2SPacket_1.UpdateSelectedSlotC2SPacket) { slot = event.packet.selectedSlot; } if (event.packet instanceof PlayerInteractItemC2SPacket_1.PlayerInteractItemC2SPacket && ((_a = _embedded_1.mc.player) === null || _a === void 0 ? void 0 : _a.inventory.main[slot].item) == Items_1.Items.ENDER_PEARL) { // use reflection to set the hand to offhand const field = event.packet.class.getDeclaredField("hand"); field.setAccessible(true); field.set(event.packet, Hand_1.Hand.OFF_HAND); _embedded_1.Client.displayChatMessage(`§cPearl use changed to hand ${event.packet.hand}`); } }); });
original typescript code
// imports /* eslint-disable unused-imports/no-unused-imports */ import { Setting, Vec3i, Vec3d, MathHelper, BlockPos, Hand, RotationAxis, mc, Client, RotationUtil, ItemUtil, NetworkUtil, InteractionUtil, BlockUtil, MovementUtil, ReflectionUtil, ParameterValidator, UnsafeThread, registerScript } from "@embedded"; /* eslint-enable unused-imports/no-unused-imports */ // DO NOT TOUCH ANYTHING ABOVE THIS LINE, also not sure why it didn't work import { PlayerInteractItemC2SPacket } from "@minecraft-yarn-definitions/types/net/minecraft/network/packet/c2s/play/PlayerInteractItemC2SPacket"; import { UpdateSelectedSlotC2SPacket } from "@minecraft-yarn-definitions/types/net/minecraft/network/packet/c2s/play/UpdateSelectedSlotC2SPacket"; import { UpdateSelectedSlotS2CPacket } from "@minecraft-yarn-definitions/types/net/minecraft/network/packet/s2c/play/UpdateSelectedSlotS2CPacket"; import { Items } from "@minecraft-yarn-definitions/types/net/minecraft/item/Items"; import { Hand as MCHand } from "@minecraft-yarn-definitions/types/net/minecraft/util/Hand"; const script = registerScript.apply({ name: "no-pearl-use", version: "1.0.0", authors: ["commandblock2"] }); script.registerModule({ name: "no-pearl-use", description: "cancels ender pearl use", category: "Player", }, (mod) => { var slot = 0 mod.on("enable", () => { slot = mc.player?.inventory.selectedSlot ?? 0; }) mod.on("packet", (event) => { if (event.packet instanceof UpdateSelectedSlotS2CPacket) { slot = event.packet.slot(); } if (event.packet instanceof UpdateSelectedSlotC2SPacket) { slot = event.packet.selectedSlot; } if (event.packet instanceof PlayerInteractItemC2SPacket && mc.player?.inventory.main[slot].item == Items.ENDER_PEARL ) { // use reflection to set the hand to offhand const field = (event.packet as any).class.getDeclaredField("hand"); field.setAccessible(true); field.set(event.packet, MCHand.OFF_HAND); Client.displayChatMessage(`§cPearl use changed to hand ${event.packet.hand}`); } }) })
This will indeed cancel the usage of the pearl on 1.8.x protocols
function __require(path) { if (path.startsWith("@embedded")) { return globalThis } if (path.startsWith("@minecraft-yarn-definitions/types/")) { return { [path.substring(path.lastIndexOf("/") + 1)]: Java.type(path .replaceAll("@minecraft-yarn-definitions/types/", "") .replaceAll("/", ".") ) } } return require(path); } var exports = {} "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // imports /* eslint-disable unused-imports/no-unused-imports */ const _embedded_1 = __require("@embedded"); /* eslint-enable unused-imports/no-unused-imports */ // DO NOT TOUCH ANYTHING ABOVE THIS LINE, also not sure why it didn't work const PlayerInteractItemC2SPacket_1 = __require("@minecraft-yarn-definitions/types/net/minecraft/network/packet/c2s/play/PlayerInteractItemC2SPacket"); const UpdateSelectedSlotC2SPacket_1 = __require("@minecraft-yarn-definitions/types/net/minecraft/network/packet/c2s/play/UpdateSelectedSlotC2SPacket"); const UpdateSelectedSlotS2CPacket_1 = __require("@minecraft-yarn-definitions/types/net/minecraft/network/packet/s2c/play/UpdateSelectedSlotS2CPacket"); const Items_1 = __require("@minecraft-yarn-definitions/types/net/minecraft/item/Items"); const script = _embedded_1.registerScript.apply({ name: "no-pearl-use", version: "1.0.0", authors: ["commandblock2"] }); script.registerModule({ name: "no-pearl-use", description: "cancels ender pearl use", category: "Player", }, (mod) => { var slot = 0; mod.on("enable", () => { var _a, _b; slot = (_b = (_a = _embedded_1.mc.player) === null || _a === void 0 ? void 0 : _a.inventory.selectedSlot) !== null && _b !== void 0 ? _b : 0; }); mod.on("packet", (event) => { var _a; if (event.packet instanceof UpdateSelectedSlotS2CPacket_1.UpdateSelectedSlotS2CPacket) { slot = event.packet.slot(); } if (event.packet instanceof UpdateSelectedSlotC2SPacket_1.UpdateSelectedSlotC2SPacket) { slot = event.packet.selectedSlot; } if (event.packet instanceof PlayerInteractItemC2SPacket_1.PlayerInteractItemC2SPacket && ((_a = _embedded_1.mc.player) === null || _a === void 0 ? void 0 : _a.inventory.main[slot].item) == Items_1.Items.ENDER_PEARL) { event.cancelEvent(); } }); });
This will desync your inventory with the server anyway, but it is true that no end pearl will be thrown if you have one in your hand (unless u have a pearl in server side but not client side). Can be used as a example.
Later is the original ts file.// imports /* eslint-disable unused-imports/no-unused-imports */ import { Setting, Vec3i, Vec3d, MathHelper, BlockPos, Hand, RotationAxis, mc, Client, RotationUtil, ItemUtil, NetworkUtil, InteractionUtil, BlockUtil, MovementUtil, ReflectionUtil, ParameterValidator, UnsafeThread, registerScript } from "@embedded"; /* eslint-enable unused-imports/no-unused-imports */ // DO NOT TOUCH ANYTHING ABOVE THIS LINE, also not sure why it didn't work import { PlayerInteractItemC2SPacket } from "@minecraft-yarn-definitions/types/net/minecraft/network/packet/c2s/play/PlayerInteractItemC2SPacket"; import { UpdateSelectedSlotC2SPacket } from "@minecraft-yarn-definitions/types/net/minecraft/network/packet/c2s/play/UpdateSelectedSlotC2SPacket"; import { UpdateSelectedSlotS2CPacket } from "@minecraft-yarn-definitions/types/net/minecraft/network/packet/s2c/play/UpdateSelectedSlotS2CPacket"; import { Items } from "@minecraft-yarn-definitions/types/net/minecraft/item/Items"; const script = registerScript.apply({ name: "no-pearl-use", version: "1.0.0", authors: ["commandblock2"] }); script.registerModule({ name: "no-pearl-use", description: "cancels ender pearl use", category: "Player", }, (mod) => { var slot = 0 mod.on("enable", () => { slot = mc.player?.inventory.selectedSlot ?? 0; }) mod.on("packet", (event) => { if (event.packet instanceof UpdateSelectedSlotS2CPacket) { slot = event.packet.slot(); } if (event.packet instanceof UpdateSelectedSlotC2SPacket) { slot = event.packet.selectedSlot; } if (event.packet instanceof PlayerInteractItemC2SPacket && mc.player?.inventory.main[slot].item == Items.ENDER_PEARL ) { event.cancelEvent(); } }) })
-
who can write the script? noSlotChanger in the client LB for NextgenTrying with matrix on loyisa.cn with noslow mode set to None indeed will move your slot to other items. However just like I assumed previously simply ignoring the packet just won't do, you can never eat the food, even if you immediately send back a slot change. You might need something else to make a nolow mode for matrix. If you need to verify yourself, here is your script anyway.
function __require(path) { if (path.startsWith("@embedded")) { return globalThis } if (path.startsWith("@minecraft-yarn-definitions/types/")) { return { [path.substring(path.lastIndexOf("/") + 1)]: Java.type(path .replaceAll("@minecraft-yarn-definitions/types/", "") .replaceAll("/", ".") ) } } return require(path); } var exports = {} "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // imports /* eslint-disable unused-imports/no-unused-imports */ const _embedded_1 = __require("@embedded"); /* eslint-enable unused-imports/no-unused-imports */ // DO NOT TOUCH ANYTHING ABOVE THIS LINE, also not sure why it didn't work const UpdateSelectedSlotC2SPacket_1 = __require("@minecraft-yarn-definitions/types/net/minecraft/network/packet/c2s/play/UpdateSelectedSlotC2SPacket"); const UpdateSelectedSlotS2CPacket_1 = __require("@minecraft-yarn-definitions/types/net/minecraft/network/packet/s2c/play/UpdateSelectedSlotS2CPacket"); const script = _embedded_1.registerScript.apply({ name: "anti slot changing", version: "1.0.0", authors: ["commandblock2"] }); script.registerModule({ name: "anti-slot-changing", description: "like no rotate reset but for slots", category: "Exploit", settings: { resyncServerSide: _embedded_1.Setting.boolean({ name: "resync server side", default: true }) }, }, (mod) => { mod.on("packet", (event) => { var _a, _b, _c; if (event.packet instanceof UpdateSelectedSlotS2CPacket_1.UpdateSelectedSlotS2CPacket) { event.cancelEvent(); if (!mod.settings.resyncServerSide.get()) return; (_a = _embedded_1.mc.getNetworkHandler()) === null || _a === void 0 ? void 0 : _a.sendPacket(new UpdateSelectedSlotC2SPacket_1.UpdateSelectedSlotC2SPacket((_c = (_b = _embedded_1.mc.player) === null || _b === void 0 ? void 0 : _b.inventory.selectedSlot) !== null && _c !== void 0 ? _c : 0)); } }); });
-
Vectorized VelocityChanges the velocity direction or strength based on the incoming packet or minecraft player's facing direction. Usually not useful unless you need to be flying sideways or your facing direction.
Released js for LiquidBounce Nextgen 0.28.1, Licensed under GPLv3
function __require(path) { if (path.startsWith("@embedded")) { return globalThis } if (path.startsWith("@minecraft-yarn-definitions/types/")) { return { [path.substring(path.lastIndexOf("/") + 1)]: Java.type(path .replaceAll("@minecraft-yarn-definitions/types/", "") .replaceAll("/", ".") ) } } return require(path); } var exports = {} "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // imports /* eslint-disable unused-imports/no-unused-imports */ const _embedded_1 = __require("@embedded"); const EntityVelocityUpdateS2CPacket_1 = __require("@minecraft-yarn-definitions/types/net/minecraft/network/packet/s2c/play/EntityVelocityUpdateS2CPacket"); /* eslint-enable unused-imports/no-unused-imports */ // DO NOT TOUCH ANYTHING ABOVE THIS LINE, also not sure why it didn't work const script = _embedded_1.registerScript.apply({ name: "vectorized-velocity-xz", version: "1.0.0", authors: ["commandblock2"] }); script.registerModule({ name: "vectorized-velocity-xz", description: "Port of the old script for legacy, for those anticheat that doesn't have proper velocity detection", category: "Combat", settings: { offsetBasedOnPlayerOrIncomingVelocity: _embedded_1.Setting.choose({ name: "OffsetBasedOnPlayerOrIncomingVelocity", choices: ["player", "incoming"], default: "player" }), offset: _embedded_1.Setting.float({ name: "AngleOffset", default: 0, range: [-180, 180] }), amplitude: _embedded_1.Setting.float({ name: "Amplitude", default: 1, range: [-100, 100] }) } }, (mod) => { mod.on("packet", (event) => { if (!_embedded_1.mc.player) return; const packet = event.packet; if (packet instanceof EntityVelocityUpdateS2CPacket_1.EntityVelocityUpdateS2CPacket && packet.entityId == _embedded_1.mc.player.id) { const yaw = mod.settings.offset.get() + (mod.settings.offsetBasedOnPlayerOrIncomingVelocity.getValue() == "player" ? -_embedded_1.mc.player.yaw : (Math.atan2(packet.getVelocityX(), packet.getVelocityZ()) * 180 / Math.PI)); const velocity = Math.sqrt(packet.getVelocityX() * packet.getVelocityX() + packet.getVelocityZ() * packet.getVelocityZ()) * 8000 * mod.settings.amplitude.get(); // graaljs traps here: // 1. it eats error here when we have loss in precision and does not update the value // 2. packet.velocityX and packet.getVelocityX() is very different (public double getVelocityX() { return (double)this.velocityX / 8000.0; }) // and when reading velocityX graaljs calls getVelocityX() and when writing velocityX it directly writes that packet.velocityX = Math.round(velocity * Math.sin(yaw / 180 * Math.PI)); packet.velocityZ = Math.round(velocity * Math.cos(yaw / 180 * Math.PI)); } }); });
original typescript script, won't run directly in LiquidBounce, for more info, see https://github.com/commandblock2/minecraft-LBNG-types
// imports /* eslint-disable unused-imports/no-unused-imports */ import { Setting, Vec3i, Vec3d, MathHelper, BlockPos, Hand, RotationAxis, mc, Client, RotationUtil, ItemUtil, NetworkUtil, InteractionUtil, BlockUtil, MovementUtil, ReflectionUtil, ParameterValidator, UnsafeThread, registerScript } from "@embedded"; import { EntityVelocityUpdateS2CPacket } from "@minecraft-yarn-definitions/types/net/minecraft/network/packet/s2c/play/EntityVelocityUpdateS2CPacket"; /* eslint-enable unused-imports/no-unused-imports */ // DO NOT TOUCH ANYTHING ABOVE THIS LINE, also not sure why it didn't work const script = registerScript.apply({ name: "vectorized-velocity-xz", version: "1.0.0", authors: ["commandblock2"] }); script.registerModule({ name: "vectorized-velocity-xz", description: "Port of the old script for legacy, for those anticheat that doesn't have proper velocity detection", category: "Combat", settings: { offsetBasedOnPlayerOrIncomingVelocity: Setting.choose({ name: "OffsetBasedOnPlayerOrIncomingVelocity", choices: ["player", "incoming"], default: "player" }), offset: Setting.float({ name: "AngleOffset", default: 0, range: [-180, 180] }), amplitude: Setting.float({ name: "Amplitude", default: 1, range: [-100, 100] }) } }, (mod) => { mod.on("packet", (event) => { if (!mc.player) return; const packet = event.packet if (packet instanceof EntityVelocityUpdateS2CPacket && packet.entityId == mc.player.id) { const yaw = mod.settings.offset.get() + (mod.settings.offsetBasedOnPlayerOrIncomingVelocity.getValue() == "player" ? -mc.player.yaw : (Math.atan2(packet.getVelocityX(), packet.getVelocityZ()) * 180 / Math.PI)); const velocity = Math.sqrt(packet.getVelocityX() * packet.getVelocityX() + packet.getVelocityZ() * packet.getVelocityZ()) * 8000 * mod.settings.amplitude.get(); // graaljs traps here: // 1. it eats error here when we have loss in precision and does not update the value // 2. packet.velocityX and packet.getVelocityX() is very different (public double getVelocityX() { return (double)this.velocityX / 8000.0; }) // and when reading velocityX graaljs calls getVelocityX() and when writing velocityX it directly writes that packet.velocityX = Math.round(velocity * Math.sin(yaw / 180 * Math.PI)) packet.velocityZ = Math.round(velocity * Math.cos(yaw / 180 * Math.PI)) } }) })
-
who can write the script? noSlotChanger in the client LB for NextgenThis might be more than just 'preventing the server side anti-cheat to change the hot bar slot' since you mentioned that you are using noslow while eating. Can you please post what anti cheat (might be using
UpdateSelectedSlotS2CPacket
to sync your hotbar) and what noslow modes are you using? (grim noslow modes switches your hotbar server side)internal class NoSlowSharedGrim2364MC18(override val parent: ChoiceConfigurable<*>) : Choice("Grim2364-1.8") { @Suppress("unused") private val onNetworkTick = handler<PlayerNetworkMovementTickEvent> { event -> if (player.isUsingItem && event.state == EventState.PRE) { // Switch slots so grim exempts noslow... // Introduced with https://github.com/GrimAnticheat/Grim/issues/874 untracked { val slot = player.inventory.selectedSlot network.sendPacket(UpdateSelectedSlotC2SPacket(slot % 8 + 1)) network.sendPacket(UpdateSelectedSlotC2SPacket(slot % 7 + 2)) network.sendPacket(UpdateSelectedSlotC2SPacket(slot)) } } } }
Even if you refuse to accept any
UpdateSelectedSlotS2CPacket
and looks as if your hotbar is not switching, there could be a desync and you won't be able to eat food. Would appreciate if you could provide more information of what you are tying to do. -
who can write the script? noSlotChanger in the client LB for Nextgenencoded a jar into base64 and embed in a script, not crazy at all xD.
-
WIP Windows10 Fluent Design ThemeFeatures (maybe xD)
- reveal effect from https://github.com/d2phap/fluent-reveal-effect
- absolutely no rounded corner
- use platform dependent font
Hack
and not packaging it into the theme xD - in-consistent effect application (not on buttons like Bind)
- not polished at all
- other gui not changed at all
- horrible performance
- no instruction to install at all
Jokes aside this is indeed a WIP theme and don't expect it be perfect. To contribute to this theme, prs and issues are welcomed, https://github.com/commandblock2/GoodOldFluentDesign
- reveal effect from https://github.com/d2phap/fluent-reveal-effect
-
Typescript definition for minecraft and LiquidBounceUpdate: subsequent updates will be available on https://github.com/commandblock2/minecraft-LBNG-types
and the generated script was reverted to a state where it was not as readable as the following example (for correctness) but still largely remained the same.
Now it can kinda generate a working script, but the ts file has a few squiggles.
template.ts
// imports import { Setting, Vec3i, Vec3d, MathHelper, BlockPos, Hand, RotationAxis, mc, Client, RotationUtil, ItemUtil, NetworkUtil, InteractionUtil, BlockUtil, MovementUtil, ReflectionUtil, ParameterValidator, UnsafeThread, registerScript } from "@embedded"; import { ScriptModule } from "@minecraft-yarn-definitions/types/net/ccbluex/liquidbounce/script/bindings/features/ScriptModule"; import { Matrix2d } from "@minecraft-yarn-definitions/types/org/joml/Matrix2d"; const script = registerScript.apply({ name: "template", version: "1.0.0", authors: ["commandblock2"] }); script.registerModule({ // @ts-ignore name: "example-from-template", // @ts-ignore description: "Ths is an example module generated in ts", // @ts-ignore category: "Client" }, (mod: ScriptModule) => { mod.on("enable", () => { Client.displayChatMessage(`${mc.player}`) Client.displayChatMessage(`${new Vec3i(1, 2, 3)}`) Client.displayChatMessage(`${new Matrix2d(1.2, 1.3, 1.4, 15)}`) Client.displayChatMessage("enabled") }) mod.on("disable", () => Client.displayChatMessage("disabled")) })
compiled template.js
function __require(path) { if (path.startsWith("@embedded")) { return { _embedded: globalThis } } if (path.startsWith("@minecraft-yarn-definitions/types/")) { return { [path.substring(path.lastIndexOf("/") + 1)]: Java.type(path .replaceAll("@minecraft-yarn-definitions/types/", "") .replaceAll("/", ".") ) } } return require(path); } var exports = {} "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const { _embedded } = __require("@embedded"); const { Matrix2d } = __require("@minecraft-yarn-definitions/types/org/joml/Matrix2d"); const script = _embedded.registerScript.apply({ name: "template", version: "1.0.0", authors: ["commandblock2"] }); script.registerModule({ // @ts-ignore name: "example-from-template", // @ts-ignore description: "Ths is an example module generated in ts", // @ts-ignore category: "Client" }, (mod) => { mod.on("enable", () => { _embedded.Client.displayChatMessage(`${_embedded.mc.player}`); _embedded.Client.displayChatMessage(`${new Vec3i(1, 2, 3)}`); _embedded.Client.displayChatMessage(`${new Matrix2d(1.2, 1.3, 1.4, 15)}`); _embedded.Client.displayChatMessage("enabled"); }); mod.on("disable", () => _embedded.Client.displayChatMessage("disabled")); });
-
Typescript definition for minecraft and LiquidBounceUpdate: now the script will also print the embedded context made available by the script api
// Import required Java classes // type: array /** @type any[]*/ var globalEntries = Object.entries(this); const System = Java.type("java.lang.System"); const URLClassLoader = Java.type("java.net.URLClassLoader"); const File = Java.type("java.io.File"); const URL = Java.type("java.net.URL"); const Thread = Java.type("java.lang.Thread"); const Paths = Java.type("java.nio.file.Paths"); const Map = Java.type("java.util.HashMap"); const ArrayList = Java.type("java.util.ArrayList"); const JvmClassMappingKt = Java.type("kotlin.jvm.JvmClassMappingKt"); const Class = Java.type("java.lang.Class"); // Function to create a URLClassLoader from a JAR path function createClassLoaderFromJar(jarPath) { try { // Create File object for the JAR const jarFile = new File(jarPath); // Convert File to URL const jarUrl = jarFile.toURI().toURL(); // Create URLClassLoader with the system class loader as parent return new URLClassLoader( [jarUrl], Thread.currentThread().getContextClassLoader() ); } catch (e) { console.error("Error creating ClassLoader:", e); throw e; } } // Function to load a class from a given ClassLoader function loadClassFromJar(classLoader, className) { try { return classLoader.loadClass(className); } catch (e) { console.error(`Error loading class ${className}:`, e); throw e; } } const script = registerScript({ name: "for-repl", version: "1.0.0", authors: ["commandblock2"], }); script.registerModule( { name: "for-repl", category: "Client", description: "Sausage", settings: { path: Setting.text({ name: "Path", default: "/mnt/old-linux/home/commandblock2/git_repo/MultiMC5/build/instances/LBNG-Production/minecraft/LiquidBounce/scripts", }), packageName: Setting.text({ name: "NPMPackageName", default: "minecraft-yarn-definitions", }), }, }, (mod) => { mod.on("enable", (event) => { const loader = createClassLoaderFromJar( mod.settings.path.value + "/ts-generator-1.0.0.jar" ); const NPMGen = loadClassFromJar( loader, "me.commandblock2.tsGenerator.NPMPackageGenerator" ); const TsGen = loadClassFromJar( loader, "me.ntrrgc.tsGenerator.TypeScriptGenerator" ); const VoidType = loadClassFromJar( loader, "me.ntrrgc.tsGenerator.VoidType" ); const NULL = VoidType.getEnumConstants()[0]; const javaClasses = globalEntries .filter((entry) => entry[1] != undefined) .map((entry) => (entry[1] instanceof Class ? entry[1] : entry[1].class)) .filter((entry) => entry != undefined); const kotlinClasses = javaClasses.map((entry) => JvmClassMappingKt.getKotlinClass(entry) ); const classes = new ArrayList(kotlinClasses); try { const generated = new TsGen( classes, new Map(), new ArrayList(), new ArrayList(), "number", NULL ); const npmPack = new NPMGen(generated, mod.settings.packageName.value); npmPack.writePackageTo( Paths.get(mod.settings.path.value + "/types-gen") ); const embeddedDefinition = ` // imports ${javaClasses .map((clazz) => { return `import { ${clazz.simpleName} } from "@${mod.settings.packageName.value}/types/${clazz.name.replaceAll(".", "/")}";`; }) .join("\n")} // definitions for objects ${globalEntries .filter((entry) => entry[1] != undefined) .filter((entry) => !(entry[1] instanceof Class)) .filter((entry) => entry[1].class != undefined) .map((entry) => `export var ${entry[0]}: ${entry[1].class.simpleName};`) .join("\n\n")} `; console.log(embeddedDefinition) } catch (e) { e.printStackTrace(); console.error(e); throw e; } // ReflectionUtil.invokeMethod(mc.player, "getName") // event.context.drawGuiTexture(RenderLayer.getGuiTextured, CLOSE_TEXTURE, 0, 0, 16, 16, -1); }); } );
-
Typescript definition for minecraft and LiquidBounceUpdate: Experimental Support For ScriptAPI
minecraft-LBNG-types
This repo contains
- instruction and scripts for creating
- typescript definitions for Minecraft (with mods*)
- typescript definitions for LiquidBounce NextGen
- typescript definitions for embedded context of LiquidBounce NextGen scriptAPI
- a set of manually maintained patches to make the script api work properly
- a set of examples LiquidBounce NextGen script using typescript
- a compiler script that will compile all the .ts files into .js files that could run in graaljs (LiquidBounce NextGen runtime)
Note: the mods are only limited to those presented at the development environment of LiquidBounce NextGen.
When writing your script in typescript, expect inconsistencies with script API in js, but please report them to this repo if you can. But the following example already works(tested)
See also: This amazing plugin that colors each (member)variable to different colors similar to KDevelop
Original:
Typescript definition for minecraft and LiquidBounce (and virtually every mod installed plus java/kotlin infrustructure). The definitions will not be uploaded for potential legal risks (Although I don't really think that would be a violation or smth, I am not lawyer tho, just trying to be safe from distributing the game). See the demo video.
But
- it must be launched from the development environment to generate the definition(for now, will change if I decide to use the remapper or someone else whoever want to make it work can try.)
- there are ofc many nuances not dealt with (typescript -> graaljs).
- there is not yet a fully working project that can convert this to a script that LB compatible js (convert the import for certain prefixes to Java.type()"
- source mapping for the previous process
- it cannot properly deal with graaljs integration (implicit conversions for sometimes),
Any | null | any
and something like that. - Other problems with kotlin reflection vs java reflection but idk about those undiscovered traps.
This is a demo just for showing what is possible, certainly not as good as you think it is
Resources:
Download the ts-generator(FOSS, GPLv3 and Apache 2.0 dual licensed) and extract the zip, or ofc build the jar yourself. create a types-gen folder at the same path, modify the path in the script. Or read the script and support yourself, whatever.
The script for generating the definition:
// Import required Java classes const System = Java.type('java.lang.System'); const URLClassLoader = Java.type('java.net.URLClassLoader'); const File = Java.type('java.io.File'); const URL = Java.type('java.net.URL'); const Thread = Java.type('java.lang.Thread'); const Paths = Java.type('java.nio.file.Paths'); // Function to create a URLClassLoader from a JAR path function createClassLoaderFromJar(jarPath) { try { // Create File object for the JAR const jarFile = new File(jarPath); // Convert File to URL const jarUrl = jarFile.toURI().toURL(); // Create URLClassLoader with the system class loader as parent return new URLClassLoader([jarUrl], Thread.currentThread().getContextClassLoader()); } catch (e) { console.error('Error creating ClassLoader:', e); throw e; } } // Function to load a class from a given ClassLoader function loadClassFromJar(classLoader, className) { try { return classLoader.loadClass(className); } catch (e) { console.error(`Error loading class ${className}:`, e); throw e; } } const script = registerScript({ name: "for-repl", version: "1.0.0", authors: ["commandblock2"] }); script.registerModule({ name: "for-repl", category: "Client", description: "Sausage" }, (mod) => { mod.on("enable", (event) => { if (!mc.player || !mc.world) return; // This is working but lags a lot // The following will be fixed in this pr loader = createClassLoaderFromJar('/path/tots-generator-1.0.0.jar') NPMGen = loadClassFromJar(loader, "me.commandblock2.tsGenerator.NPMPackageGenerator") NPMGenKt = loadClassFromJar(loader, "me.commandblock2.tsGenerator.NPMPackageGeneratorKt") TsGen = loadClassFromJar(loader, "me.ntrrgc.tsGenerator.TypeScriptGenerator") VoidType = loadClassFromJar(loader, "me.ntrrgc.tsGenerator.VoidType") NULL = VoidType.getEnumConstants()[0] Map = Java.type("java.util.HashMap") ArrayList = Java.type("java.util.ArrayList") JvmClassMappingKt = Java.type('kotlin.jvm.JvmClassMappingKt'); kClass = JvmClassMappingKt.getKotlinClass(Client.class); classes = new ArrayList([kClass]); try { generated = new TsGen(classes, new Map(), new ArrayList(), new ArrayList(), "number", NULL); npmPack = new NPMGen(generated, "minecraft-yarn-definitions"); npmPack.writePackageTo(Paths.get("/path/totypes-gen")); console.log(generated); } catch (e) { e.printStackTrace() console.error(e); throw e; } // ReflectionUtil.invokeMethod(mc.player, "getName") // event.context.drawGuiTexture(RenderLayer.getGuiTextured, CLOSE_TEXTURE, 0, 0, 16, 16, -1); }) });
- instruction and scripts for creating