---
# System prepended metadata

title: FTB Materials Unification System - Implementation Plan

---

# FTB Materials Unification System - Implementation Plan Ideas

## Problem Statement

Multiple mods add duplicate material items (lead ingot, copper wire, etc.) with matching tags (`c:ingots/lead`, `c:wires/copper`). Manually mapping these for each modpack is unsustainable since mod availability varies by pack and Minecraft version.

## Proposed Solution

An automated material unification system **built into FTB Materials** that:

1. **Discovers materials at runtime** by scanning unified tags (`c:ingots/{material}`, etc.)
2. **Prioritizes FTB Materials items first**, then falls back to configured priority
3. **Allows overrides** for materials not in FTB Materials or when another mod's version is needed
4. **Full unification scope:** recipes, loot tables, and world generation
5. **Supports common tech mods:** Mekanism, Thermal, Create, Immersive Engineering and new mods as needed

## Architecture Decision: Built Into FTB Materials

**Rationale:**

- Single mod installation for pack devs
- Guaranteed compatibility with material definitions
- Can be enabled/disabled via config
- Direct access to Resource enum and ResourceType definitions

---

## Core Components

### 1. UnificationManager (Orchestrator)

- Central singleton that coordinates all unification subsystems.

**Responsibilities:**

- Initialize config and subsystems during mod init (or deferred to some ftblibs implementation)
- Build material index when tags are populated (SERVER_STARTED event)
- Handle datapack reloads
- Provide unified API for querying preferred items

### 2. UnificationConfig

**Config Files Location:** `config/ftbmaterials/unification/`

```
config/ftbmaterials/unification/
├── settings.json             # Global settings
├── priorities.json           # Mod priority list
├── extra-materials.json      # Materials not in Resource enum
├── disabled.json             # Materials/types to skip
└── worldgen.json             # Worldgen-specific settings
```

**settings.json:**

```json
{
  "enabled": true,
  "unifyRecipes": true,
  "unifyLootTables": true,
  "unifyWorldGen": true,
  "convertInputsToTags": true,
  "hideNonPreferredInJEI": true,
  "removeDuplicateRecipes": true,
  "removeTagsFromNonPreffered": true,
  "debugLogging": false
}
```

**priorities.json:**

```json
{
  "default": ["ftbmaterials", "mekanism", "thermal", "create", "immersiveengineering", "minecraft"],
  "overrides": {
    "osmium": ["mekanism"],
    "refined_glowstone": ["mekanism"],
    "andesite_alloy": ["create"]
  }
}
```

### 3. MaterialLookup (Tag Scanner)

**Purpose:** Discover what items exist for each material type at runtime

**Algorithm:**

```
For each ResourceType (INGOT, DUST, PLATE, WIRE, etc.):
  For each known material (from Resource enum + config):
    Resolve tag: c:ingots/{material}, c:dusts/{material}, etc.
    Query tag contents from registry
    Build bidirectional index: item <-> tag
```

**Key Maps:**

- `Map<ResourceLocation, UnificationEntry>` - item ID to entry
- `Map<TagKey<Item>, UnificationEntry>` - tag to entry
- `Map<String, UnificationEntry>` - "material:type" to entry

### 4. TagResolver

**Purpose:** Handle tag namespace resolution (c:/forge:/fabric: conventions)

**Tag Namespaces in Priority Order:**

1. `c:` (modern NeoForge/Fabric convention)
2. `forge:` (legacy Forge)
3. `fabric:` (legacy Fabric)

**Special Cases:**

- ResourceType.SHARD has `"shards|mekanism:shards"` - need to handle pipe-separated alternatives
- RAW_BLOCK uses name mutator: `raw_{material}` pattern

### 5. PriorityResolver

**Purpose:** Determine which item version to prefer for each tag

**Default Priority Order:**

1. `ftbmaterials` (ALWAYS first - this is the mod's core value proposition)
2. Configured mod list (mekanism, thermal, create, etc.)
3. `minecraft` (fallback for vanilla items)

### 6. UnificationEntry

**Data Class containing:**

- Material name
- Resource type
- Unified tag
- All items in tag
- Preferred item (cached)

---

## Intial Foundation & Core Lookup

### Modifications to Existing Files

**FTBMaterials.java:**

```java
// Add to init():
UnificationManager.get().init();

// Add SERVER_STARTED event:
LifecycleEvent.SERVER_STARTED.register(server -> {
    UnificationManager.get().onTagsPopulated();
});

// Add to registerCommands():
.then(UnificationCommands.register())
```

### Debug Commands

```
/ftbmaterials unify dump              # List all unified materials
/ftbmaterials unify check <item>      # Show unification info for item
/ftbmaterials unify stats             # Show index statistics
/ftbmaterials unify material <name>   # Show all types for a material
/ftbmaterials unify reload            # Force rebuild caches
```

### Deliverable

System that logs discovered materials and preferred items on server start.

---

## Vanilla Recipe Transformation

### RecipeManager Mixin Strategy

- Create accessor mixin to get recipe map
- Inject at `apply()` method TAIL to transform after loading

### Recipe Types to Handle

**Vanilla:**

- ShapedRecipe (requires reflection for pattern access most likely)
- ShapelessRecipe
- SmeltingRecipe
- BlastingRecipe
- SmokingRecipe
- CampfireCookingRecipe
- StonecutterRecipe
- SmithingRecipe

### Data Component Preservation

```java
ItemStack result = new ItemStack(preferredItem, original.getCount());
if (!original.getComponents().isEmpty()) {
    result.applyComponents(original.getComponents());
}
```

### Deliverable

All vanilla recipe outputs unified to FTB Materials items.

---

## Tech Mod Recipe Support

### Files to Create

```
common/src/main/java/dev/ftb/mods/ftbmaterials/unification/recipe/
└── modhandlers/
    ├── RecipeHandler.java          # Interface
    ├── MekanismRecipeHandler.java
    ├── ThermalRecipeHandler.java
    ├── CreateRecipeHandler.java
    └── IERecipeHandler.java
    └── MiscMods.java
    └── FutureMods.java
```

etc etc

### Soft Dependencies

```java
public class MekanismRecipeHandler implements RecipeHandler {
    private static final boolean MEKANISM_LOADED =
        ModList.get().isLoaded("mekanism");

    @Override
    public boolean canHandle(Recipe<?> recipe) {
        if (!MEKANISM_LOADED) return false;
        return recipe.getClass().getName().contains("mekanism");
    }
}
```

### Tech Mod Recipe Types

**Mekanism:**

- Crushing, Enriching, Combining, Purifying
- Injecting, Infusing, Crystallizing
- Note: Many use `ItemStackToItemStackRecipe` base class

**Thermal:**

- Pulverizer, Smelter, Press
- Sawmill, Centrifuge, Refinery
- Note: Most extend `SingleItemRecipe` variants

**Create:**

- Crushing, Milling, Pressing
- Mixing, Compacting, Washing
- Note: All extend `ProcessingRecipe`

**Immersive Engineering:**

- Crusher, Arc Furnace
- Metal Press, Alloy Kiln
- Note: Multiblock recipes may need special handling

### Deliverable

Full tech mod recipe unification.

---

## Loot Table Unification

### Approach Options

- **Mixin into LootTable loading** - Intercept during load

### Loot Entry Types to Handle

- `LootItem` entries (direct item drops)
- Preserve counts, functions, conditions
- Skip entries that reference specific mod items (don't unify mod-specific loot)

### Deliverable

All loot drops use preferred items.

---

## World Generation Control

### Files to Create

```
common/src/main/java/dev/ftb/mods/ftbmaterials/
├── unification/worldgen/
│   └── OreFeatureDisabler.java
├── mixin/
│   └── BiomeGenerationMixin.java (or use platform API)
```

### Strategy Options

1. **Feature Removal:** Remove configured features from biome generation
2. **Ore Replacement:** Replace other mod ores with FTB Materials ores in world
3. **Config Generation:** Generate configs for other mods to disable their ores

### Considered Approach

Feature removal via mixin into `BiomeGenerationSettings`:

- Scan for ore features that place blocks matching unification tags
- Remove features that place non-preferred ore variants
- Keep FTB Materials ore generation active

### Config

**worldgen.json:**

```json
{
  "disableOtherModOres": true,
  "modsToDisable": ["mekanism", "thermal", "immersiveengineering"],
  "keepModOres": {
    "mekanism": ["osmium", "fluorite"],
    "thermal": ["cinnabar", "niter"]
  }
}
```

### Deliverable

Only FTB Materials ores generate (configurable).

---

## Integrations & Polish

### JEI/EMI Integration

- Hide non-preferred items from ingredient list
- Ensure recipes show correctly with unified outputs
- Implement via `IIngredientFilter` (JEI) or similar

### Performance Optimization

- Profile startup time impact
- Implement lazy caching where possible
- Use early termination in loops

## Data Flow

### Datapack Reload Flow

```
1. /reload command
   └── Clear caches
   └── Rebuild MaterialLookup index
   └── Re-transform recipes
```

---

## Existing Codebase Integration Points

### Potential Unit Tests

- `PriorityResolverTest` - Verify FTB Materials always wins, overrides work
- `TagResolverTest` - Test c:/forge:/fabric: fallback logic
- `MaterialLookupTest` - Test bidirectional index building

---

## Risk Mitigation

| Risk | Mitigation |
|------|------------|
| Performance with 200+ mods | Lazy caching, batch operations, early termination |
| Recipe type not handled | Fallback to generic handler, log warning |
| Mod API changes | Use reflection with fallbacks, version checks |
| Circular ore processing chains | Track processed items to avoid infinite loops |
| Config conflicts | Validation on load, clear error messages |
| 1.21 API changes | Verify all mappings against Mojang/Yarn, use accessor mixins |

---