ORTS

ScriptObj.C

Go to the documentation of this file.
00001 /** @file ScriptObj.C
00002     @see ScriptObj.H
00003 
00004     $Id: ScriptObj.C 5279 2007-06-23 02:49:08Z mburo $
00005     $Source$
00006 */
00007 
00008 // This is an ORTS file
00009 // (c) Tim Furtak
00010 // (c) Michael Buro
00011 // licensed under the GPL
00012 
00013 #include "ScriptObj.H"
00014 #include "Blueprints.H"
00015 #include "PlayerInfo.H"
00016 #include "Script.H"
00017 #include "ByteData.H"
00018 
00019 using namespace std;
00020 
00021 #define PARANOID
00022 
00023 set<ScriptObj*> ScriptObj::ptr_list;
00024 
00025 //===================================================================
00026 
00027 IdObjMap ScriptObj::id2obj_map;
00028 ObjIdMap ScriptObj::obj2id_map;
00029 IdFactory ScriptObj::idf(100000);
00030 
00031 Vector<ScriptObj*> ScriptObj::dead_objs;
00032 list<ScriptObj*> ScriptObj::destroyed_objs;
00033 
00034 //===================================================================
00035 
00036 ScriptObj::BasePtr::BasePtr(ScriptObj *s)
00037 {
00038   check_ptr(s);
00039 
00040   p = s;
00041   if (p == 0) {
00042     id = 0;
00043     return;
00044   }
00045   FIND (ScriptObj::obj2id_map, it, p);
00046   if (it == obj2id_map.end()) {
00047     ERR("bad pointer");
00048   }
00049   id = it->second;
00050 }
00051 
00052 //-------------------------------------------------------------------
00053 
00054 ScriptObj::BasePtr::BasePtr(const ScriptObj::BasePtr &ptr)
00055 {
00056   p = ptr.p;
00057   id = ptr.id;
00058   check_ptr(p);
00059 }
00060 
00061 //-------------------------------------------------------------------
00062 
00063 void ScriptObj::BasePtr::reset()
00064 {
00065   p = 0;
00066   id = 0;
00067 }
00068 
00069 //===================================================================
00070 
00071 ScriptObj::Ptr::Ptr(ScriptObj *s) : BasePtr(s)
00072 {
00073   if (!p) return;
00074   p->hard_refs.insert(this);
00075   p->add_ref();
00076 }
00077 
00078 //-------------------------------------------------------------------
00079 
00080 ScriptObj::Ptr::Ptr(const ScriptObj::Ptr &ptr) : BasePtr(ptr)
00081 {
00082   if (!p) return;
00083   p->hard_refs.insert(this);
00084   p->add_ref();
00085 }
00086 
00087 //-------------------------------------------------------------------
00088 
00089 ScriptObj::Ptr& ScriptObj::Ptr::operator=(const ScriptObj::Ptr &ptr)
00090 {
00091   check_ptr(p);
00092   if (p) {
00093     p->hard_refs.erase(this);
00094     p->del_ref();
00095   }
00096   
00097   p = ptr.p;
00098   id = ptr.id;
00099 
00100   check_ptr(p);
00101   if (p) {
00102     p->hard_refs.insert(this);
00103     p->add_ref();
00104   }
00105   return *this;
00106 }
00107 
00108 //-------------------------------------------------------------------
00109 
00110 ScriptObj::Ptr::~Ptr()
00111 {
00112   check_ptr(p);
00113   if (!p) return;
00114   p->hard_refs.erase(this);
00115   p->del_ref();
00116 }
00117 
00118 //-------------------------------------------------------------------
00119 
00120 void ScriptObj::Ptr::save(ostream &os) const
00121 {
00122   ObjId id = ScriptObj::obj2id_map[p];
00123   OS_WRITE(id);
00124 }
00125 
00126 //-------------------------------------------------------------------
00127 
00128 void ScriptObj::Ptr::load(istream &is)
00129 {
00130   ObjId id;
00131   IS_READ(id);
00132   p = ScriptObj::id2obj_map[id];
00133 }
00134 
00135 //===================================================================
00136 
00137 ScriptObj::WPtr::WPtr(ScriptObj *s) : BasePtr(s)
00138 {
00139   if (!p) return;
00140   p->soft_refs.insert(this);
00141 }
00142 
00143 //-------------------------------------------------------------------
00144 
00145 ScriptObj::WPtr::WPtr(const ScriptObj::WPtr &ptr) : BasePtr(ptr)
00146 {
00147   if (!p) return;
00148   p->soft_refs.insert(this);
00149 }
00150 
00151 //-------------------------------------------------------------------
00152 
00153 ScriptObj::WPtr& ScriptObj::WPtr::operator=(const ScriptObj::WPtr &ptr)
00154 {
00155   check_ptr(p);
00156   if (p) {
00157     p->soft_refs.erase(this);
00158   }
00159   
00160   p = ptr.p;
00161   id = ptr.id;
00162 
00163   check_ptr(p);
00164   if (p) {
00165     p->soft_refs.insert(this);
00166   }
00167   return *this;
00168 }
00169 
00170 //-------------------------------------------------------------------
00171 
00172 ScriptObj::WPtr::~WPtr()
00173 {
00174   if (!p) return;
00175   p->soft_refs.erase(this);
00176 }
00177 
00178 //-------------------------------------------------------------------
00179 
00180 void ScriptObj::WPtr::save(ostream &os) const
00181 {
00182   ObjId id = ScriptObj::obj2id_map[p];
00183   OS_WRITE(id);
00184 }
00185 
00186 //-------------------------------------------------------------------
00187 
00188 void ScriptObj::WPtr::load(istream &is)
00189 {
00190   ObjId id;
00191   IS_READ(id);
00192   p = ScriptObj::id2obj_map[id];
00193 }
00194 
00195 //===================================================================
00196 
00197 ScriptObj::ScriptObj()
00198 {
00199   num_refs = 0;
00200   dead = false;
00201   enabled = true;
00202   parent = this;
00203 #ifdef PARANOID
00204   //The relevant types cannot be registered due to some unknown reason: FIND(ptr_list, i, this);
00205   set<ScriptObj*>::iterator i = ptr_list.find(this);
00206   if (i != ptr_list.end()) ERR("already in set?");
00207   ptr_list.insert(this);
00208 #endif
00209 
00210   id = idf.next();
00211   assert(id2obj_map[id] == 0);
00212   id2obj_map[id] = this;
00213   obj2id_map[this] = id;
00214 }
00215 
00216 //-------------------------------------------------------------------
00217 
00218 ScriptObj::~ScriptObj()
00219 {
00220   FORALL (soft_refs, it) {
00221     (*it)->reset();
00222   }
00223   FORALL (hard_refs, it) {
00224     (*it)->reset();
00225   }
00226 
00227   idf.free(id);
00228   id2obj_map.erase(id2obj_map.find(id));
00229   obj2id_map.erase(obj2id_map.find(this));
00230 #ifdef PARANOID
00231   //The relevant types cannot be registered due to some unknown reason: FIND(ptr_list, i, this);
00232   set<ScriptObj*>::iterator it = ptr_list.find(this);
00233   if (it != ptr_list.end()) ptr_list.erase(it);
00234 #endif
00235 }
00236 
00237 //-------------------------------------------------------------------
00238 
00239 void ScriptObj::save(ostream &os) const
00240 {
00241   string s;
00242   ERR("need PlayerInfo data here");
00243   gen_diff(true, true, s, 0);
00244   os << s;
00245 }
00246 
00247 //-------------------------------------------------------------------
00248 
00249 void ScriptObj::load(istream &is)
00250 {
00251   string s;
00252   is >> s;
00253   ByteStream bs(s);
00254   ERR ("need PlayerInfo data here");
00255   apply_diff(bs, 0);
00256 }
00257 
00258 //-------------------------------------------------------------------
00259 
00260 /** Intended for use in saving/loading the game state in combination with set_ids. */
00261 
00262 void ScriptObj::get_ids(Vector<ScriptObj*> &objs, Vector<ObjId> &ids)
00263 {
00264   ids.clear();
00265   objs.clear();
00266 
00267   FORALL (id2obj_map, it) {
00268     ids.push_back(it->first);
00269     objs.push_back(it->second);
00270   }
00271 }
00272 
00273 //-------------------------------------------------------------------
00274 
00275 /** Intended for use in saving/loading the game state in combination with get_ids. */
00276 
00277 void ScriptObj::set_ids(const Vector<ScriptObj*> &objs, const Vector<ObjId> &ids)
00278 {
00279   if (objs.size() != ids.size()) ERR("size mismatch");
00280   id2obj_map.clear();
00281   obj2id_map.clear();
00282   idf.reserve(ids);
00283   FORU (i, objs.size()) {
00284     id2obj_map[ids[i]] = objs[i];
00285     obj2id_map[objs[i]] = ids[i];
00286   }
00287 }
00288 
00289 //-------------------------------------------------------------------
00290 
00291 ObjId ScriptObj::get_obj_id(ScriptObj *s)
00292 {
00293   FIND(obj2id_map, it, s);
00294   if (it == obj2id_map.end()) return 0;
00295   return it->second;
00296 }
00297 
00298 //-------------------------------------------------------------------
00299 
00300 void ScriptObj::kill()
00301 {
00302   if (!dead) dead_objs.push_back(this);
00303   dead = true;
00304 }
00305 
00306 //-------------------------------------------------------------------
00307 
00308 /** Call script destructors for dead objects.
00309     Delete them if they're not being referenced.
00310     NOTE: it's possible for new objects to be added to dead_objs when the destructors are called.
00311 */
00312 
00313 void ScriptObj::collect_dead(std::set<ScriptObj*> &dead)
00314 {
00315   dead.clear();
00316   // note: if new objects are added to dead_objs when the destructors are called
00317   //       then the iterator will be invalidated, so do it this way.
00318   FORU_DYN (i, dead_objs.size()) {
00319     ScriptObj *g = dead_objs[i];
00320     dead.insert(g);
00321     g->destruct();
00322     if (g->get_refs() == 0) {
00323       delete g;
00324     } else {
00325       destroyed_objs.push_back(g);
00326     }
00327   }
00328   dead_objs.clear();
00329 }
00330 
00331 //-------------------------------------------------------------------
00332 
00333 /** Delete dead objects that aren't being referenced. */
00334 
00335 void ScriptObj::collect_destroyed()
00336 {
00337   list<ScriptObj*>::iterator it;
00338   for (it = destroyed_objs.begin(); it != destroyed_objs.end();) {
00339     if ((*it)->get_refs() == 0) {
00340       delete *it;
00341       it = destroyed_objs.erase(it);
00342       continue;
00343     }
00344     ++it;
00345   }
00346 }
00347 
00348 //-------------------------------------------------------------------
00349 
00350 void ScriptObj::check_ptr(ScriptObj *ptr) {
00351 #ifdef PARANOID
00352   if (ptr == 0) return;
00353   if (ptr_list.find(ptr) != ptr_list.end()) return;
00354   cerr << ptr << endl;
00355   volatile int foo = 0;
00356   foo /= foo;
00357   ERR("no such scriptobj");
00358 #endif
00359 }
00360 
00361 //-------------------------------------------------------------------
00362 
00363 bool ScriptObj::has_attr(const string &a) const {
00364   return get_val_ptr(a) != 0;
00365 }
00366 
00367 //-------------------------------------------------------------------
00368 
00369 stype ScriptObj::get_val(const string &a) const {
00370   const stype *p = get_val_ptr(a);
00371   if (p == 0) {
00372     cerr << "object type = " << bp_name() << endl;
00373     ERR2("unknown attribute ", a.c_str());
00374     return stype();
00375   }
00376   return *p;
00377 }
00378 
00379 //-------------------------------------------------------------------
00380 
00381 void ScriptObj::set_val(const string &a, stype v, bool warn) {
00382   stype *p =  get_val_ptr(a);
00383   if (p == 0) {
00384     if (warn) ERR2("unknown attribute", a.c_str());
00385     return;
00386   }
00387   *p = v;
00388 }
00389 
00390 //-------------------------------------------------------------------
00391 
00392 sint4 ScriptObj::get_int(const string &a) const {
00393   const stype *p = get_val_ptr(a);
00394   if (!p) ERR2("unknown attribute", a.c_str());
00395   return p->to_int();
00396 }
00397 
00398 //-------------------------------------------------------------------
00399 
00400 sint4 ScriptObj::get_int_prev(const string &a) const {
00401   stype p = get_val_prev(a);
00402   return p.to_int();
00403 }
00404 
00405 //-------------------------------------------------------------------
00406 
00407 sintptr* ScriptObj::get_int_ptr(const string &a) {
00408   stype *p = get_val_ptr(a);
00409   if (!p) return 0;
00410   if (p->type == stype::NONE) return 0;
00411   if (p->type != stype::INT) ERR2("not integer", a.c_str());
00412   return &p->val.i;
00413 }
00414 
00415 //-------------------------------------------------------------------
00416 
00417 const sintptr* ScriptObj::get_int_ptr(const string &a) const {
00418   const stype *p = get_val_ptr(a);
00419   if (!p) return 0;
00420   if (p->type != stype::INT) ERR2("not integer", a.c_str());
00421   return &p->val.i;
00422 }
00423 
00424 //-------------------------------------------------------------------
00425 
00426 void ScriptObj::set_int(const string &a, sint4 v, bool warn) {
00427   sintptr *p = get_int_ptr(a);
00428   if (!p) {
00429     if (warn) ERR2("unknown attribute", a.c_str());
00430     return;
00431   }
00432   *p = v;
00433 }
00434 
00435 //===================================================================
00436 


Generated on Fri May 18 2012 03:02:44 for ORTS by Doxygen1.7.3