From f5af6416ffa1934c1735eb029729190422c25816 Mon Sep 17 00:00:00 2001 From: Atlaskor Date: Thu, 13 Nov 2025 15:32:40 +0000 Subject: [PATCH] Add server/static/main.js --- server/static/main.js | 137 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 server/static/main.js diff --git a/server/static/main.js b/server/static/main.js new file mode 100644 index 0000000..7d5e8e9 --- /dev/null +++ b/server/static/main.js @@ -0,0 +1,137 @@ +import { setupAuthPanel } from './ui_auth.js'; +import { setupHUD } from './ui_hud.js'; +import { setupChat } from './ui_chat.js'; +import { setupInventory } from './ui_inventory.js'; +import { setupCrafting } from './ui_crafting.js'; +import { MapView } from './map.js'; + +const socket = io(); + +// global-ish state for modules +const state = { + me: null, + world: null, + inventory: [], + players: [], + nodes: [] +}; + +// expose to UIs if they need it +window.GameState = state; +window.GameSocket = socket; + +async function fetchMe() { + const res = await fetch('/api/me', { credentials: 'include' }); + if (res.status !== 200) return null; + return res.json(); +} + +// Phaser scene +class GameScene extends Phaser.Scene { + constructor() { + super('Game'); + } + preload() { + this.textures.generate('player', { data: ['333', '383', '333'], pixelWidth: 8 }); + this.textures.generate('other', { data: ['939', '999', '939'], pixelWidth: 8 }); + this.textures.generate('wood', { data: ['060', '660', '060'], pixelWidth: 8 }); + this.textures.generate('stone', { data: ['888', 'aaa', '888'], pixelWidth: 8 }); + this.textures.generate('ore', { data: ['a73', 'c95', 'a73'], pixelWidth: 8 }); + this.textures.generate('fiber', { data: ['6a6', '8c8', '6a6'], pixelWidth: 8 }); + } + create() { + this.mapView = new MapView(this); + this.mapView.create(state.me, state.world, state.nodes); + + // click to move + this.input.on('pointerdown', p => { + this.mapView.setTarget(p.worldX, p.worldY); + socket.emit('move:click', { x: p.worldX, y: p.worldY }); + }); + + // gather on E + this.input.keyboard.on('keydown-E', () => { + const nodeId = this.mapView.getClosestNodeIdInRange(40); + if (nodeId == null) return; + socket.emit('gather', { nodeId }, res => { + if (res?.ok) { + window.updateXP?.(res.level); + window.addChatLine?.(`You gather 1 ${res.item} (+${res.xp} xp)`); + // inventory not re-fetched here for brevity + } else if (res?.error) { + window.addChatLine?.(`Gather failed: ${res.error}`); + } + }); + }); + + // socket updates hooked to MapView + socket.on('nodes:init', list => { + state.nodes = list; + this.mapView.replaceNodes(list); + }); + socket.on('node:update', u => { + this.mapView.updateNode(u); + }); + socket.on('state', snap => { + state.players = snap.players; + this.mapView.updateOtherPlayers(snap.players); + }); + + // zoom from HUD + window.setGameZoom = z => this.mapView.setZoom(z); + } + update(time, delta) { + this.mapView.update(delta); + } +} + +async function boot() { + // mount UIs + setupAuthPanel(document.getElementById('ui-auth'), socket, bootAfterLogin); + setupHUD(document.getElementById('ui-hud')); + setupChat(document.getElementById('ui-chat'), socket); + setupInventory(document.getElementById('ui-inventory')); + setupCrafting(document.getElementById('ui-crafting')); + + // attempt auto-login + const meData = await fetchMe(); + if (!meData) { + // show auth + document.getElementById('ui-auth').firstElementChild?.classList.remove('hidden'); + return; + } + await bootAfterLogin(); +} + +async function bootAfterLogin() { + const data = await fetchMe(); + if (!data) return; + state.me = data.character; + state.inventory = data.inventory; + state.world = data.world; + + // join socket world + await new Promise(resolve => { + socket.emit('auth:join', ack => { + resolve(ack); + }); + }); + + document.getElementById('ui-auth').innerHTML = ''; // hide auth + document.getElementById('ui-hud').firstElementChild?.classList.remove('hidden'); + document.getElementById('ui-chat').firstElementChild?.classList.remove('hidden'); + + // start Phaser game + const config = { + type: Phaser.AUTO, + parent: 'game', + width: window.innerWidth, + height: window.innerHeight, + backgroundColor: '#020617', + scene: [GameScene] + }; + + new Phaser.Game(config); +} + +boot();