display known player names for pending invites

When an invitation is pending for a player in GameSummary or
scoreboard, show "<Name> invited" instead of "remote missing."
This commit is contained in:
Eric House 2024-07-28 08:46:01 -07:00
parent f3fb43e93b
commit 2f91ff1f78
14 changed files with 168 additions and 28 deletions

View file

@ -1483,12 +1483,8 @@ class BoardDelegate(delegator: Delegator) :
}
}
override fun getInviteeName(plyrNum: Int): String? {
return if (null == mSummary) null else mSummary!!.summarizePlayer(
mActivity,
mRowid,
plyrNum
)
override fun getInviteeName(index: Int): String? {
return mSummary?.summarizePlayer( mActivity, mRowid, index)
}
override fun playerScoreHeld(player: Int) {

View file

@ -580,6 +580,17 @@ object GameUtils {
return rowid
}
fun inviteeName(context: Context, rowid: Long, playerPosn: Int): String? {
var result =
GameWrapper.make(context, rowid).use { gw ->
gw?.let {
val name = XwJNI.server_inviteeName(it.gamePtr(), playerPosn)
name
}
}
return result
}
fun handleInvitation(
context: Context, nli: NetLaunchInfo,
procs: TransportProcs?

View file

@ -468,8 +468,8 @@ object MQTTUtils {
.callback(this@Conn)
.send()
.whenComplete{ ack, throwable ->
Log.d( TAG, "$this.whenComplete(); topic=$mTopic, "
+ "ack=$ack, err=$throwable")
// Log.d( TAG, "$this.whenComplete(); topic=$mTopic, "
// + "ack=$ack, err=$throwable")
}
}
}
@ -486,7 +486,7 @@ object MQTTUtils {
.retain(true)
.send()
.whenComplete { mqtt3Publish, throwable ->
Log.d(TAG, "whenComplete(): $mqtt3Publish")
// Log.d(TAG, "whenComplete(): $mqtt3Publish")
mStats.addSend(throwable == null)
if (throwable != null) {
// Handle failure to publish

View file

@ -29,6 +29,7 @@ import java.io.Serializable
import org.eehouse.android.xw4.Assert
import org.eehouse.android.xw4.BuildConfig
import org.eehouse.android.xw4.DBUtils
import org.eehouse.android.xw4.GameUtils
import org.eehouse.android.xw4.Log
import org.eehouse.android.xw4.R
import org.eehouse.android.xw4.Utils
@ -199,7 +200,8 @@ class GameSummary : Serializable {
val prev = nxt
nxt = playersStr.indexOf(sep, nxt)
val name =
if (-1 == nxt) playersStr.substring(prev) else playersStr.substring(prev, nxt)
if (-1 == nxt) playersStr.substring(prev)
else playersStr.substring(prev, nxt)
m_players!![ii] = name
if (-1 == nxt) {
break
@ -372,16 +374,12 @@ class GameSummary : Serializable {
if (!isLocal(indx)) {
val isMissing = 0 != ((1 shl indx) and missingPlayers)
if (isMissing) {
val si = DBUtils.getInvitesFor(context, rowid)
var kp: String? = null
if (null != si) {
kp = si.getKPName(context)
}
player = if (null == kp) {
LocUtils.getString(context, R.string.missing_player)
} else {
LocUtils.getString(context, R.string.invitee_fmt, kp)
}
val kp = GameUtils.inviteeName(context, rowid, indx)
player =
if (TextUtils.isEmpty(kp))
LocUtils.getString(context, R.string.missing_player)
else
LocUtils.getString(context, R.string.invitee_fmt, kp)
} else {
formatID = R.string.str_nonlocal_name_fmt
}

View file

@ -786,6 +786,9 @@ class XwJNI private constructor() {
@JvmStatic
external fun server_endGame(gamePtr: GamePtr?)
@JvmStatic
external fun server_inviteeName(gamePtr: GamePtr?, channelNo: Int): String?
// hybrid to save work
@JvmStatic
external fun board_server_prefsChanged(

View file

@ -2835,6 +2835,24 @@ Java_org_eehouse_android_xw4_jni_XwJNI_server_1endGame
XWJNI_END();
}
JNIEXPORT jstring JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_server_1inviteeName
( JNIEnv* env, jclass C, GamePtrType gamePtr, jint channel )
{
jstring result = NULL;
XWJNI_START(gamePtr);
XP_ASSERT( !!state->game.server );
XP_UCHAR buf[32] = {0};
XP_U16 len = VSIZE(buf);
server_inviteeName( state->game.server, env, channel, buf, &len );
if ( !!buf[0] ) {
result = (*env)->NewStringUTF( env, buf );
}
XWJNI_END();
return result;
}
JNIEXPORT void JNICALL Java_org_eehouse_android_xw4_jni_XwJNI_board_1pause
( JNIEnv* env, jclass C, GamePtrType gamePtr, jstring jmsg )
{

View file

@ -1836,7 +1836,7 @@ getInvitedProc( MsgQueueElem* elem, void* closure )
if ( IS_INVITE( elem ) ) {
GetInvitedData* gidp = (GetInvitedData*)closure;
XP_PlayerAddr channelNo = elem->channelNo & CHANNEL_MASK;
XP_LOGFF( "got invite on channel %d", channelNo );
XP_LOGFF( "found invite on channel %d", channelNo );
XP_U16 thisBit = 1 << channelNo;
XP_ASSERT( 0 == (thisBit & gidp->allBits) ); /* should be no dupes */
if ( 0 == (thisBit & gidp->allBits) ) {
@ -1857,6 +1857,51 @@ comms_getInvited( RELCONST CommsCtxt* comms, XP_U16* nInvites )
// LOG_RETURNF( "%d", *nInvites );
COMMS_MUTEX_UNLOCK();
}
typedef struct _GetNamesData {
const CommsCtxt* comms;
XWEnv xwe;
InviteeNames* names;
} GetNamesData;
static ForEachAct
getNamesProc( MsgQueueElem* elem, void* closure )
{
LOG_FUNC();
if ( IS_INVITE( elem ) ) {
GetNamesData* gndp = (GetNamesData*)closure;
XP_PlayerAddr channelNo = elem->channelNo & CHANNEL_MASK;
XP_LOGFF( "channelNo: %d", channelNo );
const AddressRecord* rec = getRecordFor( gndp->comms, channelNo );
XP_ASSERT( !!rec );
const CommsAddrRec* addr = &rec->addr;
const XP_UCHAR* name =
kplr_nameForAddress( gndp->comms->dutil, gndp->xwe, addr );
InviteeNames* names = gndp->names;
if ( !!name ) {
XP_STRCAT( names->name[names->count], name );
XP_LOGFF( "copied name %s to pos %d (pos %d)", name,
channelNo, names->count );
}
++names->count;
}
return FEA_OK;
}
void
comms_inviteeNames( CommsCtxt* comms, XWEnv xwe,
InviteeNames* names )
{
COMMS_MUTEX_LOCK(comms);
GetNamesData gnd = {
.comms = comms,
.xwe = xwe,
.names = names,
};
forEachElem( (CommsCtxt*)comms, getNamesProc, &gnd );
COMMS_MUTEX_UNLOCK();
}
#endif
/* Send a message using the sequentially next MsgID. Save the message so
@ -3079,7 +3124,7 @@ parseBeefHeader( CommsCtxt* comms, XWStreamCtxt* stream, HeaderStuff* stuff )
&& stream_gotU32( stream, &stuff->msgID )
&& stream_gotU32( stream, &stuff->lastMsgRcd );
LOG_RETURNF( "%s", boolToStr(messageValid) );
// LOG_RETURNF( "%s", boolToStr(messageValid) );
return messageValid;
}
@ -3111,7 +3156,7 @@ parseSmallHeader( CommsCtxt* comms, XWStreamCtxt* msgStream,
stream_destroy( hdrStream );
}
LOG_RETURNF( "%s", boolToStr(messageValid) );
// LOG_RETURNF( "%s", boolToStr(messageValid) );
COMMS_MUTEX_UNLOCK();
return messageValid;
}

View file

@ -207,6 +207,12 @@ void addrToStream( XWStreamCtxt* stream, const CommsAddrRec* addr );
void comms_invite( CommsCtxt* comms, XWEnv xwe, const NetLaunchInfo* nli,
const CommsAddrRec* destAddr, XP_Bool sendNow );
void comms_getInvited( RELCONST CommsCtxt* comms, XP_U16* nInvites );
typedef struct _InviteeNames {
XP_UCHAR name[4][32];
XP_U16 count;
} InviteeNames;
void comms_inviteeNames( CommsCtxt* comms, XWEnv xwe, InviteeNames* names );
#endif
XP_S16 comms_send( CommsCtxt* comms, XWEnv xwe, XWStreamCtxt* stream );
XP_S16 comms_resendAll( CommsCtxt* comms, XWEnv xwe, CommsConnType filter,

View file

@ -434,6 +434,20 @@ kplr_nameForMqttDev( XW_DUtilCtxt* dutil, XWEnv xwe,
return ms.name;
}
const XP_UCHAR*
kplr_nameForAddress( XW_DUtilCtxt* dutil, XWEnv xwe,
const CommsAddrRec* addr )
{
const XP_UCHAR* result = NULL;
if ( addr_hasType( addr, COMMS_CONN_MQTT ) ) {
result = kplr_nameForMqttDev( dutil, xwe,
&addr->u.mqtt.devID );
} else {
XP_ASSERT(0); /* FIXME */
}
return result;
}
static void
freeKP( XW_DUtilCtxt* XP_UNUSED_DBG(dutil), KnownPlayer* kp )
{

View file

@ -45,6 +45,8 @@ XP_Bool kplr_getAddr( XW_DUtilCtxt* dutil, XWEnv xwe, const XP_UCHAR* name,
CommsAddrRec* addr, XP_U32* lastMod );
const XP_UCHAR* kplr_nameForMqttDev( XW_DUtilCtxt* dutil, XWEnv xwe,
const MQTTDevID* devID );
const XP_UCHAR* kplr_nameForAddress( XW_DUtilCtxt* dutil, XWEnv xwe,
const CommsAddrRec* addr );
KP_Rslt kplr_renamePlayer( XW_DUtilCtxt* dutil, XWEnv xwe, const XP_UCHAR* oldName,
const XP_UCHAR* newName );

View file

@ -486,7 +486,7 @@ getNV( XWStreamCtxt* stream, ServerNonvolatiles* nv, XP_U16 nPlayers )
if ( STREAM_SAVE_PREVWORDS < version ) {
nv->streamVersion = stream_getU8 ( stream );
}
/* XP_LOGF( "%s: read streamVersion: 0x%x", __func__, nv->streamVersion ); */
/* XP_LOGFF( "read streamVersion: 0x%x", nv->streamVersion ); */
#endif
if ( version >= STREAM_VERS_DUPLICATE ) {
@ -527,7 +527,7 @@ putNV( XWStreamCtxt* stream, const ServerNonvolatiles* nv, XP_U16 nPlayers )
}
#ifdef STREAM_VERS_BIGBOARD
stream_putU8( stream, nv->streamVersion );
/* XP_LOGF( "%s: wrote streamVersion: 0x%x", __func__, nv->streamVersion ); */
/* XP_LOGFF( "wrote streamVersion: 0x%x", nv->streamVersion ); */
#endif
for ( int ii = 0; ii < nPlayers; ++ii ) {
@ -2723,7 +2723,7 @@ trayAllowsMoves( ServerCtxt* server, XWEnv xwe, XP_U16 turn,
XP_MEMCPY( tmpTiles, &tray->tiles[0], nInTray * sizeof(tmpTiles[0]) );
XP_MEMCPY( &tmpTiles[nInTray], &tiles[0], nTiles * sizeof(tmpTiles[0]) );
/* XP_LOGF( "%s(nTiles=%d)", __func__, nTiles ); */
/* XP_LOGFF( "%s(nTiles=%d)", __func__, nTiles ); */
EngineCtxt* tmpEngine = NULL;
EngineCtxt* engine = server_getEngineFor( server, turn );
if ( !engine ) {
@ -3702,7 +3702,7 @@ dupe_checkWhatsDone( const ServerCtxt* server, XP_Bool amHost,
}
}
// XP_LOGF( "%s(): allDone: %d; allLocalsDone: %d", __func__, allDone, allLocalsDone );
// XP_LOGFF( "allDone: %d; allLocalsDone: %d", allDone, allLocalsDone );
*allDoneP = allDone;
*allLocalsDoneP = allLocalsDone;
}
@ -4018,7 +4018,7 @@ server_isPlayersTurn( const ServerCtxt* server, XP_U16 turn )
result = turn == server_getCurrentTurn( server, NULL );
}
// XP_LOGF( "%s(%d) => %d", __func__, turn, result );
// XP_LOGFF( "(%d) => %d", turn, result );
return result;
}
@ -4686,6 +4686,38 @@ server_endGame( ServerCtxt* server, XWEnv xwe )
}
} /* server_endGame */
void
server_inviteeName( const ServerCtxt* server,
XWEnv xwe, XP_U16 playerPosn,
XP_UCHAR* buf, XP_U16* bufLen )
{
int nameIndx = 0;
for ( int ii = 0; ii <= playerPosn; ++ii ) {
const ServerPlayer* sp = &server->srvPlyrs[ii];
if ( -1 == sp->deviceIndex ) { /* not yet claimed */
if ( playerPosn == ii ) {
CommsCtxt* comms = server->vol.comms;
InviteeNames names = {0};
comms_inviteeNames( comms, xwe, &names );
if ( nameIndx < names.count ) {
XP_LOGFF( "got a match: player %d for channel %d; name: \"%s\"",
playerPosn, nameIndx, names.name[nameIndx] );
*bufLen = XP_SNPRINTF( buf, *bufLen, names.name[nameIndx], playerPosn );
} else {
XP_LOGFF( "expected %dth name but found only %d",
nameIndx, names.count );
}
break;
}
++nameIndx;
}
}
XP_LOGFF( "(%d) => %s", playerPosn, buf );
}
/* If game is about to end because one player's out of tiles, we don't want to
* keep trying to move. Note that in duplicate mode if ANY player has tiles
* the answer's yes. */

View file

@ -117,6 +117,10 @@ XP_Bool server_commitTrade( ServerCtxt* server, XWEnv xwe,
/* call this when user wants to end the game */
void server_endGame( ServerCtxt* server, XWEnv xwe );
void server_inviteeName( const ServerCtxt* server,
XWEnv xwe, XP_U16 channelNo,
XP_UCHAR* buf, XP_U16* bufLen );
/* called when running as either client or server */
XP_Bool server_receiveMessage( ServerCtxt* server, XWEnv xwe, XWStreamCtxt* incoming );

View file

@ -748,6 +748,14 @@ log_hex( const XP_U8* memp, XP_U16 len, const char* tag )
XP_LOGF( "%s", buf );
}
}
void
log_devid( const MQTTDevID* devID, const XP_UCHAR* tag )
{
XP_UCHAR buf[32];
XP_SNPRINTF( buf, VSIZE(buf), MQTTDevID_FMT, *devID );
XP_LOGFF( "%s: id: %s", tag, buf );
}
#endif
#ifdef CPLUS

View file

@ -140,10 +140,13 @@ XP_Bool strToMQTTCDevID( const XP_UCHAR* str, MQTTDevID* result );
#ifdef DEBUG
void assertSorted( const MoveInfo* mi );
void log_hex( const XP_U8* memp, XP_U16 len, const char* tag );
void log_devid( const MQTTDevID* devID, const XP_UCHAR* tag );
# define LOG_HEX(m,l,t) log_hex((const XP_U8*)(m),(l),(t))
# define LOG_DEVID(ID, TAG) log_devid((ID), (TAG))
#else
# define assertSorted(mi)
# define LOG_HEX(m,l,t)
# define LOG_DEVID(id, tag)
#endif
#ifdef CPLUS