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

Add dimensionChange event #3275

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitpod.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
tasks:
- command: sdk install java < /dev/null # install java v20
- command: npm install
6 changes: 6 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1354,6 +1354,12 @@ comparison.

Note that `oldBlock` may be `null`.

#### "dimensionChange" (dimension)

Emitted after the dimension the bot is in has changed.

* `dimension` - The dimension that was switched to

#### "blockPlaced" (oldBlock, newBlock)

Fires when bot places block. Both `oldBlock` and `newBlock` provided for
Expand Down
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export interface BotEvents {
playerLeft: (entity: Player) => Promise<void> | void
blockUpdate: (oldBlock: Block | null, newBlock: Block) => Promise<void> | void
'blockUpdate:(x, y, z)': (oldBlock: Block | null, newBlock: Block | null) => Promise<void> | void
dimensionChange: (dimension: Dimension) => Promise<void> | void
chunkColumnLoad: (entity: Vec3) => Promise<void> | void
chunkColumnUnload: (entity: Vec3) => Promise<void> | void
soundEffectHeard: (
Expand Down
13 changes: 9 additions & 4 deletions lib/plugins/blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ const paintingFaceToVec = [
new Vec3(1, 0, 0)
]

const dimensionNames = {
'-1': 'minecraft:nether',
const dimensionIdentifiers = {
'-1': 'minecraft:the_nether',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you sure its the_nether and not world_nether?

0: 'minecraft:overworld',
1: 'minecraft:end'
1: 'minecraft:the_end'
}

function inject (bot, { version, storageBuilder, hideErrors }) {
Expand Down Expand Up @@ -493,7 +493,7 @@ function inject (bot, { version, storageBuilder, hideErrors }) {
let worldName
function dimensionToFolderName (dimension) {
if (bot.supportFeature('dimensionIsAnInt')) {
return dimensionNames[dimension]
return dimensionIdentifiers[dimension]
} else if (bot.supportFeature('dimensionIsAString') || bot.supportFeature('dimensionIsAWorld')) {
return worldName
}
Expand Down Expand Up @@ -525,6 +525,8 @@ function inject (bot, { version, storageBuilder, hideErrors }) {
bot.world = new World(null, storageBuilder ? storageBuilder({ version: bot.version, worldName: dimensionToFolderName(dimension) }) : null).sync
startListenerProxy()
}
console.log('[blocks] Emitting dim change', worldName)
bot.emit('dimensionChange', worldName.replace('minecraft:', ''))
}

bot._client.on('login', (packet) => {
Expand All @@ -535,20 +537,23 @@ function inject (bot, { version, storageBuilder, hideErrors }) {
dimension = packet.dimension
worldName = /^minecraft:.+/.test(packet.worldName) ? packet.worldName : `minecraft:${packet.worldName}`
}
console.log('[blocks] login', packet)
switchWorld()
})

bot._client.on('respawn', (packet) => {
if (bot.supportFeature('dimensionIsAnInt')) { // <=1.15.2
if (dimension === packet.dimension) return
dimension = packet.dimension
worldName = dimensionToFolderName(dimension)
} 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
// Metadata is true when switching dimensions however, then the world name is different
dimension = packet.dimension
worldName = packet.worldName
}
console.log('[blocks] respawn', packet)
switchWorld()
})

Expand Down
4 changes: 2 additions & 2 deletions test/externalTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ for (const supportedVersion of mineflayer.testedVersions) {
}, (err, results) => {
if (err) return done(err)
console.log('pong')
assert.ok(results.latency >= 0)
assert.ok(results.latency <= 1000)
assert.ok(results.latency >= 0, results.latency)
assert.ok(results.latency <= 1000, results.latency)
begin()
})
})
Expand Down
2 changes: 1 addition & 1 deletion test/externalTests/bed.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ module.exports = () => async (bot) => {
await bot.test.wait(1000)

console.log(bot.time.timeOfDay, bot.blockAt(bedPos1).name, bot.blockAt(bedPos2).name)
assert(bot.time.timeOfDay >= midnight)
assert(bot.time.timeOfDay >= midnight, `${bot.time.timeOfDay} >= ${midnight}`)
assert(bot.blockAt(bedPos1).name.endsWith('bed'))
assert(bot.blockAt(bedPos2).name.endsWith('bed'))

Expand Down
2 changes: 1 addition & 1 deletion test/externalTests/chat.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ module.exports = () => {
bot.once('chat:test', listener)
bot.chat('/tellraw @p {"translate":"chat.type.text", "with":["U9G", "Hello"]}')
await once(bot, 'message')
assert.ok(triggered === false)
assert.strictEqual(triggered, false)
bot.off('chat:test', listener)
})

Expand Down
2 changes: 1 addition & 1 deletion test/externalTests/commandBlock.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ module.exports = () => async (bot) => {
timeout: 5000,
checkCondition: (message) => message.json.with[0] === command
})
assert(message.json.translate === 'advMode.setCommand.success')
assert.strictEqual(message.json.translate, 'advMode.setCommand.success')
}
4 changes: 2 additions & 2 deletions test/externalTests/creative.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ module.exports = () => async (bot) => {
bot.creative.setInventorySlot(SLOT, item1)
} catch (err) {
assert.ok(err instanceof Error, 'The error has not been passed')
assert.ok(bot.inventory.slots[SLOT] == null)
assert.equal(bot.inventory.slots[SLOT], null)
}

// setting a slot once works
await promise
assert.ok(bot.inventory.slots[SLOT] != null)
assert.ok(bot.inventory.slots[SLOT].type === item2.type)
assert.strictEqual(bot.inventory.slots[SLOT].type, item2.type)
// set the same item in the same slot again to ensure we don't hang
const returnValue = await Promise.race([
bot.creative.setInventorySlot(SLOT, item2),
Expand Down
6 changes: 3 additions & 3 deletions test/externalTests/elytra.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module.exports = () => async (bot) => {
await bot.test.setInventorySlot(6, new Item(bot.registry.itemsByName.elytra.id, 1))
if (supportsFireworkRockets) {
const fireworkItem = bot.registry.itemsArray.find(item => item.displayName === 'Firework Rocket')
assert.ok(fireworkItem !== undefined)
assert.notStrictEqual(fireworkItem, undefined)
await bot.test.setInventorySlot(36, new Item(fireworkItem.id, 64))
}
await bot.test.teleport(bot.entity.position.offset(0, 100, 0))
Expand All @@ -35,7 +35,7 @@ module.exports = () => async (bot) => {
}
await bot.waitForTicks(3)
let lateActivations = 0
assert.ok(bot.fireworkRocketDuration > 0)
assert.ok(bot.fireworkRocketDuration > 0, `${bot.fireworkRocketDuration} > 0`)
for (let i = bot.fireworkRocketDuration; i > 0; --i) {
await bot.waitForTicks(1)
assert.ok(bot.entity.elytraFlying)
Expand All @@ -45,5 +45,5 @@ module.exports = () => async (bot) => {
}
assert.ok(lateActivations <= activationTicks)
}
assert.ok(bot.fireworkRocketDuration === 0)
assert.strictEqual(bot.fireworkRocketDuration, 0)
}
4 changes: 2 additions & 2 deletions test/externalTests/furnace.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ module.exports = () => async (bot) => {

// Wait and take the output and inputs
await bot.test.wait(500)
assert(furnace.fuel > 0 && furnace.fuel < 1)
assert(furnace.progress > 0 && furnace.progress < 1)
assert(furnace.fuel > 0 && furnace.fuel < 1, furnace.fuel)
assert(furnace.progress > 0 && furnace.progress < 1, furnace.progress)

await bot.test.wait(furnace.progressSeconds * 1000 + 500)
assert.strictEqual(furnace.outputItem(), furnace.slots[2])
Expand Down
131 changes: 88 additions & 43 deletions test/externalTests/nether.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,97 @@
const assert = require('assert')
const Vec3 = require('vec3')
const { once } = require('../../lib/promise_utils')
const { onceWithCleanup, sleep } = require('../../lib/promise_utils')
const { Vec3 } = require('vec3')

module.exports = () => async (bot) => {
// Test spawn event on death
const Item = require('prismarine-item')(bot.registry)
module.exports = (version) => {
async function runTest (bot, testFunction) {
await testFunction(bot)
}

const tests = []

let signItem = null
for (const name in bot.registry.itemsByName) {
if (name.includes('sign') && !name.includes('hanging')) signItem = bot.registry.itemsByName[name]
function addTest (name, f) {
tests[name] = bot => runTest(bot, f)
}
assert.notStrictEqual(signItem, null)

const p = new Promise((resolve, reject) => {
bot._client.on('open_sign_entity', (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)

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

if (sign.blockEntity) {
// Check block update
bot.activateBlock(sign)
assert.notStrictEqual(sign.blockEntity, undefined)
}

bot.test.sayEverywhere('/setblock ~ ~ ~ portal')
bot.test.sayEverywhere('/setblock ~ ~ ~ nether_portal')
once(bot, 'spawn').then(resolve)
}, 500)
})

addTest('spawn event on death and nether sign', async (bot) => {
// Test spawn event on death
const Item = require('prismarine-item')(bot.registry)

let signItem = null
for (const name in bot.registry.itemsByName) {
if (name.includes('sign') && !name.includes('hanging')) signItem = bot.registry.itemsByName[name]
}
assert.notStrictEqual(signItem, null, 'Could not find sign item')

await bot.waitForChunksToLoad()
bot.test.sayEverywhere('/setblock ~2 ~ ~ nether_portal')
bot.test.sayEverywhere('/setblock ~2 ~ ~ portal')
bot.test.sayEverywhere('/tp ~2 ~ ~')
await onceWithCleanup(bot, 'spawn')

await bot.test.resetNetherRoofToBedrock()
bot.test.sayEverywhere('/tp ~ 128 ~')
await onceWithCleanup(bot, 'forcedMove')
await bot.waitForChunksToLoad()

const lowerBlock = bot.blockAt(bot.entity.position.offset(0, -1, 0))
await bot.lookAt(lowerBlock.position.offset(0.5, 0.5, 0.5), true)

await bot.test.setInventorySlot(36, new Item(signItem.id, 1, 0))
bot.placeBlock(lowerBlock, new Vec3(0, 1, 0)).catch(err => assert.rejects(err))

const [packet] = await onceWithCleanup(bot._client, 'open_sign_entity')

console.log('[test/nether] Open Sign Packet', packet)
const sign = bot.blockAt(new Vec3(packet.location.x, packet.location.y, packet.location.z))
bot.updateSign(sign, '1\n2\n3\n')

await sleep(500)
// Get updated sign
const newSign = bot.blockAt(bot.entity.position)

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

if (newSign.blockEntity) {
// Check block update
bot.activateBlock(newSign)
assert.notStrictEqual(newSign.blockEntity, undefined)
}

// Get back to the overworld
bot.test.sayEverywhere('/tp ~ 128 ~')
await onceWithCleanup(bot, 'forcedMove')
await sleep(1000)
bot.test.sayEverywhere('/setblock ~ ~ ~ portal')
bot.test.sayEverywhere('/setblock ~ ~ ~ nether_portal')
await onceWithCleanup(bot, 'spawn')
await sleep(1000)
})

bot.test.sayEverywhere('/setblock ~ ~ ~ nether_portal')
bot.test.sayEverywhere('/setblock ~ ~ ~ portal')
await once(bot, 'spawn')
bot.test.sayEverywhere('/tp 0 128 0')
addTest('nether dimension change event', async (bot) => {
// Test dimension change event
const DimensionChangeTimeout = 10000
bot.test.sayEverywhere('/setblock ~ ~ ~ nether_portal')
bot.test.sayEverywhere('/setblock ~ ~ ~ portal')
// Start listening for dimension change event
const dimensionChange = onceWithCleanup(bot, 'dimensionChange', { timeout: DimensionChangeTimeout })
await onceWithCleanup(bot, 'spawn')

await once(bot, 'forcedMove')
await bot.waitForChunksToLoad()
const [dimensionName] = await dimensionChange
assert.equal(dimensionName, 'the_nether')

// Get back to the overworld
await bot.test.resetNetherRoofToBedrock()
bot.test.sayEverywhere('/tp ~ 128 ~')
await onceWithCleanup(bot, 'forcedMove')
await sleep(1000)
bot.test.sayEverywhere('/setblock ~ ~ ~ portal')
bot.test.sayEverywhere('/setblock ~ ~ ~ nether_portal')
// Check that the dimension change event is fired again
const [dimensionName2] = await onceWithCleanup(bot, 'dimensionChange', { timeout: DimensionChangeTimeout })
assert.equal(dimensionName2, 'overworld')
await sleep(1000)
})

const lowerBlock = bot.blockAt(bot.entity.position.offset(0, -1, 0))
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
return tests
}
16 changes: 8 additions & 8 deletions test/externalTests/placeEntity.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module.exports = (version) => {
await bot.test.setBlock({ z: 1, relative: true, blockName: 'obsidian' })
await bot.test.awaitItemRecieved(`/give ${bot.username} end_crystal`)
const crystal = await bot.placeEntity(bot.blockAt(bot.entity.position.offset(0, 0, 1)), new Vec3(0, 1, 0))
assert(crystal !== null)
assert.ok(crystal)
let name = 'EnderCrystal'
if (bot.supportFeature('enderCrystalNameEndsInErNoCaps')) {
name = 'ender_crystal'
Expand All @@ -28,7 +28,7 @@ module.exports = (version) => {
name = 'end_crystal'
}
const entity = bot.nearestEntity(o => o.name === name)
assert(entity?.name === name)
assert.strictEqual(entity?.name, name)
bot.attack(entity)
await once(bot, 'entityGone')
await bot.test.setBlock({ z: 1, blockName: 'air', relative: true })
Expand All @@ -47,10 +47,10 @@ module.exports = (version) => {
await placeBlocksForTest('water')
await bot.test.awaitItemRecieved(`/give ${bot.username} ${bot.registry.oak_boat ? 'oak_boat' : 'boat'}`)
const boat = await bot.placeEntity(bot.blockAt(bot.entity.position.offset(0, -1, -2)), new Vec3(0, -1, 0))
assert(boat !== null)
assert.ok(boat)
const name = bot.supportFeature('entityNameUpperCaseNoUnderscore') ? 'Boat' : 'boat'
const entity = bot.nearestEntity(o => o.name === name)
assert(entity?.name === name)
assert.strictEqual(entity?.name, name)
await placeBlocksForTest('air')
bot.attack(entity)
await once(bot, 'entityGone')
Expand All @@ -71,18 +71,18 @@ module.exports = (version) => {
}
await bot.test.awaitItemRecieved(command)
const zombie = await bot.placeEntity(bot.blockAt(bot.entity.position.offset(0, 0, 1)), new Vec3(0, 1, 0))
assert(zombie !== null)
assert.ok(zombie)
const name = bot.supportFeature('entityNameUpperCaseNoUnderscore') ? 'Zombie' : 'zombie'
const entity = bot.nearestEntity(o => o.name === name)
assert(entity?.name === name)
assert.strictEqual(entity?.name, name)
bot.chat(`/kill @e[type=${name}]`) // use /kill instead of bot.attack() because it takes more than one hit to kill
await once(bot, 'entityGone')
})

addTest('place armor stand', async (bot) => {
await bot.test.awaitItemRecieved(`/give ${bot.username} armor_stand`)
const armorStand = await bot.placeEntity(bot.blockAt(bot.entity.position.offset(0, 0, 1)), new Vec3(0, 1, 0))
assert(armorStand !== null)
assert.ok(armorStand)
let name
if (bot.supportFeature('entityNameUpperCaseNoUnderscore')) {
name = 'ArmorStand'
Expand All @@ -92,7 +92,7 @@ module.exports = (version) => {
name = 'armor_stand'
}
const entity = bot.nearestEntity(o => o.name === name)
assert(entity?.name === name)
assert.strictEqual(entity?.name, name)
bot.attack(entity)
await once(bot, 'entityGone')
})
Expand Down
Loading
Loading