Add server/static/main.js
This commit is contained in:
137
server/static/main.js
Normal file
137
server/static/main.js
Normal file
@@ -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();
|
||||||
Reference in New Issue
Block a user