1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-06-13 13:04:03 +00:00

Add unstacker building

This commit is contained in:
Jasper Meggitt 2020-05-24 03:53:47 -07:00
parent c6bf070287
commit c23e4ff50b
8 changed files with 151 additions and 10 deletions

View File

@ -1,15 +1,17 @@
import { globalConfig } from "../../core/config";
import { enumDirection, Vector } from "../../core/vector";
import { ItemAcceptorComponent, enumItemAcceptorItemFilter } from "../components/item_acceptor";
import { ItemEjectorComponent } from "../components/item_ejector";
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building";
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals";
import { formatItemsPerSecond } from "../../core/utils";
import { T } from "../../translations";
/** @enum {string} */
export const enumStackerVariants = { unstacker: "unstacker" };
export class MetaStackerBuilding extends MetaBuilding {
constructor() {
super("stacker");
@ -29,10 +31,24 @@ export class MetaStackerBuilding extends MetaBuilding {
* @returns {Array<[string, string]>}
*/
getAdditionalStatistics(root, variant) {
const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.stacker);
const speed = root.hubGoals.getProcessorBaseSpeed(
variant === enumStackerVariants.unstacker
? enumItemProcessorTypes.unstacker
: enumItemProcessorTypes.stacker
);
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
}
/**
* @param {GameRoot} root
*/
getAvailableVariants(root) {
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_unstacker)) {
return [defaultBuildingVariant, enumStackerVariants.unstacker];
}
return super.getAvailableVariants(root);
}
/**
* @param {GameRoot} root
*/
@ -74,4 +90,54 @@ export class MetaStackerBuilding extends MetaBuilding {
})
);
}
/**
*
* @param {Entity} entity
* @param {number} rotationVariant
* @param {string} variant
*/
updateVariants(entity, rotationVariant, variant) {
switch (variant) {
case defaultBuildingVariant: {
entity.components.ItemEjector.setSlots([
{ pos: new Vector(0, 0), direction: enumDirection.top },
]);
entity.components.ItemAcceptor.setSlots([
{
pos: new Vector(0, 0),
directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.shape,
},
{
pos: new Vector(1, 0),
directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.shape,
},
]);
entity.components.ItemProcessor.type = enumItemProcessorTypes.stacker;
entity.components.ItemProcessor.inputsPerCharge = 2;
break;
}
case enumStackerVariants.unstacker: {
entity.components.ItemEjector.setSlots([
{ pos: new Vector(0, 0), direction: enumDirection.top },
{ pos: new Vector(1, 0), direction: enumDirection.top },
]);
entity.components.ItemAcceptor.setSlots([
{
pos: new Vector(0, 0),
directions: [enumDirection.bottom],
filter: enumItemAcceptorItemFilter.shape,
},
]);
entity.components.ItemProcessor.type = enumItemProcessorTypes.unstacker;
entity.components.ItemProcessor.inputsPerCharge = 1;
break;
}
default:
assertAlways(false, "Unknown stacker variant: " + variant);
}
}
}

View File

@ -12,6 +12,7 @@ export const enumItemProcessorTypes = {
rotater: "rotater",
rotaterCCW: "rotaterCCW",
stacker: "stacker",
unstacker: "unstacker",
trash: "trash",
mixer: "mixer",
painter: "painter",

View File

@ -407,7 +407,8 @@ export class HubGoals extends BasicSerializableObject {
case enumItemProcessorTypes.cutterQuad:
case enumItemProcessorTypes.rotater:
case enumItemProcessorTypes.rotaterCCW:
case enumItemProcessorTypes.stacker: {
case enumItemProcessorTypes.stacker:
case enumItemProcessorTypes.unstacker: {
assert(
globalConfig.buildingSpeeds[processorType],
"Processor type has no speed set in globalConfig.buildingSpeeds: " + processorType

View File

@ -465,6 +465,43 @@ export class ShapeDefinition extends BasicSerializableObject {
return new ShapeDefinition({ layers: newLayers });
}
/**
* Stacks the given shape definition on top.
*/
cloneAndUnstack() {
const lowerLayers = this.internalCloneLayers();
if (this.isEntirelyEmpty()) {
assert(false, "Can not stack entirely empty definition");
}
// Check if there is only one layer
if (this.layers.length === 1) {
return [new ShapeDefinition({ layers: lowerLayers })];
}
let upperLayers = [];
layerCheck:
for (let i = lowerLayers.length - 1; i >= 0; --i) {
const layerToCheck = lowerLayers[i];
for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) {
// Check for a layer with items on it to remove
if (layerToCheck[quadrantIndex]) {
upperLayers.push(layerToCheck);
lowerLayers[i] = [null, null, null, null];
break layerCheck;
}
}
}
return [
new ShapeDefinition({ layers: lowerLayers }),
new ShapeDefinition({ layers: upperLayers }),
];
}
/**
* Clones the shape and colors everything in the given color
* @param {enumColors} color

View File

@ -144,6 +144,21 @@ export class ShapeDefinitionManager extends BasicSerializableObject {
));
}
/**
* Generates a definition for stacking the upper definition onto the lower one
* @param {ShapeDefinition} definition
* @returns {[ShapeDefinition, ShapeDefinition]}
*/
shapeActionUnstack(definition) {
const key = "unstack:" + definition.getHash();
if (this.operationCache[key]) {
return /** @type {[ShapeDefinition, ShapeDefinition]} */ (this.operationCache[key]);
}
const unstacked = definition.cloneAndUnstack();
return /** @type {[ShapeDefinition, ShapeDefinition]} */ (this.operationCache[key] = unstacked);
}
/**
* Generates a definition for painting it with the given color
* @param {ShapeDefinition} definition

View File

@ -23,7 +23,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
// First of all, process the current recipe
processorComp.secondsUntilEject = Math_max(
0,
processorComp.secondsUntilEject - this.root.dynamicTickrate.deltaSeconds
processorComp.secondsUntilEject - this.root.dynamicTickrate.deltaSeconds,
);
// Check if we have any finished items we can eject
@ -196,7 +196,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
const stackedDefinition = this.root.shapeDefinitionMgr.shapeActionStack(
lowerItem.definition,
upperItem.definition
upperItem.definition,
);
outItems.push({
item: new ShapeItem(stackedDefinition),
@ -204,6 +204,23 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
break;
}
// UNSTACKER
case enumItemProcessorTypes.unstacker: {
const item = /** @type {ShapeItem} */ (itemsBySlot[0].item);
assert(item instanceof ShapeItem, "Input for unstack is not a shape");
const unstackedDefinitions = this.root.shapeDefinitionMgr.shapeActionUnstack(item.definition);
for (let i = 0; i < unstackedDefinitions.length; ++i) {
outItems.push({
item: new ShapeItem(unstackedDefinitions[i]),
requiredSlot: i,
});
}
break;
}
// TRASH
case enumItemProcessorTypes.trash: {
@ -244,7 +261,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
const colorizedDefinition = this.root.shapeDefinitionMgr.shapeActionPaintWith(
shapeItem.definition,
colorItem.color
colorItem.color,
);
outItems.push({
@ -267,12 +284,12 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
const colorizedDefinition1 = this.root.shapeDefinitionMgr.shapeActionPaintWith(
shapeItem1.definition,
colorItem.color
colorItem.color,
);
const colorizedDefinition2 = this.root.shapeDefinitionMgr.shapeActionPaintWith(
shapeItem2.definition,
colorItem.color
colorItem.color,
);
outItems.push({
item: new ShapeItem(colorizedDefinition1),
@ -302,7 +319,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
const colorizedDefinition = this.root.shapeDefinitionMgr.shapeActionPaintWith4Colors(
shapeItem.definition,
[colorItem2.color, colorItem3.color, colorItem4.color, colorItem1.color]
[colorItem2.color, colorItem3.color, colorItem4.color, colorItem1.color],
);
outItems.push({

View File

@ -11,6 +11,7 @@ export const enumHubGoalRewards = {
reward_painter: "reward_painter",
reward_mixer: "reward_mixer",
reward_stacker: "reward_stacker",
reward_unstacker: "reward_unstacker",
reward_splitter: "reward_splitter",
reward_tunnel: "reward_tunnel",

View File

@ -341,6 +341,9 @@ buildings:
default:
name: &stacker Stacker
description: Stacks both items. If they can not be merged, the right item is placed above the left item.
unstacker:
name: Unstacker
description: Takes the top most shape off of a stack and outputs it onto the right.
mixer:
default: