Skip to content
DurdeuVladPublic

About

Server-side NeoForge mod for Minecraft 1.21.1 that reconstructs explainable item movement from authoritative evidence.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

347 Commits

Folders and files

Repository files navigation

ItemGraph

Trace item movement through time.

ItemGraph is a server-side Minecraft moderation and forensic analysis mod for NeoForge and Fabric 1.21.1. It answers the question ordinary grief loggers cannot: given the recorded evidence, how did this item plausibly move from one place to another?

Players do not need the mod on their clients. ItemGraph records native server evidence into its own database — plausible item-type and stack-quantity movement across players, supported vanilla containers, and ground/entity observations over time, plus a native audit ledger for non-item events — and builds an explainable temporal item-flow graph from it.

New here? Start with the admin quick start — it maps common incident questions to the exact command that answers each one.

What ItemGraph proves — and what it never claims

ItemGraph keeps four kinds of results strictly separate, on every line of output and in every stored row:

Label Meaning
OBSERVED A specific event or inventory delta was directly recorded.
INFERRED ItemGraph linked observations under deterministic temporal, quantity, metadata, endpoint, and candidate rules. An explanation, not a direct observation.
AMBIGUOUS Multiple targets or candidate flows fit. The candidates are shown; nothing is silently picked.
UNRESOLVED The event is known, but its cause, destination, or relationship cannot be safely claimed.

Two rules follow from this:

  • ItemGraph reconstructs item type / metadata / quantity flow. It does not assign a permanent UUID to every physical item, and a matching fingerprint never proves two stacks are the same physical item.
  • Unless creation, destruction, or transformation evidence exists, inferred flow must conserve quantity. Every inferred edge links back to the exact evidence IDs and deterministic scoring factors behind it — ask /ig explain <edgeId>.

An empty query result means no matching stored row exists. It does not prove nothing happened; the coverage limits list event families that are not yet captured.

Install

Releases ship exactly two files. Pick the one matching the server's loader — NeoForge is the primary loader and Fabric is also supported.

  • itemgraph-<version>-neoforge.jar
  • itemgraph-<version>-fabric.jar

Place the jar in the server's mods/ folder and restart. ItemGraph targets Minecraft 1.21.1 on dedicated servers.

ItemGraph replaces GriefLogger — the two mods must not be installed together, and each loader declares the conflict in its metadata (NeoForge incompatible, Fabric breaks). Both jars embed a SQLite driver in a way the module system cannot deduplicate, so coexistence was never a stable state. The 0.4.0-beta.1 release published two -grieflogger-compatible jars as the final coexistence artifacts; they are deprecated and no later release ships them.

ItemGraph runs independently of GriefLogger. Native capture, storage, reconstruction, and native queries require neither the GriefLogger jar nor its database. Fabric and NeoForge use loader-specific event adapters over the same ItemGraph ledger. Native replacement coverage is tracked in GriefLogger replacement parity.

Migrate a server that runs GriefLogger

A separate read-only migration bridge can import legacy evidence when explicitly enabled. It is disabled by default and never probes database.db on its own.

  1. Stop the server.
  2. Remove the GriefLogger mod jar. Keep its database.db file.
  3. Install the standard ItemGraph jar for the loader.
  4. Enable the bridge: set NeoForge general.grieflogger_integration_enabled=true or Fabric grieflogger_integration_enabled=true, and set grieflogger_database_path to the retained GriefLogger database.
  5. Restart, then run /ig ingest history to queue the import. The source database stays read-only; ItemGraph writes imported rows and reports only to its own database.

Only the GriefLogger 1.2.10-1.21.1 schema is a tested import source; other versions are rejected cleanly rather than mis-imported. Queries over imported legacy rows require a completed source sync/import. Full procedure: GriefLogger integration.

Configure storage

ItemGraph-owned storage defaults to SQLite — most servers need no database configuration at all. The full key, default, range, and restart matrix is in the configuration reference; the essentials:

Goal Setting
MySQL/MariaDB instead of SQLite database_backend=mysql_mariadb plus database_host, database_port, database_name, database_username, database_password, database_ssl_mode, database_connection_timeout_ms
TLS to MySQL/MariaDB database_ssl_mode=verify-full for production (use verify-ca with an explicitly trusted CA); verify-full/verify-ca are required for MySQL caching_sha2_password. disable is intended for a server authentication method that does not require RSA key retrieval, keeps database traffic plaintext, and warns when used with a non-loopback host
Optional non-unique lookup indexes Enabled by default. Set NeoForge storage.use_indexes=false or Fabric use_indexes=false and restart to drop them; set true and restart to recreate. Required unique indexes stay for deduplication; MySQL/MariaDB also retain an index when it alone supports a foreign key
Query page size Output defaults to ten rows, capped by query.max_page_size/max_page_size (range 1–100)

NeoForge's database connection keys are under general; the index setting is under storage in its server TOML. Raw evidence retention is fixed at indefinite; ItemGraph does not purge raw evidence. Legacy V3–V5 topology resets preserve old observation rows and their raw payloads in ig_legacy_observation_evidence; those superseded rows remain available for forensic review and are excluded from current graph queries.

Verify ItemGraph is working

/ig status
/ig audit

/ig status starts with an ACTION line — a safe next step when a database/capture stop is reported, or a warning that no stop was reported (capture coverage is still unproven). captureState=ACTIVE confirms the capture path is open; it does not prove every event type is supported. /ig audit checks stored-data invariants off-thread. Before trusting an empty search, confirm capture was active and the event type is supported — the admin quick start has the full status-field table.

Native ItemGraph event capture starts automatically when enabled in config.

Commands

/itemgraph and /ig are the same root. Every command requires itemgraph.command plus its exact leaf nodes where listed. Unset named permissions fall back to vanilla permission level 2; permission providers can delegate each sensitive surface by exact node, nodes do not inherit through dotted names, and an explicit permission-provider denial overrides operator status. Run /ig help permissions for the exact access nodes; the full contract is in Security and permissions.

/ig help [topic]
/ig help permissions
/ig status
/ig audit
/ig ingest now
/ig ingest history
/ig event   <observationId>
/ig explain <edgeId>
/ig lookup <eventType> [limit] [sinceMinutes]
/ig lookup near <dimension> <x> <y> <z> <radius> <eventType> [limit] [sinceMinutes]
/ig lookup player <playerName> <eventType> [limit] [sinceMinutes]
/ig lookup page <page> <eventType> [limit] [sinceMinutes]
/ig lookup action.<value> [user.<value>] [include.<value>] [exclude.<value>] [time.<value>] radius.<value>
/ig lookup provenance <sourceSha256> <table> <sourceKey> [limit]
/ig page <page> [session]
/ig trace item <query> [limit] [sinceMinutes]
/ig trace player <playerName> [limit] [sinceMinutes]
/ig trace container <x> <y> <z> [limit] [sinceMinutes]
/ig gui item <query> [sinceMinutes]
/ig gui player <playerName> [sinceMinutes]
/ig gui container <dimension> <x> <y> <z> [sinceMinutes]
/ig inspect [on|off|status]

What each one is for:

  • /ig help: bare /itemgraph or /ig shows a short task-first overview. /ig help commands is a compact task hub that points to detailed topics; /ig help <topic> provides exact routes, syntax, and examples where applicable. Unknown topics suggest the closest matches and point to /ig help commands.
  • /ig audit: performs off-thread verification of database invariants (conservation, positivity, relational graph integrity, and allocation state consistency).
  • /ig trace item: accepts numeric fingerprint IDs, item registry names, or custom item names. Quote namespaced IDs or names containing spaces (for example, /ig gui item "minecraft:netherite_boots"); use /ig gui item "id:123" to force an exact fingerprint ID when a bare numeric query is ambiguous. Shows supported chronological lineage, including anvil transformations. Craft/smelt outputs with unobserved inputs remain unresolved audit events and do not create trace edges.
  • /ig trace player: shows all movements involving a player across inventories, ground drops/pickups, containers, and armor stands.
  • /ig trace container: reconstructs item ingress and egress for a container at coordinates (x, y, z).
  • /ig event, /ig explain, and /ig trace: preserve their stable visible text and provide bounded hover fields for evidence class, safe item identity, canonical fingerprint hash, event kind, UTC time, and recorded endpoints. Recorded spatial endpoints include a player-only, one-use [Go to ...] link; it rechecks the originating query permissions when clicked and works only while that dimension is loaded.
  • /ig gui: opens item/player/container timelines in a vanilla six-row chest menu. Each page has at most nine entries. A numbered chat companion identifies each row by evidence class, safe item identity, event kind, and UTC time when available; row numbers match menu slots. Hover text and icons add detail. In a selected detail page, hover each paper icon to read its field; use the page controls and Back button to navigate. Ambiguous targets require candidate selection; missing identities have an explicit fallback. The command and every menu action require itemgraph.command, itemgraph.gui, and itemgraph.audit; see Security and permissions. The menu uses no custom client screen or packet and rejects inventory-movement actions.
  • /ig inspect: toggles per-player inspection mode. Left-clicking a block shows that block's paginated audit history in chat. Right-clicking a block entity that implements Container opens the read-only flow browser instead of the normal container GUI. Double chests clicked on either half resolve to the same canonical anchor used when their contents are recorded. Other right-clicks show paginated block history; ordinary blocks select the block on the clicked face. A click is consumed when its read-only request is accepted and when the request is denied for a missing grant — denied inspection clicks must not break or toggle blocks — while transient rejections and rejected container right-clicks preserve vanilla interaction. on, off, and status are deterministic forms. The command and each inspection click require itemgraph.command.inspect; an inspection click on a container also requires itemgraph.gui. Permission loss disables inspection mode, tells the player why, and consumes the click that detected it. Consumption covers the click's whole packet set — the block use, the off-hand useItemOn, the item-use twin packet, entity right-clicks (interact/interactAt, denied and recorded as INTERACT_ENTITY_DENIED evidence), and entity left-clicks (attacks, denied and recorded as ATTACK_ENTITY_DENIED evidence) — so held or off-hand items, armor stands, shears, milk buckets, and name tags are never used on the inspected scene and no predicted hit can damage it, even on the revocation-detecting click; inspection does not record an inspection click as a transfer.
  • /ig lookup: a level-1 lookup-only moderator needs both itemgraph.command and itemgraph.command.lookup. Add itemgraph.command.page for /ig page and clickable page controls. Provider denies override operator level 2; unset nodes use the level-2 fallback. Use /ig help permissions for the other nodes.
  • /ig lookup and /ig lookup filters return native or unified evidence, depending on the syntax. Historical reads are asynchronous and read-only. Native event capture runs automatically when enabled in config. /ig ingest now optionally syncs from a configured GriefLogger source; /ig ingest history is a separate read-only import from that source. Full argument table and output format: Query model.

Reading a trace result

Every result line is labeled with its evidence class — never once at the top, so a paste of the output cannot silently upgrade inference to observation:

[OBSERVED] CONTAINER 10,64,10 -> AlphaA : 1x at 2026-09-16 14:31:08 UTC (observation#8812 REMOVE_ITEM)
[OBSERVED] AlphaA -> GROUND 20,64,20 : 1x at 2026-09-16 14:31:18 UTC (observation#8813 DROP_ITEM)
[INFERRED conf=0.9990] AlphaA -> BetaB : 1x at 2026-09-16 14:31:18 UTC (edge#9931 inferred transfer spanning 1m0s)
[OBSERVED] GROUND 20,64,20 -> BetaB : 1x at 2026-09-16 14:32:18 UTC (observation#8814 PICKUP_ITEM)

A confidence value is a deterministic score computed from documented evidence factors — not a calibrated probability that the history is true. /ig explain shows the factors and candidate counts behind a link.

How it thinks

ItemGraph models item history as a directed temporal multigraph.

  • Nodes represent inventories or locations capable of holding items.
  • Observed events record direct evidence.
  • Inferred edges connect compatible observations into plausible item flow.
  • Time is a first-class constraint: later evidence cannot explain an earlier event.
  • Quantity is conserved unless creation, destruction, or transformation evidence exists.
  • Confidence is explicit and explainable.
Chest A --14:31, 1x named helmet--> Alice
Alice   --14:52, 1x named helmet--> Ground
Ground  --14:52, 1x named helmet--> Bob
Bob     --15:08, 1x named helmet--> Chest B
Minecraft / Mod hooks / (optional) GriefLogger source
               |
               v
        Raw observations
               |
               v
        Evidence storage
               |
               v
    Correlation / inference engine
               |
               v
         Item Flow Graph
               |
               v
       Query + explanation UI

When the optional migration bridge is enabled, confirmed cross-source copies preserve both raw rows but contribute one quantity capacity; uncertain matches remain ambiguous. Container GUI observations are session net deltas with explicit time bounds, not click history, and generic IItemHandler rows keep caller/cause identity UNKNOWN.

Existing grief and audit loggers answer who removed items from this chest or what was broken here. ItemGraph adds the reconstruction layer: given all available evidence, how did this named armor piece plausibly move from one inventory to another over the last two days?

The first useful vertical slice (the MVP contract) should:

  1. Read relevant GriefLogger evidence without mutating it.
  2. Record only missing high-value inventory events where necessary.
  3. Canonicalize an item fingerprint.
  4. Represent inventories as graph nodes.
  5. Represent raw observations separately from inferred movement.
  6. Reconstruct a simple item path through time.
  7. Trace a distinctive named item.
  8. Trace ordinary stack quantity flow.
  9. Explain why an inferred edge exists.
  10. Persist across restarts.
  11. Demonstrate the feature safely on staging.

Server message language

Server messages can use en_us, nl_nl, or zh_tw through NeoForge general.language or Fabric language. Text is rendered server-side for vanilla clients; missing keys fall back to English. Help entry text and navigation labels have translated entries; 174 authored source phrases currently use the explicit English fallback inventory, including detailed help topics. The exact GriefLogger 1.2.10-1.21.1 locale inventory is unknown; supported ItemGraph locales are based on pinned 26.2 source config research only.

Preview integration API

Trusted server mods can use com.itemgraph.api PREVIEW_1 to register their own source identity, submit bounded raw observations, and run asynchronous item/player/container queries. The API is shipped in this JAR, uses a service-issued SourceHandle, and returns immutable DTOs plus opaque evidence URIs—not JDBC, schema IDs, mutable Minecraft state, or caller-provided inference. A compiling NeoForge fixture lives in examples/api-consumer. The complete boundary and authorization rules are in Preview integration API.

Project identity

  • Name: ItemGraph
  • Mod ID: itemgraph
  • Primary command: /itemgraph
  • Alias: /ig
  • Platforms: Fabric, NeoForge
  • Target Minecraft version: 1.21.1
  • Primary deployment model: dedicated server
  • Preview integration API: com.itemgraph.api PREVIEW_1 in the main JAR
  • Changelog: CHANGELOG.md
  • Tagline: Trace item movement through time.

Documentation

For server admins and moderators:

For integrators and contributors:

Records and project state:

Open-source project

ItemGraph is developed in the open under the MIT License. External contributions use forks and pull requests. The configured non-publishing CI workflow runs on pull requests and pushes to main; release publishing remains a maintainer-only tag operation and never exposes release credentials to fork contributors.

Read CONTRIBUTING.md before opening a pull request. Report security issues privately using SECURITY.md.

Development rule

Production must never be used as the development environment.

All discovery, schema inspection, testing, database exploration, and early implementation must happen on staging.

Evidence first. Inference second. Confidence explicit. Every conclusion traceable.

About

Server-side NeoForge mod for Minecraft 1.21.1 that reconstructs explainable item movement from authoritative evidence.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages