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.
|
// Per-player SQLite integration.
|
||||||
// TESSERA world database (data/otivm.sqlite3) — read-only, unchanged.
|
// TESSERA world database (data/otivm.sqlite3) — read-only, unchanged.
|
||||||
// Player databases (data/saves/{token}.sqlite3) — one per player,
|
// Player databases (data/saves/{token}.sqlite3) — one per player,
|
||||||
@@ -7,6 +7,12 @@
|
|||||||
// JSON save files (data/saves/{token}.json) — never deleted, migrated
|
// JSON save files (data/saves/{token}.json) — never deleted, migrated
|
||||||
// transparently on first SQLite access if present.
|
// transparently on first SQLite access if present.
|
||||||
// Frontend interface unchanged — GET/POST /api/save/:token same as before.
|
// 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 Fastify from 'fastify'
|
||||||
import fastifyStatic from '@fastify/static'
|
import fastifyStatic from '@fastify/static'
|
||||||
@@ -17,10 +23,10 @@ import { existsSync } from 'fs'
|
|||||||
import Database from 'better-sqlite3'
|
import Database from 'better-sqlite3'
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||||
const ROOT = join(__dirname, '..')
|
const ROOT = join(__dirname, '..')
|
||||||
const DIST = join(ROOT, 'dist')
|
const DIST = join(ROOT, 'dist')
|
||||||
const SAVES_DIR = join(ROOT, 'data', 'saves')
|
const SAVES_DIR = join(ROOT, 'data', 'saves')
|
||||||
const DB_PATH = join(ROOT, 'data', 'otivm.sqlite3')
|
const DB_PATH = join(ROOT, 'data', 'otivm.sqlite3')
|
||||||
const SCHEMA_PATH = join(ROOT, 'data', 'create_player_db.sql')
|
const SCHEMA_PATH = join(ROOT, 'data', 'create_player_db.sql')
|
||||||
|
|
||||||
await mkdir(SAVES_DIR, { recursive: true })
|
await mkdir(SAVES_DIR, { recursive: true })
|
||||||
@@ -36,10 +42,10 @@ const stmtEpoch = db.prepare(
|
|||||||
const stmtH7 = db.prepare(`
|
const stmtH7 = db.prepare(`
|
||||||
SELECT
|
SELECT
|
||||||
h7,
|
h7,
|
||||||
AVG(lat) AS lat,
|
AVG(lat) AS lat,
|
||||||
AVG(lon) AS lon,
|
AVG(lon) AS lon,
|
||||||
SUM(CASE WHEN elev_cm > ? THEN 1 ELSE 0 END) AS h7_land,
|
SUM(CASE WHEN elev_cm > ? THEN 1 ELSE 0 END) AS h7_land,
|
||||||
COUNT(*) AS h9_total
|
COUNT(*) AS h9_total
|
||||||
FROM tessera_cells
|
FROM tessera_cells
|
||||||
WHERE h5 = ? AND status = 2
|
WHERE h5 = ? AND status = 2
|
||||||
GROUP BY h7
|
GROUP BY h7
|
||||||
@@ -296,6 +302,13 @@ function autToInt(band) {
|
|||||||
// Writes parameter changes as new actor_parameters rows (append-only).
|
// Writes parameter changes as new actor_parameters rows (append-only).
|
||||||
// Appends new events to the events table.
|
// Appends new events to the events table.
|
||||||
// Marks superseded parameter rows.
|
// 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) {
|
function writePlayerState(token, pdb, body) {
|
||||||
const now = new Date().toISOString()
|
const now = new Date().toISOString()
|
||||||
@@ -307,29 +320,57 @@ function writePlayerState(token, pdb, body) {
|
|||||||
).get(actorId)
|
).get(actorId)
|
||||||
|
|
||||||
if (!profile) {
|
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(`
|
pdb.prepare(`
|
||||||
INSERT OR IGNORE INTO actor_profile
|
INSERT OR IGNORE INTO actor_profile
|
||||||
(actor_id, session_id, background_id, actor_name, epoch, schema_version, recorded_at)
|
(actor_id, session_id, background_id, actor_name, epoch, schema_version, recorded_at)
|
||||||
VALUES (?, ?, ?, ?, 'roman_14bce', 3, ?)
|
VALUES (?, ?, ?, ?, 'roman_14bce', 4, ?)
|
||||||
`).run(
|
`).run(actorId, actorId, backgroundId, actorName, now)
|
||||||
actorId,
|
|
||||||
actorId,
|
// Seed all parameters from background_starting_values for chosen background.
|
||||||
body.background_id || 'unknown',
|
// auctoritas gets value_social seeded from the same row's value_true.
|
||||||
body.actor_name || 'Mercator',
|
|
||||||
now
|
|
||||||
)
|
|
||||||
// Seed parameters from background_starting_values
|
|
||||||
pdb.prepare(`
|
pdb.prepare(`
|
||||||
INSERT OR IGNORE INTO actor_parameters
|
INSERT OR IGNORE INTO actor_parameters
|
||||||
(actor_id, parameter_token, scope, layer,
|
(actor_id, parameter_token, scope, layer,
|
||||||
value_true, value_perceived, confidence_tag, observable_level,
|
value_true, value_perceived, value_social,
|
||||||
drift_source, recorded_at)
|
confidence_tag, observable_level, drift_source, recorded_at)
|
||||||
SELECT ?, parameter_token, 'actor', 'roman',
|
SELECT
|
||||||
value_true, value_perceived, confidence_tag, observable_level,
|
?, parameter_token, 'actor',
|
||||||
'initial', ?
|
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
|
FROM background_starting_values
|
||||||
WHERE background_id = ?
|
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
|
// Update liquiditas if den changed
|
||||||
@@ -540,7 +581,7 @@ fastify.setNotFoundHandler((req, reply) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await fastify.listen({ port: 3000, host: '0.0.0.0' })
|
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) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
|
|||||||
Reference in New Issue
Block a user