// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program 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 Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . //=================================================================== #include "nel/misc/debug.h" #include "game_share/xml.h" #include "ai_manager.h" #include "ai_service.h" #include "ai_files.h" //=================================================================== //--------------------------------------------------- // INSTANTIATED CLASS: Public methods //------------- // a few read accessors (static properties) // the manager id (0..255) sint CAIManager::id() const { return int(this-_managers); } // the manager name .. ie the source file name minus extension const std::string &CAIManager::name() const { return _name; } // the CPU load rating of the manager for auto-load ballancing purposes uint CAIManager::weightCPU() const { return _weightCPU; } // the RAM load rating of the manager for auto-load ballancing purposes uint CAIManager::weightRAM() const { return _weightRAM; } //------------- // a few read accessors (state of the files on disk) // indicates whether newer source files than object files have been located bool CAIManager::needCompile() const { return _needCompile; } // indicate whether an object file has been located in the object directory bool CAIManager::objExists() const { return _objExists; } //------------- // a few read accessors (relating to assignment to & execution by an ai service) // has the manager been opened (it may still be waiting to be assigned) bool CAIManager::isOpen() const { return _isOpen; } // has the manager been assigned to a service bool CAIManager::isAssigned() const { return _isAssigned; } // is the manager up and running on the assigned service bool CAIManager::isUp() const { return _isUp; } // the id of the service to which the manager is assigned sint CAIManager::serviceId() const { return _service; } //------------- // a few basic actions (relating to disk files) const std::string &xmlDelimitedString(CxmlNode *xmlNode,const std::string &delimiter) { static const std::string emptyString; for (uint i=0;ichildCount();++i) { CxmlNode *child=xmlNode->child(i); if (child->type()==delimiter) if (child->childCount()==1) if (child->child(0)->type()=="") { return child->child(0)->txt(); } } return emptyString; } const std::string &getProp(CxmlNode *xmlNode,const std::string &propertyName) { static const std::string emptyString; for (uint i=0;ichildCount();++i) { CxmlNode *child=xmlNode->child(i); if (child->type()=="PROPERTY") { const std::string &name= xmlDelimitedString(child,std::string("NAME")); if (name==propertyName) return xmlDelimitedString(child,std::string("STRING")); } } return emptyString; } // compile the source files to generate new object files void CAIManager::compile() { std::string srcFile=CAIFiles::fullSrcFileName(id()); std::string objFile=CAIFiles::fullObjFileName(id()); nlinfo("Compile %s => %s",srcFile.c_str(),objFile.c_str()); // open and parse the xml file CxmlNode xmlfile; xmlfile.read(srcFile); // locate the mgr node in the file std::list nodes; nodes.push_back(&xmlfile); while (!nodes.empty()) { // pop the next node off the list CxmlNode *node=*nodes.begin(); nodes.pop_front(); // push our children so that they can be treated too for (uint i=0;ichildCount();++i) nodes.push_back(node->child(i)); // if this is a child node then we're in business so dump a few infos to the screen if (node->type()=="CHILD" && !getProp(node,std::string("AI_TYPE")).empty()) { nlinfo("child: AI_TYPE: %s NAME: %s",getProp(node,std::string("AI_TYPE")).c_str(),getProp(node,std::string("Name")).c_str()); } } } // delete the object files (but not the save files) void CAIManager::clean() { CAIFiles::clean(id()); } //------------- // a few basic actions (relating to assignment to & execution by an ai service) // open the manager on an unspecified service // (may be queued until a service is available) void CAIManager::open() { CAIService::openMgr(id()); } // assign manager to a specified service and begin execution void CAIManager::assign(sint serviceId) { // make sure that the manager isn't assigned to a service already if (isAssigned()) { nlwarning("Cannot assign manager %04d (%s) to service %d as already assigned to %d", id(), name(), serviceId, _service); return; } // flag me as assigned _isAssigned=true; _service=serviceId; // transfer control to the service's assignMgr() method CAIService *service=CAIService::getServiceById(serviceId); if (service!=NULL) service->assignMgr(id()); } // stop execution on the current service and assign to a new service void CAIManager::reassign(sint serviceId) { CAIService *service=CAIService::getServiceById(_service); if (service!=NULL) service->reassignMgr(id(),serviceId); } // stop execution of a manager void CAIManager::close() { // make sure that the manager isn't assigned to a service already if (!isAssigned()) { nlwarning("Cannot unassign manager %04d (%s) as it is already unassigned", id(), name()); return; } // if the service is running then transfer control to the service singleton's closeMgr() method if (isUp()) { CAIService::closeMgr(id()); return; } // flag me as unassigned _isAssigned=false; _isOpen=false; _service=-1; } //------------- // a few basic actions (miscelaneous) // display information about the state of the manager void CAIManager::display() const { if (isAssigned()) nlinfo("AI Manager %04d: %s: %s ON SERVICE %d (%s)", id(), _name.c_str(), isUp()? "UP AND RUNNING": /* else */ "ASSIGNED TO BUT NOT YET UP", _service, isOpen()? "auto-assigned": /* else */ "manualy assigned" ); else nlinfo("AI Manager %04d: %s: %s", id(), _name.c_str(), isOpen()? "OPEN - AWAITING ASSIGNMENT": !objExists()? "NOT OPEN - OBJECT FILE NOT FOUND": needCompile()? "NOT OPEN - OBJECT FILE OLDER THAN SOURCE": /* else */ "NOT OPEN - OBJECT FILE IS UP TO DATE" ); } //------------- // a few write accessors (miscelaneous) // set the name assigned to manager // if no name previously assigned then reset all manager properties // if a name already exists and does not match new name then do nohing and return false bool CAIManager::set(const std::string &name) { // if we already have a name associated with this slot then simply check that it matches the new name if (!_name.empty()) return (_name==name); _reset(); _name=name; return true; } // set the state of the needCompile flag void CAIManager::setNeedCompile(bool val) { _needCompile=val; } // set the state of the objFileExists flag void CAIManager::setObjFileExists(bool val) { _objExists=val; } // set the state of the isUp flag void CAIManager::setIsUp(bool val) { _isUp=val; } // set the state of the isOpen flag void CAIManager::setIsOpen(bool val) { _isOpen=val; } //--------------------------------------------------- // INSTANTIATED CLASS: Private methods // default constructor - may only be instantiated by the singleton CAIManager::CAIManager() { // manager id - make sure that the managers are all in the one static array // note that id is calaulated from the array address and the addess of 'this' nlassert(uint(id())=maxManagers()) { nlwarning("CAIManager::getManagerById(id): id %d not in range 0..%d",id,maxManagers()-1); return NULL; } return &(_managers[id]); } // get a pointer to the manager with given index (0..numManagers-1) CAIManager *CAIManager::getManagerByIdx(uint idx) { uint count=0; for (uint i=0;i=numManagers (%d)",idx,count); return NULL; } // get the handle for the manager of given name and optionally create a new // handle if none found - return -1 if none found or no free slots int CAIManager::nameToId(std::string name, bool assignNewIfNotFound) { // see if the name is a numeric version of an id uint val=atoi(name.c_str()); if (!name.empty() && name.size()<=4 && ( (val>0 && val