Improve performance by getting rid of instanceof

This commit is contained in:
tobspr 2020-06-27 10:38:11 +02:00
parent d8bf4f9cd8
commit 419401b9be
21 changed files with 239 additions and 199 deletions

View File

@ -144,9 +144,9 @@ export class AtlasSprite extends BaseSprite {
*/ */
drawCached(parameters, x, y, w = null, h = null, clipping = true) { drawCached(parameters, x, y, w = null, h = null, clipping = true) {
if (G_IS_DEV) { if (G_IS_DEV) {
assertAlways(parameters instanceof DrawParameters, "Not a valid context"); assert(parameters instanceof DrawParameters, "Not a valid context");
assertAlways(!!w && w > 0, "Not a valid width:" + w); assert(!!w && w > 0, "Not a valid width:" + w);
assertAlways(!!h && h > 0, "Not a valid height:" + h); assert(!!h && h > 0, "Not a valid height:" + h);
} }
const visibleRect = parameters.visibleRect; const visibleRect = parameters.visibleRect;

View File

@ -1,6 +1,11 @@
import { DrawParameters } from "../core/draw_parameters"; import { DrawParameters } from "../core/draw_parameters";
import { BasicSerializableObject, types } from "../savegame/serialization"; import { BasicSerializableObject } from "../savegame/serialization";
import { THEME } from "./theme";
/** @enum {string} */
export const enumItemType = {
shape: "shape",
color: "color",
};
/** /**
* Class for items on belts etc. Not an entity for performance reasons * Class for items on belts etc. Not an entity for performance reasons
@ -19,6 +24,12 @@ export class BaseItem extends BasicSerializableObject {
return {}; return {};
} }
/** @returns {enumItemType} */
getItemType() {
abstract;
return "";
}
/** /**
* Draws the item at the given position * Draws the item at the given position
* @param {number} x * @param {number} x

View File

@ -82,7 +82,9 @@ export class BeltPath extends BasicSerializableObject {
this.init(); this.init();
this.debug_checkIntegrity("constructor"); if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_checkIntegrity("constructor");
}
} }
/** /**
* Initializes the path by computing the properties which are not saved * Initializes the path by computing the properties which are not saved
@ -168,6 +170,9 @@ export class BeltPath extends BasicSerializableObject {
} }
} }
// Following code will be compiled out outside of dev versions
/* dev:start */
/** /**
* Helper to throw an error on mismatch * Helper to throw an error on mismatch
* @param {string} change * @param {string} change
@ -181,10 +186,6 @@ export class BeltPath extends BasicSerializableObject {
* Checks if this path is valid * Checks if this path is valid
*/ */
debug_checkIntegrity(currentChange = "change") { debug_checkIntegrity(currentChange = "change") {
if (!G_IS_DEV) {
return;
}
const fail = (...args) => this.debug_failIntegrity(currentChange, ...args); const fail = (...args) => this.debug_failIntegrity(currentChange, ...args);
// Check for empty path // Check for empty path
@ -319,6 +320,8 @@ export class BeltPath extends BasicSerializableObject {
} }
} }
/* dev:end */
/** /**
* Extends the belt path by the given belt * Extends the belt path by the given belt
* @param {Entity} entity * @param {Entity} entity
@ -368,7 +371,9 @@ export class BeltPath extends BasicSerializableObject {
// Update bounds // Update bounds
this.worldBounds = this.computeBounds(); this.worldBounds = this.computeBounds();
this.debug_checkIntegrity("extend-on-end"); if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_checkIntegrity("extend-on-end");
}
} }
/** /**
@ -398,7 +403,9 @@ export class BeltPath extends BasicSerializableObject {
// Update bounds // Update bounds
this.worldBounds = this.computeBounds(); this.worldBounds = this.computeBounds();
this.debug_checkIntegrity("extend-on-begin"); if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_checkIntegrity("extend-on-begin");
}
} }
/** /**
@ -574,8 +581,10 @@ export class BeltPath extends BasicSerializableObject {
// Update bounds // Update bounds
this.worldBounds = this.computeBounds(); this.worldBounds = this.computeBounds();
this.debug_checkIntegrity("split-two-first"); if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
secondPath.debug_checkIntegrity("split-two-second"); this.debug_checkIntegrity("split-two-first");
secondPath.debug_checkIntegrity("split-two-second");
}
return secondPath; return secondPath;
} }
@ -683,7 +692,9 @@ export class BeltPath extends BasicSerializableObject {
// Update bounds // Update bounds
this.worldBounds = this.computeBounds(); this.worldBounds = this.computeBounds();
this.debug_checkIntegrity("delete-on-end"); if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_checkIntegrity("delete-on-end");
}
} }
/** /**
@ -810,7 +821,9 @@ export class BeltPath extends BasicSerializableObject {
// Update bounds // Update bounds
this.worldBounds = this.computeBounds(); this.worldBounds = this.computeBounds();
this.debug_checkIntegrity("delete-on-start"); if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_checkIntegrity("delete-on-start");
}
} }
/** /**
@ -882,7 +895,9 @@ export class BeltPath extends BasicSerializableObject {
this.onPathChanged(); this.onPathChanged();
this.debug_checkIntegrity("extend-by-path"); if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_checkIntegrity("extend-by-path");
}
} }
/** /**
@ -901,7 +916,9 @@ export class BeltPath extends BasicSerializableObject {
* Performs one tick * Performs one tick
*/ */
update() { update() {
this.debug_checkIntegrity("pre-update"); if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_checkIntegrity("pre-update");
}
// Divide by item spacing on belts since we use throughput and not speed // Divide by item spacing on belts since we use throughput and not speed
let beltSpeed = let beltSpeed =
@ -945,7 +962,9 @@ export class BeltPath extends BasicSerializableObject {
} }
} }
this.debug_checkIntegrity("post-update"); if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_checkIntegrity("post-update");
}
} }
/** /**

View File

@ -1,14 +1,14 @@
import { globalConfig } from "../../core/config"; import { formatItemsPerSecond } from "../../core/utils";
import { enumDirection, Vector } from "../../core/vector"; import { enumDirection, Vector } from "../../core/vector";
import { enumItemAcceptorItemFilter, ItemAcceptorComponent } from "../components/item_acceptor"; import { T } from "../../translations";
import { ItemAcceptorComponent } from "../components/item_acceptor";
import { ItemEjectorComponent } from "../components/item_ejector"; import { ItemEjectorComponent } from "../components/item_ejector";
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
import { T } from "../../translations"; import { enumItemType } from "../base_item";
import { formatItemsPerSecond } from "../../core/utils";
/** @enum {string} */ /** @enum {string} */
export const enumCutterVariants = { quad: "quad" }; export const enumCutterVariants = { quad: "quad" };
@ -82,7 +82,7 @@ export class MetaCutterBuilding extends MetaBuilding {
{ {
pos: new Vector(0, 0), pos: new Vector(0, 0),
directions: [enumDirection.bottom], directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
], ],
}) })

View File

@ -1,11 +1,12 @@
import { enumDirection, Vector } from "../../core/vector"; import { enumDirection, Vector } from "../../core/vector";
import { ItemAcceptorComponent, enumItemAcceptorItemFilter } from "../components/item_acceptor"; import { ItemAcceptorComponent } from "../components/item_acceptor";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building"; import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
import { EnergyGeneratorComponent } from "../components/energy_generator"; import { EnergyGeneratorComponent } from "../components/energy_generator";
import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins"; import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins";
import { enumItemType } from "../base_item";
export class MetaEnergyGenerator extends MetaBuilding { export class MetaEnergyGenerator extends MetaBuilding {
constructor() { constructor() {
@ -52,23 +53,23 @@ export class MetaEnergyGenerator extends MetaBuilding {
{ {
pos: new Vector(0, 0), pos: new Vector(0, 0),
directions: [enumDirection.top], directions: [enumDirection.top],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(1, 0), pos: new Vector(1, 0),
directions: [enumDirection.top], directions: [enumDirection.top],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(0, 1), pos: new Vector(0, 1),
directions: [enumDirection.bottom], directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(1, 1), pos: new Vector(1, 1),
directions: [enumDirection.bottom], directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
], ],
}) })

View File

@ -1,11 +1,11 @@
import { enumDirection, Vector } from "../../core/vector"; import { enumDirection, Vector } from "../../core/vector";
import { enumItemAcceptorItemFilter, ItemAcceptorComponent } from "../components/item_acceptor"; import { enumItemType } from "../base_item";
import { HubComponent } from "../components/hub";
import { ItemAcceptorComponent } from "../components/item_acceptor";
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
import { UnremovableComponent } from "../components/unremovable";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building"; import { MetaBuilding } from "../meta_building";
import { ItemProcessorComponent, enumItemProcessorTypes } from "../components/item_processor";
import { globalConfig } from "../../core/config";
import { UnremovableComponent } from "../components/unremovable";
import { HubComponent } from "../components/hub";
export class MetaHubBuilding extends MetaBuilding { export class MetaHubBuilding extends MetaBuilding {
constructor() { constructor() {
@ -51,72 +51,72 @@ export class MetaHubBuilding extends MetaBuilding {
{ {
pos: new Vector(0, 0), pos: new Vector(0, 0),
directions: [enumDirection.top, enumDirection.left], directions: [enumDirection.top, enumDirection.left],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(1, 0), pos: new Vector(1, 0),
directions: [enumDirection.top], directions: [enumDirection.top],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(2, 0), pos: new Vector(2, 0),
directions: [enumDirection.top], directions: [enumDirection.top],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(3, 0), pos: new Vector(3, 0),
directions: [enumDirection.top, enumDirection.right], directions: [enumDirection.top, enumDirection.right],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(0, 3), pos: new Vector(0, 3),
directions: [enumDirection.bottom, enumDirection.left], directions: [enumDirection.bottom, enumDirection.left],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(1, 3), pos: new Vector(1, 3),
directions: [enumDirection.bottom], directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(2, 3), pos: new Vector(2, 3),
directions: [enumDirection.bottom], directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(3, 3), pos: new Vector(3, 3),
directions: [enumDirection.bottom, enumDirection.right], directions: [enumDirection.bottom, enumDirection.right],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(0, 1), pos: new Vector(0, 1),
directions: [enumDirection.left], directions: [enumDirection.left],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(0, 2), pos: new Vector(0, 2),
directions: [enumDirection.left], directions: [enumDirection.left],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(0, 3), pos: new Vector(0, 3),
directions: [enumDirection.left], directions: [enumDirection.left],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(3, 1), pos: new Vector(3, 1),
directions: [enumDirection.right], directions: [enumDirection.right],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(3, 2), pos: new Vector(3, 2),
directions: [enumDirection.right], directions: [enumDirection.right],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(3, 3), pos: new Vector(3, 3),
directions: [enumDirection.right], directions: [enumDirection.right],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
], ],
}) })

View File

@ -1,14 +1,14 @@
import { globalConfig } from "../../core/config"; import { formatItemsPerSecond } from "../../core/utils";
import { enumDirection, Vector } from "../../core/vector"; import { enumDirection, Vector } from "../../core/vector";
import { ItemAcceptorComponent, enumItemAcceptorItemFilter } from "../components/item_acceptor"; import { T } from "../../translations";
import { enumItemType } from "../base_item";
import { ItemAcceptorComponent } from "../components/item_acceptor";
import { ItemEjectorComponent } from "../components/item_ejector"; import { ItemEjectorComponent } from "../components/item_ejector";
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building"; import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
import { T } from "../../translations";
import { formatItemsPerSecond } from "../../core/utils";
export class MetaMixerBuilding extends MetaBuilding { export class MetaMixerBuilding extends MetaBuilding {
constructor() { constructor() {
@ -63,12 +63,12 @@ export class MetaMixerBuilding extends MetaBuilding {
{ {
pos: new Vector(0, 0), pos: new Vector(0, 0),
directions: [enumDirection.bottom], directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.color, filter: enumItemType.color,
}, },
{ {
pos: new Vector(1, 0), pos: new Vector(1, 0),
directions: [enumDirection.bottom], directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.color, filter: enumItemType.color,
}, },
], ],
}) })

View File

@ -1,14 +1,14 @@
import { globalConfig } from "../../core/config"; import { formatItemsPerSecond } from "../../core/utils";
import { enumDirection, Vector } from "../../core/vector"; import { enumDirection, Vector } from "../../core/vector";
import { enumItemAcceptorItemFilter, ItemAcceptorComponent } from "../components/item_acceptor"; import { T } from "../../translations";
import { ItemAcceptorComponent } from "../components/item_acceptor";
import { ItemEjectorComponent } from "../components/item_ejector"; import { ItemEjectorComponent } from "../components/item_ejector";
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { enumHubGoalRewards } from "../tutorial_goals";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { T } from "../../translations"; import { enumHubGoalRewards } from "../tutorial_goals";
import { formatItemsPerSecond } from "../../core/utils"; import { enumItemType } from "../base_item";
/** @enum {string} */ /** @enum {string} */
export const enumPainterVariants = { mirrored: "mirrored", double: "double", quad: "quad" }; export const enumPainterVariants = { mirrored: "mirrored", double: "double", quad: "quad" };
@ -98,12 +98,12 @@ export class MetaPainterBuilding extends MetaBuilding {
{ {
pos: new Vector(0, 0), pos: new Vector(0, 0),
directions: [enumDirection.left], directions: [enumDirection.left],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(1, 0), pos: new Vector(1, 0),
directions: [enumDirection.top], directions: [enumDirection.top],
filter: enumItemAcceptorItemFilter.color, filter: enumItemType.color,
}, },
], ],
}) })
@ -124,14 +124,14 @@ export class MetaPainterBuilding extends MetaBuilding {
{ {
pos: new Vector(0, 0), pos: new Vector(0, 0),
directions: [enumDirection.left], directions: [enumDirection.left],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(1, 0), pos: new Vector(1, 0),
directions: [ directions: [
variant === defaultBuildingVariant ? enumDirection.top : enumDirection.bottom, variant === defaultBuildingVariant ? enumDirection.top : enumDirection.bottom,
], ],
filter: enumItemAcceptorItemFilter.color, filter: enumItemType.color,
}, },
]); ]);
@ -147,17 +147,17 @@ export class MetaPainterBuilding extends MetaBuilding {
{ {
pos: new Vector(0, 0), pos: new Vector(0, 0),
directions: [enumDirection.left], directions: [enumDirection.left],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(0, 1), pos: new Vector(0, 1),
directions: [enumDirection.left], directions: [enumDirection.left],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(1, 0), pos: new Vector(1, 0),
directions: [enumDirection.top], directions: [enumDirection.top],
filter: enumItemAcceptorItemFilter.color, filter: enumItemType.color,
}, },
]); ]);
@ -174,27 +174,27 @@ export class MetaPainterBuilding extends MetaBuilding {
{ {
pos: new Vector(0, 0), pos: new Vector(0, 0),
directions: [enumDirection.left], directions: [enumDirection.left],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(0, 0), pos: new Vector(0, 0),
directions: [enumDirection.bottom], directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.color, filter: enumItemType.color,
}, },
{ {
pos: new Vector(1, 0), pos: new Vector(1, 0),
directions: [enumDirection.bottom], directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.color, filter: enumItemType.color,
}, },
{ {
pos: new Vector(2, 0), pos: new Vector(2, 0),
directions: [enumDirection.bottom], directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.color, filter: enumItemType.color,
}, },
{ {
pos: new Vector(3, 0), pos: new Vector(3, 0),
directions: [enumDirection.bottom], directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.color, filter: enumItemType.color,
}, },
]); ]);

View File

@ -1,14 +1,14 @@
import { globalConfig } from "../../core/config"; import { formatItemsPerSecond } from "../../core/utils";
import { enumDirection, Vector } from "../../core/vector"; import { enumDirection, Vector } from "../../core/vector";
import { ItemAcceptorComponent, enumItemAcceptorItemFilter } from "../components/item_acceptor"; import { T } from "../../translations";
import { ItemAcceptorComponent } from "../components/item_acceptor";
import { ItemEjectorComponent } from "../components/item_ejector"; import { ItemEjectorComponent } from "../components/item_ejector";
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { enumHubGoalRewards } from "../tutorial_goals";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { T } from "../../translations"; import { enumHubGoalRewards } from "../tutorial_goals";
import { formatItemsPerSecond } from "../../core/utils"; import { enumItemType } from "../base_item";
/** @enum {string} */ /** @enum {string} */
export const enumRotaterVariants = { ccw: "ccw" }; export const enumRotaterVariants = { ccw: "ccw" };
@ -77,7 +77,7 @@ export class MetaRotaterBuilding extends MetaBuilding {
{ {
pos: new Vector(0, 0), pos: new Vector(0, 0),
directions: [enumDirection.bottom], directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
], ],
}) })

View File

@ -1,14 +1,14 @@
import { globalConfig } from "../../core/config"; import { formatItemsPerSecond } from "../../core/utils";
import { enumDirection, Vector } from "../../core/vector"; import { enumDirection, Vector } from "../../core/vector";
import { ItemAcceptorComponent, enumItemAcceptorItemFilter } from "../components/item_acceptor"; import { T } from "../../translations";
import { ItemAcceptorComponent } from "../components/item_acceptor";
import { ItemEjectorComponent } from "../components/item_ejector"; import { ItemEjectorComponent } from "../components/item_ejector";
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building"; import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
import { formatItemsPerSecond } from "../../core/utils"; import { enumItemType } from "../base_item";
import { T } from "../../translations";
export class MetaStackerBuilding extends MetaBuilding { export class MetaStackerBuilding extends MetaBuilding {
constructor() { constructor() {
@ -63,12 +63,12 @@ export class MetaStackerBuilding extends MetaBuilding {
{ {
pos: new Vector(0, 0), pos: new Vector(0, 0),
directions: [enumDirection.bottom], directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
{ {
pos: new Vector(1, 0), pos: new Vector(1, 0),
directions: [enumDirection.bottom], directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.shape, filter: enumItemType.shape,
}, },
], ],
}) })

View File

@ -37,12 +37,7 @@ export class EnergyGeneratorComponent extends Component {
* @param {BaseItem} item * @param {BaseItem} item
*/ */
tryTakeItem(item) { tryTakeItem(item) {
if (!(item instanceof ShapeItem)) { if (/** @type {ShapeItem} */ (item).definition.getHash() !== this.requiredKey) {
// Not a shape
return false;
}
if (item.definition.getHash() !== this.requiredKey) {
// Not our shape // Not our shape
return false; return false;
} }

View File

@ -1,23 +1,12 @@
import { Component } from "../component"; import { enumDirection, enumInvertedDirections, Vector } from "../../core/vector";
import { Vector, enumDirection, enumInvertedDirections } from "../../core/vector";
import { BaseItem } from "../base_item";
import { ShapeItem } from "../items/shape_item";
import { ColorItem } from "../items/color_item";
import { types } from "../../savegame/serialization"; import { types } from "../../savegame/serialization";
import { BaseItem, enumItemType } from "../base_item";
/** import { Component } from "../component";
* @enum {string?}
*/
export const enumItemAcceptorItemFilter = {
shape: "shape",
color: "color",
none: null,
};
/** @typedef {{ /** @typedef {{
* pos: Vector, * pos: Vector,
* directions: enumDirection[], * directions: enumDirection[],
* filter?: enumItemAcceptorItemFilter * filter?: enumItemType
* }} ItemAcceptorSlot */ * }} ItemAcceptorSlot */
/** /**
@ -39,7 +28,7 @@ export class ItemAcceptorComponent extends Component {
types.structured({ types.structured({
pos: types.vector, pos: types.vector,
directions: types.array(types.enum(enumDirection)), directions: types.array(types.enum(enumDirection)),
filter: types.nullable(types.enum(enumItemAcceptorItemFilter)), filter: types.nullable(types.enum(enumItemType)),
}) })
), ),
animated: types.bool, animated: types.bool,
@ -49,16 +38,6 @@ export class ItemAcceptorComponent extends Component {
direction: types.enum(enumDirection), direction: types.enum(enumDirection),
}) })
), ),
// We don't actually need to store the animations
// itemConsumptionAnimations: types.array(
// types.structured({
// item: types.obj(gItemRegistry),
// slotIndex: types.uint,
// animProgress: types.float,
// direction: types.enum(enumDirection),
// })
// ),
}; };
} }
@ -92,7 +71,7 @@ export class ItemAcceptorComponent extends Component {
/** /**
* *
* @param {object} param0 * @param {object} param0
* @param {Array<{pos: Vector, directions: enumDirection[], filter?: enumItemAcceptorItemFilter}>} param0.slots The slots from which we accept items * @param {Array<{pos: Vector, directions: enumDirection[], filter?: enumItemType}>} param0.slots The slots from which we accept items
* @param {boolean=} param0.animated Whether to animate item consumption * @param {boolean=} param0.animated Whether to animate item consumption
* @param {Array<{pos: Vector, direction: enumDirection}>=} param0.beltUnderlays Where to render belt underlays * @param {Array<{pos: Vector, direction: enumDirection}>=} param0.beltUnderlays Where to render belt underlays
*/ */
@ -115,10 +94,10 @@ export class ItemAcceptorComponent extends Component {
/** /**
* *
* @param {Array<{pos: Vector, directions: enumDirection[], filter?: enumItemAcceptorItemFilter}>} slots * @param {Array<{pos: Vector, directions: enumDirection[], filter?: enumItemType}>} slots
*/ */
setSlots(slots) { setSlots(slots) {
/** @type {Array<{pos: Vector, directions: enumDirection[], filter?: enumItemAcceptorItemFilter}>} */ /** @type {Array<{pos: Vector, directions: enumDirection[], filter?: enumItemType}>} */
this.slots = []; this.slots = [];
for (let i = 0; i < slots.length; ++i) { for (let i = 0; i < slots.length; ++i) {
const slot = slots[i]; const slot = slots[i];
@ -126,7 +105,7 @@ export class ItemAcceptorComponent extends Component {
pos: slot.pos, pos: slot.pos,
directions: slot.directions, directions: slot.directions,
// Which type of item to accept (shape | color | all) @see enumItemAcceptorItemFilter // Which type of item to accept (shape | color | all) @see enumItemType
filter: slot.filter, filter: slot.filter,
}); });
} }
@ -139,16 +118,7 @@ export class ItemAcceptorComponent extends Component {
*/ */
canAcceptItem(slotIndex, item) { canAcceptItem(slotIndex, item) {
const slot = this.slots[slotIndex]; const slot = this.slots[slotIndex];
switch (slot.filter) { return slot.filter === null || slot.filter === item.getItemType();
case enumItemAcceptorItemFilter.shape: {
return item instanceof ShapeItem;
}
case enumItemAcceptorItemFilter.color: {
return item instanceof ColorItem;
}
default:
return true;
}
} }
/** /**

View File

@ -1,7 +1,7 @@
import { Component } from "../component"; import { Component } from "../component";
import { types } from "../../savegame/serialization"; import { types } from "../../savegame/serialization";
import { gItemRegistry } from "../../core/global_registries"; import { gItemRegistry } from "../../core/global_registries";
import { BaseItem } from "../base_item"; import { BaseItem, enumItemType } from "../base_item";
import { ColorItem } from "../items/color_item"; import { ColorItem } from "../items/color_item";
import { ShapeItem } from "../items/shape_item"; import { ShapeItem } from "../items/shape_item";
@ -60,17 +60,23 @@ export class StorageComponent extends Component {
return true; return true;
} }
if (item instanceof ColorItem) { const itemType = item.getItemType();
return this.storedItem instanceof ColorItem && this.storedItem.color === item.color;
// Check type matches
if (itemType !== this.storedItem.getItemType()) {
return false;
} }
if (item instanceof ShapeItem) { if (itemType === enumItemType.color) {
return /** @type {ColorItem} */ (this.storedItem).color === /** @type {ColorItem} */ (item).color;
}
if (itemType === enumItemType.shape) {
return ( return (
this.storedItem instanceof ShapeItem && /** @type {ShapeItem} */ (this.storedItem).definition.getHash() ===
this.storedItem.definition.getHash() === item.definition.getHash() /** @type {ShapeItem} */ (item).definition.getHash()
); );
} }
return false; return false;
} }

View File

@ -7,6 +7,7 @@ import { DrawParameters } from "../../../core/draw_parameters";
import { THEME } from "../../theme"; import { THEME } from "../../theme";
import { globalConfig } from "../../../core/config"; import { globalConfig } from "../../../core/config";
import { T } from "../../../translations"; import { T } from "../../../translations";
import { enumItemType } from "../../base_item";
export class HUDColorBlindHelper extends BaseHUDPart { export class HUDColorBlindHelper extends BaseHUDPart {
createElements(parent) { createElements(parent) {
@ -49,8 +50,8 @@ export class HUDColorBlindHelper extends BaseHUDPart {
// Check if the belt has a color item // Check if the belt has a color item
if (beltComp) { if (beltComp) {
const item = beltComp.assignedPath.findItemAtTile(tile); const item = beltComp.assignedPath.findItemAtTile(tile);
if (item && item instanceof ColorItem) { if (item && item.getItemType() === enumItemType.color) {
return item.color; return /** @type {ColorItem} */ (item).color;
} }
} }
@ -59,16 +60,16 @@ export class HUDColorBlindHelper extends BaseHUDPart {
if (ejectorComp) { if (ejectorComp) {
for (let i = 0; i < ejectorComp.slots.length; ++i) { for (let i = 0; i < ejectorComp.slots.length; ++i) {
const slot = ejectorComp.slots[i]; const slot = ejectorComp.slots[i];
if (slot.item && slot.item instanceof ColorItem) { if (slot.item && slot.item.getItemType() === enumItemType.color) {
return slot.item.color; return /** @type {ColorItem} */ (slot.item).color;
} }
} }
} }
} else { } else {
// We hovered a lower layer, show the color there // We hovered a lower layer, show the color there
const lowerLayer = this.root.map.getLowerLayerContentXY(tile.x, tile.y); const lowerLayer = this.root.map.getLowerLayerContentXY(tile.x, tile.y);
if (lowerLayer && lowerLayer instanceof ColorItem) { if (lowerLayer && lowerLayer.getItemType() === enumItemType.color) {
return lowerLayer.color; return /** @type {ColorItem} */ (lowerLayer).color;
} }
} }

View File

@ -2,7 +2,7 @@ import { globalConfig } from "../../core/config";
import { smoothenDpi } from "../../core/dpi_manager"; import { smoothenDpi } from "../../core/dpi_manager";
import { DrawParameters } from "../../core/draw_parameters"; import { DrawParameters } from "../../core/draw_parameters";
import { types } from "../../savegame/serialization"; import { types } from "../../savegame/serialization";
import { BaseItem } from "../base_item"; import { BaseItem, enumItemType } from "../base_item";
import { enumColors, enumColorsToHexCode } from "../colors"; import { enumColors, enumColorsToHexCode } from "../colors";
import { THEME } from "../theme"; import { THEME } from "../theme";
@ -23,6 +23,10 @@ export class ColorItem extends BaseItem {
this.color = data; this.color = data;
} }
getItemType() {
return enumItemType.color;
}
/** /**
* @param {enumColors} color * @param {enumColors} color
*/ */

View File

@ -1,6 +1,6 @@
import { DrawParameters } from "../../core/draw_parameters"; import { DrawParameters } from "../../core/draw_parameters";
import { types } from "../../savegame/serialization"; import { types } from "../../savegame/serialization";
import { BaseItem } from "../base_item"; import { BaseItem, enumItemType } from "../base_item";
import { ShapeDefinition } from "../shape_definition"; import { ShapeDefinition } from "../shape_definition";
import { THEME } from "../theme"; import { THEME } from "../theme";
@ -21,6 +21,10 @@ export class ShapeItem extends BaseItem {
this.definition = ShapeDefinition.fromShortKey(data); this.definition = ShapeDefinition.fromShortKey(data);
} }
getItemType() {
return enumItemType.shape;
}
/** /**
* @param {ShapeDefinition} definition * @param {ShapeDefinition} definition
*/ */

View File

@ -1,7 +1,7 @@
import { GameRoot } from "./root"; import { GameRoot } from "./root";
import { ShapeDefinition } from "./shape_definition"; import { ShapeDefinition } from "./shape_definition";
import { globalConfig } from "../core/config"; import { globalConfig } from "../core/config";
import { BaseItem } from "./base_item"; import { BaseItem, enumItemType } from "./base_item";
import { ShapeItem } from "./items/shape_item"; import { ShapeItem } from "./items/shape_item";
import { BasicSerializableObject } from "../savegame/serialization"; import { BasicSerializableObject } from "../savegame/serialization";
@ -53,8 +53,8 @@ export class ProductionAnalytics extends BasicSerializableObject {
* @param {BaseItem} item * @param {BaseItem} item
*/ */
onItemProduced(item) { onItemProduced(item) {
if (item instanceof ShapeItem) { if (item.getItemType() === enumItemType.shape) {
const definition = item.definition; const definition = /** @type {ShapeItem} */ (item).definition;
const key = definition.getHash(); const key = definition.getHash();
const entry = this.history[enumAnalyticsDataSource.produced]; const entry = this.history[enumAnalyticsDataSource.produced];
entry[entry.length - 1][key] = (entry[entry.length - 1][key] || 0) + 1; entry[entry.length - 1][key] = (entry[entry.length - 1][key] || 0) + 1;

View File

@ -102,7 +102,9 @@ export class BeltSystem extends GameSystemWithFilter {
logger.warn("Restored", this.beltPaths.length, "belt paths"); logger.warn("Restored", this.beltPaths.length, "belt paths");
} }
this.verifyBeltPaths(); if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_verifyBeltPaths();
}
} }
/** /**
@ -171,12 +173,16 @@ export class BeltSystem extends GameSystemWithFilter {
this.addEntityToPaths(targetEntity); this.addEntityToPaths(targetEntity);
// Sanity // Sanity
this.verifyBeltPaths(); if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_verifyBeltPaths();
}
} }
} }
} }
this.verifyBeltPaths(); if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_verifyBeltPaths();
}
} }
/** /**
@ -195,7 +201,9 @@ 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.deleteEntityFromPath(assignedPath, entity);
this.verifyBeltPaths(); if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_verifyBeltPaths();
}
} }
/** /**
@ -281,7 +289,9 @@ export class BeltSystem extends GameSystemWithFilter {
} }
this.addEntityToPaths(entity); this.addEntityToPaths(entity);
this.verifyBeltPaths(); if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_verifyBeltPaths();
}
} }
/** /**
@ -297,21 +307,19 @@ export class BeltSystem extends GameSystemWithFilter {
/** /**
* Verifies all belt paths * Verifies all belt paths
*/ */
verifyBeltPaths() { debug_verifyBeltPaths() {
if (G_IS_DEV && true) { for (let i = 0; i < this.beltPaths.length; ++i) {
for (let i = 0; i < this.beltPaths.length; ++i) { this.beltPaths[i].debug_checkIntegrity("general-verify");
this.beltPaths[i].debug_checkIntegrity("general-verify"); }
}
const belts = this.root.entityMgr.getAllWithComponent(BeltComponent); const belts = this.root.entityMgr.getAllWithComponent(BeltComponent);
for (let i = 0; i < belts.length; ++i) { for (let i = 0; i < belts.length; ++i) {
const path = belts[i].components.Belt.assignedPath; const path = belts[i].components.Belt.assignedPath;
if (!path) { if (!path) {
throw new Error("Belt has no path: " + belts[i].uid); throw new Error("Belt has no path: " + belts[i].uid);
} }
if (this.beltPaths.indexOf(path) < 0) { if (this.beltPaths.indexOf(path) < 0) {
throw new Error("Path of entity not contained: " + belts[i].uid); throw new Error("Path of entity not contained: " + belts[i].uid);
}
} }
} }
} }
@ -450,13 +458,17 @@ export class BeltSystem extends GameSystemWithFilter {
* Updates all belts * Updates all belts
*/ */
update() { update() {
this.verifyBeltPaths(); if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_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(); if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_verifyBeltPaths();
}
} }
/** /**

View File

@ -21,20 +21,23 @@ export class ItemAcceptorSystem extends GameSystemWithFilter {
} }
update() { update() {
const progress =
this.root.dynamicTickrate.deltaSeconds *
this.root.hubGoals.getBeltBaseSpeed() *
2 * // * 2 because its only a half tile
globalConfig.itemSpacingOnBelts;
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];
const aceptorComp = entity.components.ItemAcceptor; const aceptorComp = entity.components.ItemAcceptor;
const animations = aceptorComp.itemConsumptionAnimations;
// Process item consumption animations to avoid items popping from the belts // Process item consumption animations to avoid items popping from the belts
for (let animIndex = 0; animIndex < aceptorComp.itemConsumptionAnimations.length; ++animIndex) { for (let animIndex = 0; animIndex < animations.length; ++animIndex) {
const anim = aceptorComp.itemConsumptionAnimations[animIndex]; const anim = animations[animIndex];
anim.animProgress += anim.animProgress += progress;
this.root.dynamicTickrate.deltaSeconds *
this.root.hubGoals.getBeltBaseSpeed() *
2 *
globalConfig.itemSpacingOnBelts;
if (anim.animProgress > 1) { if (anim.animProgress > 1) {
aceptorComp.itemConsumptionAnimations.splice(animIndex, 1); animations.splice(animIndex, 1);
animIndex -= 1; animIndex -= 1;
} }
} }

View File

@ -193,18 +193,19 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
if (!sourceEjectorComp.cachedConnectedSlots) { if (!sourceEjectorComp.cachedConnectedSlots) {
continue; continue;
} }
for (let j = 0; j < sourceEjectorComp.cachedConnectedSlots.length; j++) {
const sourceSlot = sourceEjectorComp.cachedConnectedSlots[j];
const destSlot = sourceSlot.cachedDestSlot;
const targetEntity = sourceSlot.cachedTargetEntity;
const slots = sourceEjectorComp.cachedConnectedSlots;
for (let j = 0; j < slots.length; ++j) {
const sourceSlot = slots[j];
const item = sourceSlot.item; const item = sourceSlot.item;
if (!item) { if (!item) {
// No item available to be ejected // No item available to be ejected
continue; continue;
} }
const destSlot = sourceSlot.cachedDestSlot;
const targetEntity = sourceSlot.cachedTargetEntity;
// Advance items on the slot // Advance items on the slot
sourceSlot.progress = Math_min(1, sourceSlot.progress + progressGrowth); sourceSlot.progress = Math_min(1, sourceSlot.progress + progressGrowth);
@ -248,15 +249,8 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
if (path.tryAcceptItem(item)) { if (path.tryAcceptItem(item)) {
return true; return true;
} }
} // Belt can have nothing else
return false;
const storageComp = receiver.components.Storage;
if (storageComp) {
// It's a storage
if (storageComp.canAcceptItem(item)) {
storageComp.takeItem(item);
return true;
}
} }
const itemProcessorComp = receiver.components.ItemProcessor; const itemProcessorComp = receiver.components.ItemProcessor;
@ -265,6 +259,8 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
if (itemProcessorComp.tryTakeItem(item, slotIndex)) { if (itemProcessorComp.tryTakeItem(item, slotIndex)) {
return true; return true;
} }
// Item processor can have nothing else
return false;
} }
const undergroundBeltComp = receiver.components.UndergroundBelt; const undergroundBeltComp = receiver.components.UndergroundBelt;
@ -278,6 +274,21 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
) { ) {
return true; return true;
} }
// Underground belt can have nothing else
return false;
}
const storageComp = receiver.components.Storage;
if (storageComp) {
// It's a storage
if (storageComp.canAcceptItem(item)) {
storageComp.takeItem(item);
return true;
}
// Storage can't have anything else
return false;
} }
const energyGeneratorComp = receiver.components.EnergyGenerator; const energyGeneratorComp = receiver.components.EnergyGenerator;
@ -286,6 +297,9 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
// Passed it over // Passed it over
return true; return true;
} }
// Energy generator comp can't have anything else
return false;
} }
return false; return false;

View File

@ -30,21 +30,21 @@ export class UndergroundBeltSystem extends GameSystemWithFilter {
} }
update() { update() {
const delta = this.root.dynamicTickrate.deltaSeconds;
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];
const undergroundComp = entity.components.UndergroundBelt; const undergroundComp = entity.components.UndergroundBelt;
const pendingItems = undergroundComp.pendingItems;
// Decrease remaining time of all items in belt // Decrease remaining time of all items in belt
for (let k = 0; k < undergroundComp.pendingItems.length; ++k) { for (let k = 0; k < pendingItems.length; ++k) {
const item = undergroundComp.pendingItems[k]; const item = pendingItems[k];
item[1] = Math_max(0, item[1] - this.root.dynamicTickrate.deltaSeconds); item[1] = Math_max(0, item[1] - delta);
if (G_IS_DEV && globalConfig.debug.instantBelts) { if (G_IS_DEV && globalConfig.debug.instantBelts) {
item[1] = 0; item[1] = 0;
} }
} }
if (undergroundComp.mode === enumUndergroundBeltMode.sender) { if (undergroundComp.mode === enumUndergroundBeltMode.sender) {
this.handleSender(entity); this.handleSender(entity);
} else { } else {