* Fixes to ship registry:

- is_template is no longer inherited, causing all derived ships to be
    silently deleted. 
  - Ships whose model can’t be found are now reported and deleted from the
    registry.
  - Ships used as subentities no longer require roles. 
  - Ships with invalid subentity definitions (not exactly eight tokens) are
    now reported and deleted from the registry. 
  - New is_external_dependency key suppresses errors for missing like_ship and
    subentity references. (A ship with is_external_dependency will still be
    deleted from the registry if it can’t be properly resolved, there just
    won't be a message about it.)
 * Added missing compatibility method player.spawnOne().
 * Default galactic_hyperspace_behaviour respelled to BEHAVIOUR_STANDARD.
 * Corrected warning text in setGalacticHyperspaceBehaviourTo:.
 * Added nil check in collision detection.


git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@1853 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Jens Ayton 2008-11-13 09:47:15 +00:00
parent 520c61fbb3
commit 19cbb04377
10 changed files with 135 additions and 22 deletions

View File

@ -10,7 +10,7 @@
"trader",
"shuttle",
// Known trader-like roles from pre-1-70 plug-ins
// Known trader-like roles from pre-1.70 plug-ins
"delta",
"gemini",
"starseeker",

View File

@ -21,9 +21,9 @@
// Uncomment the desired behaviour for galactic hyperspace exit. Fixed coordinates will put the arrival
// of an intergalactic jump on map coordinates specified by the key galactic_hyperspace_fixed_coords.
"galactic_hyperspace_behaviour" = "GALACTIC_HYPERSPACE_BEHAVIOUR_STANDARD";
//"GALACTIC_HYPERSPACE_BEHAVIOUR_ALL_SYSTEMS_REACHABLE";
//"GALACTIC_HYPERSPACE_BEHAVIOUR_FIXED_COORDINATES";
"galactic_hyperspace_behaviour" = "BEHAVIOUR_STANDARD";
//"BEHAVIOUR_ALL_SYSTEMS_REACHABLE";
//"BEHAVIOUR_FIXED_COORDINATES";
// When using the GALACTIC_HYPERSPACE_BEHAVIOUR_FIXED_COORDINATES, the key below is used to specify the
// actual fixed coordinates for the intergalactic jump.

View File

@ -198,6 +198,7 @@ this.defineCompatibilitySubMethod("player", "ship", "removeAllCargo");
this.defineCompatibilitySubMethod("player", "ship", "useSpecialCargo");
this.defineCompatibilitySubMethod("player", "ship", "setGalacticHyperspaceBehaviour");
this.defineCompatibilitySubMethod("player", "ship", "setGalacticHyperspaceFixedCoords");
this.defineCompatibilitySubMethod("player", "ship", "spawnOne");
this.defineCompatibilitySubGetter("player", "ship", "AI");
this.defineCompatibilitySubGetterAndSetter("player", "ship", "AIState");

View File

@ -924,7 +924,7 @@ static PlayerEntity *sSharedPlayer = nil;
[self setSystem_seed:[UNIVERSE findSystemAtCoords:[self galaxy_coordinates] withGalaxySeed:[self galaxy_seed]]];
[self setGalacticHyperspaceBehaviourTo:[[UNIVERSE planetInfo] stringForKey:@"galactic_hyperspace_behaviour" defaultValue:@"GALACTIC_HYPERSPACE_BEHAVIOUR_STANDARD"]];
[self setGalacticHyperspaceBehaviourTo:[[UNIVERSE planetInfo] stringForKey:@"galactic_hyperspace_behaviour" defaultValue:@"BEHAVIOUR_STANDARD"]];
[self setGalacticHyperspaceFixedCoordsTo:[[UNIVERSE planetInfo] stringForKey:@"galactic_hyperspace_fixed_coords" defaultValue:@"96 96"]];
[[OOMusicController sharedController] stop];

View File

@ -2685,7 +2685,7 @@ static int scriptRandomSeed = -1; // ensure proper random function
if (ghBehaviour == GALACTIC_HYPERSPACE_BEHAVIOUR_UNKNOWN)
{
OOLog(@"player.setGalacticHyperspaceBehaviour.invalidInput",
@"setGalacticHyperspaceBehaviour: called with unknown behaviour %@.", galacticHyperspaceBehaviourString);
@"setGalacticHyperspaceBehaviourTo: called with unknown behaviour %@.", galacticHyperspaceBehaviourString);
}
[self setGalacticHyperspaceBehaviour:ghBehaviour];
}

View File

@ -361,6 +361,7 @@ static NSString * const kOOLogEntityBehaviourChanged = @"entity.behaviour.change
smooth:[shipDict boolForKey:@"smooth"]
shaderMacros:DefaultShipShaderMacros()
shaderBindingTarget:self];
if (mesh == nil) return NO;
[self setMesh:mesh];
}

View File

@ -253,7 +253,7 @@ static OOMaterial *sActiveMaterial = nil;
if ([textures count] != 0) [newConfig setObject:textures forKey:@"textures"];
if ([uniforms count] != 0) [newConfig setObject:uniforms forKey:@"uniforms"];
[newConfig setObject:modifiedMacros forKey:@"_synthesized_material_macros"];
[newConfig setObject:modifiedMacros forKey:@"_oo_synthesized_material_macros"];
return newConfig;
}
@ -302,7 +302,7 @@ static OOMaterial *sActiveMaterial = nil;
result = [self materialWithName:name
forModelNamed:modelName
configuration:synthesizedConfig
macros:[synthesizedConfig objectForKey:@"_synthesized_material_macros"]
macros:[synthesizedConfig objectForKey:@"_oo_synthesized_material_macros"]
bindingTarget:target
forSmoothedMesh:YES];
}

View File

@ -35,7 +35,7 @@ MA 02110-1301, USA.
#if OOLITE_MAC_OS_X
#define CACHE_PLIST_FORMAT NSPropertyListBinaryFormat_v1_0
#else
#define CACHE_PLIST_FORMAT NSPropertyListGNUstepBinaryFormat // NSPropertyListXMLFormat_v1_0
#define CACHE_PLIST_FORMAT NSPropertyListGNUstepBinaryFormat
#endif
@ -64,7 +64,7 @@ static NSString * const kCacheKeyCaches = @"caches";
enum
{
kEndianTagValue = 0x0123456789ABCDEFULL,
kFormatVersionValue = 22
kFormatVersionValue = 24
};

View File

@ -53,6 +53,7 @@ SOFTWARE.
#import "NSDictionaryOOExtensions.h"
#import "OOProbabilitySet.h"
#import "OORoleSet.h"
#import "OOStringParsing.h"
static OOShipRegistry *sSingleton = nil;
@ -76,6 +77,7 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
- (NSDictionary *) mergeShip:(NSDictionary *)child withParent:(NSDictionary *)parent;
- (BOOL) loadAndMergeShipyard:(NSMutableDictionary *)ioData;
- (BOOL) loadAndApplyShipDataOverrides:(NSMutableDictionary *)ioData;
- (BOOL) tagSubEntities:(NSMutableDictionary *)ioData;
- (BOOL) removeUnusableEntries:(NSMutableDictionary *)ioData;
- (void) mergeShipRoles:(NSString *)roles forShipKey:(NSString *)shipKey intoProbabilityMap:(NSMutableDictionary *)probabilitySets;
@ -242,7 +244,7 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
{
if (![[result objectForKey:key] isKindOfClass:[NSDictionary class]])
{
OOLog(@"shipData.load.badEntry", @"***** ERROR: the shipdata.plist entry \"%@\" is not a dictionary, ignoring.", key);
OOLog(@"shipData.load.badEntry", @"***** ERROR: the shipdata.plist entry \"%@\" is not a dictionary.", key);
[result removeObjectForKey:key];
}
}
@ -253,6 +255,9 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
// Apply patches.
if (![self loadAndApplyShipDataOverrides:result]) return;
// Tag subentities so they won't be pruned.
if (![self tagSubEntities:result]) return;
// Clean out templates and invalid entries.
if (![self removeUnusableEntries:result]) return;
@ -391,6 +396,7 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
NSDictionary *shipEntry = nil;
NSDictionary *parentEntry = nil;
unsigned count, lastCount;
NSMutableArray *reportedBadShips = nil;
// Build set of ships with like_ship references
remainingLikeShips = [NSMutableSet set];
@ -427,12 +433,22 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
count = [remainingLikeShips count];
if (count == lastCount)
{
// Fail: we couldn't resolve all like_ship entries. Remove unresolved ones.
OOLog(@"shipData.merge.failed", @"***** ERROR: one or more shipdata.plist entries have like_ship references that cannot be resolved: %@", remainingLikeShips);
/* Fail: we couldn't resolve all like_ship entries.
Remove unresolved entries, building a list of the ones that
don't have is_external_dependency set.
*/
reportedBadShips = [NSMutableArray array];
for (enumerator = [remainingLikeShips objectEnumerator]; (key = [enumerator nextObject]); )
{
[reportedBadShips addObject:key];
[ioData removeObjectForKey:key];
}
if ([reportedBadShips count] != 0)
{
[reportedBadShips sortUsingSelector:@selector(caseInsensitiveCompare:)];
OOLog(@"shipData.merge.failed", @"***** ERROR: one or more shipdata.plist entries have like_ship references that cannot be resolved: ", reportedBadShips);
}
break;
}
lastCount = count;
@ -450,8 +466,9 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
[result addEntriesFromDictionary:child];
[result removeObjectForKey:@"like_ship"];
// As a special case, display_name cannot be inherited.
// Certain properties cannot be inherited.
if ([child stringForKey:@"display_name"] == nil) [result removeObjectForKey:@"display_name"];
if ([child stringForKey:@"is_template"] == nil) [result removeObjectForKey:@"is_template"];
return [[result copy] autorelease];
}
@ -478,7 +495,7 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
overridesEntry = [overrides objectForKey:key];
if (![overridesEntry isKindOfClass:[NSDictionary class]])
{
OOLog(@"shipData.load.error", @"***** ERROR: the shipdata-overrides.plist entry \"%@\" is not a dictionary, ignoring.", key);
OOLog(@"shipData.load.error", @"***** ERROR: the shipdata-overrides.plist entry \"%@\" is not a dictionary.", key);
}
else
{
@ -559,27 +576,119 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
}
- (BOOL) tagSubEntities:(NSMutableDictionary *)ioData
{
NSEnumerator *shipKeyEnum = nil;
NSString *shipKey = nil;
NSDictionary *shipEntry = nil;
NSArray *subEntityDeclarations = nil;
NSEnumerator *subEntityEnum = nil;
NSString *subEntityKey = nil;
NSArray *subEntityDef = nil;
NSDictionary *subEntityShipEntry = nil;
BOOL remove;
NSMutableSet *badSubEntities = nil;
NSString *badSubEntitiesList = nil;
// Add _oo_is_subentity=YES to all entries used as subentities.
// Iterate over all ships. (Iterates over a copy of keys since it mutates the dictionary.)
for (shipKeyEnum = [[ioData allKeys] objectEnumerator]; (shipKey = [shipKeyEnum nextObject]); )
{
shipEntry = [ioData objectForKey:shipKey];
remove = NO;
badSubEntities = nil;
// Iterate over each subentity declaration of each ship
subEntityDeclarations = [shipEntry arrayForKey:@"subentities"];
for (subEntityEnum = [subEntityDeclarations objectEnumerator]; (subEntityKey = [subEntityEnum nextObject]); )
{
subEntityDef = ScanTokensFromString(subEntityKey);
// While we're at it, do basic sanity checking on subentity defs.
if ([subEntityDef count] != 8)
{
OOLog(@"shipData.load.error", @"***** ERROR: the shipdata.plist entry \"%@\" has a broken role definition \"%@\" (should have 8 tokens, has %u).", shipKey, subEntityKey, [subEntityDef count]);
remove = YES;
}
else
{
subEntityKey = [subEntityDef stringAtIndex:0];
if (![subEntityKey isEqualToString:@"*FLASHER*"])
{
subEntityShipEntry = [ioData objectForKey:subEntityKey];
if (subEntityShipEntry == nil)
{
// Oops, reference to non-existent subent
if (badSubEntities == nil) badSubEntities = [NSMutableSet set];
[badSubEntities addObject:subEntityKey];
}
else if (![subEntityShipEntry boolForKey:@"_oo_is_subentity"])
{
// Subent exists, add _oo_is_subentity so roles aren't required
subEntityShipEntry = [subEntityShipEntry dictionaryByAddingObject:[NSNumber numberWithBool:YES] forKey:@"_oo_is_subentity"];
[ioData setObject:subEntityShipEntry forKey:subEntityKey];
}
}
}
}
if (badSubEntities != nil)
{
if (![shipEntry boolForKey:@"is_external_dependency"])
{
badSubEntitiesList = [[[badSubEntities allObjects] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] componentsJoinedByString:@", "];
OOLog(@"shipData.load.error", @"***** ERROR: the shipdata.plist entry \"%@\" has unresolved subentit%@ %@.", shipKey, ([badSubEntities count] == 1) ? @"y" : @"ies", badSubEntitiesList);
}
remove = YES;
}
if (remove)
{
// Removal is deferred to avoid bogus "entry doesn't exist" errors.
shipEntry = [shipEntry dictionaryByAddingObject:[NSNumber numberWithBool:YES] forKey:@"_oo_deferred_remove"];
[ioData setObject:shipEntry forKey:shipKey];
}
}
return YES;
}
- (BOOL) removeUnusableEntries:(NSMutableDictionary *)ioData
{
NSEnumerator *shipKeyEnum = nil;
NSString *shipKey = nil;
NSDictionary *shipEntry = nil;
BOOL remove;
NSString *modelName = nil;
// Clean out invalid entries and templates. (Iterates over a copy of keys since it mutates the dictionary.)
for (shipKeyEnum = [[ioData allKeys] objectEnumerator]; (shipKey = [shipKeyEnum nextObject]); )
{
shipEntry = [ioData objectForKey:shipKey];
if ([shipEntry boolForKey:@"is_template"]) [ioData removeObjectForKey:shipKey];
else if ([[shipEntry stringForKey:@"roles"] length] == 0)
remove = NO;
if ([shipEntry boolForKey:@"is_template"] || [shipEntry boolForKey:@"_oo_deferred_remove"]) remove = YES;
else if ([[shipEntry stringForKey:@"roles"] length] == 0 && ![shipEntry boolForKey:@"_oo_is_subentity"])
{
OOLog(@"shipData.load.error", @"***** ERROR: the shipdata.plist entry \"%@\" specifies no %@, ignoring.", shipKey, @"roles");
[ioData removeObjectForKey:shipKey];
OOLog(@"shipData.load.error", @"***** ERROR: the shipdata.plist entry \"%@\" specifies no %@.", shipKey, @"roles");
remove = YES;
}
else if ([[shipEntry stringForKey:@"model"] length] == 0)
else
{
OOLog(@"shipData.load.error", @"***** ERROR: the shipdata.plist entry \"%@\" specifies no %@, ignoring.", shipKey, @"model");
[ioData removeObjectForKey:shipKey];
modelName = [shipEntry stringForKey:@"model"];
if ([modelName length] == 0)
{
OOLog(@"shipData.load.error", @"***** ERROR: the shipdata.plist entry \"%@\" specifies no %@.", shipKey, @"model");
remove = YES;
}
else if ([ResourceManager pathForFileNamed:modelName inFolder:@"Models"] == nil)
{
OOLog(@"shipData.load.error", @"***** ERROR: the shipdata.plist entry \"%@\" specifies non-existent model \"%@\".", shipKey, modelName, @"model");
remove = YES;
}
}
if (remove) [ioData removeObjectForKey:shipKey];
}
return YES;

View File

@ -692,6 +692,8 @@ BOOL isHitByOctree( Octree_details axialDetails,
- (BOOL) isHitByOctree:(Octree*) other withOrigin: (Vector) v0 andIJK: (Triangle) ijk
{
if (other == nil) return NO;
BOOL hit = isHitByOctree( [self octreeDetails], [other octreeDetails], v0, ijk);
hasCollision = hasCollision | hit;