mirror of
https://github.com/tobspr/shapez.io.git
synced 2024-10-27 20:34:29 +00:00
Huge refactoring of the whole placement logic
This commit is contained in:
parent
ca8745b1c0
commit
d09bd0bcd7
@ -90,17 +90,7 @@ export class Blueprint {
|
||||
const rect = staticComp.getTileSpaceBounds();
|
||||
rect.moveBy(tile.x, tile.y);
|
||||
|
||||
let placeable = true;
|
||||
placementCheck: for (let x = rect.x; x < rect.right(); ++x) {
|
||||
for (let y = rect.y; y < rect.bottom(); ++y) {
|
||||
if (parameters.root.map.isTileUsedXY(x, y, entity.layer)) {
|
||||
placeable = false;
|
||||
break placementCheck;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!placeable) {
|
||||
if (!parameters.root.logic.checkCanPlaceEntity(entity, tile)) {
|
||||
parameters.context.globalAlpha = 0.3;
|
||||
} else {
|
||||
parameters.context.globalAlpha = 1;
|
||||
@ -150,21 +140,8 @@ export class Blueprint {
|
||||
let anyPlaceable = false;
|
||||
|
||||
for (let i = 0; i < this.entities.length; ++i) {
|
||||
let placeable = true;
|
||||
const entity = this.entities[i];
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
const rect = staticComp.getTileSpaceBounds();
|
||||
rect.moveBy(tile.x, tile.y);
|
||||
placementCheck: for (let x = rect.x; x < rect.right(); ++x) {
|
||||
for (let y = rect.y; y < rect.bottom(); ++y) {
|
||||
if (root.map.isTileUsedXY(x, y, entity.layer)) {
|
||||
placeable = false;
|
||||
break placementCheck;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (placeable) {
|
||||
if (root.logic.checkCanPlaceEntity(entity, tile)) {
|
||||
anyPlaceable = true;
|
||||
}
|
||||
}
|
||||
@ -188,48 +165,17 @@ export class Blueprint {
|
||||
return root.logic.performBulkOperation(() => {
|
||||
let anyPlaced = false;
|
||||
for (let i = 0; i < this.entities.length; ++i) {
|
||||
let placeable = true;
|
||||
const entity = this.entities[i];
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
const rect = staticComp.getTileSpaceBounds();
|
||||
rect.moveBy(tile.x, tile.y);
|
||||
placementCheck: for (let x = rect.x; x < rect.right(); ++x) {
|
||||
for (let y = rect.y; y < rect.bottom(); ++y) {
|
||||
const contents = root.map.getLayerContentXY(x, y, entity.layer);
|
||||
if (contents && !contents.components.ReplaceableMapEntity) {
|
||||
placeable = false;
|
||||
break placementCheck;
|
||||
}
|
||||
}
|
||||
if (!root.logic.checkCanPlaceEntity(entity, tile)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (placeable) {
|
||||
for (let x = rect.x; x < rect.right(); ++x) {
|
||||
for (let y = rect.y; y < rect.bottom(); ++y) {
|
||||
const contents = root.map.getLayerContentXY(x, y, entity.layer);
|
||||
if (contents) {
|
||||
assert(
|
||||
contents.components.ReplaceableMapEntity,
|
||||
"Can not delete entity for blueprint"
|
||||
);
|
||||
if (!root.logic.tryDeleteBuilding(contents)) {
|
||||
assertAlways(
|
||||
false,
|
||||
"Building has replaceable component but is also unremovable in blueprint"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const clone = entity.duplicateWithoutContents();
|
||||
clone.components.StaticMapEntity.origin.addInplace(tile);
|
||||
|
||||
root.map.placeStaticEntity(clone);
|
||||
|
||||
root.entityMgr.registerEntity(clone);
|
||||
anyPlaced = true;
|
||||
}
|
||||
const clone = entity.duplicateWithoutContents();
|
||||
clone.components.StaticMapEntity.origin.addInplace(tile);
|
||||
root.logic.freeEntityAreaBeforeBuild(clone);
|
||||
root.map.placeStaticEntity(clone);
|
||||
root.entityMgr.registerEntity(clone);
|
||||
anyPlaced = true;
|
||||
}
|
||||
return anyPlaced;
|
||||
});
|
||||
|
@ -130,7 +130,8 @@ export class GameCore {
|
||||
this.root.gameIsFresh = true;
|
||||
this.root.map.seed = randomInt(0, 100000);
|
||||
|
||||
gMetaBuildingRegistry.findByClass(MetaHubBuilding).createAndPlaceEntity({
|
||||
// Place the hub
|
||||
const hub = gMetaBuildingRegistry.findByClass(MetaHubBuilding).createEntity({
|
||||
root: this.root,
|
||||
origin: new Vector(-2, -2),
|
||||
rotation: 0,
|
||||
@ -138,6 +139,8 @@ export class GameCore {
|
||||
rotationVariant: 0,
|
||||
variant: defaultBuildingVariant,
|
||||
});
|
||||
this.root.map.placeStaticEntity(hub);
|
||||
this.root.entityMgr.registerEntity(hub);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -276,14 +276,7 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic {
|
||||
staticComp.tileSize = metaBuilding.getDimensions(this.currentVariant.get());
|
||||
metaBuilding.updateVariants(this.fakeEntity, rotationVariant, this.currentVariant.get());
|
||||
|
||||
// Check if we could place the buildnig
|
||||
const canBuild = this.root.logic.checkCanPlaceBuilding({
|
||||
origin: mouseTile,
|
||||
rotation,
|
||||
rotationVariant,
|
||||
building: metaBuilding,
|
||||
variant: this.currentVariant.get(),
|
||||
});
|
||||
const canBuild = this.root.logic.checkCanPlaceEntity(this.fakeEntity);
|
||||
|
||||
// Fade in / out
|
||||
parameters.context.lineWidth = 1;
|
||||
|
@ -1,12 +1,10 @@
|
||||
import { GameRoot, enumLayer, arrayLayers } from "./root";
|
||||
import { Entity } from "./entity";
|
||||
import { Vector, enumDirectionToVector, enumDirection } from "../core/vector";
|
||||
import { MetaBuilding } from "./meta_building";
|
||||
import { StaticMapEntityComponent } from "./components/static_map_entity";
|
||||
import { createLogger } from "../core/logging";
|
||||
import { MetaBeltBaseBuilding, arrayBeltVariantToRotation } from "./buildings/belt_base";
|
||||
import { SOUNDS } from "../platform/sound";
|
||||
import { round2Digits } from "../core/utils";
|
||||
import { enumDirection, enumDirectionToVector, Vector } from "../core/vector";
|
||||
import { Entity } from "./entity";
|
||||
import { MetaBuilding } from "./meta_building";
|
||||
import { enumLayer, GameRoot } from "./root";
|
||||
import { STOP_PROPAGATION } from "../core/signal";
|
||||
|
||||
const logger = createLogger("ingame/logic");
|
||||
|
||||
@ -47,125 +45,41 @@ export class GameLogic {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} param0
|
||||
* @param {Vector} param0.origin
|
||||
* @param {number} param0.rotation
|
||||
* @param {number} param0.rotationVariant
|
||||
* @param {string} param0.variant
|
||||
* @param {MetaBuilding} param0.building
|
||||
* @returns {boolean}
|
||||
* Checks if the given entity can be placed
|
||||
* @param {Entity} entity
|
||||
* @param {Vector=} offset Optional, move the entity by the given offset first
|
||||
* @returns {boolean} true if the entity could be placed there
|
||||
*/
|
||||
isAreaFreeToBuild({ origin, rotation, rotationVariant, variant, building }) {
|
||||
const checker = new StaticMapEntityComponent({
|
||||
origin,
|
||||
tileSize: building.getDimensions(variant),
|
||||
rotation,
|
||||
blueprintSpriteKey: "",
|
||||
});
|
||||
|
||||
const layer = building.getLayer();
|
||||
const rect = checker.getTileSpaceBounds();
|
||||
checkCanPlaceEntity(entity, offset = null) {
|
||||
// Compute area of the building
|
||||
const rect = entity.components.StaticMapEntity.getTileSpaceBounds();
|
||||
if (offset) {
|
||||
rect.x += offset.x;
|
||||
rect.y += offset.y;
|
||||
}
|
||||
|
||||
// Check the whole area of the building
|
||||
for (let x = rect.x; x < rect.x + rect.w; ++x) {
|
||||
for (let y = rect.y; y < rect.y + rect.h; ++y) {
|
||||
const contents = this.root.map.getLayerContentXY(x, y, layer);
|
||||
if (contents) {
|
||||
if (
|
||||
!this.checkCanReplaceBuilding({
|
||||
original: contents,
|
||||
building,
|
||||
rotation,
|
||||
rotationVariant,
|
||||
})
|
||||
) {
|
||||
// Content already has same rotation
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for any pins which are in the way
|
||||
if (layer === enumLayer.wires) {
|
||||
const regularContents = this.root.map.getLayerContentXY(x, y, enumLayer.regular);
|
||||
if (regularContents) {
|
||||
const staticComp = regularContents.components.StaticMapEntity;
|
||||
const pinComponent = regularContents.components.WiredPins;
|
||||
if (pinComponent) {
|
||||
const pins = pinComponent.slots;
|
||||
for (let i = 0; i < pins.length; ++i) {
|
||||
const pos = staticComp.localTileToWorld(pins[i].pos);
|
||||
// Occupied by a pin
|
||||
if (pos.x === x && pos.y === y) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if there is any direct collision
|
||||
const otherEntity = this.root.map.getLayerContentXY(x, y, entity.layer);
|
||||
if (otherEntity && !otherEntity.components.ReplaceableMapEntity) {
|
||||
// This one is a direct blocker
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given building can be replaced by another
|
||||
* @param {object} param0
|
||||
* @param {Entity} param0.original
|
||||
* @param {number} param0.rotation
|
||||
* @param {number} param0.rotationVariant
|
||||
* @param {MetaBuilding} param0.building
|
||||
* @returns {boolean}
|
||||
*/
|
||||
checkCanReplaceBuilding({ original, building, rotation, rotationVariant }) {
|
||||
if (!original.components.ReplaceableMapEntity) {
|
||||
// Can not get replaced at all
|
||||
// Perform additional placement checks
|
||||
if (this.root.signals.prePlacementCheck.dispatch(entity, offset) === STOP_PROPAGATION) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (building.getLayer() !== original.layer) {
|
||||
// Layer mismatch
|
||||
return false;
|
||||
}
|
||||
|
||||
const staticComp = original.components.StaticMapEntity;
|
||||
assert(staticComp, "Building is not static");
|
||||
const beltComp = original.components.Belt;
|
||||
if (beltComp && building instanceof MetaBeltBaseBuilding) {
|
||||
// Its a belt, check if it differs in either rotation or rotation variant
|
||||
if (staticComp.rotation !== rotation) {
|
||||
return true;
|
||||
}
|
||||
if (beltComp.direction !== arrayBeltVariantToRotation[rotationVariant]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} param0
|
||||
* @param {Vector} param0.origin
|
||||
* @param {number} param0.rotation
|
||||
* @param {number} param0.rotationVariant
|
||||
* @param {string} param0.variant
|
||||
* @param {MetaBuilding} param0.building
|
||||
*/
|
||||
checkCanPlaceBuilding({ origin, rotation, rotationVariant, variant, building }) {
|
||||
if (!building.getIsUnlocked(this.root)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.isAreaFreeToBuild({
|
||||
origin,
|
||||
rotation,
|
||||
rotationVariant,
|
||||
variant,
|
||||
building,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Attempts to place the given building
|
||||
* @param {object} param0
|
||||
* @param {Vector} param0.origin
|
||||
* @param {number} param0.rotation
|
||||
@ -176,44 +90,51 @@ export class GameLogic {
|
||||
* @returns {Entity}
|
||||
*/
|
||||
tryPlaceBuilding({ origin, rotation, rotationVariant, originalRotation, variant, building }) {
|
||||
if (this.checkCanPlaceBuilding({ origin, rotation, rotationVariant, variant, building })) {
|
||||
// Remove any removeable entities below
|
||||
const checker = new StaticMapEntityComponent({
|
||||
origin,
|
||||
tileSize: building.getDimensions(variant),
|
||||
rotation,
|
||||
blueprintSpriteKey: "",
|
||||
});
|
||||
|
||||
const layer = building.getLayer();
|
||||
|
||||
const rect = checker.getTileSpaceBounds();
|
||||
for (let x = rect.x; x < rect.x + rect.w; ++x) {
|
||||
for (let y = rect.y; y < rect.y + rect.h; ++y) {
|
||||
const contents = this.root.map.getLayerContentXY(x, y, layer);
|
||||
if (contents) {
|
||||
if (!this.tryDeleteBuilding(contents)) {
|
||||
logger.error("Building has replaceable component but is also unremovable");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const entity = building.createAndPlaceEntity({
|
||||
root: this.root,
|
||||
origin,
|
||||
rotation,
|
||||
rotationVariant,
|
||||
originalRotation,
|
||||
variant,
|
||||
});
|
||||
|
||||
const entity = building.createEntity({
|
||||
root: this.root,
|
||||
origin,
|
||||
rotation,
|
||||
originalRotation,
|
||||
rotationVariant,
|
||||
variant,
|
||||
});
|
||||
if (this.checkCanPlaceEntity(entity)) {
|
||||
this.freeEntityAreaBeforeBuild(entity);
|
||||
this.root.map.placeStaticEntity(entity);
|
||||
this.root.entityMgr.registerEntity(entity);
|
||||
return entity;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all entities with a RemovableMapEntityComponent which need to get
|
||||
* removed before placing this entity
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
freeEntityAreaBeforeBuild(entity) {
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
const rect = staticComp.getTileSpaceBounds();
|
||||
// Remove any removeable colliding entities on the same layer
|
||||
for (let x = rect.x; x < rect.x + rect.w; ++x) {
|
||||
for (let y = rect.y; y < rect.y + rect.h; ++y) {
|
||||
const contents = this.root.map.getLayerContentXY(x, y, entity.layer);
|
||||
if (contents) {
|
||||
assertAlways(
|
||||
contents.components.ReplaceableMapEntity,
|
||||
"Tried to replace non-repleaceable entity"
|
||||
);
|
||||
if (!this.tryDeleteBuilding(contents)) {
|
||||
assertAlways(false, "Tried to replace non-repleaceable entity #2");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Perform other callbacks
|
||||
this.root.signals.freeEntityAreaBeforeBuild.dispatch(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a bulk operation, not updating caches in the meantime
|
||||
* @param {function} operation
|
||||
@ -266,6 +187,7 @@ export class GameLogic {
|
||||
/** @type {AcceptorsAffectingTile} */
|
||||
let acceptors = [];
|
||||
|
||||
// Well .. please ignore this code! :D
|
||||
for (let dx = -1; dx <= 1; ++dx) {
|
||||
for (let dy = -1; dy <= 1; ++dy) {
|
||||
if (Math.abs(dx) + Math.abs(dy) !== 1) {
|
||||
|
@ -144,30 +144,6 @@ export class MetaBuilding {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
* @param {object} param0
|
||||
* @param {GameRoot} param0.root
|
||||
* @param {Vector} param0.origin Origin tile
|
||||
* @param {number=} param0.rotation Rotation
|
||||
* @param {number} param0.originalRotation Original Rotation
|
||||
* @param {number} param0.rotationVariant Rotation variant
|
||||
* @param {string} param0.variant
|
||||
*/
|
||||
createAndPlaceEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) {
|
||||
const entity = this.createEntity({
|
||||
root,
|
||||
origin,
|
||||
rotation,
|
||||
originalRotation,
|
||||
rotationVariant,
|
||||
variant,
|
||||
});
|
||||
root.map.placeStaticEntity(entity);
|
||||
root.entityMgr.registerEntity(entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the entity without placing it
|
||||
* @param {object} param0
|
||||
|
@ -27,6 +27,7 @@ import { ShapeDefinition } from "./shape_definition";
|
||||
import { BaseItem } from "./base_item";
|
||||
import { DynamicTickrate } from "./dynamic_tickrate";
|
||||
import { KeyActionMapper } from "./key_action_mapper";
|
||||
import { Vector } from "../core/vector";
|
||||
/* typehints:end */
|
||||
|
||||
const logger = createLogger("game/root");
|
||||
@ -169,6 +170,14 @@ export class GameRoot {
|
||||
bulkOperationFinished: /** @type {TypedSignal<[]>} */ (new Signal()),
|
||||
|
||||
editModeChanged: /** @type {TypedSignal<[enumLayer]>} */ (new Signal()),
|
||||
|
||||
// Called to check if an entity can be placed, second parameter is an additional offset.
|
||||
// Use to introduce additional placement checks
|
||||
prePlacementCheck: /** @type {TypedSignal<[Entity, Vector]>} */ (new Signal()),
|
||||
|
||||
// Called before actually placing an entity, use to perform additional logic
|
||||
// for freeing space before actually placing.
|
||||
freeEntityAreaBeforeBuild: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
||||
};
|
||||
|
||||
// RNG's
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { globalConfig } from "../../core/config";
|
||||
import { DrawParameters } from "../../core/draw_parameters";
|
||||
import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins";
|
||||
import { Loader } from "../../core/loader";
|
||||
import { Vector } from "../../core/vector";
|
||||
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
|
||||
import { Entity } from "../entity";
|
||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||
import { MapChunkView } from "../map_chunk_view";
|
||||
import { Loader } from "../../core/loader";
|
||||
import { enumLayer } from "../root";
|
||||
|
||||
export class WiredPinsSystem extends GameSystemWithFilter {
|
||||
constructor(root) {
|
||||
@ -20,6 +21,127 @@ export class WiredPinsSystem extends GameSystemWithFilter {
|
||||
"sprites/wires/pin_negative_accept.png"
|
||||
),
|
||||
};
|
||||
|
||||
this.root.signals.prePlacementCheck.add(this.prePlacementCheck, this);
|
||||
this.root.signals.freeEntityAreaBeforeBuild.add(this.freeEntityAreaBeforeBuild, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs pre-placement checks
|
||||
* @param {Entity} entity
|
||||
* @param {Vector} offset
|
||||
*/
|
||||
prePlacementCheck(entity, offset) {
|
||||
// Compute area of the building
|
||||
const rect = entity.components.StaticMapEntity.getTileSpaceBounds();
|
||||
if (offset) {
|
||||
rect.x += offset.x;
|
||||
rect.y += offset.y;
|
||||
}
|
||||
|
||||
// If this entity is placed on the wires layer, make sure we don't
|
||||
// place it above a pin
|
||||
if (entity.layer === enumLayer.wires) {
|
||||
for (let x = rect.x; x < rect.x + rect.w; ++x) {
|
||||
for (let y = rect.y; y < rect.y + rect.h; ++y) {
|
||||
// Find which entities are in same tiles of both layers
|
||||
const entities = this.root.map.getLayersContentsMultipleXY(x, y);
|
||||
for (let i = 0; i < entities.length; ++i) {
|
||||
const otherEntity = entities[i];
|
||||
|
||||
// Check if entity has a wired component
|
||||
const pinComponent = otherEntity.components.WiredPins;
|
||||
const staticComp = otherEntity.components.StaticMapEntity;
|
||||
if (!pinComponent) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (otherEntity.components.ReplaceableMapEntity) {
|
||||
// Don't mind here, even if there would be a collision we
|
||||
// could replace it
|
||||
continue;
|
||||
}
|
||||
|
||||
// Go over all pins and check if they are blocking
|
||||
const pins = pinComponent.slots;
|
||||
for (let pinSlot = 0; pinSlot < pins.length; ++pinSlot) {
|
||||
const pos = staticComp.localTileToWorld(pins[pinSlot].pos);
|
||||
// Occupied by a pin
|
||||
if (pos.x === x && pos.y === y) {
|
||||
return STOP_PROPAGATION;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for collisions on the wires layer
|
||||
if (this.checkEntityPinsCollide(entity, offset)) {
|
||||
return STOP_PROPAGATION;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the pins of the given entity collide on the wires layer
|
||||
* @param {Entity} entity
|
||||
* @param {Vector=} offset Optional, move the entity by the given offset first
|
||||
* @returns {boolean} True if the pins collide
|
||||
*/
|
||||
checkEntityPinsCollide(entity, offset) {
|
||||
const pinsComp = entity.components.WiredPins;
|
||||
if (!pinsComp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Go over all slots
|
||||
for (let slotIndex = 0; slotIndex < pinsComp.slots.length; ++slotIndex) {
|
||||
const slot = pinsComp.slots[slotIndex];
|
||||
|
||||
// Figure out which tile this slot is on
|
||||
const worldPos = entity.components.StaticMapEntity.localTileToWorld(slot.pos);
|
||||
if (offset) {
|
||||
worldPos.x += offset.x;
|
||||
worldPos.y += offset.y;
|
||||
}
|
||||
|
||||
// Check if there is any entity on that tile (Wired pins are always on the wires layer)
|
||||
const collidingEntity = this.root.map.getLayerContentXY(worldPos.x, worldPos.y, enumLayer.wires);
|
||||
|
||||
// If there's an entity, and it can't get removed -> That's a collision
|
||||
if (collidingEntity && !collidingEntity.components.ReplaceableMapEntity) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to free space for the given entity
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
freeEntityAreaBeforeBuild(entity) {
|
||||
const pinsComp = entity.components.WiredPins;
|
||||
if (!pinsComp) {
|
||||
// Entity has no pins
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove any stuff which collides with the pins
|
||||
for (let i = 0; i < pinsComp.slots.length; ++i) {
|
||||
const slot = pinsComp.slots[i];
|
||||
const worldPos = entity.components.StaticMapEntity.localTileToWorld(slot.pos);
|
||||
const collidingEntity = this.root.map.getLayerContentXY(worldPos.x, worldPos.y, enumLayer.wires);
|
||||
if (collidingEntity) {
|
||||
assertAlways(
|
||||
collidingEntity.components.ReplaceableMapEntity,
|
||||
"Tried to replace non-repleaceable entity for pins"
|
||||
);
|
||||
if (!this.root.logic.tryDeleteBuilding(collidingEntity)) {
|
||||
assertAlways(false, "Tried to replace non-repleaceable entity for pins #2");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update() {
|
||||
|
Loading…
Reference in New Issue
Block a user