diff --git a/xwords4/android/jni/xwjni.c b/xwords4/android/jni/xwjni.c index 1aa737a6c..0f19529fb 100644 --- a/xwords4/android/jni/xwjni.c +++ b/xwords4/android/jni/xwjni.c @@ -780,10 +780,10 @@ Java_org_eehouse_android_xw4_jni_XwJNI_kplr_1getPlayers DVC_HEADER(jniGlobalPtr); XP_U16 nFound = 0; - kplr_getPlayers( globalState->dutil, env, NULL, &nFound ); + kplr_getNames( globalState->dutil, env, NULL, &nFound ); if ( 0 < nFound ) { const XP_UCHAR* names[nFound]; - kplr_getPlayers( globalState->dutil, env, names, &nFound ); + kplr_getNames( globalState->dutil, env, names, &nFound ); jnames = makeStringArray( env, nFound, names ); } DVC_HEADER_END(); diff --git a/xwords4/common/comms.c b/xwords4/common/comms.c index 06573c3a6..012661ae1 100644 --- a/xwords4/common/comms.c +++ b/xwords4/common/comms.c @@ -202,7 +202,7 @@ static AddressRecord* rememberChannelAddress( CommsCtxt* comms, XWEnv xwe, static void augmentChannelAddr( CommsCtxt* comms, AddressRecord* rec, const CommsAddrRec* addr, XWHostID hostID ); static XP_Bool augmentAddrIntrnl( CommsCtxt* comms, CommsAddrRec* dest, - const CommsAddrRec* src ); + const CommsAddrRec* src, XP_Bool isNewer ); static XP_Bool channelToAddress( CommsCtxt* comms, XWEnv xwe, XP_PlayerAddr channelNo, const CommsAddrRec** addr ); static AddressRecord* getRecordFor( CommsCtxt* comms, XWEnv xwe, @@ -1039,7 +1039,7 @@ comms_augmentHostAddr( CommsCtxt* comms, XWEnv xwe, const CommsAddrRec* addr ) && ! addr_hasType( &comms->addr, COMMS_CONN_RELAY ); CommsAddrRec tmp = comms->addr; - augmentAddrIntrnl( comms, &tmp, addr ); + augmentAddrIntrnl( comms, &tmp, addr, XP_TRUE ); util_addrChange( comms->util, xwe, &comms->addr, &tmp ); comms->addr = tmp; @@ -1069,7 +1069,7 @@ comms_addMQTTDevID( CommsCtxt* comms, XP_PlayerAddr channelNo, CommsAddrRec addr = {0}; addr_setType( &addr, COMMS_CONN_MQTT ); addr.u.mqtt.devID = *devID; - augmentAddrIntrnl( comms, &rec->addr, &addr ); + augmentAddrIntrnl( comms, &rec->addr, &addr, XP_TRUE ); } } if ( !found ) { @@ -2594,7 +2594,7 @@ comms_isConnected( const CommsCtxt* const comms ) } void -comms_gatherPlayers( CommsCtxt* comms, XWEnv xwe ) +comms_gatherPlayers( CommsCtxt* comms, XWEnv xwe, XP_U32 created ) { #ifdef XWFEATURE_KNOWNPLAYERS LOG_FUNC(); @@ -2604,7 +2604,7 @@ comms_gatherPlayers( CommsCtxt* comms, XWEnv xwe ) comms_getAddrs( comms, NULL, addrs, &nRecs ); const CurGameInfo* gi = comms->util->gameInfo; - if ( kplr_addAddrs( comms->dutil, xwe, gi, addrs, nRecs ) ) { + if ( kplr_addAddrs( comms->dutil, xwe, gi, addrs, nRecs, created ) ) { XP_LOGFF( "not setting flag :-)" ); // comms->flags |= FLAG_HARVEST_DONE; } @@ -2956,7 +2956,7 @@ static void augmentChannelAddr( CommsCtxt* comms, AddressRecord* const rec, const CommsAddrRec* addr, XWHostID hostID ) { - augmentAddrIntrnl( comms, &rec->addr, addr ); + augmentAddrIntrnl( comms, &rec->addr, addr, XP_TRUE ); if ( addr_hasType( &rec->addr, COMMS_CONN_RELAY ) ) { if ( 0 != hostID ) { rec->rr.hostID = hostID; @@ -2977,13 +2977,15 @@ augmentChannelAddr( CommsCtxt* comms, AddressRecord* const rec, static XP_Bool augmentAddrIntrnl( CommsCtxt* comms, CommsAddrRec* destAddr, - const CommsAddrRec* srcAddr ) + const CommsAddrRec* srcAddr, XP_Bool isNewer ) { XP_Bool changed = XP_FALSE; + const CommsAddrRec empty = {0}; if ( !!srcAddr ) { CommsConnType typ; for ( XP_U32 st = 0; addr_iter( srcAddr, &typ, &st ); ) { - if ( ! addr_hasType( destAddr, typ ) ) { + XP_Bool newType = !addr_hasType( destAddr, typ ); + if ( newType ) { XP_LOGFF( "adding new type %s to rec", ConnType2Str(typ) ); addr_addType( destAddr, typ ); @@ -3040,19 +3042,20 @@ augmentAddrIntrnl( CommsCtxt* comms, CommsAddrRec* destAddr, break; } if ( !!dest ) { - XP_Bool changing = 0 != XP_MEMCMP( dest, src, siz ); - if ( changing ) { -#ifdef DEBUG - CommsAddrRec dummy = {0}; - if ( 0 == XP_MEMCMP( &dummy, dest, siz ) ) { - XP_LOGFF( "setting %s-type addr for first time", ConnType2Str(typ) ); - } else if ( 0 != XP_MEMCMP( dest, src, siz ) ) { - XP_LOGFF( "actually changing addr info for typ %s", ConnType2Str(typ) ); + XP_Bool different = 0 != XP_MEMCMP( dest, src, siz ); + if ( different ) { + /* If the dest is non-empty AND the src is older, don't do + anything: don't replace newer info with older. Note + that this assumes unset values are empty!!! */ + if ( !isNewer && !newType + && 0 != XP_MEMCMP( &empty, dest, siz ) ) { + XP_LOGFF( "%s: not replacing new info with old", + ConnType2Str(typ) ); + } else { + XP_MEMCPY( dest, src, siz ); + changed = XP_TRUE; } -#endif - XP_MEMCPY( dest, src, siz ); } - changed = changed || changing; } } } @@ -3060,9 +3063,9 @@ augmentAddrIntrnl( CommsCtxt* comms, CommsAddrRec* destAddr, } XP_Bool -augmentAddr( CommsAddrRec* addr, const CommsAddrRec* newer ) +augmentAddr( CommsAddrRec* addr, const CommsAddrRec* newer, XP_Bool isNewer ) { - return augmentAddrIntrnl( NULL, addr, newer ); + return augmentAddrIntrnl( NULL, addr, newer, isNewer ); } static XP_Bool diff --git a/xwords4/common/comms.h b/xwords4/common/comms.h index ef857196e..8ee68d031 100644 --- a/xwords4/common/comms.h +++ b/xwords4/common/comms.h @@ -238,7 +238,8 @@ XP_Bool comms_isConnected( const CommsCtxt* const comms ); void comms_gameJoined( CommsCtxt* comms, const XP_UCHAR* connname, XWHostID hid ); #endif -XP_Bool augmentAddr( CommsAddrRec* addr, const CommsAddrRec* newer ); +XP_Bool augmentAddr( CommsAddrRec* addr, const CommsAddrRec* newer, + XP_Bool isNewer ); CommsConnType addr_getType( const CommsAddrRec* addr ); void addr_setType( CommsAddrRec* addr, CommsConnType type ); @@ -262,7 +263,7 @@ void comms_setAddrDisabled( CommsCtxt* comms, CommsConnType typ, XP_Bool comms_getAddrDisabled( const CommsCtxt* comms, CommsConnType typ, XP_Bool send ); -void comms_gatherPlayers( CommsCtxt* comms, XWEnv xwe ); +void comms_gatherPlayers( CommsCtxt* comms, XWEnv xwe, XP_U32 created ); # else # define comms_setAddrDisabled( comms, typ, send, enabled ) diff --git a/xwords4/common/comtypes.h b/xwords4/common/comtypes.h index 1d275227e..59a4f253e 100644 --- a/xwords4/common/comtypes.h +++ b/xwords4/common/comtypes.h @@ -229,7 +229,7 @@ typedef enum { #define SUFFIX_NEXTID "nextID" #define SUFFIX_DEVSTATE "devState" #define SUFFIX_MQTT_DEVID "mqtt_devid_key" -#define SUFFIX_KNOWN_PLAYERS "known_players_key" +#define SUFFIX_KNOWN_PLAYERS "known_players_key_dev1" #define FULL_KEY(PARTIAL) "persist_key:" PARTIAL diff --git a/xwords4/common/game.c b/xwords4/common/game.c index 91a61e3dd..0a2e97b1c 100644 --- a/xwords4/common/game.c +++ b/xwords4/common/game.c @@ -136,7 +136,6 @@ game_makeNewGame( MPFORMAL XWEnv xwe, XWGame* game, CurGameInfo* gi, gi->gameID = makeGameID( util ); } game->created = dutil_getCurSeconds( util_getDevUtilCtxt( util, xwe ), xwe ); - game->util = util; game->model = model_make( MPPARM(mpool) xwe, (DictionaryCtxt*)NULL, @@ -328,9 +327,6 @@ game_makeFromStream( MPFORMAL XWEnv xwe, XWStreamCtxt* stream, XWGame* game, if ( success && !!game && !!game->comms ) { XP_ASSERT( comms_getIsServer(game->comms) == server_getIsServer(game->server) ); - if ( server_getGameIsConnected( game->server ) ) { - comms_gatherPlayers( game->comms, xwe ); - } } return success; @@ -368,7 +364,14 @@ game_saveToStream( const XWGame* game, XWEnv xwe, const CurGameInfo* gi, gi_writeToStream( stream, gi ); if ( !!game ) { - stream_putU32( stream, game->created ); + const XP_U32 created = game->created; + if ( !!game->comms + && 0 != created + && server_getGameIsConnected( game->server ) ) { + comms_gatherPlayers( game->comms, xwe, created ); + } + + stream_putU32( stream, created ); XP_ASSERT( 0 != saveToken ); XP_U8 flags = NULL == game->comms ? 0 : FLAG_HASCOMMS; diff --git a/xwords4/common/game.h b/xwords4/common/game.h index 856e26ba2..69ce2f15c 100644 --- a/xwords4/common/game.h +++ b/xwords4/common/game.h @@ -51,7 +51,7 @@ typedef struct _GameStateInfo { XP_Bool canUnpause; /* duplicate-mode only */ } GameStateInfo; -typedef struct XWGame { +typedef struct _XWGame { XW_UtilCtxt* util; BoardCtxt* board; ModelCtxt* model; diff --git a/xwords4/common/knownplyr.c b/xwords4/common/knownplyr.c index 3da259c77..2e81af859 100644 --- a/xwords4/common/knownplyr.c +++ b/xwords4/common/knownplyr.c @@ -26,6 +26,7 @@ typedef struct _KnownPlayer { struct _KnownPlayer* next; + XP_U32 newestMod; XP_UCHAR* name; CommsAddrRec addr; } KnownPlayer; @@ -38,7 +39,8 @@ typedef struct _KPState { } KPState; static void addPlayer( XW_DUtilCtxt* dutil, KPState* state, - const XP_UCHAR* name, const CommsAddrRec* addr ); + const XP_UCHAR* name, const CommsAddrRec* addr, + XP_U32 newestMod ); static void getPlayersImpl( const KPState* state, const XP_UCHAR** players, XP_U16* nFound ); @@ -47,13 +49,14 @@ loadFromStream( XW_DUtilCtxt* dutil, KPState* state, XWStreamCtxt* stream ) { LOG_FUNC(); while ( 0 < stream_getSize( stream ) ) { + XP_U32 newestMod = stream_getU32( stream ); XP_UCHAR buf[64]; stringFromStreamHere( stream, buf, VSIZE(buf) ); CommsAddrRec addr = {0}; addrFromStream( &addr, stream ); - addPlayer( dutil, state, buf, &addr ); + addPlayer( dutil, state, buf, &addr, newestMod ); } } @@ -88,6 +91,7 @@ saveState( XW_DUtilCtxt* dutil, XWEnv xwe, KPState* state ) dutil_getVTManager(dutil) ); stream_putU8( stream, CUR_STREAM_VERS ); for ( KnownPlayer* kp = state->players; !!kp; kp = kp->next ) { + stream_putU32( stream, kp->newestMod ); stringToStream( stream, kp->name ); addrToStream( stream, &kp->addr ); } @@ -156,8 +160,8 @@ makeUniqueName( const KPState* state, const XP_UCHAR* name, * For early testing, however, just make a new name. */ static void -addPlayer( XW_DUtilCtxt* dutil, KPState* state, - const XP_UCHAR* name, const CommsAddrRec* addr ) +addPlayer( XW_DUtilCtxt* dutil, KPState* state, const XP_UCHAR* name, + const CommsAddrRec* addr, XP_U32 newestMod ) { XP_LOGFF( "(name=%s)", name ); KnownPlayer* withSameDevID = NULL; @@ -176,7 +180,12 @@ addPlayer( XW_DUtilCtxt* dutil, KPState* state, XP_UCHAR tmpName[64]; if ( !!withSameDevID ) { /* only one allowed */ - state->dirty = augmentAddr( &withSameDevID->addr, addr ) || state->dirty; + XP_Bool isNewer = newestMod > withSameDevID->newestMod; + XP_Bool changed = augmentAddr( &withSameDevID->addr, addr, isNewer ); + if ( isNewer ) { + withSameDevID->newestMod = newestMod; + } + state->dirty = changed || state->dirty; } else { if ( !!withSameName ) { /* Same name but different devID? Create a unique name */ @@ -197,7 +206,7 @@ addPlayer( XW_DUtilCtxt* dutil, KPState* state, XP_Bool kplr_addAddrs( XW_DUtilCtxt* dutil, XWEnv xwe, const CurGameInfo* gi, - CommsAddrRec addrs[], XP_U16 nAddrs ) + CommsAddrRec addrs[], XP_U16 nAddrs, XP_U32 modTime ) { LOG_FUNC(); XP_Bool canUse = XP_TRUE; @@ -213,7 +222,7 @@ kplr_addAddrs( XW_DUtilCtxt* dutil, XWEnv xwe, const CurGameInfo* gi, for ( int ii = 0; ii < nAddrs && canUse; ++ii ) { const XP_UCHAR* name = figureNameFor( ii, gi ); if ( !!name ) { - addPlayer( dutil, state, name, &addrs[ii] ); + addPlayer( dutil, state, name, &addrs[ii], modTime ); } else { XP_LOGFF( "unable to find %dth name", ii ); } @@ -247,8 +256,8 @@ getPlayersImpl( const KPState* state, const XP_UCHAR** players, XP_U16* nFound ) } void -kplr_getPlayers( XW_DUtilCtxt* dutil, XWEnv xwe, - const XP_UCHAR** players, XP_U16* nFound ) +kplr_getNames( XW_DUtilCtxt* dutil, XWEnv xwe, + const XP_UCHAR** players, XP_U16* nFound ) { KPState* state = loadState( dutil, xwe ); getPlayersImpl( state, players, nFound ); diff --git a/xwords4/common/knownplyr.h b/xwords4/common/knownplyr.h index 1adc712b4..ae6a6a5ca 100644 --- a/xwords4/common/knownplyr.h +++ b/xwords4/common/knownplyr.h @@ -32,13 +32,13 @@ void kplr_cleanup( XW_DUtilCtxt* dutil ); XP_Bool kplr_havePlayers( XW_DUtilCtxt* dutil, XWEnv xwe ); -void kplr_getPlayers( XW_DUtilCtxt* dutil, XWEnv xwe, const XP_UCHAR** players, - XP_U16* nFound ); +void kplr_getNames( XW_DUtilCtxt* dutil, XWEnv xwe, const XP_UCHAR** players, + XP_U16* nFound ); XP_Bool kplr_getAddr( XW_DUtilCtxt* dutil, XWEnv xwe, const XP_UCHAR* name, CommsAddrRec* addr ); XP_Bool kplr_addAddrs( XW_DUtilCtxt* dutil, XWEnv xwe, const CurGameInfo* gi, - CommsAddrRec addrs[], XP_U16 nAddrs ); + CommsAddrRec addrs[], XP_U16 nAddrs, XP_U32 modTime ); # else # define kplr_cleanup( dutil ) # endif diff --git a/xwords4/linux/gtkinvit.c b/xwords4/linux/gtkinvit.c index eb2cbadef..5333e4b55 100644 --- a/xwords4/linux/gtkinvit.c +++ b/xwords4/linux/gtkinvit.c @@ -286,10 +286,10 @@ makeKnownsPage( GtkInviteState* state, PageData* data ) gtk_box_pack_start( GTK_BOX(hbox), label, FALSE, TRUE, 0 ); XP_U16 nFound = 0; - kplr_getPlayers( state->dutil, NULL_XWE, NULL, &nFound ); + kplr_getNames( state->dutil, NULL_XWE, NULL, &nFound ); XP_ASSERT( nFound > 0 ); const XP_UCHAR* names[nFound]; - kplr_getPlayers( state->dutil, NULL_XWE, names, &nFound ); + kplr_getNames( state->dutil, NULL_XWE, names, &nFound ); GtkWidget* combo = state->knownsCombo = gtk_combo_box_text_new(); for ( int ii = 0; ii < nFound; ++ii ) {