Manual AI seats for matches: host toggles empty seats, co-op allies fight heroes
This commit is contained in:
1 parent
3492eacd59
commit
ee7b76fa6a
10 files changed
+308
-43
No files matched your search
+49
-2
@@ -29,6 +29,7 @@ pub struct SeatUi {
|
||||
pub name: String,
|
||||
pub ready: bool,
|
||||
pub connected: bool,
|
||||
pub ai: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
@@ -51,6 +52,7 @@ pub struct MatchUi {
|
||||
pub is_host: bool,
|
||||
pub sides: Vec<u8>,
|
||||
pub seats: Vec<SeatUi>,
|
||||
pub ai: Vec<u8>,
|
||||
pub rooms: Vec<RoomUi>,
|
||||
pub started: bool,
|
||||
pub paused: bool,
|
||||
@@ -76,6 +78,7 @@ pub struct StartInfo {
|
||||
pub sides: Vec<u8>,
|
||||
pub local_side: Option<u8>,
|
||||
pub mission: Option<usize>,
|
||||
pub ai: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
@@ -84,6 +87,7 @@ struct SeatInfo {
|
||||
name: String,
|
||||
ready: bool,
|
||||
connected: bool,
|
||||
ai: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
@@ -211,6 +215,13 @@ impl MatchClient {
|
||||
self.outbox.push_back(json!({"t":"take_side","side":side}).to_string());
|
||||
}
|
||||
|
||||
pub fn set_ai(&mut self, side: u8, ai: bool) {
|
||||
if !self.connected {
|
||||
return;
|
||||
}
|
||||
self.outbox.push_back(json!({"t":"set_ai","side":side,"ai":ai}).to_string());
|
||||
}
|
||||
|
||||
pub fn ready(&mut self, ready: bool) {
|
||||
if !self.connected {
|
||||
return;
|
||||
@@ -394,6 +405,12 @@ impl MatchClient {
|
||||
let difficulty = v.get("difficulty").and_then(|x| x.as_u64()).unwrap_or(1) as u8;
|
||||
let sides = array_bytes(v.get("sides"));
|
||||
let mission = v.get("mission").and_then(|x| x.as_u64()).map(|x| x as usize);
|
||||
let mut ai = array_bytes(v.get("ai"));
|
||||
if ai.is_empty() {
|
||||
if let Some(r) = self.room.as_ref() {
|
||||
ai = r.ai.clone();
|
||||
}
|
||||
}
|
||||
let local_side = self.room.as_ref().and_then(|r| r.seats.iter().find(|s| s.name == self.name && s.connected).map(|s| s.side));
|
||||
self.local_side = local_side;
|
||||
if let Some(r) = self.room.as_mut() {
|
||||
@@ -404,8 +421,9 @@ impl MatchClient {
|
||||
if !sides.is_empty() {
|
||||
r.sides = sides.clone();
|
||||
}
|
||||
r.ai = ai.clone();
|
||||
}
|
||||
self.start = Some(StartInfo { seed, map_w, map_h, difficulty, sides, local_side, mission });
|
||||
self.start = Some(StartInfo { seed, map_w, map_h, difficulty, sides, local_side, mission, ai });
|
||||
self.error = None;
|
||||
self.status = None;
|
||||
}
|
||||
@@ -449,7 +467,8 @@ impl MatchClient {
|
||||
ready,
|
||||
is_host,
|
||||
sides: room.sides.clone(),
|
||||
seats: room.seats.iter().map(|s| SeatUi { side: s.side, name: s.name.clone(), ready: s.ready, connected: s.connected }).collect(),
|
||||
ai: room.ai.clone(),
|
||||
seats: room.seats.iter().map(|s| SeatUi { side: s.side, name: s.name.clone(), ready: s.ready, connected: s.connected, ai: s.ai }).collect(),
|
||||
rooms: self.rooms.clone(),
|
||||
started: room.started,
|
||||
paused: room.paused,
|
||||
@@ -477,6 +496,7 @@ fn seats_from(v: Option<&Value>) -> Vec<SeatInfo> {
|
||||
name: s.get("name").and_then(|x| x.as_str()).unwrap_or("").to_string(),
|
||||
ready: s.get("ready").and_then(|x| x.as_bool()).unwrap_or(false),
|
||||
connected: s.get("connected").and_then(|x| x.as_bool()).unwrap_or(false),
|
||||
ai: s.get("ai").and_then(|x| x.as_bool()).unwrap_or(false),
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
@@ -542,4 +562,31 @@ mod tests {
|
||||
let chat = client.take_new_chat();
|
||||
assert_eq!(chat[0], (Some(0), "red".to_string(), "hello".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_bridge_holds_ai_seats_through_the_lobby() {
|
||||
let mut client = MatchClient::new();
|
||||
client.on_connect("red");
|
||||
pop(&mut client); // rooms
|
||||
|
||||
client.create(&[0, 2, 3, 4], 96, 128, 1);
|
||||
pop(&mut client); // create
|
||||
|
||||
client.set_ai(3, true);
|
||||
let req = pop(&mut client);
|
||||
assert_eq!(req["t"].as_str(), Some("set_ai"));
|
||||
assert_eq!(req["side"].as_u64(), Some(3));
|
||||
assert_eq!(req["ai"].as_bool(), Some(true));
|
||||
|
||||
client.feed(r#"{"t":"room","code":"ABC123","sides":[0,2,3,4],"seats":[{"side":0,"name":"red","ready":false,"connected":true,"ai":false},{"side":2,"name":"","ready":false,"connected":false,"ai":false},{"side":3,"name":"","ready":false,"connected":false,"ai":true},{"side":4,"name":"","ready":false,"connected":false,"ai":false}],"ai":[3],"turn":0,"started":false,"paused":false,"missing":false}"#);
|
||||
let ui = client.ui();
|
||||
assert_eq!(ui.ai, vec![3u8]);
|
||||
assert!(ui.seats.iter().any(|s| s.side == 3 && s.ai));
|
||||
assert!(ui.seats.iter().any(|s| s.side == 2 && !s.connected && !s.ai));
|
||||
|
||||
client.feed(r#"{"t":"start","seed":7,"map_w":96,"map_h":128,"difficulty":1,"sides":[0,3],"ai":[3]}"#);
|
||||
let start = client.take_start().expect("start info with ai seats");
|
||||
assert_eq!(start.sides, vec![0u8, 3u8]);
|
||||
assert_eq!(start.ai, vec![3u8]);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user