mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-25 22:42:04 +02:00
Full rework of pre-game interface and networking
New features for players: * Loading for multiplayer. Any save could be used for multiplayer. * Restart for multiplayer. All clients will restart together. * Loading from single save. * Hotseat mixed with network game. Multiple players per client. * Now connection to server could be cancelled. * Return to menu on disconnections instead of crashes. * Restoring of last selected map, save or campaign on next run. TLDR on important changes in engine code: * UI: work with server separated from UI * UI: all explitic blitting replaced with IntObject's * UI: all new code use smart pointers instead of DISPOSE * Gameplay always start through lobby controlled by server. * Threads receiving netpacks now shared for lobby and gameplay. * Campaigns: heroes for crossover now serialized as JsonNode.
This commit is contained in:
@@ -35,8 +35,9 @@ using namespace boost::asio::ip;
|
||||
|
||||
void CConnection::init()
|
||||
{
|
||||
boost::asio::ip::tcp::no_delay option(true);
|
||||
socket->set_option(option);
|
||||
socket->set_option(boost::asio::ip::tcp::no_delay(true));
|
||||
socket->set_option(boost::asio::socket_base::send_buffer_size(4194304));
|
||||
socket->set_option(boost::asio::socket_base::receive_buffer_size(4194304));
|
||||
|
||||
enableSmartPointerSerialization();
|
||||
disableStackSendingByID();
|
||||
@@ -50,25 +51,21 @@ void CConnection::init()
|
||||
connected = true;
|
||||
std::string pom;
|
||||
//we got connection
|
||||
oser & std::string("Aiya!\n") & name & myEndianess; //identify ourselves
|
||||
iser & pom & pom & contactEndianess;
|
||||
logNetwork->info("Established connection with %s", pom);
|
||||
wmx = new boost::mutex();
|
||||
rmx = new boost::mutex();
|
||||
oser & std::string("Aiya!\n") & name & uuid & myEndianess; //identify ourselves
|
||||
iser & pom & pom & contactUuid & contactEndianess;
|
||||
logNetwork->info("Established connection with %s. UUID: %s", pom, contactUuid);
|
||||
mutexRead = std::make_shared<boost::mutex>();
|
||||
mutexWrite = std::make_shared<boost::mutex>();
|
||||
|
||||
handler = nullptr;
|
||||
receivedStop = sendStop = false;
|
||||
static int cid = 1;
|
||||
connectionID = cid++;
|
||||
iser.fileVersion = SERIALIZATION_VERSION;
|
||||
}
|
||||
|
||||
CConnection::CConnection(std::string host, ui16 port, std::string Name)
|
||||
:iser(this), oser(this), io_service(new asio::io_service), name(Name)
|
||||
CConnection::CConnection(std::string host, ui16 port, std::string Name, std::string UUID)
|
||||
: iser(this), oser(this), io_service(std::make_shared<asio::io_service>()), connectionID(0), name(Name), uuid(UUID)
|
||||
{
|
||||
int i;
|
||||
boost::system::error_code error = asio::error::host_not_found;
|
||||
socket = new tcp::socket(*io_service);
|
||||
socket = std::make_shared<tcp::socket>(*io_service);
|
||||
tcp::resolver resolver(*io_service);
|
||||
tcp::resolver::iterator end, pom, endpoint_iterator = resolver.resolve(tcp::resolver::query(host, std::to_string(port)),error);
|
||||
if(error)
|
||||
@@ -114,25 +111,23 @@ connerror1:
|
||||
logNetwork->error(error.message());
|
||||
else
|
||||
logNetwork->error("No error info. ");
|
||||
delete io_service;
|
||||
//delete socket;
|
||||
throw std::runtime_error("Can't establish connection :(");
|
||||
}
|
||||
CConnection::CConnection(TSocket * Socket, std::string Name )
|
||||
:iser(this), oser(this), socket(Socket),io_service(&Socket->get_io_service()), name(Name)//, send(this), rec(this)
|
||||
CConnection::CConnection(std::shared_ptr<TSocket> Socket, std::string Name, std::string UUID)
|
||||
: iser(this), oser(this), socket(Socket), io_service(&Socket->get_io_service()), connectionID(0), name(Name), uuid(UUID)
|
||||
{
|
||||
init();
|
||||
}
|
||||
CConnection::CConnection(TAcceptor * acceptor, boost::asio::io_service *Io_service, std::string Name)
|
||||
: iser(this), oser(this), name(Name)//, send(this), rec(this)
|
||||
CConnection::CConnection(std::shared_ptr<TAcceptor> acceptor, std::shared_ptr<boost::asio::io_service> Io_service, std::string Name, std::string UUID)
|
||||
: iser(this), oser(this), connectionID(0), name(Name), uuid(UUID)
|
||||
{
|
||||
boost::system::error_code error = asio::error::host_not_found;
|
||||
socket = new tcp::socket(*io_service);
|
||||
socket = std::make_shared<tcp::socket>(*io_service);
|
||||
acceptor->accept(*socket,error);
|
||||
if (error)
|
||||
{
|
||||
logNetwork->error("Error on accepting: %s", error.message());
|
||||
delete socket;
|
||||
socket.reset();
|
||||
throw std::runtime_error("Can't establish connection :(");
|
||||
}
|
||||
init();
|
||||
@@ -171,12 +166,7 @@ CConnection::~CConnection()
|
||||
if(handler)
|
||||
handler->join();
|
||||
|
||||
delete handler;
|
||||
|
||||
close();
|
||||
delete io_service;
|
||||
delete wmx;
|
||||
delete rmx;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@@ -193,7 +183,7 @@ void CConnection::close()
|
||||
if(socket)
|
||||
{
|
||||
socket->close();
|
||||
vstd::clear_pointer(socket);
|
||||
socket.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,11 +192,6 @@ bool CConnection::isOpen() const
|
||||
return socket && connected;
|
||||
}
|
||||
|
||||
bool CConnection::isHost() const
|
||||
{
|
||||
return connectionID == 1;
|
||||
}
|
||||
|
||||
void CConnection::reportState(vstd::CLoggerBase * out)
|
||||
{
|
||||
out->debug("CConnection");
|
||||
@@ -219,19 +204,26 @@ void CConnection::reportState(vstd::CLoggerBase * out)
|
||||
|
||||
CPack * CConnection::retrievePack()
|
||||
{
|
||||
CPack *ret = nullptr;
|
||||
boost::unique_lock<boost::mutex> lock(*rmx);
|
||||
logNetwork->trace("Listening... ");
|
||||
iser & ret;
|
||||
logNetwork->trace("\treceived server message of type %s", (ret? typeid(*ret).name() : "nullptr"));
|
||||
return ret;
|
||||
CPack * pack = nullptr;
|
||||
boost::unique_lock<boost::mutex> lock(*mutexRead);
|
||||
iser & pack;
|
||||
logNetwork->trace("\treceived CPack of type %s", (pack ? typeid(*pack).name() : "nullptr"));
|
||||
if(pack == nullptr)
|
||||
{
|
||||
logNetwork->error("Received a nullptr CPack! You should check whether client and server ABI matches.");
|
||||
}
|
||||
else
|
||||
{
|
||||
pack->c = this->shared_from_this();
|
||||
}
|
||||
return pack;
|
||||
}
|
||||
|
||||
void CConnection::sendPackToServer(const CPack &pack, PlayerColor player, ui32 requestID)
|
||||
void CConnection::sendPack(const CPack * pack)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(*wmx);
|
||||
logNetwork->trace("Sending to server a pack of type %s", typeid(pack).name());
|
||||
oser & player & requestID & &pack; //packs has to be sent as polymorphic pointers!
|
||||
boost::unique_lock<boost::mutex> lock(*mutexWrite);
|
||||
logNetwork->trace("Sending a pack of type %s", typeid(*pack).name());
|
||||
oser & pack;
|
||||
}
|
||||
|
||||
void CConnection::disableStackSendingByID()
|
||||
@@ -254,16 +246,7 @@ void CConnection::enableSmartPointerSerialization()
|
||||
iser.smartPointerSerialization = oser.smartPointerSerialization = true;
|
||||
}
|
||||
|
||||
void CConnection::prepareForSendingHeroes()
|
||||
{
|
||||
iser.loadedPointers.clear();
|
||||
oser.savedPointers.clear();
|
||||
disableSmartVectorMemberSerialization();
|
||||
enableSmartPointerSerialization();
|
||||
disableStackSendingByID();
|
||||
}
|
||||
|
||||
void CConnection::enterPregameConnectionMode()
|
||||
void CConnection::enterLobbyConnectionMode()
|
||||
{
|
||||
iser.loadedPointers.clear();
|
||||
oser.savedPointers.clear();
|
||||
@@ -271,6 +254,13 @@ void CConnection::enterPregameConnectionMode()
|
||||
disableSmartPointerSerialization();
|
||||
}
|
||||
|
||||
void CConnection::enterGameplayConnectionMode(CGameState * gs)
|
||||
{
|
||||
enableStackSendingByID();
|
||||
disableSmartPointerSerialization();
|
||||
addStdVecItems(gs);
|
||||
}
|
||||
|
||||
void CConnection::disableSmartVectorMemberSerialization()
|
||||
{
|
||||
CSerializer::smartVectorMembersSerialization = false;
|
||||
@@ -283,7 +273,7 @@ void CConnection::enableSmartVectorMemberSerializatoin()
|
||||
|
||||
std::string CConnection::toString() const
|
||||
{
|
||||
boost::format fmt("Connection with %s (ID: %d)");
|
||||
fmt % name % connectionID;
|
||||
return fmt.str();
|
||||
boost::format fmt("Connection with %s (ID: %d UUID: %s)");
|
||||
fmt % name % connectionID % uuid;
|
||||
return fmt.str();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user