Added big fat deprecation warning for scriptActionOnTarget:. Added skanky code to avoid running world scripts more than once with certain player states (such as STATUS_EXITING_WITCHSPACE).
git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@1445 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
parent
1a75b7f6bf
commit
959dc99d88
@ -2817,7 +2817,6 @@
|
||||
0865424C06B8447D000CA0AB /* Resources */,
|
||||
0865430306B8447D000CA0AB /* Sources */,
|
||||
0865431B06B8447D000CA0AB /* Frameworks */,
|
||||
1A5DB2D10BBEA46F00D57389 /* Sync logcontrol.plist.xml */,
|
||||
1A5BF29C0916D49800BF238F /* Copy MDImporter */,
|
||||
1A23153A0B9C773B00EF0852 /* Copy Images */,
|
||||
1A2316C80B9CFAB800EF0852 /* Copy Config */,
|
||||
@ -2954,22 +2953,6 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "TARGET_DIR=\"$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.app/Contents/Resources/Schemata\"\n\nif [ $COPY_SCHEMATA ]\nthen\n\techo \"Copying schemata\"\n\t\n\tSRC_DIR=\"$SRCROOT/Schemata/\";\n\t\n\tif [ ! -e \"$TARGET_DIR\" ]\n\tthen\n\t\tmkdir \"$TARGET_DIR\"\n\tfi\n\tfor item in `ls \"$SRC_DIR\"`\n\tdo\n\t\tcp \"$SRC_DIR/$item\" \"$TARGET_DIR/\"\n\tdone\n\trm \"$TARGET_DIR/README.txt\"\nelse\n\tif [ -e \"$TARGET_DIR\" ]\n\tthen\n\t\trmdir \"$TARGET_DIR\"\n\tfi\nfi\n";
|
||||
};
|
||||
1A5DB2D10BBEA46F00D57389 /* Sync logcontrol.plist.xml */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$(SRCROOT)/Resources/Config/logcontrol.plist",
|
||||
);
|
||||
name = "Sync logcontrol.plist.xml";
|
||||
outputPaths = (
|
||||
"$(SRCROOT)/Resources/Config/logcontrol.plist.xml",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "plutil -convert xml1 -o $SRCROOT/Resources/Config/logcontrol.plist.xml $SRCROOT/Resources/Config/logcontrol.plist\necho Updated logcontrol.plist.xml.\n";
|
||||
};
|
||||
1AD0C7300C47BDEF0070BD23 /* Copy SCR Shim (test release only) */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
{
|
||||
// To be removed after 1.71
|
||||
"shipSpawned" = "didSpawn";
|
||||
"shipDied" = ("didBecomeDead", "didDie");
|
||||
"shipWasScooped" = "wasScooped";
|
||||
@ -30,4 +31,7 @@
|
||||
"shipWillExitWitchspace" = "willExitWitchSpace";
|
||||
"shipExitedWitchspace" = "didExitWitchSpace";
|
||||
"shipWillEnterWitchspace" = "willEnterWitchSpace";
|
||||
|
||||
// To be removed after 1.72
|
||||
"shipBeingAttacked" = "beingAttacked";
|
||||
}
|
||||
|
@ -64,7 +64,7 @@
|
||||
|
||||
|
||||
/*** Module-specific message classes ***/
|
||||
ai = $entityState;
|
||||
ai = yes; // AI messages are sent if a ship's reportAIMessages property is set, for instance through the JavaScript console.
|
||||
ai.message.receive = inherit;
|
||||
ai.takeAction.takeAction = inherit;
|
||||
ai.takeAction.noAction = inherit;
|
||||
@ -268,6 +268,8 @@
|
||||
script.trace.plist.run = inherit;
|
||||
script.trace.javaScript.call = inherit; // Prints selector and parameter string on Player.call()
|
||||
|
||||
script.deprecated.scriptActionOnTarget = $scriptError; // Warning not to use scriptActionOnTarget:
|
||||
|
||||
|
||||
searchPaths.dumpAll = $troubleShootingDump;
|
||||
|
||||
|
@ -51,6 +51,9 @@ MA 02110-1301, USA.
|
||||
|
||||
}
|
||||
|
||||
+ (AI *) currentlyRunningAI;
|
||||
+ (NSString *) currentlyRunningAIDescription;
|
||||
|
||||
- (NSString *) name;
|
||||
- (NSString *) state;
|
||||
|
||||
|
@ -41,6 +41,9 @@ typedef struct
|
||||
} OOAIDeferredCallTrampolineInfo;
|
||||
|
||||
|
||||
static AI *sCurrentlyRunningAI = nil;
|
||||
|
||||
|
||||
@interface AI (OOPrivate)
|
||||
|
||||
// Wrapper for performSelector:withObject:afterDelay: to catch/fix bugs.
|
||||
@ -54,6 +57,25 @@ typedef struct
|
||||
|
||||
@implementation AI
|
||||
|
||||
+ (AI *) currentlyRunningAI
|
||||
{
|
||||
return sCurrentlyRunningAI;
|
||||
}
|
||||
|
||||
|
||||
+ (NSString *) currentlyRunningAIDescription
|
||||
{
|
||||
if (sCurrentlyRunningAI != nil)
|
||||
{
|
||||
return [NSString stringWithFormat:@"%@ in state %@", [sCurrentlyRunningAI name], [sCurrentlyRunningAI state]];
|
||||
}
|
||||
else
|
||||
{
|
||||
return @"<no AI running>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (id) init
|
||||
{
|
||||
self = [super init];
|
||||
@ -91,6 +113,8 @@ typedef struct
|
||||
[currentState release];
|
||||
[pendingMessages release];
|
||||
|
||||
if (sCurrentlyRunningAI == self) sCurrentlyRunningAI = nil;
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@ -149,7 +173,9 @@ typedef struct
|
||||
format:@"AI stack overflow for %@", _owner];
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
if ([[self owner] reportAIMessages]) OOLog(@"ai.stack.push", @"Pushing state machine for %@", self);
|
||||
#endif
|
||||
[aiStack insertObject:pickledMachine atIndex:0]; // PUSH
|
||||
}
|
||||
|
||||
@ -160,7 +186,9 @@ typedef struct
|
||||
|
||||
NSMutableDictionary *pickledMachine = [aiStack objectAtIndex:0];
|
||||
|
||||
#ifndef NDEBUG
|
||||
if ([[self owner] reportAIMessages]) OOLog(@"ai.stack.pop", @"Popping previous state machine for %@", self);
|
||||
#endif
|
||||
|
||||
[stateMachine release];
|
||||
stateMachine = [[pickledMachine objectForKey:@"stateMachine"] retain];
|
||||
@ -282,6 +310,8 @@ typedef struct
|
||||
NSDictionary *messagesForState = nil;
|
||||
ShipEntity *owner = [self owner];
|
||||
static unsigned recursionLimiter = 0;
|
||||
AI *previousRunning = sCurrentlyRunningAI;
|
||||
|
||||
|
||||
/* CRASH in _freedHandler when called via -setState: __NSFireDelayedPerform (1.69, OS X/x86).
|
||||
Analysis: owner invalid.
|
||||
@ -306,15 +336,18 @@ typedef struct
|
||||
messagesForState = [stateMachine objectForKey:currentState];
|
||||
if (messagesForState == nil) return;
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (currentState != nil && ![message isEqual:@"UPDATE"] && [owner reportAIMessages])
|
||||
{
|
||||
OOLog(@"ai.message.receive", @"AI for %@ in state '%@' receives message '%@'", ownerDesc, currentState, message);
|
||||
}
|
||||
#endif
|
||||
|
||||
actions = [[[messagesForState objectForKey:message] copy] autorelease];
|
||||
|
||||
|
||||
if (rulingInstinct != nil) [rulingInstinct freezeShipVars]; // preserve the pre-thinking state
|
||||
|
||||
|
||||
sCurrentlyRunningAI = self;
|
||||
if ([actions count] > 0)
|
||||
{
|
||||
NS_DURING
|
||||
@ -338,6 +371,7 @@ typedef struct
|
||||
}
|
||||
}
|
||||
}
|
||||
sCurrentlyRunningAI = previousRunning;
|
||||
|
||||
if (rulingInstinct != nil)
|
||||
{
|
||||
@ -354,14 +388,15 @@ typedef struct
|
||||
NSString *selectorStr;
|
||||
SEL selector;
|
||||
ShipEntity *owner = [self owner];
|
||||
BOOL report = [owner reportAIMessages];
|
||||
|
||||
report = [owner reportAIMessages];
|
||||
#ifndef NDEBUG
|
||||
BOOL report = [owner reportAIMessages];
|
||||
if (report)
|
||||
{
|
||||
OOLog(@"ai.takeAction.takeAction", @"%@ to take action %@", ownerDesc, action);
|
||||
OOLogIndent();
|
||||
}
|
||||
#endif
|
||||
|
||||
if ([tokens count] != 0)
|
||||
{
|
||||
@ -400,13 +435,17 @@ typedef struct
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (report) OOLog(@"ai.takeAction.noAction", @" - no action '%@'", action);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (report)
|
||||
{
|
||||
OOLogOutdent();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -1056,15 +1056,21 @@ static GLfloat texture_uv_array[10400 * 2];
|
||||
if ([ship isShuttle])
|
||||
{
|
||||
[ship landOnPlanet];
|
||||
#ifndef NDEBUG
|
||||
if ([ship reportAIMessages])
|
||||
{
|
||||
OOLog(@"planet.collide.shuttleLanded", @"DEBUG %@ landed on planet %@", other, self);
|
||||
}
|
||||
#endif
|
||||
return NO;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
if ([ship reportAIMessages])
|
||||
{
|
||||
Vector p1 = ship->position;
|
||||
OOLog(@"planet.collide.shipHit", @"DEBUG %@ %d collided with planet at (%.1f,%.1f,%.1f)",[ship name], [ship universalID], p1.x,p1.y,p1.z);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return YES;
|
||||
|
@ -194,20 +194,73 @@ OOINLINE void PerformScriptActions(NSArray *actions, Entity *target)
|
||||
}
|
||||
|
||||
|
||||
OOINLINE OOEntityStatus RecursiveRemapStatus(OOEntityStatus status)
|
||||
{
|
||||
// Some player stutuses should only be seen once per "event". This remaps them to something innocuous in case of recursion.
|
||||
if (status == STATUS_DOCKING ||
|
||||
status == STATUS_LAUNCHING ||
|
||||
status == STATUS_ENTERING_WITCHSPACE ||
|
||||
status == STATUS_EXITING_WITCHSPACE)
|
||||
{
|
||||
return STATUS_IN_FLIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static BOOL sRunningScript = NO;
|
||||
|
||||
|
||||
- (void) checkScript
|
||||
{
|
||||
NSEnumerator *scriptEnum = nil;
|
||||
OOScript *theScript = nil;
|
||||
BOOL wasRunningScript = sRunningScript;
|
||||
OOEntityStatus restoreStatus;
|
||||
|
||||
[self setScriptTarget:self];
|
||||
|
||||
OOLog(@"script.trace.runWorld", @"----- Running world script with state %@", [self status_string]);
|
||||
OOLogIndentIf(@"script.trace.runWorld");
|
||||
|
||||
for (scriptEnum = [worldScripts objectEnumerator]; (theScript = [scriptEnum nextObject]); )
|
||||
/* World scripts can potentially be invoked recursively, through
|
||||
scriptActionOnTarget: and possibly other mechanisms. This is bad, but
|
||||
that's the way it is. Legacy world scripts rely on only seeing certain
|
||||
player statuses once per "event". To ensure this, we must lie about
|
||||
the player's status when invoked recursively.
|
||||
|
||||
Of course, there are also methods in the game that rely on status not
|
||||
lying. However, I don't believe any that rely on these particular
|
||||
statuses can be legitimately invoked by scripts. The alternative would
|
||||
be to track the "status-as-seen-by-scripts" separately from the "real"
|
||||
status, which'd risk synchronization problems.
|
||||
|
||||
In summary, scriptActionOnTarget: is bad, and calling it from scripts
|
||||
rather than AIs is very bad.
|
||||
-- Ahruman, 20080302
|
||||
*/
|
||||
restoreStatus = status;
|
||||
if (sRunningScript)
|
||||
{
|
||||
[theScript runWithTarget:self];
|
||||
status = RecursiveRemapStatus(status);
|
||||
if (status != restoreStatus)
|
||||
{
|
||||
OOLog(@"script.trace.runWorld.recurse.lying", @"----- Running world script recursively and temporarily changing player status from %@ to %@.", EntityStatusToString(restoreStatus), EntityStatusToString(status));
|
||||
}
|
||||
else
|
||||
{
|
||||
OOLog(@"script.trace.runWorld.recurse", @"----- Running world script recursively.", EntityStatusToString(restoreStatus), EntityStatusToString(status));
|
||||
}
|
||||
}
|
||||
sRunningScript = YES;
|
||||
|
||||
// After all that, actually running the scripts is trivial.
|
||||
[[worldScripts allValues] makeObjectsPerformSelector:@selector(runWithTarget:) withObject:self];
|
||||
|
||||
// Restore anti-recursion measures.
|
||||
sRunningScript = wasRunningScript;
|
||||
status = restoreStatus;
|
||||
|
||||
OOLogOutdentIf(@"script.trace.runWorld");
|
||||
}
|
||||
|
@ -1572,8 +1572,7 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
if ([other isKindOfClass:[ShipEntity class]]) source = other;
|
||||
else source = from;
|
||||
|
||||
[self doScriptEvent:@"beingAttacked" withArgument:source];
|
||||
[shipAI reactToMessage:@"ATTACKED"];
|
||||
[self doScriptEvent:@"shipBeingAttacked" withArgument:source andReactToAIMessage:@"ATTACKED"];
|
||||
}
|
||||
|
||||
|
||||
@ -6458,11 +6457,13 @@ BOOL class_masslocks(int some_class)
|
||||
being_mined = NO;
|
||||
ShipEntity *hunter = nil;
|
||||
|
||||
if ((other)&&(other->isShip))
|
||||
if ([other isShip])
|
||||
{
|
||||
hunter = (ShipEntity *)other;
|
||||
if ([hunter isCloaked])
|
||||
{
|
||||
[self doScriptEvent:@"shipBeingAttackedByCloaked" andReactToAIMessage:@"ATTACKED_BY_CLOAKED"];
|
||||
|
||||
// lose it!
|
||||
other = nil;
|
||||
hunter = nil;
|
||||
|
@ -1053,9 +1053,13 @@ WormholeEntity* whole;
|
||||
ShipEntity *mother = [UNIVERSE entityForUniversalID:primaryTarget];
|
||||
if (mother)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (reportAIMessages)
|
||||
{
|
||||
OOLog(@"ai.suggestEscort", @"DEBUG %@ suggests escorting %@", self, mother);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
if ([mother acceptAsEscort:self])
|
||||
{
|
||||
// copy legal status across
|
||||
@ -1071,8 +1075,12 @@ WormholeEntity* whole;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (reportAIMessages)
|
||||
{
|
||||
OOLog(@"ai.suggestEscort.refused", @"DEBUG %@ refused by %@", self, mother);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
[self setOwner:NULL];
|
||||
@ -1758,6 +1766,17 @@ WormholeEntity* whole;
|
||||
PlayerEntity *player = [PlayerEntity sharedPlayer];
|
||||
Entity *targEnt = [UNIVERSE entityForUniversalID:primaryTarget];
|
||||
ShipEntity *oldTarget = nil;
|
||||
static BOOL deprecationWarning = NO;
|
||||
|
||||
if (!deprecationWarning)
|
||||
{
|
||||
deprecationWarning = YES;
|
||||
OOLog(@"script.deprecated.scriptActionOnTarget", @"***** WARNING in AI %@: the AI method scriptActionOnTarget: is deprecated and should not be used. It is slow and has unpredictable side effects. The recommended alternative is to use sendScriptMessage: to call a function in a ship's JavaScript ship script instead. scriptActionOnTarget: should not be used at all from scripts.", [AI currentlyRunningAIDescription]);
|
||||
}
|
||||
else
|
||||
{
|
||||
OOLog(@"script.deprecated.scriptActionOnTarget.repeat", @"***** WARNING in AI %@: the AI method scriptActionOnTarget: is deprecated and should not be used.", [AI currentlyRunningAIDescription]);
|
||||
}
|
||||
|
||||
if ([targEnt isShip])
|
||||
{
|
||||
|
@ -275,7 +275,12 @@ static JSFunctionSpec sScriptMethods[] =
|
||||
|
||||
- (void)runWithTarget:(Entity *)target
|
||||
{
|
||||
OOLog(@"script.trace.js.run", @"Runing script \"%@\"", [self name]);
|
||||
OOLogIndentIf(@"script.trace.js.run");
|
||||
|
||||
[self doEvent:@"tickle" withArguments:[NSArray arrayWithObject:[[PlayerEntity sharedPlayer] status_string]]];
|
||||
|
||||
OOLogOutdentIf(@"script.trace.js.run");
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user