For years, I believed that world boundaries for entities were hardcoded in the engine. That is until a buddy of mine told me otherwise.
So yeah, for the most part, they actually aren't limited.
The first step was to raise this limit inside the HL SDK. There was a function in CBaseEntity that would check whether an entity is inside the world boundaries.
However, entities would still get stuck at +-4096. The player would go up to +-8192 and then get stuck. Interestingly, moving entities like func_train would still keep their collision until +-8192.
Video
It's time for the second step. If we look at the files in the mod folder, there is a
delta.lst
file. In a nutshell, it defines how many bits are used to carry entity data (position, angles, velocity etc.) and at what precision. More about it can be found in NetworkEntity.doc inside the HL SDK. I'll put up a part of it here:
The format for delta.lst is straightforward. The only lines that require additional explanation are the actual definitions, which take the form:So, what does this mean? Imagine the player is located at 2050 units on the X axis. This gets multiplied by 128, and it's 262400. So, the engine is gonna send this number to us. We receive it, then divide by 128, and we get 2050. For example, if we were located at 0.5 units on the X axis, which is perfectly possible, the engine would send 64 to us. We divide by 128, and we get 0.5 again.
DEFINE_DELTA( origin[0], DT_SIGNED | DT_FLOAT, 21, 128.0 ),
This definition specifies that the x – array index [0] -- coordinate of the field named origin ( a three component vector field in this data structure ) represents a signed floating point value. When sending this value over the network, the value should be multiplied by 128.0, converted to an integer, and sent in 21 bits ( 20 for the value, 1 for the sign bit ). The receiving side will know to cast it to a floating point value and divide by 128.0 to obtain the final value on the remote side.
Alright. So we have 20 bits for the absolute value, and that means that the maximum value for origin[0] is 1048576. When we divide that maximum value by 128, what do we get?
I'll let the reader guess. :^)
So, in order to increase that limit, we can do two things here. Either decrease the multiplier, which will decrease our precision from 1/128th of a unit to, say, 1/64th, oooor, increase the number of bits being sent. I went with the latter, giving me a total of 31 value bits, which corresponds to about 16 million when divided by 128. 16 million units. Dayum.
Now that I think about it, it would be smarter to decrease that to 16 + 7 + 1 = 24 bits. It'll give me about +-65k units to work with.
Now, the third step, obviously, was to modify the compilers to allow for this kind of thing.
God. VHLT source code is a mess. But I can handle it. I added a simple compile parameter (
-maxentrange
, defaults to 32768 units) that will let you set your own world boundaries, so for example, if an entity goes outside of +-65k units, it warns you about it. Either way though, all this work resulted in this:
Video
So, this is basically gonna allow me (and potentially, you) to make larger maps. :3 For the hub maps, this will be amazing. For some certain missions in the mod, it will be amazing as well.
Any kind of entity is gonna work in this new range. Now, in the beginning of the post, I actually said "for the most part". This has its limits and I'll work around that. The limit I'm talking about are things like particles, explosions and stuff like that. Can't recall if decals are affected as well.
I might write about this in more in an actual tutorial. So we'll see.
Obviously, I still have the clipnodes limit, AllocBlock, and the rest. I can't change those. But, considering the level of detail this mod's levels will have, it's fine to me.