Skip to content

Commit

Permalink
Additional blind mode options
Browse files Browse the repository at this point in the history
  • Loading branch information
past-due committed Jan 12, 2025
1 parent 46e7e2e commit 3f9e15f
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 36 deletions.
9 changes: 4 additions & 5 deletions lib/netplay/netplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -737,9 +737,8 @@ static void NETSendNPlayerInfoTo(uint32_t *index, uint32_t indexLen, unsigned to
NETbool(&NetPlay.players[index[n]].allocated);
NETbool(&NetPlay.players[index[n]].heartbeat);
NETbool(&NetPlay.players[index[n]].kick);
if (game.blindMode != BLIND_MODE::NONE // if in blind mode
&& index[n] < MAX_PLAYER_SLOTS // and an actual player slot (not a spectator slot)
&& !ingame.endTime.has_value()) // and game has not ended
if (isBlindPlayerInfoState() // if in blind player info state
&& index[n] < MAX_PLAYER_SLOTS) // and an actual player slot (not a spectator slot)
{
// send a generic player name
const char* genericName = getPlayerGenericName(index[n]);
Expand Down Expand Up @@ -1018,7 +1017,7 @@ static void NETplayerLeaving(UDWORD index, bool quietSocketClose)
NET_DestroyPlayer(index); // sets index player's array to false
if (!wasSpectator)
{
resetReadyStatus(false, game.blindMode == BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY); // reset ready status for all players
resetReadyStatus(false, isBlindSimpleLobby(game.blindMode)); // reset ready status for all players
resetReadyCalled = true;
}

Expand Down Expand Up @@ -1059,7 +1058,7 @@ static void NETplayerDropped(UDWORD index)
NET_DestroyPlayer(id); // just clears array
if (!wasSpectator)
{
resetReadyStatus(false, game.blindMode == BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY); // reset ready status for all players
resetReadyStatus(false, isBlindSimpleLobby(game.blindMode)); // reset ready status for all players
resetReadyCalled = true;
}

Expand Down
2 changes: 1 addition & 1 deletion src/loop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ static void gameStateUpdate()
NetPlay.players[0].allocated, NetPlay.players[1].allocated, NetPlay.players[2].allocated, NetPlay.players[3].allocated, NetPlay.players[4].allocated, NetPlay.players[5].allocated, NetPlay.players[6].allocated, NetPlay.players[7].allocated, NetPlay.players[8].allocated, NetPlay.players[9].allocated,
NetPlay.players[0].position, NetPlay.players[1].position, NetPlay.players[2].position, NetPlay.players[3].position, NetPlay.players[4].position, NetPlay.players[5].position, NetPlay.players[6].position, NetPlay.players[7].position, NetPlay.players[8].position, NetPlay.players[9].position
);
bool overrideHandleClientBlindNames = (game.blindMode != BLIND_MODE::NONE) && (NetPlay.isHost || NETisReplay()) && !ingame.endTime.has_value();
bool overrideHandleClientBlindNames = (game.blindMode >= BLIND_MODE::BLIND_GAME) && (NetPlay.isHost || NETisReplay()) && !ingame.endTime.has_value();
for (unsigned n = 0; n < MAX_PLAYERS; ++n)
{
syncDebug("Player %d = \"%s\"", n, (!overrideHandleClientBlindNames) ? NetPlay.players[n].name : getPlayerGenericName(n));
Expand Down
53 changes: 35 additions & 18 deletions src/multiint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1540,7 +1540,7 @@ int allPlayersOnSameTeam(int except)

int WzMultiplayerOptionsTitleUI::playerRowY0(uint32_t row) const
{
if (game.blindMode == BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY && !NetPlay.isHost)
if (isBlindSimpleLobby(game.blindMode) && !NetPlay.isHost)
{
// Get Y position of virtual player row in WzPlayerBlindWaitingRoom widget
auto pBlindWaitingRoom = widgFormGetFromID(psWScreen->psForm, MULTIOP_BLIND_WAITING_ROOM);
Expand Down Expand Up @@ -1671,7 +1671,7 @@ void WzMultiplayerOptionsTitleUI::openDifficultyChooser(uint32_t player)
ASSERT_OR_RETURN(, pStrongPtr.operator bool(), "WzMultiplayerOptionsTitleUI no longer exists");
NetPlay.players[player].difficulty = difficultyValue[difficultyIdx];
NETBroadcastPlayerInfo(player);
resetReadyStatus(false, game.blindMode == BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY);
resetReadyStatus(false, isBlindSimpleLobby(game.blindMode));
widgScheduleTask([pStrongPtr] {
pStrongPtr->closeDifficultyChooser();
pStrongPtr->addPlayerBox(true);
Expand Down Expand Up @@ -1780,7 +1780,7 @@ void WzMultiplayerOptionsTitleUI::openAiChooser(uint32_t player)
// common code
NetPlay.players[player].difficulty = AIDifficulty::DISABLED; // disable AI for this slot
NETBroadcastPlayerInfo(player);
resetReadyStatus(false, game.blindMode == BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY);
resetReadyStatus(false, isBlindSimpleLobby(game.blindMode));
}
else
{
Expand Down Expand Up @@ -1930,7 +1930,7 @@ class WzPlayerSelectionChangePositionRow : public W_BUTTON
auto strongTitleUI = titleUI.lock();
ASSERT_OR_RETURN(, strongTitleUI != nullptr, "Title UI is gone?");
// Switch player
resetReadyStatus(false, game.blindMode == BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY); // will reset only locally if not a host
resetReadyStatus(false, isBlindSimpleLobby(game.blindMode)); // will reset only locally if not a host
SendPositionRequest(switcherPlayerIdx, NetPlay.players[selectPositionRow->targetPlayerIdx].position);
widgScheduleTask([strongTitleUI] {
strongTitleUI->closePositionChooser();
Expand Down Expand Up @@ -1997,7 +1997,7 @@ class WzPlayerIndexSwapPositionRow : public W_BUTTON
std::string playerName = getPlayerName(switcherPlayerIdx, true);

NETmoveSpectatorToPlayerSlot(switcherPlayerIdx, selectPositionRow->targetPlayerIdx, true);
resetReadyStatus(true, game.blindMode == BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY); //reset and send notification to all clients
resetReadyStatus(true, isBlindSimpleLobby(game.blindMode)); //reset and send notification to all clients
widgScheduleTask([strongTitleUI] {
strongTitleUI->closePlayerSlotSwapChooser();
strongTitleUI->updatePlayers();
Expand Down Expand Up @@ -2236,7 +2236,7 @@ void WzMultiplayerOptionsTitleUI::openTeamChooser(uint32_t player)
ASSERT(id >= MULTIOP_TEAMCHOOSER
&& (id - MULTIOP_TEAMCHOOSER) < MAX_PLAYERS, "processMultiopWidgets: wrong id - MULTIOP_TEAMCHOOSER value (%d)", id - MULTIOP_TEAMCHOOSER);

resetReadyStatus(false, game.blindMode == BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY); // will reset only locally if not a host
resetReadyStatus(false, isBlindSimpleLobby(game.blindMode)); // will reset only locally if not a host

SendTeamRequest(player, (UBYTE)id - MULTIOP_TEAMCHOOSER);

Expand Down Expand Up @@ -4309,7 +4309,7 @@ void WzMultiplayerOptionsTitleUI::addPlayerBox(bool players)

auto titleUI = std::dynamic_pointer_cast<WzMultiplayerOptionsTitleUI>(shared_from_this());

if (game.blindMode == BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY && !NetPlay.isHost)
if (isBlindSimpleLobby(game.blindMode) && !NetPlay.isHost)
{
// Display custom "waiting room" that completely blinds the current player

Expand Down Expand Up @@ -5407,6 +5407,27 @@ static void updateMapWidgets(LEVEL_DATASET *mapData)
widgSetString(psWScreen, MULTIOP_MAP + 1, name.toUtf8().c_str()); //What a horrible, horrible way to do this! FIX ME! (See addBlueForm)
}

bool blindModeFromStr(const WzString& str, BLIND_MODE& mode_output)
{
const std::unordered_map<WzString, BLIND_MODE> mappings = {
{"none", BLIND_MODE::NONE},
{"blind_lobby", BLIND_MODE::BLIND_LOBBY},
{"blind_lobby_simple_lobby", BLIND_MODE::BLIND_LOBBY_SIMPLE_LOBBY},
{"blind_game", BLIND_MODE::BLIND_GAME},
{"blind_game_simple_lobby", BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY},
};

auto it = mappings.find(str);
if (it != mappings.end())
{
mode_output = it->second;
return true;
}

mode_output = BLIND_MODE::NONE;
return false;
}

static bool loadMapChallengeSettings(WzConfig& ini)
{
ini.beginGroup("locked"); // GUI lockdown
Expand Down Expand Up @@ -5474,14 +5495,10 @@ static bool loadMapChallengeSettings(WzConfig& ini)
defaultOpenSpectatorSlots = static_cast<uint16_t>(std::min<unsigned int>(openSpectatorSlots_uint, MAX_SPECTATOR_SLOTS));

// Allow setting "blind mode"
unsigned int blindMode_uint = ini.value("blindMode", 0).toUInt();
if (blindMode_uint <= static_cast<unsigned int>(BLIND_MODE_MAX))
{
game.blindMode = static_cast<BLIND_MODE>(blindMode_uint);
}
else
WzString blindMode_str = ini.value("blindMode", "none").toWzString();
if (!blindModeFromStr(blindMode_str, game.blindMode))
{
debug(LOG_ERROR, "Invalid blindMode (%u) specified in config .json - ignoring", blindMode_uint);
debug(LOG_ERROR, "Invalid blindMode (%s) specified in config .json - ignoring", blindMode_str.toUtf8().c_str());
}

// DEPRECATED: This seems to have been odd workaround for not having the locked group handled.
Expand Down Expand Up @@ -6392,7 +6409,7 @@ class WzHostLobbyOperationsInterface : public HostLobbyOperationsInterface
return true;
}
::changeTeam(player, team, responsibleIdx);
resetReadyStatus(false, game.blindMode == BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY);
resetReadyStatus(false, isBlindSimpleLobby(game.blindMode));
return true;
}
virtual bool changePosition(uint32_t player, uint8_t position, uint32_t responsibleIdx) override
Expand All @@ -6414,7 +6431,7 @@ class WzHostLobbyOperationsInterface : public HostLobbyOperationsInterface
{
return false;
}
resetReadyStatus(false, game.blindMode == BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY);
resetReadyStatus(false, isBlindSimpleLobby(game.blindMode));
return true;
}
virtual bool changeBase(uint8_t baseValue) override
Expand Down Expand Up @@ -6477,7 +6494,7 @@ class WzHostLobbyOperationsInterface : public HostLobbyOperationsInterface
std::string slotType = (NetPlay.players[player].isSpectator) ? "spectator" : "player";
sendRoomSystemMessage((std::string("Kicking ")+slotType+": "+std::string(getPlayerName(player, true))).c_str());
::kickPlayer(player, reason, ERROR_KICKED, ban);
resetReadyStatus(false, game.blindMode == BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY);
resetReadyStatus(false, isBlindSimpleLobby(game.blindMode));
return true;
}
virtual bool changeHostChatPermissions(uint32_t player, bool freeChatEnabled) override
Expand Down Expand Up @@ -6881,7 +6898,7 @@ void WzMultiplayerOptionsTitleUI::frontendMultiMessages(bool running)
{
uint32_t player_id = MAX_CONNECTED_PLAYERS;

resetReadyStatus(false, game.blindMode == BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY);
resetReadyStatus(false, isBlindSimpleLobby(game.blindMode));

NETbeginDecode(queue, NET_PLAYER_DROPPED);
{
Expand Down
20 changes: 19 additions & 1 deletion src/multiplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,24 @@ bool multiPlayerLoop()
ingame.lastPlayerDataCheck2 = std::chrono::steady_clock::now();
wz_command_interface_output("WZEVENT: allPlayersJoined\n");
wz_command_interface_output_room_status_json();

// If in blind *lobby* mode, send data on who the players are
if (game.blindMode != BLIND_MODE::NONE && game.blindMode < BLIND_MODE::BLIND_GAME)
{
if (NetPlay.isHost)
{
debug(LOG_INFO, "Revealing actual player names and identities to all players");

// Send updated player info (which will include real player names) to all players
NETSendAllPlayerInfoTo(NET_ALL_PLAYERS);

// Send the verified player identity from initial join for each player
for (uint32_t idx = 0; idx < MAX_CONNECTED_PLAYERS; ++idx)
{
sendMultiStatsHostVerifiedIdentities(idx);
}
}
}
}
if (NetPlay.bComms)
{
Expand Down Expand Up @@ -674,7 +692,7 @@ BASE_OBJECT *IdToPointer(UDWORD id, UDWORD player)
return nullptr;
}

static inline bool isBlindPlayerInfoState()
bool isBlindPlayerInfoState()
{
if (game.blindMode == BLIND_MODE::NONE)
{
Expand Down
1 change: 1 addition & 0 deletions src/multiplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ Vector3i cameraToHome(UDWORD player, bool scroll, bool fromSave);

bool multiPlayerLoop(); // for loop.c

bool isBlindPlayerInfoState();
// return a "generic" player name that is fixed based on the player idx (useful for blind mode games)
const char *getPlayerGenericName(int player);

Expand Down
4 changes: 4 additions & 0 deletions src/multiplaydefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,14 @@ constexpr PLAYER_LEAVE_MODE PLAYER_LEAVE_MODE_DEFAULT = PLAYER_LEAVE_MODE::SPLIT
enum class BLIND_MODE : uint8_t
{
NONE,
BLIND_LOBBY, // standard blind mode lobby (players' true identities are hidden from everyone except a spectator host until the game starts)
BLIND_LOBBY_SIMPLE_LOBBY, // BLIND_LOBBY, but not showing any other players in lobby (players will just be informed that they are waiting for other players)
BLIND_GAME, // standard blind mode game (players' true identities are hidden from everyone except a spectator host until the game is over)
BLIND_GAME_SIMPLE_LOBBY // BLIND_GAME, but not showing any other players in lobby (players will just be informed that they are waiting for other players)
};

constexpr BLIND_MODE BLIND_MODE_MAX = BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY;

static inline bool isBlindSimpleLobby(BLIND_MODE mode) { return mode == BLIND_MODE::BLIND_LOBBY_SIMPLE_LOBBY || mode == BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY; }

#endif // __INCLUDED_SRC_MULTIPLAYDEFS_H__
16 changes: 11 additions & 5 deletions src/multistat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ bool swapPlayerMultiStatsLocal(uint32_t playerIndexA, uint32_t playerIndexB)
return true;
}

bool sendMultiStats(uint32_t playerIndex, optional<uint32_t> recipientPlayerIndex /*= nullopt*/)
static bool sendMultiStatsInternal(uint32_t playerIndex, optional<uint32_t> recipientPlayerIndex = nullopt, bool sendHostVerifiedJoinIdentity = false)
{
ASSERT(NetPlay.isHost || playerIndex == realSelectedPlayer, "Hah");

Expand Down Expand Up @@ -363,7 +363,7 @@ bool sendMultiStats(uint32_t playerIndex, optional<uint32_t> recipientPlayerInde
EcKey::Key identityPublicKey;
bool isHostVerifiedIdentity = false;
// Choose the identity to send
if (!ingame.endTime.has_value() || !NetPlay.isHost)
if (!sendHostVerifiedJoinIdentity || !NetPlay.isHost)
{
if (playerIndex == realSelectedPlayer)
{
Expand All @@ -385,7 +385,8 @@ bool sendMultiStats(uint32_t playerIndex, optional<uint32_t> recipientPlayerInde
}
else
{
// Once game has ended, if we're the host, send the hostVerifiedJoinIdentity
// Once game has begun or ended (depending on settings), if we're the host, send the hostVerifiedJoinIdentity
ASSERT(NetPlay.isHost && !isBlindPlayerInfoState(), "Not time to send host verified identity yet?");
isHostVerifiedIdentity = true;
if (!hostVerifiedJoinIdentities[playerIndex].empty())
{
Expand All @@ -400,11 +401,16 @@ bool sendMultiStats(uint32_t playerIndex, optional<uint32_t> recipientPlayerInde
return true;
}

bool sendMultiStats(uint32_t playerIndex, optional<uint32_t> recipientPlayerIndex /*= nullopt*/)
{
return sendMultiStatsInternal(playerIndex, recipientPlayerIndex, false);
}

bool sendMultiStatsHostVerifiedIdentities(uint32_t playerIndex)
{
ASSERT_HOST_ONLY(return false);
ASSERT_OR_RETURN(false, ingame.endTime.has_value(), "Game hasn't ended yet");
return sendMultiStats(playerIndex); // rely on sendMultiStats behavior when game has ended and this is the host to send the host-verified join identity
ASSERT_OR_RETURN(false, !isBlindPlayerInfoState(), "Not time to send host verified identities yet");
return sendMultiStatsInternal(playerIndex, nullopt, true);
}

// ////////////////////////////////////////////////////////////////////////////
Expand Down
12 changes: 6 additions & 6 deletions src/titleui/widgets/lobbyplayerrow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ void displayPlayer(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset)

static bool canChooseTeamFor(int i)
{
if (game.blindMode == BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY && !NetPlay.isHost)
if (isBlindSimpleLobby(game.blindMode) && !NetPlay.isHost)
{
return false;
}
Expand Down Expand Up @@ -603,7 +603,7 @@ std::shared_ptr<WzPlayerRow> WzPlayerRow::make(uint32_t playerIdx, const std::sh
&& !locked.position
&& player < MAX_PLAYERS
&& !isSpectatorOnlySlot(player)
&& ((game.blindMode != BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY) || NetPlay.isHost))
&& (!isBlindSimpleLobby(game.blindMode) || NetPlay.isHost))
{
widgScheduleTask([strongTitleUI, player] {
strongTitleUI->openPositionChooser(player);
Expand All @@ -628,7 +628,7 @@ std::shared_ptr<WzPlayerRow> WzPlayerRow::make(uint32_t playerIdx, const std::sh
}
widgScheduleTask([strongTitleUI] {
strongTitleUI->updatePlayers();
resetReadyStatus(false, game.blindMode == BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY);
resetReadyStatus(false, isBlindSimpleLobby(game.blindMode));
});
}
else
Expand Down Expand Up @@ -709,7 +709,7 @@ void WzPlayerRow::updateState()
&& NetPlay.players[playerIdx].allocated
&& !locked.position
&& !isSpectatorOnlySlot(playerIdx)
&& ((game.blindMode != BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY) || NetPlay.isHost))
&& (!isBlindSimpleLobby(game.blindMode) || NetPlay.isHost))
{
playerInfoTooltip = _("Click to change player position");
}
Expand Down Expand Up @@ -813,7 +813,7 @@ void WzPlayerRow::updateState()

void WzPlayerRow::updateReadyButton()
{
bool disallow = (allPlayersOnSameTeam(-1) != -1) && (game.blindMode != BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY);
bool disallow = (allPlayersOnSameTeam(-1) != -1) && !isBlindSimpleLobby(game.blindMode);

const auto& aidata = getAIData();
const auto& locked = getLockedOptions();
Expand Down Expand Up @@ -969,7 +969,7 @@ void WzPlayerRow::updateReadyButton()
std::string msg = astringf(_("The host has kicked %s from the game!"), getPlayerName(player, true));
sendRoomSystemMessage(msg.c_str());
kickPlayer(player, _("The host has kicked you from the game."), ERROR_KICKED, false);
resetReadyStatus(true, game.blindMode == BLIND_MODE::BLIND_GAME_SIMPLE_LOBBY); //reset and send notification to all clients
resetReadyStatus(true, isBlindSimpleLobby(game.blindMode)); //reset and send notification to all clients
}
}
});
Expand Down

0 comments on commit 3f9e15f

Please sign in to comment.