NetPlay: Sync host cheat codes with clients

This commit is contained in:
Souryo 2016-01-21 20:30:00 -05:00
parent 40eac94d18
commit a2c9122f74
6 changed files with 79 additions and 24 deletions

View file

@ -156,4 +156,30 @@ void CheatManager::ApplyPrgCodes(uint8_t *prgRam, uint32_t prgSize)
}
}
Console::Resume();
}
vector<CodeInfo> CheatManager::GetCheats()
{
//Used by NetPlay
vector<CodeInfo> cheats;
for(unique_ptr<vector<CodeInfo>> &codes : Instance->_relativeCheatCodes) {
if(codes) {
std::copy(codes.get()->begin(), codes.get()->end(), std::back_inserter(cheats));
}
}
std::copy(Instance->_absoluteCheatCodes.begin(), Instance->_absoluteCheatCodes.end(), std::back_inserter(cheats));
return cheats;
}
void CheatManager::SetCheats(vector<CodeInfo> &cheats)
{
//Used by NetPlay
Instance->ClearCodes();
if(cheats.size() > 0) {
MessageManager::DisplayMessage("NetPlay", std::to_string(cheats.size()) + " cheats applied.");
for(CodeInfo &cheat : cheats) {
Instance->AddCode(cheat);
}
}
}

View file

@ -29,6 +29,8 @@ public:
static void AddProActionRockyCode(uint32_t code);
static void AddCustomCode(uint32_t address, uint8_t value, int32_t compareValue = -1, bool isRelativeAddress = true);
static void ClearCodes();
static vector<CodeInfo> GetCheats();
static void SetCheats(vector<CodeInfo> &cheats);
static void ApplyRamCodes(uint16_t addr, uint8_t &value);
static void ApplyPrgCodes(uint8_t *prgRam, uint32_t prgSize);

View file

@ -37,20 +37,8 @@ GameServerConnection::~GameServerConnection()
void GameServerConnection::SendGameState()
{
Console::Pause();
stringstream state;
Console::SaveState(state);
_handshakeCompleted = true;
ControlManager::RegisterControlDevice(this, _controllerPort);
Console::Resume();
uint32_t size = (uint32_t)state.tellp();
char* buffer = new char[size];
state.read(buffer, size);
SaveStateMessage message(buffer, size, true);
SaveStateMessage message;
SendNetMessage(message);
delete[] buffer;
}
void GameServerConnection::SendGameInformation()
@ -89,11 +77,17 @@ void GameServerConnection::ProcessMessage(NetMessage* message)
case MessageType::HandShake:
//Send the game's current state to the client and register the controller
if(((HandShakeMessage*)message)->IsValid()) {
Console::Pause();
_connectionData.reset(new ClientConnectionData("", 0, ((HandShakeMessage*)message)->GetPlayerName(), ((HandShakeMessage*)message)->GetAvatarData(), ((HandShakeMessage*)message)->GetAvatarSize()));
MessageManager::DisplayToast("Net Play", _connectionData->PlayerName + " (Player " + std::to_string(_controllerPort + 1) + ") connected.", _connectionData->AvatarData, _connectionData->AvatarSize);
SendGameInformation();
SendGameState();
_handshakeCompleted = true;
ControlManager::RegisterControlDevice(this, _controllerPort);
Console::Resume();
}
break;
case MessageType::InputData:

View file

@ -10,7 +10,8 @@ protected:
bool _sending;
vector<uint8_t> _buffer;
uint32_t _position = 0;
vector<void*> _pointersToRelease;
vector<uint8_t*> _arraysToRelease;
vector<char*> _stringsToRelease;
template<typename T>
void Stream(T &value)
@ -40,7 +41,7 @@ protected:
Stream<uint32_t>(length);
if(*value == nullptr) {
*value = (void*)new uint8_t[length];
_pointersToRelease.push_back(*value);
_arraysToRelease.push_back((uint8_t*)*value);
}
uint8_t* bytes = (uint8_t*)(*value);
for(uint32_t i = 0, len = length; i < len; i++) {
@ -71,8 +72,11 @@ protected:
public:
virtual ~NetMessage()
{
for(void *pointer : _pointersToRelease) {
delete[] pointer;
for(uint8_t *arrayPtr: _arraysToRelease) {
delete[] arrayPtr;
}
for(char *stringPtr: _stringsToRelease) {
delete[] stringPtr;
}
}
@ -100,7 +104,7 @@ public:
length = (uint32_t)(src.length() + 1);
*dest = new char[length];
memcpy(*dest, src.c_str(), length);
_pointersToRelease.push_back(*dest);
_stringsToRelease.push_back(*dest);
}
protected:

View file

@ -2,26 +2,54 @@
#include "stdafx.h"
#include "NetMessage.h"
#include "Console.h"
#include "CheatManager.h"
class SaveStateMessage : public NetMessage
{
private:
void* _stateData;
uint8_t* _stateData;
uint32_t _dataSize;
CodeInfo* _cheats;
uint32_t _cheatArraySize;
protected:
virtual void ProtectedStreamState()
{
StreamArray(&_stateData, _dataSize);
vector<CodeInfo> cheats;
StreamArray((void**)&_stateData, _dataSize);
if(_sending) {
cheats = CheatManager::GetCheats();
_cheats = &cheats[0];
_cheatArraySize = (uint32_t)cheats.size() * sizeof(CodeInfo);
StreamArray((void**)&_cheats, _cheatArraySize);
delete[] _stateData;
} else {
StreamArray((void**)&_cheats, _cheatArraySize);
for(uint32_t i = 0; i < _cheatArraySize / sizeof(CodeInfo); i++) {
cheats.push_back(((CodeInfo*)_cheats)[i]);
}
CheatManager::SetCheats(cheats);
}
}
public:
SaveStateMessage(void* buffer, uint32_t length) : NetMessage(buffer, length) { }
SaveStateMessage(void* stateData, uint32_t dataSize, bool forSend) : NetMessage(MessageType::SaveState)
{
_stateData = stateData;
_dataSize = dataSize;
SaveStateMessage() : NetMessage(MessageType::SaveState)
{
//Used when sending state to clients
Console::Pause();
stringstream state;
Console::SaveState(state);
Console::Resume();
_dataSize = (uint32_t)state.tellp();
_stateData = new uint8_t[_dataSize];
state.read((char*)_stateData, _dataSize);
}
void LoadState()

View file

@ -279,6 +279,7 @@ namespace Mesen.GUI.Forms
mnuConnect.Enabled = !netPlay;
mnuDisconnect.Enabled = !mnuConnect.Enabled && !InteropEmu.IsServerRunning();
mnuCheats.Enabled = !InteropEmu.IsConnected();
mnuEmulationSpeed.Enabled = !InteropEmu.IsConnected();
bool moviePlaying = InteropEmu.MoviePlaying();