2009-08-21 22:21:05 +02:00
/*
* This file is part of OpenTTD .
* OpenTTD 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 , version 2.
* OpenTTD 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 OpenTTD . If not , see < http : //www.gnu.org/licenses/>.
*/
2011-11-30 00:21:52 +01:00
/** @file ai_info.cpp Implementation of AIInfo and AILibrary */
2009-01-12 18:11:45 +01:00
# include "../stdafx.h"
2011-11-30 00:21:52 +01:00
# include "../script/squirrel_class.hpp"
2009-01-12 18:11:45 +01:00
# include "ai_info.hpp"
# include "ai_scanner.hpp"
2009-08-18 20:51:42 +02:00
# include "../debug.h"
2014-04-25 17:40:32 +02:00
# include "../string_func.h"
2009-09-22 13:10:04 +02:00
# include "../rev.h"
2009-01-12 18:11:45 +01:00
2014-04-23 22:13:33 +02:00
# include "../safeguards.h"
2010-08-01 00:16:34 +02:00
/**
* Check if the API version provided by the AI is supported .
* @ param api_version The API version as provided by the AI .
*/
2023-05-04 23:06:21 +02:00
static bool CheckAPIVersion ( const std : : string & api_version )
2009-08-18 20:51:42 +02:00
{
2024-02-18 17:38:26 +01:00
static const std : : set < std : : string > versions = { " 0.7 " , " 1.0 " , " 1.1 " , " 1.2 " , " 1.3 " , " 1.4 " , " 1.5 " , " 1.6 " , " 1.7 " , " 1.8 " , " 1.9 " , " 1.10 " , " 1.11 " , " 12 " , " 13 " , " 14 " , " 15 " } ;
2020-02-14 17:53:24 +01:00
return versions . find ( api_version ) ! = versions . end ( ) ;
2009-08-18 20:51:42 +02:00
}
2018-12-09 02:28:14 +01:00
# if defined(_WIN32)
2011-11-30 00:21:52 +01:00
# undef GetClassName
2018-12-09 02:28:14 +01:00
# endif /* _WIN32 */
2023-04-16 21:00:55 +02:00
template < > const char * GetClassName < AIInfo , ScriptType : : AI > ( ) { return " AIInfo " ; }
2011-11-30 00:21:52 +01:00
/* static */ void AIInfo : : RegisterAPI ( Squirrel * engine )
{
/* Create the AIInfo class, and add the RegisterAI function */
2023-04-16 21:00:55 +02:00
DefSQClass < AIInfo , ScriptType : : AI > SQAIInfo ( " AIInfo " ) ;
2011-11-30 00:21:52 +01:00
SQAIInfo . PreRegister ( engine ) ;
SQAIInfo . AddConstructor < void ( AIInfo : : * ) ( ) , 1 > ( engine , " x " ) ;
SQAIInfo . DefSQAdvancedMethod ( engine , & AIInfo : : AddSetting , " AddSetting " ) ;
SQAIInfo . DefSQAdvancedMethod ( engine , & AIInfo : : AddLabels , " AddLabels " ) ;
2011-11-30 00:26:35 +01:00
SQAIInfo . DefSQConst ( engine , SCRIPTCONFIG_NONE , " CONFIG_NONE " ) ;
2024-01-31 23:24:36 +01:00
SQAIInfo . DefSQConst ( engine , SCRIPTCONFIG_NONE , " CONFIG_RANDOM " ) ; // Deprecated, mapped to NONE.
2011-11-30 00:26:35 +01:00
SQAIInfo . DefSQConst ( engine , SCRIPTCONFIG_BOOLEAN , " CONFIG_BOOLEAN " ) ;
SQAIInfo . DefSQConst ( engine , SCRIPTCONFIG_INGAME , " CONFIG_INGAME " ) ;
SQAIInfo . DefSQConst ( engine , SCRIPTCONFIG_DEVELOPER , " CONFIG_DEVELOPER " ) ;
/* Pre 1.2 had an AI prefix */
SQAIInfo . DefSQConst ( engine , SCRIPTCONFIG_NONE , " AICONFIG_NONE " ) ;
2024-01-31 23:24:36 +01:00
SQAIInfo . DefSQConst ( engine , SCRIPTCONFIG_NONE , " AICONFIG_RANDOM " ) ; // Deprecated, mapped to NONE.
2011-11-30 00:26:35 +01:00
SQAIInfo . DefSQConst ( engine , SCRIPTCONFIG_BOOLEAN , " AICONFIG_BOOLEAN " ) ;
SQAIInfo . DefSQConst ( engine , SCRIPTCONFIG_INGAME , " AICONFIG_INGAME " ) ;
2011-11-30 00:21:52 +01:00
SQAIInfo . PostRegister ( engine ) ;
engine - > AddMethod ( " RegisterAI " , & AIInfo : : Constructor , 2 , " tx " ) ;
engine - > AddMethod ( " RegisterDummyAI " , & AIInfo : : DummyConstructor , 2 , " tx " ) ;
}
2009-01-12 18:11:45 +01:00
/* static */ SQInteger AIInfo : : Constructor ( HSQUIRRELVM vm )
{
/* Get the AIInfo */
2019-04-10 23:07:06 +02:00
SQUserPointer instance = nullptr ;
2021-06-16 21:10:41 +02:00
if ( SQ_FAILED ( sq_getinstanceup ( vm , 2 , & instance , nullptr ) ) | | instance = = nullptr ) return sq_throwerror ( vm , " Pass an instance of a child class of AIInfo to RegisterAI " ) ;
2009-01-12 18:11:45 +01:00
AIInfo * info = ( AIInfo * ) instance ;
2011-11-30 00:21:52 +01:00
SQInteger res = ScriptInfo : : Constructor ( vm , info ) ;
2009-01-12 18:11:45 +01:00
if ( res ! = 0 ) return res ;
2023-05-06 14:19:41 +02:00
if ( info - > engine - > MethodExists ( info - > SQ_instance , " MinVersionToLoad " ) ) {
if ( ! info - > engine - > CallIntegerMethod ( info - > SQ_instance , " MinVersionToLoad " , & info - > min_loadable_version , MAX_GET_OPS ) ) return SQ_ERROR ;
2009-02-13 02:44:56 +01:00
} else {
info - > min_loadable_version = info - > GetVersion ( ) ;
}
2009-04-21 21:13:32 +02:00
/* When there is an UseAsRandomAI function, call it. */
2023-05-06 14:19:41 +02:00
if ( info - > engine - > MethodExists ( info - > SQ_instance , " UseAsRandomAI " ) ) {
if ( ! info - > engine - > CallBoolMethod ( info - > SQ_instance , " UseAsRandomAI " , & info - > use_as_random , MAX_GET_OPS ) ) return SQ_ERROR ;
2009-04-21 21:13:32 +02:00
} else {
info - > use_as_random = true ;
}
2009-08-18 20:51:42 +02:00
/* Try to get the API version the AI is written for. */
2023-05-06 14:19:41 +02:00
if ( info - > engine - > MethodExists ( info - > SQ_instance , " GetAPIVersion " ) ) {
if ( ! info - > engine - > CallStringMethod ( info - > SQ_instance , " GetAPIVersion " , & info - > api_version , MAX_GET_OPS ) ) return SQ_ERROR ;
2009-08-18 20:51:42 +02:00
if ( ! CheckAPIVersion ( info - > api_version ) ) {
2021-06-12 09:10:17 +02:00
Debug ( script , 1 , " Loading info.nut from ({}.{}): GetAPIVersion returned invalid version " , info - > GetName ( ) , info - > GetVersion ( ) ) ;
2009-08-18 20:51:42 +02:00
return SQ_ERROR ;
}
} else {
2023-05-04 23:06:21 +02:00
info - > api_version = " 0.7 " ;
2009-08-18 20:51:42 +02:00
}
2009-01-12 18:11:45 +01:00
/* Remove the link to the real instance, else it might get deleted by RegisterAI() */
2019-04-10 23:07:06 +02:00
sq_setinstanceup ( vm , 2 , nullptr ) ;
2009-01-12 18:11:45 +01:00
/* Register the AI to the base system */
2011-11-30 00:21:52 +01:00
info - > GetScanner ( ) - > RegisterScript ( info ) ;
2009-01-12 18:11:45 +01:00
return 0 ;
}
/* static */ SQInteger AIInfo : : DummyConstructor ( HSQUIRRELVM vm )
{
/* Get the AIInfo */
SQUserPointer instance ;
2021-06-16 21:10:41 +02:00
sq_getinstanceup ( vm , 2 , & instance , nullptr ) ;
2009-01-12 18:11:45 +01:00
AIInfo * info = ( AIInfo * ) instance ;
2023-05-04 23:06:21 +02:00
info - > api_version = fmt : : format ( " {}.{} " , GB ( _openttd_newgrf_version , 28 , 4 ) , GB ( _openttd_newgrf_version , 24 , 4 ) ) ;
2009-01-12 18:11:45 +01:00
2011-11-30 00:21:52 +01:00
SQInteger res = ScriptInfo : : Constructor ( vm , info ) ;
2009-01-12 18:11:45 +01:00
if ( res ! = 0 ) return res ;
/* Remove the link to the real instance, else it might get deleted by RegisterAI() */
2019-04-10 23:07:06 +02:00
sq_setinstanceup ( vm , 2 , nullptr ) ;
2009-01-12 18:11:45 +01:00
/* Register the AI to the base system */
2011-11-30 00:21:52 +01:00
static_cast < AIScannerInfo * > ( info - > GetScanner ( ) ) - > SetDummyAI ( info ) ;
2009-01-12 18:11:45 +01:00
return 0 ;
}
2009-12-06 21:22:21 +01:00
AIInfo : : AIInfo ( ) :
min_loadable_version ( 0 ) ,
2023-05-04 23:06:21 +02:00
use_as_random ( false )
2009-01-12 18:11:45 +01:00
{
}
2009-02-13 03:11:54 +01:00
bool AIInfo : : CanLoadFromVersion ( int version ) const
2009-02-13 02:44:56 +01:00
{
if ( version = = - 1 ) return true ;
return version > = this - > min_loadable_version & & version < = this - > GetVersion ( ) ;
}
2011-11-30 00:21:52 +01:00
/* 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 " ) ;
}
2009-01-12 18:11:45 +01:00
/* static */ SQInteger AILibrary : : Constructor ( HSQUIRRELVM vm )
{
2011-11-30 00:21:52 +01:00
/* Create a new library */
2009-01-12 18:11:45 +01:00
AILibrary * library = new AILibrary ( ) ;
2011-11-30 00:21:52 +01:00
SQInteger res = ScriptInfo : : Constructor ( vm , library ) ;
2009-01-17 15:54:24 +01:00
if ( res ! = 0 ) {
delete library ;
return res ;
}
2009-01-12 18:11:45 +01:00
2009-02-13 02:44:56 +01:00
/* Cache the category */
2023-05-06 14:19:41 +02:00
if ( ! library - > CheckMethod ( " GetCategory " ) | | ! library - > engine - > CallStringMethod ( library - > SQ_instance , " GetCategory " , & library - > category , MAX_GET_OPS ) ) {
2009-02-13 18:17:34 +01:00
delete library ;
return SQ_ERROR ;
}
2009-02-13 02:44:56 +01:00
2009-01-12 18:11:45 +01:00
/* Register the Library to the base system */
2011-11-30 00:21:52 +01:00
library - > GetScanner ( ) - > RegisterScript ( library ) ;
2009-01-12 18:11:45 +01:00
return 0 ;
}