From 6f99d494359c7923b06636b80771771dbdadf1e3 Mon Sep 17 00:00:00 2001 From: isaisstillalive Date: Tue, 30 Jun 2020 16:11:34 +0900 Subject: [PATCH] Fixed momentary movement --- src/js/game/components/chainable_splitter.js | 43 ++++++- src/js/game/systems/chainable_splitter.js | 122 +++++++++++++------ 2 files changed, 123 insertions(+), 42 deletions(-) diff --git a/src/js/game/components/chainable_splitter.js b/src/js/game/components/chainable_splitter.js index 85be13e1..91c6bca1 100644 --- a/src/js/game/components/chainable_splitter.js +++ b/src/js/game/components/chainable_splitter.js @@ -4,6 +4,8 @@ import { Component } from "../component"; import { BaseItem } from "../base_item"; import { gItemRegistry } from "../../core/global_registries"; +const receivedSize = 3; + export class ChainableSplitterComponent extends Component { static getId() { return "ChainableSplitter"; @@ -13,7 +15,13 @@ export class ChainableSplitterComponent extends Component { return { chainable: types.bool, inputItem: types.nullable(types.obj(gItemRegistry)), - ejected: types.bool, + receivedItems: types.array( + types.structured({ + item: types.obj(gItemRegistry), + distance: types.float, + }) + ), + received: types.bool, }; } @@ -26,9 +34,17 @@ export class ChainableSplitterComponent extends Component { constructor({ chainable = false }) { super(); + /** @type {boolean} */ this.chainable = chainable; + + /** @type {BaseItem} */ this.inputItem = null; - this.ejected = false; + + /** @type {Array<{ item: BaseItem, distance: number }>} */ + this.receivedItems = []; + + /** @type {boolean} */ + this.received = false; } /** @@ -43,4 +59,27 @@ export class ChainableSplitterComponent extends Component { this.inputItem = item; return true; } + + /** + * + * @param {BaseItem} item + * @param {number} distance + */ + tryReceiveItem(item, distance) { + if (this.received || this.receivedItems.length > receivedSize) { + return false; + } + + this.received = true; + this.receivedItems.push({ + item: item, + distance: distance, + }); + this.receivedItems.sort((a, b) => a.distance - b.distance); + return true; + } + + resetReceived() { + this.received = false; + } } diff --git a/src/js/game/systems/chainable_splitter.js b/src/js/game/systems/chainable_splitter.js index b033042e..b544b0d3 100644 --- a/src/js/game/systems/chainable_splitter.js +++ b/src/js/game/systems/chainable_splitter.js @@ -7,6 +7,7 @@ import { formatBigNumber, lerp } from "../../core/utils"; import { Loader } from "../../core/loader"; import { enumLayer } from "../root"; import { BaseItem } from "../base_item"; +import { globalConfig } from "../../core/config"; export class ChainableSplitterSystem extends GameSystemWithFilter { constructor(root) { @@ -14,63 +15,104 @@ export class ChainableSplitterSystem extends GameSystemWithFilter { } update() { + // Precompute effective belt speed + const effectiveBeltSpeed = this.root.hubGoals.getBeltBaseSpeed() * globalConfig.itemSpacingOnBelts; + let progressGrowth = (effectiveBeltSpeed / 0.5) * this.root.dynamicTickrate.deltaSeconds; + + if (G_IS_DEV && globalConfig.debug.instantBelts) { + progressGrowth = 1; + } + for (let i = 0; i < this.allEntities.length; ++i) { const entity = this.allEntities[i]; const splitterComp = entity.components.ChainableSplitter; - if (splitterComp.inputItem === null) { + + // First, try to get rid of received item + this.tryEject(entity, progressGrowth); + + const item = splitterComp.inputItem; + if (item === null) { continue; } - const leftEdgeEntity = this.getLeftEdgeEntity(entity); - if (this.tryEject(leftEdgeEntity, splitterComp.inputItem)) { + if (splitterComp.tryReceiveItem(item, 0)) { splitterComp.inputItem = null; + continue; } - } - } - /** - * - * @param {Entity} entity - * @returns {Entity} - */ - getLeftEdgeEntity(entity) { - const leftEntity = this.getAdjacentEntity(entity, enumDirection.left); - if (leftEntity === null || !leftEntity.components.ChainableSplitter) { - return entity; - } + let resetEntities = [entity.components.ChainableSplitter]; + let sideEntities = [ + { + direction: enumDirection.left, + entity: entity, + }, + { + direction: enumDirection.right, + entity: entity, + }, + ]; + send_loop: for (let distance = 1; ; distance++) { + for (let index = 0; index < sideEntities.length; index++) { + const sideEntity = sideEntities[index]; - return this.getLeftEdgeEntity(leftEntity); - } + sideEntity.entity = this.getAdjacentEntity(sideEntity.entity, sideEntity.direction); + let sideSplitterComp; + if ( + sideEntity.entity && + (sideSplitterComp = sideEntity.entity.components.ChainableSplitter) + ) { + if (sideSplitterComp.tryReceiveItem(item, distance)) { + splitterComp.inputItem = null; + break send_loop; + } + resetEntities.push(sideSplitterComp); + } else { + sideEntities.splice(index, 1); + index--; + } + } - /** - * - * @param {Entity} entity - * @param {BaseItem} item - * @returns {boolean} - */ - tryEject(entity, item) { - const splitterComp = entity.components.ChainableSplitter; - if (!splitterComp.ejected) { - const ejectComp = entity.components.ItemEjector; - - if (ejectComp.canEjectOnSlot(0)) { - if (ejectComp.tryEject(0, item)) { - splitterComp.ejected = true; - return true; + if (sideEntities.length == 0) { + for (let index = 0; index < resetEntities.length; index++) { + resetEntities[index].resetReceived(); + } + break; } } } + } - const rightEntity = this.getAdjacentEntity(entity, enumDirection.right); - if ( - rightEntity !== null && - rightEntity.components.ChainableSplitter && - this.tryEject(rightEntity, item) - ) { - return true; + /** + * + * @param {Entity} entity + * @param {number} progressGrowth + * @returns {boolean} + */ + tryEject(entity, progressGrowth) { + const splitterComp = entity.components.ChainableSplitter; + + if (!splitterComp || splitterComp.receivedItems.length == 0) { + return false; + } + + for (let index = 0; index < splitterComp.receivedItems.length; index++) { + const item = splitterComp.receivedItems[index]; + item.distance -= progressGrowth; + } + + const item = splitterComp.receivedItems[0]; + if (item.distance > 0) { + return false; + } + + const ejectComp = entity.components.ItemEjector; + if (ejectComp.canEjectOnSlot(0)) { + if (ejectComp.tryEject(0, item.item)) { + splitterComp.receivedItems.shift(); + return true; + } } - splitterComp.ejected = false; return false; } }