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) {
if (G_IS_DEV) {
assertAlways(parameters instanceof DrawParameters, "Not a valid context");
assertAlways(!!w && w > 0, "Not a valid width:" + w);
assertAlways(!!h && h > 0, "Not a valid height:" + h);
assert(parameters instanceof DrawParameters, "Not a valid context");
assert(!!w && w > 0, "Not a valid width:" + w);
assert(!!h && h > 0, "Not a valid height:" + h);
}
const visibleRect = parameters.visibleRect;

View File

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

View File

@ -82,7 +82,9 @@ export class BeltPath extends BasicSerializableObject {
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
@ -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
* @param {string} change
@ -181,10 +186,6 @@ export class BeltPath extends BasicSerializableObject {
* Checks if this path is valid
*/
debug_checkIntegrity(currentChange = "change") {
if (!G_IS_DEV) {
return;
}
const fail = (...args) => this.debug_failIntegrity(currentChange, ...args);
// Check for empty path
@ -319,6 +320,8 @@ export class BeltPath extends BasicSerializableObject {
}
}
/* dev:end */
/**
* Extends the belt path by the given belt
* @param {Entity} entity
@ -368,7 +371,9 @@ export class BeltPath extends BasicSerializableObject {
// Update bounds
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
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
this.worldBounds = this.computeBounds();
this.debug_checkIntegrity("split-two-first");
secondPath.debug_checkIntegrity("split-two-second");
if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_checkIntegrity("split-two-first");
secondPath.debug_checkIntegrity("split-two-second");
}
return secondPath;
}
@ -683,7 +692,9 @@ export class BeltPath extends BasicSerializableObject {
// Update bounds
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
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.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
*/
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
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 { enumItemAcceptorItemFilter, ItemAcceptorComponent } from "../components/item_acceptor";
import { T } from "../../translations";
import { ItemAcceptorComponent } from "../components/item_acceptor";
import { ItemEjectorComponent } from "../components/item_ejector";
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
import { Entity } from "../entity";
import { MetaBuilding, defaultBuildingVariant } from "../meta_building";
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals";
import { T } from "../../translations";
import { formatItemsPerSecond } from "../../core/utils";
import { enumItemType } from "../base_item";
/** @enum {string} */
export const enumCutterVariants = { quad: "quad" };
@ -82,7 +82,7 @@ export class MetaCutterBuilding extends MetaBuilding {
{
pos: new Vector(0, 0),
directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
],
})

View File

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

View File

@ -1,11 +1,11 @@
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 { 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 {
constructor() {
@ -51,72 +51,72 @@ export class MetaHubBuilding extends MetaBuilding {
{
pos: new Vector(0, 0),
directions: [enumDirection.top, enumDirection.left],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(1, 0),
directions: [enumDirection.top],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(2, 0),
directions: [enumDirection.top],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(3, 0),
directions: [enumDirection.top, enumDirection.right],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(0, 3),
directions: [enumDirection.bottom, enumDirection.left],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(1, 3),
directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(2, 3),
directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(3, 3),
directions: [enumDirection.bottom, enumDirection.right],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(0, 1),
directions: [enumDirection.left],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(0, 2),
directions: [enumDirection.left],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(0, 3),
directions: [enumDirection.left],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(3, 1),
directions: [enumDirection.right],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(3, 2),
directions: [enumDirection.right],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(3, 3),
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 { 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 { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals";
import { T } from "../../translations";
import { formatItemsPerSecond } from "../../core/utils";
export class MetaMixerBuilding extends MetaBuilding {
constructor() {
@ -63,12 +63,12 @@ export class MetaMixerBuilding extends MetaBuilding {
{
pos: new Vector(0, 0),
directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.color,
filter: enumItemType.color,
},
{
pos: new Vector(1, 0),
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 { enumItemAcceptorItemFilter, ItemAcceptorComponent } from "../components/item_acceptor";
import { T } from "../../translations";
import { ItemAcceptorComponent } from "../components/item_acceptor";
import { ItemEjectorComponent } from "../components/item_ejector";
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
import { Entity } from "../entity";
import { MetaBuilding, defaultBuildingVariant } from "../meta_building";
import { enumHubGoalRewards } from "../tutorial_goals";
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
import { T } from "../../translations";
import { formatItemsPerSecond } from "../../core/utils";
import { enumHubGoalRewards } from "../tutorial_goals";
import { enumItemType } from "../base_item";
/** @enum {string} */
export const enumPainterVariants = { mirrored: "mirrored", double: "double", quad: "quad" };
@ -98,12 +98,12 @@ export class MetaPainterBuilding extends MetaBuilding {
{
pos: new Vector(0, 0),
directions: [enumDirection.left],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(1, 0),
directions: [enumDirection.top],
filter: enumItemAcceptorItemFilter.color,
filter: enumItemType.color,
},
],
})
@ -124,14 +124,14 @@ export class MetaPainterBuilding extends MetaBuilding {
{
pos: new Vector(0, 0),
directions: [enumDirection.left],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(1, 0),
directions: [
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),
directions: [enumDirection.left],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(0, 1),
directions: [enumDirection.left],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(1, 0),
directions: [enumDirection.top],
filter: enumItemAcceptorItemFilter.color,
filter: enumItemType.color,
},
]);
@ -174,27 +174,27 @@ export class MetaPainterBuilding extends MetaBuilding {
{
pos: new Vector(0, 0),
directions: [enumDirection.left],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(0, 0),
directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.color,
filter: enumItemType.color,
},
{
pos: new Vector(1, 0),
directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.color,
filter: enumItemType.color,
},
{
pos: new Vector(2, 0),
directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.color,
filter: enumItemType.color,
},
{
pos: new Vector(3, 0),
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 { ItemAcceptorComponent, enumItemAcceptorItemFilter } from "../components/item_acceptor";
import { T } from "../../translations";
import { ItemAcceptorComponent } from "../components/item_acceptor";
import { ItemEjectorComponent } from "../components/item_ejector";
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
import { Entity } from "../entity";
import { MetaBuilding, defaultBuildingVariant } from "../meta_building";
import { enumHubGoalRewards } from "../tutorial_goals";
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
import { T } from "../../translations";
import { formatItemsPerSecond } from "../../core/utils";
import { enumHubGoalRewards } from "../tutorial_goals";
import { enumItemType } from "../base_item";
/** @enum {string} */
export const enumRotaterVariants = { ccw: "ccw" };
@ -77,7 +77,7 @@ export class MetaRotaterBuilding extends MetaBuilding {
{
pos: new Vector(0, 0),
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 { ItemAcceptorComponent, enumItemAcceptorItemFilter } from "../components/item_acceptor";
import { T } from "../../translations";
import { ItemAcceptorComponent } from "../components/item_acceptor";
import { ItemEjectorComponent } from "../components/item_ejector";
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals";
import { formatItemsPerSecond } from "../../core/utils";
import { T } from "../../translations";
import { enumItemType } from "../base_item";
export class MetaStackerBuilding extends MetaBuilding {
constructor() {
@ -63,12 +63,12 @@ export class MetaStackerBuilding extends MetaBuilding {
{
pos: new Vector(0, 0),
directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
{
pos: new Vector(1, 0),
directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.shape,
filter: enumItemType.shape,
},
],
})

View File

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

View File

@ -1,23 +1,12 @@
import { Component } from "../component";
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 { enumDirection, enumInvertedDirections, Vector } from "../../core/vector";
import { types } from "../../savegame/serialization";
/**
* @enum {string?}
*/
export const enumItemAcceptorItemFilter = {
shape: "shape",
color: "color",
none: null,
};
import { BaseItem, enumItemType } from "../base_item";
import { Component } from "../component";
/** @typedef {{
* pos: Vector,
* directions: enumDirection[],
* filter?: enumItemAcceptorItemFilter
* filter?: enumItemType
* }} ItemAcceptorSlot */
/**
@ -39,7 +28,7 @@ export class ItemAcceptorComponent extends Component {
types.structured({
pos: types.vector,
directions: types.array(types.enum(enumDirection)),
filter: types.nullable(types.enum(enumItemAcceptorItemFilter)),
filter: types.nullable(types.enum(enumItemType)),
})
),
animated: types.bool,
@ -49,16 +38,6 @@ export class ItemAcceptorComponent extends Component {
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 {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 {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) {
/** @type {Array<{pos: Vector, directions: enumDirection[], filter?: enumItemAcceptorItemFilter}>} */
/** @type {Array<{pos: Vector, directions: enumDirection[], filter?: enumItemType}>} */
this.slots = [];
for (let i = 0; i < slots.length; ++i) {
const slot = slots[i];
@ -126,7 +105,7 @@ export class ItemAcceptorComponent extends Component {
pos: slot.pos,
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,
});
}
@ -139,16 +118,7 @@ export class ItemAcceptorComponent extends Component {
*/
canAcceptItem(slotIndex, item) {
const slot = this.slots[slotIndex];
switch (slot.filter) {
case enumItemAcceptorItemFilter.shape: {
return item instanceof ShapeItem;
}
case enumItemAcceptorItemFilter.color: {
return item instanceof ColorItem;
}
default:
return true;
}
return slot.filter === null || slot.filter === item.getItemType();
}
/**

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
import { GameRoot } from "./root";
import { ShapeDefinition } from "./shape_definition";
import { globalConfig } from "../core/config";
import { BaseItem } from "./base_item";
import { BaseItem, enumItemType } from "./base_item";
import { ShapeItem } from "./items/shape_item";
import { BasicSerializableObject } from "../savegame/serialization";
@ -53,8 +53,8 @@ export class ProductionAnalytics extends BasicSerializableObject {
* @param {BaseItem} item
*/
onItemProduced(item) {
if (item instanceof ShapeItem) {
const definition = item.definition;
if (item.getItemType() === enumItemType.shape) {
const definition = /** @type {ShapeItem} */ (item).definition;
const key = definition.getHash();
const entry = this.history[enumAnalyticsDataSource.produced];
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");
}
this.verifyBeltPaths();
if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_verifyBeltPaths();
}
}
/**
@ -171,12 +173,16 @@ export class BeltSystem extends GameSystemWithFilter {
this.addEntityToPaths(targetEntity);
// 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;
assert(assignedPath, "Entity has no belt path assigned");
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.verifyBeltPaths();
if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_verifyBeltPaths();
}
}
/**
@ -297,21 +307,19 @@ export class BeltSystem extends GameSystemWithFilter {
/**
* Verifies all belt paths
*/
verifyBeltPaths() {
if (G_IS_DEV && true) {
for (let i = 0; i < this.beltPaths.length; ++i) {
this.beltPaths[i].debug_checkIntegrity("general-verify");
}
debug_verifyBeltPaths() {
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);
}
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);
}
}
}
@ -450,13 +458,17 @@ export class BeltSystem extends GameSystemWithFilter {
* Updates all belts
*/
update() {
this.verifyBeltPaths();
if (G_IS_DEV && globalConfig.debug.checkBeltPaths) {
this.debug_verifyBeltPaths();
}
for (let i = 0; i < this.beltPaths.length; ++i) {
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() {
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) {
const entity = this.allEntities[i];
const aceptorComp = entity.components.ItemAcceptor;
const animations = aceptorComp.itemConsumptionAnimations;
// Process item consumption animations to avoid items popping from the belts
for (let animIndex = 0; animIndex < aceptorComp.itemConsumptionAnimations.length; ++animIndex) {
const anim = aceptorComp.itemConsumptionAnimations[animIndex];
anim.animProgress +=
this.root.dynamicTickrate.deltaSeconds *
this.root.hubGoals.getBeltBaseSpeed() *
2 *
globalConfig.itemSpacingOnBelts;
for (let animIndex = 0; animIndex < animations.length; ++animIndex) {
const anim = animations[animIndex];
anim.animProgress += progress;
if (anim.animProgress > 1) {
aceptorComp.itemConsumptionAnimations.splice(animIndex, 1);
animations.splice(animIndex, 1);
animIndex -= 1;
}
}

View File

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

View File

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