From 83a4928be55e41151c7fec2aa2c89b8f5202e747 Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Tue, 16 Jun 2020 16:02:29 -0400 Subject: [PATCH 1/3] Make miners cache mined item Saves two chunk+tile lookups per update, and one chunk+tile lookup per draw. --- src/js/game/buildings/miner.js | 10 ++++++++-- src/js/game/components/miner.js | 11 ++++++++++- src/js/game/systems/miner.js | 33 ++++++++------------------------- 3 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/js/game/buildings/miner.js b/src/js/game/buildings/miner.js index ed87bc85..2baf3fd4 100644 --- a/src/js/game/buildings/miner.js +++ b/src/js/game/buildings/miner.js @@ -44,9 +44,15 @@ export class MetaMinerBuilding extends MetaBuilding { /** * Creates the entity at the given location * @param {Entity} entity + * @param {GameRoot} root */ - setupEntityComponents(entity) { - entity.addComponent(new MinerComponent({})); + setupEntityComponents(entity, root) { + let itemBelow = null; + if (root) { + const staticComp = entity.components.StaticMapEntity; + itemBelow = root.map.getLowerLayerContentXY(staticComp.origin.x, staticComp.origin.y); + } + entity.addComponent(new MinerComponent({ minedItem: itemBelow })); entity.addComponent( new ItemEjectorComponent({ slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }], diff --git a/src/js/game/components/miner.js b/src/js/game/components/miner.js index 57de7e2f..7a4d77dd 100644 --- a/src/js/game/components/miner.js +++ b/src/js/game/components/miner.js @@ -15,6 +15,7 @@ export class MinerComponent extends Component { return { lastMiningTime: types.ufloat, chainable: types.bool, + minedItem: types.nullable(types.obj(gItemRegistry)), itemChainBuffer: types.array(types.obj(gItemRegistry)), }; } @@ -22,12 +23,15 @@ export class MinerComponent extends Component { duplicateWithoutContents() { return new MinerComponent({ chainable: this.chainable, + minedItem: this.minedItem }); } /** + * + * @param {{chainable?: boolean, minedItem?: BaseItem}} param0 */ - constructor({ chainable = false }) { + constructor({ chainable = false, minedItem = null }) { super(); this.lastMiningTime = 0; this.chainable = chainable; @@ -38,6 +42,11 @@ export class MinerComponent extends Component { * @type {Array} */ this.itemChainBuffer = []; + + /** + * @type {BaseItem} + */ + this.minedItem = minedItem; } /** diff --git a/src/js/game/systems/miner.js b/src/js/game/systems/miner.js index 78223516..41786603 100644 --- a/src/js/game/systems/miner.js +++ b/src/js/game/systems/miner.js @@ -24,10 +24,8 @@ export class MinerSystem extends GameSystemWithFilter { // Check if miner is above an actual tile const minerComp = entity.components.Miner; - const staticComp = entity.components.StaticMapEntity; - const tileBelow = this.root.map.getLowerLayerContentXY(staticComp.origin.x, staticComp.origin.y); - if (!tileBelow) { + if (!minerComp.minedItem) { continue; } @@ -40,20 +38,9 @@ export class MinerSystem extends GameSystemWithFilter { } if (this.root.time.isIngameTimerExpired(minerComp.lastMiningTime, 1 / miningSpeed)) { - const lowerLayerItem = this.root.map.getLowerLayerContentXY( - staticComp.origin.x, - staticComp.origin.y - ); - - // TODO: Should not be required actually - if (!lowerLayerItem) { - // Nothing below; - continue; - } - - if (this.tryPerformMinerEject(entity, lowerLayerItem)) { + if (this.tryPerformMinerEject(entity, minerComp.minedItem)) { // Analytics hook - this.root.signals.itemProduced.dispatch(lowerLayerItem); + this.root.signals.itemProduced.dispatch(minerComp.minedItem); // Actually mine minerComp.lastMiningTime = this.root.time.now(); @@ -114,18 +101,14 @@ export class MinerSystem extends GameSystemWithFilter { if (entity && entity.components.Miner) { const staticComp = entity.components.StaticMapEntity; + const minerComp = entity.components.Miner; if (!staticComp.shouldBeDrawn(parameters)) { continue; } - const lowerLayerItem = this.root.map.getLowerLayerContentXY( - staticComp.origin.x, - staticComp.origin.y - ); - - if (lowerLayerItem) { + if (minerComp.minedItem) { const padding = 3; - parameters.context.fillStyle = lowerLayerItem.getBackgroundColorAsResource(); + parameters.context.fillStyle = minerComp.minedItem.getBackgroundColorAsResource(); parameters.context.fillRect( staticComp.origin.x * globalConfig.tileSize + padding, staticComp.origin.y * globalConfig.tileSize + padding, @@ -134,8 +117,8 @@ export class MinerSystem extends GameSystemWithFilter { ); } - if (lowerLayerItem) { - lowerLayerItem.draw( + if (minerComp.minedItem) { + minerComp.minedItem.draw( (0.5 + staticComp.origin.x) * globalConfig.tileSize, (0.5 + staticComp.origin.y) * globalConfig.tileSize, parameters From d4fc2e6dcde2239d86a609756273b53e2b52d437 Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Tue, 16 Jun 2020 16:21:45 -0400 Subject: [PATCH 2/3] Fix lint errors --- src/js/game/components/miner.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/js/game/components/miner.js b/src/js/game/components/miner.js index 7a4d77dd..ae64223a 100644 --- a/src/js/game/components/miner.js +++ b/src/js/game/components/miner.js @@ -23,13 +23,12 @@ export class MinerComponent extends Component { duplicateWithoutContents() { return new MinerComponent({ chainable: this.chainable, - minedItem: this.minedItem + minedItem: this.minedItem, }); } /** - * - * @param {{chainable?: boolean, minedItem?: BaseItem}} param0 + * @param {{chainable?: boolean, minedItem?: BaseItem}} param0 */ constructor({ chainable = false, minedItem = null }) { super(); From f15cd5bcffbbdd27332e1ff6c4a68e8f860e6947 Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Wed, 17 Jun 2020 15:36:53 -0400 Subject: [PATCH 3/3] Rework to cache instead of serialize Using lessons from other PRs --- src/js/game/buildings/miner.js | 10 ++-------- src/js/game/components/miner.js | 10 +++------- src/js/game/systems/miner.js | 27 +++++++++++++++++++-------- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/js/game/buildings/miner.js b/src/js/game/buildings/miner.js index 2baf3fd4..ed87bc85 100644 --- a/src/js/game/buildings/miner.js +++ b/src/js/game/buildings/miner.js @@ -44,15 +44,9 @@ export class MetaMinerBuilding extends MetaBuilding { /** * Creates the entity at the given location * @param {Entity} entity - * @param {GameRoot} root */ - setupEntityComponents(entity, root) { - let itemBelow = null; - if (root) { - const staticComp = entity.components.StaticMapEntity; - itemBelow = root.map.getLowerLayerContentXY(staticComp.origin.x, staticComp.origin.y); - } - entity.addComponent(new MinerComponent({ minedItem: itemBelow })); + setupEntityComponents(entity) { + entity.addComponent(new MinerComponent({})); entity.addComponent( new ItemEjectorComponent({ slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }], diff --git a/src/js/game/components/miner.js b/src/js/game/components/miner.js index ae64223a..74a4b616 100644 --- a/src/js/game/components/miner.js +++ b/src/js/game/components/miner.js @@ -12,10 +12,10 @@ export class MinerComponent extends Component { } static getSchema() { + // cachedMinedItem is not serialized. return { lastMiningTime: types.ufloat, chainable: types.bool, - minedItem: types.nullable(types.obj(gItemRegistry)), itemChainBuffer: types.array(types.obj(gItemRegistry)), }; } @@ -23,14 +23,10 @@ export class MinerComponent extends Component { duplicateWithoutContents() { return new MinerComponent({ chainable: this.chainable, - minedItem: this.minedItem, }); } - /** - * @param {{chainable?: boolean, minedItem?: BaseItem}} param0 - */ - constructor({ chainable = false, minedItem = null }) { + constructor({ chainable = false }) { super(); this.lastMiningTime = 0; this.chainable = chainable; @@ -45,7 +41,7 @@ export class MinerComponent extends Component { /** * @type {BaseItem} */ - this.minedItem = minedItem; + this.cachedMinedItem = null; } /** diff --git a/src/js/game/systems/miner.js b/src/js/game/systems/miner.js index 41786603..b195e6ab 100644 --- a/src/js/game/systems/miner.js +++ b/src/js/game/systems/miner.js @@ -25,8 +25,16 @@ export class MinerSystem extends GameSystemWithFilter { const minerComp = entity.components.Miner; - if (!minerComp.minedItem) { - continue; + if (!minerComp.cachedMinedItem) { + const staticComp = entity.components.StaticMapEntity; + const tileBelow = this.root.map.getLowerLayerContentXY( + staticComp.origin.x, + staticComp.origin.y + ); + if (!tileBelow) { + continue; + } + minerComp.cachedMinedItem = tileBelow; } // First, try to get rid of chained items @@ -38,9 +46,9 @@ export class MinerSystem extends GameSystemWithFilter { } if (this.root.time.isIngameTimerExpired(minerComp.lastMiningTime, 1 / miningSpeed)) { - if (this.tryPerformMinerEject(entity, minerComp.minedItem)) { + if (this.tryPerformMinerEject(entity, minerComp.cachedMinedItem)) { // Analytics hook - this.root.signals.itemProduced.dispatch(minerComp.minedItem); + this.root.signals.itemProduced.dispatch(minerComp.cachedMinedItem); // Actually mine minerComp.lastMiningTime = this.root.time.now(); @@ -105,10 +113,13 @@ export class MinerSystem extends GameSystemWithFilter { if (!staticComp.shouldBeDrawn(parameters)) { continue; } + if (!minerComp.cachedMinedItem) { + continue; + } - if (minerComp.minedItem) { + if (minerComp.cachedMinedItem) { const padding = 3; - parameters.context.fillStyle = minerComp.minedItem.getBackgroundColorAsResource(); + parameters.context.fillStyle = minerComp.cachedMinedItem.getBackgroundColorAsResource(); parameters.context.fillRect( staticComp.origin.x * globalConfig.tileSize + padding, staticComp.origin.y * globalConfig.tileSize + padding, @@ -117,8 +128,8 @@ export class MinerSystem extends GameSystemWithFilter { ); } - if (minerComp.minedItem) { - minerComp.minedItem.draw( + if (minerComp.cachedMinedItem) { + minerComp.cachedMinedItem.draw( (0.5 + staticComp.origin.x) * globalConfig.tileSize, (0.5 + staticComp.origin.y) * globalConfig.tileSize, parameters