PrismarineJS / PrismarineJS/node-minecraft-protocol
proxy example: anticheat flags for actions that wouldn't get you kicked on the first time, before recreating the target client.
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 1.4k
- Forks
- 290
- Avg merge
- 4d 8h
- Merged PRs (30d)
- 7
Description
[ ] The FAQ doesn't contain a resolution to my issue
Versions
- minecraft-protocol: 1.51.0
- node: v22.11.0
Detailed description of a problem
A clear and concise description of what the problem is.
Current code
const mc = require('minecraft-protocol');
const states = mc.states;
var Socks = require("socks5-client");
const { exec } = require('child_process');
function printHelpAndExit(exitCode) {
console.log('usage: node proxy.js <target_srv> <version>');
process.exit(exitCode);
}
if (process.argv.length < 4) {
console.log('Too few arguments!');
printHelpAndExit(1);
}
process.argv.forEach(function (val) {
if (val === '-h') {
printHelpAndExit(0);
}
});
const args = process.argv.slice(2);
let host;
let port = 25565;
let version;
(function () {
let i = 0;
for (i = 0; i < args.length; i++) {
const option = args[i];
if (!/^-/.test(option)) break;
i++;
}
if (!(i + 2 <= args.length && args.length <= i + 4)) printHelpAndExit(1);
host = args[i++];
version = args[i++];
})();
if (host.indexOf(':') !== -1) {
port = host.substring(host.indexOf(':') + 1);
host = host.substring(0, host.indexOf(':'));
}
const srv = mc.createServer({
'online-mode': false,
port: 25566,
keepAlive: false,
version
});
// Array to store the connected clients
let clients = [];
let targetClients = []; // Track target clients
srv.on('login', function (client) {
const addr = client.socket.remoteAddress;
console.log('Incoming connection', '(' + addr + ')');
// Add the new client to the clients array
clients.push(client);
let endedClient = false;
let endedTargetClient = false;
let targetClient;
client.on('end', function () {
endedClient = true;
console.log('Connection closed by client', '(' + addr + ')');
// Remove client from the array when they disconnect
clients = clients.filter(c => c !== client);
if (!endedTargetClient) {
targetClient.end('End');
}
});
client.on('error', function (err) {
endedClient = false;
console.log('Connection error by client', '(' + addr + ')');
console.log(err.stack);
});
function generateRandomUsername() {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let username = '';
const length = 12;
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * characters.length);
username += characters[randomIndex];
}
return username;
}
// Function to set up the target client
function setupTargetClient() {
// Close all previously connected target clients
targetClients.forEach((tc) => {
tc.end('End');
});
// Create new target client
targetClient = mc.createClient({
host: host,
port: port,
username: generateRandomUsername(),
keepAlive: false,
version: '1.8.9'
});
// Store the new target client
targetClients = [targetClient];
// Forwarding packets between client and target server
client.on('packet', function (data, meta) {
if (targetClient.state === states.PLAY && meta.state === states.PLAY) {
// Check if the packet is not a kick packet
if (meta.name === 'kick_disconnect') {
// Do nothing to prevent the kick packet from being processed
return;
}
targetClient.write(meta.name, data);
}
});
targetClient.on('packet', function (data, meta) {
if (meta.state === states.PLAY && client.state === states.PLAY) {
// Check if the packet is not a kick packet
if (meta.name === 'kick_disconnect') {
// Do nothing to prevent the kick packet from being processed
return;
}
client.write(meta.name, data);
if (meta.name === 'set_compression') {
client.compressionThreshold = data.threshold;
}
}
});
let hasRegistered = false;
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
targetClient.on('chat', async (message) => {
if (String(message).includes('register') || hasRegistered) {
return;
}
await delay(2000);
targetClient.chat('/register 123123 123123');
hasRegistered = true;
});
targetClient.on('end', function () {
endedTargetClient = true;
console.log('Target client disconnected from server', '(' + addr + ')');
// // Run the 'resetip.bat' command first
// exec('resetip.bat', (error, stdout, stderr) => {
// if (error) {
// console.error(`exec error: ${error}`);
// return;
// }
// if (stderr) {
// console.error(`stderr: ${stderr}`);
// return;
// }
// console.log(`stdout: ${stdout}`);
// });
// -- deleted the ip resetter temporarily (in the video it isn't used)
// delay(3350).then(() => {
setupTargetClient(); // Reconnect to the target server
console.log('Reconnected with new target client');
// });
});
}
// Call the function initially
setupTargetClient();
});
Expected behavior
After reconnecting from a kick, everything should work normally, and I shouldn't be kicked, in the moment where I got kicked in the video.
Additional context
I am trying to make a code that would automatically reconnect when I get kicked from a server, also without kicking me from the localhost server, I am playing on.
What happens:
https://streamable.com/ufbfu5 (uploading here, since the file is too big).
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the behavior with the provided proxy code on minecraft-protocol 1.51.0 and Node v22.11.0, then trace the packet forwarding and target-client reconnection paths shown in the example. The issue does not name a library file or test; completion would require identifying the cause of the anticheat kick and demonstrating that reconnecting no longer triggers it.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 28/100