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
director_generic.cpp
Go to the documentation of this file.
1 #include "config.h"
2 
3 #ifdef HAVE_PYTHON
4 #include <Python.h>
5 #endif
6 
7 #include "cmd/unit_generic.h"
8 #include "cmd/ai/order.h"
9 
10 #include "configxml.h"
11 #include "gfx/cockpit_generic.h"
12 
13 #include "python/python_class.h"
14 
15 #include <boost/version.hpp>
16 #if BOOST_VERSION != 102800
17 #include <boost/python/class.hpp>
18 #else
19 #include <boost/python/detail/extension_class.hpp>
20 #endif
21 
22 #include "networking/netserver.h"
23 
24 #include "pythonmission.h"
25 #include "mission.h"
26 #include "savegame.h"
27 #include "gnuhash.h"
28 
29 using std::cout;
30 using std::cerr;
31 using std::endl;
33 
34 float getSaveData( int whichcp, const string &key, unsigned int num )
35 {
36  if ( whichcp < 0 || (unsigned int) whichcp >= _Universe->numPlayers() )
37  return 0;
38  vector< float > *ans = &( _Universe->AccessCockpit( whichcp )->savegame->getMissionData( key ) );
39  if ( num >= ans->size() )
40  return 0;
41  return (*ans)[num];
42 }
43 
44 const vector< float > &getSaveData( int whichcp, const string &key )
45 {
46  static vector< float > empty;
47  if ( whichcp < 0 || (unsigned int) whichcp >= _Universe->numPlayers() )
48  return empty;
49  return _Universe->AccessCockpit( whichcp )->savegame->getMissionData( key );
50 }
51 
52 string getSaveString( int whichcp, const string &key, unsigned int num )
53 {
54  if ( whichcp < 0 || (unsigned int) whichcp >= _Universe->numPlayers() )
55  return "";
56  vector< std::string > *ans = &( _Universe->AccessCockpit( whichcp )->savegame->getMissionStringData( key ) );
57  if ( num >= ans->size() )
58  return "";
59  return (*ans)[num];
60 }
61 unsigned int getSaveDataLength( int whichcp, const string &key )
62 {
63  if ( whichcp < 0 || (unsigned int) whichcp >= _Universe->numPlayers() )
64  return 0;
65  return _Universe->AccessCockpit( whichcp )->savegame->getMissionDataLength( key );
66 }
67 unsigned int getSaveStringLength( int whichcp, const string &key )
68 {
69  if ( whichcp < 0 || (unsigned int) whichcp >= _Universe->numPlayers() )
70  return 0;
71  return _Universe->AccessCockpit( whichcp )->savegame->getMissionStringDataLength( key );
72 }
73 unsigned int pushSaveData( int whichcp, const string &key, float val )
74 {
75  if ( whichcp < 0 || (unsigned int) whichcp >= _Universe->numPlayers() )
76  return 0;
77  vector< float > *ans = &( ( _Universe->AccessCockpit( whichcp )->savegame->getMissionData( key ) ) );
78  if (SERVER)
80  ans->size(), &key, NULL, NULL, &val );
81  ans->push_back( val );
82  return ans->size()-1;
83 }
84 
85 unsigned int eraseSaveData( int whichcp, const string &key, unsigned int index )
86 {
87  if ( whichcp < 0 || (unsigned int) whichcp >= _Universe->numPlayers() )
88  return 0;
89  vector< float > *ans = &( ( _Universe->AccessCockpit( whichcp )->savegame->getMissionData( key ) ) );
90  if ( index < ans->size() ) {
91  if (SERVER)
93  index, &key, NULL, NULL, NULL );
94  ans->erase( ans->begin()+index );
95  }
96  return ans->size();
97 }
98 
99 unsigned int clearSaveData( int whichcp, const string &key )
100 {
101  if ( whichcp < 0 || (unsigned int) whichcp >= _Universe->numPlayers() )
102  return 0;
103  vector< float > *ans = &( ( _Universe->AccessCockpit( whichcp )->savegame->getMissionData( key ) ) );
104  int ret = ans->size();
105  if (!ret) return 0;
106  if (SERVER)
108  -1, &key, NULL, NULL, NULL );
109  ans->clear();
110  return ret;
111 }
112 
113 unsigned int pushSaveString( int whichcp, const string &key, const string &value )
114 {
115  if ( whichcp < 0 || (unsigned int) whichcp >= _Universe->numPlayers() )
116  return 0;
117  vector< std::string > *ans = &( ( _Universe->AccessCockpit( whichcp )->savegame->getMissionStringData( key ) ) );
118  if (SERVER)
120  ans->size(), &key, NULL, &value, NULL );
121  ans->push_back( std::string( value ) );
122  return ans->size()-1;
123 }
124 
125 void putSaveString( int whichcp, const string &key, unsigned int num, const string &val )
126 {
127  if ( whichcp < 0 || (unsigned int) whichcp >= _Universe->numPlayers() )
128  return;
129  vector< std::string > *ans = &( ( _Universe->AccessCockpit( whichcp )->savegame->getMissionStringData( key ) ) );
130  if ( num < ans->size() ) {
131  if (SERVER)
133  num, &key, NULL, &val, NULL );
134  (*ans)[num] = val;
135  }
136 }
137 
138 void putSaveData( int whichcp, const string &key, unsigned int num, float val )
139 {
140  if ( whichcp < 0 || (unsigned int) whichcp >= _Universe->numPlayers() )
141  return;
142  vector< float > *ans = &( ( _Universe->AccessCockpit( whichcp )->savegame->getMissionData( key ) ) );
143  if ( num < ans->size() ) {
144  if (SERVER)
146  num, &key, NULL, NULL, &val );
147  (*ans)[num] = val;
148  }
149 }
150 
151 unsigned int eraseSaveString( int whichcp, const string &key, unsigned int index )
152 {
153  if ( whichcp < 0 || (unsigned int) whichcp >= _Universe->numPlayers() )
154  return 0;
155  vector< std::string > *ans = &( ( _Universe->AccessCockpit( whichcp )->savegame->getMissionStringData( key ) ) );
156  if ( index < ans->size() ) {
157  if (SERVER)
159  index, &key, NULL, NULL, NULL );
160  ans->erase( ans->begin()+index );
161  }
162  return ans->size();
163 }
164 
165 unsigned int clearSaveString( int whichcp, const string &key )
166 {
167  if ( whichcp < 0 || (unsigned int) whichcp >= _Universe->numPlayers() )
168  return 0;
169  vector< std::string > *ans = &( ( _Universe->AccessCockpit( whichcp )->savegame->getMissionStringData( key ) ) );
170  int ret = ans->size();
171  if (!ret) return 0;
172  if (SERVER)
174  -1, &key, NULL, NULL, NULL );
175  ans->clear();
176  return ret;
177 }
178 
179 vector< string > loadStringList( int playernum, const string &mykey )
180 {
181  if ( playernum < 0 || (unsigned int) playernum >= _Universe->numPlayers() )
182  return vector< string > ();
183 
184  SaveGame *savegame = _Universe->AccessCockpit( playernum )->savegame;
185  vector< string >rez;
186 
187  const vector< string > &ans = savegame->readMissionStringData( mykey );
188  if (ans.size() > 0) {
189  /* This is the modern way to store string data: as strings */
190  rez.reserve(ans.size());
191  rez.insert(rez.end(), ans.begin(), ans.end());
192  } else {
193  /* This variant loads it from float data, converting to character data.
194  It's a legacy variant, highly and unpleasantly convoluted and sub-performant,
195  but we must support it to be compatible with old savegames */
196  const vector< float > &ans = savegame->readMissionData( mykey );
197  int lengt = ans.size();
198  rez.reserve(ans.size());
199  if (lengt >= 1) {
200  string curstr;
201  int length = (int)ans[0];
202  for (int j = 0; j < length && j < lengt; j++) {
203  char myint = (char)ans[j+1];
204  if (myint != '\0') {
205  curstr += myint;
206  } else {
207  rez.push_back( curstr );
208  curstr = "";
209  }
210  }
211  }
212  }
213  return rez;
214 }
215 
216 const vector< string >& getStringList( int playernum, const string &mykey )
217 {
218  if ( playernum < 0 || (unsigned int) playernum >= _Universe->numPlayers() ) {
219  static const vector<string> empty;
220  return empty;
221  }
222 
223  SaveGame *savegame = _Universe->AccessCockpit( playernum )->savegame;
224 
225  /* Should check old-style string lists, but it would defeat the purpose
226  of this fast getter. Besides, any functionality that uses this one is
227  using the new-style string lists, so we're cool (or ought to be) */
228  return savegame->readMissionStringData( mykey );
229 }
230 
231 void saveStringList( int playernum, const string &mykey, const vector< string > &names )
232 {
233  if ( playernum < 0 || (unsigned int) playernum >= _Universe->numPlayers() )
234  return;
235 
236  SaveGame *savegame = _Universe->AccessCockpit( playernum )->savegame;
237 
238  // Erase old-style string lists
239  if (savegame->getMissionDataLength(mykey) != 0)
240  clearSaveData(playernum, mykey);
241 
242  vector< string > &ans = savegame->getMissionStringData( mykey );
243  clearSaveString(playernum, mykey);
244  for (vector<string>::const_iterator i = names.begin(); i != names.end(); ++i) {
245  if (SERVER)
247  ans.size(), &mykey, NULL, &*i, NULL );
248  ans.push_back( *i );
249  }
250 }
251 
252 void saveDataList( int whichcp, const string &key, const vector< float > &values )
253 {
254  if ( whichcp < 0 || (unsigned int) whichcp >= _Universe->numPlayers() )
255  return;
256 
257  clearSaveData(whichcp, key);
258 
259  vector< float > &ans = _Universe->AccessCockpit( whichcp )->savegame->getMissionData( key );
260  for (vector<float>::const_iterator i = values.begin(); i != values.end(); ++i) {
261  if (SERVER)
263  ans.size(), &key, NULL, NULL, &*i );
264  ans.push_back( *i );
265  }
266 }
267 
268 static float getSaveDataPy( int whichcp, string key, unsigned int num )
269 {
270  return getSaveData(whichcp, key, num);
271 }
272 
273 static string getSaveStringPy( int whichcp, string key, unsigned int num )
274 {
275  return getSaveString(whichcp, key, num);
276 }
277 
278 static unsigned int getSaveDataLengthPy( int whichcp, string key )
279 {
280  return getSaveDataLength(whichcp, key);
281 }
282 
283 static unsigned int getSaveStringLengthPy( int whichcp, string key )
284 {
285  return getSaveStringLength(whichcp, key);
286 }
287 
288 static unsigned int pushSaveDataPy( int whichcp, string key, float val )
289 {
290  return pushSaveData(whichcp, key, val);
291 }
292 
293 static unsigned int eraseSaveDataPy( int whichcp, string key, unsigned int index )
294 {
295  return eraseSaveData(whichcp, key, index);
296 }
297 
298 static unsigned int clearSaveDataPy( int whichcp, string key )
299 {
300  return clearSaveData(whichcp, key);
301 }
302 
303 static unsigned int pushSaveStringPy( int whichcp, string key, string value )
304 {
305  return pushSaveString(whichcp, key, value);
306 }
307 
308 static void putSaveStringPy( int whichcp, string key, unsigned int num, string val )
309 {
310  putSaveString(whichcp, key, num, val);
311 }
312 
313 static void putSaveDataPy( int whichcp, string key, unsigned int num, float val )
314 {
315  putSaveData(whichcp, key, num, val);
316 }
317 
318 static unsigned int eraseSaveStringPy( int whichcp, string key, unsigned int index )
319 {
320  return eraseSaveString(whichcp, key, index);
321 }
322 
323 static unsigned int clearSaveStringPy( int whichcp, string key )
324 {
325  return clearSaveString(whichcp, key);
326 }
327 
328 static vector< string >loadStringListPy( int playernum, string mykey )
329 {
330  return loadStringList(playernum, mykey);
331 }
332 
333 static void saveStringListPy( int playernum, string mykey, vector< string > names )
334 {
335  saveStringList(playernum, mykey, names);
336 }
337 
338 
339 PYTHON_BEGIN_MODULE( Director )
341 PYTHON_DEFINE_METHOD_DEFAULT( Class, &PythonMissionBaseClass::Pickle, "Pickle", pythonMission::default_Pickle );
342 PYTHON_DEFINE_METHOD_DEFAULT( Class, &PythonMissionBaseClass::UnPickle, "UnPickle", pythonMission::default_UnPickle );
343 PYTHON_DEFINE_METHOD_DEFAULT( Class, &PythonMissionBaseClass::Execute, "Execute", pythonMission::default_Execute );
344 PYTHON_END_CLASS( Director, pythonMission )
359 PYTHON_END_MODULE( Director )
360 
362 {
363  Python::reseterrors();
364  PYTHON_INIT_MODULE( Director );
365  Python::reseterrors();
366 }
367 
368 void Mission::loadModule( string modulename )
369 {
370  missionNode *node = director;
371 
372  debug( 3, node, SCRIPT_PARSE, "loading module "+modulename );
373 
374  cout<<" loading module "<<modulename<<endl;
375 
376  string filename = "modules/"+modulename+".module";
377  missionNode *import_top = importf->LoadXML( filename.c_str() );
378  if (import_top == NULL) {}
379  import_top->Tag( &tagmap );
380 
381  doModule( import_top, SCRIPT_PARSE );
382 }
384 {
385  missionNode *node = director;
386  while (import_stack.size() > 0) {
387  string importname = import_stack.back();
388  import_stack.pop_back();
389 
390  missionNode *module = runtime.modules[importname];
391  if (module == NULL)
392  loadModule( importname );
393  else
394  debug( 3, node, SCRIPT_PARSE, "already have module "+importname );
395  }
396 }
397 
398 void Mission::RunDirectorScript( const string &script )
399 {
400  runScript( director, script, 0 );
401 }
402 bool Mission::runScript( missionNode *module_node, const string &scriptname, unsigned int classid )
403 {
404  if (module_node == NULL)
405  return false;
406  missionNode *script_node = module_node->script.scripts[scriptname];
407  if (script_node == NULL)
408  return false;
409  runtime.cur_thread->module_stack.push_back( module_node );
410  runtime.cur_thread->classid_stack.push_back( classid );
411 
412  varInst *vi = doScript( script_node, SCRIPT_RUN );
413  deleteVarInst( vi );
414 
415  runtime.cur_thread->classid_stack.pop_back();
416  runtime.cur_thread->module_stack.pop_back();
417  return true;
418 }
419 
420 bool Mission::runScript( string modulename, const string &scriptname, unsigned int classid )
421 {
422  return runScript( runtime.modules[modulename], scriptname, classid );
423 }
425 {
426  return gametime;
427 }
428 
429 void Mission::addModule( string modulename )
430 {
431  import_stack.push_back( modulename );
432 }
433 
435 {
436  RunDirectorScript( "initstarsystem" );
437 }
438 
439 std::string Mission::Pickle()
440 {
441  if (!runtime.pymissions)
442  return "";
443  else
444  return runtime.pymissions->Pickle();
445 }
446 void Mission::UnPickle( string pickled )
447 {
448  if (runtime.pymissions)
449  runtime.pymissions->UnPickle( pickled );
450 }
451 
453 {
454  cout<<"DIRECTOR START"<<endl;
455 
456  static int st_debuglevel = atoi( vs_config->getVariable( "interpreter", "debuglevel", "0" ).c_str() );
457  static bool st_start_game = XMLSupport::parse_bool( vs_config->getVariable( "interpreter", "startgame", "true" ) );
458  static bool st_do_trace = XMLSupport::parse_bool( vs_config->getVariable( "interpreter", "trace", "false" ) );
459 
460  debuglevel = st_debuglevel;
461  start_game = st_start_game;
462  do_trace = st_do_trace;
463 
464  vi_counter = 0;
465  old_vi_counter = 0;
466 
467  olist_counter = 0;
468  old_olist_counter = 0;
469 
470  string_counter = 0;
471  old_string_counter = 0;
472  missionThread *main_thread = new missionThread;
473  runtime.thread_nr = 0;
474  runtime.threads.push_back( main_thread );
475  runtime.cur_thread = main_thread;
476 
477  director = NULL;
478  std::string doparse = node->attr_value( "do_parse" );
479  if ( !doparse.empty() )
480  if (XMLSupport::parse_bool( doparse ) == false)
481  return;
482  cout<<"parsing declarations for director"<<endl;
483 
484  parsemode = PARSE_DECL;
485 
486  doModule( node, SCRIPT_PARSE );
487 
488  importf = new easyDomFactory< missionNode > ();
489 
491 
492  parsemode = PARSE_FULL;
493 
494  doModule( node, SCRIPT_PARSE );
495 
496  vsUMap< string, missionNode* >::iterator iter;
497  for (iter = runtime.modules.begin(); iter != runtime.modules.end(); iter++) {
498  string mname = (*iter).first;
499  missionNode *mnode = (*iter).second;
500  if (mname != "director") {
501  cout<<" parsing full module "<<mname<<endl;
502  doModule( mnode, SCRIPT_PARSE );
503  }
504  }
505 }
507 {
509  if (nextpythonmission) {
510  //CAUSES AN UNRESOLVED EXTERNAL SYMBOL FOR PythonClass::last_instance ?!?!
511 #ifndef _WIN32
512  char *tmp = nextpythonmission;
513  while (*tmp) {
514  if (tmp[0] == '\r') tmp[0] = '\n';
515  tmp++;
516  }
517 #endif
518  runtime.pymissions = ( pythonMission::FactoryString( nextpythonmission ) );
519  delete[] nextpythonmission; //delete the allocated memory
520  nextpythonmission = NULL;
521  if ( !this->unpickleData.empty() ) {
522  if (runtime.pymissions) {
523  runtime.pymissions->UnPickle( unpickleData );
524  unpickleData = "";
525  }
526  }
527  }
528  if (director == NULL)
529  return;
530  RunDirectorScript( "initgame" );
531 }
532