1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2014-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "nel/ligo/primitive.h"
25 #include "nel/ligo/ligo_config.h"
26 #include "game_share/tick_event_handler.h"
27 #include "game_share/ryzom_version.h"
29 #include "world_container.h"
32 #include "ai_keywords.h"
35 #include "ais_actions.h"
36 #include "egs_interface.h"
37 #include "aids_interface.h"
38 #include "game_share/fame.h"
39 #include "visual_properties_interface.h"
41 #include "ais_user_models.h"
44 # ifndef NL_COMP_MINGW
48 #endif // NL_OS_WINDOWS
50 //#include "nel/misc/bitmap.h"
52 using namespace NLMISC
;
53 using namespace NLNET
;
56 // force admin module to link in
57 extern void admin_modules_forceLink();
60 admin_modules_forceLink();
63 bool EGSHasMirrorReady
= false;
64 bool IOSHasMirrorReady
= false;
67 NLLIGO::CLigoConfig LigoConfig
;
71 bool compileExternalScript (const char *filename
, const char *outputFilename
);
74 /*-----------------------------------------------------------------*\
76 \*-----------------------------------------------------------------*/
78 class CAIService
: public NLNET::IService
88 // callback for the 'tick' update message
91 // callback for the 'tick' release message
94 (static_cast<CAIService
*>(CAIService::getInstance()))->tickRelease();
97 /*-----------------------------------------------------------------*\
98 SERVICE INIT & RELEASE
99 \*-----------------------------------------------------------------*/
102 static void cbServiceMirrorUp( const std::string
& serviceName
, NLNET::TServiceId serviceId
, void * )
104 if (serviceName
== "IOS")
106 IOSHasMirrorReady
= true;
109 if (serviceName
== "EGS")
111 EGSHasMirrorReady
= true;
113 // force an AI update on EGS up
114 CAIS::instance().update();
116 //send custom data to EGS
117 CAIUserModelManager::getInstance()->sendUserModels();
118 CAIUserModelManager::getInstance()->sendCustomLootTables();
121 CAIS::instance().serviceEvent(CServiceEvent(serviceId
, serviceName
, CServiceEvent::SERVICE_UP
));
124 static void cbServiceDown( const std::string
& serviceName
, NLNET::TServiceId serviceId
, void * )
126 if ( serviceName
== "IOS" )
128 IOSHasMirrorReady
= false;
131 if ( serviceName
== "EGS" )
133 EGSHasMirrorReady
= false;
136 CAIS::instance().serviceEvent(CServiceEvent(serviceId
, serviceName
, CServiceEvent::SERVICE_DOWN
));
140 void CAIService::commandStart()
142 // Compile an AI script ?
145 string scriptFilename
= getArg ('c');
147 if (!scriptFilename
.empty ())
149 string outputFilename
;
151 outputFilename
= getArg ('o');
154 result
= AICOMP::compileExternalScript (scriptFilename
.c_str (), outputFilename
.c_str ());
157 nlwarning ("No script filename");
159 ::exit (result
?0:-1);
164 void CAIService::init (void)
166 // start any available system command.
167 CConfigFile::CVar
*sysCmds
= IService::getInstance()->ConfigFile
.getVarPtr("SystemCmd");
170 for (uint i
=0; i
<sysCmds
->size(); ++i
)
172 string cmd
= sysCmds
->asString(i
);
174 nlinfo("Invoking system command '%s'...", cmd
.c_str());
175 int ret
= system(cmd
.c_str());
176 nlinfo(" command returned %d", ret
);
180 // read sheet_id.bin and don't prune out unknown files
181 CSheetId::init(false);
183 // Init singleton manager
184 CSingletonRegistry::getInstance()->init();
186 // init static fame manager
187 CStaticFames::getInstance();
189 setVersion (RYZOM_PRODUCT_VERSION
);
192 if (!LigoConfig
.readPrimitiveClass ("world_editor_classes.xml", false))
194 // Should be in R:\leveldesign\world_editor_files
195 nlerror ("Can't load ligo primitive config file world_editor_classes.xml");
199 // have ligo library register its own class types for its class factory
202 // setup the update systems
203 setUpdateTimeout(100);
209 CMirrors::init(cbTick
, NULL
, cbTickRelease
);
211 AISHEETS::CSheets::getInstance()->init();
213 // initialise the AI_SHARE library
214 AI_SHARE::init(&LigoConfig
);
216 // set the primitive context
217 NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig
= &LigoConfig
;
221 CEGSInterface::init();
222 CTimeInterface::init();
223 CCombatInterface::init();
224 CVisualPropertiesInterface::init();
225 CAIDSInterface::init();
227 // register the service up and service down callbacks
228 CMirrors::Mirror
.setServiceMirrorUpCallback("*", cbServiceMirrorUp
, 0);
229 CMirrors::Mirror
.setServiceDownCallback( "*", cbServiceDown
, 0);
230 // CUnifiedNetwork::getInstance()->setServiceDownCallback( "*", cbServiceDown, 0);
232 CConfigFile::CVar
*clientCreature
=IService::getInstance()->ConfigFile
.getVarPtr ("CreatureDebug");
235 CAIS::instance().setClientCreatureDebug(clientCreature
->asInt()!=0);
242 void CAIService::release()
247 void CAIService::tickRelease (void)
249 CWorldContainer::clear();
251 // release sub systems
252 CAIS::instance().release();
254 CAIDSInterface::release();
255 CVisualPropertiesInterface::release();
256 CCombatInterface::release();
257 CTimeInterface::release();
258 CEGSInterface::release();
260 CAISActions::release();
262 AISHEETS::CSheets::getInstance()->release();
263 CMessages::release();
267 CFamilyProfileFactory::instance().release();
269 CSingletonRegistry::getInstance()->release();
272 void dispatchEvents()
274 H_AUTO(dispatchEvents
);
275 while (!CCombatInterface::_events
.empty())
277 CAIEntityPhysical
*target
=CAIS::instance().getEntityPhysical(CCombatInterface::_events
.front()._targetRow
);
279 target
->processEvent( CCombatInterface::_events
.front() );
280 CCombatInterface::_events
.pop_front();
284 /*-----------------------------------------------------------------*\
286 \*-----------------------------------------------------------------*/
288 ///update called on each 'tick' message from tick service
292 // cleanup stat variables
293 // StatCSpawnBotFauna = 0;
294 // StatCSpawnBotNpc = 0;
296 // StatCAIContinent = 0;
297 // StatCSpawnGroupFauna = 0;
298 // StatCSpawnGroupNpc = 0;
299 // StatCSpawnGroupPet = 0;
300 // StatCAIInstance = 0;
301 // StatCMgrFauna = 0;
304 // StatCBotPlayer = 0;
305 // StatCPlayerManager = 0;
306 // StatCcontinent = 0;
308 // StatCCellZone = 0;
310 if ( CMirrors::mirrorIsReady() )
312 CAIS::instance().update();
314 CEGSInterface::update();
315 CTimeInterface::update();
316 CVisualPropertiesInterface::update();
323 H_AUTO(CSingletonRegistry_tickUpdate
)
324 CSingletonRegistry::getInstance()->tickUpdate();
330 //prototype for a global routine in commands.cpp
331 void UpdateWatches();
335 ///update called every coplete cycle of service loop
336 bool CAIService::update (void)
338 // NLMEMORY::CheckHeap(true);
341 // NLMEMORY::CheckHeap(true);
345 // We update a false perception (as if we force ticks, it meens we don't receive true one because we're off-line).
347 // We make a false tick.
352 CSingletonRegistry::getInstance()->serviceUpdate();
359 /*-----------------------------------------------------------------*\
361 \*-----------------------------------------------------------------*/
362 NLNET_SERVICE_MAIN (CAIService
, "AIS", "ai_service", 0, EmptyCallbackArray
, "", "")