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!
The autoblock bypass issue in LiquidBounce Nextgen has been a major concern within the Chinese user community. We strongly urge the development team to prioritize fixing this critical Block problem, as it severely compromises the PvP experience. Currently, many players consistently lose battles on PvP servers when facing opponents using well-known hacked clients that exploit this flaw.
Successfully resolving this Block issue would be a significant breakthrough for the project - especially considering this problem has persisted since the legacy versions and remained unfixed even before development was discontinued."
I am trying to run Legacy so I can play 1.8.9 on my macOS, on Mac15.0. Nextgen works fine but when Legacy has been providing me with the below error:
libc++abi: terminating due to uncaught exception of type NSException
An error occured:
Process exited with non-zero exit code: 7900.
Any help would be amazing.
ScriptAPI v1 compatibility
This script re-introduces the compatibility layer for ScriptAPI v1, which was removed in LiquidBounce b83, while adding a few tweaks.
Only works on LiquidBounce legacy, NOT LiquidBounce nextgen.
NEVER contact LiquidBounce staff about errors while using legacy scripts!
For help and support, contact me on Discord: ayyyax.
For updates to script, visit my repository.
How to install
Download the provided zip file.
Extract it into your LiquidBouce-1.8.9 folder
Insert your favourite legacy scripts in scriptapi-v1/scripts
Warnings
Some scripts will simply not work. If that happens, try and contact me to sort out the issue.
LiquidBounce will take longer to start up while using this script.
I have no idea how to write scripts, so this is really bad, but it kinda works lol
Tested and confirmed working scripts
fancyderp.js by SoulPlexis
autoeat.js by SoulPlexis
DOWNLOAD - NEVER CONTACT LIQUIDBOUNCE STAFF ABOUT ERRORS WHEN USING LEGACY SCRIPTS
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);
}
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
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)!