1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-14 10:12:59 +02:00
vcmi/lib/serializer/Connection.cpp
Ivan Savenko 48c92711f2 Fixed deserialization of new artifacts (and possibly some other objects)
Was broken in my previous PR, since pointer graph serialization was
enabled by default, leading to deserializationFix triggering on netpack
apply.

Cleaned up / clarified code
2024-07-29 18:19:15 +00:00

173 lines
4.3 KiB
C++

/*
* Connection.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "StdInc.h"
#include "Connection.h"
#include "BinaryDeserializer.h"
#include "BinarySerializer.h"
#include "../gameState/CGameState.h"
#include "../networkPacks/NetPacksBase.h"
#include "../network/NetworkInterface.h"
VCMI_LIB_NAMESPACE_BEGIN
class DLL_LINKAGE ConnectionPackWriter final : public IBinaryWriter
{
public:
std::vector<std::byte> buffer;
int write(const std::byte * data, unsigned size) final;
};
class DLL_LINKAGE ConnectionPackReader final : public IBinaryReader
{
public:
const std::vector<std::byte> * buffer;
size_t position;
int read(std::byte * data, unsigned size) final;
};
int ConnectionPackWriter::write(const std::byte * data, unsigned size)
{
buffer.insert(buffer.end(), data, data + size);
return size;
}
int ConnectionPackReader::read(std::byte * data, unsigned size)
{
if (position + size > buffer->size())
throw std::runtime_error("End of file reached when reading received network pack!");
std::copy_n(buffer->begin() + position, size, data);
position += size;
return size;
}
CConnection::CConnection(std::weak_ptr<INetworkConnection> networkConnection)
: networkConnection(networkConnection)
, packReader(std::make_unique<ConnectionPackReader>())
, packWriter(std::make_unique<ConnectionPackWriter>())
, deserializer(std::make_unique<BinaryDeserializer>(packReader.get()))
, serializer(std::make_unique<BinarySerializer>(packWriter.get()))
, connectionID(-1)
{
assert(networkConnection.lock() != nullptr);
enterLobbyConnectionMode();
deserializer->version = ESerializationVersion::CURRENT;
}
CConnection::~CConnection() = default;
void CConnection::sendPack(const CPack * pack)
{
boost::mutex::scoped_lock lock(writeMutex);
auto connectionPtr = networkConnection.lock();
if (!connectionPtr)
throw std::runtime_error("Attempt to send packet on a closed connection!");
packWriter->buffer.clear();
*serializer & pack;
logNetwork->trace("Sending a pack of type %s", typeid(*pack).name());
connectionPtr->sendPacket(packWriter->buffer);
packWriter->buffer.clear();
serializer->savedPointers.clear();
}
CPack * CConnection::retrievePack(const std::vector<std::byte> & data)
{
CPack * result;
packReader->buffer = &data;
packReader->position = 0;
*deserializer & result;
if (result == nullptr)
throw std::runtime_error("Failed to retrieve pack!");
if (packReader->position != data.size())
throw std::runtime_error("Failed to retrieve pack! Not all data has been read!");
logNetwork->trace("Received CPack of type %s", typeid(*result).name());
deserializer->loadedPointers.clear();
deserializer->loadedSharedPointers.clear();
return result;
}
bool CConnection::isMyConnection(const std::shared_ptr<INetworkConnection> & otherConnection) const
{
return otherConnection != nullptr && networkConnection.lock() == otherConnection;
}
std::shared_ptr<INetworkConnection> CConnection::getConnection()
{
return networkConnection.lock();
}
void CConnection::disableStackSendingByID()
{
packReader->sendStackInstanceByIds = false;
packWriter->sendStackInstanceByIds = false;
}
void CConnection::enableStackSendingByID()
{
packReader->sendStackInstanceByIds = true;
packWriter->sendStackInstanceByIds = true;
}
void CConnection::enterLobbyConnectionMode()
{
deserializer->loadedPointers.clear();
serializer->savedPointers.clear();
disableSmartVectorMemberSerialization();
disableStackSendingByID();
}
void CConnection::setCallback(IGameCallback * cb)
{
deserializer->cb = cb;
}
void CConnection::enterGameplayConnectionMode(CGameState * gs)
{
enableStackSendingByID();
setCallback(gs->callback);
enableSmartVectorMemberSerializatoin(gs);
}
void CConnection::disableSmartVectorMemberSerialization()
{
packReader->smartVectorMembersSerialization = false;
packWriter->smartVectorMembersSerialization = false;
}
void CConnection::enableSmartVectorMemberSerializatoin(CGameState * gs)
{
packWriter->addStdVecItems(gs);
packReader->addStdVecItems(gs);
}
void CConnection::setSerializationVersion(ESerializationVersion version)
{
deserializer->version = version;
serializer->version = version;
}
VCMI_LIB_NAMESPACE_END