summaryrefslogtreecommitdiff
path: root/src/ai
diff options
context:
space:
mode:
authortruebrain <truebrain@openttd.org>2011-11-29 23:21:52 +0000
committertruebrain <truebrain@openttd.org>2011-11-29 23:21:52 +0000
commite37149a1def6a0e63dda8e0964abf1b82316761a (patch)
treed8f80cee8a3b1eb60feb883796e43300fb50cfb1 /src/ai
parentae8540f5e080adebca3e54c69aa7cd85a87e550b (diff)
downloadopenttd-e37149a1def6a0e63dda8e0964abf1b82316761a.tar.xz
(svn r23362) -Codechange: refactor AIScanner, splitting it in AIScannerInfo and AIScannerLibrary
Diffstat (limited to 'src/ai')
-rw-r--r--src/ai/ai.hpp15
-rw-r--r--src/ai/ai_core.cpp56
-rw-r--r--src/ai/ai_gui.cpp20
-rw-r--r--src/ai/ai_info.cpp69
-rw-r--r--src/ai/ai_info.hpp28
-rw-r--r--src/ai/ai_scanner.cpp342
-rw-r--r--src/ai/ai_scanner.hpp106
7 files changed, 197 insertions, 439 deletions
diff --git a/src/ai/ai.hpp b/src/ai/ai.hpp
index af1888914..d8647be0c 100644
--- a/src/ai/ai.hpp
+++ b/src/ai/ai.hpp
@@ -19,7 +19,7 @@
#include <map>
/** A list that maps AI names to their AIInfo object. */
-typedef std::map<const char *, class AIInfo *, StringCompare> AIInfoList;
+typedef std::map<const char *, class ScriptInfo *, StringCompare> ScriptInfoList;
/**
* Main AI class. Contains all functions needed to start, stop, save and load AIs.
@@ -129,11 +129,11 @@ public:
/** Wrapper function for AIScanner::GetAIConsoleLibraryList */
static char *GetConsoleLibraryList(char *p, const char *last);
/** Wrapper function for AIScanner::GetAIInfoList */
- static const AIInfoList *GetInfoList();
+ static const ScriptInfoList *GetInfoList();
/** Wrapper function for AIScanner::GetUniqueAIInfoList */
- static const AIInfoList *GetUniqueInfoList();
+ static const ScriptInfoList *GetUniqueInfoList();
/** Wrapper function for AIScanner::FindInfo */
- static AIInfo *FindInfo(const char *name, int version, bool force_exact_match);
+ static class AIInfo *FindInfo(const char *name, int version, bool force_exact_match);
/** Wrapper function for AIScanner::FindLibrary */
static class AILibrary *FindLibrary(const char *library, int version);
@@ -145,10 +145,12 @@ public:
#if defined(ENABLE_NETWORK)
/** Wrapper function for AIScanner::HasAI */
static bool HasAI(const struct ContentInfo *ci, bool md5sum);
+ static bool HasAILibrary(const ContentInfo *ci, bool md5sum);
#endif
private:
- static uint frame_counter; ///< Tick counter for the AI code
- static class AIScanner *ai_scanner; ///< AIScanner instance that is used to find AIs
+ static uint frame_counter; ///< Tick counter for the AI code
+ static class AIScannerInfo *scanner_info; ///< ScriptScanner instance that is used to find AIs
+ static class AIScannerLibrary *scanner_library; ///< ScriptScanner instance that is used to find AI Libraries
};
#else /* ENABLE_AI */
@@ -167,6 +169,7 @@ public:
static void KillAll() {}
static void GameLoop() {}
static bool HasAI(const struct ContentInfo *ci, bool md5sum) { return false; }
+ static bool HasAILibrary(const struct ContentInfo *ci, bool md5sum) { return false; }
static void Rescan() {}
static char *GetConsoleList(char *p, const char *last, bool newest_only = false) { return p; }
static void nop() { }
diff --git a/src/ai/ai_core.cpp b/src/ai/ai_core.cpp
index 462dac0e6..d6c0b7946 100644
--- a/src/ai/ai_core.cpp
+++ b/src/ai/ai_core.cpp
@@ -21,10 +21,12 @@
#include "ai_scanner.hpp"
#include "ai_instance.hpp"
#include "ai_config.hpp"
+#include "ai.hpp"
#include "../script/api/script_error.hpp"
/* static */ uint AI::frame_counter = 0;
-/* static */ AIScanner *AI::ai_scanner = NULL;
+/* static */ AIScannerInfo *AI::scanner_info = NULL;
+/* static */ AIScannerLibrary *AI::scanner_library = NULL;
/* static */ bool AI::CanStartNew()
{
@@ -42,7 +44,7 @@
AIConfig *config = AIConfig::GetConfig(company);
AIInfo *info = config->GetInfo();
if (info == NULL || (rerandomise_ai && config->IsRandomAI())) {
- info = AI::ai_scanner->SelectRandomAI();
+ info = AI::scanner_info->SelectRandomAI();
assert(info != NULL);
/* Load default data and store the name in the settings */
config->ChangeAI(info->GetName(), -1, false, true);
@@ -134,12 +136,15 @@
/* static */ void AI::Initialize()
{
- if (AI::ai_scanner != NULL) AI::Uninitialize(true);
+ if (AI::scanner_info != NULL) AI::Uninitialize(true);
AI::frame_counter = 0;
- if (AI::ai_scanner == NULL) {
+ if (AI::scanner_info == NULL) {
TarScanner::DoScan(TarScanner::AI);
- AI::ai_scanner = new AIScanner();
+ AI::scanner_info = new AIScannerInfo();
+ AI::scanner_info->Initialize("AIScanner");
+ AI::scanner_library = new AIScannerLibrary();
+ AI::scanner_library->Initialize("AISCanner");
}
}
@@ -152,8 +157,10 @@
* still load all the AIS, while keeping the configs in place */
Rescan();
} else {
- delete AI::ai_scanner;
- AI::ai_scanner = NULL;
+ delete AI::scanner_info;
+ delete AI::scanner_library;
+ AI::scanner_info = NULL;
+ AI::scanner_library = NULL;
for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
if (_settings_game.ai_config[c] != NULL) {
@@ -286,42 +293,59 @@
/* static */ char *AI::GetConsoleList(char *p, const char *last, bool newest_only)
{
- return AI::ai_scanner->GetAIConsoleList(p, last, newest_only);
+ return AI::scanner_info->GetConsoleList(p, last, newest_only);
}
/* static */ char *AI::GetConsoleLibraryList(char *p, const char *last)
{
- return AI::ai_scanner->GetAIConsoleLibraryList(p, last);
+ return AI::scanner_library->GetConsoleList(p, last, true);
}
-/* static */ const AIInfoList *AI::GetInfoList()
+/* static */ const ScriptInfoList *AI::GetInfoList()
{
- return AI::ai_scanner->GetAIInfoList();
+ return AI::scanner_info->GetInfoList();
}
-/* static */ const AIInfoList *AI::GetUniqueInfoList()
+/* static */ const ScriptInfoList *AI::GetUniqueInfoList()
{
- return AI::ai_scanner->GetUniqueAIInfoList();
+ return AI::scanner_info->GetUniqueInfoList();
}
/* static */ AIInfo *AI::FindInfo(const char *name, int version, bool force_exact_match)
{
- return AI::ai_scanner->FindInfo(name, version, force_exact_match);
+ return AI::scanner_info->FindInfo(name, version, force_exact_match);
}
/* static */ AILibrary *AI::FindLibrary(const char *library, int version)
{
- return AI::ai_scanner->FindLibrary(library, version);
+ return AI::scanner_library->FindLibrary(library, version);
}
/* static */ void AI::Rescan()
{
TarScanner::DoScan(TarScanner::AI);
- AI::ai_scanner->RescanAIDir();
+ AI::scanner_info->RescanDir();
+ AI::scanner_library->RescanDir();
ResetConfig();
InvalidateWindowData(WC_AI_LIST, 0, 1);
SetWindowClassesDirty(WC_AI_DEBUG);
SetWindowDirty(WC_AI_SETTINGS, 0);
}
+
+/**
+ * Check whether we have an AI (library) with the exact characteristics as ci.
+ * @param ci the characteristics to search on (shortname and md5sum)
+ * @param md5sum whether to check the MD5 checksum
+ * @return true iff we have an AI (library) matching.
+ */
+/* static */ bool AI::HasAI(const ContentInfo *ci, bool md5sum)
+{
+ return AI::scanner_info->HasScript(ci, md5sum);
+}
+
+/* static */ bool AI::HasAILibrary(const ContentInfo *ci, bool md5sum)
+{
+ return AI::scanner_library->HasScript(ci, md5sum);
+}
diff --git a/src/ai/ai_gui.cpp b/src/ai/ai_gui.cpp
index 7041f8bd3..2ef7d5db9 100644
--- a/src/ai/ai_gui.cpp
+++ b/src/ai/ai_gui.cpp
@@ -47,11 +47,11 @@ enum AIListWindowWidgets {
* Window that let you choose an available AI.
*/
struct AIListWindow : public Window {
- const AIInfoList *ai_info_list; ///< The list of AIs.
- int selected; ///< The currently selected AI.
- CompanyID slot; ///< The company we're selecting a new AI for.
- int line_height; ///< Height of a row in the matrix widget.
- Scrollbar *vscroll; ///< Cache of the vertical scrollbar.
+ const ScriptInfoList *ai_info_list; ///< The list of AIs.
+ int selected; ///< The currently selected AI.
+ CompanyID slot; ///< The company we're selecting a new AI for.
+ int line_height; ///< Height of a row in the matrix widget.
+ Scrollbar *vscroll; ///< Cache of the vertical scrollbar.
/**
* Constructor for the window.
@@ -74,7 +74,7 @@ struct AIListWindow : public Window {
if (AIConfig::GetConfig(slot)->HasAI()) {
AIInfo *info = AIConfig::GetConfig(slot)->GetInfo();
int i = 0;
- for (AIInfoList::const_iterator it = this->ai_info_list->begin(); it != this->ai_info_list->end(); it++, i++) {
+ for (ScriptInfoList::const_iterator it = this->ai_info_list->begin(); it != this->ai_info_list->end(); it++, i++) {
if ((*it).second == info) {
this->selected = i;
break;
@@ -105,7 +105,7 @@ struct AIListWindow : public Window {
DrawString(r.left + WD_MATRIX_LEFT, r.right - WD_MATRIX_LEFT, y + WD_MATRIX_TOP, STR_AI_CONFIG_RANDOM_AI, this->selected == -1 ? TC_WHITE : TC_BLACK);
y += this->line_height;
}
- AIInfoList::const_iterator it = this->ai_info_list->begin();
+ ScriptInfoList::const_iterator it = this->ai_info_list->begin();
for (int i = 1; it != this->ai_info_list->end(); i++, it++) {
if (this->vscroll->IsVisible(i)) {
DrawString(r.left + WD_MATRIX_LEFT, r.right - WD_MATRIX_RIGHT, y + WD_MATRIX_TOP, (*it).second->GetName(), (this->selected == i - 1) ? TC_WHITE : TC_BLACK);
@@ -116,9 +116,9 @@ struct AIListWindow : public Window {
}
case AIL_WIDGET_INFO_BG: {
AIInfo *selected_info = NULL;
- AIInfoList::const_iterator it = this->ai_info_list->begin();
+ ScriptInfoList::const_iterator it = this->ai_info_list->begin();
for (int i = 1; selected_info == NULL && it != this->ai_info_list->end(); i++, it++) {
- if (this->selected == i - 1) selected_info = (*it).second;
+ if (this->selected == i - 1) selected_info = static_cast<AIInfo *>((*it).second);
}
/* Some info about the currently selected AI. */
if (selected_info != NULL) {
@@ -150,7 +150,7 @@ struct AIListWindow : public Window {
if (this->selected == -1) {
AIConfig::GetConfig(slot)->ChangeAI(NULL);
} else {
- AIInfoList::const_iterator it = this->ai_info_list->begin();
+ ScriptInfoList::const_iterator it = this->ai_info_list->begin();
for (int i = 0; i < this->selected; i++) it++;
AIConfig::GetConfig(slot)->ChangeAI((*it).second->GetName(), (*it).second->GetVersion());
}
diff --git a/src/ai/ai_info.cpp b/src/ai/ai_info.cpp
index a729cb482..a56064e01 100644
--- a/src/ai/ai_info.cpp
+++ b/src/ai/ai_info.cpp
@@ -7,16 +7,18 @@
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
-/** @file ai_info.cpp Implementation of AIFileInfo */
+/** @file ai_info.cpp Implementation of AIInfo and AILibrary */
#include "../stdafx.h"
#include "../script/squirrel_helper.hpp"
+#include "../script/squirrel_class.hpp"
#include "ai_info.hpp"
#include "ai_scanner.hpp"
#include "../settings_type.h"
#include "../debug.h"
#include "../rev.h"
+#include "ai.hpp"
/** Maximum number of operations allowed for getting a particular setting. */
static const int MAX_GET_SETTING_OPS = 100000;
@@ -37,20 +39,6 @@ AIConfigItem _start_date_config = {
NULL
};
-AILibrary::~AILibrary()
-{
- free(this->category);
-}
-
-/* static */ SQInteger AIFileInfo::Constructor(HSQUIRRELVM vm, AIFileInfo *info)
-{
- SQInteger res = ScriptFileInfo::Constructor(vm, info);
- if (res != 0) return res;
- info->base = ((AIScanner *)Squirrel::GetGlobalPointer(vm));
-
- return 0;
-}
-
/**
* Check if the API version provided by the AI is supported.
* @param api_version The API version as provided by the AI.
@@ -60,6 +48,29 @@ static bool CheckAPIVersion(const char *api_version)
return strcmp(api_version, "0.7") == 0 || strcmp(api_version, "1.0") == 0 || strcmp(api_version, "1.1") == 0 || strcmp(api_version, "1.2") == 0;
}
+#if defined(WIN32)
+#undef GetClassName
+#endif /* WIN32 */
+template <> const char *GetClassName<AIInfo, ST_AI>() { return "AIInfo"; }
+
+/* static */ void AIInfo::RegisterAPI(Squirrel *engine)
+{
+ /* Create the AIInfo class, and add the RegisterAI function */
+ DefSQClass<AIInfo, ST_AI> SQAIInfo("AIInfo");
+ SQAIInfo.PreRegister(engine);
+ SQAIInfo.AddConstructor<void (AIInfo::*)(), 1>(engine, "x");
+ SQAIInfo.DefSQAdvancedMethod(engine, &AIInfo::AddSetting, "AddSetting");
+ SQAIInfo.DefSQAdvancedMethod(engine, &AIInfo::AddLabels, "AddLabels");
+ SQAIInfo.DefSQConst(engine, AICONFIG_NONE, "AICONFIG_NONE");
+ SQAIInfo.DefSQConst(engine, AICONFIG_RANDOM, "AICONFIG_RANDOM");
+ SQAIInfo.DefSQConst(engine, AICONFIG_BOOLEAN, "AICONFIG_BOOLEAN");
+ SQAIInfo.DefSQConst(engine, AICONFIG_INGAME, "AICONFIG_INGAME");
+ SQAIInfo.DefSQConst(engine, AICONFIG_AI_DEVELOPER, "AICONFIG_AI_DEVELOPER");
+ SQAIInfo.PostRegister(engine);
+ engine->AddMethod("RegisterAI", &AIInfo::Constructor, 2, "tx");
+ engine->AddMethod("RegisterDummyAI", &AIInfo::DummyConstructor, 2, "tx");
+}
+
/* static */ SQInteger AIInfo::Constructor(HSQUIRRELVM vm)
{
/* Get the AIInfo */
@@ -67,7 +78,7 @@ static bool CheckAPIVersion(const char *api_version)
if (SQ_FAILED(sq_getinstanceup(vm, 2, &instance, 0)) || instance == NULL) return sq_throwerror(vm, _SC("Pass an instance of a child class of AIInfo to RegisterAI"));
AIInfo *info = (AIInfo *)instance;
- SQInteger res = AIFileInfo::Constructor(vm, info);
+ SQInteger res = ScriptInfo::Constructor(vm, info);
if (res != 0) return res;
AIConfigItem config = _start_date_config;
@@ -104,7 +115,7 @@ static bool CheckAPIVersion(const char *api_version)
/* Remove the link to the real instance, else it might get deleted by RegisterAI() */
sq_setinstanceup(vm, 2, NULL);
/* Register the AI to the base system */
- info->base->RegisterAI(info);
+ info->GetScanner()->RegisterScript(info);
return 0;
}
@@ -116,7 +127,7 @@ static bool CheckAPIVersion(const char *api_version)
AIInfo *info = (AIInfo *)instance;
info->api_version = NULL;
- SQInteger res = AIFileInfo::Constructor(vm, info);
+ SQInteger res = ScriptInfo::Constructor(vm, info);
if (res != 0) return res;
char buf[8];
@@ -126,7 +137,7 @@ static bool CheckAPIVersion(const char *api_version)
/* Remove the link to the real instance, else it might get deleted by RegisterAI() */
sq_setinstanceup(vm, 2, NULL);
/* Register the AI to the base system */
- info->base->SetDummyAI(info);
+ static_cast<AIScannerInfo *>(info->GetScanner())->SetDummyAI(info);
return 0;
}
@@ -350,12 +361,26 @@ int AIInfo::GetSettingDefaultValue(const char *name) const
return -1;
}
+
+AILibrary::~AILibrary()
+{
+ free(this->category);
+}
+
+/* static */ void AILibrary::RegisterAPI(Squirrel *engine)
+{
+ /* Create the AILibrary class, and add the RegisterLibrary function */
+ engine->AddClassBegin("AILibrary");
+ engine->AddClassEnd();
+ engine->AddMethod("RegisterLibrary", &AILibrary::Constructor, 2, "tx");
+}
+
/* static */ SQInteger AILibrary::Constructor(HSQUIRRELVM vm)
{
- /* Create a new AIFileInfo */
+ /* Create a new library */
AILibrary *library = new AILibrary();
- SQInteger res = AIFileInfo::Constructor(vm, library);
+ SQInteger res = ScriptInfo::Constructor(vm, library);
if (res != 0) {
delete library;
return res;
@@ -368,7 +393,7 @@ int AIInfo::GetSettingDefaultValue(const char *name) const
}
/* Register the Library to the base system */
- library->base->RegisterLibrary(library);
+ library->GetScanner()->RegisterScript(library);
return 0;
}
diff --git a/src/ai/ai_info.hpp b/src/ai/ai_info.hpp
index f3833fdac..82ca6f925 100644
--- a/src/ai/ai_info.hpp
+++ b/src/ai/ai_info.hpp
@@ -49,25 +49,18 @@ extern AIConfigItem _start_date_config;
typedef std::list<AIConfigItem> AIConfigItemList; ///< List of AIConfig items.
-/** Base class that holds some basic information about AIs and AI libraries. */
-class AIFileInfo : public ScriptFileInfo {
-public:
- /**
- * Process the creation of a FileInfo object.
- */
- static SQInteger Constructor(HSQUIRRELVM vm, AIFileInfo *info);
-
-protected:
- class AIScanner *base; ///< AIScanner object that was used to scan this AI (library) info.
-};
-
/** All static information from an AI like name, version, etc. */
-class AIInfo : public AIFileInfo {
+class AIInfo : public ScriptInfo {
public:
AIInfo();
~AIInfo();
/**
+ * Register the functions of this class.
+ */
+ static void RegisterAPI(Squirrel *engine);
+
+ /**
* Create an AI, using this AIInfo as start-template.
*/
static SQInteger Constructor(HSQUIRRELVM vm);
@@ -130,12 +123,17 @@ private:
};
/** All static information from an AI library like name, version, etc. */
-class AILibrary : public AIFileInfo {
+class AILibrary : public ScriptInfo {
public:
- AILibrary() : AIFileInfo(), category(NULL) {};
+ AILibrary() : ScriptInfo(), category(NULL) {};
~AILibrary();
/**
+ * Register the functions of this class.
+ */
+ static void RegisterAPI(Squirrel *engine);
+
+ /**
* Create an AI, using this AIInfo as start-template.
*/
static SQInteger Constructor(HSQUIRRELVM vm);
diff --git a/src/ai/ai_scanner.cpp b/src/ai/ai_scanner.cpp
index 832b89887..3a296f00e 100644
--- a/src/ai/ai_scanner.cpp
+++ b/src/ai/ai_scanner.cpp
@@ -20,177 +20,50 @@
#include "ai_scanner.hpp"
#include "../script/api/script_controller.hpp"
-void AIScanner::RescanAIDir()
-{
- /* Get rid of information of old AIs. */
- this->Reset();
- this->Scan(PATHSEP "info.nut", AI_DIR);
- this->Scan(PATHSEP "library.nut", AI_LIBRARY_DIR);
-}
-
-template <> const char *GetClassName<AIInfo, ST_AI>() { return "AIInfo"; }
-AIScanner::AIScanner() :
+AIScannerInfo::AIScannerInfo() :
ScriptScanner(),
info_dummy(NULL)
{
- /* Create the AIInfo class, and add the RegisterAI function */
- DefSQClass<AIInfo, ST_AI> SQAIInfo("AIInfo");
- SQAIInfo.PreRegister(engine);
- SQAIInfo.AddConstructor<void (AIInfo::*)(), 1>(engine, "x");
- SQAIInfo.DefSQAdvancedMethod(this->engine, &AIInfo::AddSetting, "AddSetting");
- SQAIInfo.DefSQAdvancedMethod(this->engine, &AIInfo::AddLabels, "AddLabels");
- SQAIInfo.DefSQConst(engine, AICONFIG_NONE, "AICONFIG_NONE");
- SQAIInfo.DefSQConst(engine, AICONFIG_RANDOM, "AICONFIG_RANDOM");
- SQAIInfo.DefSQConst(engine, AICONFIG_BOOLEAN, "AICONFIG_BOOLEAN");
- SQAIInfo.DefSQConst(engine, AICONFIG_INGAME, "AICONFIG_INGAME");
- SQAIInfo.DefSQConst(engine, AICONFIG_AI_DEVELOPER, "AICONFIG_AI_DEVELOPER");
- SQAIInfo.PostRegister(engine);
- this->engine->AddMethod("RegisterAI", &AIInfo::Constructor, 2, "tx");
- this->engine->AddMethod("RegisterDummyAI", &AIInfo::DummyConstructor, 2, "tx");
-
- /* Create the AILibrary class, and add the RegisterLibrary function */
- this->engine->AddClassBegin("AILibrary");
- this->engine->AddClassEnd();
- this->engine->AddMethod("RegisterLibrary", &AILibrary::Constructor, 2, "tx");
+}
- /* Scan the AI dir for scripts */
- this->RescanAIDir();
+void AIScannerInfo::Initialize(const char *name)
+{
+ ScriptScanner::Initialize(name);
/* Create the dummy AI */
- this->engine->ResetCrashed();
-
free(this->main_script);
this->main_script = strdup("%_dummy");
extern void AI_CreateAIInfoDummy(HSQUIRRELVM vm);
AI_CreateAIInfoDummy(this->engine->GetVM());
}
-void AIScanner::Reset()
+void AIScannerInfo::SetDummyAI(class AIInfo *info)
{
- AIInfoList::iterator it = this->info_list.begin();
- for (; it != this->info_list.end(); it++) {
- free((*it).first);
- delete (*it).second;
- }
- it = this->info_single_list.begin();
- for (; it != this->info_single_list.end(); it++) {
- free((*it).first);
- }
- AILibraryList::iterator lit = this->library_list.begin();
- for (; lit != this->library_list.end(); lit++) {
- free((*lit).first);
- delete (*lit).second;
- }
-
- this->info_list.clear();
- this->info_single_list.clear();
- this->library_list.clear();
+ this->info_dummy = info;
}
-AIScanner::~AIScanner()
+AIScannerInfo::~AIScannerInfo()
{
- this->Reset();
-
delete this->info_dummy;
}
-AILibrary *AIScanner::FindLibrary(const char *library, int version)
+void AIScannerInfo::GetScriptName(ScriptInfo *info, char *name, int len)
{
- /* Internally we store libraries as 'library.version' */
- char library_name[1024];
- snprintf(library_name, sizeof(library_name), "%s.%d", library, version);
- strtolower(library_name);
-
- /* Check if the library + version exists */
- AILibraryList::iterator iter = this->library_list.find(library_name);
- if (iter == this->library_list.end()) return NULL;
-
- return (*iter).second;
+ snprintf(name, len, "%s", info->GetName());
}
-void AIScanner::RegisterLibrary(AILibrary *library)
+void AIScannerInfo::RegisterAPI(class Squirrel *engine)
{
- char library_name[1024];
- snprintf(library_name, sizeof(library_name), "%s.%s.%d", library->GetCategory(), library->GetInstanceName(), library->GetVersion());
- strtolower(library_name);
-
- if (this->library_list.find(library_name) != this->library_list.end()) {
- /* This AI was already registered */
-#ifdef WIN32
- /* Windows doesn't care about the case */
- if (strcasecmp(this->library_list[library_name]->GetMainScript(), library->GetMainScript()) == 0) {
-#else
- if (strcmp(this->library_list[library_name]->GetMainScript(), library->GetMainScript()) == 0) {
-#endif
- delete library;
- return;
- }
-
- DEBUG(ai, 1, "Registering two libraries with the same name and version");
- DEBUG(ai, 1, " 1: %s", this->library_list[library_name]->GetMainScript());
- DEBUG(ai, 1, " 2: %s", library->GetMainScript());
- DEBUG(ai, 1, "The first is taking precedence.");
-
- delete library;
- return;
- }
-
- this->library_list[strdup(library_name)] = library;
+ AIInfo::RegisterAPI(engine);
}
-void AIScanner::RegisterAI(AIInfo *info)
-{
- char ai_name[1024];
- snprintf(ai_name, sizeof(ai_name), "%s.%d", info->GetName(), info->GetVersion());
- strtolower(ai_name);
-
- /* Check if GetShortName follows the rules */
- if (strlen(info->GetShortName()) != 4) {
- DEBUG(ai, 0, "The AI '%s' returned a string from GetShortName() which is not four characaters. Unable to load the AI.", info->GetName());
- delete info;
- return;
- }
-
- if (this->info_list.find(ai_name) != this->info_list.end()) {
- /* This AI was already registered */
-#ifdef WIN32
- /* Windows doesn't care about the case */
- if (strcasecmp(this->info_list[ai_name]->GetMainScript(), info->GetMainScript()) == 0) {
-#else
- if (strcmp(this->info_list[ai_name]->GetMainScript(), info->GetMainScript()) == 0) {
-#endif
- delete info;
- return;
- }
-
- DEBUG(ai, 1, "Registering two AIs with the same name and version");
- DEBUG(ai, 1, " 1: %s", this->info_list[ai_name]->GetMainScript());
- DEBUG(ai, 1, " 2: %s", info->GetMainScript());
- DEBUG(ai, 1, "The first is taking precedence.");
-
- delete info;
- return;
- }
-
- this->info_list[strdup(ai_name)] = info;
-
- /* Add the AI to the 'unique' AI list, where only the highest version of the
- * AI is registered. */
- snprintf(ai_name, sizeof(ai_name), "%s", info->GetName());
- strtolower(ai_name);
- if (this->info_single_list.find(ai_name) == this->info_single_list.end()) {
- this->info_single_list[strdup(ai_name)] = info;
- } else if (this->info_single_list[ai_name]->GetVersion() < info->GetVersion()) {
- this->info_single_list[ai_name] = info;
- }
-}
-
-AIInfo *AIScanner::SelectRandomAI() const
+AIInfo *AIScannerInfo::SelectRandomAI() const
{
uint num_random_ais = 0;
- for (AIInfoList::const_iterator it = this->info_single_list.begin(); it != this->info_single_list.end(); it++) {
- if (it->second->UseAsRandomAI()) num_random_ais++;
+ for (ScriptInfoList::const_iterator it = this->info_single_list.begin(); it != this->info_single_list.end(); it++) {
+ AIInfo *i = static_cast<AIInfo *>((*it).second);
+ if (i->UseAsRandomAI()) num_random_ais++;
}
if (num_random_ais == 0) {
@@ -207,16 +80,17 @@ AIInfo *AIScanner::SelectRandomAI() const
}
/* Find the Nth item from the array */
- AIInfoList::const_iterator it = this->info_single_list.begin();
- while (!it->second->UseAsRandomAI()) it++;
+ ScriptInfoList::const_iterator it = this->info_single_list.begin();
+ AIInfo *i = static_cast<AIInfo *>((*it).second);
+ while (!i->UseAsRandomAI()) it++;
for (; pos > 0; pos--) {
it++;
- while (!it->second->UseAsRandomAI()) it++;
+ while (!i->UseAsRandomAI()) it++;
}
- return (*it).second;
+ return i;
}
-AIInfo *AIScanner::FindInfo(const char *nameParam, int versionParam, bool force_exact_match)
+AIInfo *AIScannerInfo::FindInfo(const char *nameParam, int versionParam, bool force_exact_match)
{
if (this->info_list.size() == 0) return NULL;
if (nameParam == NULL) return NULL;
@@ -230,7 +104,7 @@ AIInfo *AIScanner::FindInfo(const char *nameParam, int versionParam, bool force_
if (versionParam == -1) {
/* We want to load the latest version of this AI; so find it */
- if (this->info_single_list.find(ai_name) != this->info_single_list.end()) return this->info_single_list[ai_name];
+ if (this->info_single_list.find(ai_name) != this->info_single_list.end()) return static_cast<AIInfo *>(this->info_single_list[ai_name]);
/* If we didn't find a match AI, maybe the user included a version */
char *e = strrchr(ai_name, '.');
@@ -246,177 +120,45 @@ AIInfo *AIScanner::FindInfo(const char *nameParam, int versionParam, bool force_
char ai_name_tmp[1024];
snprintf(ai_name_tmp, sizeof(ai_name_tmp), "%s.%d", ai_name, versionParam);
strtolower(ai_name_tmp);
- if (this->info_list.find(ai_name_tmp) != this->info_list.end()) return this->info_list[ai_name_tmp];
+ if (this->info_list.find(ai_name_tmp) != this->info_list.end()) return static_cast<AIInfo *>(this->info_list[ai_name_tmp]);
}
/* See if there is a compatible AI which goes by that name, with the highest
* version which allows loading the requested version */
- AIInfoList::iterator it = this->info_list.begin();
+ ScriptInfoList::iterator it = this->info_list.begin();
for (; it != this->info_list.end(); it++) {
- if (strcasecmp(ai_name, (*it).second->GetName()) == 0 && (*it).second->CanLoadFromVersion(versionParam) && (version == -1 || (*it).second->GetVersion() > version)) {
+ AIInfo *i = static_cast<AIInfo *>((*it).second);
+ if (strcasecmp(ai_name, i->GetName()) == 0 && i->CanLoadFromVersion(versionParam) && (version == -1 || i->GetVersion() > version)) {
version = (*it).second->GetVersion();
- info = (*it).second;
+ info = i;
}
}
return info;
}
-char *AIScanner::GetAIConsoleList(char *p, const char *last, bool newest_only) const
-{
- p += seprintf(p, last, "List of AIs:\n");
- const AIInfoList &list = newest_only ? this->info_single_list : this->info_list;
- AIInfoList::const_iterator it = list.begin();
- for (; it != list.end(); it++) {
- AIInfo *i = (*it).second;
- p += seprintf(p, last, "%10s (v%d): %s\n", i->GetName(), i->GetVersion(), i->GetDescription());
- }
- p += seprintf(p, last, "\n");
-
- return p;
-}
-char *AIScanner::GetAIConsoleLibraryList(char *p, const char *last) const
+void AIScannerLibrary::GetScriptName(ScriptInfo *info, char *name, int len)
{
- p += seprintf(p, last, "List of AI Libraries:\n");
- AILibraryList::const_iterator it = this->library_list.begin();
- for (; it != this->library_list.end(); it++) {
- AILibrary *i = (*it).second;
- p += seprintf(p, last, "%10s (v%d): %s\n", i->GetName(), i->GetVersion(), i->GetDescription());
- }
- p += seprintf(p, last, "\n");
-
- return p;
+ AILibrary *library = static_cast<AILibrary *>(info);
+ snprintf(name, len, "%s.%s", library->GetCategory(), library->GetInstanceName());
}
-#if defined(ENABLE_NETWORK)
-#include "../network/network_content.h"
-#include "../3rdparty/md5/md5.h"
-#include "../tar_type.h"
-
-/** Helper for creating a MD5sum of all files within of an AI. */
-struct AIFileChecksumCreator : FileScanner {
- byte md5sum[16]; ///< The final md5sum
-
- /**
- * Initialise the md5sum to be all zeroes,
- * so we can easily xor the data.
- */
- AIFileChecksumCreator()
- {
- memset(this->md5sum, 0, sizeof(this->md5sum));
- }
-
- /* Add the file and calculate the md5 sum. */
- virtual bool AddFile(const char *filename, size_t basepath_length, const char *tar_filename)
- {
- Md5 checksum;
- uint8 buffer[1024];
- size_t len, size;
- byte tmp_md5sum[16];
-
- /* Open the file ... */
- FILE *f = FioFOpenFile(filename, "rb", AI_DIR, &size);
- if (f == NULL) return false;
-
- /* ... calculate md5sum... */
- while ((len = fread(buffer, 1, (size > sizeof(buffer)) ? sizeof(buffer) : size, f)) != 0 && size != 0) {
- size -= len;
- checksum.Append(buffer, len);
- }
- checksum.Finish(tmp_md5sum);
-
- FioFCloseFile(f);
-
- /* ... and xor it to the overall md5sum. */
- for (uint i = 0; i < sizeof(md5sum); i++) this->md5sum[i] ^= tmp_md5sum[i];
-
- return true;
- }
-};
-
-/**
- * Check whether the AI given in info is the same as in ci based
- * on the shortname and md5 sum.
- * @param ci the information to compare to
- * @param md5sum whether to check the MD5 checksum
- * @param info the AI to get the shortname and md5 sum from
- * @return true iff they're the same
- */
-static bool IsSameAI(const ContentInfo *ci, bool md5sum, AIFileInfo *info)
+void AIScannerLibrary::RegisterAPI(class Squirrel *engine)
{
- uint32 id = 0;
- const char *str = info->GetShortName();
- for (int j = 0; j < 4 && *str != '\0'; j++, str++) id |= *str << (8 * j);
-
- if (id != ci->unique_id) return false;
- if (!md5sum) return true;
-
- AIFileChecksumCreator checksum;
- const char *tar_filename = info->GetTarFile();
- TarList::iterator iter;
- if (tar_filename != NULL && (iter = _tar_list[AI_DIR].find(tar_filename)) != _tar_list[AI_DIR].end()) {
- /* The main script is in a tar file, so find all files that
- * are in the same tar and add them to the MD5 checksumming. */
- TarFileList::iterator tar;
- FOR_ALL_TARS(tar, AI_DIR) {
- /* Not in the same tar. */
- if (tar->second.tar_filename != iter->first) continue;
-
- /* Check the extension. */
- const char *ext = strrchr(tar->first.c_str(), '.');
- if (ext == NULL || strcasecmp(ext, ".nut") != 0) continue;
-
- checksum.AddFile(tar->first.c_str(), 0, tar_filename);
- }
- } else {
- char path[MAX_PATH];
- strecpy(path, info->GetMainScript(), lastof(path));
- /* There'll always be at least 1 path separator character in an AI's
- * main script name as the search algorithm requires the main script to
- * be in a subdirectory of the AI directory; so ai/<path>/main.nut. */
- *strrchr(path, PATHSEPCHAR) = '\0';
- checksum.Scan(".nut", path);
- }
-
- return memcmp(ci->md5sum, checksum.md5sum, sizeof(ci->md5sum)) == 0;
+ AILibrary::RegisterAPI(engine);
}
-/**
- * Check whether we have an AI (library) with the exact characteristics as ci.
- * @param ci the characteristics to search on (shortname and md5sum)
- * @param md5sum whether to check the MD5 checksum
- * @return true iff we have an AI (library) matching.
- */
-bool AIScanner::HasAI(const ContentInfo *ci, bool md5sum)
+AILibrary *AIScannerLibrary::FindLibrary(const char *library, int version)
{
- switch (ci->type) {
- case CONTENT_TYPE_AI:
- for (AIInfoList::iterator it = this->info_list.begin(); it != this->info_list.end(); it++) {
- if (IsSameAI(ci, md5sum, (*it).second)) return true;
- }
- return false;
-
- case CONTENT_TYPE_AI_LIBRARY:
- for (AILibraryList::iterator it = this->library_list.begin(); it != this->library_list.end(); it++) {
- if (IsSameAI(ci, md5sum, (*it).second)) return true;
- }
- return false;
+ /* Internally we store libraries as 'library.version' */
+ char library_name[1024];
+ snprintf(library_name, sizeof(library_name), "%s.%d", library, version);
+ strtolower(library_name);
- default:
- NOT_REACHED();
- }
-}
+ /* Check if the library + version exists */
+ ScriptInfoList::iterator iter = this->info_list.find(library_name);
+ if (iter == this->info_list.end()) return NULL;
-/**
- * Check whether we have an AI (library) with the exact characteristics as ci.
- * @param ci the characteristics to search on (shortname and md5sum)
- * @param md5sum whether to check the MD5 checksum
- * @return true iff we have an AI (library) matching.
- */
-/* static */ bool AI::HasAI(const ContentInfo *ci, bool md5sum)
-{
- return AI::ai_scanner->HasAI(ci, md5sum);
+ return static_cast<AILibrary *>((*iter).second);
}
-
-#endif /* ENABLE_NETWORK */
diff --git a/src/ai/ai_scanner.hpp b/src/ai/ai_scanner.hpp
index cbc778069..2f55c8594 100644
--- a/src/ai/ai_scanner.hpp
+++ b/src/ai/ai_scanner.hpp
@@ -13,95 +13,61 @@
#define AI_SCANNER_HPP
#include "../script/script_scanner.hpp"
-#include "ai.hpp"
-/**
- * Class that scans for available AIs.
- */
-class AIScanner : public ScriptScanner {
+class AIScannerInfo : public ScriptScanner {
public:
- AIScanner();
- ~AIScanner();
-
- /**
- * Find a library by name + version.
- * @param library The name of the library to find.
- * @param version The prefered version of the library.
- * @return The library if found, NULL otherwise.
- */
- AILibrary *FindLibrary(const char *library, int version);
-
- /**
- * Register a library to be put in the available list.
- */
- void RegisterLibrary(class AILibrary *library);
+ AIScannerInfo();
+ ~AIScannerInfo();
- /**
- * Register an AI to be put in the available list.
- */
- void RegisterAI(class AIInfo *info);
-
- /**
- * Register the dummy AI.
- * @param info The dummy AI that.
- */
- void SetDummyAI(class AIInfo *info) { this->info_dummy = info; }
+ /* virtual */ void Initialize(const char *name);
/**
- * Select a Random AI.
+ * Select a random AI.
+ * @return A random AI from the pool.
*/
class AIInfo *SelectRandomAI() const;
/**
- * Find an AI by name.
+ * Check if we have an AI by name and version available in our list.
+ * @param nameParam The name of the AI.
+ * @param versionParam The versionof the AI, or -1 if you want the latest.
+ * @param force_exact_match Only match name+version, never latest.
+ * @return NULL if no match found, otherwise the AI that matched.
*/
- class AIInfo *FindInfo(const char *name, int version, bool force_exact_match);
+ class AIInfo *FindInfo(const char *nameParam, int versionParam, bool force_exact_match);
/**
- * Get the list of available AIs for the console.
+ * Set the Dummy AI.
*/
- char *GetAIConsoleList(char *p, const char *last, bool newest_only) const;
+ void SetDummyAI(class AIInfo *info);
- /**
- * Get the list of available AI Libraries for the console.
- */
- char *GetAIConsoleLibraryList(char *p, const char *last) const;
+protected:
+ /* virtual */ void GetScriptName(ScriptInfo *info, char *name, int len);
+ /* virtual */ const char *GetFileName() const { return PATHSEP "info.nut"; }
+ /* virtual */ Subdirectory GetDirectory() const { return AI_DIR; }
+ /* virtual */ const char *GetScannerName() const { return "AIs"; }
+ /* virtual */ void RegisterAPI(class Squirrel *engine);
- /**
- * Get the list of all registered AIs.
- */
- const AIInfoList *GetAIInfoList() { return &this->info_list; }
-
- /**
- * Get the list of the newest version of all registered AIs.
- */
- const AIInfoList *GetUniqueAIInfoList() { return &this->info_single_list; }
-
- /**
- * Rescan the AI dir for scripts.
- */
- void RescanAIDir();
-
-#if defined(ENABLE_NETWORK)
- bool HasAI(const struct ContentInfo *ci, bool md5sum);
-#endif
private:
- typedef std::map<const char *, class AILibrary *, StringCompare> AILibraryList; ///< Type for the list of libraries.
-
- /**
- * Scan the AI dir for scripts.
- */
- void ScanAIDir();
+ AIInfo *info_dummy; ///< The dummy AI.
+};
+class AIScannerLibrary : public ScriptScanner {
+public:
/**
- * Reset all allocated lists.
+ * Find a library in the pool.
+ * @param library The library name to find.
+ * @param version The version the library should have.
+ * @return The library if found, NULL otherwise.
*/
- void Reset();
-
- AIInfo *info_dummy; ///< The dummy AI.
- AIInfoList info_list; ///< The list of all AIs.
- AIInfoList info_single_list; ///< The list of all unique AIs, based on shortname. The best AI (highest version) is shown.
- AILibraryList library_list; ///< The list of libraries.
+ class AILibrary *FindLibrary(const char *library, int version);
+
+protected:
+ /* virtual */ void GetScriptName(ScriptInfo *info, char *name, int len);
+ /* virtual */ const char *GetFileName() const { return PATHSEP "library.nut"; }
+ /* virtual */ Subdirectory GetDirectory() const { return AI_LIBRARY_DIR; }
+ /* virtual */ const char *GetScannerName() const { return "AI Libraries"; }
+ /* virtual */ void RegisterAPI(class Squirrel *engine);
};
#endif /* AI_SCANNER_HPP */