Spaces:
Build error
Build error
const BlockType = require('../../extension-support/block-type'); | |
const ArgumentType = require('../../extension-support/argument-type'); | |
const formatMessage = require('format-message'); | |
const Cast = require('../../util/cast'); | |
const Clone = require('../../util/clone'); | |
const Pathfinding = require('pathfinding'); | |
const Nodes = require('./nodes'); | |
const Seperator = require('./seperator'); | |
const Map = require('./map'); | |
/* | |
develope test | |
do the Seperator functions work? | |
const _testGrid = [ | |
[0, 0, 0, 0, 0], | |
[0, 1, 1, 1, 0], | |
[0, 1, 1, 1, 0], | |
[0, 0, 0, 0, 0], | |
]; | |
console.log(_testGrid); | |
const _marginGrid = Seperator.marginGrid(_testGrid, 4); | |
console.log(_marginGrid); | |
const _padGrid = Seperator.padGrid(_marginGrid, 3, 3); | |
console.log(_padGrid); | |
develope test RESULTS | |
no not really for some reason | |
one of the functions adds like 60 items to a row | |
but only the rows that were created inside of that function | |
ok now they work lol | |
*/ | |
/* | |
develope test | |
do the Map functions work? | |
const _testMap = new Map(); | |
console.log(Clone.simple(_testMap)); | |
_testMap.add(0, 0, 50, 50); | |
_testMap.add(-50, 0, 0, -50); | |
console.log(Clone.simple(_testMap)); | |
console.log(_testMap.toGrid()); | |
develope test RESULTS | |
i put the offset x and y in the wrong order lol | |
somehow Math.abs stopped working | |
nvm i just messed somethin up with the offsets and X was negative | |
ok somehow its sitll not working even though grid is the right size | |
seems like after creating blank tiles, the walls create too many tiles | |
oh i was literally just using 2 variables i shouldnt have been using | |
and now grid is blank brh | |
nevermind i was reading the wrong grid | |
Map class should fully work | |
*/ | |
/** | |
* Class for Pathfinding blocks | |
* @constructor | |
*/ | |
class JgPathfindingBlocks { | |
constructor(runtime) { | |
/** | |
* The runtime instantiating this block package. | |
* @type {Runtime} | |
*/ | |
this.runtime = runtime; | |
/** | |
* The current map and it's boxes. | |
*/ | |
this.map = new Map(); | |
/** | |
* The current settings for the pathfinding character. | |
*/ | |
this.pather = { | |
x: 0, | |
y: 0, | |
width: 1, | |
height: 1 | |
} | |
/** | |
* The current result of the pathfinding operation. | |
*/ | |
this.pathNodes = new Nodes(); | |
} | |
/** | |
* @returns {object} metadata for this extension and its blocks. | |
*/ | |
getInfo() { | |
return { | |
id: 'jgPathfinding', | |
name: 'Pathfinding', | |
color1: '#5386E2', | |
color2: '#4169B1', | |
blocks: [ | |
{ | |
opcode: 'createBlockadeAt', | |
text: formatMessage({ | |
id: 'jgPathfinding.blocks.createBlockadeAt', | |
default: 'create blockade at x1: [X1] y1: [Y1] x2: [X2] y2: [Y2]', | |
description: "Block that creates a blockade in the pathfinding area." | |
}), | |
arguments: { | |
X1: { type: ArgumentType.NUMBER, defaultValue: -70 }, | |
Y1: { type: ArgumentType.NUMBER, defaultValue: 20 }, | |
X2: { type: ArgumentType.NUMBER, defaultValue: 70 }, | |
Y2: { type: ArgumentType.NUMBER, defaultValue: -20 }, | |
}, | |
blockType: BlockType.COMMAND | |
}, | |
{ | |
opcode: 'clearBlockades', | |
text: formatMessage({ | |
id: 'jgPathfinding.blocks.clearBlockades', | |
default: 'clear blockades', | |
description: "Block that removes all blockades in the pathfinding area." | |
}), | |
blockType: BlockType.COMMAND | |
}, | |
{ | |
opcode: 'setPatherXY', | |
text: formatMessage({ | |
id: 'jgPathfinding.blocks.setPatherXY', | |
default: 'set pather starting x: [X] y: [Y]', | |
description: "Block that sets the starting position for the pather." | |
}), | |
arguments: { | |
X: { type: ArgumentType.NUMBER, defaultValue: 0 }, | |
Y: { type: ArgumentType.NUMBER, defaultValue: 120 }, | |
}, | |
blockType: BlockType.COMMAND | |
}, | |
{ | |
opcode: 'setWidthHeight', | |
text: formatMessage({ | |
id: 'jgPathfinding.blocks.setWidthHeight', | |
default: 'set pather width: [WIDTH] height: [HEIGHT]', | |
description: "Block that sets the width and height of the path follower. This allows sprites to avoid clipping inside walls on the way to the destination." | |
}), | |
arguments: { | |
WIDTH: { type: ArgumentType.NUMBER, defaultValue: 55 }, | |
HEIGHT: { type: ArgumentType.NUMBER, defaultValue: 95 }, | |
}, | |
blockType: BlockType.COMMAND | |
}, | |
{ | |
opcode: 'pathToSpot', | |
text: formatMessage({ | |
id: 'jgPathfinding.blocks.pathToSpot', | |
default: 'find path to x: [X] y: [Y] around blockades', | |
description: "Block that finds a path around blockades in the pathfinding area to get to a location." | |
}), | |
arguments: { | |
X: { type: ArgumentType.NUMBER, defaultValue: 60 }, | |
Y: { type: ArgumentType.NUMBER, defaultValue: -60 }, | |
}, | |
blockType: BlockType.COMMAND | |
}, | |
'---', | |
{ | |
opcode: 'setListToPath', | |
text: formatMessage({ | |
id: 'jgPathfinding.blocks.setListToPath', | |
default: 'set [LIST] to current path', | |
description: "Block that sets a list to the current path." | |
}), | |
arguments: { | |
LIST: { type: ArgumentType.LIST }, | |
}, | |
hideFromPalette: true, | |
blockType: BlockType.COMMAND | |
}, | |
{ | |
opcode: 'getPathAs', | |
text: formatMessage({ | |
id: 'jgPathfinding.blocks.getPathAs', | |
default: 'current path as [TYPE]', | |
description: "Block that returns the current path in a certain way." | |
}), | |
arguments: { | |
TYPE: { type: ArgumentType.STRING, menu: "pathReturnType" }, | |
}, | |
disableMonitor: true, | |
blockType: BlockType.REPORTER | |
}, | |
], | |
menus: { | |
// lists: "menuLists", | |
pathReturnType: { | |
acceptReporters: true, | |
items: [ | |
"json arrays", | |
"json array with objects", | |
"json object", | |
"comma seperated list", | |
].map(item => ({ text: item, value: item })) | |
} | |
} | |
}; | |
} | |
// menus | |
// blocks | |
createBlockadeAt(args) { | |
const x1 = Cast.toNumber(args.X1); | |
const y1 = Cast.toNumber(args.Y1); | |
const x2 = Cast.toNumber(args.X2); | |
const y2 = Cast.toNumber(args.Y2); | |
// add to map | |
this.map.add(x1, y1, x2, y2); | |
} | |
clearBlockades() { | |
this.map.clear(); | |
} | |
setPatherXY(args) { | |
const x = Cast.toNumber(args.X); | |
const y = Cast.toNumber(args.Y); | |
this.pather.x = x; | |
this.pather.y = y; | |
} | |
setWidthHeight(args) { | |
const width = Cast.toNumber(args.WIDTH); | |
const height = Cast.toNumber(args.HEIGHT); | |
this.pather.width = width; | |
this.pather.height = height; | |
} | |
pathToSpot(args) { | |
const goalX = Cast.toNumber(args.X); | |
const goalY = Cast.toNumber(args.Y); | |
const exported = this.map.toGrid(); | |
// add margins | |
const stageSize = { | |
width: this.runtime.stageWidth, | |
height: this.runtime.stageHeight | |
}; | |
const marginSize = (stageSize.height > stageSize.width ? stageSize.height : stageSize.width) | |
+ (this.pather.height > this.pather.width ? this.pather.height : this.pather.width) | |
+ 24; | |
// use the margins & add padding to the walls for the final matrix | |
const marginMatrix = Seperator.marginGrid(exported.grid, marginSize); | |
const matrix = Seperator.padGrid(marginMatrix, this.pather.width, this.pather.height); | |
// get proper offsets | |
const offset = exported.offset; | |
offset.left -= marginSize; | |
offset.top += marginSize; | |
// setup pathfinding | |
const grid = new Pathfinding.Grid(matrix); | |
const finder = new Pathfinding.AStarFinder({ | |
allowDiagonal: true, | |
dontCrossCorners: true | |
}); | |
// set real starts and goals | |
// this is based on the offset | |
const realPositions = Clone.simple({ | |
start: { | |
x: this.pather.x - offset.left, | |
y: Math.abs(this.pather.y - offset.top), | |
}, | |
end: { | |
x: goalX - offset.left, | |
y: Math.abs(goalY - offset.top), | |
} | |
}); | |
const path = Pathfinding.Util.compressPath(finder.findPath( | |
realPositions.start.x, | |
realPositions.start.y, | |
realPositions.end.x, | |
realPositions.end.y, | |
grid | |
)); | |
// we need to do more offsetting for the resulting path | |
// also need to convert it to nodes | |
const newPath = new Nodes(); | |
for (const node of path) { | |
const x = node[0] + offset.left; | |
const y = 0 - (node[1] - offset.top); | |
newPath.push([x, y]); | |
} | |
this.pathNodes = newPath; | |
} | |
setListToPath(args, util) { | |
console.log(args); | |
const list = util.target.lookupOrCreateList(args.LIST.id, args.LIST.name); | |
list.value = push(args.ITEM); | |
} | |
getPathAs(args) { | |
const switchh = Cast.toString(args.TYPE).toLowerCase(); | |
switch (switchh) { | |
case 'json array with objects': | |
return JSON.stringify(this.pathNodes.getObjects()); | |
case 'json object': | |
return JSON.stringify(this.pathNodes.getAsObject()); | |
case 'comma seperated list': | |
return this.pathNodes.getCommaSeperated(); | |
default: | |
return JSON.stringify(this.pathNodes.getRaw()); | |
} | |
} | |
} | |
module.exports = JgPathfindingBlocks; | |