1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2026-03-02 03:39:21 +00:00

Restructure buildings

This commit is contained in:
tobspr
2020-09-24 12:53:40 +02:00
parent 0202387739
commit c54ec9fd2a
99 changed files with 2374 additions and 2449 deletions

View File

@@ -0,0 +1,79 @@
import { generateMatrixRotations } from "../../core/utils";
import { enumDirection, Vector } from "../../core/vector";
import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate";
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
const overlayMatrix = generateMatrixRotations([1, 1, 0, 1, 1, 1, 0, 1, 0]);
export class MetaAnalyzerBuilding extends MetaBuilding {
constructor() {
super("analyzer");
}
getSilhouetteColor() {
return "#3a52bc";
}
/**
* @param {GameRoot} root
*/
getIsUnlocked(root) {
// @todo
return true;
}
/** @returns {"wires"} **/
getLayer() {
return "wires";
}
getDimensions() {
return new Vector(1, 1);
}
getRenderPins() {
// We already have it included
return false;
}
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) {
return overlayMatrix[rotation];
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {
entity.addComponent(
new WiredPinsComponent({
slots: [
{
pos: new Vector(0, 0),
direction: enumDirection.left,
type: enumPinSlotType.logicalEjector,
},
{
pos: new Vector(0, 0),
direction: enumDirection.right,
type: enumPinSlotType.logicalEjector,
},
{
pos: new Vector(0, 0),
direction: enumDirection.bottom,
type: enumPinSlotType.logicalAcceptor,
},
],
})
);
entity.addComponent(
new LogicGateComponent({
type: enumLogicGateType.analyzer,
})
);
}
}

View File

@@ -0,0 +1,72 @@
import { enumDirection, Vector } from "../../core/vector";
import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate";
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
export class MetaComparatorBuilding extends MetaBuilding {
constructor() {
super("comparator");
}
getSilhouetteColor() {
return "#823cab";
}
/**
* @param {GameRoot} root
*/
getIsUnlocked(root) {
// @todo
return true;
}
/** @returns {"wires"} **/
getLayer() {
return "wires";
}
getDimensions() {
return new Vector(1, 1);
}
getRenderPins() {
// We already have it included
return false;
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {
entity.addComponent(
new WiredPinsComponent({
slots: [
{
pos: new Vector(0, 0),
direction: enumDirection.top,
type: enumPinSlotType.logicalEjector,
},
{
pos: new Vector(0, 0),
direction: enumDirection.left,
type: enumPinSlotType.logicalAcceptor,
},
{
pos: new Vector(0, 0),
direction: enumDirection.right,
type: enumPinSlotType.logicalAcceptor,
},
],
})
);
entity.addComponent(
new LogicGateComponent({
type: enumLogicGateType.compare,
})
);
}
}

View File

@@ -4,6 +4,9 @@ import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
import { ConstantSignalComponent } from "../components/constant_signal";
import { generateMatrixRotations } from "../../core/utils";
const overlayMatrix = generateMatrixRotations([0, 1, 0, 1, 1, 1, 1, 1, 1]);
export class MetaConstantSignalBuilding extends MetaBuilding {
constructor() {
@@ -11,7 +14,7 @@ export class MetaConstantSignalBuilding extends MetaBuilding {
}
getSilhouetteColor() {
return "#2bafda";
return "#2b84fd";
}
/**
@@ -35,6 +38,10 @@ export class MetaConstantSignalBuilding extends MetaBuilding {
return false;
}
getSpecialOverlayRenderMatrix(rotation) {
return overlayMatrix[rotation];
}
/**
* Creates the entity at the given location
* @param {Entity} entity

View File

@@ -1,155 +1,151 @@
import { enumDirection, Vector } from "../../core/vector";
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
import { Entity } from "../entity";
import { MetaBuilding, defaultBuildingVariant } from "../meta_building";
import { GameRoot } from "../root";
import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate";
/** @enum {string} */
export const enumLogicGateVariants = {
not: "not",
xor: "xor",
or: "or",
transistor: "transistor",
};
/** @enum {string} */
export const enumVariantToGate = {
[defaultBuildingVariant]: enumLogicGateType.and,
[enumLogicGateVariants.not]: enumLogicGateType.not,
[enumLogicGateVariants.xor]: enumLogicGateType.xor,
[enumLogicGateVariants.or]: enumLogicGateType.or,
[enumLogicGateVariants.transistor]: enumLogicGateType.transistor,
};
export class MetaLogicGateBuilding extends MetaBuilding {
constructor() {
super("logic_gate");
}
getSilhouetteColor() {
return "#89dc60";
}
/**
* @param {GameRoot} root
*/
getIsUnlocked(root) {
// @todo
return true;
}
/** @returns {"wires"} **/
getLayer() {
return "wires";
}
getDimensions() {
return new Vector(1, 1);
}
getAvailableVariants() {
return [
defaultBuildingVariant,
enumLogicGateVariants.not,
enumLogicGateVariants.xor,
enumLogicGateVariants.or,
enumLogicGateVariants.transistor,
];
}
getRenderPins() {
// We already have it included
return false;
}
/**
*
* @param {Entity} entity
* @param {number} rotationVariant
*/
updateVariants(entity, rotationVariant, variant) {
const gateType = enumVariantToGate[variant];
entity.components.LogicGate.type = gateType;
const pinComp = entity.components.WiredPins;
switch (gateType) {
case enumLogicGateType.and:
case enumLogicGateType.xor:
case enumLogicGateType.or: {
pinComp.setSlots([
{
pos: new Vector(0, 0),
direction: enumDirection.top,
type: enumPinSlotType.logicalEjector,
},
{
pos: new Vector(0, 0),
direction: enumDirection.left,
type: enumPinSlotType.logicalAcceptor,
},
{
pos: new Vector(0, 0),
direction: enumDirection.right,
type: enumPinSlotType.logicalAcceptor,
},
]);
break;
}
case enumLogicGateType.transistor: {
pinComp.setSlots([
{
pos: new Vector(0, 0),
direction: enumDirection.top,
type: enumPinSlotType.logicalEjector,
},
{
pos: new Vector(0, 0),
direction: enumDirection.left,
type: enumPinSlotType.logicalAcceptor,
},
{
pos: new Vector(0, 0),
direction: enumDirection.bottom,
type: enumPinSlotType.logicalAcceptor,
},
]);
break;
}
case enumLogicGateType.not: {
pinComp.setSlots([
{
pos: new Vector(0, 0),
direction: enumDirection.top,
type: enumPinSlotType.logicalEjector,
},
{
pos: new Vector(0, 0),
direction: enumDirection.bottom,
type: enumPinSlotType.logicalAcceptor,
},
]);
break;
}
default:
assertAlways("unknown logic gate type: " + gateType);
}
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {
entity.addComponent(
new WiredPinsComponent({
slots: [],
})
);
entity.addComponent(new LogicGateComponent({}));
}
}
import { enumDirection, Vector } from "../../core/vector";
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
import { Entity } from "../entity";
import { MetaBuilding, defaultBuildingVariant } from "../meta_building";
import { GameRoot } from "../root";
import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate";
import { generateMatrixRotations } from "../../core/utils";
/** @enum {string} */
export const enumLogicGateVariants = {
not: "not",
xor: "xor",
or: "or",
};
/** @enum {string} */
export const enumVariantToGate = {
[defaultBuildingVariant]: enumLogicGateType.and,
[enumLogicGateVariants.not]: enumLogicGateType.not,
[enumLogicGateVariants.xor]: enumLogicGateType.xor,
[enumLogicGateVariants.or]: enumLogicGateType.or,
};
const overlayMatrices = {
[defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]),
[enumLogicGateVariants.xor]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]),
[enumLogicGateVariants.or]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]),
[enumLogicGateVariants.not]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]),
};
const colors = {
[defaultBuildingVariant]: "#f48d41",
[enumLogicGateVariants.xor]: "#f4a241",
[enumLogicGateVariants.or]: "#f4d041",
[enumLogicGateVariants.not]: "#f44184",
};
export class MetaLogicGateBuilding extends MetaBuilding {
constructor() {
super("logic_gate");
}
getSilhouetteColor(variant) {
return colors[variant];
}
/**
* @param {GameRoot} root
*/
getIsUnlocked(root) {
// @todo
return true;
}
/** @returns {"wires"} **/
getLayer() {
return "wires";
}
getDimensions() {
return new Vector(1, 1);
}
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) {
return overlayMatrices[variant][rotation];
}
getAvailableVariants() {
return [
defaultBuildingVariant,
enumLogicGateVariants.or,
enumLogicGateVariants.not,
enumLogicGateVariants.xor,
];
}
getRenderPins() {
// We already have it included
return false;
}
/**
*
* @param {Entity} entity
* @param {number} rotationVariant
*/
updateVariants(entity, rotationVariant, variant) {
const gateType = enumVariantToGate[variant];
entity.components.LogicGate.type = gateType;
const pinComp = entity.components.WiredPins;
switch (gateType) {
case enumLogicGateType.and:
case enumLogicGateType.xor:
case enumLogicGateType.or: {
pinComp.setSlots([
{
pos: new Vector(0, 0),
direction: enumDirection.top,
type: enumPinSlotType.logicalEjector,
},
{
pos: new Vector(0, 0),
direction: enumDirection.left,
type: enumPinSlotType.logicalAcceptor,
},
{
pos: new Vector(0, 0),
direction: enumDirection.right,
type: enumPinSlotType.logicalAcceptor,
},
]);
break;
}
case enumLogicGateType.not: {
pinComp.setSlots([
{
pos: new Vector(0, 0),
direction: enumDirection.top,
type: enumPinSlotType.logicalEjector,
},
{
pos: new Vector(0, 0),
direction: enumDirection.bottom,
type: enumPinSlotType.logicalAcceptor,
},
]);
break;
}
default:
assertAlways("unknown logic gate type: " + gateType);
}
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {
entity.addComponent(
new WiredPinsComponent({
slots: [],
})
);
entity.addComponent(new LogicGateComponent({}));
}
}

View File

@@ -0,0 +1,101 @@
import { generateMatrixRotations } from "../../core/utils";
import { enumDirection, Vector } from "../../core/vector";
import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate";
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
import { Entity } from "../entity";
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
/** @enum {string} */
export const enumTransistorVariants = {
mirrored: "mirrored",
};
const overlayMatrices = {
[defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 0, 0, 1, 0]),
[enumTransistorVariants.mirrored]: generateMatrixRotations([0, 1, 0, 0, 1, 1, 0, 1, 0]),
};
export class MetaTransistorBuilding extends MetaBuilding {
constructor() {
super("transistor");
}
getSilhouetteColor() {
return "#bc3a61";
}
/**
* @param {GameRoot} root
*/
getIsUnlocked(root) {
// @todo
return true;
}
/** @returns {"wires"} **/
getLayer() {
return "wires";
}
getDimensions() {
return new Vector(1, 1);
}
getAvailableVariants() {
return [defaultBuildingVariant, enumTransistorVariants.mirrored];
}
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) {
return overlayMatrices[variant][rotation];
}
getRenderPins() {
// We already have it included
return false;
}
/**
*
* @param {Entity} entity
* @param {number} rotationVariant
*/
updateVariants(entity, rotationVariant, variant) {
entity.components.WiredPins.slots[1].direction =
variant === enumTransistorVariants.mirrored ? enumDirection.right : enumDirection.left;
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {
entity.addComponent(
new WiredPinsComponent({
slots: [
{
pos: new Vector(0, 0),
direction: enumDirection.top,
type: enumPinSlotType.logicalEjector,
},
{
pos: new Vector(0, 0),
direction: enumDirection.left,
type: enumPinSlotType.logicalAcceptor,
},
{
pos: new Vector(0, 0),
direction: enumDirection.bottom,
type: enumPinSlotType.logicalAcceptor,
},
],
})
);
entity.addComponent(
new LogicGateComponent({
type: enumLogicGateType.transistor,
})
);
}
}

View File

@@ -4,13 +4,15 @@ import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins";
import { Entity } from "../entity";
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
import { MetaCutterBuilding } from "./cutter";
import { MetaPainterBuilding } from "./painter";
import { MetaRotaterBuilding } from "./rotater";
import { MetaStackerBuilding } from "./stacker";
/** @enum {string} */
export const enumVirtualProcessorVariants = {
analyzer: "analyzer",
rotater: "rotater",
unstacker: "unstacker",
shapecompare: "shapecompare",
stacker: "stacker",
painter: "painter",
};
@@ -18,21 +20,27 @@ export const enumVirtualProcessorVariants = {
/** @enum {string} */
export const enumVariantToGate = {
[defaultBuildingVariant]: enumLogicGateType.cutter,
[enumVirtualProcessorVariants.analyzer]: enumLogicGateType.analyzer,
[enumVirtualProcessorVariants.rotater]: enumLogicGateType.rotater,
[enumVirtualProcessorVariants.unstacker]: enumLogicGateType.unstacker,
[enumVirtualProcessorVariants.shapecompare]: enumLogicGateType.shapecompare,
[enumVirtualProcessorVariants.stacker]: enumLogicGateType.stacker,
[enumVirtualProcessorVariants.painter]: enumLogicGateType.painter,
};
const colors = {
[defaultBuildingVariant]: new MetaCutterBuilding().getSilhouetteColor(),
[enumVirtualProcessorVariants.rotater]: new MetaRotaterBuilding().getSilhouetteColor(),
[enumVirtualProcessorVariants.unstacker]: new MetaStackerBuilding().getSilhouetteColor(),
[enumVirtualProcessorVariants.stacker]: new MetaStackerBuilding().getSilhouetteColor(),
[enumVirtualProcessorVariants.painter]: new MetaPainterBuilding().getSilhouetteColor(),
};
export class MetaVirtualProcessorBuilding extends MetaBuilding {
constructor() {
super("virtual_processor");
}
getSilhouetteColor() {
return "#823cab";
getSilhouetteColor(variant) {
return colors[variant];
}
/**
@@ -56,11 +64,9 @@ export class MetaVirtualProcessorBuilding extends MetaBuilding {
return [
defaultBuildingVariant,
enumVirtualProcessorVariants.rotater,
enumVirtualProcessorVariants.unstacker,
enumVirtualProcessorVariants.analyzer,
enumVirtualProcessorVariants.stacker,
enumVirtualProcessorVariants.painter,
enumVirtualProcessorVariants.shapecompare,
enumVirtualProcessorVariants.unstacker,
];
}
@@ -80,7 +86,6 @@ export class MetaVirtualProcessorBuilding extends MetaBuilding {
const pinComp = entity.components.WiredPins;
switch (gateType) {
case enumLogicGateType.cutter:
case enumLogicGateType.analyzer:
case enumLogicGateType.unstacker: {
pinComp.setSlots([
{
@@ -116,26 +121,6 @@ export class MetaVirtualProcessorBuilding extends MetaBuilding {
]);
break;
}
case enumLogicGateType.shapecompare: {
pinComp.setSlots([
{
pos: new Vector(0, 0),
direction: enumDirection.top,
type: enumPinSlotType.logicalEjector,
},
{
pos: new Vector(0, 0),
direction: enumDirection.left,
type: enumPinSlotType.logicalAcceptor,
},
{
pos: new Vector(0, 0),
direction: enumDirection.right,
type: enumPinSlotType.logicalAcceptor,
},
]);
break;
}
case enumLogicGateType.stacker:
case enumLogicGateType.painter: {
pinComp.setSlots([

View File

@@ -1,263 +1,272 @@
import { Loader } from "../../core/loader";
import { generateMatrixRotations } from "../../core/utils";
import { enumDirection, enumDirectionToAngle, enumDirectionToVector, Vector } from "../../core/vector";
import { SOUNDS } from "../../platform/sound";
import { enumWireType, WireComponent } from "../components/wire";
import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
export const arrayWireRotationVariantToType = [
enumWireType.regular,
enumWireType.turn,
enumWireType.split,
enumWireType.cross,
];
export const wireOverlayMatrices = {
[enumWireType.regular]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]),
[enumWireType.split]: generateMatrixRotations([0, 0, 0, 1, 1, 1, 0, 1, 0]),
[enumWireType.turn]: generateMatrixRotations([0, 0, 0, 0, 1, 1, 0, 1, 0]),
[enumWireType.cross]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]),
};
export class MetaWireBuilding extends MetaBuilding {
constructor() {
super("wire");
}
getHasDirectionLockAvailable() {
return true;
}
getSilhouetteColor() {
return "#25fff2";
}
getDimensions() {
return new Vector(1, 1);
}
getStayInPlacementMode() {
return true;
}
getPlacementSound() {
return SOUNDS.placeBelt;
}
getRotateAutomaticallyWhilePlacing() {
return true;
}
/** @returns {"wires"} **/
getLayer() {
return "wires";
}
getSprite() {
return null;
}
getIsReplaceable() {
return true;
}
/**
* @param {GameRoot} root
*/
getIsUnlocked(root) {
// @todo
return true;
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {
// @todo
entity.addComponent(new WireComponent({}));
}
/**
*
* @param {Entity} entity
* @param {number} rotationVariant
*/
updateVariants(entity, rotationVariant) {
entity.components.Wire.type = arrayWireRotationVariantToType[rotationVariant];
}
/**
*
* @param {number} rotation
* @param {number} rotationVariant
* @param {string} variant
* @param {Entity} entity
*/
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
return wireOverlayMatrices[entity.components.Wire.type][rotation];
}
getPreviewSprite(rotationVariant) {
switch (arrayWireRotationVariantToType[rotationVariant]) {
case enumWireType.regular: {
return Loader.getSprite("sprites/buildings/wire.png");
}
case enumWireType.turn: {
return Loader.getSprite("sprites/buildings/wire-turn.png");
}
case enumWireType.split: {
return Loader.getSprite("sprites/buildings/wire-split.png");
}
case enumWireType.cross: {
return Loader.getSprite("sprites/buildings/wire-cross.png");
}
default: {
assertAlways(false, "Invalid wire rotation variant");
}
}
}
getBlueprintSprite(rotationVariant) {
switch (arrayWireRotationVariantToType[rotationVariant]) {
case enumWireType.regular: {
return Loader.getSprite("sprites/blueprints/wire.png");
}
case enumWireType.turn: {
return Loader.getSprite("sprites/blueprints/wire-turn.png");
}
case enumWireType.split: {
return Loader.getSprite("sprites/blueprints/wire-split.png");
}
case enumWireType.cross: {
return Loader.getSprite("sprites/blueprints/wire-cross.png");
}
default: {
assertAlways(false, "Invalid wire rotation variant");
}
}
}
/**
* Should compute the optimal rotation variant on the given tile
* @param {object} param0
* @param {GameRoot} param0.root
* @param {Vector} param0.tile
* @param {number} param0.rotation
* @param {string} param0.variant
* @param {string} param0.layer
* @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array<Entity> }}
*/
computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) {
const connections = {
top: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.top }),
right: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.right }),
bottom: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.bottom }),
left: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.left }),
};
let flag = 0;
flag |= connections.top ? 0x1000 : 0;
flag |= connections.right ? 0x100 : 0;
flag |= connections.bottom ? 0x10 : 0;
flag |= connections.left ? 0x1 : 0;
let targetType = enumWireType.regular;
// First, reset rotation
rotation = 0;
switch (flag) {
case 0x0000:
// Nothing
break;
case 0x0001:
// Left
rotation += 90;
break;
case 0x0010:
// Bottom
// END
break;
case 0x0011:
// Bottom | Left
targetType = enumWireType.turn;
rotation += 90;
break;
case 0x0100:
// Right
rotation += 90;
break;
case 0x0101:
// Right | Left
rotation += 90;
break;
case 0x0110:
// Right | Bottom
targetType = enumWireType.turn;
break;
case 0x0111:
// Right | Bottom | Left
targetType = enumWireType.split;
break;
case 0x1000:
// Top
break;
case 0x1001:
// Top | Left
targetType = enumWireType.turn;
rotation += 180;
break;
case 0x1010:
// Top | Bottom
break;
case 0x1011:
// Top | Bottom | Left
targetType = enumWireType.split;
rotation += 90;
break;
case 0x1100:
// Top | Right
targetType = enumWireType.turn;
rotation -= 90;
break;
case 0x1101:
// Top | Right | Left
targetType = enumWireType.split;
rotation += 180;
break;
case 0x1110:
// Top | Right | Bottom
targetType = enumWireType.split;
rotation -= 90;
break;
case 0x1111:
// Top | Right | Bottom | Left
targetType = enumWireType.cross;
break;
}
return {
// Clamp rotation
rotation: (rotation + 360 * 10) % 360,
rotationVariant: arrayWireRotationVariantToType.indexOf(targetType),
};
}
}
import { Loader } from "../../core/loader";
import { generateMatrixRotations } from "../../core/utils";
import { enumDirection, Vector } from "../../core/vector";
import { SOUNDS } from "../../platform/sound";
import { enumWireType, enumWireVariant, WireComponent } from "../components/wire";
import { Entity } from "../entity";
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
export const arrayWireRotationVariantToType = [
enumWireType.forward,
enumWireType.turn,
enumWireType.split,
enumWireType.cross,
];
export const wireOverlayMatrices = {
[enumWireType.forward]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]),
[enumWireType.split]: generateMatrixRotations([0, 0, 0, 1, 1, 1, 0, 1, 0]),
[enumWireType.turn]: generateMatrixRotations([0, 0, 0, 0, 1, 1, 0, 1, 0]),
[enumWireType.cross]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]),
};
/** @enum {string} */
export const wireVariants = {
second: "second",
third: "third",
};
const enumWireVariantToVariant = {
[defaultBuildingVariant]: enumWireVariant.first,
[wireVariants.second]: enumWireVariant.second,
[wireVariants.third]: enumWireVariant.third,
};
export class MetaWireBuilding extends MetaBuilding {
constructor() {
super("wire");
}
getHasDirectionLockAvailable() {
return true;
}
getSilhouetteColor() {
return "#61ef6f";
}
getAvailableVariants() {
return [defaultBuildingVariant, wireVariants.second, wireVariants.third];
}
getDimensions() {
return new Vector(1, 1);
}
getStayInPlacementMode() {
return true;
}
getPlacementSound() {
return SOUNDS.placeBelt;
}
getRotateAutomaticallyWhilePlacing() {
return true;
}
/** @returns {"wires"} **/
getLayer() {
return "wires";
}
getSprite() {
return null;
}
getIsReplaceable() {
return true;
}
/**
* @param {GameRoot} root
*/
getIsUnlocked(root) {
// @todo
return true;
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {
entity.addComponent(new WireComponent({}));
}
/**
*
* @param {Entity} entity
* @param {number} rotationVariant
* @param {string} variant
*/
updateVariants(entity, rotationVariant, variant) {
entity.components.Wire.type = arrayWireRotationVariantToType[rotationVariant];
entity.components.Wire.variant = enumWireVariantToVariant[variant];
}
/**
*
* @param {number} rotation
* @param {number} rotationVariant
* @param {string} variant
* @param {Entity} entity
*/
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
return wireOverlayMatrices[entity.components.Wire.type][rotation];
}
/**
*
* @param {number} rotationVariant
* @param {string} variant
* @returns {import("../../core/draw_utils").AtlasSprite}
*/
getPreviewSprite(rotationVariant, variant) {
const wireVariant = enumWireVariantToVariant[variant];
switch (arrayWireRotationVariantToType[rotationVariant]) {
case enumWireType.forward: {
return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_forward.png");
}
case enumWireType.turn: {
return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_turn.png");
}
case enumWireType.split: {
return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_split.png");
}
case enumWireType.cross: {
return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_cross.png");
}
default: {
assertAlways(false, "Invalid wire rotation variant");
}
}
}
getBlueprintSprite(rotationVariant, variant) {
return this.getPreviewSprite(rotationVariant, variant);
}
/**
* Should compute the optimal rotation variant on the given tile
* @param {object} param0
* @param {GameRoot} param0.root
* @param {Vector} param0.tile
* @param {number} param0.rotation
* @param {string} param0.variant
* @param {string} param0.layer
* @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array<Entity> }}
*/
computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) {
const wireVariant = enumWireVariantToVariant[variant];
const connections = {
top: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.top }),
right: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.right }),
bottom: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.bottom }),
left: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.left }),
};
let flag = 0;
flag |= connections.top ? 0x1000 : 0;
flag |= connections.right ? 0x100 : 0;
flag |= connections.bottom ? 0x10 : 0;
flag |= connections.left ? 0x1 : 0;
let targetType = enumWireType.forward;
// First, reset rotation
rotation = 0;
switch (flag) {
case 0x0000:
// Nothing
break;
case 0x0001:
// Left
rotation += 90;
break;
case 0x0010:
// Bottom
// END
break;
case 0x0011:
// Bottom | Left
targetType = enumWireType.turn;
rotation += 90;
break;
case 0x0100:
// Right
rotation += 90;
break;
case 0x0101:
// Right | Left
rotation += 90;
break;
case 0x0110:
// Right | Bottom
targetType = enumWireType.turn;
break;
case 0x0111:
// Right | Bottom | Left
targetType = enumWireType.split;
break;
case 0x1000:
// Top
break;
case 0x1001:
// Top | Left
targetType = enumWireType.turn;
rotation += 180;
break;
case 0x1010:
// Top | Bottom
break;
case 0x1011:
// Top | Bottom | Left
targetType = enumWireType.split;
rotation += 90;
break;
case 0x1100:
// Top | Right
targetType = enumWireType.turn;
rotation -= 90;
break;
case 0x1101:
// Top | Right | Left
targetType = enumWireType.split;
rotation += 180;
break;
case 0x1110:
// Top | Right | Bottom
targetType = enumWireType.split;
rotation -= 90;
break;
case 0x1111:
// Top | Right | Bottom | Left
targetType = enumWireType.cross;
break;
}
return {
// Clamp rotation
rotation: (rotation + 360 * 10) % 360,
rotationVariant: arrayWireRotationVariantToType.indexOf(targetType),
};
}
}

View File

@@ -1,87 +1,58 @@
import { Vector } from "../../core/vector";
import { Entity } from "../entity";
import { MetaBuilding, defaultBuildingVariant } from "../meta_building";
import { GameRoot } from "../root";
import { WireTunnelComponent } from "../components/wire_tunnel";
import { generateMatrixRotations } from "../../core/utils";
/** @enum {string} */
export const enumWireTunnelVariants = {
coating: "coating",
};
const wireTunnelOverlayMatrices = {
[defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]),
[enumWireTunnelVariants.coating]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]),
};
export class MetaWireTunnelBuilding extends MetaBuilding {
constructor() {
super("wire_tunnel");
}
getSilhouetteColor() {
return "#777a86";
}
/**
* @param {GameRoot} root
*/
getIsUnlocked(root) {
// @todo
return true;
}
/**
*
* @param {number} rotation
* @param {number} rotationVariant
* @param {string} variant
* @param {Entity} entity
*/
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
return wireTunnelOverlayMatrices[variant][rotation];
}
getIsRotateable(variant) {
return variant !== defaultBuildingVariant;
}
getDimensions() {
return new Vector(1, 1);
}
getAvailableVariants() {
return [defaultBuildingVariant, enumWireTunnelVariants.coating];
}
/** @returns {"wires"} **/
getLayer() {
return "wires";
}
getRotateAutomaticallyWhilePlacing() {
return true;
}
getStayInPlacementMode() {
return true;
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {
entity.addComponent(new WireTunnelComponent({}));
}
/**
* @param {Entity} entity
* @param {number} rotationVariant
* @param {string} variant
*/
updateVariants(entity, rotationVariant, variant) {
entity.components.WireTunnel.multipleDirections = variant === defaultBuildingVariant;
}
}
import { generateMatrixRotations } from "../../core/utils";
import { Vector } from "../../core/vector";
import { WireTunnelComponent } from "../components/wire_tunnel";
import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals";
const wireTunnelOverlayMatrix = generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]);
export class MetaWireTunnelBuilding extends MetaBuilding {
constructor() {
super("wire_tunnel");
}
getSilhouetteColor() {
return "#777a86";
}
/**
* @param {GameRoot} root
*/
getIsUnlocked(root) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_filters_and_levers);
}
/**
*
* @param {number} rotation
* @param {number} rotationVariant
* @param {string} variant
* @param {Entity} entity
*/
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
return wireTunnelOverlayMatrix[rotation];
}
getIsRotateable() {
return false;
}
getDimensions() {
return new Vector(1, 1);
}
/** @returns {"wires"} **/
getLayer() {
return "wires";
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {
entity.addComponent(new WireTunnelComponent({}));
}
}