feat: character/NPC management system with spritesheet support
Add drag & drop spritesheet upload in editor, character registry in sprites.js, character selector for NPCs, sprite rendering on editor canvas, server API for character persistence, and game-side character loading via characterLoader.js. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
38
server.js
38
server.js
@@ -8,6 +8,7 @@ const path = require('path');
|
||||
const PORT = process.env.PORT || 80;
|
||||
const STATIC_DIR = path.join(__dirname, 'public');
|
||||
const MAPS_FILE = path.join(STATIC_DIR, 'js', 'world', 'maps.js');
|
||||
const CHARS_FILE = path.join(STATIC_DIR, 'data', 'characters.json');
|
||||
|
||||
const MIME = {
|
||||
'.html': 'text/html',
|
||||
@@ -92,6 +93,43 @@ const server = http.createServer((req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// === API: GET /api/characters — read character data ===
|
||||
if (req.method === 'GET' && req.url === '/api/characters') {
|
||||
fs.readFile(CHARS_FILE, 'utf-8', (err, data) => {
|
||||
if (err) {
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ characters: {} }));
|
||||
return;
|
||||
}
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(data);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// === API: PUT /api/characters — write character data ===
|
||||
if (req.method === 'PUT' && req.url === '/api/characters') {
|
||||
let body = '';
|
||||
req.on('data', chunk => { body += chunk; });
|
||||
req.on('end', () => {
|
||||
try {
|
||||
const parsed = JSON.parse(body);
|
||||
// Ensure data dir exists
|
||||
const dataDir = path.dirname(CHARS_FILE);
|
||||
if (!fs.existsSync(dataDir)) fs.mkdirSync(dataDir, { recursive: true });
|
||||
fs.writeFileSync(CHARS_FILE, JSON.stringify(parsed, null, 2), 'utf-8');
|
||||
const count = Object.keys(parsed.characters || {}).length;
|
||||
console.log(`[server] characters.json saved (${count} characters)`);
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ ok: true, count }));
|
||||
} catch (e) {
|
||||
res.writeHead(400, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ error: e.message }));
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// === Static file serving ===
|
||||
let filePath = path.join(STATIC_DIR, req.url === '/' ? 'index.html' : req.url);
|
||||
// Prevent directory traversal
|
||||
|
||||
Reference in New Issue
Block a user