Get rid of item ejector / acceptor layers and new wires buildings for now
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1003 KiB |
Before Width: | Height: | Size: 226 KiB After Width: | Height: | Size: 200 KiB |
Before Width: | Height: | Size: 523 KiB After Width: | Height: | Size: 479 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 913 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.1 KiB |
@ -1,5 +1,4 @@
|
||||
$buildings: belt, cutter, miner, mixer, painter, rotater, splitter, stacker, trash, underground_belt,
|
||||
energy_generator, wire, advanced_processor, wire_crossings;
|
||||
$buildings: belt, cutter, miner, mixer, painter, rotater, splitter, stacker, trash, underground_belt;
|
||||
|
||||
@each $building in $buildings {
|
||||
[data-icon="building_icons/#{$building}.png"] {
|
||||
|
@ -53,10 +53,7 @@ export const globalConfig = {
|
||||
beltSpeedItemsPerSecond: 2,
|
||||
minerSpeedItemsPerSecond: 0, // COMPUTED
|
||||
|
||||
beltItemSpacingByLayer: {
|
||||
regular: 0.63,
|
||||
wires: 0.4,
|
||||
},
|
||||
itemSpacingOnBelts: 0.63,
|
||||
|
||||
wiresSpeedItemsPerSecond: 6,
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { DrawParameters } from "../core/draw_parameters";
|
||||
import { BasicSerializableObject } from "../savegame/serialization";
|
||||
import { enumLayer } from "./root";
|
||||
|
||||
/** @enum {string} */
|
||||
export const enumItemType = {
|
||||
@ -13,15 +12,6 @@ export const enumItemType = {
|
||||
genericEnergy: "genericEnergy",
|
||||
};
|
||||
|
||||
/** @enum {enumLayer} */
|
||||
export const enumItemTypeToLayer = {
|
||||
[enumItemType.shape]: enumLayer.regular,
|
||||
[enumItemType.color]: enumLayer.regular,
|
||||
[enumItemType.positiveEnergy]: enumLayer.wires,
|
||||
[enumItemType.negativeEnergy]: enumLayer.wires,
|
||||
[enumItemType.genericEnergy]: enumLayer.wires,
|
||||
};
|
||||
|
||||
/**
|
||||
* Class for items on belts etc. Not an entity for performance reasons
|
||||
*/
|
||||
|
@ -8,7 +8,7 @@ import { enumDirection, enumDirectionToVector, Vector, enumInvertedDirections }
|
||||
import { BasicSerializableObject, types } from "../savegame/serialization";
|
||||
import { BaseItem } from "./base_item";
|
||||
import { Entity } from "./entity";
|
||||
import { GameRoot } from "./root";
|
||||
import { GameRoot, enumLayer } from "./root";
|
||||
|
||||
const logger = createLogger("belt_path");
|
||||
|
||||
@ -115,14 +115,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
canAcceptItem() {
|
||||
return this.spacingToFirstItem >= this.getItemSpacing();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the spacing between items
|
||||
*/
|
||||
getItemSpacing() {
|
||||
return globalConfig.beltItemSpacingByLayer[this.layer];
|
||||
return this.spacingToFirstItem >= globalConfig.itemSpacingOnBelts;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,15 +123,15 @@ export class BeltPath extends BasicSerializableObject {
|
||||
* @param {BaseItem} item
|
||||
*/
|
||||
tryAcceptItem(item) {
|
||||
if (this.spacingToFirstItem >= this.getItemSpacing()) {
|
||||
if (this.spacingToFirstItem >= globalConfig.itemSpacingOnBelts) {
|
||||
// So, since we already need one tick to accept this item we will add this directly.
|
||||
const beltProgressPerTick =
|
||||
this.root.hubGoals.getBeltBaseSpeed(this.layer) *
|
||||
this.root.hubGoals.getBeltBaseSpeed() *
|
||||
this.root.dynamicTickrate.deltaSeconds *
|
||||
this.getItemSpacing();
|
||||
globalConfig.itemSpacingOnBelts;
|
||||
|
||||
// First, compute how much progress we can make *at max*
|
||||
const maxProgress = Math.max(0, this.spacingToFirstItem - this.getItemSpacing());
|
||||
const maxProgress = Math.max(0, this.spacingToFirstItem - globalConfig.itemSpacingOnBelts);
|
||||
const initialProgress = Math.min(maxProgress, beltProgressPerTick);
|
||||
|
||||
this.items.unshift([this.spacingToFirstItem - initialProgress, item]);
|
||||
@ -178,10 +171,9 @@ export class BeltPath extends BasicSerializableObject {
|
||||
}
|
||||
|
||||
/**
|
||||
* Recomputes the layer of the path and the target acceptor
|
||||
* Recomputes cache variables once the path was changed
|
||||
*/
|
||||
onPathChanged() {
|
||||
this.layer = this.entityPath[0].layer;
|
||||
this.acceptorTarget = this.computeAcceptingEntityAndSlot();
|
||||
}
|
||||
|
||||
@ -208,15 +200,13 @@ export class BeltPath extends BasicSerializableObject {
|
||||
const ejectSlotTargetWsTile = ejectSlotWsTile.add(ejectSlotWsDirectionVector);
|
||||
|
||||
// Try to find the given acceptor component to take the item
|
||||
// Since there can be cross layer dependencies, check on all layers
|
||||
const targetEntities = this.root.map.getLayersContentsMultipleXY(
|
||||
const targetEntity = this.root.map.getLayerContentXY(
|
||||
ejectSlotTargetWsTile.x,
|
||||
ejectSlotTargetWsTile.y
|
||||
ejectSlotTargetWsTile.y,
|
||||
enumLayer.regular
|
||||
);
|
||||
|
||||
for (let i = 0; i < targetEntities.length; ++i) {
|
||||
const targetEntity = targetEntities[i];
|
||||
|
||||
if (targetEntity) {
|
||||
const targetStaticComp = targetEntity.components.StaticMapEntity;
|
||||
const targetBeltComp = targetEntity.components.Belt;
|
||||
|
||||
@ -236,19 +226,18 @@ export class BeltPath extends BasicSerializableObject {
|
||||
const targetAcceptorComp = targetEntity.components.ItemAcceptor;
|
||||
if (!targetAcceptorComp) {
|
||||
// Entity doesn't accept items
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
const ejectingDirection = targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection);
|
||||
const matchingSlot = targetAcceptorComp.findMatchingSlot(
|
||||
targetStaticComp.worldToLocalTile(ejectSlotTargetWsTile),
|
||||
ejectingDirection,
|
||||
lastEntity.layer
|
||||
ejectingDirection
|
||||
);
|
||||
|
||||
if (!matchingSlot) {
|
||||
// No matching slot found
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
@ -406,7 +395,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
this.onPathChanged();
|
||||
|
||||
// Extend the path length
|
||||
const additionalLength = beltComp.getEffectiveLengthTiles(entity.layer);
|
||||
const additionalLength = beltComp.getEffectiveLengthTiles();
|
||||
this.totalLength += additionalLength;
|
||||
DEBUG && logger.log(" Extended total length by", additionalLength, "to", this.totalLength);
|
||||
|
||||
@ -449,7 +438,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
|
||||
// All items on that belt are simply lost (for now)
|
||||
|
||||
const length = beltComp.getEffectiveLengthTiles(entity.layer);
|
||||
const length = beltComp.getEffectiveLengthTiles();
|
||||
|
||||
// Extend the length of this path
|
||||
this.totalLength += length;
|
||||
@ -501,7 +490,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
const beltComp = entity.components.Belt;
|
||||
beltComp.assignedPath = null;
|
||||
|
||||
const entityLength = beltComp.getEffectiveLengthTiles(entity.layer);
|
||||
const entityLength = beltComp.getEffectiveLengthTiles();
|
||||
assert(this.entityPath.indexOf(entity) >= 0, "Entity not contained for split");
|
||||
assert(this.entityPath.indexOf(entity) !== 0, "Entity is first");
|
||||
assert(this.entityPath.indexOf(entity) !== this.entityPath.length - 1, "Entity is last");
|
||||
@ -519,7 +508,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
|
||||
++firstPathEntityCount;
|
||||
firstPathEndEntity = otherEntity;
|
||||
firstPathLength += otherEntity.components.Belt.getEffectiveLengthTiles(otherEntity.layer);
|
||||
firstPathLength += otherEntity.components.Belt.getEffectiveLengthTiles();
|
||||
}
|
||||
|
||||
DEBUG &&
|
||||
@ -663,7 +652,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
|
||||
// Ok, first remove the entity
|
||||
const beltComp = entity.components.Belt;
|
||||
const beltLength = beltComp.getEffectiveLengthTiles(entity.layer);
|
||||
const beltLength = beltComp.getEffectiveLengthTiles();
|
||||
|
||||
DEBUG &&
|
||||
logger.log(
|
||||
@ -772,7 +761,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
|
||||
// Ok, first remove the entity
|
||||
const beltComp = entity.components.Belt;
|
||||
const beltLength = beltComp.getEffectiveLengthTiles(entity.layer);
|
||||
const beltLength = beltComp.getEffectiveLengthTiles();
|
||||
|
||||
DEBUG &&
|
||||
logger.log(
|
||||
@ -912,7 +901,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
beltComp.assignedPath = this;
|
||||
|
||||
// Update our length
|
||||
const additionalLength = beltComp.getEffectiveLengthTiles(entity.layer);
|
||||
const additionalLength = beltComp.getEffectiveLengthTiles();
|
||||
this.totalLength += additionalLength;
|
||||
}
|
||||
|
||||
@ -970,7 +959,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
let length = 0;
|
||||
for (let i = 0; i < this.entityPath.length; ++i) {
|
||||
const entity = this.entityPath[i];
|
||||
length += entity.components.Belt.getEffectiveLengthTiles(this.layer);
|
||||
length += entity.components.Belt.getEffectiveLengthTiles();
|
||||
}
|
||||
return length;
|
||||
}
|
||||
@ -985,9 +974,9 @@ export class BeltPath extends BasicSerializableObject {
|
||||
|
||||
// Divide by item spacing on belts since we use throughput and not speed
|
||||
let beltSpeed =
|
||||
this.root.hubGoals.getBeltBaseSpeed(this.layer) *
|
||||
this.root.hubGoals.getBeltBaseSpeed() *
|
||||
this.root.dynamicTickrate.deltaSeconds *
|
||||
this.getItemSpacing();
|
||||
globalConfig.itemSpacingOnBelts;
|
||||
|
||||
if (G_IS_DEV && globalConfig.debug.instantBelts) {
|
||||
beltSpeed *= 100;
|
||||
@ -1014,7 +1003,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
break;
|
||||
}
|
||||
|
||||
minimumDistance = this.getItemSpacing();
|
||||
minimumDistance = globalConfig.itemSpacingOnBelts;
|
||||
}
|
||||
|
||||
// Check if we have an item which is ready to be emitted
|
||||
@ -1060,14 +1049,14 @@ export class BeltPath extends BasicSerializableObject {
|
||||
|
||||
for (let i = 0; i < this.entityPath.length; ++i) {
|
||||
const beltComp = this.entityPath[i].components.Belt;
|
||||
const localLength = beltComp.getEffectiveLengthTiles(this.layer);
|
||||
const localLength = beltComp.getEffectiveLengthTiles();
|
||||
|
||||
if (currentLength + localLength >= progress || i === this.entityPath.length - 1) {
|
||||
// Min required here due to floating point issues
|
||||
const localProgress = Math.min(1.0, progress - currentLength);
|
||||
|
||||
assert(localProgress >= 0.0, "Invalid local progress: " + localProgress);
|
||||
const localSpace = beltComp.transformBeltToLocalSpace(localProgress, this.layer);
|
||||
const localSpace = beltComp.transformBeltToLocalSpace(localProgress);
|
||||
return this.entityPath[i].components.StaticMapEntity.localTileToWorld(localSpace);
|
||||
}
|
||||
currentLength += localLength;
|
||||
@ -1085,11 +1074,6 @@ export class BeltPath extends BasicSerializableObject {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.entityPath[0].layer !== this.root.currentLayer) {
|
||||
// Don't draw
|
||||
return;
|
||||
}
|
||||
|
||||
parameters.context.fillStyle = "#d79a25";
|
||||
parameters.context.strokeStyle = "#d79a25";
|
||||
parameters.context.beginPath();
|
||||
@ -1171,7 +1155,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
for (let i = 0; i < this.entityPath.length; ++i) {
|
||||
const entity = this.entityPath[i];
|
||||
const beltComp = entity.components.Belt;
|
||||
const beltLength = beltComp.getEffectiveLengthTiles(this.layer);
|
||||
const beltLength = beltComp.getEffectiveLengthTiles();
|
||||
|
||||
// Check if the current items are on the belt
|
||||
while (trackPos + beltLength >= currentItemPos - 1e-51) {
|
||||
@ -1182,7 +1166,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||
"invalid track pos: " + currentItemPos + " vs " + trackPos + " (l =" + beltLength + ")"
|
||||
);
|
||||
|
||||
const localPos = beltComp.transformBeltToLocalSpace(currentItemPos - trackPos, this.layer);
|
||||
const localPos = beltComp.transformBeltToLocalSpace(currentItemPos - trackPos);
|
||||
const worldPos = staticComp.localTileToWorld(localPos).toWorldSpaceCenterOfTile();
|
||||
|
||||
const distanceAndItem = this.items[currentItemIndex];
|
||||
|
@ -1,108 +0,0 @@
|
||||
import { formatItemsPerSecond } from "../../core/utils";
|
||||
import { enumDirection, Vector } from "../../core/vector";
|
||||
import { T } from "../../translations";
|
||||
import { enumItemType } from "../base_item";
|
||||
import { EnergyConsumerComponent } from "../components/energy_consumer";
|
||||
import { ItemAcceptorComponent } from "../components/item_acceptor";
|
||||
import { ItemEjectorComponent } from "../components/item_ejector";
|
||||
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
|
||||
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
|
||||
import { Entity } from "../entity";
|
||||
import { MetaBuilding } from "../meta_building";
|
||||
import { enumLayer, GameRoot } from "../root";
|
||||
|
||||
export class MetaAdvancedProcessorBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("advanced_processor");
|
||||
}
|
||||
|
||||
getSilhouetteColor() {
|
||||
return "#25d7b8";
|
||||
}
|
||||
|
||||
getDimensions(variant) {
|
||||
return new Vector(2, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GameRoot} root
|
||||
* @param {string} variant
|
||||
* @returns {Array<[string, string]>}
|
||||
*/
|
||||
getAdditionalStatistics(root, variant) {
|
||||
const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.advancedProcessor);
|
||||
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GameRoot} root
|
||||
*/
|
||||
getIsUnlocked(root) {
|
||||
// TODO
|
||||
return true;
|
||||
// return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_and_trash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
setupEntityComponents(entity) {
|
||||
entity.addComponent(
|
||||
new ItemProcessorComponent({
|
||||
inputsPerCharge: 1,
|
||||
processorType: enumItemProcessorTypes.advancedProcessor,
|
||||
})
|
||||
);
|
||||
entity.addComponent(
|
||||
new ItemEjectorComponent({
|
||||
slots: [
|
||||
{ pos: new Vector(1, 0), direction: enumDirection.right },
|
||||
{ pos: new Vector(1, 0), direction: enumDirection.top, layer: enumLayer.wires },
|
||||
],
|
||||
})
|
||||
);
|
||||
entity.addComponent(
|
||||
new EnergyConsumerComponent({
|
||||
bufferSize: 3,
|
||||
perCharge: 1,
|
||||
batteryPosition: new Vector(0.63, 0.7),
|
||||
acceptorSlotIndex: 1,
|
||||
ejectorSlotIndex: 1,
|
||||
})
|
||||
);
|
||||
|
||||
entity.addComponent(
|
||||
new WiredPinsComponent({
|
||||
slots: [
|
||||
{
|
||||
pos: new Vector(0, 0),
|
||||
direction: enumDirection.top,
|
||||
type: enumPinSlotType.positiveEnergyAcceptor,
|
||||
},
|
||||
{
|
||||
pos: new Vector(1, 0),
|
||||
direction: enumDirection.top,
|
||||
type: enumPinSlotType.negativeEnergyEjector,
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
entity.addComponent(
|
||||
new ItemAcceptorComponent({
|
||||
slots: [
|
||||
{
|
||||
pos: new Vector(0, 1),
|
||||
directions: [enumDirection.left],
|
||||
},
|
||||
{
|
||||
pos: new Vector(0, 0),
|
||||
directions: [enumDirection.top],
|
||||
filter: enumItemType.positiveEnergy,
|
||||
layer: enumLayer.wires,
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@ export class MetaBeltBaseBuilding extends MetaBuilding {
|
||||
* @returns {Array<[string, string]>}
|
||||
*/
|
||||
getAdditionalStatistics(root, variant) {
|
||||
const beltSpeed = root.hubGoals.getBeltBaseSpeed(enumLayer.regular);
|
||||
const beltSpeed = root.hubGoals.getBeltBaseSpeed();
|
||||
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]];
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ export class MetaBeltBaseBuilding extends MetaBuilding {
|
||||
const bottomDirection = enumAngleToDirection[(rotation + 180) % 360];
|
||||
const leftDirection = enumAngleToDirection[(rotation + 270) % 360];
|
||||
|
||||
const { ejectors, acceptors } = root.logic.getEjectorsAndAcceptorsAtTile(tile, layer);
|
||||
const { ejectors, acceptors } = root.logic.getEjectorsAndAcceptorsAtTile(tile);
|
||||
|
||||
let hasBottomEjector = false;
|
||||
let hasRightEjector = false;
|
||||
|
@ -1,108 +0,0 @@
|
||||
import { enumDirection, Vector } from "../../core/vector";
|
||||
import { enumItemType } from "../base_item";
|
||||
import { EnergyGeneratorComponent } from "../components/energy_generator";
|
||||
import { ItemAcceptorComponent } from "../components/item_acceptor";
|
||||
import { ItemEjectorComponent } from "../components/item_ejector";
|
||||
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
|
||||
import { Entity } from "../entity";
|
||||
import { MetaBuilding } from "../meta_building";
|
||||
import { enumLayer, GameRoot } from "../root";
|
||||
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||
|
||||
export class MetaEnergyGenerator extends MetaBuilding {
|
||||
constructor() {
|
||||
super("energy_generator");
|
||||
}
|
||||
|
||||
getSilhouetteColor() {
|
||||
return "#c425d7";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GameRoot} root
|
||||
* @param {string} variant
|
||||
* @returns {Array<[string, string]>}
|
||||
*/
|
||||
getAdditionalStatistics(root, variant) {
|
||||
// TODO
|
||||
return [];
|
||||
}
|
||||
|
||||
getDimensions(variant) {
|
||||
return new Vector(2, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GameRoot} root
|
||||
*/
|
||||
getIsUnlocked(root) {
|
||||
return true;
|
||||
// return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_and_trash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
setupEntityComponents(entity) {
|
||||
entity.addComponent(
|
||||
new ItemAcceptorComponent({
|
||||
slots: [
|
||||
{
|
||||
pos: new Vector(0, 1),
|
||||
directions: [enumDirection.bottom],
|
||||
filter: enumItemType.shape,
|
||||
},
|
||||
{
|
||||
pos: new Vector(1, 1),
|
||||
directions: [enumDirection.bottom],
|
||||
filter: enumItemType.shape,
|
||||
},
|
||||
{
|
||||
pos: new Vector(1, 0),
|
||||
directions: [enumDirection.top],
|
||||
layer: enumLayer.wires,
|
||||
filter: enumItemType.negativeEnergy,
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
entity.addComponent(
|
||||
new ItemEjectorComponent({
|
||||
slots: [
|
||||
{
|
||||
pos: new Vector(0, 0),
|
||||
direction: enumDirection.top,
|
||||
layer: enumLayer.wires,
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
entity.addComponent(
|
||||
new EnergyGeneratorComponent({
|
||||
// Set by the energy generator system later
|
||||
requiredKey: null,
|
||||
wasteAcceptorSlotIndex: 2,
|
||||
})
|
||||
);
|
||||
|
||||
entity.addComponent(
|
||||
new WiredPinsComponent({
|
||||
slots: [
|
||||
{
|
||||
pos: new Vector(0, 0),
|
||||
type: enumPinSlotType.positiveEnergyEjector,
|
||||
direction: enumDirection.top,
|
||||
},
|
||||
{
|
||||
pos: new Vector(1, 0),
|
||||
type: enumPinSlotType.negativeEnergyAcceptor,
|
||||
direction: enumDirection.top,
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
import { Loader } from "../../core/loader";
|
||||
import { enumDirection } from "../../core/vector";
|
||||
import { enumLayer } from "../root";
|
||||
import { arrayBeltVariantToRotation, MetaBeltBaseBuilding } from "./belt_base";
|
||||
|
||||
export class MetaWireBaseBuilding extends MetaBeltBaseBuilding {
|
||||
constructor() {
|
||||
super("wire");
|
||||
}
|
||||
|
||||
getSilhouetteColor() {
|
||||
return "#c425d7";
|
||||
}
|
||||
|
||||
getLayer() {
|
||||
return enumLayer.wires;
|
||||
}
|
||||
|
||||
getPreviewSprite(rotationVariant) {
|
||||
switch (arrayBeltVariantToRotation[rotationVariant]) {
|
||||
case enumDirection.top: {
|
||||
return Loader.getSprite("sprites/buildings/wire_top.png");
|
||||
}
|
||||
case enumDirection.left: {
|
||||
return Loader.getSprite("sprites/buildings/wire_left.png");
|
||||
}
|
||||
case enumDirection.right: {
|
||||
return Loader.getSprite("sprites/buildings/wire_right.png");
|
||||
}
|
||||
default: {
|
||||
assertAlways(false, "Invalid belt rotation variant");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getBlueprintSprite(rotationVariant) {
|
||||
switch (arrayBeltVariantToRotation[rotationVariant]) {
|
||||
case enumDirection.top: {
|
||||
return Loader.getSprite("sprites/blueprints/wire_top.png");
|
||||
}
|
||||
case enumDirection.left: {
|
||||
return Loader.getSprite("sprites/blueprints/wire_left.png");
|
||||
}
|
||||
case enumDirection.right: {
|
||||
return Loader.getSprite("sprites/blueprints/wire_right.png");
|
||||
}
|
||||
default: {
|
||||
assertAlways(false, "Invalid belt rotation variant");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
import { enumDirection, Vector } from "../../core/vector";
|
||||
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 { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
||||
import { enumLayer, GameRoot } from "../root";
|
||||
|
||||
/** @enum {string} */
|
||||
export const enumWireCrossingVariants = {
|
||||
// Default = splitter
|
||||
merger: "merger",
|
||||
};
|
||||
|
||||
export class MetaWireCrossingsBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("wire_crossings");
|
||||
}
|
||||
|
||||
getDimensions(variant) {
|
||||
return new Vector(1, 1);
|
||||
}
|
||||
|
||||
getSilhouetteColor() {
|
||||
return "#c425d7";
|
||||
}
|
||||
|
||||
getLayer() {
|
||||
return enumLayer.wires;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GameRoot} root
|
||||
*/
|
||||
getAvailableVariants(root) {
|
||||
return [defaultBuildingVariant, enumWireCrossingVariants.merger];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GameRoot} root
|
||||
*/
|
||||
getIsUnlocked(root) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
setupEntityComponents(entity) {
|
||||
entity.addComponent(
|
||||
new ItemAcceptorComponent({
|
||||
slots: [], // set later
|
||||
})
|
||||
);
|
||||
|
||||
entity.addComponent(
|
||||
new ItemProcessorComponent({
|
||||
inputsPerCharge: 1,
|
||||
processorType: enumItemProcessorTypes.splitterWires,
|
||||
})
|
||||
);
|
||||
|
||||
entity.addComponent(
|
||||
new ItemEjectorComponent({
|
||||
slots: [], // set later
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Entity} entity
|
||||
* @param {number} rotationVariant
|
||||
* @param {string} variant
|
||||
*/
|
||||
updateVariants(entity, rotationVariant, variant) {
|
||||
switch (variant) {
|
||||
case defaultBuildingVariant: {
|
||||
entity.components.ItemAcceptor.setSlots([
|
||||
{
|
||||
pos: new Vector(0, 0),
|
||||
directions: [enumDirection.bottom],
|
||||
layer: enumLayer.wires,
|
||||
},
|
||||
]);
|
||||
|
||||
entity.components.ItemEjector.setSlots([
|
||||
{ pos: new Vector(0, 0), direction: enumDirection.top, layer: enumLayer.wires },
|
||||
{ pos: new Vector(0, 0), direction: enumDirection.right, layer: enumLayer.wires },
|
||||
]);
|
||||
|
||||
break;
|
||||
}
|
||||
case enumWireCrossingVariants.merger: {
|
||||
entity.components.ItemAcceptor.setSlots([
|
||||
{
|
||||
pos: new Vector(0, 0),
|
||||
directions: [enumDirection.top],
|
||||
layer: enumLayer.wires,
|
||||
},
|
||||
{
|
||||
pos: new Vector(0, 0),
|
||||
directions: [enumDirection.right],
|
||||
layer: enumLayer.wires,
|
||||
},
|
||||
]);
|
||||
|
||||
entity.components.ItemEjector.setSlots([
|
||||
{ pos: new Vector(0, 0), direction: enumDirection.bottom, layer: enumLayer.wires },
|
||||
]);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assertAlways(false, "Unknown painter variant: " + variant);
|
||||
}
|
||||
}
|
||||
}
|
@ -10,8 +10,6 @@ export const enumColors = {
|
||||
|
||||
white: "white",
|
||||
uncolored: "uncolored",
|
||||
|
||||
black: "black",
|
||||
};
|
||||
|
||||
/** @enum {string} */
|
||||
@ -26,8 +24,6 @@ export const enumColorToShortcode = {
|
||||
|
||||
[enumColors.white]: "w",
|
||||
[enumColors.uncolored]: "u",
|
||||
|
||||
[enumColors.black]: "0",
|
||||
};
|
||||
|
||||
/** @enum {enumColors} */
|
||||
@ -54,27 +50,9 @@ export const enumColorsToHexCode = {
|
||||
// blue + green + red
|
||||
[enumColors.white]: "#ffffff",
|
||||
|
||||
[enumColors.black]: "#31383a",
|
||||
|
||||
[enumColors.uncolored]: "#aaaaaa",
|
||||
};
|
||||
|
||||
/** @enum {enumColors} */
|
||||
export const enumInvertedColors = {
|
||||
[enumColors.red]: enumColors.cyan,
|
||||
[enumColors.green]: enumColors.purple,
|
||||
[enumColors.blue]: enumColors.yellow,
|
||||
|
||||
[enumColors.yellow]: enumColors.blue,
|
||||
[enumColors.purple]: enumColors.green,
|
||||
[enumColors.cyan]: enumColors.red,
|
||||
|
||||
[enumColors.white]: enumColors.black,
|
||||
[enumColors.black]: enumColors.white,
|
||||
|
||||
[enumColors.uncolored]: enumColors.uncolored,
|
||||
};
|
||||
|
||||
const c = enumColors;
|
||||
/** @enum {Object.<string, string>} */
|
||||
export const enumColorMixingResults = {
|
||||
@ -88,7 +66,6 @@ export const enumColorMixingResults = {
|
||||
[c.cyan]: c.white,
|
||||
|
||||
[c.white]: c.white,
|
||||
[c.black]: c.red,
|
||||
},
|
||||
|
||||
// 0, 255, 0
|
||||
@ -100,7 +77,6 @@ export const enumColorMixingResults = {
|
||||
[c.cyan]: c.cyan,
|
||||
|
||||
[c.white]: c.white,
|
||||
[c.black]: c.green,
|
||||
},
|
||||
|
||||
// 0, 255, 0
|
||||
@ -110,20 +86,17 @@ export const enumColorMixingResults = {
|
||||
[c.cyan]: c.cyan,
|
||||
|
||||
[c.white]: c.white,
|
||||
[c.black]: c.blue,
|
||||
},
|
||||
|
||||
// 255, 255, 0
|
||||
[c.yellow]: {
|
||||
[c.purple]: c.white,
|
||||
[c.cyan]: c.white,
|
||||
[c.black]: c.yellow,
|
||||
},
|
||||
|
||||
// 255, 0, 255
|
||||
[c.purple]: {
|
||||
[c.cyan]: c.white,
|
||||
[c.black]: c.purple,
|
||||
},
|
||||
|
||||
// 0, 255, 255
|
||||
@ -140,24 +113,12 @@ export const enumColorMixingResults = {
|
||||
[c.uncolored]: {
|
||||
// auto
|
||||
},
|
||||
|
||||
[c.black]: {
|
||||
// auto
|
||||
[c.white]: c.uncolored,
|
||||
[c.cyan]: c.cyan,
|
||||
[c.uncolored]: c.uncolored,
|
||||
},
|
||||
};
|
||||
|
||||
// Create same color lookups
|
||||
for (const color in enumColors) {
|
||||
enumColorMixingResults[color][color] = color;
|
||||
|
||||
// Anything with white is white again, except for black which creates gray
|
||||
if (color !== enumColors.black) {
|
||||
enumColorMixingResults[color][c.white] = c.white;
|
||||
}
|
||||
|
||||
enumColorMixingResults[color][c.white] = c.white;
|
||||
// Anything with uncolored is the same color
|
||||
enumColorMixingResults[color][c.uncolored] = color;
|
||||
}
|
||||
|
@ -10,9 +10,7 @@ import { UndergroundBeltComponent } from "./components/underground_belt";
|
||||
import { UnremovableComponent } from "./components/unremovable";
|
||||
import { HubComponent } from "./components/hub";
|
||||
import { StorageComponent } from "./components/storage";
|
||||
import { EnergyGeneratorComponent } from "./components/energy_generator";
|
||||
import { WiredPinsComponent } from "./components/wired_pins";
|
||||
import { EnergyConsumerComponent } from "./components/energy_consumer";
|
||||
import { BeltUnderlaysComponent } from "./components/belt_underlays";
|
||||
|
||||
export function initComponentRegistry() {
|
||||
@ -27,9 +25,7 @@ export function initComponentRegistry() {
|
||||
gComponentRegistry.register(UnremovableComponent);
|
||||
gComponentRegistry.register(HubComponent);
|
||||
gComponentRegistry.register(StorageComponent);
|
||||
gComponentRegistry.register(EnergyGeneratorComponent);
|
||||
gComponentRegistry.register(WiredPinsComponent);
|
||||
gComponentRegistry.register(EnergyConsumerComponent);
|
||||
gComponentRegistry.register(BeltUnderlaysComponent);
|
||||
|
||||
// IMPORTANT ^^^^^ UPDATE ENTITY COMPONENT STORAGE AFTERWARDS
|
||||
|
@ -11,7 +11,6 @@ export const curvedBeltLength = /* Math.PI / 4 */ 0.78;
|
||||
export const FAKE_BELT_ACCEPTOR_SLOT = {
|
||||
pos: new Vector(0, 0),
|
||||
directions: [enumDirection.bottom],
|
||||
layer: enumLayer.regular,
|
||||
};
|
||||
|
||||
/** @type {Object<enumDirection, import("./item_ejector").ItemEjectorSlot>} */
|
||||
@ -20,7 +19,6 @@ export const FAKE_BELT_EJECTOR_SLOT_BY_DIRECTION = {
|
||||
pos: new Vector(0, 0),
|
||||
direction: enumDirection.top,
|
||||
item: null,
|
||||
layer: enumLayer.regular,
|
||||
progress: 0,
|
||||
},
|
||||
|
||||
@ -28,7 +26,6 @@ export const FAKE_BELT_EJECTOR_SLOT_BY_DIRECTION = {
|
||||
pos: new Vector(0, 0),
|
||||
direction: enumDirection.right,
|
||||
item: null,
|
||||
layer: enumLayer.regular,
|
||||
progress: 0,
|
||||
},
|
||||
|
||||
@ -36,7 +33,6 @@ export const FAKE_BELT_EJECTOR_SLOT_BY_DIRECTION = {
|
||||
pos: new Vector(0, 0),
|
||||
direction: enumDirection.left,
|
||||
item: null,
|
||||
layer: enumLayer.regular,
|
||||
progress: 0,
|
||||
},
|
||||
};
|
||||
@ -79,14 +75,9 @@ export class BeltComponent extends Component {
|
||||
|
||||
/**
|
||||
* Returns the effective length of this belt in tile space
|
||||
* @param {enumLayer} layer
|
||||
* @returns {number}
|
||||
*/
|
||||
getEffectiveLengthTiles(layer) {
|
||||
assert(layer, "no layer given");
|
||||
if (layer === enumLayer.wires) {
|
||||
return 1.0;
|
||||
}
|
||||
getEffectiveLengthTiles() {
|
||||
return this.direction === enumDirection.top ? 1.0 : curvedBeltLength;
|
||||
}
|
||||
|
||||
@ -115,62 +106,28 @@ export class BeltComponent extends Component {
|
||||
* Converts from belt space (0 = start of belt ... 1 = end of belt) to the local
|
||||
* belt coordinates (-0.5|-0.5 to 0.5|0.5)
|
||||
* @param {number} progress
|
||||
* @param {enumLayer} layer
|
||||
* @returns {Vector}
|
||||
*/
|
||||
transformBeltToLocalSpace(progress, layer) {
|
||||
transformBeltToLocalSpace(progress) {
|
||||
assert(progress >= 0.0, "Invalid progress ( < 0): " + progress);
|
||||
switch (this.direction) {
|
||||
case enumDirection.top:
|
||||
assert(progress <= 1.02, "Invalid progress: " + progress);
|
||||
return new Vector(0, 0.5 - progress);
|
||||
|
||||
switch (layer) {
|
||||
case enumLayer.regular: {
|
||||
switch (this.direction) {
|
||||
case enumDirection.top:
|
||||
assert(progress <= 1.02, "Invalid progress: " + progress);
|
||||
return new Vector(0, 0.5 - progress);
|
||||
|
||||
case enumDirection.right: {
|
||||
assert(progress <= curvedBeltLength + 0.02, "Invalid progress 2: " + progress);
|
||||
const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI;
|
||||
return new Vector(
|
||||
0.5 - 0.5 * Math.cos(arcProgress),
|
||||
0.5 - 0.5 * Math.sin(arcProgress)
|
||||
);
|
||||
}
|
||||
case enumDirection.left: {
|
||||
assert(progress <= curvedBeltLength + 0.02, "Invalid progress 3: " + progress);
|
||||
const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI;
|
||||
return new Vector(
|
||||
-0.5 + 0.5 * Math.cos(arcProgress),
|
||||
0.5 - 0.5 * Math.sin(arcProgress)
|
||||
);
|
||||
}
|
||||
default:
|
||||
assertAlways(false, "Invalid belt direction: " + this.direction);
|
||||
return new Vector(0, 0);
|
||||
}
|
||||
case enumDirection.right: {
|
||||
assert(progress <= curvedBeltLength + 0.02, "Invalid progress 2: " + progress);
|
||||
const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI;
|
||||
return new Vector(0.5 - 0.5 * Math.cos(arcProgress), 0.5 - 0.5 * Math.sin(arcProgress));
|
||||
}
|
||||
case enumLayer.wires: {
|
||||
const pow = 0.5;
|
||||
switch (this.direction) {
|
||||
case enumDirection.top:
|
||||
assert(progress <= 1.02, "Invalid progress: " + progress);
|
||||
return new Vector(0, 0.5 - progress);
|
||||
|
||||
case enumDirection.right: {
|
||||
assert(progress <= 1.02, "Invalid progress 2: " + progress);
|
||||
return progress > 0.5 ? new Vector(progress - 0.5, 0) : new Vector(0, 0.5 - progress);
|
||||
}
|
||||
case enumDirection.left: {
|
||||
assert(progress <= 1.02, "Invalid progress 3: " + progress);
|
||||
return progress > 0.5
|
||||
? new Vector(-progress + 0.5, 0)
|
||||
: new Vector(0, 0.5 - progress);
|
||||
}
|
||||
default:
|
||||
assertAlways(false, "Invalid belt direction: " + this.direction);
|
||||
return new Vector(0, 0);
|
||||
}
|
||||
case enumDirection.left: {
|
||||
assert(progress <= curvedBeltLength + 0.02, "Invalid progress 3: " + progress);
|
||||
const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI;
|
||||
return new Vector(-0.5 + 0.5 * Math.cos(arcProgress), 0.5 - 0.5 * Math.sin(arcProgress));
|
||||
}
|
||||
default:
|
||||
assertAlways(false, "Invalid belt direction: " + this.direction);
|
||||
return new Vector(0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,133 +0,0 @@
|
||||
import { Component } from "../component";
|
||||
import { types } from "../../savegame/serialization";
|
||||
import { Vector } from "../../core/vector";
|
||||
import { BaseItem, enumItemTypeToLayer, enumItemType } from "../base_item";
|
||||
|
||||
export class EnergyConsumerComponent extends Component {
|
||||
static getId() {
|
||||
return "EnergyConsumer";
|
||||
}
|
||||
|
||||
static getSchema() {
|
||||
return {
|
||||
bufferSize: types.float,
|
||||
perCharge: types.float,
|
||||
batteryPosition: types.vector,
|
||||
energyType: types.enum(enumItemType),
|
||||
wasteType: types.enum(enumItemType),
|
||||
acceptorSlotIndex: types.uint,
|
||||
ejectorSlotIndex: types.uint,
|
||||
|
||||
stored: types.float,
|
||||
piledOutput: types.float,
|
||||
};
|
||||
}
|
||||
|
||||
duplicateWithoutContents() {
|
||||
return new EnergyConsumerComponent({
|
||||
bufferSize: this.bufferSize,
|
||||
perCharge: this.perCharge,
|
||||
batteryPosition: this.batteryPosition.copy(),
|
||||
acceptorSlotIndex: this.acceptorSlotIndex,
|
||||
ejectorSlotIndex: this.ejectorSlotIndex,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object} param0
|
||||
* @param {number} param0.bufferSize How much energy this consumer can store
|
||||
* @param {number} param0.perCharge How much energy this consumer needs per charge
|
||||
* @param {Vector} param0.batteryPosition world space render offset of the battery icon
|
||||
* @param {number} param0.acceptorSlotIndex Which slot to accept energy on
|
||||
* @param {number} param0.ejectorSlotIndex Which slot to eject energy off
|
||||
*
|
||||
*/
|
||||
constructor({
|
||||
bufferSize = 3,
|
||||
perCharge = 1,
|
||||
batteryPosition = new Vector(),
|
||||
acceptorSlotIndex = 0,
|
||||
ejectorSlotIndex = 0,
|
||||
}) {
|
||||
super();
|
||||
this.bufferSize = bufferSize;
|
||||
this.perCharge = perCharge;
|
||||
this.batteryPosition = batteryPosition;
|
||||
this.energyType = enumItemType.positiveEnergy;
|
||||
this.wasteType = enumItemType.negativeEnergy;
|
||||
this.acceptorSlotIndex = acceptorSlotIndex;
|
||||
this.ejectorSlotIndex = ejectorSlotIndex;
|
||||
|
||||
/**
|
||||
* How much energy we have stored right now
|
||||
*/
|
||||
this.stored = 0;
|
||||
|
||||
/**
|
||||
* How much waste we have piled up so far
|
||||
*/
|
||||
this.piledOutput = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to accept a given item
|
||||
* @param {BaseItem} item
|
||||
* @param {number} slotIndex
|
||||
*/
|
||||
tryAcceptItem(item, slotIndex) {
|
||||
if (slotIndex !== this.acceptorSlotIndex) {
|
||||
// Wrong slot
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item.getItemType() !== this.energyType) {
|
||||
// Not the right type
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.stored >= this.bufferSize) {
|
||||
// We are full
|
||||
return false;
|
||||
}
|
||||
|
||||
// All good, consume
|
||||
this.stored = Math.min(this.stored + 1, this.bufferSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to start the next charge
|
||||
*/
|
||||
tryStartNextCharge() {
|
||||
if (this.hasTooMuchWastePiled()) {
|
||||
// Too much waste remaining
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.stored < this.perCharge) {
|
||||
// Not enough energy stored
|
||||
return false;
|
||||
}
|
||||
|
||||
this.stored -= this.perCharge;
|
||||
this.piledOutput += this.perCharge;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if there is too much waste piled
|
||||
*/
|
||||
hasTooMuchWastePiled() {
|
||||
return this.piledOutput >= 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces the waste by the given amount
|
||||
* @param {number} amount
|
||||
*/
|
||||
reduceWaste(amount) {
|
||||
this.piledOutput = Math.max(0, this.piledOutput - amount);
|
||||
}
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
import { types } from "../../savegame/serialization";
|
||||
import { BaseItem, enumItemType } from "../base_item";
|
||||
import { Component } from "../component";
|
||||
import { ShapeItem } from "../items/shape_item";
|
||||
|
||||
const maxQueueSize = 4;
|
||||
|
||||
export class EnergyGeneratorComponent extends Component {
|
||||
static getId() {
|
||||
return "EnergyGenerator";
|
||||
}
|
||||
|
||||
static getSchema() {
|
||||
return {
|
||||
requiredKey: types.nullable(types.string),
|
||||
itemsInQueue: types.uint,
|
||||
wasteAcceptorSlotIndex: types.uint,
|
||||
};
|
||||
}
|
||||
|
||||
duplicateWithoutContents() {
|
||||
return new EnergyGeneratorComponent({
|
||||
requiredKey: null,
|
||||
wasteAcceptorSlotIndex: this.wasteAcceptorSlotIndex,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object} param0
|
||||
* @param {string=} param0.requiredKey Which shape this generator needs, can be null if not computed yet
|
||||
* @param {number} param0.wasteAcceptorSlotIndex Which slot accepts the waste
|
||||
*/
|
||||
constructor({ requiredKey, wasteAcceptorSlotIndex = 0 }) {
|
||||
super();
|
||||
this.requiredKey = requiredKey;
|
||||
|
||||
/**
|
||||
* Stores how many items are ready to be converted to energy
|
||||
* @type {number}
|
||||
*/
|
||||
this.itemsInQueue = 0;
|
||||
|
||||
/**
|
||||
* Stores which slot accepts the waste
|
||||
* @type {number}
|
||||
*/
|
||||
this.wasteAcceptorSlotIndex = wasteAcceptorSlotIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {BaseItem} item
|
||||
* @param {number} slot
|
||||
*/
|
||||
tryTakeItem(item, slot) {
|
||||
if (slot === this.wasteAcceptorSlotIndex) {
|
||||
// this is the acceptor slot on the wires layer
|
||||
// just destroy it
|
||||
return true;
|
||||
} else {
|
||||
if (item.getItemType() !== enumItemType.shape) {
|
||||
// This shouldn't happen since we have a filter - still, it doesn't hurt
|
||||
// to check either
|
||||
assertAlways(
|
||||
false,
|
||||
"Energy generator took wrong item: " +
|
||||
item.getItemType() +
|
||||
" on slot " +
|
||||
slot +
|
||||
" (waste slot = " +
|
||||
this.wasteAcceptorSlotIndex +
|
||||
")"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (/** @type {ShapeItem} */ (item).definition.getHash() !== this.requiredKey) {
|
||||
// Not our shape
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.itemsInQueue >= maxQueueSize) {
|
||||
// Queue is full
|
||||
return false;
|
||||
}
|
||||
|
||||
// Take item and put it into the queue
|
||||
++this.itemsInQueue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,6 @@ import { enumLayer } from "../root";
|
||||
/** @typedef {{
|
||||
* pos: Vector,
|
||||
* directions: enumDirection[],
|
||||
* layer: enumLayer,
|
||||
* filter?: enumItemType
|
||||
* }} ItemAcceptorSlot */
|
||||
|
||||
@ -22,7 +21,6 @@ import { enumLayer } from "../root";
|
||||
/** @typedef {{
|
||||
* pos: Vector,
|
||||
* directions: enumDirection[],
|
||||
* layer?: enumLayer,
|
||||
* filter?: enumItemType
|
||||
* }} ItemAcceptorSlotConfig */
|
||||
|
||||
@ -38,9 +36,6 @@ export class ItemAcceptorComponent extends Component {
|
||||
pos: types.vector,
|
||||
directions: types.array(types.enum(enumDirection)),
|
||||
filter: types.nullable(types.enum(enumItemType)),
|
||||
|
||||
// TODO: MIGRATE
|
||||
layer: types.enum(enumLayer),
|
||||
})
|
||||
),
|
||||
};
|
||||
@ -54,7 +49,6 @@ export class ItemAcceptorComponent extends Component {
|
||||
pos: slot.pos.copy(),
|
||||
directions: slot.directions.slice(),
|
||||
filter: slot.filter,
|
||||
layer: slot.layer,
|
||||
});
|
||||
}
|
||||
|
||||
@ -92,7 +86,6 @@ export class ItemAcceptorComponent extends Component {
|
||||
this.slots.push({
|
||||
pos: slot.pos,
|
||||
directions: slot.directions,
|
||||
layer: slot.layer || enumLayer.regular,
|
||||
|
||||
// Which type of item to accept (shape | color | all) @see enumItemType
|
||||
filter: slot.filter,
|
||||
@ -147,10 +140,9 @@ export class ItemAcceptorComponent extends Component {
|
||||
* Tries to find a slot which accepts the current item
|
||||
* @param {Vector} targetLocalTile
|
||||
* @param {enumDirection} fromLocalDirection
|
||||
* @param {enumLayer} layer
|
||||
* @returns {ItemAcceptorLocatedSlot|null}
|
||||
*/
|
||||
findMatchingSlot(targetLocalTile, fromLocalDirection, layer) {
|
||||
findMatchingSlot(targetLocalTile, fromLocalDirection) {
|
||||
// We need to invert our direction since the acceptor specifies *from* which direction
|
||||
// it accepts items, but the ejector specifies *into* which direction it ejects items.
|
||||
// E.g.: Ejector ejects into "right" direction but acceptor accepts from "left" direction.
|
||||
@ -165,11 +157,6 @@ export class ItemAcceptorComponent extends Component {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make sure the layer matches
|
||||
if (slot.layer !== layer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the acceptor slot accepts items from our direction
|
||||
for (let i = 0; i < slot.directions.length; ++i) {
|
||||
// const localDirection = targetStaticComp.localDirectionToWorld(slot.directions[l]);
|
||||
|
@ -12,7 +12,6 @@ import { BeltPath } from "../belt_path";
|
||||
* pos: Vector,
|
||||
* direction: enumDirection,
|
||||
* item: BaseItem,
|
||||
* layer: enumLayer,
|
||||
* progress: number?,
|
||||
* cachedDestSlot?: import("./item_acceptor").ItemAcceptorLocatedSlot,
|
||||
* cachedBeltPath?: BeltPath,
|
||||
@ -34,9 +33,6 @@ export class ItemEjectorComponent extends Component {
|
||||
direction: types.enum(enumDirection),
|
||||
item: types.nullable(types.obj(gItemRegistry)),
|
||||
progress: types.float,
|
||||
|
||||
// TODO: Migrate
|
||||
layer: types.enum(enumLayer),
|
||||
})
|
||||
),
|
||||
};
|
||||
@ -49,7 +45,6 @@ export class ItemEjectorComponent extends Component {
|
||||
slotsCopy.push({
|
||||
pos: slot.pos.copy(),
|
||||
direction: slot.direction,
|
||||
layer: slot.layer,
|
||||
});
|
||||
}
|
||||
|
||||
@ -61,7 +56,7 @@ export class ItemEjectorComponent extends Component {
|
||||
/**
|
||||
*
|
||||
* @param {object} param0
|
||||
* @param {Array<{pos: Vector, direction: enumDirection, layer?: enumLayer}>=} param0.slots The slots to eject on
|
||||
* @param {Array<{pos: Vector, direction: enumDirection }>=} param0.slots The slots to eject on
|
||||
*/
|
||||
constructor({ slots = [] }) {
|
||||
super();
|
||||
@ -75,7 +70,7 @@ export class ItemEjectorComponent extends Component {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<{pos: Vector, direction: enumDirection, layer?: enumLayer}>} slots The slots to eject on
|
||||
* @param {Array<{pos: Vector, direction: enumDirection }>} slots The slots to eject on
|
||||
*/
|
||||
setSlots(slots) {
|
||||
/** @type {Array<ItemEjectorSlot>} */
|
||||
@ -87,7 +82,6 @@ export class ItemEjectorComponent extends Component {
|
||||
direction: slot.direction,
|
||||
item: null,
|
||||
progress: 0,
|
||||
layer: slot.layer || enumLayer.regular,
|
||||
cachedDestSlot: null,
|
||||
cachedTargetEntity: null,
|
||||
});
|
||||
@ -108,11 +102,10 @@ export class ItemEjectorComponent extends Component {
|
||||
/**
|
||||
* Returns whether any slot ejects to the given local tile
|
||||
* @param {Vector} tile
|
||||
* @param {enumLayer} layer
|
||||
*/
|
||||
anySlotEjectsToLocalTile(tile, layer) {
|
||||
anySlotEjectsToLocalTile(tile) {
|
||||
for (let i = 0; i < this.slots.length; ++i) {
|
||||
if (this.getSlotTargetLocalTile(i).equals(tile) && this.slots[i].layer === layer) {
|
||||
if (this.getSlotTargetLocalTile(i).equals(tile)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -131,12 +124,11 @@ export class ItemEjectorComponent extends Component {
|
||||
|
||||
/**
|
||||
* Returns the first free slot on this ejector or null if there is none
|
||||
* @param {enumLayer} layer
|
||||
* @returns {number?}
|
||||
*/
|
||||
getFirstFreeSlot(layer) {
|
||||
getFirstFreeSlot() {
|
||||
for (let i = 0; i < this.slots.length; ++i) {
|
||||
if (this.canEjectOnSlot(i) && this.slots[i].layer === layer) {
|
||||
if (this.canEjectOnSlot(i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ export const enumItemProcessorTypes = {
|
||||
painter: "painter",
|
||||
painterDouble: "painterDouble",
|
||||
painterQuad: "painterQuad",
|
||||
advancedProcessor: "advancedProcessor",
|
||||
hub: "hub",
|
||||
};
|
||||
|
||||
|
@ -103,8 +103,7 @@ export class UndergroundBeltComponent extends Component {
|
||||
}
|
||||
|
||||
// Notice: We assume that for all items the travel distance is the same
|
||||
const maxItemsInTunnel =
|
||||
(2 + travelDistance) / globalConfig.beltItemSpacingByLayer[enumLayer.regular];
|
||||
const maxItemsInTunnel = (2 + travelDistance) / globalConfig.itemSpacingOnBelts;
|
||||
if (this.pendingItems.length >= maxItemsInTunnel) {
|
||||
// Simulate a real belt which gets full at some point
|
||||
return false;
|
||||
@ -114,8 +113,7 @@ export class UndergroundBeltComponent extends Component {
|
||||
// This corresponds to the item ejector - it needs 0.5 additional tiles to eject the item.
|
||||
// So instead of adding 1 we add 0.5 only.
|
||||
// Additionally it takes 1 tile for the acceptor which we just add on top.
|
||||
const travelDuration =
|
||||
(travelDistance + 1.5) / beltSpeed / globalConfig.beltItemSpacingByLayer[enumLayer.regular];
|
||||
const travelDuration = (travelDistance + 1.5) / beltSpeed / globalConfig.itemSpacingOnBelts;
|
||||
|
||||
this.pendingItems.push([item, travelDuration]);
|
||||
|
||||
|
@ -398,14 +398,14 @@ export class GameCore {
|
||||
|
||||
if (!this.root.camera.getIsMapOverlayActive()) {
|
||||
// Underlays for splitters / balancers
|
||||
systems.beltUnderlays.drawUnderlays(params, enumLayer.regular);
|
||||
systems.beltUnderlays.drawUnderlays(params);
|
||||
|
||||
// Belt items
|
||||
systems.belt.drawLayerBeltItems(params, enumLayer.regular);
|
||||
systems.belt.drawBeltItems(params);
|
||||
|
||||
// Items being ejected / accepted currently (animations)
|
||||
systems.itemEjector.drawLayer(params, enumLayer.regular);
|
||||
systems.itemAcceptor.drawLayer(params, enumLayer.regular);
|
||||
systems.itemEjector.draw(params);
|
||||
systems.itemAcceptor.draw(params);
|
||||
}
|
||||
|
||||
// Miner & Static map entities
|
||||
@ -415,28 +415,15 @@ export class GameCore {
|
||||
// HUB Overlay
|
||||
systems.hub.draw(params);
|
||||
|
||||
// Energy generator overlay
|
||||
systems.energyGenerator.draw(params);
|
||||
|
||||
// Storage items
|
||||
systems.storage.draw(params);
|
||||
|
||||
// Energy consumer (Battery icons)
|
||||
systems.energyConsumer.draw(params);
|
||||
}
|
||||
|
||||
// Green wires overlay (not within the if because it can fade)
|
||||
root.hud.parts.wiresOverlay.draw(params);
|
||||
|
||||
if (this.root.currentLayer === enumLayer.wires && !this.root.camera.getIsMapOverlayActive()) {
|
||||
// Belt sprites & Static map entities
|
||||
root.map.drawWiresLayer(params);
|
||||
|
||||
// Belt items as well as accepted / ejected items
|
||||
systems.belt.drawLayerBeltItems(params, enumLayer.wires);
|
||||
systems.itemEjector.drawLayer(params, enumLayer.wires);
|
||||
systems.itemAcceptor.drawLayer(params, enumLayer.wires);
|
||||
|
||||
// Static map entities
|
||||
root.map.drawWiresForegroundLayer(params);
|
||||
|
||||
// pins
|
||||
|
@ -169,9 +169,6 @@ export class Entity extends BasicSerializableObject {
|
||||
const ejectorSprite = Loader.getSprite("sprites/debug/ejector_slot.png");
|
||||
for (let i = 0; i < ejectorComp.slots.length; ++i) {
|
||||
const slot = ejectorComp.slots[i];
|
||||
if (slot.layer !== this.root.currentLayer) {
|
||||
continue;
|
||||
}
|
||||
const slotTile = staticComp.localTileToWorld(slot.pos);
|
||||
const direction = staticComp.localDirectionToWorld(slot.direction);
|
||||
const directionVector = enumDirectionToVector[direction];
|
||||
@ -194,9 +191,6 @@ export class Entity extends BasicSerializableObject {
|
||||
const acceptorSprite = Loader.getSprite("sprites/debug/acceptor_slot.png");
|
||||
for (let i = 0; i < acceptorComp.slots.length; ++i) {
|
||||
const slot = acceptorComp.slots[i];
|
||||
if (slot.layer !== this.root.currentLayer) {
|
||||
continue;
|
||||
}
|
||||
const slotTile = staticComp.localTileToWorld(slot.pos);
|
||||
for (let k = 0; k < slot.directions.length; ++k) {
|
||||
const direction = staticComp.localDirectionToWorld(slot.directions[k]);
|
||||
|
@ -13,9 +13,7 @@ import { HubSystem } from "./systems/hub";
|
||||
import { StaticMapEntitySystem } from "./systems/static_map_entity";
|
||||
import { ItemAcceptorSystem } from "./systems/item_acceptor";
|
||||
import { StorageSystem } from "./systems/storage";
|
||||
import { EnergyGeneratorSystem } from "./systems/energy_generator";
|
||||
import { WiredPinsSystem } from "./systems/wired_pins";
|
||||
import { EnergyConsumerSystem } from "./systems/energy_consumer";
|
||||
import { BeltUnderlaysSystem } from "./systems/belt_underlays";
|
||||
|
||||
const logger = createLogger("game_system_manager");
|
||||
@ -60,15 +58,9 @@ export class GameSystemManager {
|
||||
/** @type {StorageSystem} */
|
||||
storage: null,
|
||||
|
||||
/** @type {EnergyGeneratorSystem} */
|
||||
energyGenerator: null,
|
||||
|
||||
/** @type {WiredPinsSystem} */
|
||||
wiredPins: null,
|
||||
|
||||
/** @type {EnergyConsumerSystem} */
|
||||
energyConsumer: null,
|
||||
|
||||
/** @type {BeltUnderlaysSystem} */
|
||||
beltUnderlays: null,
|
||||
|
||||
@ -106,14 +98,10 @@ export class GameSystemManager {
|
||||
|
||||
add("hub", HubSystem);
|
||||
|
||||
add("energyGenerator", EnergyGeneratorSystem);
|
||||
|
||||
add("staticMapEntities", StaticMapEntitySystem);
|
||||
|
||||
add("wiredPins", WiredPinsSystem);
|
||||
|
||||
add("energyConsumer", EnergyConsumerSystem);
|
||||
|
||||
add("beltUnderlays", BeltUnderlaysSystem);
|
||||
|
||||
// IMPORTANT: Must be after belt system since belt system can change the
|
||||
|
@ -3,7 +3,7 @@ import { Component } from "./component";
|
||||
import { Entity } from "./entity";
|
||||
/* typehints:end */
|
||||
|
||||
import { GameRoot, enumLayer } from "./root";
|
||||
import { GameRoot } from "./root";
|
||||
import { GameSystem } from "./game_system";
|
||||
import { arrayDelete, arrayDeleteValue } from "../core/utils";
|
||||
import { DrawParameters } from "../core/draw_parameters";
|
||||
@ -39,9 +39,8 @@ export class GameSystemWithFilter extends GameSystem {
|
||||
* Calls a function for each matching entity on the screen, useful for drawing them
|
||||
* @param {DrawParameters} parameters
|
||||
* @param {function} callback
|
||||
* @param {enumLayer=} layerFilter Can be null for no filter
|
||||
*/
|
||||
forEachMatchingEntityOnScreen(parameters, callback, layerFilter = null) {
|
||||
forEachMatchingEntityOnScreen(parameters, callback) {
|
||||
const cullRange = parameters.visibleRect.toTileCullRectangle();
|
||||
if (this.allEntities.length < 100) {
|
||||
// So, its much quicker to simply perform per-entity checking
|
||||
@ -49,9 +48,7 @@ export class GameSystemWithFilter extends GameSystem {
|
||||
for (let i = 0; i < this.allEntities.length; ++i) {
|
||||
const entity = this.allEntities[i];
|
||||
if (cullRange.containsRect(entity.components.StaticMapEntity.getTileSpaceBounds())) {
|
||||
if (!layerFilter || entity.layer === layerFilter) {
|
||||
callback(parameters, entity);
|
||||
}
|
||||
callback(parameters, entity);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -94,11 +91,6 @@ export class GameSystemWithFilter extends GameSystem {
|
||||
entityLoop: for (let i = 0; i < entities.length; ++i) {
|
||||
const entity = entities[i];
|
||||
|
||||
// Avoid drawing non-layer contents
|
||||
if (layerFilter && entity.layer !== layerFilter) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Avoid drawing twice
|
||||
if (seenUids.has(entity.uid)) {
|
||||
continue;
|
||||
|
@ -367,13 +367,9 @@ export class HubGoals extends BasicSerializableObject {
|
||||
|
||||
/**
|
||||
* Belt speed
|
||||
* @param {enumLayer} layer
|
||||
* @returns {number} items / sec
|
||||
*/
|
||||
getBeltBaseSpeed(layer) {
|
||||
if (layer === enumLayer.wires) {
|
||||
return globalConfig.wiresSpeedItemsPerSecond;
|
||||
}
|
||||
getBeltBaseSpeed() {
|
||||
return globalConfig.beltSpeedItemsPerSecond * this.upgradeImprovements.belt;
|
||||
}
|
||||
|
||||
|
@ -440,11 +440,6 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic {
|
||||
for (let acceptorSlotIndex = 0; acceptorSlotIndex < slots.length; ++acceptorSlotIndex) {
|
||||
const slot = slots[acceptorSlotIndex];
|
||||
|
||||
// Only draw same layer slots
|
||||
if (slot.layer !== this.root.currentLayer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const acceptorSlotWsTile = staticComp.localTileToWorld(slot.pos);
|
||||
const acceptorSlotWsPos = acceptorSlotWsTile.toWorldSpaceCenterOfTile();
|
||||
|
||||
@ -478,20 +473,12 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic {
|
||||
|
||||
// If this entity is on the same layer as the slot - if so, it can either be
|
||||
// connected, or it can not be connected and thus block the input
|
||||
if (sourceEntity.layer === slot.layer) {
|
||||
if (
|
||||
sourceEjector &&
|
||||
sourceEjector.anySlotEjectsToLocalTile(
|
||||
ejectorAcceptLocalTile,
|
||||
this.root.currentLayer
|
||||
)
|
||||
) {
|
||||
// This one is connected, all good
|
||||
isConnected = true;
|
||||
} else {
|
||||
// This one is blocked
|
||||
isBlocked = true;
|
||||
}
|
||||
if (sourceEjector && sourceEjector.anySlotEjectsToLocalTile(ejectorAcceptLocalTile)) {
|
||||
// This one is connected, all good
|
||||
isConnected = true;
|
||||
} else {
|
||||
// This one is blocked
|
||||
isBlocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -520,11 +507,6 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic {
|
||||
for (let ejectorSlotIndex = 0; ejectorSlotIndex < slots.length; ++ejectorSlotIndex) {
|
||||
const slot = slots[ejectorSlotIndex];
|
||||
|
||||
// Only draw same layer slots
|
||||
if (slot.layer !== this.root.currentLayer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const ejectorSlotWsTile = staticComp.localTileToWorld(
|
||||
ejectorComp.getSlotTargetLocalTile(ejectorSlotIndex)
|
||||
);
|
||||
@ -546,21 +528,14 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic {
|
||||
const destAcceptor = destEntity.components.ItemAcceptor;
|
||||
const destStaticComp = destEntity.components.StaticMapEntity;
|
||||
|
||||
// If this entity is on the same layer as the slot - if so, it can either be
|
||||
// connected, or it can not be connected and thus block the input
|
||||
if (destEntity.layer === slot.layer) {
|
||||
const destLocalTile = destStaticComp.worldToLocalTile(ejectorSlotWsTile);
|
||||
const destLocalDir = destStaticComp.worldDirectionToLocal(ejectorSlotWsDirection);
|
||||
if (
|
||||
destAcceptor &&
|
||||
destAcceptor.findMatchingSlot(destLocalTile, destLocalDir, this.root.currentLayer)
|
||||
) {
|
||||
// This one is connected, all good
|
||||
isConnected = true;
|
||||
} else {
|
||||
// This one is blocked
|
||||
isBlocked = true;
|
||||
}
|
||||
const destLocalTile = destStaticComp.worldToLocalTile(ejectorSlotWsTile);
|
||||
const destLocalDir = destStaticComp.worldDirectionToLocal(ejectorSlotWsDirection);
|
||||
if (destAcceptor && destAcceptor.findMatchingSlot(destLocalTile, destLocalDir)) {
|
||||
// This one is connected, all good
|
||||
isConnected = true;
|
||||
} else {
|
||||
// This one is blocked
|
||||
isBlocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { MetaBeltBaseBuilding } from "../../buildings/belt_base";
|
||||
import { MetaCutterBuilding } from "../../buildings/cutter";
|
||||
import { MetaEnergyGenerator } from "../../buildings/energy_generator";
|
||||
import { MetaMinerBuilding } from "../../buildings/miner";
|
||||
import { MetaMixerBuilding } from "../../buildings/mixer";
|
||||
import { MetaPainterBuilding } from "../../buildings/painter";
|
||||
@ -11,7 +10,6 @@ import { MetaTrashBuilding } from "../../buildings/trash";
|
||||
import { MetaUndergroundBeltBuilding } from "../../buildings/underground_belt";
|
||||
import { enumLayer } from "../../root";
|
||||
import { HUDBaseToolbar } from "./base_toolbar";
|
||||
import { MetaAdvancedProcessorBuilding } from "../../buildings/advanced_processor";
|
||||
|
||||
const supportedBuildings = [
|
||||
MetaBeltBaseBuilding,
|
||||
@ -24,9 +22,6 @@ const supportedBuildings = [
|
||||
MetaMixerBuilding,
|
||||
MetaPainterBuilding,
|
||||
MetaTrashBuilding,
|
||||
|
||||
MetaEnergyGenerator,
|
||||
MetaAdvancedProcessorBuilding,
|
||||
];
|
||||
|
||||
export class HUDBuildingsToolbar extends HUDBaseToolbar {
|
||||
|
@ -66,9 +66,6 @@ export class HUDColorBlindHelper extends BaseHUDPart {
|
||||
if (ejectorComp) {
|
||||
for (let i = 0; i < ejectorComp.slots.length; ++i) {
|
||||
const slot = ejectorComp.slots[i];
|
||||
if (slot.layer !== this.root.currentLayer) {
|
||||
continue;
|
||||
}
|
||||
if (slot.item && slot.item.getItemType() === enumItemType.color) {
|
||||
return /** @type {ColorItem} */ (slot.item).color;
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { MetaWireBaseBuilding } from "../../buildings/wire_base";
|
||||
import { enumLayer } from "../../root";
|
||||
import { HUDBaseToolbar } from "./base_toolbar";
|
||||
import { MetaWireCrossingsBuilding } from "../../buildings/wire_crossings";
|
||||
|
||||
const supportedBuildings = [MetaWireBaseBuilding, MetaWireCrossingsBuilding];
|
||||
const supportedBuildings = [];
|
||||
|
||||
export class HUDWiresToolbar extends HUDBaseToolbar {
|
||||
constructor(root) {
|
||||
|
@ -92,7 +92,7 @@ export class TrailerMaker {
|
||||
const speed =
|
||||
globalConfig.tileSize *
|
||||
globalConfig.beltSpeedItemsPerSecond *
|
||||
globalConfig.beltItemSpacingByLayer[enumLayer.regular];
|
||||
globalConfig.itemSpacingOnBelts;
|
||||
// let time =
|
||||
// this.currentPlaybackOrigin.distance(Vector.fromSerializedObject(nextMarker.pos)) / speed;
|
||||
const time = nextMarker.time;
|
||||
|
@ -54,12 +54,6 @@ export const KEYMAPPINGS = {
|
||||
mixer: { keyCode: key("8") },
|
||||
painter: { keyCode: key("9") },
|
||||
trash: { keyCode: key("0") },
|
||||
energy_generator: { keyCode: key("O") },
|
||||
advanced_processor: { keyCode: key("P") },
|
||||
|
||||
// Wires layer
|
||||
wire: { keyCode: key("1") },
|
||||
wire_crossings: { keyCode: key("2") },
|
||||
},
|
||||
|
||||
placement: {
|
||||
|
@ -3,7 +3,7 @@ import { round2Digits } from "../core/utils";
|
||||
import { enumDirection, enumDirectionToVector, Vector } from "../core/vector";
|
||||
import { Entity } from "./entity";
|
||||
import { MetaBuilding } from "./meta_building";
|
||||
import { enumLayer, GameRoot } from "./root";
|
||||
import { GameRoot, enumLayer } from "./root";
|
||||
import { STOP_PROPAGATION } from "../core/signal";
|
||||
|
||||
const logger = createLogger("ingame/logic");
|
||||
@ -178,10 +178,9 @@ export class GameLogic {
|
||||
/**
|
||||
* Returns the acceptors and ejectors which affect the current tile
|
||||
* @param {Vector} tile
|
||||
* @param {enumLayer} layer
|
||||
* @returns {AcceptorsAndEjectorsAffectingTile}
|
||||
*/
|
||||
getEjectorsAndAcceptorsAtTile(tile, layer) {
|
||||
getEjectorsAndAcceptorsAtTile(tile) {
|
||||
/** @type {EjectorsAffectingTile} */
|
||||
let ejectors = [];
|
||||
/** @type {AcceptorsAffectingTile} */
|
||||
@ -194,10 +193,8 @@ export class GameLogic {
|
||||
continue;
|
||||
}
|
||||
|
||||
const entities = this.root.map.getLayersContentsMultipleXY(tile.x + dx, tile.y + dy);
|
||||
for (let i = 0; i < entities.length; ++i) {
|
||||
const entity = entities[i];
|
||||
|
||||
const entity = this.root.map.getLayerContentXY(tile.x + dx, tile.y + dy, enumLayer.regular);
|
||||
if (entity) {
|
||||
let ejectorSlots = [];
|
||||
let acceptorSlots = [];
|
||||
|
||||
@ -223,9 +220,6 @@ export class GameLogic {
|
||||
|
||||
for (let ejectorSlot = 0; ejectorSlot < ejectorSlots.length; ++ejectorSlot) {
|
||||
const slot = ejectorSlots[ejectorSlot];
|
||||
if (slot.layer !== layer) {
|
||||
continue;
|
||||
}
|
||||
const wsTile = staticComp.localTileToWorld(slot.pos);
|
||||
const wsDirection = staticComp.localDirectionToWorld(slot.direction);
|
||||
const targetTile = wsTile.add(enumDirectionToVector[wsDirection]);
|
||||
@ -241,10 +235,6 @@ export class GameLogic {
|
||||
|
||||
for (let acceptorSlot = 0; acceptorSlot < acceptorSlots.length; ++acceptorSlot) {
|
||||
const slot = acceptorSlots[acceptorSlot];
|
||||
if (slot.layer !== layer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const wsTile = staticComp.localTileToWorld(slot.pos);
|
||||
for (let k = 0; k < slot.directions.length; ++k) {
|
||||
const direction = slot.directions[k];
|
||||
|
@ -48,15 +48,6 @@ export class MapChunkView extends MapChunk {
|
||||
systems.staticMapEntities.drawChunk(parameters, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the wires layer
|
||||
* @param {DrawParameters} parameters
|
||||
*/
|
||||
drawWiresLayer(parameters) {
|
||||
const systems = this.root.systemMgr.systems;
|
||||
systems.belt.drawWiresChunk(parameters, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the wires layer
|
||||
* @param {DrawParameters} parameters
|
||||
|
@ -167,14 +167,6 @@ export class MapView extends BaseMap {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the wires background
|
||||
* @param {DrawParameters} parameters
|
||||
*/
|
||||
drawWiresLayer(parameters) {
|
||||
this.drawVisibleChunks(parameters, MapChunkView.prototype.drawWiresLayer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the wires foreground
|
||||
* @param {DrawParameters} parameters
|
||||
|
@ -1,10 +1,8 @@
|
||||
import { gMetaBuildingRegistry } from "../core/global_registries";
|
||||
import { createLogger } from "../core/logging";
|
||||
import { MetaAdvancedProcessorBuilding } from "./buildings/advanced_processor";
|
||||
import { MetaBeltBuilding } from "./buildings/belt";
|
||||
import { MetaBeltBaseBuilding } from "./buildings/belt_base";
|
||||
import { enumCutterVariants, MetaCutterBuilding } from "./buildings/cutter";
|
||||
import { MetaEnergyGenerator } from "./buildings/energy_generator";
|
||||
import { MetaHubBuilding } from "./buildings/hub";
|
||||
import { enumMinerVariants, MetaMinerBuilding } from "./buildings/miner";
|
||||
import { MetaMixerBuilding } from "./buildings/mixer";
|
||||
@ -14,8 +12,6 @@ import { enumSplitterVariants, MetaSplitterBuilding } from "./buildings/splitter
|
||||
import { MetaStackerBuilding } from "./buildings/stacker";
|
||||
import { enumTrashVariants, MetaTrashBuilding } from "./buildings/trash";
|
||||
import { enumUndergroundBeltVariants, MetaUndergroundBeltBuilding } from "./buildings/underground_belt";
|
||||
import { MetaWireBaseBuilding } from "./buildings/wire_base";
|
||||
import { enumWireCrossingVariants, MetaWireCrossingsBuilding } from "./buildings/wire_crossings";
|
||||
import { gBuildingVariants, registerBuildingVariant } from "./building_codes";
|
||||
import { defaultBuildingVariant } from "./meta_building";
|
||||
|
||||
@ -33,10 +29,6 @@ export function initMetaBuildingRegistry() {
|
||||
gMetaBuildingRegistry.register(MetaBeltBuilding);
|
||||
gMetaBuildingRegistry.register(MetaUndergroundBeltBuilding);
|
||||
gMetaBuildingRegistry.register(MetaHubBuilding);
|
||||
gMetaBuildingRegistry.register(MetaEnergyGenerator);
|
||||
gMetaBuildingRegistry.register(MetaWireBaseBuilding);
|
||||
gMetaBuildingRegistry.register(MetaAdvancedProcessorBuilding);
|
||||
gMetaBuildingRegistry.register(MetaWireCrossingsBuilding);
|
||||
|
||||
// Belt
|
||||
registerBuildingVariant(1, MetaBeltBaseBuilding, defaultBuildingVariant, 0);
|
||||
@ -86,21 +78,6 @@ export function initMetaBuildingRegistry() {
|
||||
// Hub
|
||||
registerBuildingVariant(26, MetaHubBuilding);
|
||||
|
||||
// Energy generator
|
||||
registerBuildingVariant(27, MetaEnergyGenerator);
|
||||
|
||||
// Wire
|
||||
registerBuildingVariant(28, MetaWireBaseBuilding, defaultBuildingVariant, 0);
|
||||
registerBuildingVariant(29, MetaWireBaseBuilding, defaultBuildingVariant, 1);
|
||||
registerBuildingVariant(30, MetaWireBaseBuilding, defaultBuildingVariant, 2);
|
||||
|
||||
// Advanced processor
|
||||
registerBuildingVariant(31, MetaAdvancedProcessorBuilding);
|
||||
|
||||
// Wire crossing
|
||||
registerBuildingVariant(32, MetaWireCrossingsBuilding);
|
||||
registerBuildingVariant(33, MetaWireCrossingsBuilding, enumWireCrossingVariants.merger);
|
||||
|
||||
// Propagate instances
|
||||
for (const key in gBuildingVariants) {
|
||||
gBuildingVariants[key].metaInstance = gMetaBuildingRegistry.findByClass(
|
||||
|
@ -5,13 +5,7 @@ import { DrawParameters } from "../core/draw_parameters";
|
||||
import { createLogger } from "../core/logging";
|
||||
import { Vector } from "../core/vector";
|
||||
import { BasicSerializableObject, types } from "../savegame/serialization";
|
||||
import {
|
||||
enumColors,
|
||||
enumColorsToHexCode,
|
||||
enumColorToShortcode,
|
||||
enumShortcodeToColor,
|
||||
enumInvertedColors,
|
||||
} from "./colors";
|
||||
import { enumColors, enumColorsToHexCode, enumColorToShortcode, enumShortcodeToColor } from "./colors";
|
||||
import { THEME } from "./theme";
|
||||
|
||||
const rusha = require("rusha");
|
||||
@ -598,23 +592,6 @@ export class ShapeDefinition extends BasicSerializableObject {
|
||||
return new ShapeDefinition({ layers: newLayers });
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones the shape and inverts all colors
|
||||
*/
|
||||
cloneAndInvertColors() {
|
||||
const newLayers = this.internalCloneLayers();
|
||||
for (let layerIndex = 0; layerIndex < newLayers.length; ++layerIndex) {
|
||||
const quadrants = newLayers[layerIndex];
|
||||
for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) {
|
||||
const item = quadrants[quadrantIndex];
|
||||
if (item) {
|
||||
item.color = enumInvertedColors[item.color];
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ShapeDefinition({ layers: newLayers });
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones the shape and colors everything in the given colors
|
||||
* @param {[enumColors, enumColors, enumColors, enumColors]} colors
|
||||
|
@ -179,22 +179,6 @@ export class ShapeDefinitionManager extends BasicSerializableObject {
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a definition for inverting all colors on that shape
|
||||
* @param {ShapeDefinition} definition
|
||||
* @returns {ShapeDefinition}
|
||||
*/
|
||||
shapeActionInvertColors(definition) {
|
||||
const key = "invert:" + definition.getHash();
|
||||
if (this.operationCache[key]) {
|
||||
return /** @type {ShapeDefinition} */ (this.operationCache[key]);
|
||||
}
|
||||
const inverted = definition.cloneAndInvertColors();
|
||||
return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle(
|
||||
inverted
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a definition for painting it with the 4 colors
|
||||
* @param {ShapeDefinition} definition
|
||||
|
@ -13,9 +13,6 @@ import { Entity } from "../entity";
|
||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||
import { MapChunkView } from "../map_chunk_view";
|
||||
import { defaultBuildingVariant } from "../meta_building";
|
||||
import { enumLayer } from "../root";
|
||||
import { MetaWireBaseBuilding } from "../buildings/wire_base";
|
||||
import { enumItemType } from "../base_item";
|
||||
|
||||
export const BELT_ANIM_COUNT = 28;
|
||||
|
||||
@ -320,14 +317,10 @@ export class BeltSystem extends GameSystemWithFilter {
|
||||
/**
|
||||
* Draws all belt paths
|
||||
* @param {DrawParameters} parameters
|
||||
* @param {enumLayer} layer
|
||||
*/
|
||||
drawLayerBeltItems(parameters, layer) {
|
||||
drawBeltItems(parameters) {
|
||||
for (let i = 0; i < this.beltPaths.length; ++i) {
|
||||
const path = this.beltPaths[i];
|
||||
if (path.layer === layer) {
|
||||
path.draw(parameters);
|
||||
}
|
||||
this.beltPaths[i].draw(parameters);
|
||||
}
|
||||
}
|
||||
|
||||
@ -497,13 +490,13 @@ export class BeltSystem extends GameSystemWithFilter {
|
||||
}
|
||||
|
||||
// Limit speed to avoid belts going backwards
|
||||
const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(enumLayer.regular), 10);
|
||||
const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(), 10);
|
||||
|
||||
// SYNC with systems/item_acceptor.js:drawEntityUnderlays!
|
||||
// 126 / 42 is the exact animation speed of the png animation
|
||||
const animationIndex = Math.floor(
|
||||
((this.root.time.realtimeNow() * speedMultiplier * BELT_ANIM_COUNT * 126) / 42) *
|
||||
globalConfig.beltItemSpacingByLayer[enumLayer.regular]
|
||||
globalConfig.itemSpacingOnBelts
|
||||
);
|
||||
const contents = chunk.contents;
|
||||
for (let y = 0; y < globalConfig.mapChunkSize; ++y) {
|
||||
@ -526,35 +519,6 @@ export class BeltSystem extends GameSystemWithFilter {
|
||||
1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a given chunk
|
||||
* @param {DrawParameters} parameters
|
||||
* @param {MapChunkView} chunk
|
||||
*/
|
||||
drawWiresChunk(parameters, chunk) {
|
||||
if (parameters.zoomLevel < globalConfig.mapChunkOverviewMinZoom) {
|
||||
return;
|
||||
}
|
||||
|
||||
const contents = chunk.wireContents;
|
||||
for (let y = 0; y < globalConfig.mapChunkSize; ++y) {
|
||||
for (let x = 0; x < globalConfig.mapChunkSize; ++x) {
|
||||
const entity = contents[x][y];
|
||||
|
||||
if (entity && entity.components.Belt) {
|
||||
const direction = entity.components.Belt.direction;
|
||||
const sprite = this.wireSprites[direction];
|
||||
entity.components.StaticMapEntity.drawSpriteOnFullEntityBounds(
|
||||
parameters,
|
||||
sprite,
|
||||
0,
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the belt path debug overlays
|
||||
* @param {DrawParameters} parameters
|
||||
|
@ -1,12 +1,11 @@
|
||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||
import { BeltUnderlaysComponent } from "../components/belt_underlays";
|
||||
import { BELT_ANIM_COUNT } from "./belt";
|
||||
import { Loader } from "../../core/loader";
|
||||
import { enumLayer } from "../root";
|
||||
import { Entity } from "../entity";
|
||||
import { enumDirectionToAngle } from "../../core/vector";
|
||||
import { globalConfig } from "../../core/config";
|
||||
import { drawRotatedSprite } from "../../core/draw_utils";
|
||||
import { Loader } from "../../core/loader";
|
||||
import { enumDirectionToAngle } from "../../core/vector";
|
||||
import { BeltUnderlaysComponent } from "../components/belt_underlays";
|
||||
import { Entity } from "../entity";
|
||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||
import { BELT_ANIM_COUNT } from "./belt";
|
||||
|
||||
export class BeltUnderlaysSystem extends GameSystemWithFilter {
|
||||
constructor(root) {
|
||||
@ -22,32 +21,25 @@ export class BeltUnderlaysSystem extends GameSystemWithFilter {
|
||||
/**
|
||||
* Draws the acceptor underlays
|
||||
* @param {import("../../core/draw_utils").DrawParameters} parameters
|
||||
* @param {enumLayer} layer
|
||||
*/
|
||||
drawUnderlays(parameters, layer) {
|
||||
this.forEachMatchingEntityOnScreen(parameters, this.drawEntityUnderlays.bind(this, layer));
|
||||
drawUnderlays(parameters) {
|
||||
this.forEachMatchingEntityOnScreen(parameters, this.drawEntityUnderlays.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {enumLayer} layer
|
||||
* @param {import("../../core/draw_utils").DrawParameters} parameters
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
drawEntityUnderlays(layer, parameters, entity) {
|
||||
drawEntityUnderlays(parameters, entity) {
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
const underlayComp = entity.components.BeltUnderlays;
|
||||
|
||||
if (entity.layer !== layer) {
|
||||
// Not our layer
|
||||
return;
|
||||
}
|
||||
|
||||
if (!staticComp.shouldBeDrawn(parameters)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Limit speed to avoid belts going backwards
|
||||
const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(layer), 10);
|
||||
const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(), 10);
|
||||
|
||||
const underlays = underlayComp.underlays;
|
||||
for (let i = 0; i < underlays.length; ++i) {
|
||||
@ -59,7 +51,7 @@ export class BeltUnderlaysSystem extends GameSystemWithFilter {
|
||||
// SYNC with systems/belt.js:drawSingleEntity!
|
||||
const animationIndex = Math.floor(
|
||||
((this.root.time.realtimeNow() * speedMultiplier * BELT_ANIM_COUNT * 126) / 42) *
|
||||
globalConfig.beltItemSpacingByLayer[layer]
|
||||
globalConfig.itemSpacingOnBelts
|
||||
);
|
||||
|
||||
drawRotatedSprite({
|
||||
|
@ -1,90 +0,0 @@
|
||||
import { DrawParameters } from "../../core/draw_parameters";
|
||||
import { Loader } from "../../core/loader";
|
||||
import { clamp } from "../../core/utils";
|
||||
import { enumItemType } from "../base_item";
|
||||
import { EnergyConsumerComponent } from "../components/energy_consumer";
|
||||
import { Entity } from "../entity";
|
||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||
import { NEGATIVE_ENERGY_ITEM_SINGLETON } from "../items/negative_energy_item";
|
||||
import { POSITIVE_ENERGY_ITEM_SINGLETON } from "../items/positive_energy_item";
|
||||
|
||||
export class EnergyConsumerSystem extends GameSystemWithFilter {
|
||||
constructor(root) {
|
||||
super(root, [EnergyConsumerComponent]);
|
||||
|
||||
this.batterySprites = [
|
||||
Loader.getSprite("sprites/wires/battery_empty.png"),
|
||||
Loader.getSprite("sprites/wires/battery_low.png"),
|
||||
Loader.getSprite("sprites/wires/battery_medium.png"),
|
||||
Loader.getSprite("sprites/wires/battery_full.png"),
|
||||
];
|
||||
|
||||
this.piledWasteSprite = Loader.getSprite("sprites/wires/waste_piled.png");
|
||||
}
|
||||
|
||||
update() {
|
||||
for (let i = 0; i < this.allEntities.length; ++i) {
|
||||
const entity = this.allEntities[i];
|
||||
const energyConsumerComp = entity.components.EnergyConsumer;
|
||||
|
||||
if (energyConsumerComp.piledOutput >= 1.0) {
|
||||
// Try to get rid of waste
|
||||
|
||||
const ejectorComp = entity.components.ItemEjector;
|
||||
const item = this.getItemSingletonByType(energyConsumerComp.wasteType);
|
||||
if (ejectorComp.tryEject(energyConsumerComp.ejectorSlotIndex, item)) {
|
||||
// Got rid of waste
|
||||
energyConsumerComp.reduceWaste(1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {enumItemType} itemType
|
||||
*/
|
||||
getItemSingletonByType(itemType) {
|
||||
switch (itemType) {
|
||||
case enumItemType.positiveEnergy:
|
||||
return POSITIVE_ENERGY_ITEM_SINGLETON;
|
||||
case enumItemType.negativeEnergy:
|
||||
return NEGATIVE_ENERGY_ITEM_SINGLETON;
|
||||
default:
|
||||
assertAlways(false, "Bad item type: " + itemType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws everything
|
||||
* @param {DrawParameters} parameters
|
||||
*/
|
||||
draw(parameters) {
|
||||
this.forEachMatchingEntityOnScreen(parameters, this.drawSingleEntity.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a given entity
|
||||
* @param {DrawParameters} parameters
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
drawSingleEntity(parameters, entity) {
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
const consumerComp = entity.components.EnergyConsumer;
|
||||
|
||||
const position = staticComp.localTileToWorld(consumerComp.batteryPosition).toWorldSpaceCenterOfTile();
|
||||
|
||||
if (consumerComp.hasTooMuchWastePiled()) {
|
||||
this.piledWasteSprite.drawCachedCentered(parameters, position.x, position.y, 12);
|
||||
} else {
|
||||
const percentage = consumerComp.stored / consumerComp.bufferSize;
|
||||
const index = clamp(
|
||||
Math.round(percentage * this.batterySprites.length),
|
||||
0,
|
||||
this.batterySprites.length - 1
|
||||
);
|
||||
|
||||
this.batterySprites[index].drawCachedCentered(parameters, position.x, position.y, 12);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
import { DrawParameters } from "../../core/draw_parameters";
|
||||
import { formatBigNumber } from "../../core/utils";
|
||||
import { T } from "../../translations";
|
||||
import { EnergyGeneratorComponent } from "../components/energy_generator";
|
||||
import { Entity } from "../entity";
|
||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||
import { POSITIVE_ENERGY_ITEM_SINGLETON } from "../items/positive_energy_item";
|
||||
import { ShapeDefinition } from "../shape_definition";
|
||||
import { Loader } from "../../core/loader";
|
||||
import { globalConfig } from "../../core/config";
|
||||
|
||||
export class EnergyGeneratorSystem extends GameSystemWithFilter {
|
||||
constructor(root) {
|
||||
super(root, [EnergyGeneratorComponent]);
|
||||
|
||||
this.energyGeneratorOverlay = Loader.getSprite("sprites/misc/energy_generator_overlay.png");
|
||||
}
|
||||
|
||||
draw(parameters) {
|
||||
this.forEachMatchingEntityOnScreen(parameters, this.drawEntity.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns which shape is required for a given generator
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
getShapeRequiredForGenerator(entity) {
|
||||
return "CuCuCuCu";
|
||||
}
|
||||
|
||||
update() {
|
||||
for (let i = 0; i < this.allEntities.length; ++i) {
|
||||
const entity = this.allEntities[i];
|
||||
const energyGenComp = entity.components.EnergyGenerator;
|
||||
const ejectorComp = entity.components.ItemEjector;
|
||||
|
||||
if (!energyGenComp.requiredKey) {
|
||||
// Compute required key for this generator
|
||||
energyGenComp.requiredKey = this.getShapeRequiredForGenerator(entity);
|
||||
}
|
||||
|
||||
if (energyGenComp.itemsInQueue > 0) {
|
||||
// FIXME: Find slot dynamically
|
||||
if (ejectorComp.tryEject(0, POSITIVE_ENERGY_ITEM_SINGLETON)) {
|
||||
energyGenComp.itemsInQueue -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DrawParameters} parameters
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
drawEntity(parameters, entity) {
|
||||
const context = parameters.context;
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
|
||||
if (!staticComp.shouldBeDrawn(parameters)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const energyGenComp = entity.components.EnergyGenerator;
|
||||
if (!energyGenComp.requiredKey) {
|
||||
// Not initialized yet
|
||||
return;
|
||||
}
|
||||
|
||||
const pos = staticComp.getTileSpaceBounds().getCenter().toWorldSpace();
|
||||
|
||||
const definition = ShapeDefinition.fromShortKey(energyGenComp.requiredKey);
|
||||
definition.draw(pos.x, pos.y, parameters, 30);
|
||||
|
||||
// Draw background
|
||||
this.energyGeneratorOverlay.drawCachedCentered(
|
||||
parameters,
|
||||
pos.x,
|
||||
pos.y,
|
||||
globalConfig.tileSize * 2 + 8
|
||||
);
|
||||
|
||||
// TODO
|
||||
const energyGenerated = 5;
|
||||
|
||||
// deliver: Deliver
|
||||
// toGenerateEnergy: For <x> energy
|
||||
context.font = "bold 9px GameFont";
|
||||
context.fillStyle = "#64666e";
|
||||
context.textAlign = "left";
|
||||
context.fillText(T.buildings.energy_generator.deliver.toUpperCase(), pos.x - 25, pos.y - 18);
|
||||
context.fillText(T.buildings.energy_generator.toGenerateEnergy.toUpperCase(), pos.x - 25, pos.y + 27);
|
||||
|
||||
context.font = "700 9px GameFont";
|
||||
context.fillStyle = "#dee1ea";
|
||||
context.fillText("" + formatBigNumber(energyGenerated), pos.x + 1, pos.y + 27);
|
||||
}
|
||||
}
|
@ -23,11 +23,8 @@ export class ItemAcceptorSystem extends GameSystemWithFilter {
|
||||
// Process item consumption animations to avoid items popping from the belts
|
||||
for (let animIndex = 0; animIndex < animations.length; ++animIndex) {
|
||||
const anim = animations[animIndex];
|
||||
const layer = aceptorComp.slots[anim.slotIndex].layer;
|
||||
anim.animProgress +=
|
||||
progress *
|
||||
this.root.hubGoals.getBeltBaseSpeed(layer) *
|
||||
globalConfig.beltItemSpacingByLayer[layer];
|
||||
progress * this.root.hubGoals.getBeltBaseSpeed() * globalConfig.itemSpacingOnBelts;
|
||||
if (anim.animProgress > 1) {
|
||||
// Original
|
||||
// animations.splice(animIndex, 1);
|
||||
@ -44,18 +41,16 @@ export class ItemAcceptorSystem extends GameSystemWithFilter {
|
||||
/**
|
||||
* Draws the acceptor items
|
||||
* @param {DrawParameters} parameters
|
||||
* @param {enumLayer} layer
|
||||
*/
|
||||
drawLayer(parameters, layer) {
|
||||
this.forEachMatchingEntityOnScreen(parameters, this.drawEntityRegularLayer.bind(this, layer));
|
||||
draw(parameters) {
|
||||
this.forEachMatchingEntityOnScreen(parameters, this.drawEntityRegularLayer.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {enumLayer} layer
|
||||
* @param {DrawParameters} parameters
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
drawEntityRegularLayer(layer, parameters, entity) {
|
||||
drawEntityRegularLayer(parameters, entity) {
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
const acceptorComp = entity.components.ItemAcceptor;
|
||||
|
||||
@ -69,10 +64,6 @@ export class ItemAcceptorSystem extends GameSystemWithFilter {
|
||||
];
|
||||
|
||||
const slotData = acceptorComp.slots[slotIndex];
|
||||
if (slotData.layer !== layer) {
|
||||
// Don't draw non-regular slots for now
|
||||
continue;
|
||||
}
|
||||
|
||||
const slotWorldPos = staticComp.applyRotationToVector(slotData.pos).add(staticComp.origin);
|
||||
const fadeOutDirection = enumDirectionToVector[staticComp.localDirectionToWorld(direction)];
|
||||
|
@ -3,11 +3,10 @@ import { DrawParameters } from "../../core/draw_parameters";
|
||||
import { createLogger } from "../../core/logging";
|
||||
import { Rectangle } from "../../core/rectangle";
|
||||
import { enumDirection, enumDirectionToVector, Vector } from "../../core/vector";
|
||||
import { BaseItem, enumItemTypeToLayer } from "../base_item";
|
||||
import { BaseItem } from "../base_item";
|
||||
import { ItemEjectorComponent } from "../components/item_ejector";
|
||||
import { Entity } from "../entity";
|
||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||
import { enumLayer } from "../root";
|
||||
|
||||
const logger = createLogger("systems/ejector");
|
||||
|
||||
@ -166,8 +165,7 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
|
||||
|
||||
const matchingSlot = targetAcceptorComp.findMatchingSlot(
|
||||
targetStaticComp.worldToLocalTile(ejectSlotTargetWsTile),
|
||||
targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection),
|
||||
ejectorSlot.layer
|
||||
targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection)
|
||||
);
|
||||
|
||||
if (!matchingSlot) {
|
||||
@ -219,8 +217,8 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
|
||||
1,
|
||||
sourceSlot.progress +
|
||||
progressGrowth *
|
||||
this.root.hubGoals.getBeltBaseSpeed(sourceSlot.layer) *
|
||||
globalConfig.beltItemSpacingByLayer[sourceSlot.layer]
|
||||
this.root.hubGoals.getBeltBaseSpeed() *
|
||||
globalConfig.itemSpacingOnBelts
|
||||
);
|
||||
|
||||
// Check if we are still in the process of ejecting, can't proceed then
|
||||
@ -272,8 +270,6 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
|
||||
// TODO: Kinda hacky. How to solve this properly? Don't want to go through inheritance hell.
|
||||
// Also its just a few cases (hope it stays like this .. :x).
|
||||
|
||||
const itemLayer = enumItemTypeToLayer[item.getItemType()];
|
||||
|
||||
const beltComp = receiver.components.Belt;
|
||||
if (beltComp) {
|
||||
const path = beltComp.assignedPath;
|
||||
@ -297,15 +293,12 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
|
||||
|
||||
const itemProcessorComp = receiver.components.ItemProcessor;
|
||||
if (itemProcessorComp) {
|
||||
// Make sure its the same layer
|
||||
if (itemLayer === receiver.layer) {
|
||||
// Its an item processor ..
|
||||
if (itemProcessorComp.tryTakeItem(item, slotIndex)) {
|
||||
return true;
|
||||
}
|
||||
// Item processor can have nothing else
|
||||
return false;
|
||||
// Its an item processor ..
|
||||
if (itemProcessorComp.tryTakeItem(item, slotIndex)) {
|
||||
return true;
|
||||
}
|
||||
// Item processor can have nothing else
|
||||
return false;
|
||||
}
|
||||
|
||||
const undergroundBeltComp = receiver.components.UndergroundBelt;
|
||||
@ -336,35 +329,22 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
|
||||
return false;
|
||||
}
|
||||
|
||||
const energyGeneratorComp = receiver.components.EnergyGenerator;
|
||||
if (energyGeneratorComp) {
|
||||
if (energyGeneratorComp.tryTakeItem(item, slotIndex)) {
|
||||
// Passed it over
|
||||
return true;
|
||||
}
|
||||
|
||||
// Energy generator comp can't have anything else
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the given layer
|
||||
* Draws everything
|
||||
* @param {DrawParameters} parameters
|
||||
* @param {enumLayer} layer
|
||||
*/
|
||||
drawLayer(parameters, layer) {
|
||||
this.forEachMatchingEntityOnScreen(parameters, this.drawSingleEntity.bind(this, layer));
|
||||
draw(parameters) {
|
||||
this.forEachMatchingEntityOnScreen(parameters, this.drawSingleEntity.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {enumLayer} layer
|
||||
* @param {DrawParameters} parameters
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
drawSingleEntity(layer, parameters, entity) {
|
||||
drawSingleEntity(parameters, entity) {
|
||||
const ejectorComp = entity.components.ItemEjector;
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
|
||||
@ -381,11 +361,6 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (slot.layer !== layer) {
|
||||
// Not our layer
|
||||
continue;
|
||||
}
|
||||
|
||||
const realPosition = slot.pos.rotateFastMultipleOf90(staticComp.rotation);
|
||||
const realDirection = Vector.transformDirectionFromMultipleOf90(
|
||||
slot.direction,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { globalConfig } from "../../core/config";
|
||||
import { BaseItem, enumItemType } from "../base_item";
|
||||
import { enumColorMixingResults, enumInvertedColors } from "../colors";
|
||||
import { enumColorMixingResults } from "../colors";
|
||||
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
|
||||
import { Entity } from "../entity";
|
||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||
@ -48,11 +48,11 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
if (ejectorComp.canEjectOnSlot(preferredSlot)) {
|
||||
slot = preferredSlot;
|
||||
} else {
|
||||
slot = ejectorComp.getFirstFreeSlot(entity.layer);
|
||||
slot = ejectorComp.getFirstFreeSlot();
|
||||
}
|
||||
} else {
|
||||
// We can eject on any slot
|
||||
slot = ejectorComp.getFirstFreeSlot(entity.layer);
|
||||
slot = ejectorComp.getFirstFreeSlot();
|
||||
}
|
||||
|
||||
if (slot !== null) {
|
||||
@ -354,35 +354,6 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
break;
|
||||
}
|
||||
|
||||
// ADVANCED PROCESSING
|
||||
|
||||
case enumItemProcessorTypes.advancedProcessor: {
|
||||
const item = items[0].item;
|
||||
|
||||
if (item.getItemType() === enumItemType.color) {
|
||||
const colorItem = /** @type {ColorItem} */ (items[0].item);
|
||||
const newColor = enumInvertedColors[colorItem.color];
|
||||
outItems.push({
|
||||
item: new ColorItem(newColor),
|
||||
requiredSlot: 0,
|
||||
});
|
||||
} else if (item.getItemType() === enumItemType.shape) {
|
||||
const shapeItem = /** @type {ShapeItem} */ (items[0].item);
|
||||
const newItem = this.root.shapeDefinitionMgr.shapeActionInvertColors(
|
||||
shapeItem.definition
|
||||
);
|
||||
|
||||
outItems.push({
|
||||
item: new ShapeItem(newItem),
|
||||
requiredSlot: 0,
|
||||
});
|
||||
} else {
|
||||
assertAlways(false, "Bad item type: " + item.getItemType() + " for advanced processor.");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assertAlways(false, "Unkown item processor type: " + processorComp.type);
|
||||
}
|
||||
|
@ -1,10 +1,9 @@
|
||||
import { GameSystem } from "../game_system";
|
||||
import { DrawParameters } from "../../core/draw_parameters";
|
||||
import { globalConfig } from "../../core/config";
|
||||
import { MapChunkView } from "../map_chunk_view";
|
||||
import { DrawParameters } from "../../core/draw_parameters";
|
||||
import { Loader } from "../../core/loader";
|
||||
import { enumDirection } from "../../core/vector";
|
||||
import { enumLayer } from "../root";
|
||||
import { GameSystem } from "../game_system";
|
||||
import { MapChunkView } from "../map_chunk_view";
|
||||
|
||||
export class StaticMapEntitySystem extends GameSystem {
|
||||
constructor(root) {
|
||||
|
@ -22,8 +22,7 @@ export class StorageSystem extends GameSystemWithFilter {
|
||||
if (storageComp.storedItem && storageComp.storedCount > 0) {
|
||||
const ejectorComp = entity.components.ItemEjector;
|
||||
|
||||
/* FIXME: WIRES */
|
||||
const nextSlot = ejectorComp.getFirstFreeSlot(enumLayer.regular);
|
||||
const nextSlot = ejectorComp.getFirstFreeSlot();
|
||||
if (nextSlot !== null) {
|
||||
if (ejectorComp.tryEject(nextSlot, storageComp.storedItem)) {
|
||||
storageComp.storedCount--;
|
||||
|
@ -395,7 +395,7 @@ export class UndergroundBeltSystem extends GameSystemWithFilter {
|
||||
if (remainingTime <= 0) {
|
||||
const ejectorComp = entity.components.ItemEjector;
|
||||
|
||||
const nextSlotIndex = ejectorComp.getFirstFreeSlot(entity.layer);
|
||||
const nextSlotIndex = ejectorComp.getFirstFreeSlot();
|
||||
if (nextSlotIndex !== null) {
|
||||
if (ejectorComp.tryEject(nextSlotIndex, nextItem)) {
|
||||
items.shift();
|
||||
|
@ -14,14 +14,6 @@ export class WiredPinsSystem extends GameSystemWithFilter {
|
||||
super(root, [WiredPinsComponent]);
|
||||
|
||||
this.pinSprites = {
|
||||
[enumPinSlotType.positiveEnergyEjector]: Loader.getSprite("sprites/wires/pin_positive_eject.png"),
|
||||
[enumPinSlotType.positiveEnergyAcceptor]: Loader.getSprite(
|
||||
"sprites/wires/pin_positive_accept.png"
|
||||
),
|
||||
[enumPinSlotType.negativeEnergyEjector]: Loader.getSprite("sprites/wires/pin_negative_eject.png"),
|
||||
[enumPinSlotType.negativeEnergyAcceptor]: Loader.getSprite(
|
||||
"sprites/wires/pin_negative_accept.png"
|
||||
),
|
||||
[enumPinSlotType.logicalEjector]: Loader.getSprite("sprites/wires/pin_negative_eject.png"),
|
||||
[enumPinSlotType.logicalAcceptor]: Loader.getSprite("sprites/wires/pin_negative_accept.png"),
|
||||
};
|
||||
|
@ -448,11 +448,6 @@ buildings:
|
||||
name: &belt Conveyor Belt
|
||||
description: Transports items, hold and drag to place multiple.
|
||||
|
||||
wire:
|
||||
default:
|
||||
name: &wire Energy Wire
|
||||
description: Allows you to transport energy.
|
||||
|
||||
# Internal name for the Extractor
|
||||
miner:
|
||||
default:
|
||||
@ -495,11 +490,6 @@ buildings:
|
||||
name: Cutter (Quad)
|
||||
description: Cuts shapes into four parts. <strong>If you use only one part, be sure to destroy the other parts or it will stall!</strong>
|
||||
|
||||
advanced_processor:
|
||||
default:
|
||||
name: &advanced_processor Color Inverter
|
||||
description: Accepts a color or shape and inverts it.
|
||||
|
||||
rotater:
|
||||
default:
|
||||
name: &rotater Rotate
|
||||
@ -547,25 +537,6 @@ buildings:
|
||||
name: Storage
|
||||
description: Stores excess items, up to a given capacity. Can be used as an overflow gate.
|
||||
|
||||
energy_generator:
|
||||
deliver: Deliver
|
||||
|
||||
# This will be shown before the amount, so for example 'For 123 Energy'
|
||||
toGenerateEnergy: For
|
||||
|
||||
default:
|
||||
name: &energy_generator Energy Generator
|
||||
description: Generates energy by consuming shapes.
|
||||
|
||||
wire_crossings:
|
||||
default:
|
||||
name: &wire_crossings Wire Splitter
|
||||
description: Splits a energy wire into two.
|
||||
|
||||
merger:
|
||||
name: Wire Merger
|
||||
description: Merges two energy wires into one.
|
||||
|
||||
storyRewards:
|
||||
# Those are the rewards gained from completing the store
|
||||
reward_cutter_and_trash:
|
||||
@ -826,14 +797,11 @@ keybindings:
|
||||
underground_belt: *underground_belt
|
||||
miner: *miner
|
||||
cutter: *cutter
|
||||
advanced_processor: *advanced_processor
|
||||
rotater: *rotater
|
||||
stacker: *stacker
|
||||
mixer: *mixer
|
||||
energy_generator: *energy_generator
|
||||
painter: *painter
|
||||
trash: *trash
|
||||
wire: *wire
|
||||
|
||||
pipette: Pipette
|
||||
rotateWhilePlacing: Rotate
|
||||
|