Den Savegamecode hoch auf 3.20 portiert. Muss noch mal ordentlich

durchgetestet werden, gerade auf 32Bit und Linux
This commit is contained in:
Yamagi Burmeister 2009-04-10 14:23:07 +00:00
parent 347d281530
commit 2590b35e2a
2 changed files with 86 additions and 130 deletions

View file

@ -559,10 +559,10 @@ extern int meansOfDeath;
extern edict_t *g_edicts;
#define FOFS(x) (int)&(((edict_t *)0)->x)
#define STOFS(x) (int)&(((spawn_temp_t *)0)->x)
#define LLOFS(x) (int)&(((level_locals_t *)0)->x)
#define CLOFS(x) (int)&(((gclient_t *)0)->x)
#define FOFS(x) (size_t)&(((edict_t *)NULL)->x)
#define STOFS(x) (size_t)&(((spawn_temp_t *)NULL)->x)
#define LLOFS(x) (size_t)&(((level_locals_t *)NULL)->x)
#define CLOFS(x) (size_t)&(((gclient_t *)NULL)->x)
#define random() ((rand () & 0x7fff) / ((float)0x7fff))
#define crandom() (2.0 * (random() - 0.5))
@ -631,6 +631,8 @@ typedef enum {
F_EDICT, // index on disk, pointer in memory
F_ITEM, // index on disk, pointer in memory
F_CLIENT, // index on disk, pointer in memory
F_FUNCTION,
F_MMOVE,
F_IGNORE
} fieldtype_t;

View file

@ -1,13 +1,8 @@
#include "g_local.h"
#if defined(_DEBUG) && defined(_Z_TESTMODE)
void InitTestWeapon(void);
void InitTestItem(void);
#endif
#define Function(f) {#f, f}
mmove_t mmove_reloc;
field_t fields[] = {
{"classname", FOFS(classname), F_LSTRING},
@ -70,83 +65,33 @@ field_t fields[] = {
{"maxyaw", STOFS(maxyaw), F_FLOAT, FFL_SPAWNTEMP},
{"minpitch", STOFS(minpitch), F_FLOAT, FFL_SPAWNTEMP},
{"maxpitch", STOFS(maxpitch), F_FLOAT, FFL_SPAWNTEMP},
{"nextmap", STOFS(nextmap), F_LSTRING, FFL_SPAWNTEMP}
};
// -------- just for savegames ----------
// all pointer fields should be listed here, or savegames
// won't work properly (they will crash and burn).
// this wasn't just tacked on to the fields array, because
// these don't need names, we wouldn't want map fields using
// some of these, and if one were accidentally present twice
// it would double swizzle (fuck) the pointer.
field_t savefields[] =
{
{"", FOFS(classname), F_LSTRING},
{"", FOFS(target), F_LSTRING},
{"", FOFS(targetname), F_LSTRING},
{"", FOFS(killtarget), F_LSTRING},
{"", FOFS(team), F_LSTRING},
{"", FOFS(pathtarget), F_LSTRING},
{"", FOFS(deathtarget), F_LSTRING},
{"", FOFS(combattarget), F_LSTRING},
{"", FOFS(model), F_LSTRING},
{"", FOFS(model2), F_LSTRING},
{"", FOFS(model3), F_LSTRING},
{"", FOFS(model4), F_LSTRING},
{"", FOFS(map), F_LSTRING},
{"", FOFS(message), F_LSTRING},
{"", FOFS(client), F_CLIENT},
{"", FOFS(item), F_ITEM},
{"", FOFS(goalentity), F_EDICT},
{"", FOFS(movetarget), F_EDICT},
{"", FOFS(enemy), F_EDICT},
{"", FOFS(oldenemy), F_EDICT},
{"", FOFS(activator), F_EDICT},
{"", FOFS(groundentity), F_EDICT},
{"", FOFS(teamchain), F_EDICT},
{"", FOFS(teammaster), F_EDICT},
{"", FOFS(owner), F_EDICT},
{"", FOFS(mynoise), F_EDICT},
{"", FOFS(mynoise2), F_EDICT},
{"", FOFS(target_ent), F_EDICT},
{"", FOFS(chain), F_EDICT},
{"nextmap", STOFS(nextmap), F_LSTRING, FFL_SPAWNTEMP},
// evolve
{"", FOFS(laser), F_EDICT},
{"", FOFS(zRaduisList), F_EDICT},
{"", FOFS(zSchoolChain), F_EDICT},
{"", FOFS(rideWith[0]), F_EDICT},
{"", FOFS(rideWith[1]), F_EDICT},
{"", FOFS(mteam), F_LSTRING},
{NULL, 0, F_INT}
{0, 0, 0, 0}
};
field_t levelfields[] =
{
{"", LLOFS(changemap), F_LSTRING},
{"", LLOFS(sight_client), F_EDICT},
{"", LLOFS(sight_entity), F_EDICT},
{"", LLOFS(sound_entity), F_EDICT},
{"", LLOFS(sound2_entity), F_EDICT},
{"changemap", LLOFS(changemap), F_LSTRING},
{"sight_client", LLOFS(sight_client), F_EDICT},
{"sight_entity", LLOFS(sight_entity), F_EDICT},
{"sound_entity", LLOFS(sound_entity), F_EDICT},
{"sound2_entity", LLOFS(sound2_entity), F_EDICT},
{NULL, 0, F_INT}
};
field_t clientfields[] =
{
{"", CLOFS(pers.weapon), F_ITEM},
{"", CLOFS(pers.lastweapon), F_ITEM},
{"", CLOFS(pers.lastweapon2), F_ITEM},
{"", CLOFS(newweapon), F_ITEM},
{"pers.weapon", CLOFS(pers.weapon), F_ITEM},
{"pers.lastweapon", CLOFS(pers.lastweapon), F_ITEM},
{"pers.lastweapon2", CLOFS(pers.lastweapon2), F_ITEM},
{"newweapon", CLOFS(newweapon), F_ITEM},
// evolve
{"", CLOFS(zCameraTrack), F_EDICT},
{"", CLOFS(zCameraLocalEntity), F_EDICT},
{"zCameraTrack", CLOFS(zCameraTrack), F_EDICT},
{"zCameraLocalEntitiy", CLOFS(zCameraLocalEntity), F_EDICT},
{NULL, 0, F_INT}
};
@ -204,23 +149,10 @@ void InitGame (void)
bob_roll = gi.cvar ("bob_roll", "0.002", 0);
gamedir = gi.cvar ("gamedir", "baseq2", CVAR_SERVERINFO);
#ifdef CACHE_SOUND
printSoundRejects = gi.cvar("printsoundrejects", "0", CVAR_SERVERINFO);
#endif
// items
InitItems ();
#if defined(_DEBUG) && defined(_Z_TESTMODE)
gi.dprintf ("==== InitTestWeapon ====\n");
InitTestWeapon();
gi.dprintf ("==== InitTestItem ====\n");
InitTestItem();
#endif
Com_sprintf (game.helpmessage1, sizeof(game.helpmessage1), "");
Com_sprintf (game.helpmessage2, sizeof(game.helpmessage2), "");
@ -248,6 +180,9 @@ void WriteField1 (FILE *f, field_t *field, byte *base)
int len;
int index;
if (field->flags & FFL_SPAWNTEMP)
return;
p = (void *)(base + field->ofs);
switch (field->type)
{
@ -288,16 +223,38 @@ void WriteField1 (FILE *f, field_t *field, byte *base)
*(int *)p = index;
break;
//relative to code segment
case F_FUNCTION:
if (*(byte **)p == NULL)
index = 0;
else
index = *(byte **)p - ((byte *)InitGame);
*(int *)p = index;
break;
//relative to data segment
case F_MMOVE:
if (*(byte **)p == NULL)
index = 0;
else
index = *(byte **)p - (byte *)&mmove_reloc;
*(int *)p = index;
break;
default:
gi.error ("WriteEdict: unknown field type");
}
}
void WriteField2 (FILE *f, field_t *field, byte *base)
{
int len;
void *p;
if (field->flags & FFL_SPAWNTEMP)
return;
p = (void *)(base + field->ofs);
switch (field->type)
{
@ -309,6 +266,8 @@ void WriteField2 (FILE *f, field_t *field, byte *base)
fwrite (*(char **)p, len, 1, f);
}
break;
default:
break;
}
}
@ -318,6 +277,9 @@ void ReadField (FILE *f, field_t *field, byte *base)
int len;
int index;
if (field->flags & FFL_SPAWNTEMP)
return;
p = (void *)(base + field->ofs);
switch (field->type)
{
@ -334,17 +296,11 @@ void ReadField (FILE *f, field_t *field, byte *base)
*(char **)p = NULL;
else
{
*(char **)p = gi.TagMalloc (len, TAG_LEVEL);
fread (*(char **)p, len, 1, f);
}
break;
case F_GSTRING:
len = *(int *)p;
if (!len)
*(char **)p = NULL;
else
{
*(char **)p = gi.TagMalloc (len, TAG_GAME);
/*
SBF: FIXME - 32 extra bytes alloc'd since the saved
string might not be long enough
*/
*(char **)p = gi.TagMalloc (32+len, TAG_LEVEL);
fread (*(char **)p, len, 1, f);
}
break;
@ -370,6 +326,24 @@ void ReadField (FILE *f, field_t *field, byte *base)
*(gitem_t **)p = &itemlist[index];
break;
//relative to code segment
case F_FUNCTION:
index = *(int *)p;
if ( index == 0 )
*(byte **)p = NULL;
else
*(byte **)p = ((byte *)InitGame) + index;
break;
//relative to data segment
case F_MMOVE:
index = *(int *)p;
if (index == 0)
*(byte **)p = NULL;
else
*(byte **)p = (byte *)&mmove_reloc + index;
break;
default:
gi.error ("ReadEdict: unknown field type");
}
@ -441,7 +415,7 @@ A single player death will automatically restore from the
last save position.
============
*/
void WriteGame (char *filename, qboolean autosave)
void WriteGame (const char *filename, qboolean autosave)
{
FILE *f;
int i;
@ -468,16 +442,14 @@ void WriteGame (char *filename, qboolean autosave)
fclose (f);
}
void ReadGame (char *filename)
void ReadGame (const char *filename)
{
FILE *f;
int i;
char str[16];
gi.FreeTags (TAG_GAME);
#ifdef CACHE_SOUND
initSoundList();
#endif
f = fopen (filename, "rb");
if (!f)
gi.error ("Couldn't open %s", filename);
@ -503,7 +475,6 @@ void ReadGame (char *filename)
//==========================================================
/*
==============
WriteEdict
@ -516,15 +487,11 @@ void WriteEdict (FILE *f, edict_t *ent)
field_t *field;
edict_t temp;
if (Q_stricmp(ent->classname, "misc_viper") == 0)
{
temp = *ent;
}
// all of the ints, floats, and vectors stay as they are
temp = *ent;
// change the pointers to lengths or indexes
for (field=savefields ; field->name ; field++)
for (field=fields ; field->name ; field++)
{
WriteField1 (f, field, (byte *)&temp);
}
@ -533,7 +500,7 @@ void WriteEdict (FILE *f, edict_t *ent)
fwrite (&temp, sizeof(temp), 1, f);
// now write any allocated data following the edict
for (field=savefields ; field->name ; field++)
for (field=fields ; field->name ; field++)
{
WriteField2 (f, field, (byte *)ent);
}
@ -570,7 +537,6 @@ void WriteLevelLocals (FILE *f)
}
}
/*
==============
ReadEdict
@ -584,7 +550,7 @@ void ReadEdict (FILE *f, edict_t *ent)
fread (ent, sizeof(*ent), 1, f);
for (field=savefields ; field->name ; field++)
for (field=fields ; field->name ; field++)
{
ReadField (f, field, (byte *)ent);
}
@ -609,17 +575,13 @@ void ReadLevelLocals (FILE *f)
}
}
//==========================================================
/*
=================
WriteLevel
=================
*/
void WriteLevel (char *filename)
void WriteLevel (const char *filename)
{
int i;
edict_t *ent;
@ -654,8 +616,6 @@ void WriteLevel (char *filename)
fwrite (&i, sizeof(i), 1, f);
fclose (f);
// write out zaero between level
}
@ -663,7 +623,7 @@ void WriteLevel (char *filename)
=================
ReadLevel
SpawnEntities will already have been called on the
SpawnEntities will allready have been called on the
level the same way it was when the level was saved.
That is necessary to get the baselines
@ -675,7 +635,7 @@ calling ReadLevel.
No clients are connected yet.
=================
*/
void ReadLevel (char *filename)
void ReadLevel (const char *filename)
{
int entnum;
FILE *f;
@ -690,9 +650,7 @@ void ReadLevel (char *filename)
// free any dynamic memory allocated by loading the level
// base state
gi.FreeTags (TAG_LEVEL);
#ifdef CACHE_SOUND
initSoundList();
#endif
// wipe all the entities
memset (g_edicts, 0, game.maxentities*sizeof(g_edicts[0]));
globals.num_edicts = maxclients->value+1;
@ -707,11 +665,7 @@ void ReadLevel (char *filename)
// check function pointer base address
fread (&base, sizeof(base), 1, f);
if (base != (void *)InitGame)
{
fclose (f);
gi.error ("ReadLevel: function pointers have moved");
}
gi.dprintf("Function offsets %d\n", ((byte *)base) - ((byte *)InitGame));
// load the level locals
ReadLevelLocals (f);