Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
CCmpTemplateManager.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2013 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. 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 General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "precompiled.h"
19 
21 #include "ICmpTemplateManager.h"
22 
24 
25 #include "lib/utf8.h"
26 #include "ps/CLogger.h"
27 #include "ps/Filesystem.h"
28 #include "ps/XML/RelaxNG.h"
29 #include "ps/XML/Xeromyces.h"
30 
31 static const wchar_t TEMPLATE_ROOT[] = L"simulation/templates/";
32 static const wchar_t ACTOR_ROOT[] = L"art/actors/";
33 
35 {
36 public:
37  static void ClassInit(CComponentManager& componentManager)
38  {
40  }
41 
42  DEFAULT_COMPONENT_ALLOCATOR(TemplateManager)
43 
44  static std::string GetSchema()
45  {
46  return "<a:component type='system'/><empty/>";
47  }
48 
49  virtual void Init(const CParamNode& UNUSED(paramNode))
50  {
51  m_DisableValidation = false;
52 
53  m_Validator.LoadGrammar(GetSimContext().GetComponentManager().GenerateSchema());
54  // TODO: handle errors loading the grammar here?
55  // TODO: support hotloading changes to the grammar
56  }
57 
58  virtual void Deinit()
59  {
60  }
61 
62  virtual void Serialize(ISerializer& serialize)
63  {
64  size_t count = 0;
65 
66  for (std::map<entity_id_t, std::string>::const_iterator it = m_LatestTemplates.begin(); it != m_LatestTemplates.end(); ++it)
67  {
68  if (ENTITY_IS_LOCAL(it->first))
69  continue;
70  ++count;
71  }
72  serialize.NumberU32_Unbounded("num entities", (u32)count);
73 
74  for (std::map<entity_id_t, std::string>::const_iterator it = m_LatestTemplates.begin(); it != m_LatestTemplates.end(); ++it)
75  {
76  if (ENTITY_IS_LOCAL(it->first))
77  continue;
78  serialize.NumberU32_Unbounded("id", it->first);
79  serialize.StringASCII("template", it->second, 0, 256);
80  }
81  // TODO: maybe we should do some kind of interning thing instead of printing so many strings?
82 
83  // TODO: will need to serialize techs too, because we need to be giving out
84  // template data before other components (like the tech components) have been deserialized
85  }
86 
87  virtual void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize)
88  {
89  Init(paramNode);
90 
91  u32 numEntities;
92  deserialize.NumberU32_Unbounded("num entities", numEntities);
93  for (u32 i = 0; i < numEntities; ++i)
94  {
95  entity_id_t ent;
96  std::string templateName;
97  deserialize.NumberU32_Unbounded("id", ent);
98  deserialize.StringASCII("template", templateName, 0, 256);
99  m_LatestTemplates[ent] = templateName;
100  }
101  }
102 
103  virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
104  {
105  switch (msg.GetType())
106  {
107  case MT_Destroy:
108  {
109  const CMessageDestroy& msgData = static_cast<const CMessageDestroy&> (msg);
110 
111  // Clean up m_LatestTemplates so it doesn't record any data for destroyed entities
112  m_LatestTemplates.erase(msgData.entity);
113 
114  break;
115  }
116  }
117  }
118 
119  virtual void DisableValidation()
120  {
121  m_DisableValidation = true;
122  }
123 
124  virtual const CParamNode* LoadTemplate(entity_id_t ent, const std::string& templateName, int playerID);
125 
126  virtual const CParamNode* GetTemplate(std::string templateName);
127 
128  virtual const CParamNode* GetTemplateWithoutValidation(std::string templateName);
129 
130  virtual const CParamNode* LoadLatestTemplate(entity_id_t ent);
131 
132  virtual std::string GetCurrentTemplateName(entity_id_t ent);
133 
134  virtual std::vector<std::string> FindAllTemplates(bool includeActors);
135 
136  virtual std::vector<entity_id_t> GetEntitiesUsingTemplate(std::string templateName);
137 
138 private:
139  // Entity template XML validator
141 
142  // Disable validation, for test cases
144 
145  // Map from template name (XML filename or special |-separated string) to the most recently
146  // loaded non-broken template data. This includes files that will fail schema validation.
147  // (Failed loads won't remove existing entries under the same name, so we behave more nicely
148  // when hotloading broken files)
149  std::map<std::string, CParamNode> m_TemplateFileData;
150 
151  // Map from template name to schema validation status.
152  // (Some files, e.g. inherited parent templates, may not be valid themselves but we still need to load
153  // them and use them; we only reject invalid templates that were requested directly by GetTemplate/etc)
154  std::map<std::string, bool> m_TemplateSchemaValidity;
155 
156  // Remember the template used by each entity, so we can return them
157  // again for deserialization.
158  // TODO: should store player ID etc.
159  std::map<entity_id_t, std::string> m_LatestTemplates;
160 
161  // (Re)loads the given template, regardless of whether it exists already,
162  // and saves into m_TemplateFileData. Also loads any parents that are not yet
163  // loaded. Returns false on error.
164  // @param templateName XML filename to load (not a |-separated string)
165  bool LoadTemplateFile(const std::string& templateName, int depth);
166 
167  // Constructs a standard static-decorative-object template for the given actor
168  void ConstructTemplateActor(const std::string& actorName, CParamNode& out);
169 
170  // Copy the non-interactive components of an entity template (position, actor, etc) into
171  // a new entity template
172  void CopyPreviewSubset(CParamNode& out, const CParamNode& in, bool corpse);
173 
174  // Copy the components of an entity necessary for a construction foundation
175  // (position, actor, armour, health, etc) into a new entity template
176  void CopyFoundationSubset(CParamNode& out, const CParamNode& in);
177 
178  // Copy the components of an entity necessary for a non-foundation construction entity
179  // into a new entity template
181 
182  // Copy the components of an entity necessary for a gatherable resource
183  // into a new entity template
184  void CopyResourceSubset(CParamNode& out, const CParamNode& in);
185 };
186 
187 REGISTER_COMPONENT_TYPE(TemplateManager)
188 
189 const CParamNode* CCmpTemplateManager::LoadTemplate(entity_id_t ent, const std::string& templateName, int UNUSED(playerID))
190 {
191  m_LatestTemplates[ent] = templateName;
192 
193  const CParamNode* templateRoot = GetTemplate(templateName);
194  if (!templateRoot)
195  return NULL;
196 
197  // TODO: Eventually we need to support techs in here, and return a different template per playerID
198 
199  return templateRoot;
200 }
201 
202 const CParamNode* CCmpTemplateManager::GetTemplate(std::string templateName)
203 {
204  // Load the template if necessary
205  if (!LoadTemplateFile(templateName, 0))
206  {
207  LOGERROR(L"Failed to load entity template '%hs'", templateName.c_str());
208  return NULL;
209  }
210 
211  if (!m_DisableValidation)
212  {
213  // Compute validity, if it's not computed before
214  if (m_TemplateSchemaValidity.find(templateName) == m_TemplateSchemaValidity.end())
215  {
216  m_TemplateSchemaValidity[templateName] = m_Validator.Validate(wstring_from_utf8(templateName), m_TemplateFileData[templateName].ToXML());
217 
218  // Show error on the first failure to validate the template
219  if (!m_TemplateSchemaValidity[templateName])
220  LOGERROR(L"Failed to validate entity template '%hs'", templateName.c_str());
221  }
222  // Refuse to return invalid templates
223  if (!m_TemplateSchemaValidity[templateName])
224  return NULL;
225  }
226 
227  const CParamNode& templateRoot = m_TemplateFileData[templateName].GetChild("Entity");
228  if (!templateRoot.IsOk())
229  {
230  // The validator should never let this happen
231  LOGERROR(L"Invalid root element in entity template '%hs'", templateName.c_str());
232  return NULL;
233  }
234 
235  return &templateRoot;
236 }
237 
239 {
240  // Load the template if necessary
241  if (!LoadTemplateFile(templateName, 0))
242  {
243  LOGERROR(L"Failed to load entity template '%hs'", templateName.c_str());
244  return NULL;
245  }
246 
247  const CParamNode& templateRoot = m_TemplateFileData[templateName].GetChild("Entity");
248  if (!templateRoot.IsOk())
249  return NULL;
250 
251  return &templateRoot;
252 }
253 
255 {
256  std::map<entity_id_t, std::string>::const_iterator it = m_LatestTemplates.find(ent);
257  if (it == m_LatestTemplates.end())
258  return NULL;
259  return LoadTemplate(ent, it->second, -1);
260 }
261 
263 {
264  std::map<entity_id_t, std::string>::const_iterator it = m_LatestTemplates.find(ent);
265  if (it == m_LatestTemplates.end())
266  return "";
267  return it->second;
268 }
269 
270 bool CCmpTemplateManager::LoadTemplateFile(const std::string& templateName, int depth)
271 {
272  // If this file was already loaded, we don't need to do anything
273  if (m_TemplateFileData.find(templateName) != m_TemplateFileData.end())
274  return true;
275 
276  // Handle infinite loops more gracefully than running out of stack space and crashing
277  if (depth > 100)
278  {
279  LOGERROR(L"Probable infinite inheritance loop in entity template '%hs'", templateName.c_str());
280  return false;
281  }
282 
283  // Handle special case "actor|foo"
284  if (templateName.find("actor|") == 0)
285  {
286  ConstructTemplateActor(templateName.substr(6), m_TemplateFileData[templateName]);
287  return true;
288  }
289 
290  // Handle special case "preview|foo"
291  if (templateName.find("preview|") == 0)
292  {
293  // Load the base entity template, if it wasn't already loaded
294  std::string baseName = templateName.substr(8);
295  if (!LoadTemplateFile(baseName, depth+1))
296  {
297  LOGERROR(L"Failed to load entity template '%hs'", baseName.c_str());
298  return false;
299  }
300  // Copy a subset to the requested template
301  CopyPreviewSubset(m_TemplateFileData[templateName], m_TemplateFileData[baseName], false);
302  return true;
303  }
304 
305  // Handle special case "corpse|foo"
306  if (templateName.find("corpse|") == 0)
307  {
308  // Load the base entity template, if it wasn't already loaded
309  std::string baseName = templateName.substr(7);
310  if (!LoadTemplateFile(baseName, depth+1))
311  {
312  LOGERROR(L"Failed to load entity template '%hs'", baseName.c_str());
313  return false;
314  }
315  // Copy a subset to the requested template
316  CopyPreviewSubset(m_TemplateFileData[templateName], m_TemplateFileData[baseName], true);
317  return true;
318  }
319 
320  // Handle special case "foundation|foo"
321  if (templateName.find("foundation|") == 0)
322  {
323  // Load the base entity template, if it wasn't already loaded
324  std::string baseName = templateName.substr(11);
325  if (!LoadTemplateFile(baseName, depth+1))
326  {
327  LOGERROR(L"Failed to load entity template '%hs'", baseName.c_str());
328  return false;
329  }
330  // Copy a subset to the requested template
332  return true;
333  }
334 
335  // Handle special case "construction|foo"
336  if (templateName.find("construction|") == 0)
337  {
338  // Load the base entity template, if it wasn't already loaded
339  std::string baseName = templateName.substr(13);
340  if (!LoadTemplateFile(baseName, depth+1))
341  {
342  LOGERROR(L"Failed to load entity template '%hs'", baseName.c_str());
343  return false;
344  }
345  // Copy a subset to the requested template
347  return true;
348  }
349 
350  // Handle special case "resource|foo"
351  if (templateName.find("resource|") == 0)
352  {
353  // Load the base entity template, if it wasn't already loaded
354  std::string baseName = templateName.substr(9);
355  if (!LoadTemplateFile(baseName, depth+1))
356  {
357  LOGERROR(L"Failed to load entity template '%hs'", baseName.c_str());
358  return false;
359  }
360  // Copy a subset to the requested template
361  CopyResourceSubset(m_TemplateFileData[templateName], m_TemplateFileData[baseName]);
362  return true;
363  }
364 
365  // Normal case: templateName is an XML file:
366 
367  VfsPath path = VfsPath(TEMPLATE_ROOT) / wstring_from_utf8(templateName + ".xml");
368  CXeromyces xero;
369  PSRETURN ok = xero.Load(g_VFS, path);
370  if (ok != PSRETURN_OK)
371  return false; // (Xeromyces already logged an error with the full filename)
372 
373  int attr_parent = xero.GetAttributeID("parent");
374  CStr parentName = xero.GetRoot().GetAttributes().GetNamedItem(attr_parent);
375  if (!parentName.empty())
376  {
377  // To prevent needless complexity in template design, we don't allow |-separated strings as parents
378  if (parentName.find('|') != parentName.npos)
379  {
380  LOGERROR(L"Invalid parent '%hs' in entity template '%hs'", parentName.c_str(), templateName.c_str());
381  return false;
382  }
383 
384  // Ensure the parent is loaded
385  if (!LoadTemplateFile(parentName, depth+1))
386  {
387  LOGERROR(L"Failed to load parent '%hs' of entity template '%hs'", parentName.c_str(), templateName.c_str());
388  return false;
389  }
390 
391  CParamNode& parentData = m_TemplateFileData[parentName];
392 
393  // Initialise this template with its parent
394  m_TemplateFileData[templateName] = parentData;
395  }
396 
397  // Load the new file into the template data (overriding parent values)
398  CParamNode::LoadXML(m_TemplateFileData[templateName], xero, wstring_from_utf8(templateName).c_str());
399 
400  return true;
401 }
402 
403 void CCmpTemplateManager::ConstructTemplateActor(const std::string& actorName, CParamNode& out)
404 {
405  // Load the base actor template if necessary
406  const char* templateName = "special/actor";
407  if (!LoadTemplateFile(templateName, 0))
408  {
409  LOGERROR(L"Failed to load entity template '%hs'", templateName);
410  return;
411  }
412 
413  // Copy the actor template
414  out = m_TemplateFileData[templateName];
415 
416  // Initialise the actor's name and make it an Atlas selectable entity.
417  std::wstring actorNameW = wstring_from_utf8(actorName);
418  std::string name = utf8_from_wstring(CParamNode::EscapeXMLString(actorNameW));
419  std::string xml = "<Entity>"
420  "<VisualActor><Actor>" + name + "</Actor></VisualActor>"
421  // arbitrary-sized Footprint definition to make actors' selection outlines show up in Atlas
422  "<Footprint><Circle radius='2.0'/><Height>1.0</Height></Footprint>"
423  "<Selectable>"
424  "<EditorOnly/>"
425  "<Overlay><Texture><MainTexture>actor.png</MainTexture><MainTextureMask>actor_mask.png</MainTextureMask></Texture></Overlay>"
426  "</Selectable>"
427  "</Entity>";
428 
429  CParamNode::LoadXMLString(out, xml.c_str(), actorNameW.c_str());
430 }
431 
432 static Status AddToTemplates(const VfsPath& pathname, const CFileInfo& UNUSED(fileInfo), const uintptr_t cbData)
433 {
434  std::vector<std::string>& templates = *(std::vector<std::string>*)cbData;
435 
436  // Strip the .xml extension
437  VfsPath pathstem = pathname.ChangeExtension(L"");
438  // Strip the root from the path
439  std::wstring name = pathstem.string().substr(ARRAY_SIZE(TEMPLATE_ROOT)-1);
440 
441  // We want to ignore template_*.xml templates, since they should never be built in the editor
442  if (name.substr(0, 9) == L"template_")
443  return INFO::OK;
444 
445  templates.push_back(std::string(name.begin(), name.end()));
446  return INFO::OK;
447 }
448 
449 static Status AddActorToTemplates(const VfsPath& pathname, const CFileInfo& UNUSED(fileInfo), const uintptr_t cbData)
450 {
451  std::vector<std::string>& templates = *(std::vector<std::string>*)cbData;
452 
453  // Strip the root from the path
454  std::wstring name = pathname.string().substr(ARRAY_SIZE(ACTOR_ROOT)-1);
455 
456  templates.push_back("actor|" + std::string(name.begin(), name.end()));
457  return INFO::OK;
458 }
459 
460 std::vector<std::string> CCmpTemplateManager::FindAllTemplates(bool includeActors)
461 {
462  // TODO: eventually this should probably read all the template files and look for flags to
463  // determine which should be displayed in the editor (and in what categories etc); for now we'll
464  // just return all the files
465 
466  std::vector<std::string> templates;
467 
468  Status ok;
469 
470  // Find all the normal entity templates first
471  ok = vfs::ForEachFile(g_VFS, TEMPLATE_ROOT, AddToTemplates, (uintptr_t)&templates, L"*.xml", vfs::DIR_RECURSIVE);
472  WARN_IF_ERR(ok);
473 
474  if (includeActors)
475  {
476  // Add all the actors too
477  ok = vfs::ForEachFile(g_VFS, ACTOR_ROOT, AddActorToTemplates, (uintptr_t)&templates, L"*.xml", vfs::DIR_RECURSIVE);
478  WARN_IF_ERR(ok);
479  }
480 
481  return templates;
482 }
483 
484 /**
485  * Get the list of entities using the specified template
486  */
487 std::vector<entity_id_t> CCmpTemplateManager::GetEntitiesUsingTemplate(std::string templateName)
488 {
489  std::vector<entity_id_t> entities;
490  for (std::map<entity_id_t, std::string>::const_iterator it = m_LatestTemplates.begin(); it != m_LatestTemplates.end(); ++it)
491  {
492  if(it->second == templateName)
493  entities.push_back(it->first);
494  }
495  return entities;
496 }
497 
499 {
500  // We only want to include components which are necessary (for the visual previewing of an entity)
501  // and safe (i.e. won't do anything that affects the synchronised simulation state), so additions
502  // to this list should be carefully considered
503  std::set<std::string> permittedComponentTypes;
504  permittedComponentTypes.insert("Identity");
505  permittedComponentTypes.insert("Ownership");
506  permittedComponentTypes.insert("Position");
507  permittedComponentTypes.insert("VisualActor");
508  permittedComponentTypes.insert("Footprint");
509  permittedComponentTypes.insert("Obstruction");
510  permittedComponentTypes.insert("Decay");
511  permittedComponentTypes.insert("BuildRestrictions");
512 
513  // Need these for the Actor Viewer:
514  permittedComponentTypes.insert("Attack");
515  permittedComponentTypes.insert("UnitMotion");
516  permittedComponentTypes.insert("Sound");
517 
518  // (This set could be initialised once and reused, but it's not worth the effort)
519 
520  CParamNode::LoadXMLString(out, "<Entity/>");
521  out.CopyFilteredChildrenOfChild(in, "Entity", permittedComponentTypes);
522 
523  // Disable the Obstruction component (if there is one) so it doesn't affect pathfinding
524  // (but can still be used for testing this entity for collisions against others)
525  if (out.GetChild("Entity").GetChild("Obstruction").IsOk())
526  CParamNode::LoadXMLString(out, "<Entity><Obstruction><Active>false</Active></Obstruction></Entity>");
527 
528  if (!corpse)
529  {
530  // Previews should not cast shadows
531  if (out.GetChild("Entity").GetChild("VisualActor").IsOk())
532  CParamNode::LoadXMLString(out, "<Entity><VisualActor><DisableShadows/></VisualActor></Entity>");
533 
534  // Previews should always be visible in fog-of-war/etc
535  CParamNode::LoadXMLString(out, "<Entity><Vision><Range>0</Range><RetainInFog>false</RetainInFog><AlwaysVisible>true</AlwaysVisible></Vision></Entity>");
536  }
537 
538  if (corpse)
539  {
540  // Corpses should include decay components and un-inactivate them
541  if (out.GetChild("Entity").GetChild("Decay").IsOk())
542  CParamNode::LoadXMLString(out, "<Entity><Decay><Inactive disable=''/></Decay></Entity>");
543 
544  // Corpses shouldn't display silhouettes (especially since they're often half underground)
545  if (out.GetChild("Entity").GetChild("VisualActor").IsOk())
546  CParamNode::LoadXMLString(out, "<Entity><VisualActor><SilhouetteDisplay>false</SilhouetteDisplay></VisualActor></Entity>");
547  }
548 }
549 
551 {
552  // TODO: this is all kind of yucky and hard-coded; it'd be nice to have a more generic
553  // extensible scriptable way to define these subsets
554 
555  std::set<std::string> permittedComponentTypes;
556  permittedComponentTypes.insert("Ownership");
557  permittedComponentTypes.insert("Position");
558  permittedComponentTypes.insert("VisualActor");
559  permittedComponentTypes.insert("Identity");
560  permittedComponentTypes.insert("BuildRestrictions");
561  permittedComponentTypes.insert("Obstruction");
562  permittedComponentTypes.insert("Selectable");
563  permittedComponentTypes.insert("Footprint");
564  permittedComponentTypes.insert("Armour");
565  permittedComponentTypes.insert("Health");
566  permittedComponentTypes.insert("StatusBars");
567  permittedComponentTypes.insert("OverlayRenderer");
568  permittedComponentTypes.insert("Decay");
569  permittedComponentTypes.insert("Cost");
570  permittedComponentTypes.insert("Sound");
571  permittedComponentTypes.insert("Vision");
572  permittedComponentTypes.insert("AIProxy");
573  permittedComponentTypes.insert("RallyPoint");
574  permittedComponentTypes.insert("RallyPointRenderer");
575 
576  CParamNode::LoadXMLString(out, "<Entity/>");
577  out.CopyFilteredChildrenOfChild(in, "Entity", permittedComponentTypes);
578 
579  // Switch the actor to foundation mode
580  CParamNode::LoadXMLString(out, "<Entity><VisualActor><Foundation/></VisualActor></Entity>");
581 
582  // Add the Foundation component, to deal with the construction process
583  CParamNode::LoadXMLString(out, "<Entity><Foundation/></Entity>");
584 
585  // Initialise health to 1
586  CParamNode::LoadXMLString(out, "<Entity><Health><Initial>1</Initial></Health></Entity>");
587 
588  // Foundations shouldn't initially block unit movement
589  if (out.GetChild("Entity").GetChild("Obstruction").IsOk())
590  CParamNode::LoadXMLString(out, "<Entity><Obstruction><DisableBlockMovement>true</DisableBlockMovement><DisableBlockPathfinding>true</DisableBlockPathfinding></Obstruction></Entity>");
591 
592  // Don't provide population bonuses yet (but still do take up population cost)
593  if (out.GetChild("Entity").GetChild("Cost").IsOk())
594  CParamNode::LoadXMLString(out, "<Entity><Cost><PopulationBonus>0</PopulationBonus></Cost></Entity>");
595 
596  // Foundations should be visible themselves in fog-of-war if their base template is,
597  // but shouldn't have any vision range
598  if (out.GetChild("Entity").GetChild("Vision").IsOk())
599  CParamNode::LoadXMLString(out, "<Entity><Vision><Range>0</Range></Vision></Entity>");
600 }
601 
603 {
604  // Currently used for buildings rising during construction
605  // Mostly serves to filter out components like Vision, UnitAI, etc.
606  std::set<std::string> permittedComponentTypes;
607  permittedComponentTypes.insert("Footprint");
608  permittedComponentTypes.insert("Ownership");
609  permittedComponentTypes.insert("Position");
610  permittedComponentTypes.insert("VisualActor");
611 
612  CParamNode::LoadXMLString(out, "<Entity/>");
613  out.CopyFilteredChildrenOfChild(in, "Entity", permittedComponentTypes);
614 }
615 
616 
618 {
619  // Currently used for animals which die and leave a gatherable corpse.
620  // Mostly serves to filter out components like Vision, UnitAI, etc.
621  std::set<std::string> permittedComponentTypes;
622  permittedComponentTypes.insert("Ownership");
623  permittedComponentTypes.insert("Position");
624  permittedComponentTypes.insert("VisualActor");
625  permittedComponentTypes.insert("Identity");
626  permittedComponentTypes.insert("Obstruction");
627  permittedComponentTypes.insert("Minimap");
628  permittedComponentTypes.insert("ResourceSupply");
629  permittedComponentTypes.insert("Selectable");
630  permittedComponentTypes.insert("Footprint");
631  permittedComponentTypes.insert("StatusBars");
632  permittedComponentTypes.insert("OverlayRenderer");
633  permittedComponentTypes.insert("Sound");
634  permittedComponentTypes.insert("AIProxy");
635 
636  CParamNode::LoadXMLString(out, "<Entity/>");
637  out.CopyFilteredChildrenOfChild(in, "Entity", permittedComponentTypes);
638 }
An entity initialisation parameter node.
Definition: ParamNode.h:112
virtual void StringASCII(const char *name, std::string &out, uint32_t minlength, uint32_t maxlength)
static void ClassInit(CComponentManager &componentManager)
#define REGISTER_COMPONENT_TYPE(cname)
Definition: Component.h:30
RelaxNGValidator m_Validator
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
#define WARN_IF_ERR(expression)
Definition: status.h:265
Path VfsPath
VFS path of the form &quot;(dir/)*file?&quot;.
Definition: vfs_path.h:40
entity_id_t entity
Definition: MessageTypes.h:221
static std::wstring EscapeXMLString(const std::wstring &str)
Escapes a string so that it is well-formed XML content/attribute text.
Definition: ParamNode.cpp:249
PSRETURN Load(const PIVFS &vfs, const VfsPath &filename)
Load from an XML file (with invisible XMB caching).
Definition: Xeromyces.cpp:65
const Status OK
Definition: status.h:386
#define LOGERROR
Definition: CLogger.h:35
const PSRETURN PSRETURN_OK
Definition: Errors.h:103
#define ENTITY_IS_LOCAL(id)
Definition: Entity.h:60
virtual std::vector< std::string > FindAllTemplates(bool includeActors)
Returns a list of strings that could be validly passed as templateName to LoadTemplate.
bool IsOk() const
Returns true if this is a valid CParamNode, false if it represents a non-existent node...
Definition: ParamNode.cpp:193
static std::string GetSchema()
std::string utf8_from_wstring(const std::wstring &src, Status *err)
opposite of wstring_from_utf8
Definition: utf8.cpp:208
void CopyConstructionSubset(CParamNode &out, const CParamNode &in)
Serialization interface; see serialization overview.
Definition: ISerializer.h:120
void CopyFoundationSubset(CParamNode &out, const CParamNode &in)
static void out(const wchar_t *fmt,...)
Definition: wdbg_sym.cpp:419
virtual const CParamNode * LoadTemplate(entity_id_t ent, const std::string &templateName, int playerID)
Loads the template XML file identified by &#39;templateName&#39; (including inheritance from parent XML files...
XMBAttributeList GetAttributes() const
Definition: XeroXMB.cpp:185
void CopyPreviewSubset(CParamNode &out, const CParamNode &in, bool corpse)
virtual void NumberU32_Unbounded(const char *name, uint32_t &out)
tuple xml
Definition: tests.py:119
#define ARRAY_SIZE(name)
static void LoadXML(CParamNode &ret, const XMBFile &file, const wchar_t *sourceIdentifier=NULL)
Loads the XML data specified by file into the node ret.
Definition: ParamNode.cpp:47
virtual int GetType() const =0
virtual void Deserialize(const CParamNode &paramNode, IDeserializer &deserialize)
const CParamNode & GetChild(const char *name) const
Returns the (unique) child node with the given name, or a node with IsOk() == false if there is none...
Definition: ParamNode.cpp:185
void StringASCII(const char *name, const std::string &value, uint32_t minlength, uint32_t maxlength)
Serialize an ASCII string.
Definition: ISerializer.cpp:70
u32 PSRETURN
Definition: Errors.h:75
std::map< std::string, bool > m_TemplateSchemaValidity
Definition: path.h:75
This is sent immediately before a destroyed entity is flushed and really destroyed.
Definition: MessageTypes.h:211
static PSRETURN LoadXMLString(CParamNode &ret, const char *xml, const wchar_t *sourceIdentifier=NULL)
See LoadXML, but parses the XML string xml.
Definition: ParamNode.cpp:62
const String & string() const
Definition: path.h:123
virtual void DisableValidation()
Permanently disable XML validation (intended solely for test cases).
static Status AddToTemplates(const VfsPath &pathname, const CFileInfo &fileInfo, const uintptr_t cbData)
bool LoadTemplateFile(const std::string &templateName, int depth)
static const wchar_t TEMPLATE_ROOT[]
virtual std::vector< entity_id_t > GetEntitiesUsingTemplate(std::string templateName)
Get the list of entities using the specified template.
#define DEFAULT_COMPONENT_ALLOCATOR(cname)
Definition: Component.h:44
i64 Status
Error handling system.
Definition: status.h:171
const CSimContext & GetSimContext() const
Definition: IComponent.h:52
CStr8 GetNamedItem(const int AttributeName) const
Definition: XeroXMB.cpp:259
void SubscribeGloballyToMessageType(MessageTypeId mtid)
Subscribe the current component type to all messages of the given message type.
bool Validate(const std::wstring &filename, const std::wstring &document)
Definition: RelaxNG.cpp:98
void NumberU32_Unbounded(const char *name, uint32_t value)
Serialize a number.
Definition: ISerializer.h:171
virtual void Init(const CParamNode &paramNode)
std::wstring wstring_from_utf8(const std::string &src, Status *err)
convert UTF-8 to a wide string (UTF-16 or UCS-4, depending on the platform&#39;s wchar_t).
Definition: utf8.cpp:225
XMBElement GetRoot() const
Definition: XeroXMB.cpp:84
#define u32
Definition: types.h:41
Path ChangeExtension(Path extension) const
Definition: path.h:185
Template manager: Handles the loading of entity template files for the initialisation and deserializa...
Status ForEachFile(const PIVFS &fs, const VfsPath &startPath, FileCallback cb, uintptr_t cbData, const wchar_t *pattern, size_t flags)
call back for each file in a directory tree
Definition: vfs_util.cpp:58
void ConstructTemplateActor(const std::string &actorName, CParamNode &out)
void CopyResourceSubset(CParamNode &out, const CParamNode &in)
virtual void Serialize(ISerializer &serialize)
bool LoadGrammar(const std::string &grammar)
Definition: RelaxNG.cpp:71
void CopyFilteredChildrenOfChild(const CParamNode &src, const char *name, const std::set< std::string > &permitted)
Finds the childs named name from src and from this, and copies the source child&#39;s children which are ...
Definition: ParamNode.cpp:170
int GetAttributeID(const char *Name) const
Definition: XeroXMB.cpp:124
virtual std::string GetCurrentTemplateName(entity_id_t ent)
Returns the name of the template most recently specified for the entity &#39;ent&#39;.
virtual const CParamNode * LoadLatestTemplate(entity_id_t ent)
Returns the template most recently specified for the entity &#39;ent&#39;.
std::map< entity_id_t, std::string > m_LatestTemplates
PIVFS g_VFS
Definition: Filesystem.cpp:30
static Status AddActorToTemplates(const VfsPath &pathname, const CFileInfo &fileInfo, const uintptr_t cbData)
u32 entity_id_t
Entity ID type.
Definition: Entity.h:24
virtual const CParamNode * GetTemplate(std::string templateName)
Loads the template XML file identified by &#39;templateName&#39; (including inheritance from parent XML files...
virtual const CParamNode * GetTemplateWithoutValidation(std::string templateName)
Like GetTemplate, except without doing the XML validation (so it&#39;s faster but may return invalid temp...
std::map< std::string, CParamNode > m_TemplateFileData
virtual void HandleMessage(const CMessage &msg, bool global)
static const wchar_t ACTOR_ROOT[]
Deserialization interface; see serialization overview.
Definition: IDeserializer.h:34