Added SaveState saving

This commit is contained in:
Sage King 2022-08-12 14:53:07 -06:00 committed by Nayla Hanegan
commit 473f54de0a
No known key found for this signature in database
GPG key ID: 3075216CED0DB01D
2 changed files with 75 additions and 2 deletions

View file

@ -45,6 +45,7 @@
#include "Core/GeckoCode.h"
#include "Core/HW/EXI/EXI.h"
#include "Core/HW/EXI/EXI_DeviceIPL.h"
#include "Core/State.h"
#ifdef HAS_LIBMGBA
#include "Core/HW/GBACore.h"
#endif
@ -975,10 +976,11 @@ void NetPlayClient::OnStartGame(sf::Packet& packet)
}
inputs.clear();
for (int i = 0; i < m_players.size(); i++)
inputs.push_back(std::vector<GCPadStatus>{});
save_states.reset();
m_dialog->OnMsgStartGame();
}
@ -1634,6 +1636,47 @@ void NetPlayClient::OnFrameEnd()
if (send_packet)
SendAsync(std::move(packet));
lock.unlock();
std::shared_ptr<SaveState> new_save_state = std::make_shared<SaveState>();
State::SaveToBuffer(*new_save_state);
lock.lock();
save_states.New() = new_save_state;
// Wait for inputs if others are behind us, continue if we're behind them
int local_player_port = -1;
for (int i = 0; i < m_pad_map.size(); i++)
{
if (m_pad_map.at(i) == m_local_player->pid)
local_player_port = i;
}
for (int remote_players = 0; remote_players < inputs.size(); remote_players++)
{
if (remote_players == local_player_port)
continue;
auto frame_difference = static_cast<long long>(inputs.at(local_player_port).size()) -
static_cast<long long>(inputs.at(remote_players).size());
if (frame_difference <= 0)
{
continue;
}
else
{
while (frame_difference > rollback_frames_supported + delay)
{
if (!m_is_running.IsSet())
break;
frame_difference = static_cast<long long>(inputs.at(local_player_port).size()) -
static_cast<long long>(inputs.at(remote_players).size());
wait_for_inputs.wait_for(lock, 1ms);
}
}
}
}
void NetPlayClient::Send(const sf::Packet& packet, const u8 channel_id)

View file

@ -43,7 +43,35 @@ struct SerializedWiimoteState;
namespace NetPlay
{
constexpr size_t rollback_frames_supported = 10;
constexpr int rollback_frames_supported = 10;
using SaveState = std::vector<u8>;
// 0 is the closest SaveState in time from the current frame
class SaveStateArray
{
public:
std::shared_ptr<SaveState>& New()
{
std::array<std::shared_ptr<SaveState>, rollback_frames_supported> new_array{};
for (int i = rollback_frames_supported - 2; i >= 0; i--)
{
new_array.at(i + 1) = main_array.at(i);
}
new_array.at(0) = std::shared_ptr<SaveState>{};
main_array = std::move(new_array);
return main_array.at(0);
};
void reset()
{
for (auto& save_state : main_array)
save_state = std::shared_ptr<SaveState>{};
}
private:
std::array<std::shared_ptr<SaveState>, rollback_frames_supported> main_array;
};
class NetPlayUI
{
@ -364,6 +392,8 @@ private:
std::vector<std::vector<GCPadStatus>> inputs;
int delay = 2;
std::condition_variable wait_for_inputs;
SaveStateArray save_states;
};
void NetPlay_Enable(NetPlayClient* const np);