Important for new members!
All future posts from members with a reputation of less than 1 will be queued for manual review to prevent forum spam. We will review your posts as soon as possible!
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
about 23 hours ago
I truly appreciate that this client has remained free and open-source, which is excellent and has given rise to many forks. However, I wonder if there has been consideration to develop an injectable client? I understand that technical expertise varies, but could we attempt to explore this path?
Take the example of CCBlueX/liquidbounce_lite, which uses DLL injection via Rust. While undoubtedly challenging (potentially taking at least two years to mature), could such an approach eventually become viable? Additionally, would an executable (EXE) based solution be worth exploring as an alternative?
General Discussion
2 days ago
Following repo means
demo
https://github.com/commandblock2/minecraft-LBNG-types.
[image: 1743439569889-9094e21e-c6b5-4f3b-b562-92cd701ba7e3-image-resized.png]
minecraft-LBNG-types
DISCLAIMER: Use this at your own risk!!! This is an unofficial project not endorsed by Mojang or fabric developers. This repo does NOT
contains any generated minecraft type definitions by itself
redistribute the game itself
guarentee the correctness of the generated definition
This repo contains
instruction and scripts for creating typescript definitions
for Minecraft (with mods*)
for LiquidBounce NextGen
for everything inside of the jvm
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) with watch mode
some prompt files to use on LLMs, specifically for claude + continue.dev vscode extension, at .continue/prompts.
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
Instruction (subject to change)
Adjust the order flexibly to your needs.
Generating the typescript definitions
Setup development environment for Liquidbounce NextGen
Clone LBNG, run git checkout 451cb31e9bf093fe07f9b28202bc2471921ea13d (for version 0.29.0 release) and launch with gradle ./gradlew runClient without intellij idea(recommened because of the sheer amount of memory it takes to generate the definition).
Place the LBNG-script/ts-defgen.js in your script folder for LiquidBounce
Build or download the latest released ts-generator jar from github, place it in your script folder as well.
Do a .script reload in your client, this should load the ts-defgen.js
Run the .ts-defgen command
See messages from chat and wait for around a few minute or more or less depending on your setup, this may take a while and also nearly 7GB of additional RAM (other than your intellij idea plus the what Minecraft needs in it's original state, causes OOM for me a lot of times xD).
Now you can find a types-gen folder in your script folder, this contains the generated typescript definitions.
.
├── ts-defgen.js
├── ts-generator-1.1.1.jar
└── types-gen
└── minecraft-yarn-definitions
├── package.json
├── tsconfig.json
└── types
├── ai
├── com
├── _COROUTINE
├── de
├── io
├── it
├── java
├── javax
├── jdk
├── joptsimple
├── kotlin
├── kotlinx
├── net
├── okhttp3
├── okio
├── org
├── oshi
└── sun
├── ... other scripts.js
Writing scripts with TypeScript Support
Run npm install in this directory.
copy the generated folder types-gen to generated-modules folder in the root of your project.
Run the script apply-patch with npm run apply-patches
Run npm install file:./generated-modules/types-gen/minecraft-yarn-definitions/ --no-save, no-save for now, not sure if I should do this.
Open the template.ts file and try start writing your script, you should see TypeScript type hints for all the classes that are available. vscode will automatically generate working imports, but you should not touch the import statement with @embedded namespace.
Run the script compile with npm like step 4 or npm run watch
Corresponding javascript file is generated in the dist directory, you can link this dist directory to your scripts directory in LB.
Contribution and TODOs
If you know how to better organize this project (architecture), please feel free to submit a PR.
If you find errors on generated definitions about Minecraft classes or LiquidBounce classes, please file your tick at ts-generator.
If you find a un-intended behavior in the ts-defgen.js, compile script or manually maintained definitions(TODO), please file an issue here.
License
This project is licensed under the GNU General Public license, see LICENSE for more information.
[image: 1738500020404-vscode-file___vscode-app_opt_vscodium_resources_app_out_vs_code_electron-sandbox_workbench_workbench.html-cropped.png]
Scripts
2 days ago
Please fix the forgegradle problem and support for Scriptapi1 in b74
I'm really bored. Countless scripts can't be used. Countless problems and scripts need to be updated. This is a community, but it doesn't mean we need to work for free. Even if I write a tool that can convert api1 scripts into api2 scripts with one click, there are still a lot of error correction steps. Who doesn't want to use the latest version of liquidbond? But we can't give up our work, so please fix the forgegradle problem and support for Scriptapi1 in b74
Bug Reports
2 days ago
Configs
3 days ago
General Discussion
3 days ago
General
3 days ago
Requests
3 days ago
It appears that FastBreak has in-built NoBreakDelay enabled. Maybe make it an option to toggle it or customise how many ticks before block selector updates to the next block?
You can get away with minor fastbreak usage, but the NoBreakDelay makes it very easy to detect regardless of the block damage parameter.
Another idea could be some sort of “balance” settings that lets you bypass those anticheats that check if you’re breaking blocks faster overall
Suggestions
5 days ago
Suggestions
6 days ago
Suggestions
8 days ago
Suggestions
8 days ago
I was not sure what the FastBreak options meant exactly, but I’m suggesting this anyway.
There seems to be a 5-tick delay when you break a block before your client switches to the next block. It would be nice if there was a module that lets you customise that value, for example between 0-5 ticks (in case anti-cheats detect 0 tick but not 1-2, etc)
Suggestions
8 days ago
Chinese
10 days ago
Hello. I'm currently trying to learn how to use nextgen's scriptAPI. I've created a simple module just to mess around and to learn it. Here is part of the code related to what I'm trying to do:
script.registerModule({
name: "TestFly",
category: "Movement",
description: "Fly module, made for learning purposes.",
settings: {
mode: Setting.choose({
name: "Mode",
choices: ["Vanilla", "Hard", "Airwalk"],
default: "Vanilla"
}),
speed: Setting.float({
name: "Speed",
default: 1.0,
range: [0.1, 5.0],
})
}
}, (mod) => {
I'm trying to make the "Speed" setting only visible when the vanilla mode is selected. Or I'm trying to make the Speed setting be within the mode setting only when Vanilla option is selected. In the default fly module the relevant settings are inside the mode setting and they change depending on which mode of fly is selected. Is this possible to do in nextgen's scriptapi? I couldn't find out how to do it in the documentation.
In short I'm asking how make settings within settings in the scriptapi.
I also want to know if is it possible to add the "Toggle/ hold" setting in the scriptapi? This is the setting next to the bind button on some modules that makes the module only active when holding down the keybind.
ScriptAPI
13 days ago
General
13 days ago
librecraft config that doesnt silent flag that would be decent if has a working timer speed, timer scaffold, tower, at least a 4 block reach (i think it doesnt silent flag until above 4 block reach normally)
liquidbounce legacy alr has a librecraft settting which does bypass but the scaffold is disgusting and slow and silent flags (unnatural placement kick) and the rest of the config randomly silent flags and you get auto banned after like 15 minutes.
Configs
14 days ago
Configs
15 days ago
General
15 days ago
General Discussion
16 days ago
-
-
-
-
General Discussion
A place to talk about anything related to LiquidBounce
-
Suggestions
Think something is missing? Let us know!
-
Bug Reports
Found a bug? Report it here!
-
Chinese
A place for our Chinese community
-
Off-Topic
Talk about anything you like (as long as you follow the rules)!