Character manager: asset uploads, per-ghost model/colour/opacity overrides, face+torso texture decals

This commit is contained in:
2026-07-24 14:47:36 +10:00
parent b6822af047
commit 5357c8464d
9 changed files with 642 additions and 39 deletions
+14
View File
@@ -12,6 +12,7 @@ const LIVE = path.join(LIVE_DIR, 'scene.live.json');
const PLAYLIST_LIVE = path.join(LIVE_DIR, 'playlist.live.json');
const MODELS_LIVE = path.join(LIVE_DIR, 'models.live.json');
const MODELS_SEED = path.join(DATA, 'models.json');
const CHARS_LIVE = path.join(LIVE_DIR, 'characters.live.json');
fs.mkdirSync(LIVE_DIR, { recursive: true });
@@ -26,6 +27,10 @@ let scene = readJSON(LIVE, null) || readJSON(SEED, { anchors: [], buildings: [],
let ghosts = readJSON(path.join(DATA, 'ghosts.json'), []);
let gradients = readJSON(path.join(DATA, 'gradients.json'), {});
let models = readJSON(MODELS_LIVE, null) || readJSON(MODELS_SEED, { models: [] });
/* characters: per-ghost visual overrides keyed by ghost id, plus defaults.
* { defaults: {...}, byId: { 'mad-fenton': { modelId, opacity, topColor, bottomColor,
* faceTextureUrl, torsoTextureUrl, heightCm, scale } } } */
let characters = readJSON(CHARS_LIVE, null) || { defaults: {}, byId: {} };
const listeners = [];
@@ -71,6 +76,15 @@ module.exports = {
return scene;
},
getGhosts: () => ({ ghosts, gradients }),
getCharacters: () => characters,
putCharacters(c) {
if (!c || typeof c !== 'object') throw new Error('characters must be object');
characters = { defaults: c.defaults || {}, byId: c.byId || {} };
writeJSON(CHARS_LIVE, characters);
listeners.forEach(f => f());
return characters;
},
liveDir: LIVE_DIR,
getModels: () => models,
putModels(m) {
if (!m || !Array.isArray(m.models)) throw new Error('models.models must be array');