phase 11 part1
This commit is contained in:
177
src/systems/WorkstationSystem.js
Normal file
177
src/systems/WorkstationSystem.js
Normal file
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* WORKSTATION SYSTEM
|
||||
* Manages processing stations like Furnace, Mint, Campfire.
|
||||
* Handles: Input -> Process Time -> Output
|
||||
*/
|
||||
class WorkstationSystem {
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
this.stations = new Map(); // Key: "x,y", Value: StationData
|
||||
|
||||
// Define Recipes
|
||||
this.recipes = {
|
||||
'furnace': [
|
||||
{ input: 'ore_iron', fuel: 'coal', output: 'iron_bar', time: 5000 },
|
||||
{ input: 'ore_stone', fuel: 'coal', output: 'stone_brick', time: 3000 },
|
||||
{ input: 'sand', fuel: 'coal', output: 'glass', time: 3000 },
|
||||
{ input: 'log', fuel: 'log', output: 'charcoal', time: 4000 } // Wood to charcoal
|
||||
],
|
||||
'mint': [
|
||||
{ input: 'iron_bar', fuel: 'coal', output: 'coin_gold', time: 2000, outputCount: 10 }
|
||||
],
|
||||
'campfire': [
|
||||
{ input: 'raw_meat', fuel: 'stick', output: 'cooked_meat', time: 3000 }
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new workstation at coordinates
|
||||
*/
|
||||
addStation(x, y, type) {
|
||||
const key = `${x},${y}`;
|
||||
if (this.stations.has(key)) return;
|
||||
|
||||
this.stations.set(key, {
|
||||
x, y, type,
|
||||
input: null, // { itemId, count }
|
||||
fuel: null, // { itemId, count }
|
||||
output: null, // { itemId, count }
|
||||
isProcessing: false,
|
||||
timer: 0,
|
||||
maxTime: 0,
|
||||
currentRecipe: null
|
||||
});
|
||||
console.log(`🏭 Created ${type} at ${x},${y}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Player interacts with station
|
||||
* (Simple version: Click with item to insert, Click empty to take output)
|
||||
*/
|
||||
interact(x, y, playerItem) {
|
||||
const key = `${x},${y}`;
|
||||
const station = this.stations.get(key);
|
||||
if (!station) return false;
|
||||
|
||||
// 1. If Output exists, take it (Prioritize taking output)
|
||||
if (station.output) {
|
||||
this.scene.inventorySystem.addItem(station.output.itemId, station.output.count);
|
||||
this.showFloatingText(x, y, `+${station.output.count} ${station.output.itemId}`, '#00FF00');
|
||||
station.output = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2. If holding item, try to insert (Input or Fuel)
|
||||
if (playerItem) {
|
||||
// Check if it's Valid Input for this station type
|
||||
const recipe = this.findRecipe(station.type, playerItem.itemId);
|
||||
|
||||
// Is it Fuel? (Assume 'coal', 'log', 'stick' are fuels)
|
||||
const isFuel = ['coal', 'log', 'stick', 'charcoal'].includes(playerItem.itemId);
|
||||
|
||||
if (recipe && !station.input) {
|
||||
// Insert Input
|
||||
station.input = { itemId: playerItem.itemId, count: 1 };
|
||||
this.scene.inventorySystem.removeItem(playerItem.itemId, 1);
|
||||
this.showFloatingText(x, y, `Inserted ${playerItem.itemId}`, '#FFFFFF');
|
||||
this.tryStartProcess(station);
|
||||
return true;
|
||||
} else if (isFuel && !station.fuel) {
|
||||
// Insert Fuel
|
||||
station.fuel = { itemId: playerItem.itemId, count: 1 };
|
||||
this.scene.inventorySystem.removeItem(playerItem.itemId, 1);
|
||||
this.showFloatingText(x, y, `Fueled with ${playerItem.itemId}`, '#FFA500');
|
||||
this.tryStartProcess(station);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Status Check
|
||||
if (station.isProcessing) {
|
||||
const progress = Math.floor((station.timer / station.maxTime) * 100);
|
||||
this.showFloatingText(x, y, `Processing... ${progress}%`, '#FFFF00');
|
||||
} else {
|
||||
this.showFloatingText(x, y, 'Missing Input or Fuel', '#FF0000');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
findRecipe(stationType, inputItem) {
|
||||
const stationRecipes = this.recipes[stationType];
|
||||
if (!stationRecipes) return null;
|
||||
return stationRecipes.find(r => r.input === inputItem);
|
||||
}
|
||||
|
||||
tryStartProcess(station) {
|
||||
if (station.isProcessing) return;
|
||||
if (!station.input || !station.fuel) return;
|
||||
|
||||
// Find matching recipe
|
||||
const recipe = this.recipes[station.type].find(r =>
|
||||
r.input === station.input.itemId &&
|
||||
(r.fuel === 'any' || r.fuel === station.fuel.itemId)
|
||||
);
|
||||
|
||||
// Specific fuel check can be relaxed later
|
||||
if (recipe) {
|
||||
station.isProcessing = true;
|
||||
station.timer = 0;
|
||||
station.maxTime = recipe.time;
|
||||
station.currentRecipe = recipe;
|
||||
console.log(`🔥 Started processing ${recipe.input} -> ${recipe.output}`);
|
||||
|
||||
// Visual feedback (Particles?)
|
||||
// this.scene.addParticles...
|
||||
}
|
||||
}
|
||||
|
||||
update(delta) {
|
||||
for (const station of this.stations.values()) {
|
||||
if (station.isProcessing) {
|
||||
station.timer += delta;
|
||||
|
||||
// Visual: Float smoke occasionally?
|
||||
if (Math.random() < 0.05) {
|
||||
// emit smoke particle
|
||||
}
|
||||
|
||||
if (station.timer >= station.maxTime) {
|
||||
// COMPLETE
|
||||
const recipe = station.currentRecipe;
|
||||
const outCount = recipe.outputCount || 1;
|
||||
|
||||
// Consume inputs
|
||||
// (Actually we keep them in slots until done? Or consume at start?
|
||||
// Let's say inputs are consumed at start visually, but logically here we swap to output)
|
||||
|
||||
station.output = { itemId: recipe.output, count: outCount };
|
||||
station.input = null;
|
||||
station.fuel = null; // Consume 1 fuel per operation for now (Simple)
|
||||
|
||||
station.isProcessing = false;
|
||||
station.timer = 0;
|
||||
station.currentRecipe = null;
|
||||
|
||||
this.showFloatingText(station.x, station.y, 'DONE!', '#00FF00');
|
||||
if (this.scene.soundManager) this.scene.soundManager.playSuccess(); // Placeholder sound
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
showFloatingText(x, y, text, color) {
|
||||
// Convert grid to screen
|
||||
// Assuming interact passes Grid X,Y
|
||||
if (this.scene.events) {
|
||||
const screen = this.scene.iso.toScreen(x, y);
|
||||
this.scene.events.emit('show-floating-text', {
|
||||
x: screen.x + this.scene.terrainOffsetX,
|
||||
y: screen.y + this.scene.terrainOffsetY - 30,
|
||||
text: text,
|
||||
color: color
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user