mirror of
https://github.com/tobspr/shapez.io.git
synced 2024-10-27 20:34:29 +00:00
Second take on belt performance
This commit is contained in:
parent
192d1dbedb
commit
9ce912dbdd
@ -1,18 +1,18 @@
|
|||||||
|
import { Math_min } from "../core/builtins";
|
||||||
import { globalConfig } from "../core/config";
|
import { globalConfig } from "../core/config";
|
||||||
import { DrawParameters } from "../core/draw_parameters";
|
import { DrawParameters } from "../core/draw_parameters";
|
||||||
|
import { createLogger } from "../core/logging";
|
||||||
|
import { epsilonCompare, round4Digits } from "../core/utils";
|
||||||
import { Vector } from "../core/vector";
|
import { Vector } from "../core/vector";
|
||||||
import { BaseItem } from "./base_item";
|
import { BaseItem } from "./base_item";
|
||||||
import { Entity } from "./entity";
|
import { Entity } from "./entity";
|
||||||
import { GameRoot } from "./root";
|
import { GameRoot } from "./root";
|
||||||
import { round4Digits, epsilonCompare } from "../core/utils";
|
|
||||||
import { Math_min } from "../core/builtins";
|
|
||||||
import { createLogger, logSection } from "../core/logging";
|
|
||||||
|
|
||||||
const logger = createLogger("belt_path");
|
const logger = createLogger("belt_path");
|
||||||
|
|
||||||
// Helpers for more semantic access into interleaved arrays
|
// Helpers for more semantic access into interleaved arrays
|
||||||
const NEXT_ITEM_OFFSET_INDEX = 0;
|
const _nextDistance = 0;
|
||||||
const ITEM_INDEX = 1;
|
const _item = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores a path of belts, used for optimizing performance
|
* Stores a path of belts, used for optimizing performance
|
||||||
@ -82,7 +82,7 @@ export class BeltPath {
|
|||||||
|
|
||||||
// Check for mismatching length
|
// Check for mismatching length
|
||||||
const totalLength = this.computeTotalLength();
|
const totalLength = this.computeTotalLength();
|
||||||
if (this.totalLength !== totalLength) {
|
if (!epsilonCompare(this.totalLength, totalLength)) {
|
||||||
return this.debug_failIntegrity(
|
return this.debug_failIntegrity(
|
||||||
currentChange,
|
currentChange,
|
||||||
"Total length mismatch, stored =",
|
"Total length mismatch, stored =",
|
||||||
@ -95,6 +95,10 @@ export class BeltPath {
|
|||||||
// Check for misconnected entities
|
// Check for misconnected entities
|
||||||
for (let i = 0; i < this.entityPath.length - 1; ++i) {
|
for (let i = 0; i < this.entityPath.length - 1; ++i) {
|
||||||
const entity = this.entityPath[i];
|
const entity = this.entityPath[i];
|
||||||
|
if (entity.destroyed) {
|
||||||
|
return fail("Reference to destroyed entity " + entity.uid);
|
||||||
|
}
|
||||||
|
|
||||||
const followUp = this.root.systemMgr.systems.belt.findFollowUpEntity(entity);
|
const followUp = this.root.systemMgr.systems.belt.findFollowUpEntity(entity);
|
||||||
if (!followUp) {
|
if (!followUp) {
|
||||||
return fail(
|
return fail(
|
||||||
@ -168,17 +172,17 @@ export class BeltPath {
|
|||||||
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 (item[NEXT_ITEM_OFFSET_INDEX] < 0 || item[NEXT_ITEM_OFFSET_INDEX] > this.totalLength) {
|
if (item[_nextDistance] < 0 || item[_nextDistance] > this.totalLength) {
|
||||||
return fail(
|
return fail(
|
||||||
"Item has invalid offset to next item: ",
|
"Item has invalid offset to next item: ",
|
||||||
item[0],
|
item[_nextDistance],
|
||||||
"(total length:",
|
"(total length:",
|
||||||
this.totalLength,
|
this.totalLength,
|
||||||
")"
|
")"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentPos += item[0];
|
currentPos += item[_nextDistance];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the total sum matches
|
// Check the total sum matches
|
||||||
@ -190,7 +194,7 @@ export class BeltPath {
|
|||||||
this.spacingToFirstItem,
|
this.spacingToFirstItem,
|
||||||
") and items does not match total length (",
|
") and items does not match total length (",
|
||||||
this.totalLength,
|
this.totalLength,
|
||||||
")"
|
") -> items: " + this.items.map(i => i[_nextDistance]).join("|")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -229,11 +233,11 @@ export class BeltPath {
|
|||||||
const lastItem = this.items[this.items.length - 1];
|
const lastItem = this.items[this.items.length - 1];
|
||||||
logger.log(
|
logger.log(
|
||||||
" Extended spacing of last item from",
|
" Extended spacing of last item from",
|
||||||
lastItem[NEXT_ITEM_OFFSET_INDEX],
|
lastItem[_nextDistance],
|
||||||
"to",
|
"to",
|
||||||
lastItem[NEXT_ITEM_OFFSET_INDEX] + additionalLength
|
lastItem[_nextDistance] + additionalLength
|
||||||
);
|
);
|
||||||
lastItem[NEXT_ITEM_OFFSET_INDEX] += additionalLength;
|
lastItem[_nextDistance] += additionalLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update handles
|
// Update handles
|
||||||
@ -267,8 +271,8 @@ export class BeltPath {
|
|||||||
|
|
||||||
// Set handles and append entity
|
// Set handles and append entity
|
||||||
beltComp.assignedPath = this;
|
beltComp.assignedPath = this;
|
||||||
this.initialBeltComponent = this.entityPath[0].components.Belt;
|
|
||||||
this.entityPath.unshift(entity);
|
this.entityPath.unshift(entity);
|
||||||
|
this.initialBeltComponent = this.entityPath[0].components.Belt;
|
||||||
|
|
||||||
this.debug_checkIntegrity("extend-on-begin");
|
this.debug_checkIntegrity("extend-on-begin");
|
||||||
}
|
}
|
||||||
@ -337,7 +341,7 @@ export class BeltPath {
|
|||||||
logger.log("Splitting", this.items.length, "items");
|
logger.log("Splitting", this.items.length, "items");
|
||||||
logger.log(
|
logger.log(
|
||||||
"Old items are",
|
"Old items are",
|
||||||
this.items.map(i => i[NEXT_ITEM_OFFSET_INDEX])
|
this.items.map(i => i[_nextDistance])
|
||||||
);
|
);
|
||||||
|
|
||||||
// Create second path
|
// Create second path
|
||||||
@ -347,7 +351,7 @@ export class BeltPath {
|
|||||||
let itemPos = this.spacingToFirstItem;
|
let itemPos = 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];
|
||||||
const distanceToNext = item[NEXT_ITEM_OFFSET_INDEX];
|
const distanceToNext = item[_nextDistance];
|
||||||
|
|
||||||
logger.log(" Checking item at", itemPos, "with distance of", distanceToNext, "to next");
|
logger.log(" Checking item at", itemPos, "with distance of", distanceToNext, "to next");
|
||||||
|
|
||||||
@ -361,7 +365,7 @@ export class BeltPath {
|
|||||||
// 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_INDEX]]);
|
secondPath.items.push([distanceToNext, item[_item]]);
|
||||||
logger.log(
|
logger.log(
|
||||||
" Put item to second path @",
|
" Put item to second path @",
|
||||||
itemPos,
|
itemPos,
|
||||||
@ -388,7 +392,7 @@ export class BeltPath {
|
|||||||
"to",
|
"to",
|
||||||
clampedDistanceToNext
|
clampedDistanceToNext
|
||||||
);
|
);
|
||||||
item[NEXT_ITEM_OFFSET_INDEX] = clampedDistanceToNext;
|
item[_nextDistance] = clampedDistanceToNext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,12 +402,12 @@ export class BeltPath {
|
|||||||
|
|
||||||
logger.log(
|
logger.log(
|
||||||
"New items are",
|
"New items are",
|
||||||
this.items.map(i => i[0])
|
this.items.map(i => i[_nextDistance])
|
||||||
);
|
);
|
||||||
|
|
||||||
logger.log(
|
logger.log(
|
||||||
"And second path items are",
|
"And second path items are",
|
||||||
secondPath.items.map(i => i[0])
|
secondPath.items.map(i => i[_nextDistance])
|
||||||
);
|
);
|
||||||
|
|
||||||
// Adjust our total length
|
// Adjust our total length
|
||||||
@ -424,45 +428,268 @@ export class BeltPath {
|
|||||||
return secondPath;
|
return secondPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the last entity
|
||||||
|
* @param {Entity} entity
|
||||||
|
*/
|
||||||
|
deleteEntityOnEnd(entity) {
|
||||||
|
assert(this.entityPath[this.entityPath.length - 1] === entity, "Not the last entity actually");
|
||||||
|
|
||||||
|
// Ok, first remove the entity
|
||||||
|
const beltComp = entity.components.Belt;
|
||||||
|
const beltLength = beltComp.getEffectiveLengthTiles();
|
||||||
|
|
||||||
|
logger.log(
|
||||||
|
"Deleting last entity on path with length",
|
||||||
|
this.entityPath.length,
|
||||||
|
"(reducing",
|
||||||
|
this.totalLength,
|
||||||
|
" by",
|
||||||
|
beltLength,
|
||||||
|
")"
|
||||||
|
);
|
||||||
|
this.totalLength -= beltLength;
|
||||||
|
this.entityPath.pop();
|
||||||
|
|
||||||
|
logger.log(" New path has length of", this.totalLength, "with", this.entityPath.length, "entities");
|
||||||
|
|
||||||
|
// This is just for sanity
|
||||||
|
beltComp.assignedPath = null;
|
||||||
|
|
||||||
|
// Clean up items
|
||||||
|
if (this.items.length === 0) {
|
||||||
|
// Simple case with no items, just update the first item spacing
|
||||||
|
this.spacingToFirstItem = this.totalLength;
|
||||||
|
} else {
|
||||||
|
// Ok, make sure we simply drop all items which are no longer contained
|
||||||
|
let itemOffset = this.spacingToFirstItem;
|
||||||
|
let lastItemOffset = itemOffset;
|
||||||
|
|
||||||
|
logger.log(" Adjusting", this.items.length, "items");
|
||||||
|
|
||||||
|
for (let i = 0; i < this.items.length; ++i) {
|
||||||
|
const item = this.items[i];
|
||||||
|
|
||||||
|
// Get rid of items past this path
|
||||||
|
if (itemOffset >= this.totalLength) {
|
||||||
|
logger.log("Dropping item (current index=", i, ")");
|
||||||
|
this.items.splice(i, 1);
|
||||||
|
i -= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.log("Item", i, "is at", itemOffset, "with next offset", item[_nextDistance]);
|
||||||
|
lastItemOffset = itemOffset;
|
||||||
|
itemOffset += item[_nextDistance];
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we still have an item, make sure the last item matches
|
||||||
|
if (this.items.length > 0) {
|
||||||
|
// We can easily compute the next distance since we know where the last item is now
|
||||||
|
const lastDistance = this.totalLength - lastItemOffset;
|
||||||
|
assert(
|
||||||
|
lastDistance >= 0.0,
|
||||||
|
"Last item distance mismatch: " +
|
||||||
|
lastDistance +
|
||||||
|
" -> Total length was " +
|
||||||
|
this.totalLength +
|
||||||
|
" and lastItemOffset was " +
|
||||||
|
lastItemOffset
|
||||||
|
);
|
||||||
|
|
||||||
|
logger.log(
|
||||||
|
"Adjusted distance of last item: it is at",
|
||||||
|
lastItemOffset,
|
||||||
|
"so it has a distance of",
|
||||||
|
lastDistance,
|
||||||
|
"to the end (",
|
||||||
|
this.totalLength,
|
||||||
|
")"
|
||||||
|
);
|
||||||
|
this.items[this.items.length - 1][_nextDistance] = lastDistance;
|
||||||
|
} else {
|
||||||
|
logger.log(" Removed all items so we'll update spacing to total length");
|
||||||
|
|
||||||
|
// We removed all items so update our spacing
|
||||||
|
this.spacingToFirstItem = this.totalLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update handles
|
||||||
|
this.ejectorComp = this.entityPath[this.entityPath.length - 1].components.ItemEjector;
|
||||||
|
this.ejectorSlot = this.ejectorComp.slots[0];
|
||||||
|
|
||||||
|
this.debug_checkIntegrity("delete-on-end");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the entity of the start of the path
|
||||||
|
* @see deleteEntityOnEnd
|
||||||
|
* @param {Entity} entity
|
||||||
|
*/
|
||||||
|
deleteEntityOnStart(entity) {
|
||||||
|
assert(entity === this.entityPath[0], "Not actually the start entity");
|
||||||
|
|
||||||
|
// Ok, first remove the entity
|
||||||
|
const beltComp = entity.components.Belt;
|
||||||
|
const beltLength = beltComp.getEffectiveLengthTiles();
|
||||||
|
|
||||||
|
logger.log(
|
||||||
|
"Deleting first entity on path with length",
|
||||||
|
this.entityPath.length,
|
||||||
|
"(reducing",
|
||||||
|
this.totalLength,
|
||||||
|
" by",
|
||||||
|
beltLength,
|
||||||
|
")"
|
||||||
|
);
|
||||||
|
this.totalLength -= beltLength;
|
||||||
|
this.entityPath.shift();
|
||||||
|
|
||||||
|
logger.log(" New path has length of", this.totalLength, "with", this.entityPath.length, "entities");
|
||||||
|
|
||||||
|
// This is just for sanity
|
||||||
|
beltComp.assignedPath = null;
|
||||||
|
|
||||||
|
// Clean up items
|
||||||
|
if (this.items.length === 0) {
|
||||||
|
// Simple case with no items, just update the first item spacing
|
||||||
|
this.spacingToFirstItem = this.totalLength;
|
||||||
|
} else {
|
||||||
|
// Simple case, we had no item on the beginning -> all good
|
||||||
|
if (this.spacingToFirstItem >= beltLength) {
|
||||||
|
logger.log(
|
||||||
|
" No item on the first place, so we can just adjust the spacing (spacing=",
|
||||||
|
this.spacingToFirstItem,
|
||||||
|
") removed =",
|
||||||
|
beltLength
|
||||||
|
);
|
||||||
|
this.spacingToFirstItem -= beltLength;
|
||||||
|
} else {
|
||||||
|
// Welp, okay we need to drop all items which are < beltLength and adjust
|
||||||
|
// the other item offsets as well
|
||||||
|
|
||||||
|
logger.log(
|
||||||
|
" We have at least one item in the beginning, drop those and adjust spacing (first item @",
|
||||||
|
this.spacingToFirstItem,
|
||||||
|
") since we removed",
|
||||||
|
beltLength,
|
||||||
|
"length from path"
|
||||||
|
);
|
||||||
|
logger.log(
|
||||||
|
" Items:",
|
||||||
|
this.items.map(i => i[_nextDistance])
|
||||||
|
);
|
||||||
|
|
||||||
|
// Find offset to first item
|
||||||
|
let itemOffset = this.spacingToFirstItem;
|
||||||
|
for (let i = 0; i < this.items.length; ++i) {
|
||||||
|
const item = this.items[i];
|
||||||
|
if (itemOffset <= beltLength) {
|
||||||
|
logger.log(
|
||||||
|
" -> Dropping item with index",
|
||||||
|
i,
|
||||||
|
"at",
|
||||||
|
itemOffset,
|
||||||
|
"since it was on the removed belt"
|
||||||
|
);
|
||||||
|
// This item must be dropped
|
||||||
|
this.items.splice(i, 1);
|
||||||
|
i -= 1;
|
||||||
|
itemOffset += item[_nextDistance];
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// This item can be kept, thus its the first we know
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.items.length > 0) {
|
||||||
|
logger.log(
|
||||||
|
" Offset of first non-dropped item was at:",
|
||||||
|
itemOffset,
|
||||||
|
"-> setting spacing to it (total length=",
|
||||||
|
this.totalLength,
|
||||||
|
")"
|
||||||
|
);
|
||||||
|
|
||||||
|
this.spacingToFirstItem = itemOffset - beltLength;
|
||||||
|
assert(
|
||||||
|
this.spacingToFirstItem >= 0.0,
|
||||||
|
"Invalid spacing after delete on start: " + this.spacingToFirstItem
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
logger.log(" We dropped all items, simply set spacing to total length");
|
||||||
|
// We dropped all items, simple one
|
||||||
|
this.spacingToFirstItem = this.totalLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update handles
|
||||||
|
this.initialBeltComponent = this.entityPath[0].components.Belt;
|
||||||
|
|
||||||
|
this.debug_checkIntegrity("delete-on-start");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends the path by the given other path
|
* Extends the path by the given other path
|
||||||
* @param {BeltPath} otherPath
|
* @param {BeltPath} otherPath
|
||||||
*/
|
*/
|
||||||
extendByPath(otherPath) {
|
extendByPath(otherPath) {
|
||||||
|
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");
|
logger.log("Extending path by other path, starting to add entities");
|
||||||
const oldLength = this.totalLength;
|
|
||||||
const oldLastItem = this.items[this.items.length - 1];
|
|
||||||
|
|
||||||
|
const oldLength = this.totalLength;
|
||||||
|
|
||||||
|
logger.log(" Adding", entities.length, "new entities, current length =", this.totalLength);
|
||||||
|
|
||||||
|
// First, append entities
|
||||||
for (let i = 0; i < entities.length; ++i) {
|
for (let i = 0; i < entities.length; ++i) {
|
||||||
this.extendOnEnd(entities[i]);
|
const entity = entities[i];
|
||||||
|
const beltComp = entity.components.Belt;
|
||||||
|
|
||||||
|
// Add to path and update references
|
||||||
|
this.entityPath.push(entity);
|
||||||
|
beltComp.assignedPath = this;
|
||||||
|
|
||||||
|
// Update our length
|
||||||
|
const additionalLength = beltComp.getEffectiveLengthTiles();
|
||||||
|
this.totalLength += additionalLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log(" Transferring new items:", otherPath.items);
|
logger.log(" Path is now", this.entityPath.length, "entities and has a length of", this.totalLength);
|
||||||
|
|
||||||
// Check if we have no items and thus need to adjust the spacing
|
// Update handles
|
||||||
if (this.items.length === 0) {
|
this.ejectorComp = this.entityPath[this.entityPath.length - 1].components.ItemEjector;
|
||||||
// This one is easy - Since our first path is empty, we can just
|
this.ejectorSlot = this.ejectorComp.slots[0];
|
||||||
// set the spacing to the first one to the whole first part length
|
|
||||||
// and add the spacing on the second path (Which might be the whole second part
|
|
||||||
// length if its entirely empty, too)
|
|
||||||
this.spacingToFirstItem = this.totalLength + otherPath.spacingToFirstItem;
|
|
||||||
logger.log(" Extended spacing to first to", this.totalLength, "(= total length)");
|
|
||||||
|
|
||||||
// Simply copy over all items
|
// Now, update the distance of our last item
|
||||||
for (let i = 0; i < otherPath.items.length; ++i) {
|
if (this.items.length !== 0) {
|
||||||
const item = otherPath.items[0];
|
const lastItem = this.items[this.items.length - 1];
|
||||||
this.items.push([item[0], item[1]]);
|
lastItem[_nextDistance] += otherPath.spacingToFirstItem;
|
||||||
}
|
logger.log(" Add distance to last item, effectively being", lastItem[_nextDistance], "now");
|
||||||
} else {
|
} else {
|
||||||
console.error("TODO4");
|
// Seems we have no items, update our first item distance
|
||||||
|
this.spacingToFirstItem = oldLength + otherPath.spacingToFirstItem;
|
||||||
|
logger.log(
|
||||||
|
" We had no items, so our new spacing to first is old length (",
|
||||||
|
oldLength,
|
||||||
|
") plus others spacing to first (",
|
||||||
|
otherPath.spacingToFirstItem,
|
||||||
|
") =",
|
||||||
|
this.spacingToFirstItem
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Adjust the distance from our last item to the first item of the second path.
|
logger.log(" Pushing", otherPath.items.length, "items from other path");
|
||||||
// First, find the absolute position of the first item:
|
|
||||||
let itemPosition = this.spacingToFirstItem;
|
// Aaand push the other paths items
|
||||||
for (let i = 0; i < this.items.length; ++i) {
|
for (let i = 0; i < otherPath.items.length; ++i) {
|
||||||
itemPosition += this.items[i][0];
|
const item = otherPath.items[i];
|
||||||
}
|
this.items.push([item[_nextDistance], item[_item]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.debug_checkIntegrity("extend-by-path");
|
this.debug_checkIntegrity("extend-by-path");
|
||||||
@ -490,7 +717,7 @@ export class BeltPath {
|
|||||||
|
|
||||||
// Check if the first belt took a new item
|
// Check if the first belt took a new item
|
||||||
if (transferItemAndProgress) {
|
if (transferItemAndProgress) {
|
||||||
const transferItem = transferItemAndProgress[1];
|
const transferItem = transferItemAndProgress[_item];
|
||||||
|
|
||||||
if (this.spacingToFirstItem >= globalConfig.itemSpacingOnBelts) {
|
if (this.spacingToFirstItem >= globalConfig.itemSpacingOnBelts) {
|
||||||
// Can take new item
|
// Can take new item
|
||||||
@ -519,10 +746,13 @@ export class BeltPath {
|
|||||||
const nextDistanceAndItem = this.items[i];
|
const nextDistanceAndItem = this.items[i];
|
||||||
const minimumSpacing = minimumDistance;
|
const minimumSpacing = minimumDistance;
|
||||||
|
|
||||||
const takeAway = Math.max(0, Math.min(remainingAmount, nextDistanceAndItem[0] - minimumSpacing));
|
const takeAway = Math.max(
|
||||||
|
0,
|
||||||
|
Math.min(remainingAmount, nextDistanceAndItem[_nextDistance] - minimumSpacing)
|
||||||
|
);
|
||||||
|
|
||||||
remainingAmount -= takeAway;
|
remainingAmount -= takeAway;
|
||||||
nextDistanceAndItem[0] -= takeAway;
|
nextDistanceAndItem[_nextDistance] -= takeAway;
|
||||||
|
|
||||||
this.spacingToFirstItem += takeAway;
|
this.spacingToFirstItem += takeAway;
|
||||||
if (remainingAmount === 0.0) {
|
if (remainingAmount === 0.0) {
|
||||||
@ -533,9 +763,9 @@ export class BeltPath {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const lastItem = this.items[this.items.length - 1];
|
const lastItem = this.items[this.items.length - 1];
|
||||||
if (lastItem && lastItem[0] === 0.0) {
|
if (lastItem && lastItem[_nextDistance] === 0) {
|
||||||
// Take over
|
// Take over
|
||||||
if (this.ejectorComp.tryEject(0, lastItem[1])) {
|
if (this.ejectorComp.tryEject(0, lastItem[_item])) {
|
||||||
this.items.pop();
|
this.items.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -605,12 +835,12 @@ export class BeltPath {
|
|||||||
parameters.context.font = "6px GameFont";
|
parameters.context.font = "6px GameFont";
|
||||||
parameters.context.fillStyle = "#111";
|
parameters.context.fillStyle = "#111";
|
||||||
parameters.context.fillText(
|
parameters.context.fillText(
|
||||||
"" + round4Digits(nextDistanceAndItem[0]),
|
"" + round4Digits(nextDistanceAndItem[_nextDistance]),
|
||||||
worldPos.x + 5,
|
worldPos.x + 5,
|
||||||
worldPos.y + 2
|
worldPos.y + 2
|
||||||
);
|
);
|
||||||
progress += nextDistanceAndItem[0];
|
progress += nextDistanceAndItem[_nextDistance];
|
||||||
nextDistanceAndItem[1].draw(worldPos.x, worldPos.y, parameters, 10);
|
nextDistanceAndItem[_item].draw(worldPos.x, worldPos.y, parameters, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < this.entityPath.length; ++i) {
|
for (let i = 0; i < this.entityPath.length; ++i) {
|
||||||
|
@ -144,8 +144,6 @@ export class BeltSystem extends GameSystemWithFilter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("DESTROY");
|
|
||||||
|
|
||||||
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");
|
||||||
|
|
||||||
@ -161,23 +159,25 @@ export class BeltSystem extends GameSystemWithFilter {
|
|||||||
if (toEntity) {
|
if (toEntity) {
|
||||||
const toPath = toEntity.components.Belt.assignedPath;
|
const toPath = toEntity.components.Belt.assignedPath;
|
||||||
assert(fromPath === toPath, "Invalid belt path layout (from path != to path)");
|
assert(fromPath === toPath, "Invalid belt path layout (from path != to path)");
|
||||||
console.log("Remove inbetween");
|
|
||||||
|
|
||||||
const newPath = fromPath.deleteEntityOnPathSplitIntoTwo(entity);
|
const newPath = fromPath.deleteEntityOnPathSplitIntoTwo(entity);
|
||||||
this.beltPaths.push(newPath);
|
this.beltPaths.push(newPath);
|
||||||
} else {
|
} else {
|
||||||
// TODO
|
fromPath.deleteEntityOnEnd(entity);
|
||||||
console.error("TODO 1");
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (toEntity) {
|
if (toEntity) {
|
||||||
// TODO
|
// We need to remove the entity from the beginning of the other path
|
||||||
console.error("TODO 2");
|
const toPath = toEntity.components.Belt.assignedPath;
|
||||||
|
toPath.deleteEntityOnStart(entity);
|
||||||
} else {
|
} else {
|
||||||
// TODO
|
// This is a single entity path, easy to do
|
||||||
console.error("TODO 3");
|
const path = entity.components.Belt.assignedPath;
|
||||||
|
fastArrayDeleteValue(this.beltPaths, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.verifyBeltPaths();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -208,10 +208,15 @@ export class BeltSystem extends GameSystemWithFilter {
|
|||||||
// Check if we now can extend the current path by the next path
|
// Check if we now can extend the current path by the next path
|
||||||
if (toEntity) {
|
if (toEntity) {
|
||||||
const toPath = toEntity.components.Belt.assignedPath;
|
const toPath = toEntity.components.Belt.assignedPath;
|
||||||
fromPath.extendByPath(toPath);
|
|
||||||
|
|
||||||
// Delete now obsolete path
|
if (fromPath === toPath) {
|
||||||
fastArrayDeleteValue(this.beltPaths, toPath);
|
// This is a circular dependency -> Ignore
|
||||||
|
} else {
|
||||||
|
fromPath.extendByPath(toPath);
|
||||||
|
|
||||||
|
// Delete now obsolete path
|
||||||
|
fastArrayDeleteValue(this.beltPaths, toPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (toEntity) {
|
if (toEntity) {
|
||||||
@ -224,12 +229,36 @@ export class BeltSystem extends GameSystemWithFilter {
|
|||||||
this.beltPaths.push(path);
|
this.beltPaths.push(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.verifyBeltPaths();
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(parameters) {
|
draw(parameters) {
|
||||||
this.forEachMatchingEntityOnScreen(parameters, this.drawEntityItems.bind(this));
|
this.forEachMatchingEntityOnScreen(parameters, this.drawEntityItems.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies all belt paths
|
||||||
|
*/
|
||||||
|
verifyBeltPaths() {
|
||||||
|
if (G_IS_DEV) {
|
||||||
|
for (let i = 0; i < this.beltPaths.length; ++i) {
|
||||||
|
this.beltPaths[i].debug_checkIntegrity("general-verify");
|
||||||
|
}
|
||||||
|
|
||||||
|
const belts = this.root.entityMgr.getAllWithComponent(BeltComponent);
|
||||||
|
for (let i = 0; i < belts.length; ++i) {
|
||||||
|
const path = belts[i].components.Belt.assignedPath;
|
||||||
|
if (!path) {
|
||||||
|
throw new Error("Belt has no path: " + belts[i].uid);
|
||||||
|
}
|
||||||
|
if (this.beltPaths.indexOf(path) < 0) {
|
||||||
|
throw new Error("Path of entity not contained: " + belts[i].uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the follow up entity for a given belt. Used for building the dependencies
|
* Finds the follow up entity for a given belt. Used for building the dependencies
|
||||||
* @param {Entity} entity
|
* @param {Entity} entity
|
||||||
@ -378,9 +407,11 @@ export class BeltSystem extends GameSystemWithFilter {
|
|||||||
// Compute path, start with entity and find precedors / successors
|
// Compute path, start with entity and find precedors / successors
|
||||||
const path = [entity];
|
const path = [entity];
|
||||||
|
|
||||||
|
let maxIter = 9999;
|
||||||
|
|
||||||
// Find precedors
|
// Find precedors
|
||||||
let prevEntity = this.findSupplyingEntity(entity);
|
let prevEntity = this.findSupplyingEntity(entity);
|
||||||
while (prevEntity) {
|
while (prevEntity && --maxIter > 0) {
|
||||||
if (visitedUids.has(prevEntity)) {
|
if (visitedUids.has(prevEntity)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -392,7 +423,7 @@ export class BeltSystem extends GameSystemWithFilter {
|
|||||||
|
|
||||||
// Find succedors
|
// Find succedors
|
||||||
let nextEntity = this.findFollowUpEntity(entity);
|
let nextEntity = this.findFollowUpEntity(entity);
|
||||||
while (nextEntity) {
|
while (nextEntity && --maxIter > 0) {
|
||||||
if (visitedUids.has(nextEntity)) {
|
if (visitedUids.has(nextEntity)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -403,6 +434,8 @@ export class BeltSystem extends GameSystemWithFilter {
|
|||||||
nextEntity = this.findFollowUpEntity(nextEntity);
|
nextEntity = this.findFollowUpEntity(nextEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(maxIter !== 0, "Ran out of iterations");
|
||||||
|
|
||||||
// console.log(
|
// console.log(
|
||||||
// "Found path:",
|
// "Found path:",
|
||||||
// path.map(e => debugEntity(e))
|
// path.map(e => debugEntity(e))
|
||||||
@ -422,10 +455,14 @@ export class BeltSystem extends GameSystemWithFilter {
|
|||||||
this.computeBeltCache();
|
this.computeBeltCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.verifyBeltPaths();
|
||||||
|
|
||||||
for (let i = 0; i < this.beltPaths.length; ++i) {
|
for (let i = 0; i < this.beltPaths.length; ++i) {
|
||||||
this.beltPaths[i].update();
|
this.beltPaths[i].update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.verifyBeltPaths();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user