Skip to content

Repository files navigation

index

A Minecraft mod that lets you color-code chests and search across all of them at once -- point a search at an item and get walked straight to the chest that has it.

demo mp4 here

Try it

Download the latest release here. Grab the .jar file and drop it into your mods folder.

Quick start

  1. Install Fabric Loader for 26.2
  2. Get Fabric API and your downloaded .jar file and drop them into your mods folder.
  3. Launch, hit CTRL+SHIFT+RIGHT CLICK, color your chest and start tracking!
  4. Open the search UI with RSHIFT, type an item name and matching chest light up with a floating item above and particles around the chest.

Features

  • Color-code chests -- hit the keybind to open a color picker and tint a chest any RGB color you want. The color is applied to the chest's render state, so it shows up in-world without replacing any textures.
  • Search across every colored chest at once -- type an item name and the server checks EVERY tracked chest's contents for you. You can search for several items at once; each match is marked with the specific item that was found.
  • Visual guidance -- a floating item marker hovers over each matching chest with subtle end_rod particles around it.
  • Audio feedback -- a distinct sound plays for a hit vs. a miss, so you know when a search resolved without needing to look away from what you're doing.
  • Tracked chests list -- see every chest you've colored from one screen, and untrack any of them without breaking the block.
  • Per-world color persistence -- colors are saved locally per world/server and reload automatically next time you join.
  • Server-side index persistence -- the set of colored chests is stored in the world's SavedData, so the search index survives server restarts.

Keybinds

Key Action
CTRL + SHIFT + RIGHT CLICK a chest Open the color picker for that chest
RIGHT SHIFT Open the item search screen

ONLY OPENING THE ITEM SEARCH SCREEN is rebindable from Minecraft's Controls > Keybinds screen (registered as [index] Open Search screen).

How to run/build?

First get Java 25 (or a version matching your target Minecraft version, this codebase is 26.2 only).

  1. Clone the repository:
    git clone https://github.com/mschiller890/index.git
  2. Build using Gradle
    cd index
    ./gradlew build
  3. Built jar lands in build/libs/.
  4. To test in a dev environment:
    ./gradlew runClient

How it works

The mod is split into a common (server) side and a client side, following Fabric's split-environment source set convention. The server owns the source of truth for which chests are tracked and what they contain; the client owns the colors and the UI.

src/main/java/com/mschiller890/index/           server / common
  Index.java                                       entrypoint, network handlers, tick loop
  ChestItemTracker.java                            in-memory Item -> count index per chest
  ColoredChestPositions.java                       SavedData: which chests are colored
  ChestSearchTracker.java                          per-player "active search" state
  ChestSearchMarkers.java                          per-player floating ItemEntity markers
  ChestSearchParticles.java                        end_rod particle bursts
  mixin/                                           BlockEntity / Level injections
  network/                                         C2S payloads (search, set color)

src/client/java/com/mschiller890/index/client/  client only
  IndexClient.java                                 keybinds, color-picker trigger
  ChestColorPersistence.java                       load/save colors on join/leave
  helpers/ChestColorManager.java                   in-memory BlockPos -> ARGB map
  helpers/ChestColorStorage.java                   NBT on disk per world id
  extension/ChestRenderStateExtension.java         Mixin interface on ChestRenderState
  mixin/                                           ChestRenderer / removal injections
  screens/                                         color picker, search, tracked chests UI

Indexing

Only chests you've explicitly colored get indexed -- the mod hooks BlockEntity#setChanged() and re-scans a chest's contents into an in-memory Item -> count map whenever a tracked chest changes, rather than polling every container in the world on a timer. The set of colored positions is persisted server-side via Minecraft's SavedData system (ColoredChestPositions), so the index survives restarts. On level load, every previously-colored chest is re-scanned into the index at once.

The index itself (ChestItemTracker) is a nested map keyed by ServerLevel -> BlockPos -> Item -> count. A search is then just a lookup: iterate the level's tracked chests and collect every position whose item map contains the queried item with a count greater than zero. No world scanning, no chunk loading, no container opening.

Telling "destroyed" apart from "unloaded"

Both a real chest break and a routine chunk unload (walking away, disconnecting, saving and quitting) call BlockEntity#setRemoved() -- Minecraft doesn't distinguish them at that hook. Untracking on every setRemoved() call meant chest colors and search state silently vanished on world reload, not just on actual destruction.

The fix uses Level#isLoaded(pos) as a guard: it's a cheap, non-blocking check, unlike getBlockEntity()/getChunk(), which can force a chunk to load and -- in earlier versions of this fix -- froze the game during "Saving world" by triggering exactly that kind of forced reload across thousands of unloading chunks at once. Only when the chunk is still loaded at the time setRemoved() fires does the mod treat it as a genuine removal.

A second mixin on Level#removeBlockEntity covers the case where a chest is broken directly (the block is removed before the block entity's setRemoved runs), so the index, search state, and markers are cleaned up either way.

Search

A search request is a single network round trip:

  1. The client builds a list of item IDs (from the search UI's checked items) and sends a SearchItemsC2SPayload.
  2. The server resolves each ID against the registry, looks each item up in the in-memory index, and collects matching BlockPos -> Item pairs.
  3. The server plays a hit/miss sound (note_block_pling for a hit, note_block_bass for a miss) directly to the searching player.
  4. ChestSearchMarkers spawns one lightweight, non-interactive ItemEntity per match, floating 1.2 blocks above the chest. Each marker is tagged with index_marker plus a per-player tag (index_marker_<uuid>), so it never appears for anyone but the searcher.
  5. A server tick task (every 10 ticks) spawns end_rod particles around each active match for the player who owns the search.

Markers are cleaned up the moment a match is opened (the UseBlockCallback removes that specific marker), the player disconnects (all of that player's markers are discarded), or the chest itself is destroyed (removeMarkerFromAllPlayers).

Coloring

Colors live entirely on the client. ChestColorManager holds a BlockPos -> ARGB map in memory, and ChestColorStorage persists it to <game dir>/index/chest_colors/<worldId>.dat as compressed NBT. The world id is derived from the singleplayer world folder name (sp_<name>) or the multiplayer server IP (mp_<ip>), so colors are scoped per world/server and never leak between them.

The actual tinting is done with a @ModifyConstant on ChestRenderer#submit that replaces the hardcoded tint (-1, i.e. white) with the stored color for that chest's position. To get the position into the render state, a small mixin (ChestRenderStateMixin) attaches a BlockPos field to ChestRenderState via the ChestRenderStateExtension interface, which is populated in extractRenderState and read back in submit. Ender chests are intentionally skipped so they keep their vanilla look.

When a chest is colored or uncolored, the client also sends a SetChestColorC2SPayload so the server can add/remove the position from ColoredChestPositions and start/stop indexing it. The client mirrors the same "is this a real removal?" guard (isLoaded) before clearing its local color, so colors survive chunk unloads.

Networking

Two custom payloads, both client-to-server:

Payload Purpose
SetChestColorC2SPayload(pos, colored) Add/remove a chest from the tracked set
SearchItemsC2SPayload(itemIds) Request a search across the index for a list of items

All server-side handling is dispatched onto the server thread via context.server().execute(...), so the index and SavedData are never touched off-thread.

Credits

Built on Fabric and Fabric API

About

A powerful chest indexing and item locator mod for Minecraft 26.2.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages