pull in project-slippi/Ishiiruka/commit/5a77120289f7542302a2eb53b9ee2bce43d490f6

enforce stage for fixed rules modes
This commit is contained in:
Nikhil Narayana 2021-12-18 17:20:42 -08:00
commit 3e48d6965a
4 changed files with 80 additions and 33 deletions

View file

@ -27,6 +27,7 @@
#include "Core/Host.h" #include "Core/Host.h"
#include "Core/NetPlayClient.h" #include "Core/NetPlayClient.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
#include "Core/Slippi/SlippiMatchmaking.h"
#include "Core/Slippi/SlippiPlayback.h" #include "Core/Slippi/SlippiPlayback.h"
#include "Core/Slippi/SlippiReplayComm.h" #include "Core/Slippi/SlippiReplayComm.h"
#include "Core/State.h" #include "Core/State.h"
@ -1508,7 +1509,6 @@ bool CEXISlippi::isDisconnected()
return status != SlippiNetplayClient::SlippiConnectStatus::NET_CONNECT_STATUS_CONNECTED; return status != SlippiNetplayClient::SlippiConnectStatus::NET_CONNECT_STATUS_CONNECTED;
} }
static int tempTestCount = 0;
void CEXISlippi::handleOnlineInputs(u8* payload) void CEXISlippi::handleOnlineInputs(u8* payload)
{ {
m_read_queue.clear(); m_read_queue.clear();
@ -1829,10 +1829,23 @@ void CEXISlippi::startFindMatch(u8* payload)
// give someone an early error before they even queue so that they wont enter the queue and make // give someone an early error before they even queue so that they wont enter the queue and make
// someone else get force removed from queue and have to requeue // someone else get force removed from queue and have to requeue
auto directMode = SlippiMatchmaking::OnlinePlayMode::DIRECT; auto directMode = SlippiMatchmaking::OnlinePlayMode::DIRECT;
if (search.mode < directMode && localSelections.characterId >= 26) if (SlippiMatchmaking::IsFixedRulesMode(search.mode))
{ {
forcedError = "The character you selected is not allowed in this mode"; // Character check
return; if (localSelections.characterId >= 26)
{
forcedError = "The character you selected is not allowed in this mode";
return;
}
// Stage check
if (localSelections.isStageSelected &&
std::find(singlesStages.begin(), singlesStages.end(), localSelections.stageId) ==
singlesStages.end())
{
forcedError = "The stage being requested is not allowed in this mode";
return;
}
} }
#ifndef LOCAL_TESTING #ifndef LOCAL_TESTING
@ -2070,14 +2083,53 @@ void CEXISlippi::prepareOnlineMatchState()
if (rps[i].characterId >= 26) if (rps[i].characterId >= 26)
remoteCharOk = false; remoteCharOk = false;
} }
if (lastSearch.mode < directMode && (!localCharOk || !remoteCharOk))
// TODO: This is annoying, ideally remotePlayerSelections would just include everyone including
// the local player
// TODO: Would also simplify some logic in the Netplay class
std::vector<SlippiPlayerSelections> orderedSelections(4);
orderedSelections[lps.playerIdx] = lps;
for (int i = 0; i < remotePlayerCount; i++)
{ {
// If we get here, someone is doing something bad, clear the lobby orderedSelections[rps[i].playerIdx] = rps[i];
handleConnectionCleanup(); }
// Overwrite stage information. Make sure everyone loads the same stage
u16 stageId = 0x1F; // Default to battlefield if there was no selection
for (auto selections : orderedSelections)
{
if (!selections.isStageSelected)
continue;
// Stage selected by this player, use that selection
stageId = selections.stageId;
break;
}
if (SlippiMatchmaking::IsFixedRulesMode(lastSearch.mode))
{
// If we enter one of these conditions, someone is doing something bad, clear the lobby
if (!localCharOk) if (!localCharOk)
{
handleConnectionCleanup();
forcedError = "The character you selected is not allowed in this mode"; forcedError = "The character you selected is not allowed in this mode";
prepareOnlineMatchState(); prepareOnlineMatchState();
return; return;
}
if (!remoteCharOk)
{
handleConnectionCleanup();
prepareOnlineMatchState();
return;
}
if (std::find(singlesStages.begin(), singlesStages.end(), stageId) == singlesStages.end())
{
handleConnectionCleanup();
prepareOnlineMatchState();
return;
}
} }
// Overwrite local player character // Overwrite local player character
@ -2121,20 +2173,6 @@ void CEXISlippi::prepareOnlineMatchState()
onlineMatchBlock[0x61 + 3 * 0x24] = 0; onlineMatchBlock[0x61 + 3 * 0x24] = 0;
} }
// Overwrite stage
u16 stageId;
if (isDecider)
{
stageId = lps.isStageSelected ? lps.stageId : rps[0].stageId;
}
else
{
stageId = rps[0].isStageSelected ? rps[0].stageId : lps.stageId;
}
u16* stage = (u16*)&onlineMatchBlock[0xE];
*stage = Common::swap16(stageId);
// Set rng offset // Set rng offset
rngOffset = isDecider ? lps.rngOffset : rps[0].rngOffset; rngOffset = isDecider ? lps.rngOffset : rps[0].rngOffset;
WARN_LOG(SLIPPI_ONLINE, "Rng Offset: 0x%x", rngOffset); WARN_LOG(SLIPPI_ONLINE, "Rng Offset: 0x%x", rngOffset);
@ -2244,22 +2282,22 @@ void CEXISlippi::prepareOnlineMatchState()
m_read_queue.insert(m_read_queue.end(), onlineMatchBlock.begin(), onlineMatchBlock.end()); m_read_queue.insert(m_read_queue.end(), onlineMatchBlock.begin(), onlineMatchBlock.end());
} }
std::vector<u16> CEXISlippi::singlesStages = {
// 0x2, // FoD
0x3, // Pokemon
0x8, // Yoshi's Story
0x1C, // Dream Land
0x1F, // Battlefield
0x20, // Final Destination
};
u16 CEXISlippi::getRandomStage() u16 CEXISlippi::getRandomStage()
{ {
static u16 selectedStage; static u16 selectedStage;
static std::vector<u16> stages = {
0x2, // FoD
0x3, // Pokemon
0x8, // Yoshi's Story
0x1C, // Dream Land
0x1F, // Battlefield
0x20, // Final Destination
};
// Reset stage pool if it's empty // Reset stage pool if it's empty
if (stagePool.empty()) if (stagePool.empty())
stagePool.insert(stagePool.end(), stages.begin(), stages.end()); stagePool.insert(stagePool.end(), singlesStages.begin(), singlesStages.end());
// Get random stage // Get random stage
int randIndex = generator() % stagePool.size(); int randIndex = generator() % stagePool.size();

View file

@ -251,5 +251,7 @@ private:
std::map<s32, std::unique_ptr<SlippiSavestate>> activeSavestates; std::map<s32, std::unique_ptr<SlippiSavestate>> activeSavestates;
std::deque<std::unique_ptr<SlippiSavestate>> availableSavestates; std::deque<std::unique_ptr<SlippiSavestate>> availableSavestates;
static std::vector<u16> singlesStages;
}; };
} // namespace ExpansionInterface } // namespace ExpansionInterface

View file

@ -85,6 +85,12 @@ std::unique_ptr<SlippiNetplayClient> SlippiMatchmaking::GetNetplayClient()
return std::move(m_netplayClient); return std::move(m_netplayClient);
} }
bool IsFixedRulesMode(SlippiMatchmaking::OnlinePlayMode mode)
{
return mode == SlippiMatchmaking::OnlinePlayMode::UNRANKED ||
mode == SlippiMatchmaking::OnlinePlayMode::RANKED;
}
void SlippiMatchmaking::sendMessage(json msg) void SlippiMatchmaking::sendMessage(json msg)
{ {
enet_uint32 flags = ENET_PACKET_FLAG_RELIABLE; enet_uint32 flags = ENET_PACKET_FLAG_RELIABLE;

View file

@ -57,6 +57,7 @@ public:
std::vector<SlippiUser::UserInfo> GetPlayerInfo(); std::vector<SlippiUser::UserInfo> GetPlayerInfo();
std::string GetPlayerName(u8 port); std::string GetPlayerName(u8 port);
u8 RemotePlayerCount(); u8 RemotePlayerCount();
static bool IsFixedRulesMode(OnlinePlayMode mode);
protected: protected:
const std::string MM_HOST_DEV = "35.197.121.196"; // Dev host const std::string MM_HOST_DEV = "35.197.121.196"; // Dev host