Fix stuff implementing the re-synchronization after connection loss
This commit is contained in:
parent
19aa959c64
commit
81216e3f01
8 changed files with 119 additions and 89 deletions
|
@ -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 {
|
||||
|
|
|
@ -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}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
});
|
||||
}
|
||||
|
||||
|
|
108
js/Games.js
108
js/Games.js
|
@ -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');
|
||||
}
|
||||
|
|
32
js/Room.js
32
js/Room.js
|
@ -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);});
|
||||
}
|
||||
|
|
14
js/Table.js
14
js/Table.js
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue