Changeset - r18363:f8c9df886df8
[Not reviewed]
master
0 9 0
truebrain - 13 years ago 2011-11-13 20:43:48
truebrain@openttd.org
(svn r23209) -Codechange: track the current active script instance directly, instead of assuming the current company points you to the right one.
9 files changed with 138 insertions and 52 deletions:
0 comments (0 inline, 0 general)
src/ai/ai_core.cpp
Show inline comments
 
@@ -52,7 +52,8 @@
 

	
 
	c->ai_info = info;
 
	assert(c->ai_instance == NULL);
 
	c->ai_instance = new AIInstance(info);
 
	c->ai_instance = new AIInstance();
 
	c->ai_instance->Initialize(info);
 

	
 
	cur_company.Restore();
 

	
 
@@ -214,7 +215,7 @@
 

	
 
	/* Queue the event */
 
	Backup<CompanyByte> cur_company(_current_company, company, FILE_LINE);
 
	AIEventController::InsertEvent(event);
 
	Company::Get(_current_company)->ai_instance->InsertEvent(event);
 
	cur_company.Restore();
 

	
 
	event->Release();
 
@@ -248,15 +249,7 @@
 
 */
 
void CcAI(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
 
{
 
	AIObject::SetLastCommandRes(result.Succeeded());
 

	
 
	if (result.Failed()) {
 
		AIObject::SetLastError(AIError::StringToError(result.GetErrorMessage()));
 
	} else {
 
		AIObject::IncreaseDoCommandCosts(result.GetCost());
 
		AIObject::SetLastCost(result.GetCost());
 
	}
 

	
 
	Company::Get(_current_company)->ai_instance->DoCommandCallback(result, tile, p1, p2);
 
	Company::Get(_current_company)->ai_instance->Continue();
 
}
 

	
 
@@ -327,7 +320,7 @@ void CcAI(const CommandCost &result, Til
 

	
 
/* static */ bool AI::ImportLibrary(const char *library, const char *class_name, int version, HSQUIRRELVM vm)
 
{
 
	return AI::ai_scanner->ImportLibrary(library, class_name, version, vm, Company::Get(_current_company)->ai_instance->GetController());
 
	return AI::ai_scanner->ImportLibrary(library, class_name, version, vm, AIObject::GetActiveInstance()->GetController());
 
}
 

	
 
/* static */ void AI::Rescan()
src/ai/ai_gui.cpp
Show inline comments
 
@@ -931,9 +931,7 @@ struct AIDebugWindow : public QueryStrin
 
		/* If there are no active companies, don't display anything else. */
 
		if (ai_debug_company == INVALID_COMPANY) return;
 

	
 
		Backup<CompanyByte> cur_company(_current_company, ai_debug_company, FILE_LINE);
 
		AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
 
		cur_company.Restore();
 
		AILog::LogData *log = (AILog::LogData *)Company::Get(ai_debug_company)->ai_instance->GetLogPointer();
 

	
 
		int scroll_count = (log == NULL) ? 0 : log->used;
 
		if (this->vscroll->GetCount() != scroll_count) {
 
@@ -986,9 +984,7 @@ struct AIDebugWindow : public QueryStrin
 

	
 
		switch (widget) {
 
			case AID_WIDGET_LOG_PANEL: {
 
				Backup<CompanyByte> cur_company(_current_company, ai_debug_company, FILE_LINE);
 
				AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
 
				cur_company.Restore();
 
				AILog::LogData *log = (AILog::LogData *)Company::Get(ai_debug_company)->ai_instance->GetLogPointer();
 
				if (log == NULL) return;
 

	
 
				int y = this->top_offset;
 
@@ -1029,9 +1025,7 @@ struct AIDebugWindow : public QueryStrin
 
		this->RaiseWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
 
		ai_debug_company = show_ai;
 

	
 
		Backup<CompanyByte> cur_company(_current_company, ai_debug_company, FILE_LINE);
 
		AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
 
		cur_company.Restore();
 
		AILog::LogData *log = (AILog::LogData *)Company::Get(ai_debug_company)->ai_instance->GetLogPointer();
 
		this->vscroll->SetCount((log == NULL) ? 0 : log->used);
 

	
 
		this->LowerWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
 
@@ -1130,8 +1124,7 @@ struct AIDebugWindow : public QueryStrin
 
		 * This needs to be done in gameloop-scope, so the AI is suspended immediately. */
 
		if (!gui_scope && data == ai_debug_company && this->break_check_enabled && !StrEmpty(this->edit_str_buf)) {
 
			/* Get the log instance of the active company */
 
			Backup<CompanyByte> cur_company(_current_company, ai_debug_company, FILE_LINE);
 
			AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
 
			AILog::LogData *log = (AILog::LogData *)Company::Get(ai_debug_company)->ai_instance->GetLogPointer();
 

	
 
			if (log != NULL && case_sensitive_break_check?
 
					strstr(log->lines[log->pos], this->edit_str_buf) != 0 :
 
@@ -1149,8 +1142,6 @@ struct AIDebugWindow : public QueryStrin
 
				/* Highlight row that matched */
 
				this->highlight_row = log->pos;
 
			}
 

	
 
			cur_company.Restore();
 
		}
 
	}
 

	
src/ai/ai_instance.cpp
Show inline comments
 
@@ -100,7 +100,7 @@ static void PrintFunc(bool error_msg, co
 
	AIController::Print(error_msg, SQ2OTTD(message));
 
}
 

	
 
AIInstance::AIInstance(AIInfo *info) :
 
AIInstance::AIInstance() :
 
	controller(NULL),
 
	storage(NULL),
 
	engine(NULL),
 
@@ -111,13 +111,16 @@ AIInstance::AIInstance(AIInfo *info) :
 
	suspend(0),
 
	callback(NULL)
 
{
 
	/* Set the instance already, so we can use AIObject::Set commands */
 
	Company::Get(_current_company)->ai_instance = this;
 
	this->storage = new AIStorage();
 
	this->engine  = new Squirrel();
 
	this->engine->SetPrintFunction(&PrintFunc);
 
}
 

	
 
void AIInstance::Initialize(AIInfo *info)
 
{
 
	AIObject::ActiveInstance active(this);
 

	
 
	this->controller = new AIController();
 
	this->storage    = new AIStorage();
 
	this->engine     = new Squirrel();
 
	this->engine->SetPrintFunction(&PrintFunc);
 

	
 
	/* The import method is available at a very early stage */
 
	this->engine->AddMethod("import", &AILibrary::Import, 4, ".ssi");
 
@@ -163,6 +166,8 @@ AIInstance::AIInstance(AIInfo *info) :
 

	
 
AIInstance::~AIInstance()
 
{
 
	AIObject::ActiveInstance active(this);
 

	
 
	if (instance != NULL) this->engine->ReleaseObject(this->instance);
 
	if (engine != NULL) delete this->engine;
 
	delete this->storage;
 
@@ -316,6 +321,8 @@ void AIInstance::Died()
 

	
 
void AIInstance::GameLoop()
 
{
 
	AIObject::ActiveInstance active(this);
 

	
 
	if (this->IsDead()) return;
 
	if (this->engine->HasScriptCrashed()) {
 
		/* The script crashed during saving, kill it here. */
 
@@ -423,10 +430,16 @@ void AIInstance::CollectGarbage() const
 
	instance->engine->InsertResult(AIObject::GetNewGroupID());
 
}
 

	
 
/* static */ AIStorage *AIInstance::GetStorage()
 
AIStorage *AIInstance::GetStorage()
 
{
 
	assert(Company::IsValidAiID(_current_company));
 
	return Company::Get(_current_company)->ai_instance->storage;
 
	return this->storage;
 
}
 

	
 
void *AIInstance::GetLogPointer()
 
{
 
	AIObject::ActiveInstance active(this);
 

	
 
	return AIObject::GetLogPointer();
 
}
 

	
 
/*
 
@@ -598,6 +611,8 @@ static const uint AISAVE_MAX_DEPTH = 25;
 

	
 
void AIInstance::Save()
 
{
 
	AIObject::ActiveInstance active(this);
 

	
 
	/* Don't save data if the AI didn't start yet or if it crashed. */
 
	if (this->engine == NULL || this->engine->HasScriptCrashed()) {
 
		SaveEmpty();
 
@@ -662,7 +677,6 @@ void AIInstance::Save()
 
		_ai_sl_byte = 0;
 
		SlObject(NULL, _ai_byte);
 
	}
 

	
 
}
 

	
 
void AIInstance::Suspend()
 
@@ -739,6 +753,8 @@ void AIInstance::Suspend()
 

	
 
void AIInstance::Load(int version)
 
{
 
	AIObject::ActiveInstance active(this);
 

	
 
	if (this->engine == NULL || version == -1) {
 
		LoadEmpty();
 
		return;
 
@@ -795,3 +811,24 @@ SQInteger AIInstance::GetOpsTillSuspend(
 
{
 
	return this->engine->GetOpsTillSuspend();
 
}
 

	
 
void AIInstance::DoCommandCallback(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
 
{
 
	AIObject::ActiveInstance active(this);
 

	
 
	AIObject::SetLastCommandRes(result.Succeeded());
 

	
 
	if (result.Failed()) {
 
		AIObject::SetLastError(AIError::StringToError(result.GetErrorMessage()));
 
	} else {
 
		AIObject::IncreaseDoCommandCosts(result.GetCost());
 
		AIObject::SetLastCost(result.GetCost());
 
	}
 
}
 

	
 
void AIInstance::InsertEvent(class AIEvent *event)
 
{
 
	AIObject::ActiveInstance active(this);
 

	
 
	AIEventController::InsertEvent(event);
 
}
src/ai/ai_instance.hpp
Show inline comments
 
@@ -81,10 +81,15 @@ public:
 

	
 
	/**
 
	 * Create a new AI.
 
	 */
 
	AIInstance();
 
	~AIInstance();
 

	
 
	/**
 
	 * Initialize the AI and prepare it for its first run.
 
	 * @param info The AI to create the instance of.
 
	 */
 
	AIInstance(class AIInfo *info);
 
	~AIInstance();
 
	void Initialize(class AIInfo *info);
 

	
 
	/**
 
	 * An AI in multiplayer waits for the server to handle his DoCommand.
 
@@ -105,7 +110,12 @@ public:
 
	/**
 
	 * Get the storage of this AI.
 
	 */
 
	static class AIStorage *GetStorage();
 
	class AIStorage *GetStorage();
 

	
 
	/**
 
	 * Get the log pointer of this AI.
 
	 */
 
	void *GetLogPointer();
 

	
 
	/**
 
	 * Return a true/false reply for a DoCommand.
 
@@ -173,6 +183,22 @@ public:
 
	 * @return The number of operations to execute.
 
	 */
 
	SQInteger GetOpsTillSuspend();
 

	
 
	/**
 
	 * DoCommand callback function for all commands executed by AIs.
 
	 * @param result The result of the command.
 
	 * @param tile The tile on which the command was executed.
 
	 * @param p1 p1 as given to DoCommandPInternal.
 
	 * @param p2 p2 as given to DoCommandPInternal.
 
	 */
 
	void DoCommandCallback(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2);
 

	
 
	/**
 
	 * Insert an event for this AI.
 
	 * @param event The event to insert.
 
	 */
 
	void InsertEvent(class AIEvent *event);
 

	
 
private:
 
	class AIController *controller;  ///< The AI main class.
 
	class AIStorage *storage;        ///< Some global information for each running AI.
src/ai/api/ai_controller.cpp
Show inline comments
 
@@ -63,12 +63,12 @@ AIController::~AIController()
 

	
 
/* static */ uint AIController::GetTick()
 
{
 
	return ::Company::Get(_current_company)->ai_instance->GetController()->ticks;
 
	return AIObject::GetActiveInstance()->GetController()->ticks;
 
}
 

	
 
/* static */ int AIController::GetOpsTillSuspend()
 
{
 
	return ::Company::Get(_current_company)->ai_instance->GetOpsTillSuspend();
 
	return AIObject::GetActiveInstance()->GetOpsTillSuspend();
 
}
 

	
 
/* static */ int AIController::GetSetting(const char *name)
src/ai/api/ai_execmode.cpp
Show inline comments
 
@@ -32,9 +32,8 @@ AIExecMode::AIExecMode()
 
AIExecMode::~AIExecMode()
 
{
 
	if (this->GetDoCommandModeInstance() != this) {
 
		AIInstance *instance = Company::Get(_current_company)->ai_instance;
 
		/* Ignore this error if the AI already died. */
 
		if (!instance->IsDead()) {
 
		if (!AIObject::GetActiveInstance()->IsDead()) {
 
			throw AI_FatalError("AIExecMode object was removed while it was not the latest AI*Mode object created.");
 
		}
 
	}
src/ai/api/ai_object.cpp
Show inline comments
 
@@ -12,8 +12,6 @@
 
#include "../../stdafx.h"
 
#include "../../script/squirrel.hpp"
 
#include "../../command_func.h"
 
#include "../../company_base.h"
 
#include "../../company_func.h"
 
#include "../../network/network.h"
 
#include "../../tunnelbridge.h"
 

	
 
@@ -27,9 +25,30 @@
 
 */
 
static AIStorage *GetStorage()
 
{
 
	return AIInstance::GetStorage();
 
	return AIObject::GetActiveInstance()->GetStorage();
 
}
 

	
 

	
 
/* static */ AIInstance *AIObject::ActiveInstance::active = NULL;
 

	
 
AIObject::ActiveInstance::ActiveInstance(AIInstance *instance)
 
{
 
	this->last_active = AIObject::ActiveInstance::active;
 
	AIObject::ActiveInstance::active = instance;
 
}
 

	
 
AIObject::ActiveInstance::~ActiveInstance()
 
{
 
	AIObject::ActiveInstance::active = this->last_active;
 
}
 

	
 
/* static */ AIInstance *AIObject::GetActiveInstance()
 
{
 
	assert(AIObject::ActiveInstance::active != NULL);
 
	return AIObject::ActiveInstance::active;
 
}
 

	
 

	
 
/* static */ void AIObject::SetDoCommandDelay(uint ticks)
 
{
 
	assert(ticks > 0);
 
@@ -179,7 +198,7 @@ static AIStorage *GetStorage()
 

	
 
/* static */ bool AIObject::CanSuspend()
 
{
 
	Squirrel *squirrel = Company::Get(_current_company)->ai_instance->engine;
 
	Squirrel *squirrel = AIObject::GetActiveInstance()->engine;
 
	return GetStorage()->allow_do_command && squirrel->CanSuspend();
 
}
 

	
src/ai/api/ai_object.hpp
Show inline comments
 
@@ -35,10 +35,26 @@ typedef bool (AIModeProc)();
 
 *   command processing, and command-validation checks.
 
 */
 
class AIObject : public SimpleCountedObject {
 
friend void CcAI(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2);
 
friend class AIInstance;
 
friend class AIController;
 
#ifndef DOXYGEN_AI_DOCS
 
protected:
 
	/**
 
	 * A class that handles the current active instance. By instantiating it at
 
	 *  the beginning of a function with the current active instance, it remains
 
	 *  active till the scope of the variable closes. It then automatically
 
	 *  reverts to the active instance it was before instantiating.
 
	 */
 
	class ActiveInstance {
 
	friend class AIObject;
 
	public:
 
		ActiveInstance(AIInstance *instance);
 
		~ActiveInstance();
 
	private:
 
		AIInstance *last_active;    ///< The active instance before we go instantiated.
 

	
 
		static AIInstance *active;  ///< The global current active instance.
 
	};
 

	
 
public:
 
	/**
 
	 * Store the latest result of a DoCommand per company.
 
@@ -47,9 +63,10 @@ public:
 
	static void SetLastCommandRes(bool res);
 

	
 
	/**
 
	 * Get the pointer to store log message in.
 
	 * Get the currently active instance.
 
	 * @return The instance.
 
	 */
 
	static void *&GetLogPointer();
 
	static class AIInstance *GetActiveInstance();
 

	
 
protected:
 
	/**
 
@@ -197,6 +214,11 @@ protected:
 
	 */
 
	static void *&GetEventPointer();
 

	
 
	/**
 
	 * Get the pointer to store log message in.
 
	 */
 
	static void *&GetLogPointer();
 

	
 
private:
 
	/**
 
	 * Store a new_vehicle_id per company.
src/ai/api/ai_testmode.cpp
Show inline comments
 
@@ -32,9 +32,8 @@ AITestMode::AITestMode()
 
AITestMode::~AITestMode()
 
{
 
	if (this->GetDoCommandModeInstance() != this) {
 
		AIInstance *instance = Company::Get(_current_company)->ai_instance;
 
		/* Ignore this error if the AI already died. */
 
		if (!instance->IsDead()) {
 
		if (!AIObject::GetActiveInstance()->IsDead()) {
 
			throw AI_FatalError("AITestmode object was removed while it was not the latest AI*Mode object created.");
 
		}
 
	}
0 comments (0 inline, 0 general)