diff --git a/Info.plist b/Info.plist
index f82ec6a6a..14c1b198d 100644
--- a/Info.plist
+++ b/Info.plist
@@ -49,6 +49,10 @@
NSAllowsArbitraryLoads
+ UIBackgroundModes
+
+ audio
+
UIDeviceFamily
1
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index cf8efef1a..20b19af97 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -177,9 +177,7 @@ if(WIN32)
target_compile_definitions(vcmiclient PRIVATE WINDOWS_IGNORE_PACKING_MISMATCH)
elseif(APPLE_IOS)
target_link_libraries(vcmiclient PRIVATE
- vcmiserver
- # SDL2_image:
- "-framework Foundation -framework UIKit -framework QuartzCore -framework CoreGraphics -framework CoreServices -framework ImageIO"
+ "-framework Foundation -framework UIKit -framework QuartzCore -framework CoreGraphics -framework CoreServices -framework ImageIO" # SDL2_image
)
target_sources(vcmiclient PRIVATE ${CMAKE_SOURCE_DIR}/client/LaunchScreen.storyboard)
diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp
index 39024dc1b..93d44cefa 100644
--- a/client/CServerHandler.cpp
+++ b/client/CServerHandler.cpp
@@ -24,8 +24,7 @@
#ifdef VCMI_ANDROID
#include "../lib/CAndroidVMHelper.h"
#elif defined(VCMI_IOS)
-#include "../server/CVCMIServer.h"
-// todo ios
+//TODO
#else
#include "../lib/Interprocess.h"
#endif
@@ -185,18 +184,7 @@ void CServerHandler::startLocalServerAndConnect()
envHelper.callStaticVoidMethod(CAndroidVMHelper::NATIVE_METHODS_DEFAULT_CLASS, "startServer", true);
}
#elif defined(VCMI_IOS)
- // 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");
+ // TODO
#else
threadRunLocalServer = std::make_shared(&CServerHandler::threadRunServer, this); //runs server executable;
#endif
@@ -214,14 +202,7 @@ void CServerHandler::startLocalServerAndConnect()
logNetwork->info("waiting for server finished...");
androidTestServerReadyFlag = false;
#elif defined(VCMI_IOS)
- // todo ios
- {
- boost::mutex m;
- boost::unique_lock lock{m};
- logNetwork->info("[ios] wait for server");
- cond.wait(lock);
- logNetwork->info("[ios] server ready");
- }
+ //TODO
#else
if(shm)
shm->sr->waitTillReady();
diff --git a/lib/VCMIDirs.cpp b/lib/VCMIDirs.cpp
index c8c523fb8..5a59ff03e 100644
--- a/lib/VCMIDirs.cpp
+++ b/lib/VCMIDirs.cpp
@@ -391,7 +391,6 @@ class VCMIDirsIOS final : public VCMIDirsApple
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;
};
@@ -431,7 +430,6 @@ boost::filesystem::path VCMIDirsIOS::fullLibraryPath(const std::string & desired
#endif
}
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/package_ios.sh b/package_ios.sh
index 849d4dc3a..5240b74a1 100755
--- a/package_ios.sh
+++ b/package_ios.sh
@@ -2,18 +2,20 @@
pushd bin/Debug
mkdir -p vcmiclient.app/Frameworks
-cp *.dylib AI/*.dylib vcmiclient.app
-badInstallNamePrefix=$(pwd)
-cd vcmiclient.app
+productsDir=$(pwd)
sdl2Path=~/dev/ios/vcmi-ios-deps/SDL2-lib/lib
-cp "$sdl2Path/libSDL2.dylib" .
-install_name_tool -rpath "$sdl2Path" '@executable_path/Frameworks' vcmiclient
+for app in vcmiclient vcmiserver; do
+ install_name_tool -rpath "$sdl2Path" '@executable_path/Frameworks' "$productsDir/$app.app/$app"
+done
+
+cp *.dylib AI/*.dylib "$sdl2Path/libSDL2.dylib" vcmiclient.app
+cd vcmiclient.app
for b in vcmiclient *.dylib; do
for l in minizip vcmi; do
libName="lib${l}.dylib"
- install_name_tool -change "$badInstallNamePrefix/$libName" "@rpath/$libName" "$b"
+ install_name_tool -change "$productsDir/$libName" "@rpath/$libName" "$b"
done
if [ "$b" != vcmiclient ]; then
install_name_tool -id "@rpath/$b" "$b"
@@ -23,5 +25,15 @@ done
mv -f *.dylib Frameworks
popd
-cp -f ../vcmi/Info.plist "$badInstallNamePrefix/vcmiclient.app"
-cp -R bin/Debug-iphoneos/* "$badInstallNamePrefix/vcmiclient.app"
+for app in vcmiclient vcmiserver; do
+ cp -f ../vcmi/Info.plist "$productsDir/$app.app"
+done
+sed -i '' -e 's/client/server/g' -e 's/>VCMI>VCMI server' "$productsDir/vcmiserver.app/Info.plist"
+
+cp -R bin/Debug-iphoneos/* "$productsDir/vcmiclient.app"
+cp -fR "$productsDir/vcmiclient.app/Frameworks" "$productsDir/vcmiserver.app"
+
+for l in minizip vcmi; do
+ libName="lib${l}.dylib"
+ install_name_tool -change "$productsDir/$libName" "@rpath/$libName" "$productsDir/vcmiserver.app/vcmiserver"
+done
diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt
index 8fae51ed1..61d06ded4 100644
--- a/server/CMakeLists.txt
+++ b/server/CMakeLists.txt
@@ -16,21 +16,23 @@ set(server_HEADERS
CVCMIServer.h
)
+if(APPLE_IOS)
+ set(server_SRCS ${server_SRCS} main_ios.mm)
+endif(APPLE_IOS)
+
assign_source_group(${server_SRCS} ${server_HEADERS})
if(ANDROID) # android needs client/server to be libraries, not executables, so we can't reuse the build part of this script
return()
endif()
-if(APPLE_IOS)
- add_library(vcmiserver STATIC ${server_SRCS} ${server_HEADERS})
-else()
- add_executable(vcmiserver ${server_SRCS} ${server_HEADERS})
-endif()
+add_executable(vcmiserver ${server_SRCS} ${server_HEADERS})
set(server_LIBS vcmi)
if(CMAKE_SYSTEM_NAME MATCHES FreeBSD)
set(server_LIBS execinfo ${server_LIBS})
+elseif(APPLE_IOS)
+ set(server_LIBS ${server_LIBS} "-framework UIKit -framework AVFoundation")
endif()
target_link_libraries(vcmiserver PRIVATE ${server_LIBS} minizip::minizip)
@@ -44,6 +46,10 @@ if(WIN32)
OUTPUT_NAME "VCMI_server"
PROJECT_LABEL "VCMI_server"
)
+elseif(APPLE_IOS)
+ # TODO: move to a common dir / add macro?
+ target_sources(vcmiclient PRIVATE ${CMAKE_SOURCE_DIR}/client/LaunchScreen.storyboard)
+ set_source_files_properties(${CMAKE_SOURCE_DIR}/client/LaunchScreen.storyboard PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
endif()
vcmi_set_output_dir(vcmiserver "")
diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp
index 902d1a8e2..aa6f5ed82 100644
--- a/server/CVCMIServer.cpp
+++ b/server/CVCMIServer.cpp
@@ -114,8 +114,8 @@ public:
}
};
-std::string SERVER_NAME_AFFIX = "server";
-std::string SERVER_NAME = GameConstants::VCMI_VERSION + std::string(" (") + SERVER_NAME_AFFIX + ')';
+std::string NAME_AFFIX = "server";
+std::string NAME = GameConstants::VCMI_VERSION + std::string(" (") + 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, SERVER_NAME, uuid);
+ auto c = std::make_shared(upcomingConnection, NAME, uuid);
upcomingConnection.reset();
connections.insert(c);
c->handler = std::make_shared(&CVCMIServer::threadHandleClient, this, c);
@@ -920,14 +920,9 @@ int main(int argc, char * argv[])
console = new CConsoleHandler();
CBasicLogConfigurator logConfig(VCMIDirs::get().userLogsPath() / "VCMI_Server_log.txt", console);
logConfig.configureDefault();
- logGlobal->info(SERVER_NAME);
+ logGlobal->info(NAME);
- boost::program_options::variables_map opts;
-#ifdef VCMI_IOS
- argc = 1;
- boost::condition_variable * cond = reinterpret_cast(argv[1]);
- cond->notify_one();
-#else
+ boost::program_options::variables_map opts;
handleCommandOptions(argc, argv, opts);
preinitDLL(console);
settings.init();
@@ -935,7 +930,6 @@ int main(int argc, char * argv[])
loadDLLClasses();
srand((ui32)time(nullptr));
-#endif
try
{
boost::asio::io_service io_service;
@@ -975,17 +969,10 @@ int main(int argc, char * argv[])
return 0;
}
-#ifdef VCMI_ANDROID
+#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
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 5e68c62eb..7cd84eb46 100644
--- a/server/CVCMIServer.h
+++ b/server/CVCMIServer.h
@@ -101,9 +101,7 @@ public:
ui8 getIdOfFirstUnallocatedPlayer() const;
-#ifdef VCMI_ANDROID
+#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
static void create();
-#elif defined(VCMI_IOS)
- static void create(boost::condition_variable * cond);
#endif
};
diff --git a/server/main_ios.mm b/server/main_ios.mm
new file mode 100644
index 000000000..ec28d8c64
--- /dev/null
+++ b/server/main_ios.mm
@@ -0,0 +1,63 @@
+/*
+ * main_ios.mm, 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
+ *
+ */
+#import
+#import
+
+//#include "StdInc.h"
+#include "../Global.h"
+#include "CVCMIServer.h"
+
+@interface ViewController : UIViewController
+@end
+
+@implementation ViewController
+@end
+
+
+@interface AppDelegate : UIResponder
+@property (nonatomic, strong) UIWindow *window;
+@property (nonatomic, strong) AVPlayerLooper *looper;
+@end
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+ self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
+ self.window.rootViewController = [ViewController new];
+ [self.window makeKeyAndVisible];
+
+ [AVAudioSession.sharedInstance setCategory:AVAudioSessionCategoryPlayback mode:AVAudioSessionModeDefault options:AVAudioSessionCategoryOptionMixWithOthers error:nullptr];
+
+ auto item = [AVPlayerItem playerItemWithURL:[NSBundle.mainBundle URLForResource:@"silence" withExtension:@"wav"]];
+ auto player = [AVQueuePlayer new];
+ player.allowsExternalPlayback = NO;
+ [player play];
+ self.looper = [AVPlayerLooper playerLooperWithPlayer:player templateItem:item];
+
+ [NSThread detachNewThreadWithBlock:^
+ {
+ NSThread.currentThread.name = @"CVCMIServer";
+ NSLog(@"starting server from thread %@", NSThread.currentThread);
+ CVCMIServer::create();
+ }];
+ return YES;
+}
+
+@end
+
+
+int main(int argc, char * argv[])
+{
+ @autoreleasepool
+ {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}