Case file — hei_hw1_02

Two maps, one building.Fix one door, break the other.

A bank heist door and a casino entrance, eighty-eight metres apart, both served by edited copies of the same vanilla building. This is how we proved whether the two could coexist — including the part where we decided they could not, and were wrong.

Reported by
Server owner, live dev environment
Symptom
Bank heist door will not open. Casino intact.
Contested asset
hei_hw1_02 (vanilla downtown building)
Separation
≈88 m between the two doors
First verdict
Cannot coexist — withdrawn
Final verdict
Mergeable. Both function.

The report was simple enough. Two paid map resources were installed. Disable the casino and the bank heist door opened. Disable the bank and the casino worked. Run both and whichever loaded last won, which meant one of the two was always broken. The doors are nowhere near each other — you can stand at one and not see the other — so nothing about the symptom suggests they are related.

They are related because of a rule that has nothing to do with geography: the game keeps exactly one file of any given name, and both resources ship a file called hei_hw1_02_strm_1.ymap. Two doors, eighty-eight metres apart, decided by a filename collision.

The two resources

One is a Pacific Standard bank interior with the heist door and vault. The other is a casino built into the same downtown block. Neither is doing anything wrong. Both did what map resources normally do: they took the vanilla building they sit in, edited it, and shipped their edited copy.

That is the entire mechanism. There is no error, no warning and no log line, because from the game’s point of view nothing unusual happened — it was handed two files with the same name and kept one.

What each one actually ships

Before you can say anything useful about a conflict you have to know what is in it. These are the real files, at the real sizes, pulled off the server:

Evidence A — the contested hei_hw1_02 family
FileBankCasinoWhat it is
hei_hw1_02_strm_1.ymap14,325 B13,754 BPlacement — the entities
hei_hw1_02_0.ybn233,696 B244,280 BCollision — the solid world
hei_hw1_02.ymap2,700 BBase / LOD, 38 SLOD entities
..._heist_ornate_bank_milo_.ymap1,207 BBank interior
..._v_cinema_milo_.ymap1,192 BCasino interior

Two things are already visible. The interiors are not in conflict — they have different filenames and different archetypes, so both can load and both do. And the casino ships a [compatibility_folder] containing a previous hand-patch against a different resource entirely, which tells you this building has been fought over before.

So the contest is over two files: the placement .ymap and the collision .ybn. That distinction turns out to matter enormously.

The decisive comparison

A difference in byte count tells you the files are not identical. It tells you nothing about whether they can be reconciled. For that you have to dump both to XML and compare what is actually inside — entity by entity, archetype and position.

Evidence B — entity comparison, hei_hw1_02_strm_1.ymap
MeasureResult
Bank entities339
Casino entities319
Present in bank, absent from casino21
Present in casino, absent from bank0
Location of the 21x 300–310, y 203–220, z ≈104–105

That last row is the whole case. The twenty-one entities the bank adds are not scattered through the building — they sit in one tight cluster, and that cluster is the heist door zone. Eleven of them are lights carrying CExtensionDefLightEffect; the rest are door and frame geometry.

And the row above it is the reason a merge is possible at all: the casino adds nothing the bank lacks. The casino’s placement file is a subset. The two edits do not overlap, they stack — so “keep both” is not a compromise between them, it is simply the union.

Two files being different is not a conflict. Two files being different in the same place is a conflict. Almost all of the diagnostic work is telling those apart.

We merged the placement file, built it, and put it on the server. The casino stayed completely intact. All twenty-one heist entities were present and correct — the door frame, the lights, the geometry.

And the heist door still would not open.

Where we got it wrong

At that point we concluded that this pair was genuinely irreconcilable: that the casino claims the building’s interior at runtime, that the bank’s door lives in collision rather than placement, and that between the two there was no version of the world where both worked. A hard wall. We said so.

That conclusion was wrong, and it was proven wrong by somebody else’s product. The owner ran the same two resources through a commercial merging tool, and both worked — the casino intact, the heist functioning end to end. So we did the only useful thing available: we read the files that tool produced, to find out what it knew that we did not.

Two things, as it turned out.

The first is that we had merged the wrong half. The placement file was the obvious candidate because it is the one with readable entities in it, but the heist door is collision. Merging the .ymap put the door’s geometry and lights back into the world while the .ybn still came wholesale from whichever resource won — so the door was visibly there and physically absent. The visible world and the solid world are separate files and they were still disagreeing.

The second is a delivery detail. Rather than shipping a merged file and hoping it wins the naming contest, the merged asset can be registered at runtime — the server hands the client the combined file directly, so the question of which resource loaded last stops mattering at all. It sidesteps the race instead of trying to win it.

Neither of those is obvious, and we did not get to them by reasoning. We got to them by being contradicted by a working result and going to look at why.

How to run this yourself

Nothing above requires our tools. If you have two map resources fighting, this is the sequence:

  1. Find the collision. List the stream folder of every map resource and look for the same filename appearing twice. That is your contested asset — usually a .ymap, a .ybn, or both.
  2. Separate placement from collision. A .ymap decides what is drawn and where. A .ybn decides what is solid. A door that is visible but will not open, or a wall you can see through but not walk through, is the two disagreeing.
  3. Dump both copies to XML and compare entities, not bytes. You are asking one question: does each file contain something the other does not, and are those somethings in the same place?
  4. If one file’s entities are a superset of the other’s, the edits stack and a merge is a union rather than a judgement call. If both add different things at the same coordinates, somebody has to lose, and you should decide that deliberately rather than by load order.
  5. Fix every contested file, not the interesting one. This is the mistake we made, and it produced a door that looked perfect and did nothing.

The rule worth keeping

Two resources editing the same building is not automatically a conflict you have to resolve by choosing. Quite often the edits are disjoint, and the reason you are forced to choose is not the content of the files but the fact that they share a name.

Whether that is true of your two resources is a question with an actual answer, and you can get to it in about ten minutes with a file listing and a diff. It is worth doing before you delete anything, because the version of this that ends with “I removed the casino” was never the only option on the table.