mirror of
https://github.com/danbulant/flying-squid
synced 2026-07-07 12:10:46 +00:00
Merge pull request #320 from PrismarineJS/circle
Migrate to CircleCI 2 and Jest
This commit is contained in:
commit
0015986621
13 changed files with 611 additions and 532 deletions
16
.circleci/config.yml
Normal file
16
.circleci/config.yml
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
docker:
|
||||||
|
- image: circleci/node:carbon
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- restore_cache:
|
||||||
|
key: dependency-cache-{{ checksum "package.json" }}
|
||||||
|
- run: npm i
|
||||||
|
- save_cache:
|
||||||
|
key: dependency-cache-{{ checksum "package.json" }}
|
||||||
|
paths:
|
||||||
|
- ./node_modules
|
||||||
|
- run: npm test
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
machine:
|
|
||||||
node:
|
|
||||||
version: 8
|
|
||||||
10
package.json
10
package.json
|
|
@ -15,7 +15,7 @@
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepare": "require-self",
|
"prepare": "require-self",
|
||||||
"test": "mocha --reporter spec"
|
"test": "jest --verbose --runInBand"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"licenses": {
|
"licenses": {
|
||||||
|
|
@ -44,7 +44,6 @@
|
||||||
"range": "^0.0.3",
|
"range": "^0.0.3",
|
||||||
"request": "^2.83.0",
|
"request": "^2.83.0",
|
||||||
"request-promise": "^4.1.0",
|
"request-promise": "^4.1.0",
|
||||||
"requireindex": "~1.1.0",
|
|
||||||
"spiralloop": "^1.0.2",
|
"spiralloop": "^1.0.2",
|
||||||
"vec3": "^0.1.3"
|
"vec3": "^0.1.3"
|
||||||
},
|
},
|
||||||
|
|
@ -57,10 +56,9 @@
|
||||||
"url": "http://github.com/PrismarineJS/flying-squid/issues"
|
"url": "http://github.com/PrismarineJS/flying-squid/issues"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"chai": "^3.2.0",
|
"jest": "^22.1.4",
|
||||||
"longjohn": "^0.2.8",
|
"longjohn": "^0.2.12",
|
||||||
"mineflayer": "^2.6.1",
|
"mineflayer": "^2.6.1",
|
||||||
"mocha": "^3.0.0",
|
"require-self": "^0.2.1"
|
||||||
"require-self": "^0.1.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
const mc = require('minecraft-protocol');
|
const mc = require('minecraft-protocol');
|
||||||
const EventEmitter = require('events').EventEmitter;
|
const EventEmitter = require('events').EventEmitter;
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const requireIndex = require('requireindex');
|
const requireIndex = require('./lib/requireindex');
|
||||||
require('emit-then').register();
|
require('emit-then').register();
|
||||||
if (process.env.NODE_ENV === 'dev'){
|
if (process.env.NODE_ENV === 'dev'){
|
||||||
require('longjohn');
|
require('longjohn');
|
||||||
|
|
@ -33,7 +33,7 @@ class MCServer extends EventEmitter {
|
||||||
|
|
||||||
connect(options) {
|
connect(options) {
|
||||||
const plugins = requireIndex(path.join(__dirname, 'lib', 'plugins'));
|
const plugins = requireIndex(path.join(__dirname, 'lib', 'plugins'));
|
||||||
this._server = mc.createServer(options);
|
this._server = mc.createServer(options);
|
||||||
Object.keys(plugins)
|
Object.keys(plugins)
|
||||||
.filter(pluginName => plugins[pluginName].server!=undefined)
|
.filter(pluginName => plugins[pluginName].server!=undefined)
|
||||||
.forEach(pluginName => plugins[pluginName].server(this, options));
|
.forEach(pluginName => plugins[pluginName].server(this, options));
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
const Vec3 = require("vec3").Vec3;
|
const Vec3 = require("vec3").Vec3;
|
||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const requireIndex = require('requireindex');
|
const requireIndex = require('../requireindex');
|
||||||
const plugins = requireIndex(path.join(__dirname,'..', 'plugins'));
|
const plugins = requireIndex(path.join(__dirname,'..', 'plugins'));
|
||||||
const Command = require('flying-squid').Command;
|
const Command = require('flying-squid').Command;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ const mobsById=require("minecraft-data")(version).mobs;
|
||||||
const objectsById=require("minecraft-data")(version).objects;
|
const objectsById=require("minecraft-data")(version).objects;
|
||||||
const Entity = require("prismarine-entity");
|
const Entity = require("prismarine-entity");
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const requireIndex = require('requireindex');
|
const requireIndex = require('../requireindex');
|
||||||
const plugins = requireIndex(path.join(__dirname,'..', 'plugins'));
|
const plugins = requireIndex(path.join(__dirname,'..', 'plugins'));
|
||||||
const Item = require("prismarine-item")(version);
|
const Item = require("prismarine-item")(version);
|
||||||
const UserError = require('flying-squid').UserError;
|
const UserError = require('flying-squid').UserError;
|
||||||
|
|
|
||||||
59
src/lib/requireindex.js
Normal file
59
src/lib/requireindex.js
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
// Adapted from https://github.com/stephenhandley/requireindex (under the MIT license)
|
||||||
|
|
||||||
|
const fs = require('fs')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
module.exports = function(dir, basenames) {
|
||||||
|
let requires = {}
|
||||||
|
|
||||||
|
if (arguments.length === 2) {
|
||||||
|
// If basenames argument is passed, explicitly include those files
|
||||||
|
basenames.forEach(function (basename) {
|
||||||
|
let filepath = path.resolve(path.join(dir, basename))
|
||||||
|
requires[basename] = require(filepath)
|
||||||
|
})
|
||||||
|
} else if (arguments.length === 1) {
|
||||||
|
// If basenames arguments isn't passed, require all JavaScript
|
||||||
|
// Files (except for those prefixed with _) and all directories
|
||||||
|
|
||||||
|
let files = fs.readdirSync(dir)
|
||||||
|
|
||||||
|
// Sort files in lowercase alpha for Linux
|
||||||
|
files.sort((a, b) => {
|
||||||
|
a = a.toLowerCase()
|
||||||
|
b = b.toLowerCase()
|
||||||
|
|
||||||
|
if (a < b) {
|
||||||
|
return -1
|
||||||
|
} else if (b < a) {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
files.forEach(filename => {
|
||||||
|
// Ignore `index.js` and files prefixed with underscore and
|
||||||
|
if ((filename === 'index.js') || (filename[0] === '_') || (filename[0] === '.')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let filepath = path.resolve(path.join(dir, filename))
|
||||||
|
let ext = path.extname(filename)
|
||||||
|
let stats = fs.statSync(filepath)
|
||||||
|
|
||||||
|
// Don't require non-javascript files (.txt, .md, etc.)
|
||||||
|
if (stats.isFile() && !(['.js', '.node', '.json'].includes(ext))) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let basename = path.basename(filename, ext)
|
||||||
|
|
||||||
|
requires[basename] = require(filepath)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
throw new Error('Must pass directory as first argument')
|
||||||
|
}
|
||||||
|
|
||||||
|
return requires
|
||||||
|
}
|
||||||
|
|
@ -1,248 +0,0 @@
|
||||||
const net = require('net');
|
|
||||||
const mcServer=require("flying-squid");
|
|
||||||
const settings = require('../config/default-settings');
|
|
||||||
const mineflayer = require("mineflayer");
|
|
||||||
const assert = require('chai').assert;
|
|
||||||
const Vec3 = require('vec3').Vec3;
|
|
||||||
const Item = require('prismarine-item')("1.8");
|
|
||||||
|
|
||||||
function assertPosEqual(actual,expected) {
|
|
||||||
assert.isBelow(actual.distanceTo(expected),1,"expected: "+expected+", actual: "+actual+"\n");
|
|
||||||
}
|
|
||||||
const once = require('event-promise');
|
|
||||||
|
|
||||||
describe("Server with mineflayer connection", function() {
|
|
||||||
this.timeout(60 * 1000);
|
|
||||||
let bot;
|
|
||||||
let bot2;
|
|
||||||
let serv;
|
|
||||||
|
|
||||||
async function onGround(bot)
|
|
||||||
{
|
|
||||||
await new Promise((cb) => {
|
|
||||||
const l=() => {
|
|
||||||
if(bot.entity.onGround) {
|
|
||||||
bot.removeListener("move",l);
|
|
||||||
cb();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
bot.on("move",l);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function waitMessage(bot,message) {
|
|
||||||
const msg1=await once(bot,'message');
|
|
||||||
assert.equal(msg1.extra[0].text,message);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function waitMessages(bot,messages) {
|
|
||||||
const toReceive=messages.reduce((acc,message) => {
|
|
||||||
acc[message]=1;
|
|
||||||
return acc;
|
|
||||||
},{});
|
|
||||||
const received={};
|
|
||||||
return new Promise(cb => {
|
|
||||||
const listener=msg => {
|
|
||||||
const message=msg.extra[0].text;
|
|
||||||
if(!toReceive[message]) throw new Error("Received "+message+" , expected to receive one of "+messages);
|
|
||||||
if(received[message]) throw new Error("Received "+message+" two times");
|
|
||||||
received[message]=1;
|
|
||||||
if(Object.keys(received).length==messages.length)
|
|
||||||
{
|
|
||||||
bot.removeListener('message',listener);
|
|
||||||
cb();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
bot.on('message',listener);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function waitLoginMessage(bot) {
|
|
||||||
return Promise.all([waitMessages(bot,['bot joined the game.','bot2 joined the game.'])]);
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(async function () {
|
|
||||||
this.timeout(60 * 1000);
|
|
||||||
const options = settings;
|
|
||||||
options["online-mode"]=false;
|
|
||||||
options["port"]=25566;
|
|
||||||
options["view-distance"]=2;
|
|
||||||
options["worldFolder"]=undefined;
|
|
||||||
|
|
||||||
serv=mcServer.createMCServer(options);
|
|
||||||
|
|
||||||
await once(serv,"listening");
|
|
||||||
bot = mineflayer.createBot({
|
|
||||||
host: "localhost",
|
|
||||||
port: 25566,
|
|
||||||
username: "bot",
|
|
||||||
version: "1.8"
|
|
||||||
});
|
|
||||||
bot2 = mineflayer.createBot({
|
|
||||||
host: "localhost",
|
|
||||||
port: 25566,
|
|
||||||
username: "bot2",
|
|
||||||
version: "1.8"
|
|
||||||
});
|
|
||||||
|
|
||||||
await Promise.all([once(bot,'login'),once(bot2,'login')]);
|
|
||||||
bot.entity.onGround=false;
|
|
||||||
bot2.entity.onGround=false;
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(async () => {
|
|
||||||
await serv.quit();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("actions",() => {
|
|
||||||
|
|
||||||
function waitSpawnZone(bot,view)
|
|
||||||
{
|
|
||||||
const nbChunksExpected=(view*2)*(view*2);
|
|
||||||
let c=0;
|
|
||||||
return new Promise(cb => {
|
|
||||||
const listener=() => {
|
|
||||||
c++;
|
|
||||||
if(c==nbChunksExpected)
|
|
||||||
{
|
|
||||||
bot.removeListener('chunkColumnLoad',listener);
|
|
||||||
cb();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
bot.on('chunkColumnLoad',listener);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
it("can dig",async function () {
|
|
||||||
this.timeout(60 * 1000);
|
|
||||||
await Promise.all([waitSpawnZone(bot,2),waitSpawnZone(bot2,2),onGround(bot),onGround(bot2)]);
|
|
||||||
|
|
||||||
const pos=bot.entity.position.offset(0,-1,0).floored();
|
|
||||||
bot.dig(bot.blockAt(pos));
|
|
||||||
|
|
||||||
let [,newBlock]=await once(bot2,'blockUpdate',{array:true});
|
|
||||||
assertPosEqual(newBlock.position,pos);
|
|
||||||
assert.equal(newBlock.type,0,"block "+pos+" should have been dug");
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it("can place a block",async function () {
|
|
||||||
this.timeout(60 * 1000);
|
|
||||||
await Promise.all([waitSpawnZone(bot,2),waitSpawnZone(bot2,2),onGround(bot),onGround(bot2)]);
|
|
||||||
|
|
||||||
const pos=bot.entity.position.offset(0,-2,0).floored();
|
|
||||||
bot.dig(bot.blockAt(pos));
|
|
||||||
|
|
||||||
let [oldBlock,newBlock]=await once(bot2,'blockUpdate',{array:true});
|
|
||||||
assertPosEqual(newBlock.position,pos);
|
|
||||||
assert.equal(newBlock.type,0,"block "+pos+" should have been dug");
|
|
||||||
|
|
||||||
bot.creative.setInventorySlot(36, new Item(1,1));
|
|
||||||
await new Promise((cb) => {
|
|
||||||
bot.inventory.on("windowUpdate",(slot,oldItem,newItem) => {
|
|
||||||
if(slot==36 && newItem && newItem.type==1)
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
bot.placeBlock(bot.blockAt(pos.offset(0,-1,0)),new Vec3(0,1,0));
|
|
||||||
|
|
||||||
[oldBlock,newBlock]=await once(bot2,'blockUpdate',{array:true});
|
|
||||||
assertPosEqual(newBlock.position,pos);
|
|
||||||
assert.equal(newBlock.type,1,"block "+pos+" should have been placed");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("commands",() => {
|
|
||||||
|
|
||||||
it("has an help command", async () => {
|
|
||||||
await waitLoginMessage(bot);
|
|
||||||
bot.chat("/help");
|
|
||||||
await once(bot,"message");
|
|
||||||
});
|
|
||||||
it("can use /particle",async () => {
|
|
||||||
bot.chat("/particle 5 10 100 100 100");
|
|
||||||
await once(bot._client,'world_particles');
|
|
||||||
});
|
|
||||||
it("can use /playsound",async () => {
|
|
||||||
bot.chat('/playsound ambient.weather.rain');
|
|
||||||
await once(bot,'soundEffectHeard');
|
|
||||||
});
|
|
||||||
|
|
||||||
function waitDragon()
|
|
||||||
{
|
|
||||||
return new Promise((done) => {
|
|
||||||
const listener=(entity) => {
|
|
||||||
if(entity.name=="EnderDragon") {
|
|
||||||
bot.removeListener('entitySpawn',listener);
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
bot.on('entitySpawn',listener);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
it("can use /summon",async () => {
|
|
||||||
bot.chat('/summon EnderDragon');
|
|
||||||
await waitDragon();
|
|
||||||
});
|
|
||||||
it("can use /kill",async () => {
|
|
||||||
bot.chat('/summon EnderDragon');
|
|
||||||
await waitDragon();
|
|
||||||
bot.chat('/kill @e[type=EnderDragon]');
|
|
||||||
const entity=await once(bot,'entityDead');
|
|
||||||
assert.equal(entity.name,"EnderDragon");
|
|
||||||
});
|
|
||||||
describe("can use /tp",() => {
|
|
||||||
it("can tp myself", async () => {
|
|
||||||
bot.chat('/tp 2 3 4');
|
|
||||||
await once(bot,'forcedMove');
|
|
||||||
assertPosEqual(bot.entity.position, new Vec3(2, 3, 4));
|
|
||||||
});
|
|
||||||
it("can tp somebody else",async () => {
|
|
||||||
bot.chat('/tp bot2 2 3 4');
|
|
||||||
await once(bot2,'forcedMove');
|
|
||||||
assertPosEqual(bot2.entity.position, new Vec3(2, 3, 4));
|
|
||||||
});
|
|
||||||
it("can tp to somebody else",async () => {
|
|
||||||
await onGround(bot);
|
|
||||||
bot.chat('/tp bot2 bot');
|
|
||||||
await once(bot2,'forcedMove');
|
|
||||||
assertPosEqual(bot2.entity.position, bot.entity.position);
|
|
||||||
});
|
|
||||||
it("can tp with relative positions",async () => {
|
|
||||||
await onGround(bot);
|
|
||||||
const initialPosition=bot.entity.position.clone();
|
|
||||||
bot.chat('/tp ~1 ~-2 ~3');
|
|
||||||
await once(bot,'forcedMove');
|
|
||||||
assertPosEqual(bot.entity.position,initialPosition.offset(1,-2,3));
|
|
||||||
});
|
|
||||||
it("can tp somebody else with relative positions",async () => {
|
|
||||||
await Promise.all([onGround(bot),onGround(bot2)]);
|
|
||||||
const initialPosition=bot2.entity.position.clone();
|
|
||||||
bot.chat('/tp bot2 ~1 ~-2 ~3');
|
|
||||||
await once(bot2,'forcedMove');
|
|
||||||
assertPosEqual(bot2.entity.position,initialPosition.offset(1,-2,3));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it("can use /deop",async () => {
|
|
||||||
await waitLoginMessage(bot);
|
|
||||||
bot.chat('/deop bot');
|
|
||||||
await waitMessage(bot,'bot is deopped');
|
|
||||||
bot.chat('/op bot');
|
|
||||||
await waitMessage(bot,'You do not have permission to use this command');
|
|
||||||
serv.getPlayer("bot").op=true;
|
|
||||||
});
|
|
||||||
it("can use /setblock",async() => {
|
|
||||||
await once(bot, 'chunkColumnLoad');
|
|
||||||
bot.chat('/setblock 1 2 3 95 0');
|
|
||||||
let [,newBlock]=await once(bot,'blockUpdate:'+new Vec3(1,2,3),{array:true});
|
|
||||||
assert.equal(newBlock.type,95);
|
|
||||||
});
|
|
||||||
it("can use /xp",async() => {
|
|
||||||
bot.chat('/xp 100');
|
|
||||||
await once(bot,"experience");
|
|
||||||
assert.equal(bot.experience.points,100);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
238
test/mineflayer.test.js
Normal file
238
test/mineflayer.test.js
Normal file
|
|
@ -0,0 +1,238 @@
|
||||||
|
const net = require('net')
|
||||||
|
const squid = require('flying-squid')
|
||||||
|
const settings = require('../config/default-settings')
|
||||||
|
const mineflayer = require('mineflayer')
|
||||||
|
const { Vec3 } = require('vec3')
|
||||||
|
const Item = require('prismarine-item')('1.8')
|
||||||
|
|
||||||
|
function assertPosEqual (actual, expected) {
|
||||||
|
expect(actual.distanceTo(expected)).toBeLessThan(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const once = require('event-promise')
|
||||||
|
|
||||||
|
describe('server with mineflayer connection', () => {
|
||||||
|
jest.setTimeout(60 * 1000)
|
||||||
|
let bot
|
||||||
|
let bot2
|
||||||
|
let serv
|
||||||
|
|
||||||
|
async function onGround (bot) {
|
||||||
|
await new Promise((cb) => {
|
||||||
|
const l = () => {
|
||||||
|
if (bot.entity.onGround) {
|
||||||
|
bot.removeListener('move', l)
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bot.on('move', l)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function waitMessage (bot, message) {
|
||||||
|
const msg1 = await once(bot, 'message')
|
||||||
|
expect(msg1.extra[0].text).toEqual(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function waitMessages (bot, messages) {
|
||||||
|
const toReceive = messages.reduce((acc, message) => {
|
||||||
|
acc[message] = 1
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
const received = {}
|
||||||
|
return new Promise(cb => {
|
||||||
|
const listener = msg => {
|
||||||
|
const message = msg.extra[0].text
|
||||||
|
if (!toReceive[message]) throw new Error('Received ' + message + ' , expected to receive one of ' + messages)
|
||||||
|
if (received[message]) throw new Error('Received ' + message + ' two times')
|
||||||
|
received[message] = 1
|
||||||
|
if (Object.keys(received).length == messages.length) {
|
||||||
|
bot.removeListener('message', listener)
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bot.on('message', listener)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function waitLoginMessage (bot) {
|
||||||
|
return Promise.all([waitMessages(bot, ['bot joined the game.', 'bot2 joined the game.'])])
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const options = settings
|
||||||
|
options['online-mode'] = false
|
||||||
|
options['port'] = 25566
|
||||||
|
options['view-distance'] = 2
|
||||||
|
options['worldFolder'] = undefined
|
||||||
|
options['logging'] = false
|
||||||
|
|
||||||
|
serv = squid.createMCServer(options)
|
||||||
|
|
||||||
|
await once(serv, 'listening')
|
||||||
|
bot = mineflayer.createBot({
|
||||||
|
host: 'localhost',
|
||||||
|
port: 25566,
|
||||||
|
username: 'bot',
|
||||||
|
version: '1.8'
|
||||||
|
})
|
||||||
|
bot2 = mineflayer.createBot({
|
||||||
|
host: 'localhost',
|
||||||
|
port: 25566,
|
||||||
|
username: 'bot2',
|
||||||
|
version: '1.8'
|
||||||
|
})
|
||||||
|
|
||||||
|
await Promise.all([once(bot, 'login'), once(bot2, 'login')])
|
||||||
|
bot.entity.onGround = false
|
||||||
|
bot2.entity.onGround = false
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await serv.quit()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('actions', () => {
|
||||||
|
function waitSpawnZone (bot, view) {
|
||||||
|
const nbChunksExpected = (view * 2) * (view * 2)
|
||||||
|
let c = 0
|
||||||
|
return new Promise(cb => {
|
||||||
|
const listener = () => {
|
||||||
|
c++
|
||||||
|
if (c == nbChunksExpected) {
|
||||||
|
bot.removeListener('chunkColumnLoad', listener)
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bot.on('chunkColumnLoad', listener)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
test('can dig', async () => {
|
||||||
|
await Promise.all([waitSpawnZone(bot, 2), waitSpawnZone(bot2, 2), onGround(bot), onGround(bot2)])
|
||||||
|
|
||||||
|
const pos = bot.entity.position.offset(0, -1, 0).floored()
|
||||||
|
bot.dig(bot.blockAt(pos))
|
||||||
|
|
||||||
|
let [, newBlock] = await once(bot2, 'blockUpdate', {array: true})
|
||||||
|
assertPosEqual(newBlock.position, pos)
|
||||||
|
expect(newBlock.type).toEqual(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('can place a block', async () => {
|
||||||
|
await Promise.all([waitSpawnZone(bot, 2), waitSpawnZone(bot2, 2), onGround(bot), onGround(bot2)])
|
||||||
|
|
||||||
|
const pos = bot.entity.position.offset(0, -2, 0).floored()
|
||||||
|
bot.dig(bot.blockAt(pos))
|
||||||
|
|
||||||
|
let [oldBlock, newBlock] = await once(bot2, 'blockUpdate', {array: true})
|
||||||
|
assertPosEqual(newBlock.position, pos)
|
||||||
|
expect(newBlock.type).toEqual(0)
|
||||||
|
|
||||||
|
bot.creative.setInventorySlot(36, new Item(1, 1))
|
||||||
|
await new Promise((cb) => {
|
||||||
|
bot.inventory.on('windowUpdate', (slot, oldItem, newItem) => {
|
||||||
|
if (slot == 36 && newItem && newItem.type == 1) { cb() }
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
bot.placeBlock(bot.blockAt(pos.offset(0, -1, 0)), new Vec3(0, 1, 0));
|
||||||
|
|
||||||
|
[oldBlock, newBlock] = await once(bot2, 'blockUpdate', {array: true})
|
||||||
|
assertPosEqual(newBlock.position, pos)
|
||||||
|
expect(newBlock.type).toEqual(1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('commands', () => {
|
||||||
|
jest.setTimeout(10 * 1000)
|
||||||
|
test('has an help command', async () => {
|
||||||
|
await waitLoginMessage(bot)
|
||||||
|
bot.chat('/help')
|
||||||
|
await once(bot, 'message')
|
||||||
|
})
|
||||||
|
test('can use /particle', async () => {
|
||||||
|
bot.chat('/particle 5 10 100 100 100')
|
||||||
|
await once(bot._client, 'world_particles')
|
||||||
|
})
|
||||||
|
test('can use /playsound', async () => {
|
||||||
|
bot.chat('/playsound ambient.weather.rain')
|
||||||
|
await once(bot, 'soundEffectHeard')
|
||||||
|
})
|
||||||
|
|
||||||
|
function waitDragon () {
|
||||||
|
return new Promise((done) => {
|
||||||
|
const listener = (entity) => {
|
||||||
|
if (entity.name == 'EnderDragon') {
|
||||||
|
bot.removeListener('entitySpawn', listener)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bot.on('entitySpawn', listener)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
test('can use /summon', async () => {
|
||||||
|
bot.chat('/summon EnderDragon')
|
||||||
|
await waitDragon()
|
||||||
|
})
|
||||||
|
test('can use /kill', async () => {
|
||||||
|
bot.chat('/summon EnderDragon')
|
||||||
|
await waitDragon()
|
||||||
|
bot.chat('/kill @e[type=EnderDragon]')
|
||||||
|
const entity = await once(bot, 'entityDead')
|
||||||
|
expect(entity.name).toEqual('EnderDragon')
|
||||||
|
})
|
||||||
|
describe('can use /tp', () => {
|
||||||
|
test('can tp myself', async () => {
|
||||||
|
bot.chat('/tp 2 3 4')
|
||||||
|
await once(bot, 'forcedMove')
|
||||||
|
assertPosEqual(bot.entity.position, new Vec3(2, 3, 4))
|
||||||
|
})
|
||||||
|
test('can tp somebody else', async () => {
|
||||||
|
bot.chat('/tp bot2 2 3 4')
|
||||||
|
await once(bot2, 'forcedMove')
|
||||||
|
assertPosEqual(bot2.entity.position, new Vec3(2, 3, 4))
|
||||||
|
})
|
||||||
|
test('can tp to somebody else', async () => {
|
||||||
|
await onGround(bot)
|
||||||
|
bot.chat('/tp bot2 bot')
|
||||||
|
await once(bot2, 'forcedMove')
|
||||||
|
assertPosEqual(bot2.entity.position, bot.entity.position)
|
||||||
|
})
|
||||||
|
test('can tp with relative positions', async () => {
|
||||||
|
await onGround(bot)
|
||||||
|
const initialPosition = bot.entity.position.clone()
|
||||||
|
bot.chat('/tp ~1 ~-2 ~3')
|
||||||
|
await once(bot, 'forcedMove')
|
||||||
|
assertPosEqual(bot.entity.position, initialPosition.offset(1, -2, 3))
|
||||||
|
})
|
||||||
|
test('can tp somebody else with relative positions', async () => {
|
||||||
|
await Promise.all([onGround(bot), onGround(bot2)])
|
||||||
|
const initialPosition = bot2.entity.position.clone()
|
||||||
|
bot.chat('/tp bot2 ~1 ~-2 ~3')
|
||||||
|
await once(bot2, 'forcedMove')
|
||||||
|
assertPosEqual(bot2.entity.position, initialPosition.offset(1, -2, 3))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
test('can use /deop', async () => {
|
||||||
|
await waitLoginMessage(bot)
|
||||||
|
bot.chat('/deop bot')
|
||||||
|
await waitMessage(bot, 'bot is deopped')
|
||||||
|
bot.chat('/op bot')
|
||||||
|
await waitMessage(bot, 'You do not have permission to use this command')
|
||||||
|
serv.getPlayer('bot').op = true
|
||||||
|
})
|
||||||
|
test('can use /setblock', async () => {
|
||||||
|
await once(bot, 'chunkColumnLoad')
|
||||||
|
bot.chat('/setblock 1 2 3 95 0')
|
||||||
|
let [, newBlock] = await once(bot, 'blockUpdate:' + new Vec3(1, 2, 3), {array: true})
|
||||||
|
expect(newBlock.type).toEqual(95)
|
||||||
|
})
|
||||||
|
test('can use /xp', async () => {
|
||||||
|
bot.chat('/xp 100')
|
||||||
|
await once(bot, 'experience')
|
||||||
|
expect(bot.experience.points).toEqual(100)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
253
test/portal.test.js
Normal file
253
test/portal.test.js
Normal file
|
|
@ -0,0 +1,253 @@
|
||||||
|
const {
|
||||||
|
portal_detector: {
|
||||||
|
detectFrame,
|
||||||
|
findPotentialLines,
|
||||||
|
findBorder,
|
||||||
|
getAir,
|
||||||
|
generateLine,
|
||||||
|
generatePortal,
|
||||||
|
makeWorldWithPortal
|
||||||
|
}
|
||||||
|
} = require('flying-squid')
|
||||||
|
|
||||||
|
const { Vec3 } = require('vec3')
|
||||||
|
const { range } = require('range')
|
||||||
|
|
||||||
|
describe('generate portal', () => {
|
||||||
|
test('generate a line', () => {
|
||||||
|
expect(generateLine(new Vec3(3, 1, 1), new Vec3(1, 0, 0), 2)).toEqual([new Vec3(3, 1, 1), new Vec3(4, 1, 1)])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('generate a portal', () => {
|
||||||
|
expect(generatePortal(new Vec3(2, 1, 1), new Vec3(1, 0, 0), 4, 5)).toEqual({
|
||||||
|
bottom: generateLine(new Vec3(3, 1, 1), new Vec3(1, 0, 0), 2),
|
||||||
|
left: generateLine(new Vec3(2, 2, 1), new Vec3(0, 1, 0), 3),
|
||||||
|
right: generateLine(new Vec3(5, 2, 1), new Vec3(0, 1, 0), 3),
|
||||||
|
top: generateLine(new Vec3(3, 5, 1), new Vec3(1, 0, 0), 2),
|
||||||
|
air: generateLine(new Vec3(3, 2, 1), new Vec3(0, 1, 0), 3).concat(generateLine(new Vec3(4, 2, 1), new Vec3(0, 1, 0), 3))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('detect portal', () => {
|
||||||
|
jest.setTimeout(60 * 1000)
|
||||||
|
const portalData = []
|
||||||
|
|
||||||
|
portalData.push({
|
||||||
|
name: 'simple portal frame x',
|
||||||
|
bottomLeft: new Vec3(2, 1, 1),
|
||||||
|
direction: new Vec3(1, 0, 0),
|
||||||
|
width: 4,
|
||||||
|
height: 5,
|
||||||
|
additionalAir: [],
|
||||||
|
additionalObsidian: []
|
||||||
|
})
|
||||||
|
|
||||||
|
portalData.push({
|
||||||
|
name: 'simple portal frame z',
|
||||||
|
bottomLeft: new Vec3(2, 1, 1),
|
||||||
|
direction: new Vec3(0, 0, 1),
|
||||||
|
width: 4,
|
||||||
|
height: 5,
|
||||||
|
additionalAir: [],
|
||||||
|
additionalObsidian: []
|
||||||
|
})
|
||||||
|
|
||||||
|
portalData.push({
|
||||||
|
name: 'big simple portal frame x',
|
||||||
|
bottomLeft: new Vec3(2, 1, 1),
|
||||||
|
direction: new Vec3(1, 0, 0),
|
||||||
|
width: 10,
|
||||||
|
height: 10,
|
||||||
|
additionalAir: [],
|
||||||
|
additionalObsidian: []
|
||||||
|
})
|
||||||
|
|
||||||
|
portalData.push({
|
||||||
|
name: 'simple portal frame x with borders',
|
||||||
|
bottomLeft: new Vec3(2, 1, 1),
|
||||||
|
direction: new Vec3(1, 0, 0),
|
||||||
|
width: 4,
|
||||||
|
height: 5,
|
||||||
|
additionalAir: [],
|
||||||
|
additionalObsidian: [new Vec3(2, 1, 1), new Vec3(5, 1, 1), new Vec3(2, 6, 1), new Vec3(5, 6, 1)]
|
||||||
|
})
|
||||||
|
|
||||||
|
const {bottom, left, right, top, air} = generatePortal(new Vec3(2, 1, 2), new Vec3(1, 0, 0), 4, 5)
|
||||||
|
|
||||||
|
portalData.push({
|
||||||
|
name: '2 portals',
|
||||||
|
bottomLeft: new Vec3(2, 1, 1),
|
||||||
|
direction: new Vec3(1, 0, 0),
|
||||||
|
width: 4,
|
||||||
|
height: 5,
|
||||||
|
additionalAir: air,
|
||||||
|
additionalObsidian: [].concat.apply([], [bottom, left, right, top])
|
||||||
|
})
|
||||||
|
|
||||||
|
portalData.push({
|
||||||
|
name: 'huge simple portal frame z',
|
||||||
|
bottomLeft: new Vec3(2, 1, 1),
|
||||||
|
direction: new Vec3(0, 0, 1),
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
additionalAir: [],
|
||||||
|
additionalObsidian: []
|
||||||
|
})
|
||||||
|
|
||||||
|
portalData.forEach(({name, bottomLeft, direction, width, height, additionalAir, additionalObsidian}) => {
|
||||||
|
const portal = generatePortal(bottomLeft, direction, width, height)
|
||||||
|
const {bottom, left, right, top, air} = portal
|
||||||
|
describe('Detect ' + name, () => {
|
||||||
|
const expectedBorder = {bottom, left, right, top}
|
||||||
|
|
||||||
|
let world
|
||||||
|
beforeAll(async function () {
|
||||||
|
world = await makeWorldWithPortal(portal, additionalAir, additionalObsidian)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('detect potential first lines', () => {
|
||||||
|
test('detect potential first lines from bottom left', async () => {
|
||||||
|
let potentialLines = await findPotentialLines(world, bottom[0], new Vec3(0, 1, 0))
|
||||||
|
expect(potentialLines).toContainEqual({
|
||||||
|
'direction': direction,
|
||||||
|
'line': bottom
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('detect potential first lines from bottom right', async () => {
|
||||||
|
let potentialLines = await findPotentialLines(world, bottom[bottom.length - 1], new Vec3(0, 1, 0))
|
||||||
|
expect(potentialLines).toContainEqual({
|
||||||
|
'direction': direction,
|
||||||
|
'line': bottom
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('detect potential first lines from top left', async () => {
|
||||||
|
let potentialLines = await findPotentialLines(world, top[0], new Vec3(0, -1, 0))
|
||||||
|
expect(potentialLines).toContainEqual({
|
||||||
|
'direction': direction,
|
||||||
|
'line': top
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('detect potential first lines from top right', async () => {
|
||||||
|
let potentialLines = await findPotentialLines(world, top[top.length - 1], new Vec3(0, -1, 0))
|
||||||
|
expect(potentialLines).toContainEqual({
|
||||||
|
'direction': direction,
|
||||||
|
'line': top
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('detect potential first lines from left top', async () => {
|
||||||
|
let potentialLines = await findPotentialLines(world, left[left.length - 1], direction)
|
||||||
|
expect(potentialLines).toEqual([{
|
||||||
|
'direction': new Vec3(0, 1, 0),
|
||||||
|
'line': left
|
||||||
|
}])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('detect potential first lines from right bottom', async () => {
|
||||||
|
let potentialLines = await findPotentialLines(world, right[0], direction.scaled(-1))
|
||||||
|
expect(potentialLines).toEqual([{
|
||||||
|
'direction': new Vec3(0, 1, 0),
|
||||||
|
'line': right
|
||||||
|
}])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('find borders', () => {
|
||||||
|
test('find borders from bottom', async () => {
|
||||||
|
const border = await findBorder(world, {
|
||||||
|
'direction': direction,
|
||||||
|
'line': bottom
|
||||||
|
}, new Vec3(0, 1, 0))
|
||||||
|
expect(border).toEqual(expectedBorder)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('find borders from top', async () => {
|
||||||
|
const border = await findBorder(world, {
|
||||||
|
'direction': direction,
|
||||||
|
'line': top
|
||||||
|
}, new Vec3(0, -1, 0))
|
||||||
|
expect(border).toEqual(expectedBorder)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('find borders from left', async () => {
|
||||||
|
const border = await findBorder(world, {
|
||||||
|
'direction': new Vec3(0, 1, 0),
|
||||||
|
'line': left
|
||||||
|
}, direction)
|
||||||
|
expect(border).toEqual(expectedBorder)
|
||||||
|
})
|
||||||
|
test('find borders from right', async () => {
|
||||||
|
const border = await findBorder(world, {
|
||||||
|
'direction': new Vec3(0, 1, 0),
|
||||||
|
'line': right
|
||||||
|
}, direction.scaled(-1))
|
||||||
|
expect(border).toEqual(expectedBorder)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('detect portals', () => {
|
||||||
|
test('detect portals from bottom left', async () => {
|
||||||
|
const portals = await detectFrame(world, bottom[0], new Vec3(0, 1, 0))
|
||||||
|
expect(portals).toEqual([portal])
|
||||||
|
})
|
||||||
|
test('detect portals from top left', async () => {
|
||||||
|
const portals = await detectFrame(world, top[0], new Vec3(0, -1, 0))
|
||||||
|
expect(portals).toEqual([portal])
|
||||||
|
})
|
||||||
|
test('detect portals from right top', async () => {
|
||||||
|
const portals = await detectFrame(world, right[right.length - 1], direction.scaled(-1))
|
||||||
|
expect(portals).toEqual([portal])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('get air', () => {
|
||||||
|
const foundAir = getAir(expectedBorder)
|
||||||
|
expect(foundAir).toEqual(air)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("doesn't detect non-portal", () => {
|
||||||
|
const portalData = []
|
||||||
|
|
||||||
|
portalData.push({
|
||||||
|
name: 'simple portal frame x with one obsidian in the middle',
|
||||||
|
bottomLeft: new Vec3(2, 1, 1),
|
||||||
|
direction: new Vec3(1, 0, 0),
|
||||||
|
width: 5,
|
||||||
|
height: 5,
|
||||||
|
additionalAir: [],
|
||||||
|
additionalObsidian: [new Vec3(4, 3, 1)]
|
||||||
|
})
|
||||||
|
|
||||||
|
portalData.forEach(({name, bottomLeft, direction, width, height, additionalAir, additionalObsidian}) => {
|
||||||
|
const portal = generatePortal(bottomLeft, direction, width, height)
|
||||||
|
const {bottom, left, right, top} = portal
|
||||||
|
describe("doesn't detect detect " + name, () => {
|
||||||
|
let world
|
||||||
|
beforeAll(async function () {
|
||||||
|
world = await makeWorldWithPortal(portal, additionalAir, additionalObsidian)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("doesn't detect portals", () => {
|
||||||
|
test("doesn't detect portals from bottom left", async () => {
|
||||||
|
const portals = await detectFrame(world, bottom[0], new Vec3(0, 1, 0))
|
||||||
|
expect(portals).toEqual([])
|
||||||
|
})
|
||||||
|
test("doesn't detect portals from top left", async () => {
|
||||||
|
const portals = await detectFrame(world, top[0], new Vec3(0, -1, 0))
|
||||||
|
expect(portals).toEqual([])
|
||||||
|
})
|
||||||
|
test("doesn't detect portals from right top", async () => {
|
||||||
|
const portals = await detectFrame(world, right[right.length - 1], direction.scaled(-1))
|
||||||
|
expect(portals).toEqual([])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
@ -1,247 +0,0 @@
|
||||||
const {detectFrame,findPotentialLines,findBorder,getAir,generateLine,generatePortal,makeWorldWithPortal}=require("flying-squid").portal_detector;
|
|
||||||
const Vec3 = require("vec3").Vec3;
|
|
||||||
const assert = require('chai').assert;
|
|
||||||
const range = require('range').range;
|
|
||||||
|
|
||||||
|
|
||||||
describe("Generate portal",function(){
|
|
||||||
it("generate a line",() => {
|
|
||||||
assert.deepEqual(generateLine(new Vec3(3,1,1),new Vec3(1,0,0),2),[new Vec3(3, 1, 1), new Vec3(4, 1, 1)])
|
|
||||||
});
|
|
||||||
it("generate a portal", () => {
|
|
||||||
assert.deepEqual(generatePortal(new Vec3(2,1,1),new Vec3(1,0,0),4,5),{
|
|
||||||
bottom:generateLine(new Vec3(3,1,1),new Vec3(1,0,0),2),
|
|
||||||
left:generateLine(new Vec3(2,2,1),new Vec3(0,1,0),3),
|
|
||||||
right:generateLine(new Vec3(5,2,1),new Vec3(0,1,0),3),
|
|
||||||
top:generateLine(new Vec3(3,5,1),new Vec3(1,0,0),2),
|
|
||||||
air:generateLine(new Vec3(3,2,1),new Vec3(0,1,0),3).concat(generateLine(new Vec3(4,2,1),new Vec3(0,1,0),3))
|
|
||||||
})
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Detect portal", function() {
|
|
||||||
this.timeout(60 * 1000);
|
|
||||||
const portalData=[];
|
|
||||||
portalData.push({
|
|
||||||
name:"simple portal frame x",
|
|
||||||
bottomLeft:new Vec3(2,1,1),
|
|
||||||
direction:new Vec3(1,0,0),
|
|
||||||
width:4,
|
|
||||||
height:5,
|
|
||||||
additionalAir:[],
|
|
||||||
additionalObsidian:[]
|
|
||||||
});
|
|
||||||
portalData.push({
|
|
||||||
name:"simple portal frame z",
|
|
||||||
bottomLeft:new Vec3(2,1,1),
|
|
||||||
direction:new Vec3(0,0,1),
|
|
||||||
width:4,
|
|
||||||
height:5,
|
|
||||||
additionalAir:[],
|
|
||||||
additionalObsidian:[]
|
|
||||||
});
|
|
||||||
portalData.push({
|
|
||||||
name:"big simple portal frame x",
|
|
||||||
bottomLeft:new Vec3(2,1,1),
|
|
||||||
direction:new Vec3(1,0,0),
|
|
||||||
width:10,
|
|
||||||
height:10,
|
|
||||||
additionalAir:[],
|
|
||||||
additionalObsidian:[]
|
|
||||||
});
|
|
||||||
portalData.push({
|
|
||||||
name:"simple portal frame x with borders",
|
|
||||||
bottomLeft:new Vec3(2,1,1),
|
|
||||||
direction:new Vec3(1,0,0),
|
|
||||||
width:4,
|
|
||||||
height:5,
|
|
||||||
additionalAir:[],
|
|
||||||
additionalObsidian:[new Vec3(2,1,1),new Vec3(5,1,1),new Vec3(2,6,1),new Vec3(5,6,1)]
|
|
||||||
});
|
|
||||||
const {bottom,left,right,top,air}=generatePortal(new Vec3(2,1,2),new Vec3(1,0,0),4,5);
|
|
||||||
|
|
||||||
portalData.push({
|
|
||||||
name:"2 portals",
|
|
||||||
bottomLeft:new Vec3(2,1,1),
|
|
||||||
direction:new Vec3(1,0,0),
|
|
||||||
width:4,
|
|
||||||
height:5,
|
|
||||||
additionalAir:air,
|
|
||||||
additionalObsidian:[].concat.apply([], [bottom, left, right,top])
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
portalData.push({
|
|
||||||
name:"huge simple portal frame z",
|
|
||||||
bottomLeft:new Vec3(2,1,1),
|
|
||||||
direction:new Vec3(0,0,1),
|
|
||||||
width:50,
|
|
||||||
height:50,
|
|
||||||
additionalAir:[],
|
|
||||||
additionalObsidian:[]
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
portalData.forEach(({name,bottomLeft,direction,width,height,additionalAir,additionalObsidian}) => {
|
|
||||||
const portal=generatePortal(bottomLeft,direction,width,height);
|
|
||||||
const {bottom,left,right,top,air}=portal;
|
|
||||||
describe("Detect "+name,() => {
|
|
||||||
const expectedBorder={bottom,left,right,top};
|
|
||||||
|
|
||||||
let world;
|
|
||||||
before(async function(){
|
|
||||||
world=await makeWorldWithPortal(portal,additionalAir,additionalObsidian);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe("detect potential first lines",function(){
|
|
||||||
it("detect potential first lines from bottom left", async function() {
|
|
||||||
let potentialLines=await findPotentialLines(world,bottom[0],new Vec3(0,1,0));
|
|
||||||
assert.include(potentialLines,{
|
|
||||||
"direction": direction,
|
|
||||||
"line": bottom
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("detect potential first lines from bottom right", async function() {
|
|
||||||
let potentialLines=await findPotentialLines(world,bottom[bottom.length-1],new Vec3(0,1,0));
|
|
||||||
assert.include(potentialLines,{
|
|
||||||
"direction": direction,
|
|
||||||
"line": bottom
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it("detect potential first lines from top left", async function() {
|
|
||||||
let potentialLines=await findPotentialLines(world,top[0],new Vec3(0,-1,0));
|
|
||||||
assert.include(potentialLines,{
|
|
||||||
"direction": direction,
|
|
||||||
"line": top
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("detect potential first lines from top right", async function() {
|
|
||||||
let potentialLines=await findPotentialLines(world,top[top.length-1],new Vec3(0,-1,0));
|
|
||||||
assert.include(potentialLines,{
|
|
||||||
"direction": direction,
|
|
||||||
"line": top
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("detect potential first lines from left top", async function() {
|
|
||||||
let potentialLines=await findPotentialLines(world,left[left.length-1],direction);
|
|
||||||
assert.include(potentialLines,{
|
|
||||||
"direction": new Vec3(0,1,0),
|
|
||||||
"line": left
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("detect potential first lines from right bottom", async function() {
|
|
||||||
let potentialLines=await findPotentialLines(world,right[0],direction.scaled(-1));
|
|
||||||
assert.include(potentialLines,{
|
|
||||||
"direction": new Vec3(0,1,0),
|
|
||||||
"line": right
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe("find borders",function() {
|
|
||||||
it("find borders from bottom", async function () {
|
|
||||||
const border = await findBorder(world, {
|
|
||||||
"direction": direction,
|
|
||||||
"line": bottom
|
|
||||||
}, new Vec3(0, 1, 0));
|
|
||||||
assert.deepEqual(border, expectedBorder)
|
|
||||||
});
|
|
||||||
|
|
||||||
it("find borders from top", async function () {
|
|
||||||
const border = await findBorder(world, {
|
|
||||||
"direction": direction,
|
|
||||||
"line": top
|
|
||||||
}, new Vec3(0, -1, 0));
|
|
||||||
assert.deepEqual(border, expectedBorder)
|
|
||||||
});
|
|
||||||
|
|
||||||
it("find borders from left", async function () {
|
|
||||||
const border = await findBorder(world, {
|
|
||||||
"direction": new Vec3(0, 1, 0),
|
|
||||||
"line": left
|
|
||||||
},direction);
|
|
||||||
assert.deepEqual(border, expectedBorder)
|
|
||||||
});
|
|
||||||
it("find borders from right", async function () {
|
|
||||||
const border = await findBorder(world, {
|
|
||||||
"direction": new Vec3(0, 1, 0),
|
|
||||||
"line": right
|
|
||||||
}, direction.scaled(-1));
|
|
||||||
assert.deepEqual(border, expectedBorder)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("detect portals",function(){
|
|
||||||
it("detect portals from bottom left",async function() {
|
|
||||||
const portals=await detectFrame(world,bottom[0],new Vec3(0,1,0));
|
|
||||||
assert.deepEqual(portals,[portal])
|
|
||||||
});
|
|
||||||
it("detect portals from top left",async function() {
|
|
||||||
const portals=await detectFrame(world,top[0],new Vec3(0,-1,0));
|
|
||||||
assert.deepEqual(portals,[portal])
|
|
||||||
});
|
|
||||||
it("detect portals from right top",async function() {
|
|
||||||
const portals=await detectFrame(world,right[right.length-1],direction.scaled(-1));
|
|
||||||
assert.deepEqual(portals,[portal])
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
it("get air",function(){
|
|
||||||
const foundAir=getAir(expectedBorder);
|
|
||||||
assert.deepEqual(foundAir,air);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe("Doesn't detect non-portal",function() {
|
|
||||||
const portalData=[];
|
|
||||||
|
|
||||||
portalData.push({
|
|
||||||
name:"simple portal frame x with one obsidian in the middle",
|
|
||||||
bottomLeft:new Vec3(2,1,1),
|
|
||||||
direction:new Vec3(1,0,0),
|
|
||||||
width:5,
|
|
||||||
height:5,
|
|
||||||
additionalAir:[],
|
|
||||||
additionalObsidian:[new Vec3(4,3,1)]
|
|
||||||
});
|
|
||||||
|
|
||||||
portalData.forEach(({name,bottomLeft,direction,width,height,additionalAir,additionalObsidian}) => {
|
|
||||||
const portal = generatePortal(bottomLeft, direction, width, height);
|
|
||||||
const {bottom,left,right,top}=portal;
|
|
||||||
describe("Doesn't detect detect " + name, () => {
|
|
||||||
let world;
|
|
||||||
before(async function () {
|
|
||||||
world=await makeWorldWithPortal(portal, additionalAir, additionalObsidian);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("doesn't detect portals",function(){
|
|
||||||
it("doesn't detect portals from bottom left",async function() {
|
|
||||||
const portals=await detectFrame(world,bottom[0],new Vec3(0,1,0));
|
|
||||||
assert.deepEqual(portals,[])
|
|
||||||
});
|
|
||||||
it("doesn't detect portals from top left",async function() {
|
|
||||||
const portals=await detectFrame(world,top[0],new Vec3(0,-1,0));
|
|
||||||
assert.deepEqual(portals,[])
|
|
||||||
});
|
|
||||||
it("doesn't detect portals from right top",async function() {
|
|
||||||
const portals=await detectFrame(world,right[right.length-1],direction.scaled(-1));
|
|
||||||
assert.deepEqual(portals,[])
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
const net = require('net');
|
|
||||||
describe("Server", function() {
|
|
||||||
let serv;
|
|
||||||
before(function(done){
|
|
||||||
serv=require("../app");
|
|
||||||
serv.on("listening",function(){
|
|
||||||
done(null);
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
after(function(done){
|
|
||||||
serv._server.close();
|
|
||||||
serv._server.on("close",function(){
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it("Is running", function(done) {
|
|
||||||
const client = net.Socket();
|
|
||||||
client.connect(serv._server.socketServer.address().port, '127.0.0.1', done);
|
|
||||||
client.on('error', done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
35
test/simple.test.js
Normal file
35
test/simple.test.js
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
const net = require('net')
|
||||||
|
const squid = require('flying-squid')
|
||||||
|
|
||||||
|
const settings = require('../config/default-settings')
|
||||||
|
|
||||||
|
describe('server', () => {
|
||||||
|
let serv
|
||||||
|
|
||||||
|
beforeAll(done => {
|
||||||
|
const options = settings
|
||||||
|
options['online-mode'] = false
|
||||||
|
options['port'] = 25566
|
||||||
|
options['view-distance'] = 2
|
||||||
|
options['worldFolder'] = undefined
|
||||||
|
options['logging'] = false
|
||||||
|
serv = squid.createMCServer(options)
|
||||||
|
|
||||||
|
serv.on('listening', () => {
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(done => {
|
||||||
|
serv._server.close()
|
||||||
|
serv._server.on('close', () => {
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('is running', done => {
|
||||||
|
const client = net.Socket()
|
||||||
|
client.connect(serv._server.socketServer.address().port, '127.0.0.1', done)
|
||||||
|
client.on('error', done)
|
||||||
|
})
|
||||||
|
})
|
||||||
Loading…
Reference in a new issue