diff --git a/xwords4/common/game.c b/xwords4/common/game.c index 387f59af9..0160c63e2 100644 --- a/xwords4/common/game.c +++ b/xwords4/common/game.c @@ -21,6 +21,7 @@ #include "game.h" #include "dictnry.h" #include "strutils.h" +#include "nli.h" #ifdef CPLUS extern "C" { @@ -335,6 +336,33 @@ game_makeFromStream( MPFORMAL XWEnv xwe, XWStreamCtxt* stream, XWGame* game, return success; } /* game_makeFromStream */ +XP_Bool +game_makeFromInvite( MPFORMAL XWEnv xwe, const NetLaunchInfo* nli, + XWGame* game, CurGameInfo* gi, + DictionaryCtxt* dict, const PlayerDicts* dicts, + XW_UtilCtxt* util, DrawCtx* draw, + CommonPrefs* cp, const TransportProcs* procs ) +{ + gi_setNPlayers( gi, nli->nPlayersT, nli->nPlayersH ); + gi->boardSize = 15; + gi->gameID = nli->gameID; + gi->dictLang = nli->lang; + gi->forceChannel = nli->forceChannel; + gi->inDuplicateMode = nli->inDuplicateMode; + gi->serverRole = SERVER_ISCLIENT; /* recipient of invitation is client */ + replaceStringIfDifferent( mpool, &gi->dictName, nli->dict ); + + game_makeNewGame( MPPARM(mpool) xwe, game, gi, util, draw, cp, procs ); + model_setDictionary( game->model, xwe, dict ); + model_setPlayerDicts( game->model, xwe, dicts ); + + CommsAddrRec returnAddr; + nli_makeAddrRec( nli, &returnAddr ); + comms_augmentHostAddr( game->comms, NULL, &returnAddr ); + + return XP_TRUE; +} + void game_saveNewGame( MPFORMAL XWEnv xwe, const CurGameInfo* gi, XW_UtilCtxt* util, const CommonPrefs* cp, XWStreamCtxt* out ) diff --git a/xwords4/common/game.h b/xwords4/common/game.h index 69ce2f15c..369fe80f0 100644 --- a/xwords4/common/game.h +++ b/xwords4/common/game.h @@ -81,6 +81,12 @@ XP_Bool game_makeFromStream( MPFORMAL XWEnv xwe, XWStreamCtxt* stream, XW_UtilCtxt* util, DrawCtx* draw, CommonPrefs* cp, const TransportProcs* procs ); +XP_Bool game_makeFromInvite( MPFORMAL XWEnv xwe, const NetLaunchInfo* nli, + XWGame* game, CurGameInfo* gi, + DictionaryCtxt* dict, const PlayerDicts* dicts, + XW_UtilCtxt* util, DrawCtx* draw, + CommonPrefs* cp, const TransportProcs* procs ); + void game_saveNewGame( MPFORMAL XWEnv xwe, const CurGameInfo* gi, XW_UtilCtxt* util, const CommonPrefs* cp, XWStreamCtxt* out ); diff --git a/xwords4/common/nli.c b/xwords4/common/nli.c index 18c23a835..c2809060d 100644 --- a/xwords4/common/nli.c +++ b/xwords4/common/nli.c @@ -95,6 +95,12 @@ nli_setInviteID( NetLaunchInfo* nli, const XP_UCHAR* inviteID ) XP_STRCAT( nli->inviteID, inviteID ); } +void +nli_setGameName( NetLaunchInfo* nli, const XP_UCHAR* gameName ) +{ + XP_SNPRINTF( nli->gameName, sizeof(nli->gameName), "%s", gameName ); +} + void nli_setMQTTDevID( NetLaunchInfo* nli, const MQTTDevID* mqttDevID ) { diff --git a/xwords4/common/nli.h b/xwords4/common/nli.h index 4171d9e9f..227c34dd4 100644 --- a/xwords4/common/nli.h +++ b/xwords4/common/nli.h @@ -34,7 +34,7 @@ void nli_init( NetLaunchInfo* nli, const CurGameInfo* gi, const CommsAddrRec* addr, - XP_U16 nPlayers, XP_U16 forceChannel ); + XP_U16 nPlayersH, XP_U16 forceChannel ); XP_Bool nli_makeFromStream( NetLaunchInfo* nli, XWStreamCtxt* stream ); diff --git a/xwords4/wasm/main.c b/xwords4/wasm/main.c index bd82d9a62..01ebca36a 100644 --- a/xwords4/wasm/main.c +++ b/xwords4/wasm/main.c @@ -166,8 +166,40 @@ startGame( Globals* globals ) LOG_RETURN_VOID(); } +static bool +gameFromInvite( Globals* globals, const NetLaunchInfo* invite ) +{ + bool success = false; + if ( ! call_confirm( "Invitation received; replace current game?" ) ) { + } else if ( invite->lang != 1 ) { + call_alert( "Invitations are only supported for play in English right now." ); + } else { + if ( !!globals->util ) { + game_dispose( &globals->game, NULL ); + wasm_util_destroy( globals->util ); + globals->util = NULL; + } + XP_LOGFF( "done with cleanup" ); /* not reaching this */ + + gi_disposePlayerInfo( MPPARM(globals->mpool) &globals->gi ); + XP_MEMSET( &globals->gi, 0, sizeof(globals->gi) ); + + globals->util = wasm_util_make( globals->mpool, &globals->gi, + globals->dutil, globals ); + + success = game_makeFromInvite( MPPARM(globals->mpool) NULL, invite, + &globals->game, &globals->gi, + globals->dict, NULL, + globals->util, globals->draw, + &globals->cp, &globals->procs ); + + } + return success; +} + static void -makeAndDraw( Globals* globals, bool forceNew, bool p0robot, bool p1robot ) +makeAndDraw( Globals* globals, const NetLaunchInfo* invite, + bool forceNew, bool p0robot, bool p1robot ) { if ( !!globals->util ) { game_dispose( &globals->game, NULL ); @@ -193,7 +225,11 @@ makeAndDraw( Globals* globals, bool forceNew, bool p0robot, bool p1robot ) globals->dutil, globals ); XP_Bool loaded = XP_FALSE; - if ( ! forceNew ) { + XP_ASSERT( !forceNew || !invite ); /* won't both be set */ + + if ( !!invite ) { + loaded = gameFromInvite( globals, invite ); + } else if ( ! forceNew ) { /* Let's see if there's a saved game */ XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(globals->mpool) globals->vtMgr ); @@ -224,50 +260,9 @@ makeAndDraw( Globals* globals, bool forceNew, bool p0robot, bool p1robot ) void main_gameFromInvite( Globals* globals, const NetLaunchInfo* invite ) { - LOG_FUNC(); - if ( ! call_confirm( "Invitation received; replace current game?" ) ) { - } else if ( invite->lang != 1 ) { - call_alert( "Invitation received, but only English supported now" ); - } else { - if ( !!globals->util ) { - XP_LOGFF( "calling game_dispose" ); - game_dispose( &globals->game, NULL ); - XP_LOGFF( "calling wasm_util_destroy" ); - wasm_util_destroy( globals->util ); - globals->util = NULL; - } - XP_LOGFF( "done with cleanup" ); /* not reaching this */ - - XP_MEMSET( &globals->gi, 0, sizeof(globals->gi) ); - - gi_setNPlayers( &globals->gi, invite->nPlayersT, invite->nPlayersH ); - // ensureLocalPlayerNames( params, &gi ); - - globals->gi.boardSize = 15; - globals->gi.gameID = invite->gameID; - globals->gi.dictLang = invite->lang; - globals->gi.forceChannel = invite->forceChannel; - globals->gi.inDuplicateMode = invite->inDuplicateMode; - globals->gi.serverRole = SERVER_ISCLIENT; /* recipient of invitation is client */ - replaceStringIfDifferent( globals->mpool, &globals->gi.dictName, - invite->dict ); - - globals->util = wasm_util_make( globals->mpool, &globals->gi, - globals->dutil, globals ); - - game_makeNewGame( MPPARM(globals->mpool) NULL, - &globals->game, &globals->gi, - globals->util, globals->draw, - &globals->cp, &globals->procs ); - - CommsAddrRec returnAddr; - nli_makeAddrRec( invite, &returnAddr ); - addr_setType( &returnAddr, COMMS_CONN_MQTT ); /* nuke everything else */ - comms_augmentHostAddr( globals->game.comms, NULL, &returnAddr ); - + if ( gameFromInvite( globals, invite ) ) { startGame( globals ); } - LOG_RETURN_VOID(); } void @@ -467,8 +462,78 @@ button( const char* msg ) } } +static bool +loadInvite( Globals* globals, NetLaunchInfo* nlip, + int argc, const char** argv ) +{ + LOG_FUNC(); + CurGameInfo gi = {0}; + CommsAddrRec addr = {0}; + MQTTDevID mqttDevID = 0; + XP_U16 nPlayersH = 0; + XP_U16 forceChannel = 0; + const XP_UCHAR* gameName = NULL; + const XP_UCHAR* inviteID = NULL; + + for ( int ii = 0; ii < argc; ++ii ) { + const char* argp = argv[ii]; + char* param = strchr(argp, '='); + if ( !param ) { /* no '='? */ + continue; + } + char arg[8]; + int argLen = param - argp; + XP_MEMCPY( arg, argp, argLen ); + arg[argLen] = '\0'; + ++param; /* skip the '=' */ + + if ( 0 == strcmp( "lang", arg ) ) { + gi.dictLang = atoi(param); + } else if ( 0 == strcmp( "np", arg ) ) { + gi.nPlayers = atoi(param); + } else if ( 0 == strcmp( "nh", arg ) ) { + nPlayersH = atoi(param); + } else if ( 0 == strcmp( "gid", arg ) ) { + gi.gameID = atoi(param); + } else if ( 0 == strcmp( "fc", arg ) ) { + gi.forceChannel = atoi(param); + } else if ( 0 == strcmp( "nm", arg ) ) { + gameName = param; + } else if ( 0 == strcmp( "id", arg ) ) { + inviteID = param; + } else if ( 0 == strcmp( "wl", arg ) ) { + replaceStringIfDifferent( globals->mpool, &gi.dictName, param ); + } else if ( 0 == strcmp( "r2id", arg ) ) { + if ( strToMQTTCDevID( param, &addr.u.mqtt.devID ) ) { + addr_addType( &addr, COMMS_CONN_MQTT ); + } else { + XP_LOGFF( "bad devid %s", param ); + } + } else { + XP_LOGFF( "dropping arg %s, param %s", arg, param ); + } + } + + bool success = 0 < nPlayersH && + addr_hasType( &addr, COMMS_CONN_MQTT ); + + if ( success ) { + nli_init( nlip, &gi, &addr, nPlayersH, forceChannel ); + if ( !!gameName ) { + nli_setGameName( nlip, gameName ); + } + if ( !!inviteID ) { + nli_setInviteID( nlip, inviteID ); + } + LOGNLI( nlip ); + } + gi_disposePlayerInfo( MPPARM(globals->mpool) &gi ); + LOG_RETURNF( "%d", success ); + return success; +} + static void -initNoReturn() +initNoReturn( int argc, const char** argv ) { time_t now = getCurMS(); srandom( now ); @@ -477,6 +542,12 @@ initNoReturn() Globals* globals = calloc(1, sizeof(*globals)); sGlobals = globals; + NetLaunchInfo nli = {0}; + NetLaunchInfo* nlip = NULL; + if ( loadInvite( globals, &nli, argc, argv ) ) { + nlip = &nli; + } + SDL_Init( SDL_INIT_EVENTS ); TTF_Init(); @@ -489,7 +560,7 @@ initNoReturn() initDeviceGlobals( globals ); - makeAndDraw( globals, false, false, true ); + makeAndDraw( globals, nlip, false, false, true ); emscripten_set_main_loop_arg( looper, globals, -1, 1 ); } @@ -499,7 +570,7 @@ newgame(bool p0, bool p1) { XP_LOGFF( "(args: %d,%d)", p0, p1 ); XP_ASSERT( !!sGlobals ); - makeAndDraw( sGlobals, true, p0, p1 ); + makeAndDraw( sGlobals, NULL, true, p0, p1 ); } void @@ -511,12 +582,9 @@ gotMQTTMsg( void* closure, int len, const uint8_t* msg ) } int -main( int argc, char** argv ) +main( int argc, const char** argv ) { XP_LOGFF( "(argc=%d)", argc ); - for ( int ii = 0; ii < argc; ++ii ) { - XP_LOGFF( "arg[%d]: %s", ii, argv[ii] ); - } - initNoReturn(); + initNoReturn( argc, argv ); return 0; } diff --git a/xwords4/wasm/shell_minimal.html b/xwords4/wasm/shell_minimal.html index 69d72cbb3..725123fe4 100644 --- a/xwords4/wasm/shell_minimal.html +++ b/xwords4/wasm/shell_minimal.html @@ -3,7 +3,7 @@
-