# TrontMod

Minimal Fabric mod template for Minecraft 26.2. Two items and nothing else; copy this folder to start a new mod.

**New to modding? Read [TUTORIAL.md](TUTORIAL.md).** It walks this exact code from "what is a mod" to shipping,
with exercises and a 2026 translation table for all the old Yarn-era tutorials that no longer compile.

| Item | What | Where |
|---|---|---|
| `trontmod:tront_coin` | plain do-nothing item | creative: Ingredients |
| `trontmod:emerald_sword` | real weapon: 7 damage (= diamond), 1200 durability, enchantability 20, repairs with emerald, craftable (2 emerald + stick) | creative: Combat, after diamond sword |

## Requirements

- JDK 25 (Minecraft 26.2 requires it). Gradle auto-detects JDKs in `~/.jdks`; this machine has Temurin 25 there.
- Nothing else: the Gradle wrapper downloads Gradle, Loom, Minecraft, and Fabric API on first run (5-10 min once).

## Commands

```
gradlew test         # JUnit, no server: registry + item component checks (~5s)
gradlew runGameTest  # headless server with datapacks: recipe/tag/ItemStack checks (~10s)
gradlew build        # compile + both test kinds + jar -> build/libs/trontmod-<version>.jar
gradlew runClient    # launches a dev Minecraft client with the mod loaded (offline, no login)
```

Two test layers, both headless:
- `src/test/` (JUnit + fabric-loader-junit): fast, no world. Note the `@BeforeAll` dance: since 26.x item
  components are not bound at bootstrap, so the test builds them via `VanillaRegistries.createLookup()`.
- `src/gametest/` (Fabric game tests, `@GameTest`): a real server loads the mod's `data/` files, so this is
  where recipes and tags are proven. Runs as part of `build`. `eula = true` in build.gradle accepts the
  Minecraft EULA for that throwaway server.

IntelliJ: open the folder, let Gradle import, then use the generated "Minecraft Client" run config.

## Layout

```
src/main/java/xyz/tront/trontmod/
    TrontMod.java        entrypoint (fabric.mod.json "main"); calls ModItems.initialize()
    ModItems.java        ToolMaterial + item registration + creative tab hooks
src/client/java/xyz/tront/trontmod/client/
    TrontModClient.java  client entrypoint; empty, for rendering/keybinds later
src/test/java/xyz/tront/trontmod/
    ModItemsTest.java    fabric-loader-junit registry + component test
src/gametest/java/xyz/tront/trontmod/gametest/
    TrontModGameTest.java   server game tests (recipe, tag, stats); manifest in src/gametest/resources
src/main/resources/
    fabric.mod.json      mod id, entrypoints, dependencies
    assets/trontmod/
        items/tront_coin.json          client item definition (which model to use)
        models/item/tront_coin.json    flat "generated" item model pointing at the texture
        textures/item/tront_coin.png   16x16
        lang/en_us.json                display names
    data/trontmod/
        recipe/emerald_sword.json              shaped crafting recipe (vanilla format)
        tags/item/emerald_tool_materials.json  what repairs emerald gear (minecraft:emerald)
    data/minecraft/tags/item/swords.json       adds our sword to #minecraft:swords so vanilla sword enchants apply
```

## Adding another item

1. `ModItems.java`: add `public static final Item FOO = register("foo", Item::new, new Item.Properties());`
   and `tab.accept(FOO)` in the creative tab hook.
2. Add `items/foo.json`, `models/item/foo.json`, `textures/item/foo.png` (copy the coin files, rename).
3. Add `"item.trontmod.foo": "Foo"` to `lang/en_us.json`.
4. `gradlew test` then `gradlew runClient`.

## Adding a tool or weapon

Same as an item, but the properties do the work: `new Item.Properties().sword(MATERIAL, 3.0F, -2.4F)`
(or `.pickaxe(...)`, `.axe(...)`, `.shovel(...)`, `.hoe(...)`). Model parent is `minecraft:item/handheld`.
Add the item to the matching `#minecraft:swords` / `pickaxes` / ... tag via `data/minecraft/tags/item/<tag>.json`.

## Textures from AI images (art/)

`art/unfake_texture.py` turns an AI-generated "fake pixel art" PNG into a real texture: detects the fake-pixel
grid, snaps each cell to one colour, flood-fills the background away, crops, recolors the AI black outline into
material-dark (vanilla never uses black edges), pads so the pommel is bottom-left and the tip top-right, then
area-average downscales and quantizes to 32x32 (20 colours) and 16x16 (12). Flags: --outline keep|strip,
--method dominant, --colors32 N.

```
python art/unfake_texture.py art/emerald_sword_source.png art/emerald_sword --outline-tint "#0a4a22" --tint-mix 0.6 --palette vanilla-emerald
```

Item textures can be any power-of-two size. Two finished versions live in `art/`, swap with one copy:

```
cp art/emerald_sword_16_vanilla.png src/main/resources/assets/trontmod/textures/item/emerald_sword.png   # shipped: vanilla-res
cp art/emerald_sword_64.png         src/main/resources/assets/trontmod/textures/item/emerald_sword.png   # hi-res, faithful to the AI art
```

- `emerald_sword_16_vanilla.png` comes from `art/vanilla_sword_16.py`: vanilla's diamond sword skeleton pulled
  from the Minecraft jar, blade remapped to emerald tones, iron guard + pommel, green gems. Sits next to vanilla.
- `emerald_sword_64.png` is the unfaked AI sprite as-is (no lossy downscale). The 32 and 16 downscales are there
  too, but a straight downscale mushes the guard; hand-built wins at 16.
- `--palette vanilla-emerald` locks colours to Mojang's own emerald/iron/stick tones; `--outline-tint` leans the
  recolored outline toward one material colour.
- Alternative tool: the unfake.js native CLI (`C:/trontstack/clonedrepos/unfake.js`, `cargo build --release`,
  then `unfake detect|snap|downscale|quantize`).

## Installing into the real launcher

1. Run the Fabric installer once for 26.2 (creates a "fabric-loader-26.2" launcher profile).
2. Copy `build/libs/trontmod-<version>.jar` and the matching Fabric API jar into `%APPDATA%\.minecraft\mods\`.
3. Launch the Fabric profile. The coin is in the creative menu under Ingredients.

## Versions

See `gradle.properties`. Bump `minecraft_version`, `loader_version`, `fabric_api_version` together from https://fabricmc.net/develop.
