2017-07-13 08:03:52 -04:00
|
|
|
const mc = require('minecraft-protocol');
|
2015-02-22 17:13:22 -05:00
|
|
|
|
2017-07-13 08:03:52 -04:00
|
|
|
const states = mc.states;
|
2015-03-18 06:58:20 -04:00
|
|
|
function printHelpAndExit(exitCode) {
|
2016-01-06 19:55:20 -05:00
|
|
|
console.log("usage: node proxy.js [<options>...] <target_srv> <version>");
|
2015-05-14 16:08:49 -04:00
|
|
|
console.log("options:");
|
2015-09-23 09:05:52 -04:00
|
|
|
console.log(" --dump name");
|
|
|
|
console.log(" print to stdout messages with the specified name.");
|
2015-05-14 16:08:49 -04:00
|
|
|
console.log(" --dump-all");
|
|
|
|
console.log(" print to stdout all messages, except those specified with -x.");
|
2015-09-23 09:05:52 -04:00
|
|
|
console.log(" -x name");
|
|
|
|
console.log(" do not print messages with this name.");
|
|
|
|
console.log(" name");
|
|
|
|
console.log(" a packet name as defined in protocol.json");
|
2015-05-14 16:08:49 -04:00
|
|
|
console.log("examples:");
|
2016-03-21 10:40:53 -04:00
|
|
|
console.log(" node proxy.js --dump-all -x keep_alive -x update_time -x entity_velocity -x rel_entity_move -x entity_look -x entity_move_look -x entity_teleport -x entity_head_rotation -x position localhost 1.8");
|
2015-05-14 16:08:49 -04:00
|
|
|
console.log(" print all messages except for some of the most prolific.");
|
2016-01-06 19:55:20 -05:00
|
|
|
console.log(" node examples/proxy.js --dump open_window --dump close_window --dump set_slot --dump window_items --dump craft_progress_bar --dump transaction --dump close_window --dump window_click --dump set_creative_slot --dump enchant_item localhost 1.8");
|
2015-05-14 16:08:49 -04:00
|
|
|
console.log(" print messages relating to inventory management.");
|
2015-03-18 06:58:20 -04:00
|
|
|
|
2015-05-14 16:08:49 -04:00
|
|
|
process.exit(exitCode);
|
2015-02-22 17:13:22 -05:00
|
|
|
}
|
|
|
|
|
2015-05-14 16:08:49 -04:00
|
|
|
if(process.argv.length < 4) {
|
|
|
|
console.log("Too few arguments!");
|
|
|
|
printHelpAndExit(1);
|
2015-02-22 17:13:22 -05:00
|
|
|
}
|
|
|
|
|
2015-11-30 16:19:56 -05:00
|
|
|
process.argv.forEach(function(val) {
|
2016-03-21 10:46:06 -04:00
|
|
|
if(val === "-h") {
|
2015-05-14 16:08:49 -04:00
|
|
|
printHelpAndExit(0);
|
|
|
|
}
|
2015-02-22 17:13:22 -05:00
|
|
|
});
|
|
|
|
|
2017-07-13 08:03:52 -04:00
|
|
|
const args = process.argv.slice(2);
|
|
|
|
let host;
|
|
|
|
let port = 25565;
|
|
|
|
let version;
|
2015-03-18 06:58:20 -04:00
|
|
|
|
2017-07-13 08:03:52 -04:00
|
|
|
let printAllNames = false;
|
|
|
|
const printNameWhitelist = {};
|
|
|
|
const printNameBlacklist = {};
|
2015-03-18 06:58:20 -04:00
|
|
|
(function() {
|
2017-08-10 17:50:12 -04:00
|
|
|
let i = 0;
|
|
|
|
for(i = 0; i < args.length; i++) {
|
2017-07-13 08:03:52 -04:00
|
|
|
const option = args[i];
|
2015-05-14 16:08:49 -04:00
|
|
|
if(!/^-/.test(option)) break;
|
2016-03-21 10:46:06 -04:00
|
|
|
if(option === "--dump-all") {
|
2015-09-23 09:05:52 -04:00
|
|
|
printAllNames = true;
|
2015-05-14 16:08:49 -04:00
|
|
|
continue;
|
2015-03-18 06:58:20 -04:00
|
|
|
}
|
2015-05-14 16:08:49 -04:00
|
|
|
i++;
|
2017-07-13 08:03:52 -04:00
|
|
|
const name = args[i];
|
2016-03-21 10:46:06 -04:00
|
|
|
if(option === "--dump") {
|
2015-09-23 09:05:52 -04:00
|
|
|
printNameWhitelist[name] = "io";
|
2016-03-21 10:46:06 -04:00
|
|
|
} else if(option === "-x") {
|
2015-09-23 09:05:52 -04:00
|
|
|
printNameBlacklist[name] = "io";
|
2015-05-14 16:08:49 -04:00
|
|
|
} else {
|
|
|
|
printHelpAndExit(1);
|
|
|
|
}
|
|
|
|
}
|
2015-09-29 18:16:39 -04:00
|
|
|
if(!(i + 2 <= args.length && args.length <= i + 4)) printHelpAndExit(1);
|
2015-05-14 16:08:49 -04:00
|
|
|
host = args[i++];
|
2015-09-29 18:16:39 -04:00
|
|
|
version = args[i++];
|
2015-03-18 06:58:20 -04:00
|
|
|
})();
|
2015-02-22 17:13:22 -05:00
|
|
|
|
2016-03-21 10:46:06 -04:00
|
|
|
if(host.indexOf(':') !== -1) {
|
2015-05-14 16:08:49 -04:00
|
|
|
port = host.substring(host.indexOf(':') + 1);
|
|
|
|
host = host.substring(0, host.indexOf(':'));
|
2015-02-22 17:13:22 -05:00
|
|
|
}
|
|
|
|
|
2017-07-13 08:03:52 -04:00
|
|
|
const srv = mc.createServer({
|
2015-02-22 17:13:22 -05:00
|
|
|
'online-mode': false,
|
2015-08-08 11:29:54 -04:00
|
|
|
port: 25566,
|
2015-09-29 18:16:39 -04:00
|
|
|
keepAlive: false,
|
|
|
|
version:version
|
2015-02-22 17:13:22 -05:00
|
|
|
});
|
2015-05-14 16:08:49 -04:00
|
|
|
srv.on('login', function(client) {
|
2017-07-13 08:03:52 -04:00
|
|
|
const addr = client.socket.remoteAddress;
|
2015-05-14 16:08:49 -04:00
|
|
|
console.log('Incoming connection', '(' + addr + ')');
|
2017-07-13 08:03:52 -04:00
|
|
|
let endedClient = false;
|
|
|
|
let endedTargetClient = false;
|
2015-02-22 17:13:22 -05:00
|
|
|
client.on('end', function() {
|
|
|
|
endedClient = true;
|
2015-05-14 16:08:49 -04:00
|
|
|
console.log('Connection closed by client', '(' + addr + ')');
|
|
|
|
if(!endedTargetClient)
|
2015-02-22 17:13:22 -05:00
|
|
|
targetClient.end("End");
|
|
|
|
});
|
2016-02-15 14:50:42 -05:00
|
|
|
client.on('error', function(err) {
|
2015-02-22 17:13:22 -05:00
|
|
|
endedClient = true;
|
2015-05-14 16:08:49 -04:00
|
|
|
console.log('Connection error by client', '(' + addr + ')');
|
2016-02-15 14:50:42 -05:00
|
|
|
console.log(err.stack);
|
2015-05-14 16:08:49 -04:00
|
|
|
if(!endedTargetClient)
|
2015-02-24 18:44:59 -05:00
|
|
|
targetClient.end("Error");
|
2015-02-22 17:13:22 -05:00
|
|
|
});
|
2017-07-13 08:03:52 -04:00
|
|
|
const targetClient = mc.createClient({
|
2015-02-22 17:13:22 -05:00
|
|
|
host: host,
|
|
|
|
port: port,
|
2015-11-07 16:06:49 -05:00
|
|
|
username: client.username,
|
2015-09-29 18:16:39 -04:00
|
|
|
keepAlive:false,
|
|
|
|
version:version
|
2015-02-22 17:13:22 -05:00
|
|
|
});
|
2015-09-23 09:05:52 -04:00
|
|
|
client.on('packet', function(data, meta) {
|
2016-03-21 10:46:06 -04:00
|
|
|
if(targetClient.state === states.PLAY && meta.state === states.PLAY) {
|
2015-09-23 09:05:52 -04:00
|
|
|
if(shouldDump(meta.name, "o")) {
|
2015-03-18 06:58:20 -04:00
|
|
|
console.log("client->server:",
|
2015-10-02 20:14:01 -04:00
|
|
|
client.state + " "+ meta.name + " :",
|
2015-09-23 09:05:52 -04:00
|
|
|
JSON.stringify(data));
|
2015-03-18 06:58:20 -04:00
|
|
|
}
|
2015-05-14 16:08:49 -04:00
|
|
|
if(!endedTargetClient)
|
2015-09-23 09:05:52 -04:00
|
|
|
targetClient.write(meta.name, data);
|
2015-02-22 17:13:22 -05:00
|
|
|
}
|
|
|
|
});
|
2015-09-23 09:05:52 -04:00
|
|
|
targetClient.on('packet', function(data, meta) {
|
2016-03-21 10:46:06 -04:00
|
|
|
if(meta.state === states.PLAY && client.state === states.PLAY) {
|
2015-09-23 09:05:52 -04:00
|
|
|
if(shouldDump(meta.name, "i")) {
|
2015-03-18 06:58:20 -04:00
|
|
|
console.log("client<-server:",
|
2015-09-23 09:05:52 -04:00
|
|
|
targetClient.state + "." + meta.name + " :" +
|
|
|
|
JSON.stringify(data));
|
2015-03-18 06:58:20 -04:00
|
|
|
}
|
2015-11-06 19:25:12 -05:00
|
|
|
if(!endedClient) {
|
2015-09-23 09:05:52 -04:00
|
|
|
client.write(meta.name, data);
|
2016-03-21 10:46:06 -04:00
|
|
|
if(meta.name === 'set_compression'){
|
2015-11-06 19:25:12 -05:00
|
|
|
client.compressionThreshold = data.threshold;
|
2016-03-21 10:46:06 -04:00
|
|
|
} // Set compression
|
2015-11-06 19:25:12 -05:00
|
|
|
}
|
2015-02-22 17:13:22 -05:00
|
|
|
}
|
|
|
|
});
|
2017-07-13 08:03:52 -04:00
|
|
|
const bufferEqual = require('buffer-equal');
|
2015-09-23 09:05:52 -04:00
|
|
|
targetClient.on('raw', function(buffer, meta) {
|
2016-03-21 10:46:06 -04:00
|
|
|
if(client.state !== states.PLAY || meta.state !== states.PLAY)
|
2015-03-03 07:43:46 -05:00
|
|
|
return;
|
2017-07-13 08:03:52 -04:00
|
|
|
const packetData = targetClient.deserializer.parsePacketBuffer(buffer).data.params;
|
|
|
|
const packetBuff = client.serializer.createPacketBuffer({name:meta.name, params:packetData});
|
2015-10-13 11:11:51 -04:00
|
|
|
if(!bufferEqual(buffer, packetBuff)) {
|
2016-02-15 17:18:57 -05:00
|
|
|
console.log("client<-server: Error in packet " + meta.state + "." + meta.name);
|
2016-02-27 12:10:11 -05:00
|
|
|
console.log("received buffer",buffer.toString('hex'));
|
|
|
|
console.log("produced buffer",packetBuff.toString('hex'));
|
|
|
|
console.log("received length",buffer.length);
|
|
|
|
console.log("produced length",packetBuff.length);
|
2015-03-03 07:43:46 -05:00
|
|
|
}
|
2016-03-21 10:46:06 -04:00
|
|
|
/*if (client.state === states.PLAY && brokenPackets.indexOf(packetId.value) !=== -1)
|
2015-05-14 16:08:49 -04:00
|
|
|
{
|
|
|
|
console.log(`client<-server: raw packet);
|
|
|
|
console.log(packetData);
|
|
|
|
if (!endedClient)
|
|
|
|
client.writeRaw(buffer);
|
|
|
|
}*/
|
2015-03-03 07:43:46 -05:00
|
|
|
});
|
2015-09-23 09:05:52 -04:00
|
|
|
client.on('raw', function(buffer, meta) {
|
2016-03-21 10:46:06 -04:00
|
|
|
if(meta.state !== states.PLAY || targetClient.state !== states.PLAY)
|
2015-03-03 07:43:46 -05:00
|
|
|
return;
|
2017-07-13 08:03:52 -04:00
|
|
|
const packetData = client.deserializer.parsePacketBuffer(buffer).data.params;
|
|
|
|
const packetBuff = targetClient.serializer.createPacketBuffer({name:meta.name, params:packetData});
|
2015-10-13 11:11:51 -04:00
|
|
|
if(!bufferEqual(buffer, packetBuff)) {
|
2016-02-15 17:18:57 -05:00
|
|
|
console.log("client->server: Error in packet " + meta.state + "." + meta.name);
|
2016-02-27 12:10:11 -05:00
|
|
|
console.log("received buffer",buffer.toString('hex'));
|
|
|
|
console.log("produced buffer",packetBuff.toString('hex'));
|
|
|
|
console.log("received length",buffer.length);
|
|
|
|
console.log("produced length",packetBuff.length);
|
2015-03-03 07:43:46 -05:00
|
|
|
}
|
|
|
|
});
|
2015-02-22 17:13:22 -05:00
|
|
|
targetClient.on('end', function() {
|
|
|
|
endedTargetClient = true;
|
2015-05-14 16:08:49 -04:00
|
|
|
console.log('Connection closed by server', '(' + addr + ')');
|
|
|
|
if(!endedClient)
|
2015-02-22 17:13:22 -05:00
|
|
|
client.end("End");
|
|
|
|
});
|
2015-07-29 20:41:49 -04:00
|
|
|
targetClient.on('error', function(err) {
|
2015-02-22 17:13:22 -05:00
|
|
|
endedTargetClient = true;
|
2015-07-29 20:41:49 -04:00
|
|
|
console.log('Connection error by server', '(' + addr + ') ',err);
|
|
|
|
console.log(err.stack);
|
2015-05-14 16:08:49 -04:00
|
|
|
if(!endedClient)
|
2015-02-22 17:13:22 -05:00
|
|
|
client.end("Error");
|
|
|
|
});
|
|
|
|
});
|
2015-03-18 06:58:20 -04:00
|
|
|
|
2015-09-23 09:05:52 -04:00
|
|
|
function shouldDump(name, direction) {
|
|
|
|
if(matches(printNameBlacklist[name])) return false;
|
|
|
|
if(printAllNames) return true;
|
2015-11-30 16:19:56 -05:00
|
|
|
return matches(printNameWhitelist[name]);
|
|
|
|
|
2015-03-24 19:43:38 -04:00
|
|
|
function matches(result) {
|
2017-08-10 17:50:12 -04:00
|
|
|
return result !== undefined && result !== null && result.indexOf(direction) !== -1;
|
2015-03-24 19:43:38 -04:00
|
|
|
}
|
2015-03-18 06:58:20 -04:00
|
|
|
}
|