ObjectManager.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2002-2005 The Pentagram team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #include "pent_include.h"
00020 
00021 #include "ObjectManager.h"
00022 
00023 #include <map>
00024 #include "idMan.h"
00025 #include "Object.h"
00026 #include "Item.h"
00027 #include "Actor.h"
00028 #include "Gump.h"
00029 #include "IDataSource.h"
00030 #include "ODataSource.h"
00031 #include "ItemFactory.h"
00032 #include "GUIApp.h"
00033 
00034 #include "MainActor.h"
00035 #include "Egg.h"
00036 #include "MonsterEgg.h"
00037 #include "TeleportEgg.h"
00038 #include "GlobEgg.h"
00039 #include "GameMapGump.h"
00040 #include "DesktopGump.h"
00041 #include "ConsoleGump.h"
00042 #include "AskGump.h"
00043 #include "BarkGump.h"
00044 #include "ContainerGump.h"
00045 #include "PaperdollGump.h"
00046 #include "TextWidget.h"
00047 #include "ButtonWidget.h"
00048 #include "SlidingWidget.h"
00049 #include "MiniStatsGump.h"
00050 #include "MiniMapGump.h"
00051 
00052 ObjectManager* ObjectManager::objectmanager = 0;
00053 
00054 
00055 // a template class  to prevent having to write a load function for
00056 // every object separately
00057 template<class T>
00058 struct ObjectLoader {
00059         static Object* load(IDataSource* ids, uint32 version) {
00060                 T* p = new T();
00061                 bool ok = p->loadData(ids, version);
00062                 if (!ok) {
00063                         delete p;
00064                         p = 0;
00065                 }
00066                 return p;
00067         }
00068 };
00069 
00070 ObjectManager::ObjectManager()
00071 {
00072         con.Print(MM_INFO, "Creating ObjectManager...\n");
00073 
00074         assert(objectmanager == 0);
00075         objectmanager = this;
00076 
00077         setupLoaders();
00078 
00079         objects.resize(65536);
00080 
00082         objIDs = new idMan(256,65534,8192);     // Want range of 256 to 65534
00083         actorIDs = new idMan(1,255,255);
00084 }
00085 
00086 ObjectManager::~ObjectManager()
00087 {
00088         reset();
00089         con.Print(MM_INFO, "Destroying ObjectManager...\n");
00090 
00091         objectmanager = 0;
00092 
00093         delete objIDs;
00094         delete actorIDs;
00095 }
00096 
00097 void ObjectManager::reset()
00098 {
00099         con.Print(MM_INFO, "Resetting ObjectManager...\n");
00100 
00101         unsigned int i;
00102 
00103         for (i = 0; i < objects.size(); ++i) {
00104                 if (objects[i] == 0) continue;
00105 #if 0
00106                 Item* item = p_dynamic_cast<Item*>(objects[i]);
00107                 if (item && item->getParent()) continue; // will be deleted by parent
00108 #endif
00109                 Gump* gump = p_dynamic_cast<Gump*>(objects[i]);
00110                 if (gump && gump->GetParent()) continue; // will be deleted by parent
00111                 delete objects[i];
00112         }
00113 
00114         for (i = 0; i < objects.size(); ++i) {
00115                 assert(objects[i] == 0);
00116         }
00117 
00118 
00119         objects.clear();
00120         objects.resize(65536);
00121         objIDs->clearAll();
00122         objIDs->reserveID(666);         // 666 is reserved for the Guardian Bark hack
00123         actorIDs->clearAll();
00124 }
00125 
00126 void ObjectManager::objectStats()
00127 {
00128         unsigned int i, npccount = 0, objcount = 0;
00129 
00131         for (i = 1; i < 256; i++) {
00132                 if (objects[i] != 0)
00133                         npccount++;
00134         }
00135         for (i = 256; i < objects.size(); i++) {
00136                 if (objects[i] != 0)
00137                         objcount++;
00138         }
00139 
00140         pout << "Object memory stats:" << std::endl;
00141         pout << "NPCs       : " << npccount << "/255" << std::endl;
00142         pout << "Objects    : " << objcount << "/65279" << std::endl;
00143 }
00144 
00145 void ObjectManager::objectTypes()
00146 {
00147         pout << "Current object types:" << std::endl;
00148         std::map<std::string, unsigned int> objecttypes;
00149         for (unsigned int i = 1; i < objects.size(); ++i) {
00150                 Object* o = objects[i];
00151                 if (!o) continue;
00152                 objecttypes[o->GetClassType().class_name]++;
00153         }
00154 
00155         std::map<std::string, unsigned int>::iterator iter;
00156         for (iter = objecttypes.begin(); iter != objecttypes.end(); ++iter) {
00157                 pout << (*iter).first << ": " << (*iter).second << std::endl;
00158         }
00159 }
00160 
00161 void ObjectManager::ConCmd_objectTypes(const Console::ArgvType & /*argv*/)
00162 {
00163         ObjectManager::get_instance()->objectTypes();
00164 }
00165 
00166 void ObjectManager::ConCmd_objectInfo(const Console::ArgvType& argv)
00167 {
00168         if (argv.size() != 2) {
00169                 pout << "usage: objectInfo <objectnum>" << std::endl;
00170                 return;
00171         }
00172 
00173         ObjectManager* objman = ObjectManager::get_instance();
00174 
00175         ObjId objid = strtol(argv[1].c_str(), 0, 0);
00176 
00177         Object* obj = objman->getObject(objid);
00178         if (obj == 0) {
00179                 bool reserved = false;
00180                 if (objid >= 256) // CONSTANT!
00181                         reserved = objman->objIDs->isIDUsed(objid);
00182                 else
00183                         reserved = objman->actorIDs->isIDUsed(objid);
00184                 if (reserved)
00185                         pout << "Reserved objid: " << objid << std::endl;
00186                 else
00187                         pout << "No such object: " << objid << std::endl;
00188         } else {
00189                 obj->dumpInfo();
00190         }
00191 }
00192 
00193 
00194 uint16 ObjectManager::assignObjId(Object* obj, ObjId new_objid)
00195 {
00196         if (new_objid == 0xFFFF)
00197                 new_objid = objIDs->getNewID();
00198         else
00199                 objIDs->reserveID(new_objid);
00200 
00201         // failure???
00202         if (new_objid != 0) {
00203                 assert(objects[new_objid] == 0);
00204                 objects[new_objid] = obj;
00205         }
00206         return new_objid;
00207 }
00208 
00209 uint16 ObjectManager::assignActorObjId(Actor* actor, ObjId new_objid)
00210 {
00211         if (new_objid == 0xFFFF)
00212                 new_objid = actorIDs->getNewID();
00213         else
00214                 actorIDs->reserveID(new_objid);
00215 
00216         // failure???
00217         if (new_objid != 0) {
00218                 assert(objects[new_objid] == 0);
00219                 objects[new_objid] = actor;
00220         }
00221         return new_objid;
00222 }
00223 
00224 bool ObjectManager::reserveObjId(ObjId objid)
00225 {
00226         if (objid >= 256) // !constant
00227                 return objIDs->reserveID(objid);
00228         else
00229                 return actorIDs->reserveID(objid);
00230 }
00231 
00232 void ObjectManager::clearObjId(ObjId objid)
00233 {
00234         // need to make this assert check only permanent NPCs
00235 //      assert(objid >= 256); // !constant
00236         if (objid >= 256) // !constant
00237                 objIDs->clearID(objid);
00238         else
00239                 actorIDs->clearID(objid);
00240 
00241         objects[objid] = 0;
00242 }
00243 
00244 Object* ObjectManager::getObject(ObjId objid) const
00245 {
00246         return objects[objid];
00247 }
00248 
00249 void ObjectManager::save(ODataSource* ods)
00250 {
00251         objIDs->save(ods);
00252         actorIDs->save(ods);
00253 
00254         for (unsigned int i = 0; i < objects.size(); ++i) {
00255                 Object* object = objects[i];
00256                 if (!object) continue;
00257 
00258                 // child items/gumps are saved by their parent.
00259                 Item* item = p_dynamic_cast<Item*>(object);
00260                 if (item && item->getParent()) continue;
00261                 Gump* gump = p_dynamic_cast<Gump*>(object);
00262 
00263                 // don't save Gumps with DONT_SAVE and Gumps with parents, unless
00264                 // the parent is a core gump
00265                 if (gump && !gump->mustSave(true)) continue;
00266 
00267                 object->save(ods);
00268         }
00269 
00270         ods->write2(0);
00271 }
00272 
00273 
00274 bool ObjectManager::load(IDataSource* ids, uint32 version)
00275 {
00276         if (!objIDs->load(ids, version)) return false;
00277         if (!actorIDs->load(ids, version)) return false;
00278 
00279         do {
00280                 // peek ahead for terminator
00281                 uint16 classlen = ids->read2();
00282                 if (classlen == 0) break;
00283                 char* buf = new char[classlen+1];
00284                 ids->read(buf, classlen);
00285                 buf[classlen] = 0;
00286 
00287                 std::string classname = buf;
00288                 delete[] buf;
00289 
00290                 Object* obj = loadObject(ids, classname, version);
00291                 if (!obj) return false;
00292 
00293                 // top level gumps have to be added to the correct core gump
00294                 Gump* gump = p_dynamic_cast<Gump*>(obj);
00295                 if (gump) {
00296                         GUIApp::get_instance()->addGump(gump);
00297                 }
00298 
00299         } while(true);
00300 
00301         return true;
00302 }
00303 
00304 Object* ObjectManager::loadObject(IDataSource* ids, uint32 version)
00305 {
00306         uint16 classlen = ids->read2();
00307         char* buf = new char[classlen+1];
00308         ids->read(buf, classlen);
00309         buf[classlen] = 0;
00310 
00311         std::string classname = buf;
00312         delete[] buf;
00313 
00314         return loadObject(ids, classname, version);
00315 }
00316 
00317 Object* ObjectManager::loadObject(IDataSource* ids, std::string classname,
00318                                                                   uint32 version)
00319 {
00320         std::map<std::string, ObjectLoadFunc>::iterator iter;
00321         iter = objectloaders.find(classname);
00322 
00323         if (iter == objectloaders.end()) {
00324                 perr << "Unknown Object class: " << classname << std::endl;
00325                 return 0;
00326         }
00327 
00328         Object* obj = (*(iter->second))(ids, version);
00329 
00330         if (!obj) {
00331                 perr << "Error loading object of type " << classname << std::endl;
00332                 return 0;
00333         }
00334         uint16 objid = obj->getObjId();
00335 
00336         if (objid != 0xFFFF) {
00337                 objects[objid] = obj;
00338                 bool used;
00339                 if (objid >= 256)
00340                         used = objIDs->isIDUsed(objid);
00341                 else
00342                         used = actorIDs->isIDUsed(objid);
00343                 if (!used) {
00344                         perr << "Error: object ID " << objid
00345                                  << " used but marked available. " << std::endl;
00346                         return 0;
00347                 }
00348         }
00349 
00350         return obj;
00351 }
00352 
00353 void ObjectManager::setupLoaders()
00354 {
00355         addObjectLoader("Item", ObjectLoader<Item>::load);
00356         addObjectLoader("Container", ObjectLoader<Container>::load);
00357         addObjectLoader("Actor", ObjectLoader<Actor>::load);
00358         addObjectLoader("MainActor", ObjectLoader<MainActor>::load);
00359         addObjectLoader("Egg", ObjectLoader<Egg>::load);
00360         addObjectLoader("MonsterEgg", ObjectLoader<MonsterEgg>::load);
00361         addObjectLoader("TeleportEgg", ObjectLoader<TeleportEgg>::load);
00362         addObjectLoader("GlobEgg", ObjectLoader<GlobEgg>::load);
00363         addObjectLoader("Gump", ObjectLoader<Gump>::load);
00364         addObjectLoader("ItemRelativeGump", ObjectLoader<ItemRelativeGump>::load);
00365         addObjectLoader("AskGump", ObjectLoader<AskGump>::load);
00366         addObjectLoader("BarkGump", ObjectLoader<BarkGump>::load);
00367         addObjectLoader("ContainerGump", ObjectLoader<ContainerGump>::load);
00368         addObjectLoader("PaperdollGump", ObjectLoader<PaperdollGump>::load);
00369         addObjectLoader("TextWidget", ObjectLoader<TextWidget>::load);
00370         addObjectLoader("ButtonWidget", ObjectLoader<ButtonWidget>::load);
00371         addObjectLoader("SlidingWidget", ObjectLoader<SlidingWidget>::load);
00372         addObjectLoader("MiniStatsGump", ObjectLoader<MiniStatsGump>::load);
00373         addObjectLoader("MiniMapGump", ObjectLoader<MiniMapGump>::load);
00374 }
00375 

Generated on Fri Jul 27 22:27:27 2007 for pentagram by  doxygen 1.4.7