Преглед изворни кода

make server a static lib, run it in a separate thread

issues to solve:
- dynamic_cast error 2: One or more of the following type_info's has hidden visibility or is defined in more than one translation unit. They should all have public visibility. 13CPackForLobby, 20LobbyClientConnected, 20LobbyClientConnected.
- error setting socket option: set_option: No buffer space available
Andrey Filipenkov пре 4 година
родитељ
комит
2e18299897

+ 4 - 2
client/CMT.cpp

@@ -433,6 +433,7 @@ int main(int argc, char * argv[])
 
 
 #ifndef VCMI_NO_THREADED_LOAD
+    // todo ios
 	#ifdef VCMI_ANDROID // android loads the data quite slowly so we display native progressbar to prevent having only black screen for few seconds
 	{
 		CAndroidVMHelper vmHelper;
@@ -1136,9 +1137,9 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen, int displayIn
             logGlobal->warn("Metal unavailable, using OpenGL ES");
             createWindow();
         }
-        SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight"); // TODO: isn't setting in Info.plist not enough?
+//        SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight"); // TODO: isn't setting in Info.plist not enough?
         SDL_SetHint(SDL_HINT_IOS_HIDE_HOME_INDICATOR, "1");
-        //SDL_HINT_RETURN_KEY_HIDES_IME
+        SDL_SetHint(SDL_HINT_RETURN_KEY_HIDES_IME, "1");
 
         logGlobal->info("before SDL_GetWindowSize %dx%d", w, h);
         SDL_GetWindowSize(mainWindow, &w, &h);
@@ -1315,6 +1316,7 @@ static void handleEvent(SDL_Event & ev)
 {
 	if((ev.type==SDL_QUIT) ||(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4 && (ev.key.keysym.mod & KMOD_ALT)))
 	{
+        // todo ios
 #ifdef VCMI_ANDROID
 		handleQuit(false);
 #else

+ 3 - 1
client/CMakeLists.txt

@@ -177,7 +177,9 @@ if(WIN32)
 	target_compile_definitions(vcmiclient PRIVATE WINDOWS_IGNORE_PACKING_MISMATCH)
 elseif(APPLE_IOS)
 	target_link_libraries(vcmiclient PRIVATE
-		"-framework Foundation -framework UIKit -framework QuartzCore -framework CoreGraphics -framework CoreServices -framework ImageIO" # SDL2_image
+		vcmiserver
+		# SDL2_image:
+		"-framework Foundation -framework UIKit -framework QuartzCore -framework CoreGraphics -framework CoreServices -framework ImageIO"
 	)
 
 	target_sources(vcmiclient PRIVATE ${CMAKE_SOURCE_DIR}/client/LaunchScreen.storyboard)

+ 1 - 0
client/CPlayerInterface.cpp

@@ -364,6 +364,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
 	for(int i = 1; i < 32; i += 2 * speed)
 	{
 		movementPxStep(details, i, hp, hero);
+        // todo ios
 #ifndef VCMI_ANDROID
 		// currently android doesn't seem to be able to handle all these full redraws here, so let's disable it so at least it looks less choppy;
 		// most likely this is connected with the way that this manual animation+framerate handling is solved

+ 22 - 3
client/CServerHandler.cpp

@@ -24,7 +24,8 @@
 #ifdef VCMI_ANDROID
 #include "../lib/CAndroidVMHelper.h"
 #elif defined(VCMI_IOS)
-//TODO
+#include "../server/CVCMIServer.h"
+// todo ios
 #else
 #include "../lib/Interprocess.h"
 #endif
@@ -184,7 +185,18 @@ void CServerHandler::startLocalServerAndConnect()
 		envHelper.callStaticVoidMethod(CAndroidVMHelper::NATIVE_METHODS_DEFAULT_CLASS, "startServer", true);
 	}
 #elif defined(VCMI_IOS)
-	// TODO
+    // todo ios: hide keyboard
+    logNetwork->info("[ios] create server thread");
+    boost::condition_variable cond;
+    threadRunLocalServer = std::make_shared<boost::thread>([&cond, this] {
+        setThreadName("CVCMIServer");
+        CVCMIServer::create(&cond);
+        // todo ios copypaste
+        threadRunLocalServer.reset();
+        CSH->campaignServerRestartLock.setn(false);
+    });
+//    threadRunLocalServer->detach();
+    logNetwork->info("[ios] detach server thread");
 #else
 	threadRunLocalServer = std::make_shared<boost::thread>(&CServerHandler::threadRunServer, this); //runs server executable;
 #endif
@@ -202,7 +214,14 @@ void CServerHandler::startLocalServerAndConnect()
 	logNetwork->info("waiting for server finished...");
 	androidTestServerReadyFlag = false;
 #elif defined(VCMI_IOS)
-	//TODO
+    // todo ios
+    {
+        boost::mutex m;
+        boost::unique_lock<boost::mutex> lock{m};
+        logNetwork->info("[ios] wait for server");
+        cond.wait(lock);
+        logNetwork->info("[ios] server ready");
+    }
 #else
 	if(shm)
 		shm->sr->waitTillReady();

+ 5 - 0
client/windows/CAdvmapInterface.cpp

@@ -126,6 +126,7 @@ void CTerrainRect::clickLeft(tribool down, bool previousState)
 		return;
 
 #ifdef VCMI_ANDROID
+    // todo ios
 	if(adventureInt->swipeEnabled)
 	{
 		if(handleSwipeStateChange((bool)down == true))
@@ -151,6 +152,7 @@ void CTerrainRect::clickLeft(tribool down, bool previousState)
 void CTerrainRect::clickRight(tribool down, bool previousState)
 {
 #ifdef VCMI_ANDROID
+    // todo ios
 	if(adventureInt->swipeEnabled && isSwiping)
 		return;
 #endif
@@ -180,6 +182,7 @@ void CTerrainRect::mouseMoved(const SDL_MouseMotionEvent & sEvent)
 void CTerrainRect::handleSwipeMove(const SDL_MouseMotionEvent & sEvent)
 {
 #ifdef VCMI_ANDROID
+    // todo ios
 	if(sEvent.state == 0) // any "button" is enough on android
 #else //!VCMI_ANDROID
 	if((sEvent.state & SDL_BUTTON_MMASK) == 0) // swipe only works with middle mouse on other platforms
@@ -1050,6 +1053,7 @@ void CAdvMapInt::show(SDL_Surface * to)
 		handleSwipeUpdate();
 	}
 #ifdef VCMI_ANDROID // on android, map-moving mode is exclusive (TODO technically it might work with both enabled; to be checked)
+    // todo ios
 	else
 #endif // VCMI_ANDROID
 	{
@@ -1452,6 +1456,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView)
 void CAdvMapInt::mouseMoved( const SDL_MouseMotionEvent & sEvent )
 {
 #ifdef VCMI_ANDROID
+    // todo ios
 	if(swipeEnabled)
 		return;
 #endif

+ 3 - 2
configure_ios.sh

@@ -5,11 +5,12 @@ ffmpegDir=~/dev/ios/vcmi-ios-deps/mobile-ffmpeg-min-universal
 sdlLibsDir=~/dev/ios/vcmi-ios-deps/SDL2-lib
 
 srcDir="../vcmi"
-"${2:-cmake}" "$srcDir" -G "$1" \
+/Users/Shared/xbmc-depends/x86_64-darwin19.6.0-native/bin/cmake "$srcDir" -G Xcode \
   -DENABLE_LAUNCHER=0 \
   -Wno-dev \
   -DCMAKE_TOOLCHAIN_FILE="$srcDir/ios.toolchain.cmake" \
-  -DPLATFORM=OS64 \
+  -DPLATFORM=${1:-OS64} \
+  -DDEPLOYMENT_TARGET=9.0 \
   -DENABLE_BITCODE=0 \
   -DCMAKE_BINARY_DIR=$(pwd) \
   -DCMAKE_PREFIX_PATH="$boostPrefix;$ffmpegDir;$sdlLibsDir" \

+ 6 - 1
lib/VCMIDirs.cpp

@@ -389,7 +389,9 @@ class VCMIDirsIOS final : public VCMIDirsApple
 		std::vector<bfs::path> dataPaths() const override;
 
 		bfs::path libraryPath() const override;
+        boost::filesystem::path fullLibraryPath(const std::string & desiredFolder, const std::string & baseLibName) const override;
 		bfs::path binaryPath() const override;
+        bfs::path serverPath() const override;
 
 		bool developmentMode() const override;
 };
@@ -398,10 +400,13 @@ bfs::path VCMIDirsIOS::userDataPath() const { return {ios_documentsPath()}; }
 bfs::path VCMIDirsIOS::userCachePath() const { return {ios_cachesPath()}; }
 bfs::path VCMIDirsIOS::userLogsPath() const { return {ios_documentsPath()}; }
 
-std::vector<bfs::path> VCMIDirsIOS::dataPaths() const { return {userDataPath()}; }
+std::vector<bfs::path> VCMIDirsIOS::dataPaths() const { return {binaryPath(), userDataPath()}; }
 
 bfs::path VCMIDirsIOS::libraryPath() const { return {ios_frameworksPath()}; }
+// todo ios: place AI libs in subdir?
+boost::filesystem::path VCMIDirsIOS::fullLibraryPath(const std::string & desiredFolder, const std::string & baseLibName) const { return libraryPath() / libraryName(baseLibName); }
 bfs::path VCMIDirsIOS::binaryPath() const { return {ios_bundlePath()}; }
+bfs::path VCMIDirsIOS::serverPath() const { return clientPath(); }
 
 bool VCMIDirsIOS::developmentMode() const { return false; }
 #elif defined(VCMI_MAC)

+ 3 - 1
lib/filesystem/AdapterLoaders.cpp

@@ -154,7 +154,9 @@ std::vector<const ISimpleResourceLoader *> CFilesystemList::getResourcesWithName
 	std::vector<const ISimpleResourceLoader *> ret;
 
 	for (auto & loader : loaders)
-		boost::range::copy(loader->getResourcesWithName(resourceName), std::back_inserter(ret));
+        // todo ios
+        if (loader)
+            boost::range::copy(loader->getResourcesWithName(resourceName), std::back_inserter(ret));
 
 	return ret;
 }

+ 9 - 2
lib/serializer/Connection.cpp

@@ -33,8 +33,15 @@ using namespace boost::asio::ip;
 void CConnection::init()
 {
 	socket->set_option(boost::asio::ip::tcp::no_delay(true));
-	socket->set_option(boost::asio::socket_base::send_buffer_size(4194304));
-	socket->set_option(boost::asio::socket_base::receive_buffer_size(4194304));
+    try
+    {
+        socket->set_option(boost::asio::socket_base::send_buffer_size(4194304));
+        socket->set_option(boost::asio::socket_base::receive_buffer_size(4194304));
+    }
+    catch (const boost::system::system_error & e)
+    {
+        logNetwork->error("error setting socket option: %s", e.what());
+    }
 
 	enableSmartPointerSerialization();
 	disableStackSendingByID();

+ 5 - 1
server/CMakeLists.txt

@@ -22,7 +22,11 @@ if(ANDROID) # android needs client/server to be libraries, not executables, so w
 	return()
 endif()
 
-add_executable(vcmiserver ${server_SRCS} ${server_HEADERS})
+if(APPLE_IOS)
+	add_library(vcmiserver STATIC ${server_SRCS} ${server_HEADERS})
+else()
+	add_executable(vcmiserver ${server_SRCS} ${server_HEADERS})
+endif()
 
 set(server_LIBS vcmi)
 if(CMAKE_SYSTEM_NAME MATCHES FreeBSD)

+ 26 - 8
server/CVCMIServer.cpp

@@ -30,7 +30,7 @@
 #ifdef VCMI_ANDROID
 #include "lib/CAndroidVMHelper.h"
 #elif defined(VCMI_IOS)
-	//TODO
+// todo ios
 #else
 #include "../lib/Interprocess.h"
 #endif
@@ -114,8 +114,8 @@ public:
 	}
 };
 
-std::string NAME_AFFIX = "server";
-std::string NAME = GameConstants::VCMI_VERSION + std::string(" (") + NAME_AFFIX + ')';
+std::string SERVER_NAME_AFFIX = "server";
+std::string SERVER_NAME = GameConstants::VCMI_VERSION + std::string(" (") + SERVER_NAME_AFFIX + ')';
 
 CVCMIServer::CVCMIServer(boost::program_options::variables_map & opts)
 	: port(3030), io(std::make_shared<boost::asio::io_service>()), state(EServerState::LOBBY), cmdLineOptions(opts), currentClientId(1), currentPlayerId(1), restartGameplay(false)
@@ -293,7 +293,7 @@ void CVCMIServer::connectionAccepted(const boost::system::error_code & ec)
 	try
 	{
 		logNetwork->info("We got a new connection! :)");
-		auto c = std::make_shared<CConnection>(upcomingConnection, NAME, uuid);
+		auto c = std::make_shared<CConnection>(upcomingConnection, SERVER_NAME, uuid);
 		upcomingConnection.reset();
 		connections.insert(c);
 		c->handler = std::make_shared<boost::thread>(&CVCMIServer::threadHandleClient, this, c);
@@ -901,6 +901,9 @@ static void handleCommandOptions(int argc, char * argv[], boost::program_options
 	}
 }
 
+#ifdef VCMI_IOS
+#define main server_main
+#endif
 int main(int argc, char * argv[])
 {
 #if !defined(VCMI_ANDROID) && !defined(VCMI_IOS)
@@ -913,12 +916,19 @@ int main(int argc, char * argv[])
 	signal(SIGSEGV, handleLinuxSignal);
 #endif
 
+    // todo ios: double console log
 	console = new CConsoleHandler();
 	CBasicLogConfigurator logConfig(VCMIDirs::get().userLogsPath() / "VCMI_Server_log.txt", console);
 	logConfig.configureDefault();
-	logGlobal->info(NAME);
-
-	boost::program_options::variables_map opts;
+	logGlobal->info(SERVER_NAME);
+
+    boost::program_options::variables_map opts;
+#ifdef VCMI_IOS
+    argc = 1;
+    boost::condition_variable * cond = reinterpret_cast<boost::condition_variable *>(argv[1]);
+    cond->notify_one();
+//#endif
+#else
 	handleCommandOptions(argc, argv, opts);
 	preinitDLL(console);
 	settings.init();
@@ -926,6 +936,8 @@ int main(int argc, char * argv[])
 
 	loadDLLClasses();
 	srand((ui32)time(nullptr));
+//#ifdef VCMI_IOS
+#endif
 	try
 	{
 		boost::asio::io_service io_service;
@@ -965,11 +977,17 @@ int main(int argc, char * argv[])
 	return 0;
 }
 
-// TODO iOS
 #ifdef VCMI_ANDROID
 void CVCMIServer::create()
 {
 	const char * foo[1] = {"android-server"};
 	main(1, const_cast<char **>(foo));
 }
+#elif defined(VCMI_IOS)
+void CVCMIServer::create(boost::condition_variable * cond)
+{
+    const auto executablePath = VCMIDirs::get().serverPath();
+    void *argv[] = {const_cast<char *>(executablePath.c_str()), cond};
+    main(2, reinterpret_cast<char **>(argv));
+}
 #endif

+ 2 - 0
server/CVCMIServer.h

@@ -103,5 +103,7 @@ public:
 
 #ifdef VCMI_ANDROID
 	static void create();
+#elif defined(VCMI_IOS)
+    static void create(boost::condition_variable * cond);
 #endif
 };