pull in project-slippi/Ishiiruka/pull/246/commits/bd882a308b51ab0d5a914816647ea08a65b1d57e

improve allowed stages logic
This commit is contained in:
Nikhil Narayana 2021-12-19 11:44:50 -08:00
commit b8284fff32
4 changed files with 64 additions and 26 deletions

View file

@ -137,6 +137,16 @@ CEXISlippi::CEXISlippi()
user->ListenForLogIn();
#endif
// Use sane stage defaults (should get overwritten)
allowedStages = {
0x2, // FoD
0x3, // Pokemon
0x8, // Yoshi's Story
0x1C, // Dream Land
0x1F, // Battlefield
0x20, // Final Destination
};
#ifdef CREATE_DIFF_FILES
// MnMaAll.usd
std::string origStr;
@ -1838,8 +1848,9 @@ void CEXISlippi::startFindMatch(u8* payload)
}
// Stage check
if (localSelections.isStageSelected && std::find(legalStages.begin(), legalStages.end(),
localSelections.stageId) == legalStages.end())
if (localSelections.isStageSelected &&
std::find(allowedStages.begin(), allowedStages.end(), localSelections.stageId) ==
allowedStages.end())
{
forcedError = "The stage being requested is not allowed in this mode";
return;
@ -1923,6 +1934,13 @@ void CEXISlippi::prepareOnlineMatchState()
slippi_netplay = matchmaking->GetNetplayClient();
#endif
// This happens on the initial connection to a player. Let's now grab the allowed stages
// returned to us from the matchmaking service and pick a new random stage before sending
// the selections to the opponent
allowedStages = matchmaking->GetStages();
stagePool
.clear(); // Clear stage pool so that when we call getRandomStage it will use full list
localSelections.stageId = getRandomStage();
slippi_netplay->SetMatchSelections(localSelections);
}
@ -2120,7 +2138,7 @@ void CEXISlippi::prepareOnlineMatchState()
return;
}
if (std::find(legalStages.begin(), legalStages.end(), stageId) == legalStages.end())
if (std::find(allowedStages.begin(), allowedStages.end(), stageId) == allowedStages.end())
{
handleConnectionCleanup();
prepareOnlineMatchState();
@ -2279,22 +2297,13 @@ void CEXISlippi::prepareOnlineMatchState()
m_read_queue.insert(m_read_queue.end(), onlineMatchBlock.begin(), onlineMatchBlock.end());
}
std::vector<u16> CEXISlippi::legalStages = {
0x2, // FoD
0x3, // Pokemon
0x8, // Yoshi's Story
0x1C, // Dream Land
0x1F, // Battlefield
0x20, // Final Destination
};
u16 CEXISlippi::getRandomStage(u8 onlineMode)
u16 CEXISlippi::getRandomStage()
{
static u16 selectedStage;
// Reset stage pool if it's empty
if (stagePool.empty())
stagePool.insert(stagePool.end(), legalStages.begin(), legalStages.end());
stagePool.insert(stagePool.end(), allowedStages.begin(), allowedStages.end());
// Get random stage
int randIndex = generator() % stagePool.size();
@ -2303,14 +2312,6 @@ u16 CEXISlippi::getRandomStage(u8 onlineMode)
// Remove last selection from stage pool
stagePool.erase(stagePool.begin() + randIndex);
// If the mode is teams, don't allow FoD to be selected, re-roll instead. Note that this will
// cause a stack overflow exception/infinite recursion in the case where a dev removes all
// stages but FoD from the legalStages vector
if (onlineMode == (u8)SlippiMatchmaking::OnlinePlayMode::TEAMS && selectedStage == 0x2)
{
return getRandomStage(onlineMode);
}
return selectedStage;
}
@ -2325,13 +2326,13 @@ void CEXISlippi::setMatchSelections(u8* payload)
s.stageId = Common::swap16(&payload[4]);
u8 stageSelectOption = payload[6];
u8 onlineMode = payload[7];
// u8 onlineMode = payload[7];
s.isStageSelected = stageSelectOption == 1 || stageSelectOption == 3;
if (stageSelectOption == 3)
{
// If stage requested is random, select a random stage
s.stageId = getRandomStage(onlineMode);
s.stageId = getRandomStage();
}
INFO_LOG(SLIPPI, "LPS set char: %d, iSS: %d, %d, stage: %d, team: %d", s.isCharacterSelected,

View file

@ -163,7 +163,7 @@ private:
std::vector<u8> m_payload;
// online play stuff
u16 getRandomStage(u8 onlineMode);
u16 getRandomStage();
bool isDisconnected();
void handleOnlineInputs(u8* payload);
void prepareOpponentInputs(u8* payload);
@ -251,6 +251,6 @@ private:
std::map<s32, std::unique_ptr<SlippiSavestate>> activeSavestates;
std::deque<std::unique_ptr<SlippiSavestate>> availableSavestates;
static std::vector<u16> legalStages;
std::vector<u16> allowedStages;
};
} // namespace ExpansionInterface

View file

@ -483,6 +483,36 @@ void SlippiMatchmaking::handleMatchmaking()
}
m_isHost = getResp.value("isHost", false);
// Get allowed stages. For stage select modes like direct and teams, this will only impact the
// first map selected
m_allowedStages.clear();
auto stages = getResp["stages"];
if (stages.is_array())
{
for (json::iterator it = stages.begin(); it != stages.end(); ++it)
{
json el = *it;
auto stageId = el.get<int>();
m_allowedStages.push_back(stageId);
}
}
if (m_allowedStages.empty())
{
// Default case, shouldn't ever really be hit but it's here just in case
m_allowedStages.push_back(0x3); // Pokemon
m_allowedStages.push_back(0x8); // Yoshi's Story
m_allowedStages.push_back(0x1C); // Dream Land
m_allowedStages.push_back(0x1F); // Battlefield
m_allowedStages.push_back(0x20); // Final Destination
// Add FoD if singles
if (m_playerInfo.size() == 2)
{
m_allowedStages.push_back(0x2); // FoD
}
}
// Disconnect and destroy enet client to mm server
terminateMmConnection();
@ -501,6 +531,11 @@ std::vector<SlippiUser::UserInfo> SlippiMatchmaking::GetPlayerInfo()
return m_playerInfo;
}
std::vector<u16> SlippiMatchmaking::GetStages()
{
return m_allowedStages;
}
std::string SlippiMatchmaking::GetPlayerName(u8 port)
{
if (port >= m_playerInfo.size())

View file

@ -56,6 +56,7 @@ public:
int LocalPlayerIndex();
std::vector<SlippiUser::UserInfo> GetPlayerInfo();
std::string GetPlayerName(u8 port);
std::vector<u16> GetStages();
u8 RemotePlayerCount();
static bool IsFixedRulesMode(OnlinePlayMode mode);
@ -88,6 +89,7 @@ protected:
int m_localPlayerIndex;
std::vector<std::string> m_remoteIps;
std::vector<SlippiUser::UserInfo> m_playerInfo;
std::vector<u16> m_allowedStages;
bool m_joinedLobby;
bool m_isHost;