diff --git a/game/glass/btl4lobby.cpp b/game/glass/btl4lobby.cpp index 2f80f90..482d5b6 100644 --- a/game/glass/btl4lobby.cpp +++ b/game/glass/btl4lobby.cpp @@ -96,6 +96,11 @@ static void matchmaking->SetLobbyMemberData(currentLobby, "vh", vehicle); matchmaking->SetLobbyMemberData(currentLobby, "cl", color); matchmaking->SetLobbyMemberData(currentLobby, "xp", experience); + // BUILD GATE, member half: publish our exact build so the HOST can + // reject mismatches at GO time. This is what catches OLD exes -- they + // predate the joiner-side lobby filter, but they can't fake a "bv" key + // they never set. + matchmaking->SetLobbyMemberData(currentLobby, "bv", BT_VERSION_STRING); } static int @@ -187,10 +192,17 @@ static void int n = 0; for (const char *s = member.name; *s && n < 60; ++s) name[n++] = (WCHAR)*s; name[n] = 0; - wsprintfW(line, L" %d. %-16s %hs, %hs%s", i + 1, name, + // BUILD GATE: flag mismatched members in the roster so the host + // sees WHO won't launch before pressing GO (the log alone left + // the operator guessing on field nights). + const char *bv = matchmaking->GetLobbyMemberData(currentLobby, + matchmaking->GetLobbyMemberByIndex(currentLobby, i), "bv"); + int build_ok = (bv != NULL && strcmp(bv, BT_VERSION_STRING) == 0); + wsprintfW(line, L" %d. %-16s %hs, %hs%s%s", i + 1, name, member.vehicle[0] ? member.vehicle : "mech", member.color[0] ? member.color : "-", - member.isSelf ? L" (you)" : L""); + member.isSelf ? L" (you)" : L"", + build_ok ? L"" : L" [WRONG BUILD -- WILL NOT LAUNCH]"); } else { @@ -378,6 +390,25 @@ int { continue; } + if (!member.isSelf) + { + // BUILD GATE, host half: a member on a different zip (or an + // exe old enough to have no "bv" key at all) gets NO token. + // Omitted from btl4map, their client -- old builds included, + // the code predates the gate -- hits its own "the host's map + // is missing us" path and fails the join cleanly instead of + // desyncing the session (#108's stale-zip confound). + const char *bv = matchmaking->GetLobbyMemberData( + currentLobby, CSteamID(member.steamID), "bv"); + if (bv == NULL || strcmp(bv, BT_VERSION_STRING) != 0) + { + LobbyLog("host: REJECT %s at GO -- their build [%s], " + "ours %s (no token minted; their join will fail)", + member.name, (bv && *bv) ? bv : "pre-gate/unknown", + BT_VERSION_STRING); + continue; + } + } if ((pass == 0) == (member.isSelf != 0)) { roster_out->members[roster_out->memberCount++] = member;