00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00056
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);
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;
00108 #endif
00109 Gump* gump = p_dynamic_cast<Gump*>(objects[i]);
00110 if (gump && gump->GetParent()) continue;
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);
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 & )
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)
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
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
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)
00227 return objIDs->reserveID(objid);
00228 else
00229 return actorIDs->reserveID(objid);
00230 }
00231
00232 void ObjectManager::clearObjId(ObjId objid)
00233 {
00234
00235
00236 if (objid >= 256)
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
00259 Item* item = p_dynamic_cast<Item*>(object);
00260 if (item && item->getParent()) continue;
00261 Gump* gump = p_dynamic_cast<Gump*>(object);
00262
00263
00264
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
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
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