1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2026-03-02 03:39:21 +00:00

Remove ejector cache; use slot caches instead

This is a small refactoring that removes the main ejector cache. The
cache is now tracked by slots and ejector components.

It avoids a large array allocation and many small object allocations,
but adds many small array allocations. It's net neutral for performance.
This commit is contained in:
Phlosioneer
2020-06-16 21:11:26 -04:00
parent b753187cde
commit 36cf28029e
2 changed files with 61 additions and 42 deletions

View File

@@ -14,15 +14,6 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
constructor(root) {
super(root, [ItemEjectorComponent]);
/**
* @type {Array<{
* targetEntity: Entity,
* sourceSlot: import("../components/item_ejector").ItemEjectorSlot,
* destSlot: import("../components/item_acceptor").ItemAcceptorLocatedSlot
* }>}
*/
this.cache = [];
this.cacheNeedsUpdate = true;
this.root.signals.entityAdded.add(this.invalidateCache, this);
@@ -39,18 +30,24 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
recomputeCache() {
logger.log("Recomputing cache");
const cache = [];
// Try to find acceptors for every ejector
let entryCount = 0;
for (let i = 0; i < this.allEntities.length; ++i) {
const entity = this.allEntities[i];
const ejectorComp = entity.components.ItemEjector;
const staticComp = entity.components.StaticMapEntity;
// Clear the old cache.
ejectorComp.cachedConnectedSlots = null;
// For every ejector slot, try to find an acceptor
for (let ejectorSlotIndex = 0; ejectorSlotIndex < ejectorComp.slots.length; ++ejectorSlotIndex) {
const ejectorSlot = ejectorComp.slots[ejectorSlotIndex];
// Clear the old cache.
ejectorSlot.cachedDestSlot = null;
ejectorSlot.cachedTargetEntity = null;
// Figure out where and into which direction we eject items
const ejectSlotWsTile = staticComp.localTileToWorld(ejectorSlot.pos);
const ejectSlotWsDirection = staticComp.localDirectionToWorld(ejectorSlot.direction);
@@ -82,16 +79,18 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
}
// Ok we found a connection
cache.push({
targetEntity,
sourceSlot: ejectorSlot,
destSlot: matchingSlot,
});
if (ejectorComp.cachedConnectedSlots) {
ejectorComp.cachedConnectedSlots.push(ejectorSlot);
} else {
ejectorComp.cachedConnectedSlots = [ejectorSlot];
}
ejectorSlot.cachedTargetEntity = targetEntity;
ejectorSlot.cachedDestSlot = matchingSlot;
entryCount += 1;
}
}
this.cache = cache;
logger.log("Found", cache.length, "entries to update");
logger.log("Found", entryCount, "entries to update");
}
update() {
@@ -109,35 +108,45 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
}
// Go over all cache entries
for (let i = 0; i < this.cache.length; ++i) {
const { sourceSlot, destSlot, targetEntity } = this.cache[i];
const item = sourceSlot.item;
if (!item) {
// No item available to be ejected
for (let i = 0; i < this.allEntities.length; ++i) {
const sourceEntity = this.allEntities[i];
const sourceEjectorComp = sourceEntity.components.ItemEjector;
if (!sourceEjectorComp.cachedConnectedSlots) {
continue;
}
for (let j = 0; j < sourceEjectorComp.cachedConnectedSlots.length; j++) {
const sourceSlot = sourceEjectorComp.cachedConnectedSlots[j];
const destSlot = sourceSlot.cachedDestSlot;
const targetEntity = sourceSlot.cachedTargetEntity;
// Advance items on the slot
sourceSlot.progress = Math_min(1, sourceSlot.progress + progressGrowth);
const item = sourceSlot.item;
// Check if we are still in the process of ejecting, can't proceed then
if (sourceSlot.progress < 1.0) {
continue;
}
if (!item) {
// No item available to be ejected
continue;
}
// Check if the target acceptor can actually accept this item
const targetAcceptorComp = targetEntity.components.ItemAcceptor;
if (!targetAcceptorComp.canAcceptItem(destSlot.index, item)) {
continue;
}
// Advance items on the slot
sourceSlot.progress = Math_min(1, sourceSlot.progress + progressGrowth);
// Try to hand over the item
if (this.tryPassOverItem(item, targetEntity, destSlot.index)) {
// Handover successful, clear slot
targetAcceptorComp.onItemAccepted(destSlot.index, destSlot.acceptedDirection, item);
sourceSlot.item = null;
continue;
// Check if we are still in the process of ejecting, can't proceed then
if (sourceSlot.progress < 1.0) {
continue;
}
// Check if the target acceptor can actually accept this item
const targetAcceptorComp = targetEntity.components.ItemAcceptor;
if (!targetAcceptorComp.canAcceptItem(destSlot.index, item)) {
continue;
}
// Try to hand over the item
if (this.tryPassOverItem(item, targetEntity, destSlot.index)) {
// Handover successful, clear slot
targetAcceptorComp.onItemAccepted(destSlot.index, destSlot.acceptedDirection, item);
sourceSlot.item = null;
continue;
}
}
}
}