mirror of
https://github.com/vcmi/vcmi.git
synced 2025-06-21 00:19:29 +02:00
Implemented option to run server as a thread with shared VLC
This commit is contained in:
@ -12,6 +12,7 @@
|
||||
#include "CServerHandler.h"
|
||||
#include "Client.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "ServerRunner.h"
|
||||
#include "CPlayerInterface.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "gui/WindowHandler.h"
|
||||
@ -25,17 +26,6 @@
|
||||
#include "mainmenu/CPrologEpilogVideo.h"
|
||||
#include "mainmenu/CHighScoreScreen.h"
|
||||
|
||||
#ifdef VCMI_ANDROID
|
||||
#include "../lib/CAndroidVMHelper.h"
|
||||
#elif defined(VCMI_IOS)
|
||||
#include "ios/utils.h"
|
||||
#include <dispatch/dispatch.h>
|
||||
#endif
|
||||
|
||||
#ifdef SINGLE_PROCESS_APP
|
||||
#include "../server/CVCMIServer.h"
|
||||
#endif
|
||||
|
||||
#include "../lib/CConfigHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CThreadHelper.h"
|
||||
@ -61,16 +51,8 @@
|
||||
|
||||
#include <vcmi/events/EventBus.h>
|
||||
|
||||
#ifdef VCMI_WINDOWS
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
template<typename T> class CApplyOnLobby;
|
||||
|
||||
#if defined(VCMI_ANDROID) && !defined(SINGLE_PROCESS_APP)
|
||||
extern std::atomic_bool androidTestServerReadyFlag;
|
||||
#endif
|
||||
|
||||
class CBaseForLobbyApply
|
||||
{
|
||||
public:
|
||||
@ -195,67 +177,17 @@ INetworkHandler & CServerHandler::getNetworkHandler()
|
||||
|
||||
void CServerHandler::startLocalServerAndConnect(bool connectToLobby)
|
||||
{
|
||||
if(threadRunLocalServer.joinable())
|
||||
threadRunLocalServer.join();
|
||||
|
||||
th->update();
|
||||
|
||||
#if defined(SINGLE_PROCESS_APP)
|
||||
boost::condition_variable cond;
|
||||
std::vector<std::string> args{"--port=" + std::to_string(getLocalPort())};
|
||||
if(connectToLobby)
|
||||
args.push_back("--lobby");
|
||||
|
||||
threadRunLocalServer = boost::thread([&cond, args] {
|
||||
setThreadName("CVCMIServer");
|
||||
CVCMIServer::create(&cond, args);
|
||||
});
|
||||
#elif defined(VCMI_ANDROID)
|
||||
{
|
||||
CAndroidVMHelper envHelper;
|
||||
envHelper.callStaticVoidMethod(CAndroidVMHelper::NATIVE_METHODS_DEFAULT_CLASS, "startServer", true);
|
||||
}
|
||||
#ifdef VCMI_MOBILE
|
||||
// mobile apps can't spawn separate processes - only thread mode is available
|
||||
serverRunner.reset(new ServerThreadRunner());
|
||||
#else
|
||||
threadRunLocalServer = boost::thread(&CServerHandler::threadRunServer, this, connectToLobby); //runs server executable;
|
||||
#endif
|
||||
logNetwork->trace("Setting up thread calling server: %d ms", th->getDiff());
|
||||
|
||||
th->update();
|
||||
|
||||
#ifdef SINGLE_PROCESS_APP
|
||||
{
|
||||
#ifdef VCMI_IOS
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
iOS_utils::showLoadingIndicator();
|
||||
});
|
||||
if (settings["server"]["useProcess"].Bool())
|
||||
serverRunner.reset(new ServerProcessRunner());
|
||||
else
|
||||
serverRunner.reset(new ServerThreadRunner());
|
||||
#endif
|
||||
|
||||
boost::mutex m;
|
||||
boost::unique_lock<boost::mutex> lock{m};
|
||||
logNetwork->info("waiting for server");
|
||||
cond.wait(lock);
|
||||
logNetwork->info("server is ready");
|
||||
|
||||
#ifdef VCMI_IOS
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
iOS_utils::hideLoadingIndicator();
|
||||
});
|
||||
#endif
|
||||
}
|
||||
#elif defined(VCMI_ANDROID)
|
||||
logNetwork->info("waiting for server");
|
||||
while(!androidTestServerReadyFlag.load())
|
||||
{
|
||||
logNetwork->info("still waiting...");
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
|
||||
}
|
||||
logNetwork->info("waiting for server finished...");
|
||||
androidTestServerReadyFlag = false;
|
||||
#endif
|
||||
logNetwork->trace("Waiting for server: %d ms", th->getDiff());
|
||||
|
||||
th->update(); //put breakpoint here to attach to server before it does something stupid
|
||||
|
||||
serverRunner->start(getLocalPort(), connectToLobby);
|
||||
connectToServer(getLocalHostname(), getLocalPort());
|
||||
|
||||
logNetwork->trace("\tConnecting to the server: %d ms", th->getDiff());
|
||||
@ -374,7 +306,7 @@ void CServerHandler::setState(EClientState newState)
|
||||
|
||||
bool CServerHandler::isServerLocal() const
|
||||
{
|
||||
return threadRunLocalServer.joinable();
|
||||
return serverRunner != nullptr;
|
||||
}
|
||||
|
||||
bool CServerHandler::isHost() const
|
||||
@ -758,7 +690,6 @@ void CServerHandler::startCampaignScenario(HighScoreParameter param, std::shared
|
||||
}
|
||||
};
|
||||
|
||||
threadRunLocalServer.join();
|
||||
if(epilogue.hasPrologEpilog)
|
||||
{
|
||||
GH.windows().createAndPushWindow<CPrologEpilogVideo>(epilogue, finisher);
|
||||
@ -899,6 +830,12 @@ void CServerHandler::onPacketReceived(const std::shared_ptr<INetworkConnection>
|
||||
|
||||
void CServerHandler::onDisconnected(const std::shared_ptr<INetworkConnection> & connection, const std::string & errorMessage)
|
||||
{
|
||||
if (serverRunner)
|
||||
{
|
||||
serverRunner->wait();
|
||||
serverRunner.reset();
|
||||
}
|
||||
|
||||
if(getState() == EClientState::DISCONNECTING)
|
||||
{
|
||||
assert(networkConnection == nullptr);
|
||||
@ -942,55 +879,6 @@ void CServerHandler::visitForClient(CPackForClient & clientPack)
|
||||
client->handlePack(&clientPack);
|
||||
}
|
||||
|
||||
void CServerHandler::threadRunServer(bool connectToLobby)
|
||||
{
|
||||
#if !defined(VCMI_MOBILE)
|
||||
setThreadName("runServer");
|
||||
const std::string logName = (VCMIDirs::get().userLogsPath() / "server_log.txt").string();
|
||||
std::string comm = VCMIDirs::get().serverPath().string()
|
||||
+ " --port=" + std::to_string(getLocalPort())
|
||||
+ " --run-by-client";
|
||||
if(connectToLobby)
|
||||
comm += " --lobby";
|
||||
|
||||
comm += " > \"" + logName + '\"';
|
||||
logGlobal->info("Server command line: %s", comm);
|
||||
|
||||
#ifdef VCMI_WINDOWS
|
||||
int result = -1;
|
||||
const auto bufSize = ::MultiByteToWideChar(CP_UTF8, 0, comm.c_str(), comm.size(), nullptr, 0);
|
||||
if(bufSize > 0)
|
||||
{
|
||||
std::wstring wComm(bufSize, {});
|
||||
const auto convertResult = ::MultiByteToWideChar(CP_UTF8, 0, comm.c_str(), comm.size(), &wComm[0], bufSize);
|
||||
if(convertResult > 0)
|
||||
result = ::_wsystem(wComm.c_str());
|
||||
else
|
||||
logNetwork->error("Error " + std::to_string(GetLastError()) + ": failed to convert server launch command to wide string: " + comm);
|
||||
}
|
||||
else
|
||||
logNetwork->error("Error " + std::to_string(GetLastError()) + ": failed to obtain buffer length to convert server launch command to wide string : " + comm);
|
||||
#else
|
||||
int result = std::system(comm.c_str());
|
||||
#endif
|
||||
if (result == 0)
|
||||
{
|
||||
logNetwork->info("Server closed correctly");
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
|
||||
|
||||
if (getState() == EClientState::CONNECTING)
|
||||
{
|
||||
showServerError(CGI->generaltexth->translate("vcmi.server.errors.existingProcess"));
|
||||
setState(EClientState::CONNECTION_CANCELLED); // stop attempts to reconnect
|
||||
}
|
||||
logNetwork->error("Error: server failed to close correctly or crashed!");
|
||||
logNetwork->error("Check %s for more info", logName);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CServerHandler::sendLobbyPack(const CPackForLobby & pack) const
|
||||
{
|
||||
|
Reference in New Issue
Block a user