Guest User

Untitled

a guest
Oct 19th, 2018
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.60 KB | None | 0 0
  1. // p_tick.h -------------------------------------------------------------------
  2.  
  3. // Enumeration
  4. // For thinkers needing savegame enumeration.
  5. void setOrdinal(unsigned int i) { ordinal = shouldSerialize() ? i : 0; }
  6. unsigned int getOrdinal() const { return ordinal; }
  7.  
  8. // Serialization
  9. // When using serialize, always call your parent implementation!
  10. virtual void serialize(SaveArchive &arc);
  11. // De-swizzling should restore pointers to other thinkers.
  12. virtual void deSwizzle() {}
  13. virtual bool shouldSerialize() const { return !removed; }
  14. virtual const char *getClassName() const { return "Thinker"; }
  15.  
  16. ...
  17.  
  18. //
  19. // Thinker Factory
  20. //
  21. // haleyjd 12/07/10: The save game code needs to be able to construct thinkers
  22. // of any class without resort to a gigantic switch statement. This calls for
  23. // a factory pattern.
  24. //
  25. class ThinkerType
  26. {
  27. protected:
  28. ThinkerType *next;
  29. const char *name;
  30.  
  31. public:
  32. ThinkerType(const char *pName);
  33.  
  34. // newThinker is a pure virtual method that must be overridden by a child
  35. // class to construct a specific type of thinker
  36. virtual Thinker *newThinker() const = 0;
  37.  
  38. // FindType is a static method that will find the ThinkerType given the
  39. // name of a Thinker-descendent class (ie., "FireFlickerThinker"). The returned
  40. // object can then be used to construct a new instance of that type by
  41. // calling the newThinker method. The instance can then be fed to the
  42. // serialization mechanism.
  43. static ThinkerType *FindType(const char *pName); // find a type in the list
  44. };
  45.  
  46. //
  47. // IMPLEMENT_THINKER_TYPE
  48. //
  49. // Use this macro once per Thinker descendant. Best placed near the Think
  50. // routine.
  51. // Example:
  52. // IMPLEMENT_THINKER_TYPE(FireFlickerThinker)
  53. // This defines FireFlickerThinkerType, which constructs a ThinkerType parent
  54. // with "FireFlickerThinker" as its name member and which returns a new FireFlickerThinker
  55. // instance via its newThinker virtual method.
  56. //
  57. #define IMPLEMENT_THINKER_TYPE(name) \
  58. class name ## Type : public ThinkerType \
  59. { \
  60. protected: \
  61. static name ## Type global ## name ## Type ; \
  62. public: \
  63. name ## Type() : ThinkerType( #name ) {} \
  64. virtual Thinker *newThinker() const { return new name ; } \
  65. }; \
  66. name ## Type name ## Type :: global ## name ## Type;
  67.  
  68.  
  69. // p_saveg.cpp ----------------------------------------------------------------
  70.  
  71. static void P_NumberThinkers(void)
  72. {
  73. Thinker *th;
  74.  
  75. num_thinkers = 0; // init to 0
  76.  
  77. // killough 2/14/98:
  78. // count the number of thinkers, and mark each one with its index, using
  79. // the prev field as a placeholder, since it can be restored later.
  80.  
  81. // haleyjd 11/26/10: Replaced with virtual enumeration facility
  82.  
  83. for(th = thinkercap.next; th != &thinkercap; th = th->next)
  84. {
  85. th->setOrdinal(num_thinkers + 1);
  86. if(th->getOrdinal() == num_thinkers + 1) // if accepted, increment
  87. ++num_thinkers;
  88. }
  89. }
  90.  
  91. static void P_DeNumberThinkers(void)
  92. {
  93. Thinker *th;
  94.  
  95. for(th = thinkercap.next; th != &thinkercap; th = th->next)
  96. th->setOrdinal(0);
  97. }
  98.  
  99. //
  100. // P_NumForThinker
  101. //
  102. // Get the mobj number from the mobj.
  103. //
  104. unsigned int P_NumForThinker(Thinker *th)
  105. {
  106. return th ? th->getOrdinal() : 0; // 0 == NULL
  107. }
  108.  
  109. //
  110. // P_ThinkerForNum
  111. //
  112. Thinker *P_ThinkerForNum(unsigned int n)
  113. {
  114. return n <= num_thinkers ? thinker_p[n] : NULL;
  115. }
  116.  
  117. ...
  118.  
  119. //
  120. // Thinkers
  121. //
  122.  
  123. #define tc_end "TC_END"
  124.  
  125. //
  126. // P_RemoveAllThinkers
  127. //
  128. static void P_RemoveAllThinkers(void)
  129. {
  130. Thinker *th;
  131.  
  132. // FIXME/TODO: This leaks all mobjs til the next level by calling
  133. // Thinker::InitThinkers. This should really be handled more
  134. // uniformly with a virtual method.
  135.  
  136. // remove all the current thinkers
  137. for(th = thinkercap.next; th != &thinkercap; )
  138. {
  139. Thinker *next;
  140. Mobj *mo;
  141. next = th->next;
  142. if((mo = dynamic_cast<Mobj *>(th)))
  143. mo->removeThinker();
  144. else
  145. delete th;
  146. th = next;
  147. }
  148.  
  149. // Clear out the list
  150. Thinker::InitThinkers();
  151. }
  152.  
  153. //
  154. // P_ArchiveThinkers
  155. //
  156. // 2/14/98 killough: substantially modified to fix savegame bugs
  157. //
  158. static void P_ArchiveThinkers(SaveArchive &arc)
  159. {
  160. Thinker *th;
  161.  
  162. // first, save or load count of enumerated thinkers
  163. arc << num_thinkers;
  164.  
  165. if(arc.isSaving())
  166. {
  167. // save off the current thinkers
  168. for(th = thinkercap.next; th != &thinkercap; th = th->next)
  169. {
  170. if(th->shouldSerialize())
  171. th->serialize(arc);
  172. }
  173.  
  174. // add a terminating marker
  175. arc.WriteLString(tc_end);
  176. }
  177. else
  178. {
  179. char *className = "";
  180. size_t len;
  181. unsigned int idx = 1; // Start at index 1, as 0 means NULL
  182. ThinkerType *thinkerType;
  183. Thinker *newThinker;
  184.  
  185. // allocate thinker table
  186. thinker_p = (Thinker **)(calloc(num_thinkers+1, sizeof(Thinker *)));
  187.  
  188. // clear out the thinker list
  189. P_RemoveAllThinkers();
  190.  
  191. while(1)
  192. {
  193. if(*className != '\0')
  194. free(className);
  195.  
  196. // Get the next class name
  197. arc.ArchiveLString(className, len);
  198.  
  199. // Find the ThinkerType matching this name
  200. if(!(thinkerType = ThinkerType::FindType(className)))
  201. {
  202. if(!strcmp(className, tc_end))
  203. break; // Reached end of thinker list
  204. else
  205. I_Error("Unknown tclass %s in savegame\n", className);
  206. }
  207.  
  208. // Create a thinker of the appropriate type and load it
  209. newThinker = thinkerType->newThinker();
  210. newThinker->serialize(arc);
  211.  
  212. // Put it in the table
  213. thinker_p[idx++] = newThinker;
  214.  
  215. // Add it
  216. newThinker->addThinker();
  217. }
  218.  
  219. // Now, call deswizzle to fix up mutual references between thinkers, such
  220. // as mobj targets/tracers and ACS triggers.
  221. for(th = thinkercap.next; th != &thinkercap; th = th->next)
  222. th->deSwizzle();
  223.  
  224. // killough 3/26/98: Spawn icon landings:
  225. // haleyjd 3/30/03: call P_InitThingLists
  226. P_InitThingLists();
  227. }
  228.  
  229. // Do sound targets
  230. P_ArchiveSoundTargets(arc);
  231. }
  232.  
  233. //
  234. // killough 11/98
  235. //
  236. // Same as P_SetTarget() in p_tick.c, except that the target is nullified
  237. // first, so that no old target's reference count is decreased (when loading
  238. // savegames, old targets are indices, not really pointers to targets).
  239. //
  240. void P_SetNewTarget(Mobj **mop, Mobj *targ)
  241. {
  242. *mop = NULL;
  243. P_SetTarget<Mobj>(mop, targ);
  244. }
  245.  
  246. // FIN ------------------------------------------------------------------------
Add Comment
Please, Sign In to add comment