Skip to content

Stop tile recolouring from stacking material clones until tiles vanish - #36

Merged
tomluchowski merged 1 commit into
tomluchowski:shaders-improvementfrom
Upabjojr:split/tile-recolour-material-leak
Aug 21, 2026
Merged

Stop tile recolouring from stacking material clones until tiles vanish#36
tomluchowski merged 1 commit into
tomluchowski:shaders-improvementfrom
Upabjojr:split/tile-recolour-material-leak

Conversation

@Upabjojr

Copy link
Copy Markdown

This is the actual cause of the disappearing bridge meshes on the ForgottenTreasures2 level from #34.

colourizeMaterial() names its colourized copy by appending the colour suffix to the material it was given, and colourizeEntity() recovers the original material by cutting the name at a ## separator. The separator was commented out of the append in the Z pre-pass work (understandably — the outliner/brighter suffixes use ## too, and a generic find("##") strip would eat theirs), so every recolour since then has been cloning the already colourized material and growing the name by one more suffix: WoodBridgeWoodBridgeColor_1_WoodBridgeColor_1_Color_2_ → … one fresh Ogre material per refresh.

Tiles that rarely change colour hide this well. Bridge claiming walks right into it: every handover refreshes the square and its neighbours, the clone chain grows by a link each time, and a few claims in, the cloned material stops rendering — the planks vanish from the map while the server keeps correctly reporting the bridge (I verified the packets: hasBridge=1, WoodBridge.mesh, waterGround all the way through). That's why #34 makes it visible: square-by-square claiming multiplies the recolour events. The bug itself is independent of #34 and was quietly leaking a material clone on every tile recolour.

The fix brings the separator back as @@, which nothing else uses: recolouring now replaces the suffix instead of stacking it, the find("##_Outliner")/find("##_Brighter") checks can never match a colourized name, and the set of materials stays bounded at one per (material, seat colour, dig mark, vision) combination. colourizeEntity() is only ever called for tile meshes and bridge meshes, so nothing else changes behaviour.

Verified on your level with seat 2's workers claiming WoodenBridge_9 in skirmish:

  • unfixed: five claimed squares lost their planks within a minute, exactly as you reported;
  • fixed: all 27 squares stay drawn through 14 handovers, recoloured to the claimer's colour square by square, and the material name stays WoodBridge@@Color_2_ instead of growing without bound.

Loading the level in the editor and in skirmish before any claims looks identical before/after.

🤖 Generated with Claude Code

https://claude.ai/code/session_014hrk8PiEUMgjYJnTxLF2PU

colourizeMaterial() names its colourized copy by appending the colour
suffix to the material it was given, and colourizeEntity() recovers the
original material by cutting the name at a "##" separator. The separator
went away when the Z pre-pass work commented it out of the append (the
outliner and brighter suffixes use "##" too, and a generic find("##")
strip would eat theirs), so every recolour has been cloning the already
colourized material and growing the name by one more suffix:
WoodBridge, WoodBridgeColor_1_, WoodBridgeColor_1_Color_2_, and so on,
one fresh Ogre material per refresh.

A tile that rarely changes colour hides this well enough. Claiming
enemy squares walks right into it: every handover refreshes the tile
and its neighbours, the chain of clones grows by one link each time,
and a few claims in, the cloned material no longer renders - the
square's bridge planks disappear from the map while the server keeps
saying, correctly, that the bridge is there. The claim-a-bridge level
from the review of the square-by-square claiming change shows exactly
that: bridge tiles wink out one by one as the enemy workers dance.

Bring the separator back as "@@", which nothing else uses, so the
recolour replaces the suffix instead of stacking it and never touches
the "##_Outliner"/"##_Brighter" names: colourizeEntity() only ever
serves tile and bridge meshes, and the set of materials stays bounded
at one per (material, seat colour, dig mark, vision) combination.

Verified on ForgottenTreasures2 with enemy workers claiming a bridge:
unfixed, five claimed squares lost their planks within a minute;
fixed, all 27 squares stay drawn through 14 handovers, recoloured to
the claimer's colour, and the material name stays WoodBridge@@Color_2_
instead of growing without bound.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014hrk8PiEUMgjYJnTxLF2PU
@tomluchowski
tomluchowski merged commit 1db3187 into tomluchowski:shaders-improvement Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants