g_save.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. // Copyright (c) ZeniMax Media Inc.
  2. // Licensed under the GNU General Public License 2.0.
  3. #include "g_local.h"
  4. #define Function(f) {#f, f}
  5. mmove_t mmove_reloc;
  6. field_t fields[] = {
  7. {"classname", FOFS(classname), F_LSTRING},
  8. {"model", FOFS(model), F_LSTRING},
  9. {"spawnflags", FOFS(spawnflags), F_INT},
  10. {"speed", FOFS(speed), F_FLOAT},
  11. {"accel", FOFS(accel), F_FLOAT},
  12. {"decel", FOFS(decel), F_FLOAT},
  13. {"target", FOFS(target), F_LSTRING},
  14. {"targetname", FOFS(targetname), F_LSTRING},
  15. {"pathtarget", FOFS(pathtarget), F_LSTRING},
  16. {"deathtarget", FOFS(deathtarget), F_LSTRING},
  17. {"killtarget", FOFS(killtarget), F_LSTRING},
  18. {"combattarget", FOFS(combattarget), F_LSTRING},
  19. {"message", FOFS(message), F_LSTRING},
  20. {"team", FOFS(team), F_LSTRING},
  21. {"wait", FOFS(wait), F_FLOAT},
  22. {"delay", FOFS(delay), F_FLOAT},
  23. {"random", FOFS(random), F_FLOAT},
  24. {"move_origin", FOFS(move_origin), F_VECTOR},
  25. {"move_angles", FOFS(move_angles), F_VECTOR},
  26. {"style", FOFS(style), F_INT},
  27. {"count", FOFS(count), F_INT},
  28. {"health", FOFS(health), F_INT},
  29. {"sounds", FOFS(sounds), F_INT},
  30. {"light", 0, F_IGNORE},
  31. {"dmg", FOFS(dmg), F_INT},
  32. {"mass", FOFS(mass), F_INT},
  33. {"volume", FOFS(volume), F_FLOAT},
  34. {"attenuation", FOFS(attenuation), F_FLOAT},
  35. {"map", FOFS(map), F_LSTRING},
  36. {"origin", FOFS(s.origin), F_VECTOR},
  37. {"angles", FOFS(s.angles), F_VECTOR},
  38. {"angle", FOFS(s.angles), F_ANGLEHACK},
  39. {"goalentity", FOFS(goalentity), F_EDICT, FFL_NOSPAWN},
  40. {"movetarget", FOFS(movetarget), F_EDICT, FFL_NOSPAWN},
  41. {"enemy", FOFS(enemy), F_EDICT, FFL_NOSPAWN},
  42. {"oldenemy", FOFS(oldenemy), F_EDICT, FFL_NOSPAWN},
  43. {"activator", FOFS(activator), F_EDICT, FFL_NOSPAWN},
  44. {"groundentity", FOFS(groundentity), F_EDICT, FFL_NOSPAWN},
  45. {"teamchain", FOFS(teamchain), F_EDICT, FFL_NOSPAWN},
  46. {"teammaster", FOFS(teammaster), F_EDICT, FFL_NOSPAWN},
  47. {"owner", FOFS(owner), F_EDICT, FFL_NOSPAWN},
  48. {"mynoise", FOFS(mynoise), F_EDICT, FFL_NOSPAWN},
  49. {"mynoise2", FOFS(mynoise2), F_EDICT, FFL_NOSPAWN},
  50. {"target_ent", FOFS(target_ent), F_EDICT, FFL_NOSPAWN},
  51. {"chain", FOFS(chain), F_EDICT, FFL_NOSPAWN},
  52. {"prethink", FOFS(prethink), F_FUNCTION, FFL_NOSPAWN},
  53. {"think", FOFS(think), F_FUNCTION, FFL_NOSPAWN},
  54. {"blocked", FOFS(blocked), F_FUNCTION, FFL_NOSPAWN},
  55. {"touch", FOFS(touch), F_FUNCTION, FFL_NOSPAWN},
  56. {"use", FOFS(use), F_FUNCTION, FFL_NOSPAWN},
  57. {"pain", FOFS(pain), F_FUNCTION, FFL_NOSPAWN},
  58. {"die", FOFS(die), F_FUNCTION, FFL_NOSPAWN},
  59. {"stand", FOFS(monsterinfo.stand), F_FUNCTION, FFL_NOSPAWN},
  60. {"idle", FOFS(monsterinfo.idle), F_FUNCTION, FFL_NOSPAWN},
  61. {"search", FOFS(monsterinfo.search), F_FUNCTION, FFL_NOSPAWN},
  62. {"walk", FOFS(monsterinfo.walk), F_FUNCTION, FFL_NOSPAWN},
  63. {"run", FOFS(monsterinfo.run), F_FUNCTION, FFL_NOSPAWN},
  64. {"dodge", FOFS(monsterinfo.dodge), F_FUNCTION, FFL_NOSPAWN},
  65. {"attack", FOFS(monsterinfo.attack), F_FUNCTION, FFL_NOSPAWN},
  66. {"melee", FOFS(monsterinfo.melee), F_FUNCTION, FFL_NOSPAWN},
  67. {"sight", FOFS(monsterinfo.sight), F_FUNCTION, FFL_NOSPAWN},
  68. {"checkattack", FOFS(monsterinfo.checkattack), F_FUNCTION, FFL_NOSPAWN},
  69. {"currentmove", FOFS(monsterinfo.currentmove), F_MMOVE, FFL_NOSPAWN},
  70. {"endfunc", FOFS(moveinfo.endfunc), F_FUNCTION, FFL_NOSPAWN},
  71. // temp spawn vars -- only valid when the spawn function is called
  72. {"lip", STOFS(lip), F_INT, FFL_SPAWNTEMP},
  73. {"distance", STOFS(distance), F_INT, FFL_SPAWNTEMP},
  74. {"height", STOFS(height), F_INT, FFL_SPAWNTEMP},
  75. {"noise", STOFS(noise), F_LSTRING, FFL_SPAWNTEMP},
  76. {"pausetime", STOFS(pausetime), F_FLOAT, FFL_SPAWNTEMP},
  77. {"item", STOFS(item), F_LSTRING, FFL_SPAWNTEMP},
  78. //need for item field in edict struct, FFL_SPAWNTEMP item will be skipped on saves
  79. {"item", FOFS(item), F_ITEM},
  80. {"gravity", STOFS(gravity), F_LSTRING, FFL_SPAWNTEMP},
  81. {"sky", STOFS(sky), F_LSTRING, FFL_SPAWNTEMP},
  82. {"skyrotate", STOFS(skyrotate), F_FLOAT, FFL_SPAWNTEMP},
  83. {"skyaxis", STOFS(skyaxis), F_VECTOR, FFL_SPAWNTEMP},
  84. {"minyaw", STOFS(minyaw), F_FLOAT, FFL_SPAWNTEMP},
  85. {"maxyaw", STOFS(maxyaw), F_FLOAT, FFL_SPAWNTEMP},
  86. {"minpitch", STOFS(minpitch), F_FLOAT, FFL_SPAWNTEMP},
  87. {"maxpitch", STOFS(maxpitch), F_FLOAT, FFL_SPAWNTEMP},
  88. {"nextmap", STOFS(nextmap), F_LSTRING, FFL_SPAWNTEMP},
  89. // ROGUE
  90. {"bad_area", FOFS(bad_area), F_EDICT},
  91. // while the hint_path stuff could be reassembled on the fly, no reason to be different
  92. {"hint_chain", FOFS(hint_chain), F_EDICT},
  93. {"monster_hint_chain", FOFS(monster_hint_chain), F_EDICT},
  94. {"target_hint_chain", FOFS(target_hint_chain), F_EDICT},
  95. //
  96. {"goal_hint", FOFS(monsterinfo.goal_hint), F_EDICT},
  97. {"badMedic1", FOFS(monsterinfo.badMedic1), F_EDICT},
  98. {"badMedic2", FOFS(monsterinfo.badMedic2), F_EDICT},
  99. {"last_player_enemy", FOFS(monsterinfo.last_player_enemy), F_EDICT},
  100. {"commander", FOFS(monsterinfo.commander), F_EDICT},
  101. {"blocked", FOFS(monsterinfo.blocked), F_MMOVE, FFL_NOSPAWN},
  102. {"duck", FOFS(monsterinfo.duck), F_MMOVE, FFL_NOSPAWN},
  103. {"unduck", FOFS(monsterinfo.unduck), F_MMOVE, FFL_NOSPAWN},
  104. {"sidestep", FOFS(monsterinfo.sidestep), F_MMOVE, FFL_NOSPAWN},
  105. // ROGUE
  106. {0, 0, 0, 0}
  107. };
  108. field_t levelfields[] =
  109. {
  110. {"changemap", LLOFS(changemap), F_LSTRING},
  111. {"sight_client", LLOFS(sight_client), F_EDICT},
  112. {"sight_entity", LLOFS(sight_entity), F_EDICT},
  113. {"sound_entity", LLOFS(sound_entity), F_EDICT},
  114. {"sound2_entity", LLOFS(sound2_entity), F_EDICT},
  115. // ROGUE
  116. {"disguise_violator", LLOFS(disguise_violator), F_EDICT},
  117. // ROGUE
  118. {NULL, 0, F_INT}
  119. };
  120. field_t clientfields[] =
  121. {
  122. {"pers.weapon", CLOFS(pers.weapon), F_ITEM},
  123. {"pers.lastweapon", CLOFS(pers.lastweapon), F_ITEM},
  124. {"newweapon", CLOFS(newweapon), F_ITEM},
  125. // ROGUE
  126. {"owned_sphere", CLOFS(owned_sphere), F_EDICT},
  127. // ROGUE
  128. {NULL, 0, F_INT}
  129. };
  130. /*
  131. ============
  132. InitGame
  133. This will be called when the dll is first loaded, which
  134. only happens when a new game is started or a save game
  135. is loaded.
  136. ============
  137. */
  138. void InitGame (void)
  139. {
  140. gi.dprintf ("==== InitGame ====\n");
  141. gun_x = gi.cvar ("gun_x", "0", 0);
  142. gun_y = gi.cvar ("gun_y", "0", 0);
  143. gun_z = gi.cvar ("gun_z", "0", 0);
  144. //FIXME: sv_ prefix is wrong for these
  145. sv_rollspeed = gi.cvar ("sv_rollspeed", "200", 0);
  146. sv_rollangle = gi.cvar ("sv_rollangle", "2", 0);
  147. sv_maxvelocity = gi.cvar ("sv_maxvelocity", "2000", 0);
  148. sv_gravity = gi.cvar ("sv_gravity", "800", 0);
  149. sv_stopspeed = gi.cvar ("sv_stopspeed", "100", 0); // PGM - was #define in g_phys.c
  150. //ROGUE
  151. g_showlogic = gi.cvar ("g_showlogic", "0", 0);
  152. huntercam = gi.cvar ("huntercam", "1", CVAR_SERVERINFO|CVAR_LATCH);
  153. strong_mines = gi.cvar ("strong_mines", "0", 0);
  154. randomrespawn = gi.cvar ("randomrespawn", "0", 0);
  155. //ROGUE
  156. // noset vars
  157. dedicated = gi.cvar ("dedicated", "0", CVAR_NOSET);
  158. // latched vars
  159. sv_cheats = gi.cvar ("cheats", "0", CVAR_SERVERINFO|CVAR_LATCH);
  160. gi.cvar ("gamename", GAMEVERSION , CVAR_SERVERINFO | CVAR_LATCH);
  161. gi.cvar ("gamedate", __DATE__ , CVAR_SERVERINFO | CVAR_LATCH);
  162. maxclients = gi.cvar ("maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH);
  163. maxspectators = gi.cvar ("maxspectators", "4", CVAR_SERVERINFO);
  164. deathmatch = gi.cvar ("deathmatch", "0", CVAR_LATCH);
  165. coop = gi.cvar ("coop", "0", CVAR_LATCH);
  166. skill = gi.cvar ("skill", "1", CVAR_LATCH);
  167. maxentities = gi.cvar ("maxentities", "1024", CVAR_LATCH);
  168. gamerules = gi.cvar ("gamerules", "0", CVAR_LATCH); //PGM
  169. // change anytime vars
  170. dmflags = gi.cvar ("dmflags", "0", CVAR_SERVERINFO);
  171. fraglimit = gi.cvar ("fraglimit", "0", CVAR_SERVERINFO);
  172. timelimit = gi.cvar ("timelimit", "0", CVAR_SERVERINFO);
  173. password = gi.cvar ("password", "", CVAR_USERINFO);
  174. spectator_password = gi.cvar ("spectator_password", "", CVAR_USERINFO);
  175. filterban = gi.cvar ("filterban", "1", 0);
  176. g_select_empty = gi.cvar ("g_select_empty", "0", CVAR_ARCHIVE);
  177. run_pitch = gi.cvar ("run_pitch", "0.002", 0);
  178. run_roll = gi.cvar ("run_roll", "0.005", 0);
  179. bob_up = gi.cvar ("bob_up", "0.005", 0);
  180. bob_pitch = gi.cvar ("bob_pitch", "0.002", 0);
  181. bob_roll = gi.cvar ("bob_roll", "0.002", 0);
  182. // flood control
  183. flood_msgs = gi.cvar ("flood_msgs", "4", 0);
  184. flood_persecond = gi.cvar ("flood_persecond", "4", 0);
  185. flood_waitdelay = gi.cvar ("flood_waitdelay", "10", 0);
  186. // dm map list
  187. sv_maplist = gi.cvar ("sv_maplist", "", 0);
  188. // items
  189. InitItems ();
  190. Com_sprintf (game.helpmessage1, sizeof(game.helpmessage1), "");
  191. Com_sprintf (game.helpmessage2, sizeof(game.helpmessage2), "");
  192. // initialize all entities for this game
  193. game.maxentities = maxentities->value;
  194. g_edicts = gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
  195. globals.edicts = g_edicts;
  196. globals.max_edicts = game.maxentities;
  197. // initialize all clients for this game
  198. game.maxclients = maxclients->value;
  199. game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);
  200. globals.num_edicts = game.maxclients+1;
  201. //======
  202. //ROGUE
  203. if(gamerules)
  204. {
  205. InitGameRules(); // if there are game rules to set up, do so now.
  206. }
  207. //ROGUE
  208. //======
  209. }
  210. //=========================================================
  211. void WriteField1 (FILE *f, field_t *field, byte *base)
  212. {
  213. void *p;
  214. int len;
  215. int index;
  216. if (field->flags & FFL_SPAWNTEMP)
  217. return;
  218. p = (void *)(base + field->ofs);
  219. switch (field->type)
  220. {
  221. case F_INT:
  222. case F_FLOAT:
  223. case F_ANGLEHACK:
  224. case F_VECTOR:
  225. case F_IGNORE:
  226. break;
  227. case F_LSTRING:
  228. case F_GSTRING:
  229. if ( *(char **)p )
  230. len = strlen(*(char **)p) + 1;
  231. else
  232. len = 0;
  233. *(int *)p = len;
  234. break;
  235. case F_EDICT:
  236. if ( *(edict_t **)p == NULL)
  237. index = -1;
  238. else
  239. index = *(edict_t **)p - g_edicts;
  240. *(int *)p = index;
  241. break;
  242. case F_CLIENT:
  243. if ( *(gclient_t **)p == NULL)
  244. index = -1;
  245. else
  246. index = *(gclient_t **)p - game.clients;
  247. *(int *)p = index;
  248. break;
  249. case F_ITEM:
  250. if ( *(edict_t **)p == NULL)
  251. index = -1;
  252. else
  253. index = *(gitem_t **)p - itemlist;
  254. *(int *)p = index;
  255. break;
  256. //relative to code segment
  257. case F_FUNCTION:
  258. if (*(byte **)p == NULL)
  259. index = 0;
  260. else
  261. index = *(byte **)p - ((byte *)InitGame);
  262. *(int *)p = index;
  263. break;
  264. //relative to data segment
  265. case F_MMOVE:
  266. if (*(byte **)p == NULL)
  267. index = 0;
  268. else
  269. index = *(byte **)p - (byte *)&mmove_reloc;
  270. *(int *)p = index;
  271. break;
  272. default:
  273. gi.error ("WriteEdict: unknown field type");
  274. }
  275. }
  276. void WriteField2 (FILE *f, field_t *field, byte *base)
  277. {
  278. int len;
  279. void *p;
  280. if (field->flags & FFL_SPAWNTEMP)
  281. return;
  282. p = (void *)(base + field->ofs);
  283. switch (field->type)
  284. {
  285. case F_LSTRING:
  286. if ( *(char **)p )
  287. {
  288. len = strlen(*(char **)p) + 1;
  289. fwrite (*(char **)p, len, 1, f);
  290. }
  291. break;
  292. }
  293. }
  294. void ReadField (FILE *f, field_t *field, byte *base)
  295. {
  296. void *p;
  297. int len;
  298. int index;
  299. if (field->flags & FFL_SPAWNTEMP)
  300. return;
  301. p = (void *)(base + field->ofs);
  302. switch (field->type)
  303. {
  304. case F_INT:
  305. case F_FLOAT:
  306. case F_ANGLEHACK:
  307. case F_VECTOR:
  308. case F_IGNORE:
  309. break;
  310. case F_LSTRING:
  311. len = *(int *)p;
  312. if (!len)
  313. *(char **)p = NULL;
  314. else
  315. {
  316. *(char **)p = gi.TagMalloc (len, TAG_LEVEL);
  317. fread (*(char **)p, len, 1, f);
  318. }
  319. break;
  320. case F_EDICT:
  321. index = *(int *)p;
  322. if ( index == -1 )
  323. *(edict_t **)p = NULL;
  324. else
  325. *(edict_t **)p = &g_edicts[index];
  326. break;
  327. case F_CLIENT:
  328. index = *(int *)p;
  329. if ( index == -1 )
  330. *(gclient_t **)p = NULL;
  331. else
  332. *(gclient_t **)p = &game.clients[index];
  333. break;
  334. case F_ITEM:
  335. index = *(int *)p;
  336. if ( index == -1 )
  337. *(gitem_t **)p = NULL;
  338. else
  339. *(gitem_t **)p = &itemlist[index];
  340. break;
  341. //relative to code segment
  342. case F_FUNCTION:
  343. index = *(int *)p;
  344. if ( index == 0 )
  345. *(byte **)p = NULL;
  346. else
  347. *(byte **)p = ((byte *)InitGame) + index;
  348. break;
  349. //relative to data segment
  350. case F_MMOVE:
  351. index = *(int *)p;
  352. if (index == 0)
  353. *(byte **)p = NULL;
  354. else
  355. *(byte **)p = (byte *)&mmove_reloc + index;
  356. break;
  357. default:
  358. gi.error ("ReadEdict: unknown field type");
  359. }
  360. }
  361. //=========================================================
  362. /*
  363. ==============
  364. WriteClient
  365. All pointer variables (except function pointers) must be handled specially.
  366. ==============
  367. */
  368. void WriteClient (FILE *f, gclient_t *client)
  369. {
  370. field_t *field;
  371. gclient_t temp;
  372. // all of the ints, floats, and vectors stay as they are
  373. temp = *client;
  374. // change the pointers to lengths or indexes
  375. for (field=clientfields ; field->name ; field++)
  376. {
  377. WriteField1 (f, field, (byte *)&temp);
  378. }
  379. // write the block
  380. fwrite (&temp, sizeof(temp), 1, f);
  381. // now write any allocated data following the edict
  382. for (field=clientfields ; field->name ; field++)
  383. {
  384. WriteField2 (f, field, (byte *)client);
  385. }
  386. }
  387. /*
  388. ==============
  389. ReadClient
  390. All pointer variables (except function pointers) must be handled specially.
  391. ==============
  392. */
  393. void ReadClient (FILE *f, gclient_t *client)
  394. {
  395. field_t *field;
  396. fread (client, sizeof(*client), 1, f);
  397. for (field=clientfields ; field->name ; field++)
  398. {
  399. ReadField (f, field, (byte *)client);
  400. }
  401. }
  402. /*
  403. ============
  404. WriteGame
  405. This will be called whenever the game goes to a new level,
  406. and when the user explicitly saves the game.
  407. Game information include cross level data, like multi level
  408. triggers, help computer info, and all client states.
  409. A single player death will automatically restore from the
  410. last save position.
  411. ============
  412. */
  413. void WriteGame (char *filename, qboolean autosave)
  414. {
  415. FILE *f;
  416. int i;
  417. char str[16];
  418. if (!autosave)
  419. SaveClientData ();
  420. f = fopen (filename, "wb");
  421. if (!f)
  422. gi.error ("Couldn't open %s", filename);
  423. memset (str, 0, sizeof(str));
  424. strcpy (str, __DATE__);
  425. fwrite (str, sizeof(str), 1, f);
  426. game.autosaved = autosave;
  427. fwrite (&game, sizeof(game), 1, f);
  428. game.autosaved = false;
  429. for (i=0 ; i<game.maxclients ; i++)
  430. WriteClient (f, &game.clients[i]);
  431. fclose (f);
  432. }
  433. void ReadGame (char *filename)
  434. {
  435. FILE *f;
  436. int i;
  437. char str[16];
  438. gi.FreeTags (TAG_GAME);
  439. f = fopen (filename, "rb");
  440. if (!f)
  441. gi.error ("Couldn't open %s", filename);
  442. fread (str, sizeof(str), 1, f);
  443. if (strcmp (str, __DATE__))
  444. {
  445. fclose (f);
  446. gi.error ("Savegame from an older version.\n");
  447. }
  448. g_edicts = gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
  449. globals.edicts = g_edicts;
  450. fread (&game, sizeof(game), 1, f);
  451. game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);
  452. for (i=0 ; i<game.maxclients ; i++)
  453. ReadClient (f, &game.clients[i]);
  454. fclose (f);
  455. }
  456. //==========================================================
  457. /*
  458. ==============
  459. WriteEdict
  460. All pointer variables (except function pointers) must be handled specially.
  461. ==============
  462. */
  463. void WriteEdict (FILE *f, edict_t *ent)
  464. {
  465. field_t *field;
  466. edict_t temp;
  467. // all of the ints, floats, and vectors stay as they are
  468. temp = *ent;
  469. // change the pointers to lengths or indexes
  470. for (field=fields ; field->name ; field++)
  471. {
  472. WriteField1 (f, field, (byte *)&temp);
  473. }
  474. // write the block
  475. fwrite (&temp, sizeof(temp), 1, f);
  476. // now write any allocated data following the edict
  477. for (field=fields ; field->name ; field++)
  478. {
  479. WriteField2 (f, field, (byte *)ent);
  480. }
  481. }
  482. /*
  483. ==============
  484. WriteLevelLocals
  485. All pointer variables (except function pointers) must be handled specially.
  486. ==============
  487. */
  488. void WriteLevelLocals (FILE *f)
  489. {
  490. field_t *field;
  491. level_locals_t temp;
  492. // all of the ints, floats, and vectors stay as they are
  493. temp = level;
  494. // change the pointers to lengths or indexes
  495. for (field=levelfields ; field->name ; field++)
  496. {
  497. WriteField1 (f, field, (byte *)&temp);
  498. }
  499. // write the block
  500. fwrite (&temp, sizeof(temp), 1, f);
  501. // now write any allocated data following the edict
  502. for (field=levelfields ; field->name ; field++)
  503. {
  504. WriteField2 (f, field, (byte *)&level);
  505. }
  506. }
  507. /*
  508. ==============
  509. ReadEdict
  510. All pointer variables (except function pointers) must be handled specially.
  511. ==============
  512. */
  513. void ReadEdict (FILE *f, edict_t *ent)
  514. {
  515. field_t *field;
  516. fread (ent, sizeof(*ent), 1, f);
  517. for (field=fields ; field->name ; field++)
  518. {
  519. ReadField (f, field, (byte *)ent);
  520. }
  521. }
  522. /*
  523. ==============
  524. ReadLevelLocals
  525. All pointer variables (except function pointers) must be handled specially.
  526. ==============
  527. */
  528. void ReadLevelLocals (FILE *f)
  529. {
  530. field_t *field;
  531. fread (&level, sizeof(level), 1, f);
  532. for (field=levelfields ; field->name ; field++)
  533. {
  534. ReadField (f, field, (byte *)&level);
  535. }
  536. }
  537. /*
  538. =================
  539. WriteLevel
  540. =================
  541. */
  542. void WriteLevel (char *filename)
  543. {
  544. int i;
  545. edict_t *ent;
  546. FILE *f;
  547. void *base;
  548. f = fopen (filename, "wb");
  549. if (!f)
  550. gi.error ("Couldn't open %s", filename);
  551. // write out edict size for checking
  552. i = sizeof(edict_t);
  553. fwrite (&i, sizeof(i), 1, f);
  554. // write out a function pointer for checking
  555. base = (void *)InitGame;
  556. fwrite (&base, sizeof(base), 1, f);
  557. // write out level_locals_t
  558. WriteLevelLocals (f);
  559. // write out all the entities
  560. for (i=0 ; i<globals.num_edicts ; i++)
  561. {
  562. ent = &g_edicts[i];
  563. if (!ent->inuse)
  564. continue;
  565. fwrite (&i, sizeof(i), 1, f);
  566. WriteEdict (f, ent);
  567. }
  568. i = -1;
  569. fwrite (&i, sizeof(i), 1, f);
  570. fclose (f);
  571. }
  572. /*
  573. =================
  574. ReadLevel
  575. SpawnEntities will already have been called on the
  576. level the same way it was when the level was saved.
  577. That is necessary to get the baselines
  578. set up identically.
  579. The server will have cleared all of the world links before
  580. calling ReadLevel.
  581. No clients are connected yet.
  582. =================
  583. */
  584. void ReadLevel (char *filename)
  585. {
  586. int entnum;
  587. FILE *f;
  588. int i;
  589. void *base;
  590. edict_t *ent;
  591. f = fopen (filename, "rb");
  592. if (!f)
  593. gi.error ("Couldn't open %s", filename);
  594. // free any dynamic memory allocated by loading the level
  595. // base state
  596. gi.FreeTags (TAG_LEVEL);
  597. // wipe all the entities
  598. memset (g_edicts, 0, game.maxentities*sizeof(g_edicts[0]));
  599. globals.num_edicts = maxclients->value+1;
  600. // check edict size
  601. fread (&i, sizeof(i), 1, f);
  602. if (i != sizeof(edict_t))
  603. {
  604. fclose (f);
  605. gi.error ("ReadLevel: mismatched edict size");
  606. }
  607. // check function pointer base address
  608. fread (&base, sizeof(base), 1, f);
  609. #ifdef _WIN32
  610. if (base != (void *)InitGame)
  611. {
  612. fclose (f);
  613. gi.error ("ReadLevel: function pointers have moved");
  614. }
  615. #else
  616. gi.dprintf("Function offsets %d\n", ((byte *)base) - ((byte *)InitGame));
  617. #endif
  618. // load the level locals
  619. ReadLevelLocals (f);
  620. // load all the entities
  621. while (1)
  622. {
  623. if (fread (&entnum, sizeof(entnum), 1, f) != 1)
  624. {
  625. fclose (f);
  626. gi.error ("ReadLevel: failed to read entnum");
  627. }
  628. if (entnum == -1)
  629. break;
  630. if (entnum >= globals.num_edicts)
  631. globals.num_edicts = entnum+1;
  632. ent = &g_edicts[entnum];
  633. ReadEdict (f, ent);
  634. // let the server rebuild world links for this ent
  635. memset (&ent->area, 0, sizeof(ent->area));
  636. gi.linkentity (ent);
  637. }
  638. fclose (f);
  639. // PMM - rebuild the hint path chains
  640. // InitHintPaths();
  641. // pmm
  642. // mark all clients as unconnected
  643. for (i=0 ; i<maxclients->value ; i++)
  644. {
  645. ent = &g_edicts[i+1];
  646. ent->client = game.clients + i;
  647. ent->client->pers.connected = false;
  648. }
  649. // do any load time things at this point
  650. for (i=0 ; i<globals.num_edicts ; i++)
  651. {
  652. ent = &g_edicts[i];
  653. if (!ent->inuse)
  654. continue;
  655. // fire any cross-level triggers
  656. if (ent->classname)
  657. if (strcmp(ent->classname, "target_crosslevel_target") == 0)
  658. ent->nextthink = level.time + ent->delay;
  659. }
  660. }