Skip to content

Add "Hidden icons" rules, applied at draw time - #9

Open
LostPoE wants to merge 1 commit into
exApiTools:poe1from
LostPoE:hidden-icon-rules
Open

Add "Hidden icons" rules, applied at draw time#9
LostPoE wants to merge 1 commit into
exApiTools:poe1from
LostPoE:hidden-icon-rules

Conversation

@LostPoE

@LostPoE LostPoE commented Aug 14, 2026

Copy link
Copy Markdown

Problem

Both existing ways to suppress an icon run at icon creation. An entry in ignored_entities.txt, or in the hardcoded MinimapIcons.Ignored list, makes IconsBuilder.SkipIcon return before an icon object exists:

if (IgnoredEntities.Any(x => entity.Path?.Contains(x) == true)) return true;

Two consequences:

  • An exclusion can't be undone without an area change. ReadIgnoreFile only runs on AreaChange, and even after a reload the icon was never built, so there's nothing to draw.
  • MinimapIcons.Ignored can't be undone at all without editing the plugin and rebuilding.

There's also no way to add an exclusion from the UI — you have to find the metadata path, locate the right file, and change zone.

What sent me looking: a Fortress map with ~30 Metadata/Monsters/LeagueHeist/Robot/LightBot/MapLightBot in it. They're hostile white monsters, so MonsterIcon gives them the same large red circle as a real pack, but they're ambient props you never fight — enough dots to make the map hard to read.

Change

A ContentNode<IconIgnoreRule> in the settings menu. Each row is a label, an unanchored metadata regex, and its own Hide toggle. Matching runs in the draw loop, right after the existing Ignored check:

if (IsHiddenByRule(icon.Entity.Path))
    continue;

Because it's applied at draw time rather than at creation, a toggle takes effect on the next frame in both directions — an unwanted icon can be silenced, and brought back, without a restart or a rebuild.

The list ships empty, so behaviour is unchanged unless a rule is added. The change is purely additive: 156 insertions, no deletions, nothing existing touched.

Performance

Render() runs every frame, so the matching is kept cheap:

  • Regexes compile once per pattern and are cached by pattern text.
  • path -> hide answers are cached, so a breach with hundreds of entities behind a handful of distinct paths costs one dictionary hit per icon.
  • The cache is invalidated by a per-frame integer hash of the rule set, not by building and comparing a string, so the per-frame path doesn't allocate.
  • A pattern that fails to compile is logged once and then skipped — a half-typed regex is a normal state while editing the field, not something to log every frame or take the other rules down with.

Notes

IconIgnoreRule.ToString() names the row in the settings UI, which otherwise falls back to object.ToString() and shows every row as MinimapIcons.IconIgnoreRule. It ends in ### so the ImGui id stays stable while the visible label changes, otherwise the row collapses itself as you type — same idiom used for ContentNode rows elsewhere in the ecosystem.

Testing

Built against ExileCore on net10.0-windows, 0 warnings, 0 errors, and run in-game. Verified with a temporary per-frame dump of every icon that survives the filter chain:

  • Rule on, pattern Metadata/Monsters/RockGolem/ → 91 icons drawn, no RockGolemSummoned, while ChaosElementalSummoned, LightningGolemSummoned and FireElementalSummoned all still drew. Sibling paths unaffected.
  • Same rule toggled off → RockGolemSummoned back.
  • With the light bots rule on, the five red dots on the large map disappeared; their five drawn-icon entries matched the dots' screen positions one-to-one beforehand.

🤖 Generated with Claude Code

Both existing ways to suppress an icon run at icon *creation*: an entry in
ignored_entities.txt or in the hardcoded MinimapIcons.Ignored list makes
IconsBuilder.SkipIcon return before an icon object exists.

That has two consequences. An exclusion cannot be undone without an area
change, because ReadIgnoreFile only runs on AreaChange and the icon was never
built; and the hardcoded list cannot be undone at all without editing the
plugin. There is also no way to add one from the UI.

This adds a ContentNode of rules to the settings menu, each with a label, an
unanchored metadata regex, and its own Hide toggle. They are applied in the
draw loop instead, so toggling one takes effect on the next frame in both
directions, and an unwanted icon can be silenced without a restart or a
rebuild.

The list ships empty, so behaviour is unchanged unless a rule is added.

Render() runs every frame, so the matching is kept cheap: regexes compile once
per pattern, path -> hide answers are cached, and the cache is invalidated by a
per-frame integer hash of the rule set rather than by rebuilding a string. A
pattern that fails to compile is logged once and skipped, since a half-typed
regex is a normal state while editing the field.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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