/* eslint-env mocha */ const mc = require('../') const assert = require('power-assert') const { firstVersion, lastVersion } = require('./common/parallel') const w = { piglin_safe: { type: 'byte', value: 0 }, natural: { type: 'byte', value: 1 }, ambient_light: { type: 'float', value: 0 }, infiniburn: { type: 'string', value: 'minecraft:infiniburn_overworld' }, respawn_anchor_works: { type: 'byte', value: 0 }, has_skylight: { type: 'byte', value: 1 }, bed_works: { type: 'byte', value: 1 }, has_raids: { type: 'byte', value: 1 }, name: { type: 'string', value: 'minecraft:overworld' }, logical_height: { type: 'int', value: 256 }, shrunk: { type: 'byte', value: 0 }, ultrawarm: { type: 'byte', value: 0 }, has_ceiling: { type: 'byte', value: 0 } } mc.supportedVersions.forEach(function (supportedVersion, i) { if (!(i >= firstVersion && i <= lastVersion)) { return } const PORT = Math.round(30000 + Math.random() * 20000) const mcData = require('minecraft-data')(supportedVersion) const version = mcData.version describe('mc-server ' + version.minecraftVersion, function () { this.timeout(5000) it('starts listening and shuts down cleanly', function (done) { const server = mc.createServer({ 'online-mode': false, version: version.minecraftVersion, port: PORT }) let listening = false server.on('listening', function () { listening = true server.close() }) server.on('close', function () { assert.ok(listening) done() }) }) it('kicks clients that do not log in', function (done) { const server = mc.createServer({ 'online-mode': false, kickTimeout: 100, checkTimeoutInterval: 10, version: version.minecraftVersion, port: PORT }) let count = 2 server.on('connection', function (client) { client.on('end', function (reason) { assert.strictEqual(reason, 'LoginTimeout') server.close() }) }) server.on('close', function () { resolve() }) server.on('listening', function () { const client = new mc.Client(false, version.minecraftVersion) client.on('end', function () { resolve() }) client.connect(PORT, '127.0.0.1') }) function resolve () { count -= 1 if (count <= 0) done() } }) it('kicks clients that do not send keepalive packets', function (done) { const server = mc.createServer({ 'online-mode': false, kickTimeout: 100, checkTimeoutInterval: 10, version: version.minecraftVersion, port: PORT }) let count = 2 server.on('connection', function (client) { client.on('end', function (reason) { assert.strictEqual(reason, 'KeepAliveTimeout') server.close() }) }) server.on('close', function () { resolve() }) server.on('listening', function () { const client = mc.createClient({ username: 'superpants', host: '127.0.0.1', port: PORT, keepAlive: false, version: version.minecraftVersion }) client.on('end', function () { resolve() }) }) function resolve () { count -= 1 if (count <= 0) done() } }) it('responds to ping requests', function (done) { const server = mc.createServer({ 'online-mode': false, motd: 'test1234', 'max-players': 120, version: version.minecraftVersion, port: PORT }) server.on('listening', function () { mc.ping({ host: '127.0.0.1', version: version.minecraftVersion, port: PORT }, function (err, results) { if (err) return done(err) assert.ok(results.latency >= 0) assert.ok(results.latency <= 1000) delete results.latency assert.deepEqual(results, { version: { name: version.minecraftVersion, protocol: version.version }, players: { max: 120, online: 0, sample: [] }, description: { text: 'test1234' } }) server.close() }) }) server.on('close', done) }) it('clients can log in and chat', function (done) { const server = mc.createServer({ 'online-mode': false, version: version.minecraftVersion, port: PORT }) const username = ['player1', 'player2'] let index = 0 server.on('login', function (client) { assert.notEqual(client.id, null) assert.strictEqual(client.username, username[index++]) broadcast(client.username + ' joined the game.') client.on('end', function () { broadcast(client.username + ' left the game.', client) if (client.username === 'player2') server.close() }) const loginPacket = { entityId: client.id, levelType: 'default', gameMode: 1, previousGameMode: 255, worldNames: ['minecraft:overworld'], dimensionCodec: (version.version >= 735 ? mcData.loginPacket.dimension : { name: '', type: 'compound', value: { dimension: { type: 'list', value: { type: 'compound', value: [w] } } } }), dimension: (version.version >= 735 ? mcData.loginPacket.dimension : 0), worldName: 'minecraft:overworld', hashedSeed: [0, 0], difficulty: 2, maxPlayers: server.maxPlayers, reducedDebugInfo: (version.version >= 735 ? false : 0), enableRespawnScreen: true } if (version.version >= 735) { // 1.16x loginPacket.isDebug = false loginPacket.isFlat = false loginPacket.isHardcore = false loginPacket.viewDistance = 10 delete loginPacket.levelType delete loginPacket.difficulty } client.write('login', loginPacket) client.on('chat', function (packet) { const message = '<' + client.username + '>' + ' ' + packet.message broadcast(message) }) }) server.on('close', done) server.on('listening', function () { const player1 = mc.createClient({ username: 'player1', host: '127.0.0.1', version: version.minecraftVersion, port: PORT }) player1.on('login', function (packet) { assert.strictEqual(packet.gameMode, 1) player1.once('chat', function (packet) { assert.strictEqual(packet.message, '{"text":"player2 joined the game."}') player1.once('chat', function (packet) { assert.strictEqual(packet.message, '{"text":" hi"}') player2.once('chat', fn) function fn (packet) { if (//.test(packet.message)) { player2.once('chat', fn) return } assert.strictEqual(packet.message, '{"text":" hello"}') player1.once('chat', function (packet) { assert.strictEqual(packet.message, '{"text":"player2 left the game."}') player1.end() }) player2.end() } player1.write('chat', { message: 'hello' }) }) player2.write('chat', { message: 'hi' }) }) const player2 = mc.createClient({ username: 'player2', host: '127.0.0.1', version: version.minecraftVersion, port: PORT }) }) }) function broadcast (message, exclude) { let client for (const clientId in server.clients) { if (server.clients[clientId] === undefined) continue client = server.clients[clientId] if (client !== exclude) client.write('chat', { message: JSON.stringify({ text: message }), position: 0, sender: '0' }) } } }) it('kicks clients when invalid credentials', function (done) { this.timeout(10000) const server = mc.createServer({ version: version.minecraftVersion, port: PORT }) let count = 4 server.on('connection', function (client) { client.on('end', function (reason) { resolve() server.close() }) }) server.on('close', function () { resolve() }) server.on('listening', function () { resolve() const client = mc.createClient({ username: 'lalalal', host: '127.0.0.1', version: version.minecraftVersion, port: PORT }) client.on('end', function () { resolve() }) }) function resolve () { count -= 1 if (count <= 0) done() } }) it('gives correct reason for kicking clients when shutting down', function (done) { const server = mc.createServer({ 'online-mode': false, version: version.minecraftVersion, port: PORT }) let count = 2 server.on('login', function (client) { client.on('end', function (reason) { assert.strictEqual(reason, 'ServerShutdown') resolve() }) const loginPacket = { entityId: client.id, levelType: 'default', gameMode: 1, previousGameMode: 255, worldNames: ['minecraft:overworld'], dimensionCodec: (version.version >= 735 ? mcData.loginPacket.dimension : { name: '', type: 'compound', value: { dimension: { type: 'list', value: { type: 'compound', value: [w] } } } }), dimension: (version.version >= 735 ? mcData.loginPacket.dimension : 0), worldName: 'minecraft:overworld', hashedSeed: [0, 0], difficulty: 2, maxPlayers: server.maxPlayers, reducedDebugInfo: (version.version >= 735 ? false : 0), enableRespawnScreen: true } if (version.version >= 735) { // 1.16x loginPacket.isDebug = false loginPacket.isFlat = false loginPacket.isHardcore = false loginPacket.viewDistance = 10 delete loginPacket.levelType delete loginPacket.difficulty } client.write('login', loginPacket) }) server.on('close', function () { resolve() }) server.on('listening', function () { const client = mc.createClient({ username: 'lalalal', host: '127.0.0.1', version: version.minecraftVersion, port: PORT }) client.on('login', function () { server.close() }) }) function resolve () { count -= 1 if (count <= 0) done() } }) }) })