Take 3 on the belt performance (+ tslint fixes)

This commit is contained in:
tobspr 2020-06-26 17:02:52 +02:00
parent 9ce912dbdd
commit a71c0b8039
8 changed files with 249 additions and 221 deletions

View File

@ -19,7 +19,7 @@ export class FormElement {
abstract; abstract;
} }
focus(parent) {} focus() {}
isValid() { isValid() {
return true; return true;

View File

@ -72,6 +72,7 @@ function objectPolyfills() {
} }
if (!Object.entries) { if (!Object.entries) {
// @ts-ignore
Object.entries = function entries(O) { Object.entries = function entries(O) {
return reduce( return reduce(
keys(O), keys(O),

View File

@ -405,8 +405,6 @@ export function findNiceValue(num) {
return Math_round(niceValue * 100) / 100; return Math_round(niceValue * 100) / 100;
} }
window.fn = findNiceValue;
/** /**
* Finds a nice integer value * Finds a nice integer value
* @see findNiceValue * @see findNiceValue

View File

@ -14,6 +14,8 @@ const logger = createLogger("belt_path");
const _nextDistance = 0; const _nextDistance = 0;
const _item = 1; const _item = 1;
const DEBUG = G_IS_DEV && false;
/** /**
* Stores a path of belts, used for optimizing performance * Stores a path of belts, used for optimizing performance
*/ */
@ -204,7 +206,7 @@ export class BeltPath {
* @param {Entity} entity * @param {Entity} entity
*/ */
extendOnEnd(entity) { extendOnEnd(entity) {
logger.log("Extending belt path by entity at", entity.components.StaticMapEntity.origin); DEBUG && logger.log("Extending belt path by entity at", entity.components.StaticMapEntity.origin);
const beltComp = entity.components.Belt; const beltComp = entity.components.Belt;
@ -212,7 +214,7 @@ export class BeltPath {
const pendingItem = this.ejectorComp.takeSlotItem(0); const pendingItem = this.ejectorComp.takeSlotItem(0);
if (pendingItem) { if (pendingItem) {
// Ok, so we have a pending item // Ok, so we have a pending item
logger.log("Taking pending item and putting it back on the path"); DEBUG && logger.log("Taking pending item and putting it back on the path");
this.items.push([0, pendingItem]); this.items.push([0, pendingItem]);
} }
@ -222,21 +224,22 @@ export class BeltPath {
// Extend the path length // Extend the path length
const additionalLength = beltComp.getEffectiveLengthTiles(); const additionalLength = beltComp.getEffectiveLengthTiles();
this.totalLength += additionalLength; this.totalLength += additionalLength;
logger.log(" Extended total length by", additionalLength, "to", this.totalLength); DEBUG && logger.log(" Extended total length by", additionalLength, "to", this.totalLength);
// If we have no item, just update the distance to the first item // If we have no item, just update the distance to the first item
if (this.items.length === 0) { if (this.items.length === 0) {
this.spacingToFirstItem = this.totalLength; this.spacingToFirstItem = this.totalLength;
logger.log(" Extended spacing to first to", this.totalLength, "(= total length)"); DEBUG && logger.log(" Extended spacing to first to", this.totalLength, "(= total length)");
} else { } else {
// Otherwise, update the next-distance of the last item // Otherwise, update the next-distance of the last item
const lastItem = this.items[this.items.length - 1]; const lastItem = this.items[this.items.length - 1];
logger.log( DEBUG &&
" Extended spacing of last item from", logger.log(
lastItem[_nextDistance], " Extended spacing of last item from",
"to", lastItem[_nextDistance],
lastItem[_nextDistance] + additionalLength "to",
); lastItem[_nextDistance] + additionalLength
);
lastItem[_nextDistance] += additionalLength; lastItem[_nextDistance] += additionalLength;
} }
@ -257,7 +260,7 @@ export class BeltPath {
extendOnBeginning(entity) { extendOnBeginning(entity) {
const beltComp = entity.components.Belt; const beltComp = entity.components.Belt;
logger.log("Extending the path on the beginning"); DEBUG && logger.log("Extending the path on the beginning");
// All items on that belt are simply lost (for now) // All items on that belt are simply lost (for now)
@ -277,6 +280,24 @@ export class BeltPath {
this.debug_checkIntegrity("extend-on-begin"); this.debug_checkIntegrity("extend-on-begin");
} }
/**
* Returns if the given entity is the end entity of the path
* @param {Entity} entity
* @returns {boolean}
*/
isEndEntity(entity) {
return this.entityPath[this.entityPath.length - 1] === entity;
}
/**
* Returns if the given entity is the start entity of the path
* @param {Entity} entity
* @returns {boolean}
*/
isStartEntity(entity) {
return this.entityPath[0] === entity;
}
/** /**
* Splits this path at the given entity by removing it, and * Splits this path at the given entity by removing it, and
* returning the new secondary paht * returning the new secondary paht
@ -284,7 +305,7 @@ export class BeltPath {
* @returns {BeltPath} * @returns {BeltPath}
*/ */
deleteEntityOnPathSplitIntoTwo(entity) { deleteEntityOnPathSplitIntoTwo(entity) {
logger.log("Splitting path at entity", entity.components.StaticMapEntity.origin); DEBUG && logger.log("Splitting path at entity", entity.components.StaticMapEntity.origin);
// First, find where the current path ends // First, find where the current path ends
const beltComp = entity.components.Belt; const beltComp = entity.components.Belt;
@ -302,7 +323,7 @@ export class BeltPath {
for (let i = 0; i < this.entityPath.length; ++i) { for (let i = 0; i < this.entityPath.length; ++i) {
const otherEntity = this.entityPath[i]; const otherEntity = this.entityPath[i];
if (otherEntity === entity) { if (otherEntity === entity) {
logger.log("Found entity at", i, "of length", firstPathLength); DEBUG && logger.log("Found entity at", i, "of length", firstPathLength);
break; break;
} }
@ -311,38 +332,41 @@ export class BeltPath {
firstPathLength += otherEntity.components.Belt.getEffectiveLengthTiles(); firstPathLength += otherEntity.components.Belt.getEffectiveLengthTiles();
} }
logger.log( DEBUG &&
"First path ends at", logger.log(
firstPathLength, "First path ends at",
"and entity", firstPathLength,
firstPathEndEntity.components.StaticMapEntity.origin, "and entity",
"and has", firstPathEndEntity.components.StaticMapEntity.origin,
firstPathEntityCount, "and has",
"entities" firstPathEntityCount,
); "entities"
);
// Compute length of second path // Compute length of second path
const secondPathLength = this.totalLength - firstPathLength - entityLength; const secondPathLength = this.totalLength - firstPathLength - entityLength;
const secondPathStart = firstPathLength + entityLength; const secondPathStart = firstPathLength + entityLength;
const secondEntities = this.entityPath.splice(firstPathEntityCount + 1); const secondEntities = this.entityPath.splice(firstPathEntityCount + 1);
logger.log( DEBUG &&
"Second path starts at", logger.log(
secondPathStart, "Second path starts at",
"and has a length of ", secondPathStart,
secondPathLength, "and has a length of ",
"with", secondPathLength,
secondEntities.length, "with",
"entities" secondEntities.length,
); "entities"
);
// Remove the last item // Remove the last item
this.entityPath.pop(); this.entityPath.pop();
logger.log("Splitting", this.items.length, "items"); DEBUG && logger.log("Splitting", this.items.length, "items");
logger.log( DEBUG &&
"Old items are", logger.log(
this.items.map(i => i[_nextDistance]) "Old items are",
); this.items.map(i => i[_nextDistance])
);
// Create second path // Create second path
const secondPath = new BeltPath(this.root, secondEntities); const secondPath = new BeltPath(this.root, secondEntities);
@ -353,45 +377,48 @@ export class BeltPath {
const item = this.items[i]; const item = this.items[i];
const distanceToNext = item[_nextDistance]; const distanceToNext = item[_nextDistance];
logger.log(" Checking item at", itemPos, "with distance of", distanceToNext, "to next"); DEBUG && logger.log(" Checking item at", itemPos, "with distance of", distanceToNext, "to next");
// Check if this item is past the first path // Check if this item is past the first path
if (itemPos >= firstPathLength) { if (itemPos >= firstPathLength) {
// Remove it from the first path // Remove it from the first path
this.items.splice(i, 1); this.items.splice(i, 1);
i -= 1; i -= 1;
logger.log(" Removed item from first path since its no longer contained @", itemPos); DEBUG &&
logger.log(" Removed item from first path since its no longer contained @", itemPos);
// Check if its on the second path (otherwise its on the removed belt and simply lost) // Check if its on the second path (otherwise its on the removed belt and simply lost)
if (itemPos >= secondPathStart) { if (itemPos >= secondPathStart) {
// Put item on second path // Put item on second path
secondPath.items.push([distanceToNext, item[_item]]); secondPath.items.push([distanceToNext, item[_item]]);
logger.log( DEBUG &&
" Put item to second path @", logger.log(
itemPos, " Put item to second path @",
"with distance to next =", itemPos,
distanceToNext "with distance to next =",
); distanceToNext
);
// If it was the first item, adjust the distance to the first item // If it was the first item, adjust the distance to the first item
if (secondPath.items.length === 1) { if (secondPath.items.length === 1) {
logger.log(" Sinc it was the first, set sapcing of first to", itemPos); DEBUG && logger.log(" Sinc it was the first, set sapcing of first to", itemPos);
secondPath.spacingToFirstItem = itemPos - secondPathStart; secondPath.spacingToFirstItem = itemPos - secondPathStart;
} }
} else { } else {
logger.log(" Item was on the removed belt, so its gone - forever!"); DEBUG && logger.log(" Item was on the removed belt, so its gone - forever!");
} }
} else { } else {
// Seems this item is on the first path (so all good), so just make sure it doesn't // Seems this item is on the first path (so all good), so just make sure it doesn't
// have a nextDistance which is bigger than the total path length // have a nextDistance which is bigger than the total path length
const clampedDistanceToNext = Math_min(itemPos + distanceToNext, firstPathLength) - itemPos; const clampedDistanceToNext = Math_min(itemPos + distanceToNext, firstPathLength) - itemPos;
if (clampedDistanceToNext < distanceToNext) { if (clampedDistanceToNext < distanceToNext) {
logger.log( DEBUG &&
"Correcting next distance (first path) from", logger.log(
distanceToNext, "Correcting next distance (first path) from",
"to", distanceToNext,
clampedDistanceToNext "to",
); clampedDistanceToNext
);
item[_nextDistance] = clampedDistanceToNext; item[_nextDistance] = clampedDistanceToNext;
} }
} }
@ -400,15 +427,17 @@ export class BeltPath {
itemPos += distanceToNext; itemPos += distanceToNext;
} }
logger.log( DEBUG &&
"New items are", logger.log(
this.items.map(i => i[_nextDistance]) "New items are",
); this.items.map(i => i[_nextDistance])
);
logger.log( DEBUG &&
"And second path items are", logger.log(
secondPath.items.map(i => i[_nextDistance]) "And second path items are",
); secondPath.items.map(i => i[_nextDistance])
);
// Adjust our total length // Adjust our total length
this.totalLength = firstPathLength; this.totalLength = firstPathLength;
@ -433,25 +462,36 @@ export class BeltPath {
* @param {Entity} entity * @param {Entity} entity
*/ */
deleteEntityOnEnd(entity) { deleteEntityOnEnd(entity) {
assert(this.entityPath[this.entityPath.length - 1] === entity, "Not the last entity actually"); assert(
this.entityPath[this.entityPath.length - 1] === entity,
"Not actually the last entity (instead " + this.entityPath.indexOf(entity) + ")"
);
// Ok, first remove the entity // Ok, first remove the entity
const beltComp = entity.components.Belt; const beltComp = entity.components.Belt;
const beltLength = beltComp.getEffectiveLengthTiles(); const beltLength = beltComp.getEffectiveLengthTiles();
logger.log( DEBUG &&
"Deleting last entity on path with length", logger.log(
this.entityPath.length, "Deleting last entity on path with length",
"(reducing", this.entityPath.length,
this.totalLength, "(reducing",
" by", this.totalLength,
beltLength, " by",
")" beltLength,
); ")"
);
this.totalLength -= beltLength; this.totalLength -= beltLength;
this.entityPath.pop(); this.entityPath.pop();
logger.log(" New path has length of", this.totalLength, "with", this.entityPath.length, "entities"); DEBUG &&
logger.log(
" New path has length of",
this.totalLength,
"with",
this.entityPath.length,
"entities"
);
// This is just for sanity // This is just for sanity
beltComp.assignedPath = null; beltComp.assignedPath = null;
@ -465,20 +505,20 @@ export class BeltPath {
let itemOffset = this.spacingToFirstItem; let itemOffset = this.spacingToFirstItem;
let lastItemOffset = itemOffset; let lastItemOffset = itemOffset;
logger.log(" Adjusting", this.items.length, "items"); DEBUG && logger.log(" Adjusting", this.items.length, "items");
for (let i = 0; i < this.items.length; ++i) { for (let i = 0; i < this.items.length; ++i) {
const item = this.items[i]; const item = this.items[i];
// Get rid of items past this path // Get rid of items past this path
if (itemOffset >= this.totalLength) { if (itemOffset >= this.totalLength) {
logger.log("Dropping item (current index=", i, ")"); DEBUG && logger.log("Dropping item (current index=", i, ")");
this.items.splice(i, 1); this.items.splice(i, 1);
i -= 1; i -= 1;
continue; continue;
} }
logger.log("Item", i, "is at", itemOffset, "with next offset", item[_nextDistance]); DEBUG && logger.log("Item", i, "is at", itemOffset, "with next offset", item[_nextDistance]);
lastItemOffset = itemOffset; lastItemOffset = itemOffset;
itemOffset += item[_nextDistance]; itemOffset += item[_nextDistance];
} }
@ -497,18 +537,19 @@ export class BeltPath {
lastItemOffset lastItemOffset
); );
logger.log( DEBUG &&
"Adjusted distance of last item: it is at", logger.log(
lastItemOffset, "Adjusted distance of last item: it is at",
"so it has a distance of", lastItemOffset,
lastDistance, "so it has a distance of",
"to the end (", lastDistance,
this.totalLength, "to the end (",
")" this.totalLength,
); ")"
);
this.items[this.items.length - 1][_nextDistance] = lastDistance; this.items[this.items.length - 1][_nextDistance] = lastDistance;
} else { } else {
logger.log(" Removed all items so we'll update spacing to total length"); DEBUG && logger.log(" Removed all items so we'll update spacing to total length");
// We removed all items so update our spacing // We removed all items so update our spacing
this.spacingToFirstItem = this.totalLength; this.spacingToFirstItem = this.totalLength;
@ -528,25 +569,36 @@ export class BeltPath {
* @param {Entity} entity * @param {Entity} entity
*/ */
deleteEntityOnStart(entity) { deleteEntityOnStart(entity) {
assert(entity === this.entityPath[0], "Not actually the start entity"); assert(
entity === this.entityPath[0],
"Not actually the start entity (instead " + this.entityPath.indexOf(entity) + ")"
);
// Ok, first remove the entity // Ok, first remove the entity
const beltComp = entity.components.Belt; const beltComp = entity.components.Belt;
const beltLength = beltComp.getEffectiveLengthTiles(); const beltLength = beltComp.getEffectiveLengthTiles();
logger.log( DEBUG &&
"Deleting first entity on path with length", logger.log(
this.entityPath.length, "Deleting first entity on path with length",
"(reducing", this.entityPath.length,
this.totalLength, "(reducing",
" by", this.totalLength,
beltLength, " by",
")" beltLength,
); ")"
);
this.totalLength -= beltLength; this.totalLength -= beltLength;
this.entityPath.shift(); this.entityPath.shift();
logger.log(" New path has length of", this.totalLength, "with", this.entityPath.length, "entities"); DEBUG &&
logger.log(
" New path has length of",
this.totalLength,
"with",
this.entityPath.length,
"entities"
);
// This is just for sanity // This is just for sanity
beltComp.assignedPath = null; beltComp.assignedPath = null;
@ -558,41 +610,45 @@ export class BeltPath {
} else { } else {
// Simple case, we had no item on the beginning -> all good // Simple case, we had no item on the beginning -> all good
if (this.spacingToFirstItem >= beltLength) { if (this.spacingToFirstItem >= beltLength) {
logger.log( DEBUG &&
" No item on the first place, so we can just adjust the spacing (spacing=", logger.log(
this.spacingToFirstItem, " No item on the first place, so we can just adjust the spacing (spacing=",
") removed =", this.spacingToFirstItem,
beltLength ") removed =",
); beltLength
);
this.spacingToFirstItem -= beltLength; this.spacingToFirstItem -= beltLength;
} else { } else {
// Welp, okay we need to drop all items which are < beltLength and adjust // Welp, okay we need to drop all items which are < beltLength and adjust
// the other item offsets as well // the other item offsets as well
logger.log( DEBUG &&
" We have at least one item in the beginning, drop those and adjust spacing (first item @", logger.log(
this.spacingToFirstItem, " We have at least one item in the beginning, drop those and adjust spacing (first item @",
") since we removed", this.spacingToFirstItem,
beltLength, ") since we removed",
"length from path" beltLength,
); "length from path"
logger.log( );
" Items:", DEBUG &&
this.items.map(i => i[_nextDistance]) logger.log(
); " Items:",
this.items.map(i => i[_nextDistance])
);
// Find offset to first item // Find offset to first item
let itemOffset = this.spacingToFirstItem; let itemOffset = this.spacingToFirstItem;
for (let i = 0; i < this.items.length; ++i) { for (let i = 0; i < this.items.length; ++i) {
const item = this.items[i]; const item = this.items[i];
if (itemOffset <= beltLength) { if (itemOffset <= beltLength) {
logger.log( DEBUG &&
" -> Dropping item with index", logger.log(
i, " -> Dropping item with index",
"at", i,
itemOffset, "at",
"since it was on the removed belt" itemOffset,
); "since it was on the removed belt"
);
// This item must be dropped // This item must be dropped
this.items.splice(i, 1); this.items.splice(i, 1);
i -= 1; i -= 1;
@ -605,13 +661,14 @@ export class BeltPath {
} }
if (this.items.length > 0) { if (this.items.length > 0) {
logger.log( DEBUG &&
" Offset of first non-dropped item was at:", logger.log(
itemOffset, " Offset of first non-dropped item was at:",
"-> setting spacing to it (total length=", itemOffset,
this.totalLength, "-> setting spacing to it (total length=",
")" this.totalLength,
); ")"
);
this.spacingToFirstItem = itemOffset - beltLength; this.spacingToFirstItem = itemOffset - beltLength;
assert( assert(
@ -619,7 +676,7 @@ export class BeltPath {
"Invalid spacing after delete on start: " + this.spacingToFirstItem "Invalid spacing after delete on start: " + this.spacingToFirstItem
); );
} else { } else {
logger.log(" We dropped all items, simply set spacing to total length"); DEBUG && logger.log(" We dropped all items, simply set spacing to total length");
// We dropped all items, simple one // We dropped all items, simple one
this.spacingToFirstItem = this.totalLength; this.spacingToFirstItem = this.totalLength;
} }
@ -640,11 +697,11 @@ export class BeltPath {
assert(otherPath !== this, "Circular path dependency"); assert(otherPath !== this, "Circular path dependency");
const entities = otherPath.entityPath; const entities = otherPath.entityPath;
logger.log("Extending path by other path, starting to add entities"); DEBUG && logger.log("Extending path by other path, starting to add entities");
const oldLength = this.totalLength; const oldLength = this.totalLength;
logger.log(" Adding", entities.length, "new entities, current length =", this.totalLength); DEBUG && logger.log(" Adding", entities.length, "new entities, current length =", this.totalLength);
// First, append entities // First, append entities
for (let i = 0; i < entities.length; ++i) { for (let i = 0; i < entities.length; ++i) {
@ -660,7 +717,13 @@ export class BeltPath {
this.totalLength += additionalLength; this.totalLength += additionalLength;
} }
logger.log(" Path is now", this.entityPath.length, "entities and has a length of", this.totalLength); DEBUG &&
logger.log(
" Path is now",
this.entityPath.length,
"entities and has a length of",
this.totalLength
);
// Update handles // Update handles
this.ejectorComp = this.entityPath[this.entityPath.length - 1].components.ItemEjector; this.ejectorComp = this.entityPath[this.entityPath.length - 1].components.ItemEjector;
@ -670,21 +733,23 @@ export class BeltPath {
if (this.items.length !== 0) { if (this.items.length !== 0) {
const lastItem = this.items[this.items.length - 1]; const lastItem = this.items[this.items.length - 1];
lastItem[_nextDistance] += otherPath.spacingToFirstItem; lastItem[_nextDistance] += otherPath.spacingToFirstItem;
logger.log(" Add distance to last item, effectively being", lastItem[_nextDistance], "now"); DEBUG &&
logger.log(" Add distance to last item, effectively being", lastItem[_nextDistance], "now");
} else { } else {
// Seems we have no items, update our first item distance // Seems we have no items, update our first item distance
this.spacingToFirstItem = oldLength + otherPath.spacingToFirstItem; this.spacingToFirstItem = oldLength + otherPath.spacingToFirstItem;
logger.log( DEBUG &&
" We had no items, so our new spacing to first is old length (", logger.log(
oldLength, " We had no items, so our new spacing to first is old length (",
") plus others spacing to first (", oldLength,
otherPath.spacingToFirstItem, ") plus others spacing to first (",
") =", otherPath.spacingToFirstItem,
this.spacingToFirstItem ") =",
); this.spacingToFirstItem
);
} }
logger.log(" Pushing", otherPath.items.length, "items from other path"); DEBUG && logger.log(" Pushing", otherPath.items.length, "items from other path");
// Aaand push the other paths items // Aaand push the other paths items
for (let i = 0; i < otherPath.items.length; ++i) { for (let i = 0; i < otherPath.items.length; ++i) {

View File

@ -1,13 +1,13 @@
import { DrawParameters } from "../../../core/draw_parameters"; import { DrawParameters } from "../core/draw_parameters";
import { Loader } from "../../../core/loader"; import { Loader } from "../core/loader";
import { createLogger } from "../../../core/logging"; import { createLogger } from "../core/logging";
import { Vector } from "../../../core/vector"; import { Vector } from "../core/vector";
import { Entity } from "../../entity"; import { Entity } from "./entity";
import { GameRoot } from "../../root"; import { GameRoot } from "./root";
import { findNiceIntegerValue } from "../../../core/utils"; import { findNiceIntegerValue } from "../core/utils";
import { Math_pow } from "../../../core/builtins"; import { Math_pow } from "../core/builtins";
import { blueprintShape } from "../../upgrades"; import { blueprintShape } from "./upgrades";
import { globalConfig } from "../../../core/config"; import { globalConfig } from "../core/config";
const logger = createLogger("blueprint"); const logger = createLogger("blueprint");
@ -176,7 +176,6 @@ export class Blueprint {
tryPlace(root, tile) { tryPlace(root, tile) {
return root.logic.performBulkOperation(() => { return root.logic.performBulkOperation(() => {
let anyPlaced = false; let anyPlaced = false;
const beltsToRegisterLater = [];
for (let i = 0; i < this.entities.length; ++i) { for (let i = 0; i < this.entities.length; ++i) {
let placeable = true; let placeable = true;
const entity = this.entities[i]; const entity = this.entities[i];
@ -217,21 +216,10 @@ export class Blueprint {
root.map.placeStaticEntity(clone); root.map.placeStaticEntity(clone);
// Registering a belt immediately triggers a recalculation of surrounding belt root.entityMgr.registerEntity(clone);
// directions, which is no good when not all belts have been placed. To resolve
// this, only register belts after all entities have been placed.
if (!clone.components.Belt) {
root.entityMgr.registerEntity(clone);
} else {
beltsToRegisterLater.push(clone);
}
anyPlaced = true; anyPlaced = true;
} }
} }
for (let i = 0; i < beltsToRegisterLater.length; i++) {
root.entityMgr.registerEntity(beltsToRegisterLater[i]);
}
return anyPlaced; return anyPlaced;
}); });
} }

View File

@ -9,7 +9,7 @@ import { KEYMAPPINGS } from "../../key_action_mapper";
import { blueprintShape } from "../../upgrades"; import { blueprintShape } from "../../upgrades";
import { BaseHUDPart } from "../base_hud_part"; import { BaseHUDPart } from "../base_hud_part";
import { DynamicDomAttach } from "../dynamic_dom_attach"; import { DynamicDomAttach } from "../dynamic_dom_attach";
import { Blueprint } from "./blueprint"; import { Blueprint } from "../../blueprint";
import { SOUNDS } from "../../../platform/sound"; import { SOUNDS } from "../../../platform/sound";
export class HUDBlueprintPlacer extends BaseHUDPart { export class HUDBlueprintPlacer extends BaseHUDPart {

View File

@ -196,7 +196,7 @@ export class GameLogic {
* @param {function} operation * @param {function} operation
*/ */
performBulkOperation(operation) { performBulkOperation(operation) {
logger.log("Running bulk operation ..."); logger.warn("Running bulk operation ...");
assert(!this.root.bulkOperationRunning, "Can not run two bulk operations twice"); assert(!this.root.bulkOperationRunning, "Can not run two bulk operations twice");
this.root.bulkOperationRunning = true; this.root.bulkOperationRunning = true;
const now = performanceNow(); const now = performanceNow();

View File

@ -146,38 +146,35 @@ export class BeltSystem extends GameSystemWithFilter {
const assignedPath = entity.components.Belt.assignedPath; const assignedPath = entity.components.Belt.assignedPath;
assert(assignedPath, "Entity has no belt path assigned"); assert(assignedPath, "Entity has no belt path assigned");
this.deleteEntityFromPath(assignedPath, entity);
this.verifyBeltPaths();
}
// Find from and to entities /**
const fromEntity = this.findSupplyingEntity(entity); * Attempts to delete the belt from its current path
const toEntity = this.findFollowUpEntity(entity); * @param {BeltPath} path
* @param {Entity} entity
// Check if the belt had a previous belt */
if (fromEntity) { deleteEntityFromPath(path, entity) {
const fromPath = fromEntity.components.Belt.assignedPath; if (path.entityPath.length === 1) {
// This is a single entity path, easy to do, simply erase whole path
// Check if the entity had a followup - belt fastArrayDeleteValue(this.beltPaths, path);
if (toEntity) { return;
const toPath = toEntity.components.Belt.assignedPath;
assert(fromPath === toPath, "Invalid belt path layout (from path != to path)");
const newPath = fromPath.deleteEntityOnPathSplitIntoTwo(entity);
this.beltPaths.push(newPath);
} else {
fromPath.deleteEntityOnEnd(entity);
}
} else {
if (toEntity) {
// We need to remove the entity from the beginning of the other path
const toPath = toEntity.components.Belt.assignedPath;
toPath.deleteEntityOnStart(entity);
} else {
// This is a single entity path, easy to do
const path = entity.components.Belt.assignedPath;
fastArrayDeleteValue(this.beltPaths, path);
}
} }
this.verifyBeltPaths(); // Notice: Since there might be circular references, it is important to check
// which role the entity has
if (path.isStartEntity(entity)) {
// We tried to delete the start
path.deleteEntityOnStart(entity);
} else if (path.isEndEntity(entity)) {
// We tried to delete the end
path.deleteEntityOnEnd(entity);
} else {
// We tried to delete something inbetween
const newPath = path.deleteEntityOnPathSplitIntoTwo(entity);
this.beltPaths.push(newPath);
}
} }
/** /**
@ -193,13 +190,9 @@ export class BeltSystem extends GameSystemWithFilter {
return; return;
} }
console.log("ADD");
const fromEntity = this.findSupplyingEntity(entity); const fromEntity = this.findSupplyingEntity(entity);
const toEntity = this.findFollowUpEntity(entity); const toEntity = this.findFollowUpEntity(entity);
console.log("From:", fromEntity, "to:", toEntity);
// Check if we can add the entity to the previous path // Check if we can add the entity to the previous path
if (fromEntity) { if (fromEntity) {
const fromPath = fromEntity.components.Belt.assignedPath; const fromPath = fromEntity.components.Belt.assignedPath;
@ -385,22 +378,15 @@ export class BeltSystem extends GameSystemWithFilter {
*/ */
computeBeltPaths() { computeBeltPaths() {
const visitedUids = new Set(); const visitedUids = new Set();
console.log("Computing belt paths");
const debugEntity = e => e.components.StaticMapEntity.origin.toString();
// const stackToVisit = this.allEntities.slice();
const result = []; const result = [];
const currentPath = null;
for (let i = 0; i < this.allEntities.length; ++i) { for (let i = 0; i < this.allEntities.length; ++i) {
const entity = this.allEntities[i]; const entity = this.allEntities[i];
if (visitedUids.has(entity.uid)) { if (visitedUids.has(entity.uid)) {
continue; continue;
} }
// console.log("Starting at", debugEntity(entity));
// Mark entity as visited // Mark entity as visited
visitedUids.add(entity.uid); visitedUids.add(entity.uid);
@ -412,10 +398,9 @@ export class BeltSystem extends GameSystemWithFilter {
// Find precedors // Find precedors
let prevEntity = this.findSupplyingEntity(entity); let prevEntity = this.findSupplyingEntity(entity);
while (prevEntity && --maxIter > 0) { while (prevEntity && --maxIter > 0) {
if (visitedUids.has(prevEntity)) { if (visitedUids.has(prevEntity.uid)) {
break; break;
} }
// console.log(" -> precedor: ", debugEntity(prevEntity));
path.unshift(prevEntity); path.unshift(prevEntity);
visitedUids.add(prevEntity.uid); visitedUids.add(prevEntity.uid);
prevEntity = this.findSupplyingEntity(prevEntity); prevEntity = this.findSupplyingEntity(prevEntity);
@ -424,26 +409,17 @@ export class BeltSystem extends GameSystemWithFilter {
// Find succedors // Find succedors
let nextEntity = this.findFollowUpEntity(entity); let nextEntity = this.findFollowUpEntity(entity);
while (nextEntity && --maxIter > 0) { while (nextEntity && --maxIter > 0) {
if (visitedUids.has(nextEntity)) { if (visitedUids.has(nextEntity.uid)) {
break; break;
} }
// console.log(" -> succedor: ", debugEntity(nextEntity));
path.push(nextEntity); path.push(nextEntity);
visitedUids.add(nextEntity.uid); visitedUids.add(nextEntity.uid);
nextEntity = this.findFollowUpEntity(nextEntity); nextEntity = this.findFollowUpEntity(nextEntity);
} }
assert(maxIter !== 0, "Ran out of iterations"); assert(maxIter > 1, "Ran out of iterations");
// console.log(
// "Found path:",
// path.map(e => debugEntity(e))
// );
result.push(new BeltPath(this.root, path)); result.push(new BeltPath(this.root, path));
// let prevEntity = this.findSupplyingEntity(srcEntity);
} }
logger.log("Found", this.beltPaths.length, "belt paths"); logger.log("Found", this.beltPaths.length, "belt paths");