Add packet dumper, configuable vanilla server, client events
This commit is contained in:
parent
184de537f5
commit
cf6471f6eb
3 changed files with 105 additions and 26 deletions
|
|
@ -108,10 +108,8 @@ class Client extends Connection {
|
|||
}
|
||||
|
||||
onDisconnectRequest (packet) {
|
||||
// We're talking over UDP, so there is no connection to close, instead
|
||||
// we stop communicating with the server
|
||||
console.warn(`Server requested ${packet.hide_disconnect_reason ? 'silent disconnect' : 'disconnect'}: ${packet.message}`)
|
||||
process.exit(1) // TODO: handle
|
||||
this.emit('kick', packet)
|
||||
}
|
||||
|
||||
onPlayStatus (statusPacket) {
|
||||
|
|
@ -125,6 +123,7 @@ class Client extends Connection {
|
|||
}
|
||||
|
||||
close () {
|
||||
this.emit('close')
|
||||
clearInterval(this.loop)
|
||||
clearTimeout(this.connectTimeout)
|
||||
this.q = []
|
||||
|
|
@ -155,22 +154,13 @@ class Client extends Connection {
|
|||
const des = this.deserializer.parsePacketBuffer(packet)
|
||||
const pakData = { name: des.data.name, params: des.data.params }
|
||||
this.inLog('-> C', pakData.name/*, serialize(pakData.params).slice(0, 100) */)
|
||||
this.emit('packet', pakData)
|
||||
|
||||
if (debugging) {
|
||||
// Packet verifying (decode + re-encode + match test)
|
||||
if (pakData.name) {
|
||||
this.tryRencode(pakData.name, pakData.params, packet)
|
||||
}
|
||||
|
||||
// console.info('->', JSON.stringify(pakData, (k,v) => typeof v == 'bigint' ? v.toString() : v))
|
||||
// Packet dumping
|
||||
try {
|
||||
const root = __dirname + `../data/${this.options.version}/sample/`
|
||||
if (!fs.existsSync(root + `packets/${pakData.name}.json`)) {
|
||||
fs.writeFileSync(root + `packets/${pakData.name}.json`, serialize(pakData.params, 2))
|
||||
fs.writeFileSync(root + `packets/${pakData.name}.txt`, packet.toString('hex'))
|
||||
}
|
||||
} catch { }
|
||||
}
|
||||
|
||||
// Abstract some boilerplate before sending to listeners
|
||||
|
|
@ -187,8 +177,6 @@ class Client extends Connection {
|
|||
case 'play_status':
|
||||
this.onPlayStatus(pakData.params)
|
||||
break
|
||||
default:
|
||||
// console.log('Sending to listeners')
|
||||
}
|
||||
|
||||
// Emit packet
|
||||
|
|
|
|||
83
tools/genPacketDumps.js
Normal file
83
tools/genPacketDumps.js
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/* eslint-disable */
|
||||
// Collect sample packets needed for `serverTest.js`
|
||||
// process.env.DEBUG = 'minecraft-protocol'
|
||||
const fs = require('fs')
|
||||
const vanillaServer = require('../tools/startVanillaServer')
|
||||
const { Client } = require('../src/client')
|
||||
const { serialize, waitFor } = require('../src/datatypes/util')
|
||||
const { CURRENT_VERSION } = require('../src/options')
|
||||
const { join } = require('path')
|
||||
|
||||
let loop
|
||||
|
||||
async function main() {
|
||||
const random = ((Math.random() * 100) | 0)
|
||||
const port = 19130 + random
|
||||
|
||||
const handle = await vanillaServer.startServerAndWait(CURRENT_VERSION, 1000 * 120, { 'server-port': port, path: 'bds_' })
|
||||
|
||||
console.log('Started server')
|
||||
const client = new Client({
|
||||
hostname: '127.0.0.1',
|
||||
port,
|
||||
username: 'Boat' + random,
|
||||
offline: true
|
||||
})
|
||||
|
||||
return waitFor(async res => {
|
||||
const root = join(__dirname, `../data/${client.options.version}/sample/packets/`)
|
||||
if (!fs.existsSync(root)) {
|
||||
fs.mkdirSync(root, { recursive: true })
|
||||
}
|
||||
|
||||
client.once('resource_packs_info', (packet) => {
|
||||
client.write('resource_pack_client_response', {
|
||||
response_status: 'completed',
|
||||
resourcepackids: []
|
||||
})
|
||||
|
||||
client.once('resource_pack_stack', (stack) => {
|
||||
client.write('resource_pack_client_response', {
|
||||
response_status: 'completed',
|
||||
resourcepackids: []
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
client.queue('client_cache_status', { enabled: false })
|
||||
client.queue('request_chunk_radius', { chunk_radius: 1 })
|
||||
// client.queue('tick_sync', { request_time: BigInt(Date.now()), response_time: 0n })
|
||||
|
||||
clearInterval(loop)
|
||||
loop = setInterval(() => {
|
||||
client.queue('tick_sync', { request_time: BigInt(Date.now()), response_time: BigInt(Date.now()) })
|
||||
}, 200)
|
||||
})
|
||||
|
||||
client.on('packet', pakData => { // Packet dumping
|
||||
if (pakData.name == 'level_chunk') return
|
||||
try {
|
||||
if (!fs.existsSync(root + `${pakData.name}.json`)) {
|
||||
fs.promises.writeFile(root + `${pakData.name}.json`, serialize(pakData.params, 2))
|
||||
}
|
||||
} catch (e) { console.log(e) }
|
||||
})
|
||||
|
||||
console.log('Awaiting join...')
|
||||
|
||||
client.on('spawn', () => {
|
||||
console.log('Spawned!')
|
||||
clearInterval(loop)
|
||||
client.close()
|
||||
handle.kill()
|
||||
res()
|
||||
})
|
||||
}, 1000 * 60, () => {
|
||||
clearInterval(loop)
|
||||
throw Error('timed out')
|
||||
})
|
||||
}
|
||||
|
||||
main().then(() => {
|
||||
console.log('Successfully dumped packets')
|
||||
})
|
||||
|
|
@ -17,18 +17,18 @@ function fetchLatestStable () {
|
|||
}
|
||||
|
||||
// Download + extract vanilla server and enter the directory
|
||||
async function download (os, version) {
|
||||
async function download (os, version, path = 'bds-') {
|
||||
process.chdir(__dirname)
|
||||
const verStr = version.split('.').slice(0, 3).join('.')
|
||||
const dir = 'bds-' + version
|
||||
const dir = path + version
|
||||
|
||||
if (fs.existsSync(dir) && getFiles(dir).length) {
|
||||
process.chdir('bds-' + version) // Enter server folder
|
||||
process.chdir(path + version) // Enter server folder
|
||||
return verStr
|
||||
}
|
||||
try { fs.mkdirSync(dir) } catch { }
|
||||
|
||||
process.chdir('bds-' + version) // Enter server folder
|
||||
process.chdir(path + version) // Enter server folder
|
||||
const url = (os, version) => `https://minecraft.azureedge.net/bin-${os}/bedrock-server-${version}.zip`
|
||||
|
||||
let found = false
|
||||
|
|
@ -53,10 +53,18 @@ async function download (os, version) {
|
|||
return verStr
|
||||
}
|
||||
|
||||
const defaultOptions = {
|
||||
'level-generator': '2',
|
||||
'server-port': '19130',
|
||||
'online-mode': 'false'
|
||||
}
|
||||
|
||||
// Setup the server
|
||||
function configure () {
|
||||
function configure (options = {}) {
|
||||
const opts = { ...defaultOptions, ...options }
|
||||
let config = fs.readFileSync('./server.properties', 'utf-8')
|
||||
config += '\nlevel-generator=2\nserver-port=19130\nplayer-idle-timeout=1\nallow-cheats=true\ndefault-player-permission-level=operator\nonline-mode=false'
|
||||
config += '\nplayer-idle-timeout=1\nallow-cheats=true\ndefault-player-permission-level=operator'
|
||||
for (const o in opts) config += `\n${o}=${opts[o]}`
|
||||
fs.writeFileSync('./server.properties', config)
|
||||
}
|
||||
|
||||
|
|
@ -66,13 +74,13 @@ function run (inheritStdout = true) {
|
|||
}
|
||||
|
||||
// Run the server
|
||||
async function startServer (version, onStart) {
|
||||
async function startServer (version, onStart, options = {}) {
|
||||
const os = process.platform === 'win32' ? 'win' : process.platform
|
||||
if (os !== 'win' && os !== 'linux') {
|
||||
throw Error('unsupported os ' + os)
|
||||
}
|
||||
await download(os, version)
|
||||
configure()
|
||||
await download(os, version, options.path)
|
||||
configure(options)
|
||||
const handle = run(!onStart)
|
||||
if (onStart) {
|
||||
handle.stdout.on('data', data => data.includes('Server started.') ? onStart() : null)
|
||||
|
|
@ -83,10 +91,10 @@ async function startServer (version, onStart) {
|
|||
}
|
||||
|
||||
// Start the server and wait for it to be ready, with a timeout
|
||||
async function startServerAndWait (version, withTimeout) {
|
||||
async function startServerAndWait (version, withTimeout, options) {
|
||||
let handle
|
||||
await waitFor(async res => {
|
||||
handle = await startServer(version, res)
|
||||
handle = await startServer(version, res, options)
|
||||
}, withTimeout, () => {
|
||||
handle?.kill()
|
||||
throw new Error('Server did not start on time ' + withTimeout)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue