69               NSMutableDictionary *attributes, 
 
   70               CFStringRef contentTypeUTI,
 
   77            if (UTTypeConformsTo(contentTypeUTI, CFSTR(
"org.aegidian.oolite.save")))
 
   81            if (UTTypeConformsTo(contentTypeUTI, CFSTR(
"org.aegidian.oolite.expansion")))
 
 
   95    NSDictionary *content = [NSDictionary dictionaryWithContentsOfFile:pathToFile];
 
   96    if (content == 
nil)  
return false;
 
   98    NSString *playerName = [content oo_stringForKey:@"player_name"];
 
   99    if (playerName != 
nil)  attributes[kTitle] = playerName;
 
  101    NSString *shipDesc = [content oo_stringForKey:@"ship_desc"];
 
  102    if (shipDesc != 
nil)  attributes[kShipIDs] = shipDesc;
 
  104    NSString *shipName = [content oo_stringForKey:@"ship_name"];
 
  105    if (shipName != 
nil)  attributes[kShipClassNames] = shipName;
 
  107    NSString *currentSystemName = [content oo_stringForKey:@"current_system_name"];
 
  108    if (currentSystemName != 
nil)  attributes[kSystemName] = currentSystemName;
 
  110    NSArray *commLog = [content oo_arrayForKey:@"comm_log"];
 
  111    if (commLog.count != 0)  attributes[kTextContent] = [commLog componentsJoinedByString:@"\n"];
 
  113    NSInteger killCount = [content oo_integerForKey:@"ship_kills"];
 
  120            const int kRequiredKills[8] = { 0x0008,  0x0010,  0x0020,  0x0040,  0x0080,  0x0200,  0x0A00,  0x1900 };
 
  122            while (rating < 8 && kRequiredKills[rating] <= killCount)
 
  127            attributes[kCombatRating] = ratings[rating];
 
 
  140        NSString *title = [manifest oo_stringForKey:@"title"];
 
  141        if (title != 
nil)  attributes[kTitle] = title;
 
  143        NSString *identifier = [manifest oo_stringForKey:@"identifier"];
 
  144        if (identifier != 
nil)  attributes[kIdentifier] = identifier;
 
  146        NSString *version = [manifest oo_stringForKey:@"version"];
 
  147        if (version != 
nil)  attributes[kVersion] = version;
 
  150        id author = manifest[@"author"];
 
  151        if ([author isKindOfClass:NSString.class])  author = @[author];
 
  152        if ([author isKindOfClass:NSArray.class])  attributes[kAuthors] = author;
 
  154        NSString *description = [manifest oo_stringForKey:@"description"];
 
  155        if (description != 
nil)  attributes[kDescription] = description;
 
  157        NSString *copyright = [manifest oo_stringForKey:@"copyright"];
 
  158        if (copyright == 
nil)  copyright = [manifest oo_stringForKey:@"license"];
 
  159        if (copyright != 
nil)  attributes[kCopyright] = copyright;
 
  161        NSString *url = [manifest oo_stringForKey:@"download_url"];
 
  162        if (url == 
nil)  url = [manifest oo_stringForKey:@"information_url"];
 
  163        if (url != 
nil)  attributes[kURL] = url;
 
  165        NSString *minVersion = [manifest oo_stringForKey:@"required_oolite_version"];
 
  166        if (minVersion != 
nil)  attributes[kMinOoliteVersion] = minVersion;
 
  175            NSString *minVersion = [requires objectForKey:@"version"];
 
  176            if (minVersion != 
nil)  attributes[kMinOoliteVersion] = minVersion;
 
  178            NSString *maxVersion = [requires objectForKey:@"max_version"];
 
  179            if (maxVersion != 
nil)  attributes[kMaxOoliteVersion] = maxVersion;
 
  184        NSString *version = [infoPList oo_stringForKey:@"CFBundleVersion"];
 
  185        if (version != 
nil)  attributes[kVersion] = version;
 
  189    NSDictionary *shipDataOverrides = 
ConfigDictionary(pathToFile, 
@"shipdata-overrides.plist");
 
  192    if (shipData.count != 0)
 
  194        NSMutableSet *shipNames = [NSMutableSet setWithCapacity:shipData.count];
 
  195        NSMutableSet *shipModels = [NSMutableSet setWithCapacity:shipData.count];
 
  196        NSMutableSet *shipRoles = [NSMutableSet new];
 
  198        attributes[kShipIDs] = shipData.allKeys;
 
  200        for (NSDictionary *ship in shipData)
 
  202            if (![ship isKindOfClass:NSDictionary.class])  
continue;
 
  204            NSString *name = [ship oo_stringForKey:@"name"];
 
  205            if (name != 
nil)  [shipNames addObject:name];
 
  207            NSString *model = [ship oo_stringForKey:@"model"];
 
  208            if (model != 
nil)  [shipModels addObject:model];
 
  210            NSString *role = [ship oo_stringForKey:@"roles"];
 
  211            if (role != 
nil)  [shipRoles addObjectsFromArray:OOParseRolesFromString(role).allKeys];
 
  214        attributes[kShipClassNames] = shipNames.allObjects;
 
  215        attributes[kShipModels] = shipModels.allObjects;
 
  216        attributes[kShipRoles] = shipRoles.allObjects;
 
 
  237    NSString *path = [[basePath stringByAppendingPathComponent:@"Config"] stringByAppendingPathComponent:name];
 
  238    NSData *data = [NSData oo_dataWithOXZFile:path];
 
  241        path = [basePath stringByAppendingPathComponent:name];
 
  242        data = [NSData oo_dataWithOXZFile:path];
 
  246        id plist = [NSPropertyListSerialization propertyListWithData:data
 
  250        if ([plist isKindOfClass:NSDictionary.class])  
return plist;
 
 
  257static NSDictionary *
MergeShipData(NSDictionary *shipData, NSDictionary *shipDataOverrides)
 
  259    NSDictionary            *baseDict = 
nil;
 
  260    NSDictionary            *overrideDict = 
nil;
 
  262    if (shipDataOverrides == 
nil)  
return shipData;
 
  263    if (shipData == 
nil)  
return shipDataOverrides;
 
  265    NSMutableDictionary *mutableShipData = [NSMutableDictionary dictionaryWithDictionary:shipData];
 
  266    for (NSString *key in shipDataOverrides)
 
  268        baseDict = [shipData oo_dictionaryForKey:key];
 
  269        overrideDict = [shipDataOverrides oo_dictionaryForKey:key];
 
  273    return mutableShipData;
 
 
  292    NSMutableDictionary     *result = 
nil;
 
  293    NSArray                 *tokens = 
nil;
 
  295    NSString                *role = 
nil;
 
  297    NSScanner               *scanner = 
nil;
 
  300    if (
string == 
nil)  
return nil;
 
  303    count = [tokens count];
 
  306    result = [NSMutableDictionary dictionaryWithCapacity:count];
 
  309    for (i = 0; i != 
count; ++i)
 
  311        role = [tokens objectAtIndex:i];
 
  314        if ([role rangeOfString:
@"("].location != NSNotFound)
 
  316            scanner = [[NSScanner alloc] initWithString:role];
 
  317            [scanner scanUpToString:@"(" intoString:&role];
 
  318            [scanner scanString:@"(" intoString:NULL];
 
  319            if (![scanner scanFloat:&probability])  probability = 1.0f;
 
  324        if (0 <= probability && ![role hasPrefix:
@"["])
 
  326            [result setObject:[NSNumber numberWithFloat:probability] forKey:role];
 
  330    if ([result 
count] == 0)  result = 
nil;
 
 
  337    NSMutableArray          *result = 
nil;
 
  338    NSScanner               *scanner = 
nil;
 
  339    NSString                *token = 
nil;
 
  340    static NSCharacterSet   *space_set = 
nil;
 
  342    if (values == 
nil)  
return [NSMutableArray array];
 
  343    if (space_set == 
nil) space_set = [NSCharacterSet whitespaceAndNewlineCharacterSet];
 
  345    result = [NSMutableArray array];
 
  346    scanner = [NSScanner scannerWithString:values];
 
  348    while (![scanner isAtEnd])
 
  350        [scanner ooliteScanCharactersFromSet:space_set intoString:NULL];
 
  351        if ([scanner ooliteScanUpToCharactersFromSet:space_set intoString:&token])
 
  353            [result addObject:token];