Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Is there any way to reassign server to a different client, when one gets kicked (without kicking the player on the current server)?] #1357

Closed
xeonise opened this issue Dec 14, 2024 · 2 comments

Comments

@xeonise
Copy link

xeonise commented Dec 14, 2024

const mc = require('minecraft-protocol');
const states = mc.states;
var Socks = require("socks5-client");

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
});

srv.on('login', function (client) {
    const addr = client.socket.remoteAddress;
    console.log('Incoming connection', '(' + addr + ')');

    let endedClient = false;
    let endedTargetClient = false;
    let targetClient;

    client.on('end', function () {
        endedClient = true;
        console.log('Connection closed by client', '(' + addr + ')');
        if (!endedTargetClient) {
            targetClient.end('End');
        }
    });

    client.on('error', function (err) {
        endedClient = true;
        console.log('Connection error by client', '(' + addr + ')');
        console.log(err.stack);
        if (!endedTargetClient) {
            targetClient.end('Error');
        }
    });

    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 setupTargetClient() {
        targetClient = mc.createClient({
            host: host,
            port: port,
            username: generateRandomUsername(),
            keepAlive: false,
            version
        });

        // Forwarding packets between client and target server
        client.on('packet', function (data, meta) {
            if (targetClient.state === states.PLAY && meta.state === states.PLAY) {
                if (!endedTargetClient) {
                    targetClient.write(meta.name, data);
                }
            }
        });

        targetClient.on('packet', function (data, meta) {
            if (meta.state === states.PLAY && client.state === states.PLAY) {
                if (!endedClient) {
                    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 + ')');
            setTimeout(() => {
                setupTargetClient();
                console.log('Reconnected with new target client');
            }, 2000);
        });

        targetClient.on('error', function (err) {
            endedTargetClient = true;
            console.log('Target client connection error', '(' + addr + ')', err);
            console.log(err.stack);
            setTimeout(() => {
                setupTargetClient();
                console.log('Reconnected after error');
            }, 2000);
        });
    }

    setupTargetClient();
});

that's my current code.
what's expected:
what I want to do is, when one client gets kicked, another one will rejoin, and the server will reassign it to all players connected to it right now, but I don't have any success with it.
what happens:
when I get kicked, it reconnects, but than on the client(minecraft 1.8.9) connected to the server that connected I get "downloading terrain".
image
image
than I get readtimeout exception.

@xeonise
Copy link
Author

xeonise commented Dec 14, 2024

Also there are no errors, it's usually just like this:
Target client disconnected from server (::ffff:127.0.0.1)
Reconnected with new target client

@xeonise
Copy link
Author

xeonise commented Dec 14, 2024

nevermind, I fixed it myself

@xeonise xeonise closed this as completed Dec 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant