prologue: wire background_id into new player creation on server
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// OTIVM server — OTIVM-III
|
||||
// OTIVM server — OTIVM-IV
|
||||
// Per-player SQLite integration.
|
||||
// TESSERA world database (data/otivm.sqlite3) — read-only, unchanged.
|
||||
// Player databases (data/saves/{token}.sqlite3) — one per player,
|
||||
@@ -7,6 +7,12 @@
|
||||
// JSON save files (data/saves/{token}.json) — never deleted, migrated
|
||||
// transparently on first SQLite access if present.
|
||||
// Frontend interface unchanged — GET/POST /api/save/:token same as before.
|
||||
//
|
||||
// Change 3 (OTIVM-IV): background_id from the frontend is now a real
|
||||
// canonical identifier (e.g. 'former_legionary'). On new player creation,
|
||||
// seed actor_parameters from background_starting_values for that background.
|
||||
// The previous default of 'unknown' is kept only as a fallback for legacy
|
||||
// saves that predate Change 3.
|
||||
|
||||
import Fastify from 'fastify'
|
||||
import fastifyStatic from '@fastify/static'
|
||||
@@ -17,10 +23,10 @@ import { existsSync } from 'fs'
|
||||
import Database from 'better-sqlite3'
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||
const ROOT = join(__dirname, '..')
|
||||
const DIST = join(ROOT, 'dist')
|
||||
const SAVES_DIR = join(ROOT, 'data', 'saves')
|
||||
const DB_PATH = join(ROOT, 'data', 'otivm.sqlite3')
|
||||
const ROOT = join(__dirname, '..')
|
||||
const DIST = join(ROOT, 'dist')
|
||||
const SAVES_DIR = join(ROOT, 'data', 'saves')
|
||||
const DB_PATH = join(ROOT, 'data', 'otivm.sqlite3')
|
||||
const SCHEMA_PATH = join(ROOT, 'data', 'create_player_db.sql')
|
||||
|
||||
await mkdir(SAVES_DIR, { recursive: true })
|
||||
@@ -36,10 +42,10 @@ const stmtEpoch = db.prepare(
|
||||
const stmtH7 = db.prepare(`
|
||||
SELECT
|
||||
h7,
|
||||
AVG(lat) AS lat,
|
||||
AVG(lon) AS lon,
|
||||
SUM(CASE WHEN elev_cm > ? THEN 1 ELSE 0 END) AS h7_land,
|
||||
COUNT(*) AS h9_total
|
||||
AVG(lat) AS lat,
|
||||
AVG(lon) AS lon,
|
||||
SUM(CASE WHEN elev_cm > ? THEN 1 ELSE 0 END) AS h7_land,
|
||||
COUNT(*) AS h9_total
|
||||
FROM tessera_cells
|
||||
WHERE h5 = ? AND status = 2
|
||||
GROUP BY h7
|
||||
@@ -296,6 +302,13 @@ function autToInt(band) {
|
||||
// Writes parameter changes as new actor_parameters rows (append-only).
|
||||
// Appends new events to the events table.
|
||||
// Marks superseded parameter rows.
|
||||
//
|
||||
// On new player creation (no actor_profile row yet):
|
||||
// - Uses background_id from the request body (sent by frontend after
|
||||
// player chooses on the Prologue tab).
|
||||
// - Seeds actor_parameters from background_starting_values for that background.
|
||||
// - Sets liquiditas to the background's starting_den value from the body.
|
||||
// - Falls back to 'unknown' only if no background_id is present (legacy saves).
|
||||
|
||||
function writePlayerState(token, pdb, body) {
|
||||
const now = new Date().toISOString()
|
||||
@@ -307,29 +320,57 @@ function writePlayerState(token, pdb, body) {
|
||||
).get(actorId)
|
||||
|
||||
if (!profile) {
|
||||
// New player — use the background_id sent by the frontend.
|
||||
// The Prologue tab ensures this is a canonical identifier before sending.
|
||||
const backgroundId = body.background_id || 'unknown'
|
||||
const actorName = body.actor_name || 'Mercator'
|
||||
|
||||
pdb.prepare(`
|
||||
INSERT OR IGNORE INTO actor_profile
|
||||
(actor_id, session_id, background_id, actor_name, epoch, schema_version, recorded_at)
|
||||
VALUES (?, ?, ?, ?, 'roman_14bce', 3, ?)
|
||||
`).run(
|
||||
actorId,
|
||||
actorId,
|
||||
body.background_id || 'unknown',
|
||||
body.actor_name || 'Mercator',
|
||||
now
|
||||
)
|
||||
// Seed parameters from background_starting_values
|
||||
VALUES (?, ?, ?, ?, 'roman_14bce', 4, ?)
|
||||
`).run(actorId, actorId, backgroundId, actorName, now)
|
||||
|
||||
// Seed all parameters from background_starting_values for chosen background.
|
||||
// auctoritas gets value_social seeded from the same row's value_true.
|
||||
pdb.prepare(`
|
||||
INSERT OR IGNORE INTO actor_parameters
|
||||
(actor_id, parameter_token, scope, layer,
|
||||
value_true, value_perceived, confidence_tag, observable_level,
|
||||
drift_source, recorded_at)
|
||||
SELECT ?, parameter_token, 'actor', 'roman',
|
||||
value_true, value_perceived, confidence_tag, observable_level,
|
||||
'initial', ?
|
||||
value_true, value_perceived, value_social,
|
||||
confidence_tag, observable_level, drift_source, recorded_at)
|
||||
SELECT
|
||||
?, parameter_token, 'actor',
|
||||
CASE WHEN parameter_token IN ('auctoritas','clientela','liquiditas','fama',
|
||||
'disciplina','mercatus_scientia','itineris_scientia','ius_accessus',
|
||||
'periculum_tolerantia','negotiatio','litterae','officia_burden')
|
||||
THEN 'roman' ELSE 'universal' END,
|
||||
value_true, value_perceived,
|
||||
CASE WHEN parameter_token = 'auctoritas' THEN value_true ELSE NULL END,
|
||||
confidence_tag, observable_level, 'initial', ?
|
||||
FROM background_starting_values
|
||||
WHERE background_id = ?
|
||||
`).run(actorId, now, body.background_id || 'unknown')
|
||||
`).run(actorId, now, backgroundId)
|
||||
|
||||
// Override liquiditas with the den value from the body (which was set
|
||||
// from BACKGROUNDS[x].starting_den on the frontend). This is the
|
||||
// authoritative starting value — the seed row is superseded immediately.
|
||||
if (body.den !== undefined) {
|
||||
// Supersede the seed row
|
||||
pdb.prepare(`
|
||||
UPDATE actor_parameters
|
||||
SET superseded_at = ?
|
||||
WHERE actor_id = ? AND parameter_token = 'liquiditas' AND superseded_at IS NULL
|
||||
`).run(now, actorId)
|
||||
// Insert the confirmed starting value
|
||||
pdb.prepare(`
|
||||
INSERT INTO actor_parameters
|
||||
(actor_id, parameter_token, scope, layer,
|
||||
value_true, value_perceived,
|
||||
confidence_tag, observable_level, drift_source, recorded_at)
|
||||
VALUES (?, 'liquiditas', 'actor', 'roman',
|
||||
?, ?, 'measured', 'full', 'initial', ?)
|
||||
`).run(actorId, String(body.den), String(body.den), now)
|
||||
}
|
||||
}
|
||||
|
||||
// Update liquiditas if den changed
|
||||
@@ -540,7 +581,7 @@ fastify.setNotFoundHandler((req, reply) => {
|
||||
|
||||
try {
|
||||
await fastify.listen({ port: 3000, host: '0.0.0.0' })
|
||||
console.log('OTIVM server running on port 3000 — OTIVM-III')
|
||||
console.log('OTIVM server running on port 3000 — OTIVM-IV')
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
|
||||
Reference in New Issue
Block a user