Merge spectate and history views; increase bot delay to 1 second.
This commit is contained in:
parent
d4d578a5a7
commit
762f2abab2
@ -202,12 +202,6 @@ impl App {
|
|||||||
)).await.ok();
|
)).await.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
QRPacketData::RGameHistory(response) => {
|
|
||||||
socket.send(Message::Binary(
|
|
||||||
encode_response(CODE_GAME_HISTORY, response.encode())
|
|
||||||
)).await.ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => { }
|
_ => { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,9 +380,6 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
|
|||||||
app.sessions.set(&token, session);
|
app.sessions.set(&token, session);
|
||||||
app.session_time.set(chain_id, token);
|
app.session_time.set(chain_id, token);
|
||||||
|
|
||||||
// Set player to Dawn.
|
|
||||||
response.mode = 0;
|
|
||||||
|
|
||||||
response.status = STATUS_OK;
|
response.status = STATUS_OK;
|
||||||
response.token = token;
|
response.token = token;
|
||||||
}
|
}
|
||||||
@ -419,10 +416,8 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
|
|||||||
session.p_dusk = session.p_dawn.clone();
|
session.p_dusk = session.p_dawn.clone();
|
||||||
session.p_dawn.user = Some(uid);
|
session.p_dawn.user = Some(uid);
|
||||||
session.p_dawn.connections.clear();
|
session.p_dawn.connections.clear();
|
||||||
response.mode = 0;
|
|
||||||
} else {
|
} else {
|
||||||
session.p_dusk.user = Some(uid);
|
session.p_dusk.user = Some(uid);
|
||||||
response.mode = 1;
|
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
@ -444,7 +439,6 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
|
|||||||
else {
|
else {
|
||||||
println!("User resumes session.");
|
println!("User resumes session.");
|
||||||
response.status = STATUS_OK;
|
response.status = STATUS_OK;
|
||||||
response.mode = (session.p_dusk.user == user_id) as u8;
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
} else { response.status = STATUS_NOAUTH; false }
|
} else { response.status = STATUS_NOAUTH; false }
|
||||||
@ -455,14 +449,20 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
|
|||||||
println!("User spectates session.");
|
println!("User spectates session.");
|
||||||
|
|
||||||
response.status = STATUS_OK;
|
response.status = STATUS_OK;
|
||||||
response.mode = 2;
|
|
||||||
true
|
true
|
||||||
} {
|
} {
|
||||||
// Associate session and connection on join
|
// Associate session and connection on join
|
||||||
if let Some(conn) = app.connections.get_mut(qr.id as usize) {
|
if let Some(conn) = app.connections.get_mut(qr.id as usize) {
|
||||||
conn.session = Some(session.token);
|
conn.session = Some(session.token);
|
||||||
}
|
}
|
||||||
session.add_connection(response.mode, qr.id);
|
let mode = if user_id == session.p_dawn.user {
|
||||||
|
0
|
||||||
|
} else if user_id == session.p_dusk.user {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
2
|
||||||
|
};
|
||||||
|
session.add_connection(mode, qr.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,21 +618,6 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QRPacketData::QGameHistory(request) => {
|
|
||||||
let mut response = PacketGameHistoryResponse::new();
|
|
||||||
|
|
||||||
println!("Request: Game History");
|
|
||||||
|
|
||||||
if let Some(session) = app.sessions.get(&request.token) {
|
|
||||||
response.status = STATUS_OK;
|
|
||||||
response = generate_game_history(&app, &session);
|
|
||||||
} else {
|
|
||||||
response.status = STATUS_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(QRPacket::new(qr.id, QRPacketData::RGameHistory(response)))
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => { Some(QRPacket::new(0, QRPacketData::None)) }
|
_ => { Some(QRPacket::new(0, QRPacketData::None)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -644,60 +629,13 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
|
|||||||
|
|
||||||
fn generate_game_state(app:&App, session:&Session) -> protocol::PacketGameStateResponse
|
fn generate_game_state(app:&App, session:&Session) -> protocol::PacketGameStateResponse
|
||||||
{
|
{
|
||||||
use protocol::{PacketGameStateResponse, PacketGameStateResponsePiece};
|
use protocol::PacketGameStateResponse;
|
||||||
|
|
||||||
let mut response = PacketGameStateResponse::new();
|
let mut response = PacketGameStateResponse::new();
|
||||||
|
|
||||||
response.player = 2;
|
|
||||||
response.turn = session.game.turn;
|
|
||||||
if session.game.history.len() > 0 {
|
|
||||||
response.play = session.game.history[session.game.history.len() - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Dawn handle
|
|
||||||
if let Some(id) = session.p_dawn.user {
|
|
||||||
if let Some(user) = app.get_user_by_id(id) {
|
|
||||||
response.dawn_handle = user.handle.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Dusk handle
|
|
||||||
if let Some(id) = session.p_dusk.user {
|
|
||||||
if let Some(user) = app.get_user_by_id(id) {
|
|
||||||
response.dusk_handle = user.handle.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get pool sizes
|
|
||||||
response.dawn_pool = session.game.pool[0];
|
|
||||||
response.dusk_pool = session.game.pool[1];
|
|
||||||
|
|
||||||
// Get list of pieces
|
|
||||||
for i in 0..session.game.board.pieces.len() {
|
|
||||||
response.pieces[i] = if let Some(piece) = &session.game.board.pieces[i] {
|
|
||||||
PacketGameStateResponsePiece {
|
|
||||||
valid:true,
|
|
||||||
piece:piece.class,
|
|
||||||
promoted:piece.promoted,
|
|
||||||
player:piece.player,
|
|
||||||
tile:piece.tile,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
PacketGameStateResponsePiece::new()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
response
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_game_history(app:&App, session:&Session) -> protocol::PacketGameHistoryResponse
|
|
||||||
{
|
|
||||||
use protocol::PacketGameHistoryResponse;
|
|
||||||
|
|
||||||
let mut response = PacketGameHistoryResponse::new();
|
|
||||||
|
|
||||||
response.token = session.token;
|
response.token = session.token;
|
||||||
|
response.player = 2;
|
||||||
|
|
||||||
// Get Dawn handle
|
// Get Dawn handle
|
||||||
if let Some(id) = session.p_dawn.user {
|
if let Some(id) = session.p_dawn.user {
|
||||||
if let Some(user) = app.get_user_by_id(id) {
|
if let Some(user) = app.get_user_by_id(id) {
|
||||||
@ -712,6 +650,7 @@ fn generate_game_history(app:&App, session:&Session) -> protocol::PacketGameHist
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get history
|
||||||
response.history = session.game.history.clone();
|
response.history = session.game.history.clone();
|
||||||
|
|
||||||
response
|
response
|
||||||
|
@ -161,20 +161,13 @@ pub async fn handle_ws(ws:WebSocketStream<TokioIo<Upgraded>>, args:HttpServiceAr
|
|||||||
Err(_) => { println!("error: packet decode failed."); }
|
Err(_) => { println!("error: packet decode failed."); }
|
||||||
}
|
}
|
||||||
|
|
||||||
CODE_GAME_HISTORY => match PacketGameHistory::decode(&data, &mut index) {
|
|
||||||
Ok(packet) => {
|
|
||||||
args.bus.send(
|
|
||||||
bus_ds,
|
|
||||||
QRPacket::new(conn_id, QRPacketData::QGameHistory(packet))
|
|
||||||
).ok();
|
|
||||||
}
|
|
||||||
Err(_) => { println!("error: packet decode failed."); }
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => { }
|
_ => { }
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Message::Close(_) => { true }
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
println!("notice: received unexpected websocket data.");
|
println!("notice: received unexpected websocket data.");
|
||||||
true
|
true
|
||||||
|
@ -31,4 +31,3 @@ pub const CODE_SESSION_LEAVE :u16 = 0x002F;
|
|||||||
|
|
||||||
pub const CODE_GAME_STATE :u16 = 0x0030;
|
pub const CODE_GAME_STATE :u16 = 0x0030;
|
||||||
pub const CODE_GAME_PLAY :u16 = 0x0031;
|
pub const CODE_GAME_PLAY :u16 = 0x0031;
|
||||||
pub const CODE_GAME_HISTORY :u16 = 0x0032;
|
|
||||||
|
@ -23,6 +23,9 @@ pub enum QRPacketData {
|
|||||||
|
|
||||||
QAuthRevoke,
|
QAuthRevoke,
|
||||||
|
|
||||||
|
QUserList(PacketUserList),
|
||||||
|
RUserList(PacketUserListResponse),
|
||||||
|
|
||||||
QSessionList(PacketSessionList),
|
QSessionList(PacketSessionList),
|
||||||
RSessionList(PacketSessionListResponse),
|
RSessionList(PacketSessionListResponse),
|
||||||
|
|
||||||
@ -40,9 +43,6 @@ pub enum QRPacketData {
|
|||||||
RGameState(PacketGameStateResponse),
|
RGameState(PacketGameStateResponse),
|
||||||
|
|
||||||
QGamePlay(PacketGamePlay),
|
QGamePlay(PacketGamePlay),
|
||||||
|
|
||||||
QGameHistory(PacketGameHistory),
|
|
||||||
RGameHistory(PacketGameHistoryResponse),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -42,6 +42,7 @@ impl Packet for PacketGameHistory {
|
|||||||
pub struct PacketGameHistoryResponse {
|
pub struct PacketGameHistoryResponse {
|
||||||
pub status:u16,
|
pub status:u16,
|
||||||
pub token:SessionToken,
|
pub token:SessionToken,
|
||||||
|
pub player:u8,
|
||||||
pub dawn_handle:String,
|
pub dawn_handle:String,
|
||||||
pub dusk_handle:String,
|
pub dusk_handle:String,
|
||||||
pub history:Vec<Play>,
|
pub history:Vec<Play>,
|
||||||
|
@ -3,7 +3,7 @@ use crate::{
|
|||||||
util::pack::pack_u16,
|
util::pack::pack_u16,
|
||||||
};
|
};
|
||||||
|
|
||||||
use game::{game::Pool, history::Play};
|
use game::history::Play;
|
||||||
|
|
||||||
use super::Packet;
|
use super::Packet;
|
||||||
|
|
||||||
@ -38,53 +38,25 @@ impl Packet for PacketGameState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub struct PacketGameStateResponsePiece {
|
|
||||||
pub valid:bool,
|
|
||||||
pub piece:u8,
|
|
||||||
pub promoted:bool,
|
|
||||||
pub player:u8,
|
|
||||||
pub tile:u8,
|
|
||||||
}
|
|
||||||
impl PacketGameStateResponsePiece {
|
|
||||||
pub fn new() -> Self
|
|
||||||
{
|
|
||||||
Self {
|
|
||||||
valid:false,
|
|
||||||
piece:0,
|
|
||||||
promoted:false,
|
|
||||||
player:0,
|
|
||||||
tile:0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct PacketGameStateResponse {
|
pub struct PacketGameStateResponse {
|
||||||
pub status:u16,
|
pub status:u16,
|
||||||
pub turn:u16,
|
pub token:SessionToken,
|
||||||
pub player:u8,
|
pub player:u8,
|
||||||
pub play:Play,
|
|
||||||
pub dawn_handle:String,
|
pub dawn_handle:String,
|
||||||
pub dusk_handle:String,
|
pub dusk_handle:String,
|
||||||
pub dawn_pool:Pool,
|
pub history:Vec<Play>,
|
||||||
pub dusk_pool:Pool,
|
|
||||||
pub pieces:[PacketGameStateResponsePiece; game::consts::PIECES_TOTAL],
|
|
||||||
}
|
}
|
||||||
impl PacketGameStateResponse {
|
impl PacketGameStateResponse {
|
||||||
pub fn new() -> Self
|
pub fn new() -> Self
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
status:0,
|
status:0,
|
||||||
turn:0,
|
token:SessionToken::default(),
|
||||||
player:0,
|
player:2,
|
||||||
play:Play::new(),
|
|
||||||
dawn_handle:String::new(),
|
dawn_handle:String::new(),
|
||||||
dusk_handle:String::new(),
|
dusk_handle:String::new(),
|
||||||
dawn_pool:Pool::default(),
|
history:Vec::new(),
|
||||||
dusk_pool:Pool::default(),
|
|
||||||
pieces:[PacketGameStateResponsePiece::new(); game::consts::PIECES_TOTAL],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,53 +65,28 @@ impl Packet for PacketGameStateResponse {
|
|||||||
|
|
||||||
fn encode(&self) -> Vec<u8>
|
fn encode(&self) -> Vec<u8>
|
||||||
{
|
{
|
||||||
let mut flags = 0u16;
|
let mut history_bytes = Vec::new();
|
||||||
flags |= self.player as u16;
|
for play in &self.history {
|
||||||
|
let mut data = 0;
|
||||||
let mut play = 0;
|
data |= play.source as u16;
|
||||||
play |= self.play.source as u16;
|
data |= (play.from as u16) << 4;
|
||||||
play |= (self.play.from as u16) << 4;
|
data |= (play.to as u16) << 10;
|
||||||
play |= (self.play.to as u16) << 10;
|
history_bytes.append(&mut pack_u16(data));
|
||||||
|
|
||||||
let mut piece_bytes = Vec::new();
|
|
||||||
for piece in &self.pieces {
|
|
||||||
let piece_data: u16 = piece.valid as u16
|
|
||||||
| ((piece.piece as u16) << 1)
|
|
||||||
| ((piece.promoted as u16) << 4)
|
|
||||||
| ((piece.player as u16) << 5)
|
|
||||||
| ((piece.tile as u16) << 6);
|
|
||||||
|
|
||||||
piece_bytes.append(&mut pack_u16(piece_data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let dawn_pool_bytes :u16 = self.dawn_pool[0] as u16
|
let mut flags = 0u16;
|
||||||
| ((self.dawn_pool[1] as u16) << 5)
|
flags |= self.player as u16;
|
||||||
| ((self.dawn_pool[2] as u16) << 7)
|
|
||||||
| ((self.dawn_pool[3] as u16) << 9)
|
|
||||||
| ((self.dawn_pool[4] as u16) << 11)
|
|
||||||
| ((self.dawn_pool[5] as u16) << 13)
|
|
||||||
| ((self.dawn_pool[6] as u16) << 14);
|
|
||||||
|
|
||||||
let dusk_pool_bytes :u16 = self.dusk_pool[0] as u16
|
|
||||||
| ((self.dusk_pool[1] as u16) << 5)
|
|
||||||
| ((self.dusk_pool[2] as u16) << 7)
|
|
||||||
| ((self.dusk_pool[3] as u16) << 9)
|
|
||||||
| ((self.dusk_pool[4] as u16) << 11)
|
|
||||||
| ((self.dusk_pool[5] as u16) << 13)
|
|
||||||
| ((self.dusk_pool[6] as u16) << 14);
|
|
||||||
|
|
||||||
[
|
[
|
||||||
pack_u16(self.status),
|
pack_u16(self.status),
|
||||||
|
self.token.to_vec(),
|
||||||
pack_u16(flags),
|
pack_u16(flags),
|
||||||
pack_u16(play),
|
|
||||||
pack_u16(self.turn),
|
|
||||||
pack_u16(self.dawn_handle.len() as u16),
|
pack_u16(self.dawn_handle.len() as u16),
|
||||||
self.dawn_handle.as_bytes().to_vec(),
|
self.dawn_handle.as_bytes().to_vec(),
|
||||||
pack_u16(self.dusk_handle.len() as u16),
|
pack_u16(self.dusk_handle.len() as u16),
|
||||||
self.dusk_handle.as_bytes().to_vec(),
|
self.dusk_handle.as_bytes().to_vec(),
|
||||||
pack_u16(dawn_pool_bytes),
|
pack_u16(self.history.len() as u16),
|
||||||
pack_u16(dusk_pool_bytes),
|
history_bytes,
|
||||||
piece_bytes,
|
|
||||||
].concat()
|
].concat()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ mod register; pub use register::*;
|
|||||||
mod auth; pub use auth::*;
|
mod auth; pub use auth::*;
|
||||||
mod resume; pub use resume::*;
|
mod resume; pub use resume::*;
|
||||||
|
|
||||||
|
mod user_list; pub use user_list::*;
|
||||||
|
|
||||||
mod session_list; pub use session_list::*;
|
mod session_list; pub use session_list::*;
|
||||||
mod session_create; pub use session_create::*;
|
mod session_create; pub use session_create::*;
|
||||||
mod session_join; pub use session_join::*;
|
mod session_join; pub use session_join::*;
|
||||||
@ -11,7 +13,7 @@ mod session_retire; pub use session_retire::*;
|
|||||||
|
|
||||||
mod game_state; pub use game_state::*;
|
mod game_state; pub use game_state::*;
|
||||||
mod game_play; pub use game_play::*;
|
mod game_play; pub use game_play::*;
|
||||||
mod game_history; pub use game_history::*;
|
//mod game_history; pub use game_history::*;
|
||||||
|
|
||||||
mod prelude {
|
mod prelude {
|
||||||
pub trait Packet {
|
pub trait Packet {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
app::session::SessionToken,
|
app::session::SessionToken,
|
||||||
util::pack::{pack_u8, pack_u16},
|
util::pack::pack_u16,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::Packet;
|
use super::Packet;
|
||||||
@ -29,7 +29,6 @@ impl Packet for PacketSessionCreate {
|
|||||||
pub struct PacketSessionCreateResponse {
|
pub struct PacketSessionCreateResponse {
|
||||||
pub status:u16,
|
pub status:u16,
|
||||||
pub token:SessionToken,
|
pub token:SessionToken,
|
||||||
pub mode:u8,
|
|
||||||
}
|
}
|
||||||
impl PacketSessionCreateResponse {
|
impl PacketSessionCreateResponse {
|
||||||
pub fn new() -> Self
|
pub fn new() -> Self
|
||||||
@ -37,7 +36,6 @@ impl PacketSessionCreateResponse {
|
|||||||
Self {
|
Self {
|
||||||
status:0,
|
status:0,
|
||||||
token:SessionToken::default(),
|
token:SessionToken::default(),
|
||||||
mode:0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,7 +46,6 @@ impl Packet for PacketSessionCreateResponse {
|
|||||||
{
|
{
|
||||||
[
|
[
|
||||||
pack_u16(self.status),
|
pack_u16(self.status),
|
||||||
pack_u8(self.mode),
|
|
||||||
self.token.to_vec(),
|
self.token.to_vec(),
|
||||||
].concat()
|
].concat()
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
app::session::SessionToken,
|
app::session::SessionToken,
|
||||||
util::pack::{pack_u8, pack_u16},
|
util::pack::pack_u16,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::Packet;
|
use super::Packet;
|
||||||
@ -41,7 +41,6 @@ impl Packet for PacketSessionJoin {
|
|||||||
pub struct PacketSessionJoinResponse {
|
pub struct PacketSessionJoinResponse {
|
||||||
pub status:u16,
|
pub status:u16,
|
||||||
pub token:SessionToken,
|
pub token:SessionToken,
|
||||||
pub mode:u8,
|
|
||||||
}
|
}
|
||||||
impl PacketSessionJoinResponse {
|
impl PacketSessionJoinResponse {
|
||||||
pub fn new() -> Self
|
pub fn new() -> Self
|
||||||
@ -49,7 +48,6 @@ impl PacketSessionJoinResponse {
|
|||||||
Self {
|
Self {
|
||||||
status:0,
|
status:0,
|
||||||
token:SessionToken::default(),
|
token:SessionToken::default(),
|
||||||
mode:0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,7 +58,6 @@ impl Packet for PacketSessionJoinResponse {
|
|||||||
{
|
{
|
||||||
[
|
[
|
||||||
pack_u16(self.status),
|
pack_u16(self.status),
|
||||||
pack_u8(self.mode),
|
|
||||||
self.token.to_vec(),
|
self.token.to_vec(),
|
||||||
].concat()
|
].concat()
|
||||||
}
|
}
|
||||||
|
76
server/src/protocol/packet/user_list.rs
Normal file
76
server/src/protocol/packet/user_list.rs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
use crate::util::pack::{pack_u16, unpack_u16};
|
||||||
|
|
||||||
|
use super::Packet;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct PacketUserList {
|
||||||
|
pub page:u16,
|
||||||
|
}
|
||||||
|
impl PacketUserList {
|
||||||
|
pub fn new() -> Self
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
page:0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Packet for PacketUserList {
|
||||||
|
type Data = Self;
|
||||||
|
|
||||||
|
fn decode(data:&Vec<u8>, index:&mut usize) -> Result<Self::Data, ()>
|
||||||
|
{
|
||||||
|
let mut result = Self::new();
|
||||||
|
|
||||||
|
if data.len() - *index == 2 {
|
||||||
|
result.page = unpack_u16(data, index);
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct PacketUserListResponseRecord {
|
||||||
|
//pub token:UserToken,
|
||||||
|
pub handle:String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct PacketUserListResponse {
|
||||||
|
pub status:u16,
|
||||||
|
pub records:Vec<PacketUserListResponseRecord>,
|
||||||
|
}
|
||||||
|
impl PacketUserListResponse {
|
||||||
|
pub fn new() -> Self
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
status:0,
|
||||||
|
records:Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Packet for PacketUserListResponse {
|
||||||
|
type Data = Self;
|
||||||
|
|
||||||
|
fn encode(&self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
let mut result = pack_u16(self.status as u16);
|
||||||
|
|
||||||
|
result.append(&mut pack_u16(self.records.len() as u16));
|
||||||
|
|
||||||
|
for record in &self.records {
|
||||||
|
let mut chunk = Vec::new(); //record.token.to_vec();
|
||||||
|
|
||||||
|
// Handle
|
||||||
|
let mut bytes = record.handle.as_bytes().to_vec();
|
||||||
|
chunk.append(&mut pack_u16(bytes.len() as u16));
|
||||||
|
if bytes.len() > 0 { chunk.append(&mut bytes); }
|
||||||
|
|
||||||
|
result.append(&mut chunk);
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
@ -3,8 +3,8 @@ let INTERFACE_DATA = null;
|
|||||||
const INTERFACE = {
|
const INTERFACE = {
|
||||||
Mode: {
|
Mode: {
|
||||||
Local: 0,
|
Local: 0,
|
||||||
Online: 1,
|
Player: 1,
|
||||||
Replay: 2,
|
Review: 2,
|
||||||
},
|
},
|
||||||
|
|
||||||
Color: {
|
Color: {
|
||||||
@ -290,16 +290,17 @@ const INTERFACE = {
|
|||||||
draw() {
|
draw() {
|
||||||
if(INTERFACE_DATA === null) return;
|
if(INTERFACE_DATA === null) return;
|
||||||
|
|
||||||
if(INTERFACE_DATA.mode == INTERFACE.Mode.Replay) {
|
|
||||||
document.getElementById("ind_turn").innerText = INTERFACE_DATA.replay_turn + " of " + INTERFACE_DATA.history.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
let canvas = INTERFACE_DATA.canvas;
|
let canvas = INTERFACE_DATA.canvas;
|
||||||
let ctx = INTERFACE_DATA.context;
|
let ctx = INTERFACE_DATA.context;
|
||||||
|
|
||||||
INTERFACE.resize();
|
INTERFACE.resize();
|
||||||
INTERFACE.resolve_board();
|
INTERFACE.resolve_board();
|
||||||
|
|
||||||
|
let play = null;
|
||||||
|
if(INTERFACE_DATA.replay_turn > 0) {
|
||||||
|
play = INTERFACE_DATA.history[INTERFACE_DATA.replay_turn - 1];
|
||||||
|
}
|
||||||
|
|
||||||
let width = canvas.width;
|
let width = canvas.width;
|
||||||
let height = canvas.height;
|
let height = canvas.height;
|
||||||
|
|
||||||
@ -369,7 +370,7 @@ const INTERFACE = {
|
|||||||
case 1: ctx.fillStyle = INTERFACE.Color.TileLight; break;
|
case 1: ctx.fillStyle = INTERFACE.Color.TileLight; break;
|
||||||
case 2: ctx.fillStyle = INTERFACE.Color.TileDark; break;
|
case 2: ctx.fillStyle = INTERFACE.Color.TileDark; break;
|
||||||
}
|
}
|
||||||
if(GAME_DATA.turn > 0 && INTERFACE_DATA.play.source < 2 && (INTERFACE_DATA.play.to == i || (INTERFACE_DATA.play.source == 0 && INTERFACE_DATA.play.from == i))) {
|
if(GAME_DATA.turn > 0 && play.source < 2 && (play.to == i || (play.source == 0 && play.from == i))) {
|
||||||
ctx.fillStyle = INTERFACE.Color.HintPlay;
|
ctx.fillStyle = INTERFACE.Color.HintPlay;
|
||||||
} else if(GAME_DATA.state.check != 0 && piece !== null && piece.piece == GAME.Const.PieceId.Omen && piece.player == (GAME_DATA.turn & 1)) {
|
} else if(GAME_DATA.state.check != 0 && piece !== null && piece.piece == GAME.Const.PieceId.Omen && piece.player == (GAME_DATA.turn & 1)) {
|
||||||
ctx.fillStyle = INTERFACE.Color.HintCheck;
|
ctx.fillStyle = INTERFACE.Color.HintCheck;
|
||||||
@ -704,35 +705,18 @@ const INTERFACE = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
init(data, mode) {
|
init(token, mode) {
|
||||||
GAME.init();
|
GAME.init();
|
||||||
|
|
||||||
let token = null;
|
let player = 2;
|
||||||
let player = 0;
|
if(mode == INTERFACE.Mode.Local) { player = 0; }
|
||||||
|
|
||||||
let history = [ ];
|
let history = [ ];
|
||||||
let dawn = null;
|
let dawn = null;
|
||||||
let dusk = null;
|
let dusk = null;
|
||||||
|
|
||||||
if(data !== null) {
|
|
||||||
switch(mode) {
|
|
||||||
case INTERFACE.Mode.Online: {
|
|
||||||
token = data.token;
|
|
||||||
player = data.mode;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case INTERFACE.Mode.Replay: {
|
|
||||||
history = data.history;
|
|
||||||
player = 2;
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(data.dawn !== undefined) { dawn = data.dawn; }
|
|
||||||
if(data.dusk !== undefined) { dusk = data.dusk; }
|
|
||||||
}
|
|
||||||
|
|
||||||
INTERFACE_DATA = {
|
INTERFACE_DATA = {
|
||||||
mode: mode,
|
mode: mode,
|
||||||
|
|
||||||
token: token,
|
token: token,
|
||||||
|
|
||||||
canvas: document.getElementById("game"),
|
canvas: document.getElementById("game"),
|
||||||
@ -747,15 +731,14 @@ const INTERFACE = {
|
|||||||
|
|
||||||
handles: [dawn, dusk],
|
handles: [dawn, dusk],
|
||||||
board_state: [ ],
|
board_state: [ ],
|
||||||
play: null,
|
|
||||||
retire:false,
|
retire:false,
|
||||||
retire_warn:false,
|
retire_warn:false,
|
||||||
|
|
||||||
auto_mode: null,
|
history: history,
|
||||||
|
|
||||||
replay_turn: 0,
|
replay_turn: 0,
|
||||||
replay_auto: false,
|
replay_auto: false,
|
||||||
history: history,
|
auto_mode: null,
|
||||||
|
|
||||||
Ui: {
|
Ui: {
|
||||||
scale: 0,
|
scale: 0,
|
||||||
@ -780,24 +763,18 @@ const INTERFACE = {
|
|||||||
window.addEventListener("resize", INTERFACE.draw);
|
window.addEventListener("resize", INTERFACE.draw);
|
||||||
|
|
||||||
switch(INTERFACE_DATA.mode) {
|
switch(INTERFACE_DATA.mode) {
|
||||||
case INTERFACE.Mode.Replay:
|
|
||||||
case INTERFACE.Mode.Local: {
|
case INTERFACE.Mode.Local: {
|
||||||
INTERFACE.draw();
|
INTERFACE.draw();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case INTERFACE.Mode.Online: {
|
|
||||||
MESSAGE_COMPOSE([
|
|
||||||
PACK.u16(OpCode.GameState),
|
|
||||||
INTERFACE_DATA.token,
|
|
||||||
]);
|
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
LOAD(SCENES.Browse);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
uninit() {
|
uninit() {
|
||||||
if(INTERFACE_DATA !== null) {
|
if(INTERFACE_DATA !== null) {
|
||||||
if(INTERFACE_DATA.mode == INTERFACE.Mode.Online) {
|
if(INTERFACE_DATA.mode != INTERFACE.Mode.Local) {
|
||||||
MESSAGE_COMPOSE([
|
MESSAGE_COMPOSE([
|
||||||
PACK.u16(OpCode.SessionLeave),
|
PACK.u16(OpCode.SessionLeave),
|
||||||
]);
|
]);
|
||||||
@ -820,44 +797,51 @@ const INTERFACE = {
|
|||||||
if(data === null) { return; }
|
if(data === null) { return; }
|
||||||
|
|
||||||
switch(code) {
|
switch(code) {
|
||||||
case OpCode.GameState: {
|
|
||||||
INTERFACE_DATA.player = data.player;
|
|
||||||
GAME_DATA.turn = data.turn;
|
|
||||||
INTERFACE_DATA.play = data.play;
|
|
||||||
|
|
||||||
if(INTERFACE_DATA.play.source == 2) {
|
case OpCode.SessionCreate:
|
||||||
GAME_DATA.state.code = 2;
|
case OpCode.SessionJoin: {
|
||||||
|
if(data.status != Status.Ok) {
|
||||||
|
LOAD(SCENES.Browse);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(INTERFACE_DATA.mode) {
|
||||||
|
case INTERFACE.Mode.Review:
|
||||||
|
case INTERFACE.Mode.Player: {
|
||||||
|
MESSAGE_COMPOSE([
|
||||||
|
PACK.u16(OpCode.GameState),
|
||||||
|
INTERFACE_DATA.token,
|
||||||
|
]);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case OpCode.GameState: {
|
||||||
|
if(INTERFACE_DATA.mode == INTERFACE.Mode.Player) {
|
||||||
|
INTERFACE_DATA.player = data.player;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERFACE_DATA.history = [ ];
|
||||||
|
for(let i = 0; i < data.history.length; ++i) {
|
||||||
|
INTERFACE.history_push(data.history[i]);
|
||||||
|
}
|
||||||
|
let turn = INTERFACE_DATA.history.length;
|
||||||
|
|
||||||
|
if(INTERFACE_DATA.history.length > 0) {
|
||||||
|
if(INTERFACE_DATA.history[INTERFACE_DATA.history.length-1].source == 2) {
|
||||||
|
GAME_DATA.state.code = 2;
|
||||||
|
turn = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data.dawn.length > 0) { INTERFACE_DATA.handles[0] = data.dawn; }
|
if(data.dawn.length > 0) { INTERFACE_DATA.handles[0] = data.dawn; }
|
||||||
if(data.dusk.length > 0) { INTERFACE_DATA.handles[1] = data.dusk; }
|
if(data.dusk.length > 0) { INTERFACE_DATA.handles[1] = data.dusk; }
|
||||||
|
|
||||||
// Clear piece placement.
|
INTERFACE.replay_jump(turn);
|
||||||
for(let i = 0; i < GAME_DATA.board.tiles.length; ++i) {
|
|
||||||
GAME_DATA.board.tiles[i].piece = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update pools.
|
|
||||||
GAME_DATA.pools[0].pieces = data.pool_dawn;
|
|
||||||
GAME_DATA.pools[1].pieces = data.pool_dusk;
|
|
||||||
|
|
||||||
// Replace pieces list.
|
|
||||||
for(let i = 0; i < GAME_DATA.board.pieces.length; ++i) {
|
|
||||||
GAME_DATA.board.pieces[i] = data.pieces[i];
|
|
||||||
if(data.pieces[i] !== null) {
|
|
||||||
GAME_DATA.board.tiles[data.pieces[i].tile].piece = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GAME_DATA.update_board();
|
|
||||||
INTERFACE.draw();
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case OpCode.GamePlay: {
|
case OpCode.GamePlay: {
|
||||||
if(data.status == Status.Ok && data.turn == GAME_DATA.turn) {
|
if(data.status == Status.Ok && data.turn == INTERFACE_DATA.history.length) {
|
||||||
INTERFACE_DATA.play = data.play;
|
INTERFACE.history_push(data.play);
|
||||||
GAME_DATA.process(data.play);
|
|
||||||
INTERFACE.draw();
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
@ -868,8 +852,7 @@ const INTERFACE = {
|
|||||||
switch(INTERFACE_DATA.mode) {
|
switch(INTERFACE_DATA.mode) {
|
||||||
// Apply action and change turn for local game.
|
// Apply action and change turn for local game.
|
||||||
case INTERFACE.Mode.Local: {
|
case INTERFACE.Mode.Local: {
|
||||||
INTERFACE_DATA.play = play;
|
INTERFACE.history_push(play);
|
||||||
GAME_DATA.process(play);
|
|
||||||
|
|
||||||
INTERFACE_DATA.player = +(!INTERFACE_DATA.player);
|
INTERFACE_DATA.player = +(!INTERFACE_DATA.player);
|
||||||
INTERFACE_DATA.rotate = +(!INTERFACE_DATA.rotate);
|
INTERFACE_DATA.rotate = +(!INTERFACE_DATA.rotate);
|
||||||
@ -877,12 +860,12 @@ const INTERFACE = {
|
|||||||
INTERFACE.draw();
|
INTERFACE.draw();
|
||||||
|
|
||||||
if(INTERFACE_DATA.auto_mode !== null && INTERFACE_DATA.auto_mode == (GAME_DATA.turn & 1)) {
|
if(INTERFACE_DATA.auto_mode !== null && INTERFACE_DATA.auto_mode == (GAME_DATA.turn & 1)) {
|
||||||
setTimeout(INTERFACE.auto_play, 500);
|
setTimeout(INTERFACE.auto_play, 1000);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
// Send action to server for validation.
|
// Send action to server for validation.
|
||||||
case INTERFACE.Mode.Online: {
|
case INTERFACE.Mode.Player: {
|
||||||
let move_data = play.source | (play.from << 1) | (play.to << 7);
|
let move_data = play.source | (play.from << 1) | (play.to << 7);
|
||||||
MESSAGE_COMPOSE([
|
MESSAGE_COMPOSE([
|
||||||
PACK.u16(OpCode.GamePlay),
|
PACK.u16(OpCode.GamePlay),
|
||||||
@ -891,11 +874,6 @@ const INTERFACE = {
|
|||||||
PACK.u16(move_data),
|
PACK.u16(move_data),
|
||||||
]);
|
]);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
// Branch into local game from here.
|
|
||||||
case INTERFACE.Mode.Replay: {
|
|
||||||
|
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -910,7 +888,7 @@ const INTERFACE = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
retire() {
|
retire() {
|
||||||
if(INTERFACE_DATA.mode == INTERFACE.Mode.Online) {
|
if(INTERFACE_DATA.mode == INTERFACE.Mode.Player) {
|
||||||
let button_retire = document.getElementById("button-retire");
|
let button_retire = document.getElementById("button-retire");
|
||||||
|
|
||||||
if(INTERFACE_DATA.retire_warn) {
|
if(INTERFACE_DATA.retire_warn) {
|
||||||
@ -939,25 +917,40 @@ const INTERFACE = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
history_push(play) {
|
||||||
|
INTERFACE_DATA.history.push(play);
|
||||||
|
if(INTERFACE_DATA.mode == INTERFACE.Mode.Review) {
|
||||||
|
document.getElementById("indicator-turn").innerText = INTERFACE_DATA.replay_turn + " of " + INTERFACE_DATA.history.length;
|
||||||
|
document.getElementById("turn-slider").setAttribute("max", INTERFACE_DATA.history.length);
|
||||||
|
}
|
||||||
|
if(INTERFACE_DATA.replay_turn == INTERFACE_DATA.history.length - 1) {
|
||||||
|
INTERFACE.replay_next();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
replay_jump(turn) {
|
replay_jump(turn) {
|
||||||
turn = +turn;
|
turn = +turn;
|
||||||
if(INTERFACE_DATA.mode == INTERFACE.Mode.Replay) {
|
|
||||||
if(turn >= 0 && turn <= INTERFACE_DATA.history.length) {
|
if(turn >= 0 && turn <= INTERFACE_DATA.history.length) {
|
||||||
INTERFACE_DATA.replay_turn = turn;
|
if(turn < INTERFACE_DATA.replay_turn) {
|
||||||
|
|
||||||
GAME.init();
|
GAME.init();
|
||||||
for(let i = 0; i < INTERFACE_DATA.replay_turn; ++i) {
|
for(let i = 0; i < turn; ++i) {
|
||||||
GAME_DATA.process(INTERFACE_DATA.history[i]);
|
GAME_DATA.process(INTERFACE_DATA.history[i]);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
INTERFACE_DATA.play = null;
|
while(INTERFACE_DATA.replay_turn < turn) {
|
||||||
if(INTERFACE_DATA.replay_turn > 0) {
|
GAME_DATA.process(INTERFACE_DATA.history[INTERFACE_DATA.replay_turn]);
|
||||||
INTERFACE_DATA.play = INTERFACE_DATA.history[INTERFACE_DATA.replay_turn - 1];
|
INTERFACE_DATA.replay_turn++;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById("turn-slider").value = INTERFACE_DATA.replay_turn;
|
|
||||||
INTERFACE.draw();
|
|
||||||
}
|
}
|
||||||
|
INTERFACE_DATA.replay_turn = turn;
|
||||||
|
|
||||||
|
if(INTERFACE_DATA.mode == INTERFACE.Mode.Review) {
|
||||||
|
document.getElementById("indicator-turn").innerText = INTERFACE_DATA.replay_turn + " of " + INTERFACE_DATA.history.length;
|
||||||
|
document.getElementById("turn-slider").value = INTERFACE_DATA.replay_turn;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERFACE.draw();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
replay_first() {
|
replay_first() {
|
||||||
|
111
www/js/scene.js
111
www/js/scene.js
@ -229,12 +229,6 @@ const SCENES = {
|
|||||||
table.appendChild(UI.session_table(data.records));
|
table.appendChild(UI.session_table(data.records));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case OpCode.SessionCreate:
|
|
||||||
case OpCode.SessionJoin: {
|
|
||||||
if(data.status == Status.Ok) {
|
|
||||||
LOAD(SCENES.Game, data);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
disconnect() {
|
disconnect() {
|
||||||
@ -398,8 +392,7 @@ const SCENES = {
|
|||||||
table.appendChild(UI.session_table(data.records));
|
table.appendChild(UI.session_table(data.records));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case OpCode.SessionCreate:
|
{
|
||||||
case OpCode.SessionJoin: {
|
|
||||||
if(data.status == Status.Ok) {
|
if(data.status == Status.Ok) {
|
||||||
LOAD(SCENES.Game, data);
|
LOAD(SCENES.Game, data);
|
||||||
}
|
}
|
||||||
@ -453,11 +446,6 @@ const SCENES = {
|
|||||||
table.appendChild(UI.session_table_history(data.records));
|
table.appendChild(UI.session_table_history(data.records));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case OpCode.GameHistory: {
|
|
||||||
if(data.status == Status.Ok) {
|
|
||||||
LOAD(SCENES.GameHistory, data);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
disconnect() {
|
disconnect() {
|
||||||
@ -525,10 +513,8 @@ const SCENES = {
|
|||||||
|
|
||||||
Game:{
|
Game:{
|
||||||
load(data) {
|
load(data) {
|
||||||
if(data === null) { return false; }
|
|
||||||
|
|
||||||
let buttons_bottom = [ ];
|
let buttons_bottom = [ ];
|
||||||
if(data.mode != 2) {
|
if(data.mode != INTERFACE.Mode.Review) {
|
||||||
let button_retire = UI.button("Surrender", () => { INTERFACE.retire(); });
|
let button_retire = UI.button("Surrender", () => { INTERFACE.retire(); });
|
||||||
button_retire.setAttribute("id", "button-retire");
|
button_retire.setAttribute("id", "button-retire");
|
||||||
buttons_bottom.push(button_retire);
|
buttons_bottom.push(button_retire);
|
||||||
@ -540,11 +526,34 @@ const SCENES = {
|
|||||||
UI.button("Mirror", () => { INTERFACE.mirror(); }),
|
UI.button("Mirror", () => { INTERFACE.mirror(); }),
|
||||||
], buttons_bottom);
|
], buttons_bottom);
|
||||||
|
|
||||||
|
if(data.mode == INTERFACE.Mode.Review) {
|
||||||
|
let ind_turn = UI.div([UI.text("0 of 0")]);
|
||||||
|
ind_turn.setAttribute("id", "indicator-turn");
|
||||||
|
|
||||||
|
UI.mainnav(
|
||||||
|
[ ],
|
||||||
|
[
|
||||||
|
UI.button("Auto", () => { INTERFACE.replay_toggle_auto(); }),
|
||||||
|
UI.button("◀", () => { INTERFACE.replay_first(); }),
|
||||||
|
UI.button("◁", () => { INTERFACE.replay_prev(); }),
|
||||||
|
ind_turn,
|
||||||
|
UI.button("▷", () => { INTERFACE.replay_next(); }),
|
||||||
|
UI.button("▶", () => { INTERFACE.replay_last(); }),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
let slider = UI.slider((event) => { INTERFACE.replay_jump(event.target.value); });
|
||||||
|
slider.setAttribute("id", "turn-slider");
|
||||||
|
slider.setAttribute("min", "0");
|
||||||
|
slider.setAttribute("max", "0");
|
||||||
|
MAIN.appendChild(UI.div([ slider ], "turn-slider-padding"));
|
||||||
|
}
|
||||||
|
|
||||||
let canvas = document.createElement("canvas");
|
let canvas = document.createElement("canvas");
|
||||||
canvas.setAttribute("id", "game");
|
canvas.setAttribute("id", "game");
|
||||||
MAIN.appendChild(canvas);
|
MAIN.appendChild(canvas);
|
||||||
|
|
||||||
INTERFACE.init(data, INTERFACE.Mode.Online);
|
INTERFACE.init(data.token, data.mode);
|
||||||
|
|
||||||
history.pushState(null, "Omen - Game", "/game/" + PACK.base64(data.token).slice(0, -1));
|
history.pushState(null, "Omen - Game", "/game/" + PACK.base64(data.token).slice(0, -1));
|
||||||
return true;
|
return true;
|
||||||
@ -554,13 +563,9 @@ const SCENES = {
|
|||||||
},
|
},
|
||||||
message(code, data) {
|
message(code, data) {
|
||||||
switch(code) {
|
switch(code) {
|
||||||
case OpCode.GameState: {
|
case OpCode.SessionCreate:
|
||||||
if(data.status == Status.Ok) {
|
case OpCode.SessionJoin:
|
||||||
INTERFACE.message(code, data);
|
case OpCode.GameState:
|
||||||
} else {
|
|
||||||
LOAD(SCENES.Browse);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case OpCode.GamePlay: {
|
case OpCode.GamePlay: {
|
||||||
INTERFACE.message(code, data);
|
INTERFACE.message(code, data);
|
||||||
} break;
|
} break;
|
||||||
@ -587,7 +592,7 @@ const SCENES = {
|
|||||||
canvas.setAttribute("id", "game");
|
canvas.setAttribute("id", "game");
|
||||||
MAIN.appendChild(canvas);
|
MAIN.appendChild(canvas);
|
||||||
|
|
||||||
INTERFACE.init(data, INTERFACE.Mode.Local);
|
INTERFACE.init(null, INTERFACE.Mode.Local);
|
||||||
|
|
||||||
history.pushState(null, "Omen - Practice", "/practice/");
|
history.pushState(null, "Omen - Practice", "/practice/");
|
||||||
return true;
|
return true;
|
||||||
@ -596,51 +601,6 @@ const SCENES = {
|
|||||||
INTERFACE.uninit();
|
INTERFACE.uninit();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
GameHistory:{
|
|
||||||
load(data) {
|
|
||||||
let buttons_bottom = [ ];
|
|
||||||
buttons_bottom.push(UI.button("Back", () => { LOAD(SCENES.History) }));
|
|
||||||
|
|
||||||
UI.nav([
|
|
||||||
UI.button("Rotate", () => { INTERFACE.rotate(); }),
|
|
||||||
UI.button("Mirror", () => { INTERFACE.mirror(); }),
|
|
||||||
], buttons_bottom);
|
|
||||||
|
|
||||||
let ind_turn = UI.div([UI.text("0 of 0")]);
|
|
||||||
ind_turn.setAttribute("id", "ind_turn");
|
|
||||||
|
|
||||||
UI.mainnav(
|
|
||||||
[ ],
|
|
||||||
[
|
|
||||||
UI.button("Auto", () => { INTERFACE.replay_toggle_auto(); }),
|
|
||||||
UI.button("◀", () => { INTERFACE.replay_first(); }),
|
|
||||||
UI.button("◁", () => { INTERFACE.replay_prev(); }),
|
|
||||||
ind_turn,
|
|
||||||
UI.button("▷", () => { INTERFACE.replay_next(); }),
|
|
||||||
UI.button("▶", () => { INTERFACE.replay_last(); }),
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
let slider = UI.slider((event) => { INTERFACE.replay_jump(event.target.value); });
|
|
||||||
slider.setAttribute("id", "turn-slider");
|
|
||||||
slider.setAttribute("min", "0");
|
|
||||||
slider.setAttribute("max", data.history.length);
|
|
||||||
MAIN.appendChild(UI.div([ slider ], "turn-slider-padding"));
|
|
||||||
|
|
||||||
let canvas = document.createElement("canvas");
|
|
||||||
canvas.setAttribute("id", "game");
|
|
||||||
MAIN.appendChild(canvas);
|
|
||||||
|
|
||||||
INTERFACE.init(data, INTERFACE.Mode.Replay);
|
|
||||||
|
|
||||||
history.pushState(null, "Omen - History", "/history/" + PACK.base64(data.token).slice(0, -1));
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
unload() {
|
|
||||||
INTERFACE.uninit();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function LOAD(scene, data=null) {
|
function LOAD(scene, data=null) {
|
||||||
@ -665,17 +625,6 @@ function LOAD_URL() {
|
|||||||
case "guide": LOAD(SCENES.Guide); break;
|
case "guide": LOAD(SCENES.Guide); break;
|
||||||
case "practice": LOAD(SCENES.About); break;
|
case "practice": LOAD(SCENES.About); break;
|
||||||
|
|
||||||
case "history": {
|
|
||||||
LOAD(SCENES.History);
|
|
||||||
if(parts[2]) {
|
|
||||||
let token = UNPACK.base64(parts[2] + "=");
|
|
||||||
MESSAGE_COMPOSE([
|
|
||||||
PACK.u16(OpCode.GameHistory),
|
|
||||||
token,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case "join": {
|
case "join": {
|
||||||
LOAD(SCENES.Join);
|
LOAD(SCENES.Join);
|
||||||
if(parts[2]) {
|
if(parts[2]) {
|
||||||
|
185
www/js/system.js
185
www/js/system.js
@ -185,21 +185,16 @@ function MESSAGE(event) {
|
|||||||
case OpCode.SessionJoin: {
|
case OpCode.SessionJoin: {
|
||||||
console.log("RECV SessionCreate/Join");
|
console.log("RECV SessionCreate/Join");
|
||||||
|
|
||||||
if(bytes.length - index == 11) {
|
if(bytes.length - index == 10) {
|
||||||
data = {
|
data = {
|
||||||
status:0,
|
status:0,
|
||||||
token:new Uint8Array(8),
|
token:new Uint8Array(8),
|
||||||
mode:2,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
result = UNPACK.u16(bytes, index);
|
result = UNPACK.u16(bytes, index);
|
||||||
index = result.index;
|
index = result.index;
|
||||||
data.status = result.data;
|
data.status = result.data;
|
||||||
|
|
||||||
result = UNPACK.u8(bytes, index);
|
|
||||||
index = result.index;
|
|
||||||
data.mode = result.data;
|
|
||||||
|
|
||||||
for(let i = 0; i < 8; ++i) { data.token[i] = bytes[index++]; }
|
for(let i = 0; i < 8; ++i) { data.token[i] = bytes[index++]; }
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@ -207,95 +202,54 @@ function MESSAGE(event) {
|
|||||||
case OpCode.GameState: {
|
case OpCode.GameState: {
|
||||||
console.log("RECV GameState");
|
console.log("RECV GameState");
|
||||||
|
|
||||||
//if(bytes.length - index >= 22) {
|
data = {
|
||||||
data = {
|
status:0,
|
||||||
status:0,
|
token:new Uint8Array(8),
|
||||||
player:2,
|
player:2,
|
||||||
turn:0,
|
dawn:"",
|
||||||
play:new GAME.Play(),
|
dusk:"",
|
||||||
dawn:"",
|
history:[ ],
|
||||||
dusk:"",
|
};
|
||||||
pool_dawn:[ ],
|
|
||||||
pool_dusk:[ ],
|
|
||||||
pieces:[ ],
|
|
||||||
};
|
|
||||||
|
|
||||||
// Status
|
// Status
|
||||||
|
result = UNPACK.u16(bytes, index);
|
||||||
|
index = result.index;
|
||||||
|
data.status = result.data;
|
||||||
|
|
||||||
|
// Token
|
||||||
|
for(let i = 0; i < 8; ++i) { data.token[i] = bytes[index++]; }
|
||||||
|
|
||||||
|
// Flags
|
||||||
|
result = UNPACK.u16(bytes, index);
|
||||||
|
index = result.index;
|
||||||
|
let flags = result.data;
|
||||||
|
|
||||||
|
data.player = flags & 0x3;
|
||||||
|
|
||||||
|
// Handles
|
||||||
|
result = UNPACK.string(bytes, index);
|
||||||
|
index = result.index;
|
||||||
|
data.dawn = result.data;
|
||||||
|
|
||||||
|
result = UNPACK.string(bytes, index);
|
||||||
|
index = result.index;
|
||||||
|
data.dusk = result.data;
|
||||||
|
|
||||||
|
// History
|
||||||
|
result = UNPACK.u16(bytes, index);
|
||||||
|
index = result.index;
|
||||||
|
let history_length = result.data;
|
||||||
|
|
||||||
|
for(let i = 0; i < history_length; ++i) {
|
||||||
result = UNPACK.u16(bytes, index);
|
result = UNPACK.u16(bytes, index);
|
||||||
index = result.index;
|
index = result.index;
|
||||||
data.status = result.data;
|
|
||||||
|
data.history.push(new GAME.Play(
|
||||||
// Flags
|
result.data & 0xF,
|
||||||
result = UNPACK.u16(bytes, index);
|
(result.data >> 4) & 0x3F,
|
||||||
index = result.index;
|
(result.data >> 10) & 0x3F,
|
||||||
let flags = result.data;
|
));
|
||||||
|
}
|
||||||
data.player = flags & 0x3;
|
|
||||||
|
|
||||||
// Last Play
|
|
||||||
result = UNPACK.u16(bytes, index);
|
|
||||||
index = result.index;
|
|
||||||
data.play.source = result.data & 0xF;
|
|
||||||
data.play.from = (result.data >> 4) & 0x3F;
|
|
||||||
data.play.to = (result.data >> 10) & 0x3F;
|
|
||||||
|
|
||||||
// Turn
|
|
||||||
result = UNPACK.u16(bytes, index);
|
|
||||||
index = result.index;
|
|
||||||
data.turn = result.data;
|
|
||||||
|
|
||||||
// Handles
|
|
||||||
result = UNPACK.string(bytes, index);
|
|
||||||
index = result.index;
|
|
||||||
data.dawn = result.data;
|
|
||||||
|
|
||||||
result = UNPACK.string(bytes, index);
|
|
||||||
index = result.index;
|
|
||||||
data.dusk = result.data;
|
|
||||||
|
|
||||||
// Dawn pool
|
|
||||||
result = UNPACK.u16(bytes, index);
|
|
||||||
index = result.index;
|
|
||||||
let dawn_pool_bits = result.data;
|
|
||||||
|
|
||||||
data.pool_dawn.push(dawn_pool_bits & 0x1F);
|
|
||||||
data.pool_dawn.push((dawn_pool_bits >> 5) & 0x3);
|
|
||||||
data.pool_dawn.push((dawn_pool_bits >> 7) & 0x3);
|
|
||||||
data.pool_dawn.push((dawn_pool_bits >> 9) & 0x3);
|
|
||||||
data.pool_dawn.push((dawn_pool_bits >> 11) & 0x3);
|
|
||||||
data.pool_dawn.push((dawn_pool_bits >> 13) & 0x1);
|
|
||||||
data.pool_dawn.push((dawn_pool_bits >> 14) & 0x1);
|
|
||||||
|
|
||||||
// Dusk pool
|
|
||||||
result = UNPACK.u16(bytes, index);
|
|
||||||
index = result.index;
|
|
||||||
let dusk_pool_bits = result.data;
|
|
||||||
|
|
||||||
data.pool_dusk.push(dusk_pool_bits & 0x1f);
|
|
||||||
data.pool_dusk.push((dusk_pool_bits >> 5) & 0x3);
|
|
||||||
data.pool_dusk.push((dusk_pool_bits >> 7) & 0x3);
|
|
||||||
data.pool_dusk.push((dusk_pool_bits >> 9) & 0x3);
|
|
||||||
data.pool_dusk.push((dusk_pool_bits >> 11) & 0x3);
|
|
||||||
data.pool_dusk.push((dusk_pool_bits >> 13) & 0x1);
|
|
||||||
data.pool_dusk.push((dusk_pool_bits >> 14) & 0x1);
|
|
||||||
|
|
||||||
// Pieces
|
|
||||||
for(let i = 0; i < GAME.Const.Count.Pieces; ++i) {
|
|
||||||
result = UNPACK.u16(bytes, index);
|
|
||||||
index = result.index;
|
|
||||||
let piece_data = result.data;
|
|
||||||
|
|
||||||
if((piece_data & 1) != 0) {
|
|
||||||
let piece = new GAME.Piece((piece_data >> 1) & 0x7, (piece_data >> 5) & 1);
|
|
||||||
piece.promoted = ((piece_data >> 4) & 1) != 0;
|
|
||||||
piece.tile = (piece_data >> 6) & 0x3F;
|
|
||||||
|
|
||||||
data.pieces.push(piece);
|
|
||||||
} else {
|
|
||||||
data.pieces.push(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//}
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case OpCode.GamePlay: {
|
case OpCode.GamePlay: {
|
||||||
@ -324,55 +278,12 @@ function MESSAGE(event) {
|
|||||||
data.play.to = (result.data >> 10) & 0x3F;
|
data.play.to = (result.data >> 10) & 0x3F;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case OpCode.GameHistory: {
|
|
||||||
console.log("RECV GameHistory");
|
|
||||||
|
|
||||||
data = {
|
|
||||||
status:0,
|
|
||||||
token:new Uint8Array(8),
|
|
||||||
dawn:"",
|
|
||||||
dusk:"",
|
|
||||||
history:[ ],
|
|
||||||
};
|
|
||||||
|
|
||||||
// Status
|
|
||||||
result = UNPACK.u16(bytes, index);
|
|
||||||
index = result.index;
|
|
||||||
data.status = result.data;
|
|
||||||
|
|
||||||
// Token
|
|
||||||
for(let i = 0; i < 8; ++i) { data.token[i] = bytes[index++]; }
|
|
||||||
|
|
||||||
// Handles
|
|
||||||
result = UNPACK.string(bytes, index);
|
|
||||||
index = result.index;
|
|
||||||
data.dawn = result.data;
|
|
||||||
|
|
||||||
result = UNPACK.string(bytes, index);
|
|
||||||
index = result.index;
|
|
||||||
data.dusk = result.data;
|
|
||||||
|
|
||||||
// Pieces
|
|
||||||
result = UNPACK.u16(bytes, index);
|
|
||||||
index = result.index;
|
|
||||||
let history_length = result.data;
|
|
||||||
|
|
||||||
for(let i = 0; i < history_length; ++i) {
|
|
||||||
result = UNPACK.u16(bytes, index);
|
|
||||||
index = result.index;
|
|
||||||
|
|
||||||
data.history.push(new GAME.Play(
|
|
||||||
result.data & 0xF,
|
|
||||||
(result.data >> 4) & 0x3F,
|
|
||||||
(result.data >> 10) & 0x3F,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.log("RECV Undefined " + code);
|
console.log("RECV Undefined " + code);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(data);
|
||||||
if(SCENE.message !== undefined) { SCENE.message(code, data) };
|
if(SCENE.message !== undefined) { SCENE.message(code, data) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
www/js/ui.js
24
www/js/ui.js
@ -163,22 +163,31 @@ const UI = {
|
|||||||
for(let r = 0; r < records.length; ++r) {
|
for(let r = 0; r < records.length; ++r) {
|
||||||
let buttons = [ ];
|
let buttons = [ ];
|
||||||
let join_callback = function() {
|
let join_callback = function() {
|
||||||
|
LOAD(SCENES.Game, {
|
||||||
|
token:this.token,
|
||||||
|
mode:INTERFACE.Mode.Player,
|
||||||
|
});
|
||||||
MESSAGE_SESSION_JOIN(this.token, true);
|
MESSAGE_SESSION_JOIN(this.token, true);
|
||||||
};
|
};
|
||||||
join_callback = join_callback.bind({token: records[r].token});
|
join_callback = join_callback.bind({token: records[r].token});
|
||||||
|
|
||||||
let spectate_callback = function() {
|
let spectate_callback = function() {
|
||||||
|
LOAD(SCENES.Game, {
|
||||||
|
token:this.token,
|
||||||
|
mode:INTERFACE.Mode.Review,
|
||||||
|
});
|
||||||
MESSAGE_SESSION_JOIN(this.token, false);
|
MESSAGE_SESSION_JOIN(this.token, false);
|
||||||
};
|
};
|
||||||
spectate_callback = spectate_callback.bind({token: records[r].token});
|
spectate_callback = spectate_callback.bind({token: records[r].token});
|
||||||
|
|
||||||
if(records[r].player) {
|
if(records[r].player) {
|
||||||
buttons.push(UI.button("Resume", join_callback));
|
buttons.push(UI.button("Resume", join_callback));
|
||||||
|
buttons.push(UI.button("Review", spectate_callback));
|
||||||
} else {
|
} else {
|
||||||
if(sessionStorage.getItem("auth") !== null && (records[r].dawn == "" || records[r].dusk == "")) {
|
if(sessionStorage.getItem("auth") !== null && (records[r].dawn == "" || records[r].dusk == "")) {
|
||||||
buttons.push(UI.button("Join", join_callback));
|
buttons.push(UI.button("Join", join_callback));
|
||||||
}
|
}
|
||||||
buttons.push(UI.button("Spectate", spectate_callback));
|
buttons.push(UI.button("View", spectate_callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
let dawn = UI.text(records[r].dawn);
|
let dawn = UI.text(records[r].dawn);
|
||||||
@ -210,6 +219,10 @@ const UI = {
|
|||||||
for(let r = 0; r < records.length; ++r) {
|
for(let r = 0; r < records.length; ++r) {
|
||||||
let buttons = [ ];
|
let buttons = [ ];
|
||||||
let join_callback = function() {
|
let join_callback = function() {
|
||||||
|
LOAD(SCENES.Game, {
|
||||||
|
token:this.token,
|
||||||
|
mode:INTERFACE.Mode.Player,
|
||||||
|
});
|
||||||
MESSAGE_SESSION_JOIN(this.token, true);
|
MESSAGE_SESSION_JOIN(this.token, true);
|
||||||
};
|
};
|
||||||
join_callback = join_callback.bind({token: records[r].token});
|
join_callback = join_callback.bind({token: records[r].token});
|
||||||
@ -243,10 +256,11 @@ const UI = {
|
|||||||
for(let r = 0; r < records.length; ++r) {
|
for(let r = 0; r < records.length; ++r) {
|
||||||
let buttons = [ ];
|
let buttons = [ ];
|
||||||
let view_callback = function() {
|
let view_callback = function() {
|
||||||
MESSAGE_COMPOSE([
|
LOAD(SCENES.Game, {
|
||||||
PACK.u16(OpCode.GameHistory),
|
token:this.token,
|
||||||
this.token,
|
mode:INTERFACE.Mode.Review,
|
||||||
]);
|
});
|
||||||
|
MESSAGE_SESSION_JOIN(this.token, false);
|
||||||
};
|
};
|
||||||
view_callback = view_callback.bind({token: records[r].token});
|
view_callback = view_callback.bind({token: records[r].token});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user