From e792f5d671bdd187f524b42828af9599a0899da8 Mon Sep 17 00:00:00 2001 From: Romain Beaumont Date: Mon, 14 Dec 2015 22:36:15 +0100 Subject: [PATCH] fix destroying multiple portal at the same time, add /portal command to create a portal, expose various portal generation function --- src/lib/plugins/portal.js | 72 ++++++++++++++++++++++++++++++++++++++ src/lib/plugins/useItem.js | 42 ---------------------- src/lib/portal_detector.js | 49 +++++++++++++++++++++++++- test/portal_detector.js | 38 +------------------- 4 files changed, 121 insertions(+), 80 deletions(-) create mode 100644 src/lib/plugins/portal.js diff --git a/src/lib/plugins/portal.js b/src/lib/plugins/portal.js new file mode 100644 index 0000000..a16a52a --- /dev/null +++ b/src/lib/plugins/portal.js @@ -0,0 +1,72 @@ +var {detectFrame,generatePortal,addPortalToWorld}=require("flying-squid").portal_detector; +var Vec3 = require("vec3").Vec3; +var UserError=require("flying-squid").UserError; + +module.exports.player=function(player,serv) { + player.use_flint_and_steel=async (referencePosition,direction) => { + let block=await player.world.getBlock(referencePosition); + if(block.name=="obsidian") + { + var frames=await detectFrame(player.world,referencePosition,direction); + if(frames.length==0) + return; + var air=frames[0].air; + air.forEach(pos => player.setBlock(pos,90,(frames[0].bottom[0].x-frames[0].bottom[1].x)!=0 ? 1 : 2)); + player.world.portals.push(frames[0]); + } + }; + + player.on("dug",({position,block}) => { + + function destroyPortal(portal,positionAlreadyDone=null) + { + player.world.portals=player.world.portals.splice(player.world.portals.indexOf(portal),1); + portal + .air + .filter(ap => positionAlreadyDone==null || !ap.equals(positionAlreadyDone)) + .forEach(ap => serv.setBlock(player.world,ap,0,0)); + } + + if(block.name=="obsidian") + { + const p=player.world.portals.filter(({bottom,top,left,right}) => + [].concat.apply([], [bottom, left, right,top]) + .reduce((acc,pos) => acc || pos.equals(position),false)); + p.forEach(portal => destroyPortal(portal,position)); + } + + if(block.name=="portal") + { + const p=player.world.portals.filter(({air}) => air.reduce((acc,pos) => acc || pos.equals(position),false)); + p.forEach(portal => destroyPortal(portal,position)); + } + }); + + + + player.commands.add({ + base: 'portal', + info: 'Create a portal frame', + usage: '/portal > ', + op: true, + parse(str) { + var pars=str.split(' '); + if(pars.length!=6) + return false; + let [x,y,z,direction,width,height]=pars; + [x,y,z] = [x,y,z].map((val, i) => serv.posFromString(val, player.position[['x','y','z'][i]] / 32)); + const bottomLeft=new Vec3(x,y,z); + if(direction!="x" && direction!="z") + throw new UserError('Wrong Direction'); + direction=direction=='x' ? new Vec3(1,0,0) : Vec3(0,0,1); + return {bottomLeft,direction,width,height}; + }, + async action({bottomLeft,direction,width,height}) { + var portal=generatePortal(bottomLeft,direction,width,height); + await addPortalToWorld(player.world,portal,[],[],(pos,type) => { + serv.setBlock(player.world,pos,type,0); + }); + } + }); + +}; \ No newline at end of file diff --git a/src/lib/plugins/useItem.js b/src/lib/plugins/useItem.js index 73a28be..d3e7606 100644 --- a/src/lib/plugins/useItem.js +++ b/src/lib/plugins/useItem.js @@ -1,6 +1,5 @@ var items=require("minecraft-data")(require("flying-squid").version).items; var Vec3 = require("vec3").Vec3; -var {detectFrame,getAir}=require("flying-squid").portal_detector; module.exports.player=function(player,serv) { @@ -14,46 +13,5 @@ module.exports.player=function(player,serv) if(item.name=="flint_and_steel") player.use_flint_and_steel(referencePosition,directionVector); }); - - player.use_flint_and_steel=async (referencePosition,direction) => { - let block=await player.world.getBlock(referencePosition); - if(block.name=="obsidian") - { - var frames=await detectFrame(player.world,referencePosition,direction); - if(frames.length==0) - return; - var air=frames[0].air; - air.forEach(pos => player.setBlock(pos,90,(frames[0].bottom[0].x-frames[0].bottom[1].x)!=0 ? 1 : 2)); - player.world.portals.push(frames[0]); - } - }; - - player.on("dug",({position,block}) => { - - function destroyPortal(portal,positionAlreadyDone=null) - { - portal - .air - .filter(ap => positionAlreadyDone==null || !ap.equals(positionAlreadyDone)) - .forEach(ap => serv.setBlock(player.world,ap,0,0)); - player.world.portals=player.world.portals.splice(player.world.portals.indexOf(portal),1); - } - - if(block.name=="obsidian") - { - const p=player.world.portals.filter(({bottom,top,left,right}) => - [].concat.apply([], [bottom, left, right,top]) - .reduce((acc,pos) => acc || pos.equals(position),false)); - if(p.length>0) - destroyPortal(p[0],position); - } - - if(block.name=="portal") - { - const p=player.world.portals.filter(({air}) => air.reduce((acc,pos) => acc || pos.equals(position),false)); - if(p.length>0) - destroyPortal(p[0],position); - } - }); }; var directionToVector=[new Vec3(0,-1,0),new Vec3(0,1,0),new Vec3(0,0,-1),new Vec3(0,0,1),new Vec3(-1,0,0),new Vec3(1,0,0)]; \ No newline at end of file diff --git a/src/lib/portal_detector.js b/src/lib/portal_detector.js index b4535ea..85fee4b 100644 --- a/src/lib/portal_detector.js +++ b/src/lib/portal_detector.js @@ -3,7 +3,7 @@ var assert = require('assert'); var flatMap = require('flatmap'); var range = require('range').range; -module.exports={detectFrame,findPotentialLines,findBorder,getAir}; +module.exports={detectFrame,findPotentialLines,findBorder,getAir,generateLine,generatePortal,addPortalToWorld,makeWorldWithPortal}; async function findLineInDirection(world,startingPoint,type,direction,directionV) { @@ -105,4 +105,51 @@ function getAir(border) { var {bottom,top}=border; return flatMap(bottom,pos => range(1,top[0].y-bottom[0].y).map(i => pos.offset(0,i,0))); +} + + +var World = require('prismarine-world'); +var Chunk = require('prismarine-chunk')(require("./version")); + +function generateLine(startingPoint,direction,length) { + return range(0,length).map(i => startingPoint.plus(direction.scaled(i))); +} + +function generatePortal(bottomLeft,direction,width,height){ + var directionV=new Vec3(0,1,0); + return { + bottom:generateLine(bottomLeft.plus(direction),direction,width-2), + left:generateLine(bottomLeft.plus(directionV),directionV,height-2), + right:generateLine(bottomLeft.plus(direction.scaled(width-1)).plus(directionV),directionV,height-2), + top:generateLine(bottomLeft.plus(directionV.scaled(height-1).plus(direction)),direction,width-2), + air:flatMap(generateLine(bottomLeft.plus(direction).plus(directionV),direction,width-2), + p => generateLine(p,directionV,height-2)) + } +} + +function addPortalToWorld(world,portal,additionalAir,additionalObsidian,setBlockType=null) +{ + if(setBlockType==null) + setBlockType=world.setBlockType.bind(world); + let {bottom,left,right,top,air}=portal; + + var p=flatMap([bottom,left,right,top],border => border.map(pos => setBlockType(pos,49))); + p.push(air.map(pos => setBlockType(pos,0))); + + p.push(additionalAir.map(pos => setBlockType(pos,0))); + p.push(additionalObsidian.map(pos => setBlockType(pos,49))); + + return Promise.all(p); +} + + +async function makeWorldWithPortal(portal,additionalAir,additionalObsidian) +{ + + var world=new World(); + var chunk=new Chunk(); + await world.setColumn(0,0,chunk); + await addPortalToWorld(world,portal,additionalAir,additionalObsidian); + + return world; } \ No newline at end of file diff --git a/test/portal_detector.js b/test/portal_detector.js index d22ade2..8050dd6 100644 --- a/test/portal_detector.js +++ b/test/portal_detector.js @@ -1,44 +1,8 @@ -var {detectFrame,findPotentialLines,findBorder,getAir}=require("flying-squid").portal_detector; -var World = require('prismarine-world'); -var Chunk = require('prismarine-chunk')(require("flying-squid").version); +var {detectFrame,findPotentialLines,findBorder,getAir,generateLine,generatePortal,addPortalToWorld,makeWorldWithPortal}=require("flying-squid").portal_detector; var Vec3 = require("vec3").Vec3; var assert = require('chai').assert; var range = require('range').range; -var flatMap = require('flatmap'); -function generateLine(startingPoint,direction,length) { - return range(0,length).map(i => startingPoint.plus(direction.scaled(i))); -} - -function generatePortal(bottomLeft,direction,width,height){ - var directionV=new Vec3(0,1,0); - return { - bottom:generateLine(bottomLeft.plus(direction),direction,width-2), - left:generateLine(bottomLeft.plus(directionV),directionV,height-2), - right:generateLine(bottomLeft.plus(direction.scaled(width-1)).plus(directionV),directionV,height-2), - top:generateLine(bottomLeft.plus(directionV.scaled(height-1).plus(direction)),direction,width-2), - air:flatMap(generateLine(bottomLeft.plus(direction).plus(directionV),direction,width-2), - p => generateLine(p,directionV,height-2)) - } -} - - -async function makeWorldWithPortal(portal,additionalAir,additionalObsidian) -{ - var {bottom,left,right,top,air}=portal; - var world=new World(); - var chunk=new Chunk(); - - [bottom,left,right,top].forEach(border => border.forEach(pos => chunk.setBlockType(pos,49))); - air.forEach(pos => chunk.setBlockType(pos,0)); - - additionalAir.forEach(pos => chunk.setBlockType(pos,0)); - additionalObsidian.forEach(pos => chunk.setBlockType(pos,49)); - - - await world.setColumn(0,0,chunk); - return world; -} describe("Generate portal",function(){ it("generate a line",() => {