mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-14 08:01:38 +01:00
save stateAfterShow as part of serialized game state. Fixes problem
where games with more than two devices would hang because server.c code was dropping messages that comms.c code thought were good and so ACK'd preventing them from being sent again. They were being dropped because the game was in the wrong state after displaying a move-made dialog because the state it was to move to after doing that display had not been saved.
This commit is contained in:
parent
0eec455119
commit
4b75174170
2 changed files with 28 additions and 23 deletions
|
@ -31,6 +31,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define STREAM_VERS_SERVER_SAVES_TOSHOW 0x10
|
||||
#define STREAM_VERS_PLAYERDICTS 0x0F
|
||||
#define STREAM_SAVE_PREVMOVE 0x0E /* server saves prev move explanation */
|
||||
#define STREAM_VERS_ROBOTIQ STREAM_SAVE_PREVMOVE /* robots have different smarts */
|
||||
|
@ -51,7 +52,7 @@ extern "C" {
|
|||
#define STREAM_VERS_41B4 0x02
|
||||
#define STREAM_VERS_405 0x01
|
||||
|
||||
#define CUR_STREAM_VERS STREAM_VERS_PLAYERDICTS
|
||||
#define CUR_STREAM_VERS STREAM_VERS_SERVER_SAVES_TOSHOW
|
||||
|
||||
typedef struct LocalPlayer {
|
||||
XP_UCHAR* name;
|
||||
|
|
|
@ -75,20 +75,17 @@ typedef struct ServerVolatiles {
|
|||
void* turnChangeData;
|
||||
GameOverListener gameOverListener;
|
||||
void* gameOverData;
|
||||
XW_State stateAfterShow; /* do I need to serialize this? What if
|
||||
someone quits before I can show the
|
||||
scores? PENDING(ehouse) */
|
||||
XP_Bool showPrevMove;
|
||||
} ServerVolatiles;
|
||||
|
||||
typedef struct ServerNonvolatiles {
|
||||
XP_U8 nDevices;
|
||||
XW_State gameState;
|
||||
XW_State stateAfterShow;
|
||||
XP_S8 currentTurn; /* invalid when game is over */
|
||||
XP_U8 pendingRegistrations;
|
||||
XP_Bool showRobotScores;
|
||||
XP_Bool sortNewTiles;
|
||||
|
||||
#ifdef XWFEATURE_SLOW_ROBOT
|
||||
XP_U16 robotThinkMin, robotThinkMax; /* not saved (yet) */
|
||||
#endif
|
||||
|
@ -177,7 +174,7 @@ getStateStr( XW_State st )
|
|||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
logNewState( XW_State old, XW_State newst )
|
||||
{
|
||||
|
@ -258,46 +255,52 @@ server_make( MPFORMAL ModelCtxt* model, CommsCtxt* comms, XW_UtilCtxt* util )
|
|||
static void
|
||||
getNV( XWStreamCtxt* stream, ServerNonvolatiles* nv, XP_U16 nPlayers )
|
||||
{
|
||||
XP_U16 i;
|
||||
XP_U16 ii;
|
||||
XP_U16 version = stream_getVersion( stream );
|
||||
|
||||
/* This should go away when stream format changes */
|
||||
(void)stream_getBits( stream, 3 ); /* was npassesinrow */
|
||||
if ( version < STREAM_VERS_SERVER_SAVES_TOSHOW ) {
|
||||
/* no longer used */
|
||||
(void)stream_getBits( stream, 3 ); /* was npassesinrow */
|
||||
}
|
||||
|
||||
nv->nDevices = (XP_U8)stream_getBits( stream, NDEVICES_NBITS );
|
||||
if ( stream_getVersion( stream ) > STREAM_VERS_41B4 ) {
|
||||
if ( version > STREAM_VERS_41B4 ) {
|
||||
++nv->nDevices;
|
||||
}
|
||||
|
||||
XP_ASSERT( XWSTATE_GAMEOVER < 1<<4 );
|
||||
nv->gameState = (XW_State)stream_getBits( stream, 4 );
|
||||
nv->gameState = (XW_State)stream_getBits( stream, XWSTATE_NBITS );
|
||||
if ( version >= STREAM_VERS_SERVER_SAVES_TOSHOW ) {
|
||||
nv->stateAfterShow = (XW_State)stream_getBits( stream, XWSTATE_NBITS );
|
||||
}
|
||||
|
||||
nv->currentTurn = (XP_S8)stream_getBits( stream, NPLAYERS_NBITS ) - 1;
|
||||
nv->pendingRegistrations = (XP_U8)stream_getBits( stream, NPLAYERS_NBITS );
|
||||
|
||||
for ( i = 0; i < nPlayers; ++i ) {
|
||||
nv->addresses[i].channelNo = (XP_PlayerAddr)stream_getBits( stream,
|
||||
16 );
|
||||
for ( ii = 0; ii < nPlayers; ++ii ) {
|
||||
nv->addresses[ii].channelNo =
|
||||
(XP_PlayerAddr)stream_getBits( stream, 16 );
|
||||
}
|
||||
} /* getNV */
|
||||
|
||||
static void
|
||||
putNV( XWStreamCtxt* stream, ServerNonvolatiles* nv, XP_U16 nPlayers )
|
||||
{
|
||||
XP_U16 i;
|
||||
XP_U16 ii;
|
||||
|
||||
stream_putBits( stream, 3, 0 ); /* was nPassesInRow */
|
||||
/* number of players is upper limit on device count */
|
||||
stream_putBits( stream, NDEVICES_NBITS, nv->nDevices-1 );
|
||||
|
||||
XP_ASSERT( XWSTATE_GAMEOVER < 1<<4 );
|
||||
stream_putBits( stream, 4, nv->gameState );
|
||||
stream_putBits( stream, XWSTATE_NBITS, nv->gameState );
|
||||
stream_putBits( stream, XWSTATE_NBITS, nv->stateAfterShow );
|
||||
|
||||
/* +1: make -1 (NOTURN) into a positive number */
|
||||
stream_putBits( stream, NPLAYERS_NBITS, nv->currentTurn+1 );
|
||||
stream_putBits( stream, NPLAYERS_NBITS, nv->pendingRegistrations );
|
||||
|
||||
for ( i = 0; i < nPlayers; ++i ) {
|
||||
stream_putBits( stream, 16, nv->addresses[i].channelNo );
|
||||
for ( ii = 0; ii < nPlayers; ++ii ) {
|
||||
stream_putBits( stream, 16, nv->addresses[ii].channelNo );
|
||||
}
|
||||
} /* putNV */
|
||||
|
||||
|
@ -851,7 +854,7 @@ showPrevScore( ServerCtxt* server )
|
|||
(void)util_userQuery( util, QUERY_ROBOT_MOVE, stream );
|
||||
stream_destroy( stream );
|
||||
}
|
||||
SETSTATE( server, server->vol.stateAfterShow );
|
||||
SETSTATE( server, server->nv.stateAfterShow );
|
||||
} /* showPrevScore */
|
||||
|
||||
XP_Bool
|
||||
|
@ -1073,7 +1076,7 @@ client_readInitialMessage( ServerCtxt* server, XWStreamCtxt* stream )
|
|||
stream_setVersion( stream, streamVersion );
|
||||
|
||||
gameID = stream_getU32( stream );
|
||||
XP_STATUSF( "read gameID of %lx; calling comms_setConnID", gameID );
|
||||
XP_LOGF( "read gameID of %lx; calling comms_setConnID", gameID );
|
||||
server->vol.gi->gameID = gameID;
|
||||
comms_setConnID( server->vol.comms, gameID );
|
||||
|
||||
|
@ -1671,7 +1674,7 @@ nextTurn( ServerCtxt* server, XP_S16 nxtTurn )
|
|||
if ( server->vol.showPrevMove ) {
|
||||
server->vol.showPrevMove = XP_FALSE;
|
||||
if ( server->nv.showRobotScores ) {
|
||||
server->vol.stateAfterShow = server->nv.gameState;
|
||||
server->nv.stateAfterShow = server->nv.gameState;
|
||||
SETSTATE( server, XWSTATE_NEED_SHOWSCORE );
|
||||
moreToDo = XP_TRUE;
|
||||
}
|
||||
|
@ -1769,7 +1772,7 @@ sendMoveTo( ServerCtxt* server, XP_U16 devIndex, XP_U16 turn,
|
|||
|
||||
if ( gi->timerEnabled ) {
|
||||
stream_putU16( stream, gi->players[turn].secondsUsed );
|
||||
XP_STATUSF("*** wrote secondsUsed for player %d: %d",
|
||||
XP_LOGF("%s: wrote secondsUsed for player %d: %d", __func__,
|
||||
turn, gi->players[turn].secondsUsed );
|
||||
} else {
|
||||
XP_ASSERT( gi->players[turn].secondsUsed == 0 );
|
||||
|
@ -1964,6 +1967,7 @@ reflectMove( ServerCtxt* server, XWStreamCtxt* stream )
|
|||
XWStreamCtxt* mvStream = NULL;
|
||||
|
||||
moveOk = XWSTATE_INTURN == server->nv.gameState;
|
||||
XP_ASSERT( moveOk ); /* message permanently lost if dropped here! */
|
||||
if ( moveOk ) {
|
||||
readMoveInfo( server, stream, &whoMoved, &isTrade, &newTiles,
|
||||
&tradedTiles, &isLegal ); /* modifies model */
|
||||
|
|
Loading…
Reference in a new issue