Follow move of 'logs' into PublicGame structure and start implementing re-sync protocol on the client side
This commit is contained in:
parent
ef947f7942
commit
428e48f6f4
2 changed files with 77 additions and 46 deletions
|
@ -27,11 +27,11 @@ function init(gameID) {
|
|||
initMessageHandlers();
|
||||
Async.run(
|
||||
Async.bind(
|
||||
getSavedMessages(gameID),
|
||||
function(messages) {
|
||||
getSavedStates(gameID),
|
||||
function(states) {
|
||||
return Async.sequence(
|
||||
startSession(),
|
||||
previously(messages)
|
||||
previously(states)
|
||||
);
|
||||
}
|
||||
)
|
||||
|
@ -51,9 +51,9 @@ function fail(errorCode) {
|
|||
}
|
||||
}
|
||||
|
||||
function getSavedMessages(gameID) {
|
||||
var messages = Save.get('games.message.Game#' + gameID);
|
||||
return messages != undefined ? Async.wrap(messages) : fail('gameNotFound');
|
||||
function getSavedStates(gameID) {
|
||||
var states = Save.get('games.message.Game#' + gameID);
|
||||
return states != undefined ? Async.wrap(states) : fail('gameNotFound');
|
||||
}
|
||||
|
||||
function startSession() {
|
||||
|
@ -66,21 +66,21 @@ function startSession() {
|
|||
}
|
||||
}
|
||||
|
||||
function previously(messages) {
|
||||
if(messages.former != undefined && messages.latest.logs.length > 0) {
|
||||
function previously(states) {
|
||||
if(states.former != undefined && states.latest.logs.length > 0) {
|
||||
return Async.sequence(
|
||||
setGame(messages.former),
|
||||
handleGameMessage(messages.latest)
|
||||
setGame(states.former),
|
||||
handleGameMessage(states.latest)
|
||||
);
|
||||
} else {
|
||||
return setGame(messages.latest);
|
||||
return setGame(states.latest);
|
||||
}
|
||||
}
|
||||
|
||||
function initMessageHandlers() {
|
||||
window.addEventListener('focus', catchUp);
|
||||
Messaging.addEventListener(["Game"], function(o) {
|
||||
delay(handleGameMessage(o));
|
||||
delay(handleGameMessage(o.state));
|
||||
if(document.hasFocus() && getQueue().length == 1) {
|
||||
catchUp();
|
||||
} else {
|
||||
|
@ -89,54 +89,54 @@ function initMessageHandlers() {
|
|||
});
|
||||
}
|
||||
|
||||
function handleGameMessage(o) {
|
||||
if(o.state.public.coordinates.turn == 0) {
|
||||
if(o.logs.length > 0) { // but still some logs, from the previous round
|
||||
return Async.sequence(applyDiff(o), setGame(o)); // so play the diff, then set the new round
|
||||
function handleGameMessage(state) {
|
||||
if(state.public.coordinates.turn == 0) {
|
||||
if(state.logs.length > 0) { // but still some logs, from the previous round
|
||||
return Async.sequence(applyDiff(state), setGame(state)); // so play the diff, then set the new round
|
||||
} else {
|
||||
return setGame(o); // directly set a whole new game
|
||||
return setGame(state); // directly set a whole new game
|
||||
}
|
||||
} else {
|
||||
return applyDiff(o);
|
||||
return applyDiff(state);
|
||||
}
|
||||
}
|
||||
|
||||
function setGame(o) {
|
||||
function setGame(state) {
|
||||
return function(f) {
|
||||
setStatus(o.state);
|
||||
setCaptures(o.state);
|
||||
setStatus(state);
|
||||
setCaptures(state);
|
||||
[
|
||||
[sets.river, o.state.public.river, RiverCard.make],
|
||||
[sets.you.hand, o.state.playerHand, HandCard.make]
|
||||
[sets.river, state.public.river, RiverCard.make],
|
||||
[sets.you.hand, state.playerHand, HandCard.make]
|
||||
].forEach(function(args) {setCardSet.apply(null, args)});
|
||||
setTheirCards(o.state);
|
||||
handleStep(o)(f);
|
||||
setTheirCards(state);
|
||||
handleStep(state)(f);
|
||||
};
|
||||
}
|
||||
|
||||
function handleStep(o) {
|
||||
function handleStep(state) {
|
||||
return function(f) {
|
||||
handleTurnedCard(o, f);
|
||||
handleTurnedCard(state, f);
|
||||
if(state.step == "Scored") {
|
||||
if(state.playing) {
|
||||
askKoikoi(o, f);
|
||||
askKoikoi(state, f);
|
||||
} else {
|
||||
theyScored(o, f);
|
||||
theyScored(state, f);
|
||||
}
|
||||
} else if (state.step == "Over") {
|
||||
gameEnd(o, f);
|
||||
gameEnd(state, f);
|
||||
} else {
|
||||
f();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function handleTurnedCard(o, f) {
|
||||
function handleTurnedCard(state, f) {
|
||||
if(state.step == "Turned") {
|
||||
setTurned(o.state.public.step.contents);
|
||||
setTurned(state.public.step.contents);
|
||||
} else {
|
||||
if(state.step == "ToPlay" && o.state.public.playing == o.state.public.oyake) {
|
||||
rest.className = ["card", "turn" + o.state.public.coordinates.turn].join(' ');
|
||||
if(state.step == "ToPlay" && state.public.playing == state.public.oyake) {
|
||||
rest.className = ["card", "turn" + state.public.coordinates.turn].join(' ');
|
||||
}
|
||||
if(deck.lastChild.id != "rest") {
|
||||
deck.removeChild(deck.lastChild);
|
||||
|
@ -144,7 +144,7 @@ function handleTurnedCard(o, f) {
|
|||
}
|
||||
}
|
||||
|
||||
function askKoikoi(o, f) {
|
||||
function askKoikoi(state, f) {
|
||||
Screen.dialog({
|
||||
text: I18n.get('youScored'),
|
||||
answers: [
|
||||
|
@ -154,21 +154,21 @@ function askKoikoi(o, f) {
|
|||
});
|
||||
}
|
||||
|
||||
function theyScored(o, f) {
|
||||
function theyScored(state, f) {
|
||||
Screen.dialog({
|
||||
text: I18n.get('theyScored')(players.get(o.state.public.playing)),
|
||||
text: I18n.get('theyScored')(players.get(state.public.playing)),
|
||||
answers: [
|
||||
{label: 'ok', action: f}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
function gameEnd(o, f) {
|
||||
function gameEnd(state, f) {
|
||||
var winner, maxScore;
|
||||
for(var key in o.state.public.scores) {
|
||||
if(maxScore == undefined || o.state.public.scores[key] > maxScore) {
|
||||
for(var key in state.public.scores) {
|
||||
if(maxScore == undefined || state.public.scores[key] > maxScore) {
|
||||
winner = key;
|
||||
maxScore = o.state.public.scores[key];
|
||||
maxScore = state.public.scores[key];
|
||||
}
|
||||
}
|
||||
Screen.dialog({
|
||||
|
@ -177,11 +177,11 @@ function gameEnd(o, f) {
|
|||
});
|
||||
}
|
||||
|
||||
function applyDiff(o) {
|
||||
function applyDiff(state) {
|
||||
return Async.sequence.apply(null,
|
||||
o.logs.map(animate).concat(
|
||||
Async.apply(setStatus, o.state),
|
||||
handleStep(o)
|
||||
state.logs.map(animate).concat(
|
||||
Async.apply(setStatus, state),
|
||||
handleStep(state)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
33
js/Games.js
33
js/Games.js
|
@ -39,12 +39,43 @@ function pushMessage(gameID, message) {
|
|||
Save.set(latestPath, message);
|
||||
}
|
||||
|
||||
function compare(gameCoordinatesA, gameCoordinatesB) {
|
||||
if(gameCoordinatesA.month < gameCoordinatesB.month) {
|
||||
return -1;
|
||||
} else if(gameCoordinatesA.month > gameCoordinatesB.month) {
|
||||
return 1;
|
||||
} else if(gameCoordinatesA.turn < gameCoordinatesB.turn) {
|
||||
return -1;
|
||||
} else if(gameCoordinatesA.turn > gameCoordinatesB.turn) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function initMessageHandlers() {
|
||||
Messaging.addEventListener(["Game"], function(o) {
|
||||
var gameID = o.state.public.coordinates.gameID;
|
||||
var entry = makeEntry(o.state);
|
||||
pushMessage(gameID, o);
|
||||
pushMessage(gameID, o.state);
|
||||
Save.set("games.entry." + gameID, entry);
|
||||
entries.insert(gameID, entry);
|
||||
});
|
||||
|
||||
Messaging.addEventListener(["Relay", "Sync"], function(o) {
|
||||
var gameID = o.message.latestKnown.gameID;
|
||||
var latestKnownHere = Save.get("games.message." + 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});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue