Skip to content

Architecture Overview

This document describes the high-level architecture of Ansible Crafting, its package structure, key classes, and data flows.

See also: Development Guide for building and testing, Guidelines for coding conventions.


High-Level Architecture

Ansible Crafting is a client-server Minecraft mod for Fabric, Forge, and NeoForge that scans nearby inventories on the server, syncs the data to the client for display, and handles crafting requests that pull items from remote containers. The codebase uses Stonecutter + Modstitch for multi-version, multi-loader support from a single source tree.

flowchart TB
    subgraph Server Side
        SCANNER["InventoryScanner<br/>Scans nearby blocks"]
        AGG["AggregatedInventory<br/>Merges all inventories"]
        STATE["InventoryStateManager<br/>Persistent enable/disable"]
        CRAFT["RemoteCraftingHandler<br/>Extracts items from containers"]
        SESSION["CraftingSessionManager<br/>Tracks active crafting sessions"]
    end

    subgraph Network
        SYNC_PKT["InventorySyncPacket<br/>Item data โ†’ client"]
        STATE_PKT["InventoryStateSyncPacket<br/>Enable/disable states โ†’ client"]
        TOGGLE_PKT["InventoryToggleRequestPacket<br/>Toggle request โ†’ server"]
        RESYNC_PKT["StateResyncRequestPacket<br/>Resync request โ†’ server"]
    end

    subgraph Client Side
        CACHE["ClientInventoryCache<br/>Stores synced item data"]
        PANEL["InventoryPanelWidget<br/>Side panel UI"]
        HIGHLIGHT["HighlightRenderer<br/>Block outline highlights"]
        OVERLAY["InventoryOverlayRenderer<br/>Wifi status icons"]
        SHADER["ShaderCompat<br/>Shader mod detection"]
        TRACKER["InventoryPanelTracker<br/>Panel lifecycle"]
        TEXTURES["AnsibleCraftingTextures<br/>Texture identifiers"]
    end

    subgraph Integrations
        EMI["EMI Plugin<br/>Recipe transfer + exclusion zones"]
        REI["REI Plugin<br/>Recipe transfer + exclusion zones"]
    end

    SCANNER --> AGG
    AGG --> SYNC_PKT
    STATE --> STATE_PKT
    SYNC_PKT --> CACHE
    STATE_PKT --> CACHE
    CACHE --> PANEL
    PANEL --> HIGHLIGHT
    TOGGLE_PKT --> STATE
    RESYNC_PKT --> STATE
    EMI --> CRAFT
    REI --> CRAFT
    CRAFT --> SESSION

Package Structure

com.ansiblecrafting/
โ”œโ”€โ”€ AnsibleCraftingMod          โ€” Server-side mod entrypoint, lifecycle
โ”œโ”€โ”€ ModResourceLocation         โ€” Version-safe ResourceLocation factory
โ”œโ”€โ”€ RegistryHelper              โ€” Version-safe registry lookup utility
โ”œโ”€โ”€ ServerTickHandler           โ€” Per-tick inventory scanning orchestration
โ”œโ”€โ”€ client/
โ”‚   โ”œโ”€โ”€ AnsibleCraftingClient   โ€” Client-side mod entrypoint
โ”‚   โ”œโ”€โ”€ AnsibleCraftingTextures โ€” Texture ResourceLocation constants
โ”‚   โ”œโ”€โ”€ ClientInventoryCache    โ€” Client-side inventory data cache
โ”‚   โ”œโ”€โ”€ HighlightRenderer       โ€” 3D block highlight rendering
โ”‚   โ”œโ”€โ”€ InventoryOverlayRenderer โ€” 3D inventory icon overlay rendering
โ”‚   โ”œโ”€โ”€ ShaderCompat            โ€” Shader mod detection (Iris/Optifine)
โ”‚   โ””โ”€โ”€ ui/
โ”‚       โ”œโ”€โ”€ InventoryPanelTracker โ€” Panel visibility state tracking
โ”‚       โ””โ”€โ”€ InventoryPanelWidget  โ€” Side panel UI widget
โ”œโ”€โ”€ config/
โ”‚   โ”œโ”€โ”€ ConfigScreenBuilder     โ€” Cloth Config screen builder
โ”‚   โ”œโ”€โ”€ ModConfig               โ€” Configuration data class
โ”‚   โ””โ”€โ”€ ModMenuIntegration      โ€” Mod Menu config screen provider
โ”œโ”€โ”€ crafting/
โ”‚   โ”œโ”€โ”€ ClientCacheRecipePopulator โ€” Client-side recipe ingredient populator
โ”‚   โ”œโ”€โ”€ CombinedPlayerInventory โ€” Player + nearby inventory wrapper
โ”‚   โ”œโ”€โ”€ CraftingSessionManager  โ€” Per-player crafting session state (CraftingSession is a Java record)
โ”‚   โ”œโ”€โ”€ GridSlotSourceHolder    โ€” Tracks which container each grid slot's item came from
โ”‚   โ”œโ”€โ”€ RemoteCraftingHandler   โ€” Item extraction/insertion from nearby containers
โ”‚   โ”œโ”€โ”€ VirtualInventory        โ€” Read-only Container for recipe filling
โ”‚   โ””โ”€โ”€ VirtualSlot             โ€” Single slot in a VirtualInventory
โ”œโ”€โ”€ integration/
โ”‚   โ”œโ”€โ”€ NearbyInventoryHelper   โ€” Shared recipe viewer helper methods
โ”‚   โ”œโ”€โ”€ emi/
โ”‚   โ”‚   โ”œโ”€โ”€ AnsibleCraftingEmiExclusionArea
โ”‚   โ”‚   โ”œโ”€โ”€ AnsibleCraftingEmiPlugin
โ”‚   โ”‚   โ””โ”€โ”€ AnsibleCraftingRecipeHandler
โ”‚   โ”œโ”€โ”€ jei/
โ”‚   โ”‚   โ”œโ”€โ”€ AnsibleCraftingJeiPlugin
โ”‚   โ”‚   โ”œโ”€โ”€ JeiExclusionAreaHandler
โ”‚   โ”‚   โ””โ”€โ”€ JeiTransferHandler
โ”‚   โ””โ”€โ”€ rei/
โ”‚       โ”œโ”€โ”€ ReiExclusionZoneProvider
โ”‚       โ”œโ”€โ”€ ReiPlugin
โ”‚       โ””โ”€โ”€ ReiTransferHandler
โ”œโ”€โ”€ inventory/
โ”‚   โ”œโ”€โ”€ AggregatedInventory     โ€” Merged view of all nearby container contents
โ”‚   โ”œโ”€โ”€ CapabilityBackedInventory โ€” Forge/NeoForge capability wrapper
โ”‚   โ”œโ”€โ”€ InventoryLookup         โ€” Block entity โ†’ Container resolution
โ”‚   โ”œโ”€โ”€ InventoryScanner        โ€” Nearby container discovery and caching
โ”‚   โ”œโ”€โ”€ InventoryStateManager   โ€” Per-inventory enable/disable persistence
โ”‚   โ”œโ”€โ”€ InventoryToggleHandler  โ€” Toggle request processing
โ”‚   โ””โ”€โ”€ StorageBackedInventory  โ€” Fabric Transfer API wrapper
โ”œโ”€โ”€ mixin/
โ”‚   โ”œโ”€โ”€ AbstractRecipeScreenHandlerMixin โ€” Recipe placement injection
โ”‚   โ”œโ”€โ”€ CraftingScreenHandlerMixin      โ€” Crafting menu lifecycle hooks
โ”‚   โ””โ”€โ”€ client/
โ”‚       โ”œโ”€โ”€ ContainerScreenMixin โ€” Generic container screen hooks
โ”‚       โ””โ”€โ”€ CraftingScreenMixin  โ€” Crafting screen panel integration
โ””โ”€โ”€ network/
    โ”œโ”€โ”€ InventoryStateSyncPacket    โ€” Serverโ†’Client state sync
    โ”œโ”€โ”€ InventorySyncPacket         โ€” Serverโ†’Client inventory data sync
    โ”œโ”€โ”€ InventoryToggleRequestPacket โ€” Clientโ†’Server toggle request
    โ”œโ”€โ”€ NetworkHandler              โ€” Forge/NeoForge network channel setup
    โ”œโ”€โ”€ RemoteCraftFillRequestPacket โ€” Clientโ†’Server craft request
    โ”œโ”€โ”€ StateResyncRequestPacket    โ€” Clientโ†’Server state resync request
    โ””โ”€โ”€ StateSyncHelper             โ€” State sync utility methods

Key Data Flows

Inventory Scanning and Sync

sequenceDiagram
    participant Server as Server (tick loop)
    participant Scanner as InventoryScanner
    participant Agg as AggregatedInventory
    participant Net as Network
    participant Cache as ClientInventoryCache
    participant Panel as InventoryPanelWidget

    Server->>Scanner: scanInventories(player) every N ticks
    Scanner->>Scanner: Find blocks with inventories within range
    Scanner->>Agg: Aggregate all inventory contents
    Agg->>Net: InventorySyncPacket (item stacks + positions)
    Net->>Cache: Update cached item data
    Cache->>Panel: Panel reads cache on render

Remote Crafting (via Recipe Viewer)

sequenceDiagram
    participant Player as Player
    participant EMI as EMI / REI
    participant Handler as RecipeHandler
    participant Mixin as CraftingScreenHandlerMixin
    participant Remote as RemoteCraftingHandler
    participant Container as Nearby Container

    Player->>EMI: Click recipe to craft
    EMI->>Handler: Transfer recipe to crafting grid
    Handler->>Mixin: fillInputSlots() with remote sources
    Mixin->>Remote: Extract items from remote inventories
    Remote->>Container: Remove items from container slots
    Remote->>Mixin: Place items in crafting grid
    Player->>Mixin: Take crafted result
    Mixin->>Remote: Return unused items to source containers

Inventory Toggle

sequenceDiagram
    participant Player as Player (Client)
    participant Net as Network
    participant State as InventoryStateManager
    participant PState as PersistentState (World Save)

    Player->>Net: InventoryToggleRequestPacket (blockPos, enabled)
    Net->>State: Toggle inventory at position
    State->>PState: Persist to world save data
    State->>Net: InventoryStateSyncPacket (updated states)
    Net->>Player: Client updates overlay icons

Mixin Strategy

The mod uses four mixins to hook into Minecraft's crafting system and screen rendering:

Mixin Target Purpose
CraftingScreenHandlerMixin CraftingScreenHandler Injects remote inventory support into the crafting handler; implements GridSlotSourceHolder
AbstractRecipeScreenHandlerMixin AbstractRecipeScreenHandler Extends recipe book to consider remote items
CraftingScreenMixin CraftingScreen Injects the inventory panel into the crafting table screen
ContainerScreenMixin HandledScreen Injects the inventory panel into container screens (chests, barrels, etc.)

Mixin policy: No empty stub mixins. Every mixin must contain at least one functional injection. See Guidelines โ€” Mixin Best Practices.


Recipe Viewer Integration

Both EMI and REI integrations follow the same pattern:

flowchart LR
    PLUGIN["Plugin Registration<br/>EmiPlugin / REIClientPlugin"] --> HANDLER["Recipe Transfer Handler<br/>Fills crafting grid from remote items"]
    PLUGIN --> EXCLUSION["Exclusion Zone Provider<br/>Prevents recipe viewer overlapping panel"]
Component EMI REI
Plugin AnsibleCraftingEmiPlugin ReiPlugin
Transfer Handler AnsibleCraftingRecipeHandler ReiTransferHandler
Exclusion Zone AnsibleCraftingEmiExclusionArea ReiExclusionZoneProvider

JEI is supported on Forge (1.20.1) and NeoForge (1.21.1+) via the integration/jei/ package.


Client-Server Boundary

All code is strictly separated by side:

Side Entry Point Packages
Server (both dedicated + integrated) AnsibleCraftingMod inventory, crafting, config, network, mixin
Client only AnsibleCraftingClient client/*, client/ui/*, mixin/client/*, integration/*

Client-only classes use @Environment(EnvType.CLIENT) to prevent loading on dedicated servers. Entry points are declared in fabric.mod.json:

{
  "entrypoints": {
    "main": ["com.ansiblecrafting.AnsibleCraftingMod"],
    "client": ["com.ansiblecrafting.client.AnsibleCraftingClient"]
  }
}

Persistent State

InventoryStateManager extends Minecraft's PersistentState to save per-inventory enable/disable toggles to the world save. This means:

  • Toggle states survive server restarts
  • Each world/dimension has its own state
  • States are synced to clients via InventoryStateSyncPacket