Resume interrupted editor co-op runs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f87b59390e
commit
c7c3e979d6
24 files changed
+145
-6
No files matched your search
+29
-2
@@ -9,6 +9,8 @@
|
||||
// {"t":"create","sides":[0,2,3,4]?,"map_w":96?,"map_h":128?,"difficulty":1?,"mission":12?,"doc":{..}?}
|
||||
// -> "doc": an editor campaign (CampaignDoc JSON) for a co-op
|
||||
// match of its mission "mission"; it goes along with "start"
|
||||
// "seed":77?,"carry":[..]? with a doc: an interrupted run goes
|
||||
// on - "start" then has this seed, the carry and "resume":true
|
||||
// {"t":"join","code":"ABC123"}
|
||||
// {"t":"take_side","side":2}
|
||||
// {"t":"ready","ready":true}
|
||||
@@ -85,6 +87,7 @@ struct Room {
|
||||
difficulty: u8,
|
||||
mission: Option<usize>,
|
||||
doc: Option<Value>, // editor campaign of a co-op match (sent to every client at the start)
|
||||
resume: Option<(u32, Value)>, // a resumed editor campaign run: its seed and what the masters carry
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -358,6 +361,10 @@ impl Netplay {
|
||||
let difficulty = msg.get("difficulty").and_then(|v| v.as_u64()).unwrap_or(1).clamp(0, 2) as u8;
|
||||
let mission = mission_of(msg.get("mission"));
|
||||
let doc = msg.get("doc").filter(|d| !d.is_null()).cloned();
|
||||
let resume = match (&doc, msg.get("seed").and_then(|v| v.as_u64())) {
|
||||
(Some(_), Some(seed)) => Some((seed as u32, msg.get("carry").filter(|c| c.is_array()).cloned().unwrap_or_else(|| json!([])))),
|
||||
_ => None,
|
||||
};
|
||||
match &doc {
|
||||
Some(d) => {
|
||||
let count = d.get("missions").and_then(|m| m.as_array()).map_or(0, |m| m.len());
|
||||
@@ -375,7 +382,7 @@ impl Netplay {
|
||||
}
|
||||
let name = self.clients.get(&conn).map(|c| c.name.clone()).unwrap_or_else(|| "Guest".into());
|
||||
let seats = sides.iter().map(|s| (*s, new_seat(*s, false))).collect::<HashMap<_, _>>();
|
||||
let room = Room { code: code.clone(), sides, seats, pending: HashMap::new(), turn: 0, started: false, paused: false, missing: false, seed: None, map_w, map_h, difficulty, mission, doc };
|
||||
let room = Room { code: code.clone(), sides, seats, pending: HashMap::new(), turn: 0, started: false, paused: false, missing: false, seed: None, map_w, map_h, difficulty, mission, doc, resume };
|
||||
self.rooms.insert(code.clone(), room);
|
||||
if let Some(c) = self.clients.get_mut(&conn) {
|
||||
c.room = Some(code.clone());
|
||||
@@ -630,7 +637,7 @@ impl Netplay {
|
||||
r.started = true;
|
||||
r.paused = false;
|
||||
r.missing = false;
|
||||
r.seed = Some(random_seed());
|
||||
r.seed = Some(r.resume.as_ref().map_or_else(random_seed, |x| x.0));
|
||||
r.turn = 0;
|
||||
r.sides = active;
|
||||
}
|
||||
@@ -640,6 +647,10 @@ impl Netplay {
|
||||
if let Some(doc) = &r.doc {
|
||||
m["doc"] = doc.clone();
|
||||
}
|
||||
if let Some((_, carry)) = &r.resume {
|
||||
m["carry"] = carry.clone();
|
||||
m["resume"] = json!(true);
|
||||
}
|
||||
m
|
||||
}
|
||||
None => return,
|
||||
@@ -971,6 +982,22 @@ mod tests {
|
||||
assert_eq!(start_red["mission"].as_u64(), Some(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_resumed_run_starts_with_its_seed_and_carry() {
|
||||
let mut net = Netplay::new();
|
||||
let (tx, mut rx) = mpsc::unbounded_channel();
|
||||
let red = net.connect(tx, Some("red".into()), None);
|
||||
let doc = json!({"format":"dungeoncraft-campaign","name":"Mine","missions":[{"key":"a","title":"First"},{"key":"b","title":"Second","size":[96,96]}]});
|
||||
let carry = json!([[0, {"gold": 100.0, "creatures": []}]]);
|
||||
net.handle(red, json!({"t":"create","sides":[0,2],"mission":1,"doc":doc,"seed":4242,"carry":carry}));
|
||||
net.handle(red, json!({"t":"ready"}));
|
||||
net.handle(red, json!({"t":"start"}));
|
||||
let start = until(&mut rx, "start");
|
||||
assert_eq!(start["seed"].as_u64(), Some(4242));
|
||||
assert_eq!(start["carry"], carry);
|
||||
assert_eq!(start["resume"].as_bool(), Some(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_editor_campaign_goes_from_the_create_to_every_start() {
|
||||
let mut net = Netplay::new();
|
||||
|
||||
Reference in new issue
Block a user