> ## Documentation Index
> Fetch the complete documentation index at: https://wiki.refineryteam.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Version Abstraction

> Checking server capabilities without branching on raw Minecraft version strings.

`xyz.refineryteam.refinerycore.api.version` centralizes version-specific behavior behind a `ServerImplementation` interface, instead of scattering `Bukkit.getMinecraftVersion()` string comparisons across your plugin.

## Why not just check the version string?

Comparing raw version strings (`Bukkit.getMinecraftVersion().startsWith("1.21")`) is brittle and gets duplicated across every place that needs a version check. RefineryCore instead models version-dependent behavior as a set of named `Feature` flags, resolved once per server boot via the currently-running `ServerImplementation`.

## Checking a feature

```java WolfArmorApplication.java icon="java" theme={"system"}
ServerImplementation server = RefineryCorePlugin.getInstance().getServerImplementation();

if (server.supports(Feature.WOLF_ARMOR)) {
    // safe to reference wolf armor items/equipment slot
}
```

Or, from any class implementing `RefineryPluginImplementation`:

```java EnchantmentManager.java icon="java" theme={"system"}
if (getServerImplementation().supports(Feature.DATA_DRIVEN_ENCHANTMENTS)) {
    // use Registry.ENCHANTMENT
} else {
    // fall back to legacy static Enchantment constants
}
```

## `Feature`

Capability flags for behavior that differs between Minecraft versions. Add a new constant here whenever a plugin feature needs to behave differently on a given server version:

| Constant                   | Meaning                                                                                                                               |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `DATA_DRIVEN_ENCHANTMENTS` | Whether `Registry.ENCHANTMENT` exposes the data-driven enchantment registry (1.21+) rather than legacy static `Enchantment` constants |
| `WOLF_ARMOR`               | Whether wolf armor items and the related equipment slot exist (added 1.21.2)                                                          |
| `COPPER_OXIDATION_ITEMS`   | Whether the vanilla copper block/tool family with oxidation states exists                                                             |
| `BOGGED_MOB`               | Whether the Bogged mob and its associated equipment behavior exist (added 1.21)                                                       |

## `ServerImplementation`

The interface exposing version info and feature checks:

| Method                    | Description                                                                                                  |
| ------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `getMinecraftVersion()`   | Raw version string (e.g. `"1.21.4"`) — for logging/diagnostics only, prefer `supports(Feature)` for behavior |
| `getVersionOrdinal()`     | Comparable integer ordinal, encoded as `major * 10_000 + minor * 100 + patch`                                |
| `supports(Feature)`       | Whether the running server supports the given capability                                                     |
| `isAtLeast(String other)` | Whether this server's version is the same as or newer than `other`                                           |

## Resolution — `ServerImplementations`

`ServerImplementations` (plural) resolves the correct `ServerImplementation` for whatever server is currently running:

```java MyPlugin.java icon="java" theme={"system"}
ServerImplementation current = ServerImplementations.current();
```

Implementations are registered against a **minimum version** (inclusive). At resolution time, the highest-registered implementation whose minimum version is `<=` the running server's version is selected — so new patch releases automatically fall through to the newest compatible implementation without needing a new registration, until a genuine breaking change requires one.

```java ServerImplementations.java icon="java" theme={"system"}
static {
    register("1.20.0", new Server1_20Implementation(runningVersion()));
    register("1.21.0", new Server1_21Implementation(runningVersion()));
    // register("1.22.0", new Server1_22Implementation(runningVersion()));
}
```

### Adding support for a new version

Only add a new implementation class when a version genuinely changes behavior that matters to the plugin (a renamed enum, a newly added registry entry, an API not present below a certain version) — most versions within a minor line can share a single implementation.

1. Create a class extending `AbstractServerImplementation`:

```java Server1_22Implementation.java icon="java" theme={"system"}
public class Server1_22Implementation extends AbstractServerImplementation {
    public Server1_22Implementation(String minecraftVersion) {
        super(minecraftVersion);
    }

    @Override
    public boolean supports(Feature feature) {
        return switch (feature) {
            case DATA_DRIVEN_ENCHANTMENTS, BOGGED_MOB, COPPER_OXIDATION_ITEMS, WOLF_ARMOR -> true;
            // add new cases here as new Feature constants are introduced
        };
    }
}
```

2. Register it in `ServerImplementations`'s static block:

```java ServerImplementations.java icon="java" theme={"system"}
register("1.22.0", new Server1_22Implementation(runningVersion()));
```

`AbstractServerImplementation` handles storing/exposing the version string and computing its ordinal — subclasses only implement `supports(Feature)`.

<Note>
  If the running server's version is older than every registered implementation's minimum version, `ServerImplementations` falls back to the **oldest registered** implementation rather than throwing, so the plugin can still attempt to load (features will report as whatever that oldest implementation says, which may be incorrect for a truly unsupported version — this is a best-effort fallback, not a guarantee of correctness).
</Note>
