Implement undo button for live games.
This commit is contained in:
parent
b848492c5a
commit
60b48e4708
@ -42,6 +42,7 @@ impl Game {
|
||||
|
||||
pub fn init(&mut self)
|
||||
{
|
||||
*self = Self::new();
|
||||
self.board.init();
|
||||
}
|
||||
|
||||
@ -73,7 +74,6 @@ impl Game {
|
||||
//
|
||||
|
||||
if valid {
|
||||
|
||||
// Move piece on board.
|
||||
if match play.source {
|
||||
0 | 2 => {
|
||||
|
@ -23,7 +23,7 @@ pub struct Session {
|
||||
pub time:u64,
|
||||
pub chain_id:usize,
|
||||
|
||||
pub undo:Option<u8>,
|
||||
pub undo:u8,
|
||||
}
|
||||
impl Session {
|
||||
pub fn get_connections(&self) -> Vec<(u32, u8)>
|
||||
|
@ -637,8 +637,6 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
|
||||
| GameMessageData::PlayDrop(turn, from, to)
|
||||
| GameMessageData::PlayAlt(turn, from, to)
|
||||
=> {
|
||||
println!("HERE");
|
||||
|
||||
if !session.game.is_complete() {
|
||||
if (user_id == Some(session.p_dawn.user) && session.game.turn & 1 == 0)
|
||||
|| (user_id == Some(session.p_dusk.user) && session.game.turn & 1 == 1) {
|
||||
@ -653,8 +651,6 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
|
||||
from, to,
|
||||
};
|
||||
|
||||
println!("play {} {} {}", play.source, play.from, play.to);
|
||||
|
||||
if session.game.process(&play).is_ok() {
|
||||
// Commit play to history
|
||||
app.filesystem.session_history_push(session.id, play).ok();
|
||||
@ -670,6 +666,8 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
|
||||
// Send status to players.
|
||||
send_user_status.push(session.p_dawn.user);
|
||||
send_user_status.push(session.p_dusk.user);
|
||||
|
||||
session.undo = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -677,11 +675,59 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
|
||||
}
|
||||
|
||||
GameMessageData::Undo(turn, _) => {
|
||||
if !session.game.is_complete() {
|
||||
if (user_id == Some(session.p_dawn.user) && session.game.turn & 1 == 0)
|
||||
|| (user_id == Some(session.p_dusk.user) && session.game.turn & 1 == 1) {
|
||||
if turn == session.game.turn {
|
||||
// Request or commit undo
|
||||
use packet::PacketGameMessage;
|
||||
|
||||
if session.game.turn > 0 && !session.game.is_complete() {
|
||||
let player = if user_id == Some(session.p_dawn.user) { 1 }
|
||||
else if user_id == Some(session.p_dusk.user) { 2 }
|
||||
else { 0 };
|
||||
|
||||
if player != 0 {
|
||||
if turn == session.game.turn && (session.undo & player) == 0 {
|
||||
if session.undo == 0 {
|
||||
|
||||
// Send undo request to opposing player
|
||||
let packet = GameMessageData::Undo(turn, 0);
|
||||
|
||||
if player == 1 {
|
||||
for cid in &session.p_dusk.connections {
|
||||
packets.push(QRPacket::new(
|
||||
*cid,
|
||||
QRPacketData::GameMessage(PacketGameMessage::with(packet))
|
||||
));
|
||||
}
|
||||
} else {
|
||||
for cid in &session.p_dawn.connections {
|
||||
packets.push(QRPacket::new(
|
||||
*cid,
|
||||
QRPacketData::GameMessage(PacketGameMessage::with(packet))
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
session.undo |= player;
|
||||
} else {
|
||||
// Send undo command to clients
|
||||
let revert_count = if session.game.turn > 1 && session.undo == (1 << (session.game.turn & 1)) { 2 } else { 1 };
|
||||
|
||||
for _ in 0..revert_count {
|
||||
session.game.history.pop();
|
||||
app.filesystem.session_history_pop(session.id).ok();
|
||||
}
|
||||
session.game.apply_history(&session.game.history.clone()).ok();
|
||||
|
||||
let packet = GameMessageData::Undo(session.game.turn, 1);
|
||||
|
||||
// Send undo request to opposing player
|
||||
for (cid, _) in session.get_connections() {
|
||||
packets.push(QRPacket::new(
|
||||
cid,
|
||||
QRPacketData::GameMessage(PacketGameMessage::with(packet))
|
||||
));
|
||||
}
|
||||
|
||||
session.undo = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -691,6 +737,8 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
|
||||
if !session.game.is_complete() {
|
||||
if (user_id == Some(session.p_dawn.user) && session.game.turn & 1 == 0)
|
||||
|| (user_id == Some(session.p_dusk.user) && session.game.turn & 1 == 1) {
|
||||
|
||||
session.undo = 0;
|
||||
|
||||
// Forward messsage to all clients
|
||||
for (cid, _) in session.get_connections() {
|
||||
@ -818,7 +866,7 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
|
||||
time:std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u64,
|
||||
chain_id,
|
||||
|
||||
undo:None,
|
||||
undo:0,
|
||||
};
|
||||
session.game.init();
|
||||
|
||||
@ -930,11 +978,12 @@ fn generate_game_state(app:&App, session:&Session) -> protocol::PacketGameStateR
|
||||
if let Some(user) = app.get_user_by_id(session.p_dusk.user) {
|
||||
response.dusk_handle = user.handle.clone();
|
||||
}
|
||||
|
||||
response.dawn_online = session.p_dawn.connections.len() > 0;
|
||||
response.dusk_online = session.p_dusk.connections.len() > 0;
|
||||
response.spectators = session.connections.len() as u32;
|
||||
|
||||
response.undo = session.undo;
|
||||
|
||||
// Get history
|
||||
response.history = session.game.history.clone();
|
||||
|
||||
|
@ -35,6 +35,11 @@ impl PacketGameMessage {
|
||||
data:GameMessageData::Error,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with(data:GameMessageData) -> Self
|
||||
{
|
||||
Self { data }
|
||||
}
|
||||
}
|
||||
impl Packet for PacketGameMessage {
|
||||
type Data = Self;
|
||||
@ -63,8 +68,8 @@ impl Packet for PacketGameMessage {
|
||||
),
|
||||
|
||||
GMSG_UNDO => GameMessageData::Undo(
|
||||
((data >> 8) & 0xFFFF) as u16,
|
||||
((data >> 24) & 0x1) as u8,
|
||||
((data >> 9) & 0xFFFF) as u16,
|
||||
((data >> 8) & 0x1) as u8,
|
||||
),
|
||||
|
||||
GMSG_RETIRE => GameMessageData::Resign,
|
||||
@ -111,8 +116,8 @@ impl Packet for PacketGameMessage {
|
||||
|
||||
GameMessageData::Undo(turn, state) => {
|
||||
GMSG_UNDO as u64
|
||||
| ((turn as u64) << 8)
|
||||
| ((state as u64) << 24)
|
||||
| ((state as u64) << 8)
|
||||
| ((turn as u64) << 9)
|
||||
}
|
||||
GameMessageData::Resign => {
|
||||
GMSG_RETIRE as u64
|
||||
|
@ -43,11 +43,15 @@ pub struct PacketGameStateResponse {
|
||||
pub status:u16,
|
||||
pub token:SessionToken,
|
||||
pub player:u8,
|
||||
|
||||
pub undo:u8,
|
||||
|
||||
pub dawn_handle:String,
|
||||
pub dusk_handle:String,
|
||||
pub dawn_online:bool,
|
||||
pub dusk_online:bool,
|
||||
pub spectators:u32,
|
||||
|
||||
pub history:Vec<Play>,
|
||||
}
|
||||
impl PacketGameStateResponse {
|
||||
@ -57,11 +61,15 @@ impl PacketGameStateResponse {
|
||||
status:0,
|
||||
token:SessionToken::default(),
|
||||
player:2,
|
||||
|
||||
undo:0,
|
||||
|
||||
dawn_handle:String::new(),
|
||||
dusk_handle:String::new(),
|
||||
dawn_online:false,
|
||||
dusk_online:false,
|
||||
spectators:0,
|
||||
|
||||
history:Vec::new(),
|
||||
}
|
||||
}
|
||||
@ -84,6 +92,7 @@ impl Packet for PacketGameStateResponse {
|
||||
flags |= self.player as u16;
|
||||
flags |= (self.dawn_online as u16) << 2;
|
||||
flags |= (self.dusk_online as u16) << 3;
|
||||
flags |= (self.undo as u16) << 8;
|
||||
|
||||
[
|
||||
pack_u16(self.status),
|
||||
|
@ -204,7 +204,7 @@ impl FileSystem {
|
||||
time,
|
||||
chain_id:0,
|
||||
|
||||
undo:None,
|
||||
undo:0,
|
||||
})
|
||||
} else { Err(()) }
|
||||
}
|
||||
@ -216,8 +216,6 @@ impl FileSystem {
|
||||
let bucket_index = id & !HANDLE_BUCKET_MASK;
|
||||
let dir_index = id & HANDLE_BUCKET_MASK;
|
||||
|
||||
println!("A");
|
||||
|
||||
let bucket_path = Path::new(DIR_SESSION)
|
||||
.join(format!("{:08x}", bucket_index))
|
||||
.join(format!("{:08x}", dir_index));
|
||||
@ -241,6 +239,37 @@ impl FileSystem {
|
||||
} else { Err(()) }
|
||||
}
|
||||
|
||||
pub fn session_history_pop(&mut self, id:u32) -> Result<(),()>
|
||||
{
|
||||
let bucket_index = id & !HANDLE_BUCKET_MASK;
|
||||
let dir_index = id & HANDLE_BUCKET_MASK;
|
||||
|
||||
let bucket_path = Path::new(DIR_SESSION)
|
||||
.join(format!("{:08x}", bucket_index))
|
||||
.join(format!("{:08x}", dir_index));
|
||||
|
||||
// Open session history file
|
||||
if let Ok(mut file) = File::options().read(true).write(true).open(bucket_path.join(GENERIC_HISTORY)) {
|
||||
let mut buffer_size = [0u8; 2];
|
||||
|
||||
// Update length
|
||||
file.seek(SeekFrom::Start(0)).map_err(|_| ())?;
|
||||
file.read_exact(&mut buffer_size).map_err(|_| ())?;
|
||||
|
||||
let size = unpack_u16(&buffer_size, &mut 0);
|
||||
|
||||
if size > 0 {
|
||||
let new_size = size - 1;
|
||||
|
||||
file.seek(SeekFrom::Start(0)).map_err(|_| ())?;
|
||||
file.write(&pack_u16(new_size)).map_err(|_| ())?;
|
||||
file.set_len(2 + (2 * new_size as u64)).map_err(|_| ())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
} else { Err(()) }
|
||||
}
|
||||
|
||||
pub fn session_history_fetch(&mut self, id:u32) -> Result<Vec<Play>,()>
|
||||
{
|
||||
let mut result = Vec::new();
|
||||
|
@ -3,7 +3,7 @@ span.c_dawn{color:#ffe082;}
|
||||
span.c_dusk{color:#f6a1bd;}
|
||||
span.bold{font-weight:bold;}
|
||||
|
||||
button#button-resign.warn {
|
||||
button.warn {
|
||||
background-color:#471414;
|
||||
color:#e0e0e0;
|
||||
}
|
||||
|
@ -202,13 +202,13 @@ const INTERFACE = {
|
||||
}
|
||||
}
|
||||
|
||||
if(initial_hover != INTERFACE_DATA.hover) { INTERFACE.step(); }
|
||||
if(initial_hover != INTERFACE_DATA.hover) { INTERFACE.game_step(); }
|
||||
},
|
||||
|
||||
unhover() {
|
||||
let redraw = (INTERFACE_DATA.hover !== null);
|
||||
INTERFACE_DATA.hover = null;
|
||||
if(redraw) { INTERFACE.step(); }
|
||||
if(redraw) { INTERFACE.game_step(); }
|
||||
},
|
||||
|
||||
click(event) {
|
||||
@ -326,7 +326,7 @@ const INTERFACE = {
|
||||
} break;
|
||||
}
|
||||
|
||||
INTERFACE.step();
|
||||
INTERFACE.game_step();
|
||||
},
|
||||
|
||||
contextmenu() {
|
||||
@ -341,7 +341,7 @@ const INTERFACE = {
|
||||
if(INTERFACE.Ui.match_select(INTERFACE_DATA.hover, INTERFACE_DATA.select)) {
|
||||
INTERFACE_DATA.select = null;
|
||||
INTERFACE_DATA.alt_mode = false;
|
||||
INTERFACE.step();
|
||||
INTERFACE.game_step();
|
||||
} else {
|
||||
INTERFACE.click({button:0});
|
||||
}
|
||||
@ -381,6 +381,46 @@ const INTERFACE = {
|
||||
INTERFACE_DATA.Render.pool_offset = INTERFACE_DATA.Render.offset.x + Math.floor(INTERFACE.PoolOffset * gui_scale);
|
||||
},
|
||||
|
||||
game_step() {
|
||||
if(INTERFACE_DATA === null) return;
|
||||
|
||||
if(GAME_DATA.turn == 0) {
|
||||
INTERFACE_DATA.Ui.request_undo = 0;
|
||||
}
|
||||
|
||||
switch(INTERFACE_DATA.mode) {
|
||||
case INTERFACE.Mode.Player: {
|
||||
let b_resign = document.getElementById("button-resign");
|
||||
if(GAME_DATA.state.code == 0 && (GAME_DATA.turn & 1) == INTERFACE_DATA.player) {
|
||||
b_resign.removeAttribute("disabled");
|
||||
} else {
|
||||
b_resign.setAttribute("disabled", "");
|
||||
}
|
||||
|
||||
let b_undo = document.getElementById("button-undo");
|
||||
if(GAME_DATA.turn == 0 || INTERFACE_DATA.Ui.request_undo == 1) {
|
||||
b_undo.setAttribute("disabled", "");
|
||||
b_undo.removeAttribute("class");
|
||||
} else {
|
||||
b_undo.removeAttribute("disabled");
|
||||
|
||||
if(INTERFACE_DATA.Ui.request_undo == 2) {
|
||||
b_undo.setAttribute("class", "warn");
|
||||
} else {
|
||||
b_undo.removeAttribute("class");
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case INTERFACE.Mode.Review: {
|
||||
document.getElementById("indicator-turn").innerText = INTERFACE_DATA.Replay.turn + " / " + INTERFACE_DATA.Game.history.length;
|
||||
document.getElementById("turn-slider").setAttribute("max", INTERFACE_DATA.Game.history.length);
|
||||
} break;
|
||||
}
|
||||
|
||||
INTERFACE.step();
|
||||
},
|
||||
|
||||
step() {
|
||||
if(INTERFACE_DATA === null) return;
|
||||
|
||||
@ -389,15 +429,6 @@ const INTERFACE = {
|
||||
if(INTERFACE_DATA.Timeout.draw === null) {
|
||||
INTERFACE.draw();
|
||||
}
|
||||
|
||||
if(INTERFACE_DATA.mode == INTERFACE.Mode.Player) {
|
||||
let b_resign = document.getElementById("button-resign");
|
||||
if(GAME_DATA.state.code == 0 && (GAME_DATA.turn & 1) == INTERFACE_DATA.player) {
|
||||
b_resign.removeAttribute("disabled");
|
||||
} else {
|
||||
b_resign.setAttribute("disabled", "");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
draw() {
|
||||
@ -1154,7 +1185,7 @@ const INTERFACE = {
|
||||
},
|
||||
|
||||
Ui: {
|
||||
request_undo:false,
|
||||
request_undo:0,
|
||||
resign_warn:false,
|
||||
},
|
||||
|
||||
@ -1202,7 +1233,7 @@ const INTERFACE = {
|
||||
|
||||
switch(INTERFACE_DATA.mode) {
|
||||
case INTERFACE.Mode.Local: {
|
||||
INTERFACE.step();
|
||||
INTERFACE.game_step();
|
||||
} break;
|
||||
}
|
||||
} else {
|
||||
@ -1246,11 +1277,29 @@ const INTERFACE = {
|
||||
},
|
||||
|
||||
undo() {
|
||||
INTERFACE_DATA.Game.auto = null;
|
||||
if(INTERFACE_DATA.Game.history.length > 0) {
|
||||
INTERFACE_DATA.Replay.turn = INTERFACE_DATA.Game.history.length + 1;
|
||||
INTERFACE_DATA.Game.history.pop();
|
||||
INTERFACE.replay_jump(INTERFACE_DATA.Game.history.length, false);
|
||||
switch(INTERFACE_DATA.mode) {
|
||||
case INTERFACE.Mode.Local: {
|
||||
INTERFACE_DATA.Game.auto = null;
|
||||
if(INTERFACE_DATA.Game.history.length > 0) {
|
||||
INTERFACE_DATA.Replay.turn = INTERFACE_DATA.Game.history.length + 1;
|
||||
INTERFACE_DATA.Game.history.pop();
|
||||
INTERFACE.replay_jump(INTERFACE_DATA.Game.history.length, false);
|
||||
}
|
||||
} break;
|
||||
|
||||
case INTERFACE.Mode.Player: {
|
||||
let high = 0;
|
||||
let low = GameMessage.Undo | (GAME_DATA.turn << 9);
|
||||
|
||||
MESSAGE_COMPOSE([
|
||||
PACK.u16(OpCode.GameMessage),
|
||||
PACK.u32(high),
|
||||
PACK.u32(low),
|
||||
]);
|
||||
|
||||
INTERFACE_DATA.Ui.request_undo = 1;
|
||||
INTERFACE.game_step();
|
||||
} break;
|
||||
}
|
||||
},
|
||||
|
||||
@ -1261,6 +1310,13 @@ const INTERFACE = {
|
||||
case OpCode.GameState: {
|
||||
if(INTERFACE_DATA.mode == INTERFACE.Mode.Player) {
|
||||
INTERFACE_DATA.player = data.player;
|
||||
if(data.undo > 0) {
|
||||
if((1 << INTERFACE_DATA.player) == data.undo) {
|
||||
INTERFACE_DATA.Ui.request_undo = 1;
|
||||
} else {
|
||||
INTERFACE_DATA.Ui.request_undo = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INTERFACE_DATA.Game.history = data.history;
|
||||
@ -1269,6 +1325,7 @@ const INTERFACE = {
|
||||
INTERFACE_DATA.Session.Client.Dawn.online = data.dawn_online;
|
||||
INTERFACE_DATA.Session.Client.Dusk.online = data.dusk_online;
|
||||
INTERFACE_DATA.Session.Client.Spectators.count = data.spectators;
|
||||
|
||||
|
||||
if(INTERFACE_DATA.Game.history.length > 0) {
|
||||
if(INTERFACE_DATA.Replay.turn == 0) {
|
||||
@ -1319,23 +1376,26 @@ const INTERFACE = {
|
||||
} break;
|
||||
|
||||
case GameMessage.Undo: {
|
||||
switch(data.state) {
|
||||
case 0: {
|
||||
// Request undo
|
||||
if(data.turn == INTERFACE_DATA.Game.history.length) {
|
||||
INTERFACE_DATA.Ui.request_undo = true;
|
||||
}
|
||||
} break;
|
||||
case 1: {
|
||||
// Perform undo
|
||||
INTERFACE.undo();
|
||||
} break;
|
||||
if(data.state == 0) {
|
||||
// Request undo
|
||||
if(data.turn == INTERFACE_DATA.Game.history.length) {
|
||||
INTERFACE_DATA.Ui.request_undo = 2;
|
||||
INTERFACE.game_step();
|
||||
}
|
||||
} else {
|
||||
// Perform undo
|
||||
INTERFACE_DATA.Ui.request_undo = 0;
|
||||
|
||||
while(data.turn < INTERFACE_DATA.Game.history.length) {
|
||||
INTERFACE_DATA.Game.history.pop();
|
||||
}
|
||||
INTERFACE.replay_last(false);
|
||||
}
|
||||
} break;
|
||||
|
||||
case GameMessage.Resign: {
|
||||
GAME_DATA.state.code = GAME.Const.State.Resign;
|
||||
INTERFACE.step();
|
||||
INTERFACE.game_step();
|
||||
} break;
|
||||
|
||||
case GameMessage.Reaction: {
|
||||
@ -1379,7 +1439,7 @@ const INTERFACE = {
|
||||
case INTERFACE.Mode.Local: {
|
||||
INTERFACE.history_push(play, true);
|
||||
|
||||
INTERFACE.step();
|
||||
INTERFACE.game_step();
|
||||
|
||||
if(INTERFACE_DATA.Game.auto !== null && INTERFACE_DATA.Game.auto == (GAME_DATA.turn & 1)) {
|
||||
setTimeout(INTERFACE.auto_play, 1000);
|
||||
@ -1410,12 +1470,12 @@ const INTERFACE = {
|
||||
|
||||
rotate() {
|
||||
INTERFACE_DATA.rotate ^= 1;
|
||||
INTERFACE.step();
|
||||
INTERFACE.game_step();
|
||||
},
|
||||
|
||||
mirror() {
|
||||
INTERFACE_DATA.mirror = !INTERFACE_DATA.mirror;
|
||||
INTERFACE.step();
|
||||
INTERFACE.game_step();
|
||||
},
|
||||
|
||||
resign() {
|
||||
@ -1449,13 +1509,13 @@ const INTERFACE = {
|
||||
},
|
||||
|
||||
history_push(play, animate=false) {
|
||||
INTERFACE_DATA.Ui.request_undo = 0;
|
||||
|
||||
INTERFACE_DATA.Game.history.push(play);
|
||||
if(INTERFACE_DATA.mode == INTERFACE.Mode.Review) {
|
||||
document.getElementById("indicator-turn").innerText = INTERFACE_DATA.Replay.turn + " / " + INTERFACE_DATA.Game.history.length;
|
||||
document.getElementById("turn-slider").setAttribute("max", INTERFACE_DATA.Game.history.length);
|
||||
}
|
||||
if(INTERFACE_DATA.Replay.turn == INTERFACE_DATA.Game.history.length - 1) {
|
||||
INTERFACE.replay_next(animate);
|
||||
} else {
|
||||
INTERFACE.game_step();
|
||||
}
|
||||
},
|
||||
|
||||
@ -1519,7 +1579,7 @@ const INTERFACE = {
|
||||
document.getElementById("turn-slider").value = INTERFACE_DATA.Replay.turn;
|
||||
}
|
||||
|
||||
INTERFACE.step();
|
||||
INTERFACE.game_step();
|
||||
}
|
||||
},
|
||||
replay_first() {
|
||||
@ -1562,7 +1622,7 @@ const INTERFACE = {
|
||||
} else {
|
||||
INTERFACE_DATA.Game.auto = null;
|
||||
}
|
||||
INTERFACE.step();
|
||||
INTERFACE.game_step();
|
||||
},
|
||||
|
||||
auto_play() {
|
||||
|
@ -621,6 +621,10 @@ const SCENES = {
|
||||
// Bottom Buttons
|
||||
let buttons_bottom = [ ];
|
||||
if(data.mode == INTERFACE.Mode.Player) {
|
||||
let button_undo = UI.button(LANG("undo"), () => { INTERFACE.undo(); });
|
||||
button_undo.setAttribute("id", "button-undo");
|
||||
buttons_bottom.push(button_undo);
|
||||
|
||||
let button_resign = UI.button(LANG("resign"), () => { INTERFACE.resign(); });
|
||||
button_resign.setAttribute("id", "button-resign");
|
||||
buttons_bottom.push(button_resign);
|
||||
@ -651,7 +655,6 @@ const SCENES = {
|
||||
callback_resume = callback_resume.bind({
|
||||
token: data.token,
|
||||
});
|
||||
|
||||
buttons_top.push(UI.button(LANG("resume"), callback_resume));
|
||||
}
|
||||
} else {
|
||||
|
@ -263,11 +263,15 @@ function MESSAGE(event) {
|
||||
status:0,
|
||||
token:new Uint8Array(8),
|
||||
player:2,
|
||||
|
||||
undo:0,
|
||||
|
||||
dawn:"",
|
||||
dusk:"",
|
||||
dawn_online:false,
|
||||
dusk_online:false,
|
||||
spectators:0,
|
||||
|
||||
history:[ ],
|
||||
};
|
||||
|
||||
@ -284,10 +288,12 @@ function MESSAGE(event) {
|
||||
index = result.index;
|
||||
let flags = result.data;
|
||||
|
||||
data.player = flags & 0x3;
|
||||
data.player = flags & 3;
|
||||
data.dawn_online = (flags >> 2) & 1;
|
||||
data.dusk_online = (flags >> 3) & 1;
|
||||
|
||||
data.undo = (flags >> 8) & 3;
|
||||
|
||||
result = UNPACK.u32(bytes, index);
|
||||
index = result.index;
|
||||
data.spectators = result.data;
|
||||
@ -365,7 +371,8 @@ function MESSAGE(event) {
|
||||
} break;
|
||||
|
||||
case GameMessage.Undo: {
|
||||
data.state = dat & 0x3;
|
||||
data.state = dat & 0x1;
|
||||
data.turn = (dat >> 1) & 0xFFFF;
|
||||
} break;
|
||||
|
||||
case GameMessage.Resign: { } break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user