2018-05-13 16:50:16 -04:00
|
|
|
const mc = require('minecraft-protocol')
|
2015-02-22 17:13:22 -05:00
|
|
|
|
2018-05-13 16:50:16 -04:00
|
|
|
const states = mc.states
|
|
|
|
function printHelpAndExit (exitCode) {
|
|
|
|
console.log('usage: node proxy.js [<options>...] <target_srv> <version>')
|
|
|
|
console.log('options:')
|
|
|
|
console.log(' --dump name')
|
|
|
|
console.log(' print to stdout messages with the specified name.')
|
|
|
|
console.log(' --dump-all')
|
|
|
|
console.log(' print to stdout all messages, except those specified with -x.')
|
|
|
|
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')
|
|
|
|
console.log('examples:')
|
|
|
|
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')
|
|
|
|
console.log(' print all messages except for some of the most prolific.')
|
|
|
|
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')
|
|
|
|
console.log(' print messages relating to inventory management.')
|
2015-03-18 06:58:20 -04:00
|
|
|
|
2018-05-13 16:50:16 -04:00
|
|
|
process.exit(exitCode)
|
2015-02-22 17:13:22 -05:00
|
|
|
}
|
|
|
|
|
2018-05-13 16:50:16 -04:00
|
|
|
if (process.argv.length < 4) {
|
|
|
|
console.log('Too few arguments!')
|
|
|
|
printHelpAndExit(1)
|
2015-02-22 17:13:22 -05:00
|
|
|
}
|
|
|
|
|
2018-05-13 16:50:16 -04:00
|
|
|
process.argv.forEach(function (val) {
|
|
|
|
if (val === '-h') {
|
|
|
|
printHelpAndExit(0)
|
2015-05-14 16:08:49 -04:00
|
|
|
}
|
2018-05-13 16:50:16 -04:00
|
|
|
})
|
2015-02-22 17:13:22 -05:00
|
|
|
|
2018-05-13 16:50:16 -04:00
|
|
|
const args = process.argv.slice(2)
|
|
|
|
let host
|
|
|
|
let port = 25565
|
|
|
|
let version
|
2015-03-18 06:58:20 -04:00
|
|
|
|
2018-05-13 16:50:16 -04:00
|
|
|
let printAllNames = false
|
|
|
|
const printNameWhitelist = {}
|
2017-07-13 08:03:52 -04:00
|
|
|
const printNameBlacklist = {};
|
2018-05-13 16:50:16 -04:00
|
|
|
(function () {
|
|
|
|
let i = 0
|
|
|
|
for (i = 0; i < args.length; i++) {
|
|
|
|
const option = args[i]
|
|
|
|
if (!/^-/.test(option)) break
|
|
|
|
if (option === '--dump-all') {
|
|
|
|
printAllNames = true
|
|
|
|
continue
|
2015-03-18 06:58:20 -04:00
|
|
|
}
|
2018-05-13 16:50:16 -04:00
|
|
|
i++
|
|
|
|
const name = args[i]
|
|
|
|
if (option === '--dump') {
|
|
|
|
printNameWhitelist[name] = 'io'
|
|
|
|
} else if (option === '-x') {
|
|
|
|
printNameBlacklist[name] = 'io'
|
2015-05-14 16:08:49 -04:00
|
|
|
} else {
|
2018-05-13 16:50:16 -04:00
|
|
|
printHelpAndExit(1)
|
2015-05-14 16:08:49 -04:00
|
|
|
}
|
|
|
|
}
|
2018-05-13 16:50:16 -04:00
|
|
|
if (!(i + 2 <= args.length && args.length <= i + 4)) printHelpAndExit(1)
|
|
|
|
host = args[i++]
|
|
|
|
version = args[i++]
|
|
|
|
})()
|
2015-02-22 17:13:22 -05:00
|
|
|
|
2018-05-13 16:50:16 -04:00
|
|
|
if (host.indexOf(':') !== -1) {
|
|
|
|
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,
|
2018-05-13 16:50:16 -04:00
|
|
|
version: version
|
|
|
|
})
|
|
|
|
srv.on('login', function (client) {
|
|
|
|
const addr = client.socket.remoteAddress
|
|
|
|
console.log('Incoming connection', '(' + addr + ')')
|
|
|
|
let endedClient = false
|
|
|
|
let endedTargetClient = false
|
|
|
|
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') }
|
|
|
|
})
|
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,
|
2018-05-13 16:50:16 -04:00
|
|
|
keepAlive: false,
|
|
|
|
version: version
|
|
|
|
})
|
|
|
|
client.on('packet', function (data, meta) {
|
|
|
|
if (targetClient.state === states.PLAY && meta.state === states.PLAY) {
|
|
|
|
if (shouldDump(meta.name, 'o')) {
|
|
|
|
console.log('client->server:',
|
|
|
|
client.state + ' ' + meta.name + ' :',
|
|
|
|
JSON.stringify(data))
|
2015-03-18 06:58:20 -04:00
|
|
|
}
|
2018-05-13 16:50:16 -04:00
|
|
|
if (!endedTargetClient) { targetClient.write(meta.name, data) }
|
2015-02-22 17:13:22 -05:00
|
|
|
}
|
2018-05-13 16:50:16 -04:00
|
|
|
})
|
|
|
|
targetClient.on('packet', function (data, meta) {
|
|
|
|
if (meta.state === states.PLAY && client.state === states.PLAY) {
|
|
|
|
if (shouldDump(meta.name, 'i')) {
|
|
|
|
console.log('client<-server:',
|
|
|
|
targetClient.state + '.' + meta.name + ' :' +
|
|
|
|
JSON.stringify(data))
|
2015-03-18 06:58:20 -04:00
|
|
|
}
|
2018-05-13 16:50:16 -04:00
|
|
|
if (!endedClient) {
|
|
|
|
client.write(meta.name, data)
|
|
|
|
if (meta.name === 'set_compression') {
|
|
|
|
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
|
|
|
}
|
2018-05-13 16:50:16 -04:00
|
|
|
})
|
|
|
|
const bufferEqual = require('buffer-equal')
|
|
|
|
targetClient.on('raw', function (buffer, meta) {
|
|
|
|
if (client.state !== states.PLAY || meta.state !== states.PLAY) { return }
|
|
|
|
const packetData = targetClient.deserializer.parsePacketBuffer(buffer).data.params
|
|
|
|
const packetBuff = client.serializer.createPacketBuffer({name: meta.name, params: packetData})
|
|
|
|
if (!bufferEqual(buffer, packetBuff)) {
|
|
|
|
console.log('client<-server: Error in packet ' + meta.state + '.' + meta.name)
|
|
|
|
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
|
|
|
}
|
2018-05-13 16:50:16 -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);
|
2018-05-13 16:50:16 -04:00
|
|
|
} */
|
|
|
|
})
|
|
|
|
client.on('raw', function (buffer, meta) {
|
|
|
|
if (meta.state !== states.PLAY || targetClient.state !== states.PLAY) { return }
|
|
|
|
const packetData = client.deserializer.parsePacketBuffer(buffer).data.params
|
|
|
|
const packetBuff = targetClient.serializer.createPacketBuffer({name: meta.name, params: packetData})
|
|
|
|
if (!bufferEqual(buffer, packetBuff)) {
|
|
|
|
console.log('client->server: Error in packet ' + meta.state + '.' + meta.name)
|
|
|
|
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
|
|
|
}
|
2018-05-13 16:50:16 -04:00
|
|
|
})
|
|
|
|
targetClient.on('end', function () {
|
|
|
|
endedTargetClient = true
|
|
|
|
console.log('Connection closed by server', '(' + addr + ')')
|
|
|
|
if (!endedClient) { client.end('End') }
|
|
|
|
})
|
|
|
|
targetClient.on('error', function (err) {
|
|
|
|
endedTargetClient = true
|
|
|
|
console.log('Connection error by server', '(' + addr + ') ', err)
|
|
|
|
console.log(err.stack)
|
|
|
|
if (!endedClient) { client.end('Error') }
|
|
|
|
})
|
|
|
|
})
|
2015-03-18 06:58:20 -04:00
|
|
|
|
2018-05-13 16:50:16 -04:00
|
|
|
function shouldDump (name, direction) {
|
|
|
|
if (matches(printNameBlacklist[name])) return false
|
|
|
|
if (printAllNames) return true
|
|
|
|
return matches(printNameWhitelist[name])
|
2015-11-30 16:19:56 -05:00
|
|
|
|
2018-05-13 16:50:16 -04:00
|
|
|
function matches (result) {
|
|
|
|
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
|
|
|
}
|