Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MapReader.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 
20 #include "MapReader.h"
21 
22 #include "graphics/Camera.h"
23 #include "graphics/CinemaTrack.h"
24 #include "graphics/Entity.h"
25 #include "graphics/GameView.h"
26 #include "graphics/MapGenerator.h"
27 #include "graphics/Patch.h"
28 #include "graphics/Terrain.h"
31 #include "lib/timer.h"
33 #include "maths/MathUtil.h"
34 #include "ps/CLogger.h"
35 #include "ps/Loader.h"
36 #include "ps/LoaderThunks.h"
37 #include "ps/World.h"
38 #include "ps/XML/Xeromyces.h"
40 #include "renderer/SkyManager.h"
41 #include "renderer/WaterManager.h"
51 
52 #include <boost/algorithm/string/predicate.hpp>
53 
54 
56  : xml_reader(0), m_PatchesPerSide(0), m_MapGen(0)
57 {
58  cur_terrain_tex = 0; // important - resets generator state
59 
60  // Maps that don't override the default probably want the old lighting model
61  //m_LightEnv.SetLightingModel("old");
62  //pPostproc->SetPostEffect(L"default");
63 
64 }
65 
66 // LoadMap: try to load the map from given file; reinitialise the scene to new data if successful
67 void CMapReader::LoadMap(const VfsPath& pathname, const CScriptValRooted& settings, CTerrain *pTerrain_,
68  WaterManager* pWaterMan_, SkyManager* pSkyMan_,
69  CLightEnv *pLightEnv_, CGameView *pGameView_, CCinemaManager* pCinema_, CTriggerManager* pTrigMan_, CPostprocManager* pPostproc_,
70  CSimulation2 *pSimulation2_, const CSimContext* pSimContext_, int playerID_, bool skipEntities)
71 {
72  // latch parameters (held until DelayedLoadFinished)
73  pTerrain = pTerrain_;
74  pLightEnv = pLightEnv_;
75  pGameView = pGameView_;
76  pWaterMan = pWaterMan_;
77  pSkyMan = pSkyMan_;
78  pCinema = pCinema_;
79  pTrigMan = pTrigMan_;
80  pPostproc = pPostproc_;
81  pSimulation2 = pSimulation2_;
82  pSimContext = pSimContext_;
83  m_PlayerID = playerID_;
84  m_SkipEntities = skipEntities;
86  m_ScriptSettings = settings;
87 
88  filename_xml = pathname.ChangeExtension(L".xml");
89 
90  // In some cases (particularly tests) we don't want to bother storing a large
91  // mostly-empty .pmp file, so we let the XML file specify basic terrain instead.
92  // If there's an .xml file and no .pmp, then we're probably in this XML-only mode
93  only_xml = false;
94  if (!VfsFileExists(pathname) && VfsFileExists(filename_xml))
95  {
96  only_xml = true;
97  }
98 
99  file_format_version = CMapIO::FILE_VERSION; // default if there's no .pmp
100 
101  if (!only_xml)
102  {
103  // [25ms]
104  unpacker.Read(pathname, "PSMP");
106  }
107 
108  // check oldest supported version
111 
112  // delete all existing entities
113  if (pSimulation2)
115 
116  // reset post effects
117  if (pPostproc)
118  pPostproc->SetPostEffect(L"default");
119 
120  // load map or script settings script
121  if (settings.undefined())
122  RegMemFun(this, &CMapReader::LoadScriptSettings, L"CMapReader::LoadScriptSettings", 50);
123  else
124  RegMemFun(this, &CMapReader::LoadRMSettings, L"CMapReader::LoadRMSettings", 50);
125 
126  // load player settings script (must be done before reading map)
127  RegMemFun(this, &CMapReader::LoadPlayerSettings, L"CMapReader::LoadPlayerSettings", 50);
128 
129  // unpack the data
130  if (!only_xml)
131  RegMemFun(this, &CMapReader::UnpackMap, L"CMapReader::UnpackMap", 1200);
132 
133  // read the corresponding XML file
134  RegMemFun(this, &CMapReader::ReadXML, L"CMapReader::ReadXML", 5800);
135 
136  // apply data to the world
137  RegMemFun(this, &CMapReader::ApplyData, L"CMapReader::ApplyData", 5);
138 
139  // load map settings script (must be done after reading map)
140  RegMemFun(this, &CMapReader::LoadMapSettings, L"CMapReader::LoadMapSettings", 5);
141 
142  RegMemFun(this, &CMapReader::DelayLoadFinished, L"CMapReader::DelayLoadFinished", 5);
143 }
144 
145 // LoadRandomMap: try to load the map data; reinitialise the scene to new data if successful
146 void CMapReader::LoadRandomMap(const CStrW& scriptFile, const CScriptValRooted& settings, CTerrain *pTerrain_,
147  WaterManager* pWaterMan_, SkyManager* pSkyMan_,
148  CLightEnv *pLightEnv_, CGameView *pGameView_, CCinemaManager* pCinema_, CTriggerManager* pTrigMan_, CPostprocManager* pPostproc_,
149  CSimulation2 *pSimulation2_, int playerID_)
150 {
151  // latch parameters (held until DelayedLoadFinished)
152  m_ScriptFile = scriptFile;
153  m_ScriptSettings = settings;
154  pTerrain = pTerrain_;
155  pLightEnv = pLightEnv_;
156  pGameView = pGameView_;
157  pWaterMan = pWaterMan_;
158  pSkyMan = pSkyMan_;
159  pCinema = pCinema_;
160  pTrigMan = pTrigMan_;
161  pPostproc = pPostproc_;
162  pSimulation2 = pSimulation2_;
164  m_PlayerID = playerID_;
165  m_SkipEntities = false;
167 
168  // delete all existing entities
169  if (pSimulation2)
171 
172  only_xml = false;
173 
174  // copy random map settings (before entity creation)
175  RegMemFun(this, &CMapReader::LoadRMSettings, L"CMapReader::LoadRMSettings", 50);
176 
177  // load player settings script (must be done before reading map)
178  RegMemFun(this, &CMapReader::LoadPlayerSettings, L"CMapReader::LoadPlayerSettings", 50);
179 
180  // load map generator with random map script
181  RegMemFun(this, &CMapReader::GenerateMap, L"CMapReader::GenerateMap", 5000);
182 
183  // parse RMS results into terrain structure
184  RegMemFun(this, &CMapReader::ParseTerrain, L"CMapReader::ParseTerrain", 500);
185 
186  // parse RMS results into environment settings
187  RegMemFun(this, &CMapReader::ParseEnvironment, L"CMapReader::ParseEnvironment", 5);
188 
189  // parse RMS results into camera settings
190  RegMemFun(this, &CMapReader::ParseCamera, L"CMapReader::ParseCamera", 5);
191 
192  // parse RMS results into entities
193  RegMemFun(this, &CMapReader::ParseEntities, L"CMapReader::ParseEntities", 1000);
194 
195  // apply data to the world
196  RegMemFun(this, &CMapReader::ApplyData, L"CMapReader::ApplyData", 5);
197 
198  // load map settings script (must be done after reading map)
199  RegMemFun(this, &CMapReader::LoadMapSettings, L"CMapReader::LoadMapSettings", 5);
200 
201  RegMemFun(this, &CMapReader::DelayLoadFinished, L"CMapReader::DelayLoadFinished", 5);
202 }
203 
204 // UnpackMap: unpack the given data from the raw data stream into local variables
206 {
207  // now unpack everything into local data
208  int ret = UnpackTerrain();
209  if (ret != 0) // failed or timed out
210  {
211  return ret;
212  }
213 
214  return 0;
215 }
216 
217 // UnpackTerrain: unpack the terrain from the end of the input data stream
218 // - data: map size, heightmap, list of textures used by map, texture tile assignments
220 {
221  // yield after this time is reached. balances increased progress bar
222  // smoothness vs. slowing down loading.
223  const double end_time = timer_Time() + 200e-3;
224 
225  // first call to generator (this is skipped after first call,
226  // i.e. when the loop below was interrupted)
227  if (cur_terrain_tex == 0)
228  {
230 
231  // unpack heightmap [600us]
232  size_t verticesPerSide = m_PatchesPerSide*PATCH_SIZE+1;
233  m_Heightmap.resize(SQR(verticesPerSide));
234  unpacker.UnpackRaw(&m_Heightmap[0], SQR(verticesPerSide)*sizeof(u16));
235 
236  // unpack # textures
239  }
240 
241  // unpack texture names; find handle for each texture.
242  // interruptible.
244  {
245  CStr texturename;
246  unpacker.UnpackString(texturename);
247 
248  ENSURE(CTerrainTextureManager::IsInitialised()); // we need this for the terrain properties (even when graphics are disabled)
249  CTerrainTextureEntry* texentry = g_TexMan.FindTexture(texturename);
250  m_TerrainTextures.push_back(texentry);
251 
252  cur_terrain_tex++;
254  }
255 
256  // unpack tile data [3ms]
257  ssize_t tilesPerSide = m_PatchesPerSide*PATCH_SIZE;
258  m_Tiles.resize(size_t(SQR(tilesPerSide)));
259  unpacker.UnpackRaw(&m_Tiles[0], sizeof(STileDesc)*m_Tiles.size());
260 
261  // reset generator state.
262  cur_terrain_tex = 0;
263 
264  return 0;
265 }
266 
267 // ApplyData: take all the input data, and rebuild the scene from it
269 {
270  if (m_PatchesPerSide == 0)
271  {
272  // we'll probably crash when trying to use this map later
273  throw PSERROR_Game_World_MapLoadFailed("Error loading map: no terrain data.\nCheck application log for details.");
274  }
275 
276  if (!only_xml)
277  {
278  // initialise the terrain
280 
281  // setup the textures on the minipatches
282  STileDesc* tileptr = &m_Tiles[0];
283  for (ssize_t j=0; j<m_PatchesPerSide; j++) {
284  for (ssize_t i=0; i<m_PatchesPerSide; i++) {
285  for (ssize_t m=0; m<PATCH_SIZE; m++) {
286  for (ssize_t k=0; k<PATCH_SIZE; k++) {
287  CMiniPatch& mp = pTerrain->GetPatch(i,j)->m_MiniPatches[m][k]; // can't fail
288 
289  mp.Tex = m_TerrainTextures[tileptr->m_Tex1Index];
290  mp.Priority = tileptr->m_Priority;
291 
292  tileptr++;
293  }
294  }
295  }
296  }
297  }
298 
299  // copy over the lighting parameters
300  if (pLightEnv)
302 
304 
305  if (pGameView && cmpPlayerManager)
306  {
307  // Default to global camera (with constraints)
309 
310  // TODO: Starting rotation?
311  CmpPtr<ICmpPlayer> cmpPlayer(*pSimContext, cmpPlayerManager->GetPlayerByID(m_PlayerID));
312  if (cmpPlayer && cmpPlayer->HasStartingCamera())
313  {
314  // Use player starting camera
315  CFixedVector3D pos = cmpPlayer->GetStartingCameraPos();
317  }
319  {
320  // Point camera at entity
322  if (cmpPosition)
323  {
324  CFixedVector3D pos = cmpPosition->GetPosition();
326  }
327  }
328  }
329 
331  if (cmpTerrain)
332  cmpTerrain->ReloadTerrain();
333 
334  return 0;
335 }
336 
337 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
338 
339 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
340 
341 
343 {
344  VfsPath filename_xml = pathname.ChangeExtension(L".xml");
345 
346  CXeromyces xmb_file;
347  if (xmb_file.Load(g_VFS, filename_xml) != PSRETURN_OK)
349 
350  // Define all the relevant elements used in the XML file
351  #define EL(x) int el_##x = xmb_file.GetElementID(#x)
352  #define AT(x) int at_##x = xmb_file.GetAttributeID(#x)
353  EL(scenario);
354  EL(scriptsettings);
355  #undef AT
356  #undef EL
357 
358  XMBElement root = xmb_file.GetRoot();
359  ENSURE(root.GetNodeName() == el_scenario);
360 
361  XERO_ITER_EL(root, child)
362  {
363  int child_name = child.GetNodeName();
364  if (child_name == el_scriptsettings)
365  {
366  m_ScriptSettings = child.GetText();
367  }
368  }
369 
370  return PSRETURN_OK;
371 }
372 
374 {
375  CScriptValRooted data;
376  scriptInterface.Eval("({})", data);
377  if (!m_ScriptSettings.empty())
378  scriptInterface.SetProperty(data.get(), "settings", scriptInterface.ParseJSON(m_ScriptSettings), false);
379  return data;
380 }
381 
382 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
383 
384 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
385 
386 
387 // Holds various state data while reading maps, so that loading can be
388 // interrupted (e.g. to update the progress display) then later resumed.
390 {
392 public:
393  CXMLReader(const VfsPath& xml_filename, CMapReader& mapReader)
394  : m_MapReader(mapReader)
395  {
396  Init(xml_filename);
397  }
398 
399  CStr ReadScriptSettings();
400 
401  // return semantics: see Loader.cpp!LoadFunc.
402  int ProgressiveRead();
403 
404 private:
406 
408 
413  int el_actor;
414  int at_x, at_y, at_z;
416  int at_id;
417  int at_angle;
418  int at_uid;
419  int at_seed;
420 
421  XMBElementList nodes; // children of root
422 
423  // loop counters
424  int node_idx;
426 
427  // # entities+nonentities processed and total (for progress calc)
429 
430  // maximum used entity ID, so we can safely allocate new ones
432 
433  void Init(const VfsPath& xml_filename);
434 
435  void ReadTerrain(XMBElement parent);
436  void ReadEnvironment(XMBElement parent);
437  void ReadCamera(XMBElement parent);
438  void ReadCinema(XMBElement parent);
439  void ReadTriggers(XMBElement parent);
440  int ReadEntities(XMBElement parent, double end_time);
441 };
442 
443 
444 void CXMLReader::Init(const VfsPath& xml_filename)
445 {
446  // must only assign once, so do it here
447  node_idx = entity_idx = 0;
448 
449  if (xmb_file.Load(g_VFS, xml_filename) != PSRETURN_OK)
450  throw PSERROR_File_ReadFailed();
451 
452  // define the elements and attributes that are frequently used in the XML file,
453  // so we don't need to do lots of string construction and comparison when
454  // reading the data.
455  // (Needs to be synchronised with the list in CXMLReader - ugh)
456 #define EL(x) el_##x = xmb_file.GetElementID(#x)
457 #define AT(x) at_##x = xmb_file.GetAttributeID(#x)
458  EL(entity);
459  EL(tracks);
460  EL(template);
461  EL(player);
462  EL(position);
463  EL(orientation);
464  EL(obstruction);
465  EL(actor);
466  AT(x); AT(y); AT(z);
467  AT(group); AT(group2);
468  AT(angle);
469  AT(uid);
470  AT(seed);
471 #undef AT
472 #undef EL
473 
474  XMBElement root = xmb_file.GetRoot();
475  ENSURE(xmb_file.GetElementString(root.GetNodeName()) == "Scenario");
476  nodes = root.GetChildNodes();
477 
478  // find out total number of entities+nonentities
479  // (used when calculating progress)
480  completed_jobs = 0;
481  total_jobs = 0;
482  for (int i = 0; i < nodes.Count; i++)
484 
485  // Find the maximum entity ID, so we can safely allocate new IDs without conflicts
486 
488 
490  XERO_ITER_EL(ents, ent)
491  {
492  CStr uid = ent.GetAttributes().GetNamedItem(at_uid);
493  max_uid = std::max(max_uid, (entity_id_t)uid.ToUInt());
494  }
495 }
496 
497 
499 {
500  XMBElement root = xmb_file.GetRoot();
501  ENSURE(xmb_file.GetElementString(root.GetNodeName()) == "Scenario");
502  nodes = root.GetChildNodes();
503 
504  XMBElement settings = nodes.GetFirstNamedItem(xmb_file.GetElementID("ScriptSettings"));
505 
506  return settings.GetText();
507 }
508 
509 
511 {
512 #define AT(x) int at_##x = xmb_file.GetAttributeID(#x)
513  AT(patches);
514  AT(texture);
515  AT(priority);
516  AT(height);
517 #undef AT
518 
519  ssize_t patches = 9;
520  CStr texture = "grass1_spring";
521  int priority = 0;
522  u16 height = 16384;
523 
524  XERO_ITER_ATTR(parent, attr)
525  {
526  if (attr.Name == at_patches)
527  patches = attr.Value.ToInt();
528  else if (attr.Name == at_texture)
529  texture = attr.Value;
530  else if (attr.Name == at_priority)
531  priority = attr.Value.ToInt();
532  else if (attr.Name == at_height)
533  height = (u16)attr.Value.ToInt();
534  }
535 
536  m_MapReader.m_PatchesPerSide = patches;
537 
538  // Load the texture
539  ENSURE(CTerrainTextureManager::IsInitialised()); // we need this for the terrain properties (even when graphics are disabled)
540  CTerrainTextureEntry* texentry = g_TexMan.FindTexture(texture);
541 
542  m_MapReader.pTerrain->Initialize(patches, NULL);
543 
544  // Fill the heightmap
545  u16* heightmap = m_MapReader.pTerrain->GetHeightMap();
546  ssize_t verticesPerSide = m_MapReader.pTerrain->GetVerticesPerSide();
547  for (ssize_t i = 0; i < SQR(verticesPerSide); ++i)
548  heightmap[i] = height;
549 
550  // Fill the texture map
551  for (ssize_t pz = 0; pz < patches; ++pz)
552  {
553  for (ssize_t px = 0; px < patches; ++px)
554  {
555  CPatch* patch = m_MapReader.pTerrain->GetPatch(px, pz); // can't fail
556 
557  for (ssize_t z = 0; z < PATCH_SIZE; ++z)
558  {
559  for (ssize_t x = 0; x < PATCH_SIZE; ++x)
560  {
561  patch->m_MiniPatches[z][x].Tex = texentry;
562  patch->m_MiniPatches[z][x].Priority = priority;
563  }
564  }
565  }
566  }
567 }
568 
570 {
571 #define EL(x) int el_##x = xmb_file.GetElementID(#x)
572 #define AT(x) int at_##x = xmb_file.GetAttributeID(#x)
573  EL(lightingmodel);
574  EL(posteffect);
575  EL(skyset);
576  EL(suncolour);
577  EL(sunelevation);
578  EL(sunrotation);
579  EL(terrainambientcolour);
580  EL(unitsambientcolour);
581  EL(water);
582  EL(waterbody);
583  EL(type);
584  EL(colour);
585  EL(height);
586  EL(shininess);
587  EL(waviness);
588  EL(murkiness);
589  EL(tint);
590  EL(reflectiontint);
591  EL(reflectiontintstrength);
592  EL(fog);
593  EL(fogcolour);
594  EL(fogfactor);
595  EL(fogthickness);
596  EL(postproc);
597  EL(brightness);
598  EL(contrast);
599  EL(saturation);
600  EL(bloom);
601  AT(r); AT(g); AT(b);
602 #undef AT
603 #undef EL
604 
605  XERO_ITER_EL(parent, element)
606  {
607  int element_name = element.GetNodeName();
608 
609  XMBAttributeList attrs = element.GetAttributes();
610 
611  if (element_name == el_lightingmodel)
612  {
613  // NOP - obsolete.
614  }
615  else if (element_name == el_skyset)
616  {
617  if (m_MapReader.pSkyMan)
618  m_MapReader.pSkyMan->SetSkySet(element.GetText().FromUTF8());
619  }
620  else if (element_name == el_suncolour)
621  {
623  attrs.GetNamedItem(at_r).ToFloat(),
624  attrs.GetNamedItem(at_g).ToFloat(),
625  attrs.GetNamedItem(at_b).ToFloat());
626  }
627  else if (element_name == el_sunelevation)
628  {
630  }
631  else if (element_name == el_sunrotation)
632  {
634  }
635  else if (element_name == el_terrainambientcolour)
636  {
638  attrs.GetNamedItem(at_r).ToFloat(),
639  attrs.GetNamedItem(at_g).ToFloat(),
640  attrs.GetNamedItem(at_b).ToFloat());
641  }
642  else if (element_name == el_unitsambientcolour)
643  {
645  attrs.GetNamedItem(at_r).ToFloat(),
646  attrs.GetNamedItem(at_g).ToFloat(),
647  attrs.GetNamedItem(at_b).ToFloat());
648  }
649  else if (element_name == el_fog)
650  {
651  XERO_ITER_EL(element, fog)
652  {
653  int element_name = fog.GetNodeName();
654  if (element_name == el_fogcolour)
655  {
656  XMBAttributeList attrs = fog.GetAttributes();
658  attrs.GetNamedItem(at_r).ToFloat(),
659  attrs.GetNamedItem(at_g).ToFloat(),
660  attrs.GetNamedItem(at_b).ToFloat());
661  }
662  else if (element_name == el_fogfactor)
663  {
664  m_MapReader.m_LightEnv.m_FogFactor = fog.GetText().ToFloat();
665  }
666  else if (element_name == el_fogthickness)
667  {
668  m_MapReader.m_LightEnv.m_FogMax = fog.GetText().ToFloat();
669  }
670  }
671  }
672  else if (element_name == el_postproc)
673  {
674  XERO_ITER_EL(element, postproc)
675  {
676  int element_name = postproc.GetNodeName();
677  if (element_name == el_brightness)
678  {
679  m_MapReader.m_LightEnv.m_Brightness = postproc.GetText().ToFloat();
680  }
681  else if (element_name == el_contrast)
682  {
683  m_MapReader.m_LightEnv.m_Contrast = postproc.GetText().ToFloat();
684  }
685  else if (element_name == el_saturation)
686  {
687  m_MapReader.m_LightEnv.m_Saturation = postproc.GetText().ToFloat();
688  }
689  else if (element_name == el_bloom)
690  {
691  m_MapReader.m_LightEnv.m_Bloom = postproc.GetText().ToFloat();
692  }
693  else if (element_name == el_posteffect)
694  {
696  m_MapReader.pPostproc->SetPostEffect(postproc.GetText().FromUTF8());
697  }
698  }
699  }
700  else if (element_name == el_water)
701  {
702  XERO_ITER_EL(element, waterbody)
703  {
704  ENSURE(waterbody.GetNodeName() == el_waterbody);
705  XERO_ITER_EL(waterbody, waterelement)
706  {
707  int element_name = waterelement.GetNodeName();
708  if (element_name == el_height)
709  {
711  ENSURE(cmpWaterManager);
712  cmpWaterManager->SetWaterLevel(entity_pos_t::FromString(waterelement.GetText()));
713  continue;
714  }
715 
716  // The rest are purely graphical effects, and should be ignored if
717  // graphics are disabled
718  if (!m_MapReader.pWaterMan)
719  continue;
720 
721  if (element_name == el_type)
722  {
723  // TODO: implement this, when WaterManager supports it
724  }
725 #define READ_COLOUR(el, out) \
726  else if (element_name == el) \
727  { \
728  XMBAttributeList attrs = waterelement.GetAttributes(); \
729  out = CColor( \
730  attrs.GetNamedItem(at_r).ToFloat(), \
731  attrs.GetNamedItem(at_g).ToFloat(), \
732  attrs.GetNamedItem(at_b).ToFloat(), \
733  1.f); \
734  }
735 
736 #define READ_FLOAT(el, out) \
737  else if (element_name == el) \
738  { \
739  out = waterelement.GetText().ToFloat(); \
740  } \
741 
748  READ_FLOAT(el_reflectiontintstrength, m_MapReader.pWaterMan->m_ReflectionTintStrength)
749 
750 #undef READ_FLOAT
751 #undef READ_COLOUR
752 
753  else
754  debug_warn(L"Invalid map XML data");
755  }
756 
757  }
758  }
759  else
760  debug_warn(L"Invalid map XML data");
761  }
762 
764 }
765 
767 {
768  // defaults if we don't find player starting camera
769 #define EL(x) int el_##x = xmb_file.GetElementID(#x)
770 #define AT(x) int at_##x = xmb_file.GetAttributeID(#x)
771  EL(declination);
772  EL(rotation);
773  EL(position);
774  AT(angle);
775  AT(x); AT(y); AT(z);
776 #undef AT
777 #undef EL
778 
779  float declination = DEGTORAD(30.f), rotation = DEGTORAD(-45.f);
780  CVector3D translation = CVector3D(100, 150, -100);
781 
782  XERO_ITER_EL(parent, element)
783  {
784  int element_name = element.GetNodeName();
785 
786  XMBAttributeList attrs = element.GetAttributes();
787  if (element_name == el_declination)
788  {
789  declination = attrs.GetNamedItem(at_angle).ToFloat();
790  }
791  else if (element_name == el_rotation)
792  {
793  rotation = attrs.GetNamedItem(at_angle).ToFloat();
794  }
795  else if (element_name == el_position)
796  {
797  translation = CVector3D(
798  attrs.GetNamedItem(at_x).ToFloat(),
799  attrs.GetNamedItem(at_y).ToFloat(),
800  attrs.GetNamedItem(at_z).ToFloat());
801  }
802  else
803  debug_warn(L"Invalid map XML data");
804  }
805 
807  {
812  }
813 }
814 
816 {
817  #define EL(x) int el_##x = xmb_file.GetElementID(#x)
818  #define AT(x) int at_##x = xmb_file.GetAttributeID(#x)
819 
820  EL(path);
821  EL(rotation);
822  EL(distortion);
823  EL(node);
824  EL(position);
825  EL(time);
826  AT(name);
827  AT(timescale);
828  AT(mode);
829  AT(style);
830  AT(growth);
831  AT(switch);
832  AT(x);
833  AT(y);
834  AT(z);
835 
836 #undef EL
837 #undef AT
838 
839  std::map<CStrW, CCinemaPath> pathList;
840  XERO_ITER_EL(parent, element)
841  {
842  int elementName = element.GetNodeName();
843 
844  if ( elementName == el_path )
845  {
846  XMBAttributeList attrs = element.GetAttributes();
847  CStrW name(attrs.GetNamedItem(at_name).FromUTF8());
848  float timescale = attrs.GetNamedItem(at_timescale).ToFloat();
849  CCinemaData pathData;
850  pathData.m_Timescale = timescale;
851  TNSpline spline, backwardSpline;
852 
853  XERO_ITER_EL(element, pathChild)
854  {
855  elementName = pathChild.GetNodeName();
856  attrs = pathChild.GetAttributes();
857 
858  //Load distortion attributes
859  if ( elementName == el_distortion )
860  {
861  pathData.m_Mode = attrs.GetNamedItem(at_mode).ToInt();
862  pathData.m_Style = attrs.GetNamedItem(at_style).ToInt();
863  pathData.m_Growth = attrs.GetNamedItem(at_growth).ToInt();
864  pathData.m_Switch = attrs.GetNamedItem(at_switch).ToInt();
865  }
866 
867  //Load node data used for spline
868  else if ( elementName == el_node )
869  {
870  SplineData data;
871  XERO_ITER_EL(pathChild, nodeChild)
872  {
873  elementName = nodeChild.GetNodeName();
874  attrs = nodeChild.GetAttributes();
875 
876  //Fix?: assumes that time is last element
877  if ( elementName == el_position )
878  {
879  data.Position.X = attrs.GetNamedItem(at_x).ToFloat();
880  data.Position.Y = attrs.GetNamedItem(at_y).ToFloat();
881  data.Position.Z = attrs.GetNamedItem(at_z).ToFloat();
882  continue;
883  }
884  else if ( elementName == el_rotation )
885  {
886  data.Rotation.X = attrs.GetNamedItem(at_x).ToFloat();
887  data.Rotation.Y = attrs.GetNamedItem(at_y).ToFloat();
888  data.Rotation.Z = attrs.GetNamedItem(at_z).ToFloat();
889  continue;
890  }
891  else if ( elementName == el_time )
892  data.Distance = nodeChild.GetText().ToFloat();
893  else
894  debug_warn(L"Invalid cinematic element for node child");
895 
896  backwardSpline.AddNode(data.Position, data.Rotation, data.Distance);
897  }
898  }
899  else
900  debug_warn(L"Invalid cinematic element for path child");
901 
902 
903  }
904 
905  //Construct cinema path with data gathered
906  CCinemaPath temp(pathData, backwardSpline);
907  const std::vector<SplineData>& nodes = temp.GetAllNodes();
908  if ( nodes.empty() )
909  {
910  debug_warn(L"Failure loading cinematics");
911  return;
912  }
913 
914  for ( std::vector<SplineData>::const_reverse_iterator it = nodes.rbegin();
915  it != nodes.rend(); ++it )
916  {
917  spline.AddNode(it->Position, it->Rotation, it->Distance);
918  }
919 
920  CCinemaPath path(pathData, spline);
921  pathList[name] = path;
922  }
923  else
924  ENSURE("Invalid cinema child");
925  }
926 
927  if (m_MapReader.pCinema)
928  m_MapReader.pCinema->SetAllPaths(pathList);
929 }
930 
932 {
933 }
934 
935 int CXMLReader::ReadEntities(XMBElement parent, double end_time)
936 {
937  XMBElementList entities = parent.GetChildNodes();
938 
941  CmpPtr<ICmpPlayerManager> cmpPlayerManager(sim, SYSTEM_ENTITY);
942 
943  while (entity_idx < entities.Count)
944  {
945  // all new state at this scope and below doesn't need to be
946  // wrapped, since we only yield after a complete iteration.
947 
948  XMBElement entity = entities.Item(entity_idx++);
949  ENSURE(entity.GetNodeName() == el_entity);
950 
951  XMBAttributeList attrs = entity.GetAttributes();
952  CStr uid = attrs.GetNamedItem(at_uid);
953  ENSURE(!uid.empty());
954  int EntityUid = uid.ToInt();
955 
956  CStrW TemplateName;
957  int PlayerID = 0;
958  CFixedVector3D Position;
959  CFixedVector3D Orientation;
960  long Seed = -1;
961 
962  // Obstruction control groups.
963  entity_id_t ControlGroup = INVALID_ENTITY;
964  entity_id_t ControlGroup2 = INVALID_ENTITY;
965 
966  XERO_ITER_EL(entity, setting)
967  {
968  int element_name = setting.GetNodeName();
969 
970  // <template>
971  if (element_name == el_template)
972  {
973  TemplateName = setting.GetText().FromUTF8();
974  }
975  // <player>
976  else if (element_name == el_player)
977  {
978  PlayerID = setting.GetText().ToInt();
979  }
980  // <position>
981  else if (element_name == el_position)
982  {
983  XMBAttributeList attrs = setting.GetAttributes();
984  Position = CFixedVector3D(
988  }
989  // <orientation>
990  else if (element_name == el_orientation)
991  {
992  XMBAttributeList attrs = setting.GetAttributes();
993  Orientation = CFixedVector3D(
997  // TODO: what happens if some attributes are missing?
998  }
999  // <obstruction>
1000  else if (element_name == el_obstruction)
1001  {
1002  XMBAttributeList attrs = setting.GetAttributes();
1003  ControlGroup = attrs.GetNamedItem(at_group).ToInt();
1004  ControlGroup2 = attrs.GetNamedItem(at_group2).ToInt();
1005  }
1006  // <actor>
1007  else if (element_name == el_actor)
1008  {
1009  XMBAttributeList attrs = setting.GetAttributes();
1010  CStr seedStr = attrs.GetNamedItem(at_seed);
1011  if (!seedStr.empty())
1012  {
1013  Seed = seedStr.ToLong();
1014  ENSURE(Seed >= 0);
1015  }
1016  }
1017  else
1018  debug_warn(L"Invalid map XML data");
1019  }
1020 
1021  entity_id_t ent = sim.AddEntity(TemplateName, EntityUid);
1022  entity_id_t player = cmpPlayerManager->GetPlayerByID(PlayerID);
1023  if (ent == INVALID_ENTITY || player == INVALID_ENTITY)
1024  { // Don't add entities with invalid player IDs
1025  LOGERROR(L"Failed to load entity template '%ls'", TemplateName.c_str());
1026  }
1027  else
1028  {
1029  CmpPtr<ICmpPosition> cmpPosition(sim, ent);
1030  if (cmpPosition)
1031  {
1032  cmpPosition->JumpTo(Position.X, Position.Z);
1033  cmpPosition->SetYRotation(Orientation.Y);
1034  // TODO: other parts of the position
1035  }
1036 
1037  CmpPtr<ICmpOwnership> cmpOwnership(sim, ent);
1038  if (cmpOwnership)
1039  cmpOwnership->SetOwner(PlayerID);
1040 
1041  CmpPtr<ICmpObstruction> cmpObstruction(sim, ent);
1042  if (cmpObstruction)
1043  {
1044  if (ControlGroup != INVALID_ENTITY)
1045  cmpObstruction->SetControlGroup(ControlGroup);
1046  if (ControlGroup2 != INVALID_ENTITY)
1047  cmpObstruction->SetControlGroup2(ControlGroup2);
1048 
1049  cmpObstruction->ResolveFoundationCollisions();
1050  }
1051 
1052  CmpPtr<ICmpVisual> cmpVisual(sim, ent);
1053  if (cmpVisual)
1054  {
1055  if (Seed != -1)
1056  cmpVisual->SetActorSeed((u32)Seed);
1057  // TODO: variation/selection strings
1058  }
1059 
1060  if (PlayerID == m_MapReader.m_PlayerID && (boost::algorithm::ends_with(TemplateName, L"civil_centre") || m_MapReader.m_StartingCameraTarget == INVALID_ENTITY))
1061  {
1062  // Focus on civil centre or first entity owned by player
1064  }
1065  }
1066 
1067  completed_jobs++;
1069  }
1070 
1071  return 0;
1072 }
1073 
1075 {
1076  // yield after this time is reached. balances increased progress bar
1077  // smoothness vs. slowing down loading.
1078  const double end_time = timer_Time() + 200e-3;
1079 
1080  int ret;
1081 
1082  while (node_idx < nodes.Count)
1083  {
1084  XMBElement node = nodes.Item(node_idx);
1085  CStr name = xmb_file.GetElementString(node.GetNodeName());
1086  if (name == "Terrain")
1087  {
1088  ReadTerrain(node);
1089  }
1090  else if (name == "Environment")
1091  {
1092  ReadEnvironment(node);
1093  }
1094  else if (name == "Camera")
1095  {
1096  ReadCamera(node);
1097  }
1098  else if (name == "ScriptSettings")
1099  {
1100  //Already loaded - this is to prevent an assertion
1101  }
1102  else if (name == "Entities")
1103  {
1105  {
1106  ret = ReadEntities(node, end_time);
1107  if (ret != 0) // error or timed out
1108  return ret;
1109  }
1110  }
1111  else if (name == "Paths")
1112  {
1113  ReadCinema(node);
1114  }
1115  else if (name == "Triggers")
1116  {
1117  ReadTriggers(node);
1118  }
1119  else if (name == "Script")
1120  {
1123  }
1124  else
1125  {
1126  debug_printf(L"Invalid XML element in map file: %hs\n", name.c_str());
1127  debug_warn(L"Invalid map XML data");
1128  }
1129 
1130  node_idx++;
1131  }
1132 
1133  return 0;
1134 }
1135 
1136 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1137 
1138 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1139 
1140 
1141 // load script settings from map
1143 {
1144  if (!xml_reader)
1145  xml_reader = new CXMLReader(filename_xml, *this);
1146 
1147  // parse the script settings
1148  if (pSimulation2)
1150 
1151  return 0;
1152 }
1153 
1154 // load player settings script
1156 {
1157  if (pSimulation2)
1159  return 0;
1160 }
1161 
1162 // load map settings script
1164 {
1165  if (pSimulation2)
1167  return 0;
1168 }
1169 
1170 // progressive
1172 {
1173  if (!xml_reader)
1174  xml_reader = new CXMLReader(filename_xml, *this);
1175 
1176  int ret = xml_reader->ProgressiveRead();
1177  // finished or failed
1178  if (ret <= 0)
1179  {
1181  }
1182 
1183  return ret;
1184 }
1185 
1187 {
1188  // we were dynamically allocated by CWorld::Initialize
1189  delete this;
1190 
1191  return 0;
1192 }
1193 
1194 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1195 
1196 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1197 
1198 
1200 {
1201  // copy random map settings over to sim
1204 
1205  return 0;
1206 }
1207 
1209 {
1210  if (!m_MapGen)
1211  {
1212  // Initialize map generator
1213  m_MapGen = new CMapGenerator();
1214 
1215  VfsPath scriptPath;
1216 
1217  if (m_ScriptFile.length())
1218  scriptPath = L"maps/random/"+m_ScriptFile;
1219 
1220  // Stringify settings to pass across threads
1221  std::string scriptSettings = pSimulation2->GetScriptInterface().StringifyJSON(m_ScriptSettings.get());
1222 
1223  // Try to generate map
1224  m_MapGen->GenerateMap(scriptPath, scriptSettings);
1225  }
1226 
1227  // Check status
1228  int progress = m_MapGen->GetProgress();
1229  if (progress < 0)
1230  {
1231  // RMS failed - return to main menu
1232  throw PSERROR_Game_World_MapLoadFailed("Error generating random map.\nCheck application log for details.");
1233  }
1234  else if (progress == 0)
1235  {
1236  // Finished, get results as StructuredClone object, which must be read to obtain the JS val
1237  shared_ptr<ScriptInterface::StructuredClone> results = m_MapGen->GetResults();
1238 
1239  // Parse data into simulation context
1241  if (data.undefined())
1242  {
1243  // RMS failed - return to main menu
1244  throw PSERROR_Game_World_MapLoadFailed("Error generating random map.\nCheck application log for details.");
1245  }
1246  else
1247  {
1248  m_MapData = data;
1249  }
1250  }
1251  else
1252  {
1253  // Still working
1254 
1255  // Sleep for a while, slowing down the rendering thread
1256  // to allow more CPU for the map generator thread
1257  SDL_Delay(100);
1258  }
1259 
1260  // return progress
1261  return progress;
1262 };
1263 
1264 
1266 {
1267  TIMER(L"ParseTerrain");
1268 
1269  // parse terrain from map data
1270  // an error here should stop the loading process
1271 #define GET_TERRAIN_PROPERTY(val, prop, out)\
1272  if (!pSimulation2->GetScriptInterface().GetProperty(val, #prop, out))\
1273  { LOGERROR(L"CMapReader::ParseTerrain() failed to get '%hs' property", #prop);\
1274  throw PSERROR_Game_World_MapLoadFailed("Error parsing terrain data.\nCheck application log for details"); }
1275 
1276  u32 size;
1277  GET_TERRAIN_PROPERTY(m_MapData.get(), size, size)
1278 
1279  m_PatchesPerSide = size / PATCH_SIZE;
1280 
1281  // flat heightmap of u16 data
1283 
1284  // load textures
1285  std::vector<std::string> textureNames;
1286  GET_TERRAIN_PROPERTY(m_MapData.get(), textureNames, textureNames)
1287  num_terrain_tex = textureNames.size();
1288 
1290  {
1291  ENSURE(CTerrainTextureManager::IsInitialised()); // we need this for the terrain properties (even when graphics are disabled)
1292  CTerrainTextureEntry* texentry = g_TexMan.FindTexture(textureNames[cur_terrain_tex]);
1293  m_TerrainTextures.push_back(texentry);
1294 
1295  cur_terrain_tex++;
1296  }
1297 
1298  // build tile data
1299  m_Tiles.resize(SQR(size));
1300 
1301  CScriptValRooted tileData;
1302  GET_TERRAIN_PROPERTY(m_MapData.get(), tileData, tileData)
1303 
1304  // parse tile data object into flat arrays
1305  std::vector<u16> tileIndex;
1306  std::vector<u16> tilePriority;
1307  GET_TERRAIN_PROPERTY(tileData.get(), index, tileIndex);
1308  GET_TERRAIN_PROPERTY(tileData.get(), priority, tilePriority);
1309 
1310  ENSURE(SQR(size) == tileIndex.size() && SQR(size) == tilePriority.size());
1311 
1312  // reorder by patches and store
1313  for (size_t x = 0; x < size; ++x)
1314  {
1315  size_t patchX = x / PATCH_SIZE;
1316  size_t offX = x % PATCH_SIZE;
1317  for (size_t y = 0; y < size; ++y)
1318  {
1319  size_t patchY = y / PATCH_SIZE;
1320  size_t offY = y % PATCH_SIZE;
1321 
1322  STileDesc tile;
1323  tile.m_Tex1Index = tileIndex[y*size + x];
1324  tile.m_Tex2Index = 0xFFFF;
1325  tile.m_Priority = tilePriority[y*size + x];
1326 
1327  m_Tiles[(patchY * m_PatchesPerSide + patchX) * SQR(PATCH_SIZE) + (offY * PATCH_SIZE + offX)] = tile;
1328  }
1329  }
1330 
1331  // reset generator state
1332  cur_terrain_tex = 0;
1333 
1334 #undef GET_TERRAIN_PROPERTY
1335 
1336  return 0;
1337 }
1338 
1340 {
1341  TIMER(L"ParseEntities");
1342 
1343  // parse entities from map data
1344  std::vector<Entity> entities;
1345 
1346  if (!pSimulation2->GetScriptInterface().GetProperty(m_MapData.get(), "entities", entities))
1347  LOGWARNING(L"CMapReader::ParseEntities() failed to get 'entities' property");
1348 
1349  CSimulation2& sim = *pSimulation2;
1350  CmpPtr<ICmpPlayerManager> cmpPlayerManager(sim, SYSTEM_ENTITY);
1351 
1352  size_t entity_idx = 0;
1353  size_t num_entities = entities.size();
1354 
1355  Entity currEnt;
1356 
1357  while (entity_idx < num_entities)
1358  {
1359  // Get current entity struct
1360  currEnt = entities[entity_idx];
1361 
1362  entity_id_t ent = pSimulation2->AddEntity(currEnt.templateName, currEnt.entityID);
1363  entity_id_t player = cmpPlayerManager->GetPlayerByID(currEnt.playerID);
1364  if (ent == INVALID_ENTITY || player == INVALID_ENTITY)
1365  { // Don't add entities with invalid player IDs
1366  LOGERROR(L"Failed to load entity template '%ls'", currEnt.templateName.c_str());
1367  }
1368  else
1369  {
1370  CmpPtr<ICmpPosition> cmpPosition(sim, ent);
1371  if (cmpPosition)
1372  {
1373  cmpPosition->JumpTo(currEnt.position.X, currEnt.position.Z);
1374  cmpPosition->SetYRotation(currEnt.rotation.Y);
1375  // TODO: other parts of the position
1376  }
1377 
1378  CmpPtr<ICmpOwnership> cmpOwnership(sim, ent);
1379  if (cmpOwnership)
1380  cmpOwnership->SetOwner(currEnt.playerID);
1381 
1382  // Detect and fix collisions between foundation-blocking entities.
1383  // This presently serves to copy wall tower control groups to wall
1384  // segments, allowing players to expand RMS-generated walls.
1385  CmpPtr<ICmpObstruction> cmpObstruction(sim, ent);
1386  if (cmpObstruction)
1387  cmpObstruction->ResolveFoundationCollisions();
1388 
1389  if (currEnt.playerID == m_PlayerID && (boost::algorithm::ends_with(currEnt.templateName, L"civil_centre") || m_StartingCameraTarget == INVALID_ENTITY))
1390  {
1391  // Focus on civil centre or first entity owned by player
1392  m_StartingCameraTarget = currEnt.entityID;
1393  }
1394  }
1395 
1396  entity_idx++;
1397  }
1398 
1399  return 0;
1400 }
1401 
1403 {
1404  // parse environment settings from map data
1405 
1406 #define GET_ENVIRONMENT_PROPERTY(val, prop, out)\
1407  if (!pSimulation2->GetScriptInterface().GetProperty(val, #prop, out))\
1408  LOGWARNING(L"CMapReader::ParseEnvironment() failed to get '%hs' property", #prop);
1409 
1410  CScriptValRooted envObj;
1411  GET_ENVIRONMENT_PROPERTY(m_MapData.get(), Environment, envObj)
1412 
1413  if (envObj.undefined())
1414  {
1415  LOGWARNING(L"CMapReader::ParseEnvironment(): Environment settings not found");
1416  return 0;
1417  }
1418 
1419  //m_LightEnv.SetLightingModel("standard");
1420  if (pPostproc)
1421  pPostproc->SetPostEffect(L"default");
1422 
1423  std::wstring skySet;
1424  GET_ENVIRONMENT_PROPERTY(envObj.get(), SkySet, skySet)
1425  if (pSkyMan)
1426  pSkyMan->SetSkySet(skySet);
1427 
1428  CColor sunColor;
1429  GET_ENVIRONMENT_PROPERTY(envObj.get(), SunColour, sunColor)
1430  m_LightEnv.m_SunColor = RGBColor(sunColor.r, sunColor.g, sunColor.b);
1431 
1432  GET_ENVIRONMENT_PROPERTY(envObj.get(), SunElevation, m_LightEnv.m_Elevation)
1433  GET_ENVIRONMENT_PROPERTY(envObj.get(), SunRotation, m_LightEnv.m_Rotation)
1434 
1435  CColor terrainAmbientColor;
1436  GET_ENVIRONMENT_PROPERTY(envObj.get(), TerrainAmbientColour, terrainAmbientColor)
1437  m_LightEnv.m_TerrainAmbientColor = RGBColor(terrainAmbientColor.r, terrainAmbientColor.g, terrainAmbientColor.b);
1438 
1439  CColor unitsAmbientColor;
1440  GET_ENVIRONMENT_PROPERTY(envObj.get(), UnitsAmbientColour, unitsAmbientColor)
1441  m_LightEnv.m_UnitsAmbientColor = RGBColor(unitsAmbientColor.r, unitsAmbientColor.g, unitsAmbientColor.b);
1442 
1443  // Water properties
1444  CScriptValRooted waterObj;
1445  GET_ENVIRONMENT_PROPERTY(envObj.get(), Water, waterObj)
1446 
1447  CScriptValRooted waterBodyObj;
1448  GET_ENVIRONMENT_PROPERTY(waterObj.get(), WaterBody, waterBodyObj)
1449 
1450  // Water level - necessary
1451  float waterHeight;
1452  GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Height, waterHeight)
1453 
1455  ENSURE(cmpWaterManager);
1456  cmpWaterManager->SetWaterLevel(entity_pos_t::FromFloat(waterHeight));
1457 
1458  // If we have graphics, get rest of settings
1459  if (pWaterMan)
1460  {
1461  // TODO: Water type not implemented
1462 
1463  GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Colour, pWaterMan->m_WaterColor)
1464  GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Shininess, pWaterMan->m_Shininess)
1465  GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Waviness, pWaterMan->m_Waviness)
1466  GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Murkiness, pWaterMan->m_Murkiness)
1467  GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Tint, pWaterMan->m_WaterTint)
1468  GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), ReflectionTint, pWaterMan->m_ReflectionTint)
1469  GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), ReflectionTintStrength, pWaterMan->m_ReflectionTintStrength)
1470  }
1471 
1473 
1474 #undef GET_ENVIRONMENT_PROPERTY
1475 
1476  return 0;
1477 }
1478 
1480 {
1481  // parse camera settings from map data
1482  // defaults if we don't find player starting camera
1483  float declination = DEGTORAD(30.f), rotation = DEGTORAD(-45.f);
1484  CVector3D translation = CVector3D(100, 150, -100);
1485 
1486 #define GET_CAMERA_PROPERTY(val, prop, out)\
1487  if (!pSimulation2->GetScriptInterface().GetProperty(val, #prop, out))\
1488  LOGWARNING(L"CMapReader::ParseCamera() failed to get '%hs' property", #prop);
1489 
1490  CScriptValRooted cameraObj;
1491  GET_CAMERA_PROPERTY(m_MapData.get(), Camera, cameraObj)
1492 
1493  if (!cameraObj.undefined())
1494  { // If camera property exists, read values
1495  CFixedVector3D pos;
1496  GET_CAMERA_PROPERTY(cameraObj.get(), Position, pos)
1497  translation = pos;
1498 
1499  GET_CAMERA_PROPERTY(cameraObj.get(), Rotation, rotation)
1500  GET_CAMERA_PROPERTY(cameraObj.get(), Declination, declination)
1501  }
1502 #undef GET_CAMERA_PROPERTY
1503 
1504  if (pGameView)
1505  {
1506  pGameView->GetCamera()->m_Orientation.SetXRotation(declination);
1507  pGameView->GetCamera()->m_Orientation.RotateY(rotation);
1508  pGameView->GetCamera()->m_Orientation.Translate(translation);
1510  }
1511 
1512  return 0;
1513 }
1514 
1516 {
1517  // Cleaup objects
1518  delete xml_reader;
1519  delete m_MapGen;
1520 }
int completed_jobs
Definition: MapReader.cpp:428
void Translate(float x, float y, float z)
Definition: Matrix3D.cpp:172
float m_Timescale
Definition: CinemaTrack.h:52
int total_jobs
Definition: MapReader.cpp:428
int GetProgress()
Get status of the map generator thread.
#define g_TexMan
CScriptValRooted GetMapSettings(ScriptInterface &scriptInterface)
Returns a value of the form:
Definition: MapReader.cpp:373
void CalculateSunDirection()
Definition: LightEnv.cpp:56
const CSimContext & GetSimContext() const
CPostprocManager * pPostproc
Definition: MapReader.h:133
float m_Switch
Definition: CinemaTrack.h:49
void ReadTriggers(XMBElement parent)
Definition: MapReader.cpp:931
void UnpackRaw(void *rawData, size_t rawDataSize)
unpack given number of bytes from the input into the given array.
Definition: FileIo.cpp:150
float g
Definition: Overlay.h:57
float m_Shininess
Definition: WaterManager.h:118
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
float m_Growth
Definition: CinemaTrack.h:48
std::vector< CTerrainTextureEntry * > m_TerrainTextures
Definition: MapReader.h:113
PSRETURN Load(const PIVFS &vfs, const VfsPath &filename)
Load from an XML file (with invisible XMB caching).
Definition: Xeromyces.cpp:65
#define LOGERROR
Definition: CLogger.h:35
CVector3D Position
Definition: NUSpline.h:31
#define XERO_ITER_ATTR(parent_element, attribute)
Definition: Xeromyces.h:99
void SDL_Delay(Uint32 ms)
Definition: wsdl.cpp:1457
const PSRETURN PSRETURN_OK
Definition: Errors.h:103
int ParseEntities()
Definition: MapReader.cpp:1339
CMapGenerator * m_MapGen
Definition: MapReader.h:126
CLightEnv m_LightEnv
Definition: MapReader.h:117
#define READ_FLOAT(el, out)
Definition: Overlay.h:34
XMBElement GetFirstNamedItem(const int ElementName) const
Definition: XeroXMB.cpp:214
virtual void SetControlGroup2(entity_id_t group2)=0
int el_obstruction
Definition: MapReader.cpp:412
int GetElementID(const char *Name) const
Definition: XeroXMB.cpp:104
std::vector< u16 > m_Heightmap
Definition: MapReader.h:111
int ParseEnvironment()
Definition: MapReader.cpp:1402
RGBColor m_TerrainAmbientColor
Definition: LightEnv.h:70
int ReadXML()
Definition: MapReader.cpp:1171
CVector3D RGBColor
Definition: Color.h:31
float m_Waviness
Definition: WaterManager.h:120
CFileUnpacker unpacker
Definition: MapReader.h:129
XMBAttributeList GetAttributes() const
Definition: XeroXMB.cpp:185
XMBElementList GetChildNodes() const
Definition: XeroXMB.cpp:174
#define GET_ENVIRONMENT_PROPERTY(val, prop, out)
void ResetState(bool skipScriptedComponents=false, bool skipAI=false)
Initialise (or re-initialise) the complete simulation state.
CScriptValRooted m_MapData
Definition: MapReader.h:124
ssize_t GetVerticesPerSide() const
Definition: Terrain.h:65
#define XERO_ITER_EL(parent_element, child_element)
Definition: Xeromyces.h:91
#define SQR(x)
Definition: MathUtil.h:23
#define EL(x)
XMBElementList nodes
Definition: MapReader.cpp:421
SkyManager * pSkyMan
Definition: MapReader.h:132
virtual void ResolveFoundationCollisions()=0
Detects collisions between foundation-blocking entities and tries to fix them by setting control grou...
RGBColor m_SunColor
Definition: LightEnv.h:69
void SetAllPaths(const std::map< CStrW, CCinemaPath > &tracks)
std::string StringifyJSON(jsval obj, bool indent=true)
Stringify to a JSON string, UTF-8 encoded.
virtual void SetOwner(player_id_t playerID)=0
u32 GetVersion() const
Definition: FileIo.h:115
CCinemaManager * pCinema
Definition: MapReader.h:136
Contains pointers to various &#39;global&#39; objects that are needed by the simulation code, to allow easy access without using real (evil) global variables.
Definition: SimContext.h:32
CScriptValRooted ParseJSON(const std::string &string_utf8)
Parse a UTF-8-encoded JSON string.
Random map generator interface.
Definition: MapGenerator.h:37
const entity_id_t SYSTEM_ENTITY
Entity ID for singleton &#39;system&#39; components.
Definition: Entity.h:44
Public API for simulation system.
Definition: Simulation2.h:46
int ParseTerrain()
Definition: MapReader.cpp:1265
float Distance
Definition: NUSpline.h:34
#define LOGWARNING
Definition: CLogger.h:34
void SetMapSettings(const std::string &settings)
Set the initial map settings (as a UTF-8-encoded JSON string), which will be used to set up the simul...
float m_Elevation
Height of sun above the horizon, in radians.
Definition: LightEnv.h:46
RGBColor m_UnitsAmbientColor
Definition: LightEnv.h:71
RGBColor m_FogColor
Definition: LightEnv.h:72
void ReadTerrain(XMBElement parent)
Definition: MapReader.cpp:510
float m_Murkiness
Definition: WaterManager.h:121
void ReadEnvironment(XMBElement parent)
Definition: MapReader.cpp:569
#define LDR_CHECK_TIMEOUT(completed_jobs, total_jobs)
Definition: Loader.h:172
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
int ParseCamera()
Definition: MapReader.cpp:1479
void RotateY(float angle)
Definition: Matrix3D.cpp:117
const std::vector< SplineData > & GetAllNodes() const
Definition: NUSpline.h:48
float b
Definition: Overlay.h:57
virtual void SetYRotation(entity_angle_t y)=0
Rotate immediately to the given angle around the upwards axis.
CTerrainTextureEntry * Tex
Definition: MiniPatch.h:38
size_t num_terrain_tex
Definition: MapReader.h:150
CStr8 GetText() const
Definition: XeroXMB.cpp:196
float X
Definition: Vector3D.h:31
u32 PSRETURN
Definition: Errors.h:75
Definition: path.h:75
CColor m_WaterTint
Definition: WaterManager.h:116
float m_FogMax
Definition: LightEnv.h:75
WaterManager * pWaterMan
Definition: MapReader.h:131
float m_Rotation
Direction of sun on the compass, in radians.
Definition: LightEnv.h:54
float Y
Definition: Vector3D.h:31
int LoadScriptSettings()
Definition: MapReader.cpp:1142
bool m_SkipEntities
Definition: MapReader.h:141
virtual entity_id_t GetPlayerByID(int32_t id)=0
float ToFloat() const
Convert to float. May be lossy - float can&#39;t represent all values.
Definition: Fixed.h:161
virtual void SetWaterLevel(entity_pos_t h)=0
Set the height of the water level, as a constant value across the whole map.
u32 file_format_version
Definition: MapReader.h:144
friend class CXMLReader
Definition: MapReader.h:48
void Read(const VfsPath &filename, const char magic[4])
open and read in given file, check magic bits against those given; throw variety of exceptions if ope...
Definition: FileIo.cpp:111
CFixedVector3D position
Definition: Entity.h:29
CStr ReadScriptSettings()
Definition: MapReader.cpp:498
float m_Bloom
Definition: LightEnv.h:77
int Priority
Definition: MiniPatch.h:40
std::wstring templateName
Definition: Entity.h:26
ScriptInterface & GetScriptInterface() const
u16 playerID
Definition: Entity.h:28
#define SAFE_DELETE(p)
delete memory ensuing from new and set the pointer to zero (thus making double-frees safe / a no-op) ...
CScriptValRooted m_ScriptSettings
Definition: MapReader.h:123
bool undefined() const
Returns whether the value is uninitialised or is JSVAL_VOID.
Definition: ScriptVal.cpp:58
size_t UnpackSize()
use UnpackRaw to retrieve 32-bits; returns their value as size_t after converting from little endian ...
Definition: FileIo.cpp:162
bool Eval(const char *code)
void UnpackString(CStr8 &result)
unpack a string from the raw data stream.
Definition: FileIo.cpp:170
CCamera * GetCamera()
Definition: GameView.cpp:390
Definition: Patch.h:48
u16 entityID
Definition: Entity.h:27
static CFixed FromString(const CStr8 &s)
Definition: Fixed.cpp:27
void LoadMap(const VfsPath &pathname, const CScriptValRooted &settings, CTerrain *, WaterManager *, SkyManager *, CLightEnv *, CGameView *, CCinemaManager *, CTriggerManager *, CPostprocManager *pPostproc, CSimulation2 *, const CSimContext *, int playerID, bool skipEntities)
Definition: MapReader.cpp:67
ssize_t m_PatchesPerSide
Definition: MapReader.h:109
#define READ_COLOUR(el, out)
float m_Contrast
Definition: LightEnv.h:77
entity_id_t max_uid
Definition: MapReader.cpp:431
CStr8 GetNamedItem(const int AttributeName) const
Definition: XeroXMB.cpp:259
int el_position
Definition: MapReader.cpp:412
int UnpackTerrain()
Definition: MapReader.cpp:219
CMapReader & m_MapReader
Definition: MapReader.cpp:407
double timer_Time()
Definition: timer.cpp:98
bool Initialize(ssize_t patchesPerSide, const u16 *ptr)
Definition: Terrain.cpp:70
int m_PlayerID
Definition: MapReader.h:140
std::string GetElementString(const int ID) const
Definition: XeroXMB.cpp:148
A simplified syntax for accessing entity components.
Definition: CmpPtr.h:55
CStrW m_ScriptFile
Definition: MapReader.h:122
std::vector< STileDesc > m_Tiles
Definition: MapReader.h:115
intptr_t ssize_t
Definition: wposix_types.h:82
const PSRETURN PSRETURN_File_ReadFailed
#define TIMER(description)
Measures the time taken to execute code up until end of the current scope; displays it via debug_prin...
Definition: timer.h:108
int LoadRMSettings()
Definition: MapReader.cpp:1199
bool GetProperty(jsval obj, const char *name, T &out)
Get the named property on the given object.
#define u16
Definition: types.h:40
void LoadRandomMap(const CStrW &scriptFile, const CScriptValRooted &settings, CTerrain *, WaterManager *, SkyManager *, CLightEnv *, CGameView *, CCinemaManager *, CTriggerManager *, CPostprocManager *pPostproc_, CSimulation2 *, int playerID)
Definition: MapReader.cpp:146
void LoadMapSettings()
Loads the map settings script (called after map is loaded)
void AddNode(const CVector3D &pos, const CVector3D &rotation, float timePeriod)
Definition: NUSpline.cpp:166
NONCOPYABLE(CXMLReader)
void UpdateFrustum(const CBoundingBoxAligned &scissor=CBoundingBoxAligned(CVector3D(-1.0f,-1.0f,-1.0f), CVector3D(1.0f, 1.0f, 1.0f)))
Definition: Camera.cpp:83
size_t cur_terrain_tex
Definition: MapReader.h:149
PSRETURN LoadMap(const VfsPath &pathname)
Try to load a map file.
Definition: MapReader.cpp:342
int GenerateMap()
Definition: MapReader.cpp:1208
int ProgressiveRead()
Definition: MapReader.cpp:1074
#define GET_TERRAIN_PROPERTY(val, prop, out)
void Init(const VfsPath &xml_filename)
Definition: MapReader.cpp:444
void ReadCamera(XMBElement parent)
Definition: MapReader.cpp:766
XMBElement GetRoot() const
Definition: XeroXMB.cpp:84
#define u32
Definition: types.h:41
Path ChangeExtension(Path extension) const
Definition: path.h:185
int LoadPlayerSettings()
Definition: MapReader.cpp:1155
float m_ReflectionTintStrength
Definition: WaterManager.h:123
void GenerateMap(const VfsPath &scriptFile, const std::string &settings)
Start the map generator thread.
int UnpackMap()
Definition: MapReader.cpp:205
virtual CFixedVector3D GetPosition()=0
Returns the current x,y,z position (no interpolation).
CXeromyces xmb_file
Definition: MapReader.cpp:405
CPatch * GetPatch(ssize_t i, ssize_t j) const
Definition: Terrain.cpp:283
CLightEnv * pLightEnv
Definition: MapReader.h:134
CTriggerManager * pTrigMan
Definition: MapReader.h:137
CXMLReader(const VfsPath &xml_filename, CMapReader &mapReader)
Definition: MapReader.cpp:393
virtual void JumpTo(entity_pos_t x, entity_pos_t z)=0
Move immediately to the given location, with no interpolation.
float m_FogFactor
Definition: LightEnv.h:74
bool VfsFileExists(const VfsPath &pathname)
Definition: Filesystem.cpp:34
virtual void ReloadTerrain()=0
Call when the underlying CTerrain has been modified behind our backs.
Definition: Entity.h:24
entity_id_t AddEntity(const std::wstring &templateName)
Construct a new entity and add it to the world.
int entity_idx
Definition: MapReader.cpp:425
void SetXRotation(float angle)
Definition: Matrix3D.cpp:61
CColor m_WaterColor
Definition: WaterManager.h:74
float m_Saturation
Definition: LightEnv.h:77
CMiniPatch m_MiniPatches[PATCH_SIZE][PATCH_SIZE]
Definition: Patch.h:66
CMatrix3D m_Orientation
Definition: Camera.h:112
shared_ptr< ScriptInterface::StructuredClone > GetResults()
Get random map data, according to this format: http://trac.wildfiregames.com/wiki/Random_Map_Generato...
float m_Brightness
Definition: LightEnv.h:77
entity_id_t m_StartingCameraTarget
Definition: MapReader.h:145
static CFixed FromFloat(float n)
Definition: Fixed.h:141
jsval get() const
Returns the current value (or JSVAL_VOID if uninitialised).
Definition: ScriptVal.cpp:45
float Z
Definition: Vector3D.h:31
const CSimContext * pSimContext
Definition: MapReader.h:139
Abstraction around a SpiderMonkey JSContext.
CSimulation2 * pSimulation2
Definition: MapReader.h:138
#define debug_warn(expr)
display the error dialog with the given text.
Definition: debug.h:324
int ApplyData()
Definition: MapReader.cpp:268
CFixedVector3D rotation
Definition: Entity.h:30
#define GET_CAMERA_PROPERTY(val, prop, out)
void SetSkySet(const CStrW &name)
GetSkySet(): Set the sky set name, potentially loading the textures.
Definition: SkyManager.cpp:179
int el_orientation
Definition: MapReader.cpp:412
void RegMemFun(T *this_, int(T::*func)(void), const wchar_t *description, int estimated_duration_ms)
Definition: LoaderThunks.h:67
int DelayLoadFinished()
Definition: MapReader.cpp:1186
bool SetProperty(jsval obj, const char *name, const T &value, bool constant=false, bool enumerate=true)
Set the named property on the given object.
void ReadCinema(XMBElement parent)
Definition: MapReader.cpp:815
u16 * GetHeightMap() const
Definition: Terrain.h:103
#define DEGTORAD(a)
Definition: MathUtil.h:21
int ReadEntities(XMBElement parent, double end_time)
Definition: MapReader.cpp:935
Class CLightEnv: description of a lighting environment - contains all the necessary parameters for re...
Definition: LightEnv.h:36
int LoadMapSettings()
Definition: MapReader.cpp:1163
XMBElement Item(const int id)
Definition: XeroXMB.cpp:233
jsval ReadStructuredClone(const shared_ptr< StructuredClone > &ptr)
const entity_id_t INVALID_ENTITY
Invalid entity ID.
Definition: Entity.h:36
PIVFS g_VFS
Definition: Filesystem.cpp:30
CGameView * pGameView
Definition: MapReader.h:135
void SetStartupScript(const std::string &script)
Set a startup script, which will get executed before the first turn.
virtual void SetControlGroup(entity_id_t group)=0
Change the control group that the entity belongs to.
u32 entity_id_t
Entity ID type.
Definition: Entity.h:24
bool only_xml
Definition: MapReader.h:143
int el_template
Definition: MapReader.cpp:411
CVector3D GetFocus() const
Definition: Camera.cpp:289
CTerrain * pTerrain
Definition: MapReader.h:130
CVector3D Rotation
Definition: NUSpline.h:33
const ssize_t PATCH_SIZE
Definition: Patch.h:34
CXMLReader * xml_reader
Definition: MapReader.h:152
VfsPath filename_xml
Definition: MapReader.h:142
JSContext * GetContext() const
void ResetCameraTarget(const CVector3D &target)
Definition: GameView.cpp:988
virtual void SetActorSeed(u32 seed)=0
Set actor seed for random variations and reload model.
#define AT(x)
void SetPostEffect(CStrW name)
void debug_printf(const wchar_t *fmt,...)
write a formatted string to the debug channel, subject to filtering (see below).
Definition: debug.cpp:142
float r
Definition: Overlay.h:57
int GetNodeName() const
Definition: XeroXMB.cpp:166
void LoadPlayerSettings(bool newPlayers)
Loads the player settings script (called before map is loaded)
Class WaterManager: Maintain water settings and textures.
Definition: WaterManager.h:49
CColor m_ReflectionTint
Definition: WaterManager.h:122
Class SkyManager: Maintain sky settings and textures, and render the sky.
Definition: SkyManager.h:30