r703 - trunk/game

lordhavoc at icculus.org lordhavoc at icculus.org
Fri May 5 12:23:34 EDT 2006


Author: lordhavoc
Date: 2006-05-05 12:23:34 -0400 (Fri, 05 May 2006)
New Revision: 703

Modified:
   trunk/game/g_entity.c
   trunk/game/g_main.h
Log:
thanks to painQuin for a patch to handle freed entity timeouts (to give
other entities a chance to notice that their reference is dead)


Modified: trunk/game/g_entity.c
===================================================================
--- trunk/game/g_entity.c	2006-05-04 23:09:55 UTC (rev 702)
+++ trunk/game/g_entity.c	2006-05-05 16:23:34 UTC (rev 703)
@@ -8,7 +8,9 @@
 G_Entity *G_Entity_New(G_Entity *parent, const G_Entity_Class *eclass, const G_Entity_Position *position)
 {
 	G_Entity *entity;
-	NUint32 childindex = 0;
+	Nbool bestfound = false;
+	Nvec tbest = 0;
+	NUint32 childindex = 0, bestindex = 0;
 	if (!eclass)
 		return NULL;
 	if (!eclass->codeclass->name)
@@ -33,32 +35,56 @@
 	}
 	if (!position)
 		position = &GS.identityposition;
-	// TODO: add a timeout after freeing an entity before it will be reused?  (if so this will need to scan twice if it can't find one with the timeout)
+
 	for (entity = G.entities + G.allocentity;G.allocentity < G_MAX_ENTITIES;G.allocentity++, entity++)
 	{
 		if (!entity->eclass)
 		{
-			G.allocentity++;
-			G.numentities = Max(G.numentities, G.allocentity);
-			memset(entity, 0, sizeof(G_Entity));
-			entity->eclass = eclass;
-			// mark this entity as not being a network related entity
-			// (if it really is, the network code will change this)
-			entity->networkindex = -1;
-			if (parent)
+			if (G.time - entity->freetime >= FREETIMEOUT)
 			{
-				entity->owner = parent;
-				parent->children[childindex] = entity;
+				// this entity has not been used recently, so anything
+				// referencing it has probably cleared its references already,
+				// so it is probably safe to reuse it now
+				bestfound = true;
+				bestindex = G.allocentity++;
+				break;
 			}
-			entity->position = *position;
-			if (entity->eclass->modelname && entity->eclass->modelname[0])
-				G_Entity_SetModel(entity, entity->eclass->modelname);
-			entity->lifetime = entity->eclass->lifetime;
-			return entity;
+			else if (!foundbest || (entity->freetime < tbest))
+			{
+				// found a free slot that hasn't timed out yet, keep track of
+				// which one is oldest incase we can't find one
+				// (this is a dangerous situation but it's even worse to fail)
+				foundbest = true;
+				bestindex = G.allocentity;
+				tbest = entity->freetime;
+			}
 		}
 	}
-	Console_Printf("Ran out of entities (%i)\n", G_MAX_ENTITIES);
-	return NULL;
+	if (!bestfound)
+	{
+		Console_Printf("Ran out of entities (%i)\n", G_MAX_ENTITIES);
+		return NULL;
+	}
+	entity = G.entities + bestindex;
+	// update entity range to include this newly allocated entity
+	// (the entity range is used to avoid processing the entire array each
+	//  frame)
+	G.numentities = Max(G.numentities, bestindex);
+	memset(entity, 0, sizeof(G_Entity));
+	entity->eclass = eclass;
+	// mark this entity as not being a network related entity
+	// (if it really is, the network code will change this)
+	entity->networkindex = -1;
+	if (parent)
+	{
+		entity->owner = parent;
+		parent->children[childindex] = entity;
+	}
+	entity->position = *position;
+	if (entity->eclass->modelname && entity->eclass->modelname[0])
+		G_Entity_SetModel(entity, entity->eclass->modelname);
+	entity->lifetime = entity->eclass->lifetime;
+	return entity;
 }
 
 void G_Entity_Spawn(G_Entity *entity)
@@ -115,6 +141,7 @@
 	memset(entity, 0, sizeof(*entity));
 	// reset allocentity to a level that will find this freshly freed entity
 	G.allocentity = Min(G.allocentity, entitynum);
+	entity->freetime = G.time;
 }
 
 void G_Entity_RemoveChildren(G_Entity *entity)

Modified: trunk/game/g_main.h
===================================================================
--- trunk/game/g_main.h	2006-05-04 23:09:55 UTC (rev 702)
+++ trunk/game/g_main.h	2006-05-05 16:23:34 UTC (rev 703)
@@ -541,9 +541,14 @@
 	Nvec lifetime;
 	// weapons
 	Nvec attackdelay;
+
+	Nvec freetime;
 }
 G_Entity;
 
+// number of seconds before an entity slot will be reused (unless overloaded, in which case the least recently freed entity will be chosen)
+#define FREETIMEOUT 0.2
+
 typedef struct G_Trace
 {
 	G_Entity *moveentity;




More information about the neither-commits mailing list