Browse Source

Merge pull request #3609 from IvanSavenko/single_process

Allow running server as part of client process
Ivan Savenko 1 year ago
parent
commit
9ebd194ab1

+ 3 - 3
AI/BattleAI/CMakeLists.txt

@@ -24,12 +24,12 @@ set(battleAI_HEADERS
 		BattleExchangeVariant.h
 )
 
-if(NOT ENABLE_STATIC_AI_LIBS)
+if(NOT ENABLE_STATIC_LIBS)
 	list(APPEND battleAI_SRCS main.cpp StdInc.cpp)
 endif()
 assign_source_group(${battleAI_SRCS} ${battleAI_HEADERS})
 
-if(ENABLE_STATIC_AI_LIBS)
+if(ENABLE_STATIC_LIBS)
 	add_library(BattleAI STATIC ${battleAI_SRCS} ${battleAI_HEADERS})
 else()
 	add_library(BattleAI SHARED ${battleAI_SRCS} ${battleAI_HEADERS})
@@ -37,7 +37,7 @@ else()
 endif()
 
 target_include_directories(BattleAI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
-target_link_libraries(BattleAI PRIVATE ${VCMI_LIB_TARGET} TBB::tbb)
+target_link_libraries(BattleAI PRIVATE vcmi TBB::tbb)
 
 vcmi_set_output_dir(BattleAI "AI")
 enable_pch(BattleAI)

+ 3 - 3
AI/EmptyAI/CMakeLists.txt

@@ -8,12 +8,12 @@ set(emptyAI_HEADERS
 		CEmptyAI.h
 )
 
-if(NOT ENABLE_STATIC_AI_LIBS)
+if(NOT ENABLE_STATIC_LIBS)
 	list(APPEND emptyAI_SRCS main.cpp StdInc.cpp)
 endif()
 assign_source_group(${emptyAI_SRCS} ${emptyAI_HEADERS})
 
-if(ENABLE_STATIC_AI_LIBS)
+if(ENABLE_STATIC_LIBS)
 	add_library(EmptyAI STATIC ${emptyAI_SRCS} ${emptyAI_HEADERS})
 else()
 	add_library(EmptyAI SHARED ${emptyAI_SRCS} ${emptyAI_HEADERS})
@@ -21,7 +21,7 @@ else()
 endif()
 
 target_include_directories(EmptyAI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
-target_link_libraries(EmptyAI PRIVATE ${VCMI_LIB_TARGET})
+target_link_libraries(EmptyAI PRIVATE vcmi)
 
 vcmi_set_output_dir(EmptyAI "AI")
 enable_pch(EmptyAI)

+ 3 - 3
AI/Nullkiller/CMakeLists.txt

@@ -125,12 +125,12 @@ set(Nullkiller_HEADERS
 		AIGateway.h
 )
 
-if(NOT ENABLE_STATIC_AI_LIBS)
+if(NOT ENABLE_STATIC_LIBS)
 	list(APPEND Nullkiller_SRCS main.cpp StdInc.cpp)
 endif()
 assign_source_group(${Nullkiller_SRCS} ${Nullkiller_HEADERS})
 
-if(ENABLE_STATIC_AI_LIBS)
+if(ENABLE_STATIC_LIBS)
 	add_library(Nullkiller STATIC ${Nullkiller_SRCS} ${Nullkiller_HEADERS})
 else()
 	add_library(Nullkiller SHARED ${Nullkiller_SRCS} ${Nullkiller_HEADERS})
@@ -138,7 +138,7 @@ else()
 endif()
 
 target_include_directories(Nullkiller PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
-target_link_libraries(Nullkiller PUBLIC ${VCMI_LIB_TARGET} fuzzylite::fuzzylite TBB::tbb)
+target_link_libraries(Nullkiller PUBLIC vcmi fuzzylite::fuzzylite TBB::tbb)
 
 vcmi_set_output_dir(Nullkiller "AI")
 enable_pch(Nullkiller)

+ 3 - 3
AI/StupidAI/CMakeLists.txt

@@ -8,19 +8,19 @@ set(stupidAI_HEADERS
 		StupidAI.h
 )
 
-if(NOT ENABLE_STATIC_AI_LIBS)
+if(NOT ENABLE_STATIC_LIBS)
 	list(APPEND stupidAI_SRCS main.cpp StdInc.cpp)
 endif()
 assign_source_group(${stupidAI_SRCS} ${stupidAI_HEADERS})
 
-if(ENABLE_STATIC_AI_LIBS)
+if(ENABLE_STATIC_LIBS)
 	add_library(StupidAI STATIC ${stupidAI_SRCS} ${stupidAI_HEADERS})
 else()
 	add_library(StupidAI SHARED ${stupidAI_SRCS} ${stupidAI_HEADERS})
 	install(TARGETS StupidAI RUNTIME DESTINATION ${AI_LIB_DIR} LIBRARY DESTINATION ${AI_LIB_DIR})
 endif()
 
-target_link_libraries(StupidAI PRIVATE ${VCMI_LIB_TARGET})
+target_link_libraries(StupidAI PRIVATE vcmi)
 target_include_directories(StupidAI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
 
 vcmi_set_output_dir(StupidAI "AI")

+ 3 - 3
AI/VCAI/CMakeLists.txt

@@ -94,12 +94,12 @@ set(VCAI_HEADERS
 		VCAI.h
 )
 
-if(NOT ENABLE_STATIC_AI_LIBS)
+if(NOT ENABLE_STATIC_LIBS)
 	list(APPEND VCAI_SRCS main.cpp StdInc.cpp)
 endif()
 assign_source_group(${VCAI_SRCS} ${VCAI_HEADERS})
 
-if(ENABLE_STATIC_AI_LIBS)
+if(ENABLE_STATIC_LIBS)
 	add_library(VCAI STATIC ${VCAI_SRCS} ${VCAI_HEADERS})
 else()
 	add_library(VCAI SHARED ${VCAI_SRCS} ${VCAI_HEADERS})
@@ -107,7 +107,7 @@ else()
 endif()
 
 target_include_directories(VCAI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
-target_link_libraries(VCAI PUBLIC ${VCMI_LIB_TARGET} fuzzylite::fuzzylite)
+target_link_libraries(VCAI PUBLIC vcmi fuzzylite::fuzzylite)
 
 vcmi_set_output_dir(VCAI "AI")
 enable_pch(VCAI)

+ 62 - 58
CMakeLists.txt

@@ -41,64 +41,77 @@ if(NOT CMAKE_BUILD_TYPE)
 	set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo)
 endif()
 
-set(buildLobby OFF)
-set(singleProcess OFF)
-set(staticAI OFF)
-if(ANDROID)
-	set(staticAI ON)
-	set(singleProcess ON)
-endif()
+# Platform-independent options
 
 option(ENABLE_ERM "Enable compilation of ERM scripting module" OFF)
 option(ENABLE_LUA "Enable compilation of LUA scripting module" OFF)
-if(NOT ANDROID)
-	option(ENABLE_LAUNCHER "Enable compilation of launcher" ON)
-	option(ENABLE_EDITOR "Enable compilation of map editor" ON)
-endif()
 option(ENABLE_TRANSLATIONS "Enable generation of translations for launcher and editor" ON)
 option(ENABLE_NULLKILLER_AI "Enable compilation of Nullkiller AI library" ON)
+option(ENABLE_GITVERSION "Enable Version.cpp with Git commit hash" ON)
 
-if(APPLE_IOS)
-	set(BUNDLE_IDENTIFIER_PREFIX "" CACHE STRING "Bundle identifier prefix")
-	set(APP_DISPLAY_NAME "VCMI" CACHE STRING "App name on the home screen")
-	set(ENABLE_SINGLE_APP_BUILD ON)
-else()
-	option(ENABLE_TEST "Enable compilation of unit tests" OFF)
-	option(ENABLE_SINGLE_APP_BUILD "Builds client and server as single executable" ${singleProcess})
-endif()
+# Compilation options
 
 option(ENABLE_PCH "Enable compilation using precompiled headers" ON)
-option(ENABLE_GITVERSION "Enable Version.cpp with Git commit hash" ON)
 option(ENABLE_DEBUG_CONSOLE "Enable debug console for Windows builds" ON)
 option(ENABLE_STRICT_COMPILATION "Treat all compiler warnings as errors" OFF)
 option(ENABLE_MULTI_PROCESS_BUILDS "Enable /MP flag for MSVS solution" ON)
-option(COPY_CONFIG_ON_BUILD "Copies config folder into output directory at building phase" ON)
-option(ENABLE_STATIC_AI_LIBS "Add AI code into VCMI lib directly" ${staticAI})
-
 option(ENABLE_COLORIZED_COMPILER_OUTPUT "Colorize compilation output (Clang/GNU)." ON)
+option(ENABLE_CCACHE "Speed up recompilation by caching previous compilations" OFF)
 
-if(ENABLE_COLORIZED_COMPILER_OUTPUT)
-	if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
-		add_compile_options(-fcolor-diagnostics)
-	elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
-		add_compile_options(-fdiagnostics-color=always)
-	endif()
+# Platform-specific options
+
+if(ANDROID)
+	set(ENABLE_STATIC_LIBS ON)
+	set(ENABLE_LAUNCHER OFF)
+else()
+	option(ENABLE_STATIC_LIBS "Build library and all components such as AI statically" OFF)
+	option(ENABLE_LAUNCHER "Enable compilation of launcher" ON)
 endif()
 
-# Used for Snap packages and also useful for debugging
-if(NOT APPLE_IOS AND NOT ANDROID)
-	option(ENABLE_MONOLITHIC_INSTALL "Install everything in single directory on Linux and Mac" OFF)
+if(APPLE_IOS OR ANDROID)
+	set(ENABLE_MONOLITHIC_INSTALL OFF)
+	set(ENABLE_SINGLE_APP_BUILD ON)
+	set(ENABLE_EDITOR OFF)
+	set(ENABLE_TEST OFF)
+	set(ENABLE_LOBBY OFF)
+	set(ENABLE_SERVER OFF)
+	set(COPY_CONFIG_ON_BUILD OFF)
+else()
+	option(ENABLE_MONOLITHIC_INSTALL "Install everything in single directory on Linux and Mac" OFF) # Used for Snap packages and also useful for debugging
+	option(COPY_CONFIG_ON_BUILD "Copies config folder into output directory at building phase" ON)
+	option(ENABLE_SERVER "Enable compilation of dedicated server" 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(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
-	set(buildLobby ON)
+# ERM depends on LUA implicitly
+if(ENABLE_ERM AND NOT ENABLE_LUA)
+	set(ENABLE_LUA ON)
 endif()
 
-if(NOT APPLE_IOS AND NOT ANDROID)
-	option(ENABLE_LOBBY "Enable compilation of lobby server" ${buildLobby})
+############################################
+#        Miscellaneous options             #
+############################################
+
+if (ENABLE_STATIC_LIBS AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+	set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+endif()
+
+if(APPLE_IOS)
+	set(BUNDLE_IDENTIFIER_PREFIX "" CACHE STRING "Bundle identifier prefix")
+	set(APP_DISPLAY_NAME "VCMI" CACHE STRING "App name on the home screen")
+endif()
+
+if(ENABLE_COLORIZED_COMPILER_OUTPUT)
+	if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+		add_compile_options(-fcolor-diagnostics)
+	elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+		add_compile_options(-fdiagnostics-color=always)
+	endif()
 endif()
 
-option(ENABLE_CCACHE "Speed up recompilation by caching previous compilations" OFF)
 if(ENABLE_CCACHE)
 	find_program(CCACHE ccache REQUIRED)
 endif()
@@ -128,20 +141,6 @@ endif()
 set(PACKAGE_NAME_SUFFIX "" CACHE STRING "Suffix for CPack package name")
 set(PACKAGE_FILE_NAME "" CACHE STRING "Override for CPack package filename")
 
-# ERM depends on LUA implicitly
-if(ENABLE_ERM AND NOT ENABLE_LUA)
-	set(ENABLE_LUA ON)
-endif()
-
-# We don't want to deploy assets into build directory for android/iOS build
-if((APPLE_IOS OR ANDROID) AND COPY_CONFIG_ON_BUILD)
-	set(COPY_CONFIG_ON_BUILD OFF)
-endif()
-
-############################################
-#        Miscellaneous options             #
-############################################
-
 set(CMAKE_MODULE_PATH ${CMAKE_HOME_DIRECTORY}/cmake_modules ${PROJECT_SOURCE_DIR}/CI)
 # Contains custom functions and macros, but don't altering any options
 
@@ -250,7 +249,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)
@@ -609,21 +608,19 @@ if(APPLE_IOS)
 	add_subdirectory(ios)
 endif()
 
-set(VCMI_LIB_TARGET vcmi)
 add_subdirectory_with_folder("AI" AI)
 
-include(VCMI_lib)
 add_subdirectory(lib)
-if(ENABLE_SINGLE_APP_BUILD)
-	add_subdirectory(lib_server)
-endif()
+add_subdirectory(server)
 
 if(ENABLE_ERM)
 	add_subdirectory(scripting/erm)
 endif()
+
 if(ENABLE_LUA)
 	add_subdirectory(scripting/lua)
 endif()
+
 if(NOT TARGET minizip::minizip)
 	add_subdirectory_with_folder("3rdparty" lib/minizip)
 	add_library(minizip::minizip ALIAS minizip)
@@ -632,14 +629,21 @@ endif()
 if(ENABLE_LAUNCHER)
 	add_subdirectory(launcher)
 endif()
+
 if(ENABLE_EDITOR)
 	add_subdirectory(mapeditor)
 endif()
+
 if(ENABLE_LOBBY)
 	add_subdirectory(lobby)
 endif()
+
 add_subdirectory(client)
-add_subdirectory(server)
+
+if(ENABLE_SERVER)
+	add_subdirectory(serverapp)
+endif()
+
 if(ENABLE_TEST)
 	enable_testing()
 	add_subdirectory(test)

+ 2 - 1
CMakePresets.json

@@ -51,7 +51,8 @@
             "inherits": "linux-release",
             "hidden": true,
             "cacheVariables": {
-                "ENABLE_TEST": "ON",
+                "ENABLE_LOBBY": "ON",
+				"ENABLE_TEST": "ON",
                 "ENABLE_LUA": "ON"
             }
         },

+ 0 - 62
android/vcmi-app/src/main/java/eu/vcmi/vcmi/NativeMethods.java

@@ -36,12 +36,6 @@ public class NativeMethods
 
     public static native void initClassloader();
 
-    public static native void createServer();
-
-    public static native void notifyServerReady();
-
-    public static native void notifyServerClosed();
-
     public static native boolean tryToSaveTheGame();
 
     public static void setupMsg(final Messenger msg)
@@ -77,62 +71,6 @@ public class NativeMethods
         return ctx.getApplicationInfo().nativeLibraryDir;
     }
 
-    @SuppressWarnings(Const.JNI_METHOD_SUPPRESS)
-    public static void startServer()
-    {
-        Log.i("Got server create request");
-        final Context ctx = SDL.getContext();
-
-        if (!(ctx instanceof VcmiSDLActivity))
-        {
-            Log.e("Unexpected context... " + ctx);
-            return;
-        }
-
-        Intent intent = new Intent(ctx, SDLActivity.class);
-        intent.setAction(VcmiSDLActivity.NATIVE_ACTION_CREATE_SERVER);
-        // I probably do something incorrectly, but sending new intent to the activity "normally" breaks SDL events handling (probably detaches jnienv?)
-        // so instead let's call onNewIntent directly, as out context SHOULD be SDLActivity anyway
-        ((VcmiSDLActivity) ctx).hackCallNewIntentDirectly(intent);
-//        ctx.startActivity(intent);
-    }
-
-    @SuppressWarnings(Const.JNI_METHOD_SUPPRESS)
-    public static void killServer()
-    {
-        Log.i("Got server close request");
-
-        final Context ctx = SDL.getContext();
-        ctx.stopService(new Intent(ctx, ServerService.class));
-
-        Messenger messenger = requireServerMessenger();
-        try
-        {
-            // we need to actually inform client about killing the server, beacuse it needs to unbind service connection before server gets destroyed
-            messenger.send(Message.obtain(null, VcmiSDLActivity.SERVER_MESSAGE_SERVER_KILLED));
-        }
-        catch (RemoteException e)
-        {
-            Log.w("Connection with client process broken?");
-        }
-    }
-
-    @SuppressWarnings(Const.JNI_METHOD_SUPPRESS)
-    public static void onServerReady()
-    {
-        Log.i("Got server ready msg");
-        Messenger messenger = requireServerMessenger();
-
-        try
-        {
-            messenger.send(Message.obtain(null, VcmiSDLActivity.SERVER_MESSAGE_SERVER_READY));
-        }
-        catch (RemoteException e)
-        {
-            Log.w("Connection with client process broken?");
-        }
-    }
-
     @SuppressWarnings(Const.JNI_METHOD_SUPPRESS)
     public static void showProgress()
     {

+ 0 - 10
android/vcmi-app/src/main/java/eu/vcmi/vcmi/ServerService.java

@@ -58,15 +58,6 @@ public class ServerService extends Service
         void onClientRegistered(Messenger client);
     }
 
-    private static class ServerStartThread extends Thread
-    {
-        @Override
-        public void run()
-        {
-            NativeMethods.createServer();
-        }
-    }
-
     private static class IncomingClientMessageHandler extends Handler
     {
         private WeakReference<IncomingClientMessageHandlerCallback> mCallbackRef;
@@ -88,7 +79,6 @@ public class ServerService extends Service
                         callback.onClientRegistered(msg.replyTo);
                     }
                     NativeMethods.setupMsg(msg.replyTo);
-                    new ServerStartThread().start();
                     break;
                 default:
                     super.handleMessage(msg);

+ 0 - 28
android/vcmi-app/src/main/java/eu/vcmi/vcmi/VcmiSDLActivity.java

@@ -20,9 +20,6 @@ import eu.vcmi.vcmi.util.Log;
 
 public class VcmiSDLActivity extends SDLActivity
 {
-    public static final int SERVER_MESSAGE_SERVER_READY = 1000;
-    public static final int SERVER_MESSAGE_SERVER_KILLED = 1001;
-    public static final String NATIVE_ACTION_CREATE_SERVER = "SDLActivity.Action.CreateServer";
     protected static final int COMMAND_USER = 0x8000;
 
     final Messenger mClientMessenger = new Messenger(
@@ -96,10 +93,6 @@ public class VcmiSDLActivity extends SDLActivity
     protected void onNewIntent(final Intent intent)
     {
         Log.i(this, "Got new intent with action " + intent.getAction());
-        if (NATIVE_ACTION_CREATE_SERVER.equals(intent.getAction()))
-        {
-            initService();
-        }
     }
 
     @Override
@@ -188,26 +181,5 @@ public class VcmiSDLActivity extends SDLActivity
         {
             mCallback = callback;
         }
-
-        @Override
-        public void handleMessage(Message msg)
-        {
-            Log.i(this, "Got server msg " + msg);
-            switch (msg.what)
-            {
-                case SERVER_MESSAGE_SERVER_READY:
-                    NativeMethods.notifyServerReady();
-                    break;
-                case SERVER_MESSAGE_SERVER_KILLED:
-                    if (mCallback != null)
-                    {
-                        mCallback.unbindServer();
-                    }
-                    NativeMethods.notifyServerClosed();
-                    break;
-                default:
-                    super.handleMessage(msg);
-            }
-        }
     }
 }

+ 4 - 0
client/CMT.cpp

@@ -190,6 +190,7 @@ int main(int argc, char * argv[])
 	console->start();
 #endif
 
+	setThreadNameLoggingOnly("MainGUI");
 	const boost::filesystem::path logPath = VCMIDirs::get().userLogsPath() / "VCMI_Client_log.txt";
 	logConfig = new CBasicLogConfigurator(logPath, console);
 	logConfig->configureDefault();
@@ -398,7 +399,10 @@ void playIntro()
 
 static void mainLoop()
 {
+#ifndef VCMI_UNIX
+	// on Linux, name of main thread is also name of our process. Which we don't want to change
 	setThreadName("MainGUI");
+#endif
 
 	while(1) //main SDL events loop
 	{

+ 8 - 8
client/CMakeLists.txt

@@ -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
 )
 
@@ -373,8 +375,7 @@ else()
 	add_executable(vcmiclient ${client_SRCS} ${client_HEADERS})
 endif()
 
-add_dependencies(vcmiclient vcmiserver)
-if(NOT ENABLE_STATIC_AI_LIBS)
+if(NOT ENABLE_STATIC_LIBS)
 	add_dependencies(vcmiclient
 		BattleAI
 		EmptyAI
@@ -451,14 +452,13 @@ 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
+		vcmi SDL2::SDL2 SDL2::Image SDL2::Mixer SDL2::TTF
 )
 
 if(ffmpeg_LIBRARIES)

+ 53 - 127
client/CServerHandler.cpp

@@ -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:
@@ -126,9 +108,14 @@ public:
 
 CServerHandler::~CServerHandler()
 {
+	if (serverRunner)
+		serverRunner->shutdown();
 	networkHandler->stop();
 	try
 	{
+		if (serverRunner)
+			serverRunner->wait();
+		serverRunner.reset();
 		threadNetwork.join();
 	}
 	catch (const std::runtime_error & e)
@@ -195,70 +182,22 @@ 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);
-	}
+	logNetwork->trace("\tLocal server startup has been requested");
+#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();
-		});
-#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;
+	if (settings["server"]["useProcess"].Bool())
+		serverRunner.reset(new ServerProcessRunner());
+	else
+		serverRunner.reset(new ServerThreadRunner());
 #endif
-	logNetwork->trace("Waiting for server: %d ms", th->getDiff());
-
-	th->update(); //put breakpoint here to attach to server before it does something stupid
 
+	logNetwork->trace("\tStarting local server");
+	serverRunner->start(getLocalPort(), connectToLobby);
+	logNetwork->trace("\tConnecting to local server");
 	connectToServer(getLocalHostname(), getLocalPort());
-
-	logNetwork->trace("\tConnecting to the server: %d ms", th->getDiff());
+	logNetwork->trace("\tWaiting for connection");
 }
 
 void CServerHandler::connectToServer(const std::string & addr, const ui16 port)
@@ -306,6 +245,10 @@ void CServerHandler::onTimer()
 	if(getState() == EClientState::CONNECTION_CANCELLED)
 	{
 		logNetwork->info("Connection aborted by player!");
+		serverRunner->wait();
+		serverRunner.reset();
+		if (GH.windows().topWindow<CSimpleJoinScreen>() != nullptr)
+			GH.windows().popWindows(1);
 		return;
 	}
 
@@ -369,12 +312,15 @@ EClientState CServerHandler::getState() const
 
 void CServerHandler::setState(EClientState newState)
 {
+	if (newState == EClientState::CONNECTION_CANCELLED && serverRunner != nullptr)
+		serverRunner->shutdown();
+
 	state = newState;
 }
 
 bool CServerHandler::isServerLocal() const
 {
-	return threadRunLocalServer.joinable();
+	return serverRunner != nullptr;
 }
 
 bool CServerHandler::isHost() const
@@ -758,7 +704,6 @@ void CServerHandler::startCampaignScenario(HighScoreParameter param, std::shared
 			}
 		};
 
-		threadRunLocalServer.join();
 		if(epilogue.hasPrologEpilog)
 		{
 			GH.windows().createAndPushWindow<CPrologEpilogVideo>(epilogue, finisher);
@@ -899,6 +844,8 @@ void CServerHandler::onPacketReceived(const std::shared_ptr<INetworkConnection>
 
 void CServerHandler::onDisconnected(const std::shared_ptr<INetworkConnection> & connection, const std::string & errorMessage)
 {
+	waitForServerShutdown();
+
 	if(getState() == EClientState::DISCONNECTING)
 	{
 		assert(networkConnection == nullptr);
@@ -928,70 +875,49 @@ void CServerHandler::onDisconnected(const std::shared_ptr<INetworkConnection> &
 	networkConnection.reset();
 }
 
-void CServerHandler::visitForLobby(CPackForLobby & lobbyPack)
-{
-	if(applier->getApplier(CTypeList::getInstance().getTypeID(&lobbyPack))->applyOnLobbyHandler(this, lobbyPack))
-	{
-		if(!settings["session"]["headless"].Bool())
-			applyPackOnLobbyScreen(lobbyPack);
-	}
-}
-
-void CServerHandler::visitForClient(CPackForClient & clientPack)
+void CServerHandler::waitForServerShutdown()
 {
-	client->handlePack(&clientPack);
-}
+	if (!serverRunner)
+		return; // may not exist for guest in MP
 
-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";
+	serverRunner->wait();
+	int exitCode = serverRunner->exitCode();
+	serverRunner.reset();
 
-	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)
+	if (exitCode == 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);
+		logNetwork->error("Check log file for more info");
 	}
-#endif
+
+	serverRunner.reset();
 }
 
+void CServerHandler::visitForLobby(CPackForLobby & lobbyPack)
+{
+	if(applier->getApplier(CTypeList::getInstance().getTypeID(&lobbyPack))->applyOnLobbyHandler(this, lobbyPack))
+	{
+		if(!settings["session"]["headless"].Bool())
+			applyPackOnLobbyScreen(lobbyPack);
+	}
+}
+
+void CServerHandler::visitForClient(CPackForClient & clientPack)
+{
+	client->handlePack(&clientPack);
+}
+
+
 void CServerHandler::sendLobbyPack(const CPackForLobby & pack) const
 {
 	if(getState() != EClientState::STARTING)

+ 3 - 2
client/CServerHandler.h

@@ -36,6 +36,7 @@ VCMI_LIB_NAMESPACE_END
 class CClient;
 class CBaseForLobbyApply;
 class GlobalLobbyClient;
+class IServerRunner;
 
 class HighScoreCalculation;
 class HighScoreParameter;
@@ -100,17 +101,17 @@ 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> localPlayerNames;
 	std::shared_ptr<HighScoreCalculation> highScoreCalc;
 
-	boost::thread threadRunLocalServer;
 	boost::thread threadNetwork;
 
 	std::atomic<EClientState> state;
 
 	void threadRunNetwork();
-	void threadRunServer(bool connectToLobby);
+	void waitForServerShutdown();
 
 	void sendLobbyPack(const CPackForLobby & pack) const override;
 

+ 0 - 20
client/Client.cpp

@@ -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");

+ 88 - 0
client/ServerRunner.cpp

@@ -0,0 +1,88 @@
+/*
+ * 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;
+
+void ServerThreadRunner::start(uint16_t port, bool connectToLobby)
+{
+	server = std::make_unique<CVCMIServer>(port, connectToLobby, true);
+
+	threadRunLocalServer = boost::thread([this]{
+		setThreadName("runServer");
+		server->run();
+	});
+}
+
+void ServerThreadRunner::shutdown()
+{
+	server->setState(EServerState::SHUTDOWN);
+}
+
+void ServerThreadRunner::wait()
+{
+	threadRunLocalServer.join();
+}
+
+int ServerThreadRunner::exitCode()
+{
+	return 0;
+}
+
+#ifndef VCMI_MOBILE
+
+ServerProcessRunner::ServerProcessRunner() = default;
+ServerProcessRunner::~ServerProcessRunner() = default;
+
+void ServerProcessRunner::shutdown()
+{
+	child->terminate();
+}
+
+void ServerProcessRunner::wait()
+{
+	child->wait();
+}
+
+int ServerProcessRunner::exitCode()
+{
+	return child->exit_code();
+}
+
+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());
+}
+
+#endif

+ 61 - 0
client/ServerRunner.h

@@ -0,0 +1,61 @@
+/*
+ * 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 shutdown() = 0;
+	virtual void wait() = 0;
+	virtual int exitCode() = 0;
+
+	virtual ~IServerRunner() = default;
+};
+
+/// Class that runs server instance 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 shutdown() override;
+	void wait() override;
+	int exitCode() override;
+
+	ServerThreadRunner();
+	~ServerThreadRunner();
+};
+
+#ifndef VCMI_MOBILE
+
+namespace boost::process {
+class child;
+}
+
+/// Class that runs server instance as a child process
+/// Available only on desktop systems where process management is allowed
+class ServerProcessRunner : public IServerRunner, boost::noncopyable
+{
+	std::unique_ptr<boost::process::child> child;
+
+public:
+	void start(uint16_t port, bool connectToLobby) override;
+	void shutdown() override;
+	void wait() override;
+	int exitCode() override;
+
+	ServerProcessRunner();
+	~ServerProcessRunner();
+};
+#endif

+ 0 - 12
client/mainmenu/CMainMenu.cpp

@@ -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

+ 0 - 757
cmake_modules/VCMI_lib.cmake

@@ -1,757 +0,0 @@
-macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
-	if(NOT DEFINED MAIN_LIB_DIR)
-		set(MAIN_LIB_DIR "${CMAKE_SOURCE_DIR}/lib")
-	endif()
-
-	set(lib_SRCS
-		${MAIN_LIB_DIR}/StdInc.cpp
-
-		${MAIN_LIB_DIR}/battle/AccessibilityInfo.cpp
-		${MAIN_LIB_DIR}/battle/BattleAction.cpp
-		${MAIN_LIB_DIR}/battle/BattleAttackInfo.cpp
-		${MAIN_LIB_DIR}/battle/BattleHex.cpp
-		${MAIN_LIB_DIR}/battle/BattleInfo.cpp
-		${MAIN_LIB_DIR}/battle/BattleProxy.cpp
-		${MAIN_LIB_DIR}/battle/BattleStateInfoForRetreat.cpp
-		${MAIN_LIB_DIR}/battle/CBattleInfoCallback.cpp
-		${MAIN_LIB_DIR}/battle/CBattleInfoEssentials.cpp
-		${MAIN_LIB_DIR}/battle/CObstacleInstance.cpp
-		${MAIN_LIB_DIR}/battle/CPlayerBattleCallback.cpp
-		${MAIN_LIB_DIR}/battle/CUnitState.cpp
-		${MAIN_LIB_DIR}/battle/DamageCalculator.cpp
-		${MAIN_LIB_DIR}/battle/Destination.cpp
-		${MAIN_LIB_DIR}/battle/IBattleState.cpp
-		${MAIN_LIB_DIR}/battle/ReachabilityInfo.cpp
-		${MAIN_LIB_DIR}/battle/SideInBattle.cpp
-		${MAIN_LIB_DIR}/battle/SiegeInfo.cpp
-		${MAIN_LIB_DIR}/battle/Unit.cpp
-
-		${MAIN_LIB_DIR}/bonuses/Bonus.cpp
-		${MAIN_LIB_DIR}/bonuses/BonusEnum.cpp
-		${MAIN_LIB_DIR}/bonuses/BonusList.cpp
-		${MAIN_LIB_DIR}/bonuses/BonusParams.cpp
-		${MAIN_LIB_DIR}/bonuses/BonusSelector.cpp
-		${MAIN_LIB_DIR}/bonuses/BonusCustomTypes.cpp
-		${MAIN_LIB_DIR}/bonuses/CBonusProxy.cpp
-		${MAIN_LIB_DIR}/bonuses/CBonusSystemNode.cpp
-		${MAIN_LIB_DIR}/bonuses/IBonusBearer.cpp
-		${MAIN_LIB_DIR}/bonuses/Limiters.cpp
-		${MAIN_LIB_DIR}/bonuses/Propagators.cpp
-		${MAIN_LIB_DIR}/bonuses/Updaters.cpp
-
-		${MAIN_LIB_DIR}/campaign/CampaignHandler.cpp
-		${MAIN_LIB_DIR}/campaign/CampaignState.cpp
-
-		${MAIN_LIB_DIR}/constants/EntityIdentifiers.cpp
-
-		${MAIN_LIB_DIR}/events/ApplyDamage.cpp
-		${MAIN_LIB_DIR}/events/GameResumed.cpp
-		${MAIN_LIB_DIR}/events/ObjectVisitEnded.cpp
-		${MAIN_LIB_DIR}/events/ObjectVisitStarted.cpp
-		${MAIN_LIB_DIR}/events/PlayerGotTurn.cpp
-		${MAIN_LIB_DIR}/events/TurnStarted.cpp
-
-		${MAIN_LIB_DIR}/filesystem/AdapterLoaders.cpp
-		${MAIN_LIB_DIR}/filesystem/CArchiveLoader.cpp
-		${MAIN_LIB_DIR}/filesystem/CBinaryReader.cpp
-		${MAIN_LIB_DIR}/filesystem/CCompressedStream.cpp
-		${MAIN_LIB_DIR}/filesystem/CFileInputStream.cpp
-		${MAIN_LIB_DIR}/filesystem/CFilesystemLoader.cpp
-		${MAIN_LIB_DIR}/filesystem/CMemoryBuffer.cpp
-		${MAIN_LIB_DIR}/filesystem/CMemoryStream.cpp
-		${MAIN_LIB_DIR}/filesystem/CZipLoader.cpp
-		${MAIN_LIB_DIR}/filesystem/CZipSaver.cpp
-		${MAIN_LIB_DIR}/filesystem/FileInfo.cpp
-		${MAIN_LIB_DIR}/filesystem/Filesystem.cpp
-		${MAIN_LIB_DIR}/filesystem/MinizipExtensions.cpp
-		${MAIN_LIB_DIR}/filesystem/ResourcePath.cpp
-
-		${MAIN_LIB_DIR}/gameState/CGameState.cpp
-		${MAIN_LIB_DIR}/gameState/CGameStateCampaign.cpp
-		${MAIN_LIB_DIR}/gameState/InfoAboutArmy.cpp
-		${MAIN_LIB_DIR}/gameState/TavernHeroesPool.cpp
-
-		${MAIN_LIB_DIR}/logging/CBasicLogConfigurator.cpp
-		${MAIN_LIB_DIR}/logging/CLogger.cpp
-
-		${MAIN_LIB_DIR}/mapObjectConstructors/AObjectTypeHandler.cpp
-		${MAIN_LIB_DIR}/mapObjectConstructors/CBankInstanceConstructor.cpp
-		${MAIN_LIB_DIR}/mapObjectConstructors/CObjectClassesHandler.cpp
-		${MAIN_LIB_DIR}/mapObjectConstructors/CommonConstructors.cpp
-		${MAIN_LIB_DIR}/mapObjectConstructors/CRewardableConstructor.cpp
-		${MAIN_LIB_DIR}/mapObjectConstructors/DwellingInstanceConstructor.cpp
-		${MAIN_LIB_DIR}/mapObjectConstructors/HillFortInstanceConstructor.cpp
-		${MAIN_LIB_DIR}/mapObjectConstructors/ShipyardInstanceConstructor.cpp
-
-		${MAIN_LIB_DIR}/mapObjects/CArmedInstance.cpp
-		${MAIN_LIB_DIR}/mapObjects/CBank.cpp
-		${MAIN_LIB_DIR}/mapObjects/CGCreature.cpp
-		${MAIN_LIB_DIR}/mapObjects/CGDwelling.cpp
-		${MAIN_LIB_DIR}/mapObjects/CGHeroInstance.cpp
-		${MAIN_LIB_DIR}/mapObjects/CGMarket.cpp
-		${MAIN_LIB_DIR}/mapObjects/CGObjectInstance.cpp
-		${MAIN_LIB_DIR}/mapObjects/CGPandoraBox.cpp
-		${MAIN_LIB_DIR}/mapObjects/CGTownBuilding.cpp
-		${MAIN_LIB_DIR}/mapObjects/CGTownInstance.cpp
-		${MAIN_LIB_DIR}/mapObjects/CObjectHandler.cpp
-		${MAIN_LIB_DIR}/mapObjects/CQuest.cpp
-		${MAIN_LIB_DIR}/mapObjects/CRewardableObject.cpp
-		${MAIN_LIB_DIR}/mapObjects/IMarket.cpp
-		${MAIN_LIB_DIR}/mapObjects/IObjectInterface.cpp
-		${MAIN_LIB_DIR}/mapObjects/MiscObjects.cpp
-		${MAIN_LIB_DIR}/mapObjects/ObjectTemplate.cpp
-
-		${MAIN_LIB_DIR}/mapping/CDrawRoadsOperation.cpp
-		${MAIN_LIB_DIR}/mapping/CMap.cpp
-		${MAIN_LIB_DIR}/mapping/CMapHeader.cpp
-		${MAIN_LIB_DIR}/mapping/CMapEditManager.cpp
-		${MAIN_LIB_DIR}/mapping/CMapInfo.cpp
-		${MAIN_LIB_DIR}/mapping/CMapOperation.cpp
-		${MAIN_LIB_DIR}/mapping/CMapService.cpp
-		${MAIN_LIB_DIR}/mapping/MapEditUtils.cpp
-		${MAIN_LIB_DIR}/mapping/MapIdentifiersH3M.cpp
-		${MAIN_LIB_DIR}/mapping/MapFeaturesH3M.cpp
-		${MAIN_LIB_DIR}/mapping/MapFormatH3M.cpp
-		${MAIN_LIB_DIR}/mapping/MapReaderH3M.cpp
-		${MAIN_LIB_DIR}/mapping/MapFormatJson.cpp
-		${MAIN_LIB_DIR}/mapping/ObstacleProxy.cpp
-
-		${MAIN_LIB_DIR}/modding/ActiveModsInSaveList.cpp
-		${MAIN_LIB_DIR}/modding/CModHandler.cpp
-		${MAIN_LIB_DIR}/modding/CModInfo.cpp
-		${MAIN_LIB_DIR}/modding/CModVersion.cpp
-		${MAIN_LIB_DIR}/modding/ContentTypeHandler.cpp
-		${MAIN_LIB_DIR}/modding/IdentifierStorage.cpp
-		${MAIN_LIB_DIR}/modding/ModUtility.cpp
-
-		${MAIN_LIB_DIR}/network/NetworkConnection.cpp
-		${MAIN_LIB_DIR}/network/NetworkHandler.cpp
-		${MAIN_LIB_DIR}/network/NetworkServer.cpp
-
-		${MAIN_LIB_DIR}/networkPacks/NetPacksLib.cpp
-
-		${MAIN_LIB_DIR}/pathfinder/CGPathNode.cpp
-		${MAIN_LIB_DIR}/pathfinder/CPathfinder.cpp
-		${MAIN_LIB_DIR}/pathfinder/NodeStorage.cpp
-		${MAIN_LIB_DIR}/pathfinder/PathfinderOptions.cpp
-		${MAIN_LIB_DIR}/pathfinder/PathfindingRules.cpp
-		${MAIN_LIB_DIR}/pathfinder/TurnInfo.cpp
-
-		${MAIN_LIB_DIR}/rewardable/Configuration.cpp
-		${MAIN_LIB_DIR}/rewardable/Info.cpp
-		${MAIN_LIB_DIR}/rewardable/Interface.cpp
-		${MAIN_LIB_DIR}/rewardable/Limiter.cpp
-		${MAIN_LIB_DIR}/rewardable/Reward.cpp
-
-		${MAIN_LIB_DIR}/rmg/RmgArea.cpp
-		${MAIN_LIB_DIR}/rmg/RmgObject.cpp
-		${MAIN_LIB_DIR}/rmg/RmgPath.cpp
-		${MAIN_LIB_DIR}/rmg/CMapGenerator.cpp
-		${MAIN_LIB_DIR}/rmg/CMapGenOptions.cpp
-		${MAIN_LIB_DIR}/rmg/CRmgTemplate.cpp
-		${MAIN_LIB_DIR}/rmg/CRmgTemplateStorage.cpp
-		${MAIN_LIB_DIR}/rmg/CZonePlacer.cpp
-		${MAIN_LIB_DIR}/rmg/TileInfo.cpp
-		${MAIN_LIB_DIR}/rmg/Zone.cpp
-		${MAIN_LIB_DIR}/rmg/Functions.cpp
-		${MAIN_LIB_DIR}/rmg/RmgMap.cpp
-		${MAIN_LIB_DIR}/rmg/PenroseTiling.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/Modificator.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/ObjectManager.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/ObjectDistributor.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/RoadPlacer.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/TreasurePlacer.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/PrisonHeroPlacer.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/QuestArtifactPlacer.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/ConnectionsPlacer.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/WaterAdopter.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/MinePlacer.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/TownPlacer.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/WaterProxy.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/WaterRoutes.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/RockPlacer.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/RockFiller.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/ObstaclePlacer.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/RiverPlacer.cpp
-		${MAIN_LIB_DIR}/rmg/modificators/TerrainPainter.cpp
-		${MAIN_LIB_DIR}/rmg/threadpool/MapProxy.cpp
-
-		${MAIN_LIB_DIR}/serializer/BinaryDeserializer.cpp
-		${MAIN_LIB_DIR}/serializer/BinarySerializer.cpp
-		${MAIN_LIB_DIR}/serializer/CLoadFile.cpp
-		${MAIN_LIB_DIR}/serializer/CMemorySerializer.cpp
-		${MAIN_LIB_DIR}/serializer/Connection.cpp
-		${MAIN_LIB_DIR}/serializer/CSaveFile.cpp
-		${MAIN_LIB_DIR}/serializer/CSerializer.cpp
-		${MAIN_LIB_DIR}/serializer/CTypeList.cpp
-		${MAIN_LIB_DIR}/serializer/JsonDeserializer.cpp
-		${MAIN_LIB_DIR}/serializer/JsonSerializeFormat.cpp
-		${MAIN_LIB_DIR}/serializer/JsonSerializer.cpp
-		${MAIN_LIB_DIR}/serializer/JsonUpdater.cpp
-
-		${MAIN_LIB_DIR}/spells/AbilityCaster.cpp
-		${MAIN_LIB_DIR}/spells/AdventureSpellMechanics.cpp
-		${MAIN_LIB_DIR}/spells/BattleSpellMechanics.cpp
-		${MAIN_LIB_DIR}/spells/BonusCaster.cpp
-		${MAIN_LIB_DIR}/spells/CSpellHandler.cpp
-		${MAIN_LIB_DIR}/spells/ExternalCaster.cpp
-		${MAIN_LIB_DIR}/spells/ISpellMechanics.cpp
-		${MAIN_LIB_DIR}/spells/ObstacleCasterProxy.cpp
-		${MAIN_LIB_DIR}/spells/Problem.cpp
-		${MAIN_LIB_DIR}/spells/ProxyCaster.cpp
-		${MAIN_LIB_DIR}/spells/TargetCondition.cpp
-		${MAIN_LIB_DIR}/spells/ViewSpellInt.cpp
-
-		${MAIN_LIB_DIR}/spells/effects/Catapult.cpp
-		${MAIN_LIB_DIR}/spells/effects/Clone.cpp
-		${MAIN_LIB_DIR}/spells/effects/Damage.cpp
-		${MAIN_LIB_DIR}/spells/effects/DemonSummon.cpp
-		${MAIN_LIB_DIR}/spells/effects/Dispel.cpp
-		${MAIN_LIB_DIR}/spells/effects/Effect.cpp
-		${MAIN_LIB_DIR}/spells/effects/Effects.cpp
-		${MAIN_LIB_DIR}/spells/effects/Heal.cpp
-		${MAIN_LIB_DIR}/spells/effects/LocationEffect.cpp
-		${MAIN_LIB_DIR}/spells/effects/Moat.cpp
-		${MAIN_LIB_DIR}/spells/effects/Obstacle.cpp
-		${MAIN_LIB_DIR}/spells/effects/Registry.cpp
-		${MAIN_LIB_DIR}/spells/effects/UnitEffect.cpp
-		${MAIN_LIB_DIR}/spells/effects/Summon.cpp
-		${MAIN_LIB_DIR}/spells/effects/Teleport.cpp
-		${MAIN_LIB_DIR}/spells/effects/Timed.cpp
-		${MAIN_LIB_DIR}/spells/effects/RemoveObstacle.cpp
-		${MAIN_LIB_DIR}/spells/effects/Sacrifice.cpp
-
-		${MAIN_LIB_DIR}/vstd/DateUtils.cpp
-		${MAIN_LIB_DIR}/vstd/StringUtils.cpp
-
-		${MAIN_LIB_DIR}/ArtifactUtils.cpp
-		${MAIN_LIB_DIR}/BasicTypes.cpp
-		${MAIN_LIB_DIR}/BattleFieldHandler.cpp
-		${MAIN_LIB_DIR}/CAndroidVMHelper.cpp
-		${MAIN_LIB_DIR}/CArtHandler.cpp
-		${MAIN_LIB_DIR}/CArtifactInstance.cpp
-		${MAIN_LIB_DIR}/CBonusTypeHandler.cpp
-		${MAIN_LIB_DIR}/CBuildingHandler.cpp
-		${MAIN_LIB_DIR}/CConfigHandler.cpp
-		${MAIN_LIB_DIR}/CConsoleHandler.cpp
-		${MAIN_LIB_DIR}/CCreatureHandler.cpp
-		${MAIN_LIB_DIR}/CCreatureSet.cpp
-		${MAIN_LIB_DIR}/CGameInfoCallback.cpp
-		${MAIN_LIB_DIR}/CGameInterface.cpp
-		${MAIN_LIB_DIR}/CGeneralTextHandler.cpp
-		${MAIN_LIB_DIR}/CHeroHandler.cpp
-		${MAIN_LIB_DIR}/CPlayerState.cpp
-		${MAIN_LIB_DIR}/CRandomGenerator.cpp
-		${MAIN_LIB_DIR}/CScriptingModule.cpp
-		${MAIN_LIB_DIR}/CSkillHandler.cpp
-		${MAIN_LIB_DIR}/CStack.cpp
-		${MAIN_LIB_DIR}/CThreadHelper.cpp
-		${MAIN_LIB_DIR}/CTownHandler.cpp
-		${MAIN_LIB_DIR}/GameSettings.cpp
-		${MAIN_LIB_DIR}/IGameCallback.cpp
-		${MAIN_LIB_DIR}/IHandlerBase.cpp
-		${MAIN_LIB_DIR}/JsonDetail.cpp
-		${MAIN_LIB_DIR}/JsonNode.cpp
-		${MAIN_LIB_DIR}/JsonRandom.cpp
-		${MAIN_LIB_DIR}/LoadProgress.cpp
-		${MAIN_LIB_DIR}/LogicalExpression.cpp
-		${MAIN_LIB_DIR}/MetaString.cpp
-		${MAIN_LIB_DIR}/ObstacleHandler.cpp
-		${MAIN_LIB_DIR}/StartInfo.cpp
-		${MAIN_LIB_DIR}/ResourceSet.cpp
-		${MAIN_LIB_DIR}/RiverHandler.cpp
-		${MAIN_LIB_DIR}/RoadHandler.cpp
-		${MAIN_LIB_DIR}/ScriptHandler.cpp
-		${MAIN_LIB_DIR}/TerrainHandler.cpp
-		${MAIN_LIB_DIR}/TextOperations.cpp
-		${MAIN_LIB_DIR}/TurnTimerInfo.cpp
-		${MAIN_LIB_DIR}/VCMIDirs.cpp
-		${MAIN_LIB_DIR}/VCMI_Lib.cpp
-	)
-
-    # Version.cpp is a generated file
-	if(ENABLE_GITVERSION)
-		list(APPEND lib_SRCS ${CMAKE_BINARY_DIR}/Version.cpp)
-		set_source_files_properties(${CMAKE_BINARY_DIR}/Version.cpp
-			PROPERTIES GENERATED TRUE
-		)
-    endif()
-
-	set(lib_HEADERS
-		${MAIN_LIB_DIR}/../include/vstd/CLoggerBase.h
-		${MAIN_LIB_DIR}/../Global.h
-		${MAIN_LIB_DIR}/../AUTHORS.h
-		${MAIN_LIB_DIR}/StdInc.h
-
-		${MAIN_LIB_DIR}/../include/vstd/ContainerUtils.h
-		${MAIN_LIB_DIR}/../include/vstd/RNG.h
-		${MAIN_LIB_DIR}/../include/vstd/DateUtils.h
-		${MAIN_LIB_DIR}/../include/vstd/StringUtils.h
-
-		${MAIN_LIB_DIR}/../include/vcmi/events/AdventureEvents.h
-		${MAIN_LIB_DIR}/../include/vcmi/events/ApplyDamage.h
-		${MAIN_LIB_DIR}/../include/vcmi/events/BattleEvents.h
-		${MAIN_LIB_DIR}/../include/vcmi/events/Event.h
-		${MAIN_LIB_DIR}/../include/vcmi/events/EventBus.h
-		${MAIN_LIB_DIR}/../include/vcmi/events/GameResumed.h
-		${MAIN_LIB_DIR}/../include/vcmi/events/GenericEvents.h
-		${MAIN_LIB_DIR}/../include/vcmi/events/ObjectVisitEnded.h
-		${MAIN_LIB_DIR}/../include/vcmi/events/ObjectVisitStarted.h
-		${MAIN_LIB_DIR}/../include/vcmi/events/PlayerGotTurn.h
-		${MAIN_LIB_DIR}/../include/vcmi/events/SubscriptionRegistry.h
-		${MAIN_LIB_DIR}/../include/vcmi/events/TurnStarted.h
-
-		${MAIN_LIB_DIR}/../include/vcmi/scripting/Service.h
-
-		${MAIN_LIB_DIR}/../include/vcmi/spells/Caster.h
-		${MAIN_LIB_DIR}/../include/vcmi/spells/Magic.h
-		${MAIN_LIB_DIR}/../include/vcmi/spells/Service.h
-		${MAIN_LIB_DIR}/../include/vcmi/spells/Spell.h
-
-		${MAIN_LIB_DIR}/../include/vcmi/Artifact.h
-		${MAIN_LIB_DIR}/../include/vcmi/ArtifactService.h
-		${MAIN_LIB_DIR}/../include/vcmi/Creature.h
-		${MAIN_LIB_DIR}/../include/vcmi/CreatureService.h
-		${MAIN_LIB_DIR}/../include/vcmi/Entity.h
-		${MAIN_LIB_DIR}/../include/vcmi/Environment.h
-		${MAIN_LIB_DIR}/../include/vcmi/Faction.h
-		${MAIN_LIB_DIR}/../include/vcmi/FactionService.h
-		${MAIN_LIB_DIR}/../include/vcmi/HeroClass.h
-		${MAIN_LIB_DIR}/../include/vcmi/HeroClassService.h
-		${MAIN_LIB_DIR}/../include/vcmi/HeroType.h
-		${MAIN_LIB_DIR}/../include/vcmi/HeroTypeService.h
-		${MAIN_LIB_DIR}/../include/vcmi/Metatype.h
-		${MAIN_LIB_DIR}/../include/vcmi/Player.h
-		${MAIN_LIB_DIR}/../include/vcmi/ServerCallback.h
-		${MAIN_LIB_DIR}/../include/vcmi/Services.h
-		${MAIN_LIB_DIR}/../include/vcmi/Skill.h
-		${MAIN_LIB_DIR}/../include/vcmi/SkillService.h
-		${MAIN_LIB_DIR}/../include/vcmi/Team.h
-
-		${MAIN_LIB_DIR}/battle/AccessibilityInfo.h
-		${MAIN_LIB_DIR}/battle/AutocombatPreferences.h
-		${MAIN_LIB_DIR}/battle/BattleAction.h
-		${MAIN_LIB_DIR}/battle/BattleAttackInfo.h
-		${MAIN_LIB_DIR}/battle/BattleHex.h
-		${MAIN_LIB_DIR}/battle/BattleInfo.h
-		${MAIN_LIB_DIR}/battle/BattleStateInfoForRetreat.h
-		${MAIN_LIB_DIR}/battle/BattleProxy.h
-		${MAIN_LIB_DIR}/battle/CBattleInfoCallback.h
-		${MAIN_LIB_DIR}/battle/CBattleInfoEssentials.h
-		${MAIN_LIB_DIR}/battle/CObstacleInstance.h
-		${MAIN_LIB_DIR}/battle/CPlayerBattleCallback.h
-		${MAIN_LIB_DIR}/battle/CUnitState.h
-		${MAIN_LIB_DIR}/battle/DamageCalculator.h
-		${MAIN_LIB_DIR}/battle/Destination.h
-		${MAIN_LIB_DIR}/battle/IBattleInfoCallback.h
-		${MAIN_LIB_DIR}/battle/IBattleState.h
-		${MAIN_LIB_DIR}/battle/IUnitInfo.h
-		${MAIN_LIB_DIR}/battle/PossiblePlayerBattleAction.h
-		${MAIN_LIB_DIR}/battle/ReachabilityInfo.h
-		${MAIN_LIB_DIR}/battle/SideInBattle.h
-		${MAIN_LIB_DIR}/battle/SiegeInfo.h
-		${MAIN_LIB_DIR}/battle/Unit.h
-
-		${MAIN_LIB_DIR}/bonuses/Bonus.h
-		${MAIN_LIB_DIR}/bonuses/BonusEnum.h
-		${MAIN_LIB_DIR}/bonuses/BonusList.h
-		${MAIN_LIB_DIR}/bonuses/BonusParams.h
-		${MAIN_LIB_DIR}/bonuses/BonusSelector.h
-		${MAIN_LIB_DIR}/bonuses/BonusCustomTypes.h
-		${MAIN_LIB_DIR}/bonuses/CBonusProxy.h
-		${MAIN_LIB_DIR}/bonuses/CBonusSystemNode.h
-		${MAIN_LIB_DIR}/bonuses/IBonusBearer.h
-		${MAIN_LIB_DIR}/bonuses/Limiters.h
-		${MAIN_LIB_DIR}/bonuses/Propagators.h
-		${MAIN_LIB_DIR}/bonuses/Updaters.h
-
-		${MAIN_LIB_DIR}/campaign/CampaignConstants.h
-		${MAIN_LIB_DIR}/campaign/CampaignHandler.h
-		${MAIN_LIB_DIR}/campaign/CampaignScenarioPrologEpilog.h
-		${MAIN_LIB_DIR}/campaign/CampaignState.h
-
-		${MAIN_LIB_DIR}/constants/EntityIdentifiers.h
-		${MAIN_LIB_DIR}/constants/Enumerations.h
-		${MAIN_LIB_DIR}/constants/IdentifierBase.h
-		${MAIN_LIB_DIR}/constants/VariantIdentifier.h
-		${MAIN_LIB_DIR}/constants/NumericConstants.h
-		${MAIN_LIB_DIR}/constants/StringConstants.h
-
-		${MAIN_LIB_DIR}/events/ApplyDamage.h
-		${MAIN_LIB_DIR}/events/GameResumed.h
-		${MAIN_LIB_DIR}/events/ObjectVisitEnded.h
-		${MAIN_LIB_DIR}/events/ObjectVisitStarted.h
-		${MAIN_LIB_DIR}/events/PlayerGotTurn.h
-		${MAIN_LIB_DIR}/events/TurnStarted.h
-
-		${MAIN_LIB_DIR}/filesystem/AdapterLoaders.h
-		${MAIN_LIB_DIR}/filesystem/CArchiveLoader.h
-		${MAIN_LIB_DIR}/filesystem/CBinaryReader.h
-		${MAIN_LIB_DIR}/filesystem/CCompressedStream.h
-		${MAIN_LIB_DIR}/filesystem/CFileInputStream.h
-		${MAIN_LIB_DIR}/filesystem/CFilesystemLoader.h
-		${MAIN_LIB_DIR}/filesystem/CInputOutputStream.h
-		${MAIN_LIB_DIR}/filesystem/CInputStream.h
-		${MAIN_LIB_DIR}/filesystem/CMemoryBuffer.h
-		${MAIN_LIB_DIR}/filesystem/CMemoryStream.h
-		${MAIN_LIB_DIR}/filesystem/COutputStream.h
-		${MAIN_LIB_DIR}/filesystem/CStream.h
-		${MAIN_LIB_DIR}/filesystem/CZipLoader.h
-		${MAIN_LIB_DIR}/filesystem/CZipSaver.h
-		${MAIN_LIB_DIR}/filesystem/FileInfo.h
-		${MAIN_LIB_DIR}/filesystem/Filesystem.h
-		${MAIN_LIB_DIR}/filesystem/ISimpleResourceLoader.h
-		${MAIN_LIB_DIR}/filesystem/MinizipExtensions.h
-		${MAIN_LIB_DIR}/filesystem/ResourcePath.h
-
-		${MAIN_LIB_DIR}/gameState/CGameState.h
-		${MAIN_LIB_DIR}/gameState/CGameStateCampaign.h
-		${MAIN_LIB_DIR}/gameState/EVictoryLossCheckResult.h
-		${MAIN_LIB_DIR}/gameState/InfoAboutArmy.h
-		${MAIN_LIB_DIR}/gameState/SThievesGuildInfo.h
-		${MAIN_LIB_DIR}/gameState/TavernHeroesPool.h
-		${MAIN_LIB_DIR}/gameState/TavernSlot.h
-		${MAIN_LIB_DIR}/gameState/QuestInfo.h
-
-		${MAIN_LIB_DIR}/logging/CBasicLogConfigurator.h
-		${MAIN_LIB_DIR}/logging/CLogger.h
-
-		${MAIN_LIB_DIR}/mapObjectConstructors/AObjectTypeHandler.h
-		${MAIN_LIB_DIR}/mapObjectConstructors/CBankInstanceConstructor.h
-		${MAIN_LIB_DIR}/mapObjectConstructors/CDefaultObjectTypeHandler.h
-		${MAIN_LIB_DIR}/mapObjectConstructors/CObjectClassesHandler.h
-		${MAIN_LIB_DIR}/mapObjectConstructors/CommonConstructors.h
-		${MAIN_LIB_DIR}/mapObjectConstructors/CRewardableConstructor.h
-		${MAIN_LIB_DIR}/mapObjectConstructors/DwellingInstanceConstructor.h
-		${MAIN_LIB_DIR}/mapObjectConstructors/HillFortInstanceConstructor.h
-		${MAIN_LIB_DIR}/mapObjectConstructors/IObjectInfo.h
-		${MAIN_LIB_DIR}/mapObjectConstructors/RandomMapInfo.h
-		${MAIN_LIB_DIR}/mapObjectConstructors/ShipyardInstanceConstructor.h
-		${MAIN_LIB_DIR}/mapObjectConstructors/SObjectSounds.h
-
-		${MAIN_LIB_DIR}/mapObjects/CArmedInstance.h
-		${MAIN_LIB_DIR}/mapObjects/CBank.h
-		${MAIN_LIB_DIR}/mapObjects/CGCreature.h
-		${MAIN_LIB_DIR}/mapObjects/CGDwelling.h
-		${MAIN_LIB_DIR}/mapObjects/CGHeroInstance.h
-		${MAIN_LIB_DIR}/mapObjects/CGMarket.h
-		${MAIN_LIB_DIR}/mapObjects/CGObjectInstance.h
-		${MAIN_LIB_DIR}/mapObjects/CGPandoraBox.h
-		${MAIN_LIB_DIR}/mapObjects/CGTownBuilding.h
-		${MAIN_LIB_DIR}/mapObjects/CGTownInstance.h
-		${MAIN_LIB_DIR}/mapObjects/CObjectHandler.h
-		${MAIN_LIB_DIR}/mapObjects/CQuest.h
-		${MAIN_LIB_DIR}/mapObjects/CRewardableObject.h
-		${MAIN_LIB_DIR}/mapObjects/IMarket.h
-		${MAIN_LIB_DIR}/mapObjects/IObjectInterface.h
-		${MAIN_LIB_DIR}/mapObjects/MapObjects.h
-		${MAIN_LIB_DIR}/mapObjects/MiscObjects.h
-		${MAIN_LIB_DIR}/mapObjects/ObjectTemplate.h
-
-		${MAIN_LIB_DIR}/mapping/CDrawRoadsOperation.h
-		${MAIN_LIB_DIR}/mapping/CMapDefines.h
-		${MAIN_LIB_DIR}/mapping/CMapEditManager.h
-		${MAIN_LIB_DIR}/mapping/CMapHeader.h
-		${MAIN_LIB_DIR}/mapping/CMap.h
-		${MAIN_LIB_DIR}/mapping/CMapInfo.h
-		${MAIN_LIB_DIR}/mapping/CMapOperation.h
-		${MAIN_LIB_DIR}/mapping/CMapService.h
-		${MAIN_LIB_DIR}/mapping/MapEditUtils.h
-		${MAIN_LIB_DIR}/mapping/MapIdentifiersH3M.h
-		${MAIN_LIB_DIR}/mapping/MapFeaturesH3M.h
-		${MAIN_LIB_DIR}/mapping/MapFormatH3M.h
-		${MAIN_LIB_DIR}/mapping/MapFormat.h
-		${MAIN_LIB_DIR}/mapping/MapReaderH3M.h
-		${MAIN_LIB_DIR}/mapping/MapFormatJson.h
-		${MAIN_LIB_DIR}/mapping/ObstacleProxy.h
-
-		${MAIN_LIB_DIR}/modding/ActiveModsInSaveList.h
-		${MAIN_LIB_DIR}/modding/CModHandler.h
-		${MAIN_LIB_DIR}/modding/CModInfo.h
-		${MAIN_LIB_DIR}/modding/CModVersion.h
-		${MAIN_LIB_DIR}/modding/ContentTypeHandler.h
-		${MAIN_LIB_DIR}/modding/IdentifierStorage.h
-		${MAIN_LIB_DIR}/modding/ModIncompatibility.h
-		${MAIN_LIB_DIR}/modding/ModScope.h
-		${MAIN_LIB_DIR}/modding/ModUtility.h
-		${MAIN_LIB_DIR}/modding/ModVerificationInfo.h
-
-		${MAIN_LIB_DIR}/network/NetworkConnection.h
-		${MAIN_LIB_DIR}/network/NetworkDefines.h
-		${MAIN_LIB_DIR}/network/NetworkHandler.h
-		${MAIN_LIB_DIR}/network/NetworkInterface.h
-		${MAIN_LIB_DIR}/network/NetworkServer.h
-
-		${MAIN_LIB_DIR}/networkPacks/ArtifactLocation.h
-		${MAIN_LIB_DIR}/networkPacks/BattleChanges.h
-		${MAIN_LIB_DIR}/networkPacks/Component.h
-		${MAIN_LIB_DIR}/networkPacks/EInfoWindowMode.h
-		${MAIN_LIB_DIR}/networkPacks/EntityChanges.h
-		${MAIN_LIB_DIR}/networkPacks/EOpenWindowMode.h
-		${MAIN_LIB_DIR}/networkPacks/NetPacksBase.h
-		${MAIN_LIB_DIR}/networkPacks/NetPackVisitor.h
-		${MAIN_LIB_DIR}/networkPacks/ObjProperty.h
-		${MAIN_LIB_DIR}/networkPacks/PacksForClient.h
-		${MAIN_LIB_DIR}/networkPacks/PacksForClientBattle.h
-		${MAIN_LIB_DIR}/networkPacks/PacksForLobby.h
-		${MAIN_LIB_DIR}/networkPacks/PacksForServer.h
-		${MAIN_LIB_DIR}/networkPacks/SetStackEffect.h
-		${MAIN_LIB_DIR}/networkPacks/StackLocation.h
-		${MAIN_LIB_DIR}/networkPacks/TradeItem.h
-
-		${MAIN_LIB_DIR}/pathfinder/INodeStorage.h
-		${MAIN_LIB_DIR}/pathfinder/CGPathNode.h
-		${MAIN_LIB_DIR}/pathfinder/CPathfinder.h
-		${MAIN_LIB_DIR}/pathfinder/NodeStorage.h
-		${MAIN_LIB_DIR}/pathfinder/PathfinderOptions.h
-		${MAIN_LIB_DIR}/pathfinder/PathfinderUtil.h
-		${MAIN_LIB_DIR}/pathfinder/PathfindingRules.h
-		${MAIN_LIB_DIR}/pathfinder/TurnInfo.h
-
-		${MAIN_LIB_DIR}/registerTypes/RegisterTypes.h
-		${MAIN_LIB_DIR}/registerTypes/RegisterTypesClientPacks.h
-		${MAIN_LIB_DIR}/registerTypes/RegisterTypesLobbyPacks.h
-		${MAIN_LIB_DIR}/registerTypes/RegisterTypesMapObjects.h
-		${MAIN_LIB_DIR}/registerTypes/RegisterTypesServerPacks.h
-
-		${MAIN_LIB_DIR}/rewardable/Configuration.h
-		${MAIN_LIB_DIR}/rewardable/Info.h
-		${MAIN_LIB_DIR}/rewardable/Interface.h
-		${MAIN_LIB_DIR}/rewardable/Limiter.h
-		${MAIN_LIB_DIR}/rewardable/Reward.h
-
-		${MAIN_LIB_DIR}/rmg/RmgArea.h
-		${MAIN_LIB_DIR}/rmg/RmgObject.h
-		${MAIN_LIB_DIR}/rmg/RmgPath.h
-		${MAIN_LIB_DIR}/rmg/CMapGenerator.h
-		${MAIN_LIB_DIR}/rmg/CMapGenOptions.h
-		${MAIN_LIB_DIR}/rmg/CRmgTemplate.h
-		${MAIN_LIB_DIR}/rmg/CRmgTemplateStorage.h
-		${MAIN_LIB_DIR}/rmg/CZonePlacer.h
-		${MAIN_LIB_DIR}/rmg/TileInfo.h
-		${MAIN_LIB_DIR}/rmg/Zone.h
-		${MAIN_LIB_DIR}/rmg/RmgMap.h
-		${MAIN_LIB_DIR}/rmg/float3.h
-		${MAIN_LIB_DIR}/rmg/Functions.h
-		${MAIN_LIB_DIR}/rmg/PenroseTiling.h
-		${MAIN_LIB_DIR}/rmg/modificators/Modificator.h
-		${MAIN_LIB_DIR}/rmg/modificators/ObjectManager.h
-		${MAIN_LIB_DIR}/rmg/modificators/ObjectDistributor.h
-		${MAIN_LIB_DIR}/rmg/modificators/RoadPlacer.h
-		${MAIN_LIB_DIR}/rmg/modificators/TreasurePlacer.h
-		${MAIN_LIB_DIR}/rmg/modificators/PrisonHeroPlacer.h
-		${MAIN_LIB_DIR}/rmg/modificators/QuestArtifactPlacer.h
-		${MAIN_LIB_DIR}/rmg/modificators/ConnectionsPlacer.h
-		${MAIN_LIB_DIR}/rmg/modificators/WaterAdopter.h
-		${MAIN_LIB_DIR}/rmg/modificators/MinePlacer.h
-		${MAIN_LIB_DIR}/rmg/modificators/TownPlacer.h
-		${MAIN_LIB_DIR}/rmg/modificators/WaterProxy.h
-		${MAIN_LIB_DIR}/rmg/modificators/WaterRoutes.h
-		${MAIN_LIB_DIR}/rmg/modificators/RockPlacer.h
-		${MAIN_LIB_DIR}/rmg/modificators/RockFiller.h
-		${MAIN_LIB_DIR}/rmg/modificators/ObstaclePlacer.h
-		${MAIN_LIB_DIR}/rmg/modificators/RiverPlacer.h
-		${MAIN_LIB_DIR}/rmg/modificators/TerrainPainter.h
-		${MAIN_LIB_DIR}/rmg/threadpool/BlockingQueue.h
-		${MAIN_LIB_DIR}/rmg/threadpool/ThreadPool.h
-		${MAIN_LIB_DIR}/rmg/threadpool/MapProxy.h
-
-		${MAIN_LIB_DIR}/serializer/BinaryDeserializer.h
-		${MAIN_LIB_DIR}/serializer/BinarySerializer.h
-		${MAIN_LIB_DIR}/serializer/CLoadFile.h
-		${MAIN_LIB_DIR}/serializer/CMemorySerializer.h
-		${MAIN_LIB_DIR}/serializer/Connection.h
-		${MAIN_LIB_DIR}/serializer/CSaveFile.h
-		${MAIN_LIB_DIR}/serializer/CSerializer.h
-		${MAIN_LIB_DIR}/serializer/CTypeList.h
-		${MAIN_LIB_DIR}/serializer/JsonDeserializer.h
-		${MAIN_LIB_DIR}/serializer/JsonSerializeFormat.h
-		${MAIN_LIB_DIR}/serializer/JsonSerializer.h
-		${MAIN_LIB_DIR}/serializer/JsonUpdater.h
-		${MAIN_LIB_DIR}/serializer/Cast.h
-		${MAIN_LIB_DIR}/serializer/ESerializationVersion.h
-
-		${MAIN_LIB_DIR}/spells/AbilityCaster.h
-		${MAIN_LIB_DIR}/spells/AdventureSpellMechanics.h
-		${MAIN_LIB_DIR}/spells/BattleSpellMechanics.h
-		${MAIN_LIB_DIR}/spells/BonusCaster.h
-		${MAIN_LIB_DIR}/spells/CSpellHandler.h
-		${MAIN_LIB_DIR}/spells/ExternalCaster.h
-		${MAIN_LIB_DIR}/spells/ISpellMechanics.h
-		${MAIN_LIB_DIR}/spells/ObstacleCasterProxy.h
-		${MAIN_LIB_DIR}/spells/Problem.h
-		${MAIN_LIB_DIR}/spells/ProxyCaster.h
-		${MAIN_LIB_DIR}/spells/TargetCondition.h
-		${MAIN_LIB_DIR}/spells/ViewSpellInt.h
-
-		${MAIN_LIB_DIR}/spells/effects/Catapult.h
-		${MAIN_LIB_DIR}/spells/effects/Clone.h
-		${MAIN_LIB_DIR}/spells/effects/Damage.h
-		${MAIN_LIB_DIR}/spells/effects/DemonSummon.h
-		${MAIN_LIB_DIR}/spells/effects/Dispel.h
-		${MAIN_LIB_DIR}/spells/effects/Effect.h
-		${MAIN_LIB_DIR}/spells/effects/Effects.h
-		${MAIN_LIB_DIR}/spells/effects/EffectsFwd.h
-		${MAIN_LIB_DIR}/spells/effects/Heal.h
-		${MAIN_LIB_DIR}/spells/effects/LocationEffect.h
-		${MAIN_LIB_DIR}/spells/effects/Obstacle.h
-		${MAIN_LIB_DIR}/spells/effects/Registry.h
-		${MAIN_LIB_DIR}/spells/effects/UnitEffect.h
-		${MAIN_LIB_DIR}/spells/effects/Summon.h
-		${MAIN_LIB_DIR}/spells/effects/Teleport.h
-		${MAIN_LIB_DIR}/spells/effects/Timed.h
-		${MAIN_LIB_DIR}/spells/effects/RemoveObstacle.h
-		${MAIN_LIB_DIR}/spells/effects/Sacrifice.h
-
-		${MAIN_LIB_DIR}/AI_Base.h
-		${MAIN_LIB_DIR}/ArtifactUtils.h
-		${MAIN_LIB_DIR}/BattleFieldHandler.h
-		${MAIN_LIB_DIR}/CAndroidVMHelper.h
-		${MAIN_LIB_DIR}/CArtHandler.h
-		${MAIN_LIB_DIR}/CArtifactInstance.h
-		${MAIN_LIB_DIR}/CBonusTypeHandler.h
-		${MAIN_LIB_DIR}/CBuildingHandler.h
-		${MAIN_LIB_DIR}/CConfigHandler.h
-		${MAIN_LIB_DIR}/CConsoleHandler.h
-		${MAIN_LIB_DIR}/CCreatureHandler.h
-		${MAIN_LIB_DIR}/CCreatureSet.h
-		${MAIN_LIB_DIR}/CGameInfoCallback.h
-		${MAIN_LIB_DIR}/CGameInterface.h
-		${MAIN_LIB_DIR}/CGeneralTextHandler.h
-		${MAIN_LIB_DIR}/CHeroHandler.h
-		${MAIN_LIB_DIR}/CondSh.h
-		${MAIN_LIB_DIR}/ConstTransitivePtr.h
-		${MAIN_LIB_DIR}/Color.h
-		${MAIN_LIB_DIR}/CPlayerState.h
-		${MAIN_LIB_DIR}/CRandomGenerator.h
-		${MAIN_LIB_DIR}/CScriptingModule.h
-		${MAIN_LIB_DIR}/CSkillHandler.h
-		${MAIN_LIB_DIR}/CSoundBase.h
-		${MAIN_LIB_DIR}/CStack.h
-		${MAIN_LIB_DIR}/CStopWatch.h
-		${MAIN_LIB_DIR}/CThreadHelper.h
-		${MAIN_LIB_DIR}/CTownHandler.h
-		${MAIN_LIB_DIR}/ExtraOptionsInfo.h
-		${MAIN_LIB_DIR}/FunctionList.h
-		${MAIN_LIB_DIR}/GameCallbackHolder.h
-		${MAIN_LIB_DIR}/GameConstants.h
-		${MAIN_LIB_DIR}/GameSettings.h
-		${MAIN_LIB_DIR}/IBonusTypeHandler.h
-		${MAIN_LIB_DIR}/IGameCallback.h
-		${MAIN_LIB_DIR}/IGameEventsReceiver.h
-		${MAIN_LIB_DIR}/IHandlerBase.h
-		${MAIN_LIB_DIR}/int3.h
-		${MAIN_LIB_DIR}/JsonDetail.h
-		${MAIN_LIB_DIR}/JsonNode.h
-		${MAIN_LIB_DIR}/JsonRandom.h
-		${MAIN_LIB_DIR}/Languages.h
-		${MAIN_LIB_DIR}/LoadProgress.h
-		${MAIN_LIB_DIR}/LogicalExpression.h
-		${MAIN_LIB_DIR}/MetaString.h
-		${MAIN_LIB_DIR}/ObstacleHandler.h
-		${MAIN_LIB_DIR}/Point.h
-		${MAIN_LIB_DIR}/Rect.h
-		${MAIN_LIB_DIR}/Rect.cpp
-		${MAIN_LIB_DIR}/ResourceSet.h
-		${MAIN_LIB_DIR}/RiverHandler.h
-		${MAIN_LIB_DIR}/RoadHandler.h
-		${MAIN_LIB_DIR}/ScriptHandler.h
-		${MAIN_LIB_DIR}/ScopeGuard.h
-		${MAIN_LIB_DIR}/StartInfo.h
-		${MAIN_LIB_DIR}/TerrainHandler.h
-		${MAIN_LIB_DIR}/TextOperations.h
-		${MAIN_LIB_DIR}/TurnTimerInfo.h
-		${MAIN_LIB_DIR}/UnlockGuard.h
-		${MAIN_LIB_DIR}/VCMIDirs.h
-		${MAIN_LIB_DIR}/vcmi_endian.h
-		${MAIN_LIB_DIR}/VCMI_Lib.h
-	)
-
-    assign_source_group(${lib_SRCS} ${lib_HEADERS})
-
-	add_library(${TARGET_NAME} ${LIBRARY_TYPE} ${lib_SRCS} ${lib_HEADERS})
-	set_target_properties(${TARGET_NAME} PROPERTIES COMPILE_DEFINITIONS "VCMI_DLL=1")
-	target_link_libraries(${TARGET_NAME} PUBLIC
-		minizip::minizip ZLIB::ZLIB
-		${SYSTEM_LIBS} Boost::boost Boost::thread Boost::filesystem Boost::program_options Boost::locale Boost::date_time
-	)
-    if(APPLE_IOS)
-		target_link_libraries(${TARGET_NAME} PUBLIC iOS_utils)
-	endif()
-
-	target_include_directories(${TARGET_NAME}
-		PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
-		PUBLIC ${MAIN_LIB_DIR}/..
-		PUBLIC ${MAIN_LIB_DIR}/../include
-		PUBLIC ${MAIN_LIB_DIR}
-	)
-
-    if(WIN32)
-		set_target_properties(${TARGET_NAME}
-			PROPERTIES
-			    OUTPUT_NAME "VCMI_lib"
-				PROJECT_LABEL "VCMI_lib"
-		)
-    endif()
-
-	vcmi_set_output_dir(${TARGET_NAME} "")
-
-	enable_pch(${TARGET_NAME})
-
-	# We want to deploy assets into build directory for easier debugging without install
-	if(COPY_CONFIG_ON_BUILD)
-		add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
-			COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/config
-			COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/Mods
-			COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake_modules/create_link.cmake ${MAIN_LIB_DIR}/../config ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/config
-			COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake_modules/create_link.cmake ${MAIN_LIB_DIR}/../Mods ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/Mods
-		)
-    endif()
-
-	# Update version before vcmi compiling
-	if(TARGET update_version)
-		add_dependencies(${TARGET_NAME} update_version)
-	endif()
-
-	if("${LIBRARY_TYPE}" STREQUAL SHARED)
-		install(TARGETS ${TARGET_NAME} RUNTIME DESTINATION ${LIB_DIR} LIBRARY DESTINATION ${LIB_DIR})
-	endif()
-	if(APPLE_IOS AND NOT USING_CONAN)
-		get_target_property(LINKED_LIBS ${TARGET_NAME} LINK_LIBRARIES)
-		foreach(LINKED_LIB IN LISTS LINKED_LIBS)
-			if(NOT TARGET ${LINKED_LIB})
-				if(LINKED_LIB MATCHES "\\${CMAKE_SHARED_LIBRARY_SUFFIX}$")
-					install(FILES ${LINKED_LIB} DESTINATION ${LIB_DIR})
-				endif()
-				continue()
-			endif()
-
-			get_target_property(LIB_TYPE ${LINKED_LIB} TYPE)
-			if(NOT LIB_TYPE STREQUAL "SHARED_LIBRARY")
-				continue()
-			endif()
-
-			get_target_property(_aliased ${LINKED_LIB} ALIASED_TARGET)
-			if(_aliased)
-				set(LINKED_LIB_REAL ${_aliased})
-			else()
-				set(LINKED_LIB_REAL ${LINKED_LIB})
-			endif()
-
-			get_target_property(_imported ${LINKED_LIB_REAL} IMPORTED)
-			if(_imported)
-				set(INSTALL_TYPE IMPORTED_RUNTIME_ARTIFACTS)
-				get_target_property(BOOST_DEPENDENCIES ${LINKED_LIB_REAL} INTERFACE_LINK_LIBRARIES)
-				foreach(BOOST_DEPENDENCY IN LISTS BOOST_DEPENDENCIES)
-					get_target_property(BOOST_DEPENDENCY_TYPE ${BOOST_DEPENDENCY} TYPE)
-					if(BOOST_DEPENDENCY_TYPE STREQUAL "SHARED_LIBRARY")
-						install(IMPORTED_RUNTIME_ARTIFACTS ${BOOST_DEPENDENCY} LIBRARY DESTINATION ${LIB_DIR})
-					endif()
-				endforeach()
-			else()
-				set(INSTALL_TYPE TARGETS)
-			endif()
-			install(${INSTALL_TYPE} ${LINKED_LIB_REAL} LIBRARY DESTINATION ${LIB_DIR})
-		endforeach()
-	endif()
-endmacro()

+ 1 - 1
config/schemas/settings.json

@@ -463,7 +463,7 @@
 					"properties" : {
 						"format" : {
 							"type" : "string",
-							"default" : "[%c] %l %n - %m"
+							"default" : "[%c] %l [%t] %n - %m"
 						}
 					}
 				},

+ 1 - 1
launcher/CMakeLists.txt

@@ -135,7 +135,7 @@ if (NOT APPLE_IOS AND NOT ANDROID)
 	target_link_libraries(vcmilauncher SDL2::SDL2)
 endif()
 
-target_link_libraries(vcmilauncher ${VCMI_LIB_TARGET} Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network)
+target_link_libraries(vcmilauncher vcmi Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network)
 target_include_directories(vcmilauncher
 	PUBLIC	${CMAKE_CURRENT_SOURCE_DIR}
 )

+ 766 - 9
lib/CMakeLists.txt

@@ -1,18 +1,775 @@
-if(ENABLE_STATIC_AI_LIBS)
-	add_main_lib(${VCMI_LIB_TARGET} STATIC)
-	target_compile_definitions(${VCMI_LIB_TARGET} PRIVATE STATIC_AI)
-	target_link_libraries(${VCMI_LIB_TARGET} PRIVATE
+set(lib_SRCS
+	StdInc.cpp
+
+	battle/AccessibilityInfo.cpp
+	battle/BattleAction.cpp
+	battle/BattleAttackInfo.cpp
+	battle/BattleHex.cpp
+	battle/BattleInfo.cpp
+	battle/BattleProxy.cpp
+	battle/BattleStateInfoForRetreat.cpp
+	battle/CBattleInfoCallback.cpp
+	battle/CBattleInfoEssentials.cpp
+	battle/CObstacleInstance.cpp
+	battle/CPlayerBattleCallback.cpp
+	battle/CUnitState.cpp
+	battle/DamageCalculator.cpp
+	battle/Destination.cpp
+	battle/IBattleState.cpp
+	battle/ReachabilityInfo.cpp
+	battle/SideInBattle.cpp
+	battle/SiegeInfo.cpp
+	battle/Unit.cpp
+
+	bonuses/Bonus.cpp
+	bonuses/BonusEnum.cpp
+	bonuses/BonusList.cpp
+	bonuses/BonusParams.cpp
+	bonuses/BonusSelector.cpp
+	bonuses/BonusCustomTypes.cpp
+	bonuses/CBonusProxy.cpp
+	bonuses/CBonusSystemNode.cpp
+	bonuses/IBonusBearer.cpp
+	bonuses/Limiters.cpp
+	bonuses/Propagators.cpp
+	bonuses/Updaters.cpp
+
+	campaign/CampaignHandler.cpp
+	campaign/CampaignState.cpp
+
+	constants/EntityIdentifiers.cpp
+
+	events/ApplyDamage.cpp
+	events/GameResumed.cpp
+	events/ObjectVisitEnded.cpp
+	events/ObjectVisitStarted.cpp
+	events/PlayerGotTurn.cpp
+	events/TurnStarted.cpp
+
+	filesystem/AdapterLoaders.cpp
+	filesystem/CArchiveLoader.cpp
+	filesystem/CBinaryReader.cpp
+	filesystem/CCompressedStream.cpp
+	filesystem/CFileInputStream.cpp
+	filesystem/CFilesystemLoader.cpp
+	filesystem/CMemoryBuffer.cpp
+	filesystem/CMemoryStream.cpp
+	filesystem/CZipLoader.cpp
+	filesystem/CZipSaver.cpp
+	filesystem/FileInfo.cpp
+	filesystem/Filesystem.cpp
+	filesystem/MinizipExtensions.cpp
+	filesystem/ResourcePath.cpp
+
+	gameState/CGameState.cpp
+	gameState/CGameStateCampaign.cpp
+	gameState/InfoAboutArmy.cpp
+	gameState/TavernHeroesPool.cpp
+
+	logging/CBasicLogConfigurator.cpp
+	logging/CLogger.cpp
+
+	mapObjectConstructors/AObjectTypeHandler.cpp
+	mapObjectConstructors/CBankInstanceConstructor.cpp
+	mapObjectConstructors/CObjectClassesHandler.cpp
+	mapObjectConstructors/CommonConstructors.cpp
+	mapObjectConstructors/CRewardableConstructor.cpp
+	mapObjectConstructors/DwellingInstanceConstructor.cpp
+	mapObjectConstructors/HillFortInstanceConstructor.cpp
+	mapObjectConstructors/ShipyardInstanceConstructor.cpp
+
+	mapObjects/CArmedInstance.cpp
+	mapObjects/CBank.cpp
+	mapObjects/CGCreature.cpp
+	mapObjects/CGDwelling.cpp
+	mapObjects/CGHeroInstance.cpp
+	mapObjects/CGMarket.cpp
+	mapObjects/CGObjectInstance.cpp
+	mapObjects/CGPandoraBox.cpp
+	mapObjects/CGTownBuilding.cpp
+	mapObjects/CGTownInstance.cpp
+	mapObjects/CObjectHandler.cpp
+	mapObjects/CQuest.cpp
+	mapObjects/CRewardableObject.cpp
+	mapObjects/IMarket.cpp
+	mapObjects/IObjectInterface.cpp
+	mapObjects/MiscObjects.cpp
+	mapObjects/ObjectTemplate.cpp
+
+	mapping/CDrawRoadsOperation.cpp
+	mapping/CMap.cpp
+	mapping/CMapHeader.cpp
+	mapping/CMapEditManager.cpp
+	mapping/CMapInfo.cpp
+	mapping/CMapOperation.cpp
+	mapping/CMapService.cpp
+	mapping/MapEditUtils.cpp
+	mapping/MapIdentifiersH3M.cpp
+	mapping/MapFeaturesH3M.cpp
+	mapping/MapFormatH3M.cpp
+	mapping/MapReaderH3M.cpp
+	mapping/MapFormatJson.cpp
+	mapping/ObstacleProxy.cpp
+
+	modding/ActiveModsInSaveList.cpp
+	modding/CModHandler.cpp
+	modding/CModInfo.cpp
+	modding/CModVersion.cpp
+	modding/ContentTypeHandler.cpp
+	modding/IdentifierStorage.cpp
+	modding/ModUtility.cpp
+
+	network/NetworkConnection.cpp
+	network/NetworkHandler.cpp
+	network/NetworkServer.cpp
+
+	networkPacks/NetPacksLib.cpp
+
+	pathfinder/CGPathNode.cpp
+	pathfinder/CPathfinder.cpp
+	pathfinder/NodeStorage.cpp
+	pathfinder/PathfinderOptions.cpp
+	pathfinder/PathfindingRules.cpp
+	pathfinder/TurnInfo.cpp
+
+	rewardable/Configuration.cpp
+	rewardable/Info.cpp
+	rewardable/Interface.cpp
+	rewardable/Limiter.cpp
+	rewardable/Reward.cpp
+
+	rmg/RmgArea.cpp
+	rmg/RmgObject.cpp
+	rmg/RmgPath.cpp
+	rmg/CMapGenerator.cpp
+	rmg/CMapGenOptions.cpp
+	rmg/CRmgTemplate.cpp
+	rmg/CRmgTemplateStorage.cpp
+	rmg/CZonePlacer.cpp
+	rmg/TileInfo.cpp
+	rmg/Zone.cpp
+	rmg/Functions.cpp
+	rmg/RmgMap.cpp
+	rmg/PenroseTiling.cpp
+	rmg/modificators/Modificator.cpp
+	rmg/modificators/ObjectManager.cpp
+	rmg/modificators/ObjectDistributor.cpp
+	rmg/modificators/RoadPlacer.cpp
+	rmg/modificators/TreasurePlacer.cpp
+	rmg/modificators/PrisonHeroPlacer.cpp
+	rmg/modificators/QuestArtifactPlacer.cpp
+	rmg/modificators/ConnectionsPlacer.cpp
+	rmg/modificators/WaterAdopter.cpp
+	rmg/modificators/MinePlacer.cpp
+	rmg/modificators/TownPlacer.cpp
+	rmg/modificators/WaterProxy.cpp
+	rmg/modificators/WaterRoutes.cpp
+	rmg/modificators/RockPlacer.cpp
+	rmg/modificators/RockFiller.cpp
+	rmg/modificators/ObstaclePlacer.cpp
+	rmg/modificators/RiverPlacer.cpp
+	rmg/modificators/TerrainPainter.cpp
+	rmg/threadpool/MapProxy.cpp
+
+	serializer/BinaryDeserializer.cpp
+	serializer/BinarySerializer.cpp
+	serializer/CLoadFile.cpp
+	serializer/CMemorySerializer.cpp
+	serializer/Connection.cpp
+	serializer/CSaveFile.cpp
+	serializer/CSerializer.cpp
+	serializer/CTypeList.cpp
+	serializer/JsonDeserializer.cpp
+	serializer/JsonSerializeFormat.cpp
+	serializer/JsonSerializer.cpp
+	serializer/JsonUpdater.cpp
+
+	spells/AbilityCaster.cpp
+	spells/AdventureSpellMechanics.cpp
+	spells/BattleSpellMechanics.cpp
+	spells/BonusCaster.cpp
+	spells/CSpellHandler.cpp
+	spells/ExternalCaster.cpp
+	spells/ISpellMechanics.cpp
+	spells/ObstacleCasterProxy.cpp
+	spells/Problem.cpp
+	spells/ProxyCaster.cpp
+	spells/TargetCondition.cpp
+	spells/ViewSpellInt.cpp
+
+	spells/effects/Catapult.cpp
+	spells/effects/Clone.cpp
+	spells/effects/Damage.cpp
+	spells/effects/DemonSummon.cpp
+	spells/effects/Dispel.cpp
+	spells/effects/Effect.cpp
+	spells/effects/Effects.cpp
+	spells/effects/Heal.cpp
+	spells/effects/LocationEffect.cpp
+	spells/effects/Moat.cpp
+	spells/effects/Obstacle.cpp
+	spells/effects/Registry.cpp
+	spells/effects/UnitEffect.cpp
+	spells/effects/Summon.cpp
+	spells/effects/Teleport.cpp
+	spells/effects/Timed.cpp
+	spells/effects/RemoveObstacle.cpp
+	spells/effects/Sacrifice.cpp
+
+	vstd/DateUtils.cpp
+	vstd/StringUtils.cpp
+
+	ArtifactUtils.cpp
+	BasicTypes.cpp
+	BattleFieldHandler.cpp
+	CAndroidVMHelper.cpp
+	CArtHandler.cpp
+	CArtifactInstance.cpp
+	CBonusTypeHandler.cpp
+	CBuildingHandler.cpp
+	CConfigHandler.cpp
+	CConsoleHandler.cpp
+	CCreatureHandler.cpp
+	CCreatureSet.cpp
+	CGameInfoCallback.cpp
+	CGameInterface.cpp
+	CGeneralTextHandler.cpp
+	CHeroHandler.cpp
+	CPlayerState.cpp
+	CRandomGenerator.cpp
+	CScriptingModule.cpp
+	CSkillHandler.cpp
+	CStack.cpp
+	CThreadHelper.cpp
+	CTownHandler.cpp
+	GameSettings.cpp
+	IGameCallback.cpp
+	IHandlerBase.cpp
+	JsonDetail.cpp
+	JsonNode.cpp
+	JsonRandom.cpp
+	LoadProgress.cpp
+	LogicalExpression.cpp
+	MetaString.cpp
+	ObstacleHandler.cpp
+	StartInfo.cpp
+	ResourceSet.cpp
+	RiverHandler.cpp
+	RoadHandler.cpp
+	ScriptHandler.cpp
+	TerrainHandler.cpp
+	TextOperations.cpp
+	TurnTimerInfo.cpp
+	VCMIDirs.cpp
+	VCMI_Lib.cpp
+)
+
+# Version.cpp is a generated file
+if(ENABLE_GITVERSION)
+	list(APPEND lib_SRCS ${CMAKE_BINARY_DIR}/Version.cpp)
+	set_source_files_properties(${CMAKE_BINARY_DIR}/Version.cpp
+		PROPERTIES GENERATED TRUE
+	)
+endif()
+
+set(lib_HEADERS
+	../include/vstd/CLoggerBase.h
+	../Global.h
+	../AUTHORS.h
+	StdInc.h
+
+	../include/vstd/ContainerUtils.h
+	../include/vstd/RNG.h
+	../include/vstd/DateUtils.h
+	../include/vstd/StringUtils.h
+
+	../include/vcmi/events/AdventureEvents.h
+	../include/vcmi/events/ApplyDamage.h
+	../include/vcmi/events/BattleEvents.h
+	../include/vcmi/events/Event.h
+	../include/vcmi/events/EventBus.h
+	../include/vcmi/events/GameResumed.h
+	../include/vcmi/events/GenericEvents.h
+	../include/vcmi/events/ObjectVisitEnded.h
+	../include/vcmi/events/ObjectVisitStarted.h
+	../include/vcmi/events/PlayerGotTurn.h
+	../include/vcmi/events/SubscriptionRegistry.h
+	../include/vcmi/events/TurnStarted.h
+
+	../include/vcmi/scripting/Service.h
+
+	../include/vcmi/spells/Caster.h
+	../include/vcmi/spells/Magic.h
+	../include/vcmi/spells/Service.h
+	../include/vcmi/spells/Spell.h
+
+	../include/vcmi/Artifact.h
+	../include/vcmi/ArtifactService.h
+	../include/vcmi/Creature.h
+	../include/vcmi/CreatureService.h
+	../include/vcmi/Entity.h
+	../include/vcmi/Environment.h
+	../include/vcmi/Faction.h
+	../include/vcmi/FactionService.h
+	../include/vcmi/HeroClass.h
+	../include/vcmi/HeroClassService.h
+	../include/vcmi/HeroType.h
+	../include/vcmi/HeroTypeService.h
+	../include/vcmi/Metatype.h
+	../include/vcmi/Player.h
+	../include/vcmi/ServerCallback.h
+	../include/vcmi/Services.h
+	../include/vcmi/Skill.h
+	../include/vcmi/SkillService.h
+	../include/vcmi/Team.h
+
+	battle/AccessibilityInfo.h
+	battle/AutocombatPreferences.h
+	battle/BattleAction.h
+	battle/BattleAttackInfo.h
+	battle/BattleHex.h
+	battle/BattleInfo.h
+	battle/BattleStateInfoForRetreat.h
+	battle/BattleProxy.h
+	battle/CBattleInfoCallback.h
+	battle/CBattleInfoEssentials.h
+	battle/CObstacleInstance.h
+	battle/CPlayerBattleCallback.h
+	battle/CUnitState.h
+	battle/DamageCalculator.h
+	battle/Destination.h
+	battle/IBattleInfoCallback.h
+	battle/IBattleState.h
+	battle/IUnitInfo.h
+	battle/PossiblePlayerBattleAction.h
+	battle/ReachabilityInfo.h
+	battle/SideInBattle.h
+	battle/SiegeInfo.h
+	battle/Unit.h
+
+	bonuses/Bonus.h
+	bonuses/BonusEnum.h
+	bonuses/BonusList.h
+	bonuses/BonusParams.h
+	bonuses/BonusSelector.h
+	bonuses/BonusCustomTypes.h
+	bonuses/CBonusProxy.h
+	bonuses/CBonusSystemNode.h
+	bonuses/IBonusBearer.h
+	bonuses/Limiters.h
+	bonuses/Propagators.h
+	bonuses/Updaters.h
+
+	campaign/CampaignConstants.h
+	campaign/CampaignHandler.h
+	campaign/CampaignScenarioPrologEpilog.h
+	campaign/CampaignState.h
+
+	constants/EntityIdentifiers.h
+	constants/Enumerations.h
+	constants/IdentifierBase.h
+	constants/VariantIdentifier.h
+	constants/NumericConstants.h
+	constants/StringConstants.h
+
+	events/ApplyDamage.h
+	events/GameResumed.h
+	events/ObjectVisitEnded.h
+	events/ObjectVisitStarted.h
+	events/PlayerGotTurn.h
+	events/TurnStarted.h
+
+	filesystem/AdapterLoaders.h
+	filesystem/CArchiveLoader.h
+	filesystem/CBinaryReader.h
+	filesystem/CCompressedStream.h
+	filesystem/CFileInputStream.h
+	filesystem/CFilesystemLoader.h
+	filesystem/CInputOutputStream.h
+	filesystem/CInputStream.h
+	filesystem/CMemoryBuffer.h
+	filesystem/CMemoryStream.h
+	filesystem/COutputStream.h
+	filesystem/CStream.h
+	filesystem/CZipLoader.h
+	filesystem/CZipSaver.h
+	filesystem/FileInfo.h
+	filesystem/Filesystem.h
+	filesystem/ISimpleResourceLoader.h
+	filesystem/MinizipExtensions.h
+	filesystem/ResourcePath.h
+
+	gameState/CGameState.h
+	gameState/CGameStateCampaign.h
+	gameState/EVictoryLossCheckResult.h
+	gameState/InfoAboutArmy.h
+	gameState/SThievesGuildInfo.h
+	gameState/TavernHeroesPool.h
+	gameState/TavernSlot.h
+	gameState/QuestInfo.h
+
+	logging/CBasicLogConfigurator.h
+	logging/CLogger.h
+
+	mapObjectConstructors/AObjectTypeHandler.h
+	mapObjectConstructors/CBankInstanceConstructor.h
+	mapObjectConstructors/CDefaultObjectTypeHandler.h
+	mapObjectConstructors/CObjectClassesHandler.h
+	mapObjectConstructors/CommonConstructors.h
+	mapObjectConstructors/CRewardableConstructor.h
+	mapObjectConstructors/DwellingInstanceConstructor.h
+	mapObjectConstructors/HillFortInstanceConstructor.h
+	mapObjectConstructors/IObjectInfo.h
+	mapObjectConstructors/RandomMapInfo.h
+	mapObjectConstructors/ShipyardInstanceConstructor.h
+	mapObjectConstructors/SObjectSounds.h
+
+	mapObjects/CArmedInstance.h
+	mapObjects/CBank.h
+	mapObjects/CGCreature.h
+	mapObjects/CGDwelling.h
+	mapObjects/CGHeroInstance.h
+	mapObjects/CGMarket.h
+	mapObjects/CGObjectInstance.h
+	mapObjects/CGPandoraBox.h
+	mapObjects/CGTownBuilding.h
+	mapObjects/CGTownInstance.h
+	mapObjects/CObjectHandler.h
+	mapObjects/CQuest.h
+	mapObjects/CRewardableObject.h
+	mapObjects/IMarket.h
+	mapObjects/IObjectInterface.h
+	mapObjects/MapObjects.h
+	mapObjects/MiscObjects.h
+	mapObjects/ObjectTemplate.h
+
+	mapping/CDrawRoadsOperation.h
+	mapping/CMapDefines.h
+	mapping/CMapEditManager.h
+	mapping/CMapHeader.h
+	mapping/CMap.h
+	mapping/CMapInfo.h
+	mapping/CMapOperation.h
+	mapping/CMapService.h
+	mapping/MapEditUtils.h
+	mapping/MapIdentifiersH3M.h
+	mapping/MapFeaturesH3M.h
+	mapping/MapFormatH3M.h
+	mapping/MapFormat.h
+	mapping/MapReaderH3M.h
+	mapping/MapFormatJson.h
+	mapping/ObstacleProxy.h
+
+	modding/ActiveModsInSaveList.h
+	modding/CModHandler.h
+	modding/CModInfo.h
+	modding/CModVersion.h
+	modding/ContentTypeHandler.h
+	modding/IdentifierStorage.h
+	modding/ModIncompatibility.h
+	modding/ModScope.h
+	modding/ModUtility.h
+	modding/ModVerificationInfo.h
+
+	network/NetworkConnection.h
+	network/NetworkDefines.h
+	network/NetworkHandler.h
+	network/NetworkInterface.h
+	network/NetworkServer.h
+
+	networkPacks/ArtifactLocation.h
+	networkPacks/BattleChanges.h
+	networkPacks/Component.h
+	networkPacks/EInfoWindowMode.h
+	networkPacks/EntityChanges.h
+	networkPacks/EOpenWindowMode.h
+	networkPacks/NetPacksBase.h
+	networkPacks/NetPackVisitor.h
+	networkPacks/ObjProperty.h
+	networkPacks/PacksForClient.h
+	networkPacks/PacksForClientBattle.h
+	networkPacks/PacksForLobby.h
+	networkPacks/PacksForServer.h
+	networkPacks/SetStackEffect.h
+	networkPacks/StackLocation.h
+	networkPacks/TradeItem.h
+
+	pathfinder/INodeStorage.h
+	pathfinder/CGPathNode.h
+	pathfinder/CPathfinder.h
+	pathfinder/NodeStorage.h
+	pathfinder/PathfinderOptions.h
+	pathfinder/PathfinderUtil.h
+	pathfinder/PathfindingRules.h
+	pathfinder/TurnInfo.h
+
+	registerTypes/RegisterTypes.h
+	registerTypes/RegisterTypesClientPacks.h
+	registerTypes/RegisterTypesLobbyPacks.h
+	registerTypes/RegisterTypesMapObjects.h
+	registerTypes/RegisterTypesServerPacks.h
+
+	rewardable/Configuration.h
+	rewardable/Info.h
+	rewardable/Interface.h
+	rewardable/Limiter.h
+	rewardable/Reward.h
+
+	rmg/RmgArea.h
+	rmg/RmgObject.h
+	rmg/RmgPath.h
+	rmg/CMapGenerator.h
+	rmg/CMapGenOptions.h
+	rmg/CRmgTemplate.h
+	rmg/CRmgTemplateStorage.h
+	rmg/CZonePlacer.h
+	rmg/TileInfo.h
+	rmg/Zone.h
+	rmg/RmgMap.h
+	rmg/float3.h
+	rmg/Functions.h
+	rmg/PenroseTiling.h
+	rmg/modificators/Modificator.h
+	rmg/modificators/ObjectManager.h
+	rmg/modificators/ObjectDistributor.h
+	rmg/modificators/RoadPlacer.h
+	rmg/modificators/TreasurePlacer.h
+	rmg/modificators/PrisonHeroPlacer.h
+	rmg/modificators/QuestArtifactPlacer.h
+	rmg/modificators/ConnectionsPlacer.h
+	rmg/modificators/WaterAdopter.h
+	rmg/modificators/MinePlacer.h
+	rmg/modificators/TownPlacer.h
+	rmg/modificators/WaterProxy.h
+	rmg/modificators/WaterRoutes.h
+	rmg/modificators/RockPlacer.h
+	rmg/modificators/RockFiller.h
+	rmg/modificators/ObstaclePlacer.h
+	rmg/modificators/RiverPlacer.h
+	rmg/modificators/TerrainPainter.h
+	rmg/threadpool/BlockingQueue.h
+	rmg/threadpool/ThreadPool.h
+	rmg/threadpool/MapProxy.h
+
+	serializer/BinaryDeserializer.h
+	serializer/BinarySerializer.h
+	serializer/CLoadFile.h
+	serializer/CMemorySerializer.h
+	serializer/Connection.h
+	serializer/CSaveFile.h
+	serializer/CSerializer.h
+	serializer/CTypeList.h
+	serializer/JsonDeserializer.h
+	serializer/JsonSerializeFormat.h
+	serializer/JsonSerializer.h
+	serializer/JsonUpdater.h
+	serializer/Cast.h
+	serializer/ESerializationVersion.h
+
+	spells/AbilityCaster.h
+	spells/AdventureSpellMechanics.h
+	spells/BattleSpellMechanics.h
+	spells/BonusCaster.h
+	spells/CSpellHandler.h
+	spells/ExternalCaster.h
+	spells/ISpellMechanics.h
+	spells/ObstacleCasterProxy.h
+	spells/Problem.h
+	spells/ProxyCaster.h
+	spells/TargetCondition.h
+	spells/ViewSpellInt.h
+
+	spells/effects/Catapult.h
+	spells/effects/Clone.h
+	spells/effects/Damage.h
+	spells/effects/DemonSummon.h
+	spells/effects/Dispel.h
+	spells/effects/Effect.h
+	spells/effects/Effects.h
+	spells/effects/EffectsFwd.h
+	spells/effects/Heal.h
+	spells/effects/LocationEffect.h
+	spells/effects/Obstacle.h
+	spells/effects/Registry.h
+	spells/effects/UnitEffect.h
+	spells/effects/Summon.h
+	spells/effects/Teleport.h
+	spells/effects/Timed.h
+	spells/effects/RemoveObstacle.h
+	spells/effects/Sacrifice.h
+
+	AI_Base.h
+	ArtifactUtils.h
+	BattleFieldHandler.h
+	CAndroidVMHelper.h
+	CArtHandler.h
+	CArtifactInstance.h
+	CBonusTypeHandler.h
+	CBuildingHandler.h
+	CConfigHandler.h
+	CConsoleHandler.h
+	CCreatureHandler.h
+	CCreatureSet.h
+	CGameInfoCallback.h
+	CGameInterface.h
+	CGeneralTextHandler.h
+	CHeroHandler.h
+	CondSh.h
+	ConstTransitivePtr.h
+	Color.h
+	CPlayerState.h
+	CRandomGenerator.h
+	CScriptingModule.h
+	CSkillHandler.h
+	CSoundBase.h
+	CStack.h
+	CStopWatch.h
+	CThreadHelper.h
+	CTownHandler.h
+	ExtraOptionsInfo.h
+	FunctionList.h
+	GameCallbackHolder.h
+	GameConstants.h
+	GameSettings.h
+	IBonusTypeHandler.h
+	IGameCallback.h
+	IGameEventsReceiver.h
+	IHandlerBase.h
+	int3.h
+	JsonDetail.h
+	JsonNode.h
+	JsonRandom.h
+	Languages.h
+	LoadProgress.h
+	LogicalExpression.h
+	MetaString.h
+	ObstacleHandler.h
+	Point.h
+	Rect.h
+	Rect.cpp
+	ResourceSet.h
+	RiverHandler.h
+	RoadHandler.h
+	ScriptHandler.h
+	ScopeGuard.h
+	StartInfo.h
+	TerrainHandler.h
+	TextOperations.h
+	TurnTimerInfo.h
+	UnlockGuard.h
+	VCMIDirs.h
+	vcmi_endian.h
+	VCMI_Lib.h
+)
+
+assign_source_group(${lib_SRCS} ${lib_HEADERS})
+
+if(ENABLE_STATIC_LIBS)
+	add_library(vcmi STATIC ${lib_SRCS} ${lib_HEADERS})
+else()
+	add_library(vcmi SHARED ${lib_SRCS} ${lib_HEADERS})
+endif()
+set_target_properties(vcmi PROPERTIES COMPILE_DEFINITIONS "VCMI_DLL=1")
+target_link_libraries(vcmi PUBLIC
+	minizip::minizip ZLIB::ZLIB
+	${SYSTEM_LIBS} Boost::boost Boost::thread Boost::filesystem Boost::program_options Boost::locale Boost::date_time
+)
+
+if(ENABLE_STATIC_LIBS)
+	target_compile_definitions(vcmi PRIVATE STATIC_AI)
+	target_link_libraries(vcmi PRIVATE
 		BattleAI
 		EmptyAI
 		StupidAI
 		VCAI
 	)
 	if(ENABLE_NULLKILLER_AI)
-		target_link_libraries(${VCMI_LIB_TARGET} PRIVATE Nullkiller)
+		target_link_libraries(vcmi PRIVATE Nullkiller)
 	endif()
-else()
-	add_main_lib(${VCMI_LIB_TARGET} SHARED)
 endif()
-if(ENABLE_SINGLE_APP_BUILD)
-	target_compile_definitions(${VCMI_LIB_TARGET} PUBLIC VCMI_LIB_NAMESPACE=LIB_CLIENT)
+
+# 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 PUBLIC VCMI_LIB_NAMESPACE=VCMI)
+endif()
+
+if(APPLE_IOS)
+	target_link_libraries(vcmi PUBLIC iOS_utils)
+endif()
+
+target_include_directories(vcmi
+	PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
+	PUBLIC ${CMAKE_SOURCE_DIR}
+	PUBLIC ${CMAKE_SOURCE_DIR}/include
+)
+
+if(WIN32)
+	set_target_properties(vcmi
+		PROPERTIES
+			OUTPUT_NAME "VCMI_lib"
+			PROJECT_LABEL "VCMI_lib"
+	)
+endif()
+
+vcmi_set_output_dir(vcmi "")
+
+enable_pch(vcmi)
+
+# We want to deploy assets into build directory for easier debugging without install
+if(COPY_CONFIG_ON_BUILD)
+	add_custom_command(TARGET vcmi POST_BUILD
+		COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/config
+		COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/Mods
+		COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake_modules/create_link.cmake ${CMAKE_SOURCE_DIR}/config ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/config
+		COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake_modules/create_link.cmake ${CMAKE_SOURCE_DIR}/Mods ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/Mods
+	)
+endif()
+
+# Update version before vcmi compiling
+if(TARGET update_version)
+	add_dependencies(vcmi update_version)
+endif()
+
+if(NOT ENABLE_STATIC_LIBS)
+	install(TARGETS vcmi RUNTIME DESTINATION ${LIB_DIR} LIBRARY DESTINATION ${LIB_DIR})
 endif()
+
+if(APPLE_IOS AND NOT USING_CONAN)
+	get_target_property(LINKED_LIBS vcmi LINK_LIBRARIES)
+	foreach(LINKED_LIB IN LISTS LINKED_LIBS)
+		if(NOT TARGET ${LINKED_LIB})
+			if(LINKED_LIB MATCHES "\\${CMAKE_SHARED_LIBRARY_SUFFIX}$")
+				install(FILES ${LINKED_LIB} DESTINATION ${LIB_DIR})
+			endif()
+			continue()
+		endif()
+
+		get_target_property(LIB_TYPE ${LINKED_LIB} TYPE)
+		if(NOT LIB_TYPE STREQUAL "SHARED_LIBRARY")
+			continue()
+		endif()
+
+		get_target_property(_aliased ${LINKED_LIB} ALIASED_TARGET)
+		if(_aliased)
+			set(LINKED_LIB_REAL ${_aliased})
+		else()
+			set(LINKED_LIB_REAL ${LINKED_LIB})
+		endif()
+
+		get_target_property(_imported ${LINKED_LIB_REAL} IMPORTED)
+		if(_imported)
+			set(INSTALL_TYPE IMPORTED_RUNTIME_ARTIFACTS)
+			get_target_property(BOOST_DEPENDENCIES ${LINKED_LIB_REAL} INTERFACE_LINK_LIBRARIES)
+			foreach(BOOST_DEPENDENCY IN LISTS BOOST_DEPENDENCIES)
+				get_target_property(BOOST_DEPENDENCY_TYPE ${BOOST_DEPENDENCY} TYPE)
+				if(BOOST_DEPENDENCY_TYPE STREQUAL "SHARED_LIBRARY")
+					install(IMPORTED_RUNTIME_ARTIFACTS ${BOOST_DEPENDENCY} LIBRARY DESTINATION ${LIB_DIR})
+				endif()
+			endforeach()
+		else()
+			set(INSTALL_TYPE TARGETS)
+		endif()
+		install(${INSTALL_TYPE} ${LINKED_LIB_REAL} LIBRARY DESTINATION ${LIB_DIR})
+	endforeach()
+endif()

+ 19 - 4
lib/CThreadHelper.cpp

@@ -55,10 +55,25 @@ void CThreadHelper::processTasks()
 	}
 }
 
-// set name for this thread.
-// NOTE: on *nix string will be trimmed to 16 symbols
+static thread_local std::string threadNameForLogging;
+
+std::string getThreadName()
+{
+	if (!threadNameForLogging.empty())
+		return threadNameForLogging;
+
+	return boost::lexical_cast<std::string>(boost::this_thread::get_id());
+}
+
+void setThreadNameLoggingOnly(const std::string &name)
+{
+	threadNameForLogging = name;
+}
+
 void setThreadName(const std::string &name)
 {
+	threadNameForLogging = name;
+
 #ifdef VCMI_WINDOWS
 #ifndef __GNUC__
 	//follows http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
@@ -90,12 +105,12 @@ void setThreadName(const std::string &name)
 //not supported
 #endif
 
-#elif defined(__linux__)
-	prctl(PR_SET_NAME, name.c_str(), 0, 0, 0);
 #elif defined(VCMI_APPLE)
 	pthread_setname_np(name.c_str());
 #elif defined(VCMI_HAIKU)
 	rename_thread(find_thread(NULL), name.c_str());
+#elif defined(VCMI_UNIX)
+	prctl(PR_SET_NAME, name.c_str(), 0, 0, 0);
 #endif
 }
 

+ 8 - 1
lib/CThreadHelper.h

@@ -85,7 +85,14 @@ private:
 	}
 };
 
-
+/// Sets thread name that will be used for both logs and debugger (if supported)
+/// WARNING: on Unix-like systems this method should not be used for main thread since it will also change name of the process
 void DLL_LINKAGE setThreadName(const std::string &name);
 
+/// Sets thread name for use in logging only
+void DLL_LINKAGE setThreadNameLoggingOnly(const std::string &name);
+
+/// Returns human-readable thread name that was set before, or string form of system-provided thread ID if no human-readable name was set
+std::string DLL_LINKAGE getThreadName();
+
 VCMI_LIB_NAMESPACE_END

+ 0 - 4
lib/VCMIDirs.cpp

@@ -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"; }

+ 12 - 2
lib/logging/CLogger.cpp

@@ -9,6 +9,7 @@
  */
 #include "StdInc.h"
 #include "CLogger.h"
+#include "../CThreadHelper.h"
 
 #ifdef VCMI_ANDROID
 #include <android/log.h>
@@ -427,8 +428,7 @@ void CLogConsoleTarget::setColorMapping(const CColorMapping & colorMapping) { th
 CLogFileTarget::CLogFileTarget(const boost::filesystem::path & filePath, bool append):
 	file(filePath.c_str(), append ? std::ios_base::app : std::ios_base::out)
 {
-//	formatter.setPattern("%d %l %n [%t] - %m");
-	formatter.setPattern("%l %n [%t] - %m");
+	formatter.setPattern("[%c] %l %n [%t] - %m");
 }
 
 void CLogFileTarget::write(const LogRecord & record)
@@ -446,4 +446,14 @@ CLogFileTarget::~CLogFileTarget()
 	file.close();
 }
 
+LogRecord::LogRecord(const CLoggerDomain & domain, ELogLevel::ELogLevel level, const std::string & message)
+	: domain(domain),
+	level(level),
+	message(message),
+	timeStamp(boost::posix_time::microsec_clock::local_time()),
+	threadId(getThreadName())
+{
+
+}
+
 VCMI_LIB_NAMESPACE_END

+ 1 - 6
lib/logging/CLogger.h

@@ -107,12 +107,7 @@ private:
 /// The struct LogRecord holds the log message and additional logging information.
 struct DLL_LINKAGE LogRecord
 {
-	LogRecord(const CLoggerDomain & domain, ELogLevel::ELogLevel level, const std::string & message)
-		: domain(domain),
-		level(level),
-		message(message),
-		timeStamp(boost::posix_time::microsec_clock::local_time()),
-		threadId(boost::lexical_cast<std::string>(boost::this_thread::get_id())) { }
+	LogRecord(const CLoggerDomain & domain, ELogLevel::ELogLevel level, const std::string & message);
 
 	CLoggerDomain domain;
 	ELogLevel::ELogLevel level;

+ 0 - 3
lib_server/CMakeLists.txt

@@ -1,3 +0,0 @@
-add_main_lib(vcmi_lib_server STATIC)
-target_compile_definitions(vcmi_lib_server PUBLIC VCMI_LIB_NAMESPACE=LIB_SERVER)
-target_compile_definitions(vcmi_lib_server PUBLIC VCMI_DLL_STATIC=1)

+ 1 - 1
mapeditor/CMakeLists.txt

@@ -178,7 +178,7 @@ if(APPLE)
 	set_property(GLOBAL PROPERTY AUTOGEN_TARGETS_FOLDER vcmieditor)
 endif()
 
-target_link_libraries(vcmieditor ${VCMI_LIB_TARGET} Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network)
+target_link_libraries(vcmieditor vcmi Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network)
 target_include_directories(vcmieditor
 	PUBLIC	${CMAKE_CURRENT_SOURCE_DIR}
 )

+ 1 - 1
scripting/erm/CMakeLists.txt

@@ -15,7 +15,7 @@ set(lib_HDRS
 )
 
 add_library(vcmiERM SHARED ${lib_SRCS} ${lib_HDRS})
-target_link_libraries(vcmiERM Boost::boost ${VCMI_LIB_TARGET})
+target_link_libraries(vcmiERM Boost::boost vcmi)
 
 vcmi_set_output_dir(vcmiERM "scripting")
 enable_pch(vcmiERM)

+ 1 - 1
scripting/lua/CMakeLists.txt

@@ -83,7 +83,7 @@ set(lib_HDRS
 )
 
 add_library(vcmiLua SHARED ${lib_SRCS} ${lib_HDRS})
-target_link_libraries(vcmiLua Boost::boost luajit::luajit ${VCMI_LIB_TARGET})
+target_link_libraries(vcmiLua Boost::boost luajit::luajit vcmi)
 
 vcmi_set_output_dir(vcmiLua "scripting")
 enable_pch(vcmiLua)

+ 15 - 33
server/CMakeLists.txt

@@ -1,4 +1,4 @@
-set(server_SRCS
+set(vcmiservercommon_SRCS
 		StdInc.cpp
 
 		battles/BattleActionProcessor.cpp
@@ -15,7 +15,6 @@ set(server_SRCS
 		processors/PlayerMessageProcessor.cpp
 		processors/TurnOrderProcessor.cpp
 
-		EntryPoint.cpp
 		CGameHandler.cpp
 		GlobalLobbyProcessor.cpp
 		ServerSpellCastEnvironment.cpp
@@ -25,7 +24,7 @@ set(server_SRCS
 		TurnTimerHandler.cpp
 )
 
-set(server_HEADERS
+set(vcmiservercommon_HEADERS
 		StdInc.h
 
 		battles/BattleActionProcessor.h
@@ -51,45 +50,28 @@ set(server_HEADERS
 		TurnTimerHandler.h
 )
 
-assign_source_group(${server_SRCS} ${server_HEADERS})
-
-if(ENABLE_SINGLE_APP_BUILD)
-	add_library(vcmiserver STATIC ${server_SRCS} ${server_HEADERS})
-	target_compile_definitions(vcmiserver PUBLIC VCMI_DLL_STATIC=1)
-	set(server_LIBS vcmi_lib_server)
-else()
-	if(ANDROID)
-		add_library(vcmiserver SHARED ${server_SRCS} ${server_HEADERS})
-	else()
-		add_executable(vcmiserver ${server_SRCS} ${server_HEADERS})
-	endif()
-	set(server_LIBS vcmi)
-endif()
+assign_source_group(${vcmiservercommon_SRCS} ${vcmiservercommon_HEADERS})
+
+add_library(vcmiservercommon STATIC ${vcmiservercommon_SRCS} ${vcmiservercommon_HEADERS})
+set(vcmiservercommon_LIBS vcmi)
 
 if(CMAKE_SYSTEM_NAME MATCHES FreeBSD OR HAIKU)
-	set(server_LIBS execinfo ${server_LIBS})
+	set(vcmiservercommon_LIBS execinfo ${vcmiservercommon_LIBS})
 endif()
-target_link_libraries(vcmiserver PRIVATE ${server_LIBS} minizip::minizip)
 
-target_include_directories(vcmiserver
+target_link_libraries(vcmiservercommon PRIVATE ${vcmiservercommon_LIBS} minizip::minizip)
+
+target_include_directories(vcmiservercommon
 	PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
 )
 
 if(WIN32)
-	set_target_properties(vcmiserver
+	set_target_properties(vcmiservercommon
 		PROPERTIES
-			OUTPUT_NAME "VCMI_server"
-			PROJECT_LABEL "VCMI_server"
+			OUTPUT_NAME "VCMI_vcmiservercommon"
+			PROJECT_LABEL "VCMI_vcmiservercommon"
 	)
 endif()
 
-vcmi_set_output_dir(vcmiserver "")
-enable_pch(vcmiserver)
-
-if(NOT ENABLE_SINGLE_APP_BUILD)
-	if(ANDROID)
-		install(TARGETS vcmiserver DESTINATION ${LIB_DIR})
-	else()
-		install(TARGETS vcmiserver DESTINATION ${BIN_DIR})
-	endif()
-endif()
+vcmi_set_output_dir(vcmiservercommon "")
+enable_pch(vcmiservercommon)

+ 9 - 14
server/CVCMIServer.cpp

@@ -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();
 }
 

+ 4 - 17
server/CVCMIServer.h

@@ -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
 };

+ 1 - 1
server/NetPacksLobbyServer.cpp

@@ -81,7 +81,7 @@ void ClientPermissionsCheckerNetPackVisitor::visitLobbyClientDisconnected(LobbyC
 
 	if(pack.shutdownServer)
 	{
-		if(!srv.cmdLineOptions.count("run-by-client"))
+		if(!srv.wasStartedByClient())
 		{
 			result = false;
 			return;

+ 34 - 0
serverapp/CMakeLists.txt

@@ -0,0 +1,34 @@
+set(serverapp_SRCS
+		StdInc.cpp
+		EntryPoint.cpp
+)
+
+set(serverapp_HEADERS
+		StdInc.h
+)
+
+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(serverapp_LIBS execinfo ${serverapp_LIBS})
+endif()
+target_link_libraries(vcmiserver PRIVATE ${serverapp_LIBS} minizip::minizip vcmiservercommon)
+
+target_include_directories(vcmiserver
+	PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+if(WIN32)
+	set_target_properties(vcmiserver
+		PROPERTIES
+			OUTPUT_NAME "VCMI_server"
+			PROJECT_LABEL "VCMI_server"
+	)
+endif()
+
+vcmi_set_output_dir(vcmiserver "")
+enable_pch(vcmiserver)
+
+install(TARGETS vcmiserver DESTINATION ${BIN_DIR})

+ 13 - 79
server/EntryPoint.cpp → serverapp/EntryPoint.cpp

@@ -9,40 +9,33 @@
  */
 #include "StdInc.h"
 
-#include "CVCMIServer.h"
+#include "../server/CVCMIServer.h"
 
 #include "../lib/CConsoleHandler.h"
 #include "../lib/logging/CBasicLogConfigurator.h"
 #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";
-const std::string SERVER_NAME = GameConstants::VCMI_VERSION + std::string(" (") + SERVER_NAME_AFFIX + ')';
+static const std::string SERVER_NAME_AFFIX = "server";
+static const std::string SERVER_NAME = GameConstants::VCMI_VERSION + std::string(" (") + SERVER_NAME_AFFIX + ')';
 
 static void handleCommandOptions(int argc, const char * argv[], boost::program_options::variables_map & options)
 {
-	namespace po = boost::program_options;
-	po::options_description opts("Allowed options");
+	boost::program_options::options_description opts("Allowed options");
 	opts.add_options()
 	("help,h", "display help and exit")
 	("version,v", "display version information and exit")
 	("run-by-client", "indicate that server launched by client on same machine")
-	("port", po::value<ui16>(), "port at which server will listen to connections from client")
+	("port", boost::program_options::value<ui16>(), "port at which server will listen to connections from client")
 	("lobby", "start server in lobby mode in which server connects to a global lobby");
 
 	if(argc > 1)
 	{
 		try
 		{
-			po::store(po::parse_command_line(argc, argv, opts), options);
+			boost::program_options::store(boost::program_options::parse_command_line(argc, argv, opts), options);
 		}
 		catch(boost::program_options::error & e)
 		{
@@ -50,13 +43,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);
+	boost::program_options::notify(options);
 
-#ifndef SINGLE_PROCESS_APP
 	if(options.count("help"))
 	{
 		auto time = std::time(nullptr);
@@ -75,31 +63,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 +84,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

+ 2 - 0
serverapp/StdInc.cpp

@@ -0,0 +1,2 @@
+// Creates the precompiled header
+#include "StdInc.h"

+ 14 - 0
serverapp/StdInc.h

@@ -0,0 +1,14 @@
+/*
+ * StdInc.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
+
+#include "../Global.h"
+
+VCMI_LIB_USING_NAMESPACE