diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f7a1f6c18..14252f55d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,6 +27,8 @@ jobs: include: - javaVersion: 16 mcVersion: '1.17.1' + - javaVersion: 17 + mcVersion: '1.18.1' fail-fast: false steps: diff --git a/docs/README.md b/docs/README.md index c99953b18..80b65ad92 100644 --- a/docs/README.md +++ b/docs/README.md @@ -16,7 +16,7 @@ First time using Node.js? You may want to start with the [tutorial](tutorial.md) ## Features - * Supports Minecraft 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16 and 1.17. + * Supports Minecraft 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17 and 1.18. * Entity knowledge and tracking. * Block knowledge. You can query the world around you. Milliseconds to find any block. * Physics and movement - handle all bounding boxes @@ -230,10 +230,14 @@ The most updated and useful are : Simply run: `npm test` ### Testing specific version -Run `npm mocha_test -- -g `, where `` is a minecraft version like `1.12`, `1.15.2`... +Run `npm run mocha_test -- -g `, where `` is a minecraft version like `1.12`, `1.15.2`... ### Testing specific test -Run `npm mocha_test -- -g `, where `` is a name of the test like `bed`, `useChests`, `rayTrace`... +Run `npm run mocha_test -- -g `, where `` is a name of the test like `bed`, `useChests`, `rayTrace`... + +### Example + +`npm run mocha_test -- -g "1.18.1.*BlockFinder"` to run the block finder test for 1.18.1 ## License diff --git a/docs/api.md b/docs/api.md index cd6825fca..35b06491b 100644 --- a/docs/api.md +++ b/docs/api.md @@ -818,6 +818,14 @@ Whether the bot is using the item that it's holding, for example eating food or #### bot.game.serverBrand +#### bot.game.minY + +minimum y of the world + +#### bot.game.height + +world height + ### bot.physicsEnabled Enable physics, default true. diff --git a/lib/features.json b/lib/features.json index 2366323e4..3fbcbfe8a 100644 --- a/lib/features.json +++ b/lib/features.json @@ -7,7 +7,7 @@ { "name": "spawner", "description": "spawner is called spawner", - "versions": ["1.13", "1.17.1"] + "versions": ["1.13", "1.18.1"] }, { "name": "blockMetadata", @@ -17,12 +17,12 @@ { "name": "blockStateId", "description": "block metadata is encoded as state id", - "versions": ["1.13", "1.17.1"] + "versions": ["1.13", "1.18.1"] }, { "name": "creativeSleepNearMobs", "description": "can sleep near mobs in creative", - "versions": ["1.13", "1.17.1"] + "versions": ["1.13", "1.18.1"] }, { "name": "fixedPointPosition", @@ -32,7 +32,7 @@ { "name": "doublePosition", "description": "Entity positions are represented with double", - "versions": ["1.9", "1.17.1"] + "versions": ["1.9", "1.18.1"] }, { "name": "fixedPointDelta", @@ -42,7 +42,7 @@ { "name": "fixedPointDelta128", "description": "Delta of position are represented with fixed point numbers times 128", - "versions": ["1.9", "1.17.1"] + "versions": ["1.9", "1.18.1"] }, { "name": "customChannelMCPrefixed", @@ -52,12 +52,12 @@ { "name": "customChannelIdentifier", "description": "custom channel is an identifier starting in minecraft namespace", - "versions": ["1.13", "1.17.1"] + "versions": ["1.13", "1.18.1"] }, { "name": "dimensionDataIsAvailable", "description": "dimensionData is available, providing an additional information about the current dimension", - "versions": ["1.17", "1.17.1"] + "versions": ["1.17", "1.18.1"] }, { "name": "useItemWithBlockPlace", @@ -67,7 +67,7 @@ { "name": "useItemWithOwnPacket", "description": "use item is done with its own packet", - "versions": ["1.9", "1.17.1"] + "versions": ["1.9", "1.18.1"] }, { "name": "blockPlaceHasHeldItem", @@ -87,7 +87,7 @@ { "name": "blockPlaceHasInsideBlock", "description": "block_place packet has inside block", - "versions": ["1.14", "1.17.1"] + "versions": ["1.14", "1.18.1"] }, { "name": "teleportUsesPositionPacket", @@ -102,7 +102,7 @@ { "name": "teleportUsesOwnPacket", "description": "teleport is done using its own packet", - "versions": ["1.9", "1.17.1"] + "versions": ["1.9", "1.18.1"] }, { "name": "oneBlockForSeveralVariations", @@ -112,7 +112,7 @@ { "name": "blockSchemeIsFlat", "description": "all variations of a packet have their own id", - "versions": ["1.13", "1.17.1"] + "versions": ["1.13", "1.18.1"] }, { "name": "tabCompleteHasNoToolTip", @@ -122,7 +122,7 @@ { "name": "tabCompleteHasAToolTip", "description": "tab complete has a tool tip", - "versions": ["1.13", "1.17.1"] + "versions": ["1.13", "1.18.1"] }, { "name": "effectAreMinecraftPrefixed", @@ -132,7 +132,7 @@ { "name": "effectAreNotPrefixed", "description": "effect are not prefixed", - "versions": ["1.13", "1.17.1"] + "versions": ["1.13", "1.18.1"] }, { "name": "itemsAreAlsoBlocks", @@ -142,12 +142,12 @@ { "name": "itemsAreNotBlocks", "description": "items are not block", - "versions": ["1.13", "1.17.1"] + "versions": ["1.13", "1.18.1"] }, { "name": "fishingBobberCorrectlyNamed", "description": "the fishing hook entity is named fishing_bobber", - "versions": ["1.14", "1.17.1"] + "versions": ["1.14", "1.18.1"] }, { "name": "editBookIsPluginChannel", @@ -157,7 +157,7 @@ { "name": "hasEditBookPacket", "description": "book editing is handled through a packet", - "versions": ["1.13", "1.17.1"] + "versions": ["1.13", "1.18.1"] }, { "name": "clientUpdateBookIdWhenSign", @@ -197,12 +197,12 @@ { "name": "dimensionIsAWorld", "description": "description is a world name (string)", - "versions": ["1.16.2", "1.17.1"] + "versions": ["1.16.2", "1.18.1"] }, { "name": "dimensionDataIsAvailable", "description": "dimensionData is available, describing additional dimension information", - "versions": ["1.17", "1.17.1"] + "versions": ["1.17", "1.18.1"] }, { "name": "doesntHaveChestType", @@ -227,22 +227,22 @@ { "name": "hasAttackCooldown", "description": "if there is a cooldown after attacks to deal full damage", - "versions": ["1.9", "1.17.1"] + "versions": ["1.9", "1.18.1"] }, { "name": "usesLoginPacket", "description": "uses the login packet as defined in mcData", - "versions": ["1.16", "1.17.1"] + "versions": ["1.16", "1.18.1"] }, { "name": "usesMultiblockSingleLong", "description": "in the multi_block_change packet is stored as a single number", - "versions": ["1.16.2", "1.17.1"] + "versions": ["1.16.2", "1.18.1"] }, { "name": "usesMultiblock3DChunkCoords", "description": "in the multi_block_change packet, all 3 axis coords are defined", - "versions": ["1.16.2", "1.17.1"] + "versions": ["1.16.2", "1.18.1"] }, { "name": "setBlockUsesMetadataNumber", @@ -257,7 +257,7 @@ { "name": "selectingTradeMovesItems", "description": "selecting a trade automatically puts the required items into trading slots", - "versions": ["1.14", "1.17.1"] + "versions": ["1.14", "1.18.1"] }, { "name": "resourcePackUsesHash", @@ -272,7 +272,7 @@ { "name": "teamUsesChatComponents", "description": "teams use chatcomponents for formatting", - "versions": ["1.13", "1.17.1"] + "versions": ["1.13", "1.18.1"] }, { "name": "teamUsesScoreboard", @@ -287,7 +287,7 @@ { "name": "enderCrystalNameNoCapsWithUnderscore", "description": "this is when the end_crystal's entity name is end_crystal", - "versions": ["1.14", "1.17.1"] + "versions": ["1.14", "1.18.1"] }, { "name": "entityNameUpperCaseNoUnderscore", @@ -307,7 +307,7 @@ { "name": "stateIdUsed", "description": "starting in 1.17.1, actionId has been replaced with stateId", - "versions": ["1.17.1", "1.17.1"] + "versions": ["1.17.1", "1.18.1"] }, { "name": "actionIdUsed", @@ -317,11 +317,16 @@ { "name": "setSlotAsTransaction", "description": "use setslot as transaction instead of just hoping it'll work", - "versions": ["1.17", "1.17.1"] + "versions": ["1.17", "1.18.1"] }, { "name": "armAnimationBeforeUse", "description": "arm animation packet sent before use entity packet", "versions": ["1.8", "1.8.9"] + }, + { + "name": "tallWorld", + "description": "world starts at -64 and ends at 384", + "versions": ["1.18", "1.18.1"] } ] diff --git a/lib/loader.js b/lib/loader.js index 79e264924..4b631b85c 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -63,7 +63,7 @@ function createBot (options = {}) { options.username = options.username ?? 'Player' options.version = options.version ?? false options.plugins = options.plugins ?? {} - options.hideErrors = options.hideErrors ?? true + options.hideErrors = options.hideErrors ?? false options.logErrors = options.logErrors ?? true options.loadInternalPlugins = options.loadInternalPlugins ?? true options.client = options.client ?? null diff --git a/lib/plugins/blocks.js b/lib/plugins/blocks.js index b12c32775..16dc7f6e2 100644 --- a/lib/plugins/blocks.js +++ b/lib/plugins/blocks.js @@ -42,13 +42,15 @@ function inject (bot, { version, storageBuilder }) { delete paintingsByPos[painting.position] } - function addBlockEntity (nbtData) { - const blockEntity = nbt.simplify(nbtData) - const pos = new Vec3(blockEntity.x, blockEntity.y, blockEntity.z).floored() + function addBlockEntity (nbtData, x, y, z, type) { + const blockEntity = nbtData === undefined ? {} : nbt.simplify(nbtData) + const pos = (x !== undefined ? new Vec3(x, y, z) : new Vec3(blockEntity.x, blockEntity.y, blockEntity.z)).floored() // Set raw nbt of blockEntity blockEntity.raw = nbtData + blockEntity.type = type + const signType = 7 // Handle signs - if (blockEntity.id === 'minecraft:sign' || blockEntity.id === 'Sign') { + if (blockEntity.id === 'minecraft:sign' || blockEntity.id === 'Sign' || blockEntity.type === signType) { const prepareJson = (i) => { const data = blockEntity[`Text${i}`] @@ -90,11 +92,7 @@ function inject (bot, { version, storageBuilder }) { let column = bot.world.getColumn(args.x, args.z) if (!column) { // Allocates new chunk object while taking world's custom min/max height into account - if (bot.supportFeature('dimensionDataIsAvailable')) { - column = new Chunk({ minY: bot.game.dimensionData.min_y, worldHeight: bot.game.dimensionData.height }) - } else { - column = new Chunk() - } + column = new Chunk({ minY: bot.game.minY, worldHeight: bot.game.height }) } try { @@ -102,6 +100,9 @@ function inject (bot, { version, storageBuilder }) { if (args.biomes !== undefined) { column.loadBiomes(args.biomes) } + if (args.skyLight !== undefined) { + column.loadParsedLight(args.skyLight, args.blockLight, args.skyLightMask, args.blockLightMask, args.emptySkyLightMask, args.emptyBlockLightMask) + } bot.world.setColumn(args.x, args.z, column) } catch (e) { bot.emit('error', e) @@ -206,13 +207,17 @@ function inject (bot, { version, storageBuilder }) { let next = start while (next) { const column = bot.world.getColumn(next.x, next.z) - if (next.y >= 0 && next.y < 16 && column && !visitedSections.has(next.toString())) { - const section = column.sections[next.y] + const sectionY = next.y + Math.abs(bot.game.minY >> 4) + const totalSections = bot.game.height >> 4 + if (sectionY >= 0 && sectionY < totalSections && column && !visitedSections.has(next.toString())) { + const section = column.sections[sectionY] if (useExtraInfo === true || isBlockInSection(section, matcher)) { - const cursor = new Vec3(0, 0, 0) - for (cursor.x = next.x * 16; cursor.x < next.x * 16 + 16; cursor.x++) { - for (cursor.y = next.y * 16; cursor.y < next.y * 16 + 16; cursor.y++) { - for (cursor.z = next.z * 16; cursor.z < next.z * 16 + 16; cursor.z++) { + const begin = new Vec3(next.x * 16, sectionY * 16 + bot.game.minY, next.z * 16) + const cursor = begin.clone() + const end = cursor.offset(16, 16, 16) + for (cursor.x = begin.x; cursor.x < end.x; cursor.x++) { + for (cursor.y = begin.y; cursor.y < end.y; cursor.y++) { + for (cursor.z = begin.z; cursor.z < end.z; cursor.z++) { if (fullMatcher(cursor) && cursor.distanceTo(point) <= maxDistance) blocks.push(cursor.clone()) } } @@ -299,11 +304,7 @@ function inject (bot, { version, storageBuilder }) { bot._client.on('update_light', (packet) => { let column = bot.world.getColumn(packet.chunkX, packet.chunkZ) if (!column) { - if (bot.supportFeature('dimensionDataIsAvailable')) { - column = new Chunk({ minY: bot.game.dimensionData.min_y, worldHeight: bot.game.dimensionData.height }) - } else { - column = new Chunk() - } + column = new Chunk({ minY: bot.game.minY, worldHeight: bot.game.height }) bot.world.setColumn(packet.chunkX, packet.chunkZ, column) } @@ -323,12 +324,23 @@ function inject (bot, { version, storageBuilder }) { biomes: packet.biomes, skyLightSent: bot.game.dimension === 'minecraft:overworld', groundUp: packet.groundUp, - data: packet.chunkData + data: packet.chunkData, + trustEdges: packet.trustEdges, + skyLightMask: packet.skyLightMask, + blockLightMask: packet.blockLightMask, + emptySkyLightMask: packet.emptySkyLightMask, + emptyBlockLightMask: packet.emptyBlockLightMask, + skyLight: packet.skyLight, + blockLight: packet.blockLight }) if (typeof packet.blockEntities !== 'undefined') { - for (const nbtData of packet.blockEntities) { - addBlockEntity(nbtData) + for (const blockEntity of packet.blockEntities) { + if (blockEntity.x !== undefined) { + addBlockEntity(blockEntity.nbtData, blockEntity.x, blockEntity.y, blockEntity.z, blockEntity.type) + } else { + addBlockEntity(blockEntity) + } } } }) @@ -448,7 +460,11 @@ function inject (bot, { version, storageBuilder }) { }) bot._client.on('tile_entity_data', (packet) => { - addBlockEntity(packet.nbtData) + if (packet.location !== undefined) { + addBlockEntity(packet.nbtData, packet.location.x, packet.location.y, packet.location.z, packet.action) + } else { + addBlockEntity(packet.nbtData) + } }) bot.updateSign = (block, text) => { diff --git a/lib/plugins/game.js b/lib/plugins/game.js index 1908037b9..25946d994 100644 --- a/lib/plugins/game.js +++ b/lib/plugins/game.js @@ -37,7 +37,12 @@ function inject (bot, options) { } if (bot.supportFeature('dimensionDataIsAvailable')) { - bot.game.dimensionData = nbt.simplify(packet.dimension) + const dimensionData = nbt.simplify(packet.dimension) + bot.game.minY = dimensionData.min_y + bot.game.height = dimensionData.height + } else { + bot.game.minY = 0 + bot.game.height = 256 } if (packet.difficulty) { bot.game.difficulty = difficultyNames[packet.difficulty] diff --git a/lib/version.js b/lib/version.js index 33de0aabe..5783dc678 100644 --- a/lib/version.js +++ b/lib/version.js @@ -1,4 +1,4 @@ module.exports = { - supportedVersions: ['1.8', '1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16', '1.17'], - testedVersions: ['1.8.8', '1.9.4', '1.10.2', '1.11.2', '1.12.2', '1.13.2', '1.14.4', '1.15.2', '1.16.5', '1.17.1'] + supportedVersions: ['1.8', '1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16', '1.17', '1.18'], + testedVersions: ['1.8.8', '1.9.4', '1.10.2', '1.11.2', '1.12.2', '1.13.2', '1.14.4', '1.15.2', '1.16.5', '1.17.1', '1.18.1'] } // when updating testedVersions, make sure to update CI.yml diff --git a/package.json b/package.json index 64af8e45e..04ac08621 100644 --- a/package.json +++ b/package.json @@ -21,12 +21,12 @@ }, "license": "MIT", "dependencies": { - "minecraft-data": "^2.95.0", + "minecraft-data": "^2.109.0", "minecraft-protocol": "^1.26.5", "prismarine-biome": "^1.1.1", "prismarine-block": "^1.10.3", "prismarine-chat": "^1.3.3", - "prismarine-chunk": "^1.26.0", + "prismarine-chunk": "^1.28.1", "prismarine-entity": "^2.0.0", "prismarine-item": "^1.11.0", "prismarine-nbt": "^2.0.0", diff --git a/test/externalTests/exampleInventory.js b/test/externalTests/exampleInventory.js index 511e39952..68e93b55a 100644 --- a/test/externalTests/exampleInventory.js +++ b/test/externalTests/exampleInventory.js @@ -52,7 +52,7 @@ module.exports = () => async (bot) => { assert.strictEqual(name, 'inventory') bot.chat('/op inventory') // to counteract spawn protection bot.chat('/clear inventory') - bot.chat('/setblock 52 4 0 crafting_table') // to make stone bricks stairs + bot.chat(`/setblock 52 ${bot.test.groundY} 0 crafting_table`) // to make stone bricks stairs bot.chat('/give inventory dirt 64') bot.chat('/give inventory stick 7') bot.chat('/give inventory iron_ore 64') @@ -67,7 +67,7 @@ module.exports = () => async (bot) => { await bot.test.wait(100) } // cleanup - bot.chat('/setblock 52 4 0 air') + bot.chat(`/setblock 52 ${bot.test.groundY} 0 air`) cb() function makeTest (inStr, outStr) { diff --git a/test/externalTests/plugins/testCommon.js b/test/externalTests/plugins/testCommon.js index 91fc5cb55..2e3c40330 100644 --- a/test/externalTests/plugins/testCommon.js +++ b/test/externalTests/plugins/testCommon.js @@ -14,6 +14,7 @@ function inject (bot) { const Item = require('prismarine-item')(bot.version) bot.test = {} + bot.test.groundY = bot.supportFeature('tallWorld') ? -60 : 4 bot.test.sayEverywhere = sayEverywhere bot.test.clearInventory = callbackify(clearInventory) bot.test.becomeSurvival = callbackify(becomeSurvival) @@ -68,7 +69,8 @@ function inject (bot) { async function resetBlocksToSuperflat () { const groundY = 4 for (let y = groundY + 4; y >= groundY - 1; y--) { - bot.chat(`/fill ~-5 ${y} ~-5 ~5 ${y} ~5 ` + layerNames[y]) + const realY = y + bot.test.groundY - 4 + bot.chat(`/fill ~-5 ${realY} ~-5 ~5 ${realY} ~5 ` + layerNames[y]) } await bot.test.wait(100) } @@ -85,7 +87,7 @@ function inject (bot) { await becomeCreative() await clearInventory() bot.creative.startFlying() - await teleport(new Vec3(0, 4, 0)) + await teleport(new Vec3(0, bot.test.groundY, 0)) await bot.waitForChunksToLoad() await resetBlocksToSuperflat() await sleep(1000) @@ -197,7 +199,7 @@ function inject (bot) { checkCondition: message => message.json.translate === 'multiplayer.player.joined' }) childBotName = message.json.with[0].insertion - bot.chat(`/tp ${childBotName} 50 4 0`) + bot.chat(`/tp ${childBotName} 50 ${bot.test.groundY} 0`) setTimeout(() => { bot.chat('loaded') }, 5000) diff --git a/test/externalTests/useChests.js b/test/externalTests/useChests.js index faa6910c5..c7bcf9e56 100644 --- a/test/externalTests/useChests.js +++ b/test/externalTests/useChests.js @@ -6,12 +6,14 @@ module.exports = () => async (bot) => { const mcData = require('minecraft-data')(bot.version) const Item = require('prismarine-item')(bot.version) - const smallChestLocation = new Vec3(0, 4, -1) - const largeChestLocations = [new Vec3(0, 4, 1), new Vec3(1, 4, 1)] - const smallTrappedChestLocation = new Vec3(1, 4, 0) + bot.test.groundY = bot.supportFeature('tallWorld') ? -60 : 4 + + const smallChestLocation = new Vec3(0, bot.test.groundY, -1) + const largeChestLocations = [new Vec3(0, bot.test.groundY, 1), new Vec3(1, bot.test.groundY, 1)] + const smallTrappedChestLocation = new Vec3(1, bot.test.groundY, 0) const largeTrappedChestLocations = [ - new Vec3(-1, 4, 1), - new Vec3(-1, 4, 0) + new Vec3(-1, bot.test.groundY, 1), + new Vec3(-1, bot.test.groundY, 0) ] const chestSlot = 36 const trappedChestSlot = 37 diff --git a/test/internalTest.js b/test/internalTest.js index 449c6f34a..fd58adfb3 100644 --- a/test/internalTest.js +++ b/test/internalTest.js @@ -10,6 +10,33 @@ for (const supportedVersion of mineflayer.testedVersions) { const version = mcData.version const Chunk = require('prismarine-chunk')(supportedVersion) + function generateChunkPacket (chunk) { + const lights = chunk.dumpLight() + return { + x: 0, + z: 0, + groundUp: true, + biomes: chunk.dumpBiomes !== undefined ? chunk.dumpBiomes() : undefined, + heightmaps: { + type: 'compound', + name: '', + value: { + MOTION_BLOCKING: { type: 'longArray', value: new Array(36).fill([0, 0]) } + } + }, // send fake heightmap + bitMap: chunk.getMask(), + chunkData: chunk.dump(), + blockEntities: [], + trustEdges: false, + skyLightMask: lights?.skyLightMask, + blockLightMask: lights?.blockLightMask, + emptySkyLightMask: lights?.emptySkyLightMask, + emptyBlockLightMask: lights?.emptyBlockLightMask, + skyLight: lights?.skyLight, + blockLight: lights?.blockLight + } + } + describe(`mineflayer_internal ${version.minecraftVersion}`, function () { this.timeout(10 * 1000) let bot @@ -27,6 +54,39 @@ for (const supportedVersion of mineflayer.testedVersions) { version: supportedVersion, port: 25567 }) + bot.test = {} + + bot.test.buildChunk = () => { + if (bot.supportFeature('tallWorld')) { + return new Chunk({ minY: -64, worldHeight: 384 }) + } else { + return new Chunk() + } + } + + bot.test.generateLoginPacket = () => { + let loginPacket + if (bot.supportFeature('usesLoginPacket')) { + loginPacket = mcData.loginPacket + loginPacket.entityId = 0 // Default login packet in minecraft-data 1.16.5 is 1, so set it to 0 + } else { + loginPacket = { + entityId: 0, + levelType: 'fogetaboutit', + gameMode: 0, + previousGameMode: 255, + worldNames: ['minecraft:overworld'], + dimension: 0, + worldName: 'minecraft:overworld', + hashedSeed: [0, 0], + difficulty: 0, + maxPlayers: 20, + reducedDebugInfo: 1, + enableRespawnScreen: true + } + } + return loginPacket + } done() }) }) @@ -104,46 +164,10 @@ for (const supportedVersion of mineflayer.testedVersions) { done() }) server.on('login', (client) => { - let loginPacket - if (bot.supportFeature('usesLoginPacket')) { - loginPacket = mcData.loginPacket - } else { - loginPacket = { - entityId: 0, - levelType: 'fogetaboutit', - gameMode: 0, - previousGameMode: 255, - worldNames: ['minecraft:overworld'], - dimension: 0, - worldName: 'minecraft:overworld', - hashedSeed: [0, 0], - difficulty: 0, - maxPlayers: 20, - reducedDebugInfo: 1, - enableRespawnScreen: true - } - } - - client.write('login', loginPacket) - const chunk = new Chunk() - + client.write('login', bot.test.generateLoginPacket()) + const chunk = bot.test.buildChunk() chunk.setBlockType(pos, goldId) - client.write('map_chunk', { - x: 0, - z: 0, - groundUp: true, - biomes: chunk.dumpBiomes !== undefined ? chunk.dumpBiomes() : undefined, - heightmaps: { - type: 'compound', - name: '', - value: { - MOTION_BLOCKING: { type: 'longArray', value: new Array(36).fill([0, 0]) } - } - }, // send fake heightmap - bitMap: chunk.getMask(), - chunkData: chunk.dump(), - blockEntities: [] - }) + client.write('map_chunk', generateChunkPacket(chunk)) }) }) @@ -168,45 +192,11 @@ for (const supportedVersion of mineflayer.testedVersions) { } }) server.on('login', (client) => { - let loginPacket - if (bot.supportFeature('usesLoginPacket')) { - loginPacket = mcData.loginPacket - } else { - loginPacket = { - entityId: 0, - levelType: 'fogetaboutit', - gameMode: 0, - previousGameMode: 255, - worldNames: ['minecraft:overworld'], - dimension: 0, - worldName: 'minecraft:overworld', - hashedSeed: [0, 0], - difficulty: 0, - maxPlayers: 20, - reducedDebugInfo: 1, - enableRespawnScreen: true - } - } - client.write('login', loginPacket) - const chunk = new Chunk() + client.write('login', bot.test.generateLoginPacket()) + const chunk = bot.test.buildChunk() chunk.setBlockType(pos, goldId) - client.write('map_chunk', { - x: 0, - z: 0, - groundUp: true, - biomes: chunk.dumpBiomes !== undefined ? chunk.dumpBiomes() : undefined, - heightmaps: { - type: 'compound', - name: '', - value: { - MOTION_BLOCKING: { type: 'longArray', value: new Array(36).fill([0, 0]) } - } - }, // send fake heightmap - bitMap: chunk.getMask(), - chunkData: chunk.dump(), - blockEntities: [] - }) + client.write('map_chunk', generateChunkPacket(chunk)) client.write('position', { x: 1.5, y: 80, @@ -224,10 +214,9 @@ for (const supportedVersion of mineflayer.testedVersions) { const pos = vec3(1, 65, 1) const goldId = 41 it('switchWorld respawn', (done) => { - let loginPacket + const loginPacket = bot.test.generateLoginPacket() let respawnPacket if (bot.supportFeature('usesLoginPacket')) { - loginPacket = mcData.loginPacket loginPacket.worldName = 'minecraft:overworld' loginPacket.hashedSeed = [0, 0] loginPacket.entityId = 0 @@ -248,39 +237,10 @@ for (const supportedVersion of mineflayer.testedVersions) { gamemode: 0, levelType: 'default' } - loginPacket = { - entityId: 0, - levelType: 'fogetaboutit', - gameMode: 0, - previousGameMode: 255, - worldNames: ['minecraft:overworld', 'minecraft:nether', 'minecraft:the_end'], - dimension: 0, - worldName: 'minecraft:overworld', - hashedSeed: [0, 0], - difficulty: 0, - maxPlayers: 20, - reducedDebugInfo: 1, - enableRespawnScreen: true - } } - const chunk = new Chunk() + const chunk = bot.test.buildChunk() chunk.setBlockType(pos, goldId) - const chunkPacket = { - x: 0, - z: 0, - groundUp: true, - biomes: chunk.dumpBiomes !== undefined ? chunk.dumpBiomes() : undefined, - heightmaps: { - type: 'compound', - name: '', - value: { - MOTION_BLOCKING: { type: 'longArray', value: new Array(36).fill([0, 0]) } - } - }, // send fake heightmap - bitMap: chunk.getMask(), - chunkData: chunk.dump(), - blockEntities: [] - } + const chunkPacket = generateChunkPacket(chunk) const positionPacket = { x: 1.5, y: 80, @@ -344,26 +304,10 @@ for (const supportedVersion of mineflayer.testedVersions) { describe('entities', () => { it('entity id changes on login', (done) => { - let loginPacket + const loginPacket = bot.test.generateLoginPacket() server.on('login', (client) => { if (bot.supportFeature('usesLoginPacket')) { - loginPacket = mcData.loginPacket loginPacket.entityId = 0 // Default login packet in minecraft-data 1.16.5 is 1, so set it to 0 - } else { - loginPacket = { - entityId: 0, - levelType: 'fogetaboutit', - gameMode: 0, - previousGameMode: 255, - worldNames: ['minecraft:overworld'], - dimension: 0, - worldName: 'minecraft:overworld', - hashedSeed: [0, 0], - difficulty: 0, - maxPlayers: 20, - reducedDebugInfo: 1, - enableRespawnScreen: true - } } client.write('login', loginPacket) bot.once('login', () => { @@ -659,28 +603,10 @@ for (const supportedVersion of mineflayer.testedVersions) { server.once('login', (client) => { bot.time.timeOfDay = 18000 - let loginPacket - if (bot.supportFeature('usesLoginPacket')) { - loginPacket = mcData.loginPacket - } else { - loginPacket = { - entityId: 0, - levelType: 'fogetaboutit', - gameMode: 0, - previousGameMode: 255, - worldNames: ['minecraft:overworld'], - dimension: 0, - worldName: 'minecraft:overworld', - hashedSeed: [0, 0], - difficulty: 0, - maxPlayers: 20, - reducedDebugInfo: 1, - enableRespawnScreen: true - } - } + const loginPacket = bot.test.generateLoginPacket() client.write('login', loginPacket) - const chunk = new Chunk() + const chunk = bot.test.buildChunk() for (const bed in beds) { chunk.setBlockType(beds[bed].head, bedId) @@ -739,22 +665,7 @@ for (const supportedVersion of mineflayer.testedVersions) { metadata: [] }) - client.write('map_chunk', { - x: 0, - z: 0, - groundUp: true, - biomes: chunk.dumpBiomes !== undefined ? chunk.dumpBiomes() : undefined, - heightmaps: { - type: 'compound', - name: '', - value: { - MOTION_BLOCKING: { type: 'longArray', value: new Array(36).fill([0, 0]) } - } - }, // send fake heightmap - bitMap: chunk.getMask(), - chunkData: chunk.dump(), - blockEntities: [] - }) + client.write('map_chunk', generateChunkPacket(chunk)) }) })