1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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
;
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","")
49 StrToBool (verboseLog
, args
[0]);
51 nlinfo("verboseAIDSActionLogging is %s",verboseLog
?"ON":"OFF");
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
]);
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
]);
95 node
.Name
.clear(); // clearing the name makes the slot re-usable next compile
99 //----------------------------------------------------------------------------
101 //----------------------------------------------------------------------------
103 void CAIDSActions::openFile(const std::string
&fileName
)
105 LOG("Scanning file: %s",fileName
.c_str());
109 DefaultNode
.Child
.clear();
110 DefaultNode
.Data
.clear();
111 CurrentMgrDfnNodes
.clear();
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
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());
140 // if we've encountered a parse problem just count levels of indentation
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)
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
));
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
]);
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
);
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
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
229 void CAIDSActions::execute(uint64 action
,const std::vector
<CAIActions::CArg
> &args
)
231 // if we've encountered a parse problem don't execute...
237 // generate a string to describe the action
239 txt
+=toString("%-8.8s",&action
);
241 for (uint i
=0;i
<args
.size();++i
)
243 txt
+=args
[i
].toString();
244 if (i
<args
.size()-1) 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
;
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
));