definitionmgr.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933
  1. /*
  2. ** Command & Conquer Generals(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:: 8/28/01 7:33p $*
  29. * *
  30. * $Revision:: 33 $*
  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.\n"));
  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 name_string(name,true);
  211. DynamicVectorClass<DefinitionClass*>* defs = DefinitionHash->Get(name_string);
  212. if (defs) {
  213. for (int i=0;i<defs->Length();++i) {
  214. DefinitionClass* curr_def=(*defs)[i];
  215. WWASSERT(curr_def);
  216. uint32 curr_class_id = curr_def->Get_Class_ID ();
  217. if ( (curr_class_id == class_id) ||
  218. (::SuperClassID_From_ClassID (curr_class_id) == class_id) ||
  219. (twiddle && (curr_def->Get_Class_ID () == CLASSID_TWIDDLERS)))
  220. {
  221. definition = curr_def;
  222. break;
  223. }
  224. }
  225. }
  226. //
  227. // Loop through all the definitions and see if we can
  228. // find the one with the requested name
  229. //
  230. if (!definition) {
  231. for (int index = 0; index < _DefinitionCount; index ++) {
  232. DefinitionClass *curr_def = _SortedDefinitionArray[index];
  233. if (curr_def != NULL) {
  234. //
  235. // Is this the correct class of definition?
  236. //
  237. uint32 curr_class_id = curr_def->Get_Class_ID ();
  238. if ( (curr_class_id == class_id) ||
  239. (::SuperClassID_From_ClassID (curr_class_id) == class_id) ||
  240. (twiddle && (curr_def->Get_Class_ID () == CLASSID_TWIDDLERS)))
  241. {
  242. //
  243. // Is this the definition we were looking for?
  244. //
  245. if (::stricmp (curr_def->Get_Name (), name) == 0) {
  246. definition = curr_def;
  247. // Add the definition to the hash table, so that it can be quickly accessed the next time it is needed.
  248. if (!defs) {
  249. defs=W3DNEW DynamicVectorClass<DefinitionClass*>;
  250. DefinitionHash->Insert(name_string,defs);
  251. }
  252. defs->Add(definition);
  253. break;
  254. }
  255. }
  256. }
  257. }
  258. }
  259. //
  260. // Should we twiddle this definition? (Twiddling refers to our randomizing
  261. // framework for definitions)
  262. //
  263. if ( twiddle &&
  264. definition != NULL &&
  265. definition->Get_Class_ID () == CLASSID_TWIDDLERS)
  266. {
  267. definition = ((TwiddlerClass *)definition)->Twiddle ();
  268. }
  269. return definition;
  270. }
  271. //////////////////////////////////////////////////////////////////////////////////
  272. //
  273. // List_Available_Definitions
  274. //
  275. //////////////////////////////////////////////////////////////////////////////////
  276. void
  277. DefinitionMgrClass::List_Available_Definitions (void)
  278. {
  279. //
  280. // Loop through all the definitions and print the definition name
  281. //
  282. WWDEBUG_SAY(("Available definitions:\n"));
  283. for (int index = 0; index < _DefinitionCount; index ++) {
  284. DefinitionClass *curr_def = _SortedDefinitionArray[index];
  285. if (curr_def != NULL) {
  286. WWDEBUG_SAY((" >%s<\n", curr_def->Get_Name ()));
  287. }
  288. }
  289. return ;
  290. }
  291. //////////////////////////////////////////////////////////////////////////////////
  292. //
  293. // List_Available_Definitions
  294. //
  295. //////////////////////////////////////////////////////////////////////////////////
  296. void
  297. DefinitionMgrClass::List_Available_Definitions (int superclass_id)
  298. {
  299. //
  300. // Loop through all the definitions and print the definition name
  301. //
  302. WWDEBUG_SAY(("Available superclass definitions for 0x%8X:\n", superclass_id));
  303. DefinitionClass *definition = NULL;
  304. for ( definition = Get_First (superclass_id, DefinitionMgrClass::ID_SUPERCLASS);
  305. definition != NULL;
  306. definition = Get_Next (definition, superclass_id, DefinitionMgrClass::ID_SUPERCLASS))
  307. {
  308. WWDEBUG_SAY((" >%s<\n", definition->Get_Name ()));
  309. }
  310. return ;
  311. }
  312. //////////////////////////////////////////////////////////////////////////////////
  313. //
  314. // Get_First
  315. //
  316. //////////////////////////////////////////////////////////////////////////////////
  317. DefinitionClass *
  318. DefinitionMgrClass::Get_First (uint32 id, ID_TYPE type)
  319. {
  320. DefinitionClass *definition = NULL;
  321. //
  322. // Loop through all the definitions and find the first
  323. // one that belongs to the requested class
  324. //
  325. for ( int index = 0;
  326. (definition == NULL) && (index < _DefinitionCount);
  327. index ++)
  328. {
  329. DefinitionClass *curr_def = _SortedDefinitionArray[index];
  330. if (curr_def != NULL) {
  331. //
  332. // Is this the definition we were looking for?
  333. //
  334. if ( (type == ID_SUPERCLASS) &&
  335. (::SuperClassID_From_ClassID (curr_def->Get_Class_ID ()) == id)) {
  336. definition = curr_def;
  337. } else if ( (type == ID_CLASS) &&
  338. (curr_def->Get_Class_ID () == id)) {
  339. definition = curr_def;
  340. }
  341. }
  342. }
  343. return definition;
  344. }
  345. //////////////////////////////////////////////////////////////////////////////////
  346. //
  347. // Get_Next
  348. //
  349. //////////////////////////////////////////////////////////////////////////////////
  350. DefinitionClass *
  351. DefinitionMgrClass::Get_Next
  352. (
  353. DefinitionClass * curr_def,
  354. uint32 id,
  355. ID_TYPE type
  356. )
  357. {
  358. DefinitionClass *definition = NULL;
  359. //
  360. // Loop through all the definitions and find the first
  361. // one that belongs to the requested class
  362. //
  363. for ( int index = curr_def->m_DefinitionMgrLink + 1;
  364. (definition == NULL) && (index < _DefinitionCount);
  365. index ++)
  366. {
  367. DefinitionClass *curr_def = _SortedDefinitionArray[index];
  368. if (curr_def != NULL) {
  369. //
  370. // Is this the definition we were looking for?
  371. //
  372. if ( (type == ID_SUPERCLASS) &&
  373. (::SuperClassID_From_ClassID (curr_def->Get_Class_ID ()) == id)) {
  374. definition = curr_def;
  375. } else if ( (type == ID_CLASS) &&
  376. (curr_def->Get_Class_ID () == id)) {
  377. definition = curr_def;
  378. }
  379. }
  380. }
  381. return definition;
  382. }
  383. ////////////////////////////////////////////////////////////////////////////
  384. //
  385. // Get_Next
  386. //
  387. ////////////////////////////////////////////////////////////////////////////
  388. DefinitionClass *
  389. DefinitionMgrClass::Get_Next (DefinitionClass *curr_def)
  390. {
  391. WWASSERT (curr_def != NULL);
  392. DefinitionClass *definition = NULL;
  393. int index = curr_def->m_DefinitionMgrLink + 1;
  394. if (index < _DefinitionCount) {
  395. definition = _SortedDefinitionArray[index];
  396. }
  397. return definition;
  398. }
  399. ////////////////////////////////////////////////////////////////////////////
  400. //
  401. // Free_Definitions
  402. //
  403. ////////////////////////////////////////////////////////////////////////////
  404. void
  405. DefinitionMgrClass::Free_Definitions (void)
  406. {
  407. // Clear the hash table
  408. if (DefinitionHash) {
  409. HashTemplateIterator<StringClass,DynamicVectorClass<DefinitionClass*>*> ite(*DefinitionHash);
  410. for (ite.First();!ite.Is_Done();ite.Next()) {
  411. DynamicVectorClass<DefinitionClass*>* defs=ite.Peek_Value();
  412. // delete ite.Peek_Value();
  413. delete defs;
  414. }
  415. DefinitionHash->Remove_All();
  416. delete DefinitionHash;
  417. DefinitionHash=NULL;
  418. }
  419. //
  420. // Free each of the definition objects
  421. //
  422. for (int index = 0; index < _DefinitionCount; index ++) {
  423. DefinitionClass *definition = _SortedDefinitionArray[index];
  424. if (definition != NULL) {
  425. delete definition;
  426. }
  427. }
  428. //
  429. // Free the definition array
  430. //
  431. if (_SortedDefinitionArray != NULL) {
  432. delete [] _SortedDefinitionArray;
  433. }
  434. _SortedDefinitionArray = NULL;
  435. _MaxDefinitionCount = 0;
  436. _DefinitionCount = 0;
  437. return ;
  438. }
  439. ////////////////////////////////////////////////////////////////////////////
  440. //
  441. // Prepare_Definition_Array
  442. //
  443. ////////////////////////////////////////////////////////////////////////////
  444. void
  445. DefinitionMgrClass::Prepare_Definition_Array (void)
  446. {
  447. if (_DefinitionCount + 1 > _MaxDefinitionCount) {
  448. //
  449. // Allocate a new, bigger array
  450. //
  451. int new_size = _MaxDefinitionCount + DEFINTION_LIST_GROW_SIZE;
  452. DefinitionClass **new_array = W3DNEWARRAY DefinitionClass *[new_size];
  453. //
  454. // Copy the entries from the old array to the new array
  455. //
  456. ::memcpy (new_array, _SortedDefinitionArray, _DefinitionCount * sizeof (DefinitionClass *));
  457. //
  458. // Free the old array and start using the new array
  459. //
  460. if (_SortedDefinitionArray != NULL) {
  461. delete [] _SortedDefinitionArray;
  462. }
  463. _SortedDefinitionArray = new_array;
  464. _MaxDefinitionCount = new_size;
  465. }
  466. if (!DefinitionHash) DefinitionHash=W3DNEW HashTemplateClass<StringClass, DynamicVectorClass<DefinitionClass*>*>;
  467. return ;
  468. }
  469. ////////////////////////////////////////////////////////////////////////////
  470. //
  471. // Register_Definition
  472. //
  473. ////////////////////////////////////////////////////////////////////////////
  474. void
  475. DefinitionMgrClass::Register_Definition (DefinitionClass *definition)
  476. {
  477. WWASSERT (definition != NULL);
  478. if (definition != NULL && definition->m_DefinitionMgrLink == -1 && definition->Get_ID () != 0) {
  479. //
  480. // Make sure the definition array is large enough
  481. //
  482. Prepare_Definition_Array ();
  483. //
  484. // Calculate where in the list we should insert this definition
  485. //
  486. uint32 id = definition->Get_ID ();
  487. int lower_index = 0;
  488. int upper_index = _DefinitionCount - 1;
  489. int index = upper_index / 2;
  490. int insert_index = _DefinitionCount;
  491. bool keep_going = (_DefinitionCount > 0);
  492. bool is_valid = true;
  493. while (keep_going) {
  494. DefinitionClass *curr_def = _SortedDefinitionArray[index];
  495. WWASSERT (curr_def != NULL);
  496. //
  497. // Check to make sure we aren't trying to register a definition
  498. // that has the same ID as a definition that is already in the list.
  499. //
  500. if (curr_def->Get_ID () == id) {
  501. insert_index = index;
  502. keep_going = false;
  503. is_valid = false;
  504. } else {
  505. //
  506. // Cut our 'window' in half
  507. //
  508. if (id > curr_def->Get_ID ()) {
  509. lower_index = index;
  510. index += (upper_index - index) / 2;
  511. } else {
  512. upper_index = index;
  513. index -= (index - lower_index) / 2;
  514. }
  515. //
  516. // If we've narrowed down the window to 2 entries, then quick check
  517. // the different possibilities.
  518. //
  519. if (upper_index <= lower_index + 1) {
  520. if (_SortedDefinitionArray[upper_index]->Get_ID () <= id) {
  521. insert_index = upper_index + 1;
  522. } else if (_SortedDefinitionArray[lower_index]->Get_ID () <= id) {
  523. insert_index = upper_index;
  524. } else {
  525. insert_index = lower_index;
  526. }
  527. keep_going = false;
  528. }
  529. }
  530. }
  531. //WWASSERT (is_valid);
  532. if (is_valid) {
  533. //
  534. // Re-index all the definitions that got bumped one cell due to this insertion.
  535. //
  536. for (index = _DefinitionCount - 1; index >= insert_index; index --) {
  537. _SortedDefinitionArray[index + 1] = _SortedDefinitionArray[index];
  538. _SortedDefinitionArray[index + 1]->m_DefinitionMgrLink = index + 1;
  539. }
  540. //
  541. // Insert this definition into the list
  542. //
  543. definition->m_DefinitionMgrLink = insert_index;
  544. _SortedDefinitionArray[insert_index] = definition;
  545. _DefinitionCount ++;
  546. }
  547. }
  548. return ;
  549. }
  550. ////////////////////////////////////////////////////////////////////////////
  551. //
  552. // Unregister_Definition
  553. //
  554. ////////////////////////////////////////////////////////////////////////////
  555. void
  556. DefinitionMgrClass::Unregister_Definition (DefinitionClass *definition)
  557. {
  558. WWASSERT (definition != 0);
  559. //WWASSERT (definition->m_DefinitionMgrLink >= 0 && definition->m_DefinitionMgrLink < _DefinitionCount);
  560. if (definition != NULL && definition->m_DefinitionMgrLink != -1) {
  561. //
  562. // Re-index the definitions that come after this definition in the list
  563. //
  564. for (int index = definition->m_DefinitionMgrLink; index < _DefinitionCount - 1; index ++) {
  565. _SortedDefinitionArray[index] = _SortedDefinitionArray[index + 1];
  566. _SortedDefinitionArray[index]->m_DefinitionMgrLink = index;
  567. }
  568. _SortedDefinitionArray[_DefinitionCount - 1] = NULL;
  569. definition->m_DefinitionMgrLink = -1;
  570. _DefinitionCount --;
  571. }
  572. return ;
  573. }
  574. //////////////////////////////////////////////////////////////////////////////////
  575. //
  576. // Save
  577. //
  578. //////////////////////////////////////////////////////////////////////////////////
  579. bool
  580. DefinitionMgrClass::Save
  581. (
  582. ChunkSaveClass & csave
  583. )
  584. {
  585. WWMEMLOG(MEM_GAMEDATA);
  586. bool retval = true;
  587. //
  588. // Create a chunk to contain the class variables we need to serialize.
  589. //
  590. csave.Begin_Chunk (CHUNKID_VARIABLES);
  591. Save_Variables (csave);
  592. csave.End_Chunk ();
  593. //
  594. // Have the base class write the objects to their own chunk.
  595. //
  596. csave.Begin_Chunk (CHUNKID_OBJECTS);
  597. retval &= Save_Objects (csave);
  598. csave.End_Chunk ();
  599. return retval;
  600. }
  601. //////////////////////////////////////////////////////////////////////////////////
  602. //
  603. // Load
  604. //
  605. //////////////////////////////////////////////////////////////////////////////////
  606. bool
  607. DefinitionMgrClass::Load (ChunkLoadClass &cload)
  608. {
  609. WWMEMLOG(MEM_GAMEDATA);
  610. bool retval = true;
  611. while (cload.Open_Chunk ()) {
  612. switch (cload.Cur_Chunk_ID ()) {
  613. //
  614. // If this is the chunk that contains the class variables, then
  615. // loop through and read each microchunk
  616. //
  617. case CHUNKID_VARIABLES:
  618. retval &= Load_Variables (cload);
  619. break;
  620. //
  621. // Load all the definition objects from this chunk
  622. //
  623. case CHUNKID_OBJECTS:
  624. retval &= Load_Objects (cload);
  625. break;
  626. }
  627. cload.Close_Chunk ();
  628. }
  629. return retval;
  630. }
  631. //////////////////////////////////////////////////////////////////////////////////
  632. //
  633. // Save_Objects
  634. //
  635. //////////////////////////////////////////////////////////////////////////////////
  636. bool
  637. DefinitionMgrClass::Save_Objects
  638. (
  639. ChunkSaveClass & csave
  640. )
  641. {
  642. bool retval = true;
  643. //
  644. // Loop through all the definition objects
  645. //
  646. for (int index = 0; index < _DefinitionCount; index ++) {
  647. DefinitionClass *definition = _SortedDefinitionArray[index];
  648. if (definition != NULL && definition->Is_Save_Enabled ()) {
  649. //
  650. // Save this definition object
  651. //
  652. csave.Begin_Chunk (definition->Get_Factory ().Chunk_ID ());
  653. definition->Get_Factory ().Save (csave, definition);
  654. csave.End_Chunk ();
  655. }
  656. }
  657. return retval;
  658. }
  659. //////////////////////////////////////////////////////////////////////////////////
  660. //
  661. // Save_Variables
  662. //
  663. //////////////////////////////////////////////////////////////////////////////////
  664. bool
  665. DefinitionMgrClass::Save_Variables (ChunkSaveClass &csave)
  666. {
  667. bool retval = true;
  668. return retval;
  669. }
  670. float _alloc_time;
  671. float _load_time;
  672. float _reg_time;
  673. //////////////////////////////////////////////////////////////////////////////////
  674. //
  675. // Load_Objects
  676. //
  677. //////////////////////////////////////////////////////////////////////////////////
  678. bool
  679. DefinitionMgrClass::Load_Objects (ChunkLoadClass &cload)
  680. {
  681. bool retval = true;
  682. while (cload.Open_Chunk ()) {
  683. //
  684. // Load this definition from the chunk (if possible)
  685. //
  686. PersistFactoryClass *factory = SaveLoadSystemClass::Find_Persist_Factory (cload.Cur_Chunk_ID ());
  687. if (factory != NULL) {
  688. DefinitionClass *definition = (DefinitionClass *)factory->Load (cload);
  689. if (definition != NULL) {
  690. //
  691. // Add this definition to our array
  692. //
  693. Prepare_Definition_Array ();
  694. _SortedDefinitionArray[_DefinitionCount ++] = definition;
  695. }
  696. }
  697. cload.Close_Chunk ();
  698. }
  699. //
  700. // Sort the definitions
  701. //
  702. if (_DefinitionCount > 0) {
  703. ::qsort (_SortedDefinitionArray, _DefinitionCount, sizeof (DefinitionClass *), fnCompareDefinitionsCallback);
  704. }
  705. //
  706. // Assign a mgr link to each definition
  707. //
  708. for (int index = 0; index < _DefinitionCount; index ++) {
  709. _SortedDefinitionArray[index]->m_DefinitionMgrLink = index;
  710. }
  711. return retval;
  712. }
  713. //////////////////////////////////////////////////////////////////////////////////
  714. //
  715. // Load_Variables
  716. //
  717. //////////////////////////////////////////////////////////////////////////////////
  718. bool
  719. DefinitionMgrClass::Load_Variables (ChunkLoadClass &cload)
  720. {
  721. bool retval = true;
  722. //
  723. // Loop through all the microchunks that define the variables
  724. //
  725. while (cload.Open_Micro_Chunk ()) {
  726. switch (cload.Cur_Micro_Chunk_ID ()) {
  727. case VARID_NEXTDEFID:
  728. break;
  729. }
  730. cload.Close_Micro_Chunk ();
  731. }
  732. return retval;
  733. }
  734. /////////////////////////////////////////////////////////////////////
  735. //
  736. // Get_New_ID
  737. //
  738. /////////////////////////////////////////////////////////////////////
  739. uint32
  740. DefinitionMgrClass::Get_New_ID (uint32 class_id)
  741. {
  742. uint32 idrange_start = (class_id - DEF_CLASSID_START) * IDRANGE_PER_CLASS;
  743. uint32 idrange_end = (idrange_start + IDRANGE_PER_CLASS);
  744. uint32 new_id = idrange_start;
  745. //
  746. // Loop through all the definition objects
  747. //
  748. for (int index = 0; index < _DefinitionCount; index ++) {
  749. DefinitionClass *definition = _SortedDefinitionArray[index];
  750. if (definition != NULL) {
  751. //
  752. // Get this definition's ID
  753. //
  754. uint32 curr_id = definition->Get_ID ();
  755. //
  756. // Is this id in the range we are looking for?
  757. //
  758. if (curr_id >= idrange_start && curr_id < idrange_end) {
  759. //
  760. // Take the largest ID in the range
  761. //
  762. new_id = max (new_id, curr_id);
  763. }
  764. }
  765. }
  766. new_id ++;
  767. return new_id;
  768. }
  769. ////////////////////////////////////////////////////////////////
  770. //
  771. // fnCompareDefinitionsCallback
  772. //
  773. ////////////////////////////////////////////////////////////////
  774. int __cdecl
  775. DefinitionMgrClass::fnCompareDefinitionsCallback
  776. (
  777. const void *elem1,
  778. const void *elem2
  779. )
  780. {
  781. WWASSERT (elem1 != NULL);
  782. WWASSERT (elem2 != NULL);
  783. DefinitionClass *definition1 = *((DefinitionClass **)elem1);
  784. DefinitionClass *definition2 = *((DefinitionClass **)elem2);
  785. //
  786. // Sort the definitions based on ID
  787. //
  788. int result = 0;
  789. if (definition1->Get_ID () > definition2->Get_ID ()) {
  790. result = 1;
  791. } else if (definition1->Get_ID () < definition2->Get_ID ()) {
  792. result = -1;
  793. } else {
  794. result = 0;
  795. }
  796. return result;
  797. }