BunnymodXT icon indicating copy to clipboard operation
BunnymodXT copied to clipboard

feature: concept of expanding origin limit for temp entities

Open SmileyAG opened this issue 1 year ago • 3 comments

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_ParseTEnt and MSG_ReadCoord engine functions
  • PF_MessageBegin_I: start tracking the svc_tempentity message 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

SmileyAG avatar Feb 11 '24 18:02 SmileyAG

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.

khanghugo avatar Mar 02 '24 06:03 khanghugo

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.

khanghugo avatar Mar 02 '24 06:03 khanghugo

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_COORD to WRING_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_ParseTEnt function 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.h file to see the documentation of how to parse the each specific event of temp entity

SmileyAG avatar Mar 02 '24 13:03 SmileyAG