Follow move of 'logs' into PublicGame structure and start implementing re-sync protocol on the client side

This commit is contained in:
Tissevert 2020-01-20 22:58:57 +01:00
parent ef947f7942
commit 428e48f6f4
2 changed files with 77 additions and 46 deletions

View file

@ -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)
)
);
}

View file

@ -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});
}
});
}