Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PrismarineJS
GitHub Repository: PrismarineJS/mineflayer
Path: blob/master/test/externalTest.js
9427 views
1
/* eslint-env mocha */
2
3
const assert = require('assert')
4
const mineflayer = require('../')
5
const commonTest = require('./externalTests/plugins/testCommon')
6
const mc = require('minecraft-protocol')
7
const fs = require('fs')
8
const path = require('path')
9
10
const { getPort } = require('./common/util')
11
const { once } = require('../lib/promise_utils')
12
13
// set this to false if you want to test without starting a server automatically
14
const START_THE_SERVER = true
15
// if you want to have time to look what's happening increase this (milliseconds)
16
const TEST_TIMEOUT_MS = 90000
17
18
const excludedTests = ['digEverything', 'book', 'anvil', 'placeEntity']
19
20
const propOverrides = {
21
'level-type': 'FLAT',
22
'spawn-npcs': 'true',
23
'spawn-animals': 'false',
24
'online-mode': 'false',
25
gamemode: '1',
26
'spawn-monsters': 'false',
27
'generate-structures': 'false',
28
'enable-command-block': 'true',
29
'use-native-transport': 'false' // java 16 throws errors without this, https://www.spigotmc.org/threads/unable-to-access-address-of-buffer.311602
30
}
31
32
const Wrap = require('minecraft-wrap').Wrap
33
const download = require('minecraft-wrap').download
34
35
const MC_SERVER_PATH = path.join(__dirname, 'server')
36
37
for (const supportedVersion of mineflayer.testedVersions) {
38
let PORT = 25565
39
const registry = require('prismarine-registry')(supportedVersion)
40
const version = registry.version
41
const MC_SERVER_JAR_DIR = process.env.MC_SERVER_JAR_DIR || `${process.cwd()}/server_jars`
42
const MC_SERVER_JAR = `${MC_SERVER_JAR_DIR}/minecraft_server.${version.minecraftVersion}.jar`
43
const wrap = new Wrap(MC_SERVER_JAR, `${MC_SERVER_PATH}_${supportedVersion}`)
44
wrap.on('line', (line) => {
45
console.log(line)
46
})
47
48
describe(`mineflayer_external ${supportedVersion}v`, function () {
49
let bot
50
this.timeout(10 * 60 * 1000)
51
before(async function () {
52
PORT = await getPort()
53
console.log(`Port chosen: ${PORT}`)
54
})
55
before(function (done) {
56
this.timeout(1000 * 120)
57
function begin () {
58
bot = mineflayer.createBot({
59
username: 'flatbot',
60
viewDistance: 'tiny',
61
port: PORT,
62
host: '127.0.0.1',
63
version: supportedVersion
64
})
65
commonTest(bot, wrap)
66
bot.test.port = PORT
67
68
console.log('starting bot')
69
bot.once('spawn', () => {
70
console.log('bot spawned, opping...')
71
wrap.writeServer('op flatbot\n')
72
if (bot.supportFeature('gameRuleUsesResourceLocation')) {
73
wrap.writeServer('gamerule minecraft:spawn_monsters false\n')
74
} else {
75
wrap.writeServer('gamerule spawnMonsters false\n')
76
}
77
bot.once('messagestr', msg => {
78
if (msg.includes('Made flatbot a server operator') || msg === '[Server: Opped flatbot]') {
79
done()
80
}
81
})
82
})
83
}
84
85
if (START_THE_SERVER) {
86
console.log('downloading and starting server')
87
download(version.minecraftVersion, MC_SERVER_JAR, (err) => {
88
if (err) {
89
console.log(err)
90
done(err)
91
return
92
}
93
propOverrides['server-port'] = PORT
94
wrap.startServer(propOverrides, (err) => {
95
if (err) return done(err)
96
console.log(`pinging ${version.minecraftVersion} port : ${PORT}`)
97
mc.ping({
98
port: PORT,
99
host: '127.0.0.1',
100
version: supportedVersion
101
}, (err, results) => {
102
if (err) return done(err)
103
console.log('pong')
104
assert.ok(results.latency >= 0)
105
assert.ok(results.latency <= 1000)
106
begin()
107
})
108
})
109
})
110
} else begin()
111
})
112
113
after((done) => {
114
if (bot) bot.quit()
115
wrap.stopServer((err) => {
116
if (err) {
117
console.log(err)
118
}
119
wrap.deleteServerData((err) => {
120
if (err) {
121
console.log(err)
122
}
123
done(err)
124
})
125
})
126
})
127
128
async function reconnectBot () {
129
console.log(' Bot disconnected, reconnecting...')
130
try { bot.end() } catch (e) { /* ignore */ }
131
await new Promise(resolve => setTimeout(resolve, 1000))
132
bot = mineflayer.createBot({
133
username: 'flatbot',
134
viewDistance: 'tiny',
135
port: PORT,
136
host: '127.0.0.1',
137
version: supportedVersion
138
})
139
commonTest(bot, wrap)
140
bot.test.port = PORT
141
await once(bot, 'spawn')
142
console.log(' Bot reconnected')
143
wrap.writeServer('op flatbot\n')
144
await new Promise(resolve => setTimeout(resolve, 2000))
145
}
146
147
const externalTestsFolder = path.resolve(__dirname, './externalTests')
148
let distinctFailures = 0
149
// Sort test files so example tests (which spawn child processes and can
150
// crash/disconnect the bot) run last, limiting their blast radius.
151
const dangerousTests = ['exampleBee', 'exampleDigger', 'exampleInventory']
152
fs.readdirSync(externalTestsFolder)
153
.filter(file => fs.statSync(path.join(externalTestsFolder, file)).isFile())
154
.sort((a, b) => {
155
const aName = path.basename(a, '.js')
156
const bName = path.basename(b, '.js')
157
const aDangerous = dangerousTests.includes(aName) ? 1 : 0
158
const bDangerous = dangerousTests.includes(bName) ? 1 : 0
159
return aDangerous - bDangerous
160
})
161
.forEach((test) => {
162
test = path.basename(test, '.js')
163
const testFunctions = require(`./externalTests/${test}`)(supportedVersion)
164
const runTest = (testName, testFunction) => {
165
return function (done) {
166
this.timeout(TEST_TIMEOUT_MS)
167
// Disable retries if too many different tests have already failed
168
// on their first attempt (indicates a systemic issue, not flakiness)
169
if (distinctFailures >= 3) this.retries(0)
170
if (this.test._currentRetry > 0) {
171
console.log(` [retry ${this.test._currentRetry}] ${testName}`)
172
}
173
// Reconnect if bot got disconnected by a previous test
174
const reconnect = !bot.entity
175
? reconnectBot()
176
: Promise.resolve()
177
reconnect.then(() => bot.test.resetState())
178
.then(() => {
179
bot.test.sayEverywhere(`### Starting ${testName}`)
180
return testFunction(bot, done)
181
})
182
.then(res => done())
183
.catch(e => {
184
if (this.test._currentRetry === 0) {
185
distinctFailures++
186
}
187
done(e)
188
})
189
}
190
}
191
if (excludedTests.indexOf(test) === -1) {
192
if (typeof testFunctions === 'object') {
193
for (const testFunctionName in testFunctions) {
194
if (testFunctions[testFunctionName] !== undefined) {
195
it(`${test} ${testFunctionName}`, (testFunctionName => runTest(`${test} ${testFunctionName}`, testFunctions[testFunctionName]))(testFunctionName))
196
}
197
}
198
} else {
199
it(test, runTest(test, testFunctions))
200
}
201
}
202
})
203
})
204
}
205
206