mirror of
https://github.com/danbulant/flying-squid
synced 2026-07-03 18:20:42 +00:00
fix destroying multiple portal at the same time, add /portal command to create a portal, expose various portal generation function
This commit is contained in:
parent
6cb2bba019
commit
e792f5d671
4 changed files with 121 additions and 80 deletions
72
src/lib/plugins/portal.js
Normal file
72
src/lib/plugins/portal.js
Normal file
|
|
@ -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 <bottomLeft:<x> <y> <z>> <direction:x|z> <width> <height>',
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
var items=require("minecraft-data")(require("flying-squid").version).items;
|
var items=require("minecraft-data")(require("flying-squid").version).items;
|
||||||
var Vec3 = require("vec3").Vec3;
|
var Vec3 = require("vec3").Vec3;
|
||||||
var {detectFrame,getAir}=require("flying-squid").portal_detector;
|
|
||||||
|
|
||||||
module.exports.player=function(player,serv)
|
module.exports.player=function(player,serv)
|
||||||
{
|
{
|
||||||
|
|
@ -14,46 +13,5 @@ module.exports.player=function(player,serv)
|
||||||
if(item.name=="flint_and_steel")
|
if(item.name=="flint_and_steel")
|
||||||
player.use_flint_and_steel(referencePosition,directionVector);
|
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)];
|
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)];
|
||||||
|
|
@ -3,7 +3,7 @@ var assert = require('assert');
|
||||||
var flatMap = require('flatmap');
|
var flatMap = require('flatmap');
|
||||||
var range = require('range').range;
|
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)
|
async function findLineInDirection(world,startingPoint,type,direction,directionV)
|
||||||
{
|
{
|
||||||
|
|
@ -105,4 +105,51 @@ function getAir(border)
|
||||||
{
|
{
|
||||||
var {bottom,top}=border;
|
var {bottom,top}=border;
|
||||||
return flatMap(bottom,pos => range(1,top[0].y-bottom[0].y).map(i => pos.offset(0,i,0)));
|
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;
|
||||||
}
|
}
|
||||||
|
|
@ -1,44 +1,8 @@
|
||||||
var {detectFrame,findPotentialLines,findBorder,getAir}=require("flying-squid").portal_detector;
|
var {detectFrame,findPotentialLines,findBorder,getAir,generateLine,generatePortal,addPortalToWorld,makeWorldWithPortal}=require("flying-squid").portal_detector;
|
||||||
var World = require('prismarine-world');
|
|
||||||
var Chunk = require('prismarine-chunk')(require("flying-squid").version);
|
|
||||||
var Vec3 = require("vec3").Vec3;
|
var Vec3 = require("vec3").Vec3;
|
||||||
var assert = require('chai').assert;
|
var assert = require('chai').assert;
|
||||||
var range = require('range').range;
|
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(){
|
describe("Generate portal",function(){
|
||||||
it("generate a line",() => {
|
it("generate a line",() => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue