Edict t: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
(destubbed)
Line 1: Line 1:
{{wrongtitle|title=edict_t}}
{{toc-right}} {{DISPLAYTITLE:edict_t}}
{{stub}}
'''Purpose:''' The engine's internal representation of an entity, including some basic collision and position info and a pointer to the class wrapped on top of the structure.


==Basic discussion==
'''<code>edict_t</code>''' ("entity dictionary") is an [[interface]] [[struct]] used to refer to [[entity|entities]] across DLL boundaries, including the client/server divide. In each location it provides a pointer to the local representation of its assigned entity.
An edict, an abbreviation of "entity dictionary" attributed to John Carmack, is a way to store basic properties about an entity (e.g., location, rotation).


Do not attempt to change the class definition of edict_t when modding.  As a member of the HL Coders list put it, "messing with them will cause the magic smoke to evaporate from your compiler."  The Source engine is compiled with a specific edict structure.  Mod code cannot add or remove properties because it would cause size and behaviour mismatches between parts of the engine you compile when modding and parts of the engine that were pre-compiled by Valve.
{{note|An edict is not reliable between frames, as it can be freed from one entity and and reallocated to another at any time. Use <code>[[CHandle]]</code> for long-term storage.}}


http://www.mail-archive.com/hlcoders@list.valvesoftware.com/msg01215.html suggests that it's not a good idea to rely upon a destructor being called for this class either.  The naming of this class ("edict_t", as opposed to "edict") suggests this also.
{{warning|Never modify <code>edict_t</code> or <code>CBaseEdict</code>. If the memory footprint of either changes, engine DLLs will start accessing invalid addresses.}}


== How do I obtain an edict_t? ==
{{todo|Is the dictionary synced between client and server even for non-networked ents?}}
edict_t * const entity_dictionary = engine->PEntityOfEntIndex(player_index /* 1-32 */);


== How do I obtain a CBaseEntity from an edict_t? ==
== Edict limit ==
CBaseEntity * const base_entity = pEdict->GetUnknown()->GetBaseEntity();


==Related content==
Source can have up to 2048 edicts allocated at any one time, and going over that will cause the engine to exit with an error message. This is commonly referred to as the [[entity limit]], which is inaccurate; there is an entity limit, but it is 4096 and hitting it will cause only console errors.
[[CBaseEdict]]
 
[[Category:Structures]]
== Avoiding ==
 
Edicts are automatically assigned by <code>[[CBaseEntity]]::PostConstructor()</code>. To prevent this, [[Constructor|construct]] your entity like so:
 
<source lang=cpp>CMyEntity() : CBaseEntity(true) { /*...*/ }</source>
 
{{tip|<code>CServerOnlyEntity</code> already does this. <code>[[CLogicalEntity]]</code> inherits, and as such none of Valve's [[Special:PrefixIndex/logic_|logic entities]] or [[:Category:Constraints|VPhysics constraints]] have edicts.}}
 
Edict-less entities still count toward the overall entity limit, which is 4096.
 
== Getting ==
 
; <code>edict_t* CBaseEntity::edict()</code>
: Simple accessor. Returns null if there is no edict.
; <code>edict_t* PEntityOfEntIndex([[int]] iEntIndex)</code>
: Given an [[entity index]], returns a pointer to the corresponding edict.
; <code>int GetEntityCount()</code>
: Returns the current number of assigned edicts (''not'' entities).
 
== Setting ==
 
; <code>void [[CBaseEntity]]::NetworkProp()->AttachEdict(edict_t* pRequiredEdict);</code>
: Assigns an edict via the entity's <code>[[CServerNetworkProperty]]</code> object. Pass NULL unless a specific edict is required.
; <code>void CBaseEntity::NetworkProp()->DetachEdict()</code>
: Detaches the entity's assigned edict. It will go back into the edict pool for re-use.
 
== Notable members ==
 
; <code>[[CBaseEntity]]* GetUnknown()->GetBaseEntity()</code>
: Pointer to the entity's local representation.
; <code>char* GetClassName()</code>
: The [[classname]] of the assigned entity.
; <code>[[bool]] IsFree()</code>
: Whether there is currently an entity assigned to this edict.
; <code>[[float]] freetime</code>
: The server timestamp at which the edict was last freed. Can be used to avoid reallocating the edict immediately.
; <code>[[IServerEntity]]* GetIServerEntity()</code>
; <code>[[IServerNetworkable]]* GetNetworkable()</code>
; <code>[[ICollideable]]* GetCollideable()</code>
: Accessors to various interfaces.
 
== See also ==
 
* [[Entity index]]
* [[Entity limit]]
* <code>[[CHandle]]</code>
* [http://www.mail-archive.com/hlcoders@list.valvesoftware.com/msg01215.html Discussion on GoldSrc edicts]
* [http://www.quake2.com/dll/doc/ent_atr.html Quake 2's edict_t.] Storing so many disparate variables in an engine interface was a bad idea!
 
[[Category:Interfaces]]

Revision as of 12:55, 15 September 2009

edict_t ("entity dictionary") is an interface struct used to refer to entities across DLL boundaries, including the client/server divide. In each location it provides a pointer to the local representation of its assigned entity.

Note.pngNote:An edict is not reliable between frames, as it can be freed from one entity and and reallocated to another at any time. Use CHandle for long-term storage.
Warning.pngWarning:Never modify edict_t or CBaseEdict. If the memory footprint of either changes, engine DLLs will start accessing invalid addresses.
Todo: Is the dictionary synced between client and server even for non-networked ents?

Edict limit

Source can have up to 2048 edicts allocated at any one time, and going over that will cause the engine to exit with an error message. This is commonly referred to as the entity limit, which is inaccurate; there is an entity limit, but it is 4096 and hitting it will cause only console errors.

Avoiding

Edicts are automatically assigned by CBaseEntity::PostConstructor(). To prevent this, construct your entity like so:

CMyEntity() : CBaseEntity(true) { /*...*/ }
Tip.pngTip:CServerOnlyEntity already does this. CLogicalEntity inherits, and as such none of Valve's logic entities or VPhysics constraints have edicts.

Edict-less entities still count toward the overall entity limit, which is 4096.

Getting

edict_t* CBaseEntity::edict()
Simple accessor. Returns null if there is no edict.
edict_t* PEntityOfEntIndex(int iEntIndex)
Given an entity index, returns a pointer to the corresponding edict.
int GetEntityCount()
Returns the current number of assigned edicts (not entities).

Setting

void CBaseEntity::NetworkProp()->AttachEdict(edict_t* pRequiredEdict);
Assigns an edict via the entity's CServerNetworkProperty object. Pass NULL unless a specific edict is required.
void CBaseEntity::NetworkProp()->DetachEdict()
Detaches the entity's assigned edict. It will go back into the edict pool for re-use.

Notable members

CBaseEntity* GetUnknown()->GetBaseEntity()
Pointer to the entity's local representation.
char* GetClassName()
The classname of the assigned entity.
bool IsFree()
Whether there is currently an entity assigned to this edict.
float freetime
The server timestamp at which the edict was last freed. Can be used to avoid reallocating the edict immediately.
IServerEntity* GetIServerEntity()
IServerNetworkable* GetNetworkable()
ICollideable* GetCollideable()
Accessors to various interfaces.

See also