mirror of
https://github.com/thepaperpilot/Advent-Incremental.git
synced 2024-11-24 09:21:48 +00:00
Merge branch 'day-20-factory' of https://github.com/thepaperpilot/Advent-Incremental into day-20-factory
This commit is contained in:
commit
6f3f1f1985
2 changed files with 208 additions and 122 deletions
|
@ -10,6 +10,7 @@ import { globalBus } from "game/events";
|
|||
import { createLayer } from "game/layers";
|
||||
import { Persistent, persistent, State } from "game/persistence";
|
||||
import player from "game/player";
|
||||
import { format, formatWhole } from "util/bignum";
|
||||
import { Direction } from "util/common";
|
||||
import { computed, ComputedRef, reactive, ref, watchEffect } from "vue";
|
||||
import conveyor from "./factory-components/conveyor.png";
|
||||
|
@ -103,31 +104,19 @@ const factory = createLayer(id, () => {
|
|||
imageSrc: cursor,
|
||||
name: "Cursor",
|
||||
description: "Use this to move.",
|
||||
tick: 0,
|
||||
consumption: {},
|
||||
consumptionStock: {},
|
||||
production: {},
|
||||
productionStock: {}
|
||||
tick: 0
|
||||
},
|
||||
rotate: {
|
||||
imageSrc: rotate,
|
||||
name: "Rotate",
|
||||
description: "Use this to rotate components.",
|
||||
tick: 0,
|
||||
consumption: {},
|
||||
consumptionStock: {},
|
||||
production: {},
|
||||
productionStock: {}
|
||||
tick: 0
|
||||
},
|
||||
conveyor: {
|
||||
imageSrc: conveyor,
|
||||
name: "Conveyor",
|
||||
description: "Moves 1 item per tick.",
|
||||
tick: 1,
|
||||
consumption: {},
|
||||
consumptionStock: {},
|
||||
production: {},
|
||||
productionStock: {},
|
||||
ports: {
|
||||
[Direction.Left]: {
|
||||
type: "input"
|
||||
|
@ -139,24 +128,51 @@ const factory = createLayer(id, () => {
|
|||
},
|
||||
square: {
|
||||
imageSrc: square,
|
||||
name: "???",
|
||||
name: "Producer",
|
||||
description: "Produces 1 square every 1 tick.",
|
||||
tick: 1,
|
||||
production: {
|
||||
square: 1
|
||||
outputs: {
|
||||
square: {
|
||||
amount: 1
|
||||
}
|
||||
}
|
||||
},
|
||||
receiver: {
|
||||
imageSrc: square,
|
||||
name: "Receiver",
|
||||
description: "Obtains squares. Pretty much does nothing else.",
|
||||
tick: 0,
|
||||
inputs: {
|
||||
square: {
|
||||
amount: Infinity
|
||||
}
|
||||
}
|
||||
},
|
||||
shrinker: {
|
||||
imageSrc: square,
|
||||
name: "Shrinker",
|
||||
description:
|
||||
"Converts 100 squares to 1 square. I don't know why you would want to do this but here you go anyways.",
|
||||
tick: 1,
|
||||
inputs: {
|
||||
square: {
|
||||
amount: 100,
|
||||
capacity: 10000
|
||||
}
|
||||
},
|
||||
productionStock: {
|
||||
square: Infinity
|
||||
},
|
||||
consumption: {},
|
||||
consumptionStock: {}
|
||||
outputs: {
|
||||
square: {
|
||||
amount: 1,
|
||||
capacity: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
} as Record<string, FactoryComponentDeclaration>;
|
||||
} as Record<FactoryCompNames, FactoryComponentDeclaration>;
|
||||
const RESOURCES = {
|
||||
square: square
|
||||
} as Record<string, string>;
|
||||
|
||||
type FactoryCompNames = keyof typeof FACTORY_COMPONENTS;
|
||||
type FactoryCompNames = "cursor" | "rotate" | "conveyor" | "square" | "receiver" | "shrinker";
|
||||
type BuildableCompName = Exclude<FactoryCompNames, "cursor">;
|
||||
|
||||
interface FactoryComponentBase extends Record<string, State> {
|
||||
|
@ -165,10 +181,10 @@ const factory = createLayer(id, () => {
|
|||
|
||||
interface FactoryComponentProducer extends FactoryComponentBase {
|
||||
type: Exclude<BuildableCompName, "conveyor">;
|
||||
consumptionStock: Record<string, number>;
|
||||
inputStock?: Record<string, number>;
|
||||
|
||||
// current production stock
|
||||
productionStock: Record<string, number>;
|
||||
outputStock?: Record<string, number>;
|
||||
ticksDone: number;
|
||||
}
|
||||
|
||||
|
@ -186,13 +202,21 @@ const factory = createLayer(id, () => {
|
|||
description: string;
|
||||
|
||||
/** amount it consumes */
|
||||
consumption: Record<string, number>;
|
||||
/** maximum stock of consumption */
|
||||
consumptionStock: Record<string, number>;
|
||||
inputs?: Record<
|
||||
string,
|
||||
{
|
||||
amount: number;
|
||||
capacity?: number;
|
||||
}
|
||||
>;
|
||||
/** amount it produces */
|
||||
production: Record<string, number>;
|
||||
/** maximum stock of production */
|
||||
productionStock: Record<string, number>;
|
||||
outputs?: Record<
|
||||
string,
|
||||
{
|
||||
amount: number;
|
||||
capacity?: number;
|
||||
}
|
||||
>;
|
||||
|
||||
/** on produce, do something */
|
||||
onProduce?: (times: number) => void;
|
||||
|
@ -223,8 +247,8 @@ const factory = createLayer(id, () => {
|
|||
// in block amts, not screen
|
||||
x: number;
|
||||
y: number;
|
||||
lastX: number;
|
||||
lastY: number;
|
||||
// make blocks turn in random amounts;
|
||||
turbulance: number;
|
||||
}
|
||||
|
||||
// mouse positions
|
||||
|
@ -321,8 +345,6 @@ const factory = createLayer(id, () => {
|
|||
globalBus.on("update", diff => {
|
||||
if (taskIsRunning || !loaded) return;
|
||||
//debugger
|
||||
// will change soon:tm:
|
||||
const tick = diff;
|
||||
// make them produce
|
||||
for (const id in components.value) {
|
||||
const [x, y] = id.split("x").map(p => +p);
|
||||
|
@ -339,12 +361,13 @@ const factory = createLayer(id, () => {
|
|||
// use a copy
|
||||
compData.packages = compData.packages.concat(compData.nextPackages);
|
||||
compData.nextPackages = [];
|
||||
for (const [key, block] of [...compData.packages].entries()) {
|
||||
const inputDirection = rotateDir(data.direction, Direction.Left);
|
||||
for (let key = 0; key < compData.packages.length; key++) {
|
||||
const block = compData.packages[key];
|
||||
const inputDirection = data.direction;
|
||||
const dirType = getDirection(inputDirection);
|
||||
const dirAmt = directionToNum(inputDirection);
|
||||
if (dirType === "h") {
|
||||
if (block.x <= block.lastX + dirAmt) {
|
||||
if ((block.x - x) * dirAmt >= 1 + block.turbulance) {
|
||||
const compBehind = compInternalData[x + dirAmt + "x" + y];
|
||||
const storedComp = components.value[x + dirAmt + "x" + y];
|
||||
|
||||
|
@ -352,29 +375,34 @@ const factory = createLayer(id, () => {
|
|||
if (compBehind === undefined) {
|
||||
// just delete it
|
||||
movingBlocks.removeChild(block.sprite);
|
||||
compData.packages.splice(key, 1);
|
||||
} else if (compBehind.type === "conveyor") {
|
||||
// push it to the next conveyor, kill it from the
|
||||
// curent conveyor
|
||||
block.lastX += dirAmt;
|
||||
block.turbulance = Math.random() * 0.4 - 0.2;
|
||||
(compBehind as FactoryInternalConveyor).nextPackages.push(block);
|
||||
compData.packages.splice(key, 1);
|
||||
} else {
|
||||
// send it to the factory
|
||||
// destory its sprite and data
|
||||
const factoryData = storedComp as FactoryComponentProducer;
|
||||
factoryData.consumptionStock[block.type]++;
|
||||
if (factoryData.inputStock !== undefined)
|
||||
factoryData.inputStock[block.type] = Math.min(
|
||||
(factoryData.inputStock[block.type] ?? 0) + 1,
|
||||
FACTORY_COMPONENTS[compBehind.type].inputs?.[block.type]
|
||||
?.capacity ?? Infinity
|
||||
);
|
||||
movingBlocks.removeChild(block.sprite);
|
||||
compData.packages.splice(key, 1);
|
||||
}
|
||||
|
||||
compData.packages.splice(key, 1);
|
||||
key--;
|
||||
} else {
|
||||
const change =
|
||||
dirAmt * Math.min(Math.abs(block.x + 1 - block.lastX), tick);
|
||||
dirAmt * Math.min(Math.abs(x + 1.3 * dirAmt - block.x), diff);
|
||||
block.x += change;
|
||||
block.sprite.x += change * blockSize;
|
||||
}
|
||||
} else {
|
||||
if (block.y <= block.lastY + dirAmt) {
|
||||
if ((block.y - y) * dirAmt >= 1 + block.turbulance) {
|
||||
const compBehind = compInternalData[x + "x" + (y + dirAmt)];
|
||||
const storedComp = components.value[x + "x" + (y + dirAmt)];
|
||||
|
||||
|
@ -382,23 +410,28 @@ const factory = createLayer(id, () => {
|
|||
if (compBehind === undefined) {
|
||||
// just delete it
|
||||
movingBlocks.removeChild(block.sprite);
|
||||
compData.packages.splice(key, 1);
|
||||
} else if (compBehind.type === "conveyor") {
|
||||
// push it to the next conveyor, kill it from the
|
||||
// curent conveyor
|
||||
block.lastY += dirAmt;
|
||||
block.turbulance = Math.random() * 0.4 - 0.2;
|
||||
(compBehind as FactoryInternalConveyor).nextPackages.push(block);
|
||||
compData.packages.splice(key, 1);
|
||||
} else {
|
||||
// send it to the factory
|
||||
// destory its sprite and data
|
||||
const factoryData = storedComp as FactoryComponentProducer;
|
||||
factoryData.consumptionStock[block.type]++;
|
||||
const data = storedComp as FactoryComponentProducer;
|
||||
if (factoryData.inputs?.[block.type] !== undefined) {
|
||||
if (data.inputStock === undefined) data.inputStock = {};
|
||||
data.inputStock[block.type] =
|
||||
(data.inputStock[block.type] ?? 0) + 1;
|
||||
}
|
||||
movingBlocks.removeChild(block.sprite);
|
||||
compData.packages.splice(key, 1);
|
||||
}
|
||||
|
||||
compData.packages.splice(key, 1);
|
||||
key--;
|
||||
} else {
|
||||
const change = dirAmt * Math.min(Math.abs(block.y - block.lastY), tick);
|
||||
const change =
|
||||
dirAmt * Math.min(Math.abs(y + 1.3 * dirAmt - block.y), diff);
|
||||
block.y += change;
|
||||
block.sprite.y += change * blockSize;
|
||||
}
|
||||
|
@ -410,55 +443,67 @@ const factory = createLayer(id, () => {
|
|||
// factory part
|
||||
// PRODUCTION
|
||||
if (data.ticksDone >= factoryData.tick) {
|
||||
if (!compData.canProduce.value) continue;
|
||||
const cyclesDone = Math.floor(data.ticksDone / factoryData.tick);
|
||||
factoryData.onProduce?.(cyclesDone);
|
||||
for (const [key, val] of Object.entries(factoryData.consumption)) {
|
||||
data.consumptionStock[key] -= val;
|
||||
if (compData.canProduce.value) {
|
||||
const cyclesDone = Math.floor(data.ticksDone / factoryData.tick);
|
||||
factoryData.onProduce?.(cyclesDone);
|
||||
if (factoryData.inputs !== undefined) {
|
||||
if (data.inputStock === undefined) data.inputStock = {};
|
||||
for (const [key, val] of Object.entries(factoryData.inputs)) {
|
||||
data.inputStock[key] = (data.inputStock[key] ?? 0) - val.amount;
|
||||
}
|
||||
}
|
||||
if (factoryData.outputs !== undefined) {
|
||||
if (data.outputStock === undefined) data.outputStock = {};
|
||||
for (const [key, val] of Object.entries(factoryData.outputs)) {
|
||||
data.outputStock[key] = (data.outputStock[key] ?? 0) + val.amount;
|
||||
}
|
||||
}
|
||||
data.ticksDone -= cyclesDone * factoryData.tick;
|
||||
}
|
||||
for (const [key, val] of Object.entries(factoryData.production)) {
|
||||
data.productionStock[key] += val;
|
||||
}
|
||||
data.ticksDone -= cyclesDone * factoryData.tick;
|
||||
} else {
|
||||
data.ticksDone += tick;
|
||||
data.ticksDone += diff;
|
||||
}
|
||||
// now look at each component direction and see if it accepts items coming in
|
||||
// components are 1x1 so simple math for now
|
||||
|
||||
let yInc = 0;
|
||||
let xInc = 0;
|
||||
const incs: [number, number][] = [];
|
||||
if (
|
||||
components.value[x + "x" + (y + 1)]?.type === "conveyor" &&
|
||||
components.value[x + "x" + (y + 1)].direction === Direction.Up
|
||||
components.value[x + "x" + (y + 1)].direction === Direction.Down
|
||||
) {
|
||||
yInc = 1;
|
||||
} else if (
|
||||
incs.push([0, 1]);
|
||||
}
|
||||
if (
|
||||
components.value[x + "x" + (y - 1)]?.type === "conveyor" &&
|
||||
components.value[x + "x" + (y - 1)].direction === Direction.Down
|
||||
components.value[x + "x" + (y - 1)].direction === Direction.Up
|
||||
) {
|
||||
yInc = -1;
|
||||
} else if (
|
||||
incs.push([0, -1]);
|
||||
}
|
||||
if (
|
||||
components.value[x + 1 + "x" + y]?.type === "conveyor" &&
|
||||
components.value[x + 1 + "x" + y].direction === Direction.Right
|
||||
) {
|
||||
xInc = 1;
|
||||
} else if (
|
||||
incs.push([1, 0]);
|
||||
}
|
||||
if (
|
||||
components.value[x - 1 + "x" + y]?.type === "conveyor" &&
|
||||
components.value[x - 1 + "x" + y].direction === Direction.Left
|
||||
) {
|
||||
xInc = -1;
|
||||
incs.push([-1, 0]);
|
||||
}
|
||||
// no suitable location to dump stuff in
|
||||
// console.log(x, y);
|
||||
// debugger;
|
||||
if (xInc === 0 && yInc === 0) continue;
|
||||
if (incs.length <= 0) continue;
|
||||
const [xInc, yInc] = incs[Math.floor(Math.random() * incs.length)];
|
||||
let itemToMove: [string, number] | undefined = undefined;
|
||||
for (const [name, amt] of Object.entries(data.productionStock)) {
|
||||
if (amt >= 1) {
|
||||
itemToMove = [name, amt];
|
||||
data.productionStock[name]--;
|
||||
break;
|
||||
if (data.outputStock !== undefined) {
|
||||
for (const [name, amt] of Object.entries(data.outputStock)) {
|
||||
if (amt >= 1) {
|
||||
itemToMove = [name, amt];
|
||||
data.outputStock[name]--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// there is nothing to move
|
||||
|
@ -479,20 +524,17 @@ const factory = createLayer(id, () => {
|
|||
// if X is being moved, then we don't need to adjust x
|
||||
// however it needs to be aligned if Y is being moved
|
||||
// vice-versa
|
||||
const spriteDiffX = xInc !== 0 ? 0 : 0.5;
|
||||
const spriteDiffY = yInc !== 0 ? 0 : 0.5;
|
||||
sprite.x = (x + spriteDiffX) * blockSize;
|
||||
sprite.y = (y + spriteDiffY) * blockSize;
|
||||
sprite.x = (x + xInc * 0.3) * blockSize;
|
||||
sprite.y = (y + yInc * 0.3) * blockSize;
|
||||
sprite.anchor.set(0.5);
|
||||
sprite.width = blockSize / 2.5;
|
||||
sprite.height = blockSize / 5;
|
||||
//console.log(sprite);
|
||||
const block: Block = {
|
||||
sprite,
|
||||
x: x,
|
||||
y: y,
|
||||
lastX: x,
|
||||
lastY: y,
|
||||
x: x + xInc * 0.3,
|
||||
y: y + yInc * 0.3,
|
||||
turbulance: Math.random() * 0.4 - 0.2,
|
||||
type: itemToMove[0]
|
||||
};
|
||||
|
||||
|
@ -533,17 +575,17 @@ const factory = createLayer(id, () => {
|
|||
components.value[x + "x" + y] = {
|
||||
ticksDone: 0,
|
||||
direction: Direction.Right,
|
||||
consumptionStock:
|
||||
data.type === "conveyor"
|
||||
inputStock:
|
||||
factoryBaseData.inputs === undefined
|
||||
? undefined
|
||||
: Object.fromEntries(
|
||||
Object.keys(factoryBaseData.consumptionStock).map(i => [i, 0])
|
||||
Object.entries(factoryBaseData.inputs).map(x => [x[0], 0])
|
||||
),
|
||||
productionStock:
|
||||
data.type === "conveyor"
|
||||
outputStock:
|
||||
factoryBaseData.outputs === undefined
|
||||
? undefined
|
||||
: Object.fromEntries(
|
||||
Object.keys(factoryBaseData.productionStock).map(i => [i, 0])
|
||||
Object.entries(factoryBaseData.outputs).map(x => [x[0], 0])
|
||||
),
|
||||
...data
|
||||
} as FactoryComponent;
|
||||
|
@ -557,17 +599,17 @@ const factory = createLayer(id, () => {
|
|||
if (!(factoryBaseData.canProduce?.value ?? true)) return false;
|
||||
// this should NEVER be null
|
||||
const compData = components.value[x + "x" + y] as FactoryComponentProducer;
|
||||
for (const [key, res] of Object.entries(compData.productionStock)) {
|
||||
// if the current stock + production is more than you can handle
|
||||
if (
|
||||
res + factoryBaseData.production[key] >
|
||||
factoryBaseData.productionStock[key]
|
||||
)
|
||||
return false;
|
||||
if (factoryBaseData.inputs !== undefined) {
|
||||
for (const [res, val] of Object.entries(factoryBaseData.inputs))
|
||||
if ((compData.inputStock?.[res] ?? 0) < val.amount) return false;
|
||||
}
|
||||
for (const [key, res] of Object.entries(compData.consumptionStock)) {
|
||||
// make sure you have enough to produce
|
||||
if (res < factoryBaseData.consumptionStock[key]) return false;
|
||||
if (factoryBaseData.outputs !== undefined) {
|
||||
for (const [res, val] of Object.entries(factoryBaseData.outputs))
|
||||
if (
|
||||
(compData.outputStock?.[res] ?? 0) + val.amount >
|
||||
(val.capacity ?? Infinity)
|
||||
)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
|
@ -681,7 +723,16 @@ const factory = createLayer(id, () => {
|
|||
} else if (e.button === 2) {
|
||||
const data = compInternalData[x + "x" + y];
|
||||
if (data === undefined) return;
|
||||
|
||||
if (data.type === "conveyor") {
|
||||
const cData = data as FactoryInternalConveyor;
|
||||
for (const p of cData.packages) {
|
||||
p.sprite.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
delete components.value[x + "x" + y];
|
||||
delete compInternalData[x + "x" + y];
|
||||
spriteContainer.removeChild(data.sprite);
|
||||
}
|
||||
}
|
||||
|
@ -746,24 +797,58 @@ const factory = createLayer(id, () => {
|
|||
<br />
|
||||
{compHovered.value.type !== "conveyor" ? (
|
||||
<>
|
||||
Stock:{" "}
|
||||
{Object.entries({
|
||||
...(compHovered.value.productionStock as Record<
|
||||
string,
|
||||
number
|
||||
>),
|
||||
...(compHovered.value.consumptionStock as Record<
|
||||
string,
|
||||
number
|
||||
>)
|
||||
}).map(i => {
|
||||
return `${i[0]}: ${i[1]}/${
|
||||
FACTORY_COMPONENTS[compHovered.value?.type ?? "cursor"]
|
||||
.consumptionStock[i[0]] ??
|
||||
FACTORY_COMPONENTS[compHovered.value?.type ?? "cursor"]
|
||||
.productionStock[i[0]]
|
||||
}`;
|
||||
})}
|
||||
{compHovered.value.inputStock !== undefined ? (
|
||||
<>
|
||||
<br />
|
||||
<h5>Inputs:</h5>
|
||||
{Object.entries(compHovered.value.inputStock).map(x => (
|
||||
<div>
|
||||
{x[0]}: {formatWhole(x[1])}
|
||||
{FACTORY_COMPONENTS[
|
||||
compHovered.value?.type ?? "cursor"
|
||||
].inputs?.[x[0]].amount !== undefined
|
||||
? " / " +
|
||||
formatWhole(
|
||||
FACTORY_COMPONENTS[
|
||||
compHovered.value?.type ?? "cursor"
|
||||
].inputs?.[x[0]].amount ?? 0
|
||||
)
|
||||
: ""}
|
||||
{FACTORY_COMPONENTS[
|
||||
compHovered.value?.type ?? "cursor"
|
||||
].inputs?.[x[0]].capacity !== undefined
|
||||
? " / " +
|
||||
formatWhole(
|
||||
FACTORY_COMPONENTS[
|
||||
compHovered.value?.type ?? "cursor"
|
||||
].inputs?.[x[0]].capacity ?? 0
|
||||
)
|
||||
: ""}
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
) : undefined}
|
||||
{compHovered.value.outputStock !== undefined ? (
|
||||
<>
|
||||
<br />
|
||||
<h5>Outputs:</h5>
|
||||
{Object.entries(compHovered.value.outputStock).map(x => (
|
||||
<div>
|
||||
{x[0]}: {formatWhole(x[1])}
|
||||
{FACTORY_COMPONENTS[
|
||||
compHovered.value?.type ?? "cursor"
|
||||
].outputs?.[x[0]].capacity !== undefined
|
||||
? " / " +
|
||||
formatWhole(
|
||||
FACTORY_COMPONENTS[
|
||||
compHovered.value?.type ?? "cursor"
|
||||
].outputs?.[x[0]].capacity ?? 0
|
||||
)
|
||||
: ""}
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
) : undefined}
|
||||
</>
|
||||
) : undefined}
|
||||
</div>
|
||||
|
|
|
@ -48,6 +48,7 @@ export type State =
|
|||
| string
|
||||
| number
|
||||
| boolean
|
||||
| undefined
|
||||
| DecimalSource
|
||||
| { [key: string]: State }
|
||||
| { [key: number]: State };
|
||||
|
|
Loading…
Reference in a new issue