mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-06-13 13:04:03 +00:00
Clear duplicated code and add input requirements for acceptor
This commit is contained in:
parent
3a99628670
commit
0cacbcd267
@ -263,16 +263,7 @@ export class BeltPath extends BasicSerializableObject {
|
|||||||
const matchingSlotIndex = matchingSlot.index;
|
const matchingSlotIndex = matchingSlot.index;
|
||||||
|
|
||||||
return function (item, startProgress = 0.0) {
|
return function (item, startProgress = 0.0) {
|
||||||
const storageComp = targetEntity.components.Storage;
|
if (targetAcceptorComp.tryAcceptItem(targetEntity, matchingSlotIndex, item, startProgress)) {
|
||||||
if (
|
|
||||||
storageComp &&
|
|
||||||
storageComp.tryAcceptItem(item) &&
|
|
||||||
targetAcceptorComp.tryAcceptItem(matchingSlotIndex, item, startProgress)
|
|
||||||
) {
|
|
||||||
// unique duplicated code for storage
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (targetAcceptorComp.tryAcceptItem(matchingSlotIndex, item, startProgress)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { formatItemsPerSecond } from "../../core/utils";
|
import { formatItemsPerSecond } 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 { enumInputRequirements, ItemAcceptorComponent } from "../components/item_acceptor";
|
||||||
import { ItemEjectorComponent } from "../components/item_ejector";
|
import { ItemEjectorComponent } from "../components/item_ejector";
|
||||||
import {
|
import {
|
||||||
enumItemProcessorTypes,
|
enumItemProcessorTypes,
|
||||||
@ -274,6 +274,7 @@ export class MetaPainterBuilding extends MetaBuilding {
|
|||||||
filter: "color",
|
filter: "color",
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
entity.components.ItemAcceptor.inputRequirement = enumInputRequirements.quadPainter;
|
||||||
|
|
||||||
entity.components.ItemEjector.setSlots([
|
entity.components.ItemEjector.setSlots([
|
||||||
{ pos: new Vector(0, 0), direction: enumDirection.top },
|
{ pos: new Vector(0, 0), direction: enumDirection.top },
|
||||||
|
@ -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 { enumInputRequirements, 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";
|
||||||
@ -81,6 +81,7 @@ export class MetaStorageBuilding extends MetaBuilding {
|
|||||||
direction: enumDirection.bottom,
|
direction: enumDirection.bottom,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
inputRequirement: enumInputRequirements.storage,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ 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";
|
import { Entity } from "../entity";
|
||||||
|
import { isTruthyItem } from "../items/boolean_item";
|
||||||
import { typeItemSingleton } from "../item_resolver";
|
import { typeItemSingleton } from "../item_resolver";
|
||||||
import { GameRoot } from "../root";
|
import { GameRoot } from "../root";
|
||||||
|
|
||||||
@ -49,6 +50,12 @@ import { GameRoot } from "../root";
|
|||||||
* }} InputCompletedArgs
|
* }} InputCompletedArgs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** @enum {string} */
|
||||||
|
export const enumInputRequirements = {
|
||||||
|
quadPainter: "quadPainter",
|
||||||
|
storage: "storage",
|
||||||
|
};
|
||||||
|
|
||||||
export class ItemAcceptorComponent extends Component {
|
export class ItemAcceptorComponent extends Component {
|
||||||
static getId() {
|
static getId() {
|
||||||
return "ItemAcceptor";
|
return "ItemAcceptor";
|
||||||
@ -78,18 +85,26 @@ 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 {number=} param0.maxSlotInputs The maximum amount of items one slot can accept before it is full
|
* @param {number=} param0.maxSlotInputs The maximum amount of items one slot can accept before it is full
|
||||||
|
* @param {string|null=} param0.inputRequirement The requirement to accept items
|
||||||
*/
|
*/
|
||||||
constructor({ slots = [], maxSlotInputs = 2 }) {
|
constructor({ slots = [], maxSlotInputs = 2, inputRequirement = null }) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
this.setSlots(slots);
|
||||||
|
|
||||||
|
this.inputRequirement = inputRequirement;
|
||||||
|
|
||||||
|
// setting this to 1 will cause throughput issues at very high speeds
|
||||||
|
this.maxSlotInputs = maxSlotInputs;
|
||||||
|
|
||||||
|
this.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
/** @type {ItemAcceptorInputs} */
|
/** @type {ItemAcceptorInputs} */
|
||||||
this.inputs = [];
|
this.inputs = [];
|
||||||
/** @type {ItemAcceptorCompletedInputs} */
|
/** @type {ItemAcceptorCompletedInputs} */
|
||||||
this.completedInputs = [];
|
this.completedInputs = [];
|
||||||
this.setSlots(slots);
|
|
||||||
|
|
||||||
// setting this to 1 will cause throughput issues at very high speeds
|
|
||||||
this.maxSlotInputs = maxSlotInputs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -111,16 +126,74 @@ export class ItemAcceptorComponent extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Entity} entity
|
||||||
|
* @param {BaseItem} item
|
||||||
|
* @param {number} slotIndex
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
canAcceptItem(entity, item, slotIndex) {
|
||||||
|
const slot = this.slots[slotIndex];
|
||||||
|
|
||||||
|
// make sure there is a slot and we match the filter
|
||||||
|
if (slot && !(slot.filter && slot.filter != item.getItemType())) {
|
||||||
|
switch (this.inputRequirement) {
|
||||||
|
case null: {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case enumInputRequirements.quadPainter: {
|
||||||
|
const pinsComp = entity.components.WiredPins;
|
||||||
|
|
||||||
|
if (slotIndex === 0) {
|
||||||
|
// Always accept the shape
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the network value at the given slot
|
||||||
|
const network = pinsComp.slots[slotIndex - 1].linkedNetwork;
|
||||||
|
const slotIsEnabled = network && network.hasValue() && isTruthyItem(network.currentValue);
|
||||||
|
if (!slotIsEnabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case enumInputRequirements.storage: {
|
||||||
|
const storageComp = entity.components.Storage;
|
||||||
|
|
||||||
|
if (storageComp.storedCount >= storageComp.maximumStorage) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const itemType = item.getItemType();
|
||||||
|
if (storageComp.storedItem && itemType !== storageComp.storedItem.getItemType()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the item straight away - this way different kinds of items can't be inq the acceptor
|
||||||
|
storageComp.storedItem = item;
|
||||||
|
storageComp.storedCount++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
assertAlways(false, "Input requirement is not recognised: " + slot.filter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when trying to input a new item
|
* Called when trying to input a new item
|
||||||
|
* @param {Entity} entity
|
||||||
* @param {number} slotIndex
|
* @param {number} slotIndex
|
||||||
* @param {BaseItem} item
|
* @param {BaseItem} item
|
||||||
* @param {number} startProgress 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
|
* @returns {boolean} if the input was succesful
|
||||||
*/
|
*/
|
||||||
tryAcceptItem(slotIndex, item, startProgress = 0.0) {
|
tryAcceptItem(entity, slotIndex, item, startProgress = 0.0) {
|
||||||
const slot = this.slots[slotIndex];
|
// make sure we have space to actually accept
|
||||||
|
|
||||||
let existingInputs = 0;
|
let existingInputs = 0;
|
||||||
for (let i = 0; i < this.inputs.length; i++) {
|
for (let i = 0; i < this.inputs.length; i++) {
|
||||||
if (this.inputs[i].slotIndex == slotIndex) {
|
if (this.inputs[i].slotIndex == slotIndex) {
|
||||||
@ -136,8 +209,7 @@ export class ItemAcceptorComponent extends Component {
|
|||||||
if (existingInputs >= this.maxSlotInputs) {
|
if (existingInputs >= this.maxSlotInputs) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!this.canAcceptItem(entity, item, slotIndex)) {
|
||||||
if (slot.filter && slot.filter != item.getItemType()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,17 +202,7 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
|
|||||||
const destSlot = sourceSlot.cachedDestSlot;
|
const destSlot = sourceSlot.cachedDestSlot;
|
||||||
if (destEntity && destSlot) {
|
if (destEntity && destSlot) {
|
||||||
const targetAcceptorComp = destEntity.components.ItemAcceptor;
|
const targetAcceptorComp = destEntity.components.ItemAcceptor;
|
||||||
const storageComp = destEntity.components.Storage;
|
if (targetAcceptorComp.tryAcceptItem(destEntity, destSlot.index, item, extraProgress)) {
|
||||||
if (
|
|
||||||
storageComp &&
|
|
||||||
storageComp.tryAcceptItem(item) &&
|
|
||||||
targetAcceptorComp.tryAcceptItem(destSlot.index, item, extraProgress)
|
|
||||||
) {
|
|
||||||
// unique duplicated code for storage - hacky :(
|
|
||||||
sourceSlot.item = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (targetAcceptorComp.tryAcceptItem(destSlot.index, item, extraProgress)) {
|
|
||||||
// Handover successful, clear slot
|
// Handover successful, clear slot
|
||||||
sourceSlot.item = null;
|
sourceSlot.item = null;
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// requirements are no longer needed as items will always be accepted, only the next method is.
|
// input requirements are now handled in the item acceptor, which also fits better with what the acceptor is supposed to do
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether it's possible to process something
|
* Checks whether it's possible to process something
|
||||||
@ -160,21 +160,35 @@ 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 acceptorComp.completedInputs.length >= processorComp.inputsPerCharge;
|
// Since each slot might have more than one input, don't check each slot more than once
|
||||||
|
let usedSlots = [];
|
||||||
|
for (let i = 0; i < acceptorComp.completedInputs.length; i++) {
|
||||||
|
const index = acceptorComp.completedInputs[i].slotIndex;
|
||||||
|
if (!usedSlots.includes(index)) {
|
||||||
|
usedSlots.push(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return usedSlots.length >= processorComp.inputsPerCharge;
|
||||||
}
|
}
|
||||||
|
|
||||||
// QUAD PAINTER
|
// QUAD PAINTER
|
||||||
// For the quad painter, it might be possible to start processing earlier
|
// For the quad painter, it might be possible to start processing earlier
|
||||||
case enumItemProcessorRequirements.painterQuad: {
|
case enumItemProcessorRequirements.painterQuad: {
|
||||||
const pinsComp = entity.components.WiredPins;
|
const pinsComp = entity.components.WiredPins;
|
||||||
|
const inputs = acceptorComp.completedInputs;
|
||||||
|
|
||||||
const input = acceptorComp.completedInputs[0];
|
// split inputs efficiently
|
||||||
if (!input) {
|
let items = new Map();
|
||||||
return false;
|
for (let i = 0; i < inputs.length; i++) {
|
||||||
|
const input = inputs[i];
|
||||||
|
|
||||||
|
if (!items.get(input.slotIndex)) {
|
||||||
|
items.set(input.slotIndex, input.item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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} */ (input.item);
|
const shapeItem = /** @type {ShapeItem} */ (items.get(0));
|
||||||
if (!shapeItem) {
|
if (!shapeItem) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -203,10 +217,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 (
|
if (slotStatus[i] && !items.get(1 + i)) {
|
||||||
slotStatus[i] &&
|
|
||||||
!acceptorComp.completedInputs.find(input => input.slotIndex == i + 1) // @TODO this is slow
|
|
||||||
) {
|
|
||||||
// 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) {
|
||||||
@ -217,7 +228,6 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,8 +253,12 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
for (let i = 0; i < inputs.length; i++) {
|
for (let i = 0; i < inputs.length; i++) {
|
||||||
const input = inputs[i];
|
const input = inputs[i];
|
||||||
|
|
||||||
|
if (!items.get(input.slotIndex)) {
|
||||||
items.set(input.slotIndex, input.item);
|
items.set(input.slotIndex, input.item);
|
||||||
extraProgress = Math.max(extraProgress, input.extraProgress);
|
extraProgress = Math.max(extraProgress, input.extraProgress);
|
||||||
|
inputs.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type {Array<ProducedItem>} */
|
/** @type {Array<ProducedItem>} */
|
||||||
@ -283,18 +297,6 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
items: outItems,
|
items: outItems,
|
||||||
remainingTime: timeToProcess,
|
remainingTime: timeToProcess,
|
||||||
};
|
};
|
||||||
|
|
||||||
// only remove one item from each slot - we don't want to delete extra items!
|
|
||||||
let usedSlots = [];
|
|
||||||
for (let i = 0; i < acceptorComp.completedInputs.length; i++) {
|
|
||||||
const index = acceptorComp.completedInputs[i].slotIndex;
|
|
||||||
|
|
||||||
if (!usedSlots.includes(index)) {
|
|
||||||
usedSlots.push(index);
|
|
||||||
acceptorComp.completedInputs.splice(i, 1);
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user