Tutorial: How to fix those leaks Last edited 1 month ago2024-09-09 15:20:13 UTC

In other words: how to become a GoldSrc plumber. :walter:

In this tutorial, I'll cover what leaks are, what can cause them, and ultimately, how to fix them.
Before I explain those, I gotta mention a couple of very important things: hulls, the void and playable map space.

Introduction

Hulls are essentially collections of meshes in your map. There are 4 of them: You cannot see hull1 to 3, but you can touch them. They are meant for collision data.

Playable map space is, in technical terms, all enclosed volumes in the map that contain at least 1 entity. In other words, if you put an info_player_start in a room, that is playable map space. A single, isolated room, without any entities in it, will not get compiled into the map.

Here's a playable map space:
User posted image
The void is any space that is not playable map space.
User posted image
All this darkness and empty space around the room.

So, what are leaks then?
You can think of them as "holes" in a map, that will expose the playable map space to the void.

This is a leak:
User posted image
Sometimes, it can be a really small gap in your map.
User posted image
That must be all about leaks. This tutorial is over, right?
No.

How to identify that there's a leak

Compilers will always tell when a leak is found in the map. Only one leak can be reported at a time, even though your map may have multiple leaks.

If you use J.A.C.K., it may even warn you that the .prt file was not built (which is necessary for HLVIS to work):
User posted image
In the compile log, under the HLBSP section, you will get a message like this:
Warning: === LEAK in hull 0 ===
Entity light @ ( -56,  -8, 232)
Error:
  A LEAK is a hole in the map, where the inside of it is exposed to the
(unwanted) outside region.  The entity listed in the error is just a helpful
indication of where the beginning of the leak pointfile starts, so the
beginning of the line can be quickly found and traced to until reaching the
outside. Unless this entity is accidentally on the outside of the map, it
probably should not be deleted.  Some complex rotating objects entities need
their origins outside the map.  To deal with these, just enclose the origin
brush with a solid world brush

Leak pointfile generated
It will prevent HLVIS and HLRAD from doing their job. The .bsp file will still be compiled, however, it will be fullbright and the entire map will be rendered at once, causing lag.

The given coordinates are from the first entity that "spotted" the leak. It's almost never the leak itself.

Causes of leaks

Apart from visible gaps (which can be REALLY small), there are many other ways a leak can be made.
Those include:

Invalid brushes causing leaks

My personal favourite, the non-planar faces error, will be used as an example here.
User posted image
Let's go and compile this map!
User posted image
As expected. There is a leak here. This is because the intermediary .map format does not support non-planar surfaces. It would be similar to pressing Fix in the "Check map for problems" window. Let's try to simulate that:
User posted image
This is basically what the compilers will see, resulting in a leak.

Solution

Obviously, the solution is to make the brush valid. J.A.C.K.'s auto-triangulation option is very helpful for beginners (Ctrl+Alt+T in the Vertex Manipulation tool), TrenchBroom absolutely cannot produce an error like this, and Hammer... well... you can either flatten the face manually, or use Ctrl+F to split the face into 2 (in the Vertex Manipulation tool, after you've selected 2 non-neighbouring vertices).

Solid entities causing leaks

Any solid entity will get ignored when the compilers check for leaks. This means, if you converted a wall into a func_wall, you'd get a leak.
Let's actually do that:
User posted image
This can only end badly.
User posted image
Therefore, I'd recommend you to hide all solid entities while looking for a leak.

Solution

Revert the brush to a world brush. Alternatively, if it really needs to be an entity, then place some extra world brushes behind it.

Entities outside the playable map space

User posted image
Earlier on, I said that entities define the playable map space. So, if an entity is located in the void, it will automatically cause a leak.
What actually counts is the centre of the entity, i.e. the origin point. So if that happens to be outside of the map, then it's a leak.
If it's inside a brush, it's not a leak.

Solution

Just move them back into the map.

About solid entities

I said the origin point is what counts. What I'm about to say is gonna apply only to entities that require the origin brush.

This means, if your brush entity goes outside of the map, but its origin is inside the map, it won't make a leak.
To demonstrate this, I'll have a room with an empty middle space:
User posted image
And let's put some crates in the corners.
User posted image
They will all be tied to a single func_wall for this specific demonstration.
User posted image
Essentially, the centre of this entity will be the middle of the image.

However, it's not gonna leak. It's one of those entities that do not require an origin brush. However, if we added one anyway:
User posted image
Then it'd leak. A way of solving this exact problem would be to put a NULL brush around the origin, as long as the origin ends up inside of said brush. Another way would be, of course, to just move the origin brush elsewhere (however, that will affect things like trains, doors etc., so be careful).

NOCLIP texture leaks

This is a very obscure one, I must admit, but it's still very possible and can only be done manually/intentionally.
User posted image
Suppose we have a brush textured entirely with NOCLIP and it's cut into the floor.

So far, we've only been getting leaks in hull 0, but this one will make it leak in the other 3 hulls!
HLVIS and HLRAD should be allowed to do their job (they still fail, it's like a safety mechanism), but that means if you stepped on that brush, you'd fall through the floor, since there's a hole in the collision hull for it.
User posted image

How to use this to your advantage

We can do some trickery with cliphull1, cliphull2 and cliphull3 textures. Place two brushes on that same spot, one textured with cliphull1, the other with cliphull2.
User posted image
Now, let's do something different with cliphull3. We'll make a pit out of it.
Cliphull1 and 2 and NOCLIP temporarily hidden so you can see cliphull3Cliphull1 and 2 and NOCLIP temporarily hidden so you can see cliphull3
If we compile the map, it should compile without any leaks. Now walk to the spot with cliphull1, and crouch. You'll fall through it when you crouch, and land right into the void, or to be exact, where the pit ends. You may also notice that you cannot stand up once you're on cliphull3-only ground. :)

While this effect here is not particularly useful for most general cases, it shows how you can use leaks to your advantage, to fool the compilers. Can be useful if you're working on a really trippy-themed mod.

The pointfile, recognising the type of leak

Earlier in the tutorial, I showed this screenshot:
User posted image
You should always press No if this happens. J.A.C.K. will then load a pointfile, which will draw an initially red line, starting from the place where the leak was found. The line will become more blue towards its end.
Load the .map
Kimilil advises to load the exported .map file when looking for leaks. It's what is given to the compilers, and the point file is generated from them, so you might as well look at that.

In J.A.C.K., if you see a discrepancy between the exported map and the JMF, then you most likely have an invalid brush!
In TrenchBroom this does not apply.
Pointfiles are fairly precise and they always pick the shortest path to the leak:
User posted image
If it's going through a solid, world brush, then there's a problem with that brush, it might be invalid.
If it starts on the outside of the map, that means you have an entity outside of the map.
If it goes through an entity, that's normal. But sometimes it might mean that there's nothing behind your entity to seal the map from the void.

A lot of beginner mappers complain that the pointfile is too confusing and doesn't show them anything. You just need to know how to follow it properly. Start from the most red spot (which might be near the reported coordinates), and slowly follow along, until you find a gap, or an invalid brush, and so on.

How to avoid leaks, and how not to fix them

There are a few guidelines to avoid producing leaks.

Stay on the grid. If you're a beginner mapper, you probably aren't very used to working strictly with the grid. Think in powers of 2, think 16, 32, 64, instead of 1, 10 and 100. If you turn off snap-on-grid by accident, press Shift+W (if you're in J.A.C.K.). Smaller the grid, potentially smaller the gap.

Always place entities inside the map. This one needs no explanation, really.

Now, perhaps one of the most important pieces of advice in this tutorial:
Do not put a hollow box around the map to fix the leak, even when prototyping. Instead, seal your map properly as you work on it. Improve your map editing speed by doing it the tedious way, and soon it'll become second nature.

If you still end up sky "boxing" the map, it'll bite you later on when you start working on large maps. They will take much longer to compile, you'll hit the engine limitations sooner, and it will lag more in-game.

In the end

Generally, leaks don't deserve this much attention but, they are still one of the biggest obstacles for beginner mappers. A lot of people can just say "Open the pointfile and find the leak", and that doesn't mean much if you don't know how to follow the actual pointfile. Beginners should get to know quite a bit about leaks, and how to fight them, which is why I wrote this tutorial.

As you get more experienced, you'll generally produce fewer and fewer leaks.

So, happy mapping!
-Admer

2 Comments

Commented 1 month ago2024-09-09 05:54:50 UTC Comment #106377
I feel strongly about loading the exported .map file to find leaks, since it's what the compilers actually see when they compile the level. In fact this image from the page might have been just that, so why not just explicitly tell people to do it?
Commented 1 month ago2024-09-09 14:08:51 UTC Comment #106379
This is a good idea NGL. There could be omitted visgroups ("export only visible objects") and non-planar faces.
Edit: ack, the visgroup part doesn't make too much sense since you don't see them anyway when disabled. Bah! It can still happen under some circumstances.

You must log in to post a comment. You can login or register a new account.