Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / server / src / ai_data_service / aids_actions.cpp
blobface248fccb83f1ff08819eaf16018f88ac54486
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 //----------------------------------------------------------------------------
22 #include "nel/misc/command.h"
23 #include "nel/misc/debug.h"
24 #include "nel/misc/config_file.h"
25 #include "nel/misc/path.h"
26 #include "nel/net/service.h"
27 #include "aids_actions.h"
29 using namespace NLMISC;
30 using namespace NLNET;
31 using namespace std;
34 //----------------------------------------------------------------------------
35 // Stuff for debug message logging
36 //----------------------------------------------------------------------------
38 static bool verboseLog=false;
39 #define TAB toString("%*s",CurrentMgrDfnNodes.size()*4,"").c_str()
40 #define TAB1 toString("%*s",CurrentMgrDfnNodes.size()*4-4,"").c_str()
41 #define LOG if (!verboseLog) {} else nlinfo
43 NLMISC_COMMAND(verboseAIDSActionLog,"Turn on or off or check the state of verbose AIDSAction parser logging","")
45 if(args.size()>1)
46 return false;
48 if(args.size()==1)
49 StrToBool (verboseLog, args[0]);
51 nlinfo("verboseAIDSActionLogging is %s",verboseLog?"ON":"OFF");
52 return true;
56 //----------------------------------------------------------------------------
57 // Singleton data instantiation
58 //----------------------------------------------------------------------------
60 CAIDSActions *CAIDSActions::Instance=NULL;
61 uint CAIDSActions::CurrentManager=0;
64 //----------------------------------------------------------------------------
65 // Local utility functions and variables
66 //----------------------------------------------------------------------------
68 static uint BadParseDepth=0;
69 static CAIManager::SMgrDfnNode DefaultNode;
70 static std::vector<CAIManager::SMgrDfnNode *> CurrentMgrDfnNodes;
71 static bool FoundAIData=false;
72 static std::string FileName;
74 static void Prepare(CAIManager::SMgrDfnNode &node)
76 // recurse through children
77 for (uint i=0;i<node.Child.size();++i)
78 Prepare(*node.Child[i]);
80 // deal with self
81 node.Visited=false;
82 node.Data.clear();
85 static void Clean(CAIManager::SMgrDfnNode &node)
87 // recurse through children
88 for (uint i=0;i<node.Child.size();++i)
89 Clean(*node.Child[i]);
91 // deal with self
92 if (!node.Visited)
94 node.Child.clear();
95 node.Name.clear(); // clearing the name makes the slot re-usable next compile
99 //----------------------------------------------------------------------------
100 // Public methods
101 //----------------------------------------------------------------------------
103 void CAIDSActions::openFile(const std::string &fileName)
105 LOG("Scanning file: %s",fileName.c_str());
107 // setup local vars
108 BadParseDepth=0;
109 DefaultNode.Child.clear();
110 DefaultNode.Data.clear();
111 CurrentMgrDfnNodes.clear();
112 FoundAIData=false;
115 void CAIDSActions::closeFile(const std::string &fileName)
117 // if the primitive file didn't contain anything interesting then add it to the ignore list
118 if (!FoundAIData)
120 nlinfo("No manager found in primitive file: %s - adding to ignore list",fileName.c_str());
122 // lookup the ignore files in the config file and copy into a temp vector
123 CConfigFile::CVar *varPtr=IService::getInstance()->ConfigFile.getVarPtr(std::string("IgnorePrimitives"));
124 std::vector<std::string> ignoreFiles;
125 for (uint i=0;i<varPtr->size();++i)
126 ignoreFiles.push_back(CFile::getFilenameWithoutExtension(varPtr->asString(i)));
128 //append this file to the vector and pass it back to the config file manager for storage
129 ignoreFiles.push_back(NLMISC::CFile::getFilenameWithoutExtension(fileName));
130 varPtr->setAsString(ignoreFiles);
131 IService::getInstance()->ConfigFile.save();
135 void CAIDSActions::begin(const std::string &contextName)
137 LOG("%s{ // %s",TAB,contextName.c_str());
138 uint i;
140 // if we've encountered a parse problem just count levels of indentation
141 if (BadParseDepth)
143 ++BadParseDepth;
144 return;
147 // if the CurrentMgrDfnNodes vector is empty then we must be parsing a new manager
148 if (CurrentMgrDfnNodes.empty())
150 nlinfo("- Parsing: %s",contextName.c_str());
152 // update variables used in this source file (AIDS_ACTIONS.CPP)
153 FoundAIData=true;
154 CurrentMgrDfnNodes.push_back(&(CAIManager::getManagerById(CurrentManager)->MgrDfnRootNode));
155 CurrentMgrDfnNodes[0]->Name=contextName;
157 // reset the 'visited' flags for the manager's data tree
158 Prepare(*CurrentMgrDfnNodes[0]);
159 CurrentMgrDfnNodes[0]->Visited=true;
161 // copy the default dfn nodes to the current node and add a 'set_slot' action
162 CAIManager::SMgrDfnNode *curNode=CurrentMgrDfnNodes[CurrentMgrDfnNodes.size()-1];
163 for (uint i=0;i<DefaultNode.Data.size();++i)
164 curNode->Data.push_back(DefaultNode.Data[i]);
165 // add a set_slot action with value uint slot id = CurrentManager
166 std::vector <CAIActions::CArg> args;
167 args.push_back(CAIActions::CArg(CurrentManager));
168 curNode->Data.push_back(CAIManager::SMgrDfnElm(*(uint64*)"SET_SLOT",args));
170 else
172 CAIManager::SMgrDfnNode *curNode=CurrentMgrDfnNodes[CurrentMgrDfnNodes.size()-1];
174 // try to find a node with the name matching contextName
175 // if there are a number of nodes with the same name then this code should work ok as
176 // it uses the 'visited' flags to avoid multi-use of same node slot
177 CAIManager::SMgrDfnNode *node=NULL;
178 for (i=0;i<curNode->Child.size();++i)
179 if ((curNode->Child[i]->Name.empty() || curNode->Child[i]->Name==contextName) && !curNode->Child[i]->Visited)
181 node=(curNode->Child[i]);
182 break;
185 // if need be allocate a new data node
186 if (i==curNode->Child.size())
188 curNode->Child.push_back(new CAIManager::SMgrDfnNode(contextName));
189 node=curNode->Child[i];
192 // add a set_slot action with value uint slot id = i
193 std::vector <CAIActions::CArg> args;
194 args.push_back(CAIActions::CArg(i));
195 curNode->Child[i]->Data.push_back(CAIManager::SMgrDfnElm(*(uint64*)"SET_SLOT",args));
197 // update variables used in this source file (AIDS_ACTIONS.CPP)
198 CurrentMgrDfnNodes.push_back(node);
199 node->Visited=true;
203 void CAIDSActions::end(const std::string &contextName)
205 LOG("%s} // %s",TAB1,contextName.c_str());
207 // if we've encountered a parse problem just count levels of indentation
208 if (BadParseDepth)
210 --BadParseDepth;
211 return;
214 // make sure the name of the context that we're closing matches the name of the context that we opened
215 CAIManager::SMgrDfnNode *curNode=CurrentMgrDfnNodes[CurrentMgrDfnNodes.size()-1];
216 nlassert(contextName==curNode->Name);
218 // close this context
219 CurrentMgrDfnNodes.pop_back();
221 // if we've finished then do some housekeeping
222 if (CurrentMgrDfnNodes.empty())
224 // run back through tree stripping out unvisitted entries
225 Clean(*curNode);
229 void CAIDSActions::execute(uint64 action,const std::vector <CAIActions::CArg> &args)
231 // if we've encountered a parse problem don't execute...
232 if (BadParseDepth)
234 return;
237 // generate a string to describe the action
238 std::string txt;
239 txt+=toString("%-8.8s",&action);
240 txt+='(';
241 for (uint i=0;i<args.size();++i)
243 txt+=args[i].toString();
244 if (i<args.size()-1) txt+=", ";
246 txt+=')';
247 LOG("%s%s",TAB,txt.c_str());
249 CAIManager::SMgrDfnNode *curNode;
251 // if we havent yet opened our first context then store this data record in the default node
252 // otherwise store it in the node on the top of the CurrentMgrDfnNodes vector
253 if (CurrentMgrDfnNodes.empty())
254 curNode=&DefaultNode;
255 else
256 curNode=CurrentMgrDfnNodes[CurrentMgrDfnNodes.size()-1];
258 // add the data record to the top node on the CurrentMgrDfnNodes vector
259 curNode->Data.push_back(CAIManager::SMgrDfnElm(action,args));