Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.20.6 #3412

Merged
merged 38 commits into from
Oct 13, 2024
Merged

1.20.6 #3412

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
78df793
1.20.5
extremeheat Jul 2, 2024
8b82952
lint
extremeheat Jul 2, 2024
8894dfe
fix
extremeheat Jul 2, 2024
bf471fb
update registry
extremeheat Jul 6, 2024
cd3b5fb
update java
extremeheat Jul 6, 2024
cbe3670
add debug
extremeheat Jul 7, 2024
d4b549a
fix
extremeheat Jul 7, 2024
a337794
debug
extremeheat Jul 7, 2024
2950649
Update testCommon.js
extremeheat Jul 7, 2024
69511d7
update ci
extremeheat Jul 20, 2024
e0499cb
add protodef AOT compile code
extremeheat Aug 25, 2024
15a0ae5
Update protodefCompile.js
extremeheat Aug 26, 2024
373dd23
Update testCommon.js
extremeheat Aug 26, 2024
7a8bb0a
pitem, fix `login` event
extremeheat Aug 29, 2024
ff8c48f
debug
extremeheat Aug 29, 2024
cb5aedc
Update testCommon.js
extremeheat Aug 29, 2024
c8786c7
Update package.json test
extremeheat Aug 29, 2024
2db4366
Update package.json
extremeheat Aug 29, 2024
bf0bd1f
update test events
extremeheat Sep 8, 2024
6821e8a
Update testCommon.js
extremeheat Sep 8, 2024
f7d830d
update
extremeheat Sep 8, 2024
307ef39
fix pitem source
extremeheat Sep 8, 2024
11245f2
remove some debug logging
extremeheat Sep 8, 2024
8794fa3
update
extremeheat Sep 20, 2024
3f6786b
Fix trade test
extremeheat Oct 12, 2024
18d1e6b
remove manual protodef install from ci
rom1504 Oct 12, 2024
b53b0ff
remove unnecessary install in ci
rom1504 Oct 12, 2024
4bd6cbe
change back version.js to support latest version
rom1504 Oct 12, 2024
3b352b6
update deps
rom1504 Oct 12, 2024
349e17a
remove compile protocol in ci
rom1504 Oct 12, 2024
e15e4d8
bump to support 1.20.6
rom1504 Oct 12, 2024
70a14ea
in tests teleport to overworld to prevent nether test to break the en…
rom1504 Oct 13, 2024
f10c891
fix respawn in internal tests
rom1504 Oct 13, 2024
8eaa94e
use normal tp before 1.14
rom1504 Oct 13, 2024
bc724d8
lint
rom1504 Oct 13, 2024
911a53e
fix held item test
rom1504 Oct 13, 2024
7bfdb2c
fix item drop internal test for 1.20.6
rom1504 Oct 13, 2024
679cc13
cleanup
rom1504 Oct 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
- name: Setup Java JDK
uses: actions/[email protected]
with:
java-version: 17
java-version: 21
java-package: jre
- name: Install Dependencies
run: npm install
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ test/server_*
.vscode
.DS_Store
launcher_accounts.json
data
2 changes: 1 addition & 1 deletion .gitpod.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
tasks:
- command: npm install
- command: npm install && sdk install java
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ First time using Node.js? You may want to start with the [tutorial](tutorial.md)

## Features

* Supports Minecraft 1.8 to 1.20.4 (1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19 and 1.20)
* Supports Minecraft 1.8 to 1.20.5 (1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19 and 1.20 upto 1.20.6)
* 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
Expand Down
1 change: 1 addition & 0 deletions lib/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ function createBot (options = {}) {
}).map(key => options.plugins[key])
bot.loadPlugins([...internalPlugins, ...externalPlugins])

options.validateChannelProtocol = false
bot._client = bot._client ?? mc.createClient(options)
bot._client.on('connect', () => {
bot.emit('connect')
Expand Down
30 changes: 21 additions & 9 deletions lib/particle.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ module.exports = loader
function loader (registry) {
class Particle {
constructor (id, position, offset, count = 1, movementSpeed = 0, longDistanceRender = false) {
Object.assign(this, registry.particles[id])
this.id = id
Object.assign(this, registry.particles[id] || registry.particlesByName[id])
this.position = position
this.offset = offset
this.count = count
Expand All @@ -15,14 +15,26 @@ function loader (registry) {
}

static fromNetwork (packet) {
return new Particle(
packet.particleId,
new Vec3(packet.x, packet.y, packet.z),
new Vec3(packet.offsetX, packet.offsetY, packet.offsetZ),
packet.particles,
packet.particleData,
packet.longDistance
)
if (registry.supportFeature('updatedParticlesPacket')) {
// TODO: We add extra data that's inside packet.particle.data that varies by the particle's .type
return new Particle(
packet.particle.type,
new Vec3(packet.x, packet.y, packet.z),
new Vec3(packet.offsetX, packet.offsetY, packet.offsetZ),
packet.amount,
packet.velocityOffset,
packet.longDistance
)
} else {
return new Particle(
packet.particleId,
new Vec3(packet.x, packet.y, packet.z),
new Vec3(packet.offsetX, packet.offsetY, packet.offsetZ),
packet.particles,
packet.particleData,
packet.longDistance
)
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions lib/plugins/blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,9 @@ function inject (bot, { version, storageBuilder, hideErrors }) {
if (bot.supportFeature('dimensionIsAnInt')) {
dimension = packet.dimension
worldName = dimensionToFolderName(dimension)
} else if (bot.supportFeature('spawnRespawnWorldDataField')) { // 1.20.5+
dimension = packet.worldState.dimension
worldName = packet.worldState.name
} else {
dimension = packet.dimension
worldName = /^minecraft:.+/.test(packet.worldName) ? packet.worldName : `minecraft:${packet.worldName}`
Expand All @@ -542,6 +545,11 @@ function inject (bot, { version, storageBuilder, hideErrors }) {
if (bot.supportFeature('dimensionIsAnInt')) { // <=1.15.2
if (dimension === packet.dimension) return
dimension = packet.dimension
} else if (bot.supportFeature('spawnRespawnWorldDataField')) { // 1.20.5+
if (dimension === packet.worldState.dimension) return
if (worldName === packet.worldState.name && packet.copyMetadata === true) return // don't unload chunks if in same world and metaData is true
dimension = packet.worldState.dimension
worldName = packet.worldState.name
} else { // >= 1.15.2
if (dimension === packet.dimension) return
if (worldName === packet.worldName && packet.copyMetadata === true) return // don't unload chunks if in same world and metaData is true
Expand Down
22 changes: 12 additions & 10 deletions lib/plugins/breath.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
module.exports = inject

function inject (bot) {
if (bot.supportFeature('mcDataHasEntityMetadata')) {
// this is handled inside entities.js. We don't yet have entity metadataKeys for all versions but once we do
// we can delete the numerical checks here and in entities.js https://github.com/extremeheat/mineflayer/blob/eb9982aa04973b0086aac68a2847005d77f01a3d/lib/plugins/entities.js#L469
return
}
bot._client.on('entity_metadata', (packet) => {
if (!bot?.entity?.id === packet?.entityId) return
if (packet?.metadata[1]?.key === 1) {
if (!packet?.metadata[1]?.value) return
bot.oxygenLevel = Math.round(packet.metadata[1].value / 15)
bot.emit('breath')
}
if (packet?.metadata[0]?.key === 1) {
if (!packet?.metadata[0]?.value) return
bot.oxygenLevel = Math.round(packet.metadata[0].value / 15)
bot.emit('breath')
if (!bot.entity) return
if (bot.entity.id !== packet.entityId) return
for (const metadata of packet.metadata) {
if (metadata.key === 1) {
bot.oxygenLevel = Math.round(packet.metadata[1].value / 15)
bot.emit('breath')
}
}
})
}
5 changes: 4 additions & 1 deletion lib/plugins/creative.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ function inject (bot) {
item: Item.toNotch(item)
})

await onceWithCleanup(bot.inventory, `updateSlot:${slot}`, { checkCondition: (oldItem, newItem) => item === null ? newItem === null : newItem?.name === item.name && newItem?.count === item.count && newItem?.metadata === item.metadata })
await onceWithCleanup(bot.inventory, `updateSlot:${slot}`, {
timeout: 5000,
checkCondition: (oldItem, newItem) => item === null ? newItem === null : newItem?.name === item.name && newItem?.count === item.count && newItem?.metadata === item.metadata
})
creativeSlotsUpdates[slot] = false
}

Expand Down
6 changes: 6 additions & 0 deletions lib/plugins/entities.js
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,12 @@ function inject (bot) {
bot.emit('entityUncrouch', entity)
}
}

// Breathing (formerly in breath.js)
if (metas.air_supply != null) {
bot.oxygenLevel = Math.round(metas.air_supply / 15)
bot.emit('breath')
}
} else {
const typeSlot = (bot.supportFeature('itemsAreAlsoBlocks') ? 5 : 6) + (bot.supportFeature('entityMetadataHasLong') ? 1 : 0)
const slot = packet.metadata.find(e => e.type === typeSlot)
Expand Down
9 changes: 7 additions & 2 deletions lib/plugins/fishing.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@ function inject (bot) {
if (!lastBobber || fishingTask.done) return

const pos = lastBobber.position
const parts = bot.registry.particlesByName
if (packet.particleId === (parts?.fishing ?? parts.bubble).id && packet.particles === 6 && pos.distanceTo(new Vec3(packet.x, pos.y, packet.z)) <= 1.23) {

const bobberCondition = bot.registry.supportFeature('updatedParticlesPacket')
? ((packet.particle.type === 'fishing' || packet.particle.type === 'bubble') && packet.amount === 6 && pos.distanceTo(new Vec3(packet.x, pos.y, packet.z)) <= 1.23)
// This "(particles.fishing ?? particles.bubble).id" condition doesn't make sense (these are both valid types)
: (packet.particleId === (bot.registry.particlesByName.fishing ?? bot.registry.particlesByName.bubble).id && packet.particles === 6 && pos.distanceTo(new Vec3(packet.x, pos.y, packet.z)) <= 1.23)

if (bobberCondition) {
bot.activateItem()
lastBobber = undefined
fishingTask.finish()
Expand Down
42 changes: 25 additions & 17 deletions lib/plugins/game.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,14 @@ 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 = parseGameMode(packet.gameMode)
if (bot.supportFeature('dimensionIsAnInt')) {
bot.game.gameMode = packet.gamemode || parseGameMode(packet.gameMode)
if (bot.supportFeature('segmentedRegistryCodecData')) { // 1.20.5
if (typeof packet.dimension === 'number') {
bot.game.dimension = bot.registry.dimensionsArray[packet.dimension]?.name?.replace('minecraft:', '')
} else if (typeof packet.dimension === 'string') { // iirc, in 1.21 it's back to a string
bot.game.dimension = packet.dimension.replace('minecraft:', '')
}
} else if (bot.supportFeature('dimensionIsAnInt')) {
bot.game.dimension = dimensionNames[packet.dimension]
} else if (bot.supportFeature('dimensionIsAString')) {
bot.game.dimension = packet.dimension.replace('minecraft:', '')
Expand All @@ -40,25 +46,25 @@ function inject (bot, options) {
bot.registry.loadDimensionCodec(packet.dimensionCodec)
}

bot.game.minY = 0
bot.game.height = 256

if (bot.supportFeature('dimensionDataInCodec')) { // 1.19+
if (packet.worldType) { // login
// pre 1.20.5 before we consolidated login and respawn's SpawnInfo structure into one type,
// "dimension" was called "worldType" in login_packet's payload but not respawn.
if (packet.worldType && !bot.game.dimension) {
bot.game.dimension = packet.worldType.replace('minecraft:', '')
const { minY, height } = bot.registry.dimensionsByName[bot.game.dimension]
bot.game.minY = minY
bot.game.height = height
} else if (packet.dimension) { // respawn
bot.game.dimension = packet.dimension.replace('minecraft:', '')
const { minY, height } = bot.registry.dimensionsByName[bot.game.dimension]
bot.game.minY = minY
bot.game.height = height
}
console.log('*Dimension data', bot.game.dimension, bot.registry.dimensionsByName, packet)
const dimData = bot.registry.dimensionsByName[bot.game.dimension]
if (dimData) {
bot.game.minY = dimData.minY
bot.game.height = dimData.height
}
} else if (bot.supportFeature('dimensionDataIsAvailable')) { // 1.18
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) {
Expand All @@ -73,11 +79,12 @@ function inject (bot, options) {

// 1.20.2
bot._client.on('registry_data', (packet) => {
bot.registry.loadDimensionCodec(packet.codec)
console.log('Loading Dimension Codec', JSON.stringify(packet).slice(0, 100))
bot.registry.loadDimensionCodec(packet.codec || packet)
})

bot._client.on('login', (packet) => {
handleRespawnPacketData(packet)
handleRespawnPacketData(packet.worldState || packet)

bot.game.maxPlayers = packet.maxPlayers
if (packet.enableRespawnScreen) {
Expand All @@ -95,7 +102,8 @@ function inject (bot, options) {
})

bot._client.on('respawn', (packet) => {
handleRespawnPacketData(packet)
// in 1.20.5+ protocol we move the shared spawn data into one SpawnInfo type under .worldState
handleRespawnPacketData(packet.worldState || packet)
bot.emit('game')
})

Expand Down
2 changes: 1 addition & 1 deletion lib/version.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const 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.2', '1.19', '1.19.2', '1.19.3', '1.19.4', '1.20.1', '1.20.2', '1.20.4']
const 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.2', '1.19', '1.19.2', '1.19.3', '1.19.4', '1.20.1', '1.20.2', '1.20.4', '1.20.6']
module.exports = {

testedVersions,
Expand Down
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "index.js",
"types": "index.d.ts",
"scripts": {
"mocha_test": "mocha --reporter spec --exit",
"mocha_test": "mocha --reporter spec --exit --bail",
"test": "npm run mocha_test",
"pretest": "npm run lint",
"lint": "standard && standard-markdown",
Expand All @@ -21,21 +21,21 @@
},
"license": "MIT",
"dependencies": {
"minecraft-data": "^3.56.0",
"minecraft-protocol": "^1.47.0",
"minecraft-data": "^3.76.0",
"minecraft-protocol": "^1.49.0",
"prismarine-biome": "^1.1.1",
"prismarine-block": "^1.17.0",
"prismarine-chat": "^1.7.1",
"prismarine-chunk": "^1.34.0",
"prismarine-entity": "^2.3.0",
"prismarine-item": "^1.14.0",
"prismarine-item": "^1.15.0",
"prismarine-nbt": "^2.0.0",
"prismarine-physics": "^1.8.0",
"prismarine-recipe": "^1.3.0",
"prismarine-registry": "^1.5.0",
"prismarine-registry": "^1.8.0",
"prismarine-windows": "^2.9.0",
"prismarine-world": "^3.6.0",
"protodef": "^1.14.0",
"protodef": "1.17.0",
"typed-emitter": "^1.0.0",
"vec3": "^0.1.7"
},
Expand All @@ -45,6 +45,7 @@
"minecraft-wrap": "^1.3.0",
"mineflayer": "file:.",
"mocha": "^10.0.0",
"protodef-yaml": "^1.5.3",
"standard": "^17.0.0",
"standard-markdown": "^7.1.0",
"typescript": "^5.4.5"
Expand Down
2 changes: 1 addition & 1 deletion test/externalTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ for (const supportedVersion of mineflayer.testedVersions) {
const runTest = (testName, testFunction) => {
return function (done) {
this.timeout(TEST_TIMEOUT_MS)
bot.test.sayEverywhere(`starting ${testName}`)
bot.test.sayEverywhere(`### Starting ${testName}`)
testFunction(bot, done).then(res => done()).catch(e => done(e))
}
}
Expand Down
1 change: 1 addition & 0 deletions test/externalTests/heldItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module.exports = () => async (bot) => {

await bot.test.becomeCreative()
await bot.test.clearInventory()
await bot.test.wait(100)
assert.equal(bot.heldItem, null)

const stoneId = bot.registry.itemsByName.stone.id
Expand Down
4 changes: 3 additions & 1 deletion test/externalTests/nether.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ module.exports = () => async (bot) => {

const p = new Promise((resolve, reject) => {
bot._client.on('open_sign_entity', (packet) => {
console.log('Open sign', packet)
const sign = bot.blockAt(new Vec3(packet.location))
bot.updateSign(sign, '1\n2\n3\n')

setTimeout(() => {
// Get updated sign
const sign = bot.blockAt(bot.entity.position)
console.log('Updated sign', sign)

assert.strictEqual(sign.signText.trimEnd(), '1\n2\n3')

Expand Down Expand Up @@ -48,5 +50,5 @@ module.exports = () => async (bot) => {
await bot.lookAt(lowerBlock.position, true)
await bot.test.setInventorySlot(36, new Item(signItem.id, 1, 0))
await bot.placeBlock(lowerBlock, new Vec3(0, 1, 0))
return p
await p
}
6 changes: 5 additions & 1 deletion test/externalTests/particles.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ module.exports = () => async (bot) => {

return new Promise((resolve, reject) => {
function onParticleEvent (particle) {
assert.strictEqual(particle.id, particleData.id)
if (typeof particle.id === 'number') {
assert.strictEqual(particle.id, particleData.id)
} else {
assert.strictEqual(particle.id, particleData.name)
}
assert.strictEqual(particle.name, particleData.name)
assert.strictEqual(particle.position.x, bot.entity.position.x)
assert.strictEqual(particle.position.y, bot.entity.position.y)
Expand Down
Loading
Loading