const assert = require('assert')
const mineflayer = require('../')
const commonTest = require('./externalTests/plugins/testCommon')
const mc = require('minecraft-protocol')
const fs = require('fs')
const path = require('path')
const { getPort } = require('./common/util')
const { once } = require('../lib/promise_utils')
const START_THE_SERVER = true
const TEST_TIMEOUT_MS = 90000
const excludedTests = ['digEverything', 'book', 'anvil', 'placeEntity']
const propOverrides = {
'level-type': 'FLAT',
'spawn-npcs': 'true',
'spawn-animals': 'false',
'online-mode': 'false',
gamemode: '1',
'spawn-monsters': 'false',
'generate-structures': 'false',
'enable-command-block': 'true',
'use-native-transport': 'false'
}
const Wrap = require('minecraft-wrap').Wrap
const download = require('minecraft-wrap').download
const MC_SERVER_PATH = path.join(__dirname, 'server')
for (const supportedVersion of mineflayer.testedVersions) {
let PORT = 25565
const registry = require('prismarine-registry')(supportedVersion)
const version = registry.version
const MC_SERVER_JAR_DIR = process.env.MC_SERVER_JAR_DIR || `${process.cwd()}/server_jars`
const MC_SERVER_JAR = `${MC_SERVER_JAR_DIR}/minecraft_server.${version.minecraftVersion}.jar`
const wrap = new Wrap(MC_SERVER_JAR, `${MC_SERVER_PATH}_${supportedVersion}`)
wrap.on('line', (line) => {
console.log(line)
})
describe(`mineflayer_external ${supportedVersion}v`, function () {
let bot
this.timeout(10 * 60 * 1000)
before(async function () {
PORT = await getPort()
console.log(`Port chosen: ${PORT}`)
})
before(function (done) {
this.timeout(1000 * 120)
function begin () {
bot = mineflayer.createBot({
username: 'flatbot',
viewDistance: 'tiny',
port: PORT,
host: '127.0.0.1',
version: supportedVersion
})
commonTest(bot, wrap)
bot.test.port = PORT
console.log('starting bot')
bot.once('spawn', () => {
console.log('bot spawned, opping...')
wrap.writeServer('op flatbot\n')
if (bot.supportFeature('gameRuleUsesResourceLocation')) {
wrap.writeServer('gamerule minecraft:spawn_monsters false\n')
} else {
wrap.writeServer('gamerule spawnMonsters false\n')
}
bot.once('messagestr', msg => {
if (msg.includes('Made flatbot a server operator') || msg === '[Server: Opped flatbot]') {
done()
}
})
})
}
if (START_THE_SERVER) {
console.log('downloading and starting server')
download(version.minecraftVersion, MC_SERVER_JAR, (err) => {
if (err) {
console.log(err)
done(err)
return
}
propOverrides['server-port'] = PORT
wrap.startServer(propOverrides, (err) => {
if (err) return done(err)
console.log(`pinging ${version.minecraftVersion} port : ${PORT}`)
mc.ping({
port: PORT,
host: '127.0.0.1',
version: supportedVersion
}, (err, results) => {
if (err) return done(err)
console.log('pong')
assert.ok(results.latency >= 0)
assert.ok(results.latency <= 1000)
begin()
})
})
})
} else begin()
})
after((done) => {
if (bot) bot.quit()
wrap.stopServer((err) => {
if (err) {
console.log(err)
}
wrap.deleteServerData((err) => {
if (err) {
console.log(err)
}
done(err)
})
})
})
async function reconnectBot () {
console.log(' Bot disconnected, reconnecting...')
try { bot.end() } catch (e) { }
await new Promise(resolve => setTimeout(resolve, 1000))
bot = mineflayer.createBot({
username: 'flatbot',
viewDistance: 'tiny',
port: PORT,
host: '127.0.0.1',
version: supportedVersion
})
commonTest(bot, wrap)
bot.test.port = PORT
await once(bot, 'spawn')
console.log(' Bot reconnected')
wrap.writeServer('op flatbot\n')
await new Promise(resolve => setTimeout(resolve, 2000))
}
const externalTestsFolder = path.resolve(__dirname, './externalTests')
let distinctFailures = 0
const dangerousTests = ['exampleBee', 'exampleDigger', 'exampleInventory']
fs.readdirSync(externalTestsFolder)
.filter(file => fs.statSync(path.join(externalTestsFolder, file)).isFile())
.sort((a, b) => {
const aName = path.basename(a, '.js')
const bName = path.basename(b, '.js')
const aDangerous = dangerousTests.includes(aName) ? 1 : 0
const bDangerous = dangerousTests.includes(bName) ? 1 : 0
return aDangerous - bDangerous
})
.forEach((test) => {
test = path.basename(test, '.js')
const testFunctions = require(`./externalTests/${test}`)(supportedVersion)
const runTest = (testName, testFunction) => {
return function (done) {
this.timeout(TEST_TIMEOUT_MS)
if (distinctFailures >= 3) this.retries(0)
if (this.test._currentRetry > 0) {
console.log(` [retry ${this.test._currentRetry}] ${testName}`)
}
const reconnect = !bot.entity
? reconnectBot()
: Promise.resolve()
reconnect.then(() => bot.test.resetState())
.then(() => {
bot.test.sayEverywhere(`### Starting ${testName}`)
return testFunction(bot, done)
})
.then(res => done())
.catch(e => {
if (this.test._currentRetry === 0) {
distinctFailures++
}
done(e)
})
}
}
if (excludedTests.indexOf(test) === -1) {
if (typeof testFunctions === 'object') {
for (const testFunctionName in testFunctions) {
if (testFunctions[testFunctionName] !== undefined) {
it(`${test} ${testFunctionName}`, (testFunctionName => runTest(`${test} ${testFunctionName}`, testFunctions[testFunctionName]))(testFunctionName))
}
}
} else {
it(test, runTest(test, testFunctions))
}
}
})
})
}