Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - QwazyWabbit

Pages: 1 [2]
16
0x1337c0de / Entity List Management in Q2 Mods
« on: March 20, 2012, 10:20:04 PM »
Several extensive attempts were made to crash the Loxophilia server via the entity list crash pathway. These attempts did not succeed. The crash is produced when the active entity list is filled and a subseqent call to G_Spawn in the game mod can't find space in the entity list to instantiate a new entity. The function fails with a call to gi.error ("ED_Alloc: no free edicts"); which halts the game server resulting in a temporary denial of service.

There are two factors influencing this relative immunity to DoS.

1. Entity list size: old game default is 1024 entities. Loxo uses 2048 by default.
2. List management code in LOX was modified long ago and is now an historic artifact in LOX.

Three functions were modified in g_utils.c to speed up entity initialization and freeing.
The functions are listed below. These functions are common to all Quake2 mods.
NOTE: The entity member "classnum" is used in LOX to speed up class comparisons instead of using string matching based on "classname". The CN_* values are simply #defines or enumated constants for all entity classes in the relevant mod. You may freely discard the code dealing with this data member.

Code: [Select]
void G_InitEdict (edict_t *e)
{
e->inuse = QTRUE;
e->classname = "noclass";
e->classnum = CN_NOCLASS;
e->gravity = 1.0;
e->s.number = e - g_edicts;

// Clear what the free-edict list may have set.
e->chain = NULL;

// This is another headache.
e->think = NULL;
e->nextthink = 0;
}

// The free-edict list.  Meant to vastly speed up G_Spawn().
edict_t *g_freeEdictsH = NULL;
edict_t *g_freeEdictsT = NULL;

/*
=================
G_Spawn

Either finds a free edict, or allocates a new one.
Try to avoid reusing an entity that was recently freed, because it
can cause the client to think the entity morphed into something else
instead of being removed and recreated, which can cause interpolated
angles and bad trails.
=================
*/

edict_t *G_Spawn (void)
{
int i;
edict_t *e;
// char string[64];

// If the free-edict queue can help, let it.
while (g_freeEdictsH != NULL)
{
// Remove the first item.
e = g_freeEdictsH;
g_freeEdictsH = g_freeEdictsH->chain;
if (g_freeEdictsH == NULL)
g_freeEdictsT = NULL;

// If it's in use, get another one.
if (e->inuse)
continue;

// If it's safe to use it, do so.
if (e->freetime < 2 || level.time - e->freetime > 0.5)
{
G_InitEdict (e);
return e;
}

// If we can't use it, we won't be able to use any of these -- anything
// after it in the queue was freed even later.
else
break;
}

// The old way to find a free edict.
e = &g_edicts[(int)maxclients->value+1];
for ( i = (int) maxclients->value + 1 ; i < globals.num_edicts ; i++, e++)
{
// the first couple seconds of server time can involve a lot of
// freeing and allocating, so relax the replacement policy
if (!e->inuse && ( e->freetime < 2 || level.time - e->freetime > 0.5 ) )
{
G_InitEdict (e);
return e;
}
}

if (i == game.maxentities)
gi.error ("ED_Alloc: no free edicts");

globals.num_edicts++;
G_InitEdict (e);
// sprintf(string, "num_edicts is %i\n", globals.num_edicts);
// OutputDebugString(string);
return e;
}

/*
=================
G_FreeEdict

Marks the edict as free
=================
*/
void G_FreeEdict (edict_t *ed)
{
gi.unlinkentity (ed); // unlink from world

if ((ed - g_edicts) <= (maxclients->value + BODY_QUEUE_SIZE))
{
// gi.dprintf("tried to free special edict\n");
return;
}

memset (ed, 0, sizeof(*ed));
ed->classname = "freed";
ed->classnum = CN_NOCLASS;
ed->freetime = level.time;
ed->inuse = QFALSE;

// Put this edict into the free-edict queue.
if (g_freeEdictsH == NULL)
g_freeEdictsH = ed;
else
g_freeEdictsT->chain = ed;
g_freeEdictsT = ed;
ed->chain = NULL;
}

In server configuration files you can set maxentities 2048 or you can modify g_save.c in the game source:

Code: [Select]
maxentities = gi.cvar ("maxentities", "2048", CVAR_LATCH);

17
Release b8012 is confirmed not to load SP mode in a system with the full commercial version of Q2 installed. The program insists that single player data is missing. This appears to be a malfunction in the StartGame function in the new version. It checks to see if base1 will load. There is a bug introduced in this version as a result of StartGame calling the CM_MapWillLoad function which looks for two files, base1.bsp and base1.override. This function gets called twice, first by StartGame looking in the Quake2 root folder for both of these files and the second time by SV_GameMap_f looking for them in the maps folder. BOTH tests must pass, indicating that one or the other file exists or the game will fail to start. Since base.bsp is properly stored in the maps folder of pak0.pak it never exists in the quake2 root. The result is that the first call, by GameStart doesn't find base1.bsp or base1.override in the root and announces the failure, preventing SP mode.

You can work around this bug by putting an empty base1.override file into your Quake2\baseq2 folder.

Once that file exists and you restart r1q2, the empty override file will be found in the root, passing the first test and base1.bsp will be found in the maps folder of pak0.pak on the second pass and you will be able to play single player.


18
/dev/random / Spray-on Clothing
« on: August 15, 2011, 08:33:38 PM »

http://www.wimp.com/sprayclothing/

The good doctor did manage to find a reasonably nice looking subject to demonstrate the product.

Anna-Nichole types might have an over-spray problem.
The more hirsute among us may have a removal problem.

19
Tech Junkie Lounge / Lion
« on: July 20, 2011, 05:39:37 PM »
Just installed OS X 10.7 Lion, thirty bucks via App Store. A redundancy, it should be called OS X.7 :) Watched my CPU get to 157 degrees F while Spotlight reindexed the hard drive. You definitely want to do this upgrade with your laptop on line power. Currently downloading the Xcode 4.1 update because the Xcode they shipped last month for 10.6.8 Snow Leopard won't run on 10.7. The problem is, the App Store malfunctions if you try to update Xcode through it or via the update tool. You have to go through the Safari browser to get it to invoke the app store and download the update.

Parallels Desktop 6 also needed updating but Parallels notified me via email the moment I opened the Mail application. Incidentally, OS X Mail now looks a whole lot like Microsoft Outlook 2003, with folder list, topic list and preview panes, complete with drab tool bar. Next, they will probably be putting those lame ribbons on their apps.

Best new feature of Lion so far: Draggable borders. You can finally drag a window by its border in OS X! User interface heaven. No more stupid corner drag.

20
0x1337c0de / Need Help Coding Chase in-eyes View
« on: March 13, 2011, 09:52:21 PM »
OK, it looks like no-one has ever solved the problem of player clipping in the in-eyes view mode. The original Q2 code had chasecam from behind the chased player. Setting in-eyes would seem to be just a matter of copying the target player's look-angle into the chasing view but this renders the chaser's POV inside the head of the target player with all the nice artifacts dancing in the view. I've got semi-working chasecam code but I get lost in the vector functions and can't tell when to use gi.trace, VectorMA, VectorNormalize, etc.

Maybe we can put our collective heads together and figure this one out.

Here's what I have so far:

void ChaseCamUpdate(edict_t *ent)
{
   vec3_t o, ownerv, goal;
   edict_t *targ;
   vec3_t forward;
   trace_t trace;
   vec3_t angles;

   assert(ent != NULL);
   targ = ent->client->chase_target;

   VectorCopy(targ->s.origin, ownerv);

   if (ent->client->chase_mode == CHASE_EYES)
   {
      VectorCopy (targ->s.origin, goal);
      goal[2] += targ->viewheight + 6;
   }
   
   if (ent->client->chase_mode == CHASE_THIRDPERSON)
   {
      ownerv[2] += targ->viewheight;

      VectorCopy(targ->client->v_angle, angles);
      if (angles[PITCH] > ent->lclient->cam_maxpitch)
         angles[PITCH] = ent->lclient->cam_maxpitch;
      AngleVectors (angles, forward, NULL, NULL);
      VectorNormalize(forward);
      VectorMA(ownerv, -ent->lclient->cam_distance, forward, o);

      if (o[2] < targ->s.origin[2] + ent->lclient->cam_height)
         o[2] = targ->s.origin[2] + ent->lclient->cam_height;

      // jump animation lifts
      if (!targ->groundentity)
         o[2] += ent->lclient->cam_jump;

      trace = gi.trace(ownerv, vec3_origin, vec3_origin, o, targ, MASK_SOLID);
      VectorCopy(trace.endpos, goal);
      VectorMA(goal, 2, forward, goal);

      // pad for floors and ceilings
      VectorCopy(goal, o);
      o[2] += 6;
      trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID);
      if (trace.fraction < 1)
      {
         VectorCopy(trace.endpos, goal);
         goal[2] -= 6;
      }

      VectorCopy(goal, o);
      o[2] -= 6;
      trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID);
      if (trace.fraction < 1)
      {
         VectorCopy(trace.endpos, goal);
         goal[2] += 6;
      }
   }

   //common to all chase modes
 VectorCopy(goal, ent->s.origin);

   if(!ent->lclient->cam_freelook)
   {
      int i;
      ent->client->ps.pmove.pm_type = PM_FREEZE;
      for(i = 0; i < 3; i++)
         ent->client->ps.pmove.delta_angles = ANGLE2SHORT(targ->client->v_angle - ent->client->resp.cmd_angles);

      VectorCopy(targ->client->v_angle, ent->client->ps.viewangles);
      VectorCopy(targ->client->v_angle, ent->client->v_angle);
   }
   else
      ent->client->ps.pmove.pm_type = PM_NORMAL;

   ent->viewheight = 0;
   ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION;
   gi.linkentity(ent);
}

I've highlighted the relevant block in yellow, this produces a in-head view, slightly elevated by 6 units, just to make it a little less annoying. I think the solution would be to push the camera POV forward of the targ->s.origin but I don't know how to do that at the moment.

Another solution might be to ID the chased player and then not render him in the chasing client.

Ideas anyone?

Pages: 1 [2]