definitionmgr.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWSaveLoad *
  23. * *
  24. * $Archive:: /Commando/Code/wwsaveload/definitionmgr.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 3/29/02 4:13p $*
  29. * *
  30. * $Revision:: 36 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "definitionmgr.h"
  36. #include "definition.h"
  37. #include "definitionfactory.h"
  38. #include "definitionfactorymgr.h"
  39. #include "definitionclassids.h"
  40. #include "chunkio.h"
  41. #include "persistfactory.h"
  42. #include "wwdebug.h"
  43. #include "wwmemlog.h"
  44. #include "twiddler.h"
  45. #include <string.h>
  46. #include "wwprofile.h"
  47. //////////////////////////////////////////////////////////////////////////////////
  48. // Global instance
  49. //////////////////////////////////////////////////////////////////////////////////
  50. DefinitionMgrClass _TheDefinitionMgr;
  51. //////////////////////////////////////////////////////////////////////////////////
  52. // Constants
  53. //////////////////////////////////////////////////////////////////////////////////
  54. static const int DEFINTION_LIST_GROW_SIZE = 1000;
  55. static const uint32 IDRANGE_PER_CLASS = 10000;
  56. enum
  57. {
  58. CHUNKID_VARIABLES = 0x00000100,
  59. CHUNKID_OBJECTS,
  60. CHUNKID_OBJECT
  61. };
  62. enum
  63. {
  64. VARID_NEXTDEFID = 0x01
  65. };
  66. //////////////////////////////////////////////////////////////////////////////////
  67. // Static member initialization
  68. //////////////////////////////////////////////////////////////////////////////////
  69. DefinitionClass ** DefinitionMgrClass::_SortedDefinitionArray = NULL;
  70. int DefinitionMgrClass::_DefinitionCount = 0;
  71. int DefinitionMgrClass::_MaxDefinitionCount = 0;
  72. HashTemplateClass<StringClass, DynamicVectorClass<DefinitionClass*>*>* DefinitionMgrClass::DefinitionHash;
  73. //////////////////////////////////////////////////////////////////////////////////
  74. //
  75. // DefinitionMgrClass
  76. //
  77. //////////////////////////////////////////////////////////////////////////////////
  78. DefinitionMgrClass::DefinitionMgrClass (void)
  79. {
  80. return ;
  81. }
  82. //////////////////////////////////////////////////////////////////////////////////
  83. //
  84. // ~DefinitionMgrClass
  85. //
  86. //////////////////////////////////////////////////////////////////////////////////
  87. DefinitionMgrClass::~DefinitionMgrClass (void)
  88. {
  89. Free_Definitions ();
  90. return ;
  91. }
  92. //////////////////////////////////////////////////////////////////////////////////
  93. //
  94. // Find_Definition
  95. //
  96. //////////////////////////////////////////////////////////////////////////////////
  97. DefinitionClass *
  98. DefinitionMgrClass::Find_Definition (uint32 id, bool twiddle)
  99. {
  100. DefinitionClass *definition = NULL;
  101. int lower_index = 0;
  102. int upper_index = _DefinitionCount - 1;
  103. int index = upper_index / 2;
  104. bool keep_going = (_DefinitionCount > 0);
  105. //
  106. // Binary search the list until we've found the definition
  107. //
  108. while (keep_going) {
  109. DefinitionClass *curr_def = _SortedDefinitionArray[index];
  110. WWASSERT (curr_def != NULL);
  111. //
  112. // Is this the definition we are looking for?
  113. //
  114. if (curr_def->Get_ID () == id) {
  115. definition = _SortedDefinitionArray[index];
  116. keep_going = false;
  117. } else if (upper_index <= lower_index + 1) {
  118. //
  119. // When the window get's too small, our divide by two won't catch
  120. // both entries, so just go ahead and do them both now.
  121. //
  122. keep_going = false;
  123. if (_SortedDefinitionArray[lower_index]->Get_ID () == id) {
  124. definition = _SortedDefinitionArray[lower_index];
  125. } else if (_SortedDefinitionArray[upper_index]->Get_ID () == id) {
  126. definition = _SortedDefinitionArray[upper_index];
  127. }
  128. } else {
  129. //
  130. // Cut our 'window' in half
  131. //
  132. if (id > curr_def->Get_ID ()) {
  133. lower_index = index;
  134. index += (upper_index - index) / 2;
  135. } else {
  136. upper_index = index;
  137. index -= (index - lower_index) / 2;
  138. }
  139. }
  140. }
  141. //
  142. // Should we twiddle this definition? (Twiddling refers to our randomizing
  143. // framework for definitions)
  144. //
  145. if ( twiddle &&
  146. definition != NULL &&
  147. definition->Get_Class_ID () == CLASSID_TWIDDLERS)
  148. {
  149. definition = ((TwiddlerClass *)definition)->Twiddle ();
  150. }
  151. return definition;
  152. }
  153. //////////////////////////////////////////////////////////////////////////////////
  154. //
  155. // Find_Named_Definition
  156. //
  157. //////////////////////////////////////////////////////////////////////////////////
  158. DefinitionClass *
  159. DefinitionMgrClass::Find_Named_Definition (const char *name, bool twiddle)
  160. {
  161. DefinitionClass *definition = NULL;
  162. //
  163. // Loop through all the definitions and see if we can
  164. // find the one with the requested name
  165. //
  166. for (int index = 0; index < _DefinitionCount; index ++) {
  167. DefinitionClass *curr_def = _SortedDefinitionArray[index];
  168. //
  169. // Is this the definition we were looking for?
  170. //
  171. if (curr_def != NULL && ::stricmp (curr_def->Get_Name (), name) == 0) {
  172. definition = curr_def;
  173. break;
  174. }
  175. }
  176. //
  177. // Should we twiddle this definition? (Twiddling refers to our randomizing
  178. // framework for definitions)
  179. //
  180. if ( twiddle &&
  181. definition != NULL &&
  182. definition->Get_Class_ID () == CLASSID_TWIDDLERS)
  183. {
  184. definition = ((TwiddlerClass *)definition)->Twiddle ();
  185. }
  186. return definition;
  187. }
  188. //////////////////////////////////////////////////////////////////////////////////
  189. //
  190. // Find_Typed_Definition
  191. //
  192. //////////////////////////////////////////////////////////////////////////////////
  193. DefinitionClass *
  194. DefinitionMgrClass::Find_Typed_Definition (const char *name, uint32 class_id, bool twiddle)
  195. {
  196. //
  197. // Sanity check
  198. //
  199. if (DefinitionHash == NULL) {
  200. WWDEBUG_SAY (("DefinitionMgrClass::Find_Typed_Definition () failed due to a NULL DefinitionHash. %s\n", name));
  201. return NULL;
  202. }
  203. DefinitionClass *definition = NULL;
  204. // Check the hash table first. The hash table is built as we need the definitions, so if definition is not
  205. // in the table, it will be added there.
  206. //
  207. // TSS null deref on this sucker 08/03/01
  208. //
  209. WWASSERT(DefinitionHash != NULL);
  210. StringClass lower_case_name(name,true);
  211. _strlwr(lower_case_name.Peek_Buffer());
  212. DynamicVectorClass<DefinitionClass*>* defs = DefinitionHash->Get(lower_case_name);
  213. if (defs) {
  214. for (int i=0;i<defs->Length();++i) {
  215. DefinitionClass* curr_def=(*defs)[i];
  216. WWASSERT(curr_def);
  217. uint32 curr_class_id = curr_def->Get_Class_ID ();
  218. if ( (curr_class_id == class_id) ||
  219. (::SuperClassID_From_ClassID (curr_class_id) == class_id) ||
  220. (twiddle && (curr_def->Get_Class_ID () == CLASSID_TWIDDLERS)))
  221. {
  222. definition = curr_def;
  223. break;
  224. }
  225. }
  226. }
  227. //
  228. // Loop through all the definitions and see if we can
  229. // find the one with the requested name
  230. //
  231. if (!definition) {
  232. for (int index = 0; index < _DefinitionCount; index ++) {
  233. DefinitionClass *curr_def = _SortedDefinitionArray[index];
  234. if (curr_def != NULL) {
  235. //
  236. // Is this the correct class of definition?
  237. //
  238. uint32 curr_class_id = curr_def->Get_Class_ID ();
  239. if ( (curr_class_id == class_id) ||
  240. (::SuperClassID_From_ClassID (curr_class_id) == class_id) ||
  241. (twiddle && (curr_def->Get_Class_ID () == CLASSID_TWIDDLERS)))
  242. {
  243. //
  244. // Is this the definition we were looking for?
  245. //
  246. if (::stricmp (curr_def->Get_Name (), name) == 0) {
  247. definition = curr_def;
  248. // Add the definition to the hash table, so that it can be quickly accessed the next time it is needed.
  249. if (!defs) {
  250. defs=new DynamicVectorClass<DefinitionClass*>;
  251. DefinitionHash->Insert(lower_case_name,defs);
  252. }
  253. defs->Add(definition);
  254. break;
  255. }
  256. }
  257. }
  258. }
  259. }
  260. //
  261. // Should we twiddle this definition? (Twiddling refers to our randomizing
  262. // framework for definitions)
  263. //
  264. if ( twiddle &&
  265. definition != NULL &&
  266. definition->Get_Class_ID () == CLASSID_TWIDDLERS)
  267. {
  268. definition = ((TwiddlerClass *)definition)->Twiddle ();
  269. }
  270. return definition;
  271. }
  272. //////////////////////////////////////////////////////////////////////////////////
  273. //
  274. // List_Available_Definitions
  275. //
  276. //////////////////////////////////////////////////////////////////////////////////
  277. void
  278. DefinitionMgrClass::List_Available_Definitions (void)
  279. {
  280. //
  281. // Loop through all the definitions and print the definition name
  282. //
  283. WWDEBUG_SAY(("Available definitions:\n"));
  284. for (int index = 0; index < _DefinitionCount; index ++) {
  285. DefinitionClass *curr_def = _SortedDefinitionArray[index];
  286. if (curr_def != NULL) {
  287. WWDEBUG_SAY((" >%s<\n", curr_def->Get_Name ()));
  288. }
  289. }
  290. return ;
  291. }
  292. //////////////////////////////////////////////////////////////////////////////////
  293. //
  294. // List_Available_Definitions
  295. //
  296. //////////////////////////////////////////////////////////////////////////////////
  297. void
  298. DefinitionMgrClass::List_Available_Definitions (int superclass_id)
  299. {
  300. //
  301. // Loop through all the definitions and print the definition name
  302. //
  303. WWDEBUG_SAY(("Available superclass definitions for 0x%8X:\n", superclass_id));
  304. DefinitionClass *definition = NULL;
  305. for ( definition = Get_First (superclass_id, DefinitionMgrClass::ID_SUPERCLASS);
  306. definition != NULL;
  307. definition = Get_Next (definition, superclass_id, DefinitionMgrClass::ID_SUPERCLASS))
  308. {
  309. WWDEBUG_SAY((" >%s<\n", definition->Get_Name ()));
  310. }
  311. return ;
  312. }
  313. //////////////////////////////////////////////////////////////////////////////////
  314. //
  315. // Get_First
  316. //
  317. //////////////////////////////////////////////////////////////////////////////////
  318. DefinitionClass *
  319. DefinitionMgrClass::Get_First (uint32 id, ID_TYPE type)
  320. {
  321. DefinitionClass *definition = NULL;
  322. //
  323. // Loop through all the definitions and find the first
  324. // one that belongs to the requested class
  325. //
  326. for ( int index = 0;
  327. (definition == NULL) && (index < _DefinitionCount);
  328. index ++)
  329. {
  330. DefinitionClass *curr_def = _SortedDefinitionArray[index];
  331. if (curr_def != NULL) {
  332. //
  333. // Is this the definition we were looking for?
  334. //
  335. if ( (type == ID_SUPERCLASS) &&
  336. (::SuperClassID_From_ClassID (curr_def->Get_Class_ID ()) == id)) {
  337. definition = curr_def;
  338. } else if ( (type == ID_CLASS) &&
  339. (curr_def->Get_Class_ID () == id)) {
  340. definition = curr_def;
  341. }
  342. }
  343. }
  344. return definition;
  345. }
  346. //////////////////////////////////////////////////////////////////////////////////
  347. //
  348. // Get_Next
  349. //
  350. //////////////////////////////////////////////////////////////////////////////////
  351. DefinitionClass *
  352. DefinitionMgrClass::Get_Next
  353. (
  354. DefinitionClass * curr_def,
  355. uint32 id,
  356. ID_TYPE type
  357. )
  358. {
  359. DefinitionClass *definition = NULL;
  360. //
  361. // Loop through all the definitions and find the first
  362. // one that belongs to the requested class
  363. //
  364. for ( int index = curr_def->m_DefinitionMgrLink + 1;
  365. (definition == NULL) && (index < _DefinitionCount);
  366. index ++)
  367. {
  368. DefinitionClass *curr_def = _SortedDefinitionArray[index];
  369. if (curr_def != NULL) {
  370. //
  371. // Is this the definition we were looking for?
  372. //
  373. if ( (type == ID_SUPERCLASS) &&
  374. (::SuperClassID_From_ClassID (curr_def->Get_Class_ID ()) == id)) {
  375. definition = curr_def;
  376. } else if ( (type == ID_CLASS) &&
  377. (curr_def->Get_Class_ID () == id)) {
  378. definition = curr_def;
  379. }
  380. }
  381. }
  382. return definition;
  383. }
  384. ////////////////////////////////////////////////////////////////////////////
  385. //
  386. // Get_Next
  387. //
  388. ////////////////////////////////////////////////////////////////////////////
  389. DefinitionClass *
  390. DefinitionMgrClass::Get_Next (DefinitionClass *curr_def)
  391. {
  392. WWASSERT (curr_def != NULL);
  393. DefinitionClass *definition = NULL;
  394. int index = curr_def->m_DefinitionMgrLink + 1;
  395. if (index < _DefinitionCount) {
  396. definition = _SortedDefinitionArray[index];
  397. }
  398. return definition;
  399. }
  400. ////////////////////////////////////////////////////////////////////////////
  401. //
  402. // Free_Definitions
  403. //
  404. ////////////////////////////////////////////////////////////////////////////
  405. void
  406. DefinitionMgrClass::Free_Definitions (void)
  407. {
  408. // Clear the hash table
  409. if (DefinitionHash) {
  410. HashTemplateIterator<StringClass,DynamicVectorClass<DefinitionClass*>*> ite(*DefinitionHash);
  411. for (ite.First();!ite.Is_Done();ite.Next()) {
  412. DynamicVectorClass<DefinitionClass*>* defs=ite.Peek_Value();
  413. // delete ite.Peek_Value();
  414. delete defs;
  415. }
  416. DefinitionHash->Remove_All();
  417. delete DefinitionHash;
  418. DefinitionHash=NULL;
  419. }
  420. //
  421. // Free each of the definition objects
  422. //
  423. for (int index = 0; index < _DefinitionCount; index ++) {
  424. DefinitionClass *definition = _SortedDefinitionArray[index];
  425. if (definition != NULL) {
  426. delete definition;
  427. }
  428. }
  429. //
  430. // Free the definition array
  431. //
  432. if (_SortedDefinitionArray != NULL) {
  433. delete [] _SortedDefinitionArray;
  434. }
  435. _SortedDefinitionArray = NULL;
  436. _MaxDefinitionCount = 0;
  437. _DefinitionCount = 0;
  438. return ;
  439. }
  440. ////////////////////////////////////////////////////////////////////////////
  441. //
  442. // Prepare_Definition_Array
  443. //
  444. ////////////////////////////////////////////////////////////////////////////
  445. void
  446. DefinitionMgrClass::Prepare_Definition_Array (void)
  447. {
  448. if (_DefinitionCount + 1 > _MaxDefinitionCount) {
  449. //
  450. // Allocate a new, bigger array
  451. //
  452. int new_size = _MaxDefinitionCount + DEFINTION_LIST_GROW_SIZE;
  453. DefinitionClass **new_array = new DefinitionClass *[new_size];
  454. //
  455. // Copy the entries from the old array to the new array
  456. //
  457. ::memcpy (new_array, _SortedDefinitionArray, _DefinitionCount * sizeof (DefinitionClass *));
  458. //
  459. // Free the old array and start using the new array
  460. //
  461. if (_SortedDefinitionArray != NULL) {
  462. delete [] _SortedDefinitionArray;
  463. }
  464. _SortedDefinitionArray = new_array;
  465. _MaxDefinitionCount = new_size;
  466. }
  467. if (!DefinitionHash) DefinitionHash=new HashTemplateClass<StringClass, DynamicVectorClass<DefinitionClass*>*>;
  468. return ;
  469. }
  470. ////////////////////////////////////////////////////////////////////////////
  471. //
  472. // Register_Definition
  473. //
  474. ////////////////////////////////////////////////////////////////////////////
  475. void
  476. DefinitionMgrClass::Register_Definition (DefinitionClass *definition)
  477. {
  478. WWASSERT (definition != NULL);
  479. if (definition != NULL && definition->m_DefinitionMgrLink == -1 && definition->Get_ID () != 0) {
  480. //
  481. // Make sure the definition array is large enough
  482. //
  483. Prepare_Definition_Array ();
  484. //
  485. // Calculate where in the list we should insert this definition
  486. //
  487. uint32 id = definition->Get_ID ();
  488. int lower_index = 0;
  489. int upper_index = _DefinitionCount - 1;
  490. int index = upper_index / 2;
  491. int insert_index = _DefinitionCount;
  492. bool keep_going = (_DefinitionCount > 0);
  493. bool is_valid = true;
  494. while (keep_going) {
  495. DefinitionClass *curr_def = _SortedDefinitionArray[index];
  496. WWASSERT (curr_def != NULL);
  497. //
  498. // Check to make sure we aren't trying to register a definition
  499. // that has the same ID as a definition that is already in the list.
  500. //
  501. if (curr_def->Get_ID () == id) {
  502. insert_index = index;
  503. keep_going = false;
  504. is_valid = false;
  505. } else {
  506. //
  507. // Cut our 'window' in half
  508. //
  509. if (id > curr_def->Get_ID ()) {
  510. lower_index = index;
  511. index += (upper_index - index) / 2;
  512. } else {
  513. upper_index = index;
  514. index -= (index - lower_index) / 2;
  515. }
  516. //
  517. // If we've narrowed down the window to 2 entries, then quick check
  518. // the different possibilities.
  519. //
  520. if (upper_index <= lower_index + 1) {
  521. if (_SortedDefinitionArray[upper_index]->Get_ID () <= id) {
  522. insert_index = upper_index + 1;
  523. } else if (_SortedDefinitionArray[lower_index]->Get_ID () <= id) {
  524. insert_index = upper_index;
  525. } else {
  526. insert_index = lower_index;
  527. }
  528. keep_going = false;
  529. }
  530. }
  531. }
  532. //WWASSERT (is_valid);
  533. if (is_valid) {
  534. //
  535. // Re-index all the definitions that got bumped one cell due to this insertion.
  536. //
  537. for (index = _DefinitionCount - 1; index >= insert_index; index --) {
  538. _SortedDefinitionArray[index + 1] = _SortedDefinitionArray[index];
  539. _SortedDefinitionArray[index + 1]->m_DefinitionMgrLink = index + 1;
  540. }
  541. //
  542. // Insert this definition into the list
  543. //
  544. definition->m_DefinitionMgrLink = insert_index;
  545. _SortedDefinitionArray[insert_index] = definition;
  546. _DefinitionCount ++;
  547. }
  548. }
  549. return ;
  550. }
  551. ////////////////////////////////////////////////////////////////////////////
  552. //
  553. // Unregister_Definition
  554. //
  555. ////////////////////////////////////////////////////////////////////////////
  556. void
  557. DefinitionMgrClass::Unregister_Definition (DefinitionClass *definition)
  558. {
  559. WWASSERT (definition != 0);
  560. //WWASSERT (definition->m_DefinitionMgrLink >= 0 && definition->m_DefinitionMgrLink < _DefinitionCount);
  561. if (definition != NULL && definition->m_DefinitionMgrLink != -1) {
  562. //
  563. // Re-index the definitions that come after this definition in the list
  564. //
  565. for (int index = definition->m_DefinitionMgrLink; index < _DefinitionCount - 1; index ++) {
  566. _SortedDefinitionArray[index] = _SortedDefinitionArray[index + 1];
  567. _SortedDefinitionArray[index]->m_DefinitionMgrLink = index;
  568. }
  569. _SortedDefinitionArray[_DefinitionCount - 1] = NULL;
  570. definition->m_DefinitionMgrLink = -1;
  571. _DefinitionCount --;
  572. }
  573. return ;
  574. }
  575. //////////////////////////////////////////////////////////////////////////////////
  576. //
  577. // Save
  578. //
  579. //////////////////////////////////////////////////////////////////////////////////
  580. bool
  581. DefinitionMgrClass::Save
  582. (
  583. ChunkSaveClass & csave
  584. )
  585. {
  586. WWMEMLOG(MEM_GAMEDATA);
  587. bool retval = true;
  588. //
  589. // Create a chunk to contain the class variables we need to serialize.
  590. //
  591. csave.Begin_Chunk (CHUNKID_VARIABLES);
  592. Save_Variables (csave);
  593. csave.End_Chunk ();
  594. //
  595. // Have the base class write the objects to their own chunk.
  596. //
  597. csave.Begin_Chunk (CHUNKID_OBJECTS);
  598. retval &= Save_Objects (csave);
  599. csave.End_Chunk ();
  600. return retval;
  601. }
  602. //////////////////////////////////////////////////////////////////////////////////
  603. //
  604. // Load
  605. //
  606. //////////////////////////////////////////////////////////////////////////////////
  607. bool
  608. DefinitionMgrClass::Load (ChunkLoadClass &cload)
  609. {
  610. WWMEMLOG(MEM_GAMEDATA);
  611. bool retval = true;
  612. while (cload.Open_Chunk ()) {
  613. switch (cload.Cur_Chunk_ID ()) {
  614. //
  615. // If this is the chunk that contains the class variables, then
  616. // loop through and read each microchunk
  617. //
  618. case CHUNKID_VARIABLES:
  619. retval &= Load_Variables (cload);
  620. break;
  621. //
  622. // Load all the definition objects from this chunk
  623. //
  624. case CHUNKID_OBJECTS:
  625. retval &= Load_Objects (cload);
  626. break;
  627. }
  628. cload.Close_Chunk ();
  629. }
  630. return retval;
  631. }
  632. //////////////////////////////////////////////////////////////////////////////////
  633. //
  634. // Save_Objects
  635. //
  636. //////////////////////////////////////////////////////////////////////////////////
  637. bool
  638. DefinitionMgrClass::Save_Objects
  639. (
  640. ChunkSaveClass & csave
  641. )
  642. {
  643. bool retval = true;
  644. //
  645. // Loop through all the definition objects
  646. //
  647. for (int index = 0; index < _DefinitionCount; index ++) {
  648. DefinitionClass *definition = _SortedDefinitionArray[index];
  649. if (definition != NULL && definition->Is_Save_Enabled ()) {
  650. //
  651. // Save this definition object
  652. //
  653. csave.Begin_Chunk (definition->Get_Factory ().Chunk_ID ());
  654. definition->Get_Factory ().Save (csave, definition);
  655. csave.End_Chunk ();
  656. }
  657. }
  658. return retval;
  659. }
  660. //////////////////////////////////////////////////////////////////////////////////
  661. //
  662. // Save_Variables
  663. //
  664. //////////////////////////////////////////////////////////////////////////////////
  665. bool
  666. DefinitionMgrClass::Save_Variables (ChunkSaveClass &csave)
  667. {
  668. bool retval = true;
  669. return retval;
  670. }
  671. float _alloc_time;
  672. float _load_time;
  673. float _reg_time;
  674. //////////////////////////////////////////////////////////////////////////////////
  675. //
  676. // Load_Objects
  677. //
  678. //////////////////////////////////////////////////////////////////////////////////
  679. bool
  680. DefinitionMgrClass::Load_Objects (ChunkLoadClass &cload)
  681. {
  682. bool retval = true;
  683. while (cload.Open_Chunk ()) {
  684. //
  685. // Load this definition from the chunk (if possible)
  686. //
  687. PersistFactoryClass *factory = SaveLoadSystemClass::Find_Persist_Factory (cload.Cur_Chunk_ID ());
  688. if (factory != NULL) {
  689. DefinitionClass *definition = (DefinitionClass *)factory->Load (cload);
  690. if (definition != NULL) {
  691. //
  692. // Add this definition to our array
  693. //
  694. Prepare_Definition_Array ();
  695. _SortedDefinitionArray[_DefinitionCount ++] = definition;
  696. }
  697. }
  698. cload.Close_Chunk ();
  699. }
  700. //
  701. // Sort the definitions
  702. //
  703. if (_DefinitionCount > 0) {
  704. ::qsort (_SortedDefinitionArray, _DefinitionCount, sizeof (DefinitionClass *), fnCompareDefinitionsCallback);
  705. }
  706. //
  707. // Assign a mgr link to each definition
  708. //
  709. for (int index = 0; index < _DefinitionCount; index ++) {
  710. _SortedDefinitionArray[index]->m_DefinitionMgrLink = index;
  711. }
  712. return retval;
  713. }
  714. //////////////////////////////////////////////////////////////////////////////////
  715. //
  716. // Load_Variables
  717. //
  718. //////////////////////////////////////////////////////////////////////////////////
  719. bool
  720. DefinitionMgrClass::Load_Variables (ChunkLoadClass &cload)
  721. {
  722. bool retval = true;
  723. //
  724. // Loop through all the microchunks that define the variables
  725. //
  726. while (cload.Open_Micro_Chunk ()) {
  727. switch (cload.Cur_Micro_Chunk_ID ()) {
  728. case VARID_NEXTDEFID:
  729. break;
  730. }
  731. cload.Close_Micro_Chunk ();
  732. }
  733. return retval;
  734. }
  735. /////////////////////////////////////////////////////////////////////
  736. //
  737. // Get_New_ID
  738. //
  739. /////////////////////////////////////////////////////////////////////
  740. uint32
  741. DefinitionMgrClass::Get_New_ID (uint32 class_id)
  742. {
  743. uint32 idrange_start = (class_id - DEF_CLASSID_START) * IDRANGE_PER_CLASS;
  744. uint32 idrange_end = (idrange_start + IDRANGE_PER_CLASS);
  745. uint32 new_id = idrange_start + 1;
  746. //
  747. // Try to find the first empty slot in this ID range
  748. //
  749. for (int index = 0; index < _DefinitionCount; index ++) {
  750. DefinitionClass *definition = _SortedDefinitionArray[index];
  751. if (definition != NULL) {
  752. //
  753. // Get this definition's ID
  754. //
  755. uint32 curr_id = definition->Get_ID ();
  756. //
  757. // Is this id in the range we are looking for?
  758. //
  759. if (curr_id >= idrange_start && curr_id < idrange_end) {
  760. bool is_ok = false;
  761. if (index < _DefinitionCount - 1) {
  762. //
  763. // Check to see if the next definition in our array leaves a hole in the
  764. // ID range.
  765. //
  766. DefinitionClass *next_definition = _SortedDefinitionArray[index + 1];
  767. if (next_definition != NULL && next_definition->Get_ID () > (curr_id + 1)) {
  768. is_ok = true;
  769. }
  770. } else {
  771. is_ok = true;
  772. }
  773. //
  774. // Return the new ID
  775. //
  776. if (is_ok) {
  777. new_id = curr_id + 1;
  778. break;
  779. }
  780. }
  781. }
  782. }
  783. return new_id;
  784. }
  785. ////////////////////////////////////////////////////////////////
  786. //
  787. // fnCompareDefinitionsCallback
  788. //
  789. ////////////////////////////////////////////////////////////////
  790. int __cdecl
  791. DefinitionMgrClass::fnCompareDefinitionsCallback
  792. (
  793. const void *elem1,
  794. const void *elem2
  795. )
  796. {
  797. WWASSERT (elem1 != NULL);
  798. WWASSERT (elem2 != NULL);
  799. DefinitionClass *definition1 = *((DefinitionClass **)elem1);
  800. DefinitionClass *definition2 = *((DefinitionClass **)elem2);
  801. //
  802. // Sort the definitions based on ID
  803. //
  804. int result = 0;
  805. if (definition1->Get_ID () > definition2->Get_ID ()) {
  806. result = 1;
  807. } else if (definition1->Get_ID () < definition2->Get_ID ()) {
  808. result = -1;
  809. } else {
  810. result = 0;
  811. }
  812. return result;
  813. }