mirror of https://github.com/OpenTTD/OpenTTD
(svn r17223) -Change [NoAI] [FS#2980]: Crash an AI when it uses a DoCommand / Sleep instead of just printing an error message in the AI Debug Window
parent
0780dc8138
commit
a4afa140f3
|
@ -311,6 +311,7 @@ SQUIRREL_API void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc);
|
|||
SQUIRREL_API SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v);
|
||||
SQUIRREL_API SQRESULT sq_suspendvm(HSQUIRRELVM v);
|
||||
SQUIRREL_API bool sq_resumecatch(HSQUIRRELVM v, int suspend = -1);
|
||||
SQUIRREL_API bool sq_resumeerror(HSQUIRRELVM v);
|
||||
SQUIRREL_API SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool resumedret,SQBool retval,SQBool raiseerror,SQBool throwerror);
|
||||
SQUIRREL_API SQInteger sq_getvmstate(HSQUIRRELVM v);
|
||||
|
||||
|
|
|
@ -1012,6 +1012,14 @@ bool sq_resumecatch(HSQUIRRELVM v, int suspend)
|
|||
return v->Execute(_null_, v->_top, -1, -1, ret, SQTrue, SQVM::ET_RESUME_OPENTTD);
|
||||
}
|
||||
|
||||
bool sq_resumeerror(HSQUIRRELVM v)
|
||||
{
|
||||
SQObjectPtr ret;
|
||||
v->_can_suspend = true;
|
||||
v->_ops_till_suspend = 1;
|
||||
return v->Execute(_null_, v->_top, -1, -1, ret, SQTrue, SQVM::ET_RESUME_THROW_VM);
|
||||
}
|
||||
|
||||
void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook)
|
||||
{
|
||||
if(sq_gettop(v) >= 1){
|
||||
|
|
|
@ -352,6 +352,10 @@ void AIInstance::GameLoop()
|
|||
} catch (AI_VMSuspend e) {
|
||||
this->suspend = e.GetSuspendTime();
|
||||
this->callback = e.GetSuspendCallback();
|
||||
} catch (AI_FatalError e) {
|
||||
this->engine->ThrowError(e.GetErrorMessage());
|
||||
this->engine->ResumeError();
|
||||
this->Died();
|
||||
}
|
||||
|
||||
this->is_started = true;
|
||||
|
@ -368,6 +372,10 @@ void AIInstance::GameLoop()
|
|||
} catch (AI_VMSuspend e) {
|
||||
this->suspend = e.GetSuspendTime();
|
||||
this->callback = e.GetSuspendCallback();
|
||||
} catch (AI_FatalError e) {
|
||||
this->engine->ThrowError(e.GetErrorMessage());
|
||||
this->engine->ResumeError();
|
||||
this->Died();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,21 @@ private:
|
|||
AISuspendCallbackProc *callback;
|
||||
};
|
||||
|
||||
/**
|
||||
* A throw-class that is given when the AI made a fatal error.
|
||||
*/
|
||||
class AI_FatalError {
|
||||
public:
|
||||
AI_FatalError(const char *msg) :
|
||||
msg(msg)
|
||||
{}
|
||||
|
||||
const char *GetErrorMessage() { return msg; }
|
||||
|
||||
private:
|
||||
const char *msg;
|
||||
};
|
||||
|
||||
class AIInstance {
|
||||
public:
|
||||
friend class AIObject;
|
||||
|
|
|
@ -24,8 +24,7 @@
|
|||
/* static */ void AIController::Sleep(int ticks)
|
||||
{
|
||||
if (!AIObject::GetAllowDoCommand()) {
|
||||
AILog::Error("You are not allowed to call Sleep in your constructor, Save(), Load(), and any valuator.\n");
|
||||
return;
|
||||
throw AI_FatalError("You are not allowed to call Sleep in your constructor, Save(), Load(), and any valuator.");
|
||||
}
|
||||
|
||||
if (ticks <= 0) {
|
||||
|
|
|
@ -191,8 +191,7 @@ int AIObject::GetCallbackVariable(int index)
|
|||
bool AIObject::DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint cmd, const char *text, AISuspendCallbackProc *callback)
|
||||
{
|
||||
if (AIObject::GetAllowDoCommand() == false) {
|
||||
AILog::Error("You are not allowed to execute any DoCommand (even indirect) in your constructor, Save(), Load(), and any valuator.\n");
|
||||
return false;
|
||||
throw AI_FatalError("You are not allowed to execute any DoCommand (even indirect) in your constructor, Save(), Load(), and any valuator.");
|
||||
}
|
||||
|
||||
CommandCost res;
|
||||
|
|
|
@ -187,6 +187,12 @@ bool Squirrel::Resume(int suspend)
|
|||
return this->vm->_suspended != 0;
|
||||
}
|
||||
|
||||
void Squirrel::ResumeError()
|
||||
{
|
||||
assert(!this->crashed);
|
||||
sq_resumeerror(this->vm);
|
||||
}
|
||||
|
||||
void Squirrel::CollectGarbage()
|
||||
{
|
||||
sq_collectgarbage(this->vm);
|
||||
|
|
|
@ -106,6 +106,11 @@ public:
|
|||
*/
|
||||
bool Resume(int suspend = -1);
|
||||
|
||||
/**
|
||||
* Resume the VM with an error so it prints a stack trace.
|
||||
*/
|
||||
void ResumeError();
|
||||
|
||||
/**
|
||||
* Tell the VM to do a garbage collection run.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue