Merge pull request #6 from thepaperpilot/day-20-factory

merge day 20 into day 18 again
This commit is contained in:
unsoftcapped3 2022-12-21 14:51:08 -08:00 committed by GitHub
commit 98afdc7301
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 400 additions and 234 deletions

1
package-lock.json generated
View file

@ -12083,6 +12083,7 @@
}, },
"vue-panzoom": { "vue-panzoom": {
"version": "git+ssh://git@github.com/thepaperpilot/vue-panzoom.git#fa3cc91f6842cdfbd1bfb433c75cac01f177fe2d", "version": "git+ssh://git@github.com/thepaperpilot/vue-panzoom.git#fa3cc91f6842cdfbd1bfb433c75cac01f177fe2d",
"integrity": "sha512-d4URo4PVl2jCFG1WNY+5lDQ8nloOVLf2gFLqE+TLNmF43+F/STgld0A58uf9aq2xbaupVJdZAp/prGtve9ESRQ==",
"from": "vue-panzoom@https://github.com/thepaperpilot/vue-panzoom.git", "from": "vue-panzoom@https://github.com/thepaperpilot/vue-panzoom.git",
"requires": { "requires": {
"panzoom": "^9.4.1" "panzoom": "^9.4.1"

View file

@ -8,6 +8,7 @@ import { globalBus } from "game/events";
import { createLayer } from "game/layers"; import { createLayer } from "game/layers";
import { Persistent, persistent, State } from "game/persistence"; import { Persistent, persistent, State } from "game/persistence";
import player from "game/player"; import player from "game/player";
import { formatWhole } from "util/bignum";
import { Direction } from "util/common"; import { Direction } from "util/common";
import { computed, ComputedRef, reactive, ref, watchEffect } from "vue"; import { computed, ComputedRef, reactive, ref, watchEffect } from "vue";
import conveyor from "./factory-components/conveyor.png"; import conveyor from "./factory-components/conveyor.png";
@ -25,12 +26,6 @@ const day = 18;
// 20x20 block size // 20x20 block size
// TODO: unhardcode stuff // TODO: unhardcode stuff
enum FactoryDirections {
Any = "ANY",
None = "NONE"
}
type FactoryDirection = FactoryDirections | Direction;
function roundDownTo(num: number, multiple: number) { function roundDownTo(num: number, multiple: number) {
return Math.floor((num + multiple / 2) / multiple) * multiple; return Math.floor((num + multiple / 2) / multiple) * multiple;
} }
@ -41,20 +36,6 @@ function getRelativeCoords(e: MouseEvent) {
y: e.clientY - rect.top y: e.clientY - rect.top
}; };
} }
function iterateDirection(dir: FactoryDirection, func: (dir: FactoryDirection) => void) {
switch (dir) {
case FactoryDirections.None:
return;
case FactoryDirections.Any:
func(Direction.Up);
func(Direction.Right);
func(Direction.Down);
func(Direction.Left);
break;
default:
func(dir);
}
}
function rotateDir(dir: Direction, relative = Direction.Right) { function rotateDir(dir: Direction, relative = Direction.Right) {
const directions = [Direction.Up, Direction.Right, Direction.Down, Direction.Left]; const directions = [Direction.Up, Direction.Right, Direction.Down, Direction.Left];
let index = directions.indexOf(dir); let index = directions.indexOf(dir);
@ -94,36 +75,26 @@ const factory = createLayer(id, () => {
const name = "The Factory"; const name = "The Factory";
const color = "grey"; const color = "grey";
// ---------------------------------------------- Components
const FACTORY_COMPONENTS = { const FACTORY_COMPONENTS = {
cursor: { cursor: {
imageSrc: cursor, imageSrc: cursor,
name: "Cursor", name: "Cursor",
description: "Use this to move.", description: "Use this to move.",
tick: 0, tick: 0
consumption: {},
consumptionStock: {},
production: {},
productionStock: {}
}, },
rotate: { rotate: {
imageSrc: rotate, imageSrc: rotate,
name: "Rotate", name: "Rotate",
description: "Use this to rotate components.", description: "Use this to rotate components.",
tick: 0, tick: 0
consumption: {},
consumptionStock: {},
production: {},
productionStock: {}
}, },
conveyor: { conveyor: {
imageSrc: conveyor, imageSrc: conveyor,
name: "Conveyor", name: "Conveyor",
description: "Moves 1 item per tick.", description: "Moves items at 1 block per second.",
tick: 1, tick: 1,
consumption: {},
consumptionStock: {},
production: {},
productionStock: {},
ports: { ports: {
[Direction.Left]: { [Direction.Left]: {
type: "input" type: "input"
@ -135,41 +106,73 @@ const factory = createLayer(id, () => {
}, },
square: { square: {
imageSrc: square, imageSrc: square,
name: "???", name: "Producer",
description: "Produces 1 square every 1 tick.", description: "Produces 1 square every 1 second.",
tick: 1, tick: 1,
production: { outputs: {
square: 1 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: { outputs: {
square: Infinity square: {
}, amount: 1,
consumption: {}, capacity: 10
consumptionStock: {} }
}
} }
} as const; } as Record<FactoryCompNames, FactoryComponentDeclaration>;
const RESOURCES = { const RESOURCES = {
square: square square: square
} as Record<string, string>; } as Record<string, string>;
type FactoryCompNames = keyof typeof FACTORY_COMPONENTS; type FactoryCompNames = "cursor" | "rotate" | "conveyor" | "square" | "receiver" | "shrinker";
type BuildableCompName = Exclude<FactoryCompNames, "cursor">; type BuildableCompName = Exclude<FactoryCompNames, "cursor">;
interface FactoryComponentBase extends Record<string, State> { interface FactoryComponentBase extends Record<string, State> {
direction: Direction; direction: Direction;
} }
interface FactoryComponentProducers extends FactoryComponentBase {
interface FactoryComponentProducer extends FactoryComponentBase {
type: Exclude<BuildableCompName, "conveyor">; type: Exclude<BuildableCompName, "conveyor">;
consumptionStock: Record<string, number>; inputStock?: Record<string, number>;
// current production stock // current production stock
productionStock: Record<string, number>; outputStock?: Record<string, number>;
ticksDone: number; ticksDone: number;
} }
interface FactoryComponentConveyor extends FactoryComponentBase { interface FactoryComponentConveyor extends FactoryComponentBase {
type: "conveyor"; type: "conveyor";
} }
type FactoryComponent = FactoryComponentBase & type FactoryComponent = FactoryComponentBase &
(FactoryComponentConveyor | FactoryComponentProducers); (FactoryComponentConveyor | FactoryComponentProducer);
interface FactoryComponentDeclaration { interface FactoryComponentDeclaration {
tick: number; tick: number;
imageSrc: string; imageSrc: string;
@ -177,13 +180,21 @@ const factory = createLayer(id, () => {
description: string; description: string;
/** amount it consumes */ /** amount it consumes */
consumption: Record<string, number>; inputs?: Record<
/** maximum stock of consumption */ string,
consumptionStock: Record<string, number>; {
amount: number;
capacity?: number;
}
>;
/** amount it produces */ /** amount it produces */
production: Record<string, number>; outputs?: Record<
/** maximum stock of production */ string,
productionStock: Record<string, number>; {
amount: number;
capacity?: number;
}
>;
/** on produce, do something */ /** on produce, do something */
onProduce?: (times: number) => void; onProduce?: (times: number) => void;
@ -214,8 +225,8 @@ const factory = createLayer(id, () => {
// in block amts, not screen // in block amts, not screen
x: number; x: number;
y: number; y: number;
lastX: number; // make blocks turn in random amounts;
lastY: number; turbulance: number;
} }
// mouse positions // mouse positions
@ -228,7 +239,10 @@ const factory = createLayer(id, () => {
y: 0 y: 0
}); });
const isMouseHoverShown = ref(false); const isMouseHoverShown = ref(false);
const isComponentHover = ref(false);
const whatIsHovered = ref<FactoryCompNames | "">(""); const whatIsHovered = ref<FactoryCompNames | "">("");
const compSelected = ref<FactoryCompNames>("cursor"); const compSelected = ref<FactoryCompNames>("cursor");
const components: Persistent<{ [key: string]: FactoryComponent }> = persistent({}); const components: Persistent<{ [key: string]: FactoryComponent }> = persistent({});
const compInternalData: Record<string, FactoryInternal> = {}; const compInternalData: Record<string, FactoryInternal> = {};
@ -240,6 +254,7 @@ const factory = createLayer(id, () => {
const graphicContainer = new Graphics(); const graphicContainer = new Graphics();
let spriteContainer = new Container(); let spriteContainer = new Container();
const movingBlocks = new Container(); const movingBlocks = new Container();
let hoverSprite = new Sprite();
spriteContainer.zIndex = 0; spriteContainer.zIndex = 0;
movingBlocks.zIndex = 1; movingBlocks.zIndex = 1;
@ -260,8 +275,8 @@ const factory = createLayer(id, () => {
const floorGraphics = new Graphics(); const floorGraphics = new Graphics();
floorGraphics.beginFill(0x70645d); floorGraphics.beginFill(0x70645d);
floorGraphics.drawRect( floorGraphics.drawRect(
-factorySize.width * blockSize, (-factorySize.width - 0.5) * blockSize,
-factorySize.height * blockSize, (-factorySize.height - 0.5) * blockSize,
factorySize.width * 2 * blockSize, factorySize.width * 2 * blockSize,
factorySize.height * 2 * blockSize factorySize.height * 2 * blockSize
); );
@ -276,7 +291,6 @@ const factory = createLayer(id, () => {
} else { } else {
for (const id in components.value) { for (const id in components.value) {
const data = components.value[id]; const data = components.value[id];
console.log(id, data);
if (data?.type === undefined) { if (data?.type === undefined) {
delete components.value[id]; delete components.value[id];
continue; continue;
@ -291,36 +305,33 @@ const factory = createLayer(id, () => {
(window as any).internal = compInternalData; (window as any).internal = compInternalData;
(window as any).comp = components; (window as any).comp = components;
(window as any).blocks = movingBlocks; (window as any).blocks = movingBlocks;
let taskIsRunning = false;
globalBus.on("update", async diff => { globalBus.on("update", diff => {
if (taskIsRunning || !loaded) return; if (!loaded) return;
taskIsRunning = true;
//debugger //debugger
// will change soon:tm:
const tick = diff;
// make them produce // make them produce
for (const id in components.value) { for (const id in components.value) {
const [x, y] = id.split("x").map(p => +p); const [x, y] = id.split("x").map(p => +p);
const data = components.value[id]; const _data = components.value[id];
const compData = compInternalData[id]; const _compData = compInternalData[id];
//console.log(compData, data) if (_data === undefined || _compData === undefined) continue;
if (data === undefined || compData === undefined) continue; const factoryData = FACTORY_COMPONENTS[_data.type];
const factoryData = FACTORY_COMPONENTS[data.type]; // debugger;
//debugger; if (_data.type === "conveyor") {
if (data.type === "conveyor") { const data = _data as FactoryComponentConveyor;
const compData = _compData as FactoryInternalConveyor;
if (compData.type !== "conveyor") throw new TypeError("this should not happen"); if (compData.type !== "conveyor") throw new TypeError("this should not happen");
// conveyor part // conveyor part
// use a copy // use a copy
//console.log(compData);
compData.packages = compData.packages.concat(compData.nextPackages); compData.packages = compData.packages.concat(compData.nextPackages);
compData.nextPackages = []; compData.nextPackages = [];
for (const [key, block] of [...compData.packages].entries()) { for (let key = 0; key < compData.packages.length; key++) {
const inputDirection = rotateDir(data.direction, Direction.Left); const block = compData.packages[key];
const inputDirection = data.direction;
const dirType = getDirection(inputDirection); const dirType = getDirection(inputDirection);
const dirAmt = directionToNum(inputDirection); const dirAmt = directionToNum(inputDirection);
if (dirType === "h") { 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 compBehind = compInternalData[x + dirAmt + "x" + y];
const storedComp = components.value[x + dirAmt + "x" + y]; const storedComp = components.value[x + dirAmt + "x" + y];
@ -328,30 +339,34 @@ const factory = createLayer(id, () => {
if (compBehind === undefined) { if (compBehind === undefined) {
// just delete it // just delete it
movingBlocks.removeChild(block.sprite); movingBlocks.removeChild(block.sprite);
compData.packages.splice(key, 1);
} else if (compBehind.type === "conveyor") { } else if (compBehind.type === "conveyor") {
// push it to the next conveyor, kill it from the // push it to the next conveyor, kill it from the
// curent conveyor // curent conveyor
block.lastX += dirAmt; block.turbulance = Math.random() * 0.4 - 0.2;
compBehind.nextPackages.push(block); (compBehind as FactoryInternalConveyor).nextPackages.push(block);
compData.packages.splice(key, 1);
} else { } else {
// send it to the factory // send it to the factory
// destory its sprite and data // destory its sprite and data
(storedComp as FactoryComponentProducers).consumptionStock[ const factoryData = storedComp as FactoryComponentProducer;
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); movingBlocks.removeChild(block.sprite);
compData.packages.splice(key, 1);
} }
compData.packages.splice(key, 1);
key--;
} else { } else {
const change = 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.x += change;
block.sprite.x += change * blockSize; block.sprite.x += change * blockSize;
} }
} else { } else {
if (block.y <= block.lastY + dirAmt) { if ((block.y - y) * dirAmt >= 1 + block.turbulance) {
const compBehind = compInternalData[x + "x" + (y + dirAmt)]; const compBehind = compInternalData[x + "x" + (y + dirAmt)];
const storedComp = components.value[x + "x" + (y + dirAmt)]; const storedComp = components.value[x + "x" + (y + dirAmt)];
@ -359,82 +374,100 @@ const factory = createLayer(id, () => {
if (compBehind === undefined) { if (compBehind === undefined) {
// just delete it // just delete it
movingBlocks.removeChild(block.sprite); movingBlocks.removeChild(block.sprite);
compData.packages.splice(key, 1);
} else if (compBehind.type === "conveyor") { } else if (compBehind.type === "conveyor") {
// push it to the next conveyor, kill it from the // push it to the next conveyor, kill it from the
// curent conveyor // curent conveyor
block.lastY += dirAmt; block.turbulance = Math.random() * 0.4 - 0.2;
compBehind.nextPackages.push(block); (compBehind as FactoryInternalConveyor).nextPackages.push(block);
compData.packages.splice(key, 1);
} else { } else {
// send it to the factory // send it to the factory
// destory its sprite and data // destory its sprite and data
const factoryData = storedComp as FactoryComponentProducers; const data = storedComp as FactoryComponentProducer;
factoryData.consumptionStock[block.type]++; 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); movingBlocks.removeChild(block.sprite);
compData.packages.splice(key, 1);
} }
compData.packages.splice(key, 1);
key--;
} else { } 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.y += change;
block.sprite.y += change * blockSize; block.sprite.y += change * blockSize;
} }
} }
} }
} else { } else {
const data = _data as FactoryComponentProducer;
const compData = _compData as FactoryInternalProducer;
// factory part // factory part
// PRODUCTION // PRODUCTION
if (data.ticksDone >= factoryData.tick) { if (data.ticksDone >= factoryData.tick) {
if (!compData.canProduce.value) continue; if (compData.canProduce.value) {
const cyclesDone = Math.floor(data.ticksDone / factoryData.tick); const cyclesDone = Math.floor(data.ticksDone / factoryData.tick);
factoryData.onProduce?.(cyclesDone); factoryData.onProduce?.(cyclesDone);
for (const [key, val] of Object.entries(factoryData.consumption)) { if (factoryData.inputs !== undefined) {
data.consumptionStock[key] -= val; 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 { } else {
data.ticksDone += tick; data.ticksDone += diff;
} }
// now look at each component direction and see if it accepts items coming in // now look at each component direction and see if it accepts items coming in
// components are 1x1 so simple math for now // components are 1x1 so simple math for now
let yInc = 0; const incs: [number, number][] = [];
let xInc = 0;
//debugger;
if ( if (
components.value[x + "x" + (y + 1)]?.type === "conveyor" && components.value[x + "x" + (y + 1)]?.type === "conveyor" &&
components.value[x + "x" + (y + 1)].direction === Direction.Up
) {
yInc = 1;
} else 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.Down
) { ) {
yInc = -1; incs.push([0, 1]);
} else if ( }
if (
components.value[x + "x" + (y - 1)]?.type === "conveyor" &&
components.value[x + "x" + (y - 1)].direction === Direction.Up
) {
incs.push([0, -1]);
}
if (
components.value[x + 1 + "x" + y]?.type === "conveyor" && components.value[x + 1 + "x" + y]?.type === "conveyor" &&
components.value[x + "x" + (y + 1)].direction === Direction.Right components.value[x + 1 + "x" + y].direction === Direction.Right
) { ) {
xInc = 1; incs.push([1, 0]);
} else if ( }
if (
components.value[x - 1 + "x" + y]?.type === "conveyor" && components.value[x - 1 + "x" + y]?.type === "conveyor" &&
components.value[x + "x" + (y + 1)].direction === Direction.Left components.value[x - 1 + "x" + y].direction === Direction.Left
) { ) {
xInc = -1; incs.push([-1, 0]);
} }
// no suitable location to dump stuff in // no suitable location to dump stuff in
//console.log(x, y) // console.log(x, y);
//debugger; // 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; let itemToMove: [string, number] | undefined = undefined;
for (const [name, amt] of Object.entries(data.productionStock)) { if (data.outputStock !== undefined) {
if (amt >= 1) { for (const [name, amt] of Object.entries(data.outputStock)) {
itemToMove = [name, amt]; if (amt >= 1) {
data.productionStock[name]--; itemToMove = [name, amt];
break; data.outputStock[name]--;
break;
}
} }
} }
// there is nothing to move // there is nothing to move
@ -455,20 +488,17 @@ const factory = createLayer(id, () => {
// if X is being moved, then we don't need to adjust x // if X is being moved, then we don't need to adjust x
// however it needs to be aligned if Y is being moved // however it needs to be aligned if Y is being moved
// vice-versa // vice-versa
const spriteDiffX = xInc !== 0 ? 0 : 0.5; sprite.x = (x + xInc * 0.3) * blockSize;
const spriteDiffY = yInc !== 0 ? 0 : 0.5; sprite.y = (y + yInc * 0.3) * blockSize;
sprite.x = (x + spriteDiffX) * blockSize;
sprite.y = (y + spriteDiffY) * blockSize;
sprite.anchor.set(0.5); sprite.anchor.set(0.5);
sprite.width = blockSize / 2.5; sprite.width = blockSize / 2.5;
sprite.height = blockSize / 5; sprite.height = blockSize / 5;
//console.log(sprite); //console.log(sprite);
const block: Block = { const block: Block = {
sprite, sprite,
x: x, x: x + xInc * 0.3,
y: y, y: y + yInc * 0.3,
lastX: x, turbulance: Math.random() * 0.4 - 0.2,
lastY: y,
type: itemToMove[0] type: itemToMove[0]
}; };
@ -478,7 +508,6 @@ const factory = createLayer(id, () => {
movingBlocks.addChild(sprite); movingBlocks.addChild(sprite);
} }
} }
taskIsRunning = false;
}); });
function addFactoryComp( function addFactoryComp(
@ -509,17 +538,17 @@ const factory = createLayer(id, () => {
components.value[x + "x" + y] = { components.value[x + "x" + y] = {
ticksDone: 0, ticksDone: 0,
direction: Direction.Right, direction: Direction.Right,
consumptionStock: inputStock:
data.type === "conveyor" factoryBaseData.inputs === undefined
? undefined ? undefined
: Object.fromEntries( : Object.fromEntries(
Object.keys(factoryBaseData.consumptionStock).map(i => [i, 0]) Object.entries(factoryBaseData.inputs).map(x => [x[0], 0])
), ),
productionStock: outputStock:
data.type === "conveyor" factoryBaseData.outputs === undefined
? undefined ? undefined
: Object.fromEntries( : Object.fromEntries(
Object.keys(factoryBaseData.productionStock).map(i => [i, 0]) Object.entries(factoryBaseData.outputs).map(x => [x[0], 0])
), ),
...data ...data
} as FactoryComponent; } as FactoryComponent;
@ -532,23 +561,23 @@ const factory = createLayer(id, () => {
if (data.type === "conveyor") return true; if (data.type === "conveyor") return true;
if (!(factoryBaseData.canProduce?.value ?? true)) return false; if (!(factoryBaseData.canProduce?.value ?? true)) return false;
// this should NEVER be null // this should NEVER be null
const compData = components.value[x + "x" + y] as FactoryComponentProducers; const compData = components.value[x + "x" + y] as FactoryComponentProducer;
for (const [key, res] of Object.entries(compData.productionStock)) { if (factoryBaseData.inputs !== undefined) {
// if the current stock + production is more than you can handle for (const [res, val] of Object.entries(factoryBaseData.inputs))
if ( if ((compData.inputStock?.[res] ?? 0) < val.amount) return false;
res + factoryBaseData.production[key] >
factoryBaseData.productionStock[key]
)
return false;
} }
for (const [key, res] of Object.entries(compData.consumptionStock)) { if (factoryBaseData.outputs !== undefined) {
// make sure you have enough to produce for (const [res, val] of Object.entries(factoryBaseData.outputs))
if (res < factoryBaseData.consumptionStock[key]) return false; if (
(compData.outputStock?.[res] ?? 0) + val.amount >
(val.capacity ?? Infinity)
)
return false;
} }
return true; return true;
}), }),
sprite sprite
} as FactoryInternal; } as FactoryInternalProducer;
spriteContainer.addChild(sprite); spriteContainer.addChild(sprite);
} }
@ -563,19 +592,28 @@ const factory = createLayer(id, () => {
spriteContainer.x = movingBlocks.x = calculatedX; spriteContainer.x = movingBlocks.x = calculatedX;
spriteContainer.y = movingBlocks.y = calculatedY; spriteContainer.y = movingBlocks.y = calculatedY;
graphicContainer.removeChild(hoverSprite);
if ( if (
isMouseHoverShown.value && isMouseHoverShown.value &&
compSelected.value !== "cursor" && compSelected.value !== "cursor" &&
compSelected.value !== "rotate" compSelected.value !== "rotate"
) { ) {
const { tx, ty } = spriteContainer.localTransform; const { tx, ty } = spriteContainer.localTransform;
graphicContainer.beginFill(0x808080); graphicContainer.lineStyle(4, 0x808080, 1);
graphicContainer.drawRect( graphicContainer.drawRect(
roundDownTo(mouseCoords.x - tx, blockSize) + tx - blockSize / 2, roundDownTo(mouseCoords.x - tx, blockSize) + tx - blockSize / 2,
roundDownTo(mouseCoords.y - ty, blockSize) + ty - blockSize / 2, roundDownTo(mouseCoords.y - ty, blockSize) + ty - blockSize / 2,
blockSize, blockSize,
blockSize blockSize
); );
const factoryBaseData = FACTORY_COMPONENTS[compSelected.value];
const sheet = Assets.get(factoryBaseData.imageSrc);
hoverSprite = new Sprite(sheet);
hoverSprite.x = roundDownTo(mouseCoords.x - tx, blockSize) + tx - blockSize / 2;
hoverSprite.y = roundDownTo(mouseCoords.y - ty, blockSize) + ty - blockSize / 2;
hoverSprite.width = blockSize;
hoverSprite.height = blockSize;
graphicContainer.addChild(hoverSprite);
} }
} }
watchEffect(updateGraphics); watchEffect(updateGraphics);
@ -600,8 +638,14 @@ const factory = createLayer(id, () => {
mapOffset.y += e.movementY / blockSize; mapOffset.y += e.movementY / blockSize;
// the maximum you can see currently // the maximum you can see currently
// total size of blocks - current size = amount you should move // total size of blocks - current size = amount you should move
mapOffset.x = Math.min(Math.max(mapOffset.x, -factorySize.width), factorySize.width); mapOffset.x = Math.min(
mapOffset.y = Math.min(Math.max(mapOffset.y, -factorySize.height), factorySize.height); Math.max(mapOffset.x, -factorySize.width + 0.5),
factorySize.width + 0.5
);
mapOffset.y = Math.min(
Math.max(mapOffset.y, -factorySize.height + 0.5),
factorySize.height + 0.5
);
} }
if (!pointerDown.value && !pointerDrag.value) { if (!pointerDown.value && !pointerDrag.value) {
const { tx, ty } = spriteContainer.localTransform; const { tx, ty } = spriteContainer.localTransform;
@ -651,7 +695,16 @@ const factory = createLayer(id, () => {
} else if (e.button === 2) { } else if (e.button === 2) {
const data = compInternalData[x + "x" + y]; const data = compInternalData[x + "x" + y];
if (data === undefined) return; 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 components.value[x + "x" + y];
delete compInternalData[x + "x" + y];
spriteContainer.removeChild(data.sprite); spriteContainer.removeChild(data.sprite);
} }
} }
@ -664,17 +717,23 @@ const factory = createLayer(id, () => {
} }
function onFactoryMouseLeave() { function onFactoryMouseLeave() {
isMouseHoverShown.value = false; isMouseHoverShown.value = false;
compHovered.value = undefined;
}
function onComponentMouseEnter(name: FactoryCompNames | "") {
whatIsHovered.value = name;
isComponentHover.value = true;
}
function onComponentMouseLeave() {
isComponentHover.value = false;
}
function onCompClick(name: FactoryCompNames) {
compSelected.value = name;
} }
function goBack() { function goBack() {
player.tabs.splice(0, Infinity, "main"); player.tabs.splice(0, Infinity, "main");
} }
function onComponentHover(name: FactoryCompNames | "") {
whatIsHovered.value = name;
}
function onCompClick(name: FactoryCompNames) {
compSelected.value = name;
}
return { return {
name, name,
day, day,
@ -696,54 +755,126 @@ const factory = createLayer(id, () => {
onPointerleave={onFactoryMouseLeave} onPointerleave={onFactoryMouseLeave}
onContextmenu={(e: MouseEvent) => e.preventDefault()} onContextmenu={(e: MouseEvent) => e.preventDefault()}
/> />
<div class="info-container">
{compHovered.value !== undefined ? ( {compHovered.value !== undefined ? (
<> <div
<b>{FACTORY_COMPONENTS[compHovered.value.type].name}</b> class="info-container"
<br /> id="factory-info"
{FACTORY_COMPONENTS[compHovered.value.type].description} style={{
<br /> ...(mouseCoords.x +
{compHovered.value.type !== "conveyor" ? ( (document.getElementById("factory-info")?.clientWidth ?? 0) >
<> app.view.width - 30
Stock:{" "} ? { right: app.view.width - mouseCoords.x + "px" }
{Object.entries({ : { left: mouseCoords.x + "px" }),
...compHovered.value.productionStock, ...(mouseCoords.y +
...compHovered.value.consumptionStock (document.getElementById("factory-info")?.clientHeight ?? 0) >
}).map(i => { app.view.height - 30
return `${i[0]}: ${i[1]}/${ ? { bottom: app.view.height - mouseCoords.y + "px" }
FACTORY_COMPONENTS[compHovered.value?.type ?? "cursor"] : { top: mouseCoords.y + "px" })
.consumptionStock[i[0]] ?? }}
FACTORY_COMPONENTS[compHovered.value?.type ?? "cursor"] >
.productionStock[i[0]] <h3>{FACTORY_COMPONENTS[compHovered.value.type].name}</h3>
}`; <br />
})} {FACTORY_COMPONENTS[compHovered.value.type].description}
</> <br />
) : undefined} {compHovered.value.type !== "conveyor" ? (
</> <>
) : undefined} {compHovered.value.inputStock !== undefined ? (
</div> <>
<div class="factory-container"> <br />
<div style="line-height: 2.5em; min-height: 2.5em"> <h5>Inputs:</h5>
{whatIsHovered.value === "" {Object.entries(compHovered.value.inputStock).map(x => (
? undefined <div>
: FACTORY_COMPONENTS[whatIsHovered.value].description} {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> </div>
<div class="comps"> ) : undefined}
<div>
{Object.entries(FACTORY_COMPONENTS).map(value => { <div class="factory-container">
const key = value[0] as FactoryCompNames; <div
const item = value[1]; class={{
return ( "comp-info": true,
<img active: isComponentHover.value
src={item.imageSrc} }}
class={{ selected: compSelected.value === key }} style={{
onMouseenter={() => onComponentHover(key)} top:
onMouseleave={() => onComponentHover("")} Math.max(
onClick={() => onCompClick(key)} Object.keys(FACTORY_COMPONENTS).indexOf(whatIsHovered.value),
></img> 0
); ) *
})} 50 +
</div> 10 +
"px"
}}
>
{whatIsHovered.value === "" ? undefined : (
<>
<h3>{FACTORY_COMPONENTS[whatIsHovered.value].name}</h3>
<br />
{FACTORY_COMPONENTS[whatIsHovered.value].description}
</>
)}
</div>
<div class="comp-list">
{Object.entries(FACTORY_COMPONENTS).map(value => {
const key = value[0] as FactoryCompNames;
const item = value[1];
return (
<img
src={item.imageSrc}
class={{ selected: compSelected.value === key }}
onMouseenter={() => onComponentMouseEnter(key)}
onMouseleave={() => onComponentMouseLeave()}
onClick={() => onCompClick(key)}
/>
);
})}
</div> </div>
</div> </div>
</div> </div>

View file

@ -17,38 +17,71 @@
.info-container { .info-container {
position: absolute; position: absolute;
height: 100px; width: max-content;
top: 0; max-width: 300px;
left: 10%;
right: 10%; margin: 20px 0 10px 10px;
transition: height ease 1s; padding: 5px 10px;
background: var(--raised-background);
border-radius: 0 0 var(--border-radius) var(--border-radius); background: var(--background);
box-shadow: 0 2px 10px black; border-radius: var(--border-radius);
margin: 0; box-shadow: 0 1px 5px black;
padding: 0;
text-align: left;
font-size: smaller;
pointer-events: none;
transition: height .3s;
} }
.factory-container { .factory-container {
position: absolute; position: absolute;
bottom: -5px; top: calc(5% + 30px);
height: 100px; bottom: 5%;
left: 10%; left: 0%;
right: 10%; width: 70px;
background: var(--raised-background);
border-radius: var(--border-radius) var(--border-radius) 0 0;
box-shadow: 0 2px 10px black;
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
.comps > div > img { .comp-info {
position: absolute;
right: 10px;
padding: 5px 10px;
width: max-content;
max-width: 300px;
background: var(--background);
border-radius: var(--border-radius);
box-shadow: 0 1px 5px #0007;
text-align: left;
font-size: smaller;
pointer-events: none;
transition: transform 0.3s;
}
.comp-info.active {
transform: translateX(calc(20px + 100%));
}
.comp-list {
position: relative;
height: 100%;
padding: 10px;
background: var(--raised-background);
border-radius: 0 var(--border-radius) var(--border-radius) 0;
box-shadow: 0 2px 10px black;
}
.comp-list > img {
display: block;
width: 50px; width: 50px;
height: 50px; height: 50px;
} }
.comps > div > img.selected { .comp-list > img.selected {
transform: translateY(-5px); transform: translate(-5px, -5px);
filter: drop-shadow(0 5px 5px #0007); filter: drop-shadow(2px 2px 0 var(--foreground)) drop-shadow(5px 5px 5px #0007);
} }

View file

@ -48,6 +48,7 @@ export type State =
| string | string
| number | number
| boolean | boolean
| undefined
| DecimalSource | DecimalSource
| { [key: string]: State } | { [key: string]: State }
| { [key: number]: State }; | { [key: number]: State };