소스 검색

load game data from shared dir

kambala-decapitator/vcmi#15
Andrey Filipenkov 4 년 전
부모
커밋
2fc4d48215
4개의 변경된 파일60개의 추가작업 그리고 37개의 파일을 삭제
  1. 15 0
      lib/CIOSUtils.h
  2. 35 4
      lib/CIOSUtils.m
  3. 2 2
      lib/VCMIDirs.cpp
  4. 8 31
      server/ios/main.mm

+ 15 - 0
lib/CIOSUtils.h

@@ -7,10 +7,25 @@
  * Full text of license available in license.txt file, in main folder
  *
  */
+#include <TargetConditionals.h>
+
+#ifdef __OBJC__
+@class NSURL;
+#endif
 
 extern const char *ios_documentsPath();
 extern const char *ios_cachesPath();
 
+#ifdef __OBJC__
+NSURL *sharedContainerURL();
+NSURL *sharedGameDataURL();
+#endif
+extern const char *ios_sharedDataPath();
+
+#if TARGET_OS_SIMULATOR
+extern const char *ios_hostApplicationSupportPath();
+#endif
+
 extern const char *ios_bundlePath();
 extern const char *ios_frameworksPath();
 

+ 35 - 4
lib/CIOSUtils.m

@@ -12,15 +12,46 @@
 
 @import Foundation;
 
-static const char *standardPath(NSSearchPathDirectory directory)
+static NSString *standardPathNative(NSSearchPathDirectory directory)
 {
-	return [NSFileManager.defaultManager URLForDirectory:directory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:NULL].path.UTF8String;
+	return [NSFileManager.defaultManager URLForDirectory:directory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:NULL].path;
 }
+static const char *standardPath(NSSearchPathDirectory directory) { return standardPathNative(directory).fileSystemRepresentation; }
 
 const char *ios_documentsPath() { return standardPath(NSDocumentDirectory); }
 const char *ios_cachesPath() { return standardPath(NSCachesDirectory); }
 
-const char *ios_bundlePath() { return NSBundle.mainBundle.bundlePath.UTF8String; }
-const char *ios_frameworksPath() { return [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"Frameworks"].UTF8String; } // TODO: sharedFrameworksPath?
+NSURL *sharedContainerURL()
+{
+    static NSURL *sharedPathURL;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        __auto_type bundleID = NSBundle.mainBundle.bundleIdentifier;
+        __auto_type lastDotPos = [bundleID rangeOfString:@"." options:NSBackwardsSearch].location;
+        __auto_type groupID = [NSString stringWithFormat:@"group.%@.vcmi", [bundleID substringToIndex:lastDotPos]];
+        sharedPathURL = [NSFileManager.defaultManager containerURLForSecurityApplicationGroupIdentifier:groupID];
+    });
+    return sharedPathURL;
+}
+NSURL *sharedGameDataURL() { return [sharedContainerURL() URLByAppendingPathComponent:@"GameData"]; }
+const char *ios_sharedDataPath() { return sharedGameDataURL().fileSystemRepresentation; }
+
+#if TARGET_OS_SIMULATOR
+const char *ios_hostApplicationSupportPath()
+{
+    static NSString *applicationSupportPath;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        __auto_type cachesPath = standardPathNative(NSCachesDirectory);
+        __auto_type afterMacOsHomeDirPos = [cachesPath rangeOfString:@"Library/Developer"].location;
+        NSCAssert(afterMacOsHomeDirPos != NSNotFound, @"simulator directory location is not under user's home directory: %@", cachesPath);
+        applicationSupportPath = [[cachesPath substringToIndex:afterMacOsHomeDirPos] stringByAppendingPathComponent:@"Library/Application Support/vcmi"].stringByResolvingSymlinksInPath;
+    });
+    return applicationSupportPath.fileSystemRepresentation;
+}
+#endif
+
+const char *ios_bundlePath() { return NSBundle.mainBundle.bundlePath.fileSystemRepresentation; }
+const char *ios_frameworksPath() { return NSBundle.mainBundle.privateFrameworksPath.fileSystemRepresentation; }
 
 const char *ios_bundleIdentifier() { return NSBundle.mainBundle.bundleIdentifier.UTF8String; }

+ 2 - 2
lib/VCMIDirs.cpp

@@ -402,9 +402,9 @@ std::vector<bfs::path> VCMIDirsIOS::dataPaths() const
 {
     return {
 #ifdef VCMI_IOS_SIM
-        // fixme ios
-        {"/Users/kambala/Library/Application Support/vcmi"},
+        {ios_hostApplicationSupportPath()},
 #endif
+        {ios_sharedDataPath()},
         binaryPath(),
         userDataPath(),
     };

+ 8 - 31
server/ios/main.mm

@@ -11,11 +11,11 @@
 
 #include "../Global.h"
 #include "CVCMIServer.h"
-
-#define SHARED_DATA_DIR @"GameData"
+extern "C" {
+#import "../lib/CIOSUtils.h"
+}
 
 @interface ViewController : UIViewController
-@property (nonatomic, copy) NSURL *sharedPathURL;
 @property (nonatomic, copy) NSArray<NSURL *> *dataDirsInDocuments;
 @end
 
@@ -35,29 +35,13 @@
         [startServerButton.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor],
     ]];
 
-    auto bundleID = NSBundle.mainBundle.bundleIdentifier;
-    auto lastDotPos = [bundleID rangeOfString:@"." options:NSBackwardsSearch].location;
-    auto groupID = [NSString stringWithFormat:@"group.%@.vcmi", [bundleID substringToIndex:lastDotPos]];
     auto fm = NSFileManager.defaultManager;
-    self.sharedPathURL = [fm containerURLForSecurityApplicationGroupIdentifier:groupID];
-    if (!self.sharedPathURL)
-    {
-        NSLog(@"shared path for group '%@' not available", groupID);
+    auto sharedGameDataUrl = sharedGameDataURL();
+    if (!sharedGameDataUrl || [fm fileExistsAtPath:sharedGameDataUrl.path])
         return;
-    }
-
-    auto dirEnumerator = [fm enumeratorAtURL:self.sharedPathURL includingPropertiesForKeys:@[NSURLNameKey] options:NSDirectoryEnumerationSkipsSubdirectoryDescendants errorHandler:nil];
-    for (NSURL *fileURL in dirEnumerator)
-    {
-        NSString *filename;
-        if ([fileURL getResourceValue:&filename forKey:NSURLNameKey error:nullptr] && [filename caseInsensitiveCompare:SHARED_DATA_DIR] == NSOrderedSame) {
-            NSLog(SHARED_DATA_DIR @" dir already exists in the shared path");
-            return;
-        }
-    }
 
     auto documentsURL = [fm URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nullptr];
-    dirEnumerator = [fm enumeratorAtURL:documentsURL includingPropertiesForKeys:@[NSURLNameKey] options:NSDirectoryEnumerationSkipsSubdirectoryDescendants errorHandler:nil];
+    auto dirEnumerator = [fm enumeratorAtURL:documentsURL includingPropertiesForKeys:@[NSURLNameKey] options:NSDirectoryEnumerationSkipsSubdirectoryDescendants errorHandler:nil];
     auto dataDirs = [NSMutableArray<NSURL *> arrayWithCapacity:3];
     for (NSURL *fileURL in dirEnumerator)
     {
@@ -68,10 +52,7 @@
             [dataDirs addObject:fileURL];
     }
     if (dataDirs.count < 3)
-    {
-        NSLog(@"not all required dirs are present, found only: %@", dataDirs);
         return;
-    }
     self.dataDirsInDocuments = dataDirs;
 
     auto moveDataButton = [UIButton buttonWithType:UIButtonTypeSystem];
@@ -100,17 +81,13 @@
 
 - (void)moveDataToSharedDir:(UIButton *)button
 {
-    button.enabled = NO;
+    [button removeFromSuperview];
     dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
         auto fm = NSFileManager.defaultManager;
-        auto destinationURL = [self.sharedPathURL URLByAppendingPathComponent:SHARED_DATA_DIR];
+        auto destinationURL = sharedGameDataURL();
         [fm createDirectoryAtURL:destinationURL withIntermediateDirectories:YES attributes:nil error:nullptr];
         for (NSURL *dirURL in self.dataDirsInDocuments)
             [fm moveItemAtURL:dirURL toURL:[destinationURL URLByAppendingPathComponent:dirURL.lastPathComponent] error:nullptr];
-
-        dispatch_sync(dispatch_get_main_queue(), ^{
-            [button removeFromSuperview];
-        });
     });
 }