revival time
This commit is contained in:
parent
66f9254429
commit
8ace3266f3
11 changed files with 675 additions and 624 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
.pnpm-debug.log
|
||||
|
12
README.md
12
README.md
|
@ -104,3 +104,15 @@ the content type
|
|||
|
||||
the content's name
|
||||
|
||||
# roadmap
|
||||
|
||||
- currently, only a small subset of the features are
|
||||
supported.
|
||||
|
||||
- version 1 will be released when all features are
|
||||
supported and there are no major bugs
|
||||
|
||||
- version 2 will be released when i implement map io
|
||||
|
||||
- more versions will be released when the schematic/map
|
||||
system changes signifigantly
|
||||
|
|
|
@ -1,332 +1,378 @@
|
|||
const { err, capitalize } = require("../util/misc.js");
|
||||
|
||||
const ContentType = [
|
||||
"item",
|
||||
"block",
|
||||
"mech_UNUSED",
|
||||
"bullet",
|
||||
"liquid",
|
||||
"status",
|
||||
"unit",
|
||||
"weather",
|
||||
"effect_UNUSED",
|
||||
"sector",
|
||||
"loadout_UNUSED",
|
||||
"typeid_UNUSED",
|
||||
"error",
|
||||
"planet",
|
||||
"ammo",
|
||||
"item",
|
||||
"block",
|
||||
"mech_UNUSED",
|
||||
"bullet",
|
||||
"liquid",
|
||||
"status",
|
||||
"unit",
|
||||
"weather",
|
||||
"effect_UNUSED",
|
||||
"sector",
|
||||
"loadout_UNUSED",
|
||||
"typeid_UNUSED",
|
||||
"error",
|
||||
"planet",
|
||||
"ammo",
|
||||
];
|
||||
|
||||
const content = {
|
||||
Block: [
|
||||
"air",
|
||||
"spawn",
|
||||
"cliff",
|
||||
"deepwater",
|
||||
"water",
|
||||
"taintedWater",
|
||||
"tar",
|
||||
"slag",
|
||||
"stone",
|
||||
"craters",
|
||||
"charr",
|
||||
"sand",
|
||||
"darksand",
|
||||
"dirt",
|
||||
"mud",
|
||||
"ice",
|
||||
"snow",
|
||||
"darksandTaintedWater",
|
||||
"space",
|
||||
"dacite",
|
||||
"stoneWall",
|
||||
"dirtWall",
|
||||
"sporeWall",
|
||||
"iceWall",
|
||||
"daciteWall",
|
||||
"sporePine",
|
||||
"snowPine",
|
||||
"pine",
|
||||
"shrubs",
|
||||
"whiteTree",
|
||||
"whiteTreeDead",
|
||||
"sporeCluster",
|
||||
"iceSnow",
|
||||
"sandWater",
|
||||
"darksandWater",
|
||||
"duneWall",
|
||||
"sandWall",
|
||||
"moss",
|
||||
"sporeMoss",
|
||||
"shale",
|
||||
"shaleWall",
|
||||
"shaleBoulder",
|
||||
"sandBoulder",
|
||||
"daciteBoulder",
|
||||
"boulder",
|
||||
"snowBoulder",
|
||||
"basaltBoulder",
|
||||
"grass",
|
||||
"salt",
|
||||
"metalFloor",
|
||||
"metalFloorDamaged",
|
||||
"metalFloor2",
|
||||
"metalFloor3",
|
||||
"metalFloor5",
|
||||
"basalt",
|
||||
"magmarock",
|
||||
"hotrock",
|
||||
"snowWall",
|
||||
"saltWall",
|
||||
"darkPanel1",
|
||||
"darkPanel2",
|
||||
"darkPanel3",
|
||||
"darkPanel4",
|
||||
"darkPanel5",
|
||||
"darkPanel6",
|
||||
"darkMetal",
|
||||
"pebbles",
|
||||
"tendrils",
|
||||
"oreCopper",
|
||||
"oreLead",
|
||||
"oreScrap",
|
||||
"oreCoal",
|
||||
"oreTitanium",
|
||||
"oreThorium",
|
||||
"siliconSmelter",
|
||||
"siliconCrucible",
|
||||
"kiln",
|
||||
"graphitePress",
|
||||
"plastaniumCompressor",
|
||||
"multiPress",
|
||||
"phaseWeaver",
|
||||
"surgeSmelter",
|
||||
"pyratiteMixer",
|
||||
"blastMixer",
|
||||
"cryofluidMixer",
|
||||
"melter",
|
||||
"separator",
|
||||
"disassembler",
|
||||
"sporePress",
|
||||
"pulverizer",
|
||||
"incinerator",
|
||||
"coalCentrifuge",
|
||||
"powerSource",
|
||||
"powerVoid",
|
||||
"itemSource",
|
||||
"itemVoid",
|
||||
"liquidSource",
|
||||
"liquidVoid",
|
||||
"illuminator",
|
||||
"copperWall",
|
||||
"copperWallLarge",
|
||||
"titaniumWall",
|
||||
"titaniumWallLarge",
|
||||
"plastaniumWall",
|
||||
"plastaniumWallLarge",
|
||||
"thoriumWall",
|
||||
"thoriumWallLarge",
|
||||
"door",
|
||||
"doorLarge",
|
||||
"phaseWall",
|
||||
"phaseWallLarge",
|
||||
"surgeWall",
|
||||
"surgeWallLarge",
|
||||
"mender",
|
||||
"mendProjector",
|
||||
"overdriveProjector",
|
||||
"overdriveDome",
|
||||
"forceProjector",
|
||||
"shockMine",
|
||||
"scrapWall",
|
||||
"scrapWallLarge",
|
||||
"scrapWallHuge",
|
||||
"scrapWallGigantic",
|
||||
"thruster",
|
||||
"conveyor",
|
||||
"titaniumConveyor",
|
||||
"plastaniumConveyor",
|
||||
"armoredConveyor",
|
||||
"distributor",
|
||||
"junction",
|
||||
"itemBridge",
|
||||
"phaseConveyor",
|
||||
"sorter",
|
||||
"invertedSorter",
|
||||
"router",
|
||||
"overflowGate",
|
||||
"underflowGate",
|
||||
"massDriver",
|
||||
"payloadConveyor",
|
||||
"payloadRouter",
|
||||
"mechanicalPump",
|
||||
"rotaryPump",
|
||||
"thermalPump",
|
||||
"conduit",
|
||||
"pulseConduit",
|
||||
"platedConduit",
|
||||
"liquidRouter",
|
||||
"liquidTank",
|
||||
"liquidJunction",
|
||||
"bridgeConduit",
|
||||
"phaseConduit",
|
||||
"combustionGenerator",
|
||||
"thermalGenerator",
|
||||
"steamGenerator",
|
||||
"differentialGenerator",
|
||||
"rtgGenerator",
|
||||
"solarPanel",
|
||||
"largeSolarPanel",
|
||||
"thoriumReactor",
|
||||
"impactReactor",
|
||||
"battery",
|
||||
"batteryLarge",
|
||||
"powerNode",
|
||||
"powerNodeLarge",
|
||||
"surgeTower",
|
||||
"diode",
|
||||
"mechanicalDrill",
|
||||
"pneumaticDrill",
|
||||
"laserDrill",
|
||||
"blastDrill",
|
||||
"waterExtractor",
|
||||
"oilExtractor",
|
||||
"cultivator",
|
||||
"coreShard",
|
||||
"coreFoundation",
|
||||
"coreNucleus",
|
||||
"vault",
|
||||
"container",
|
||||
"unloader",
|
||||
"duo",
|
||||
"scatter",
|
||||
"scorch",
|
||||
"hail",
|
||||
"arc",
|
||||
"wave",
|
||||
"lancer",
|
||||
"swarmer",
|
||||
"salvo",
|
||||
"fuse",
|
||||
"ripple",
|
||||
"cyclone",
|
||||
"foreshadow",
|
||||
"spectre",
|
||||
"meltdown",
|
||||
"segment",
|
||||
"parallax",
|
||||
"tsunami",
|
||||
"commandCenter",
|
||||
"groundFactory",
|
||||
"airFactory",
|
||||
"navalFactory",
|
||||
"additiveReconstructor",
|
||||
"multiplicativeReconstructor",
|
||||
"exponentialReconstructor",
|
||||
"tetrativeReconstructor",
|
||||
"repairPoint",
|
||||
"resupplyPoint",
|
||||
"message",
|
||||
"switchBlock",
|
||||
"microProcessor",
|
||||
"logicProcessor",
|
||||
"hyperProcessor",
|
||||
"largeLogicDisplay",
|
||||
"logicDisplay",
|
||||
"memoryCell",
|
||||
"memoryBank",
|
||||
"launchPad",
|
||||
"launchPadLarge",
|
||||
"interplanetaryAccelerator",
|
||||
"blockForge",
|
||||
"blockLoader",
|
||||
"blockUnloader",
|
||||
],
|
||||
Block: [
|
||||
"air",
|
||||
"spawn",
|
||||
"cliff",
|
||||
"deepwater",
|
||||
"water",
|
||||
"taintedWater",
|
||||
"tar",
|
||||
"slag",
|
||||
"stone",
|
||||
"craters",
|
||||
"charr",
|
||||
"sand",
|
||||
"darksand",
|
||||
"dirt",
|
||||
"mud",
|
||||
"ice",
|
||||
"snow",
|
||||
"darksandTaintedWater",
|
||||
"space",
|
||||
"dacite",
|
||||
"stoneWall",
|
||||
"dirtWall",
|
||||
"sporeWall",
|
||||
"iceWall",
|
||||
"daciteWall",
|
||||
"sporePine",
|
||||
"snowPine",
|
||||
"pine",
|
||||
"shrubs",
|
||||
"whiteTree",
|
||||
"whiteTreeDead",
|
||||
"sporeCluster",
|
||||
"iceSnow",
|
||||
"sandWater",
|
||||
"darksandWater",
|
||||
"duneWall",
|
||||
"sandWall",
|
||||
"moss",
|
||||
"sporeMoss",
|
||||
"shale",
|
||||
"shaleWall",
|
||||
"shaleBoulder",
|
||||
"sandBoulder",
|
||||
"daciteBoulder",
|
||||
"boulder",
|
||||
"snowBoulder",
|
||||
"basaltBoulder",
|
||||
"grass",
|
||||
"salt",
|
||||
"metalFloor",
|
||||
"metalFloorDamaged",
|
||||
"metalFloor2",
|
||||
"metalFloor3",
|
||||
"metalFloor5",
|
||||
"basalt",
|
||||
"magmarock",
|
||||
"hotrock",
|
||||
"snowWall",
|
||||
"saltWall",
|
||||
"darkPanel1",
|
||||
"darkPanel2",
|
||||
"darkPanel3",
|
||||
"darkPanel4",
|
||||
"darkPanel5",
|
||||
"darkPanel6",
|
||||
"darkMetal",
|
||||
"pebbles",
|
||||
"tendrils",
|
||||
"oreCopper",
|
||||
"oreLead",
|
||||
"oreScrap",
|
||||
"oreCoal",
|
||||
"oreTitanium",
|
||||
"oreThorium",
|
||||
"siliconSmelter",
|
||||
"siliconCrucible",
|
||||
"kiln",
|
||||
"graphitePress",
|
||||
"plastaniumCompressor",
|
||||
"multiPress",
|
||||
"phaseWeaver",
|
||||
"surgeSmelter",
|
||||
"pyratiteMixer",
|
||||
"blastMixer",
|
||||
"cryofluidMixer",
|
||||
"melter",
|
||||
"separator",
|
||||
"disassembler",
|
||||
"sporePress",
|
||||
"pulverizer",
|
||||
"incinerator",
|
||||
"coalCentrifuge",
|
||||
"powerSource",
|
||||
"powerVoid",
|
||||
"itemSource",
|
||||
"itemVoid",
|
||||
"liquidSource",
|
||||
"liquidVoid",
|
||||
"illuminator",
|
||||
"copperWall",
|
||||
"copperWallLarge",
|
||||
"titaniumWall",
|
||||
"titaniumWallLarge",
|
||||
"plastaniumWall",
|
||||
"plastaniumWallLarge",
|
||||
"thoriumWall",
|
||||
"thoriumWallLarge",
|
||||
"door",
|
||||
"doorLarge",
|
||||
"phaseWall",
|
||||
"phaseWallLarge",
|
||||
"surgeWall",
|
||||
"surgeWallLarge",
|
||||
"mender",
|
||||
"mendProjector",
|
||||
"overdriveProjector",
|
||||
"overdriveDome",
|
||||
"forceProjector",
|
||||
"shockMine",
|
||||
"scrapWall",
|
||||
"scrapWallLarge",
|
||||
"scrapWallHuge",
|
||||
"scrapWallGigantic",
|
||||
"thruster",
|
||||
"conveyor",
|
||||
"titaniumConveyor",
|
||||
"plastaniumConveyor",
|
||||
"armoredConveyor",
|
||||
"distributor",
|
||||
"junction",
|
||||
"itemBridge",
|
||||
"phaseConveyor",
|
||||
"sorter",
|
||||
"invertedSorter",
|
||||
"router",
|
||||
"overflowGate",
|
||||
"underflowGate",
|
||||
"massDriver",
|
||||
"payloadConveyor",
|
||||
"payloadRouter",
|
||||
"mechanicalPump",
|
||||
"rotaryPump",
|
||||
"thermalPump",
|
||||
"conduit",
|
||||
"pulseConduit",
|
||||
"platedConduit",
|
||||
"liquidRouter",
|
||||
"liquidTank",
|
||||
"liquidJunction",
|
||||
"bridgeConduit",
|
||||
"phaseConduit",
|
||||
"combustionGenerator",
|
||||
"thermalGenerator",
|
||||
"steamGenerator",
|
||||
"differentialGenerator",
|
||||
"rtgGenerator",
|
||||
"solarPanel",
|
||||
"largeSolarPanel",
|
||||
"thoriumReactor",
|
||||
"impactReactor",
|
||||
"battery",
|
||||
"batteryLarge",
|
||||
"powerNode",
|
||||
"powerNodeLarge",
|
||||
"surgeTower",
|
||||
"diode",
|
||||
"mechanicalDrill",
|
||||
"pneumaticDrill",
|
||||
"laserDrill",
|
||||
"blastDrill",
|
||||
"waterExtractor",
|
||||
"oilExtractor",
|
||||
"cultivator",
|
||||
"coreShard",
|
||||
"coreFoundation",
|
||||
"coreNucleus",
|
||||
"vault",
|
||||
"container",
|
||||
"unloader",
|
||||
"duo",
|
||||
"scatter",
|
||||
"scorch",
|
||||
"hail",
|
||||
"arc",
|
||||
"wave",
|
||||
"lancer",
|
||||
"swarmer",
|
||||
"salvo",
|
||||
"fuse",
|
||||
"ripple",
|
||||
"cyclone",
|
||||
"foreshadow",
|
||||
"spectre",
|
||||
"meltdown",
|
||||
"segment",
|
||||
"parallax",
|
||||
"tsunami",
|
||||
"commandCenter",
|
||||
"groundFactory",
|
||||
"airFactory",
|
||||
"navalFactory",
|
||||
"additiveReconstructor",
|
||||
"multiplicativeReconstructor",
|
||||
"exponentialReconstructor",
|
||||
"tetrativeReconstructor",
|
||||
"repairPoint",
|
||||
"resupplyPoint",
|
||||
"message",
|
||||
"switchBlock",
|
||||
"microProcessor",
|
||||
"logicProcessor",
|
||||
"hyperProcessor",
|
||||
"largeLogicDisplay",
|
||||
"logicDisplay",
|
||||
"memoryCell",
|
||||
"memoryBank",
|
||||
"launchPad",
|
||||
"launchPadLarge",
|
||||
"interplanetaryAccelerator",
|
||||
"blockForge",
|
||||
"blockLoader",
|
||||
"blockUnloader",
|
||||
],
|
||||
|
||||
Item: [
|
||||
"scrap",
|
||||
"copper",
|
||||
"lead",
|
||||
"graphite",
|
||||
"coal",
|
||||
"titanium",
|
||||
"thorium",
|
||||
"silicon",
|
||||
"plastanium",
|
||||
"phaseFabric",
|
||||
"surgeAlloy",
|
||||
"sporePod",
|
||||
"sand",
|
||||
"blastCompound",
|
||||
"pyratite",
|
||||
"metaglass",
|
||||
],
|
||||
Item: [
|
||||
"scrap",
|
||||
"copper",
|
||||
"lead",
|
||||
"graphite",
|
||||
"coal",
|
||||
"titanium",
|
||||
"thorium",
|
||||
"silicon",
|
||||
"plastanium",
|
||||
"phaseFabric",
|
||||
"surgeAlloy",
|
||||
"sporePod",
|
||||
"sand",
|
||||
"blastCompound",
|
||||
"pyratite",
|
||||
"metaglass",
|
||||
],
|
||||
|
||||
Liquid: ["water", "slag", "oil", "cryofluid"],
|
||||
Liquid: ["water", "slag", "oil", "cryofluid"],
|
||||
|
||||
Unit: [
|
||||
"mace",
|
||||
"dagger",
|
||||
"crawler",
|
||||
"fortress",
|
||||
"scepter",
|
||||
"reign",
|
||||
"nova",
|
||||
"pulsar",
|
||||
"quasar",
|
||||
"vela",
|
||||
"corvus",
|
||||
"atrax",
|
||||
"spiroct",
|
||||
"arkyid",
|
||||
"toxopid",
|
||||
"flare",
|
||||
"eclipse",
|
||||
"horizon",
|
||||
"zenith",
|
||||
"antumbra",
|
||||
"mono",
|
||||
"poly",
|
||||
"mega",
|
||||
"quad",
|
||||
"oct",
|
||||
"alpha",
|
||||
"beta",
|
||||
"gamma",
|
||||
"risso",
|
||||
"minke",
|
||||
"bryde",
|
||||
"sei",
|
||||
"omura",
|
||||
"block",
|
||||
],
|
||||
Unit: [
|
||||
"mace",
|
||||
"dagger",
|
||||
"crawler",
|
||||
"fortress",
|
||||
"scepter",
|
||||
"reign",
|
||||
"nova",
|
||||
"pulsar",
|
||||
"quasar",
|
||||
"vela",
|
||||
"corvus",
|
||||
"atrax",
|
||||
"spiroct",
|
||||
"arkyid",
|
||||
"toxopid",
|
||||
"flare",
|
||||
"eclipse",
|
||||
"horizon",
|
||||
"zenith",
|
||||
"antumbra",
|
||||
"mono",
|
||||
"poly",
|
||||
"mega",
|
||||
"quad",
|
||||
"oct",
|
||||
"alpha",
|
||||
"beta",
|
||||
"gamma",
|
||||
"risso",
|
||||
"minke",
|
||||
"bryde",
|
||||
"sei",
|
||||
"omura",
|
||||
"block",
|
||||
],
|
||||
|
||||
Bullet: [
|
||||
"artilleryDense",
|
||||
"artilleryPlastic",
|
||||
"artilleryPlasticFrag",
|
||||
"artilleryHoming",
|
||||
"artilleryIncendiary",
|
||||
"artilleryExplosive",
|
||||
"flakScrap",
|
||||
"flakLead",
|
||||
"flakGlass",
|
||||
"flakGlassFrag",
|
||||
"fragGlass",
|
||||
"fragExplosive",
|
||||
"fragPlastic",
|
||||
"fragSurge",
|
||||
"fragGlassFrag",
|
||||
"fragPlasticFrag",
|
||||
"missileExplosive",
|
||||
"missileIncendiary",
|
||||
"missileSurge",
|
||||
"standardCopper",
|
||||
"standardDense",
|
||||
"standardThorium",
|
||||
"standardHoming",
|
||||
"standardIncendiary",
|
||||
"standardDenseBig",
|
||||
"standardThoriumBig",
|
||||
"standardIncendiaryBig",
|
||||
"waterShot",
|
||||
"cryoShot",
|
||||
"slagShot",
|
||||
"oilShot",
|
||||
"heavyWaterShot",
|
||||
"heavyCryoShot",
|
||||
"heavySlagShot",
|
||||
"heavyOilShot",
|
||||
"damageLightning",
|
||||
"damageLightningGround",
|
||||
"fireball",
|
||||
"basicFlame",
|
||||
"pyraFlame",
|
||||
"driverBolt",
|
||||
],
|
||||
};
|
||||
|
||||
class Content {
|
||||
constructor(type, name) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
}
|
||||
constructor(type, name) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
get typeId() {
|
||||
return ContentType.indexOf(this.type.toLowerCase());
|
||||
}
|
||||
get typeId() {
|
||||
return ContentType.indexOf(this.type.toLowerCase());
|
||||
}
|
||||
|
||||
get id() {
|
||||
return content[this.type].indexOf(this.name);
|
||||
}
|
||||
get id() {
|
||||
return content[this.type].indexOf(this.name);
|
||||
}
|
||||
}
|
||||
|
||||
function getByName(kind, id) {
|
||||
if (typeof kind === "number" && !isNaN(kind)) kind = ContentType[kind];
|
||||
const selected = content[capitalize(kind)];
|
||||
if (!selected) err("content doesnt exist");
|
||||
return selected[id] ? new Content(capitalize(kind), selected[id]) : null;
|
||||
if (typeof kind === "number" && !isNaN(kind)) kind = ContentType[kind];
|
||||
const selected = content[capitalize(kind)];
|
||||
if (!selected) throw "content doesnt exist";
|
||||
return selected[id] ? new Content(capitalize(kind), selected[id]) : null;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ContentType,
|
||||
Content,
|
||||
content,
|
||||
getByName,
|
||||
ContentType,
|
||||
Content,
|
||||
content,
|
||||
getByName,
|
||||
};
|
||||
|
||||
|
|
|
@ -2,157 +2,152 @@ const zlib = require("zlib");
|
|||
const { Reader, Writer, TypeIO, Position, capitalize } = require("../util");
|
||||
const header = Buffer.from("msch");
|
||||
|
||||
class Block {
|
||||
constructor(data = {}) {
|
||||
this.block = "air";
|
||||
this.position = new Position(0);
|
||||
this.config = null;
|
||||
this.rotation = 0;
|
||||
Object.assign(this, data);
|
||||
const me = this;
|
||||
["block", "position", "config", "rotation"].forEach((i) => {
|
||||
const fmt = capitalize(i);
|
||||
this["get" + fmt] = () => {
|
||||
return me[i];
|
||||
};
|
||||
this["set" + fmt] = (val) => {
|
||||
me[i] = val;
|
||||
return me;
|
||||
};
|
||||
});
|
||||
}
|
||||
class Stile {
|
||||
constructor(data = {}) {
|
||||
this.block = "air";
|
||||
this.position = new Position(0);
|
||||
this.config = null;
|
||||
this.rotation = 0;
|
||||
|
||||
Object.assign(this, data);
|
||||
const me = this;
|
||||
for(let i of ["block", "position", "config", "rotation"]) {
|
||||
const fmt = capitalize(i);
|
||||
this["get" + fmt] = () => me[i];
|
||||
this["set" + fmt] = (val) => me[i] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Schematic {
|
||||
// load or make a new Schematic
|
||||
constructor(buffer) {
|
||||
// create a blank slate
|
||||
this.reset();
|
||||
if (!buffer) return this;
|
||||
// load or make a new Schematic
|
||||
constructor(buffer) {
|
||||
// create a blank slate
|
||||
this.reset();
|
||||
if (!buffer) return this;
|
||||
|
||||
// make sure the header exists
|
||||
const rawReader = new Reader(buffer);
|
||||
if (!rawReader.raw(4).equals(header)) err("Incorrect header");
|
||||
if (rawReader.byte() !== 1) err("Unsupported schematic version");
|
||||
// make sure the header exists
|
||||
const rawReader = new Reader(buffer);
|
||||
if (!rawReader.raw(4).equals(header)) throw "Incorrect header";
|
||||
if (rawReader.byte() !== 1) throw "Unsupported schematic version";
|
||||
|
||||
// create a reader and grab width/height
|
||||
const reader = new Reader(zlib.inflateSync(buffer.slice(5)));
|
||||
this.width = reader.short();
|
||||
this.height = reader.short();
|
||||
// create a reader and grab width/height
|
||||
const reader = new Reader(zlib.inflateSync(buffer.slice(5)));
|
||||
this.width = reader.short();
|
||||
this.height = reader.short();
|
||||
|
||||
// get tags (eg. name)
|
||||
const tagLen = reader.byte();
|
||||
for (let i = 0; i < tagLen; i++) {
|
||||
this.tags[reader.string()] = reader.string();
|
||||
}
|
||||
// get tags (eg. name)
|
||||
const tagLen = reader.byte();
|
||||
for (let i = 0; i < tagLen; i++) {
|
||||
this.tags[reader.string()] = reader.string();
|
||||
}
|
||||
|
||||
// block dictionary, each id is mapped to a block
|
||||
const dictionary = [],
|
||||
dictLen = reader.byte();
|
||||
for (let i = 0; i < dictLen; i++) {
|
||||
dictionary.push(reader.string());
|
||||
}
|
||||
// block dictionary, each id is mapped to a block
|
||||
const dictionary = [],
|
||||
dictLen = reader.byte();
|
||||
for (let i = 0; i < dictLen; i++) {
|
||||
dictionary.push(reader.string());
|
||||
}
|
||||
|
||||
// actually read the blocks
|
||||
const totalBlocks = reader.int();
|
||||
for (let i = 0; i < totalBlocks; i++) {
|
||||
const block = dictionary[reader.byte()];
|
||||
const position = new Position(reader.int());
|
||||
const config = TypeIO.read(reader);
|
||||
const rotation = reader.byte();
|
||||
if (block === "air") continue;
|
||||
this.blocks.push(
|
||||
new Block({
|
||||
block,
|
||||
position,
|
||||
config,
|
||||
rotation,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
// actually read the blocks
|
||||
const totalBlocks = reader.int();
|
||||
for (let i = 0; i < totalBlocks; i++) {
|
||||
const block = dictionary[reader.byte()];
|
||||
const position = new Position(reader.int());
|
||||
const config = TypeIO.read(reader);
|
||||
const rotation = reader.byte();
|
||||
if (block === "air") continue;
|
||||
const tile = new Stile({ block, position, config, rotation });
|
||||
this.tiles.push(new Stile(tile));
|
||||
}
|
||||
}
|
||||
|
||||
// resize the schematic
|
||||
resize(height, width) {
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
}
|
||||
// resize the schematic
|
||||
resize(height, width) {
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
// get a block at a x and y position
|
||||
// creates it if it doesn't exist
|
||||
block(x, y) {
|
||||
if (x < 0 || y < 0 || x >= this.width || y >= this.height)
|
||||
err("out of bounds, resize schematic first!");
|
||||
for (let i of this.blocks) {
|
||||
if (i.position.x === x && i.position.y === y) return i;
|
||||
}
|
||||
// get a block at a x and y position
|
||||
// creates it if it doesn't exist
|
||||
tile(x, y) {
|
||||
if (x < 0 || y < 0 || x >= this.width || y >= this.height)
|
||||
throw "out of bounds, resize schematic first!";
|
||||
for (let i of this.tiles) {
|
||||
if (i.position.x === x && i.position.y === y) return i;
|
||||
}
|
||||
|
||||
const block = new Block({
|
||||
position: new Position({ x, y }),
|
||||
});
|
||||
const block = new Stile({
|
||||
position: new Position({ x, y }),
|
||||
});
|
||||
|
||||
this.blocks.push(block);
|
||||
return block;
|
||||
}
|
||||
this.tiles.push(block);
|
||||
return block;
|
||||
}
|
||||
|
||||
// delete a block at the x and y position
|
||||
delete(x, y) {
|
||||
let index = -1;
|
||||
for (let i = 0; i < this.blocks.length; i++) {
|
||||
const pos = this.blocks[i].position;
|
||||
if (pos.x === x && pos.y === y) index = i;
|
||||
}
|
||||
if (index >= 0) this.blocks.splice(index, 1);
|
||||
}
|
||||
// delete a block at the x and y position
|
||||
delete(x, y) {
|
||||
let index = -1;
|
||||
for (let i = 0; i < this.tiles.length; i++) {
|
||||
const pos = this.tiles[i].position;
|
||||
if (pos.x === x && pos.y === y) index = i;
|
||||
}
|
||||
if (index >= 0) this.tiles.splice(index, 1);
|
||||
}
|
||||
|
||||
// loop through the blocks
|
||||
each(callback) {
|
||||
this.blocks.forEach(callback);
|
||||
}
|
||||
// loop through the blocks
|
||||
each(callback) {
|
||||
this.tiles.forEach(callback);
|
||||
}
|
||||
|
||||
toBuffer() {
|
||||
// the constructor, but it's opposite day
|
||||
toBuffer() {
|
||||
// the constructor, but it's opposite day
|
||||
|
||||
const writer = new Writer();
|
||||
writer.short(this.width);
|
||||
writer.short(this.height);
|
||||
const writer = new Writer();
|
||||
writer.short(this.width);
|
||||
writer.short(this.height);
|
||||
|
||||
writer.byte(Object.keys(this.tags).length);
|
||||
for (let i in this.tags) {
|
||||
writer.string(i);
|
||||
writer.string(this.tags[i]);
|
||||
}
|
||||
writer.byte(Object.keys(this.tags).length);
|
||||
for (let i in this.tags) {
|
||||
writer.string(i);
|
||||
writer.string(this.tags[i]);
|
||||
}
|
||||
|
||||
const dictionary = this.blocks.reduce((acc, i) => {
|
||||
if (!acc.includes(i.block)) acc.push(i.block);
|
||||
return acc;
|
||||
}, []);
|
||||
const dictionary = this.tiles.reduce((acc, i) => {
|
||||
if (!acc.includes(i.block)) acc.push(i.block);
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
writer.byte(dictionary.length);
|
||||
dictionary.forEach((i) => writer.string(i));
|
||||
writer.byte(dictionary.length);
|
||||
dictionary.forEach((i) => writer.string(i));
|
||||
|
||||
writer.int(this.blocks.length);
|
||||
for (let i of this.blocks) {
|
||||
writer.byte(dictionary.indexOf(i.block));
|
||||
writer.int(i.position.pack());
|
||||
TypeIO.write(writer, i.config);
|
||||
writer.byte(i.rotation);
|
||||
}
|
||||
writer.int(this.tiles.length);
|
||||
for (let i of this.tiles) {
|
||||
writer.byte(dictionary.indexOf(i.block));
|
||||
writer.int(i.position.pack());
|
||||
TypeIO.write(writer, i.config);
|
||||
writer.byte(i.rotation);
|
||||
}
|
||||
|
||||
return Buffer.concat([
|
||||
header,
|
||||
Buffer.from("\u0001"),
|
||||
zlib.deflateSync(writer.toBuffer()),
|
||||
]);
|
||||
}
|
||||
return Buffer.concat([
|
||||
header,
|
||||
Buffer.from("\u0001"),
|
||||
zlib.deflateSync(writer.toBuffer()),
|
||||
]);
|
||||
}
|
||||
|
||||
// reset the schematic
|
||||
reset() {
|
||||
this.width = 0;
|
||||
this.height = 0;
|
||||
this.tags = {};
|
||||
this.blocks = [];
|
||||
}
|
||||
toString() {
|
||||
let str = `Schematic "${this.tags.name}" {\n`;
|
||||
}
|
||||
|
||||
// reset the schematic
|
||||
reset() {
|
||||
this.width = 0;
|
||||
this.height = 0;
|
||||
this.tags = {};
|
||||
this.tiles= [];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Schematic;
|
||||
|
||||
|
|
3
index.js
3
index.js
|
@ -1,3 +1,4 @@
|
|||
module.exports = {
|
||||
Schematic: require("./content/schematic.js"),
|
||||
Schematic: require("./content/schematic.js"),
|
||||
};
|
||||
|
||||
|
|
34
package.json
34
package.json
|
@ -1,19 +1,19 @@
|
|||
{
|
||||
"name": "mindustryio",
|
||||
"version": "0.0.6",
|
||||
"description": "tools for interacting with mindustry",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "node ./test/index.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sample-text-here/mindustryio.git"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/sample-text-here/mindustryio/issues"
|
||||
},
|
||||
"homepage": "https://github.com/sample-text-here/mindustryio#readme"
|
||||
"name": "mindustryio",
|
||||
"version": "0.1.0",
|
||||
"description": "tools for interacting with mindustry",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "node ./test/index.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sample-text-here/mindustryio.git"
|
||||
},
|
||||
"author": "tezlm",
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/sample-text-here/mindustryio/issues"
|
||||
},
|
||||
"homepage": "https://github.com/sample-text-here/mindustryio#readme"
|
||||
}
|
||||
|
|
BIN
test/10_diffs.msch
Normal file
BIN
test/10_diffs.msch
Normal file
Binary file not shown.
|
@ -4,23 +4,29 @@ const { Schematic } = require("../index.js");
|
|||
const buffer = fs.readFileSync(__dirname + "/sample.msch");
|
||||
const schem = new Schematic(buffer);
|
||||
|
||||
// reading basic schematics
|
||||
assert(schem.width, 4);
|
||||
assert(schem.height, 8);
|
||||
assert(schem.tags.name, "Silicon/Blast/Phase/Kiln");
|
||||
assert(schem.block(2, 2).block, "phase-weaver");
|
||||
assert(schem.block(3, 4).block, "inverted-sorter");
|
||||
assert(schem.tile(2, 2).block, "phase-weaver");
|
||||
assert(schem.tile(3, 4).block, "inverted-sorter");
|
||||
schem.delete(3, 4);
|
||||
assert(schem.block(3, 4).block, "air");
|
||||
schem.block(3, 4).setBlock("copper-wall");
|
||||
assert(schem.block(3, 4).block, "copper-wall");
|
||||
// if it crashes, something's wrong
|
||||
assert(schem.tile(3, 4).block, "air");
|
||||
schem.tile(3, 4).setBlock("copper-wall");
|
||||
assert(schem.tile(3, 4).block, "copper-wall");
|
||||
new Schematic(schem.toBuffer());
|
||||
|
||||
// creating schematics
|
||||
const schem2 = new Schematic();
|
||||
schem2.resize(5, 5);
|
||||
for (let x = 0; x < 5; x++) {
|
||||
for (let y = 0; y < 5; y++) {
|
||||
schem2.block(x, y).block = "copper-wall";
|
||||
}
|
||||
for (let y = 0; y < 5; y++) {
|
||||
schem2.tile(x, y).block = "copper-wall";
|
||||
}
|
||||
}
|
||||
assert(schem2.block(3, 3).block, "copper-wall");
|
||||
assert(schem2.tile(3, 3).block, "copper-wall");
|
||||
|
||||
// schematics
|
||||
const schem3 = new Schematic(fs.readFileSync(__dirname + "/10_diffs.msch"));
|
||||
schem3.toBuffer();
|
||||
|
||||
|
|
114
util/io.js
114
util/io.js
|
@ -1,84 +1,58 @@
|
|||
class Reader {
|
||||
constructor(buffer) {
|
||||
this.buffer = buffer;
|
||||
this.offset = 0;
|
||||
}
|
||||
constructor(buffer) {
|
||||
this.buffer = buffer;
|
||||
this.offset = 0;
|
||||
}
|
||||
|
||||
raw(bytes) {
|
||||
this.offset += bytes;
|
||||
return this.buffer.slice(this.offset - bytes, this.offset);
|
||||
}
|
||||
raw(bytes) {
|
||||
const old = this.offset;
|
||||
this.offset += bytes;
|
||||
return this.buffer.slice(old, this.offset);
|
||||
}
|
||||
|
||||
byte() {
|
||||
return this.raw(1).readInt8();
|
||||
}
|
||||
byte() { return this.raw(1).readInt8() }
|
||||
short() { return this.raw(2).readInt16BE() }
|
||||
int() { return this.raw(4).readInt32BE() }
|
||||
long() { return this.raw(8).readBigInt64BE() }
|
||||
float() { return this.raw(4).readFloatBE() }
|
||||
|
||||
short() {
|
||||
return this.raw(2).readInt16BE();
|
||||
}
|
||||
|
||||
int() {
|
||||
return this.raw(4).readInt32BE();
|
||||
}
|
||||
|
||||
long() {
|
||||
return this.raw(8).readBigInt64BE();
|
||||
}
|
||||
|
||||
float() {
|
||||
return this.raw(4).readFloatBE();
|
||||
}
|
||||
|
||||
string() {
|
||||
const len = this.short();
|
||||
const str = this.raw(len).toString();
|
||||
return str;
|
||||
}
|
||||
string() {
|
||||
const len = this.short();
|
||||
return this.raw(len).toString("utf8");
|
||||
}
|
||||
}
|
||||
|
||||
class Writer {
|
||||
constructor(buffer) {
|
||||
this.parts = [];
|
||||
}
|
||||
constructor() {
|
||||
this.parts = [];
|
||||
}
|
||||
|
||||
write(size, kind, value) {
|
||||
const buf = Buffer.alloc(size);
|
||||
buf[kind](value);
|
||||
this.parts.push(buf);
|
||||
}
|
||||
write(size, kind, value) {
|
||||
const buf = Buffer.alloc(size);
|
||||
buf[kind](value);
|
||||
this.parts.push(buf);
|
||||
}
|
||||
|
||||
raw(bytes) {
|
||||
this.parts.push(Buffer.from(bytes));
|
||||
}
|
||||
raw(bytes) {
|
||||
const buf = Buffer.from(bytes);
|
||||
this.parts.push(buf);
|
||||
}
|
||||
|
||||
byte(val) {
|
||||
this.write(1, "writeInt8", val);
|
||||
}
|
||||
byte(val) { this.write(1, "writeInt8", val) }
|
||||
short(val) { this.write(2, "writeInt16BE", val) }
|
||||
int(val) { this.write(4, "writeInt32BE", val) }
|
||||
long(val) { this.write(8, "writeBigInt64BE", val) }
|
||||
float(val) { this.write(4, "writeFloatBE", val) }
|
||||
|
||||
string(str) {
|
||||
this.short(str.length);
|
||||
this.raw(str);
|
||||
}
|
||||
|
||||
short(val) {
|
||||
this.write(2, "writeInt16BE", val);
|
||||
}
|
||||
|
||||
int(val) {
|
||||
this.write(4, "writeInt32BE", val);
|
||||
}
|
||||
|
||||
long(val) {
|
||||
this.write(8, "writeBigInt64BE", val);
|
||||
}
|
||||
|
||||
float(val) {
|
||||
this.write(4, "writeFloatBE", val);
|
||||
}
|
||||
|
||||
string(str) {
|
||||
this.short(str.length);
|
||||
this.raw(str);
|
||||
}
|
||||
|
||||
toBuffer() {
|
||||
return Buffer.concat(this.parts);
|
||||
}
|
||||
toBuffer() {
|
||||
return Buffer.concat(this.parts);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { Reader, Writer };
|
||||
|
||||
|
|
28
util/misc.js
28
util/misc.js
|
@ -1,26 +1,26 @@
|
|||
const overflow = 65536;
|
||||
class Position {
|
||||
constructor(pos = 0) {
|
||||
if (typeof pos === "object" && pos) {
|
||||
this.x = pos.x;
|
||||
this.y = pos.y;
|
||||
} else {
|
||||
this.y = pos % overflow;
|
||||
this.x = Math.floor(pos / overflow);
|
||||
}
|
||||
}
|
||||
constructor(pos = 0) {
|
||||
if (typeof pos === "object" && pos) {
|
||||
this.x = pos.x;
|
||||
this.y = pos.y;
|
||||
} else {
|
||||
this.x = Math.floor(pos / overflow);
|
||||
this.y = pos % overflow;
|
||||
}
|
||||
}
|
||||
|
||||
pack() {
|
||||
return this.x * overflow + this.y;
|
||||
}
|
||||
pack() {
|
||||
return this.x * overflow + this.y;
|
||||
}
|
||||
}
|
||||
|
||||
function capitalize(str) {
|
||||
return str[0].toUpperCase() + str.slice(1).toLowerCase();
|
||||
return str[0].toUpperCase() + str.slice(1).toLowerCase();
|
||||
}
|
||||
|
||||
function err(why) {
|
||||
throw new Error(why);
|
||||
throw new Error(why);
|
||||
}
|
||||
|
||||
module.exports = { Position, overflow, err, capitalize };
|
||||
|
|
157
util/type.js
157
util/type.js
|
@ -1,73 +1,88 @@
|
|||
const { err, overflow, Position } = require("./misc.js");
|
||||
const { getByName, Content } = require("../content/content.js");
|
||||
module.exports = {
|
||||
read(stream) {
|
||||
const type = stream.byte();
|
||||
switch (type) {
|
||||
case 0:
|
||||
return null;
|
||||
case 1:
|
||||
return stream.int();
|
||||
case 2:
|
||||
return stream.long();
|
||||
case 3:
|
||||
return stream.float();
|
||||
case 4:
|
||||
return stream.string();
|
||||
case 5:
|
||||
return getByName(stream.byte(), stream.short());
|
||||
case 6:
|
||||
const length = stream.short();
|
||||
const arr = [];
|
||||
for (let i = 0; i < length; i++) arr.push(stream.int());
|
||||
return arr;
|
||||
case 7:
|
||||
return new Position({ x: stream.int(), y: stream.int() });
|
||||
// case 8: byte len = read.b(); Point2[] out = new Point2[len]; for(int i = 0; i < len; i ++) out[i] = Point2.unpack(read.i()); return out;
|
||||
// case 9: return TechTree.getNotNull(content.getByID(ContentType.all[read.b()], read.s()));
|
||||
// case 10: return read.bool();
|
||||
// case 11: return read.d();
|
||||
// case 12: return world.build(read.i());
|
||||
// case 13: return LAccess.all[read.s()];
|
||||
// case 14: int blen = read.i(); byte[] bytes = new byte[blen]; read.b(bytes); return bytes;
|
||||
// case 15: return UnitCommand.all[read.b()];
|
||||
default:
|
||||
err(
|
||||
`Unknown object type: ${type} (WIP, don't expect everything to work!)`
|
||||
);
|
||||
}
|
||||
},
|
||||
write(stream, thing) {
|
||||
if (thing === null) {
|
||||
stream.byte(0);
|
||||
} else if (typeof thing === "number" && !isNaN(thing)) {
|
||||
if (!Number.isInteger(thing)) {
|
||||
stream.byte(3);
|
||||
stream.float(thing);
|
||||
} else if (thing > overflow) {
|
||||
stream.byte(2);
|
||||
stream.long(thing);
|
||||
} else {
|
||||
stream.byte(1);
|
||||
stream.int(thing);
|
||||
}
|
||||
} else if (typeof thing === "string") {
|
||||
stream.byte(4);
|
||||
stream.string(thing);
|
||||
} else if (thing instanceof Content) {
|
||||
stream.byte(5);
|
||||
stream.byte(thing.typeId);
|
||||
stream.short(thing.id);
|
||||
} else if (thing instanceof Array) {
|
||||
stream.byte(6);
|
||||
stream.short(thing.length);
|
||||
for (let i of thing) stream.int(i);
|
||||
} else if (thing instanceof Position) {
|
||||
stream.byte(7);
|
||||
stream.int(thing.x);
|
||||
stream.int(thing.y);
|
||||
} else {
|
||||
err("can't pack");
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function read(reader) {
|
||||
const type = reader.byte();
|
||||
switch (type) {
|
||||
case 0: return null;
|
||||
case 1: return reader.int();
|
||||
case 2: return reader.long();
|
||||
case 3: return reader.float();
|
||||
case 4:
|
||||
const exists = reader.byte();
|
||||
if(exists === 0) return null;
|
||||
return reader.string();
|
||||
case 5:
|
||||
return getByName(reader.byte(), reader.short());
|
||||
case 6:
|
||||
const len = reader.short();
|
||||
const arr = [];
|
||||
for (let i = 0; i < len; i++) arr.push(reader.int());
|
||||
return arr;
|
||||
case 7:
|
||||
return new Position({ x: reader.int(), y: reader.int() });
|
||||
case 8:
|
||||
const plen = reader.byte();
|
||||
const points = [];
|
||||
for (let i = 0; i < plen; i++)
|
||||
points.push(new Position(reader.int()));
|
||||
return points;
|
||||
case 14:
|
||||
const blen = reader.int();
|
||||
const slice = reader.raw(blen);
|
||||
return slice;
|
||||
case 15:
|
||||
return ["attack", "rally", "idle"][reader.byte()];
|
||||
default:
|
||||
throw `Unknown object type: ${type}`;
|
||||
}
|
||||
}
|
||||
|
||||
function write(stream, thing) {
|
||||
if (thing === null) {
|
||||
stream.byte(0);
|
||||
} else if (typeof thing === "number" && !isNaN(thing)) {
|
||||
if (!Number.isInteger(thing)) {
|
||||
stream.byte(3);
|
||||
stream.float(thing);
|
||||
} else if (thing > overflow) {
|
||||
stream.byte(2);
|
||||
stream.long(thing);
|
||||
} else {
|
||||
stream.byte(1);
|
||||
stream.int(thing);
|
||||
}
|
||||
} else if (typeof thing === "string") {
|
||||
stream.byte(4);
|
||||
if(!thing.length) return stream.byte(0);
|
||||
stream.byte(1);
|
||||
stream.string(thing);
|
||||
} else if (thing instanceof Content) {
|
||||
stream.byte(5);
|
||||
stream.byte(thing.typeId);
|
||||
stream.short(thing.id);
|
||||
} else if (thing instanceof Array) {
|
||||
if (thing[0] instanceof Position) {
|
||||
stream.byte(8);
|
||||
stream.byte(thing.length);
|
||||
for (let i of thing) stream.int(i.pack());
|
||||
} else {
|
||||
stream.byte(6);
|
||||
stream.short(thing.length);
|
||||
for (let i of thing) stream.int(i);
|
||||
}
|
||||
} else if (thing instanceof Position) {
|
||||
stream.byte(7);
|
||||
stream.int(thing.x);
|
||||
stream.int(thing.y);
|
||||
} else if (thing instanceof Buffer) {
|
||||
stream.byte(14);
|
||||
stream.int(thing.length);
|
||||
stream.raw(thing);
|
||||
} else {
|
||||
throw "can't pack";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { read, write };
|
||||
|
||||
|
|
Loading…
Reference in a new issue