mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-12-14 02:31:51 +00:00
Item acceptor refactor part 1
This commit is contained in:
parent
2ac34665b3
commit
4a1bfcda64
@ -132,14 +132,14 @@ export class BeltPath extends BasicSerializableObject {
|
|||||||
tryAcceptItem(item) {
|
tryAcceptItem(item) {
|
||||||
if (this.spacingToFirstItem >= globalConfig.itemSpacingOnBelts) {
|
if (this.spacingToFirstItem >= globalConfig.itemSpacingOnBelts) {
|
||||||
// So, since we already need one tick to accept this item we will add this directly.
|
// So, since we already need one tick to accept this item we will add this directly.
|
||||||
const beltProgressPerTick =
|
const progressGrowth =
|
||||||
this.root.hubGoals.getBeltBaseSpeed() *
|
this.root.hubGoals.getBeltBaseSpeed() *
|
||||||
this.root.dynamicTickrate.deltaSeconds *
|
this.root.dynamicTickrate.deltaSeconds *
|
||||||
globalConfig.itemSpacingOnBelts;
|
globalConfig.itemSpacingOnBelts;
|
||||||
|
|
||||||
// First, compute how much progress we can make *at max*
|
// First, compute how much progress we can make *at max*
|
||||||
const maxProgress = Math.max(0, this.spacingToFirstItem - globalConfig.itemSpacingOnBelts);
|
const maxProgress = Math.max(0, this.spacingToFirstItem - globalConfig.itemSpacingOnBelts);
|
||||||
const initialProgress = Math.min(maxProgress, beltProgressPerTick);
|
const initialProgress = Math.min(maxProgress, progressGrowth);
|
||||||
|
|
||||||
this.items.unshift([this.spacingToFirstItem - initialProgress, item]);
|
this.items.unshift([this.spacingToFirstItem - initialProgress, item]);
|
||||||
this.spacingToFirstItem = initialProgress;
|
this.spacingToFirstItem = initialProgress;
|
||||||
@ -272,31 +272,10 @@ export class BeltPath extends BasicSerializableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const matchingSlotIndex = matchingSlot.index;
|
const matchingSlotIndex = matchingSlot.index;
|
||||||
const passOver = this.computePassOverFunctionWithoutBelts(targetEntity, matchingSlotIndex);
|
|
||||||
if (!passOver) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const matchingDirection = enumInvertedDirections[ejectingDirection];
|
const matchingDirection = enumInvertedDirections[ejectingDirection];
|
||||||
const filter = matchingSlot.slot.filter;
|
|
||||||
|
|
||||||
return function (item, remainingProgress = 0.0) {
|
return function (item, startProgress = 0.0) {
|
||||||
// Check if the acceptor has a filter
|
if (targetAcceptorComp.tryAcceptItem(matchingSlotIndex, matchingDirection, item, startProgress)) {
|
||||||
if (filter && item._type !== filter) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to pass over
|
|
||||||
if (passOver(item, matchingSlotIndex)) {
|
|
||||||
// Trigger animation on the acceptor comp
|
|
||||||
if (noSimplifiedBelts) {
|
|
||||||
targetAcceptorComp.onItemAccepted(
|
|
||||||
matchingSlotIndex,
|
|
||||||
matchingDirection,
|
|
||||||
item,
|
|
||||||
remainingProgress
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -313,7 +292,7 @@ export class BeltPath extends BasicSerializableObject {
|
|||||||
const systems = this.root.systemMgr.systems;
|
const systems = this.root.systemMgr.systems;
|
||||||
const hubGoals = this.root.hubGoals;
|
const hubGoals = this.root.hubGoals;
|
||||||
|
|
||||||
// NOTICE: THIS IS COPIED FROM THE ITEM EJECTOR SYSTEM FOR PEROFMANCE REASONS
|
// NOTICE: THIS IS COPIED FROM THE ITEM EJECTOR SYSTEM FOR PERFORMANCE REASONS
|
||||||
|
|
||||||
const itemProcessorComp = entity.components.ItemProcessor;
|
const itemProcessorComp = entity.components.ItemProcessor;
|
||||||
if (itemProcessorComp) {
|
if (itemProcessorComp) {
|
||||||
@ -323,7 +302,7 @@ export class BeltPath extends BasicSerializableObject {
|
|||||||
if (!systems.itemProcessor.checkRequirements(entity, item, matchingSlotIndex)) {
|
if (!systems.itemProcessor.checkRequirements(entity, item, matchingSlotIndex)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return itemProcessorComp.tryTakeItem(item, matchingSlotIndex);
|
//return itemProcessorComp.tryTakeItem(item, matchingSlotIndex);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -179,11 +179,11 @@ export class MetaBalancerBuilding extends MetaBuilding {
|
|||||||
entity.components.ItemAcceptor.setSlots([
|
entity.components.ItemAcceptor.setSlots([
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(1, 0),
|
pos: new Vector(1, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -204,15 +204,14 @@ export class MetaBalancerBuilding extends MetaBuilding {
|
|||||||
entity.components.ItemAcceptor.setSlots([
|
entity.components.ItemAcceptor.setSlots([
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [
|
direction:
|
||||||
variant === enumBalancerVariants.mergerInverse
|
variant === enumBalancerVariants.mergerInverse
|
||||||
? enumDirection.left
|
? enumDirection.left
|
||||||
: enumDirection.right,
|
: enumDirection.right,
|
||||||
],
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -231,7 +230,7 @@ export class MetaBalancerBuilding extends MetaBuilding {
|
|||||||
entity.components.ItemAcceptor.setSlots([
|
entity.components.ItemAcceptor.setSlots([
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@ -96,7 +96,7 @@ export class MetaCutterBuilding extends MetaBuilding {
|
|||||||
slots: [
|
slots: [
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@ -78,7 +78,7 @@ export class MetaFilterBuilding extends MetaBuilding {
|
|||||||
slots: [
|
slots: [
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
@ -45,7 +45,7 @@ export class MetaGoalAcceptorBuilding extends MetaBuilding {
|
|||||||
slots: [
|
slots: [
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { enumDirection, Vector } from "../../core/vector";
|
import { enumDirection, Vector } from "../../core/vector";
|
||||||
import { HubComponent } from "../components/hub";
|
import { HubComponent } from "../components/hub";
|
||||||
import { ItemAcceptorComponent } from "../components/item_acceptor";
|
import { enumItemAcceptorTypes, ItemAcceptorComponent } from "../components/item_acceptor";
|
||||||
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
|
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
|
||||||
import { Entity } from "../entity";
|
import { Entity } from "../entity";
|
||||||
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
||||||
@ -75,75 +75,96 @@ export class MetaHubBuilding extends MetaBuilding {
|
|||||||
slots: [
|
slots: [
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.top, enumDirection.left],
|
direction: enumDirection.top,
|
||||||
|
filter: "shape",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: new Vector(0, 0),
|
||||||
|
direction: enumDirection.left,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(1, 0),
|
pos: new Vector(1, 0),
|
||||||
directions: [enumDirection.top],
|
direction: enumDirection.top,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(2, 0),
|
pos: new Vector(2, 0),
|
||||||
directions: [enumDirection.top],
|
direction: enumDirection.top,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(3, 0),
|
pos: new Vector(3, 0),
|
||||||
directions: [enumDirection.top, enumDirection.right],
|
direction: enumDirection.top,
|
||||||
|
filter: "shape",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: new Vector(3, 0),
|
||||||
|
direction: enumDirection.right,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 3),
|
pos: new Vector(0, 3),
|
||||||
directions: [enumDirection.bottom, enumDirection.left],
|
direction: enumDirection.left,
|
||||||
|
filter: "shape",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: new Vector(0, 3),
|
||||||
|
direction: enumDirection.bottom,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(1, 3),
|
pos: new Vector(1, 3),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(2, 3),
|
pos: new Vector(2, 3),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(3, 3),
|
pos: new Vector(3, 3),
|
||||||
directions: [enumDirection.bottom, enumDirection.right],
|
direction: enumDirection.bottom,
|
||||||
|
filter: "shape",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: new Vector(3, 3),
|
||||||
|
direction: enumDirection.right,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 1),
|
pos: new Vector(0, 1),
|
||||||
directions: [enumDirection.left],
|
direction: enumDirection.left,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 2),
|
pos: new Vector(0, 2),
|
||||||
directions: [enumDirection.left],
|
direction: enumDirection.left,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 3),
|
pos: new Vector(0, 3),
|
||||||
directions: [enumDirection.left],
|
direction: enumDirection.left,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(3, 1),
|
pos: new Vector(3, 1),
|
||||||
directions: [enumDirection.right],
|
direction: enumDirection.right,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(3, 2),
|
pos: new Vector(3, 2),
|
||||||
directions: [enumDirection.right],
|
direction: enumDirection.right,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(3, 3),
|
pos: new Vector(3, 3),
|
||||||
directions: [enumDirection.right],
|
direction: enumDirection.right,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
type: enumItemAcceptorTypes.hub,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -73,12 +73,12 @@ export class MetaMixerBuilding extends MetaBuilding {
|
|||||||
slots: [
|
slots: [
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
filter: "color",
|
filter: "color",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(1, 0),
|
pos: new Vector(1, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
filter: "color",
|
filter: "color",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@ -128,12 +128,12 @@ export class MetaPainterBuilding extends MetaBuilding {
|
|||||||
slots: [
|
slots: [
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.left],
|
direction: enumDirection.left,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(1, 0),
|
pos: new Vector(1, 0),
|
||||||
directions: [enumDirection.top],
|
direction: enumDirection.top,
|
||||||
filter: "color",
|
filter: "color",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -160,14 +160,13 @@ export class MetaPainterBuilding extends MetaBuilding {
|
|||||||
entity.components.ItemAcceptor.setSlots([
|
entity.components.ItemAcceptor.setSlots([
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.left],
|
direction: enumDirection.left,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(1, 0),
|
pos: new Vector(1, 0),
|
||||||
directions: [
|
direction:
|
||||||
variant === defaultBuildingVariant ? enumDirection.top : enumDirection.bottom,
|
variant === defaultBuildingVariant ? enumDirection.top : enumDirection.bottom,
|
||||||
],
|
|
||||||
filter: "color",
|
filter: "color",
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
@ -193,17 +192,17 @@ export class MetaPainterBuilding extends MetaBuilding {
|
|||||||
entity.components.ItemAcceptor.setSlots([
|
entity.components.ItemAcceptor.setSlots([
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.left],
|
direction: enumDirection.left,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 1),
|
pos: new Vector(0, 1),
|
||||||
directions: [enumDirection.left],
|
direction: enumDirection.left,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(1, 0),
|
pos: new Vector(1, 0),
|
||||||
directions: [enumDirection.top],
|
direction: enumDirection.top,
|
||||||
filter: "color",
|
filter: "color",
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
@ -251,27 +250,27 @@ export class MetaPainterBuilding extends MetaBuilding {
|
|||||||
entity.components.ItemAcceptor.setSlots([
|
entity.components.ItemAcceptor.setSlots([
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.left],
|
direction: enumDirection.left,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
filter: "color",
|
filter: "color",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(1, 0),
|
pos: new Vector(1, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
filter: "color",
|
filter: "color",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(2, 0),
|
pos: new Vector(2, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
filter: "color",
|
filter: "color",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(3, 0),
|
pos: new Vector(3, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
filter: "color",
|
filter: "color",
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|||||||
@ -84,7 +84,7 @@ export class MetaReaderBuilding extends MetaBuilding {
|
|||||||
slots: [
|
slots: [
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
@ -128,7 +128,7 @@ export class MetaRotaterBuilding extends MetaBuilding {
|
|||||||
slots: [
|
slots: [
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@ -73,12 +73,12 @@ export class MetaStackerBuilding extends MetaBuilding {
|
|||||||
slots: [
|
slots: [
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(1, 0),
|
pos: new Vector(1, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
filter: "shape",
|
filter: "shape",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { formatBigNumber } from "../../core/utils";
|
import { formatBigNumber } from "../../core/utils";
|
||||||
import { enumDirection, Vector } from "../../core/vector";
|
import { enumDirection, Vector } from "../../core/vector";
|
||||||
import { T } from "../../translations";
|
import { T } from "../../translations";
|
||||||
import { ItemAcceptorComponent } from "../components/item_acceptor";
|
import { enumItemAcceptorTypes, ItemAcceptorComponent } from "../components/item_acceptor";
|
||||||
import { ItemEjectorComponent } from "../components/item_ejector";
|
import { ItemEjectorComponent } from "../components/item_ejector";
|
||||||
import { StorageComponent } from "../components/storage";
|
import { StorageComponent } from "../components/storage";
|
||||||
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
|
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
|
||||||
@ -74,13 +74,14 @@ export class MetaStorageBuilding extends MetaBuilding {
|
|||||||
slots: [
|
slots: [
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 1),
|
pos: new Vector(0, 1),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pos: new Vector(1, 1),
|
pos: new Vector(1, 1),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
type: enumItemAcceptorTypes.storage,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -74,15 +74,10 @@ export class MetaTrashBuilding extends MetaBuilding {
|
|||||||
entity.addComponent(
|
entity.addComponent(
|
||||||
new ItemAcceptorComponent({
|
new ItemAcceptorComponent({
|
||||||
slots: [
|
slots: [
|
||||||
{
|
{ pos: new Vector(0, 0), direction: enumDirection.top },
|
||||||
pos: new Vector(0, 0),
|
{ pos: new Vector(0, 0), direction: enumDirection.left },
|
||||||
directions: [
|
{ pos: new Vector(0, 0), direction: enumDirection.right },
|
||||||
enumDirection.top,
|
{ pos: new Vector(0, 0), direction: enumDirection.bottom },
|
||||||
enumDirection.right,
|
|
||||||
enumDirection.bottom,
|
|
||||||
enumDirection.left,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Loader } from "../../core/loader";
|
import { Loader } from "../../core/loader";
|
||||||
import { enumDirection, Vector, enumAngleToDirection, enumDirectionToVector } from "../../core/vector";
|
import { enumDirection, Vector, enumAngleToDirection, enumDirectionToVector } from "../../core/vector";
|
||||||
import { ItemAcceptorComponent } from "../components/item_acceptor";
|
import { enumItemAcceptorTypes, ItemAcceptorComponent } from "../components/item_acceptor";
|
||||||
import { ItemEjectorComponent } from "../components/item_ejector";
|
import { ItemEjectorComponent } from "../components/item_ejector";
|
||||||
import { enumUndergroundBeltMode, UndergroundBeltComponent } from "../components/underground_belt";
|
import { enumUndergroundBeltMode, UndergroundBeltComponent } from "../components/underground_belt";
|
||||||
import { Entity } from "../entity";
|
import { Entity } from "../entity";
|
||||||
@ -195,6 +195,7 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
|
|||||||
entity.addComponent(
|
entity.addComponent(
|
||||||
new ItemAcceptorComponent({
|
new ItemAcceptorComponent({
|
||||||
slots: [],
|
slots: [],
|
||||||
|
type: enumItemAcceptorTypes.undergroundBelt,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -277,7 +278,7 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
|
|||||||
entity.components.ItemAcceptor.setSlots([
|
entity.components.ItemAcceptor.setSlots([
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -8,7 +8,7 @@ export const curvedBeltLength = /* Math.PI / 4 */ 0.78;
|
|||||||
/** @type {import("./item_acceptor").ItemAcceptorSlot} */
|
/** @type {import("./item_acceptor").ItemAcceptorSlot} */
|
||||||
export const FAKE_BELT_ACCEPTOR_SLOT = {
|
export const FAKE_BELT_ACCEPTOR_SLOT = {
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
directions: [enumDirection.bottom],
|
direction: enumDirection.bottom,
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @type {Object<enumDirection, import("./item_ejector").ItemEjectorSlot>} */
|
/** @type {Object<enumDirection, import("./item_ejector").ItemEjectorSlot>} */
|
||||||
|
|||||||
@ -1,27 +1,52 @@
|
|||||||
import { enumDirection, enumInvertedDirections, Vector } from "../../core/vector";
|
import { enumDirection, enumInvertedDirections, Vector } from "../../core/vector";
|
||||||
import { types } from "../../savegame/serialization";
|
|
||||||
import { BaseItem } from "../base_item";
|
import { BaseItem } from "../base_item";
|
||||||
import { Component } from "../component";
|
import { Component } from "../component";
|
||||||
|
import { Entity } from "../entity";
|
||||||
/** @typedef {{
|
import { GameRoot } from "../root";
|
||||||
* pos: Vector,
|
|
||||||
* directions: enumDirection[],
|
|
||||||
* filter?: ItemType
|
|
||||||
* }} ItemAcceptorSlot */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @typedef {{
|
||||||
|
* pos: Vector,
|
||||||
|
* direction: enumDirection,
|
||||||
|
* filter?: ItemType
|
||||||
|
* }} ItemAcceptorSlot
|
||||||
|
*
|
||||||
* Contains information about a slot plus its location
|
* Contains information about a slot plus its location
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
* slot: ItemAcceptorSlot,
|
* slot: ItemAcceptorSlot,
|
||||||
* index: number,
|
* index: number,
|
||||||
* acceptedDirection: enumDirection
|
* acceptedDirection: enumDirection
|
||||||
* }} ItemAcceptorLocatedSlot */
|
* }} ItemAcceptorLocatedSlot
|
||||||
|
*
|
||||||
/** @typedef {{
|
* @typedef {{
|
||||||
* pos: Vector,
|
* pos: Vector,
|
||||||
* directions: enumDirection[],
|
* direction: enumDirection,
|
||||||
* filter?: ItemType
|
* filter?: ItemType
|
||||||
* }} ItemAcceptorSlotConfig */
|
* }} ItemAcceptorSlotConfig
|
||||||
|
*
|
||||||
|
* @typedef {Map<number, {
|
||||||
|
* item: BaseItem,
|
||||||
|
* animProgress: number,
|
||||||
|
* direction: enumDirection
|
||||||
|
* }>} ItemAcceptorInput
|
||||||
|
*
|
||||||
|
* @typedef {{
|
||||||
|
* root: GameRoot,
|
||||||
|
* entity: Entity,
|
||||||
|
* item: BaseItem,
|
||||||
|
* slotIndex: number,
|
||||||
|
* extraProgress: number
|
||||||
|
* }} InputCompletedArgs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @enum {string} */
|
||||||
|
export const enumItemAcceptorTypes = {
|
||||||
|
itemProcessor: "itemProcessor",
|
||||||
|
hub: "hub",
|
||||||
|
storage: "storage",
|
||||||
|
trash: "trash",
|
||||||
|
undergroundBelt: "undergroundBelt",
|
||||||
|
};
|
||||||
|
|
||||||
export class ItemAcceptorComponent extends Component {
|
export class ItemAcceptorComponent extends Component {
|
||||||
static getId() {
|
static getId() {
|
||||||
@ -32,25 +57,15 @@ export class ItemAcceptorComponent extends Component {
|
|||||||
*
|
*
|
||||||
* @param {object} param0
|
* @param {object} param0
|
||||||
* @param {Array<ItemAcceptorSlotConfig>} param0.slots The slots from which we accept items
|
* @param {Array<ItemAcceptorSlotConfig>} param0.slots The slots from which we accept items
|
||||||
|
* @param {enumItemAcceptorTypes=} param0.type Function that gets called when the input of an item is completed
|
||||||
*/
|
*/
|
||||||
constructor({ slots = [] }) {
|
constructor({ slots = [], type = enumItemAcceptorTypes.itemProcessor }) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
/** @type {ItemAcceptorInput} */
|
||||||
|
this.currentInputs = new Map(); // @SENSETODO does this need to be saved?
|
||||||
|
this.type = type;
|
||||||
this.setSlots(slots);
|
this.setSlots(slots);
|
||||||
this.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
clear() {
|
|
||||||
/**
|
|
||||||
* Fixes belt animations
|
|
||||||
* @type {Array<{
|
|
||||||
* item: BaseItem,
|
|
||||||
* slotIndex: number,
|
|
||||||
* animProgress: number,
|
|
||||||
* direction: enumDirection
|
|
||||||
* }>}
|
|
||||||
*/
|
|
||||||
this.itemConsumptionAnimations = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,7 +79,7 @@ export class ItemAcceptorComponent extends Component {
|
|||||||
const slot = slots[i];
|
const slot = slots[i];
|
||||||
this.slots.push({
|
this.slots.push({
|
||||||
pos: slot.pos,
|
pos: slot.pos,
|
||||||
directions: slot.directions,
|
direction: slot.direction,
|
||||||
|
|
||||||
// Which type of item to accept (shape | color | all) @see ItemType
|
// Which type of item to accept (shape | color | all) @see ItemType
|
||||||
filter: slot.filter,
|
filter: slot.filter,
|
||||||
@ -73,31 +88,28 @@ export class ItemAcceptorComponent extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if this acceptor can accept a new item at slot N
|
* Called when trying to input a new item
|
||||||
*
|
|
||||||
* NOTICE: The belt path ignores this for performance reasons and does his own check
|
|
||||||
* @param {number} slotIndex
|
|
||||||
* @param {BaseItem=} item
|
|
||||||
*/
|
|
||||||
canAcceptItem(slotIndex, item) {
|
|
||||||
const slot = this.slots[slotIndex];
|
|
||||||
return !slot.filter || slot.filter === item.getItemType();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when an item has been accepted so that
|
|
||||||
* @param {number} slotIndex
|
* @param {number} slotIndex
|
||||||
* @param {enumDirection} direction
|
* @param {enumDirection} direction
|
||||||
* @param {BaseItem} item
|
* @param {BaseItem} item
|
||||||
* @param {number} remainingProgress World space remaining progress, can be set to set the start position of the item
|
* @param {number} startProgress World space remaining progress, can be set to set the start position of the item
|
||||||
|
* @returns {boolean} if the input was succesful
|
||||||
*/
|
*/
|
||||||
onItemAccepted(slotIndex, direction, item, remainingProgress = 0.0) {
|
tryAcceptItem(slotIndex, direction, item, startProgress = 0.0) {
|
||||||
this.itemConsumptionAnimations.push({
|
const slot = this.slots[slotIndex];
|
||||||
|
|
||||||
|
//@SENSETODO see if this works for buildings like hub
|
||||||
|
|
||||||
|
if (this.currentInputs.has(slotIndex) || (slot.filter && slot.filter != item.getItemType())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentInputs.set(slotIndex, {
|
||||||
item,
|
item,
|
||||||
slotIndex,
|
|
||||||
direction,
|
direction,
|
||||||
animProgress: Math.min(1, remainingProgress * 2),
|
animProgress: Math.min(1, startProgress),
|
||||||
});
|
});
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -121,16 +133,12 @@ export class ItemAcceptorComponent extends Component {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the acceptor slot accepts items from our direction
|
if (desiredDirection === slot.direction) {
|
||||||
for (let i = 0; i < slot.directions.length; ++i) {
|
return {
|
||||||
// const localDirection = targetStaticComp.localDirectionToWorld(slot.directions[l]);
|
slot,
|
||||||
if (desiredDirection === slot.directions[i]) {
|
index: slotIndex,
|
||||||
return {
|
acceptedDirection: desiredDirection,
|
||||||
slot,
|
};
|
||||||
index: slotIndex,
|
|
||||||
acceptedDirection: desiredDirection,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -70,7 +70,7 @@ export class ItemEjectorComponent extends Component {
|
|||||||
direction: slot.direction,
|
direction: slot.direction,
|
||||||
item: null,
|
item: null,
|
||||||
lastItem: null,
|
lastItem: null,
|
||||||
progress: 0,
|
progress: 0, //@SENSETODO needs to be started off with extra time
|
||||||
cachedDestSlot: null,
|
cachedDestSlot: null,
|
||||||
cachedTargetEntity: null,
|
cachedTargetEntity: null,
|
||||||
});
|
});
|
||||||
@ -127,28 +127,16 @@ export class ItemEjectorComponent extends Component {
|
|||||||
* Tries to eject a given item
|
* Tries to eject a given item
|
||||||
* @param {number} slotIndex
|
* @param {number} slotIndex
|
||||||
* @param {BaseItem} item
|
* @param {BaseItem} item
|
||||||
|
* @param {number} startingProgress
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
tryEject(slotIndex, item) {
|
tryEject(slotIndex, item, startingProgress = 0.0) {
|
||||||
if (!this.canEjectOnSlot(slotIndex)) {
|
if (!this.canEjectOnSlot(slotIndex)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.slots[slotIndex].item = item;
|
this.slots[slotIndex].item = item;
|
||||||
this.slots[slotIndex].lastItem = item;
|
this.slots[slotIndex].lastItem = item;
|
||||||
this.slots[slotIndex].progress = 0;
|
this.slots[slotIndex].progress = startingProgress;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the given slot and returns the item it had
|
|
||||||
* @param {number} slotIndex
|
|
||||||
* @returns {BaseItem|null}
|
|
||||||
*/
|
|
||||||
takeSlotItem(slotIndex) {
|
|
||||||
const slot = this.slots[slotIndex];
|
|
||||||
const item = slot.item;
|
|
||||||
slot.item = null;
|
|
||||||
slot.progress = 0.0;
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,16 +27,23 @@ export const enumItemProcessorRequirements = {
|
|||||||
painterQuad: "painterQuad",
|
painterQuad: "painterQuad",
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @typedef {{
|
/**
|
||||||
|
* @typedef {{
|
||||||
* item: BaseItem,
|
* item: BaseItem,
|
||||||
* requiredSlot?: number,
|
* requiredSlot?: number,
|
||||||
* preferredSlot?: number
|
* preferredSlot?: number
|
||||||
* }} EjectorItemToEject */
|
* }} EjectorItemToEject
|
||||||
|
*
|
||||||
/** @typedef {{
|
* @typedef {{
|
||||||
* remainingTime: number,
|
* remainingTime: number,
|
||||||
* items: Array<EjectorItemToEject>,
|
* items: Array<EjectorItemToEject>,
|
||||||
* }} EjectorCharge */
|
* }} EjectorCharge
|
||||||
|
*
|
||||||
|
* @typedef {{
|
||||||
|
* item: BaseItem
|
||||||
|
* extraProgress: number
|
||||||
|
* }} ItemProcessorInput
|
||||||
|
*/
|
||||||
|
|
||||||
export class ItemProcessorComponent extends Component {
|
export class ItemProcessorComponent extends Component {
|
||||||
static getId() {
|
static getId() {
|
||||||
@ -75,9 +82,9 @@ export class ItemProcessorComponent extends Component {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Our current inputs
|
* Our current inputs
|
||||||
* @type {Map<number, BaseItem>}
|
* @type {Map<number, ItemProcessorInput>}
|
||||||
*/
|
*/
|
||||||
this.inputSlots = new Map();
|
this.inputs = new Map();
|
||||||
|
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
@ -88,13 +95,7 @@ export class ItemProcessorComponent extends Component {
|
|||||||
// sure the outputs always match
|
// sure the outputs always match
|
||||||
this.nextOutputSlot = 0;
|
this.nextOutputSlot = 0;
|
||||||
|
|
||||||
this.inputSlots.clear();
|
this.inputs.clear();
|
||||||
|
|
||||||
/**
|
|
||||||
* Current input count
|
|
||||||
* @type {number}
|
|
||||||
*/
|
|
||||||
this.inputCount = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* What we are currently processing, empty if we don't produce anything rn
|
* What we are currently processing, empty if we don't produce anything rn
|
||||||
@ -110,30 +111,4 @@ export class ItemProcessorComponent extends Component {
|
|||||||
*/
|
*/
|
||||||
this.bonusTime = 0;
|
this.bonusTime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to take the item
|
|
||||||
* @param {BaseItem} item
|
|
||||||
* @param {number} sourceSlot
|
|
||||||
*/
|
|
||||||
tryTakeItem(item, sourceSlot) {
|
|
||||||
if (
|
|
||||||
this.type === enumItemProcessorTypes.hub ||
|
|
||||||
this.type === enumItemProcessorTypes.trash ||
|
|
||||||
this.type === enumItemProcessorTypes.goal
|
|
||||||
) {
|
|
||||||
// Hub has special logic .. not really nice but efficient.
|
|
||||||
this.inputSlots.set(this.inputCount, item);
|
|
||||||
this.inputCount++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that we only take one item per slot
|
|
||||||
if (this.inputSlots.has(sourceSlot)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this.inputSlots.set(sourceSlot, item);
|
|
||||||
this.inputCount++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -500,65 +500,58 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic {
|
|||||||
const acceptorSlotWsTile = staticComp.localTileToWorld(slot.pos);
|
const acceptorSlotWsTile = staticComp.localTileToWorld(slot.pos);
|
||||||
const acceptorSlotWsPos = acceptorSlotWsTile.toWorldSpaceCenterOfTile();
|
const acceptorSlotWsPos = acceptorSlotWsTile.toWorldSpaceCenterOfTile();
|
||||||
|
|
||||||
// Go over all slots
|
const direction = slot.direction;
|
||||||
for (
|
const worldDirection = staticComp.localDirectionToWorld(direction);
|
||||||
let acceptorDirectionIndex = 0;
|
|
||||||
acceptorDirectionIndex < slot.directions.length;
|
|
||||||
++acceptorDirectionIndex
|
|
||||||
) {
|
|
||||||
const direction = slot.directions[acceptorDirectionIndex];
|
|
||||||
const worldDirection = staticComp.localDirectionToWorld(direction);
|
|
||||||
|
|
||||||
// Figure out which tile ejects to this slot
|
// Figure out which tile ejects to this slot
|
||||||
const sourceTile = acceptorSlotWsTile.add(enumDirectionToVector[worldDirection]);
|
const sourceTile = acceptorSlotWsTile.add(enumDirectionToVector[worldDirection]);
|
||||||
|
|
||||||
let isBlocked = false;
|
let isBlocked = false;
|
||||||
let isConnected = false;
|
let isConnected = false;
|
||||||
|
|
||||||
// Find all entities which are on that tile
|
// Find all entities which are on that tile
|
||||||
const sourceEntities = this.root.map.getLayersContentsMultipleXY(sourceTile.x, sourceTile.y);
|
const sourceEntities = this.root.map.getLayersContentsMultipleXY(sourceTile.x, sourceTile.y);
|
||||||
|
|
||||||
// Check for every entity:
|
// Check for every entity:
|
||||||
for (let i = 0; i < sourceEntities.length; ++i) {
|
for (let i = 0; i < sourceEntities.length; ++i) {
|
||||||
const sourceEntity = sourceEntities[i];
|
const sourceEntity = sourceEntities[i];
|
||||||
const sourceEjector = sourceEntity.components.ItemEjector;
|
const sourceEjector = sourceEntity.components.ItemEjector;
|
||||||
const sourceBeltComp = sourceEntity.components.Belt;
|
const sourceBeltComp = sourceEntity.components.Belt;
|
||||||
const sourceStaticComp = sourceEntity.components.StaticMapEntity;
|
const sourceStaticComp = sourceEntity.components.StaticMapEntity;
|
||||||
const ejectorAcceptLocalTile = sourceStaticComp.worldToLocalTile(acceptorSlotWsTile);
|
const ejectorAcceptLocalTile = sourceStaticComp.worldToLocalTile(acceptorSlotWsTile);
|
||||||
|
|
||||||
// If this entity is on the same layer as the slot - if so, it can either be
|
// 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
|
// connected, or it can not be connected and thus block the input
|
||||||
if (sourceEjector && sourceEjector.anySlotEjectsToLocalTile(ejectorAcceptLocalTile)) {
|
if (sourceEjector && sourceEjector.anySlotEjectsToLocalTile(ejectorAcceptLocalTile)) {
|
||||||
// This one is connected, all good
|
// This one is connected, all good
|
||||||
isConnected = true;
|
isConnected = true;
|
||||||
} else if (
|
} else if (
|
||||||
sourceBeltComp &&
|
sourceBeltComp &&
|
||||||
sourceStaticComp.localDirectionToWorld(sourceBeltComp.direction) ===
|
sourceStaticComp.localDirectionToWorld(sourceBeltComp.direction) ===
|
||||||
enumInvertedDirections[worldDirection]
|
enumInvertedDirections[worldDirection]
|
||||||
) {
|
) {
|
||||||
// Belt connected
|
// Belt connected
|
||||||
isConnected = true;
|
isConnected = true;
|
||||||
} else {
|
} else {
|
||||||
// This one is blocked
|
// This one is blocked
|
||||||
isBlocked = true;
|
isBlocked = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const alpha = isConnected || isBlocked ? 1.0 : 0.3;
|
|
||||||
const sprite = isBlocked ? badArrowSprite : goodArrowSprite;
|
|
||||||
|
|
||||||
parameters.context.globalAlpha = alpha;
|
|
||||||
drawRotatedSprite({
|
|
||||||
parameters,
|
|
||||||
sprite,
|
|
||||||
x: acceptorSlotWsPos.x,
|
|
||||||
y: acceptorSlotWsPos.y,
|
|
||||||
angle: Math.radians(enumDirectionToAngle[enumInvertedDirections[worldDirection]]),
|
|
||||||
size: 13,
|
|
||||||
offsetY: offsetShift + 13,
|
|
||||||
});
|
|
||||||
parameters.context.globalAlpha = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const alpha = isConnected || isBlocked ? 1.0 : 0.3;
|
||||||
|
const sprite = isBlocked ? badArrowSprite : goodArrowSprite;
|
||||||
|
|
||||||
|
parameters.context.globalAlpha = alpha;
|
||||||
|
drawRotatedSprite({
|
||||||
|
parameters,
|
||||||
|
sprite,
|
||||||
|
x: acceptorSlotWsPos.x,
|
||||||
|
y: acceptorSlotWsPos.y,
|
||||||
|
angle: Math.radians(enumDirectionToAngle[enumInvertedDirections[worldDirection]]),
|
||||||
|
size: 13,
|
||||||
|
offsetY: offsetShift + 13,
|
||||||
|
});
|
||||||
|
parameters.context.globalAlpha = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go over all slots
|
// Go over all slots
|
||||||
|
|||||||
@ -431,22 +431,20 @@ export class GameLogic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let acceptorSlot = 0; acceptorSlot < acceptorSlots.length; ++acceptorSlot) {
|
for (let i = 0; i < acceptorSlots.length; ++i) {
|
||||||
const slot = acceptorSlots[acceptorSlot];
|
const slot = acceptorSlots[i];
|
||||||
const wsTile = staticComp.localTileToWorld(slot.pos);
|
const wsTile = staticComp.localTileToWorld(slot.pos);
|
||||||
for (let k = 0; k < slot.directions.length; ++k) {
|
const direction = slot.direction;
|
||||||
const direction = slot.directions[k];
|
const wsDirection = staticComp.localDirectionToWorld(direction);
|
||||||
const wsDirection = staticComp.localDirectionToWorld(direction);
|
|
||||||
|
|
||||||
const sourceTile = wsTile.add(enumDirectionToVector[wsDirection]);
|
const sourceTile = wsTile.add(enumDirectionToVector[wsDirection]);
|
||||||
if (sourceTile.equals(tile)) {
|
if (sourceTile.equals(tile)) {
|
||||||
acceptors.push({
|
acceptors.push({
|
||||||
entity,
|
entity,
|
||||||
slot,
|
slot,
|
||||||
toTile: wsTile,
|
toTile: wsTile,
|
||||||
fromDirection: wsDirection,
|
fromDirection: wsDirection,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,58 +1,67 @@
|
|||||||
import { globalConfig } from "../../core/config";
|
import { globalConfig } from "../../core/config";
|
||||||
import { DrawParameters } from "../../core/draw_parameters";
|
import { DrawParameters } from "../../core/draw_parameters";
|
||||||
import { fastArrayDelete } from "../../core/utils";
|
|
||||||
import { enumDirectionToVector } from "../../core/vector";
|
import { enumDirectionToVector } from "../../core/vector";
|
||||||
import { ItemAcceptorComponent } from "../components/item_acceptor";
|
import {
|
||||||
|
enumItemAcceptorTypes,
|
||||||
|
ItemAcceptorComponent,
|
||||||
|
InputCompletedArgs,
|
||||||
|
} from "../components/item_acceptor";
|
||||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||||
|
import { ShapeItem } from "../items/shape_item";
|
||||||
import { MapChunkView } from "../map_chunk_view";
|
import { MapChunkView } from "../map_chunk_view";
|
||||||
|
|
||||||
export class ItemAcceptorSystem extends GameSystemWithFilter {
|
export class ItemAcceptorSystem extends GameSystemWithFilter {
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
super(root, [ItemAcceptorComponent]);
|
super(root, [ItemAcceptorComponent]);
|
||||||
|
|
||||||
// Well ... it's better to be verbose I guess?
|
/**
|
||||||
this.accumulatedTicksWhileInMapOverview = 0;
|
* @type {Object<enumItemAcceptorTypes, function(InputCompletedArgs) : string>}
|
||||||
|
*/
|
||||||
|
this.handlers = {
|
||||||
|
[enumItemAcceptorTypes.itemProcessor]: this.input_ITEMPROCESSOR,
|
||||||
|
[enumItemAcceptorTypes.hub]: this.input_HUB,
|
||||||
|
[enumItemAcceptorTypes.trash]: this.input_TRASH,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bind all handlers
|
||||||
|
for (const key in this.handlers) {
|
||||||
|
this.handlers[key] = this.handlers[key].bind(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
if (this.root.app.settings.getAllSettings().simplifiedBelts) {
|
// * 2 because its only a half tile - (same code as ejector)
|
||||||
// Disabled in potato mode
|
const progressGrowth =
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This system doesn't render anything while in map overview,
|
|
||||||
// so simply accumulate ticks
|
|
||||||
if (this.root.camera.getIsMapOverlayActive()) {
|
|
||||||
++this.accumulatedTicksWhileInMapOverview;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute how much ticks we missed
|
|
||||||
const numTicks = 1 + this.accumulatedTicksWhileInMapOverview;
|
|
||||||
const progress =
|
|
||||||
this.root.dynamicTickrate.deltaSeconds *
|
|
||||||
2 *
|
2 *
|
||||||
|
this.root.dynamicTickrate.deltaSeconds *
|
||||||
this.root.hubGoals.getBeltBaseSpeed() *
|
this.root.hubGoals.getBeltBaseSpeed() *
|
||||||
globalConfig.itemSpacingOnBelts * // * 2 because its only a half tile
|
globalConfig.itemSpacingOnBelts;
|
||||||
numTicks;
|
|
||||||
|
|
||||||
// Reset accumulated ticks
|
|
||||||
this.accumulatedTicksWhileInMapOverview = 0;
|
|
||||||
|
|
||||||
for (let i = 0; i < this.allEntities.length; ++i) {
|
for (let i = 0; i < this.allEntities.length; ++i) {
|
||||||
const entity = this.allEntities[i];
|
const entity = this.allEntities[i];
|
||||||
const aceptorComp = entity.components.ItemAcceptor;
|
const acceptorComp = entity.components.ItemAcceptor;
|
||||||
const animations = aceptorComp.itemConsumptionAnimations;
|
const inputs = acceptorComp.currentInputs;
|
||||||
|
|
||||||
// Process item consumption animations to avoid items popping from the belts
|
inputs.forEach((values, index) => {
|
||||||
for (let animIndex = 0; animIndex < animations.length; ++animIndex) {
|
if (values.animProgress >= 1) return; // items which are inputted already
|
||||||
const anim = animations[animIndex];
|
|
||||||
anim.animProgress += progress;
|
values.animProgress += progressGrowth;
|
||||||
if (anim.animProgress > 1) {
|
|
||||||
fastArrayDelete(animations, animIndex);
|
if (values.animProgress < 1) return;
|
||||||
animIndex -= 1;
|
|
||||||
}
|
/** @type {function(InputCompletedArgs) : string} */
|
||||||
}
|
const handler = this.handlers[acceptorComp.type];
|
||||||
|
assert(handler, "No handler for acceptor type defined: " + acceptorComp.type);
|
||||||
|
|
||||||
|
// Call implementation
|
||||||
|
handler({
|
||||||
|
root: this.root,
|
||||||
|
entity,
|
||||||
|
item: values.item,
|
||||||
|
slotIndex: index,
|
||||||
|
extraProgress: values.animProgress - 1,
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,17 +84,16 @@ export class ItemAcceptorSystem extends GameSystemWithFilter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const staticComp = entity.components.StaticMapEntity;
|
const staticComp = entity.components.StaticMapEntity;
|
||||||
for (let animIndex = 0; animIndex < acceptorComp.itemConsumptionAnimations.length; ++animIndex) {
|
acceptorComp.currentInputs.forEach((values, index) => {
|
||||||
const { item, slotIndex, animProgress, direction } = acceptorComp.itemConsumptionAnimations[
|
const { item, animProgress, direction } = values;
|
||||||
animIndex
|
if (animProgress >= 1) return; // items which are inputted already
|
||||||
];
|
|
||||||
|
|
||||||
const slotData = acceptorComp.slots[slotIndex];
|
const slotData = acceptorComp.slots[index];
|
||||||
const realSlotPos = staticComp.localTileToWorld(slotData.pos);
|
const realSlotPos = staticComp.localTileToWorld(slotData.pos);
|
||||||
|
|
||||||
if (!chunk.tileSpaceRectangle.containsPoint(realSlotPos.x, realSlotPos.y)) {
|
if (!chunk.tileSpaceRectangle.containsPoint(realSlotPos.x, realSlotPos.y)) {
|
||||||
// Not within this chunk
|
// Not within this chunk
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fadeOutDirection = enumDirectionToVector[staticComp.localDirectionToWorld(direction)];
|
const fadeOutDirection = enumDirectionToVector[staticComp.localDirectionToWorld(direction)];
|
||||||
@ -100,7 +108,49 @@ export class ItemAcceptorSystem extends GameSystemWithFilter {
|
|||||||
parameters,
|
parameters,
|
||||||
globalConfig.defaultItemDiameter
|
globalConfig.defaultItemDiameter
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {InputCompletedArgs} args
|
||||||
|
*/
|
||||||
|
input_ITEMPROCESSOR(args) {
|
||||||
|
const entity = args.entity;
|
||||||
|
|
||||||
|
const itemProcessorComp = entity.components.ItemProcessor;
|
||||||
|
assert(itemProcessorComp, "No item processor to input item to");
|
||||||
|
|
||||||
|
itemProcessorComp.inputs.set(args.slotIndex, {
|
||||||
|
item: args.item,
|
||||||
|
extraProgress: args.extraProgress,
|
||||||
|
}); // in the future the item processor will not need a list of items
|
||||||
|
}
|
||||||
|
//@SENSETODO this isn't set up like it should be yet
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {InputCompletedArgs} args
|
||||||
|
*/
|
||||||
|
input_HUB(args) {
|
||||||
|
const item = /** @type {ShapeItem} */ (args.item);
|
||||||
|
assert(item instanceof ShapeItem, "Input for hub is not a shape");
|
||||||
|
|
||||||
|
this.root.hubGoals.handleDefinitionDelivered(item.definition);
|
||||||
|
|
||||||
|
const acceptorComp = args.entity.components.ItemAcceptor;
|
||||||
|
acceptorComp.currentInputs.delete(args.slotIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {InputCompletedArgs} args
|
||||||
|
*/
|
||||||
|
input_TRASH(args) {
|
||||||
|
// just remove the item
|
||||||
|
const acceptorComp = args.entity.components.ItemAcceptor;
|
||||||
|
acceptorComp.currentInputs.delete(args.slotIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
//storage
|
||||||
|
|
||||||
|
//underground belt
|
||||||
}
|
}
|
||||||
|
|||||||
@ -139,169 +139,76 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
|
|||||||
update() {
|
update() {
|
||||||
this.staleAreaDetector.update();
|
this.staleAreaDetector.update();
|
||||||
|
|
||||||
// Precompute effective belt speed
|
// * 2 because its only a half tile - (same code as acceptor)
|
||||||
let progressGrowth = 2 * this.root.dynamicTickrate.deltaSeconds;
|
const progressGrowth =
|
||||||
|
2 *
|
||||||
if (G_IS_DEV && globalConfig.debug.instantBelts) {
|
this.root.dynamicTickrate.deltaSeconds *
|
||||||
progressGrowth = 1;
|
this.root.hubGoals.getBeltBaseSpeed() *
|
||||||
}
|
globalConfig.itemSpacingOnBelts;
|
||||||
|
|
||||||
// Go over all cache entries
|
// Go over all cache entries
|
||||||
for (let i = 0; i < this.allEntities.length; ++i) {
|
for (let i = 0; i < this.allEntities.length; ++i) {
|
||||||
const sourceEntity = this.allEntities[i];
|
const entity = this.allEntities[i];
|
||||||
const sourceEjectorComp = sourceEntity.components.ItemEjector;
|
const ejectorComp = entity.components.ItemEjector;
|
||||||
|
const slots = ejectorComp.slots;
|
||||||
|
|
||||||
const slots = sourceEjectorComp.slots;
|
|
||||||
for (let j = 0; j < slots.length; ++j) {
|
for (let j = 0; j < slots.length; ++j) {
|
||||||
const sourceSlot = slots[j];
|
const slot = slots[j];
|
||||||
const item = sourceSlot.item;
|
const item = slot.item;
|
||||||
if (!item) {
|
if (!item) {
|
||||||
// No item available to be ejected
|
// No output in progress
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advance items on the slot
|
// Advance items on the slot
|
||||||
sourceSlot.progress = Math.min(
|
// @SENSETODO do we really want to cap it at one, or should the excess get passed on?
|
||||||
1,
|
slot.progress = Math.min(1, slot.progress + progressGrowth);
|
||||||
sourceSlot.progress +
|
|
||||||
progressGrowth *
|
|
||||||
this.root.hubGoals.getBeltBaseSpeed() *
|
|
||||||
globalConfig.itemSpacingOnBelts
|
|
||||||
);
|
|
||||||
|
|
||||||
if (G_IS_DEV && globalConfig.debug.disableEjectorProcessing) {
|
if (G_IS_DEV && globalConfig.debug.disableEjectorProcessing) {
|
||||||
sourceSlot.progress = 1.0;
|
slot.progress = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we are still in the process of ejecting, can't proceed then
|
// Check if we are still in the process of ejecting, can't proceed then
|
||||||
if (sourceSlot.progress < 1.0) {
|
if (slot.progress < 1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we are ejecting to a belt path
|
// Check if we are ejecting to a belt path
|
||||||
const destPath = sourceSlot.cachedBeltPath;
|
const destPath = slot.cachedBeltPath;
|
||||||
if (destPath) {
|
if (destPath) {
|
||||||
// Try passing the item over
|
// Try passing the item over
|
||||||
if (destPath.tryAcceptItem(item)) {
|
if (destPath.tryAcceptItem(item)) {
|
||||||
sourceSlot.item = null;
|
slot.item = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always stop here, since there can *either* be a belt path *or*
|
// Always stop here, since there can *either* be a belt path *or* an acceptor
|
||||||
// a slot
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the target acceptor can actually accept this item
|
// Check if the target acceptor can actually accept this item
|
||||||
const destEntity = sourceSlot.cachedTargetEntity;
|
const destEntity = slot.cachedTargetEntity;
|
||||||
const destSlot = sourceSlot.cachedDestSlot;
|
const destSlot = slot.cachedDestSlot;
|
||||||
if (destSlot) {
|
if (destEntity && destSlot) {
|
||||||
const targetAcceptorComp = destEntity.components.ItemAcceptor;
|
const targetAcceptorComp = destEntity.components.ItemAcceptor;
|
||||||
if (!targetAcceptorComp.canAcceptItem(destSlot.index, item)) {
|
const extraProgress = slot.progress - 1;
|
||||||
continue;
|
if (
|
||||||
}
|
targetAcceptorComp.tryAcceptItem(
|
||||||
|
destSlot.index,
|
||||||
// Try to hand over the item
|
destSlot.acceptedDirection,
|
||||||
if (this.tryPassOverItem(item, destEntity, destSlot.index)) {
|
item,
|
||||||
|
extraProgress
|
||||||
|
)
|
||||||
|
) {
|
||||||
// Handover successful, clear slot
|
// Handover successful, clear slot
|
||||||
if (!this.root.app.settings.getAllSettings().simplifiedBelts) {
|
slot.item = null;
|
||||||
targetAcceptorComp.onItemAccepted(
|
|
||||||
destSlot.index,
|
|
||||||
destSlot.acceptedDirection,
|
|
||||||
item
|
|
||||||
);
|
|
||||||
}
|
|
||||||
sourceSlot.item = null;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//@SENSETODO deal with other buildings - acceptor code on them needs to be different!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {BaseItem} item
|
|
||||||
* @param {Entity} receiver
|
|
||||||
* @param {number} slotIndex
|
|
||||||
*/
|
|
||||||
tryPassOverItem(item, receiver, slotIndex) {
|
|
||||||
// Try figuring out how what to do with the item
|
|
||||||
// @TODO: Kinda hacky. How to solve this properly? Don't want to go through inheritance hell.
|
|
||||||
|
|
||||||
const beltComp = receiver.components.Belt;
|
|
||||||
if (beltComp) {
|
|
||||||
const path = beltComp.assignedPath;
|
|
||||||
assert(path, "belt has no path");
|
|
||||||
if (path.tryAcceptItem(item)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Belt can have nothing else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// NOTICE ! THIS CODE IS DUPLICATED IN THE BELT PATH FOR PERFORMANCE REASONS
|
|
||||||
//
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
const itemProcessorComp = receiver.components.ItemProcessor;
|
|
||||||
if (itemProcessorComp) {
|
|
||||||
// Check for potential filters
|
|
||||||
if (!this.root.systemMgr.systems.itemProcessor.checkRequirements(receiver, item, slotIndex)) {
|
|
||||||
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;
|
|
||||||
if (undergroundBeltComp) {
|
|
||||||
// Its an underground belt. yay.
|
|
||||||
if (
|
|
||||||
undergroundBeltComp.tryAcceptExternalItem(
|
|
||||||
item,
|
|
||||||
this.root.hubGoals.getUndergroundBeltBaseSpeed()
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Underground belt can have nothing else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const storageComp = receiver.components.Storage;
|
|
||||||
if (storageComp) {
|
|
||||||
// It's a storage
|
|
||||||
if (storageComp.canAcceptItem(item)) {
|
|
||||||
storageComp.takeItem(item);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Storage can't have anything else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const filterComp = receiver.components.Filter;
|
|
||||||
if (filterComp) {
|
|
||||||
// It's a filter! Unfortunately the filter has to know a lot about it's
|
|
||||||
// surrounding state and components, so it can't be within the component itself.
|
|
||||||
if (this.root.systemMgr.systems.filter.tryAcceptItem(receiver, slotIndex, item)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {DrawParameters} parameters
|
* @param {DrawParameters} parameters
|
||||||
* @param {MapChunkView} chunk
|
* @param {MapChunkView} chunk
|
||||||
@ -390,11 +297,6 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
|
|||||||
progress = Math.min(maxProgress, progress);
|
progress = Math.min(maxProgress, progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip if the item would barely be visible
|
|
||||||
if (progress < 0.05) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const realPosition = staticComp.localTileToWorld(slot.pos);
|
const realPosition = staticComp.localTileToWorld(slot.pos);
|
||||||
if (!chunk.tileSpaceRectangle.containsPoint(realPosition.x, realPosition.y)) {
|
if (!chunk.tileSpaceRectangle.containsPoint(realPosition.x, realPosition.y)) {
|
||||||
// Not within this chunk
|
// Not within this chunk
|
||||||
@ -419,4 +321,90 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////// OBSOLETE
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {BaseItem} item
|
||||||
|
* @param {Entity} receiver
|
||||||
|
* @param {number} slotIndex
|
||||||
|
*/
|
||||||
|
tryPassOverItem(item, receiver, slotIndex) {
|
||||||
|
// Try figuring out how what to do with the item
|
||||||
|
// @TODO: Kinda hacky. How to solve this properly? Don't want to go through inheritance hell.
|
||||||
|
|
||||||
|
const beltComp = receiver.components.Belt;
|
||||||
|
if (beltComp) {
|
||||||
|
const path = beltComp.assignedPath;
|
||||||
|
assert(path, "belt has no path");
|
||||||
|
if (path.tryAcceptItem(item)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Belt can have nothing else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// NOTICE ! THIS CODE IS DUPLICATED IN THE BELT PATH FOR PERFORMANCE REASONS
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
const itemProcessorComp = receiver.components.ItemProcessor;
|
||||||
|
if (itemProcessorComp) {
|
||||||
|
// Check for potential filters
|
||||||
|
if (!this.root.systemMgr.systems.itemProcessor.checkRequirements(receiver, item, slotIndex)) {
|
||||||
|
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;
|
||||||
|
if (undergroundBeltComp) {
|
||||||
|
// Its an underground belt. yay.
|
||||||
|
if (
|
||||||
|
undergroundBeltComp.tryAcceptExternalItem(
|
||||||
|
item,
|
||||||
|
this.root.hubGoals.getUndergroundBeltBaseSpeed()
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Underground belt can have nothing else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const storageComp = receiver.components.Storage;
|
||||||
|
if (storageComp) {
|
||||||
|
// It's a storage
|
||||||
|
if (storageComp.canAcceptItem(item)) {
|
||||||
|
storageComp.takeItem(item);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Storage can't have anything else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const filterComp = receiver.components.Filter;
|
||||||
|
if (filterComp) {
|
||||||
|
// It's a filter! Unfortunately the filter has to know a lot about it's
|
||||||
|
// surrounding state and components, so it can't be within the component itself.
|
||||||
|
if (this.root.systemMgr.systems.filter.tryAcceptItem(receiver, slotIndex, item)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import { ShapeItem } from "../items/shape_item";
|
|||||||
/**
|
/**
|
||||||
* We need to allow queuing charges, otherwise the throughput will stall
|
* We need to allow queuing charges, otherwise the throughput will stall
|
||||||
*/
|
*/
|
||||||
|
//@SENSETODO not sure if this is true anymore
|
||||||
const MAX_QUEUED_CHARGES = 2;
|
const MAX_QUEUED_CHARGES = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,6 +23,7 @@ const MAX_QUEUED_CHARGES = 2;
|
|||||||
*
|
*
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
* item: BaseItem,
|
* item: BaseItem,
|
||||||
|
* extraProgress?: number,
|
||||||
* preferredSlot?: number,
|
* preferredSlot?: number,
|
||||||
* requiredSlot?: number,
|
* requiredSlot?: number,
|
||||||
* doNotTrack?: boolean
|
* doNotTrack?: boolean
|
||||||
@ -32,8 +34,7 @@ const MAX_QUEUED_CHARGES = 2;
|
|||||||
* Type of a processor implementation
|
* Type of a processor implementation
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
* entity: Entity,
|
* entity: Entity,
|
||||||
* items: Map<number, BaseItem>,
|
* inputs: Map<number, import("../components/item_processor").ItemProcessorInput>,
|
||||||
* inputCount: number,
|
|
||||||
* outItems: Array<ProducedItem>
|
* outItems: Array<ProducedItem>
|
||||||
* }} ProcessorImplementationPayload
|
* }} ProcessorImplementationPayload
|
||||||
*/
|
*/
|
||||||
@ -133,6 +134,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//@SENSETODO add code in here that handles queued outputs -rearrange where this is too
|
||||||
|
|
||||||
// If the charge was entirely emptied to the outputs, start the next charge
|
// If the charge was entirely emptied to the outputs, start the next charge
|
||||||
if (itemsToEject.length === 0) {
|
if (itemsToEject.length === 0) {
|
||||||
processorComp.ongoingCharges.shift();
|
processorComp.ongoingCharges.shift();
|
||||||
@ -195,7 +198,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
// DEFAULT
|
// DEFAULT
|
||||||
// By default, we can start processing once all inputs are there
|
// By default, we can start processing once all inputs are there
|
||||||
case null: {
|
case null: {
|
||||||
return processorComp.inputCount >= processorComp.inputsPerCharge;
|
return processorComp.inputs.size >= processorComp.inputsPerCharge;
|
||||||
}
|
}
|
||||||
|
|
||||||
// QUAD PAINTER
|
// QUAD PAINTER
|
||||||
@ -204,7 +207,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
const pinsComp = entity.components.WiredPins;
|
const pinsComp = entity.components.WiredPins;
|
||||||
|
|
||||||
// First slot is the shape, so if it's not there we can't do anything
|
// First slot is the shape, so if it's not there we can't do anything
|
||||||
const shapeItem = /** @type {ShapeItem} */ (processorComp.inputSlots.get(0));
|
const shapeItem = /** @type {ShapeItem} */ (processorComp.inputs.get(0).item);
|
||||||
if (!shapeItem) {
|
if (!shapeItem) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -233,7 +236,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
|
|
||||||
// Check if all colors of the enabled slots are there
|
// Check if all colors of the enabled slots are there
|
||||||
for (let i = 0; i < slotStatus.length; ++i) {
|
for (let i = 0; i < slotStatus.length; ++i) {
|
||||||
if (slotStatus[i] && !processorComp.inputSlots.get(1 + i)) {
|
if (slotStatus[i] && !processorComp.inputs.get(1 + i)) {
|
||||||
// A slot which is enabled wasn't enabled. Make sure if there is anything on the quadrant,
|
// A slot which is enabled wasn't enabled. Make sure if there is anything on the quadrant,
|
||||||
// it is not possible to paint, but if there is nothing we can ignore it
|
// it is not possible to paint, but if there is nothing we can ignore it
|
||||||
for (let j = 0; j < 4; ++j) {
|
for (let j = 0; j < 4; ++j) {
|
||||||
@ -260,8 +263,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
startNewCharge(entity) {
|
startNewCharge(entity) {
|
||||||
const processorComp = entity.components.ItemProcessor;
|
const processorComp = entity.components.ItemProcessor;
|
||||||
|
|
||||||
// First, take items
|
// First, take inputs
|
||||||
const items = processorComp.inputSlots;
|
const inputs = processorComp.inputs;
|
||||||
|
|
||||||
/** @type {Array<ProducedItem>} */
|
/** @type {Array<ProducedItem>} */
|
||||||
const outItems = [];
|
const outItems = [];
|
||||||
@ -273,9 +276,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
// Call implementation
|
// Call implementation
|
||||||
handler({
|
handler({
|
||||||
entity,
|
entity,
|
||||||
items,
|
inputs: inputs,
|
||||||
outItems,
|
outItems,
|
||||||
inputCount: processorComp.inputCount,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Track produced items
|
// Track produced items
|
||||||
@ -298,8 +300,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
remainingTime: timeToProcess,
|
remainingTime: timeToProcess,
|
||||||
});
|
});
|
||||||
|
|
||||||
processorComp.inputSlots.clear();
|
processorComp.inputs.clear(); //@SENSETODO temp, will completely replace processorcomp.inputs with acceptor inputs later
|
||||||
processorComp.inputCount = 0;
|
entity.components.ItemAcceptor.currentInputs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -314,12 +316,12 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
const processorComp = payload.entity.components.ItemProcessor;
|
const processorComp = payload.entity.components.ItemProcessor;
|
||||||
|
|
||||||
for (let i = 0; i < 2; ++i) {
|
for (let i = 0; i < 2; ++i) {
|
||||||
const item = payload.items.get(i);
|
const input = payload.inputs.get(i);
|
||||||
if (!item) {
|
if (!input || !input.item) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
payload.outItems.push({
|
payload.outItems.push({
|
||||||
item,
|
item: input.item,
|
||||||
preferredSlot: processorComp.nextOutputSlot++ % availableSlots,
|
preferredSlot: processorComp.nextOutputSlot++ % availableSlots,
|
||||||
doNotTrack: true,
|
doNotTrack: true,
|
||||||
});
|
});
|
||||||
@ -331,7 +333,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
* @param {ProcessorImplementationPayload} payload
|
* @param {ProcessorImplementationPayload} payload
|
||||||
*/
|
*/
|
||||||
process_CUTTER(payload) {
|
process_CUTTER(payload) {
|
||||||
const inputItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
const input = payload.inputs.get(0);
|
||||||
|
const inputItem = /** @type {ShapeItem} */ (input.item);
|
||||||
assert(inputItem instanceof ShapeItem, "Input for cut is not a shape");
|
assert(inputItem instanceof ShapeItem, "Input for cut is not a shape");
|
||||||
const inputDefinition = inputItem.definition;
|
const inputDefinition = inputItem.definition;
|
||||||
|
|
||||||
@ -357,7 +360,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
* @param {ProcessorImplementationPayload} payload
|
* @param {ProcessorImplementationPayload} payload
|
||||||
*/
|
*/
|
||||||
process_CUTTER_QUAD(payload) {
|
process_CUTTER_QUAD(payload) {
|
||||||
const inputItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
const input = payload.inputs.get(0);
|
||||||
|
const inputItem = /** @type {ShapeItem} */ (input.item);
|
||||||
assert(inputItem instanceof ShapeItem, "Input for cut is not a shape");
|
assert(inputItem instanceof ShapeItem, "Input for cut is not a shape");
|
||||||
const inputDefinition = inputItem.definition;
|
const inputDefinition = inputItem.definition;
|
||||||
|
|
||||||
@ -383,7 +387,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
* @param {ProcessorImplementationPayload} payload
|
* @param {ProcessorImplementationPayload} payload
|
||||||
*/
|
*/
|
||||||
process_ROTATER(payload) {
|
process_ROTATER(payload) {
|
||||||
const inputItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
const input = payload.inputs.get(0);
|
||||||
|
const inputItem = /** @type {ShapeItem} */ (input.item);
|
||||||
assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape");
|
assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape");
|
||||||
const inputDefinition = inputItem.definition;
|
const inputDefinition = inputItem.definition;
|
||||||
|
|
||||||
@ -397,7 +402,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
* @param {ProcessorImplementationPayload} payload
|
* @param {ProcessorImplementationPayload} payload
|
||||||
*/
|
*/
|
||||||
process_ROTATER_CCW(payload) {
|
process_ROTATER_CCW(payload) {
|
||||||
const inputItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
const input = payload.inputs.get(0);
|
||||||
|
const inputItem = /** @type {ShapeItem} */ (input.item);
|
||||||
assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape");
|
assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape");
|
||||||
const inputDefinition = inputItem.definition;
|
const inputDefinition = inputItem.definition;
|
||||||
|
|
||||||
@ -411,7 +417,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
* @param {ProcessorImplementationPayload} payload
|
* @param {ProcessorImplementationPayload} payload
|
||||||
*/
|
*/
|
||||||
process_ROTATER_180(payload) {
|
process_ROTATER_180(payload) {
|
||||||
const inputItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
const input = payload.inputs.get(0);
|
||||||
|
const inputItem = /** @type {ShapeItem} */ (input.item);
|
||||||
assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape");
|
assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape");
|
||||||
const inputDefinition = inputItem.definition;
|
const inputDefinition = inputItem.definition;
|
||||||
|
|
||||||
@ -425,8 +432,10 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
* @param {ProcessorImplementationPayload} payload
|
* @param {ProcessorImplementationPayload} payload
|
||||||
*/
|
*/
|
||||||
process_STACKER(payload) {
|
process_STACKER(payload) {
|
||||||
const lowerItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
const lowerInput = payload.inputs.get(0);
|
||||||
const upperItem = /** @type {ShapeItem} */ (payload.items.get(1));
|
const upperInput = payload.inputs.get(0);
|
||||||
|
const lowerItem = /** @type {ShapeItem} */ (lowerInput.item);
|
||||||
|
const upperItem = /** @type {ShapeItem} */ (upperInput.item);
|
||||||
|
|
||||||
assert(lowerItem instanceof ShapeItem, "Input for lower stack is not a shape");
|
assert(lowerItem instanceof ShapeItem, "Input for lower stack is not a shape");
|
||||||
assert(upperItem instanceof ShapeItem, "Input for upper stack is not a shape");
|
assert(upperItem instanceof ShapeItem, "Input for upper stack is not a shape");
|
||||||
@ -451,9 +460,11 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
* @param {ProcessorImplementationPayload} payload
|
* @param {ProcessorImplementationPayload} payload
|
||||||
*/
|
*/
|
||||||
process_MIXER(payload) {
|
process_MIXER(payload) {
|
||||||
|
const input1 = payload.inputs.get(0);
|
||||||
|
const input2 = payload.inputs.get(1);
|
||||||
// Find both colors and combine them
|
// Find both colors and combine them
|
||||||
const item1 = /** @type {ColorItem} */ (payload.items.get(0));
|
const item1 = /** @type {ColorItem} */ (input1.item);
|
||||||
const item2 = /** @type {ColorItem} */ (payload.items.get(1));
|
const item2 = /** @type {ColorItem} */ (input2.item);
|
||||||
assert(item1 instanceof ColorItem, "Input for color mixer is not a color");
|
assert(item1 instanceof ColorItem, "Input for color mixer is not a color");
|
||||||
assert(item2 instanceof ColorItem, "Input for color mixer is not a color");
|
assert(item2 instanceof ColorItem, "Input for color mixer is not a color");
|
||||||
|
|
||||||
@ -475,8 +486,10 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
* @param {ProcessorImplementationPayload} payload
|
* @param {ProcessorImplementationPayload} payload
|
||||||
*/
|
*/
|
||||||
process_PAINTER(payload) {
|
process_PAINTER(payload) {
|
||||||
const shapeItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
const input1 = payload.inputs.get(0);
|
||||||
const colorItem = /** @type {ColorItem} */ (payload.items.get(1));
|
const input2 = payload.inputs.get(1);
|
||||||
|
const shapeItem = /** @type {ShapeItem} */ (input1.item);
|
||||||
|
const colorItem = /** @type {ColorItem} */ (input2.item);
|
||||||
|
|
||||||
const colorizedDefinition = this.root.shapeDefinitionMgr.shapeActionPaintWith(
|
const colorizedDefinition = this.root.shapeDefinitionMgr.shapeActionPaintWith(
|
||||||
shapeItem.definition,
|
shapeItem.definition,
|
||||||
@ -492,9 +505,9 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
* @param {ProcessorImplementationPayload} payload
|
* @param {ProcessorImplementationPayload} payload
|
||||||
*/
|
*/
|
||||||
process_PAINTER_DOUBLE(payload) {
|
process_PAINTER_DOUBLE(payload) {
|
||||||
const shapeItem1 = /** @type {ShapeItem} */ (payload.items.get(0));
|
const shapeItem1 = /** @type {ShapeItem} */ (payload.inputs.get(0).item);
|
||||||
const shapeItem2 = /** @type {ShapeItem} */ (payload.items.get(1));
|
const shapeItem2 = /** @type {ShapeItem} */ (payload.inputs.get(1).item);
|
||||||
const colorItem = /** @type {ColorItem} */ (payload.items.get(2));
|
const colorItem = /** @type {ColorItem} */ (payload.inputs.get(2).item);
|
||||||
|
|
||||||
assert(shapeItem1 instanceof ShapeItem, "Input for painter is not a shape");
|
assert(shapeItem1 instanceof ShapeItem, "Input for painter is not a shape");
|
||||||
assert(shapeItem2 instanceof ShapeItem, "Input for painter is not a shape");
|
assert(shapeItem2 instanceof ShapeItem, "Input for painter is not a shape");
|
||||||
@ -522,13 +535,14 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
* @param {ProcessorImplementationPayload} payload
|
* @param {ProcessorImplementationPayload} payload
|
||||||
*/
|
*/
|
||||||
process_PAINTER_QUAD(payload) {
|
process_PAINTER_QUAD(payload) {
|
||||||
const shapeItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
const input = payload.inputs.get(0);
|
||||||
|
const shapeItem = /** @type {ShapeItem} */ (input.item);
|
||||||
assert(shapeItem instanceof ShapeItem, "Input for painter is not a shape");
|
assert(shapeItem instanceof ShapeItem, "Input for painter is not a shape");
|
||||||
|
|
||||||
/** @type {Array<enumColors>} */
|
/** @type {Array<enumColors>} */
|
||||||
const colors = [null, null, null, null];
|
const colors = [null, null, null, null];
|
||||||
for (let i = 0; i < 4; ++i) {
|
for (let i = 0; i < 4; ++i) {
|
||||||
const colorItem = /** @type {ColorItem} */ (payload.items.get(i + 1));
|
const colorItem = /** @type {ColorItem} */ (payload.inputs.get(i + 1).item);
|
||||||
if (colorItem) {
|
if (colorItem) {
|
||||||
colors[i] = colorItem.color;
|
colors[i] = colorItem.color;
|
||||||
}
|
}
|
||||||
@ -549,7 +563,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
*/
|
*/
|
||||||
process_READER(payload) {
|
process_READER(payload) {
|
||||||
// Pass through the item
|
// Pass through the item
|
||||||
const item = payload.items.get(0);
|
const item = payload.inputs.get(0).item;
|
||||||
payload.outItems.push({
|
payload.outItems.push({
|
||||||
item,
|
item,
|
||||||
doNotTrack: true,
|
doNotTrack: true,
|
||||||
@ -565,17 +579,17 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
* @param {ProcessorImplementationPayload} payload
|
* @param {ProcessorImplementationPayload} payload
|
||||||
*/
|
*/
|
||||||
process_HUB(payload) {
|
process_HUB(payload) {
|
||||||
const hubComponent = payload.entity.components.Hub;
|
//const input = payload.inputs.get(i);
|
||||||
assert(hubComponent, "Hub item processor has no hub component");
|
//const hubComponent = payload.entity.components.Hub;
|
||||||
|
//assert(hubComponent, "Hub item processor has no hub component");
|
||||||
// Hardcoded
|
//// Hardcoded
|
||||||
for (let i = 0; i < payload.inputCount; ++i) {
|
//for (let i = 0; i < payload.inputCount; ++i) {
|
||||||
const item = /** @type {ShapeItem} */ (payload.items.get(i));
|
// const item = /** @type {ShapeItem} */ (payload.inputs.get(i));
|
||||||
if (!item) {
|
// if (!item) {
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
this.root.hubGoals.handleDefinitionDelivered(item.definition);
|
// this.root.hubGoals.handleDefinitionDelivered(item.definition);
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -583,7 +597,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
*/
|
*/
|
||||||
process_GOAL(payload) {
|
process_GOAL(payload) {
|
||||||
const goalComp = payload.entity.components.GoalAcceptor;
|
const goalComp = payload.entity.components.GoalAcceptor;
|
||||||
const item = payload.items.get(0);
|
const item = payload.inputs.get(0).item;
|
||||||
const now = this.root.time.now();
|
const now = this.root.time.now();
|
||||||
|
|
||||||
if (goalComp.item && !item.equals(goalComp.item)) {
|
if (goalComp.item && !item.equals(goalComp.item)) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user