Fix stuff implementing the re-synchronization after connection loss

This commit is contained in:
Tissevert 2020-01-25 10:56:55 +01:00
parent 19aa959c64
commit 81216e3f01
8 changed files with 119 additions and 89 deletions

View File

@ -11,7 +11,7 @@ function HandCard(name) {
return card;
function onClick() {
if(State.state.playing && State.state.step == "ToPlay") {
if(State.globalState.playing && State.globalState.step == "ToPlay") {
if(State.getSelected() != undefined) {
State.select(false);
} else {

View File

@ -17,7 +17,7 @@ function RiverCard(name) {
var withCard = State.getSelected().value.name;
State.select(false);
State.play(
State.state.step == 'ToPlay' ?
State.globalState.step == 'ToPlay' ?
{capture: [withCard, name]} : {choose: name}
);
}

View File

@ -5,7 +5,7 @@ import * as TurnedCard from GUI.Card.TurnedCard;
import * as Screen from GUI.Screen;
import {animate, catchUp, delay, getQueue} from GUI.Screen.Game.Animation;
import {
dom, init as initState, play, select, sets, state
dom, init as initState, play, select, sets, globalState
} from GUI.Screen.Game.State;
import Hanafuda;
import I18n;
@ -52,7 +52,7 @@ function fail(errorCode) {
}
function getSavedStates(gameID) {
var states = Save.get('games.message.Game#' + gameID);
var states = Save.get('games.state.Game#' + gameID);
return states != undefined ? Async.wrap(states) : fail('gameNotFound');
}
@ -117,13 +117,13 @@ function setGame(state) {
function handleStep(state) {
return function(f) {
handleTurnedCard(state, f);
if(state.step == "Scored") {
if(state.playing) {
if(globalState.step == "Scored") {
if(globalState.playing) {
askKoikoi(state, f);
} else {
theyScored(state, f);
}
} else if (state.step == "Over") {
} else if (globalState.step == "Over") {
gameEnd(state, f);
} else {
f();
@ -132,11 +132,11 @@ function handleStep(state) {
}
function handleTurnedCard(state, f) {
if(state.step == "Turned") {
if(globalState.step == "Turned") {
setTurned(state.public.step.contents);
} else {
if(state.step == "ToPlay" && state.public.playing == state.public.oyake) {
rest.className = ["card", "turn" + state.public.coordinates.turn].join(' ');
if(globalState.step == "ToPlay" && state.public.playing == state.public.oyake) {
dom.rest.className = ["card", "turn" + state.public.coordinates.turn].join(' ');
}
if(deck.lastChild.id != "rest") {
deck.removeChild(deck.lastChild);
@ -188,18 +188,18 @@ function applyDiff(state) {
function setStatus(game) {
Dom.clear(dom.status);
state.game = game;
state.step = game.public.step.tag;
if(game.public.coordinates.month != state.month) {
state.month = game.public.coordinates.month;
globalState.game = game;
globalState.step = game.public.step.tag;
if(game.public.coordinates.month != globalState.month) {
globalState.month = game.public.coordinates.month;
}
dom.status.appendChild(
Dom.make('li', {textContent: I18n.get('monthFlower')(I18n.get(state.month))})
Dom.make('li', {textContent: I18n.get('monthFlower')(I18n.get(globalState.month))})
);
var turn = null;
state.playing = Session.is(game.public.playing);
if(state.playing) {
sets.you.hand.dom.classList.toggle("yourTurn", state.step == "ToPlay");
globalState.playing = Session.is(game.public.playing);
if(globalState.playing) {
sets.you.hand.dom.classList.toggle("yourTurn", globalState.step == "ToPlay");
turn = I18n.get("yourTurn");
} else {
sets.you.hand.dom.classList.remove("yourTurn");
@ -246,8 +246,8 @@ function setTheirCards(game) {
}
function setTurned(cardName) {
state.turnedCard = TurnedCard.make(cardName);
if(state.playing) {
select(state.turnedCard);
globalState.turnedCard = TurnedCard.make(cardName);
if(globalState.playing) {
select(globalState.turnedCard);
}
}

View File

@ -59,8 +59,8 @@ function handleSource(movement, movingCards, side, cardLeft) {
} else {
var cardSet = {};
var name = cardLeft.card.value.name;
cardSet[name] = State.state.turnedCard || TurnedCard.make(name);
State.state.turnedCard = null;
cardSet[name] = State.globalState.turnedCard || TurnedCard.make(name);
State.globalState.turnedCard = null;
movingCards.push(
moveCard({card: cardSet, dom: State.dom.deck}, cardLeft.dest, cardLeft.card)
);
@ -70,7 +70,7 @@ function handleSource(movement, movingCards, side, cardLeft) {
function cardMoves(movement) {
var card;
var movingCards = [];
var side = (State.state.playing) ? 'you' : 'them';
var side = (State.globalState.playing) ? 'you' : 'them';
var cardLeft = handleCaptures(movement, movingCards, side);
handleSource(movement, movingCards, side, cardLeft);
return movingCards;

View File

@ -9,7 +9,7 @@ var dom = {
};
var selected;
var sets = {};
var state = {
var globalState = {
game: null,
playing: false,
step: null,
@ -25,7 +25,7 @@ return {
play: play,
select: select,
sets: sets,
state: state
globalState: globalState
};
function init() {
@ -64,7 +64,7 @@ function play(move) {
Messaging.send({
tag: "Play",
move: move,
onGame: state.game
onGame: globalState.game
});
}

View File

@ -5,8 +5,10 @@ import Session;
import Table;
import Time;
var states = Table.make(function(o) {return 0;});
states.load('games.state');
var metadata = Table.make(function(o) {return o.value.date;});
metadata.insertAll(Save.get('games.metadata') || {});
metadata.load('games.metadata');
initMessageHandlers();
return {
@ -14,29 +16,47 @@ return {
proposal: proposal
};
function makeMetadata(state) {
var sessionKey = Session.getKey();
return Time.timestamp({
vs: player(state.public.nextPlayer[sessionKey]),
yourTurn: state.public.playing == sessionKey
function initMessageHandlers() {
Messaging.addEventListener(["Game"], function(o) {
var gameID = o.state.public.coordinates.gameID;
pushState(gameID, o.state);
metadata.insert(gameID, getMetadata(o.state));
metadata.save('games.metadata');
});
Messaging.addEventListener(["LogIn"], function(o) {
var gamesAgainst = states.getAll(
function(game) {return isAgainst(game.value, o.from);}
);
gamesAgainst.forEach(function(game) {
Messaging.send({
tag: "Sync",
latestKnown: game.value.latest.public.coordinates,
to: o.from
});
});
});
Messaging.addEventListener(["Relay", "Sync"], function(o) {
var gameID = o.message.latestKnown.gameID;
var state = states.get(gameID);
switch(state != undefined && compare(state.latest, o.message.latestKnown)) {
case -1: Messaging.send({tag: "Yield", onGameID: gameID});
case 1: Messaging.send({tag: "Share", gameSave: state.latest});
}
});
Messaging.addEventListener(["Relay", "Yield"], function(o) {
var gameID = o.message.onGameID;
var state = states.get(gameID);
if(state != undefined && isAgainst(state, o.from)) {
Messaging.send({tag: "Share", gameSave: state.latest});
}
});
}
function proposal(playerID, yourTurn) {
metadata.insert(
playerID,
Time.timestamp({vs: player(playerID), yourTurn: yourTurn})
);
}
function pushState(gameID, state) {
var latestPath = "games.state." + gameID + ".latest";
var formerPath = "games.state." + gameID + ".former";
var former = Save.get(latestPath);
if(former != undefined) {
Save.set(formerPath, former);
}
Save.set(latestPath, state);
function isAgainst(state, playerID) {
return state.latest.public.nextPlayer[Session.getKey()] == playerID;
}
function compare(gameCoordinatesA, gameCoordinatesB) {
@ -53,29 +73,27 @@ function compare(gameCoordinatesA, gameCoordinatesB) {
}
}
function initMessageHandlers() {
Messaging.addEventListener(["Game"], function(o) {
var gameID = o.state.public.coordinates.gameID;
var metadata = makeMetadata(o.state);
pushState(gameID, o.state);
Save.set("games.metadata." + gameID, metadata);
metadata.insert(gameID, metadata);
function getMetadata(state) {
var sessionKey = Session.getKey();
return Time.timestamp({
vs: player(state.public.nextPlayer[sessionKey]),
yourTurn: state.public.playing == sessionKey
});
Messaging.addEventListener(["Relay", "Sync"], function(o) {
var gameID = o.message.latestKnown.gameID;
var latestKnownHere = Save.get("games.state." + gameID + ".latest");
switch(compare(latestKnownHere, o.message.latestKnown)) {
case -1: Messaging.send({tag: "Yield", onGameID: gameID});
case 1: Messaging.send({tag: "Sync", latestKnown: latestKnownHere});
}
});
Messaging.addEventListener(["Relay", "Yield"], function(o) {
var gameID = o.message.latestKnown.gameID;
var latestKnownHere = Save.get("games.message." + gameID + ".latest");
if(o.from == latestKnownHere.public.nextPlayer[Session.getKey()]) {
Messaging.send({tag: "Share", gameSave: latestKnownHere});
}
});
}
function proposal(playerID, yourTurn) {
metadata.insert(
playerID,
Time.timestamp({vs: player(playerID), yourTurn: yourTurn})
);
}
function pushState(gameID, newState) {
if(states.get(gameID) == undefined) {
states.insert(gameID, {});
}
var state = states.get(gameID);
state.former = state.latest;
state.latest = newState;
states.save('games.state');
}

View File

@ -14,19 +14,21 @@ function player(key) {
return {id: key, name: players.get(key)};
}
function initMessageHandlers() {
Messaging.addEventListener(["Okaeri"], function(o) {
players.insertAll(o.room);
});
Messaging.addEventListener(["Welcome"], function(o) {
players.insertAll(o.room);
});
Messaging.addEventListener(["LogIn"], function(o) {
if(!Session.is(o.from)) {
players.insert(o.from, o.as);
}
});
Messaging.addEventListener(["LogOut"], function(o) {
players.remove(o.from);
});
function enterAll(o) {
for(key in o) {
enterPlayer(key, o[key]);
}
}
function enterPlayer(key, name) {
if(!Session.is(key)) {
players.insert(key, name);
}
}
function initMessageHandlers() {
Messaging.addEventListener(["Okaeri"], function(o) {enterAll(o.room);});
Messaging.addEventListener(["Welcome"], function(o) {enterAll(o.room);});
Messaging.addEventListener(["LogIn"], function(o) {enterPlayer(o.from, o.as);});
Messaging.addEventListener(["LogOut"], function(o) {players.remove(o.from);});
}

View File

@ -1,3 +1,4 @@
import Save;
import of from UnitJS.Fun;
import {compare, of, proj} from UnitJS.Fun;
@ -8,7 +9,9 @@ function Table(sortCriterion) {
getAll: getAll,
insert: insert,
insertAll: insertAll,
remove: remove
load: load,
remove: remove,
save
};
function get(key) {
@ -22,7 +25,6 @@ function Table(sortCriterion) {
.sort(compare(sortCriterion));
}
function insert(key, value) {
items[key] = value;
}
@ -33,9 +35,17 @@ function Table(sortCriterion) {
}
}
function load(path) {
insertAll(Save.get(path) || {});
}
function remove(key) {
delete items[key];
}
function save(path) {
Save.set(path, items);
}
}
return {