You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tobspr_shapez.io/src/js/game/systems/wire.js

141 lines
6.0 KiB

import { GameSystemWithFilter } from "../game_system_with_filter";
import { WireComponent, enumWireType } from "../components/wire";
import { MapChunkView } from "../map_chunk_view";
import { globalConfig } from "../../core/config";
import { Loader } from "../../core/loader";
import { Entity } from "../entity";
import { gMetaBuildingRegistry } from "../../core/global_registries";
import { MetaWireBuilding, arrayWireRotationVariantToType } from "../buildings/wire";
import { Vector } from "../../core/vector";
import { defaultBuildingVariant } from "../meta_building";
export class WireSystem extends GameSystemWithFilter {
constructor(root) {
super(root, [WireComponent]);
this.wireSprites = {
[enumWireType.regular]: Loader.getSprite("sprites/buildings/wire.png"),
[enumWireType.turn]: Loader.getSprite("sprites/buildings/wire-turn.png"),
[enumWireType.split]: Loader.getSprite("sprites/buildings/wire-split.png"),
[enumWireType.cross]: Loader.getSprite("sprites/buildings/wire-cross.png"),
};
this.root.signals.entityDestroyed.add(this.updateSurroundingWirePlacement, this);
this.root.signals.entityAdded.add(this.updateSurroundingWirePlacement, this);
}
/**
* Draws a given chunk
* @param {import("../../core/draw_utils").DrawParameters} parameters
* @param {MapChunkView} chunk
*/
drawChunk(parameters, chunk) {
const contents = chunk.wireContents;
for (let y = 0; y < globalConfig.mapChunkSize; ++y) {
for (let x = 0; x < globalConfig.mapChunkSize; ++x) {
const entity = contents[x][y];
if (entity && entity.components.Wire) {
const wireType = entity.components.Wire.type;
const sprite = this.wireSprites[wireType];
assert(sprite, "Unknown wire type: " + wireType);
const staticComp = entity.components.StaticMapEntity;
staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 0);
if (G_IS_DEV && globalConfig.debug.renderWireRotations) {
parameters.context.fillStyle = "red";
parameters.context.font = "5px Tahoma";
parameters.context.fillText(
"" + staticComp.originalRotation,
staticComp.origin.x * globalConfig.tileSize,
staticComp.origin.y * globalConfig.tileSize + 5
);
parameters.context.fillStyle = "rgba(255, 0, 0, 0.2)";
if (staticComp.originalRotation % 180 === 0) {
parameters.context.fillRect(
(staticComp.origin.x + 0.5) * globalConfig.tileSize,
staticComp.origin.y * globalConfig.tileSize,
3,
globalConfig.tileSize
);
} else {
parameters.context.fillRect(
staticComp.origin.x * globalConfig.tileSize,
(staticComp.origin.y + 0.5) * globalConfig.tileSize,
globalConfig.tileSize,
3
);
}
}
}
}
}
}
/**
* Updates the wire placement after an entity has been added / deleted
* @param {Entity} entity
*/
updateSurroundingWirePlacement(entity) {
if (!this.root.gameInitialized) {
return;
}
const staticComp = entity.components.StaticMapEntity;
if (!staticComp) {
return;
}
const metaWire = gMetaBuildingRegistry.findByClass(MetaWireBuilding);
// Compute affected area
const originalRect = staticComp.getTileSpaceBounds();
const affectedArea = originalRect.expandedInAllDirections(1);
for (let x = affectedArea.x; x < affectedArea.right(); ++x) {
for (let y = affectedArea.y; y < affectedArea.bottom(); ++y) {
if (originalRect.containsPoint(x, y)) {
// Make sure we don't update the original entity
continue;
}
const targetEntities = this.root.map.getLayersContentsMultipleXY(x, y);
for (let i = 0; i < targetEntities.length; ++i) {
const targetEntity = targetEntities[i];
const targetWireComp = targetEntity.components.Wire;
const targetStaticComp = targetEntity.components.StaticMapEntity;
if (!targetWireComp) {
// Not a wire
continue;
}
const {
rotation,
rotationVariant,
} = metaWire.computeOptimalDirectionAndRotationVariantAtTile({
root: this.root,
tile: new Vector(x, y),
rotation: targetStaticComp.originalRotation,
variant: defaultBuildingVariant,
layer: targetEntity.layer,
});
// Compute delta to see if anything changed
const newType = arrayWireRotationVariantToType[rotationVariant];
if (targetStaticComp.rotation !== rotation || newType !== targetWireComp.type) {
// Change stuff
targetStaticComp.rotation = rotation;
metaWire.updateVariants(targetEntity, rotationVariant, defaultBuildingVariant);
// Make sure the chunks know about the update
this.root.signals.entityChanged.dispatch(targetEntity);
}
}
}
}
}
}