Update joining and session lists.

This commit is contained in:
yukirij 2024-08-16 23:42:43 -07:00
parent 0f682a21be
commit ac3d01b0d7
9 changed files with 104 additions and 51 deletions

View File

@ -7,17 +7,9 @@ use crate::{
pub type Pool = [u8; 7];
#[derive(Clone, Copy, PartialEq)]
pub enum GameState {
None,
Joinable,
Ongoing,
Complete,
}
pub struct Game {
pub complete:bool,
pub turn:u16,
pub state:GameState,
pub board:Board,
pub pool:[Pool; 2],
@ -27,7 +19,7 @@ impl Game {
pub fn new() -> Self
{
Self {
state:GameState::Joinable,
complete:false,
turn:0,

View File

@ -3,6 +3,7 @@ use game::Game;
pub type SessionToken = [u8; 8];
pub type SessionSecret = [u8; 8];
#[derive(Clone)]
pub struct Player {
pub user:Option<u32>,
pub connections:Vec<u32>,
@ -23,13 +24,19 @@ pub struct Session {
pub chain_id:usize,
}
impl Session {
pub fn get_connections(&self) -> Vec<u32>
pub fn get_connections(&self) -> Vec<(u32, u8)>
{
[
self.p_dawn.connections.clone(),
self.p_dusk.connections.clone(),
self.connections.clone(),
].concat()
let mut result = Vec::new();
for conn in &self.p_dawn.connections {
result.push((*conn, 0));
}
for conn in &self.p_dusk.connections {
result.push((*conn, 1));
}
for conn in &self.connections {
result.push((*conn, 2));
}
result
}
pub fn add_connection(&mut self, source:u8, id:u32)

View File

@ -261,8 +261,6 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
}
QRPacketData::QSessionList(request) => {
use game::game::GameState;
println!("Request: Session List");
let mut response = PacketSessionListResponse::new();
@ -280,8 +278,12 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
// - IsPlayer must have the current user in either player slot.
// - IsLive must have both users connected to the session.
let mut valid = request.game_state == GameState::None || request.game_state == session.game.state;
valid &= request.game_state != GameState::Joinable || session.p_dawn.user.is_none() || session.p_dusk.user.is_none();
let mut valid = match request.game_state {
1 => session.p_dawn.user.is_none() || session.p_dusk.user.is_none(),
2 => session.p_dawn.user.is_some() && session.p_dusk.user.is_some(),
3 => session.game.complete,
_ => true,
};
valid &= !request.is_player || session.p_dawn.user == user_id || session.p_dusk.user == user_id;
valid &= !request.is_live || (session.p_dawn.connections.len() > 0 && session.p_dusk.connections.len() > 0);
@ -402,14 +404,19 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
// User must not already be player
if session.p_dawn.user != user_id && session.p_dusk.user != user_id {
// Add user to empty player slot
if if session.p_dawn.user.is_none() {
session.p_dawn.user = Some(uid);
response.mode = 0;
true
} else if session.p_dusk.user.is_none() {
session.p_dusk.user = Some(uid);
response.mode = 1;
// Add user to session and randomize seats.
if if session.p_dusk.user.is_none() {
let mut r = [0u8; 1];
rng.fill(&mut r).ok();
if (r[0] & 1) == 0 {
session.p_dusk = session.p_dawn.clone();
session.p_dawn.user = Some(uid);
session.p_dawn.connections.clear();
response.mode = 0;
} else {
session.p_dusk.user = Some(uid);
response.mode = 1;
}
true
} else {
// Session is not empty
@ -458,12 +465,11 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
let mut packets = Vec::new();
let game_state = generate_gamestate(&app, session);
for cid in &session.get_connections() {
if *cid != qr.id {
packets.push(QRPacket::new(
*cid,
QRPacketData::RGameState(game_state.clone()),
));
for (cid, player) in session.get_connections() {
if cid != qr.id {
let mut gs = game_state.clone();
gs.player = player;
packets.push(QRPacket::new(cid, QRPacketData::RGameState(gs)));
}
}
for packet in packets {
@ -509,6 +515,11 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
if let Some(session) = app.sessions.get(&request.token) {
response = generate_gamestate(&app, &session);
if user_id.is_some() {
if user_id == session.p_dawn.user { response.player = 0; }
else if user_id == session.p_dusk.user { response.player = 1; }
}
} else {
response.status = STATUS_ERROR;
}
@ -540,9 +551,9 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
app.filesystem.session_history_push(session.id, request.play).ok();
// Forward play to all clients
for cid in &session.get_connections() {
for (cid, _) in session.get_connections() {
packets.push(QRPacket::new(
*cid,
cid,
QRPacketData::QGamePlay(request.clone())
));
}
@ -583,6 +594,8 @@ fn generate_gamestate(app:&App, session:&Session) -> protocol::PacketGameStateRe
use protocol::{PacketGameStateResponse, PacketGameStateResponsePiece};
let mut response = PacketGameStateResponse::new();
response.player = 2;
response.turn = session.game.turn;
// Get Dawn handle

View File

@ -64,6 +64,7 @@ impl PacketGameStateResponsePiece {
pub struct PacketGameStateResponse {
pub status:u16,
pub turn:u16,
pub player:u8,
pub dawn_handle:String,
pub dusk_handle:String,
pub dawn_pool:Pool,
@ -76,6 +77,7 @@ impl PacketGameStateResponse {
Self {
status:0,
turn:0,
player:0,
dawn_handle:String::new(),
dusk_handle:String::new(),
dawn_pool:Pool::default(),
@ -89,6 +91,9 @@ impl Packet for PacketGameStateResponse {
fn encode(&self) -> Vec<u8>
{
let mut flags = 0u16;
flags |= self.player as u16;
let mut piece_bytes = Vec::new();
for piece in &self.pieces {
let piece_data: u16 = piece.valid as u16
@ -118,6 +123,7 @@ impl Packet for PacketGameStateResponse {
[
pack_u16(self.status),
pack_u16(flags),
pack_u16(self.turn),
pack_u16(self.dawn_handle.len() as u16),
self.dawn_handle.as_bytes().to_vec(),

View File

@ -2,17 +2,14 @@ use crate::{
app::session::SessionToken,
util::pack::{pack_u16, pack_u32, unpack_u16},
};
use game::{
game::GameState,
util::mask,
};
use game::util::mask;
use super::Packet;
#[derive(Clone)]
pub struct PacketSessionList {
pub page:u16,
pub game_state:GameState,
pub game_state:u8,
pub is_player:bool,
pub is_live:bool,
}
@ -21,7 +18,7 @@ impl PacketSessionList {
{
Self {
page:0,
game_state:GameState::Joinable,
game_state:0,
is_player:false,
is_live:false,
}
@ -41,12 +38,7 @@ impl Packet for PacketSessionList {
*/
if data.len() - *index == 4 {
let flags = unpack_u16(data, index);
result.game_state = match flags & mask(2, 0) as u16 {
1 => GameState::Joinable,
2 => GameState::Ongoing,
3 => GameState::Complete,
_ => GameState::None,
};
result.game_state = (flags & mask(2, 0) as u16) as u8;
result.is_player = (flags & mask(1, 2) as u16) != 0;
result.is_live = (flags & mask(1, 3) as u16) != 0;

View File

@ -717,6 +717,8 @@ const INTERFACE = {
message(code, data) {
switch(code) {
case OpCode.GameState: {
console.log(data.player);
INTERFACE_DATA.player = data.player;
GAME_DATA.turn = data.turn;
if(data.dawn.length > 0) { INTERFACE_DATA.handles[0] = data.dawn; }

View File

@ -207,7 +207,7 @@ const SCENES = {
return true;
},
refresh() {
MESSAGE_SESSION_LIST(0, 0, false, false);
MESSAGE_SESSION_LIST(0, 2, false, false);
},
message(code, data) {
switch(code) {
@ -266,7 +266,7 @@ const SCENES = {
return true;
},
refresh() {
MESSAGE_SESSION_LIST(0, 0, true, false);
MESSAGE_SESSION_LIST(0, 2, true, false);
},
message(code, data) {
switch(code) {
@ -334,7 +334,7 @@ const SCENES = {
UI.clear(table);
if(data !== null) {
table.appendChild(UI.session_table(data.records));
table.appendChild(UI.session_table_join(data.records));
}
} break;
case OpCode.SessionCreate:

View File

@ -205,6 +205,7 @@ function MESSAGE(event) {
//if(bytes.length - index >= 22) {
data = {
status:0,
player:2,
turn:0,
dawn:"",
dusk:"",
@ -218,6 +219,13 @@ function MESSAGE(event) {
index = result.index;
data.status = result.data;
// Flags
result = UNPACK.u16(bytes, index);
index = result.index;
let flags = result.data;
data.player = flags & 0x3;
// Turn
result = UNPACK.u16(bytes, index);
index = result.index;

View File

@ -185,6 +185,39 @@ const UI = {
return tbody;
},
session_table_join(records) {
let rows = [ ];
for(let r = 0; r < records.length; ++r) {
let buttons = [ ];
let join_callback = function() {
MESSAGE_SESSION_JOIN(this.token, true);
};
join_callback = join_callback.bind({token: records[r].token});
if(records[r].player) {
buttons.push(UI.button("View", join_callback));
} else {
buttons.push(UI.button("Join", join_callback));
}
let host = UI.text(records[r].dawn);
if(records[r].dawn == "") { dawn = UI.span([UI.text("Vacant")], "text-system"); }
rows.push([
host,
buttons,
]);
}
let tbody = UI.table_content(
[ "Host", "" ],
rows,
);
return tbody;
},
clear(dom) {
while(dom.lastChild !== null) { dom.removeChild(document.body.lastChild); }
},