diff --git a/client/CMT.cpp b/client/CMT.cpp index 2c52a3c28..a2aa4c467 100644 --- a/client/CMT.cpp +++ b/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 diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 20b19af97..cf8efef1a 100644 --- a/client/CMakeLists.txt +++ b/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) diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 62463f048..481893bb1 100644 --- a/client/CPlayerInterface.cpp +++ b/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 diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index 93d44cefa..39024dc1b 100644 --- a/client/CServerHandler.cpp +++ b/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([&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(&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 lock{m}; + logNetwork->info("[ios] wait for server"); + cond.wait(lock); + logNetwork->info("[ios] server ready"); + } #else if(shm) shm->sr->waitTillReady(); diff --git a/client/windows/CAdvmapInterface.cpp b/client/windows/CAdvmapInterface.cpp index c42fc9019..2c5a9dfb7 100644 --- a/client/windows/CAdvmapInterface.cpp +++ b/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 diff --git a/configure_ios.sh b/configure_ios.sh index 30dc6ba8e..1a0bc58ae 100755 --- a/configure_ios.sh +++ b/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" \ diff --git a/lib/VCMIDirs.cpp b/lib/VCMIDirs.cpp index ecac91b86..fd6c744e1 100644 --- a/lib/VCMIDirs.cpp +++ b/lib/VCMIDirs.cpp @@ -389,7 +389,9 @@ class VCMIDirsIOS final : public VCMIDirsApple std::vector 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 VCMIDirsIOS::dataPaths() const { return {userDataPath()}; } +std::vector 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) diff --git a/lib/filesystem/AdapterLoaders.cpp b/lib/filesystem/AdapterLoaders.cpp index 000f44fdd..dd483d2ae 100644 --- a/lib/filesystem/AdapterLoaders.cpp +++ b/lib/filesystem/AdapterLoaders.cpp @@ -154,7 +154,9 @@ std::vector CFilesystemList::getResourcesWithName std::vector 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; } diff --git a/lib/serializer/Connection.cpp b/lib/serializer/Connection.cpp index 5d799d666..30bc4e83b 100644 --- a/lib/serializer/Connection.cpp +++ b/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(); diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 653703d11..8fae51ed1 100644 --- a/server/CMakeLists.txt +++ b/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) diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index 71b78b153..c918743e5 100644 --- a/server/CVCMIServer.cpp +++ b/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()), 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(upcomingConnection, NAME, uuid); + auto c = std::make_shared(upcomingConnection, SERVER_NAME, uuid); upcomingConnection.reset(); connections.insert(c); c->handler = std::make_shared(&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); + logGlobal->info(SERVER_NAME); - boost::program_options::variables_map opts; + boost::program_options::variables_map opts; +#ifdef VCMI_IOS + argc = 1; + boost::condition_variable * cond = reinterpret_cast(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(foo)); } +#elif defined(VCMI_IOS) +void CVCMIServer::create(boost::condition_variable * cond) +{ + const auto executablePath = VCMIDirs::get().serverPath(); + void *argv[] = {const_cast(executablePath.c_str()), cond}; + main(2, reinterpret_cast(argv)); +} #endif diff --git a/server/CVCMIServer.h b/server/CVCMIServer.h index 111ded751..5e68c62eb 100644 --- a/server/CVCMIServer.h +++ b/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 };