This commit is contained in:
Eric House 2023-11-30 11:03:27 -08:00
parent d021bb4029
commit c726477878
4 changed files with 106 additions and 78 deletions

View file

@ -135,7 +135,7 @@ static void relay_requestJoin_curses( void* closure, const XP_UCHAR* devID,
XP_U16 nPlayersTotal, XP_U16 seed, XP_U16 lang );
#endif
static XP_Bool rematch_and_save( CursesBoardGlobals* bGlobals, XP_U32* newGameID );
static XP_Bool rematch_and_save( CursesBoardGlobals* bGlobals, XP_U32* newGameIDP );
static void disposeBoard( CursesBoardGlobals* bGlobals );
static void initCP( CommonGlobals* cGlobals );
static CursesBoardGlobals* commonInit( CursesBoardState* cbState,
@ -198,7 +198,8 @@ cb_open( CursesBoardState* cbState, sqlite3_int64 rowid, const cb_dims* dims )
}
bool
cb_new( CursesBoardState* cbState, const cb_dims* dims, const CurGameInfo* gi )
cb_new( CursesBoardState* cbState, const cb_dims* dims, const CurGameInfo* gi,
XP_U32* newGameIDP )
{
CursesBoardGlobals* bGlobals = findOrOpen( cbState, -1, gi, NULL );
if ( !!bGlobals ) {
@ -206,7 +207,13 @@ cb_new( CursesBoardState* cbState, const cb_dims* dims, const CurGameInfo* gi )
enableDraw( bGlobals, dims );
setupBoard( bGlobals );
}
return NULL != bGlobals;
XP_Bool success = NULL != bGlobals;
if ( success && !!newGameIDP ) {
*newGameIDP = bGlobals->cGlobals.gi->gameID;
}
return success;
}
void
@ -687,10 +694,10 @@ cb_addInvite( CursesBoardState* cbState, XP_U32 gameID, XP_U16 forceChannel,
}
XP_Bool
cb_makeRematch( CursesBoardState* cbState, XP_U32 gameID, XP_U32* newGameID )
cb_makeRematch( CursesBoardState* cbState, XP_U32 gameID, XP_U32* newGameIDP )
{
CursesBoardGlobals* bGlobals = findOrOpenForGameID( cbState, gameID, NULL, NULL );
XP_Bool success = rematch_and_save( bGlobals, newGameID );
XP_Bool success = rematch_and_save( bGlobals, newGameIDP );
return success;
}
@ -998,7 +1005,7 @@ rematch_and_save_once( CursesBoardGlobals* bGlobals )
}
static XP_Bool
rematch_and_save( CursesBoardGlobals* bGlobals, XP_U32* newGameID )
rematch_and_save( CursesBoardGlobals* bGlobals, XP_U32* newGameIDP )
{
LOG_FUNC();
CommonGlobals* cGlobals = &bGlobals->cGlobals;
@ -1011,8 +1018,8 @@ rematch_and_save( CursesBoardGlobals* bGlobals, XP_U32* newGameID )
&cGlobals->cp, &bGlobalsNew->cGlobals.procs,
&bGlobalsNew->cGlobals.game, "newName" );
if ( success ) {
if ( !!newGameID ) {
*newGameID = bGlobalsNew->cGlobals.gi->gameID;
if ( !!newGameIDP ) {
*newGameIDP = bGlobalsNew->cGlobals.gi->gameID;
}
linuxSaveGame( &bGlobalsNew->cGlobals );
}

View file

@ -41,7 +41,8 @@ void cb_resized( CursesBoardState* cbState, const cb_dims* dims );
void cb_open( CursesBoardState* cbState, sqlite3_int64 rowid, const cb_dims* dims );
bool cb_new( CursesBoardState* cbState, const cb_dims* dims,
const CurGameInfo* gi /* optional: use from globals if unset */ );
const CurGameInfo* gi /* optional: use from globals if unset */,
XP_U32* newGameIDP );
void cb_newFor( CursesBoardState* cbState, const NetLaunchInfo* nli,
const cb_dims* dims );

View file

@ -315,7 +315,7 @@ handleNewGame( void* closure, int XP_UNUSED(key) )
const CurGameInfo* gi = &aGlobals->cag.params->pgi;
if ( !canMakeFromGI(gi) ) {
ca_inform( aGlobals->mainWin, "Unable to create game (check params?)" );
} else if ( !cb_new( aGlobals->cbState, &dims, NULL ) ) {
} else if ( !cb_new( aGlobals->cbState, &dims, NULL, NULL ) ) {
XP_ASSERT(0);
}
return XP_TRUE;
@ -1456,7 +1456,7 @@ castGid( cJSON* obj )
}
static XP_U32
gidFromObject( cJSON* obj )
gidFromObject( const cJSON* obj )
{
cJSON* tmp = cJSON_GetObjectItem( obj, "gid" );
XP_ASSERT( !!tmp );
@ -1464,14 +1464,38 @@ gidFromObject( cJSON* obj )
}
static void
addGIDToObject( cJSON* obj, XP_U32 gid, const char* key )
makeObjIfNot( cJSON** objp )
{
char buf[16];
sprintf( buf, "%08X", gid );
cJSON_AddStringToObject( obj, key, buf );
if ( NULL == *objp ) {
*objp = cJSON_CreateObject();
}
}
static XP_Bool
static void
addGIDToObject( cJSON** objp, XP_U32 gid, const char* key )
{
makeObjIfNot( objp );
char buf[16];
sprintf( buf, "%08X", gid );
cJSON_AddStringToObject( *objp, key, buf );
}
static void
addObjectToObject( cJSON** objp, const char* key, cJSON* value )
{
makeObjIfNot( objp );
cJSON_AddItemToObject( *objp, key, value );
}
static void
addSuccessToObject( cJSON** objp, XP_Bool success )
{
makeObjIfNot( objp );
cJSON_AddBoolToObject( *objp, "success", success );
}
static XP_U32
makeGameFromArgs( CursesAppGlobals* aGlobals, cJSON* args )
{
LaunchParams* params = aGlobals->cag.params;
@ -1481,8 +1505,6 @@ makeGameFromArgs( CursesAppGlobals* aGlobals, cJSON* args )
gi.boardSize = 15;
gi.traySize = 7;
gi.gameID = gidFromObject( args );
cJSON* tmp = cJSON_GetObjectItem( args, "nPlayers" );
XP_ASSERT( !!tmp );
gi.nPlayers = tmp->valueint;
@ -1512,12 +1534,13 @@ makeGameFromArgs( CursesAppGlobals* aGlobals, cJSON* args )
cb_dims dims;
figureDims( aGlobals, &dims );
LOGGI( &gi, "prior to cb_new call" );
bool success = cb_new( aGlobals->cbState, &dims, &gi );
XP_U32 newGameID;
bool success = cb_new( aGlobals->cbState, &dims, &gi, &newGameID );
XP_ASSERT( success );
gi_disposePlayerInfo( MPPARM(params->mpool) &gi );
return success;
return newGameID;
}
static XP_Bool
@ -1592,8 +1615,8 @@ getGamesStateForArgs( CursesAppGlobals* aGlobals, cJSON* args )
GameInfo gib;
if ( gdb_getGameInfoForGID( params->pDb, gameID, &gib ) ) {
cJSON* item = cJSON_CreateObject();
addGIDToObject( item, gameID, "gid" );
cJSON* item = NULL;
addGIDToObject( &item, gameID, "gid" );
cJSON_AddBoolToObject( item, "gameOver", gib.gameOver );
cJSON_AddNumberToObject( item, "nPending", gib.nPending );
cJSON_AddNumberToObject( item, "nMoves", gib.nMoves );
@ -1605,18 +1628,6 @@ getGamesStateForArgs( CursesAppGlobals* aGlobals, cJSON* args )
return result;
}
static cJSON*
makeBoolObj( const char* key, XP_Bool value )
{
cJSON* result = cJSON_CreateObject();
cJSON_AddBoolToObject( result, key, value );
/* char buf[1000]; */
/* if ( cJSON_PrintPreallocated( result, buf, sizeof(buf), 0 ) ) { */
/* XP_LOGFF( "(%s=>%s)=>%s", key, boolToStr(value), buf ); */
/* } */
return result;
}
static gboolean
on_incoming_signal( GSocketService* XP_UNUSED(service),
GSocketConnection* connection,
@ -1652,46 +1663,48 @@ on_incoming_signal( GSocketService* XP_UNUSED(service),
const char* cmdStr = cmd->valuestring;
cJSON* response = NULL;
XP_Bool success = XP_TRUE;
if ( 0 == strcmp( cmdStr, "quit" ) ) {
response = getGamesStateForArgs( aGlobals, args );
cJSON* gids = getGamesStateForArgs( aGlobals, args );
addObjectToObject( &response, "states", gids );
handleQuit( aGlobals, 0 );
} else if ( 0 == strcmp( cmdStr, "getMQTTDevID" ) ) {
MQTTDevID devID;
dvc_getMQTTDevID( params->dutil, NULL_XWE, &devID );
char buf[64];
formatMQTTDevID( &devID, buf, sizeof(buf) );
response = cJSON_CreateString( buf );
cJSON* devid = cJSON_CreateString( buf );
addObjectToObject( &response, "mqtt", devid );
} else if ( 0 == strcmp( cmdStr, "makeGame" ) ) {
XP_Bool success = makeGameFromArgs( aGlobals, args );
response = makeBoolObj( "success", success );
XP_U32 newGameID = makeGameFromArgs( aGlobals, args );
success = 0 != newGameID;
if ( success ) {
addGIDToObject( &response, newGameID, "newGid" );
}
} else if ( 0 == strcmp( cmdStr, "invite" ) ) {
XP_Bool success = inviteFromArgs( aGlobals, args );
response = makeBoolObj( "success", success );
success = inviteFromArgs( aGlobals, args );
} else if ( 0 == strcmp( cmdStr, "moveIf" ) ) {
XP_Bool success = moveifFromArgs( aGlobals, args );
response = makeBoolObj( "success", success );
success = moveifFromArgs( aGlobals, args );
} else if ( 0 == strcmp( cmdStr, "rematch" ) ) {
XP_U32 newGameID = rematchFromArgs( aGlobals, args );
if ( 0 != newGameID ) {
response = cJSON_CreateObject();
addGIDToObject( response, newGameID, "newGid" );
success = 0 != newGameID;
if ( success ) {
addGIDToObject( &response, newGameID, "newGid" );
}
} else if ( 0 == strcmp( cmdStr, "gamesState" ) ) {
response = getGamesStateForArgs( aGlobals, args );
} else {
success = XP_FALSE;
XP_ASSERT(0);
}
XP_ASSERT( !!response );
if ( !!response ) {
cJSON* tmp = cJSON_CreateObject();
cJSON_AddStringToObject( tmp, "cmd", cmdStr );
cJSON_AddNumberToObject( tmp, "key", key->valueint );
cJSON_AddItemToObject( tmp, "response", response );
addSuccessToObject( &response, success );
/*(void)*/cJSON_AddItemToArray( reply, tmp );
}
cJSON* tmp = cJSON_CreateObject();
cJSON_AddStringToObject( tmp, "cmd", cmdStr );
cJSON_AddNumberToObject( tmp, "key", key->valueint );
cJSON_AddItemToObject( tmp, "response", response );
/*(void)*/cJSON_AddItemToArray( reply, tmp );
}
cJSON_Delete( cmds ); /* this apparently takes care of all children */

View file

@ -37,11 +37,15 @@ class GuestGameInfo():
# Should be subclass of GuestGameInfo
class HostedInfo():
def __init__(self, guests, gid=None, invitesSent=False):
self.guestNames = guests
self.gid = gid and gid or '{:08X}'.format(random.randint(1, 0x7FFFFFFF))
assert len(self.gid) == 8
self.invitesSent = invitesSent
def __init__(self, guestNames, **kwargs):
self.guestNames = guestNames
self.gid = kwargs.get('gid')
self.needsInvite = kwargs.get('needsInvite', True)
def setGid(self, gid):
# set only once!
assert 8 == len(gid) and not self.gid
self.gid = gid
def __str__(self):
return 'gid: {}, guests: {}'.format(self.gid, self.guestNames)
@ -212,8 +216,11 @@ class Device():
def setDevID(self):
response = self._sendWaitReply('getMQTTDevID')
if response:
self.mqttDevID = response
mqttDevID = response and response.get('mqtt')
if mqttDevID:
self.mqttDevID = mqttDevID
else:
printError('no mqtt or no response')
def makeGames(self):
args = self.args
@ -222,9 +229,12 @@ class Device():
hostPosn = random.randint(0, nPlayers-1)
traySize = 0 == args.TRAY_SIZE and random.randint(7, 9) or args.TRAY_SIZE
self._sendWaitReply('makeGame', nPlayers=nPlayers, hostPosn=hostPosn,
gid=remote.gid, dict=args.DICTS[0],
boardSize=args.BOARD_SIZE, traySize=traySize)
response = self._sendWaitReply('makeGame', nPlayers=nPlayers, hostPosn=hostPosn,
dict=args.DICTS[0], boardSize=args.BOARD_SIZE,
traySize=traySize)
newGid = response.get('newGid')
if newGid:
remote.setGid(newGid)
# This is the heart of things. Do something as long as we have a
# game that needs to run.
@ -232,7 +242,7 @@ class Device():
# self._log('step() called for {}'.format(self))
stepped = False
for game in self.hostedGames:
if not game.invitesSent:
if game.needsInvite:
self.invite(game)
stepped = True
break
@ -258,29 +268,26 @@ class Device():
guests.remove(self.host)
self._log('rematch: new host: {}; new guest[s]: {}, gid: {}'.format(self.host, guests, newGid))
self.hostedGames.append(HostedInfo(guests, newGid, True))
self.hostedGames.append(HostedInfo(guests, needsInvite=False, gid=newGid))
for guest in guests:
Device.getFor(guest).expectInvite(newGid)
def invite(self, game):
failed = False
for ii in range(len(game.guestNames)):
guestName = game.guestNames[ii]
# self._log('inviting {}'.format(guestName))
guestDev = self._devs[guestName]
guestDev = Device.getFor(game.guestNames[ii])
addr = {}
if self.args.WITH_MQTT: addr['mqtt'] = guestDev.mqttDevID
if self.args.WITH_SMS: addr['sms'] = guestDev.smsNumber
response = self._sendWaitReply('invite', gid=game.gid,
channel=ii+1, addr=addr,
name=guestName) # just for logging
channel=ii+1, addr=addr)
if response['success']:
guestDev.expectInvite(game.gid)
else:
failed = True
if not failed: game.invitesSent = True
if not failed: game.needsInvite = False
def expectInvite(self, gid):
self.guestGames.append(GuestGameInfo(gid))
@ -328,7 +335,7 @@ class Device():
gids = [game.gid for game in allGames if not self.gameOver(game.gid)]
response = self._sendWaitReply('quit', gids=gids)
for obj in response:
for obj in response.get('states', []):
gid = obj.get('gid')
self.gameStates[gid] = obj
@ -415,9 +422,7 @@ class Device():
return result
def addGameWith(self, guests):
# self._log('addGameWith({})'.format(guests))
hosted = HostedInfo(guests)
self.hostedGames.append(hosted)
self.hostedGames.append(HostedInfo(guests, needsInvite=True))
for guest in guests:
Device.deviceFor(self.args, guest) # in case this device never hosts
@ -635,6 +640,8 @@ def termHandler(signum, frame):
print('termHandler() called')
gDone = True
def printError(msg): print( 'ERROR: {}'.format(msg))
def main():
startTime = datetime.datetime.now()
signal.signal(signal.SIGINT, termHandler)