UNPKG

@kodamc/protocol

Version:
216 lines (175 loc) 7.13 kB
const { Server, Client } = require('../') const { dumpPackets } = require('../tools/genPacketDumps') const { ping } = require('../src/createClient') const { CURRENT_VERSION } = require('../src/options') const { join } = require('path') const { waitFor } = require('../src/datatypes/util') const { getPort } = require('./util') // First we need to dump some packets that a vanilla server would send a vanilla // client. Then we can replay those back in our custom server. function prepare (version) { return dumpPackets(version) } async function startTest (version = CURRENT_VERSION, ok) { await prepare(version) const Item = require('../types/Item')(version) const port = await getPort() const server = new Server({ host: '0.0.0.0', port, version, offline: true }) function getPath (packetPath) { return join(__dirname, `../data/${server.options.version}/${packetPath}`) } function get (packetPath) { return require(getPath('sample/' + packetPath)) } console.log('Starting internal server') server.listen() console.log('Started server') const pongData = await ping({ host: '127.0.0.1', port }) console.assert(pongData, 'did not get valid pong data from server') const respawnPacket = get('packets/respawn.json') const chunks = await requestChunks(version, respawnPacket.x, respawnPacket.z, 1) let loop // server logic server.on('connect', client => { client.on('join', () => { console.log('Client joined server', client.getUserData()) client.write('resource_packs_info', { must_accept: false, has_scripts: false, behaviour_packs: [], texture_packs: [] }) client.once('resource_pack_client_response', async rp => { // Tell the server we will compress everything (>=1 byte) client.write('network_settings', { compression_threshold: 1 }) // Send some inventory slots for (let i = 0; i < 3; i++) { client.queue('inventory_slot', { window_id: 'armor', slot: 0, item: new Item().toBedrock() }) } // client.queue('inventory_transaction', get('packets/inventory_transaction.json')) client.queue('player_list', get('packets/player_list.json')) client.queue('start_game', get('packets/start_game.json')) client.queue('item_component', { entries: [] }) client.queue('set_spawn_position', get('packets/set_spawn_position.json')) client.queue('set_time', { time: 5433771 }) client.queue('set_difficulty', { difficulty: 1 }) client.queue('set_commands_enabled', { enabled: true }) if (client.versionLessThan('1.19.10')) { client.queue('adventure_settings', get('packets/adventure_settings.json')) } client.queue('biome_definition_list', get('packets/biome_definition_list.json')) client.queue('available_entity_identifiers', get('packets/available_entity_identifiers.json')) client.queue('update_attributes', get('packets/update_attributes.json')) client.queue('creative_content', get('packets/creative_content.json')) client.queue('inventory_content', get('packets/inventory_content.json')) client.queue('player_hotbar', { selected_slot: 3, window_id: 'inventory', select_slot: true }) client.queue('crafting_data', get('packets/crafting_data.json')) client.queue('available_commands', get('packets/available_commands.json')) client.queue('chunk_radius_update', { chunk_radius: 5 }) // client.queue('set_entity_data', get('packets/set_entity_data.json')) client.queue('game_rules_changed', get('packets/game_rules_changed.json')) client.queue('respawn', get('packets/respawn.json')) for (const chunk of chunks) { client.queue('level_chunk', chunk) } loop = setInterval(() => { client.write('network_chunk_publisher_update', { coordinates: { x: 646, y: 130, z: 77 }, radius: 64 }) }, 9500) setTimeout(() => { client.write('play_status', { status: 'player_spawn' }) }, 6000) // Respond to tick synchronization packets client.on('tick_sync', (packet) => { client.queue('tick_sync', { request_time: packet.request_time, response_time: BigInt(Date.now()) }) }) }) }) }) // client logic const client = new Client({ host: '127.0.0.1', port, username: 'Notch', version, offline: true }) console.log('Started client') 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 }) }) client.once('spawn', () => { console.info('Client spawend!') setTimeout(() => { client.close() server.close().then(() => { ok?.() }) }, 500) clearInterval(loop) }) client.connect() } async function requestChunks (version, x, z, radius) { const ChunkColumn = require('bedrock-provider').chunk('bedrock_1.17.10') // const mcData = require('minecraft-data')('1.16') const cxStart = (x >> 4) - radius const cxEnd = (x >> 4) + radius const czStart = (z >> 4) - radius const czEnd = (z >> 4) + radius // const stone = mcData.blocksByName.stone const chunks = [] for (let cx = cxStart; cx < cxEnd; cx++) { for (let cz = czStart; cz < czEnd; cz++) { console.log('reading chunk at ', cx, cz) const cc = new ChunkColumn(x, z) // Temporarily disable until 1.18 PR in bedrock-provider goes through // for (let x = 0; x < 16; x++) { // for (let y = 0; y < 60; y++) { // for (let z = 0; z < 16; z++) { // cc.setBlock({ x, y, z }, stone) // } // } // } if (!cc) { console.log('no chunk') continue } const cbuf = await cc.networkEncodeNoCache() chunks.push({ x: cx, z: cz, sub_chunk_count: cc.sectionsLen, cache_enabled: false, blobs: [], payload: cbuf }) } } return chunks } async function timedTest (version, timeout = 1000 * 220) { await waitFor((resolve, reject) => { // mocha eats up stack traces... startTest(version, resolve).catch(reject) }, timeout, () => { throw Error('timed out') }) console.info('✔ ok') } // if (!module.parent) timedTest('1.19.10') module.exports = { startTest, timedTest, requestChunks }