Merged script compiler and some new script actions into trunk.

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@430 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
dajt 2006-04-04 22:12:50 +00:00
parent 4c1ae4683b
commit 18544c7d69
12 changed files with 823 additions and 75 deletions

View File

@ -21,7 +21,7 @@ endif
OBJC_PROGRAM_NAME = oolite
oolite_C_FILES = vector.c legacy_random.c strlcpy.c
oolite_OBJC_FILES = Comparison.m AI.m DustEntity.m Entity.m GameController.m GuiDisplayGen.m HeadUpDisplay.m main.m MyOpenGLView.m OpenGLSprite.m ParticleEntity.m PlanetEntity.m PlayerEntity_Additions.m PlayerEntity_contracts.m PlayerEntity_Controls.m PlayerEntity_Sound.m PlayerEntity.m ResourceManager.m RingEntity.m ShipEntity_AI.m ShipEntity.m SkyEntity.m StationEntity.m TextureStore.m Universe.m OOSound.m OOMusic.m SDLImage.m LoadSave.m OOFileManager.m JoystickHandler.m PlayerEntity_StickMapper.m OOBasicSoundReferencePoint.m OOBasicSoundSource.m OOCharacter.m OOTrumble.m WormholeEntity.m ScannerExtension.m OOXMLExtensions.m MutableDictionaryExtension.m Geometry.m Octree.m CollisionRegion.m OOColor.m
oolite_OBJC_FILES = Comparison.m AI.m DustEntity.m Entity.m GameController.m GuiDisplayGen.m HeadUpDisplay.m main.m MyOpenGLView.m OpenGLSprite.m ParticleEntity.m PlanetEntity.m PlayerEntity_Additions.m PlayerEntity_contracts.m PlayerEntity_Controls.m PlayerEntity_Sound.m PlayerEntity.m ResourceManager.m RingEntity.m ShipEntity_AI.m ShipEntity.m SkyEntity.m StationEntity.m TextureStore.m Universe.m OOSound.m OOMusic.m SDLImage.m LoadSave.m OOFileManager.m JoystickHandler.m PlayerEntity_StickMapper.m OOBasicSoundReferencePoint.m OOBasicSoundSource.m OOCharacter.m OOTrumble.m WormholeEntity.m ScannerExtension.m OOXMLExtensions.m MutableDictionaryExtension.m Geometry.m Octree.m CollisionRegion.m OOColor.m ScriptCompiler.m StringTokeniser.m
include $(GNUSTEP_MAKEFILES)/objc.make
include GNUmakefile.postamble

View File

@ -117,6 +117,7 @@ Your fair use and other rights are in no way affected by the above.
- (void) removeEquipment:(NSString *)equipString; //eg. EQ_NAVAL_ENERGY_UNIT
- (void) setPlanetinfo:(NSString *)key_valueString; // uses key=value format
- (void) setSpecificPlanetInfo:(NSString *)key_valueString; // uses galaxy#=planet#=key=value
- (void) awardCargo:(NSString *)amount_typeString;
- (void) removeAllCargo;
@ -166,6 +167,9 @@ Your fair use and other rights are in no way affected by the above.
// choices/choice phrases in missiontext.plist and also..
- (void) resetMissionChoice; // resets MissionChoice to nil
- (void) addMissionDestination:(NSString *)destinations; // mark a system on the star charts
- (void) removeMissionDestination:(NSString *)destinations; // stop a system being marked on star charts
- (void) showShipModel: (NSString *)shipKey;
- (void) setMissionMusic: (NSString *)value;
- (void) setMissionImage: (NSString *)value;

View File

@ -165,6 +165,7 @@ static NSString * mission_key;
*/
NSMutableArray* tokens = [Entity scanTokensFromString:scriptAction];
NSMutableDictionary* locals = [local_variables objectForKey:mission_key];
NSString* selectorString = nil;
NSString* valueString = nil;
SEL _selector;
@ -184,6 +185,9 @@ static NSString * mission_key;
{
[tokens removeObjectAtIndex:0];
valueString = [[tokens componentsJoinedByString:@" "] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
valueString = [universe expandDescriptionWithLocals:valueString forSystem:[self system_seed] withLocalVariables:locals];
if (debug)
NSLog(@"DEBUG ::::: after expansion: \"%@ %@\"", selectorString, valueString);
}
_selector = NSSelectorFromString(selectorString);
@ -239,6 +243,7 @@ static NSString * mission_key;
*/
NSArray* tokens = [Entity scanTokensFromString:scriptCondition];
NSMutableDictionary* locals = [local_variables objectForKey:mission_key];
NSString* selectorString = nil;
NSString* comparisonString = nil;
NSString* valueString = nil;
@ -261,6 +266,13 @@ static NSString * mission_key;
mission_string_value = (NSString *)[mission_variables objectForKey:selectorString];
selectorString = @"mission_string";
}
else if ([selectorString hasPrefix:@"local_"])
{
if (debug)
NSLog(@"DEBUG ..... checking local variable '%@'",selectorString);
mission_string_value = (NSString *)[locals objectForKey:selectorString];
selectorString = @"mission_string";
}
if ([tokens count] > 1)
{
@ -859,6 +871,27 @@ static int shipsFound;
}
- (void) setSpecificPlanetInfo:(NSString *)key_valueString // uses galaxy#=planet#=key=value
{
NSArray* tokens = [[key_valueString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] componentsSeparatedByString:@"="];
NSString* keyString = nil;
NSString* valueString = nil;
int gnum, pnum;
if ([tokens count] != 4)
{
NSLog(@"***** CANNOT SETPLANETINFO: '%@'", key_valueString);
return;
}
gnum = [(NSString*)[tokens objectAtIndex:0] intValue];
pnum = [(NSString*)[tokens objectAtIndex:1] intValue];
keyString = [(NSString*)[tokens objectAtIndex:2] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
valueString = [(NSString*)[tokens objectAtIndex:3] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
[universe setSystemDataForGalaxy:gnum planet:pnum key:keyString value:valueString];
}
- (void) awardCargo:(NSString *)amount_typeString
{
// NSArray* tokens = [amount_typeString componentsSeparatedByString:@" "];
@ -1210,8 +1243,10 @@ static int shipsFound;
- (void) set:(NSString *)missionvariable_value
{
NSMutableArray* tokens = [Entity scanTokensFromString:missionvariable_value];
NSMutableDictionary* locals = [local_variables objectForKey:mission_key];
NSString* missionVariableString = nil;
NSString* valueString = nil;
BOOL hasMissionPrefix, hasLocalPrefix;
if ([tokens count] < 2)
{
@ -1223,54 +1258,92 @@ static int shipsFound;
[tokens removeObjectAtIndex:0];
valueString = [tokens componentsJoinedByString:@" "];
if (([valueString hasSuffix:@"_number"])||([valueString hasSuffix:@"_bool"])||([valueString hasSuffix:@"_string"]))
{
SEL value_selector = NSSelectorFromString(valueString);
if ([self respondsToSelector:value_selector])
{
// substitute into valueString the result of the call
valueString = [NSString stringWithFormat:@"%@", [self performSelector:value_selector]];
}
}
hasMissionPrefix = [missionVariableString hasPrefix:@"mission_"];
hasLocalPrefix = [missionVariableString hasPrefix:@"local_"];
if (![missionVariableString hasPrefix:@"mission_"])
if (hasMissionPrefix != YES && hasLocalPrefix != YES)
{
NSLog(@"***** MISSION VARIABLE '%@' DOES NOT BEGIN WITH 'mission_'", missionvariable_value);
NSLog(@"***** IDENTIFIER '%@' DOES NOT BEGIN WITH 'mission_' or 'local_'", missionVariableString);
return;
}
[mission_variables setObject:valueString forKey:missionVariableString];
if (hasMissionPrefix)
[mission_variables setObject:valueString forKey:missionVariableString];
else
[locals setObject:valueString forKey:missionVariableString];
}
- (void) reset:(NSString *)missionvariable
{
NSString* missionVariableString = [missionvariable stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
BOOL hasMissionPrefix, hasLocalPrefix;
if (![missionVariableString hasPrefix:@"mission_"])
{
NSLog(@"***** MISSION VARIABLE '%@' DOES NOT BEGIN WITH 'mission_'", missionVariableString);
return;
}
hasMissionPrefix = [missionVariableString hasPrefix:@"mission_"];
hasLocalPrefix = [missionVariableString hasPrefix:@"local_"];
[mission_variables removeObjectForKey:missionVariableString];
if (hasMissionPrefix)
{
[mission_variables removeObjectForKey:missionVariableString];
}
else if (hasLocalPrefix)
{
NSMutableDictionary* locals = [local_variables objectForKey:mission_key];
[locals removeObjectForKey:missionVariableString];
}
else
{
NSLog(@"***** IDENTIFIER '%@' DOES NOT BEGIN WITH 'mission_' or 'local_'", missionVariableString);
}
}
- (void) increment:(NSString *)missionVariableString
{
BOOL hasMissionPrefix, hasLocalPrefix;
int value = 0;
if ([mission_variables objectForKey:missionVariableString])
value = [(NSString *)[mission_variables objectForKey:missionVariableString] intValue];
value++;
[mission_variables setObject:[NSString stringWithFormat:@"%d", value] forKey:missionVariableString];
hasMissionPrefix = [missionVariableString hasPrefix:@"mission_"];
hasLocalPrefix = [missionVariableString hasPrefix:@"local_"];
if (hasMissionPrefix)
{
if ([mission_variables objectForKey:missionVariableString])
value = [(NSString *)[mission_variables objectForKey:missionVariableString] intValue];
value++;
[mission_variables setObject:[NSString stringWithFormat:@"%d", value] forKey:missionVariableString];
}
else if (hasLocalPrefix)
{
NSMutableDictionary* locals = [local_variables objectForKey:mission_key];
if ([locals objectForKey:missionVariableString])
value = [(NSString *)[locals objectForKey:missionVariableString] intValue];
value++;
[locals setObject:[NSString stringWithFormat:@"%d", value] forKey:missionVariableString];
}
}
- (void) decrement:(NSString *)missionVariableString
{
BOOL hasMissionPrefix, hasLocalPrefix;
int value = 0;
if ([mission_variables objectForKey:missionVariableString])
value = [(NSString *)[mission_variables objectForKey:missionVariableString] intValue];
value--;
[mission_variables setObject:[NSString stringWithFormat:@"%d", value] forKey:missionVariableString];
hasMissionPrefix = [missionVariableString hasPrefix:@"mission_"];
hasLocalPrefix = [missionVariableString hasPrefix:@"local_"];
if (hasMissionPrefix)
{
if ([mission_variables objectForKey:missionVariableString])
value = [(NSString *)[mission_variables objectForKey:missionVariableString] intValue];
value--;
[mission_variables setObject:[NSString stringWithFormat:@"%d", value] forKey:missionVariableString];
}
else if (hasLocalPrefix)
{
NSMutableDictionary* locals = [local_variables objectForKey:mission_key];
if ([locals objectForKey:missionVariableString])
value = [(NSString *)[locals objectForKey:missionVariableString] intValue];
value--;
[locals setObject:[NSString stringWithFormat:@"%d", value] forKey:missionVariableString];
}
}
- (void) add:(NSString *)missionVariableString_value
@ -1279,6 +1352,8 @@ static int shipsFound;
NSString* valueString;
double value;
NSMutableArray* tokens = [Entity scanTokensFromString:missionVariableString_value];
NSMutableDictionary* locals = [local_variables objectForKey:mission_key];
BOOL hasMissionPrefix, hasLocalPrefix;
if ([tokens count] < 2)
{
@ -1290,27 +1365,28 @@ static int shipsFound;
[tokens removeObjectAtIndex:0];
valueString = [tokens componentsJoinedByString:@" "];
if (![mission_variables objectForKey:missionVariableString])
hasMissionPrefix = [missionVariableString hasPrefix:@"mission_"];
hasLocalPrefix = [missionVariableString hasPrefix:@"local_"];
if (hasMissionPrefix)
{
value = [[mission_variables objectForKey:missionVariableString] doubleValue];
value += [valueString doubleValue];
[mission_variables setObject:[NSString stringWithFormat:@"%f", value] forKey:missionVariableString];
}
else if (hasLocalPrefix)
{
value = [[locals objectForKey:missionVariableString] doubleValue];
value += [valueString doubleValue];
[locals setObject:[NSString stringWithFormat:@"%f", value] forKey:missionVariableString];
}
else
{
NSLog(@"***** CANNOT ADD: '%@'",missionVariableString_value);
NSLog(@"***** NO MISSION VARIABLE: '%@'",missionVariableString);
return;
NSLog(@"***** IDENTIFIER '%@' DOES NOT BEGIN WITH 'mission_' or 'local_'",missionVariableString);
}
if (([valueString hasSuffix:@"_number"])||([valueString hasSuffix:@"_bool"])||([valueString hasSuffix:@"_string"]))
{
SEL value_selector = NSSelectorFromString(valueString);
if ([self respondsToSelector:value_selector])
{
// substitute into valueString the result of the call
valueString = [NSString stringWithFormat:@"%@", [self performSelector:value_selector]];
}
}
value = [[mission_variables objectForKey:missionVariableString] doubleValue];
value += [valueString doubleValue];
[mission_variables setObject:[NSString stringWithFormat:@"%f", value] forKey:missionVariableString];
}
- (void) subtract:(NSString *)missionVariableString_value
@ -1319,10 +1395,12 @@ static int shipsFound;
NSString* valueString;
double value;
NSMutableArray* tokens = [Entity scanTokensFromString:missionVariableString_value];
NSMutableDictionary* locals = [local_variables objectForKey:mission_key];
BOOL hasMissionPrefix, hasLocalPrefix;
if ([tokens count] < 2)
{
NSLog(@"***** CANNOT ADD: '%@'",missionVariableString_value);
NSLog(@"***** CANNOT SUBTRACT: '%@'",missionVariableString_value);
return;
}
@ -1330,27 +1408,28 @@ static int shipsFound;
[tokens removeObjectAtIndex:0];
valueString = [tokens componentsJoinedByString:@" "];
if (![mission_variables objectForKey:missionVariableString])
hasMissionPrefix = [missionVariableString hasPrefix:@"mission_"];
hasLocalPrefix = [missionVariableString hasPrefix:@"local_"];
if (hasMissionPrefix)
{
NSLog(@"***** CANNOT ADD: '%@'",missionVariableString_value);
NSLog(@"***** NO MISSION VARIABLE: '%@'",missionVariableString);
return;
}
value = [[mission_variables objectForKey:missionVariableString] doubleValue];
value -= [valueString doubleValue];
if (([valueString hasSuffix:@"_number"])||([valueString hasSuffix:@"_bool"])||([valueString hasSuffix:@"_string"]))
[mission_variables setObject:[NSString stringWithFormat:@"%f", value] forKey:missionVariableString];
}
else if (hasLocalPrefix)
{
SEL value_selector = NSSelectorFromString(valueString);
if ([self respondsToSelector:value_selector])
{
// substitute into valueString the result of the call
valueString = [NSString stringWithFormat:@"%@", [self performSelector:value_selector]];
}
value = [[locals objectForKey:missionVariableString] doubleValue];
value -= [valueString doubleValue];
[locals setObject:[NSString stringWithFormat:@"%f", value] forKey:missionVariableString];
}
else
{
NSLog(@"***** CANNOT SUBTRACT: '%@'",missionVariableString_value);
NSLog(@"***** IDENTIFIER '%@' DOES NOT BEGIN WITH 'mission_' or 'local_'",missionVariableString);
}
value = [[mission_variables objectForKey:missionVariableString] doubleValue];
value -= [valueString doubleValue];
[mission_variables setObject:[NSString stringWithFormat:@"%f", value] forKey:missionVariableString];
}
- (void) checkForShips: (NSString *)roleString
@ -1437,6 +1516,68 @@ static int shipsFound;
missionChoice = nil;
}
- (void) addMissionDestination:(NSString *)destinations
{
int i, j;
NSNumber *pnump;
int pnum, dest;
NSMutableArray* tokens = [Entity scanTokensFromString:destinations];
BOOL addDestination;
for (j = 0; j < [tokens count]; j++)
{
dest = [(NSString *)[tokens objectAtIndex:j] intValue];
if (dest < 0 || dest > 255)
continue;
addDestination = YES;
for (i = 0; i < [missionDestinations count]; i++)
{
pnump = (NSNumber *)[missionDestinations objectAtIndex:i];
pnum = [pnump intValue];
if (pnum == dest)
{
addDestination = NO;
break;
}
}
if (addDestination == YES)
[missionDestinations addObject:[NSNumber numberWithUnsignedInt:dest]];
}
}
- (void) removeMissionDestination:(NSString *)destinations
{
int i, j;
NSNumber *pnump;
int pnum, dest;
NSMutableArray* tokens = [Entity scanTokensFromString:destinations];
BOOL removeDestination;
for (j = 0; j < [tokens count]; j++)
{
dest = [(NSString *)[tokens objectAtIndex:j] intValue];
if (dest < 0 || dest > 255)
continue;
removeDestination = NO;
for (i = 0; i < [missionDestinations count]; i++)
{
pnump = (NSNumber *)[missionDestinations objectAtIndex:i];
pnum = [pnump intValue];
if (pnum == dest)
{
removeDestination = YES;
break;
}
}
if (removeDestination == YES)
[missionDestinations removeObjectAtIndex:i];
}
}
- (void) showShipModel: (NSString *)shipKey
{
ShipEntity *ship;
@ -1676,7 +1817,7 @@ static int shipsFound;
- (void) debugMessage:(NSString *)args
{
NSLog(@"SCRIPT debugMessage: %@", [self replaceVariablesInString: args]);
NSLog(@"SCRIPT debugMessage: %@", args);
}
- (NSString*) replaceVariablesInString:(NSString*) args
@ -1693,8 +1834,7 @@ static int shipsFound;
{
[tokens replaceObjectAtIndex:i withObject:[mission_variables objectForKey:valueString]];
}
if (([valueString hasSuffix:@"_number"])||([valueString hasSuffix:@"_bool"])||([valueString hasSuffix:@"_string"]))
else if (([valueString hasSuffix:@"_number"])||([valueString hasSuffix:@"_bool"])||([valueString hasSuffix:@"_string"]))
{
SEL value_selector = NSSelectorFromString(valueString);
if ([self respondsToSelector:value_selector])

View File

@ -234,6 +234,7 @@ enum
NSDictionary *script;
NSMutableDictionary *mission_variables;
NSMutableDictionary *local_variables;
int missionTextRow;
ShipEntity *script_target;
NSString *missionChoice;
@ -262,6 +263,8 @@ enum
NSMutableDictionary *shipyard_record;
NSMutableArray *missionDestinations;
double script_time;
double script_time_check;
double script_time_interval;

View File

@ -433,6 +433,8 @@ static Quaternion quaternion_identity = { (GLfloat)1.0, (GLfloat)0.0, (GLfloat)0
[result setObject:contracts forKey:@"contracts"];
[result setObject:contract_record forKey:@"contract_record"];
[result setObject:missionDestinations forKey:@"missionDestinations"];
//shipyard
[result setObject:shipyard_record forKey:@"shipyard_record"];
@ -699,6 +701,20 @@ static Quaternion quaternion_identity = { (GLfloat)1.0, (GLfloat)0.0, (GLfloat)0
contract_record = [[NSMutableDictionary dictionaryWithCapacity:8] retain];
}
// mission destinations
if ([dict objectForKey:@"missionDestinations"])
{
if (missionDestinations)
[missionDestinations release];
missionDestinations = [[NSMutableArray arrayWithArray:(NSArray *)[dict objectForKey:@"missionDestinations"]] retain];
}
else
{
if (missionDestinations)
[missionDestinations release];
missionDestinations = [[NSMutableArray arrayWithCapacity:8] retain];
}
// shipyard
if ([dict objectForKey:@"shipyard_record"])
{
@ -910,8 +926,14 @@ static Quaternion quaternion_identity = { (GLfloat)1.0, (GLfloat)0.0, (GLfloat)0
[hud setScannerZoom:1.0];
scanner_zoom_rate = 0.0;
//
script = [[ResourceManager dictionaryFromFilesNamed:@"script.plist" inFolder:@"Config" andMerge:YES] retain];
//script = [[ResourceManager dictionaryFromFilesNamed:@"script.plist" inFolder:@"Config" andMerge:YES] retain];
script = [[ResourceManager loadScripts] retain];
mission_variables =[[NSMutableDictionary dictionaryWithCapacity:16] retain];
local_variables =[[NSMutableDictionary dictionaryWithCapacity:[script count]] retain];
NSArray *scriptKeys = [script allKeys];
for (i = 0; i < [scriptKeys count]; i++)
[local_variables setObject:[NSMutableDictionary dictionaryWithCapacity:16] forKey:[scriptKeys objectAtIndex:i]];
[self setScript_target:nil];
[self resetMissionChoice];
//
@ -938,6 +960,10 @@ static Quaternion quaternion_identity = { (GLfloat)1.0, (GLfloat)0.0, (GLfloat)0
[contract_record release];
contract_record = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
//
if (missionDestinations)
[missionDestinations release];
missionDestinations = [[NSMutableArray alloc] initWithCapacity:8];
//
if (shipyard_record)
[shipyard_record release];
shipyard_record = [[NSMutableDictionary dictionaryWithCapacity:4] retain];
@ -1422,6 +1448,20 @@ static Quaternion quaternion_identity = { (GLfloat)1.0, (GLfloat)0.0, (GLfloat)0
if (script) [script release];
if (mission_variables) [mission_variables release];
if (local_variables)
{
int i;
NSArray *objs = [local_variables allValues];
for (i = 0; i < [objs count]; i++)
{
NSMutableDictionary *dict = (NSMutableDictionary *)[objs objectAtIndex:i];
[dict dealloc];
}
[local_variables removeAllObjects];
[local_variables dealloc];
}
if (lastTextKey) [lastTextKey release];
if (extra_equipment) [extra_equipment release];
@ -1431,6 +1471,7 @@ static Quaternion quaternion_identity = { (GLfloat)1.0, (GLfloat)0.0, (GLfloat)0
if (passenger_record) [passenger_record release];
if (contracts) [contracts release];
if (contract_record) [contract_record release];
if (missionDestinations) [missionDestinations release];
if (shipyard_record) [shipyard_record release];
if (missionBackgroundImage) [missionBackgroundImage release];
@ -3791,6 +3832,10 @@ double scoopSoundPlayTime = 0.0;
if (contracts)
[contracts removeAllObjects];
// remove any mission destinations for the old galaxy
if (missionDestinations)
[missionDestinations removeAllObjects];
// expire passenger contracts for the old galaxy
if (passengers)
{
@ -4528,6 +4573,8 @@ double scoopSoundPlayTime = 0.0;
mark[[(NSNumber*)[(NSDictionary*)[passengers objectAtIndex:i] objectForKey:PASSENGER_KEY_DESTINATION] intValue]] = YES;
for (i = 0; i < [contracts count]; i++)
mark[[(NSNumber*)[(NSDictionary*)[contracts objectAtIndex:i] objectForKey:CONTRACT_KEY_DESTINATION] intValue]] = YES;
for (i = 0; i < [missionDestinations count]; i++)
mark[[(NSNumber*)[missionDestinations objectAtIndex:i] intValue]] = YES;
for (i = 0; i < 256; i++)
[destinations addObject:[NSNumber numberWithBool:mark[i]]];
@ -4552,6 +4599,8 @@ double scoopSoundPlayTime = 0.0;
mark[[(NSNumber*)[(NSDictionary*)[passengers objectAtIndex:i] objectForKey:PASSENGER_KEY_DESTINATION] intValue]] = YES;
for (i = 0; i < [contracts count]; i++)
mark[[(NSNumber*)[(NSDictionary*)[contracts objectAtIndex:i] objectForKey:CONTRACT_KEY_DESTINATION] intValue]] = YES;
for (i = 0; i < [missionDestinations count]; i++)
mark[[(NSNumber*)[missionDestinations objectAtIndex:i] intValue]] = YES;
// GUI stuff
{

View File

@ -110,4 +110,5 @@ BOOL always_include_addons;
+ (NSString*) stringFromNSPoint: (NSPoint) point;
+ (NSPoint) NSPointFromString: (NSString*) point_string;
+ (NSDictionary *) loadScripts;
@end

View File

@ -44,6 +44,7 @@ Your fair use and other rights are in no way affected by the above.
#import "MutableDictionaryExtension.h"
#import "OOSound.h"
extern NSDictionary* parseScripts(NSString* script);
@implementation ResourceManager
@ -1195,4 +1196,141 @@ NSMutableDictionary* surface_cache;
return NSMakePoint( [[tokens objectAtIndex:0] floatValue], [[tokens objectAtIndex:1] floatValue]);
}
+ (NSDictionary *) loadScripts
{
NSMutableArray *results = [NSMutableArray arrayWithCapacity:16];
NSMutableArray *fpaths = [ResourceManager paths];
NSString *foldername = [NSString stringWithString:@"Config"];
NSString *filename = [NSString stringWithString:@"script.plist"];
int i;
NSString* dict_key = [NSString stringWithFormat:@"%@:%@", foldername, filename];
if (!dictionary_cache)
dictionary_cache = [[NSMutableDictionary alloc] initWithCapacity:32];
if ([dictionary_cache objectForKey:dict_key])
{
return [NSDictionary dictionaryWithDictionary:(NSDictionary *)[dictionary_cache objectForKey:dict_key]]; // return the cached dictionary
}
for (i = 0; i < [fpaths count]; i++)
{
NSString *xfilepath = [(NSString *)[fpaths objectAtIndex:i] stringByAppendingPathComponent:filename];
NSMutableString *filepath = [NSMutableString stringWithString:xfilepath];
[filepath replaceString:@".plist" withString:@".oos"];
//NSLog(@"looking for oos file: %@", filepath);
if ([[NSFileManager defaultManager] fileExistsAtPath:filepath])
{
// load and compile oos script
NSLog(@"trying to load and parse %@", filepath);
NSString *script = [NSString stringWithContentsOfFile:filepath];
NSDictionary *scriptDict = parseScripts(script);
if (scriptDict) {
//NSLog(@"parsed ok, adding to results");
[results addObject:scriptDict];
}
}
else
{
[filepath replaceString:@".oos" withString:@".plist"];
//NSLog(@"oos not found, looking for plist file: %@", filepath);
// All this code replicated from dictionaryFromFileNamed because that method
// will traverse all possible locations and any oos files that co-exist with
// plist files will probably get their entries overwritten.
//
// This can be simplified if we make a rule that it is a configuration error
// that isn't handled if there is a script.oos and script.plist file in
// the same place. But that probably isn't realistic.
if ([[NSFileManager defaultManager] fileExistsAtPath:filepath])
{
NSDictionary* found_dic = [NSDictionary dictionaryWithContentsOfFile:filepath];
// FIX FOR WINDOWS GNUSTEP NOT PARSING XML PLISTS
NS_DURING
if (!found_dic) // try parsing it using our home-grown XML parser
found_dic = (NSDictionary*)[ResourceManager parseXMLPropertyList:[NSString stringWithContentsOfFile:filepath]];
NS_HANDLER
if ([[localException name] isEqual: OOLITE_EXCEPTION_XML_PARSING_FAILURE]) // note it happened here
{
NSLog(@"***** [ResourceManager dictionaryFromFilesNamed:::] encountered exception : %@ : %@ *****",[localException name], [localException reason]);
}
else
[localException raise];
NS_ENDHANDLER
if (found_dic)
[results addObject:found_dic];
else
NSLog(@"ERROR ***** could not parse %@ as a NSDictionary.", filepath);
}
}
if (foldername)
{
xfilepath = [[(NSString *)[fpaths objectAtIndex:i] stringByAppendingPathComponent:foldername] stringByAppendingPathComponent:filename];
filepath = [NSMutableString stringWithString:xfilepath];
[filepath replaceString:@".plist" withString:@".oos"];
//NSLog(@"looking for oos file: %@", filepath);
if ([[NSFileManager defaultManager] fileExistsAtPath:filepath])
{
// load and compile oos script
NSLog(@"trying to load and compile %@", filepath);
NSString *script = [NSString stringWithContentsOfFile:filepath];
NSDictionary *scriptDict = parseScripts(script);
if (scriptDict) {
//NSLog(@"parsed ok, adding to results");
[results addObject:scriptDict];
}
}
else
{
[filepath replaceString:@".oos" withString:@".plist"];
//NSLog(@"oos not found, looking for plist file: %@", filepath);
if ([[NSFileManager defaultManager] fileExistsAtPath:filepath])
{
NSDictionary* found_dic = [NSDictionary dictionaryWithContentsOfFile:filepath];
// FIX FOR WINDOWS GNUSTEP NOT PARSING XML PLISTS
NS_DURING
if (!found_dic) // try parsing it using our home-grown XML parser
found_dic = (NSDictionary*)[ResourceManager parseXMLPropertyList:[NSString stringWithContentsOfFile:filepath]];
NS_HANDLER
if ([[localException name] isEqual: OOLITE_EXCEPTION_XML_PARSING_FAILURE]) // note it happened here
{
NSLog(@"***** [ResourceManager dictionaryFromFilesNamed:::] encountered exception : %@ : %@ *****",[localException name], [localException reason]);
}
else
[localException raise];
NS_ENDHANDLER
if (found_dic)
[results addObject:found_dic];
else
NSLog(@"ERROR ***** could not parse %@ as a NSDictionary.", filepath);
}
}
}
}
if ([results count] == 0)
return nil;
// got results we may want to cache
//
NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:128];
for (i = 0; i < [results count]; i++)
{
[result addEntriesFromDictionary:(NSDictionary *)[results objectAtIndex:i]];
}
//
if (result) {
[dictionary_cache setObject:result forKey:dict_key];
}
// NSLog(@"DEBUG ResourceManager dictionary_cache keys:\n%@", [dictionary_cache allKeys]);
return [NSDictionary dictionaryWithDictionary:result];
}
@end

246
src/Core/ScriptCompiler.m Normal file
View File

@ -0,0 +1,246 @@
/*
* Oolite script compiler.
*
* Copyright (c) 2006 David Taylor. All rights reserved.
*
* This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike License.
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/2.0/
* or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
*
* You are free:
*
* o to copy, distribute, display, and perform the work
* o to make derivative works
*
* Under the following conditions:
*
* o Attribution. You must give the original author credit.
* o Noncommercial. You may not use this work for commercial purposes.
* o Share Alike. If you alter, transform, or build upon this work,
* you may distribute the resulting work only under a license identical to this one.
*
* For any reuse or distribution, you must make clear to others the license terms of this work.
* Any of these conditions can be waived if you get permission from the copyright holder.
* Your fair use and other rights are in no way affected by the above.
*/
#import <Foundation/Foundation.h>
#import "StringTokeniser.h"
/*
* Preprocess the source read from the oos file.
*
* Strips blank lines and lines beginning with "//".
* Strips leading and trailing whitespace off any lines that are left.
*
* Returns the processed source.
*/
NSString* preprocess(NSString* source) {
int i;
NSMutableString *processedSource = [NSMutableString stringWithString:source];
// convert DOS and MAC EOLs to *NIX EOL (DOS EOL will create blank lines,
// but these are filtered out in the loop)
[processedSource replaceOccurrencesOfString:@"\r" withString:@"\n" options:NSLiteralSearch range:NSMakeRange(0, [processedSource length])];
NSArray *lines = [processedSource componentsSeparatedByString:@"\n"];
[processedSource setString:@""];
for (i = 0; i < [lines count]; i++) {
NSString* line = (NSString*)[lines objectAtIndex:i];
NSMutableString* mutableLine = [NSMutableString stringWithString:line];
[mutableLine trimSpaces];
line = [NSString stringWithString:mutableLine];
if ([line length] == 0)
continue;
if ([line hasPrefix:@"//"])
continue;
[processedSource appendString:line];
[processedSource appendString:@"\n"];
}
return [NSString stringWithString:processedSource];
}
NSDictionary* parseIf(StringTokeniser* st) {
NSMutableString *statement = [NSMutableString stringWithCapacity:80];
NSMutableArray *conditions = [[NSMutableArray alloc] init];
NSMutableArray *actions = [[NSMutableArray alloc] init];
NSMutableDictionary *ifDict = [[NSMutableDictionary alloc] initWithCapacity:3];
BOOL inElse = NO;
[st nextToken];
while (st->tokenType != TT_WORD) {
if (st->tokenType == TT_EOS) {
// end of the script - this is fine while looking for an "if"
return nil;
}
[st nextToken];
}
if ([st->tokenWord isEqual:@"if"] != YES) {
NSLog(@"ScriptCompiler: Error (line %d): expected \"if\", found %@", st->lineNo, st->tokenWord);
return nil;
}
// parse the conditions
while (1) {
[st nextToken];
if (st->tokenType == TT_EOL)
continue;
if (st->tokenType == TT_EOS) {
NSLog(@"ScriptCompiler: Error (line %d): unexpected end of script", st->lineNo);
return nil;
}
if ([st->tokenWord isEqual:@"then"] == YES) {
[statement trimSpaces];
[statement replaceString:@" = " withString:@" equal "];
[statement replaceString:@" < " withString:@" lessthan "];
[statement replaceString:@" > " withString:@" greaterthan "];
NSString* c = [NSString stringWithString: statement];
[conditions addObject:c];
[statement setString:@""]; // is also used for the actions so needs to be cleared
break; // got the then keyword so now parse the actions
}
if ([st->tokenWord isEqual:@"and"] == YES) {
[statement trimSpaces];
[statement replaceString:@" = " withString:@" equal "];
[statement replaceString:@" < " withString:@" lessthan "];
[statement replaceString:@" > " withString:@" greaterthan "];
NSString* c = [NSString stringWithString: statement];
[conditions addObject:c];
[statement setString:@""];
continue;
}
[statement appendString:st->tokenWord];
[statement appendString:@" "];
}
[ifDict setObject:conditions forKey:@"conditions"];
// parse the actions, including else and endif keywords
while (1) {
[st nextToken];
if (st->tokenType == TT_EOL) { // marks the end of an action
[statement trimSpaces];
if ([statement length] > 0) {
NSString* c = [NSString stringWithString: statement];
[actions addObject:c];
[statement setString:@""];
}
continue;
}
if (st->tokenType == TT_EOS) {
NSLog(@"ScriptCompiler: Error (line %d): unexpected end of script, expected else or endif", st->lineNo);
return nil;
}
if ([st->tokenWord isEqual:@"else"] == YES) {
if (inElse == YES) {
NSLog(@"ScriptCompiler: Error (line %d): already in \"else\" block", st->lineNo);
return nil;
}
[ifDict setObject:actions forKey:@"do"];
[statement setString:@""];
actions = [[NSMutableArray alloc] init];
inElse = YES;
continue;
}
if ([st->tokenWord isEqual:@"endif"] == YES) {
if (inElse == YES) {
[ifDict setObject:actions forKey:@"else"];
} else {
[ifDict setObject:actions forKey:@"do"];
}
[statement setString:@""];
break;
}
if ([st->tokenWord isEqual:@"if"] == YES) {
[st pushBack];
NSDictionary* ifDict = parseIf(st);
if (ifDict != nil) {
[actions addObject:ifDict];
}
else
break; //if we read "if" and got nil back, there has certainly been an error so bail out
continue;
}
[statement appendString:st->tokenWord];
[statement appendString:@" "];
}
return ifDict;
}
NSDictionary* parseScripts(NSString* script) {
NSString *processedScript = preprocess(script);
StringTokeniser *st = [[StringTokeniser alloc] initWithString:processedScript];
NSMutableDictionary *scriptDict = [[NSMutableDictionary alloc] initWithCapacity:10];
NSDictionary *ifDict;
NSMutableArray *ifStatements = [[NSMutableArray alloc] init];
NSString *scriptName;
while (st->tokenType != TT_EOS) {
[st nextToken];
if (st->tokenType == TT_EOL)
continue;
if (st->tokenType == TT_EOS)
return;
scriptName = [NSString stringWithString:st->tokenWord];
while (st->tokenType != TT_EOS) {
[st nextToken];
if (st->tokenType == TT_EOL)
continue;
if ([st->tokenWord isEqual:@"if"] == YES) {
[st pushBack];
ifDict = parseIf(st);
if (ifDict != nil) {
[ifStatements addObject:ifDict];
}
} else {
[scriptDict setObject:ifStatements forKey:scriptName];
ifStatements = [[NSMutableArray alloc] init];
[st pushBack];
break;
}
}
}
return scriptDict;
}
#ifdef SC_TEST
int main (int argc, char** argv)
{
int i;
NSAutoreleasePool *arp = [[NSAutoreleasePool alloc] init];
NSString *filename = [NSString stringWithCString:argv[1]];
NSString *script = [NSString stringWithContentsOfFile:filename];
NSDictionary *scriptDict = parseScripts(script);
[scriptDict writeToFile:@"x.plist" atomically:YES];
[arp release];
return 0;
}
#endif

View File

@ -0,0 +1,45 @@
#import <Foundation/Foundation.h>
#define TT_WORD 1
#define TT_EOL 2
#define TT_EOS 3
@interface StringTokeniser : NSObject
{
@public
// A local copy of the string to be parsed
NSString* stringToParse;
char* cString;
// The zero based index of the next character to be parsed. 0 <= nextcharIdx < [stringToParse length]
int nextCharIdx;
// The index to go back to when a pushBack is issued
int pushBackIdx;
// Set to one of the TT_* constants after a call to nextToken
int tokenType;
// The line number currently being parsed
int lineNo;
// If tokenType is TT_WORD this contains a reference to the parsed word
NSString* tokenWord;
char* tokenPtr;
}
// Initialise an instance of the string tokeniser to parse the given string
- (id)initWithString:(NSString*)string;
- (void) dealloc;
// Parse the next token and set the tokenType property appropriately
- (void)nextToken;
// Push back the current token so the next call to nextToken returns
// the same one
- (void)pushBack;
// Returns true once the entire string has been parsed
- (BOOL)reachedEOS;
@end

View File

@ -0,0 +1,95 @@
#import "StringTokeniser.h"
@implementation StringTokeniser : NSObject
// Initialise an instance of the string tokeniser to parse the given string
- (id)initWithString:(NSString*)string {
const char* strPtr;
self = [super init];
stringToParse = [NSString stringWithString:string];
strPtr = [stringToParse cString];
cString = (char*)calloc(strlen(strPtr + 1), sizeof(char));
strcpy(cString, strPtr);
nextCharIdx = 0;
lineNo = 1;
return self;
}
- (void) dealloc {
if (cString != 0x00)
free(cString);
if (tokenPtr != 0x00)
free(tokenPtr);
[super dealloc];
}
// Parse the next token and set the tokenType property appropriately
- (void)nextToken {
int startWordIdx;
int len;
// Incrementing lineNo here so that errors caused by new lines don't get
// reported on the line after the error, as would happen if lineNo was
// incremented when the TT_EOL token is returned.
if (tokenType == TT_EOL)
lineNo++;
if (nextCharIdx >= [stringToParse length]) {
tokenType = TT_EOS;
return;
}
// skip whitespace before next word or EOL
while (cString[nextCharIdx] == 0x20 || cString[nextCharIdx] == 0x09) {
nextCharIdx++;
pushBackIdx = nextCharIdx;
if (nextCharIdx >= [stringToParse length]) {
tokenType = TT_EOS;
return;
}
}
if (cString[nextCharIdx] == 0x0A) {
tokenType = TT_EOL;
nextCharIdx++;
pushBackIdx = nextCharIdx;
return;
}
startWordIdx = nextCharIdx;
pushBackIdx = nextCharIdx;
while (cString[nextCharIdx] != 0x20 && cString[nextCharIdx] != 0x09 && cString[nextCharIdx] != 0x0A) {
nextCharIdx++;
if (nextCharIdx >= [stringToParse length]) {
break;
}
}
len = nextCharIdx - startWordIdx+1;
tokenPtr = calloc(len, sizeof(char));
strncpy(tokenPtr, &cString[startWordIdx], len-1);
tokenWord = [NSString stringWithCString:tokenPtr];
free(tokenPtr);
tokenPtr = 0x00;
tokenType = TT_WORD;
return;
}
- (void)pushBack {
nextCharIdx = pushBackIdx;
}
// Returns true once the entire string has been parsed
- (BOOL)reachedEOS {
if (nextCharIdx >= [stringToParse length])
return YES;
return NO;
}
@end

View File

@ -417,6 +417,7 @@ extern int debug;
- (NSDictionary *) generateSystemData:(Random_Seed) system_seed;
- (NSDictionary *) currentSystemData;
- (void) setSystemDataKey:(NSString*) key value:(NSObject*) object;
- (void) setSystemDataForGalaxy:(int) gnum planet:(int) pnum key:(NSString*) key value:(NSObject*) object;
- (NSString *) getSystemName:(Random_Seed) s_seed;
- (NSString *) getSystemInhabitants:(Random_Seed) s_seed;
- (NSString *) generateSystemName:(Random_Seed) system_seed;
@ -464,6 +465,7 @@ NSComparisonResult comparePrice( id dict1, id dict2, void * context);
- (NSString *) generateSystemDescription:(Random_Seed) s_seed;
- (NSString *) expandDescription:(NSString *) desc forSystem:(Random_Seed)s_seed;
- (NSString *) expandDescriptionWithLocals:(NSString *) desc forSystem:(Random_Seed)s_seed withLocalVariables:(NSDictionary *)locals;
- (NSString *) getRandomDigrams;
- (Vector) getWitchspaceExitPosition;

View File

@ -5321,6 +5321,16 @@ GLfloat starboard_matrix[] = { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
[local_overrides setObject:object forKey:key];
}
- (void) setSystemDataForGalaxy:(int) gnum planet:(int) pnum key:(NSString*) key value:(NSObject*) object
{
NSString* override_key = [NSString stringWithFormat:@"%d %d", gnum, pnum];
if ([local_planetinfo_overrides objectForKey:override_key] == nil)
[local_planetinfo_overrides setObject:[NSMutableDictionary dictionaryWithCapacity:8] forKey:override_key];
NSMutableDictionary* local_overrides = (NSMutableDictionary*)[local_planetinfo_overrides objectForKey:override_key];
[local_overrides setObject:object forKey:key];
}
- (NSString *) getSystemName:(Random_Seed) s_seed
{
@ -6942,13 +6952,17 @@ NSComparisonResult comparePrice( id dict1, id dict2, void * context)
return [self expandDescription:@"[14] is [22]." forSystem:s_seed];
}
- (NSString *) expandDescription:(NSString *) desc forSystem:(Random_Seed)s_seed;
- (NSString *) expandDescription:(NSString *) desc forSystem:(Random_Seed)s_seed
{
return [self expandDescriptionWithLocals:desc forSystem:s_seed withLocalVariables:nil];
}
- (NSString *) expandDescriptionWithLocals:(NSString *) desc forSystem:(Random_Seed)s_seed withLocalVariables:(NSDictionary *)locals
{
PlayerEntity* player = (PlayerEntity*)[self entityZero];
NSMutableString* partial = [NSMutableString stringWithString:desc];
NSMutableDictionary* all_descriptions = [NSMutableDictionary dictionaryWithDictionary:descriptions];
////
// add in mission_variables if required
if ([desc rangeOfString:@"[mission_"].location != NSNotFound)
{
@ -6958,10 +6972,16 @@ NSComparisonResult comparePrice( id dict1, id dict2, void * context)
while (key = [missVarsEnum nextObject])
[all_descriptions setObject:[mission_vars objectForKey:key] forKey:key];
}
//
////
////
// also add the mission-local vars, if they have been passed in
if (locals != nil && [desc rangeOfString:@"[local_"].location != NSNotFound)
{
NSEnumerator* localVarsEnum = [locals keyEnumerator];
id key;
while (key = [localVarsEnum nextObject])
[all_descriptions setObject:[locals objectForKey:key] forKey:key];
}
// add in player info if required
if ([desc rangeOfString:@"[commander_"].location != NSNotFound)
{
@ -6978,8 +6998,6 @@ NSComparisonResult comparePrice( id dict1, id dict2, void * context)
int legal_index = 0 + (legal_status <= 50) ? 1 : 2;
[all_descriptions setObject:[(NSArray *)[descriptions objectForKey:@"legal_status"] objectAtIndex:legal_index] forKey:@"commander_legal_status"];
}
//
////
while ([partial rangeOfString:@"["].location != NSNotFound)
{
@ -7006,6 +7024,14 @@ NSComparisonResult comparePrice( id dict1, id dict2, void * context)
part = [all_descriptions objectForKey:middle];
}
}
else if (([middle hasSuffix:@"_number"])||([middle hasSuffix:@"_bool"])||([middle hasSuffix:@"_string"]))
{
SEL value_selector = NSSelectorFromString(middle);
if ([player respondsToSelector:value_selector])
{
part = [NSString stringWithFormat:@"%@", [player performSelector:value_selector]];
}
}
else
{
// no value for that key so interpret it as a number...
@ -7021,7 +7047,6 @@ NSComparisonResult comparePrice( id dict1, id dict2, void * context)
part = (NSString *)[(NSArray *)[(NSArray *)[all_descriptions objectForKey:@"system_description"] objectAtIndex:sub] objectAtIndex:opt];
}
partial = [NSMutableString stringWithFormat:@"%@%@%@",before,part,after];
}