diff --git a/Source/Core/Core/HW/EXI_DeviceSlippi.cpp b/Source/Core/Core/HW/EXI_DeviceSlippi.cpp index 9459ac4abd..4b895a425d 100644 --- a/Source/Core/Core/HW/EXI_DeviceSlippi.cpp +++ b/Source/Core/Core/HW/EXI_DeviceSlippi.cpp @@ -1486,6 +1486,11 @@ bool CEXISlippi::shouldSkipOnlineFrame(s32 frame, s32 finalizedFrame) bool CEXISlippi::shouldAdvanceOnlineFrame(s32 frame) { + // If the opponent is a bot running ahead to give us more inputs, we should + // just keep going at our own pace rather than trying to catch up. + if (opponentRunahead()) + return false; + // Logic below is used to test frame advance by forcing it more often // SConfig::GetInstance().m_EmulationSpeed = 0.5f; // if (frame > 120 && frame % 10 < 3) @@ -1610,6 +1615,24 @@ void CEXISlippi::handleSendInputs(s32 frame, u8 delay, s32 checksumFrame, u32 ch slippi_netplay->SendSlippiPad(std::move(pad)); } +bool CEXISlippi::opponentRunahead() +{ + // Bot players might be running ahead to "donate" their delay frames to us. + + // Only registered bot accounts are allowed to do this. + auto player_info = matchmaking->GetPlayerInfo(); + for (int i = 0; i < player_info.size(); i++) + { + if (i == matchmaking->LocalPlayerIndex()) + continue; + + if (!player_info[i].isBot) + return false; + } + + return true; +} + void CEXISlippi::prepareOpponentInputs(s32 frame, bool shouldSkip) { m_read_queue.clear(); diff --git a/Source/Core/Core/HW/EXI_DeviceSlippi.h b/Source/Core/Core/HW/EXI_DeviceSlippi.h index 1b581da0e8..be6785f97f 100644 --- a/Source/Core/Core/HW/EXI_DeviceSlippi.h +++ b/Source/Core/Core/HW/EXI_DeviceSlippi.h @@ -210,6 +210,7 @@ class CEXISlippi : public IEXIDevice void setMatchSelections(u8 *payload); bool shouldSkipOnlineFrame(s32 frame, s32 finalizedFrame); bool shouldAdvanceOnlineFrame(s32 frame); + bool opponentRunahead(); void handleLogInRequest(); void handleLogOutRequest(); void handleUpdateAppRequest(); diff --git a/Source/Core/Core/Slippi/SlippiMatchmaking.cpp b/Source/Core/Core/Slippi/SlippiMatchmaking.cpp index 11baa0ab14..e78d787034 100644 --- a/Source/Core/Core/Slippi/SlippiMatchmaking.cpp +++ b/Source/Core/Core/Slippi/SlippiMatchmaking.cpp @@ -511,6 +511,7 @@ void SlippiMatchmaking::handleMatchmaking() playerInfo.displayName = el.value("displayName", ""); playerInfo.connectCode = el.value("connectCode", ""); playerInfo.port = el.value("port", 0); + playerInfo.isBot = el.value("isBot", false); if (el["chatMessages"].is_array()) { diff --git a/Source/Core/Core/Slippi/SlippiUser.h b/Source/Core/Core/Slippi/SlippiUser.h index 324b7a56db..2c4b03c2ff 100644 --- a/Source/Core/Core/Slippi/SlippiUser.h +++ b/Source/Core/Core/Slippi/SlippiUser.h @@ -31,6 +31,8 @@ class SlippiUser int port; std::vector chatMessages; + + bool isBot = false; }; SlippiUser(uintptr_t rs_exi_device_ptr);