mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-22 03:39:45 +02:00
Implemented option to run server as a thread with shared VLC
This commit is contained in:
parent
c2286e5126
commit
0d263c5571
@ -63,8 +63,9 @@ option(ENABLE_CCACHE "Speed up recompilation by caching previous compilations" O
|
||||
|
||||
if(ANDROID)
|
||||
set(ENABLE_STATIC_AI_LIBS ON)
|
||||
set(ENABLE_LAUNCHER OFF)
|
||||
else()
|
||||
option(ENABLE_STATIC_AI_LIBS "Add AI code into VCMI lib directly" ON)
|
||||
option(ENABLE_STATIC_AI_LIBS "Build all libraries statically (NOT only AI)" OFF)
|
||||
option(ENABLE_LAUNCHER "Enable compilation of launcher" ON)
|
||||
endif()
|
||||
|
||||
@ -75,15 +76,17 @@ endif()
|
||||
|
||||
if(APPLE_IOS OR ANDROID)
|
||||
option(ENABLE_MONOLITHIC_INSTALL "Install everything in single directory on Linux and Mac" OFF) # Used for Snap packages and also useful for debugging
|
||||
option(ENABLE_LOBBY "Enable compilation of lobby server" OFF)
|
||||
set(ENABLE_SINGLE_APP_BUILD ON)
|
||||
set(ENABLE_EDITOR OFF)
|
||||
set(ENABLE_TEST OFF)
|
||||
set(ENABLE_LOBBY OFF)
|
||||
set(COPY_CONFIG_ON_BUILD OFF)
|
||||
else()
|
||||
option(COPY_CONFIG_ON_BUILD "Copies config folder into output directory at building phase" ON)
|
||||
option(ENABLE_EDITOR "Enable compilation of map editor" ON)
|
||||
option(ENABLE_SINGLE_APP_BUILD "Builds client and launcher as single executable" OFF)
|
||||
option(ENABLE_TEST "Enable compilation of unit tests" OFF)
|
||||
option(ENABLE_LOBBY "Enable compilation of lobby server" OFF)
|
||||
endif()
|
||||
|
||||
if(ENABLE_COLORIZED_COMPILER_OUTPUT)
|
||||
@ -240,7 +243,7 @@ if(ENABLE_EDITOR)
|
||||
endif()
|
||||
|
||||
if(ENABLE_SINGLE_APP_BUILD)
|
||||
add_definitions(-DSINGLE_PROCESS_APP=1)
|
||||
add_definitions(-DENABLE_SINGLE_APP_BUILD)
|
||||
endif()
|
||||
|
||||
if(APPLE_IOS)
|
||||
|
@ -164,6 +164,7 @@ set(client_SRCS
|
||||
HeroMovementController.cpp
|
||||
NetPacksClient.cpp
|
||||
NetPacksLobbyClient.cpp
|
||||
ServerRunner.cpp
|
||||
)
|
||||
|
||||
set(client_HEADERS
|
||||
@ -346,6 +347,7 @@ set(client_HEADERS
|
||||
ClientNetPackVisitors.h
|
||||
HeroMovementController.h
|
||||
LobbyClientNetPackVisitors.h
|
||||
ServerRunner.h
|
||||
resource.h
|
||||
)
|
||||
|
||||
@ -451,12 +453,12 @@ elseif(APPLE_IOS)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-Wl,-e,_client_main")
|
||||
endif()
|
||||
|
||||
if(ENABLE_SINGLE_APP_BUILD)
|
||||
target_link_libraries(vcmiclient PRIVATE vcmiserver)
|
||||
if(ENABLE_LAUNCHER)
|
||||
target_link_libraries(vcmiclient PRIVATE vcmilauncher)
|
||||
endif()
|
||||
target_link_libraries(vcmiclient PRIVATE vcmiservercommon)
|
||||
|
||||
if(ENABLE_SINGLE_APP_BUILD AND ENABLE_LAUNCHER)
|
||||
target_link_libraries(vcmiclient PRIVATE vcmilauncher)
|
||||
endif()
|
||||
|
||||
target_link_libraries(vcmiclient PRIVATE
|
||||
${VCMI_LIB_TARGET} SDL2::SDL2 SDL2::Image SDL2::Mixer SDL2::TTF
|
||||
)
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -36,6 +36,7 @@ VCMI_LIB_NAMESPACE_END
|
||||
class CClient;
|
||||
class CBaseForLobbyApply;
|
||||
class GlobalLobbyClient;
|
||||
class IServerRunner;
|
||||
|
||||
class HighScoreCalculation;
|
||||
class HighScoreParameter;
|
||||
@ -100,17 +101,16 @@ class CServerHandler final : public IServerAPI, public LobbyInfo, public INetwor
|
||||
std::shared_ptr<INetworkConnection> networkConnection;
|
||||
std::unique_ptr<GlobalLobbyClient> lobbyClient;
|
||||
std::unique_ptr<CApplier<CBaseForLobbyApply>> applier;
|
||||
std::unique_ptr<IServerRunner> serverRunner;
|
||||
std::shared_ptr<CMapInfo> mapToStart;
|
||||
std::vector<std::string> myNames;
|
||||
std::shared_ptr<HighScoreCalculation> highScoreCalc;
|
||||
|
||||
boost::thread threadRunLocalServer;
|
||||
boost::thread threadNetwork;
|
||||
|
||||
std::atomic<EClientState> state;
|
||||
|
||||
void threadRunNetwork();
|
||||
void threadRunServer(bool connectToLobby);
|
||||
|
||||
void sendLobbyPack(const CPackForLobby & pack) const override;
|
||||
|
||||
|
@ -46,10 +46,6 @@
|
||||
|
||||
#ifdef VCMI_ANDROID
|
||||
#include "lib/CAndroidVMHelper.h"
|
||||
|
||||
#ifndef SINGLE_PROCESS_APP
|
||||
std::atomic_bool androidTestServerReadyFlag;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ThreadSafeVector<int> CClient::waitingRequest;
|
||||
@ -718,22 +714,6 @@ void CClient::removeGUI() const
|
||||
}
|
||||
|
||||
#ifdef VCMI_ANDROID
|
||||
#ifndef SINGLE_PROCESS_APP
|
||||
extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_notifyServerClosed(JNIEnv * env, jclass cls)
|
||||
{
|
||||
logNetwork->info("Received server closed signal");
|
||||
if (CSH) {
|
||||
CSH->campaignServerRestartLock.setn(false);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_notifyServerReady(JNIEnv * env, jclass cls)
|
||||
{
|
||||
logNetwork->info("Received server ready signal");
|
||||
androidTestServerReadyFlag.store(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL Java_eu_vcmi_vcmi_NativeMethods_tryToSaveTheGame(JNIEnv * env, jclass cls)
|
||||
{
|
||||
logGlobal->info("Received emergency save game request");
|
||||
|
96
client/ServerRunner.cpp
Normal file
96
client/ServerRunner.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* ServerRunner.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 "ServerRunner.h"
|
||||
|
||||
#include "../lib/VCMIDirs.h"
|
||||
#include "../lib/CThreadHelper.h"
|
||||
#include "../server/CVCMIServer.h"
|
||||
|
||||
#ifndef VCMI_MOBILE
|
||||
#include <boost/process/child.hpp>
|
||||
#include <boost/process/io.hpp>
|
||||
#endif
|
||||
|
||||
ServerThreadRunner::ServerThreadRunner() = default;
|
||||
ServerThreadRunner::~ServerThreadRunner() = default;
|
||||
ServerProcessRunner::ServerProcessRunner() = default;
|
||||
ServerProcessRunner::~ServerProcessRunner() = default;
|
||||
|
||||
void ServerThreadRunner::start(uint16_t port, bool connectToLobby)
|
||||
{
|
||||
setThreadName("runServer");
|
||||
|
||||
server = std::make_unique<CVCMIServer>(port, connectToLobby, true);
|
||||
|
||||
threadRunLocalServer = boost::thread([this]{
|
||||
server->run();
|
||||
});
|
||||
}
|
||||
|
||||
void ServerThreadRunner::stop()
|
||||
{
|
||||
server->setState(EServerState::SHUTDOWN);
|
||||
}
|
||||
|
||||
int ServerThreadRunner::wait()
|
||||
{
|
||||
threadRunLocalServer.join();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ServerProcessRunner::stop()
|
||||
{
|
||||
child->terminate();
|
||||
}
|
||||
|
||||
int ServerProcessRunner::wait()
|
||||
{
|
||||
child->wait();
|
||||
|
||||
return child->exit_code();
|
||||
|
||||
// if (child->exit_code() == 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);
|
||||
// }
|
||||
}
|
||||
|
||||
void ServerProcessRunner::start(uint16_t port, bool connectToLobby)
|
||||
{
|
||||
boost::filesystem::path serverPath = VCMIDirs::get().serverPath();
|
||||
boost::filesystem::path logPath = VCMIDirs::get().userLogsPath() / "server_log.txt";
|
||||
std::vector<std::string> args;
|
||||
args.push_back("--port=" + std::to_string(port));
|
||||
args.push_back("--run-by-client");
|
||||
if(connectToLobby)
|
||||
args.push_back("--lobby");
|
||||
|
||||
std::error_code ec;
|
||||
child = std::make_unique<boost::process::child>(serverPath, args, ec, boost::process::std_out > logPath);
|
||||
|
||||
if (ec)
|
||||
throw std::runtime_error("Failed to start server! Reason: " + ec.message());
|
||||
}
|
||||
|
||||
|
57
client/ServerRunner.h
Normal file
57
client/ServerRunner.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* ServerRunner.h, 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
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
class CVCMIServer;
|
||||
|
||||
class IServerRunner
|
||||
{
|
||||
public:
|
||||
virtual void start(uint16_t port, bool connectToLobby) = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual int wait() = 0;
|
||||
|
||||
virtual ~IServerRunner() = default;
|
||||
};
|
||||
|
||||
/// Server instance will run as a thread of client process
|
||||
class ServerThreadRunner : public IServerRunner, boost::noncopyable
|
||||
{
|
||||
std::unique_ptr<CVCMIServer> server;
|
||||
boost::thread threadRunLocalServer;
|
||||
public:
|
||||
void start(uint16_t port, bool connectToLobby) override;
|
||||
void stop() override;
|
||||
int wait() override;
|
||||
|
||||
ServerThreadRunner();
|
||||
~ServerThreadRunner();
|
||||
};
|
||||
|
||||
#ifndef VCMI_MOBILE
|
||||
|
||||
namespace boost::process {
|
||||
class child;
|
||||
}
|
||||
|
||||
/// Server instance will run as a separate process
|
||||
class ServerProcessRunner : public IServerRunner, boost::noncopyable
|
||||
{
|
||||
std::unique_ptr<boost::process::child> child;
|
||||
|
||||
public:
|
||||
void start(uint16_t port, bool connectToLobby) override;
|
||||
void stop() override;
|
||||
int wait() override;
|
||||
|
||||
ServerProcessRunner();
|
||||
~ServerProcessRunner();
|
||||
};
|
||||
#endif
|
@ -60,11 +60,6 @@
|
||||
#include "../../lib/CRandomGenerator.h"
|
||||
#include "../../lib/CondSh.h"
|
||||
|
||||
#if defined(SINGLE_PROCESS_APP) && defined(VCMI_ANDROID)
|
||||
#include "../../server/CVCMIServer.h"
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
|
||||
std::shared_ptr<CMainMenu> CMM;
|
||||
ISelectionScreenInfo * SEL;
|
||||
|
||||
@ -599,13 +594,6 @@ void CSimpleJoinScreen::onChange(const std::string & newText)
|
||||
|
||||
void CSimpleJoinScreen::startConnection(const std::string & addr, ui16 port)
|
||||
{
|
||||
#if defined(SINGLE_PROCESS_APP) && defined(VCMI_ANDROID)
|
||||
// in single process build server must use same JNIEnv as client
|
||||
// as server runs in a separate thread, it must not attempt to search for Java classes (and they're already cached anyway)
|
||||
// https://github.com/libsdl-org/SDL/blob/main/docs/README-android.md#threads-and-the-java-vm
|
||||
CVCMIServer::reuseClientJNIEnv(SDL_AndroidGetJNIEnv());
|
||||
#endif
|
||||
|
||||
if(addr.empty())
|
||||
CSH->startLocalServerAndConnect(false);
|
||||
else
|
||||
|
@ -14,5 +14,9 @@ else()
|
||||
add_main_lib(${VCMI_LIB_TARGET} SHARED)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(${VCMI_LIB_TARGET} PUBLIC VCMI_LIB_NAMESPACE=VCMI)
|
||||
# no longer necessary, but might be useful to keep in future
|
||||
# unfortunately at the moment tests do not support namespaced build, so enable only on some systems
|
||||
if(APPLE_IOS OR ANDROID)
|
||||
target_compile_definitions(${VCMI_LIB_TARGET} PUBLIC VCMI_LIB_NAMESPACE=VCMI)
|
||||
endif()
|
||||
|
||||
|
@ -368,11 +368,7 @@ bool IVCMIDirsUNIX::developmentMode() const
|
||||
{
|
||||
// We want to be able to run VCMI from single directory. E.g to run from build output directory
|
||||
const bool result = bfs::exists("AI") && bfs::exists("config") && bfs::exists("Mods") && bfs::exists("vcmiclient");
|
||||
#if SINGLE_PROCESS_APP
|
||||
return result;
|
||||
#else
|
||||
return result && bfs::exists("vcmiserver");
|
||||
#endif
|
||||
}
|
||||
|
||||
bfs::path IVCMIDirsUNIX::clientPath() const { return binaryPath() / "vcmiclient"; }
|
||||
|
@ -1,4 +1,4 @@
|
||||
set(libserver_SRCS
|
||||
set(vcmiservercommon_SRCS
|
||||
StdInc.cpp
|
||||
|
||||
battles/BattleActionProcessor.cpp
|
||||
@ -24,7 +24,7 @@ set(libserver_SRCS
|
||||
TurnTimerHandler.cpp
|
||||
)
|
||||
|
||||
set(libserver_HEADERS
|
||||
set(vcmiservercommon_HEADERS
|
||||
StdInc.h
|
||||
|
||||
battles/BattleActionProcessor.h
|
||||
@ -50,28 +50,28 @@ set(libserver_HEADERS
|
||||
TurnTimerHandler.h
|
||||
)
|
||||
|
||||
assign_source_group(${libserver_SRCS} ${libserver_HEADERS})
|
||||
assign_source_group(${vcmiservercommon_SRCS} ${vcmiservercommon_HEADERS})
|
||||
|
||||
add_library(libserver STATIC ${libserver_SRCS} ${libserver_HEADERS})
|
||||
set(libserver_LIBS vcmi)
|
||||
add_library(vcmiservercommon STATIC ${vcmiservercommon_SRCS} ${vcmiservercommon_HEADERS})
|
||||
set(vcmiservercommon_LIBS vcmi)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES FreeBSD OR HAIKU)
|
||||
set(libserver_LIBS execinfo ${libserver_LIBS})
|
||||
set(vcmiservercommon_LIBS execinfo ${vcmiservercommon_LIBS})
|
||||
endif()
|
||||
|
||||
target_link_libraries(libserver PRIVATE ${libserver_LIBS} minizip::minizip)
|
||||
target_link_libraries(vcmiservercommon PRIVATE ${vcmiservercommon_LIBS} minizip::minizip)
|
||||
|
||||
target_include_directories(libserver
|
||||
target_include_directories(vcmiservercommon
|
||||
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set_target_properties(vcmiserver
|
||||
set_target_properties(vcmiservercommon
|
||||
PROPERTIES
|
||||
OUTPUT_NAME "VCMI_libserver"
|
||||
PROJECT_LABEL "VCMI_libserver"
|
||||
OUTPUT_NAME "VCMI_vcmiservercommon"
|
||||
PROJECT_LABEL "VCMI_vcmiservercommon"
|
||||
)
|
||||
endif()
|
||||
|
||||
vcmi_set_output_dir(libserver "")
|
||||
enable_pch(libserver)
|
||||
vcmi_set_output_dir(vcmiservercommon "")
|
||||
enable_pch(vcmiservercommon)
|
||||
|
@ -116,10 +116,11 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
CVCMIServer::CVCMIServer(boost::program_options::variables_map & opts)
|
||||
CVCMIServer::CVCMIServer(uint16_t port, bool connectToLobby, bool runByClient)
|
||||
: currentClientId(1)
|
||||
, currentPlayerId(1)
|
||||
, cmdLineOptions(opts)
|
||||
, port(port)
|
||||
, runByClient(runByClient)
|
||||
{
|
||||
uuid = boost::uuids::to_string(boost::uuids::random_generator()());
|
||||
logNetwork->trace("CVCMIServer created! UUID: %s", uuid);
|
||||
@ -128,7 +129,7 @@ CVCMIServer::CVCMIServer(boost::program_options::variables_map & opts)
|
||||
|
||||
networkHandler = INetworkHandler::createHandler();
|
||||
|
||||
if(cmdLineOptions.count("lobby"))
|
||||
if(connectToLobby)
|
||||
lobbyProcessor = std::make_unique<GlobalLobbyProcessor>(*this);
|
||||
else
|
||||
startAcceptingIncomingConnections();
|
||||
@ -138,10 +139,6 @@ CVCMIServer::~CVCMIServer() = default;
|
||||
|
||||
void CVCMIServer::startAcceptingIncomingConnections()
|
||||
{
|
||||
uint16_t port = 3030;
|
||||
|
||||
if(cmdLineOptions.count("port"))
|
||||
port = cmdLineOptions["port"].as<uint16_t>();
|
||||
logNetwork->info("Port %d will be used", port);
|
||||
|
||||
networkServer = networkHandler->createServerTCP(*this);
|
||||
@ -197,15 +194,13 @@ std::shared_ptr<CConnection> CVCMIServer::findConnection(const std::shared_ptr<I
|
||||
throw std::runtime_error("Unknown connection received in CVCMIServer::findConnection");
|
||||
}
|
||||
|
||||
bool CVCMIServer::wasStartedByClient() const
|
||||
{
|
||||
return runByClient;
|
||||
}
|
||||
|
||||
void CVCMIServer::run()
|
||||
{
|
||||
#if defined(VCMI_ANDROID) && !defined(SINGLE_PROCESS_APP)
|
||||
if(!restartGameplay)
|
||||
{
|
||||
CAndroidVMHelper vmHelper;
|
||||
vmHelper.callStaticVoidMethod(CAndroidVMHelper::NATIVE_METHODS_DEFAULT_CLASS, "onServerReady");
|
||||
}
|
||||
#endif
|
||||
networkHandler->run();
|
||||
}
|
||||
|
||||
|
@ -12,12 +12,6 @@
|
||||
#include "../lib/network/NetworkInterface.h"
|
||||
#include "../lib/StartInfo.h"
|
||||
|
||||
#include <boost/program_options/variables_map.hpp>
|
||||
|
||||
#if defined(VCMI_ANDROID) && !defined(SINGLE_PROCESS_APP)
|
||||
#define VCMI_ANDROID_DUAL_PROCESS 1
|
||||
#endif
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class CMapInfo;
|
||||
@ -64,6 +58,8 @@ class CVCMIServer : public LobbyInfo, public INetworkServerListener, public INet
|
||||
|
||||
int currentClientId;
|
||||
ui8 currentPlayerId;
|
||||
uint16_t port;
|
||||
bool runByClient;
|
||||
|
||||
public:
|
||||
/// List of all active connections
|
||||
@ -76,13 +72,13 @@ public:
|
||||
void onTimer() override;
|
||||
|
||||
std::shared_ptr<CGameHandler> gh;
|
||||
boost::program_options::variables_map cmdLineOptions;
|
||||
|
||||
CVCMIServer(boost::program_options::variables_map & opts);
|
||||
CVCMIServer(uint16_t port, bool connectToLobby, bool runByClient);
|
||||
~CVCMIServer();
|
||||
|
||||
void run();
|
||||
|
||||
bool wasStartedByClient() const;
|
||||
bool prepareToStartGame();
|
||||
void prepareToRestart();
|
||||
void startGameImmediately();
|
||||
@ -131,13 +127,4 @@ public:
|
||||
void setCampaignBonus(int bonusId);
|
||||
|
||||
ui8 getIdOfFirstUnallocatedPlayer() const;
|
||||
|
||||
#if VCMI_ANDROID_DUAL_PROCESS
|
||||
static void create();
|
||||
#elif defined(SINGLE_PROCESS_APP)
|
||||
static void create(boost::condition_variable * cond, const std::vector<std::string> & args);
|
||||
# ifdef VCMI_ANDROID
|
||||
static void reuseClientJNIEnv(void * jniEnv);
|
||||
# endif // VCMI_ANDROID
|
||||
#endif // VCMI_ANDROID_DUAL_PROCESS
|
||||
};
|
||||
|
@ -81,7 +81,7 @@ void ClientPermissionsCheckerNetPackVisitor::visitLobbyClientDisconnected(LobbyC
|
||||
|
||||
if(pack.shutdownServer)
|
||||
{
|
||||
if(!srv.cmdLineOptions.count("run-by-client"))
|
||||
if(!srv.wasStartedByClient())
|
||||
{
|
||||
result = false;
|
||||
return;
|
||||
|
@ -1,20 +1,20 @@
|
||||
set(appserver_SRCS
|
||||
set(serverapp_SRCS
|
||||
StdInc.cpp
|
||||
EntryPoint.cpp
|
||||
)
|
||||
|
||||
set(appserver_HEADERS
|
||||
set(serverapp_HEADERS
|
||||
StdInc.h
|
||||
)
|
||||
|
||||
assign_source_group(${appserver_SRCS} ${appserver_HEADERS})
|
||||
add_executable(vcmiserver ${appserver_SRCS} ${appserver_HEADERS})
|
||||
set(appserver_LIBS vcmi)
|
||||
assign_source_group(${serverapp_SRCS} ${serverapp_HEADERS})
|
||||
add_executable(vcmiserver ${serverapp_SRCS} ${serverapp_HEADERS})
|
||||
set(serverapp_LIBS vcmi)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES FreeBSD OR HAIKU)
|
||||
set(appserver_LIBS execinfo ${appserver_LIBS})
|
||||
set(serverapp_LIBS execinfo ${serverapp_LIBS})
|
||||
endif()
|
||||
target_link_libraries(vcmiserver PRIVATE ${appserver_LIBS} minizip::minizip libserver)
|
||||
target_link_libraries(vcmiserver PRIVATE ${serverapp_LIBS} minizip::minizip vcmiservercommon)
|
||||
|
||||
target_include_directories(vcmiserver
|
||||
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
|
@ -16,12 +16,6 @@
|
||||
#include "../lib/VCMIDirs.h"
|
||||
#include "../lib/VCMI_Lib.h"
|
||||
|
||||
#ifdef VCMI_ANDROID
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
#include "lib/CAndroidVMHelper.h"
|
||||
#endif
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
const std::string SERVER_NAME_AFFIX = "server";
|
||||
@ -50,13 +44,8 @@ static void handleCommandOptions(int argc, const char * argv[], boost::program_o
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SINGLE_PROCESS_APP
|
||||
options.emplace("run-by-client", po::variable_value{true, true});
|
||||
#endif
|
||||
|
||||
po::notify(options);
|
||||
|
||||
#ifndef SINGLE_PROCESS_APP
|
||||
if(options.count("help"))
|
||||
{
|
||||
auto time = std::time(nullptr);
|
||||
@ -75,31 +64,14 @@ static void handleCommandOptions(int argc, const char * argv[], boost::program_o
|
||||
std::cout << VCMIDirs::get().genHelpString();
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SINGLE_PROCESS_APP
|
||||
#define main server_main
|
||||
#endif
|
||||
|
||||
#if VCMI_ANDROID_DUAL_PROCESS
|
||||
void CVCMIServer::create()
|
||||
{
|
||||
const int argc = 1;
|
||||
const char * argv[argc] = { "android-server" };
|
||||
#else
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
#endif
|
||||
|
||||
#if !defined(VCMI_ANDROID) && !defined(SINGLE_PROCESS_APP)
|
||||
// Correct working dir executable folder (not bundle folder) so we can use executable relative paths
|
||||
boost::filesystem::current_path(boost::filesystem::system_complete(argv[0]).parent_path());
|
||||
#endif
|
||||
|
||||
#ifndef VCMI_IOS
|
||||
console = new CConsoleHandler();
|
||||
#endif
|
||||
CBasicLogConfigurator logConfig(VCMIDirs::get().userLogsPath() / "VCMI_Server_log.txt", console);
|
||||
logConfig.configureDefault();
|
||||
logGlobal->info(SERVER_NAME);
|
||||
@ -113,58 +85,21 @@ int main(int argc, const char * argv[])
|
||||
std::srand(static_cast<uint32_t>(time(nullptr)));
|
||||
|
||||
{
|
||||
CVCMIServer server(opts);
|
||||
bool connectToLobby = opts.count("lobby");
|
||||
bool runByClient = opts.count("runByClient");
|
||||
uint16_t port = 3030;
|
||||
if(opts.count("port"))
|
||||
port = opts["port"].as<uint16_t>();
|
||||
|
||||
#ifdef SINGLE_PROCESS_APP
|
||||
boost::condition_variable * cond = reinterpret_cast<boost::condition_variable *>(const_cast<char *>(argv[0]));
|
||||
cond->notify_one();
|
||||
#endif
|
||||
CVCMIServer server(port, connectToLobby, runByClient);
|
||||
|
||||
server.run();
|
||||
|
||||
// CVCMIServer destructor must be called here - before VLC cleanup
|
||||
}
|
||||
|
||||
|
||||
#if VCMI_ANDROID_DUAL_PROCESS
|
||||
CAndroidVMHelper envHelper;
|
||||
envHelper.callStaticVoidMethod(CAndroidVMHelper::NATIVE_METHODS_DEFAULT_CLASS, "killServer");
|
||||
#endif
|
||||
logConfig.deconfigure();
|
||||
vstd::clear_pointer(VLC);
|
||||
|
||||
#if !VCMI_ANDROID_DUAL_PROCESS
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if VCMI_ANDROID_DUAL_PROCESS
|
||||
extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_createServer(JNIEnv * env, jclass cls)
|
||||
{
|
||||
__android_log_write(ANDROID_LOG_INFO, "VCMI", "Got jni call to init server");
|
||||
CAndroidVMHelper::cacheVM(env);
|
||||
|
||||
CVCMIServer::create();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_initClassloader(JNIEnv * baseEnv, jclass cls)
|
||||
{
|
||||
CAndroidVMHelper::initClassloader(baseEnv);
|
||||
}
|
||||
#elif defined(SINGLE_PROCESS_APP)
|
||||
void CVCMIServer::create(boost::condition_variable * cond, const std::vector<std::string> & args)
|
||||
{
|
||||
std::vector<const void *> argv = {cond};
|
||||
for(auto & a : args)
|
||||
argv.push_back(a.c_str());
|
||||
main(argv.size(), reinterpret_cast<const char **>(&*argv.begin()));
|
||||
}
|
||||
|
||||
#ifdef VCMI_ANDROID
|
||||
void CVCMIServer::reuseClientJNIEnv(void * jniEnv)
|
||||
{
|
||||
CAndroidVMHelper::initClassloader(jniEnv);
|
||||
CAndroidVMHelper::alwaysUseLoadedClass = true;
|
||||
}
|
||||
#endif // VCMI_ANDROID
|
||||
#endif // VCMI_ANDROID_DUAL_PROCESS
|
||||
|
Loading…
x
Reference in New Issue
Block a user