Split JS system into separate file. Started on support for ship scripts (incomplete).

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@1129 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Jens Ayton 2007-08-05 11:47:09 +00:00
parent 368444d9c2
commit 892c271501
30 changed files with 1576 additions and 708 deletions

View File

@ -26,7 +26,7 @@ endif
OBJC_PROGRAM_NAME = oolite
oolite_C_FILES = 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 PlayerEntityLegacyScriptEngine.m PlayerEntityContracts.m PlayerEntityControls.m PlayerEntityLoadSave.m PlayerEntitySound.m PlayerEntity.m ResourceManager.m RingEntity.m ShipEntityAI.m ShipEntity.m SkyEntity.m StationEntity.m Universe.m OOSound.m SDLMusic.m NSFileManagerOOExtensions.m JoystickHandler.m PlayerEntityStickMapper.m OOBasicSoundReferencePoint.m OOBasicSoundSource.m OOCharacter.m OOTrumble.m WormholeEntity.m NSScannerOOExtensions.m OOXMLExtensions.m NSMutableDictionaryOOExtensions.m Geometry.m Octree.m CollisionRegion.m OOColor.m OOLogging.m OOCacheManager.m OOCache.m OOStringParsing.m OOCollectionExtractors.m OOVector.m OOMatrix.m OOQuaternion.m OOVoxel.m OOTriangle.m OOPListParsing.m OOFastArithmetic.m OOTextureScaling.m OOConstToString.m OOScript.m OOJSScript.m OOJavaScriptEngine.m OOPListScript.m NSStringOOExtensions.m PlayerEntityScriptMethods.m OOWeakReference.m OOJSEntity.m EntityOOJavaScriptExtensions.m OOJSQuaternion.m OOMaterial.m OOShaderMaterial.m OOShaderProgram.m OOShaderUniform.m OOTexture.m OOTextureLoader.m OOPNGTextureLoader.m OOOpenGLExtensionManager.m OOBasicMaterial.m OOSingleTextureMaterial.m OOCPUInfo.m OOSelfDrawingEntity.m OOEntityWithDrawable.m OODrawable.m OOJSVector.m OOMesh.m OOOpenGL.m OOGraphicsResetManager.m OOProbabilisticTextureManager.m OODebugGLDrawing.m OOShaderUniformMethodType.m OOAsyncQueue.m TextureStore.m OOOXPVerifier.m OOOXPVerifierStage.m OOFileScannerVerifierStage.m OOCheckRequiresPListVerifierStage.m OOCheckDemoShipsPListVerifierStage.m OOCheckEquipmentPListVerifierStage.m OOTextureVerifierStage.m OOModelVerifierStage.m OOCheckShipDataPListVerifierStage.m OOPListSchemaVerifier.m OOJSShip.m OOJSPlayer.m OOJSCall.m OOJSStation.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 PlayerEntityLegacyScriptEngine.m PlayerEntityContracts.m PlayerEntityControls.m PlayerEntityLoadSave.m PlayerEntitySound.m PlayerEntity.m ResourceManager.m RingEntity.m ShipEntityAI.m ShipEntity.m SkyEntity.m StationEntity.m Universe.m OOSound.m SDLMusic.m NSFileManagerOOExtensions.m JoystickHandler.m PlayerEntityStickMapper.m OOBasicSoundReferencePoint.m OOBasicSoundSource.m OOCharacter.m OOTrumble.m WormholeEntity.m NSScannerOOExtensions.m OOXMLExtensions.m NSMutableDictionaryOOExtensions.m Geometry.m Octree.m CollisionRegion.m OOColor.m OOLogging.m OOCacheManager.m OOCache.m OOStringParsing.m OOCollectionExtractors.m OOVector.m OOMatrix.m OOQuaternion.m OOVoxel.m OOTriangle.m OOPListParsing.m OOFastArithmetic.m OOTextureScaling.m OOConstToString.m OOScript.m OOJSScript.m OOJavaScriptEngine.m OOPListScript.m NSStringOOExtensions.m PlayerEntityScriptMethods.m OOWeakReference.m OOJSEntity.m EntityOOJavaScriptExtensions.m OOJSQuaternion.m OOMaterial.m OOShaderMaterial.m OOShaderProgram.m OOShaderUniform.m OOTexture.m OOTextureLoader.m OOPNGTextureLoader.m OOOpenGLExtensionManager.m OOBasicMaterial.m OOSingleTextureMaterial.m OOCPUInfo.m OOSelfDrawingEntity.m OOEntityWithDrawable.m OODrawable.m OOJSVector.m OOMesh.m OOOpenGL.m OOGraphicsResetManager.m OOProbabilisticTextureManager.m OODebugGLDrawing.m OOShaderUniformMethodType.m OOAsyncQueue.m TextureStore.m OOOXPVerifier.m OOOXPVerifierStage.m OOFileScannerVerifierStage.m OOCheckRequiresPListVerifierStage.m OOCheckDemoShipsPListVerifierStage.m OOCheckEquipmentPListVerifierStage.m OOTextureVerifierStage.m OOModelVerifierStage.m OOCheckShipDataPListVerifierStage.m OOPListSchemaVerifier.m OOJSShip.m OOJSPlayer.m OOJSCall.m OOJSStation.m OOJSSystem.m OOLegacyEventHandlerScript.m OOPlayerProxyScript.m
include $(GNUSTEP_MAKEFILES)/objc.make
include GNUmakefile.postamble

View File

@ -370,6 +370,12 @@
1A736C800C61FD220097AC37 /* OOJSCall.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A736C7E0C61FD220097AC37 /* OOJSCall.m */; };
1A73712D0C623DAE0097AC37 /* OOJSStation.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A73712B0C623DAE0097AC37 /* OOJSStation.h */; };
1A73712E0C623DAE0097AC37 /* OOJSStation.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A73712C0C623DAE0097AC37 /* OOJSStation.m */; };
1A7376BE0C64AE330097AC37 /* OOJSSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A7376BC0C64AE330097AC37 /* OOJSSystem.h */; };
1A7376BF0C64AE330097AC37 /* OOJSSystem.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A7376BD0C64AE330097AC37 /* OOJSSystem.m */; };
1A7378E40C6515720097AC37 /* OOPlayerProxyScript.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A7378E20C6515720097AC37 /* OOPlayerProxyScript.h */; };
1A7378E50C6515720097AC37 /* OOPlayerProxyScript.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A7378E30C6515720097AC37 /* OOPlayerProxyScript.m */; };
1A73795D0C65CF090097AC37 /* OOLegacyEventHandlerScript.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A73795B0C65CF090097AC37 /* OOLegacyEventHandlerScript.h */; };
1A73795E0C65CF090097AC37 /* OOLegacyEventHandlerScript.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A73795C0C65CF090097AC37 /* OOLegacyEventHandlerScript.m */; };
1A7D3A180C4F6162008EDC33 /* OOCheckRequiresPListVerifierStage.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A7D3A160C4F6162008EDC33 /* OOCheckRequiresPListVerifierStage.h */; };
1A7D3A190C4F6162008EDC33 /* OOCheckRequiresPListVerifierStage.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A7D3A170C4F6162008EDC33 /* OOCheckRequiresPListVerifierStage.m */; };
1A7D3B9B0C4F7843008EDC33 /* OOCheckDemoShipsPListVerifierStage.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A7D3B990C4F7843008EDC33 /* OOCheckDemoShipsPListVerifierStage.h */; };
@ -1266,6 +1272,12 @@
1A736C7E0C61FD220097AC37 /* OOJSCall.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOJSCall.m; sourceTree = "<group>"; };
1A73712B0C623DAE0097AC37 /* OOJSStation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOJSStation.h; sourceTree = "<group>"; };
1A73712C0C623DAE0097AC37 /* OOJSStation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOJSStation.m; sourceTree = "<group>"; };
1A7376BC0C64AE330097AC37 /* OOJSSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOJSSystem.h; sourceTree = "<group>"; };
1A7376BD0C64AE330097AC37 /* OOJSSystem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOJSSystem.m; sourceTree = "<group>"; };
1A7378E20C6515720097AC37 /* OOPlayerProxyScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOPlayerProxyScript.h; sourceTree = "<group>"; };
1A7378E30C6515720097AC37 /* OOPlayerProxyScript.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOPlayerProxyScript.m; sourceTree = "<group>"; };
1A73795B0C65CF090097AC37 /* OOLegacyEventHandlerScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOLegacyEventHandlerScript.h; sourceTree = "<group>"; };
1A73795C0C65CF090097AC37 /* OOLegacyEventHandlerScript.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOLegacyEventHandlerScript.m; sourceTree = "<group>"; };
1A7D3A160C4F6162008EDC33 /* OOCheckRequiresPListVerifierStage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOCheckRequiresPListVerifierStage.h; sourceTree = "<group>"; };
1A7D3A170C4F6162008EDC33 /* OOCheckRequiresPListVerifierStage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOCheckRequiresPListVerifierStage.m; sourceTree = "<group>"; };
1A7D3B990C4F7843008EDC33 /* OOCheckDemoShipsPListVerifierStage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOCheckDemoShipsPListVerifierStage.h; sourceTree = "<group>"; };
@ -1904,6 +1916,10 @@
1A5DBAA20BC000DC00D57389 /* OOScript.m */,
1A5DBA9E0BC000DC00D57389 /* OOPListScript.h */,
1A5DBA9F0BC000DC00D57389 /* OOPListScript.m */,
1A7378E20C6515720097AC37 /* OOPlayerProxyScript.h */,
1A7378E30C6515720097AC37 /* OOPlayerProxyScript.m */,
1A73795B0C65CF090097AC37 /* OOLegacyEventHandlerScript.h */,
1A73795C0C65CF090097AC37 /* OOLegacyEventHandlerScript.m */,
1A5DBAB50BC000E700D57389 /* JavaScript */,
);
path = Scripting;
@ -1932,6 +1948,8 @@
1A736BD20C61E9370097AC37 /* OOJSPlayer.m */,
1A2A8D380BC6765F001E00FB /* EntityOOJavaScriptExtensions.h */,
1A2A8D390BC6765F001E00FB /* EntityOOJavaScriptExtensions.m */,
1A7376BC0C64AE330097AC37 /* OOJSSystem.h */,
1A7376BD0C64AE330097AC37 /* OOJSSystem.m */,
);
name = JavaScript;
sourceTree = "<group>";
@ -2588,6 +2606,9 @@
1A736BD30C61E9370097AC37 /* OOJSPlayer.h in Headers */,
1A736C7F0C61FD220097AC37 /* OOJSCall.h in Headers */,
1A73712D0C623DAE0097AC37 /* OOJSStation.h in Headers */,
1A7376BE0C64AE330097AC37 /* OOJSSystem.h in Headers */,
1A7378E40C6515720097AC37 /* OOPlayerProxyScript.h in Headers */,
1A73795D0C65CF090097AC37 /* OOLegacyEventHandlerScript.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -2892,6 +2913,9 @@
1A736BD40C61E9370097AC37 /* OOJSPlayer.m in Sources */,
1A736C800C61FD220097AC37 /* OOJSCall.m in Sources */,
1A73712E0C623DAE0097AC37 /* OOJSStation.m in Sources */,
1A7376BF0C64AE330097AC37 /* OOJSSystem.m in Sources */,
1A7378E50C6515720097AC37 /* OOPlayerProxyScript.m in Sources */,
1A73795E0C65CF090097AC37 /* OOLegacyEventHandlerScript.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -253,7 +253,8 @@
"missile_role",
"escape_pod_model",
"aft_eject_position",
"auto_ai"
"auto_ai",
"script"
);
knownStationKeys =
(

View File

@ -5,6 +5,119 @@
{
type = "dictionary";
requiredKeys = ( "model", "name", "roles" );
schema =
{
like_ship = "$shipRole";
max_flight_speed = "positiveFloat";
max_flight_roll = "positiveFloat";
max_flight_pitch = "positiveFloat";
max_flight_yaw = "positiveFloat";
thrust = "positiveFloat";
accuracy = "float";
max_energy = "positiveFloat";
energy_recharge_rate = "positiveFloat";
forward_weapon_type = "$weaponType";
aft_weapon_type = "$weaponType";
weapon_energy = "positiveFloat";
scanner_range = "positiveFloat";
missiles = "positiveInteger";
has_ecm = "fuzzyBoolean";
has_scoop = "fuzzyBoolean";
has_escape_pod = "positiveInteger";
has_energy_bomb = "fuzzyBoolean";
has_fuel_injection = "fuzzyBoolean";
has_cloaking_device = "fuzzyBoolean";
has_military_jammer = "fuzzyBoolean";
has_military_scanner_filter = "fuzzyBoolean";
fragment_chance = "fuzzyBoolean";
has_shield_booster = "fuzzyBoolean";
has_shield_enhancer = "fuzzyBoolean";
fuel = "positiveInteger";
bounty = "positiveInteger";
ai_type = "$aiFileName";
max_cargo = "positiveInteger";
likely_cargo = "positiveInteger";
extra_cargo = "positiveInteger";
cargo_carried = "$cargoCarried";
cargo_type = "$cargoType";
model = "$modelName";
materials = "$materialDict";
shaders = "$materialDict";
smooth = "boolean";
density = "positiveFloat";
name = "string";
roles = "$roles";
exhaust =
{
type = "array";
valueType = "$exhaustSpecifier";
};
is_hulk = "boolean";
subentities =
{
type = "array";
valueType = "$subEntitySpecifier";
};
frangible = "boolean";
laser_color = "$colorSpecifier";
scanClass = "$scanClass";
launch_actions = "$scriptActions";
script_actions = "$scriptActions";
death_actions = "$scriptActions";
setup_actions = "$scriptActions";
escorts = "positiveInteger";
beacon = "string";
rotational_velocity = "quaternion";
track_contacts = "boolean";
weapon_position_forward = "vector";
weapon_position_aft = "vector";
weapon_position_port = "vector";
weapon_position_starboard = "vector";
scoop_position = "vector";
heat_insulation = "positiveFloat";
pilot = "$characterKey";
unpiloted = "fuzzyBoolean";
escort-role = "$shipRole";
escort-ship = "$shipKey";
missile_launch_position = "vector";
missile_role = "$shipRole";
escape_pod_model = "$modelName";
aft_eject_position = "vector";
auto_ai = "boolean";
rotating = "boolean";
defense_ship = "$shipKey";
defense_ship_role = "$shipRole";
hasShipyard =
{
type = "oneOf";
options =
(
"$scriptCondition",
"boolean"
);
};
conditions = "$scriptCouplet";
port_radius = "positiveFloat";
port_dimensions = "$portDimensions";
equivalent_tech_level = "integer";
max_scavengers = "positiveInteger";
max_defense_ships = "positiveInteger";
max_police = "positiveInteger";
equipment_price_factor = "positiveFloat";
extra_equipment = "$extraEquipmentDictionary";
hud = "$hudFileName";
view_position_forward = "vector";
view_position_aft = "vector";
view_position_port = "vector";
view_position_starboard = "vector";
custom_views =
{
type = "array";
valueType = "$customViewSpec";
};
max_missiles = "positiveInteger";
script = "$scriptFileName";
};
$definitions =
{
// "Special" types referred to above.
@ -320,117 +433,11 @@
baseType = "string";
key = "cargoCarried";
};
};
schema =
{
like_ship = "$shipRole";
max_flight_speed = "positiveFloat";
max_flight_roll = "positiveFloat";
max_flight_pitch = "positiveFloat";
max_flight_yaw = "positiveFloat";
thrust = "positiveFloat";
accuracy = "float";
max_energy = "positiveFloat";
energy_recharge_rate = "positiveFloat";
forward_weapon_type = "$weaponType";
aft_weapon_type = "$weaponType";
weapon_energy = "positiveFloat";
scanner_range = "positiveFloat";
missiles = "positiveInteger";
has_ecm = "fuzzyBoolean";
has_scoop = "fuzzyBoolean";
has_escape_pod = "positiveInteger";
has_energy_bomb = "fuzzyBoolean";
has_fuel_injection = "fuzzyBoolean";
has_cloaking_device = "fuzzyBoolean";
has_military_jammer = "fuzzyBoolean";
has_military_scanner_filter = "fuzzyBoolean";
fragment_chance = "fuzzyBoolean";
has_shield_booster = "fuzzyBoolean";
has_shield_enhancer = "fuzzyBoolean";
fuel = "positiveInteger";
bounty = "positiveInteger";
ai_type = "$aiFileName";
max_cargo = "positiveInteger";
likely_cargo = "positiveInteger";
extra_cargo = "positiveInteger";
cargo_carried = "$cargoCarried";
cargo_type = "$cargoType";
model = "$modelName";
materials = "$materialDict";
shaders = "$materialDict";
smooth = "boolean";
density = "positiveFloat";
name = "string";
roles = "$roles";
exhaust =
$scriptFileName =
{
type = "array";
valueType = "$exhaustSpecifier";
type = "delegatedType";
baseType = "string";
key = "$scriptFileName";
};
is_hulk = "boolean";
subentities =
{
type = "array";
valueType = "$subEntitySpecifier";
};
frangible = "boolean";
laser_color = "$colorSpecifier";
scanClass = "$scanClass";
launch_actions = "$scriptActions";
script_actions = "$scriptActions";
death_actions = "$scriptActions";
setup_actions = "$scriptActions";
escorts = "positiveInteger";
beacon = "string";
rotational_velocity = "quaternion";
track_contacts = "boolean";
weapon_position_forward = "vector";
weapon_position_aft = "vector";
weapon_position_port = "vector";
weapon_position_starboard = "vector";
scoop_position = "vector";
heat_insulation = "positiveFloat";
pilot = "$characterKey";
unpiloted = "fuzzyBoolean";
escort-role = "$shipRole";
escort-ship = "$shipKey";
missile_launch_position = "vector";
missile_role = "$shipRole";
escape_pod_model = "$modelName";
aft_eject_position = "vector";
auto_ai = "boolean";
rotating = "boolean";
defense_ship = "$shipKey";
defense_ship_role = "$shipRole";
hasShipyard =
{
type = "oneOf";
options =
(
"$scriptCondition",
"boolean"
);
};
conditions = "$scriptCouplet";
port_radius = "positiveFloat";
port_dimensions = "$portDimensions";
equivalent_tech_level = "integer";
max_scavengers = "positiveInteger";
max_defense_ships = "positiveInteger";
max_police = "positiveInteger";
equipment_price_factor = "positiveFloat";
extra_equipment = "$extraEquipmentDictionary";
hud = "$hudFileName";
view_position_forward = "vector";
view_position_aft = "vector";
view_position_port = "vector";
view_position_starboard = "vector";
custom_views =
{
type = "array";
valueType = "$customViewSpec";
};
max_missiles = "positiveInteger";
};
}

View File

@ -202,7 +202,7 @@ typedef enum
NSString *ship_desc;
int ship_trade_in_factor;
NSDictionary *script;
NSDictionary *worldScripts;
NSMutableDictionary *mission_variables;
NSMutableDictionary *localVariables;
int missionTextRow;
@ -316,7 +316,7 @@ typedef enum
Random_Seed galaxy_seed;
OOCreditsQuantity credits;
uint8_t galaxy_number;
OOGalaxyID galaxy_number;
OOWeaponType forward_weapon; // Is there a reason for having both this and forward_weapon_type? -- ahruman
OOWeaponType aft_weapon; // ditto
OOWeaponType port_weapon;

View File

@ -51,6 +51,7 @@ MA 02110-1301, USA.
#import "OOConstToString.h"
#import "OOScript.h"
#import "OOPlayerProxyScript.h"
#import "HeadUpDisplay.h"
#ifndef GNUSTEP
@ -785,7 +786,7 @@ static PlayerEntity *sSharedPlayer = nil;
dockingReport = [[NSMutableString string] retain];
script = [[ResourceManager loadScripts] retain];
worldScripts = [[ResourceManager loadScripts] retain];
[self initControls];
@ -987,6 +988,8 @@ static PlayerEntity *sSharedPlayer = nil;
entity_personality = ranrot_rand() & 0x7FFF;
[self setSystem_seed:[UNIVERSE findSystemAtCoords:[self galaxy_coordinates] withGalaxySeed:[self galaxy_seed]]];
[self sendMessageToScripts:@"reset"];
}
@ -1206,6 +1209,9 @@ static PlayerEntity *sSharedPlayer = nil;
subentityRotationalVelocity = kIdentityQuaternion;
ScanQuaternionFromString([shipDict objectForKey:@"rotational_velocity"], &subentityRotationalVelocity);
[script release];
script = [[OOPlayerProxyScript alloc] init];
return YES;
}
@ -1216,7 +1222,7 @@ static PlayerEntity *sSharedPlayer = nil;
[hud release];
[comm_log release];
[script release];
[worldScripts release];
[mission_variables release];
[localVariables release];
@ -6231,7 +6237,7 @@ OOSound* burnersound;
NSEnumerator *scriptEnum;
OOScript *theScript;
for (scriptEnum = [script objectEnumerator]; (theScript = [scriptEnum nextObject]); )
for (scriptEnum = [worldScripts objectEnumerator]; (theScript = [scriptEnum nextObject]); )
{
[theScript doEvent:message withArguments:arguments];
}

View File

@ -125,7 +125,7 @@ static NSString * mission_key;
OOLog(@"script.trace.runWorld", @"----- Running world script with state %@", [self status_string]);
OOLogIndentIf(@"script.trace.runWorld");
for (scriptEnum = [script objectEnumerator]; (theScript = [scriptEnum nextObject]); )
for (scriptEnum = [worldScripts objectEnumerator]; (theScript = [scriptEnum nextObject]); )
{
[theScript runWithTarget:self];
}
@ -575,7 +575,7 @@ static NSString * mission_key;
result = [NSMutableArray array];
for (scriptEnum = [script keyEnumerator]; (scriptName = [scriptEnum nextObject]); )
for (scriptEnum = [worldScripts keyEnumerator]; (scriptName = [scriptEnum nextObject]); )
{
vars = [mission_variables objectForKey:scriptName];
@ -665,9 +665,7 @@ static NSString * mission_key;
- (NSNumber *) planet_number
{
if (![UNIVERSE sun])
return [NSNumber numberWithInt:-1];
return [NSNumber numberWithInt:[UNIVERSE findSystemNumberAtCoords:galaxy_coordinates withGalaxySeed:galaxy_seed]];
return [NSNumber numberWithInt:[self currentSystemID]];
}

View File

@ -46,4 +46,7 @@ MA 02110-1301, USA.
- (void) awardCargoType:(OOCargoType)type amount:(OOCargoQuantity)amount;
- (OOGalaxyID)currentGalaxyID;
- (OOSystemID)currentSystemID;
@end

View File

@ -173,4 +173,19 @@ MA 02110-1301, USA.
}
}
- (OOGalaxyID)currentGalaxyID
{
return galaxy_number;
}
- (OOSystemID)currentSystemID
{
// You'd think we'd have the current system ID stored somewhere...
if ([UNIVERSE sun] == nil) return -1; // Interstellar space
return [UNIVERSE findSystemNumberAtCoords:galaxy_coordinates withGalaxySeed:galaxy_seed];
}
@end

View File

@ -28,7 +28,7 @@ MA 02110-1301, USA.
#import "OOEntityWithDrawable.h"
@class OOBrain, OOColor, StationEntity, ParticleEntity, PlanetEntity,
WormholeEntity, AI, Octree, OOMesh;
WormholeEntity, AI, Octree, OOMesh, OOScript;
#define MAX_TARGETS 24
@ -107,9 +107,7 @@ MA 02110-1301, USA.
Quaternion subentityRotationalVelocity;
//scripting
NSArray *launch_actions;
NSArray *script_actions; // used by cargo-containers with CARGO_SCRIPT_ACTION when you scoop them, used by Stations when you dock with them, used during custom system set up too
NSArray *death_actions;
OOScript *script;
//docking instructions
NSDictionary *dockingInstructions;
@ -164,7 +162,10 @@ MA 02110-1301, USA.
isFrangible: 1, // frangible => subentities can be damaged individually
cloaking_device_active: 1, // cloaking_device
canFragment: 1, // Can it break into wreckage?
suppressExplosion: 1; // Avoid exploding on death (script hook)
suppressExplosion: 1, // Avoid exploding on death (script hook)
// scripting
haveExecutedSpawnAction: 1;
OOFuelQuantity fuel; // witch-space fuel
GLfloat fuel_accumulator;
@ -296,6 +297,8 @@ MA 02110-1301, USA.
- (NSArray *)subEntities;
- (OOScript *)shipScript;
// octree collision hunting
- (GLfloat)doesHitLine:(Vector) v0: (Vector) v1;
- (GLfloat)doesHitLine:(Vector) v0: (Vector) v1 :(ShipEntity**) hitEntity;

View File

@ -55,6 +55,8 @@ MA 02110-1301, USA.
#import "OODebugGLDrawing.h"
#import "OOScript.h"
#define kOOLogUnconvertedNSLog @"unclassified.ShipEntity"
@ -355,18 +357,6 @@ static NSString * const kOOLogEntityBehaviourChanged = @"entity.behaviour.change
// scan class. NOTE: non-standard capitalization is documented and entrenched.
scanClass = StringToScanClass([shipDict objectForKey:@"scanClass"]);
// scripting
// TODO: use OOScript here. -- Ahruman
launch_actions = [[shipDict arrayForKey:@"launch_actions"] copy];
script_actions = [[shipDict arrayForKey:@"script_actions"] copy];
death_actions = [[shipDict arrayForKey:@"death_actions"] copy];
NSArray *setUpActions = [shipDict arrayForKey:@"setup_actions"];
if (setUpActions != nil)
{
[player setScriptTarget:self];
[player scriptActions:setUpActions forTarget:self];
}
// escorts
escortCount = [shipDict unsignedIntForKey:@"escorts"];
escortsAreSetUp = (escortCount == 0);
@ -417,6 +407,42 @@ static NSString * const kOOLogEntityBehaviourChanged = @"entity.behaviour.change
// unpiloted (like missiles asteroids etc.)
if ([shipDict fuzzyBooleanForKey:@"unpiloted"]) [self setCrew:nil];
// Load (or synthesize) script
script = [OOScript nonLegacyScriptFromFileNamed:[shipDict stringForKey:@"script"]
properties:[NSDictionary dictionaryWithObject:self forKey:@"ship"]];
if (script == nil)
{
NSArray *launchActions = nil,
*scriptActions = nil,
*deathActions = nil,
*setUpActions = nil;
NSMutableDictionary *scriptHandlers = nil;
launchActions = [shipDict arrayForKey:@"launch_actions"];
scriptActions = [shipDict arrayForKey:@"script_actions"];
deathActions = [shipDict arrayForKey:@"death_actions"];
if (launchActions != nil || scriptActions != nil || deathActions != nil)
{
scriptHandlers = [NSMutableDictionary dictionary];
if (launchActions != nil) [scriptHandlers setObject:launchActions forKey:@"didSpawn"];
if (deathActions != nil) [scriptHandlers setObject:deathActions forKey:@"didDie"];
if (scriptActions != nil)
{
[scriptHandlers setObject:scriptActions forKey:@"wasScooped"];
[scriptHandlers setObject:scriptActions forKey:@"playerDidDock"];
}
script = [OOScript scriptWithLegacyEventHandlers:scriptHandlers forOwner:self];
}
setUpActions = [shipDict arrayForKey:@"setup_actions"];
if (setUpActions != nil)
{
[player setScriptTarget:self];
[player scriptActions:setUpActions forTarget:self];
}
}
[script retain];
return YES;
}
@ -437,10 +463,7 @@ static NSString * const kOOLogEntityBehaviourChanged = @"entity.behaviour.change
[roles release];
[sub_entities release];
[laser_color release];
//scripting
[launch_actions release];
[script_actions release];
[death_actions release];
[script release];
[previousCondition release];
@ -501,6 +524,12 @@ static NSString * const kOOLogEntityBehaviourChanged = @"entity.behaviour.change
}
- (OOScript *)shipScript
{
return script;
}
- (BoundingBox)findBoundingBoxRelativeToPosition:(Vector)opv InVectors:(Vector) _i :(Vector) _j :(Vector) _k
{
return [[self mesh] findBoundingBoxRelativeToPosition:opv
@ -1255,12 +1284,10 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
aegis_status = [self checkForAegis]; // is a station or something nearby??
//scripting
if (launch_actions != nil && status == STATUS_IN_FLIGHT)
if (!haveExecutedSpawnAction && script != nil && status == STATUS_IN_FLIGHT)
{
[[PlayerEntity sharedPlayer] setScriptTarget:self];
[[PlayerEntity sharedPlayer] scriptActions:launch_actions forTarget:self];
[launch_actions release];
launch_actions = nil;
[script doEvent:@"didSpawn"];
}
// behaviours according to status and behaviour
@ -3435,15 +3462,10 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple
status = STATUS_DEAD;
//scripting
if (death_actions != nil)
if (script != nil)
{
PlayerEntity* player = [PlayerEntity sharedPlayer];
[player setScriptTarget:self];
[player scriptActions:death_actions forTarget:self];
[death_actions release];
death_actions = nil;
[[PlayerEntity sharedPlayer] setScriptTarget:self];
[script doEvent:@"didDie"];
}
if ([roles isEqual:@"thargoid"])
@ -3925,20 +3947,14 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
OOCargoQuantity n_cargo = (ranrot_rand() % (likely_cargo + 1));
OOCargoQuantity cargo_to_go;
if (status == STATUS_DEAD)
return;
if (status == STATUS_DEAD) return;
status = STATUS_DEAD;
//scripting
if (death_actions != nil)
if (script != nil)
{
PlayerEntity* player = [PlayerEntity sharedPlayer];
[player setScriptTarget:self];
[player scriptActions:death_actions forTarget:self];
[death_actions release];
death_actions = nil;
[[PlayerEntity sharedPlayer] setScriptTarget:self];
[script doEvent:@"didDie"];
}
// two parts to the explosion:
@ -6073,16 +6089,12 @@ BOOL class_masslocks(int some_class)
case CARGO_SCRIPTED_ITEM:
{
NSArray* actions = other->script_actions;
//scripting
if (actions != nil)
{
PlayerEntity* player = [PlayerEntity sharedPlayer];
[player setScriptTarget:self];
[player scriptActions:actions forTarget:other];
}
PlayerEntity *player = [PlayerEntity sharedPlayer];
[player setScriptTarget:self];
[other->script doEvent:@"wasScooped" withArgument:self];
[script doEvent:@"didScoop" withArgument:other];
if (isPlayer)
{
NSString* scoopedMS = [NSString stringWithFormat:ExpandDescriptionForCurrentSystem(@"[@-scooped]"), [other name]];

View File

@ -37,6 +37,7 @@ MA 02110-1301, USA.
#import "AI.h"
#import "OOCharacter.h"
#import "OOScript.h"
#import "OODebugGLDrawing.h"
#define kOOLogUnconvertedNSLog @"unclassified.StationEntity"
@ -1176,6 +1177,8 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
- (void) noteDockedShip:(ShipEntity *) ship
{
if (ship == nil) return;
// set last launch time to avoid clashes with outgoing ships
last_launch_time = [UNIVERSE getTime];
if ([[ship roles] isEqual:@"shuttle"])
@ -1202,14 +1205,14 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
if ((id_lock[i] == ship_id)||([UNIVERSE entityForUniversalID:id_lock[i]] == nil))
id_lock[i] = NO_TARGET;
if (ship == [PlayerEntity sharedPlayer]) // ie. the player
if (script != nil)
{
//scripting
if ([script_actions count])
{
[(PlayerEntity *)ship setScriptTarget:self];
[(PlayerEntity *)ship scriptActions: script_actions forTarget: ship];
}
PlayerEntity *player = [PlayerEntity sharedPlayer];
[player setScriptTarget:self];
// Two actions here. playerDidDock is equivalent to legacy script_actions. shipDidDock is more general.
if (ship == player) [script doEvent:@"playerDidDock"];
[script doEvent:@"shipDidDock" withArgument:ship];
}
}

View File

@ -213,13 +213,13 @@ BOOL JSValueToEntity(JSContext *context, jsval value, Entity **outEntity)
BOOL JSEntityGetEntity(JSContext *context, JSObject *entityObj, Entity **outEntity)
{
OOWeakReference *proxy = nil;
// OOWeakReference *proxy = nil;
if (outEntity == NULL) return NO;
*outEntity = nil;
if (entityObj == NULL) return NO;
if (EXPECT_NOT(context == NULL)) context = [[OOJavaScriptEngine sharedEngine] context];
/*
// If it is an entity proxy...
if ([sEntitySubClasses member:[NSValue valueWithPointer:JS_GetClass(entityObj)]] != nil)
{
@ -229,8 +229,11 @@ BOOL JSEntityGetEntity(JSContext *context, JSObject *entityObj, Entity **outEnti
*outEntity = [proxy weakRefUnderlyingObject];
return YES;
}
}
}*/
*outEntity = JSObjectToObject(context, entityObj);
if ([*outEntity isKindOfClass:[Entity class]]) return YES;
*outEntity = nil;
return NO;
}
@ -251,6 +254,7 @@ void JSEntityRegisterEntitySubclass(JSClass *theClass)
{
if (sEntitySubClasses == nil) sEntitySubClasses = [[NSMutableSet alloc] init];
[sEntitySubClasses addObject:[NSValue valueWithPointer:theClass]];
JSRegisterObjectConverter(theClass, JSBasicPrivateObjectConverter);
}

View File

@ -225,7 +225,7 @@ static JSBool PlayerGetProperty(JSContext *context, JSObject *this, jsval name,
case kPlayer_dockedStation:
result = [player dockedStation];
if (result == nil) *outValue = JSVAL_NULL; // We want null, not undefined.
if (result == nil) result = [NSNull null];
break;
case kPlayer_dockedStationName:

View File

@ -23,24 +23,32 @@ MA 02110-1301, USA.
*/
#include "OOScript.h"
#include <jsapi.h>
#import "OOScript.h"
#import "OOWeakReference.h"
#import <jsapi.h>
@interface OOJSScript : OOScript
@interface OOJSScript: OOScript <OOWeakReferenceSupport>
{
JSContext *context;
JSObject *object;
NSString *name;
NSString *description;
NSString *version;
JSContext *context;
JSObject *object;
NSString *name;
NSString *description;
NSString *version;
OOWeakReference *weakSelf;
}
+ (id)scriptWithPath:(NSString *)path;
+ (id)scriptWithPath:(NSString *)path properties:(NSDictionary *)properties;
- (id)initWithPath:(NSString *)path;
- (id)initWithPath:(NSString *)path andContext:(JSContext *)context;
- (id)initWithPath:(NSString *)path properties:(NSDictionary *)properties;
- (id)initWithPath:(NSString *)path properties:(NSDictionary *)properties context:(JSContext *)context;
+ (OOJSScript *)currentlyRunningScript;
@end
void InitOOJSScript(JSContext *context, JSObject *global);

View File

@ -31,11 +31,25 @@ MA 02110-1301, USA.
#import "EntityOOJavaScriptExtensions.h"
OOJSScript *currentOOJSScript;
JSClass script_class =
typedef struct RunningStack RunningStack;
struct RunningStack
{
"JSScript",
RunningStack *back;
OOJSScript *current;
};
static JSObject *sScriptPrototype;
static RunningStack *sRunningStack = NULL;
static JSBool JSScriptConvert(JSContext *context, JSObject *this, JSType type, jsval *outValue);
static void JSScriptFinalize(JSContext *context, JSObject *this);
static JSClass sScriptClass =
{
"Script",
JSCLASS_HAS_PRIVATE,
JS_PropertyStub,
@ -44,8 +58,8 @@ JSClass script_class =
JS_PropertyStub,
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
JS_FinalizeStub
JSScriptConvert,
JSScriptFinalize
};
@ -58,25 +72,28 @@ JSClass script_class =
@implementation OOJSScript
+ (id)scriptWithPath:(NSString *)path
+ (id)scriptWithPath:(NSString *)path properties:(NSDictionary *)properties
{
return [[[self alloc] initWithPath:path] autorelease];
return [[[self alloc] initWithPath:path properties:properties] autorelease];
}
- (id)initWithPath:(NSString *)path
- (id)initWithPath:(NSString *)path properties:(NSDictionary *)properties
{
return [self initWithPath:path andContext:[[OOJavaScriptEngine sharedEngine] context]];
return [self initWithPath:path properties:properties context:[[OOJavaScriptEngine sharedEngine] context]];
}
- (id)initWithPath:(NSString *)path andContext:(JSContext *)inContext
- (id)initWithPath:(NSString *)path properties:(NSDictionary *)properties context:(JSContext *)inContext
{
NSString *problem = nil; // Acts as error flag.
NSString *fileContents = nil;
NSData *data = nil;
JSScript *script = NULL;
jsval returnValue;
NSString *problem = nil; // Acts as error flag.
NSString *fileContents = nil;
NSData *data = nil;
JSScript *script = NULL;
jsval returnValue;
NSEnumerator *keyEnum = nil;
NSString *key = nil;
id property = nil;
self = [super init];
if (self == nil) problem = @"allocation failure";
@ -85,9 +102,16 @@ JSClass script_class =
if (!problem)
{
context = inContext;
object = JS_NewObject(context, &script_class, 0x00, JS_GetGlobalObject(context));
// Do we actually want parent to be the global object here?
object = JS_NewObject(context, &sScriptClass, sScriptPrototype, JS_GetGlobalObject(context));
if (object == NULL) problem = @"allocation failure";
}
if (!problem)
{
if (!JS_SetPrivate(context, object, [self weakRetain])) problem = @"could not set private backreference";
}
if (!problem)
{
if (!JS_AddRoot(context, &object)) // note 2nd arg is a pointer-to-pointer
@ -110,6 +134,19 @@ JSClass script_class =
if (script == NULL) problem = @"compilation failed";
}
// Set properties.
if (!problem && properties != nil)
{
for (keyEnum = [properties keyEnumerator]; (key = [keyEnum nextObject]); )
{
if ([key isKindOfClass:[NSString class]])
{
property = [properties objectForKey:key];
[self defineProperty:property named:key];
}
}
}
// Run the script (allowing it to set up the properties we need, as well as setting up those event handlers)
if (!problem)
{
@ -126,7 +163,11 @@ JSClass script_class =
{
// Get display attributes from script
name = [JSPropertyAsString(context, object, "name") retain];
if (name == nil) name = [[self scriptNameFromPath:path] retain];
if (name == nil)
{
name = [[self scriptNameFromPath:path] retain];
[self setProperty:name named:@"name"];
}
version = [JSPropertyAsString(context, object, "version") retain];
description = [JSPropertyAsString(context, object, "description") retain];
@ -144,21 +185,56 @@ JSClass script_class =
return self;
}
- (void) dealloc
{
[name release];
[description release];
[version release];
[weakSelf weakRefDrop];
[super dealloc];
}
+ (OOJSScript *)currentlyRunningScript
{
if (sRunningStack == NULL) return NULL;
return sRunningStack->current;
}
- (id) weakRetain
{
if (weakSelf == nil) weakSelf = [OOWeakReference weakRefWithObject:self];
return [weakSelf retain];
}
- (void) weakRefDied:(OOWeakReference *)weakRef
{
if (weakRef == weakSelf) weakSelf = nil;
}
- (NSString *) name
{
return name;
}
- (NSString *) scriptDescription
{
return description;
}
- (NSString *) version
{
return version;
}
- (void)runWithTarget:(Entity *)target
{
[self doEvent:@"tickle" withArguments:[NSArray arrayWithObject:[[PlayerEntity sharedPlayer] status_string]]];
@ -172,6 +248,7 @@ JSClass script_class =
JSFunction *function;
uintN argc;
jsval *argv = NULL;
RunningStack stackElement;
OK = JS_GetProperty(context, object, [eventName cString], &value);
if (OK && !JSVAL_IS_VOID(value))
@ -179,10 +256,18 @@ JSClass script_class =
function = JS_ValueToFunction(context, value);
if (function != NULL)
{
currentOOJSScript = self;
// Push self on stack of running scripts
stackElement.back = sRunningStack;
stackElement.current = self;
sRunningStack = &stackElement;
JSArgumentsFromArray(context, arguments, &argc, &argv);
OK = JS_CallFunction(context, object, function, argc, argv, &value);
if (argv != NULL) free(argv);
// Pop running scripts stack
sRunningStack = stackElement.back;
return OK;
}
}
@ -191,6 +276,50 @@ JSClass script_class =
}
- (id)propertyNamed:(NSString *)propName
{
BOOL OK;
jsval value = nil;
if (propName == nil) return nil;
OK = JS_GetProperty(context, object, [propName UTF8String], &value);
if (!OK || JSVAL_IS_VOID(value)) return nil;
return JSValueToObject(context, value);
}
- (BOOL)setProperty:(id)value named:(NSString *)propName
{
jsval jsValue;
if (value == nil || propName == nil) return NO;
jsValue = [value javaScriptValueInContext:context];
if (!JSVAL_IS_VOID(jsValue))
{
return JS_DefineProperty(context, object, [propName UTF8String], jsValue, NULL, NULL, JSPROP_ENUMERATE);
}
return NO;
}
- (BOOL)defineProperty:(id)value named:(NSString *)propName
{
jsval jsValue;
if (value == nil || propName == nil) return NO;
jsValue = [value javaScriptValueInContext:context];
if (!JSVAL_IS_VOID(jsValue))
{
return JS_DefineProperty(context, object, [propName UTF8String], jsValue, NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
}
return NO;
}
/* Generate default name for script which doesn't set its name property when
first run.
@ -238,4 +367,63 @@ JSClass script_class =
return [theName stringByAppendingString:@".anon-script"];
}
- (jsval)javaScriptValueInContext:(JSContext *)context
{
return OBJECT_TO_JSVAL(object);
}
@end
@implementation OOScript(OOJavaScriptConversion)
- (jsval)javaScriptValueInContext:(JSContext *)context
{
return JSVAL_NULL;
}
@end
void InitOOJSScript(JSContext *context, JSObject *global)
{
sScriptPrototype = JS_InitClass(context, global, NULL, &sScriptClass, NULL, 0, NULL, NULL, NULL, NULL);
JSRegisterObjectConverter(&sScriptClass, JSBasicPrivateObjectConverter);
}
static JSBool JSScriptConvert(JSContext *context, JSObject *this, JSType type, jsval *outValue)
{
OOJSScript *script = nil;
switch (type)
{
case JSTYPE_VOID: // Used for string concatenation.
case JSTYPE_STRING:
// Return description of script
script = JS_GetInstancePrivate(context, this, &sScriptClass, NULL);
script = [script weakRefUnderlyingObject];
if (script != nil)
{
*outValue = [[script description] javaScriptValueInContext:context];
}
else
{
*outValue = STRING_TO_JSVAL(JS_InternString(context, "[stale Script]"));
}
return YES;
default:
// Contrary to what passes for documentation, JS_ConvertStub is not a no-op.
return JS_ConvertStub(context, this, type, outValue);
}
}
static void JSScriptFinalize(JSContext *context, JSObject *this)
{
OOLog(@"js.script.temp", @"%@ called for %p", this);
[(id)JS_GetPrivate(context, this) release];
JS_SetPrivate(context, this, nil);
}

View File

@ -102,6 +102,7 @@ enum
kShip_maxCargo, // maximum cargo, integer, read-only
kShip_speed, // current flight speed, double, read-only (should probably be read/write, but may interfere with AI behaviour)
kShip_maxSpeed, // maximum flight speed, double, read-only
kShip_script // script, Script, read-only
};
@ -136,6 +137,7 @@ static JSPropertySpec sShipProperties[] =
{ "maxCargo", kShip_maxCargo, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
{ "speed", kShip_speed, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
{ "maxSpeed", kShip_maxSpeed, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
{ "script", kShip_script, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
{ 0 }
};
@ -225,7 +227,7 @@ static JSBool ShipGetProperty(JSContext *context, JSObject *this, jsval name, js
case kShip_subEntities:
result = [entity subEntitiesForScript];
if (result == nil) *outValue = JSVAL_NULL; // We want null, not undefined.
if (result == nil) result = [NSNull null];
break;
case kShip_hasSuspendedAI:
@ -234,12 +236,12 @@ static JSBool ShipGetProperty(JSContext *context, JSObject *this, jsval name, js
case kShip_target:
result = [entity primaryTarget];
if (result == nil) *outValue = JSVAL_NULL; // We want null, not undefined.
if (result == nil) result = [NSNull null];
break;
case kShip_escorts:
result = [entity escorts];
if (result == nil) *outValue = JSVAL_NULL; // We want null, not undefined.
if (result == nil) result = [NSNull null];
break;
case kShip_temperature:
@ -260,7 +262,7 @@ static JSBool ShipGetProperty(JSContext *context, JSObject *this, jsval name, js
case kShip_beaconCode:
result = [entity beaconCode];
if (result == nil) *outValue = JSVAL_NULL; // We want null, not undefined.
if (result == nil) result = [NSNull null];
break;
case kShip_isFrangible:
@ -281,7 +283,7 @@ static JSBool ShipGetProperty(JSContext *context, JSObject *this, jsval name, js
case kShip_potentialCollider:
result = [entity proximity_alert];
if (result == nil) *outValue = JSVAL_NULL; // We want null, not undefined.
if (result == nil) result = [NSNull null];
break;
case kShip_hasHostileTarget:
@ -315,6 +317,11 @@ static JSBool ShipGetProperty(JSContext *context, JSObject *this, jsval name, js
case kShip_maxSpeed:
JS_NewDoubleValue(context, [entity maxFlightSpeed], outValue);
break;
case kShip_script:
result = [entity shipScript];
if (result == nil) result = [NSNull null];
break;
default:
OOReportJavaScriptBadPropertySelector(context, @"Ship", JSVAL_TO_INT(name));

View File

@ -0,0 +1,32 @@
/*
OOJSSystem.h
JavaScript proxy for the current system.
Oolite
Copyright (C) 2004-2007 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
#import <Foundation/Foundation.h>
#import <jsapi.h>
void InitOOJSSystem(JSContext *context, JSObject *global);

View File

@ -0,0 +1,588 @@
/*
OOJSSystem.m
Oolite
Copyright (C) 2004-2007 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
#import "OOJSSystem.h"
#import "OOJavaScriptEngine.h"
#import "OOJSVector.h"
#import "OOJSPlayer.h"
#import "Universe.h"
#import "PlanetEntity.h"
#import "PlayerEntityScriptMethods.h"
#import "OOCollectionExtractors.h"
#import "OOConstToString.h"
static JSObject *sSystemPrototype;
static JSObject *sSystemObject;
static Random_Seed sCurrentSystem;
static NSDictionary *sPlanetInfo;
static JSBool SystemGetProperty(JSContext *context, JSObject *this, jsval name, jsval *outValue);
static JSBool SystemSetProperty(JSContext *context, JSObject *this, jsval name, jsval *value);
static JSBool SystemAddPlanet(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool SystemAddMoon(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool SystemSendAllShipsAway(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool SystemSetSunNova(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool SystemCountShipsWithRole(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool SystemAddShips(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool SystemLegacyAddShips(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool SystemLegacyAddSystemShips(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool SystemLegacyAddShipsAt(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool SystemLegacyAddShipsAtPrecisely(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool SystemLegacyAddShipsWithinRadius(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool SystemLegacySpawn(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool SystemLegacySpawnShip(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSClass sSystemClass =
{
"System",
0,
JS_PropertyStub,
JS_PropertyStub,
SystemGetProperty,
SystemSetProperty,
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
JS_FinalizeStub
};
enum
{
// Property IDs
kSystem_ID, // planet number, integer, read-only
kSystem_name, // name, string, read/write
kSystem_description, // description, string, read/write
kSystem_inhabitantsDescription, // description of inhabitant species, string, read/write
kSystem_goingNova, // sun is going nova, boolean, read-only (should be moved to sun)
kSystem_goneNova, // sun has gone nova, boolean, read-only (should be moved to sun)
kSystem_government, // government ID, integer, read/write
kSystem_governmentDescription, // government ID description, string, read-only
kSystem_economy, // economy ID, integer, read/write
kSystem_economyDescription, // economy ID description, string, read-only
kSystem_techLevel, // tech level ID, integer, read/write
kSystem_population, // population, integer, read/write
kSystem_productivity, // productivity, integer, read/write
kSystem_isInterstellarSpace, // is interstellar space, boolean, read-only
kSystem_mainStation // system's main station, Station, read-only
};
static JSPropertySpec sSystemProperties[] =
{
// JS name ID flags
{ "ID", kSystem_ID, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
{ "name", kSystem_name, JSPROP_PERMANENT | JSPROP_ENUMERATE },
{ "description", kSystem_description, JSPROP_PERMANENT | JSPROP_ENUMERATE },
{ "inhabitantsDescription", kSystem_inhabitantsDescription, JSPROP_PERMANENT | JSPROP_ENUMERATE },
{ "goingNova", kSystem_goingNova, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
{ "goneNova", kSystem_goneNova, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
{ "government", kSystem_government, JSPROP_PERMANENT | JSPROP_ENUMERATE },
{ "governmentDescription", kSystem_governmentDescription, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
{ "economy", kSystem_economy, JSPROP_PERMANENT | JSPROP_ENUMERATE },
{ "economyDescription", kSystem_economyDescription, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
{ "techLevel", kSystem_techLevel, JSPROP_PERMANENT | JSPROP_ENUMERATE },
{ "population", kSystem_population, JSPROP_PERMANENT | JSPROP_ENUMERATE },
{ "productivity", kSystem_productivity, JSPROP_PERMANENT | JSPROP_ENUMERATE },
{ "isInterstellarSpace", kSystem_isInterstellarSpace, JSPROP_PERMANENT | JSPROP_ENUMERATE },
{ "mainStation", kSystem_mainStation, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
{ 0 }
};
static JSFunctionSpec sSystemMethods[] =
{
// JS name Function min args
{ "addPlanet", SystemAddPlanet, 1 },
{ "addMoon", SystemAddMoon, 1 },
{ "sendAllShipsAway", SystemSendAllShipsAway, 1 },
{ "setSunNova", SystemSetSunNova, 1 },
{ "countShipsWithRole", SystemCountShipsWithRole, 1 },
{ "addShips", SystemAddShips, 3 },
{ "legacy_addShips", SystemLegacyAddShips, 2 },
{ "legacy_addSystemShips", SystemLegacyAddSystemShips, 3 },
{ "legacy_addShipsAt", SystemLegacyAddShipsAt, 6 },
{ "legacy_addShipsAtPrecisely", SystemLegacyAddShipsAtPrecisely, 6 },
{ "legacy_addShipsWithinRadius", SystemLegacyAddShipsWithinRadius, 7 },
{ "legacy_spawn", SystemLegacySpawn, 2 },
{ "legacy_spawnShip", SystemLegacySpawnShip, 1 },
{ 0 }
};
void InitOOJSSystem(JSContext *context, JSObject *global)
{
sSystemPrototype = JS_InitClass(context, global, NULL, &sSystemClass, NULL, 0, sSystemProperties, sSystemMethods, NULL, NULL);
// Create player object as a property of the global object.
sSystemObject = JS_DefineObject(context, global, "system", &sSystemClass, sSystemPrototype, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
}
static JSBool SystemGetProperty(JSContext *context, JSObject *this, jsval name, jsval *outValue)
{
id result = nil;
PlayerEntity *player = nil;
if (!JSVAL_IS_INT(name)) return YES;
player = OPlayerForScripting();
if (!equal_seeds(sCurrentSystem, player->system_seed))
{
sCurrentSystem = player->system_seed;
[sPlanetInfo release];
sPlanetInfo = [[UNIVERSE generateSystemData:sCurrentSystem] retain];
}
switch (JSVAL_TO_INT(name))
{
case kSystem_ID:
*outValue = INT_TO_JSVAL([player currentSystemID]);
break;
case kSystem_name:
if ([UNIVERSE sun] != nil)
{
result = [sPlanetInfo objectForKey:KEY_NAME];
if (result == nil) result = [NSNull null];
}
else
{
result = @"Interstellar space";
}
break;
case kSystem_description:
result = [sPlanetInfo objectForKey:KEY_DESCRIPTION];
if (result == nil) result = [NSNull null];
break;
case kSystem_inhabitantsDescription:
result = [sPlanetInfo objectForKey:KEY_INHABITANTS];
if (result == nil) result = [NSNull null];
break;
case kSystem_goingNova:
*outValue = BOOLToJSVal([[UNIVERSE sun] willGoNova]);
break;
case kSystem_goneNova:
*outValue = BOOLToJSVal([[UNIVERSE sun] goneNova]);
break;
case kSystem_government:
*outValue = INT_TO_JSVAL([sPlanetInfo intForKey:KEY_GOVERNMENT]);
break;
case kSystem_governmentDescription:
result = GovernmentToString([sPlanetInfo intForKey:KEY_GOVERNMENT]);
if (result == nil) result = [NSNull null];
break;
case kSystem_economy:
*outValue = INT_TO_JSVAL([sPlanetInfo intForKey:KEY_ECONOMY]);
break;
case kSystem_economyDescription:
result = EconomyToString([sPlanetInfo intForKey:KEY_ECONOMY]);
if (result == nil) result = [NSNull null];
break;
case kSystem_techLevel:
*outValue = INT_TO_JSVAL([sPlanetInfo intForKey:KEY_TECHLEVEL]);
break;
case kSystem_population:
*outValue = INT_TO_JSVAL([sPlanetInfo intForKey:KEY_POPULATION]);
break;
case kSystem_productivity:
*outValue = INT_TO_JSVAL([sPlanetInfo intForKey:KEY_PRODUCTIVITY]);
break;
case kSystem_isInterstellarSpace:
*outValue = BOOLToJSVal([UNIVERSE sun] == nil);
break;
case kSystem_mainStation:
result = [UNIVERSE station];
break;
default:
OOReportJavaScriptBadPropertySelector(context, @"System", JSVAL_TO_INT(name));
return NO;
}
if (result != nil) *outValue = [result javaScriptValueInContext:context];
return YES;
}
static JSBool SystemSetProperty(JSContext *context, JSObject *this, jsval name, jsval *value)
{
PlayerEntity *player = nil;
OOGalaxyID galaxy;
OOSystemID system;
NSString *stringValue = nil;
int32 iValue;
if (!JSVAL_IS_INT(name)) return YES;
player = OPlayerForScripting();
if (!equal_seeds(sCurrentSystem, player->system_seed))
{
sCurrentSystem = player->system_seed;
[sPlanetInfo release];
sPlanetInfo = [[UNIVERSE generateSystemData:sCurrentSystem] retain];
}
galaxy = [player currentGalaxyID];
system = [player currentSystemID];
if (system == -1) return YES; // Can't change anything in interstellar space.
switch (JSVAL_TO_INT(name))
{
case kSystem_name:
stringValue = JSValToNSString(context, *value);
if (stringValue != nil) [UNIVERSE setSystemDataForGalaxy:galaxy planet:system key:KEY_NAME value:stringValue];
break;
case kSystem_description:
stringValue = JSValToNSString(context, *value);
if (stringValue != nil) [UNIVERSE setSystemDataForGalaxy:galaxy planet:system key:KEY_DESCRIPTION value:stringValue];
break;
case kSystem_inhabitantsDescription:
stringValue = JSValToNSString(context, *value);
if (stringValue != nil) [UNIVERSE setSystemDataForGalaxy:galaxy planet:system key:KEY_INHABITANTS value:stringValue];
break;
case kSystem_government:
if (JS_ValueToInt32(context, *value, &iValue))
{
if (iValue < 0) iValue = 0;
if (7 < iValue) iValue = 7;
[UNIVERSE setSystemDataForGalaxy:galaxy planet:system key:KEY_GOVERNMENT value:[NSNumber numberWithInt:iValue]];
}
break;
case kSystem_economy:
if (JS_ValueToInt32(context, *value, &iValue))
{
if (iValue < 0) iValue = 0;
if (7 < iValue) iValue = 7;
[UNIVERSE setSystemDataForGalaxy:galaxy planet:system key:KEY_ECONOMY value:[NSNumber numberWithInt:iValue]];
}
break;
case kSystem_techLevel:
if (JS_ValueToInt32(context, *value, &iValue))
{
if (iValue < 0) iValue = 0;
if (15 < iValue) iValue = 15;
[UNIVERSE setSystemDataForGalaxy:galaxy planet:system key:KEY_TECHLEVEL value:[NSNumber numberWithInt:iValue]];
}
break;
case kSystem_population:
if (JS_ValueToInt32(context, *value, &iValue))
{
[UNIVERSE setSystemDataForGalaxy:galaxy planet:system key:KEY_POPULATION value:[NSNumber numberWithInt:iValue]];
}
break;
case kSystem_productivity:
if (JS_ValueToInt32(context, *value, &iValue))
{
[UNIVERSE setSystemDataForGalaxy:galaxy planet:system key:KEY_PRODUCTIVITY value:[NSNumber numberWithInt:iValue]];
}
break;
default:
OOReportJavaScriptBadPropertySelector(context, @"System", JSVAL_TO_INT(name));
return NO;
}
return YES;
}
static JSBool SystemAddPlanet(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
PlayerEntity *player = OPlayerForScripting();
if (argc > 0 && JSVAL_IS_STRING(argv[0]))
{
NSString *key = JSValToNSString(context, argv[0]);
[player addPlanet:key];
}
return YES;
}
static JSBool SystemAddMoon(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
PlayerEntity *player = OPlayerForScripting();
if (argc > 0 && JSVAL_IS_STRING(argv[0]))
{
NSString *key = JSValToNSString(context, argv[0]);
[player addMoon:key];
}
return YES;
}
static JSBool SystemSendAllShipsAway(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
PlayerEntity *player = OPlayerForScripting();
[player sendAllShipsAway];
return YES;
}
static JSBool SystemSetSunNova(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
PlayerEntity *player = OPlayerForScripting();
NSString *key = JSValToNSString(context, argv[0]);
[player setSunNovaIn:key];
return YES;
}
static JSBool SystemCountShipsWithRole(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
NSString *role = nil;
int count;
role = JSValToNSString(context, argv[0]);
count = [UNIVERSE countShipsWithRole:role];
*outResult = INT_TO_JSVAL(count);
return YES;
}
#define DEFAULT_RADIUS 500.0
static JSBool SystemAddShips(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
NSString *role = nil;
int32 count;
Vector where;
double radius = DEFAULT_RADIUS;
uintN consumed;
role = JSValToNSString(context, argv[0]);
if (!JS_ValueToInt32(context, argv[1], &count) || count < 1 || 64 < count)
{
OOReportJavaScriptError(context, @"System.%@(): expected positive count, got %@.", @"addShips", JSValToNSString(context, argv[1]));
return YES;
}
if (!VectorFromArgumentList(context, @"System", @"addShips", argc - 2, argv + 2, &where, &consumed)) return YES;
argc += 2 + consumed;
argv += 2 + consumed;
if (argc != 0 && JS_ValueToNumber(context, argv[0], &radius))
{
}
OOReportJavaScriptError(context, @"System.addShips(): not implemented.");
return YES;
}
static JSBool SystemLegacyAddShips(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
NSString *role = nil;
int32 count;
role = JSValToNSString(context, argv[0]);
if (!JS_ValueToInt32(context, argv[1], &count) || count < 1 || 64 < count)
{
OOReportJavaScriptError(context, @"System.%@(): expected positive count, got %@.", @"legacy_addShips", JSValToNSString(context, argv[1]));
return YES;
}
while (count--) [UNIVERSE witchspaceShipWithRole:role];
return YES;
}
static JSBool SystemLegacyAddSystemShips(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
jsdouble position;
NSString *role = nil;
int32 count;
role = JSValToNSString(context, argv[0]);
if (!JS_ValueToInt32(context, argv[1], &count) || count < 1 || 64 < count)
{
OOReportJavaScriptError(context, @"System.%@(): expected positive count, got %@.", @"legacy_addSystemShips", JSValToNSString(context, argv[1]));
return YES;
}
JS_ValueToNumber(context, argv[2], &position);
while (count--) [UNIVERSE addShipWithRole:role nearRouteOneAt:position];
return YES;
}
static JSBool SystemLegacyAddShipsAt(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
PlayerEntity *player = OPlayerForScripting();
Vector where;
NSString *role = nil;
int32 count;
NSString *coordScheme = nil;
NSString *arg = nil;
role = JSValToNSString(context, argv[0]);
if (!JS_ValueToInt32(context, argv[1], &count) || count < 1 || 64 < count)
{
OOReportJavaScriptError(context, @"System.%@(): expected positive count, got %@.", @"legacy_addShipsAt", JSValToNSString(context, argv[1]));
return YES;
}
coordScheme = JSValToNSString(context, argv[2]);
if (!VectorFromArgumentList(context, @"System", @"legacy_addShipsAt", argc - 3, argv + 3, &where, NULL)) return YES;
arg = [NSString stringWithFormat:@"%@ %d %@ %f %f %f", role, count, coordScheme, where.x, where.y, where.z];
[player addShipsAt:arg];
return YES;
}
static JSBool SystemLegacyAddShipsAtPrecisely(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
PlayerEntity *player = OPlayerForScripting();
Vector where;
NSString *role = nil;
int32 count;
NSString *coordScheme = nil;
NSString *arg = nil;
role = JSValToNSString(context, argv[0]);
if (!JS_ValueToInt32(context, argv[1], &count) || count < 1 || 64 < count)
{
OOReportJavaScriptError(context, @"System.%@(): expected positive count, got %@.", @"legacy_addShipsAtPrecisely", JSValToNSString(context, argv[1]));
return YES;
}
coordScheme = JSValToNSString(context, argv[2]);
if (!VectorFromArgumentList(context, @"System", @"legacy_addShipsAtPrecisely", argc - 3, argv + 3, &where, NULL)) return YES;
arg = [NSString stringWithFormat:@"%@ %d %@ %f %f %f", role, count, coordScheme, where.x, where.y, where.z];
[player addShipsAtPrecisely:arg];
return YES;
}
static JSBool SystemLegacyAddShipsWithinRadius(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
PlayerEntity *player = OPlayerForScripting();
Vector where;
jsdouble radius;
NSString *role = nil;
int32 count;
NSString *coordScheme = nil;
NSString *arg = nil;
uintN consumed = 0;
role = JSValToNSString(context, argv[0]);
if (!JS_ValueToInt32(context, argv[1], &count) || count < 1 || 64 < count)
{
OOReportJavaScriptError(context, @"System.%@(): expected positive count, got %@.", @"legacy_addShipWithinRadius", JSValToNSString(context, argv[1]));
return YES;
}
coordScheme = JSValToNSString(context, argv[2]);
if (!VectorFromArgumentList(context, @"System", @"legacy_addShipWithinRadius", argc - 3, argv + 3, &where, &consumed)) return YES;
argc += consumed;
argv += consumed;
JS_ValueToNumber(context, argv[3], &radius);
arg = [NSString stringWithFormat:@"%@ %d %@ %f %f %f %d", role, count, coordScheme, where.x, where.y, where.z, radius];
[player addShipsWithinRadius:arg];
return YES;
}
static JSBool SystemLegacySpawn(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
PlayerEntity *player = OPlayerForScripting();
NSString *role = nil;
int32 count;
NSString *arg = nil;
role = JSValToNSString(context, argv[0]);
if (!JS_ValueToInt32(context, argv[1], &count) || count < 1 || 64 < count)
{
OOReportJavaScriptError(context, @"System.%@(): expected positive count, got %@.", @"legacy_spawn", JSValToNSString(context, argv[1]));
return YES;
}
arg = [NSString stringWithFormat:@"%@ %d", role, count];
[player spawn:arg];
return YES;
}
static JSBool SystemLegacySpawnShip(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
PlayerEntity *player = OPlayerForScripting();
[player spawnShip:JSValToNSString(context, argv[0])];
return YES;
}

View File

@ -92,8 +92,8 @@ OOINLINE jsval BOOLToJSVal(BOOL b)
/* -javaScriptValueInContext:
Return the JavaScript object representation of an object. The default
implementation returns JSVAL_NULL. At this time, NSString, NSNumber,
NSArray and Entity override this.
implementation returns JSVAL_VOID. At this time, NSString, NSNumber,
NSArray, NSNull, Entity and OOScript override this.
*/
- (jsval)javaScriptValueInContext:(JSContext *)context;
@ -124,3 +124,25 @@ OOINLINE NSString *JSValToNSString(JSContext *context, jsval value)
NSString *JSPropertyAsString(JSContext *context, JSObject *object, const char *name);
id JSValueToObject(JSContext *context, jsval value);
id JSObjectToObject(JSContext *context, JSObject *object);
/* Support for JSValueToObject()
JSClassConverterCallback specifies the prototype for a callback function
which converts a JavaScript object to an Objective-C object.
JSBasicPrivateObjectConverter() is a JSClassConverterCallback which
returns the JS object's private storage value. It automatically unpacks
OOWeakReferences if relevant.
JSRegisterObjectConverter() registers a callback for a specific JS class.
It is not automatically propagated to subclasses.
*/
typedef id (*JSClassConverterCallback)(JSContext *context, JSObject *object);
id JSBasicPrivateObjectConverter(JSContext *context, JSObject *object);
void JSRegisterObjectConverter(JSClass *theClass, JSClassConverterCallback converter);

View File

@ -31,12 +31,14 @@ MA 02110-1301, USA.
#import "OOJSShip.h"
#import "OOJSStation.h"
#import "OOJSPlayer.h"
#import "OOJSSystem.h"
#import "jsarray.h"
#import "OOCollectionExtractors.h"
#import "Universe.h"
#import "PlanetEntity.h"
#import "NSStringOOExtensions.h"
#import "OOWeakReference.h"
#include <stdio.h>
#include <string.h>
@ -46,10 +48,7 @@ extern NSString * const kOOLogDebugMessage;
static OOJavaScriptEngine *sSharedEngine = nil;
static JSObject *xglob, *systemObj, *missionObj;
extern OOJSScript *currentOOJSScript;
static JSObject *xglob, *missionObj;
// For _bool scripting methods which always return @"YES" or @"NO" and nothing else.
@ -252,467 +251,6 @@ static JSBool GlobalGetProperty(JSContext *context, JSObject *obj, jsval name, j
}
//===========================================================================
// Universe (solar system) proxy
//===========================================================================
static JSBool SystemGetProperty(JSContext *context, JSObject *obj, jsval name, jsval *vp);
static JSBool SystemSetProperty(JSContext *context, JSObject *obj, jsval name, jsval *vp);
static JSClass System_class =
{
"Universe",
0,
JS_PropertyStub,
JS_PropertyStub,
SystemGetProperty,
SystemSetProperty,
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
JS_FinalizeStub
};
enum System_propertyIDs
{
SYS_ID,
SYS_NAME,
SYS_DESCRIPTION,
SYS_GOING_NOVA,
SYS_GONE_NOVA,
SYS_GOVT_STR,
SYS_GOVT_ID,
SYS_ECONOMY_STR,
SYS_ECONOMY_ID,
SYS_TECH_LVL,
SYS_POPULATION,
SYS_PRODUCTIVITY,
SYS_INHABITANTS
};
static JSPropertySpec System_props[] =
{
// JS name ID flags
{ "ID", SYS_ID, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
{ "name", SYS_NAME, JSPROP_PERMANENT | JSPROP_ENUMERATE },
{ "description", SYS_DESCRIPTION, JSPROP_PERMANENT | JSPROP_ENUMERATE },
{ "inhabitantsDescription", SYS_INHABITANTS, JSPROP_PERMANENT | JSPROP_ENUMERATE },
{ "goingNova", SYS_GOING_NOVA, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
{ "goneNova", SYS_GONE_NOVA, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
{ "government", SYS_GOVT_ID, JSPROP_PERMANENT | JSPROP_ENUMERATE },
{ "governmentDescription", SYS_GOVT_STR, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
{ "economy", SYS_ECONOMY_ID, JSPROP_PERMANENT | JSPROP_ENUMERATE },
{ "economyDescription", SYS_ECONOMY_STR, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
{ "techLevel", SYS_TECH_LVL, JSPROP_PERMANENT | JSPROP_ENUMERATE },
{ "population", SYS_POPULATION, JSPROP_PERMANENT | JSPROP_ENUMERATE },
{ "productivity", SYS_PRODUCTIVITY, JSPROP_PERMANENT | JSPROP_ENUMERATE },
{ 0 }
};
static JSBool SystemAddPlanet(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSBool SystemAddMoon(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSBool SystemSendAllShipsAway(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSBool SystemSetSunNova(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSBool SystemCountShipsWithRole(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSBool SystemAddShips(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSBool SystemAddSystemShips(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSBool SystemAddShipsAt(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSBool SystemAddShipsAtPrecisely(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSBool SystemAddShipsWithinRadius(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSBool SystemSpawn(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSBool SystemSpawnShip(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSFunctionSpec System_funcs[] =
{
// JS name Function min args
{ "addPlanet", SystemAddPlanet, 1 },
{ "addMoon", SystemAddMoon, 1 },
{ "sendAllShipsAway", SystemSendAllShipsAway, 1 },
{ "setSunNova", SystemSetSunNova, 1 },
{ "countShipsWithRole", SystemCountShipsWithRole, 1, 0 },
{ "legacy_addShips", SystemAddShips, 2, 0 },
{ "legacy_addSystemShips", SystemAddSystemShips, 3, 0 },
{ "legacy_addShipsAt", SystemAddShipsAt, 6, 0 },
{ "legacy_addShipsAtPrecisely", SystemAddShipsAtPrecisely, 6, 0 },
{ "legacy_addShipsWithinRadius", SystemAddShipsWithinRadius, 7, 0 },
{ "legacy_spawn", SystemSpawn, 2, 0 },
{ "legacy_spawnShip", SystemSpawnShip, 1, 0 },
{ 0 }
};
static JSBool SystemAddPlanet(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
PlayerEntity *player = OPlayerForScripting();
if (argc > 0 && JSVAL_IS_STRING(argv[0]))
{
NSString *key = JSValToNSString(context, argv[0]);
[player addPlanet:key];
}
return JS_TRUE;
}
static JSBool SystemAddMoon(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
PlayerEntity *player = OPlayerForScripting();
if (argc > 0 && JSVAL_IS_STRING(argv[0]))
{
NSString *key = JSValToNSString(context, argv[0]);
[player addMoon:key];
}
return JS_TRUE;
}
static JSBool SystemSendAllShipsAway(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
PlayerEntity *player = OPlayerForScripting();
[player sendAllShipsAway];
return JS_TRUE;
}
static JSBool SystemSetSunNova(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
PlayerEntity *player = OPlayerForScripting();
if (argc > 0)
{
NSString *key = JSValToNSString(context, argv[0]);
[player setSunNovaIn:key];
}
return JS_TRUE;
}
static Random_Seed currentSystem;
static NSDictionary *planetinfo = nil;
static JSBool SystemGetProperty(JSContext *context, JSObject *obj, jsval name, jsval *vp)
{
if (!JSVAL_IS_INT(name)) return JS_TRUE;
PlayerEntity *player = OPlayerForScripting();
id result = nil;
if (!equal_seeds(currentSystem, player->system_seed))
{
currentSystem = player->system_seed;
[planetinfo release];
planetinfo = [[UNIVERSE generateSystemData:currentSystem] retain];
}
switch (JSVAL_TO_INT(name))
{
case SYS_ID:
result = [player planet_number];
break;
case SYS_NAME:
if ([UNIVERSE sun] != nil)
{
result = [planetinfo objectForKey:KEY_NAME];
if (result == nil) result = @"None"; // TODO: should this return JSVAL_VOID instead? Other cases below. -- ahruman
}
else
{
// Witchspace. (Hmm, does a system that's gone nova have a sun? If not, -[PlayerEntity planet_number] is broken, too.
result = @"Interstellar space";
}
break;
case SYS_DESCRIPTION:
result = [planetinfo objectForKey:KEY_DESCRIPTION];
if (result == nil) result = @"None";
break;
case SYS_INHABITANTS:
result = [planetinfo objectForKey:KEY_INHABITANTS];
if (result == nil) result = @"None";
break;
case SYS_GOING_NOVA:
*vp = BooleanStringToJSVal([player sunWillGoNova_bool]);
break;
case SYS_GONE_NOVA:
*vp = BooleanStringToJSVal([player sunGoneNova_bool]);
break;
case SYS_GOVT_ID:
result = [player systemGovernment_number];
break;
case SYS_GOVT_STR:
result = [player systemGovernment_string];
break;
case SYS_ECONOMY_ID:
result = [player systemEconomy_number];
break;
case SYS_ECONOMY_STR:
result = [player systemEconomy_string];
break;
case SYS_TECH_LVL:
result = [player systemTechLevel_number];
break;
case SYS_POPULATION:
result = [player systemPopulation_number];
break;
case SYS_PRODUCTIVITY:
result = [player systemProductivity_number];
break;
default:
OOReportJavaScriptBadPropertySelector(context, @"System", JSVAL_TO_INT(name));
return NO;
}
if (result != nil) *vp = [result javaScriptValueInContext:context];
return JS_TRUE;
}
static JSBool SystemSetProperty(JSContext *context, JSObject *obj, jsval name, jsval *vp)
{
if (!JSVAL_IS_INT(name)) return JS_TRUE;
PlayerEntity *player = OPlayerForScripting();
if (!equal_seeds(currentSystem, player->system_seed))
{
currentSystem = player->system_seed;
if (planetinfo) [planetinfo release];
planetinfo = [[UNIVERSE generateSystemData:currentSystem] retain];
}
int gn = [[player galaxy_number] intValue];
int pn = [[player planet_number] intValue];
switch (JSVAL_TO_INT(name))
{
case SYS_NAME:
[UNIVERSE setSystemDataForGalaxy:gn planet:pn key:KEY_NAME value:JSValToNSString(context, *vp)];
break;
case SYS_DESCRIPTION:
[UNIVERSE setSystemDataForGalaxy:gn planet:pn key:KEY_DESCRIPTION value:JSValToNSString(context, *vp)];
break;
case SYS_INHABITANTS:
[UNIVERSE setSystemDataForGalaxy:gn planet:pn key:KEY_INHABITANTS value:JSValToNSString(context, *vp)];
break;
case SYS_GOING_NOVA:
*vp = BOOLToJSVal([[UNIVERSE sun] willGoNova]);
break;
case SYS_GONE_NOVA:
*vp = BOOLToJSVal([[UNIVERSE sun] goneNova]);
break;
case SYS_GOVT_ID:
[UNIVERSE setSystemDataForGalaxy:gn planet:pn key:KEY_GOVERNMENT value:[NSNumber numberWithInt:[JSValToNSString(context, *vp) intValue]]];
break;
case SYS_ECONOMY_ID:
[UNIVERSE setSystemDataForGalaxy:gn planet:pn key:KEY_ECONOMY value:[NSNumber numberWithInt:[JSValToNSString(context, *vp) intValue]]];
break;
case SYS_TECH_LVL:
[UNIVERSE setSystemDataForGalaxy:gn planet:pn key:KEY_TECHLEVEL value:[NSNumber numberWithInt:[JSValToNSString(context, *vp) intValue]]];
break;
case SYS_POPULATION:
[UNIVERSE setSystemDataForGalaxy:gn planet:pn key:KEY_POPULATION value:[NSNumber numberWithInt:[JSValToNSString(context, *vp) intValue]]];
break;
case SYS_PRODUCTIVITY:
[UNIVERSE setSystemDataForGalaxy:gn planet:pn key:KEY_PRODUCTIVITY value:[NSNumber numberWithInt:[JSValToNSString(context, *vp) intValue]]];
break;
default:
OOReportJavaScriptBadPropertySelector(context, @"System", JSVAL_TO_INT(name));
return NO;
}
return JS_TRUE;
}
static JSBool SystemCountShipsWithRole(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
NSString *role = nil;
int count;
if (argc == 1)
{
role = JSValToNSString(context, argv[0]);
count = [UNIVERSE countShipsWithRole:role];
*rval = INT_TO_JSVAL(count);
}
return JS_TRUE;
}
static JSBool SystemAddShips(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
NSString *role = nil;
int count;
if (argc == 2)
{
role = JSValToNSString(context, argv[0]);
count = JSVAL_TO_INT(argv[1]);
while (count--) [UNIVERSE witchspaceShipWithRole:role];
}
return JS_TRUE;
}
static JSBool SystemAddSystemShips(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
jsdouble position;
NSString *role = nil;
int count;
if (argc == 3)
{
role = JSValToNSString(context, argv[0]);
count = JSVAL_TO_INT(argv[1]);
JS_ValueToNumber(context, argv[2], &position);
while (count--) [UNIVERSE addShipWithRole:role nearRouteOneAt:position];
}
return JS_TRUE;
}
static JSBool SystemAddShipsAt(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
PlayerEntity *player = OPlayerForScripting();
jsdouble x, y, z;
NSString *role = nil;
int count;
NSString *coordScheme = nil;
NSString *arg = nil;
if (argc == 6)
{
role = JSValToNSString(context, argv[0]);
count = JSVAL_TO_INT(argv[1]);
coordScheme = JSValToNSString(context, argv[2]);
JS_ValueToNumber(context, argv[3], &x);
JS_ValueToNumber(context, argv[4], &y);
JS_ValueToNumber(context, argv[5], &z);
arg = [NSString stringWithFormat:@"%@ %d %@ %f %f %f", role, count, coordScheme, x, y, z];
[player addShipsAt:arg];
}
return JS_TRUE;
}
static JSBool SystemAddShipsAtPrecisely(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
PlayerEntity *player = OPlayerForScripting();
jsdouble x, y, z;
NSString *role = nil;
int count;
NSString *coordScheme = nil;
NSString *arg = nil;
if (argc == 6)
{
role = JSValToNSString(context, argv[0]);
count = JSVAL_TO_INT(argv[1]);
coordScheme = JSValToNSString(context, argv[2]);
JS_ValueToNumber(context, argv[3], &x);
JS_ValueToNumber(context, argv[4], &y);
JS_ValueToNumber(context, argv[5], &z);
arg = [NSString stringWithFormat:@"%@ %d %@ %f %f %f", role, count, coordScheme, x, y, z];
[player addShipsAtPrecisely:arg];
}
return JS_TRUE;
}
static JSBool SystemAddShipsWithinRadius(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
PlayerEntity *player = OPlayerForScripting();
jsdouble x, y, z, radius;
NSString *role = nil;
int count;
NSString *coordScheme = nil;
NSString *arg = nil;
if (argc == 7)
{
role = JSValToNSString(context, argv[0]);
count = JSVAL_TO_INT(argv[1]);
coordScheme = JSValToNSString(context, argv[2]);
JS_ValueToNumber(context, argv[3], &x);
JS_ValueToNumber(context, argv[4], &y);
JS_ValueToNumber(context, argv[5], &z);
JS_ValueToNumber(context, argv[6], &radius);
arg = [NSString stringWithFormat:@"%@ %d %@ %f %f %f %d", role, count, coordScheme, x, y, z, radius];
[player addShipsWithinRadius:arg];
}
return JS_TRUE;
}
static JSBool SystemSpawn(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
PlayerEntity *player = OPlayerForScripting();
NSString *role = nil;
int count;
NSString *arg = nil;
if (argc == 2)
{
role = JSValToNSString(context, argv[0]);
count = JSVAL_TO_INT(argv[1]);
arg = [NSString stringWithFormat:@"%@ %d", role, count];
[player spawn:arg];
}
return JS_TRUE;
}
static JSBool SystemSpawnShip(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
PlayerEntity *player = OPlayerForScripting();
if (argc == 1)
{
[player spawnShip:JSValToNSString(context, argv[0])];
}
return JS_TRUE;
}
//===========================================================================
// Mission class
//===========================================================================
@ -845,9 +383,9 @@ static JSBool MissionSetProperty(JSContext *context, JSObject *obj, jsval name,
JSString *jskey = JS_ValueToString(context, *vp);
NSString *ins = [NSString stringWithCString:JS_GetStringBytes(jskey)];
if ([ins length])
[player setMissionDescription:ins forMission:[currentOOJSScript name]];
[player setMissionDescription:ins forMission:[[OOJSScript currentlyRunningScript] name]];
else
[player clearMissionDescriptionForMission:[currentOOJSScript name]];
[player clearMissionDescriptionForMission:[[OOJSScript currentlyRunningScript] name]];
}
break;
@ -1014,21 +552,25 @@ static void ReportJSError(JSContext *context, const char *message, JSErrorReport
JS_InitStandardClasses(context, globalObject);
JS_DefineProperties(context, globalObject, Global_props);
JS_DefineFunctions(context, globalObject, Global_funcs);
/*
systemObj = JS_DefineObject(context, globalObject, "system", &System_class, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineProperties(context, systemObj, System_props);
JS_DefineFunctions(context, systemObj, System_funcs);
*/
missionObj = JS_DefineObject(context, globalObject, "mission", &Mission_class, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineProperties(context, missionObj, Mission_props);
JS_DefineFunctions(context, missionObj, Mission_funcs);
InitOOJSVector(context, globalObject);
InitOOJSQuaternion(context, globalObject);
InitOOJSSystem(context, globalObject);
InitOOJSEntity(context, globalObject);
InitOOJSShip(context, globalObject);
InitOOJSStation(context, globalObject);
InitOOJSPlayer(context, globalObject);
InitOOJSScript(context, globalObject);
OOLog(@"script.javaScript.init.success", @"Set up JavaScript context.");
@ -1166,14 +708,10 @@ BOOL JSArgumentsFromArray(JSContext *context, NSArray *array, uintN *outArgc, js
JSContext * volatile vCtxt = context;
for (objectEnum = [array objectEnumerator]; (object = [objectEnum nextObject]); )
{
argv[i] = JSVAL_VOID;
NS_DURING
if ([object respondsToSelector:@selector(javaScriptValueInContext:)])
{
argv[i] = [object javaScriptValueInContext:vCtxt];
}
argv[i] = [object javaScriptValueInContext:vCtxt];
NS_HANDLER
argv[i] = JSVAL_VOID;
NS_ENDHANDLER
++i;
}
@ -1204,7 +742,7 @@ JSObject *JSArrayFromNSArray(JSContext *context, NSArray *array)
- (jsval)javaScriptValueInContext:(JSContext *)context
{
return JSVAL_NULL;
return JSVAL_VOID;
}
@end
@ -1397,3 +935,84 @@ NSString *JSPropertyAsString(JSContext *context, JSObject *object, const char *n
return result;
}
static NSMutableDictionary *sObjectConverters;
id JSValueToObject(JSContext *context, jsval value)
{
if (JSVAL_IS_NULL(value) || JSVAL_IS_VOID(value)) return nil;
if (JSVAL_IS_INT(value))
{
return [NSNumber numberWithInt:JSVAL_TO_INT(value)];
}
if (JSVAL_IS_DOUBLE(value))
{
return [NSNumber numberWithDouble:*JSVAL_TO_DOUBLE(value)];
}
if (JSVAL_IS_BOOLEAN(value))
{
return [NSNumber numberWithBool:JSVAL_TO_BOOLEAN(value)];
}
if (JSVAL_IS_STRING(value))
{
return JSValToNSString(context, value);
}
if (JSVAL_IS_OBJECT(value))
{
return JSObjectToObject(context, JSVAL_TO_OBJECT(value));
}
return nil;
}
id JSObjectToObject(JSContext *context, JSObject *object)
{
NSValue *wrappedClass = nil;
NSValue *wrappedConverter = nil;
JSClassConverterCallback converter = NULL;
wrappedClass = [NSValue valueWithPointer:JS_GetClass(object)];
if (wrappedClass != nil) wrappedConverter = [sObjectConverters objectForKey:wrappedClass];
if (wrappedConverter != nil)
{
converter = [wrappedConverter pointerValue];
return converter(context, object);
}
return nil;
}
id JSBasicPrivateObjectConverter(JSContext *context, JSObject *object)
{
id result;
/* This will do the right thing - for non-OOWeakReferences,
weakRefUnderlyingObject returns the object itself. For nil, of course,
it returns nil.
*/
result = JS_GetPrivate(context, object);
return [result weakRefUnderlyingObject];
}
void JSRegisterObjectConverter(JSClass *theClass, JSClassConverterCallback converter)
{
NSValue *wrappedClass = nil;
NSValue *wrappedConverter = nil;
if (theClass == NULL) return;
if (sObjectConverters == nil) sObjectConverters = [[NSMutableDictionary alloc] init];
wrappedClass = [NSValue valueWithPointer:theClass];
if (converter != nil)
{
wrappedConverter = [NSValue valueWithPointer:converter];
[sObjectConverters setObject:wrappedConverter forKey:wrappedClass];
}
else
{
[sObjectConverters removeObjectForKey:wrappedClass];
}
}

View File

@ -0,0 +1,41 @@
/*
OOLegacyEventHandlerScript.h
Script class which manages a set of event handlers implemented as legacy plist
scripts. This is used, for example, for the various event handlers for ships.
Oolite
Copyright (C) 2004-2007 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
#import "OOScript.h"
#import "OOWeakReference.h"
@interface OOLegacyEventHandlerScript: OOScript
{
NSDictionary *_eventHandlers;
id _owner;
}
- (id)initWithEventHandlers:(NSDictionary *)eventHandlers forOwner:(id<OOWeakReferenceSupport>)owner;
@end

View File

@ -0,0 +1,103 @@
/*
OOLegacyEventHandlerScript.m
Oolite
Copyright (C) 2004-2007 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
#import "OOLegacyEventHandlerScript.h"
#import "PlayerEntityLegacyScriptEngine.h"
@implementation OOLegacyEventHandlerScript
- (id)initWithEventHandlers:(NSDictionary *)eventHandlers forOwner:(id<OOWeakReferenceSupport>)owner
{
self = [super init];
if (self != nil)
{
if (eventHandlers != nil && owner != nil)
{
_eventHandlers = [eventHandlers copy];
_owner = [owner weakRetain];
}
else
{
[self release];
self = nil;
}
}
return self;
}
- (void)dealloc
{
[_eventHandlers release];
[_owner release];
[super dealloc];
}
- (NSString *)name
{
return @"<synthesized event handler script>";
}
- (NSString *)scriptDescription
{
return @"Script created by aggregation of legacy event handlers.";
}
- (NSString *)version
{
return nil;
}
- (void)runWithTarget:(Entity *)target
{
// Do nothing
}
- (BOOL)doEvent:(NSString *)eventName
{
id actions = nil;
actions = [_eventHandlers objectForKey:eventName];
if (actions != nil)
{
[[PlayerEntity sharedPlayer] scriptActions:actions forTarget:_owner];
return YES;
}
return NO;
}
- (BOOL)doEvent:(NSString *)eventName withArguments:(NSArray *)arguments
{
return [self doEvent:eventName];
}
@end

View File

@ -7,8 +7,8 @@ Property list-based script.
I started off reimplementing plist scripting here, in order to remove one of
PlayerEntity's many overloaded functions. The scale of the task was such that
I've stepped back, and this simply wraps the old plist scripting in
PlayerEntity. I intend to split it off as initially intended, hopefully as
early as 1.69.
PlayerEntity.
Oolite
Copyright (C) 2004-2007 Giles C Williams and contributors

View File

@ -90,7 +90,7 @@ static NSString * const kKeyMetadata = @"!metadata!";
OOLog(@"script.trace.plist.run", @"Running script %@", [self displayName]);
OOLogIndentIf(@"script.trace.plist.run");
[[PlayerEntity sharedPlayer] runScript:_script withName:[self name] forTarget:(ShipEntity *)target];
[[PlayerEntity sharedPlayer] runScript:_script withName:[self name] forTarget:(ShipEntity *)target];
OOLogOutdentIf(@"script.trace.plist.run");
}
@ -144,7 +144,7 @@ static NSString * const kKeyMetadata = @"!metadata!";
self = [super init];
if (self != nil)
{
_script = [script retain];
script = [script retain];
if (name != nil)
{
if (metadata == nil) metadata = [NSDictionary dictionaryWithObject:name forKey:kMDKeyName];

View File

@ -0,0 +1,34 @@
/*
OOPlayerProxyScript.h
Script which passes messages on to all world scripts, acting as the player's
ship script. This ensures all ship script messages for the player are passed
to the world scripts without needing special treatment.
Oolite
Copyright (C) 2004-2007 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
#import "OOScript.h"
@interface OOPlayerProxyScript: OOScript
@end

View File

@ -0,0 +1,74 @@
/*
OOPlayerProxyScript.m
Oolite
Copyright (C) 2004-2007 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
#import "OOPlayerProxyScript.h"
#import "PlayerEntity.h"
@implementation OOPlayerProxyScript
- (void)resetState
{
OOLog(@"temp", @"FIXME!");
}
- (NSString *)name
{
return @"<player proxy script>";
}
- (NSString *)scriptDescription
{
return @"Pseudo-script which passes all messages to all world scripts.";
}
- (NSString *)version
{
return nil;
}
- (void)runWithTarget:(Entity *)target
{
OOLog(@"temp", @"FIXME!");
}
- (BOOL)doEvent:(NSString *)eventName
{
OOLog(@"temp", @"FIXME!");
return NO;
}
- (BOOL)doEvent:(NSString *)eventName withArguments:(NSArray *)arguments
{
OOLog(@"temp", @"FIXME!");
return NO;
}
@end

View File

@ -51,6 +51,12 @@ MA 02110-1301, USA.
+ (NSArray *)scriptsFromFileAtPath:(NSString *)filePath;
// Load a single JavaScript script. Or, y'know, a future-scripting-language script.
+ (id)nonLegacyScriptFromFileNamed:(NSString *)fileName properties:(NSDictionary *)properties;
// Convert one or more plist script actions to a script with event handlers.
+ (id)scriptWithLegacyEventHandlers:(NSDictionary *)handlers forOwner:(Entity *)owner;
- (void)resetState; // Clear local variables, for instance.
- (NSString *)name;
@ -61,6 +67,13 @@ MA 02110-1301, USA.
- (void)runWithTarget:(Entity *)target;
- (BOOL)doEvent:(NSString *)eventName;
- (BOOL)doEvent:(NSString *)eventName withArguments:(NSArray *)argument;
- (BOOL)doEvent:(NSString *)eventName withArguments:(NSArray *)arguments;
- (BOOL)doEvent:(NSString *)eventName withArgument:(id)argument;
- (id)propertyNamed:(NSString *)name;
// Set a property which can be modified or deleted by the script.
- (BOOL)setProperty:(id)value named:(NSString *)name;
// Set a special property which cannot be modified or deleted by the script.
- (BOOL)defineProperty:(id)value named:(NSString *)name;
@end

View File

@ -25,6 +25,7 @@ MA 02110-1301, USA.
#import "OOScript.h"
#import "OOJSScript.h"
#import "OOPListScript.h"
#import "OOLegacyEventHandlerScript.h"
#import "OOLogging.h"
#import "Universe.h"
#import "OOJavaScriptEngine.h"
@ -80,7 +81,7 @@ static NSString * const kOOLogLoadScriptNone = @"script.load.none";
OOLog(kOOLogLoadScriptJavaScript, @"Trying to load JavaScript script %@", filePath);
OOLogIndentIf(kOOLogLoadScriptJavaScript);
script = [OOJSScript scriptWithPath:filePath];
script = [OOJSScript scriptWithPath:filePath properties:nil];
if (script != nil)
{
result = [NSArray arrayWithObject:script];
@ -169,7 +170,7 @@ static NSString * const kOOLogLoadScriptNone = @"script.load.none";
if ([extension isEqualToString:@"js"] || [extension isEqualToString:@"es"])
{
NSArray *result = nil;
OOScript *script = [OOJSScript scriptWithPath:filePath];
OOScript *script = [OOJSScript scriptWithPath:filePath properties:nil];
if (script != nil) result = [NSArray arrayWithObject:script];
return result;
}
@ -183,6 +184,41 @@ static NSString * const kOOLogLoadScriptNone = @"script.load.none";
}
+ (id)nonLegacyScriptFromFileNamed:(NSString *)fileName properties:(NSDictionary *)properties
{
NSString *extension = nil;
NSString *path = nil;
if (fileName == nil) return nil;
extension = [[fileName pathExtension] lowercaseString];
if ([extension isEqualToString:@"js"] || [extension isEqualToString:@"es"])
{
path = [ResourceManager pathForFileNamed:fileName inFolder:@"Scripts"];
if (path == nil)
{
OOLog(@"script.load.notFound", @"***** Could not find a script file named %@.", fileName);
return nil;
}
return [OOJSScript scriptWithPath:path properties:properties];
}
else if ([extension isEqualToString:@"plist"])
{
OOLog(@"script.load.badName", @"***** Can't load script named %@ - legacy scripts are not supported in this context.", fileName);
return nil;
}
OOLog(@"script.load.badName", @"***** Don't know how to load a script from %@.", fileName);
return nil;
}
+ (id)scriptWithLegacyEventHandlers:(NSDictionary *)handlers forOwner:(Entity *)owner
{
return [[[OOLegacyEventHandlerScript alloc] initWithEventHandlers:handlers forOwner:owner] autorelease];
}
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@ %p>{\"%@\" version %@}", [self class], self, [self name], [self version]];
@ -244,4 +280,28 @@ static NSString * const kOOLogLoadScriptNone = @"script.load.none";
return NO;
}
- (BOOL)doEvent:(NSString *)eventName withArgument:(id)argument
{
return [self doEvent:eventName withArguments:[NSArray arrayWithObject:argument]];
}
- (id)propertyNamed:(NSString *)name
{
return nil;
}
- (BOOL)setProperty:(id)value named:(NSString *)name
{
return NO;
}
- (BOOL)defineProperty:(id)value named:(NSString *)name
{
return NO;
}
@end

View File

@ -5665,6 +5665,8 @@ static BOOL MaintainLinkedLists(Universe* uni)
{
NSMutableDictionary *overrideDict = nil;
if (key == nil || planetKey == nil) return;
overrideDict = [localPlanetInfoOverrides objectForKey:planetKey];
if (overrideDict != nil)
{
@ -5690,7 +5692,8 @@ static BOOL MaintainLinkedLists(Universe* uni)
if (overrideDict == nil) overrideDict = [NSMutableDictionary dictionary];
[overrideDict setObject:object forKey:key];
if (object != nil) [overrideDict setObject:object forKey:key];
else [overrideDict removeObjectForKey:key];
[localPlanetInfoOverrides setObject:overrideDict forKey:planetKey];
}