Beispiel #1
0
/* DESCRIPTION: ED_LoadFromFile
// LOCATION: pr_edict.c, but it's conspicuously absent in FTEQW.
// PATH: SV_LoadEntities
//
// To quote the text block that came with it:
// The entities are directly placed in the array, rather than allocated with
// ED_Alloc, because otherwise an error loading the map would have entity
// number references out of order.
//
// Creates a server's entity / program execution context by
// parsing textual entity definitions out of an ent file.
//
// Used for both fresh maps and savegame loads.  A fresh map would also need
// to call ED_CallSpawnFunctions () to let the objects initialize themselves.
*/
void ED_LoadFromFile(const char *data) {

   edict_t *ent;
   int inhibit;

   ent = NULL;
   inhibit = 0;
   gGlobalVariables.time = global_sv.time0c;

   //parse ents
   while(1) {

      // parse the opening brace
      data = COM_Parse(data);

      if(data == NULL) { break; }
      if(global_com_token[0] != '{') {
         Sys_Error ("%s: found %s when expecting {", __FUNCTION__, global_com_token);
      }

      if(ent == NULL) {
         ent = &(global_sv.edicts[0]);
         ReleaseEntityDLLFields(ent);
         InitEntityDLLFields(ent);
      }
      else { ent = ED_Alloc(); }

      data = ED_ParseEdict(data, ent);

      // remove things from different skill levels or deathmatch
      if(cvar_deathmatch.value != 0) {

         if((ent->v.spawnflags & 0x800) != 0) { //SPAWNFLAG_NOT_DEATHMATCH

            ED_Free(ent);
            inhibit++;
            continue;
         }
      }
      // immediately call spawn function
      if(ent->v.classname == 0) {

         Con_Printf("%s: Ent with no classname.\n", __FUNCTION__);
         ED_Free(ent);
         continue;
      }

      if(gEntityInterface.pfnSpawn(ent) < 0 || ent->v.flags & FL_KILLME) {

         ED_Free(ent);
      }
   }

   Con_Printf("%i entities inhibited\n", inhibit);
}
void Server_MakeStatic(ServerEntity_t *ent)
{
	int	i,bits=0;

	if(ent->alpha == ENTALPHA_ZERO)
	{
		ED_Free(ent);
		return;
	}

	if(SV_ModelIndex(ent->v.model) & 0xFF00)
		bits |= B_LARGEMODEL;
	if((int)(ent->v.frame) & 0xFF00)
		bits |= B_LARGEFRAME;
	if(ent->alpha != ENTALPHA_DEFAULT)
		bits |= B_ALPHA;

	if(bits)
	{
		MSG_WriteByte(&sv.signon, SVC_SPAWNSTATIC2);
		MSG_WriteByte(&sv.signon, bits);
	}
	else
		MSG_WriteByte(&sv.signon, svc_spawnstatic);

	if(bits & B_LARGEMODEL)
		MSG_WriteShort(&sv.signon, SV_ModelIndex(ent->v.model));
	else
		MSG_WriteByte(&sv.signon, SV_ModelIndex(ent->v.model));

	if(bits & B_LARGEFRAME)
		MSG_WriteShort(&sv.signon,ent->v.frame);
	else
		MSG_WriteByte(&sv.signon,ent->v.frame);

	MSG_WriteByte(&sv.signon,ent->Model.fScale);
	MSG_WriteByte(&sv.signon,ent->v.colormap);
	MSG_WriteByte(&sv.signon,ent->Model.iSkin);
	for (i=0 ; i<3 ; i++)
	{
		MSG_WriteCoord(&sv.signon, ent->v.origin[i]);
		MSG_WriteAngle(&sv.signon, ent->v.angles[i]);
	}

	if (bits & B_ALPHA)
		MSG_WriteByte (&sv.signon, ent->alpha);

	ED_Free (ent);
}
Beispiel #3
0
/**
 * @brief free the mapbrush_t::nearBrushes, compositeSides and entitiesdef.h stuff.
 */
void Check_Free (void)
{
	int i;

	ED_Free();

	for (i = 0; i < nummapbrushes; i++) {
		mapbrush_t *iBrush = &mapbrushes[i];
		if (iBrush->numNear) {
			assert(iBrush->nearBrushes);
			Mem_Free(iBrush->nearBrushes);
			iBrush->numNear = 0;
			iBrush->nearBrushes = NULL;
		}
	}

	for (i = 0; i < numCompositeSides; i++) {
		compositeSide_t *cs = &compositeSides[i];
		if (cs->numMembers) {
			assert(cs->memberSides);
			Mem_Free(cs->memberSides);
			cs->numMembers = 0;
			cs->memberSides = NULL;
		}
	}
}
/*	The entities are directly placed in the array, rather than allocated with
	ED_Alloc, because otherwise an error loading the map would have entity
	number references out of order.

	Creates a server's entity / program execution context by
	parsing textual entity definitions out of an ent file.

	Used for both fresh maps and savegame loads.  A fresh map would also need
	to call ED_CallSpawnFunctions () to let the objects initialize themselves.
*/
void ED_LoadFromFile(char *data)
{
	ServerEntity_t	*eEntity = NULL;

	for(;;)
	{
		// parse the opening brace
		data = COM_Parse(data);
		if(!data)
			break;

		if(com_token[0] != '{')
			Sys_Error ("ED_LoadFromFile: found %s when expecting {",com_token);

		if(!eEntity)
			eEntity = EDICT_NUM(0);
		else
			eEntity = ED_Alloc();

		data = ED_ParseEdict(data,eEntity);

		// Immediately call spawn function
		if(!Game->Server_SpawnEntity(eEntity))
		{
			if(developer.value)
				Edict_Print(eEntity);

			ED_Free(eEntity);
			continue;
		}
	}
}
Beispiel #5
0
void EntityClassScannerUFO::scanFile (EntityClassCollector& collector)
{
	const std::string& filename = getFilename();

	AutoPtr<ArchiveTextFile> file(GlobalFileSystem().openTextFile(filename));
	if (!file) {
		std::string buffer = "Could not load " + filename;
		gtkutil::errorDialog(buffer);
		return;
	}

	const std::size_t size = file->size();
	char* entities = (char*) malloc(size + 1);
	TextInputStream &stream = file->getInputStream();
	const std::size_t realsize = stream.read(entities, size);
	entities[realsize] = '\0';
	if (ED_Parse(entities) == ED_ERROR) {
		std::string buffer = "Parsing of entities definition file failed, returned error was " + std::string(
				ED_GetLastError());
		gtkutil::errorDialog(buffer);
	} else {
		for (int i = 0; i < numEntityDefs; i++) {
			EntityClass *e = initFromDefinition(&entityDefs[i]);
			if (e)
				collector.insert(e);
		}
	}
	free(entities);
	ED_Free();
}
Beispiel #6
0
/*
================
ED_LoadFromFile
 
The entities are directly placed in the array, rather than allocated with
ED_Alloc, because otherwise an error loading the map would have entity
number references out of order.
 
Creates a server's entity / program execution context by
parsing textual entity definitions out of an ent file.
 
Used for both fresh maps and savegame loads.  A fresh map would also need
to call ED_CallSpawnFunctions () to let the objects initialize themselves.
================
*/
void ED_LoadFromFile (char *data)
{
	extern cvar_t cl_curlybraces;
	edict_t		*ent;
	int			inhibit;
	dfunction_t	*func;
	float curlybraces_oldvalue = cl_curlybraces.value;

	if (curlybraces_oldvalue) {
		Cvar_SetValue(&cl_curlybraces, 0);
	}
	ent = NULL;
	inhibit = 0;
	pr_global_struct->time = sv.time;

	// parse ents
	while (1)
	{
		// parse the opening brace
		data = COM_Parse (data);
		if (!data)
			break;
		if (com_token[0] != '{')
			SV_Error ("ED_LoadFromFile: found %s when expecting {",com_token);

		if (!ent)
			ent = EDICT_NUM(0);
		else
			ent = ED_Alloc ();
		data = ED_ParseEdict (data, ent);

		// remove things from different skill levels or deathmatch
		if ((int)deathmatch.value)
		{
			if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
			{
				ED_Free (ent);
				inhibit++;
				continue;
			}
		}
		else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY))
		         || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM))
		         || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD)) )
		{
			ED_Free (ent);
			inhibit++;
			continue;
		}

		//
		// immediately call spawn function
		//
		if (!ent->v.classname)
		{
			Con_Printf ("No classname for:\n");
			ED_Print (ent);
			ED_Free (ent);
			continue;
		}

		// look for the spawn function
		func = ED_FindFunction ( PR_GetString(ent->v.classname) );

		if (!func)
		{
			Con_Printf ("No spawn function for:\n");
			ED_Print (ent);
			ED_Free (ent);
			continue;
		}

		pr_global_struct->self = EDICT_TO_PROG(ent);
		PR_ExecuteProgram (func - pr_functions);
		SV_FlushSignon();
	}

	Con_DPrintf ("%i entities inhibited\n", inhibit);
	if (curlybraces_oldvalue) {
		Cvar_SetValue(&cl_curlybraces, curlybraces_oldvalue);
	}
}
/*
===============
Host_Loadgame_f
===============
*/
void Host_Loadgame_f (void)
{
    char	name[MAX_OSPATH];
    FILE	*f;
    char	mapname[MAX_QPATH];
    float	time, tfloat;
    char	str[32768], *start;
    int	i, r, line; // Current line # in savegame file
    edict_t	*ent;
    int	entnum, numedicts_save;
    int	version;
    float	spawn_parms[NUM_SPAWN_PARMS];
    qboolean Quote;

    if (cmd_source != src_command)
        return;

    if (Cmd_Argc() != 2)
    {
        Con_Printf ("load <savename> : load a game\n");
        return;
    }

    cls.demonum = -1;		// stop demo loop in case this fails

    sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
    COM_DefaultExtension (name, ".sav");

// we can't call SCR_BeginLoadingPlaque, because too much stack space has
// been used.  The menu calls it before stuffing loadgame command
//	SCR_BeginLoadingPlaque ();

    Con_SafePrintf ("Loading game from %s...\n", name);
    f = fopen (name, "rb"); // Use binary mode to avoid EOF issues in savegame files
    if (!f)
    {
        Con_Printf ("ERROR: couldn't open.\n");
        return;
    }

    fscanf (f, "%i\n", &version);
    if (version != SAVEGAME_VERSION)
    {
        fclose (f);
        Con_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION);
        return;
    }

    // Kludge to read saved games with newlines in title
    do
        fscanf (f, "%s\n", str);
    while (!feof(f) && !strstr(str, "kills:"));

    for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
        fscanf (f, "%f\n", &spawn_parms[i]);
// this silliness is so we can load 1.06 save files, which have float skill values
    fscanf (f, "%f\n", &tfloat);
    current_skill = (int)(tfloat + 0.1);
    Cvar_SetValue ("skill", (float)current_skill);

    fscanf (f, "%s\n",mapname);
    fscanf (f, "%f\n",&time);

    CL_Disconnect_f ();

#ifdef QUAKE2
    SV_SpawnServer (mapname, NULL);
#else
    SV_SpawnServer (mapname);
#endif
    if (!sv.active)
    {
        Con_Printf ("Couldn't load map\n");
        return;
    }
    sv.paused = true;		// pause until all clients connect
    sv.loadgame = true;

// load the light styles

    for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
    {
        fscanf (f, "%s\n", str);
        sv.lightstyles[i] = Hunk_Alloc (strlen(str)+1);
        strcpy (sv.lightstyles[i], str);
    }

// load the edicts out of the savegame file
    entnum = -1;		// -1 is the globals

    // Hack to avoid validation errors while parsing savegame file
    numedicts_save = sv.num_edicts;
    sv.num_edicts = MAX_EDICTS;

    line = 86; // 85 lines before globals in savegame
    while (!feof(f))
    {
        for (i=0, Quote = false ; i<sizeof(str)-1 ; i++)
        {
            r = fgetc (f);
            if (r == EOF || !r)
                break;

            if (r == '\n')
                ++line;

            str[i] = r;

            // Handle multiline quoted strings containing '}'
            if (!Quote)
            {
                if (r == '\"')
                    Quote = true;
                else if (r == '}')
                {
                    i++;
                    break;
                }
            }
            else if (Quote)
            {
                if (r == '\"')
                    Quote = false;
            }
        }
        if (i == sizeof(str)-1)
            Sys_Error ("Loadgame buffer overflow (%d, max = %d) on line %d", i + 1, sizeof(str) - 1, line);
        if (Quote)
            Sys_Error ("Host_Loadgame_f: %s in quoted string on line %d", r == EOF ? "EOF" : "EOS", line);
        str[i] = 0;
        start = str;
        start = COM_Parse(str);
        if (!com_token[0])
            break;		// end of file
        if (strcmp(com_token,"{"))
            Sys_Error ("First token (%s) isn't a brace on line %d", com_token, line);

        if (entnum == -1)
        {   // parse the global vars
            ED_ParseGlobals (start, line);
        }
        else
        {   // parse an edict

            ent = EDICT_NUM("Host_Loadgame_f1", entnum);

            if (!pr_free[entnum])
                ED_Free (ent); // Unlink from world

            memset (&ent->v, 0, progs->entityfields * 4);
            pr_free[entnum] = false;
            ED_ParseEdict (start, ent, line);

            // link it into the bsp tree
            if (!pr_free[entnum])
            {
                int	mindx = ent->v.modelindex;
                model_t *model = sv.models[mindx];
                char	*mname = pr_String ("Host_Loadgame_f1", ent->v.model);
                char	*cname = pr_String ("Host_Loadgame_f2", ent->v.classname);

                // Check for missing/invalid models (except e.g. player/eyes RoS switch)
                if (mindx != 0 && (model == NULL || *mname != 0 && strcmp(model->name, mname) && strcmp(cname, "player")))
                {
                    Con_Printf ("\x02Host_Loadgame_f: ");

                    if (model == NULL)
                        Con_Printf ("missing model");
                    else
                        Con_Printf ("invalid model (%s)", model->name);

                    Con_Printf (" for edict %d (%s)\n", entnum, ED_DbgEdict(&ent->v));
                }

                SV_LinkEdict (ent, false);
            }
        }

        entnum++;
    }

    sv.num_edicts = numedicts_save;

    // Free edicts not present in the savegame, might
    // otherwise cause odd SV_TouchLinks errors
    for (i = entnum; i < sv.num_edicts; ++i)
    {
        if (!pr_free[i])
        {
            ent = EDICT_NUM("Host_Loadgame_f2", i);

            // Don't warn if edict_reuse is disabled
            if (ent->area.prev && edict_reuse.value)
            {
                Con_Printf ("\002Host_Loadgame_f: ");
                Con_Printf ("invalid touched edict (%d, max = %d)\n", i, entnum);
            }

            ED_Free (ent); // Unlink from world
        }
    }

    sv.num_edicts = entnum; // Set new edict amount from savegame

    // Count active edicts
    for (i = sv.active_edicts = 0; i < sv.num_edicts; ++i)
    {
        if (!pr_free[i])
            ++sv.active_edicts;
    }

    ED_ChkEdict (true, false);

    sv.time = time;

    fclose (f);

    for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
        svs.clients->spawn_parms[i] = spawn_parms[i];

    // Chack for different saved game mode
    if (deathmatch.value != pr_global_struct->deathmatch ||
            coop.value != pr_global_struct->coop ||
            teamplay.value != pr_global_struct->teamplay)
    {
        Con_Printf ("\002Host_Loadgame_f: ");
        Con_Printf ("saved game mode different (dm=%g/%g, coop=%g/%g, team=%g/%g)\n",
                    deathmatch.value, pr_global_struct->deathmatch, coop.value, pr_global_struct->coop, teamplay.value, pr_global_struct->teamplay);
    }

    if (cls.state != ca_dedicated)
    {
        CL_EstablishConnection ("local");
        Host_Reconnect_f ();
    }
}