Forum

Loading External .Ent Files

Post tutorials on how to do certain tasks within game or engine code here.

Moderator: InsideQC Admins

Loading External .Ent Files

Postby Baker » Wed Jun 01, 2011 7:43 pm

External entity files are files like start.ent that you throw in quake\id1\maps folder that are just a text file of the entities and these get used instead of the entities in the map (like start.bsp).

Particularly useful for Frikbot waypoints, CTF or altering the entities in a single player map for whatever reason.

Every engine should support this, there is a bit of naming differences among the engines as to the cvar name to turn the feature on or off (it is always defaulted on by every engine) ...

DarkPlaces uses: sv_entpatch
FTEQW, ezQuake use: sv_loadentfiles
Oldy QIPQuake uses: external_ents

Anyway ...

1. Open sv_main.c and go to the function SV_SpawnServer.
2. Locate this code:

Code: Select all
   ED_LoadFromFile (sv.worldmodel->entities);


3. Replace with ...

Code: Select all
   {
#define SUPPORTS_EXTERNAL_ENTS 1
#if SUPPORTS_EXTERNAL_ENTS
      char *entitystring = NULL;
      if ((entitystring = (char *)COM_LoadHunkFile (va ("maps/%s.ent", sv.name))))
      {
         Con_DPrintf ("Using entfile maps/%s.ent\n", sv.name);
         // To do: Maybe set some cvar to the .ent file name
         ED_LoadFromFile (entitystring);
         // Ideally we should free the entitystring here, except we put it on the hunk
         // which gets cleared on a new map.  But we are wasting some memory here
         // .ent files can occasionally be rather big (1 MB or 2 MB) but usually aren't.
      }
      else // Either we aren't using external ent files or we didn't have one, load the old fashioned way
#endif
         ED_LoadFromFile (sv.worldmodel->entities); // Baker: This isn't loading from "file" but from memory
   }


The End.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
User avatar
Baker
 
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Postby mh » Wed Jun 01, 2011 10:18 pm

I always wanted to add this feature but I'm paranoid about how to properly handle brush models.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Postby metlslime » Wed Jun 01, 2011 10:46 pm

should work the same way -- the entity lump in a bsp is just text, and the references to the brushmodels are just strings like "*12" so that same string could be stored in an external ent file.
metlslime
 
Posts: 316
Joined: Tue Feb 05, 2008 11:03 pm

Postby mh » Wed Jun 01, 2011 10:53 pm

It's not so much that (which does work) - it's the fact that someone could try to add extra brush model entities to the replacement lump but which don't exist in the original BSP. Easy to test though, I guess.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Postby Spike » Thu Jun 02, 2011 12:01 am

the respective setmodel call can catch it and 'safely' crash if that makes you any happier. if it doesn't match then it doesn't match.
the good thing about stuff like quakeworld or auto downloads and stuff is that there's generally only one 'true' version of the bsp, other versions are renamed. alphas are bad, but they don't linger long when you have servers accusing people of cheating when they have them installed. :)
Spike
 
Posts: 2892
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Postby Baker » Thu Jun 02, 2011 2:21 am

mh wrote:It's not so much that (which does work) - it's the fact that someone could try to add extra brush model entities to the replacement lump but which don't exist in the original BSP. Easy to test though, I guess.


They could foobar a bsp -doents (-doentsonly? what it is) and royally mess up .bsp if they wanted to.

Most people doing stuff like this have mapping or modding experience and don't really need that kind of supervision. And those that are going to mess up will mess up and learn anyways.

/One thought on the topic
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
User avatar
Baker
 
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Postby mh » Thu Jun 02, 2011 9:07 am

Baker wrote:They could foobar a bsp -doents (-doentsonly? what it is) and royally mess up .bsp if they wanted to.

That's a fair point and a valid counter-argument.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Postby Baker » Thu Jun 02, 2011 7:41 pm

If you want to be really nice, you can make it so mappers can copy the entities string (whether or not you loaded external entities) to the clipboard.

Many times someone new will want or need to do this for some reason. And then you have to explain how you open a text editor, find the entities, copy them and without external ent support then you have to download a qbsp save the text file as .ent and run qbsp with such and such params.

This isn't user-friendly.

Code: Select all
#ifdef SUPPORTS_CLIPBOARD
/*
================
Con_Copy_f -- Baker -- adapted from Con_Dump
================
*/
void Con_Copy_f (void)
{
   char   outstring[CON_TEXTSIZE]="";
   int      l, x;
   char   *line;
   char   buffer[1024];

   if (Cmd_Argc() > 1) // More than just the command
   {
      if (strcmp(Cmd_Argv(1), "ents")==0)  // If argument "ents" passed and we have an entitystring
      {
         extern char *entitystring;
         if (!sv.active)      { Con_Printf ("copy ents: Not running a server"); return; }
         if (!entitystring)  { Con_Printf ("copy ents: No entities to copy");   return; }  // How would this happen, btw?
         
         Sys_CopyToClipboard (entitystring);

         Con_Printf ("Entities copied to the clipboard (%i bytes)\n", strlen(entitystring));
         return;
      }
      else // Invalid args
      {
         Con_Printf ("Usage: copy [ents]\n");
         return;
      }

   }
.
.
.

}
#endif


The above works because I make some changes in my engine so that entitystring points to sv.worldmodel->entities if external entities weren't loaded.

Code: Select all
   entitystring = NULL; // Baker: Kill the reference
#define SUPPORTS_EXTERNAL_ENTS 1
#if SUPPORTS_EXTERNAL_ENTS
   if (sv_loadentfiles.value && (entitystring = (char *)COM_LoadHunkFile (va ("maps/%s.ent", sv.name))))
   {
      Con_DPrintf ("Using entfile maps/%s.ent\n", sv.name);
      // To do: Maybe set some cvar to the .ent file name
   }
   else // Either we aren't using external ent files or we didn't have one, load the old fashioned way
#endif
      entitystring = sv.worldmodel->entities; // Point it to the standard entities string
   
   ED_LoadFromFile (entitystring); // Baker: This isn't loading from "file" but from memory
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
User avatar
Baker
 
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Postby mh » Thu Jun 02, 2011 7:54 pm

A cool feature would be the ability to specify a .ent file to be loaded from the console and have it load the next time a map loads. Obviously not going to compatible with save games so that will need to be worked over, but I could see it speeding up processes such as monster placement a good bit.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Postby Baker » Thu Jun 02, 2011 8:09 pm

mh wrote:A cool feature would be the ability to specify a .ent file to be loaded from the console and have it load the next time a map loads. Obviously not going to compatible with save games so that will need to be worked over, but I could see it speeding up processes such as monster placement a good bit.


I'm not talking CSQC here, but you could have "client side" entity placement.

Basically, this is an array of "models" and their positions that is entirely client side that gets added to the model drawing list but isn't part of the set of entities.

In CTF it is common to have to take a non-CTF level and go around and look for places to put flags. You'd have to walk around the level and figure out the "right" place a for a flag and type "viewpos" to get the map position you were at.

During maybe Quake Expo 2006 (?) or 2008, some mapper made a tool that was supposed to help with entity placement. Of course, he wasn't able to make a way to actually save the data within QuakeC. I can't remember the name of this (and I bet the tool is super-buried in the Func forums), but the need for these kind of things do exist and people have to use very primitive and silly ways to do them currently.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
User avatar
Baker
 
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Postby Lardarse » Sat Jun 04, 2011 6:07 am

I also remember that tool. QExpo 2008, I believe. Sadly, I do not remember who it was either.

Exporting in .ent/.map format using FRIK_FILE would seem to be the way to go, if anyone ever finds it, finds the source, and feels like working on it.
Roaming status: Testing and documentation
User avatar
Lardarse
 
Posts: 266
Joined: Sat Nov 05, 2005 1:58 pm
Location: Bristol, UK

Postby Baker » Sat Jun 04, 2011 10:30 pm

Lardarse wrote:I also remember that tool. QExpo 2008, I believe. Sadly, I do not remember who it was either.

Exporting in .ent/.map format using FRIK_FILE would seem to be the way to go, if anyone ever finds it, finds the source, and feels like working on it.


http://qexpo.tastyspleen.net/booth.php?id=203
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
User avatar
Baker
 
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Postby szo » Tue Jun 07, 2011 8:56 am

Noticed this one late. Baker: Is the following suits your needs? (Modified Mod_LoadEntities() for quakespasm-0.85.4 or svn version.)
Code: Select all
void Mod_LoadEntities (lump_t *l)
{
   char   entfilename[MAX_QPATH];
   char      *ents;
   int      mark;
   unsigned int   path_id;

   strcpy(entfilename, loadmodel->name);
   COM_StripExtension(entfilename, entfilename);
   strcat(entfilename, ".ent");
   Con_DPrintf("trying to load %s\n", entfilename);
   mark = Hunk_LowMark();
   ents = (char *) COM_LoadHunkFile (entfilename, &path_id);
   if (ents)
   {
      // use ent file only from the same gamedir as the map
      // itself or from a searchpath with higher priority.
      if (path_id < loadmodel->path_id)
      {
         Hunk_FreeToLowMark(mark);
         Con_Printf("ignored %s from a gamedir with lower priority\n", entfilename);
      }
      else
      {
         loadmodel->entities = ents;
         Con_DPrintf("Loaded external entity file %s\n", entfilename);
         return;
      }
   }

   if (!l->filelen)
   {
      loadmodel->entities = NULL;
      return;
   }
   loadmodel->entities = (char *) Hunk_AllocName ( l->filelen, loadname);
   memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
}

I can add this to our svn...
szo
 
Posts: 132
Joined: Mon Dec 06, 2010 4:42 pm

Postby Baker » Tue Jun 07, 2011 1:53 pm

Comments ...

1) I'd make sure there is a cvar to control it (sv_loadentfiles is probably the best name). This is a feature that someone doing testing or working on a mod will occasionally want to turn off and reload the map.

szo wrote: ents = (char *) COM_LoadHunkFile (entfilename, &path_id);
if (ents)
{
// use ent file only from the same gamedir as the map
// itself or from a searchpath with higher priority.


2) Question: If I have gamedir frikbot and frikbot\maps\start.ent is for id1\maps\start.bsp ... is it going to load start.ent like it should? It does, right ... it just wouldn't load id1\maps\start.ent for quoth\map\start.bsp. Neat. (This is the solution to protect against loading wrong .lit files, isn't it).

3) Your code above is going to load entities for health boxes and ammo boxes from .ent files. The server is going to do anything with those, but I wanted you to be aware of that. There really isn't a need for loading external entities for anything except the server worldmodel (sv.name).
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
User avatar
Baker
 
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Postby szo » Tue Jun 07, 2011 3:00 pm

Baker wrote:Comments ...

1) I'd make sure there is a cvar to control it (sv_loadentfiles is probably the best name). This is a feature that someone doing testing or working on a mod will occasionally want to turn off and reload the map.

Sounds reasonable. I'd prefer external_ents from QIP, though, because it is the first implementation (AFAIK)

Baker wrote:
szo wrote: ents = (char *) COM_LoadHunkFile (entfilename, &path_id);
if (ents)
{
// use ent file only from the same gamedir as the map
// itself or from a searchpath with higher priority.


2) Question: If I have gamedir frikbot and frikbot\maps\start.ent is for id1\maps\start.bsp ... is it going to load start.ent like it should? It does, right

Yes. Since frikbot is above id1 in the searchpath priority, it will load frikbot\maps\start.ent

Baker wrote:... it just wouldn't load id1\maps\start.ent for quoth\map\start.bsp. Neat.

Thanks. The idea was loosely from QIP, however this path_id implementation is shorter and much cleaner IMO.

Baker wrote:(This is the solution to protect against loading wrong .lit files, isn't it).

Yes. I use the same mechanism for the lit files, too.

Baker wrote:3) Your code above is going to load entities for health boxes and ammo boxes from .ent files. The server is going to do anything with those, but I wanted you to be aware of that. There really isn't a need for loading external entities for anything except the server worldmodel (sv.name).

Hmm, haven't thought of that one. (apparently QIP hadn't thought of that, either.) However that seems harmless and I don't think anyone would place individual *.ent files for ammo boxes, etc, either.
szo
 
Posts: 132
Joined: Mon Dec 06, 2010 4:42 pm

Next

Return to Programming Tutorials

Who is online

Users browsing this forum: No registered users and 1 guest