Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse

LiquidBounce Forum

C

commandblock2

@commandblock2
About
Posts
140
Topics
9
Shares
0
Groups
1
Followers
8
Following
1

Posts

Recent Best Controversial

  • air place
    C commandblock2

    https://github.com/CCBlueX/LiquidBounce/issues/2523

    I would that's a valid request

    but anyway here a possible version

    export function interactPlaceMidAir(pos: Vec3d) {
        const blockPos = new BlockPos(pos.x, pos.y, pos.z);
        const hitResult = new BlockHitResult(
            pos, // hit position
            Direction.UP, // side of the block hit (e.g., placing on top)
            blockPos, // block position
            false // insideBlock
        );
        // @ts-expect-error - The type definition for ClientPlayerInteractionManager.sendSequencedPacket expects a specific Packet type, but the lambda returns a generic Packet.
        mc.interactionManager.sendSequencedPacket(mc.world, (sequence: number) => {
            return new PlayerInteractBlockC2SPacket(
                Hand.MAIN_HAND,
                hitResult,
                sequence
            );
        });
    }
    

    but somehow it did place 2 block for me, not so sure about it?

    liquidsquid1 created this issue in CCBlueX/LiquidBounce

    open [FEATURE] Basic AirPlace Implementation #2523

    Suggestions

  • [Guide] Working with Baritone API
    C commandblock2

    It's definitely doable, but you need to use the unoptimized jar to directly call this. Here is the script in ts, but you may need to adapt the imports to Java.type in js. And also for the visualization manager it's not yet available outside of my project. will release once the api is well designed and performance becomes decent and after a proper name is found for the npm package.

    import { BaritoneAPI } from "jvm-types/baritone/api/BaritoneAPI"
    import { GoalXZ } from "jvm-types/baritone/api/pathing/goals/GoalXZ"
    import { CalculationContext } from "jvm-types/baritone/pathing/movement/CalculationContext"
    import { Favoring } from "jvm-types/baritone/utils/pathing/Favoring"
    import { BetterBlockPos } from "jvm-types/baritone/api/utils/BetterBlockPos"
    import { IPath } from "jvm-types/baritone/api/pathing/calc/IPath"
    import { VisualizationManager } from "lbng-utils-typed/dist/visualization-utils"
    import { PathCalculationResult$Type } from "jvm-types/baritone/api/utils/PathCalculationResult$Type"
    
    // note: this import is not from baritone-api jar
    // it is only presented in the baritone-unoptimized jar
    // as the `AStarPathFinder` class is possibly obfuscated in the baritone-standalone jar
    // so you will have to install the baritone-unoptimized jar to use this import
    import { AStarPathFinder } from "jvm-types/baritone/pathing/calc/AStarPathFinder"
    
    
    const script = registerScript.apply({
        name: "astar-pathfinder-example",
        version: "1.0.0",
        authors: ["commandblock2"]
    });
    
    script.registerModule({
        name: "baritone-api-example",
        description: "Baritone example module",
        category: "Client",
    
    }, (mod) => {
        mod.on("enable", () => {
            BaritoneAPI.getSettings().allowSprint.value = true;
            BaritoneAPI.getSettings().primaryTimeoutMS.value = Primitives.long(2000);
            const baritone = BaritoneAPI.getProvider().getPrimaryBaritone();
            baritone.getCustomGoalProcess().setGoalAndPath(new GoalXZ(100, 100))
        })
    })
    
    script.registerModule({
        name: "astar-pathfinder-example",
        description: "Direct AStarPathFinder construction example",
        category: "Client",
        settings: {
            goalX: Setting.float({
                name: "Goal X",
                default: 100,
                range: [-10000, 10000] // Assuming a reasonable range
            }),
            goalZ: Setting.float({
                name: "Goal Z",
                default: 100,
                range: [-10000, 10000] // Assuming a reasonable range
            }),
            recalculateInterval: Setting.int({
                name: "Recalculate Interval (ticks)",
                default: 20,
                range: [1, 200]
            })
        }
    }, (mod) => {
    
        const viz = new VisualizationManager(mod);
    
        let previousPath: IPath | null = null;
    
        let lastRecalculateTick = 0;
    
        const calculatePath = () => {
            const baritone = BaritoneAPI.getProvider().getPrimaryBaritone();
    
            // Get current player position
            const playerPos = baritone.getPlayerContext().playerFeet();
            const start = new BetterBlockPos(playerPos.getX(), playerPos.getY(), playerPos.getZ());
    
            // Create calculation context for threaded use
            const context = new CalculationContext(baritone, true);
    
            // Create favoring (empty favoring for no preferences)
            const favoring = new Favoring(baritone.getPlayerContext(), previousPath as unknown as IPath, context);
    
            // Create goal using settings
            const goal = new GoalXZ(mod.settings.goalX.get() as unknown as number, mod.settings.goalZ.get() as unknown as number);
    
            // Construct AStarPathFinder directly
            const pathfinder = new AStarPathFinder(
                start,           // realStart
                start.getX(),    // startX
                start.getY(),    // startY
                start.getZ(),    // startZ
                goal,            // goal
                favoring,        // favoring
                context          // context
            );
    
            // @ts-expect-error
            UnsafeThread.run(() => {
                const result = pathfinder.calculate(Primitives.long(2000), Primitives.long(5000));
    
                // Handle result
                if (result.getType() != PathCalculationResult$Type.CANCELLATION) {
                    const path = result.getPath().get();
                    console.log("Path found! Length: " + path.length());
                    mc.execute(() => {
                        viz.addVisualization({
                            lineData: {
                                positions: path.positions().map((pos) => new Vec3d(pos.x + .5, pos.y, pos.z + .5)),
    
                            },
                            durationTicks: 20 * 60,
                        });
                        previousPath = path;
                    });
                    // Use the path as needed - you now have direct access without execution
                } else {
                    console.log("Path calculation failed: " + result.getType().toString());
                }
            });
        };
    
        mod.on("enable", () => {
            viz.clearAllVisualizations();
            lastRecalculateTick = 0; // Reset on enable
            calculatePath(); // Initial calculation
        });
    
        mod.on("gametick", () => {
            if (mc.player && mc.world && (mc.player.age - lastRecalculateTick) >= (mod.settings.recalculateInterval.get() as unknown as number)) {
                calculatePath();
                lastRecalculateTick = mc.player.age;
            }
        });
    });
    
    export { }
    

    vlcsnap-2025-08-02-23h41m20s672.png

    Scripts

  • [Guide] Working with Baritone API
    C commandblock2

    it probably does have a AStarPathFinder just for this, but it's gonna be tested if this is really going to work.

    image.png

    Scripts

  • [Guide] Working with Baritone API
    C commandblock2

    7cd8d800-c82a-46d9-9471-dcab0068a3ad-image.png

    ts version (npm package subject to change in the near future once a proper name is found)

    import { BaritoneAPI } from "jvm-types/baritone/api/BaritoneAPI"
    import { GoalXZ } from "jvm-types/baritone/api/pathing/goals/GoalXZ"
    
    const script = registerScript.apply({
        name: "baritone-api-example",
        version: "1.0.0",
        authors: ["commandblock2"]
    });
    
    script.registerModule({
        name: "baritone-api-example",
        description: "Baritone example module",
        category: "Client",
    
    }, (mod) => {
        mod.on("enable", () => {
            BaritoneAPI.getSettings().allowSprint.value = true;
            BaritoneAPI.getSettings().primaryTimeoutMS.value = Primitives.long(2000);
            const baritone = BaritoneAPI.getProvider().getPrimaryBaritone();
            baritone.getCustomGoalProcess().setGoalAndPath(new GoalXZ(100, 100))
        })
    })
    
    export { }
    

    js version, but slightly changed from the compiled one (imports to Java.type), probably should work but never tested.
    Edit: The directly compiled version works on my custom branch. But I was kinda disappointed for baritone not documenting if they provide access to their path finding engine without path execution, if any one knows, please leave a comment.

    const BaritoneAPI_1 = Java.type("baritone.api.BaritoneAPI");
    const GoalXZ_1 = Java.type("baritone.api.pathing.goals.GoalXZ");
    const script = registerScript.apply({
        name: "baritone-api-example",
        version: "1.0.0",
        authors: ["commandblock2"]
    });
    script.registerModule({
        name: "baritone-api-example",
        description: "Baritone example module",
        category: "Client",
    }, (mod) => {
        mod.on("enable", () => {
            BaritoneAPI_1.BaritoneAPI.getSettings().allowSprint.value = true;
            BaritoneAPI_1.BaritoneAPI.getSettings().primaryTimeoutMS.value = Primitives.long(2000);
            const baritone = BaritoneAPI_1.BaritoneAPI.getProvider().getPrimaryBaritone();
            baritone.getCustomGoalProcess().setGoalAndPath(new GoalXZ_1.GoalXZ(100, 100));
        });
    });
    
    Scripts

  • What do I need to know to write scripts for liquid bounce in java script
    C commandblock2

    @dj It actually makes much more sense if they knew about the legacy script api because it had more examples and exists longer. ScriptApi has not been a static and unified thing.
    I was recently working on writing typescript for scriptapi (would probably still take a bit of time to get the changes into master branch), and I made the following prompt for roo code for my specific setup. And it turned out to be better than I thought.

          You are Roo, a highly skilled software engineer with extensive knowledge in many programming languages, frameworks, design patterns, and best practices.
    
          You are working with a project with the runtime environment of Liquidbounce Next Generation script api (graaljs on jvm) with typescript support. You may assume that classes use the yarn mapping on the latest minecraft protocol.
    
          When you are not confident about if a api exists in current api, you may look up the type information at `node_modules/jvm-types/`.  eg. `node_modules/jvm-types/types/net/minecraft/client/MinecraftClient.d.ts` contains the definition for `export class MinecraftClient extends ReentrantThreadExecutor<() => void> implements WindowEventHandler, MinecraftClientAccessor {` and `node_modules/jvm-types/types/net/ccbluex/liquidbounce/utils/movement/MovementUtilsKt.d.ts` contains `export class MovementUtilsKt extends Object {`
          The manually maintained augmentations can be found at `node_modules/jvm-types/augmentations/ScriptModule.augmentation.d.ts`  (with all events definined in LiquidBounce avaliable). Before you are going to use a event,  view this file to make sure you are using the correct event.
          If no existing script examples are given, use `src/complete.ts` to understand the script api.
    
          You will use `Outter$innver` syntax to access inner classes.
    
          You will use `import` instead of `Java.type` for imports from JVM, as the custom `require`/`import` implementation will be redirected to the graaljs's `Java.type`, direct useage of `Java.type` will loose all type information.
    
          Seeing errors like the following may suggest that the generated TypeScript definition has some problems instead of your work does. When seeing those errors, you will consider if they are errors made by the definition generator and ignore them if appropriate.
          ```
          Conversion of type 'LivingEntity' to type 'Entity' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
            Types of property 'getBoundingBox' are incompatible.
              Type '(pose: EntityPose) => Box' is not comparable to type '() => Box'.
                Target signature provides too few arguments. Expected 1 or more, but got 0.
          ```
    

    btw, gemini 2.5 flash is definitely a great model of choice. It is significantly cheaper/faster than sonnet and is good enough to write scripts, and I almost couldn't believe how powerful it is given it's price.

    Requests

  • What do I need to know to write scripts for liquid bounce in java script
    C commandblock2

    @dj You are probably right about the ChatGPT thing, I personally have never used the ChatGPT in website for anything related. My model of choice is usually sonnet, used with continue.dev or roo code. You do need to remind them that they are writing graaljs and needs to be aware of how it works. They may also sometimes give wrong/outdated Minecraft api reference to the Class/Function definitions.

    Requests

  • What do I need to know to write scripts for liquid bounce in java script
    C commandblock2

    It can be quite difficult to write script if you are new to programming. https://liquidbounce.net/docs/script-api/installation this is the official docs for writing scripts, and gpt(or generally all frontier models) are your friend you can just ask those however you want. But note that current script api is not perfect and neither is gpt's answer, the only thing you could to is to try write and test, and also see the debug session. If you have difficulties writing a specific script you can just ask help in this forum(I prefer this one though) or on discord.

    Requests

  • Java Script Api
    C commandblock2

    Yes the currently script API can be sometimes very annoying to work with, like the calling a api that accepts a float with a number in js, etc. and the error usually is not very straight forward and needs a lot of experience to understand what's going on. we are still trying to improve it. At least you have https://liquidbounce.net/docs/script-api/debugging now, although you cannot create any named variable in the console. btw the docs looks much better than before.

    Requests

  • Java Script Api
    C commandblock2

    Just write a mod and put the LiquidBounce as a dependency if you need to use kotlin/java. The only limitations for the script api is that actually you cannot use mixin. Usually there are ways to workaround whatever you are trying to do, but sometimes there are indeed something wrong. typescript support and partial npm ecosystem might be supported soon™.

    Requests

  • I hope to fix the autoblock loophole issue in LiquidBounce.
    C commandblock2

    Hard to believe that's not a GPT written one but probably won't be able to fix what ever u say unless you give more information.

    By consistently you mean how much? Which server/anti cheat combination and what config are you using? There are a lot of configurable autoblock options in killaura. What client(s) are you refering as

    well-known hacked clients that exploit this flaw

    Requests

  • [GPLv3] transaction.js
    C commandblock2

    transactions.zip Also looking forward to our marketplace, I do know that some development happened on the branch recently, hope to see it soon.

    Scripts

  • [Guide] Typescript definition for Minecraft and LiquidBounce
    C commandblock2

    Update for LiquidBounce v0.29.0:
    What's new:

    • refined disclaimer in README.md
    • localStorage in definition (no java.utils class definition yet)
    • multiChoose in manually maintained patch
    Scripts

  • [GPLv3] transaction.js
    C commandblock2

    it was kinda weird, I never see any value starting maybe with -32768 or around, it's always that giant number, is it VFP or just everyone's using the same ac? Btw I even see some server like sending 300ish transactions per second and wtf is that.

    Scripts

  • Help with setting visibility
    C commandblock2

    By reading your post again I think I need to use ChoiceConfigurable. And I think that's definitely possible.

    ScriptAPI

  • Help with setting visibility
    C commandblock2

    Also I am not sure about if we have to pass a object that implements all those functions to Java.extend(). But I think that's it for graaljs's type gymnastics, if you think this is necessary please open a issue at github. Ah just found that I forgot to use the ReflectionUtils xD.

    ScriptAPI

  • Help with setting visibility
    C commandblock2

    @Soulplexis It's done. Although not supposed to be implemented this way but it can be.

    image.png

    
    
    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 ToggleableConfigurable_1 = __require("@minecraft-yarn-definitions/types/net/ccbluex/liquidbounce/config/types/ToggleableConfigurable");
    /* 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: "example-script-api-hacking",
        version: "1.0.0",
        authors: ["commandblock2"]
    });
    script.registerModule({
        name: "example-typescript-module-script-api-hacking",
        description: "Ths is an minimal example module generated in ts but with a setting that's not supposed to be here",
        category: "Client",
    }, (mod) => {
        // Assuming you're in a JavaScript environment that supports Java.extend (like Nashorn or GraalVM)
        // @ts-expect-error
        const MyToggleableConfig = Java.extend(ToggleableConfigurable_1.ToggleableConfigurable, {
            // Implement abstract methods from ToggleableConfigurable and its parent classes
            // Required method implementations from EventListener interface
            parent: function () {
                return this.parent; // Return the parent passed in constructor
            },
            children: function () {
                return []; // Return an array of child event listeners if any
            },
            unregister: function () {
                // Implementation for unregistering this event listener
            },
            // You can also override other methods like:
            enable: function () {
                // Custom enable logic
                // @ts-expect-error
                Java.super(this).enable(); // Call the parent method if needed
            },
            disable: function () {
                // Custom disable logic
                // @ts-expect-error
                Java.super(this).disable(); // Call the parent method if needed
            }
        });
        // Create an instance with required constructor parameters
        // constructor(parent: EventListener | null, name: string, enabled: boolean, aliases: string[])
        const myConfig = new MyToggleableConfig(mod, "MyConfig", true, ["alias1", "alias2"]);
        const testBoolean = myConfig.boolean("testBoolean", false);
        _embedded_1.Client.displayChatMessage(testBoolean.toString());
        // @ts-expect-error
        const field = mod.class.getDeclaredField("_values");
        field.setAccessible(true);
        const valuesMap = field.get(mod);
        // @ts-expect-error
        valuesMap.put("MyConfig", mod.value(myConfig));
        mod.on("enable", () => {
            _embedded_1.Client.displayChatMessage(`Hi, ${_embedded_1.mc.player}`);
        });
    });
    

    // 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 { Class } from "@minecraft-yarn-definitions/types/java/lang/Class";
    import { ToggleableConfigurable } from "@minecraft-yarn-definitions/types/net/ccbluex/liquidbounce/config/types/ToggleableConfigurable";
    import { ScriptModule } from "@minecraft-yarn-definitions/types/net/ccbluex/liquidbounce/script/bindings/features/ScriptModule";
    /* 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: "example-script-api-hacking",
        version: "1.0.0",
        authors: ["commandblock2"]
    });
    
    script.registerModule({
        name: "example-typescript-module-script-api-hacking",
        description: "Ths is an minimal example module generated in ts but with a setting that's not supposed to be here",
        category: "Client",
    
    }, (mod) => {
    
        // Assuming you're in a JavaScript environment that supports Java.extend (like Nashorn or GraalVM)
        // @ts-expect-error
        const MyToggleableConfig = Java.extend(ToggleableConfigurable, {
            // Implement abstract methods from ToggleableConfigurable and its parent classes
    
            // Required method implementations from EventListener interface
            parent: function () {
                return this.parent; // Return the parent passed in constructor
            },
    
            children: function () {
                return []; // Return an array of child event listeners if any
            },
    
            unregister: function () {
                // Implementation for unregistering this event listener
            },
    
            // You can also override other methods like:
            enable: function () {
                // Custom enable logic
                // @ts-expect-error
                Java.super(this).enable(); // Call the parent method if needed
            },
    
            disable: function () {
                // Custom disable logic
                // @ts-expect-error
                Java.super(this).disable(); // Call the parent method if needed
            }
        });
    
        // Create an instance with required constructor parameters
        // constructor(parent: EventListener | null, name: string, enabled: boolean, aliases: string[])
        const myConfig = new MyToggleableConfig(mod, "MyConfig", true, ["alias1", "alias2"]);
        const testBoolean = myConfig.boolean("testBoolean", false);
        Client.displayChatMessage(testBoolean.toString());
    
        // @ts-expect-error
        const field = (mod.class as unknown as Class<ScriptModule>).getDeclaredField("_values");
        field.setAccessible(true);
        const valuesMap = field.get(mod);
        // @ts-expect-error
        valuesMap.put("MyConfig", mod.value(myConfig));
    
        mod.on("enable", () => {
            Client.displayChatMessage(`Hi, ${mc.player}`)
        })
    })
    
    ScriptAPI

  • Help with setting visibility
    C commandblock2

    This might be possible actually I think, if you put it in the lambda near mod.on that might even work, will try later

    ScriptAPI

  • Help with setting visibility
    C commandblock2

    But on another thought, we could extend the value our self maybe and make the ScriptToggleableConfigurable our self within script? Maybe we could think about that.

    Also a bit of shameless self advertising, maybe try this typescript definition generator, could be a bit hard to setup and generate the definition yet.

    ScriptAPI

  • Help with setting visibility
    C commandblock2

    Afaik, it is not possible without significant change. ScriptSetting for now does not provide the togglableConfigurable value function yet. That's all they have right now.

    export class ScriptSetting extends Object {
        static INSTANCE: ScriptSetting;
        boolean(value: BooleanValue): Value<boolean>;
        choose(value: ChooseValue): ChooseListValue<NamedChoice>;
        float(value: FloatValue): RangedValue<number>;
        floatRange(value: FloatRangeValue): RangedValue<ClosedFloatingPointRange<number>>;
        int(value: IntValue): RangedValue<number>;
        intRange(value: IntRangeValue): RangedValue<number[]>;
        key(value: KeyValue): Value<InputUtil$Key>;    text(value: TextView): Value<string>;
        textArray(value: TextArrayValue): Value<string[]>;
    }
    

    even if you would construct a ToggleableConfigurable instance with the graal anonymous class/object syntax, the constructor(parent: EventListener | null, name: string, enabled: boolean, aliases: string[]) would require a EventListener, which is supplied by this in normal kotlin non-script modules. And the this in your script api corresponds to the mod in }, (mod) => { in your last line given, which by design, is not possible to acquire.
    However I do believe we could make a pr to the script api to make this possible, but I am not sure if a script is supposed to have such complex configuration.

    ScriptAPI

  • [GPLv3] transaction.js
    C commandblock2
    
    
    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 CommonPingS2CPacket_1 = __require("@minecraft-yarn-definitions/types/net/minecraft/network/packet/s2c/common/CommonPingS2CPacket");
    // Global variables for storing transaction data
    const transactionQueue = [];
    const MAX_QUEUE_SIZE = 100;
    // Global statistics
    let totalTransactions = 0;
    let lastReportTime = 0;
    const REPORT_INTERVAL = 5000; // Report every 5 seconds
    const PARAMETER_FREQUENCY = {};
    const script = _embedded_1.registerScript.apply({
        name: "transactions",
        version: "1.0.0",
        authors: ["commandblock2"]
    });
    script.registerModule({
        name: "transactions",
        description: "Logs transactions packets for anticheat detection",
        category: "Client",
        settings: {
            reportInterval: _embedded_1.Setting.int({
                name: "ReportInterval",
                default: 5,
                range: [1, 60],
                suffix: "seconds"
            }),
            showParameters: _embedded_1.Setting.boolean({
                name: "ShowParameters",
                default: true
            }),
            logToChat: _embedded_1.Setting.boolean({
                name: "LogToChat",
                default: true
            }),
            verbose: _embedded_1.Setting.boolean({
                name: "Verbose",
                default: false
            })
        }
    }, (mod) => {
        mod.on("enable", () => {
            // Reset statistics
            totalTransactions = 0;
            lastReportTime = Date.now();
            // Clear the queue
            transactionQueue.length = 0;
            // Reset parameter frequency
            for (const key in PARAMETER_FREQUENCY) {
                delete PARAMETER_FREQUENCY[key];
            }
            _embedded_1.Client.displayChatMessage("§a[Transactions] Monitoring started. Use .txstats to see statistics.");
        });
        mod.on("disable", () => {
            _embedded_1.Client.displayChatMessage("§c[Transactions] Monitoring stopped.");
        });
        mod.on("packet", (event) => {
            if (event.packet instanceof CommonPingS2CPacket_1.CommonPingS2CPacket) {
                const parameter = event.packet.getParameter();
                const timestamp = Date.now();
                if (mod.settings.verbose.getValue()) {
                    _embedded_1.Client.displayChatMessage(`§a[Transactions] Received parameter: ${parameter}`);
                }
                // Add to queue
                transactionQueue.push({ timestamp, parameter });
                // Keep queue size limited
                if (transactionQueue.length > MAX_QUEUE_SIZE) {
                    transactionQueue.shift();
                }
                // Update statistics
                totalTransactions++;
                PARAMETER_FREQUENCY[parameter] = (PARAMETER_FREQUENCY[parameter] || 0) + 1;
                // Check if it's time to report
                const currentTime = Date.now();
                const reportIntervalMs = mod.settings.reportInterval.getValue() * 1000;
                if (mod.settings.logToChat.getValue() && currentTime - lastReportTime >= reportIntervalMs) {
                    reportStatistics();
                    lastReportTime = currentTime;
                }
            }
        });
        // Function to report statistics
        function reportStatistics() {
            if (transactionQueue.length === 0) {
                return;
            }
            const packetsPerSecond = calculatePacketsPerSecond();
            _embedded_1.Client.displayChatMessage(`§e[Transactions] §fRate: §a${packetsPerSecond.toFixed(2)} §fpackets/sec | Total: §a${totalTransactions}`);
            if (mod.settings.showParameters.getValue()) {
                const topParameters = getTopParameters(8);
                if (topParameters.length > 0) {
                    _embedded_1.Client.displayChatMessage(`§e[Transactions] §fTop parameters: ${topParameters.map(p => `§a${p.parameter}§f(${p.count})`).join(", ")}`);
                }
            }
        }
        // Calculate packets per second based on queue data
        function calculatePacketsPerSecond() {
            if (transactionQueue.length < 2) {
                return 0;
            }
            const oldestTimestamp = transactionQueue[0].timestamp;
            const newestTimestamp = transactionQueue[transactionQueue.length - 1].timestamp;
            const timeSpanSeconds = (newestTimestamp - oldestTimestamp) / 1000;
            return timeSpanSeconds > 0 ? transactionQueue.length / timeSpanSeconds : 0;
        }
        // Get top N most frequent parameters
        function getTopParameters(n) {
            return Object.entries(PARAMETER_FREQUENCY)
                .map(([parameter, count]) => ({ parameter: parseInt(parameter), count }))
                .sort((a, b) => b.count - a.count)
                .slice(0, n);
        }
    });
    // Register a command to view transaction statistics
    script.registerCommand({
        name: "txstats",
        aliases: ["transactionstats"],
        parameters: [{
                name: "action",
                required: false,
                validate: _embedded_1.ParameterValidator.string
            }],
        onExecute(action) {
            if (action === "clear") {
                // Clear statistics
                totalTransactions = 0;
                transactionQueue.length = 0;
                for (const key in PARAMETER_FREQUENCY) {
                    delete PARAMETER_FREQUENCY[key];
                }
                _embedded_1.Client.displayChatMessage("§a[Transactions] Statistics cleared.");
                return;
            }
            if (transactionQueue.length === 0) {
                _embedded_1.Client.displayChatMessage("§c[Transactions] No transaction data available.");
                return;
            }
            // Display basic statistics
            const packetsPerSecond = calculatePacketsPerSecond();
            _embedded_1.Client.displayChatMessage(`§e[Transactions] §fStatistics:`);
            _embedded_1.Client.displayChatMessage(`§fTotal transactions: §a${totalTransactions}`);
            _embedded_1.Client.displayChatMessage(`§fCurrent rate: §a${packetsPerSecond.toFixed(2)} §fpackets/sec`);
            // Display queue info
            _embedded_1.Client.displayChatMessage(`§fQueue size: §a${transactionQueue.length}/${MAX_QUEUE_SIZE}`);
            // Display top 5 parameters
            const topParameters = getTopParameters(5);
            if (topParameters.length > 0) {
                _embedded_1.Client.displayChatMessage(`§fTop 5 parameters:`);
                topParameters.forEach((p, index) => {
                    _embedded_1.Client.displayChatMessage(`§f  ${index + 1}. Parameter §a${p.parameter}§f: ${p.count} occurrences (${(p.count / totalTransactions * 100).toFixed(1)}%)`);
                });
            }
            // Display time range
            if (transactionQueue.length >= 2) {
                const oldestTimestamp = transactionQueue[0].timestamp;
                const newestTimestamp = transactionQueue[transactionQueue.length - 1].timestamp;
                const timeSpanSeconds = (newestTimestamp - oldestTimestamp) / 1000;
                _embedded_1.Client.displayChatMessage(`§fTime span: §a${timeSpanSeconds.toFixed(2)} §fseconds`);
            }
        }
    });
    // Helper functions for command execution
    function calculatePacketsPerSecond() {
        if (transactionQueue.length < 2) {
            return 0;
        }
        const oldestTimestamp = transactionQueue[0].timestamp;
        const newestTimestamp = transactionQueue[transactionQueue.length - 1].timestamp;
        const timeSpanSeconds = (newestTimestamp - oldestTimestamp) / 1000;
        return timeSpanSeconds > 0 ? transactionQueue.length / timeSpanSeconds : 0;
    }
    function getTopParameters(n) {
        return Object.entries(PARAMETER_FREQUENCY)
            .map(([parameter, count]) => ({ parameter: parseInt(parameter), count }))
            .sort((a, b) => b.count - a.count)
            .slice(0, n);
    }
    

    Note that LiquidBounce cannot run typescript, at least as of now.

    // 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 { CommonPingS2CPacket } from "@minecraft-yarn-definitions/types/net/minecraft/network/packet/s2c/common/CommonPingS2CPacket";
    /* eslint-enable unused-imports/no-unused-imports */
    // DO NOT TOUCH ANYTHING ABOVE THIS LINE
    
    // Define the TransactionEntry interface for storing packet data
    interface TransactionEntry {
        timestamp: number;
        parameter: number;
    }
    
    // Global variables for storing transaction data
    const transactionQueue: TransactionEntry[] = [];
    const MAX_QUEUE_SIZE = 100;
    
    // Global statistics
    let totalTransactions = 0;
    let lastReportTime = 0;
    const PARAMETER_FREQUENCY: { [key: number]: number } = {};
    
    const script = registerScript.apply({
        name: "transactions",
        version: "1.0.0",
        authors: ["commandblock2"]
    });
    
    script.registerModule({
        name: "transactions",
        description: "Logs transactions packets for anticheat detection",
        category: "Client",
        settings: {
            reportInterval: Setting.int({
                name: "ReportInterval",
                default: 5,
                range: [1, 60],
                suffix: "seconds"
            }),
            showParameters: Setting.boolean({
                name: "ShowParameters",
                default: true
            }),
            logToChat: Setting.boolean({
                name: "LogToChat",
                default: true
            }),
            verbose: Setting.boolean({
                name: "Verbose",
                default: false
            })
        }
    }, (mod) => {
        mod.on("enable", () => {
            // Reset statistics
            totalTransactions = 0;
            lastReportTime = Date.now();
            
            // Clear the queue
            transactionQueue.length = 0;
            
            // Reset parameter frequency
            for (const key in PARAMETER_FREQUENCY) {
                delete PARAMETER_FREQUENCY[key];
            }
            
            Client.displayChatMessage("§a[Transactions] Monitoring started. Use .txstats to see statistics.");
        });
    
        mod.on("disable", () => {
            Client.displayChatMessage("§c[Transactions] Monitoring stopped.");
        });
    
        mod.on("packet", (event) => {
            if (event.packet instanceof CommonPingS2CPacket) {
                const parameter = event.packet.getParameter();
                const timestamp = Date.now();
    
                if (mod.settings.verbose.getValue()) {
                    Client.displayChatMessage(`§a[Transactions] Received parameter: ${parameter}`);
                }
                
                // Add to queue
                transactionQueue.push({ timestamp, parameter });
                
                // Keep queue size limited
                if (transactionQueue.length > MAX_QUEUE_SIZE) {
                    transactionQueue.shift();
                }
                
                // Update statistics
                totalTransactions++;
                PARAMETER_FREQUENCY[parameter] = (PARAMETER_FREQUENCY[parameter] || 0) + 1;
                
                // Check if it's time to report
                const currentTime = Date.now();
                const reportIntervalMs = mod.settings.reportInterval.getValue() * 1000;
                
                if (mod.settings.logToChat.getValue() && currentTime - lastReportTime >= reportIntervalMs) {
                    reportStatistics();
                    lastReportTime = currentTime;
                }
            }
        });
        
        // Function to report statistics
        function reportStatistics() {
            if (transactionQueue.length === 0) {
                return;
            }
            
            const packetsPerSecond = calculatePacketsPerSecond();
            Client.displayChatMessage(`§e[Transactions] §fRate: §a${packetsPerSecond.toFixed(2)} §fpackets/sec | Total: §a${totalTransactions}`);
            
            if (mod.settings.showParameters.getValue()) {
                const topParameters = getTopParameters(8);
                if (topParameters.length > 0) {
                    Client.displayChatMessage(`§e[Transactions] §fTop parameters: ${topParameters.map(p => `§a${p.parameter}§f(${p.count})`).join(", ")}`);
                }
            }
        }
        
        // Calculate packets per second based on queue data
        function calculatePacketsPerSecond(): number {
            if (transactionQueue.length < 2) {
                return 0;
            }
            
            const oldestTimestamp = transactionQueue[0].timestamp;
            const newestTimestamp = transactionQueue[transactionQueue.length - 1].timestamp;
            const timeSpanSeconds = (newestTimestamp - oldestTimestamp) / 1000;
            
            return timeSpanSeconds > 0 ? transactionQueue.length / timeSpanSeconds : 0;
        }
        
        // Get top N most frequent parameters
        function getTopParameters(n: number): { parameter: number, count: number }[] {
            return Object.entries(PARAMETER_FREQUENCY)
                .map(([parameter, count]) => ({ parameter: parseInt(parameter), count }))
                .sort((a, b) => b.count - a.count)
                .slice(0, n);
        }
    });
    
    // Register a command to view transaction statistics
    script.registerCommand({
        name: "txstats",
        aliases: ["transactionstats"],
        parameters: [{
            name: "action",
            required: false,
            validate: ParameterValidator.string
        }],
        onExecute(action: string) {
            if (action === "clear") {
                // Clear statistics
                totalTransactions = 0;
                transactionQueue.length = 0;
                for (const key in PARAMETER_FREQUENCY) {
                    delete PARAMETER_FREQUENCY[key];
                }
                Client.displayChatMessage("§a[Transactions] Statistics cleared.");
                return;
            }
            
            if (transactionQueue.length === 0) {
                Client.displayChatMessage("§c[Transactions] No transaction data available.");
                return;
            }
            
            // Display basic statistics
            const packetsPerSecond = calculatePacketsPerSecond();
            Client.displayChatMessage(`§e[Transactions] §fStatistics:`);
            Client.displayChatMessage(`§fTotal transactions: §a${totalTransactions}`);
            Client.displayChatMessage(`§fCurrent rate: §a${packetsPerSecond.toFixed(2)} §fpackets/sec`);
            
            // Display queue info
            Client.displayChatMessage(`§fQueue size: §a${transactionQueue.length}/${MAX_QUEUE_SIZE}`);
            
            // Display top 5 parameters
            const topParameters = getTopParameters(5);
            if (topParameters.length > 0) {
                Client.displayChatMessage(`§fTop 5 parameters:`);
                topParameters.forEach((p, index) => {
                    Client.displayChatMessage(`§f  ${index + 1}. Parameter §a${p.parameter}§f: ${p.count} occurrences (${(p.count / totalTransactions * 100).toFixed(1)}%)`);
                });
            }
            
            // Display time range
            if (transactionQueue.length >= 2) {
                const oldestTimestamp = transactionQueue[0].timestamp;
                const newestTimestamp = transactionQueue[transactionQueue.length - 1].timestamp;
                const timeSpanSeconds = (newestTimestamp - oldestTimestamp) / 1000;
                Client.displayChatMessage(`§fTime span: §a${timeSpanSeconds.toFixed(2)} §fseconds`);
            }
        }
    });
    
    // Helper functions for command execution
    function calculatePacketsPerSecond(): number {
        if (transactionQueue.length < 2) {
            return 0;
        }
        
        const oldestTimestamp = transactionQueue[0].timestamp;
        const newestTimestamp = transactionQueue[transactionQueue.length - 1].timestamp;
        const timeSpanSeconds = (newestTimestamp - oldestTimestamp) / 1000;
        
        return timeSpanSeconds > 0 ? transactionQueue.length / timeSpanSeconds : 0;
    }
    
    function getTopParameters(n: number): { parameter: number, count: number }[] {
        return Object.entries(PARAMETER_FREQUENCY)
            .map(([parameter, count]) => ({ parameter: parseInt(parameter), count }))
            .sort((a, b) => b.count - a.count)
            .slice(0, n);
    }
    
    
    Scripts
  • Login

  • Login or register to search.
  • First post
    Last post
0
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups