mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-06-13 13:04:03 +00:00
(wip) 4-painter accept pins
This commit is contained in:
parent
349657bafc
commit
85eed824f9
@ -9,6 +9,8 @@ import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
||||
import { GameRoot } from "../root";
|
||||
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||
import { enumItemType } from "../base_item";
|
||||
import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins";
|
||||
import { ProcessingRequirementComponent } from "../components/processing_requirement";
|
||||
|
||||
/** @enum {string} */
|
||||
export const enumPainterVariants = { mirrored: "mirrored", double: "double", quad: "quad" };
|
||||
@ -120,6 +122,13 @@ export class MetaPainterBuilding extends MetaBuilding {
|
||||
switch (variant) {
|
||||
case defaultBuildingVariant:
|
||||
case enumPainterVariants.mirrored: {
|
||||
if (entity.components.WiredPins) {
|
||||
entity.removeComponent(WiredPinsComponent)
|
||||
}
|
||||
if (entity.components.ProcessingRequirement) {
|
||||
entity.removeComponent(ProcessingRequirementComponent);
|
||||
}
|
||||
|
||||
entity.components.ItemAcceptor.setSlots([
|
||||
{
|
||||
pos: new Vector(0, 0),
|
||||
@ -143,6 +152,13 @@ export class MetaPainterBuilding extends MetaBuilding {
|
||||
break;
|
||||
}
|
||||
case enumPainterVariants.double: {
|
||||
if (entity.components.WiredPins) {
|
||||
entity.removeComponent(WiredPinsComponent)
|
||||
}
|
||||
if (entity.components.ProcessingRequirement) {
|
||||
entity.removeComponent(ProcessingRequirementComponent);
|
||||
}
|
||||
|
||||
entity.components.ItemAcceptor.setSlots([
|
||||
{
|
||||
pos: new Vector(0, 0),
|
||||
@ -170,6 +186,39 @@ export class MetaPainterBuilding extends MetaBuilding {
|
||||
break;
|
||||
}
|
||||
case enumPainterVariants.quad: {
|
||||
if (!entity.components.WiredPins) {
|
||||
entity.addComponent(new WiredPinsComponent({
|
||||
slots: [
|
||||
{
|
||||
pos: new Vector(0, 0),
|
||||
direction: enumDirection.bottom,
|
||||
type: enumPinSlotType.logicalAcceptor
|
||||
},
|
||||
{
|
||||
pos: new Vector(1, 0),
|
||||
direction: enumDirection.bottom,
|
||||
type: enumPinSlotType.logicalAcceptor
|
||||
},
|
||||
{
|
||||
pos: new Vector(2, 0),
|
||||
direction: enumDirection.bottom,
|
||||
type: enumPinSlotType.logicalAcceptor
|
||||
},
|
||||
{
|
||||
pos: new Vector(3, 0),
|
||||
direction: enumDirection.bottom,
|
||||
type: enumPinSlotType.logicalAcceptor
|
||||
},
|
||||
]
|
||||
}));
|
||||
}
|
||||
|
||||
if (!entity.components.ProcessingRequirement) {
|
||||
entity.addComponent(new ProcessingRequirementComponent({
|
||||
processorType: enumItemProcessorTypes.painterQuad
|
||||
}));
|
||||
}
|
||||
|
||||
entity.components.ItemAcceptor.setSlots([
|
||||
{
|
||||
pos: new Vector(0, 0),
|
||||
|
@ -15,6 +15,7 @@ import { ConstantSignalComponent } from "./components/constant_signal";
|
||||
import { LogicGateComponent } from "./components/logic_gate";
|
||||
import { LeverComponent } from "./components/lever";
|
||||
import { WireTunnelComponent } from "./components/wire_tunnel";
|
||||
import { ProcessingRequirementComponent } from "./components/processing_requirement";
|
||||
|
||||
export function initComponentRegistry() {
|
||||
gComponentRegistry.register(StaticMapEntityComponent);
|
||||
@ -33,6 +34,7 @@ export function initComponentRegistry() {
|
||||
gComponentRegistry.register(LogicGateComponent);
|
||||
gComponentRegistry.register(LeverComponent);
|
||||
gComponentRegistry.register(WireTunnelComponent);
|
||||
gComponentRegistry.register(ProcessingRequirementComponent);
|
||||
|
||||
// IMPORTANT ^^^^^ UPDATE ENTITY COMPONENT STORAGE AFTERWARDS
|
||||
|
||||
@ -41,7 +43,7 @@ export function initComponentRegistry() {
|
||||
assert(
|
||||
// @ts-ignore
|
||||
require.context("./components", false, /.*\.js/i).keys().length ===
|
||||
gComponentRegistry.getNumEntries(),
|
||||
gComponentRegistry.getNumEntries(),
|
||||
"Not all components are registered"
|
||||
);
|
||||
|
||||
|
91
src/js/game/components/processing_requirement.js
Normal file
91
src/js/game/components/processing_requirement.js
Normal file
@ -0,0 +1,91 @@
|
||||
import { Component } from "../component";
|
||||
import { enumItemProcessorTypes } from "./item_processor";
|
||||
import { Entity } from "../entity";
|
||||
import { BOOL_TRUE_SINGLETON } from "../items/boolean_item";
|
||||
import { BaseItem } from "../base_item";
|
||||
import { ShapeItem } from "../items/shape_item";
|
||||
|
||||
export class ProcessingRequirementComponent extends Component {
|
||||
static getId() {
|
||||
return "ProcessingRequirement";
|
||||
}
|
||||
|
||||
duplicateWithoutContents() {
|
||||
return new ProcessingRequirementComponent({
|
||||
processorType: this.type
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object} param0
|
||||
* @param {enumItemProcessorTypes=} param0.processorType Which type of processor this is
|
||||
*
|
||||
*/
|
||||
constructor({ processorType = enumItemProcessorTypes.painterQuad }) {
|
||||
super();
|
||||
|
||||
// Type of the processor
|
||||
this.type = processorType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether it's possible to process something
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
canProcess(entity) {
|
||||
switch (this.type) {
|
||||
case enumItemProcessorTypes.painterQuad: {
|
||||
// For quad-painter, pins match slots
|
||||
// boolean true means "disable input"
|
||||
// a color means "disable if not matched"
|
||||
|
||||
const processorComp = entity.components.ItemProcessor;
|
||||
const pinsComp = entity.components.WiredPins;
|
||||
|
||||
/** @type {Object.<string, { item: BaseItem, sourceSlot: number }>} */
|
||||
const itemsBySlot = {};
|
||||
for (let i = 0; i < processorComp.inputSlots.length; ++i) {
|
||||
itemsBySlot[processorComp.inputSlots[i].sourceSlot] = processorComp.inputSlots[i];
|
||||
}
|
||||
|
||||
// first slot is the shape
|
||||
if (!itemsBySlot[0]) return false;
|
||||
const shapeItem = /** @type {ShapeItem} */ (itemsBySlot[0].item);
|
||||
|
||||
// Here we check just basic things`
|
||||
// Stop processing if anything except TRUE is
|
||||
// set and there is no item.
|
||||
for (let i = 0; i < 4; ++i) {
|
||||
const netValue = pinsComp.slots[i].linkedNetwork ?
|
||||
pinsComp.slots[i].linkedNetwork.currentValue :
|
||||
null;
|
||||
|
||||
const currentItem = itemsBySlot[i + 1];
|
||||
|
||||
if ((netValue == null || !netValue.equals(BOOL_TRUE_SINGLETON)) && currentItem == null) {
|
||||
let quadCount = 0;
|
||||
|
||||
const quadNumber = (i + 3) % 4
|
||||
for (let j = 0; j < 4; ++j) {
|
||||
const layer = shapeItem.definition.layers[j];
|
||||
if (layer && layer[quadNumber]) {
|
||||
quadCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (quadCount > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
assertAlways(false, "Unknown requirement for " + this.type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -15,6 +15,7 @@ import { ConstantSignalComponent } from "./components/constant_signal";
|
||||
import { LogicGateComponent } from "./components/logic_gate";
|
||||
import { LeverComponent } from "./components/lever";
|
||||
import { WireTunnelComponent } from "./components/wire_tunnel";
|
||||
import { ProcessingRequirementComponent } from "./components/processing_requirement";
|
||||
/* typehints:end */
|
||||
|
||||
/**
|
||||
@ -73,6 +74,9 @@ export class EntityComponentStorage {
|
||||
/** @type {WireTunnelComponent} */
|
||||
this.WireTunnel;
|
||||
|
||||
/** @type {ProcessingRequirementComponent} */
|
||||
this.ProcessingRequirement;
|
||||
|
||||
/* typehints:end */
|
||||
}
|
||||
}
|
||||
|
@ -604,7 +604,7 @@ export class ShapeDefinition extends BasicSerializableObject {
|
||||
for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) {
|
||||
const item = quadrants[quadrantIndex];
|
||||
if (item) {
|
||||
item.color = colors[quadrantIndex];
|
||||
item.color = colors[quadrantIndex] || item.color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { globalConfig } from "../../core/config";
|
||||
import { BaseItem } from "../base_item";
|
||||
import { BaseItem, enumItemType } from "../base_item";
|
||||
import { enumColorMixingResults } from "../colors";
|
||||
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
|
||||
import { Entity } from "../entity";
|
||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||
import { BOOL_TRUE_SINGLETON } from "../items/boolean_item";
|
||||
import { BOOL_TRUE_SINGLETON, BOOL_FALSE_SINGLETON } from "../items/boolean_item";
|
||||
import { ColorItem, COLOR_ITEM_SINGLETONS } from "../items/color_item";
|
||||
import { ShapeItem } from "../items/shape_item";
|
||||
|
||||
@ -68,9 +68,17 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Check if we have an empty queue and can start a new charge
|
||||
if (processorComp.itemsToEject.length === 0) {
|
||||
if (processorComp.inputSlots.length >= processorComp.inputsPerCharge) {
|
||||
const procRequirementComp = entity.components.ProcessingRequirement;
|
||||
|
||||
if (procRequirementComp) {
|
||||
if (procRequirementComp.canProcess(entity)) {
|
||||
this.startNewCharge(entity);
|
||||
}
|
||||
} else if (processorComp.inputSlots.length >= processorComp.inputsPerCharge) {
|
||||
this.startNewCharge(entity);
|
||||
}
|
||||
}
|
||||
@ -307,22 +315,66 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
|
||||
case enumItemProcessorTypes.painterQuad: {
|
||||
const shapeItem = /** @type {ShapeItem} */ (itemsBySlot[0].item);
|
||||
const colorItem1 = /** @type {ColorItem} */ (itemsBySlot[1].item);
|
||||
const colorItem2 = /** @type {ColorItem} */ (itemsBySlot[2].item);
|
||||
const colorItem3 = /** @type {ColorItem} */ (itemsBySlot[3].item);
|
||||
const colorItem4 = /** @type {ColorItem} */ (itemsBySlot[4].item);
|
||||
|
||||
assert(shapeItem instanceof ShapeItem, "Input for painter is not a shape");
|
||||
assert(colorItem1 instanceof ColorItem, "Input for painter is not a color");
|
||||
assert(colorItem2 instanceof ColorItem, "Input for painter is not a color");
|
||||
assert(colorItem3 instanceof ColorItem, "Input for painter is not a color");
|
||||
assert(colorItem4 instanceof ColorItem, "Input for painter is not a color");
|
||||
|
||||
/** @type {Array<ColorItem>} */
|
||||
const colorItems = [].fill(null, 0, 4);
|
||||
|
||||
for (let i = 0; i < colorItems.length; ++i) {
|
||||
if (itemsBySlot[i + 1]) {
|
||||
colorItems[i] = /** @type {ColorItem} */ (itemsBySlot[i + 1].item);
|
||||
assert(colorItems[i] instanceof ColorItem, "Input for painter is not a color");
|
||||
}
|
||||
}
|
||||
|
||||
const pinValues = entity.components.WiredPins.slots
|
||||
.map(slot => slot.linkedNetwork ? slot.linkedNetwork.currentValue : BOOL_FALSE_SINGLETON);
|
||||
|
||||
// @todo cleanup
|
||||
const colorTL = colorItems[0];
|
||||
const colorTR = colorItems[1];
|
||||
const colorBR = colorItems[2];
|
||||
const colorBL = colorItems[3];
|
||||
|
||||
/** @type {Array<boolean>} */
|
||||
let skipped = [];
|
||||
for (let i = 0; i < pinValues.length; ++i) {
|
||||
skipped[i] = pinValues[i] ? pinValues[i].equals(BOOL_TRUE_SINGLETON) : false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < 4; ++i) {
|
||||
if (colorItems[i] == null) {
|
||||
skipped[i] = false; // make sure we never insert null item back
|
||||
} else if (pinValues[i].getItemType() == enumItemType.color) {
|
||||
// if pin value is a color, skip anything except that color
|
||||
// but still require any color, because it would not work on
|
||||
// slow factories.
|
||||
if (!colorItems[i].equals(pinValues[i])) {
|
||||
skipped[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const colorizedDefinition = this.root.shapeDefinitionMgr.shapeActionPaintWith4Colors(
|
||||
shapeItem.definition,
|
||||
[colorItem2.color, colorItem3.color, colorItem4.color, colorItem1.color]
|
||||
[
|
||||
(!skipped[0] && colorTL) ? colorTL.color : null,
|
||||
(!skipped[1] && colorTR) ? colorTR.color : null,
|
||||
(!skipped[2] && colorBR) ? colorBR.color : null,
|
||||
(!skipped[3] && colorBL) ? colorBL.color : null,
|
||||
]
|
||||
);
|
||||
|
||||
// restore items we didn't use
|
||||
for (let i = 0; i < 4; ++i) {
|
||||
if (skipped[i]) {
|
||||
processorComp.inputSlots.push({
|
||||
item: colorItems[i],
|
||||
sourceSlot: i + 1
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
outItems.push({
|
||||
item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(colorizedDefinition),
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user