feature: concept of expanding origin limit for temp entities
Related to big map PR: https://github.com/YaLTeR/BunnymodXT/pull/500
Well, @khanghugo asked about expanding the origin limit for temp entities, and in general I have a concept of how this can be implemented:
- Hook
PF_MessageBegin_I,PF_WriteCoord_I,PF_MessageEnd_I,CL_ParseTEntandMSG_ReadCoordengine functions - PF_MessageBegin_I: start tracking the
svc_tempentitymessage calls
#define SVC_TEMPENTITY 23 // Move it to some header instead
if (msg_type == SVC_TEMPENTITY)
{
if (is_big_map)
msg_svc_tempentity_intercepted = true;
}
ORIG_PF_MessageBegin_I(msg_dest, msg_type, pOrigin, ed);
- PF_WriteCoord_I: if we have tracked the desired message, redirect it to PF_WriteLong_I
if (ServerDLL::GetInstance().pEngfuncs)
{
if (msg_svc_tempentity_intercepted)
{
ServerDLL::GetInstance().pEngfuncs->pfnWriteLong(static_cast<int>(flValue));
return;
}
}
ORIG_PF_WriteCoord_I(flValue);
- PF_MessageEnd_I: stop tracking the message
void ResetTrackedMessages()
{
msg_svc_tempentity_intercepted = false;
}
HOOK_DEF_0(HwDLL, void, __cdecl, PF_MessageEnd_I)
{
ResetTrackedMessages();
ORIG_PF_MessageEnd_I();
}
- CL_ParseTEnt: track state if inside of function
HOOK_DEF_0(HwDLL, void, __cdecl, CL_ParseTEnt)
{
inside_CL_ParseTEnt = true;
ORIG_CL_ParseTEnt();
inside_CL_ParseTEnt = false;
}
- MSG_ReadCoord: if we have tracked the inside function state, redirect it to MSG_ReadLong
if (is_big_map)
{
if (inside_CL_ParseTEnt && ORIG_MSG_ReadLong)
return static_cast<float>(ORIG_MSG_ReadLong());
}
The engine also has a function PF_StaticDecal which sent coordinates via MSG_WriteCoord, so it may also need to be replaced there with MSG_WriteLong
Perhaps there are some other temp entities in the engine that are sent via MSG_WriteCoord, I don’t seem to have found them, but I also didn’t look deeply enough
Personally I only do stuffs for movement maps so I won't have much use of this. However, when it comes to servers running big maps, this might be very needed. This idea will work nicely in other projects like ReHLDS. I can try implementing this and see. I can use BXT to test my implementation before getting it into something different.
Oh wow, after that comment it instantly came to me that it won't work in servers because clients need to decode the messages too. Woop woop.
Oh wow, after that comment it instantly came to me that it won't work in servers because clients need to decode the messages too. Woop woop.
In fact, these limits for temp entities can be expanded without engine changes, but then you must have access to change the code of both client and server sides
In simple words, expanding these limits for example for AG is not impossible, because you can make requests regarding these changes for the client (OpenAG, BHL-Rebased) and server (Adrenaline Gamer 6.7) sides
Here is the full guide on this topic: https://twhl.info/wiki/page/Tutorial%3A_Going_beyond_8192_units%3A_Part_2 But I will briefly outline to you what is generally required for these changes:
Server
- Create custom message that would sent from server to client
- Find blocks with SVC_TEMPENTITY references in code and replace in them the
WRITE_COORDtoWRING_LONG - Replace references to SVC_TEMPENTITY with your custom message
Client
- Handle that custom message on client-side
- Now you need to reverse-engineer event types of temp entities and implement their code on the client-side (look for the
CL_ParseTEntfunction in the engine, because it implements the logic of most temp entity events)
Also, in the file common/const.h from HLSDK there is documentation on how to parse each type of temp entity, which will greatly help you with your own implementation on the client side: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/common/const.h#L121
And yes, the code of these temp entities is quite implementable, since they also rely on the use of an engine interface that is transmitted to the client
For example, if in CL_ParseTEnt function for the TE_KILLBEAM case code used (*efx.R_BeamKill)(iVar15);
Then in the client code this can be implemented as gEngfuncs.pEfxAPI->R_BeamKill(iVar15);
TLDR:
- You should have edit access to both client and server code
- Use that linked TWHL guide for the concept of implementing
- Look in CL_ParseTEnt engine function for the code that used for each specific event of temp entity
- Look in
common/const.hfile to see the documentation of how to parse the each specific event of temp entity