Files
nissefolk/src/scenes/GameScene.ts

131 lines
4.8 KiB
TypeScript
Raw Normal View History

2026-03-20 08:11:31 +00:00
import Phaser from 'phaser'
import { AUTOSAVE_INTERVAL, TILE_SIZE } from '../config'
import type { BuildingType } from '../types'
import { stateManager } from '../StateManager'
import { LocalAdapter } from '../NetworkAdapter'
import { WorldSystem } from '../systems/WorldSystem'
import { CameraSystem } from '../systems/CameraSystem'
import { ResourceSystem } from '../systems/ResourceSystem'
import { BuildingSystem } from '../systems/BuildingSystem'
import { FarmingSystem } from '../systems/FarmingSystem'
import { VillagerSystem } from '../systems/VillagerSystem'
export class GameScene extends Phaser.Scene {
private adapter!: LocalAdapter
private worldSystem!: WorldSystem
private cameraSystem!: CameraSystem
private resourceSystem!: ResourceSystem
private buildingSystem!: BuildingSystem
private farmingSystem!: FarmingSystem
villagerSystem!: VillagerSystem
private autosaveTimer = 0
private menuOpen = false
constructor() { super({ key: 'Game' }) }
create(): void {
this.adapter = new LocalAdapter()
this.worldSystem = new WorldSystem(this)
this.cameraSystem = new CameraSystem(this, this.adapter)
this.resourceSystem = new ResourceSystem(this, this.adapter)
this.buildingSystem = new BuildingSystem(this, this.adapter)
this.farmingSystem = new FarmingSystem(this, this.adapter)
this.villagerSystem = new VillagerSystem(this, this.adapter, this.worldSystem)
this.villagerSystem.init(this.resourceSystem, this.farmingSystem)
this.worldSystem.create()
this.renderPersistentObjects()
this.cameraSystem.create()
this.resourceSystem.create()
this.resourceSystem.onHarvest = (msg) => this.events.emit('toast', msg)
this.buildingSystem.create()
this.buildingSystem.onModeChange = (active, building) => this.events.emit('buildModeChanged', active, building)
this.buildingSystem.onPlaced = (msg) => {
this.events.emit('toast', msg)
this.renderPersistentObjects()
}
this.farmingSystem.create()
this.farmingSystem.onMessage = (msg) => this.events.emit('toast', msg)
this.farmingSystem.onToolChange = (tool, label) => this.events.emit('farmToolChanged', tool, label)
this.villagerSystem.create()
this.villagerSystem.onMessage = (msg) => this.events.emit('toast', msg)
// Sync tile changes and building visuals through adapter
this.adapter.onAction = (action) => {
if (action.type === 'CHANGE_TILE') {
this.worldSystem.setTile(action.tileX, action.tileY, action.tile)
}
}
this.scene.launch('UI')
this.events.on('selectBuilding', (kind: BuildingType) => this.buildingSystem.selectBuilding(kind))
this.events.on('uiMenuOpen', () => { this.menuOpen = true })
this.events.on('uiMenuClose', () => { this.menuOpen = false })
this.events.on('uiRequestBuildMenu', () => {
if (!this.buildingSystem.isActive()) this.events.emit('openBuildMenu')
})
this.events.on('updatePriorities', (villagerId: string, priorities: { chop: number; mine: number; farm: number }) => {
this.adapter.send({ type: 'UPDATE_PRIORITIES', villagerId, priorities })
})
this.autosaveTimer = AUTOSAVE_INTERVAL
}
update(_time: number, delta: number): void {
if (this.menuOpen) return
this.cameraSystem.update(delta)
this.resourceSystem.update(delta)
this.farmingSystem.update(delta)
this.villagerSystem.update(delta)
this.events.emit('cameraMoved', this.cameraSystem.getCenterTile())
this.buildingSystem.update()
this.autosaveTimer -= delta
if (this.autosaveTimer <= 0) {
this.autosaveTimer = AUTOSAVE_INTERVAL
stateManager.save()
}
}
/** Render game objects that persist across sessions (buildings + crop sprites etc.) */
private renderPersistentObjects(): void {
const state = stateManager.getState()
for (const building of Object.values(state.world.buildings)) {
const wx = building.tileX * TILE_SIZE + TILE_SIZE / 2
const wy = building.tileY * TILE_SIZE + TILE_SIZE / 2
const name = `bobj_${building.id}`
if (this.children.getByName(name)) continue
if (building.kind === 'chest') {
const g = this.add.graphics().setName(name).setDepth(8)
g.fillStyle(0x8B4513); g.fillRect(wx - 10, wy - 7, 20, 14)
g.fillStyle(0xCD853F); g.fillRect(wx - 9, wy - 6, 18, 6)
g.lineStyle(1, 0x5C3317); g.strokeRect(wx - 10, wy - 7, 20, 14)
} else if (building.kind === 'bed') {
this.add.image(wx, wy, 'bed_obj').setName(name).setDepth(8)
} else if (building.kind === 'stockpile_zone') {
this.add.image(wx, wy, 'stockpile_obj').setName(name).setDepth(4).setAlpha(0.8)
}
}
}
shutdown(): void {
stateManager.save()
this.worldSystem.destroy()
this.resourceSystem.destroy()
this.buildingSystem.destroy()
this.farmingSystem.destroy()
this.villagerSystem.destroy()
}
}