Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
galaxy_xml.cpp
Go to the documentation of this file.
1 /*
2  * Vega Strike
3  * Copyright (C) 2001-2002 Daniel Horn
4  *
5  * http://vegastrike.sourceforge.net/
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21 
22 /*
23  * Daniel Horn
24  */
25 
26 #include <expat.h>
27 #include "xml_support.h"
28 #include "vsfilesystem.h"
29 #include "vs_globals.h"
30 
31 #include "galaxy_xml.h"
32 #include "galaxy_gen.h"
33 #ifdef WRITEGALAXYCOORDS
34 #include "gfx/nav/navscreen.h"
35 #endif
36 #include <float.h>
37 using namespace XMLSupport;
38 using namespace VSFileSystem;
39 
40 namespace GalaxyXML
41 {
43 {
49  VAR,
54 };
56  EnumMap::Pair( "UNKNOWN", UNKNOWN ),
57  EnumMap::Pair( "Galaxy", GALAXY ),
58  EnumMap::Pair( "Systems", SYSTEMS ),
59  EnumMap::Pair( "Sector", SECTOR ),
60  EnumMap::Pair( "System", SYSTEM ),
61  EnumMap::Pair( "Planets", PLANETS ),
62  EnumMap::Pair( "Planet", PLANET ),
63  EnumMap::Pair( "Var", VAR )
64 };
66  EnumMap::Pair( "UNKNOWN", UNKNOWN ),
67  EnumMap::Pair( "name", NAME ),
68  EnumMap::Pair( "value", VALUE )
69 };
70 
73 class XML
74 {
75 public:
77  std::vector< std::string >stak;
78 };
79 void beginElement( void *userdata, const XML_Char *nam, const XML_Char **atts )
80 {
81  AttributeList::const_iterator iter;
82  XML *xml = (XML*) userdata;
83  string tname( nam );
84  AttributeList attributes( atts );
85  GalaxyNames elem = (GalaxyNames) element_map.lookup( tname );
86  GalaxyNames attr;
87  string name;
88  string value;
89  switch (elem)
90  {
91  case GALAXY:
92  break;
93  case SYSTEMS:
94  break;
95  case PLANETS:
96  xml->stak.push_back( "<planets>" );
97  xml->g->addSection( xml->stak );
98  break;
99  case SECTOR:
100  case SYSTEM:
101 
102  case PLANET:
103  for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
104  attr = (GalaxyNames) attribute_map.lookup( (*iter).name );
105  switch (attr)
106  {
107  case NAME:
108  name = (*iter).value;
109  break;
110  default:
111  break;
112  }
113  }
114  xml->stak.push_back( name );
115  xml->g->addSection( xml->stak );
116 
117  break;
118  case VAR:
119  for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
120  attr = (GalaxyNames) attribute_map.lookup( (*iter).name );
121  switch (attr)
122  {
123  case NAME:
124  name = (*iter).value;
125  break;
126  case VALUE:
127  value = (*iter).value;
128  break;
129  default:
130  break;
131  }
132  }
133  xml->g->setVariable( xml->stak, name, value );
134  break;
135  default:
136  break;
137  }
138 }
139 void endElement( void *userdata, const XML_Char *nam )
140 {
141  XML *xml = (XML*) userdata;
142  string name( nam );
143  GalaxyNames elem = (GalaxyNames) element_map.lookup( name );
144  switch (elem)
145  {
146  case GALAXY:
147  case SYSTEMS:
148  break;
149  case VAR:
150  break;
151  case SECTOR:
152  case SYSTEM:
153  case PLANETS:
154  case PLANET:
155  xml->stak.pop_back();
156  break;
157  default:
158  break;
159  }
160 }
161 }
162 
163 using namespace GalaxyXML;
164 SGalaxy::~SGalaxy()
165 {
166  if (subheirarchy)
167  delete subheirarchy;
168  subheirarchy = NULL;
169 }
170 SGalaxy&SGalaxy::operator=( const SGalaxy &g )
171 {
172  if (g.subheirarchy) {
173  SubHeirarchy *temp = new SubHeirarchy( *g.subheirarchy );
174  if (subheirarchy)
175  delete subheirarchy;
176  subheirarchy = temp;
177  } else if (subheirarchy) {
178  delete subheirarchy;
179  subheirarchy = NULL;
180  }
181  data = g.data;
182  return *this;
183 }
184 SGalaxy::SGalaxy( const SGalaxy &g ) : data( g.data )
185 {
186  if (g.subheirarchy)
188  else
189  subheirarchy = NULL;
190 }
191 void SGalaxy::processSystem( const string &sys, const QVector &coords )
192 {
193  string sector = getStarSystemSector( sys );
194  string sys2 = getStarSystemName( sys );
195  char coord[65536];
196  sprintf( coord, "%lf %lf %lf", coords.i, coords.j, coords.k );
197  string ret = getVariable( sector, sys2, "" );
198  if (ret.length() == 0)
199  setVariable( sector, sys2, "xyz", coord );
200 }
201 void SGalaxy::processGalaxy( const string &sys )
202 {
203 #ifdef WRITEGALAXYCOORDS
204  NavigationSystem::SystemIterator si( sys, 256000 );
205  while ( !si.done() ) {
206  string sys = *si;
207  processSystem( sys, si.Position() );
208  ++si;
209  }
210 #endif
211 }
212 void dotabs( VSFileSystem::VSFile &f, unsigned int tabs )
213 {
214  for (unsigned int i = 0; i < tabs; ++i)
215  f.Fprintf( "\t" );
216 }
217 void SGalaxy::writeSector( VSFileSystem::VSFile &f, int tabs, const string &sectorType, SGalaxy *planet_types ) const
218 {
219  StringMap::const_iterator dat;
220  for (dat = data.begin(); dat != data.end(); ++dat)
221  if ( (*dat).first != "jumps" ) {
222  dotabs( f, tabs );
223  f.Fprintf( "<var name=\"%s\" value=\"%s\"/>\n", (*dat).first.c_str(), (*dat).second.c_str() );
224  }
225  dat = data.find( std::string( "jumps" ) );
226  if ( dat != data.end() ) {
227  dotabs( f, tabs );
228  f.Fprintf( "<var name=\"jumps\" value=\"%s\"/>\n", (*dat).second.c_str() );
229  }
230  if (subheirarchy) {
231  for (SubHeirarchy::const_iterator it = subheirarchy->begin(); it != subheirarchy->end(); ++it)
232  if (&(*it).second != planet_types) {
233  dotabs( f, tabs );
234  f.Fprintf( "<%s name=\"%s\">\n", sectorType.c_str(), (*it).first.c_str() );
235  (*it).second.writeSector( f, tabs+1, sectorType, planet_types );
236  dotabs( f, tabs );
237  f.Fprintf( "</%s>\n", sectorType.c_str() );
238  }
239  }
240 }
241 void SGalaxy::writeGalaxy( VSFile &f ) const
242 {
243  f.Fprintf( "<galaxy>\n<systems>\n" );
244  writeSector( f, 1, "sector", NULL );
245  f.Fprintf( "</systems>\n" );
246  f.Fprintf( "</galaxy>\n" );
247 }
248 
249 void Galaxy::writeGalaxy( VSFile &f ) const
250 {
251  f.Fprintf( "<galaxy>\n<systems>\n" );
252  writeSector( f, 1, "sector", planet_types );
253  f.Fprintf( "</systems>\n" );
254  if (planet_types) {
255  f.Fprintf( "<planets>\n" );
256  planet_types->writeSector( f, 1, "planet", NULL );
257  f.Fprintf( "</planets>\n" );
258  }
259  f.Fprintf( "</galaxy>\n" );
260 }
261 
262 SGalaxy::SGalaxy( const char *configfile )
263 {
264  using namespace VSFileSystem;
265  subheirarchy = NULL;
266  VSFile f;
267  VSError err = f.OpenReadOnly( configfile, UniverseFile );
268  if (err <= Ok) {
270  x.g = this;
271 
272  XML_Parser parser = XML_ParserCreate( NULL );
273  XML_SetUserData( parser, &x );
274  XML_SetElementHandler( parser, &GalaxyXML::beginElement, &GalaxyXML::endElement );
275  XML_Parse( parser, ( f.ReadFull() ).c_str(), f.Size(), 1 );
276  f.Close();
277 
278  XML_ParserFree( parser );
279  } else if (SERVER) {
280  std::cerr<<"!!! ERROR : couldn't find galaxy file : "<<configfile<<std::endl;
281  exit( 1 );
282  }
283 }
284 
286 {
287  if (!subheirarchy)
289  return *subheirarchy;
290 }
291 /* *********************************************************** */
292 
293 /* *********************************************************** */
294 const string& SGalaxy::getVariable( const std::vector< string > &section, const string &name,
295  const string &default_value ) const
296 {
297  const SGalaxy *g = this;
298  for (unsigned int i = 0; i < section.size(); ++i) {
299  if (g->subheirarchy) {
300  SubHeirarchy::const_iterator sub = subheirarchy->find( section[i] );
301  if ( sub != subheirarchy->end() )
302  g = &(*sub).second;
303  else return default_value;
304  } else {return default_value; }}
305  StringMap::const_iterator dat = data.find( name );
306  if ( dat != data.end() )
307  return (*dat).second;
308  return default_value;
309 }
311 {
312  return planet_types;
313 }
314 
315 void SGalaxy::addSection( const std::vector< string > &section )
316 {
317  SubHeirarchy *temp = &getHeirarchy();
318  for (unsigned int i = 0; i < section.size(); ++i)
319  temp = &( (*temp)[section[i]].getHeirarchy() );
320 }
321 void SGalaxy::setVariable( const std::vector< string > &section, const string &name, const string &value )
322 {
323  SGalaxy *g = this;
324  for (unsigned int i = 0; i < section.size(); ++i)
325  g = &g->getHeirarchy()[section[i]];
326  g->data[name] = value;
327 }
328 
329 /* *********************************************************** */
330 
331 bool SGalaxy::setVariable( const string &section, const string &name, const string &value )
332 {
333  getHeirarchy()[section].data[name] = value;
334  return true;
335 }
336 
337 bool SGalaxy::setVariable( const string &section, const string &subsection, const string &name, const string &value )
338 {
339  getHeirarchy()[section].getHeirarchy()[subsection].data[name] = value;
340  return true;
341 }
342 
343 const string& SGalaxy::getRandSystem( const string &sect, const string &def ) const
344 {
345  if (subheirarchy) {
346  const SGalaxy &sector = (*subheirarchy)[sect];
347  if (sector.subheirarchy) {
348  unsigned int size = sector.subheirarchy->size();
349  if (size > 0) {
350  int which = rand()%size;
351  SubHeirarchy::const_iterator i =
352  sector.subheirarchy->begin();
353  while (which > 0)
354  --which, ++i;
355  return (*i).first;
356  }
357  }
358  }
359  return def;
360 }
361 const string& SGalaxy::getVariable( const string &section,
362  const string &subsection,
363  const string &name,
364  const string &defaultvalue ) const
365 {
366 #ifdef WRITEGALAXYCOORDS
367  static bool blah = false;
368  if (!blah) {
369  processGalaxy( "Sol/Sol" );
370  writeGalaxy( "/tmp/outputgalaxy" );
371  blah = true;
372  }
373 #endif
375  SubHeirarchy::const_iterator i;
376  if (s) {
377  i = s->find( section );
378  if ( i != s->end() ) {
379  s = (*i).second.subheirarchy;
380  if (s) {
381  i = s->find( subsection );
382  if ( i != s->end() ) {
383  const SGalaxy *g = &(*i).second;
384  StringMap::const_iterator j = g->data.find( name );
385  if ( j != g->data.end() )
386  return (*j).second;
387  }
388  }
389  }
390  }
391  return defaultvalue;
392 }
393 
394 const string& SGalaxy::getVariable( const string &section, const string &name, const string &defaultvalue ) const
395 {
397  SubHeirarchy::const_iterator i;
398  if (s) {
399  i = s->find( section );
400  if ( i != s->end() ) {
401  const SGalaxy *g = &(*i).second;
402  StringMap::const_iterator j = g->data.find( name );
403  if ( j != g->data.end() )
404  return (*j).second;
405  }
406  }
407  return defaultvalue;
408 }
409 
410 bool Galaxy::setPlanetVariable( const string &name, const string &value )
411 {
412  if (!planet_types)
413  return false;
414  planet_types->data[name] = value;
415  return true;
416 }
417 
418 bool Galaxy::setPlanetVariable( const string &section, const string &name, const string &value )
419 {
420  if (!planet_types)
421  return false;
422  planet_types->getHeirarchy()[section].data[name] = value;
423  return true;
424 }
425 
426 const string& Galaxy::getPlanetVariable( const string &section, const string &name, const string &defaultvalue ) const
427 {
428  SGalaxy *planet_types = &( ( *subheirarchy->find( "<planets>" ) ).second );
429  if (planet_types) {
430  SubHeirarchy::const_iterator i;
431  i = planet_types->subheirarchy->find( section );
432  if ( i == planet_types->subheirarchy->end() ) {
433  return getPlanetVariable( name, defaultvalue );
434  } else {
435  const SGalaxy *g = &(*i).second;
436  StringMap::const_iterator j = g->data.find( name );
437  if ( j == g->data.end() )
438  return getPlanetVariable( name, defaultvalue );
439  else
440  return (*j).second;
441  }
442  }
443  return defaultvalue;
444 }
445 
446 const string& Galaxy::getPlanetVariable( const string &name, const string &defaultvalue ) const
447 {
448  if (planet_types) {
449  StringMap::const_iterator j = planet_types->data.find( name );
450  if ( j != planet_types->data.end() )
451  return (*j).second;
452  }
453  return defaultvalue;
454 }
455 SGalaxy* Galaxy::getInitialPlanetTypes()
456 {
457  if (subheirarchy) {
458  SubHeirarchy::iterator iter = subheirarchy->find( "<planets>" );
459  if ( iter == subheirarchy->end() )
460  return NULL;
461  else
462  return &(*iter).second;
463  }
464  return NULL;
465 }
466 void Galaxy::setupPlanetTypeMaps()
467 {
468  if (planet_types) {
469  SubHeirarchy::iterator i = planet_types->getHeirarchy().begin();
470  for (; i != planet_types->getHeirarchy().end(); ++i) {
471  string name = (*i).first;
472 
473  string val;
474 
475  {
476  static const string _unit("unit");
477  const string &unit = (*i).second[_unit];
478 
479  if (!unit.empty()) {
480  val = unit;
481  } else {
482  static const string _texture("texture");
483  const string &tex = (*i).second[_texture];
484  if (!tex.empty()) {
485  val = tex;
486 
487  // Filter out irrelevant texture bits
488  // We only want the base name of the diffuse map
489  // Texture formats are: <path>/<diffse>.<extension>|<path>/<specular>.<extension>|...
490  string::size_type pipe = val.find_first_of('|');
491  if (pipe != string::npos)
492  val = val.substr( 0, pipe );
493  string::size_type slash = val.find_last_of('/');
494  if (slash != string::npos)
495  val = val.substr( slash+1 );
496  string::size_type dot = val.find_last_of('.');
497  if (dot != string::npos)
498  val = val.substr( 0, dot );
499 
500  static const string numtag = "#num#";
501  static const string::size_type numtaglen = numtag.length();
502  string::size_type tagpos;
503  while (string::npos != (tagpos = val.find(numtag)))
504  val.erase(tagpos, numtaglen);
505  }
506  }
507  }
508 
509  if ( texture2name.find( val ) != texture2name.end() ) {
510  printf( "name conflict %s has texture %s and %s has texture %s\n",
511  name.c_str(),
512  val.c_str(),
513  texture2name[val].c_str(),
514  val.c_str() );
515  } else {
516  texture2name[val] = name;
517  }
518  val = (*i).second["initial"];
519  if ( initial2name.find( val ) != initial2name.end() ) {
520  printf( "name conflict %s has initial %s and %s has initial %s\n",
521  name.c_str(),
522  val.c_str(),
523  initial2name[val].c_str(),
524  val.c_str() );
525  } else {
526  initial2name[val] = name;
527  }
528  }
529  }
530  if ( initial2name.empty() || texture2name.empty() )
531  fprintf( stderr, "Warning, galaxy contains no overarching planet info\n" );
532 }
533 Galaxy::Galaxy( const SGalaxy &g ) : SGalaxy( g )
534 {
535  planet_types = getInitialPlanetTypes();
536  setupPlanetTypeMaps();
537 }
538 Galaxy::Galaxy( const char *configfile ) : SGalaxy( configfile )
539 {
540  planet_types = getInitialPlanetTypes();
541  setupPlanetTypeMaps();
542 }
543