diff --git a/src/js/game/components/belt.js b/src/js/game/components/belt.js index 4f106437..2772dc05 100644 --- a/src/js/game/components/belt.js +++ b/src/js/game/components/belt.js @@ -93,7 +93,7 @@ export class BeltComponent extends Component { * Returns fake acceptor slot used for matching * @returns {import("./item_ejector").ItemEjectorSlot} */ - getFakeEjectorSlots() { + getFakeEjectorSlot() { assert( FAKE_BELT_EJECTOR_SLOT_BY_DIRECTION[this.direction], "Invalid belt direction: ", diff --git a/src/js/game/components/item_ejector.js b/src/js/game/components/item_ejector.js index 905ac81a..b42eac7a 100644 --- a/src/js/game/components/item_ejector.js +++ b/src/js/game/components/item_ejector.js @@ -90,11 +90,10 @@ export class ItemEjectorComponent extends Component { /** * Returns where this slot ejects to - * @param {number} index + * @param {ItemEjectorSlot} slot * @returns {Vector} */ - getSlotTargetLocalTile(index) { - const slot = this.slots[index]; + getSlotTargetLocalTile(slot) { const directionVector = enumDirectionToVector[slot.direction]; return slot.pos.add(directionVector); } @@ -105,7 +104,7 @@ export class ItemEjectorComponent extends Component { */ anySlotEjectsToLocalTile(tile) { for (let i = 0; i < this.slots.length; ++i) { - if (this.getSlotTargetLocalTile(i).equals(tile)) { + if (this.getSlotTargetLocalTile(this.slots[i]).equals(tile)) { return true; } } diff --git a/src/js/game/hud/parts/building_placer.js b/src/js/game/hud/parts/building_placer.js index 5a2f42de..9198c69a 100644 --- a/src/js/game/hud/parts/building_placer.js +++ b/src/js/game/hud/parts/building_placer.js @@ -9,6 +9,7 @@ import { enumDirectionToVector, enumInvertedDirections, Vector, + enumDirection, } from "../../../core/vector"; import { T } from "../../../translations"; import { KEYMAPPINGS } from "../../key_action_mapper"; @@ -427,6 +428,7 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { const acceptorComp = this.fakeEntity.components.ItemAcceptor; const ejectorComp = this.fakeEntity.components.ItemEjector; const staticComp = this.fakeEntity.components.StaticMapEntity; + const beltComp = this.fakeEntity.components.Belt; const goodArrowSprite = Loader.getSprite("sprites/misc/slot_good_arrow.png"); const badArrowSprite = Loader.getSprite("sprites/misc/slot_bad_arrow.png"); @@ -435,104 +437,68 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { const offsetShift = 10; - if (acceptorComp) { - const slots = acceptorComp.slots; - for (let acceptorSlotIndex = 0; acceptorSlotIndex < slots.length; ++acceptorSlotIndex) { - const slot = slots[acceptorSlotIndex]; - - const acceptorSlotWsTile = staticComp.localTileToWorld(slot.pos); - const acceptorSlotWsPos = acceptorSlotWsTile.toWorldSpaceCenterOfTile(); - - // Go over all slots - for ( - let acceptorDirectionIndex = 0; - acceptorDirectionIndex < slot.directions.length; - ++acceptorDirectionIndex - ) { - const direction = slot.directions[acceptorDirectionIndex]; - const worldDirection = staticComp.localDirectionToWorld(direction); - - // Figure out which tile ejects to this slot - const sourceTile = acceptorSlotWsTile.add(enumDirectionToVector[worldDirection]); - - let isBlocked = false; - let isConnected = false; - - // Find all entities which are on that tile - const sourceEntities = this.root.map.getLayersContentsMultipleXY( - sourceTile.x, - sourceTile.y - ); - - // Check for every entity: - for (let i = 0; i < sourceEntities.length; ++i) { - const sourceEntity = sourceEntities[i]; - const sourceEjector = sourceEntity.components.ItemEjector; - const sourceStaticComp = sourceEntity.components.StaticMapEntity; - const ejectorAcceptLocalTile = sourceStaticComp.worldToLocalTile(acceptorSlotWsTile); - - // If this entity is on the same layer as the slot - if so, it can either be - // connected, or it can not be connected and thus block the input - if (sourceEjector && sourceEjector.anySlotEjectsToLocalTile(ejectorAcceptLocalTile)) { - // This one is connected, all good - isConnected = true; - } else { - // This one is blocked - isBlocked = true; - } - } - - const alpha = isConnected || isBlocked ? 1.0 : 0.3; - const sprite = isBlocked ? badArrowSprite : goodArrowSprite; - - parameters.context.globalAlpha = alpha; - drawRotatedSprite({ - parameters, - sprite, - x: acceptorSlotWsPos.x, - y: acceptorSlotWsPos.y, - angle: Math.radians(enumDirectionToAngle[enumInvertedDirections[worldDirection]]), - size: 13, - offsetY: offsetShift + 13, - }); - parameters.context.globalAlpha = 1; - } - } - } + let acceptorSlots = []; + let ejectorSlots = []; if (ejectorComp) { - const slots = ejectorComp.slots; + ejectorSlots = ejectorComp.slots.slice(); + } + + if (acceptorComp) { + acceptorSlots = acceptorComp.slots.slice(); + } + + if (beltComp) { + const fakeEjectorSlot = beltComp.getFakeEjectorSlot(); + const fakeAcceptorSlot = beltComp.getFakeAcceptorSlot(); + ejectorSlots.push(fakeEjectorSlot); + acceptorSlots.push(fakeAcceptorSlot); + } + + for (let acceptorSlotIndex = 0; acceptorSlotIndex < acceptorSlots.length; ++acceptorSlotIndex) { + const slot = acceptorSlots[acceptorSlotIndex]; + + const acceptorSlotWsTile = staticComp.localTileToWorld(slot.pos); + const acceptorSlotWsPos = acceptorSlotWsTile.toWorldSpaceCenterOfTile(); // Go over all slots - for (let ejectorSlotIndex = 0; ejectorSlotIndex < slots.length; ++ejectorSlotIndex) { - const slot = slots[ejectorSlotIndex]; + for ( + let acceptorDirectionIndex = 0; + acceptorDirectionIndex < slot.directions.length; + ++acceptorDirectionIndex + ) { + const direction = slot.directions[acceptorDirectionIndex]; + const worldDirection = staticComp.localDirectionToWorld(direction); - const ejectorSlotWsTile = staticComp.localTileToWorld( - ejectorComp.getSlotTargetLocalTile(ejectorSlotIndex) - ); - const ejectorSLotWsPos = ejectorSlotWsTile.toWorldSpaceCenterOfTile(); - const ejectorSlotWsDirection = staticComp.localDirectionToWorld(slot.direction); + // Figure out which tile ejects to this slot + const sourceTile = acceptorSlotWsTile.add(enumDirectionToVector[worldDirection]); let isBlocked = false; let isConnected = false; // Find all entities which are on that tile - const destEntities = this.root.map.getLayersContentsMultipleXY( - ejectorSlotWsTile.x, - ejectorSlotWsTile.y - ); + const sourceEntities = this.root.map.getLayersContentsMultipleXY(sourceTile.x, sourceTile.y); // Check for every entity: - for (let i = 0; i < destEntities.length; ++i) { - const destEntity = destEntities[i]; - const destAcceptor = destEntity.components.ItemAcceptor; - const destStaticComp = destEntity.components.StaticMapEntity; + for (let i = 0; i < sourceEntities.length; ++i) { + const sourceEntity = sourceEntities[i]; + const sourceEjector = sourceEntity.components.ItemEjector; + const sourceBeltComp = sourceEntity.components.Belt; + const sourceStaticComp = sourceEntity.components.StaticMapEntity; + const ejectorAcceptLocalTile = sourceStaticComp.worldToLocalTile(acceptorSlotWsTile); - const destLocalTile = destStaticComp.worldToLocalTile(ejectorSlotWsTile); - const destLocalDir = destStaticComp.worldDirectionToLocal(ejectorSlotWsDirection); - if (destAcceptor && destAcceptor.findMatchingSlot(destLocalTile, destLocalDir)) { + // If this entity is on the same layer as the slot - if so, it can either be + // connected, or it can not be connected and thus block the input + if (sourceEjector && sourceEjector.anySlotEjectsToLocalTile(ejectorAcceptLocalTile)) { // This one is connected, all good isConnected = true; + } else if ( + sourceBeltComp && + sourceStaticComp.localDirectionToWorld(sourceBeltComp.direction) === + enumInvertedDirections[worldDirection] + ) { + // Belt connected + isConnected = true; } else { // This one is blocked isBlocked = true; @@ -546,14 +512,69 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { drawRotatedSprite({ parameters, sprite, - x: ejectorSLotWsPos.x, - y: ejectorSLotWsPos.y, - angle: Math.radians(enumDirectionToAngle[ejectorSlotWsDirection]), + x: acceptorSlotWsPos.x, + y: acceptorSlotWsPos.y, + angle: Math.radians(enumDirectionToAngle[enumInvertedDirections[worldDirection]]), size: 13, - offsetY: offsetShift, + offsetY: offsetShift + 13, }); parameters.context.globalAlpha = 1; } } + + // Go over all slots + for (let ejectorSlotIndex = 0; ejectorSlotIndex < ejectorSlots.length; ++ejectorSlotIndex) { + const slot = ejectorSlots[ejectorSlotIndex]; + + const ejectorSlotLocalTile = slot.pos.add(enumDirectionToVector[slot.direction]); + const ejectorSlotWsTile = staticComp.localTileToWorld(ejectorSlotLocalTile); + + const ejectorSLotWsPos = ejectorSlotWsTile.toWorldSpaceCenterOfTile(); + const ejectorSlotWsDirection = staticComp.localDirectionToWorld(slot.direction); + + let isBlocked = false; + let isConnected = false; + + // Find all entities which are on that tile + const destEntities = this.root.map.getLayersContentsMultipleXY( + ejectorSlotWsTile.x, + ejectorSlotWsTile.y + ); + + // Check for every entity: + for (let i = 0; i < destEntities.length; ++i) { + const destEntity = destEntities[i]; + const destAcceptor = destEntity.components.ItemAcceptor; + const destStaticComp = destEntity.components.StaticMapEntity; + + const destLocalTile = destStaticComp.worldToLocalTile(ejectorSlotWsTile); + const destLocalDir = destStaticComp.worldDirectionToLocal(ejectorSlotWsDirection); + if (destAcceptor && destAcceptor.findMatchingSlot(destLocalTile, destLocalDir)) { + // This one is connected, all good + isConnected = true; + } else if (destEntity.components.Belt && destLocalDir === enumDirection.top) { + // Connected to a belt + isConnected = true; + } else { + // This one is blocked + isBlocked = true; + } + } + + const alpha = isConnected || isBlocked ? 1.0 : 0.3; + const sprite = isBlocked ? badArrowSprite : goodArrowSprite; + + parameters.context.globalAlpha = alpha; + drawRotatedSprite({ + parameters, + sprite, + x: ejectorSLotWsPos.x, + y: ejectorSLotWsPos.y, + angle: Math.radians(enumDirectionToAngle[ejectorSlotWsDirection]), + size: 13, + offsetY: offsetShift, + }); + parameters.context.globalAlpha = 1; + } } } diff --git a/src/js/game/logic.js b/src/js/game/logic.js index b28d346b..c90803cf 100644 --- a/src/js/game/logic.js +++ b/src/js/game/logic.js @@ -212,7 +212,7 @@ export class GameLogic { } if (beltComp) { - const fakeEjectorSlot = beltComp.getFakeEjectorSlots(); + const fakeEjectorSlot = beltComp.getFakeEjectorSlot(); const fakeAcceptorSlot = beltComp.getFakeAcceptorSlot(); ejectorSlots.push(fakeEjectorSlot); acceptorSlots.push(fakeAcceptorSlot);