Skip to content

Commit 597745c

Browse files
rom1504botgithub-actions[bot]SuperGamerTronextremeheatCopilot
authored
🎈 1.21.11 (#3781)
* Update to version 1.21.11 * add `gameRuleUsesResourceLocation` feature flag (#3820) * Use new gamerule feature * Update ci.yml * Update package.json * Update ci.yml * Update package.json --------- Co-authored-by: extremeheat <extreme@protonmail.ch> * Fix flaky time test race condition and add timeouts to promise chains (#3824) * Initial plan * Add timeouts to promises to prevent test hangs and fix time test race condition Co-authored-by: extremeheat <13713600+extremeheat@users.noreply.github.com> * Use onceWithCleanup with checkCondition for cleaner promise handling Co-authored-by: extremeheat <13713600+extremeheat@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: extremeheat <13713600+extremeheat@users.noreply.github.com> * Fix flaky CI: increase before-hook timeout and guard after-hook against undefined bot (#3825) The 1.9.4 test was failing because the 60s timeout for downloading, starting the server, connecting, and opping was too tight for CI. Increased to 120s. Also added a null guard in the after hook so it doesn't crash when bot was never created due to a before-hook timeout. Co-authored-by: Simeon Kummer <simeon@hitthecode.de> Co-authored-by: Cursor <cursoragent@cursor.com> * Clean up CI workflow by removing unnecessary commands Removed outdated commands for cloning minecraft-data and downloading protodef files. * Update minecraft-protocol dependency version --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: SuperGamerTron <45374546+SuperGamerTron@users.noreply.github.com> Co-authored-by: extremeheat <extreme@protonmail.ch> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: extremeheat <13713600+extremeheat@users.noreply.github.com> Co-authored-by: plainprince <119175160+plainprince@users.noreply.github.com> Co-authored-by: Simeon Kummer <simeon@hitthecode.de> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Romain Beaumont <romain.rom1@gmail.com>
1 parent 4858613 commit 597745c

10 files changed

Lines changed: 62 additions & 23 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,6 @@ jobs:
5656
java-package: jre
5757
- name: Install Dependencies
5858
run: npm install
59+
5960
- name: Start Tests
6061
run: npm run mocha_test -- -g ${{ matrix.mcVersion }}v

docs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ First time using Node.js? You may want to start with the [tutorial](tutorial.md)
1717

1818
## Features
1919

20-
* Supports Minecraft 1.8 to 1.21.9 (1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19, 1.20, 1.21, 1.21.9) <!--version-->
20+
* Supports Minecraft 1.8 to 1.21.11 (1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19, 1.20, 1.21, 1.21.9, 1.21.11) <!--version-->
2121
* Entity knowledge and tracking.
2222
* Block knowledge. You can query the world around you. Milliseconds to find any block.
2323
* Physics and movement - handle all bounding boxes

lib/plugins/blocks.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ function inject (bot, { version, storageBuilder, hideErrors }) {
7070
async function waitForChunksToLoad () {
7171
const dist = 2
7272
// This makes sure that the bot's real position has been already sent
73-
if (!bot.entity.height) await onceWithCleanup(bot, 'chunkColumnLoad')
73+
if (!bot.entity.height) await onceWithCleanup(bot, 'chunkColumnLoad', { timeout: 10000 })
7474
const pos = bot.entity.position
7575
const center = new Vec3(pos.x >> 4 << 4, 0, pos.z >> 4 << 4)
7676
// get corner coords of 5x5 chunks around us
@@ -84,10 +84,16 @@ function inject (bot, { version, storageBuilder, hideErrors }) {
8484
}
8585

8686
if (chunkPosToCheck.size) {
87-
return new Promise((resolve) => {
87+
return new Promise((resolve, reject) => {
88+
const timeout = setTimeout(() => {
89+
bot.world.off('chunkColumnLoad', waitForLoadEvents)
90+
reject(new Error(`Timeout waiting for ${chunkPosToCheck.size} chunks to load after 10000ms`))
91+
}, 10000)
92+
8893
function waitForLoadEvents (columnCorner) {
8994
chunkPosToCheck.delete(columnCorner.toString())
9095
if (chunkPosToCheck.size === 0) { // no chunks left to find
96+
clearTimeout(timeout)
9197
bot.world.off('chunkColumnLoad', waitForLoadEvents) // remove this listener instance
9298
resolve()
9399
}

lib/plugins/chat.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,17 @@ function inject (bot, options) {
206206
}
207207

208208
function awaitMessage (...args) {
209+
const timeout = typeof args[args.length - 1] === 'number' ? args.pop() : 20000
209210
return new Promise((resolve, reject) => {
210211
const resolveMessages = args.flatMap(x => x)
212+
const timeoutHandle = setTimeout(() => {
213+
bot.off('messagestr', messageListener)
214+
reject(new Error(`Timeout waiting for message after ${timeout}ms`))
215+
}, timeout)
216+
211217
function messageListener (msg) {
212218
if (resolveMessages.some(x => x instanceof RegExp ? x.test(msg) : msg === x)) {
219+
clearTimeout(timeoutHandle)
213220
resolve(msg)
214221
bot.off('messagestr', messageListener)
215222
}

lib/plugins/physics.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,10 +427,17 @@ function inject (bot, { physicsEnabled, maxCatchupTicks }) {
427427

428428
bot.waitForTicks = async function (ticks) {
429429
if (ticks <= 0) return
430-
await new Promise(resolve => {
430+
await new Promise((resolve, reject) => {
431+
// Assuming 20 ticks per second, add extra time for lag
432+
const timeout = setTimeout(() => {
433+
bot.removeListener('physicsTick', tickListener)
434+
reject(new Error(`Timeout waiting for ${ticks} ticks after ${(ticks * 50 + 5000)}ms`))
435+
}, ticks * 50 + 5000) // 50ms per tick + 5s buffer
436+
431437
const tickListener = () => {
432438
ticks--
433439
if (ticks === 0) {
440+
clearTimeout(timeout)
434441
bot.removeListener('physicsTick', tickListener)
435442
resolve()
436443
}

lib/version.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
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', '1.21.1', '1.21.3', '1.21.4', '1.21.5', '1.21.6', '1.21.8', '1.21.9']
1+
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', '1.21.1', '1.21.3', '1.21.4', '1.21.5', '1.21.6', '1.21.8', '1.21.9', '1.21.11']
22
module.exports = {
33

44
testedVersions,

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"license": "MIT",
2323
"dependencies": {
2424
"minecraft-data": "^3.98.0",
25-
"minecraft-protocol": "^1.63.0",
25+
"minecraft-protocol": "^1.64.0",
2626
"prismarine-biome": "^1.1.1",
2727
"prismarine-block": "^1.22.0",
2828
"prismarine-chat": "^1.7.1",

test/externalTest.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ for (const supportedVersion of mineflayer.testedVersions) {
5252
console.log(`Port chosen: ${PORT}`)
5353
})
5454
before(function (done) {
55-
this.timeout(1000 * 60)
55+
this.timeout(1000 * 120)
5656
function begin () {
5757
bot = mineflayer.createBot({
5858
username: 'flatbot',
@@ -68,7 +68,11 @@ for (const supportedVersion of mineflayer.testedVersions) {
6868
bot.once('spawn', () => {
6969
console.log('bot spawned, opping...')
7070
wrap.writeServer('op flatbot\n')
71-
wrap.writeServer('gamerule spawnMonsters false\n')
71+
if (bot.supportFeature('gameRuleUsesResourceLocation')) {
72+
wrap.writeServer('gamerule minecraft:spawn_monsters false\n')
73+
} else {
74+
wrap.writeServer('gamerule spawnMonsters false\n')
75+
}
7276
bot.once('messagestr', msg => {
7377
if (msg.includes('Made flatbot a server operator') || msg === '[Server: Opped flatbot]') {
7478
done()
@@ -112,7 +116,7 @@ for (const supportedVersion of mineflayer.testedVersions) {
112116
})
113117

114118
after((done) => {
115-
bot.quit()
119+
if (bot) bot.quit()
116120
wrap.stopServer((err) => {
117121
if (err) {
118122
console.log(err)

test/externalTests/bossBar.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const assert = require('assert')
2-
const { once } = require('../../lib/promise_utils')
2+
const { once, onceWithCleanup } = require('../../lib/promise_utils')
33

44
module.exports = (version) => async (bot) => {
55
// Skip test for versions older than 1.13 (bossbar command not available)
@@ -44,15 +44,13 @@ module.exports = (version) => async (bot) => {
4444
bot.test.sayEverywhere(`/bossbar set ${uuid} value ${newHealth * 100}`)
4545

4646
// Wait for the boss bar to have the expected state
47-
let bossBar
48-
while (true) {
49-
[bossBar] = await once(bot, 'bossBarUpdated')
50-
if (
47+
const [bossBar] = await onceWithCleanup(bot, 'bossBarUpdated', {
48+
timeout: 5000,
49+
checkCondition: (bossBar) =>
5150
bossBar.health === newHealth &&
5251
bossBar.color === newColor &&
5352
bossBar.dividers === 10
54-
) break
55-
}
53+
})
5654
assert.strictEqual(bossBar.health, newHealth)
5755
assert.strictEqual(bossBar.color, newColor)
5856
assert.strictEqual(bossBar.dividers, 10)

test/externalTests/time.js

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const assert = require('assert')
2-
const { once } = require('../../lib/promise_utils')
2+
const { once, onceWithCleanup } = require('../../lib/promise_utils')
33

44
module.exports = () => async (bot) => {
55
// Test time properties and ranges
@@ -30,9 +30,17 @@ module.exports = () => async (bot) => {
3030
// Helper functions
3131
const isTimeClose = (current, target) => Math.abs(current - target) < 510
3232
const isTimeInRange = (current, start, end) => start <= end ? current >= start && current <= end : current >= start || current <= end
33-
const waitForTime = async () => {
34-
await once(bot, 'time')
35-
await bot.test.wait(200)
33+
const waitForTime = async (expectedTime) => {
34+
// Wait for a time event that matches our expectation (if provided)
35+
// This helps avoid race conditions where we catch an old time update
36+
if (expectedTime !== undefined) {
37+
await onceWithCleanup(bot, 'time', {
38+
timeout: 5000,
39+
checkCondition: () => isTimeClose(bot.time.timeOfDay, expectedTime)
40+
})
41+
} else {
42+
await once(bot, 'time')
43+
}
3644
}
3745

3846
// Test time transitions
@@ -45,7 +53,7 @@ module.exports = () => async (bot) => {
4553

4654
for (const test of timeTests) {
4755
bot.test.sayEverywhere(`/time set ${test.time}`)
48-
await waitForTime()
56+
await waitForTime(test.time)
4957
assert(isTimeClose(bot.time.timeOfDay, test.time), `Expected time to be close to ${test.time}, got ${bot.time.timeOfDay}`)
5058
assert.strictEqual(bot.time.isDay, test.isDay, `${test.name} should be ${test.isDay ? 'day' : 'night'}`)
5159
}
@@ -60,11 +68,19 @@ module.exports = () => async (bot) => {
6068

6169
// Test daylight cycle
6270
const originalDaylightCycle = bot.time.doDaylightCycle
63-
bot.test.sayEverywhere('/gamerule doDaylightCycle false')
71+
if (bot.supportFeature('gameRuleUsesResourceLocation')) {
72+
bot.test.sayEverywhere('/gamerule minecraft:advance_time false')
73+
} else {
74+
bot.test.sayEverywhere('/gamerule doDaylightCycle false')
75+
}
6476
await waitForTime()
6577
assert.strictEqual(bot.time.doDaylightCycle, false)
6678

67-
bot.test.sayEverywhere(`/gamerule doDaylightCycle ${originalDaylightCycle}`)
79+
if (bot.supportFeature('gameRuleUsesResourceLocation')) {
80+
bot.test.sayEverywhere(`/gamerule minecraft:advance_time ${originalDaylightCycle}`)
81+
} else {
82+
bot.test.sayEverywhere(`/gamerule doDaylightCycle ${originalDaylightCycle}`)
83+
}
6884
await waitForTime()
6985
assert.strictEqual(bot.time.doDaylightCycle, originalDaylightCycle)
7086

0 commit comments

Comments
 (0)