feat(simulation): SQLite settings storage with IPC protocol v20 (#627)

Per-player settings via rusqlite (bundled, zero runtime dep). Server
owns the settings DB; client sends ChangeSettings commands over IPC.
Extensible key-value with typed columns (String/Int/Float/Bool).
Protocol bumped to v20 with settings_response in ObserverSnapshot.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 09:11:53 +01:00
co-authored by Claude Opus 4.6
parent 1a4fd578cc
commit accbe579c9
24 changed files with 776 additions and 4 deletions
+4 -1
View File
@@ -41,6 +41,7 @@ fn test_snapshot(tick: u64, entities: Vec<VisibleEntity>) -> ObserverSnapshot {
debug_response: None,
sim_errors: vec![],
current_ticker: None,
settings_response: None,
}
}
@@ -304,6 +305,7 @@ fn snapshot_v2_fields_roundtrip() {
debug_response: None,
sim_errors: vec![],
current_ticker: None,
settings_response: None,
};
let bytes = rmp_serde::to_vec_named(&snapshot).expect("serialize");
@@ -358,7 +360,7 @@ fn protocol_version_constant_matches_snapshot() {
let snapshot = test_snapshot(0, vec![]);
assert_eq!(snapshot.version, PROTOCOL_VERSION);
assert_eq!(
PROTOCOL_VERSION, 19,
PROTOCOL_VERSION, 20,
"bump this assertion when protocol version changes"
);
}
@@ -413,6 +415,7 @@ fn all_facing_direction_variants_roundtrip() {
debug_response: None,
sim_errors: vec![],
current_ticker: None,
settings_response: None,
};
let bytes = rmp_serde::to_vec_named(&snapshot).expect("serialize");
let decoded: ObserverSnapshot = rmp_serde::from_slice(&bytes).expect("deserialize");