34#import "MyOpenGLView.h"
63@interface ResourceManager (OOPrivate)
65+ (void) checkOXPMessagesInPath:(NSString *)path;
66+ (void) checkPotentialPath:(NSString *)path :(NSMutableArray *)searchPaths;
67+ (BOOL) validateManifest:(NSDictionary*)manifest forOXP:(NSString *)path;
68+ (BOOL) areRequirementsFulfilled:(NSDictionary*)requirements forOXP:(NSString *)path andFile:(NSString *)file;
69+ (void) filterSearchPathsForConflicts:(NSMutableArray *)searchPaths;
70+ (BOOL) filterSearchPathsForRequirements:(NSMutableArray *)searchPaths;
71+ (void) filterSearchPathsToExcludeScenarioOnlyPaths:(NSMutableArray *)searchPaths;
72+ (void) filterSearchPathsByScenario:(NSMutableArray *)searchPaths;
73+ (BOOL) manifestAllowedByScenario:(NSDictionary *)manifest;
74+ (BOOL) manifestAllowedByScenario:(NSDictionary *)manifest withIdentifier:(NSString *)identifier;
75+ (BOOL) manifestAllowedByScenario:(NSDictionary *)manifest withTag:(NSString *)tag;
77+ (void) addErrorWithKey:(NSString *)descriptionKey param1:(
id)param1 param2:(
id)param2;
78+ (BOOL) checkCacheUpToDateForPaths:(NSArray *)searchPaths;
80+ (void) mergeRoleCategories:(NSDictionary *)catData intoDictionary:(NSMutableDictionary *)category;
82+ (void) preloadFileListFromOXZ:(NSString *)path forFolders:(NSArray *)folders;
83+ (void) preloadFileListFromFolder:(NSString *)path forFolders:(NSArray *)folders;
84+ (void) preloadFilePathFor:(NSString *)fileName inFolder:(NSString *)subFolder atPath:(NSString *)path;
135 NSArray *error =
nil;
137 NSMutableArray *result =
nil;
138 NSString *errStr =
nil;
140 count = [sErrors count];
145 for (i = 0; i !=
count; ++i)
147 error = [sErrors objectAtIndex:i];
148 errStr = [UNIVERSE descriptionForKey:[
error oo_stringAtIndex:0]];
151 errStr = [
NSString stringWithFormat:errStr, [
error objectAtIndex:1], [
error objectAtIndex:2]];
152 [
result addObject:errStr];
159 return [
result componentsJoinedByString:@"\n"];
165 static NSArray *sRootPaths =
nil;
166 if (sRootPaths ==
nil) {
178 static NSArray *sUserRootPaths =
nil;
180 if (sUserRootPaths ==
nil)
183 NSArray *defaultAddOnsPaths = [
NSArray arrayWithObjects:
186 stringByAppendingPathComponent:@"Application Support"]
187 stringByAppendingPathComponent:@"Oolite"]
188 stringByAppendingPathComponent:@"AddOns"],
189 [[[[
NSBundle mainBundle] bundlePath]
190 stringByDeletingLastPathComponent]
191 stringByAppendingPathComponent:@"AddOns"],
200 OOLog(
@"searchPaths.debug",
@"%@",sUserRootPaths);
201 return sUserRootPaths;
213 return [[
NSBundle mainBundle] resourcePath];
225 sUseAddOnsParts = [[sUseAddOns componentsSeparatedByString:@";"] retain];
240 NSMutableArray *existingRootPaths =
nil;
241 NSEnumerator *pathEnum =
nil;
242 NSString *root =
nil;
243 NSDirectoryEnumerator *dirEnum =
nil;
244 NSString *subPath =
nil;
245 NSString *path =
nil;
250 existingRootPaths = [
NSMutableArray arrayWithCapacity:[rootPaths count]];
253 if ([fmgr fileExistsAtPath:root isDirectory:&isDirectory] && isDirectory)
262 foreach(path, existingRootPaths)
268 for (pathEnum = [existingRootPaths objectEnumerator]; (root = [
pathEnum nextObject]); )
271 if ([fmgr fileExistsAtPath:root isDirectory:&isDirectory] && isDirectory)
273 for (dirEnum = [fmgr enumeratorAtPath:root]; (subPath = [
dirEnum nextObject]); )
276 path = [
root stringByAppendingPathComponent:subPath];
277 if ([fmgr fileExistsAtPath:path isDirectory:&isDirectory])
282 if ([[[path pathExtension] lowercaseString] isEqualToString:
@"oxp"])
296 if ([[[path pathExtension] lowercaseString] isEqualToString:
@"oxz"])
339 while (![
self filterSearchPathsForRequirements:
sSearchPaths]) {}
357 NSString *path =
nil;
358 NSEnumerator *pathEnum =
nil;
361 NSArray *folders = [
NSArray arrayWithObjects:@"AIs",@"Images",@"Models",@"Music",@"Scenarios",@"Scripts",@"Shaders",@"Sounds",@"Textures",nil];
365 if ([path hasSuffix:
@".oxz"])
377+ (void) preloadFileListFromOXZ:(NSString *)path forFolders:(NSArray *)folders
380 const char* zipname = [
path UTF8String];
381 char componentName[512];
389 OOLog(
@"resourceManager.error",
@"Could not open .oxz at %@ as zip file",path);
400 NSString *zipEntry = [
NSString stringWithUTF8String:componentName];
401 NSArray *pathBits = [
zipEntry pathComponents];
402 if ([pathBits
count] >= 2)
404 NSString *folder = [
pathBits oo_stringAtIndex:0];
405 if ([folders containsObject:folder])
408 bitRange.location = 1;
409 bitRange.length = [
pathBits count]-1;
410 NSString *file = [
NSString pathWithComponents:[
pathBits subarrayWithRange:bitRange]];
411 NSString *fullPath = [[
path stringByAppendingPathComponent:folder] stringByAppendingPathComponent:file];
424+ (void) preloadFileListFromFolder:(NSString *)path forFolders:(NSArray *)folders
427 NSString *subFolder =
nil;
428 NSString *subFolderPath =
nil;
429 NSArray *fileList =
nil;
430 NSString *fileName =
nil;
433 foreach (subFolder, folders)
435 subFolderPath = [
path stringByAppendingPathComponent:subFolder];
436 fileList = [
fmgr oo_directoryContentsAtPath:subFolderPath];
437 foreach (fileName, fileList)
445+ (void) preloadFilePathFor:(NSString *)fileName inFolder:(NSString *)subFolder atPath:(NSString *)path
448 NSString *cacheKey = [
NSString stringWithFormat:@"%@/%@", subFolder, fileName];
453 OOLog(
@"resourceManager.foundFile.preLoad",
@"Found %@/%@ at %@", subFolder, fileName, path);
469+ (NSArray *)maskUserNameInPathArray:(NSArray *)inputPathArray
471 NSString *path =
nil;
473 char *userNamePathEnvVar =
475 SDL_getenv(
"USERPROFILE");
479 NSString *userName = [[
NSString stringWithFormat:@"%s", userNamePathEnvVar] lastPathComponent];
480 foreach (path, inputPathArray)
489+ (NSString *)maskUserName:(NSString *)name inPath:(NSString *)path
492 if (result && name) [
result replaceOccurrencesOfString:name withString:@"*"
493 options:NSLiteralSearch
494 range:NSMakeRange(0, [
result length])
496 return [
NSString stringWithString:result];
506+ (void)setUseAddOns:(NSString *)useAddOns
515 sUseAddOnsParts = [[sUseAddOns componentsSeparatedByString:@";"] retain];
546+ (void) addExternalPath:(NSString *)path
551 [sSearchPaths addObject:path];
554 [sExternalPaths addObject:path];
561 return [[
self paths] objectEnumerator];
567 return [[
self paths] reverseObjectEnumerator];
573 return [[sOXPsWithMessagesFound copy] autorelease];
577+ (NSDictionary *)manifestForIdentifier:(NSString *)identifier
579 return [sOXPManifests objectForKey:identifier];
583+ (void) checkOXPMessagesInPath:(NSString *)path
585 NSArray *OXPMessageArray =
OOArrayFromFile([path stringByAppendingPathComponent:
@"OXPMessages.plist"]);
587 if ([OXPMessageArray
count] > 0)
595 OOLog(
@"oxp.message",
@"%@: %@", path, oxpMessage);
599 [sOXPsWithMessagesFound addObject:[
path lastPathComponent]];
605+ (void)checkPotentialPath:(NSString *)path :(NSMutableArray *)searchPaths
607 NSDictionary *requirements =
nil;
608 NSDictionary *manifest =
nil;
609 BOOL requirementsMet = YES;
611 if (![[[path pathExtension] lowercaseString] isEqualToString:
@"oxz"])
617 if (!requirementsMet)
619 NSString *version = [[[
NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
620 OOLog(
@"oxp.versionMismatch",
@"OXP %@ is incompatible with version %@ of Oolite.", path, version);
628 if ([[[path pathExtension] lowercaseString] isEqualToString:
@"oxz"])
630 OOLog(
@"oxp.noManifest",
@"OXZ %@ has no manifest.plist", path);
636 if ([[[path pathExtension] lowercaseString] isEqualToString:
@"oxp"])
638 OOStandardsError([NSString stringWithFormat:
@"OXP %@ has no manifest.plist", path]);
646 manifest = [
NSDictionary dictionaryWithObjectsAndKeys:[
NSString stringWithFormat:@"__oolite.tmp.%@",path],kOOManifestIdentifier,@"1",kOOManifestVersion,@"OXP without manifest",kOOManifestTitle,@"1",kOOManifestRequiredOoliteVersion,nil];
660+ (BOOL) validateManifest:(NSDictionary*)manifest forOXP:(NSString *)path
668 NSString *identifier = [
manifest oo_stringForKey:kOOManifestIdentifier defaultValue:nil];
669 NSString *version = [
manifest oo_stringForKey:kOOManifestVersion defaultValue:nil];
670 NSString *required = [
manifest oo_stringForKey:kOOManifestRequiredOoliteVersion defaultValue:nil];
671 NSString *title = [
manifest oo_stringForKey:kOOManifestTitle defaultValue:nil];
673 if (identifier ==
nil)
705 NSString *version = [[[
NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
706 OOLog(
@"oxp.versionMismatch",
@"OXP %@ is incompatible with version %@ of Oolite.", path, version);
711 NSDictionary *duplicate = [sOXPManifests objectForKey:identifier];
712 if (duplicate !=
nil)
714 OOLog(
@"oxp.duplicate",
@"OXP %@ has the same identifier (%@) as %@ which has already been loaded.",path,identifier,[duplicate oo_stringForKey:
kOOManifestFilePath]);
719 [
mData setObject:path forKey:kOOManifestFilePath];
721 [sOXPManifests setObject:mData forKey:identifier];
726+ (BOOL) checkVersionCompatibility:(NSDictionary *)manifest forOXP:(NSString *)title
728 NSString *required = [
manifest oo_stringForKey:kOOManifestRequiredOoliteVersion defaultValue:nil];
729 NSString *maxRequired = [
manifest oo_stringForKey:kOOManifestMaximumOoliteVersion defaultValue:nil];
731 if (maxRequired ==
nil || [maxRequired length] == 0)
742+ (BOOL) areRequirementsFulfilled:(NSDictionary*)requirements forOXP:(NSString *)path andFile:(NSString *)file
745 NSString *requiredVersion =
nil;
746 NSString *maxVersion =
nil;
747 unsigned conditionsHandled = 0;
748 static NSArray *ooVersionComponents =
nil;
749 NSArray *oxpVersionComponents =
nil;
751 if (requirements ==
nil)
return YES;
753 if (ooVersionComponents ==
nil)
763 requiredVersion = [
requirements objectForKey:@"version"];
764 if (requiredVersion !=
nil)
767 if ([requiredVersion isKindOfClass:[NSString
class]])
770 if (NSOrderedAscending ==
CompareVersions(ooVersionComponents, oxpVersionComponents)) OK = NO;
774 OOLog(
@"requirements.wrongType",
@"Expected %@ entry \"%@\
" to be string, but got %@ in OXP %@.", file,
@"version", [requirements
class], [path lastPathComponent]);
784 maxVersion = [
requirements objectForKey:@"max_version"];
785 if (maxVersion !=
nil)
788 if ([maxVersion isKindOfClass:[NSString
class]])
791 if (NSOrderedDescending ==
CompareVersions(ooVersionComponents, oxpVersionComponents)) OK = NO;
795 OOLog(
@"requirements.wrongType",
@"Expected %@ entry \"%@\
" to be string, but got %@ in OXP %@.", file,
@"max_version", [requirements
class], [path lastPathComponent]);
801 if (OK && conditionsHandled < [requirements
count])
804 OOLog(
@"requirements.unknown",
@"requires.plist for OXP %@ contains unknown keys, rejecting.", [path lastPathComponent]);
812+ (BOOL) manifestHasConflicts:(NSDictionary *)manifest logErrors:(BOOL)logErrors
814 NSDictionary *conflicting =
nil;
815 NSDictionary *conflictManifest =
nil;
816 NSString *conflictID =
nil;
817 NSArray *conflicts =
nil;
819 conflicts = [
manifest oo_arrayForKey:kOOManifestConflictOXPs defaultValue:nil];
821 if (conflicts !=
nil && [conflicts
count] > 0)
824 foreach (conflicting, conflicts)
826 conflictID = [
conflicting oo_stringForKey:kOOManifestRelationIdentifier];
827 conflictManifest = [sOXPManifests objectForKey:conflictID];
829 if (conflictManifest !=
nil)
832 if ([
self matchVersions:conflicting withVersion:[conflictManifest oo_stringForKey:
kOOManifestVersion]])
837 OOLog(
@"oxp.conflict",
@"OXP %@ conflicts with %@ and was removed from the loading list",[[manifest oo_stringForKey:
kOOManifestFilePath] lastPathComponent],[[conflictManifest oo_stringForKey:
kOOManifestFilePath] lastPathComponent]);
848+ (void) filterSearchPathsForConflicts:(NSMutableArray *)searchPaths
850 NSDictionary *manifest =
nil;
851 NSString *identifier =
nil;
852 NSArray *identifiers = [sOXPManifests allKeys];
856 foreach (identifier, identifiers)
858 manifest = [sOXPManifests objectForKey:identifier];
861 if ([
self manifestHasConflicts:manifest logErrors:YES])
865 [sOXPManifests removeObjectForKey:identifier];
872+ (BOOL) manifestHasMissingDependencies:(NSDictionary *)manifest logErrors:(BOOL)logErrors
874 NSDictionary *required =
nil;
875 NSArray *requireds =
nil;
877 requireds = [
manifest oo_arrayForKey:kOOManifestRequiresOXPs defaultValue:nil];
879 if (requireds !=
nil && [requireds
count] > 0)
882 foreach (required, requireds)
884 if ([
ResourceManager manifest:manifest HasUnmetDependency:required logErrors:logErrors])
894+ (BOOL) manifest:(NSDictionary *)manifest HasUnmetDependency:(NSDictionary *)required logErrors:(BOOL)logErrors
896 NSString *requiredID = [
required oo_stringForKey:kOOManifestRelationIdentifier];
897 NSMutableDictionary *requiredManifest = [sOXPManifests objectForKey:requiredID];
899 BOOL requirementsMet = NO;
900 if (requiredManifest !=
nil)
903 if ([
self matchVersions:required withVersion:[requiredManifest oo_stringForKey:
kOOManifestVersion]])
905 requirementsMet = YES;
909 NSUInteger reqbycount = [
reqby count];
913 reqby = [
reqby setByAddingObject:[
manifest oo_stringForKey:kOOManifestIdentifier]];
915 reqby = [
reqby setByAddingObjectsFromSet:[
manifest oo_setForKey:kOOManifestRequiredBy]];
916 if (reqbycount < [reqby
count])
928 if (!requirementsMet)
933 OOLog(
@"oxp.requirementMissing",
@"OXP %@ had unmet requirements and was removed from the loading list",[[manifest oo_stringForKey:
kOOManifestFilePath] lastPathComponent]);
941+ (BOOL) filterSearchPathsForRequirements:(NSMutableArray *)searchPaths
943 NSDictionary *manifest =
nil;
944 NSString *identifier =
nil;
945 NSArray *identifiers = [sOXPManifests allKeys];
951 foreach (identifier, identifiers)
953 manifest = [sOXPManifests objectForKey:identifier];
956 if ([
self manifestHasMissingDependencies:manifest logErrors:YES])
960 [sOXPManifests removeObjectForKey:identifier];
970+ (BOOL) matchVersions:(NSDictionary *)rangeDict withVersion:(NSString *)version
972 NSString *minimum = [
rangeDict oo_stringForKey:kOOManifestRelationVersion defaultValue:nil];
973 NSString *maximum = [
rangeDict oo_stringForKey:kOOManifestRelationMaxVersion defaultValue:nil];
975 NSArray *reqVersionComponents =
nil;
979 if (NSOrderedAscending ==
CompareVersions(isVersionComponents, reqVersionComponents))
988 if (NSOrderedDescending ==
CompareVersions(isVersionComponents, reqVersionComponents))
999+ (void) filterSearchPathsToExcludeScenarioOnlyPaths:(NSMutableArray *)searchPaths
1001 NSDictionary *manifest =
nil;
1002 NSString *identifier =
nil;
1003 NSArray *identifiers = [sOXPManifests allKeys];
1007 foreach (identifier, identifiers)
1009 manifest = [sOXPManifests objectForKey:identifier];
1010 if (manifest !=
nil)
1015 [sOXPManifests removeObjectForKey:identifier];
1023+ (void) filterSearchPathsByScenario:(NSMutableArray *)searchPaths
1025 NSDictionary *manifest =
nil;
1026 NSString *identifier =
nil;
1027 NSArray *identifiers = [sOXPManifests allKeys];
1031 foreach (identifier, identifiers)
1033 manifest = [sOXPManifests objectForKey:identifier];
1034 if (manifest !=
nil)
1040 [sOXPManifests removeObjectForKey:identifier];
1047+ (BOOL) manifestAllowedByScenario:(NSDictionary *)manifest
1054 OOLog(
@"scenario.check",
@"%@",
@"Checked scenario allowances in all state - this is an internal error; please report this");
1059 OOLog(
@"scenario.check",
@"%@",
@"Checked scenario allowances in none state - this is an internal error; please report this");
1069 NSString *uaoBit =
nil;
1086+ (BOOL) manifestAllowedByScenario:(NSDictionary *)manifest withIdentifier:(NSString *)identifier
1104+ (BOOL) manifestAllowedByScenario:(NSDictionary *)manifest withTag:(NSString *)tag
1113 NSSet *reqby = [
manifest oo_setForKey:kOOManifestRequiredBy];
1116 NSString *identifier =
nil;
1117 foreach (identifier, reqby)
1119 NSDictionary *reqManifest = [sOXPManifests oo_dictionaryForKey:identifier defaultValue:nil];
1121 if (reqManifest !=
nil && [[reqManifest oo_arrayForKey:
kOOManifestTags] containsObject:tag])
1133+ (void) addErrorWithKey:(NSString *)descriptionKey param1:(
id)param1 param2:(
id)param2
1135 if (descriptionKey !=
nil)
1138 [sErrors addObject:[
NSArray arrayWithObjects:descriptionKey, param1 ?: (id)@"", param2 ?: (id)@"", nil]];
1143+ (BOOL)checkCacheUpToDateForPaths:(NSArray *)searchPaths
1153 BOOL upToDate = YES;
1155 NSMutableArray *modDates =
nil;
1156 NSEnumerator *pathEnum =
nil;
1157 NSString *path =
nil;
1160 if (
EXPECT_NOT([[NSUserDefaults standardUserDefaults] boolForKey:
@"always-flush-cache"]))
1172 if (upToDate && ![oldPaths isEqual:searchPaths])
1182 for (pathEnum = [searchPaths objectEnumerator]; (path = [
pathEnum nextObject]); )
1184 modDate = [[
fmgr oo_fileAttributesAtPath:path traverseLink:YES] objectForKey:NSFileModificationDate];
1188 modDate = [
NSNumber numberWithDouble:[
modDate timeIntervalSince1970]];
1219+ (BOOL) corePlist:(NSString *)fileName excludedAt:(NSString *)path
1226 NSString *uaoBit =
nil;
1231 NSString *plist = [
uaoBit substringFromIndex:[SCENARIO_OXP_DEFINITION_NOPLIST length]];
1232 if ([plist isEqualToString:fileName])
1244+ (NSDictionary *)dictionaryFromFilesNamed:(NSString *)fileName
1245 inFolder:(NSString *)folderName
1246 andMerge:(BOOL) mergeFiles
1248 return [
ResourceManager dictionaryFromFilesNamed:fileName inFolder:folderName mergeMode:mergeFiles ? MERGE_BASIC : MERGE_NONE cache:YES];
1252+ (NSDictionary *)dictionaryFromFilesNamed:(NSString *)fileName
1253 inFolder:(NSString *)folderName
1258 NSMutableArray *results =
nil;
1259 NSString *cacheKey =
nil;
1260 NSString *mergeType =
nil;
1262 NSEnumerator *enumerator =
nil;
1263 NSString *path =
nil;
1264 NSString *dictPath =
nil;
1265 NSDictionary *dict =
nil;
1267 if (fileName ==
nil)
return nil;
1272 mergeType =
@"none";
1276 mergeType =
@"basic";
1280 mergeType =
@"smart";
1283 if (mergeType ==
nil)
1285 OOLog(
kOOLogParameterError,
@"Unknown dictionary merge mode %u for %@. (This is an internal programming error, please report it.)", mergeMode, fileName);
1292 if (folderName !=
nil)
1294 cacheKey = [
NSString stringWithFormat:@"%@/%@ merge:%@", folderName, fileName, mergeType];
1298 cacheKey = [
NSString stringWithFormat:@"%@ merge:%@", fileName, mergeType];
1301 if (result !=
nil)
return result;
1309 if (folderName !=
nil)
1311 dictPath = [[
path stringByAppendingPathComponent:folderName] stringByAppendingPathComponent:fileName];
1313 if (dict !=
nil)
break;
1315 dictPath = [
path stringByAppendingPathComponent:fileName];
1317 if (dict !=
nil)
break;
1331 dictPath = [
path stringByAppendingPathComponent:fileName];
1334 if (folderName !=
nil)
1336 dictPath = [[
path stringByAppendingPathComponent:folderName] stringByAppendingPathComponent:fileName];
1342 if ([results
count] == 0)
return nil;
1347 for (enumerator = [results objectEnumerator]; (dict = [
enumerator nextObject]); )
1350 else [
result addEntriesFromDictionary:dict];
1352 result = [[
result copy] autorelease];
1361+ (NSArray *) arrayFromFilesNamed:(NSString *)fileName inFolder:(NSString *)folderName andMerge:(BOOL) mergeFiles
1367+ (NSArray *) arrayFromFilesNamed:(NSString *)fileName inFolder:(NSString *)folderName andMerge:(BOOL) mergeFiles cache:(BOOL)useCache
1370 NSMutableArray *results =
nil;
1371 NSString *cacheKey =
nil;
1373 NSEnumerator *enumerator =
nil;
1374 NSString *path =
nil;
1375 NSString *arrayPath =
nil;
1376 NSMutableArray *array =
nil;
1377 NSArray *arrayNonEditable =
nil;
1379 if (fileName ==
nil)
return nil;
1383 cacheKey = [
NSString stringWithFormat:@"%@%@ merge:%@", (folderName != nil) ? [
folderName stringByAppendingString:@"/"] : (NSString *)@"", fileName, mergeFiles ? @"yes" : @"no"];
1385 if (result !=
nil)
return result;
1393 if (folderName !=
nil)
1395 arrayPath = [[
path stringByAppendingPathComponent:folderName] stringByAppendingPathComponent:fileName];
1397 if (arrayNonEditable !=
nil)
break;
1399 arrayPath = [
path stringByAppendingPathComponent:fileName];
1401 if (arrayNonEditable !=
nil)
break;
1403 result = arrayNonEditable;
1416 arrayPath = [
path stringByAppendingPathComponent:fileName];
1417 array = [[OOArrayFromFile(arrayPath) mutableCopy] autorelease];
1426 if ([array
count] != 0 && ([[fileName lowercaseString] isEqualToString:
@"nebulatextures.plist"] ||
1427 [[fileName lowercaseString] isEqualToString:
@"startextures.plist"]))
1430 if ([array
count] != 0 && [[array objectAtIndex:0] isKindOfClass:[NSArray
class]])
1432 if ([[fileName lowercaseString] isEqualToString:
@"equipment.plist"])
1435 if (folderName !=
nil)
1437 arrayPath = [[
path stringByAppendingPathComponent:folderName] stringByAppendingPathComponent:fileName];
1438 array = [[OOArrayFromFile(arrayPath) mutableCopy] autorelease];
1441 if ([array
count] != 0 && ([[fileName lowercaseString] isEqualToString:
@"nebulatextures.plist"] ||
1442 [[fileName lowercaseString] isEqualToString:
@"startextures.plist"]))
1445 if ([array
count] != 0 && [[array objectAtIndex:0] isKindOfClass:[NSArray
class]])
1447 if ([[fileName lowercaseString] isEqualToString:
@"equipment.plist"])
1453 if ([results
count] == 0)
return nil;
1458 for (enumerator = [results objectEnumerator]; (array = [
enumerator nextObject]); )
1460 [
result addObjectsFromArray:array];
1463 if ([[fileName lowercaseString] isEqualToString:
@"equipment.plist"])
1467 result = [[
result copy] autorelease];
1472 return [
NSArray arrayWithArray:result];
1479+ (void) handleEquipmentListMerging: (NSMutableArray *)arrayToProcess forLookupIndex:(
unsigned)lookupIndex
1486 for (i = 0; i < [
refArray count]; i++)
1491 if (
count == 0)
continue;
1493 for (k=0; k <
count; k++)
1495 id processValue = [[[
arrayToProcess oo_arrayAtIndex:j] oo_arrayAtIndex:k] oo_objectAtIndex:lookupIndex defaultValue:nil];
1496 id refValue = [[
refArray oo_arrayAtIndex:i] oo_objectAtIndex:lookupIndex defaultValue:nil];
1498 if ([processValue isEqual:refValue])
1514+ (void) handleEquipmentOverrides: (NSMutableArray *)arrayToProcess
1516 NSEnumerator *equipKeyEnum =
nil;
1517 NSString *equipKey =
nil;
1518 NSDictionary *overrides =
nil;
1519 NSDictionary *overridesEntry =
nil;
1528 for (equipKeyEnum = [overrides keyEnumerator]; (equipKey = [
equipKeyEnum nextObject]); )
1530 overridesEntry = [
overrides objectForKey:equipKey];
1534 NSMutableArray *equipArray = [[[
arrayToProcess objectAtIndex:i] mutableCopy] autorelease];
1535 id refValue = [
equipArray oo_objectAtIndex:EQUIPMENT_KEY_INDEX defaultValue:nil];
1537 if ([equipKey isEqual:refValue])
1539 NSEnumerator *infoKeyEnum =
nil;
1542 for (infoKeyEnum = [overridesEntry keyEnumerator]; (infoKey = [
infoKeyEnum nextObject]); )
1545 if ([infoKey isEqualToString:
@"techlevel"])
1547 else if ([infoKey isEqualToString:
@"price"])
1549 else if ([infoKey isEqualToString:
@"short_description"])
1551 else if ([infoKey isEqualToString:
@"name"])
1553 else if ([infoKey isEqualToString:
@"long_description"])
1555 else if ([infoKey isEqualToString:
@"description"])
1559 NSMutableDictionary *extra =
nil;
1569 extra = [[
equipArray oo_dictionaryAtIndex:EQUIPMENT_EXTRA_INFO_INDEX] mutableCopy];
1572 if ([infoKey isEqualToString:
@"weapon_info"] || [infoKey isEqualToString:
@"script_info"])
1574 NSEnumerator *subEnum =
nil;
1576 NSMutableDictionary *subInfo =
nil;
1577 NSDictionary *subOverrides =
nil;
1579 if (![extra oo_dictionaryForKey:infoKey])
1586 subInfo = [[
extra oo_dictionaryForKey:infoKey] mutableCopy];
1590 for (subEnum = [subOverrides keyEnumerator]; (subKey = [
subEnum nextObject]); )
1594 [
extra setObject:[[
subInfo copy] autorelease] forKey:infoKey];
1601 [
equipArray replaceObjectAtIndex:EQUIPMENT_EXTRA_INFO_INDEX withObject:[[
extra copy] autorelease]];
1613+ (void) handleStarNebulaListMerging: (NSMutableArray *)arrayToProcess
1619 for (i = 0; i < [
refArray count]; i++)
1624 if (
count == 0)
continue;
1626 for (k = 0; k <
count; k++)
1628 id processValue = [[
arrayToProcess oo_arrayAtIndex:j] oo_objectAtIndex:k defaultValue:nil];
1629 id refValue = [
refArray oo_objectAtIndex:i defaultValue:nil];
1630 NSString *key1 =
nil;
1631 NSString *key2 =
nil;
1633 if ([processValue isKindOfClass:[NSString
class]])
1635 key1 = processValue;
1637 else if ([processValue isKindOfClass:[NSDictionary
class]])
1639 if (![processValue objectForKey:
@"key"])
1648 if (!key1)
continue;
1650 if ([refValue isKindOfClass:[NSString
class]])
1654 else if ([refValue isKindOfClass:[NSDictionary
class]])
1656 if (![refValue objectForKey:
@"key"])
1658 key2 = [
refValue objectForKey:@"texture"];
1662 key2 = [
refValue objectForKey:@"key"];
1665 if (!key2)
continue;
1667 if ([key1 isEqual:key2])
1686 NSString *path = [[[
ResourceManager builtInPath] stringByAppendingPathComponent:@"Config"] stringByAppendingPathComponent:@"whitelist.plist"];
1690 [whitelistDictionary retain];
1700 NSRange dot = [
key rangeOfString:@"."];
1701 if (dot.location != NSNotFound)
1703 return [
key substringToIndex:dot.location];
1716 stringByAppendingPathComponent:@"logcontrol.plist"];
1717 NSMutableDictionary *logControl = [
NSMutableDictionary dictionaryWithDictionary:OODictionaryFromFile(path)];
1722 NSString *key =
nil;
1725 [
coreRoots addObject:LogClassKeyRoot(key)];
1729 NSString *configPath =
nil;
1730 NSDictionary *dict =
nil;
1734 while ((path = [pathEnum nextObject]))
1736 if ([
rootPaths containsObject:path])
continue;
1738 configPath = [[
path stringByAppendingPathComponent:@"Config"]
1739 stringByAppendingPathComponent:@"logcontrol.plist"];
1743 configPath = [
path stringByAppendingPathComponent:@"logcontrol.plist"];
1756 pathEnum = [rootPaths objectEnumerator];
1757 while ((path = [pathEnum nextObject]))
1759 configPath = [[
path stringByAppendingPathComponent:@"Config"]
1760 stringByAppendingPathComponent:@"logcontrol.plist"];
1764 configPath = [
path stringByAppendingPathComponent:@"logcontrol.plist"];
1774 dict = [[
NSUserDefaults standardUserDefaults] dictionaryForKey:@"logging-enable"];
1775 if (dict !=
nil) [
logControl addEntriesFromDictionary:dict];
1785 NSString *path =
nil;
1786 NSString *configPath =
nil;
1787 NSDictionary *categories =
nil;
1790 while ((path = [pathEnum nextObject]))
1792 if ([
ResourceManager corePlist:
@"role-categories.plist" excludedAt:path])
1797 configPath = [[
path stringByAppendingPathComponent:@"Config"]
1798 stringByAppendingPathComponent:@"role-categories.plist"];
1800 if (categories !=
nil)
1818+ (void) mergeRoleCategories:(NSDictionary *)catData intoDictionary:(NSMutableDictionary *)categories
1820 NSMutableSet *contents =
nil;
1821 NSArray *catDataEntry =
nil;
1826 if (contents ==
nil)
1831 catDataEntry = [
catData oo_arrayForKey:key];
1832 OOLog(
@"shipData.load.roleCategories",
@"Adding %ld entries for category %@", (
unsigned long)[catDataEntry
count], key);
1833 [
contents addObjectsFromArray:catDataEntry];
1840 OOLog(
@"resourceManager.planetinfo.load",
@"%@",
@"Initialising manager");
1843 NSString *path =
nil;
1844 NSString *configPath =
nil;
1845 NSDictionary *categories =
nil;
1846 NSString *systemKey =
nil;
1849 while ((path = [pathEnum nextObject]))
1855 configPath = [[
path stringByAppendingPathComponent:@"Config"]
1856 stringByAppendingPathComponent:@"planetinfo.plist"];
1858 if (categories !=
nil)
1862 NSDictionary *values = [
categories oo_dictionaryForKey:systemKey defaultValue:nil];
1881 OOLog(
@"resourceManager.planetinfo.load",
@"%@",
@"Caching routes");
1883 OOLog(
@"resourceManager.planetinfo.load",
@"%@",
@"Initialised manager");
1897 NSString *path = [[[
ResourceManager builtInPath] stringByAppendingPathComponent:@"Config"] stringByAppendingPathComponent:@"shader-uniform-bindings.plist"];
1899 NSArray *keys = [
dict allKeys];
1902 unsigned changeCount = 0;
1905 NSString *key =
nil;
1908 NSDictionary *value = [
dict oo_dictionaryForKey:key];
1909 NSString *inheritKey = [
value oo_stringForKey:@"$w306"];
1910 if (inheritKey !=
nil)
1913 NSMutableDictionary *mutableValue = [[
value mutableCopy] autorelease];
1915 NSDictionary *inherited = [
dict oo_dictionaryForKey:inheritKey];
1916 if (inherited !=
nil)
1924 }
while (changeCount != 0);
1935+ (NSString *) pathForFileNamed:(NSString *)fileName inFolder:(NSString *)folderName
1942+ (NSString *) pathForFileNamed:(NSString *)fileName inFolder:(NSString *)folderName cache:(BOOL)useCache
1944 NSString *result =
nil;
1945 NSString *cacheKey =
nil;
1947 NSEnumerator *pathEnum =
nil;
1948 NSString *path =
nil;
1949 NSString *filePath =
nil;
1950 NSFileManager *fmgr =
nil;
1952 if (fileName ==
nil)
return nil;
1956 if (folderName !=
nil) cacheKey = [
NSString stringWithFormat:@"%@/%@", folderName, fileName];
1957 else cacheKey = fileName;
1959 if (result !=
nil)
return result;
1967 filePath = [[
path stringByAppendingPathComponent:folderName] stringByAppendingPathComponent:fileName];
1968 if ([fmgr oo_oxzFileExistsAtPath:filePath])
1974 filePath = [
path stringByAppendingPathComponent:fileName];
1975 if ([fmgr oo_oxzFileExistsAtPath:filePath])
1984 OOLog(
@"resourceManager.foundFile",
@"Found %@/%@ at %@", folderName, fileName, filePath);
1996+ (id) retrieveFileNamed:(NSString *)fileName
1997 inFolder:(NSString *)folderName
1998 cache:(NSMutableDictionary **)ioCache
2001 usePathCache:(BOOL)useCache
2004 NSString *path =
nil;
2008 if (key ==
nil) key = [
NSString stringWithFormat:@"%@:%@", folderName, fileName];
2009 if (*ioCache !=
nil)
2012 result = [*
ioCache objectForKey:key];
2013 if (result)
return result;
2018 if (path !=
nil) result = [[[
class alloc] initWithContentsOfFile:path] autorelease];
2020 if (result !=
nil && ioCache != NULL)
2023 [*
ioCache setObject:result forKey:key];
2030+ (
OOMusic *) ooMusicNamed:(NSString *)fileName inFolder:(NSString *)folderName
2035 key:[
NSString stringWithFormat:@"OOMusic:%@:%@", folderName, fileName]
2041+ (
OOSound *) ooSoundNamed:(NSString *)fileName inFolder:(NSString *)folderName
2046 key:[
NSString stringWithFormat:@"OOSound:%@:%@", folderName, fileName]
2052+ (NSString *) stringFromFilesNamed:(NSString *)fileName inFolder:(NSString *)folderName
2058+ (NSString *) stringFromFilesNamed:(NSString *)fileName inFolder:(NSString *)folderName cache:(BOOL)useCache
2061 NSString *path =
nil;
2062 NSString *key =
nil;
2066 key = [
NSString stringWithFormat:@"%@:%@", folderName, fileName];
2070 result = [sStringCache objectForKey:key];
2071 if (result)
return result;
2076 if (path !=
nil) result = [
NSString stringWithContentsOfUnicodeFile:path];
2078 if (result !=
nil && useCache)
2081 [sStringCache setObject:result forKey:key];
2090 NSMutableDictionary *loadedScripts =
nil;
2091 NSArray *results =
nil;
2093 NSEnumerator *pathEnum =
nil;
2094 NSString *path =
nil;
2095 NSEnumerator *scriptEnum =
nil;
2097 NSString *name =
nil;
2098 NSAutoreleasePool *pool =
nil;
2100 OOLog(
@"script.load.world.begin",
@"%@",
@"Loading world scripts...");
2104 for (pathEnum = [
paths objectEnumerator]; (path = [
pathEnum nextObject]); )
2109 if (![
ResourceManager corePlist:
@"world-scripts.plist" excludedAt:path])
2119 for (scriptEnum = [results objectEnumerator]; (script = [
scriptEnum nextObject]); )
2123 else OOLog(
@"script.load.unnamed",
@"Discarding anonymous script %@", script);
2127 @catch (NSException *exception)
2129 OOLog(
@"script.load.exception",
@"***** %s encountered exception %@ (%@) while trying to load script from %@ -- ignoring this location.", __PRETTY_FUNCTION__, [exception name], [exception reason], path);
2142 NSMutableArray *displayNames =
nil;
2143 NSEnumerator *scriptEnum =
nil;
2145 NSString *displayString =
nil;
2149 for (scriptEnum = [loadedScripts objectEnumerator]; (script = [
scriptEnum nextObject]); )
2154 displayString = [[
displayNames sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] componentsJoinedByString:@"\n "];
2155 OOLog(
@"script.load.world.listAll",
@"Loaded %llu world scripts:\n %@",
count, displayString);
2159 OOLog(
@"script.load.world.listAll",
@"%@",
@"*** No world scripts loaded.");
2163 return loadedScripts;
2167+ (BOOL) writeDiagnosticData:(NSData *)data toFileNamed:(NSString *)name
2169 if (data ==
nil || name ==
nil)
return NO;
2172 if (directory ==
nil)
return NO;
2174 NSArray *nameComponents = [
name componentsSeparatedByString:@"/"];
2180 for (NSUInteger i = 0; i <
count - 1; i++)
2183 if ([component hasPrefix:
@"."])
2187 directory = [
directory stringByAppendingPathComponent:component];
2188 [[
NSFileManager defaultManager] oo_createDirectoryAtPath:directory attributes:nil];
2192 return [
data writeToFile:[
directory stringByAppendingPathComponent:name] atomically:YES];
2196+ (BOOL) writeDiagnosticString:(NSString *)string toFileNamed:(NSString *)name
2202+ (BOOL) writeDiagnosticPList:(
id)plist toFileNamed:(NSString *)name
2204 NSData *data = [
plist oldSchoolPListFormatWithErrorDescription:NULL];
2206 if (data ==
nil)
return NO;
2218+ (BOOL)directoryExists:(NSString *)inPath create:(BOOL)inCreate
2220 BOOL exists, directory;
2223 exists = [
fmgr fileExistsAtPath:inPath isDirectory:&directory];
2225 if (exists && !directory)
2227 OOLog(
@"resourceManager.write.buildPath.failed",
@"Expected %@ to be a folder, but it is a file.", inPath);
2232 if (!inCreate)
return NO;
2233 if (![fmgr oo_createDirectoryAtPath:inPath attributes:
nil])
2235 OOLog(
@"resourceManager.write.buildPath.failed",
@"Could not create folder %@.", inPath);
2252 NSMutableArray *displayPaths =
nil;
2253 NSEnumerator *pathEnum =
nil;
2254 NSString *path =
nil;
2257 displayPaths = [
NSMutableArray arrayWithCapacity:[sSearchPaths count]];
2260 [
displayPaths addObject:[[
path stringByStandardizingPath] stringByAbbreviatingWithTildeInPath]];
2263 OOLog(
@"searchPaths.dumpAll",
@"Resource paths: %@\n %@",
sUseAddOns, [displayPaths componentsJoinedByString:
@"\n "]);
2270 [sSoundCache release];
2272 [sStringCache release];
void OOHUDResetTextEngine(void)
#define foreachkey(VAR, DICT)
void OOStandardsDeprecated(NSString *message)
BOOL OOEnforceStandards(void)
void OOStandardsError(NSString *message)
NSString * OOLogHandlerGetLogBasePath(void)
BOOL OOLogWillDisplayMessagesInClass(NSString *inMessageClass)
#define OOLog(class, format,...)
NSString *const kOOLogParameterError
static NSString *const kOOManifestTags
static NSString *const kOOManifestRequiredOoliteVersion
static NSString *const kOOManifestTitle
static NSString *const kOOManifestTagScenarioOnly
static NSString *const kOOManifestIdentifier
static NSString *const kOOManifestVersion
static NSString *const kOOManifestRequiredBy
static NSString *const kOOManifestFilePath
NSDictionary * OODictionaryFromFile(NSString *path)
NSArray * OOArrayFromFile(NSString *path)
NSArray * ComponentsFromVersionString(NSString *string)
NSComparisonResult CompareVersions(NSArray *version1, NSArray *version2)
#define SCENARIO_OXP_DEFINITION_BYID
#define SCENARIO_OXP_DEFINITION_NONE
#define SCENARIO_OXP_DEFINITION_NOPLIST
#define SCENARIO_OXP_DEFINITION_ALL
#define SCENARIO_OXP_DEFINITION_BYTAG
static NSMutableArray * sErrors
static NSString *const kOOLogCacheUpToDate
static NSArray * sUseAddOnsParts
static NSString *const kOOLogCacheStalePaths
static NSMutableArray * sSearchPaths
static NSString *const kOOCacheSearchPathModDates
static NSString *const kOOLogCacheStaleDates
static NSString *const kOOCacheKeySearchPaths
static NSMutableDictionary * sOXPManifests
static NSMutableDictionary * sSoundCache
static NSMutableArray * sOXPsWithMessagesFound
static NSString * sUseAddOns
static NSMutableDictionary * sStringCache
static NSString *const kOOLogCacheExplicitFlush
static NSString *const kOOCacheKeyModificationDates
NSDictionary * ParseOOSScripts(NSString *script)
static NSMutableArray * sExternalPaths
#define PLANETINFO_UNIVERSAL_KEY
@ EQUIPMENT_EXTRA_INFO_INDEX
#define PLANETINFO_INTERSTELLAR_KEY
void setObject:forKey:inCache:(id inElement,[forKey] NSString *inKey,[inCache] NSString *inCacheKey)
void setAllowCacheWrites:(BOOL flag)
id objectForKey:inCache:(NSString *inKey,[inCache] NSString *inCacheKey)
OOCacheManager * sharedCache()
NSString * extractAddOnsPath()
OOOXZManager * sharedManager()
NSArray * additionalAddOnsPaths()
NSArray * worldScriptsAtPath:(NSString *path)
void setUniversalProperties:(NSDictionary *properties)
void setProperties:forSystemKey:(NSDictionary *properties,[forSystemKey] NSString *key)
void setInterstellarProperties:(NSDictionary *properties)
NSString * pathForFileNamed:inFolder:cache:(NSString *fileName,[inFolder] NSString *folderName,[cache] BOOL useCache)
void filterSearchPathsForConflicts:(NSMutableArray *searchPaths)
NSDictionary * materialDefaults()
NSArray * pathsWithAddOns()
void resetManifestKnowledgeForOXZManager()
NSString * maskUserName:inPath:(NSString *name,[inPath] NSString *path)
id retrieveFileNamed:inFolder:cache:key:class:usePathCache:(NSString *fileName, [inFolder] NSString *folderName, [cache] NSMutableDictionary **ioCache, [key] NSString *key, [class] Class class, [usePathCache] BOOL useCache)
BOOL areRequirementsFulfilled:forOXP:andFile:(NSDictionary *requirements, [forOXP] NSString *path, [andFile] NSString *file)
BOOL manifestAllowedByScenario:withTag:(NSDictionary *manifest, [withTag] NSString *tag)
NSDictionary * loadScripts()
NSString * stringFromFilesNamed:inFolder:cache:(NSString *fileName,[inFolder] NSString *folderName,[cache] BOOL useCache)
void preloadFilePathFor:inFolder:atPath:(NSString *fileName, [inFolder] NSString *subFolder, [atPath] NSString *path)
void preloadFileListFromFolder:forFolders:(NSString *path, [forFolders] NSArray *folders)
NSDictionary * whitelistDictionary()
void handleEquipmentOverrides:(NSMutableArray *arrayToProcess)
NSEnumerator * reversePathEnumerator()
void handleEquipmentListMerging:forLookupIndex:(NSMutableArray *arrayToProcess,[forLookupIndex] unsigned lookupIndex)
NSArray * OXPsWithMessagesFound()
void filterSearchPathsByScenario:(NSMutableArray *searchPaths)
void checkOXPMessagesInPath:(NSString *path)
NSDictionary * dictionaryFromFilesNamed:inFolder:andMerge:(NSString *fileName,[inFolder] NSString *folderName,[andMerge] BOOL mergeFiles)
NSDictionary * logControlDictionary()
void preloadFileListFromOXZ:forFolders:(NSString *path, [forFolders] NSArray *folders)
NSArray * arrayFromFilesNamed:inFolder:andMerge:(NSString *fileName,[inFolder] NSString *folderName,[andMerge] BOOL mergeFiles)
NSEnumerator * pathEnumerator()
NSString * diagnosticFileLocation()
void mergeRoleCategories:intoDictionary:(NSDictionary *catData, [intoDictionary] NSMutableDictionary *categories)
void filterSearchPathsToExcludeScenarioOnlyPaths:(NSMutableArray *searchPaths)
BOOL checkCacheUpToDateForPaths:(NSArray *searchPaths)
BOOL manifestAllowedByScenario:withIdentifier:(NSDictionary *manifest, [withIdentifier] NSString *identifier)
void addErrorWithKey:param1:param2:(NSString *descriptionKey, [param1] id param1, [param2] id param2)
BOOL checkVersionCompatibility:forOXP:(NSDictionary *manifest,[forOXP] NSString *title)
NSArray * userRootPaths()
static NSString * LogClassKeyRoot(NSString *key)
NSDictionary * shaderBindingTypesDictionary()
BOOL writeDiagnosticData:toFileNamed:(NSData *data,[toFileNamed] NSString *name)
BOOL validateManifest:forOXP:(NSDictionary *manifest, [forOXP] NSString *path)
OOSystemDescriptionManager * systemDescriptionManager()
void handleStarNebulaListMerging:(NSMutableArray *arrayToProcess)
void checkPotentialPath:path:(NSString *, [path] NSMutableArray *searchPaths)
NSArray * arrayFromFilesNamed:inFolder:andMerge:cache:(NSString *fileName,[inFolder] NSString *folderName,[andMerge] BOOL mergeFiles,[cache] BOOL useCache)
NSDictionary * roleCategoriesDictionary()
NSDictionary * dictionaryFromFilesNamed:inFolder:mergeMode:cache:(NSString *fileName,[inFolder] NSString *folderName,[mergeMode] OOResourceMergeMode mergeMode,[cache] BOOL useCache)
int ZEXPORT unzGetCurrentFileInfo64(unzFile file, unz_file_info64 *pfile_info, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize)
int ZEXPORT unzGoToFirstFile(unzFile file)
unzFile ZEXPORT unzOpen64(const void *path)
int ZEXPORT unzGoToNextFile(unzFile file)
int ZEXPORT unzClose(unzFile file)