From e346813ed2f34f0e0c1a9f9f86e5ccecbf433e69 Mon Sep 17 00:00:00 2001 From: Ic3Tank <61137113+IceTank@users.noreply.github.com> Date: Thu, 21 Nov 2024 19:42:00 +0100 Subject: [PATCH 1/5] Fix gamemode test and implementation --- lib/plugins/game.js | 6 +++++- test/externalTests/gamemode.js | 30 +++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/lib/plugins/game.js b/lib/plugins/game.js index c992d1f74..0fbe62f07 100644 --- a/lib/plugins/game.js +++ b/lib/plugins/game.js @@ -25,7 +25,11 @@ function inject (bot, options) { function handleRespawnPacketData (packet) { bot.game.levelType = packet.levelType ?? (packet.isFlat ? 'flat' : 'default') bot.game.hardcore = packet.isHardcore ?? Boolean(packet.gameMode & 0b100) - bot.game.gameMode = packet.gamemode || parseGameMode(packet.gameMode) + if (bot.registry.isOlderThan('1.10')) { + bot.game.gameMode = parseGameMode(packet.gamemode) + } else { + bot.game.gameMode = packet.gamemode || parseGameMode(packet.gameMode & 0b1111) // lower four bits + } if (bot.supportFeature('segmentedRegistryCodecData')) { // 1.20.5 if (typeof packet.dimension === 'number') { bot.game.dimension = bot.registry.dimensionsArray[packet.dimension]?.name?.replace('minecraft:', '') diff --git a/test/externalTests/gamemode.js b/test/externalTests/gamemode.js index d4cc45a04..f6a240028 100644 --- a/test/externalTests/gamemode.js +++ b/test/externalTests/gamemode.js @@ -1,10 +1,30 @@ // test to see if bot retains creative gamemode in bot object on death const assert = require('assert') +const { onceWithCleanup } = require('../../lib/promise_utils') -module.exports = async (bot) => { - bot.test.becomeCreative() - bot.chat(`/kill ${bot.username}`) - await new Promise((resolve, reject) => setTimeout(resolve, 5000)) - assert.strictEqual(bot.game.gameMode, 'creative', 'Failed to parse respawn packet') +module.exports = () => { + const tests = [] + + function addTest (name, f) { + tests[name] = (bot) => f(bot) + } + + addTest('change', async (bot) => { + await bot.test.becomeSurvival() + assert.strictEqual(bot.game.gameMode, 'survival', 'Wrong gamemode after switching gamemode') + await bot.test.becomeCreative() + assert.strictEqual(bot.game.gameMode, 'creative', 'Wrong gamemode after switching gamemode') + }) + + addTest('after respawn', async (bot) => { + await bot.test.becomeCreative() + + bot.chat('/kill') + + await onceWithCleanup(bot, 'respawn', { timeout: 2000 }) + assert.strictEqual(bot.game.gameMode, 'creative', 'Wrong gamemode after respawn') + }) + + return tests } From cd6698652faaf293b21edbd9926087c57c4bc254 Mon Sep 17 00:00:00 2001 From: Ic3Tank <61137113+IceTank@users.noreply.github.com> Date: Thu, 21 Nov 2024 19:47:22 +0100 Subject: [PATCH 2/5] Add gamemode test related comments --- lib/plugins/game.js | 2 +- test/externalTests/gamemode.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/plugins/game.js b/lib/plugins/game.js index 0fbe62f07..1a6522907 100644 --- a/lib/plugins/game.js +++ b/lib/plugins/game.js @@ -25,7 +25,7 @@ function inject (bot, options) { function handleRespawnPacketData (packet) { bot.game.levelType = packet.levelType ?? (packet.isFlat ? 'flat' : 'default') bot.game.hardcore = packet.isHardcore ?? Boolean(packet.gameMode & 0b100) - if (bot.registry.isOlderThan('1.10')) { + if (bot.registry.isOlderThan('1.10')) { // gamemode is used pre 1.10 and post 1.20 but in between it's gameMode bot.game.gameMode = parseGameMode(packet.gamemode) } else { bot.game.gameMode = packet.gamemode || parseGameMode(packet.gameMode & 0b1111) // lower four bits diff --git a/test/externalTests/gamemode.js b/test/externalTests/gamemode.js index f6a240028..e708a3daf 100644 --- a/test/externalTests/gamemode.js +++ b/test/externalTests/gamemode.js @@ -23,6 +23,7 @@ module.exports = () => { bot.chat('/kill') await onceWithCleanup(bot, 'respawn', { timeout: 2000 }) + // Respawn packets send the gamemode. If the bot is in creative mode, it should respawn in creative mode. Tested <1.20 assert.strictEqual(bot.game.gameMode, 'creative', 'Wrong gamemode after respawn') }) From c36265847a6ee5cef033c9a9e6704c92dff1f353 Mon Sep 17 00:00:00 2001 From: Ic3Tank <61137113+IceTank@users.noreply.github.com> Date: Thu, 21 Nov 2024 20:40:12 +0100 Subject: [PATCH 3/5] Fix gamemode tests Add test function to kill the bot --- lib/plugins/game.js | 7 ++++--- test/externalTests/gamemode.js | 6 ++---- test/externalTests/plugins/testCommon.js | 5 +++++ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/plugins/game.js b/lib/plugins/game.js index 1a6522907..daf9533b4 100644 --- a/lib/plugins/game.js +++ b/lib/plugins/game.js @@ -25,10 +25,11 @@ function inject (bot, options) { function handleRespawnPacketData (packet) { bot.game.levelType = packet.levelType ?? (packet.isFlat ? 'flat' : 'default') bot.game.hardcore = packet.isHardcore ?? Boolean(packet.gameMode & 0b100) - if (bot.registry.isOlderThan('1.10')) { // gamemode is used pre 1.10 and post 1.20 but in between it's gameMode - bot.game.gameMode = parseGameMode(packet.gamemode) + // Either a respawn packet or a login packet. Depending on the packet it can be "gamemode" or "gameMode" + if (bot.registry.isNewerOrEqualTo('1.20.5')) { + bot.game.gameMode = packet.gamemode || parseGameMode(packet.gameMode) } else { - bot.game.gameMode = packet.gamemode || parseGameMode(packet.gameMode & 0b1111) // lower four bits + bot.game.gameMode = parseGameMode(packet.gamemode ?? packet.gameMode) } if (bot.supportFeature('segmentedRegistryCodecData')) { // 1.20.5 if (typeof packet.dimension === 'number') { diff --git a/test/externalTests/gamemode.js b/test/externalTests/gamemode.js index e708a3daf..ebf2d1487 100644 --- a/test/externalTests/gamemode.js +++ b/test/externalTests/gamemode.js @@ -19,10 +19,8 @@ module.exports = () => { addTest('after respawn', async (bot) => { await bot.test.becomeCreative() - - bot.chat('/kill') - - await onceWithCleanup(bot, 'respawn', { timeout: 2000 }) + bot.test.selfKill() + await onceWithCleanup(bot, 'respawn', { timeout: 5000 }) // Respawn packets send the gamemode. If the bot is in creative mode, it should respawn in creative mode. Tested <1.20 assert.strictEqual(bot.game.gameMode, 'creative', 'Wrong gamemode after respawn') }) diff --git a/test/externalTests/plugins/testCommon.js b/test/externalTests/plugins/testCommon.js index 0309fa4bf..0b25a918e 100644 --- a/test/externalTests/plugins/testCommon.js +++ b/test/externalTests/plugins/testCommon.js @@ -25,6 +25,7 @@ function inject (bot) { bot.test.placeBlock = placeBlock bot.test.runExample = runExample bot.test.tellAndListen = tellAndListen + bot.test.selfKill = selfKill bot.test.wait = function (ms) { return new Promise((resolve) => { setTimeout(resolve, ms) }) } @@ -232,4 +233,8 @@ function inject (bot) { } return closeExample() } + + function selfKill () { + bot.chat('/kill @p') + } } From e3a01583d147fa3e2de8e54bb20dd6c12f036b83 Mon Sep 17 00:00:00 2001 From: IceTank <61137113+IceTank@users.noreply.github.com> Date: Wed, 27 Nov 2024 14:34:19 +0100 Subject: [PATCH 4/5] Add gamemode out of bounds checks --- lib/plugins/game.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/plugins/game.js b/lib/plugins/game.js index daf9533b4..10964d7a1 100644 --- a/lib/plugins/game.js +++ b/lib/plugins/game.js @@ -10,7 +10,12 @@ const dimensionNames = { 1: 'the_end' } -const parseGameMode = gameModeBits => gameModes[(gameModeBits & 0b11)] // lower two bits +const parseGameMode = gameModeBits => { + if (gameModeBits < 0 || gameModeBits > 0b11) { + return 'survival' + } + return gameModes[(gameModeBits & 0b11)] // lower two bits +} function inject (bot, options) { function getBrandCustomChannelName () { From 6fb4b5dbc43cbfb6daaaed73d34ff8ffe01225e3 Mon Sep 17 00:00:00 2001 From: IceTank <61137113+IceTank@users.noreply.github.com> Date: Wed, 27 Nov 2024 14:53:58 +0100 Subject: [PATCH 5/5] Simplify gameMode parsing and check against spawnRespawnWorldDataField feature --- lib/plugins/game.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/plugins/game.js b/lib/plugins/game.js index 10964d7a1..c47db6c6e 100644 --- a/lib/plugins/game.js +++ b/lib/plugins/game.js @@ -31,8 +31,8 @@ function inject (bot, options) { bot.game.levelType = packet.levelType ?? (packet.isFlat ? 'flat' : 'default') bot.game.hardcore = packet.isHardcore ?? Boolean(packet.gameMode & 0b100) // Either a respawn packet or a login packet. Depending on the packet it can be "gamemode" or "gameMode" - if (bot.registry.isNewerOrEqualTo('1.20.5')) { - bot.game.gameMode = packet.gamemode || parseGameMode(packet.gameMode) + if (bot.supportFeature('spawnRespawnWorldDataField')) { // 1.20.5 + bot.game.gameMode = packet.gamemode } else { bot.game.gameMode = parseGameMode(packet.gamemode ?? packet.gameMode) }