-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.js
More file actions
124 lines (102 loc) · 4.75 KB
/
Copy pathserver.js
File metadata and controls
124 lines (102 loc) · 4.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import express from 'express';
import { createServer } from 'http';
import { WebSocketServer } from 'ws';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = express();
const PORT = process.env.PORT || 3000;
// ─── Static file serving (replaces GitHub Pages) ───────────────────────────
const staticOpts = { maxAge: process.env.NODE_ENV === 'production' ? '1h' : 0 };
// Serve the game client files (only safe directories)
app.use('/js', express.static(path.join(__dirname, 'js'), staticOpts));
app.use('/css', express.static(path.join(__dirname, 'css'), staticOpts));
app.use('/public', express.static(path.join(__dirname, 'public'), staticOpts));
// Serve index.html at root
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'index.html'));
});
// ─── Health check endpoint (Railway uses this) ─────────────────────────────
app.get('/health', (req, res) => {
res.json({ status: 'ok', uptime: process.uptime() });
});
// ─── API routes placeholder ────────────────────────────────────────────────
// Future: mount MUD API routes, golf lobby API, user auth, etc.
// import mudRouter from './server/mud/routes.js';
// import golfRouter from './server/golf/routes.js';
// app.use('/api/mud', mudRouter);
// app.use('/api/golf', golfRouter);
// ─── Create HTTP server ────────────────────────────────────────────────────
const server = createServer(app);
// ─── WebSocket server ──────────────────────────────────────────────────────
const wss = new WebSocketServer({ server, path: '/ws' });
wss.on('connection', (ws, req) => {
const url = new URL(req.url, `http://${req.headers.host}`);
const channel = url.searchParams.get('channel') || 'general';
console.log(`[WS] Client connected to channel: ${channel}`);
ws.channel = channel;
ws.isAlive = true;
ws.on('pong', () => { ws.isAlive = true; });
ws.on('message', (data) => {
try {
const msg = JSON.parse(data);
handleMessage(ws, channel, msg);
} catch (e) {
ws.send(JSON.stringify({ type: 'error', message: 'Invalid JSON' }));
}
});
ws.on('close', () => {
console.log(`[WS] Client disconnected from channel: ${channel}`);
});
// Welcome message
ws.send(JSON.stringify({
type: 'connected',
channel,
message: `Connected to ${channel} channel`
}));
});
// ─── WebSocket message router ──────────────────────────────────────────────
function handleMessage(ws, channel, msg) {
switch (channel) {
case 'mud':
handleMudMessage(ws, msg);
break;
case 'golf':
handleGolfMessage(ws, msg);
break;
default:
ws.send(JSON.stringify({ type: 'echo', data: msg }));
}
}
// ─── MUD handler placeholder ───────────────────────────────────────────────
function handleMudMessage(ws, msg) {
// Future: parse commands, update world state, broadcast to room
ws.send(JSON.stringify({
type: 'mud:response',
message: '[MUD server not yet implemented]'
}));
}
// ─── Golf multiplayer handler placeholder ──────────────────────────────────
function handleGolfMessage(ws, msg) {
// Future: lobby management, turn sync, shot broadcasting
ws.send(JSON.stringify({
type: 'golf:response',
message: '[Golf server not yet implemented]'
}));
}
// ─── WebSocket heartbeat (detect dead connections) ─────────────────────────
const heartbeatInterval = setInterval(() => {
wss.clients.forEach((ws) => {
if (!ws.isAlive) return ws.terminate();
ws.isAlive = false;
ws.ping();
});
}, 30000);
wss.on('close', () => clearInterval(heartbeatInterval));
// ─── Start server ──────────────────────────────────────────────────────────
server.listen(PORT, '0.0.0.0', () => {
console.log(`[Server] Listening on port ${PORT}`);
console.log(`[Server] Static files: ./ (repo root)`);
console.log(`[Server] WebSocket: ws://localhost:${PORT}/ws`);
});