diff --git a/src/js/game/components/belt_underlays.js b/src/js/game/components/belt_underlays.js index fbd254a9..78a91edb 100644 --- a/src/js/game/components/belt_underlays.js +++ b/src/js/game/components/belt_underlays.js @@ -16,6 +16,7 @@ export const enumClippedBeltUnderlayType = { topOnly: "topOnly", topCorner: "topCorner", bottomCorner: "bottomCorner", + cornerFull: "cornerFull", none: "none", }; diff --git a/src/js/game/components/item_ejector.js b/src/js/game/components/item_ejector.js index bfc54cd8..fd5d1b61 100644 --- a/src/js/game/components/item_ejector.js +++ b/src/js/game/components/item_ejector.js @@ -1,4 +1,4 @@ -import { enumDirection, enumDirectionToVector, Vector } from "../../core/vector"; +import { enumDirection, enumDirectionToVector, enumInvertedDirections, Vector } from "../../core/vector"; import { types } from "../../savegame/serialization"; import { BaseItem } from "../base_item"; import { BeltPath } from "../belt_path"; @@ -151,4 +151,33 @@ export class ItemEjectorComponent extends Component { slot.progress = 0.0; return item; } + + /** + * Tries to find a slot which ejects the current item + * @param {Vector} targetLocalTile + * @param {enumDirection} fromLocalDirection + * @returns {ItemEjectorSlot|null} + */ + findMatchingSlot(targetLocalTile, fromLocalDirection) { + // We need to invert our direction since the ejector specifies *from* which direction + // it ejects items, but the acceptor specifies *into* which direction it accepts items. + // E.g.: Acceptor ejects into "right" direction but ejector accepts from "left" direction. + const desiredDirection = enumInvertedDirections[fromLocalDirection]; + + // Go over all slots and try to find a target slot + for (let slotIndex = 0; slotIndex < this.slots.length; ++slotIndex) { + const slot = this.slots[slotIndex]; + + // Make sure the acceptor slot is on the right position + if (!slot.pos.equals(targetLocalTile)) { + continue; + } + + if (desiredDirection === slot.direction) { + return slot; + } + } + + return null; + } } diff --git a/src/js/game/systems/belt_underlays.js b/src/js/game/systems/belt_underlays.js index a8bef57a..cd9199cb 100644 --- a/src/js/game/systems/belt_underlays.js +++ b/src/js/game/systems/belt_underlays.js @@ -31,6 +31,7 @@ const enumUnderlayTypeToClipRect = { [enumClippedBeltUnderlayType.bottomOnly]: new Rectangle(0, 0.5, 1, 0.5), [enumClippedBeltUnderlayType.topCorner]: new Rectangle(0, 0, 1, 0.04), [enumClippedBeltUnderlayType.bottomCorner]: new Rectangle(0, 0.96, 1, 0.04), + [enumClippedBeltUnderlayType.cornerFull]: new Rectangle(0, 0, 0, 0), }; export class BeltUnderlaysSystem extends GameSystemWithFilter { @@ -194,21 +195,36 @@ export class BeltUnderlaysSystem extends GameSystemWithFilter { const worldDirectionVector = enumDirectionToVector[worldDirection]; // Figure out if there is anything connected at the top - const connectedTop = this.checkIsAcceptorConnected( + let connectedTop = this.checkIsAcceptorConnected( transformedPos.add(worldDirectionVector), enumInvertedDirections[worldDirection] ); + const ejectorComp = entity.components.ItemEjector; + if (ejectorComp) { + const ejectorSlot = ejectorComp.findMatchingSlot( + underlayTile.pos, + enumInvertedDirections[underlayTile.direction] + ); + if (!ejectorSlot) connectedTop = false; + } // Figure out if there is anything connected at the bottom - const connectedBottom = this.checkIsEjectorConnected( + let connectedBottom = this.checkIsEjectorConnected( transformedPos.sub(worldDirectionVector), worldDirection ); + const acceptorComp = entity.components.ItemAcceptor; + if (acceptorComp) { + const acceptorSlot = acceptorComp.findMatchingSlot(underlayTile.pos, underlayTile.direction); + if (!acceptorSlot) connectedBottom = false; + } let flag = enumClippedBeltUnderlayType.none; if (connectedTop && connectedBottom) { - flag = enumClippedBeltUnderlayType.full; + flag = underlayTile.corner + ? enumClippedBeltUnderlayType.cornerFull + : enumClippedBeltUnderlayType.full; } else if (connectedTop) { flag = underlayTile.corner ? enumClippedBeltUnderlayType.topCorner @@ -288,16 +304,39 @@ export class BeltUnderlaysSystem extends GameSystemWithFilter { ); parameters.context.translate(x, y); parameters.context.rotate(angleRadians); - this.underlayBeltSprites[ - animationIndex % this.underlayBeltSprites.length - ].drawCachedWithClipRect( - parameters, - -globalConfig.halfTileSize, - -globalConfig.halfTileSize, - globalConfig.tileSize, - globalConfig.tileSize, - clipRect - ); + if (underlayType === enumClippedBeltUnderlayType.cornerFull) { + this.underlayBeltSprites[ + animationIndex % this.underlayBeltSprites.length + ].drawCachedWithClipRect( + parameters, + -globalConfig.halfTileSize, + -globalConfig.halfTileSize, + globalConfig.tileSize, + globalConfig.tileSize, + enumUnderlayTypeToClipRect[enumClippedBeltUnderlayType.topCorner] + ); + this.underlayBeltSprites[ + animationIndex % this.underlayBeltSprites.length + ].drawCachedWithClipRect( + parameters, + -globalConfig.halfTileSize, + -globalConfig.halfTileSize, + globalConfig.tileSize, + globalConfig.tileSize, + enumUnderlayTypeToClipRect[enumClippedBeltUnderlayType.bottomCorner] + ); + } else { + this.underlayBeltSprites[ + animationIndex % this.underlayBeltSprites.length + ].drawCachedWithClipRect( + parameters, + -globalConfig.halfTileSize, + -globalConfig.halfTileSize, + globalConfig.tileSize, + globalConfig.tileSize, + clipRect + ); + } parameters.context.rotate(-angleRadians); parameters.context.translate(-x, -y); }