Skip to main content
The Fabric API provides platform-specific classes and events for integrating BetterHud with Fabric modded servers.

Installation

repositories {
    mavenCentral()
}

dependencies {
    compileOnly("io.github.toxicity188:BetterHud-standard-api:VERSION")
    modCompileOnly("io.github.toxicity188:BetterHud-fabric-api:VERSION")
    compileOnly("io.github.toxicity188:BetterCommand:VERSION")
}
Check Maven Central for the latest version.Requires Fabric API mod to be installed on the server.

Platform Support

BetterHud supports Fabric for Minecraft:
  • Minecraft 1.21.11 (server-side)

Core Classes

FabricBootstrap

The main entry point for accessing Fabric-specific functionality.
package kr.toxicity.hud.api.fabric;

public interface FabricBootstrap extends BetterHudBootstrap {
    EventRegistry<EventRegistry.Unit> PRE_RELOAD_EVENT = new EventRegistry<>();
    EventRegistry<ReloadState> POST_RELOAD_EVENT = new EventRegistry<>();
    
    @Override
    default boolean isFolia() { return false; }
    
    @Override
    default boolean isPaper() { return false; }
    
    @Override
    default boolean isVelocity() { return false; }
    
    @Override
    default boolean isFabric() { return true; }
}
Static Events:
  • PRE_RELOAD_EVENT - Fired before BetterHud reloads configuration
  • POST_RELOAD_EVENT - Fired after BetterHud completes reloading
Usage:
import kr.toxicity.hud.api.fabric.FabricBootstrap;
import kr.toxicity.hud.api.BetterHudAPI;

public class MyFabricMod implements ModInitializer {
    @Override
    public void onInitialize() {
        // Register reload listeners
        FabricBootstrap.PRE_RELOAD_EVENT.register(unit -> {
            LOGGER.info("BetterHud is about to reload!");
        });
        
        FabricBootstrap.POST_RELOAD_EVENT.register(state -> {
            if (state.success()) {
                LOGGER.info("BetterHud reloaded successfully!");
            } else {
                LOGGER.error("BetterHud reload failed: " + state.message());
            }
        });
    }
}

EventRegistry

Fabric’s custom event system for registering and firing events.
package kr.toxicity.hud.api.fabric.event;

public final class EventRegistry<T> {
    public @NotNull EventRegistry<T> register(@NotNull Consumer<? super T> consumer);
    public @NotNull EventRegistry<T> registerTemp(@NotNull Consumer<? super T> consumer);
    public void clear();
    public static void clearAll();
    public void call(@NotNull T t);
}
Methods:
  • register(Consumer) - Registers a permanent event listener
  • registerTemp(Consumer) - Registers a temporary listener (cleared on reload)
  • clear() - Clears all temporary listeners for this registry
  • clearAll() - Static method to clear all temp listeners from all registries
  • call(T) - Fires the event to all registered listeners

Events

Event Base Interfaces

FabricEvent

Base interface for all Fabric events.
package kr.toxicity.hud.api.fabric.event;

public interface FabricEvent<T extends FabricEvent<?>> {
    @NotNull EventRegistry<T> getRegistry();
}

PlayerEvent

Base interface for player-related events.
package kr.toxicity.hud.api.fabric.event;

public interface PlayerEvent<T extends FabricEvent<?>> extends FabricEvent<T> {
    @NotNull ServerPlayer player();
}

Entity Events

All entity events are implemented as Java records for simplicity.

PlayerDeathEvent

Fired when a player dies.
package kr.toxicity.hud.api.fabric.event.entity;

public record PlayerDeathEvent(@NotNull ServerPlayer player) 
    implements PlayerEvent<PlayerDeathEvent> {
    
    public static final EventRegistry<PlayerDeathEvent> REGISTRY = new EventRegistry<>();
    
    @Override
    public @NotNull EventRegistry<PlayerDeathEvent> getRegistry() {
        return REGISTRY;
    }
}
Usage:
PlayerDeathEvent.REGISTRY.register(event -> {
    ServerPlayer player = event.player();
    // Handle player death
    HudPlayer hudPlayer = BetterHudAPI.inst().getHudPlayer(player.getUUID());
    if (hudPlayer != null) {
        hudPlayer.showPopup("death_screen");
    }
});

PlayerAttackEntityEvent

Fired when a player attacks an entity.
package kr.toxicity.hud.api.fabric.event.entity;

public record PlayerAttackEntityEvent(
    @NotNull ServerPlayer player,
    @NotNull LivingEntity entity
) implements PlayerEvent<PlayerAttackEntityEvent>, EntityEvent<PlayerAttackEntityEvent> {
    
    public static final EventRegistry<PlayerAttackEntityEvent> REGISTRY = new EventRegistry<>();
    
    @Override
    public @NotNull EventRegistry<PlayerAttackEntityEvent> getRegistry() {
        return REGISTRY;
    }
}
Usage:
PlayerAttackEntityEvent.REGISTRY.register(event -> {
    ServerPlayer player = event.player();
    LivingEntity target = event.entity();
    
    // Show damage popup
    HudPlayer hudPlayer = BetterHudAPI.inst().getHudPlayer(player.getUUID());
    if (hudPlayer != null) {
        hudPlayer.showPopup("damage_indicator");
    }
});

PlayerDamageByEntityEvent

Fired when a player takes damage from an entity.
package kr.toxicity.hud.api.fabric.event.entity;

public record PlayerDamageByEntityEvent(
    @NotNull ServerPlayer player,
    @NotNull LivingEntity entity
) implements PlayerEvent<PlayerDamageByEntityEvent>, EntityEvent<PlayerDamageByEntityEvent> {
    
    public static final EventRegistry<PlayerDamageByEntityEvent> REGISTRY = new EventRegistry<>();
}

PlayerKillEntityEvent

Fired when a player kills an entity.
package kr.toxicity.hud.api.fabric.event.entity;

public record PlayerKillEntityEvent(
    @NotNull ServerPlayer player,
    @NotNull LivingEntity entity
) implements PlayerEvent<PlayerKillEntityEvent>, EntityEvent<PlayerKillEntityEvent> {
    
    public static final EventRegistry<PlayerKillEntityEvent> REGISTRY = new EventRegistry<>();
}

Triggers

HudFabricEventTrigger

Wraps Fabric events for use as HUD triggers.
package kr.toxicity.hud.api.fabric.trigger;

public interface HudFabricEventTrigger<T extends FabricEvent<?>> extends HudTrigger<T> {
    @NotNull EventRegistry<T> registry();
}
Usage:
import kr.toxicity.hud.api.fabric.trigger.HudFabricEventTrigger;
import kr.toxicity.hud.api.fabric.event.entity.PlayerKillEntityEvent;

// Create a custom trigger
HudFabricEventTrigger<PlayerKillEntityEvent> killTrigger = 
    new HudFabricEventTrigger<>() {
        @Override
        public @NotNull EventRegistry<PlayerKillEntityEvent> registry() {
            return PlayerKillEntityEvent.REGISTRY;
        }
        
        @Override
        public void invoke(@NotNull PlayerKillEntityEvent event) {
            HudPlayer player = BetterHudAPI.inst().getHudPlayer(event.player().getUUID());
            if (player != null) {
                player.showPopup("kill_notification");
            }
        }
    };

// Register the trigger
BetterHudAPI.inst().registerTrigger("entity_kill", killTrigger);

Complete Example

Here’s a complete Fabric mod using BetterHud:
import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.fabric.FabricBootstrap;
import kr.toxicity.hud.api.fabric.event.entity.*;
import kr.toxicity.hud.api.player.HudPlayer;
import net.fabricmc.api.ModInitializer;
import net.minecraft.server.level.ServerPlayer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyFabricHudMod implements ModInitializer {
    
    public static final Logger LOGGER = LoggerFactory.getLogger("myhudmod");
    
    @Override
    public void onInitialize() {
        LOGGER.info("Initializing My HUD Mod");
        
        // Register reload listeners
        FabricBootstrap.PRE_RELOAD_EVENT.register(unit -> {
            LOGGER.info("BetterHud is reloading...");
        });
        
        FabricBootstrap.POST_RELOAD_EVENT.register(state -> {
            if (state.success()) {
                LOGGER.info("BetterHud reload complete!");
            } else {
                LOGGER.error("BetterHud reload failed: " + state.message());
            }
        });
        
        // Register player death handler
        PlayerDeathEvent.REGISTRY.register(event -> {
            ServerPlayer player = event.player();
            HudPlayer hudPlayer = BetterHudAPI.inst().getHudPlayer(player.getUUID());
            
            if (hudPlayer != null) {
                hudPlayer.showPopup("death_screen");
                LOGGER.info(player.getName().getString() + " died");
            }
        });
        
        // Register attack handler
        PlayerAttackEntityEvent.REGISTRY.register(event -> {
            ServerPlayer player = event.player();
            HudPlayer hudPlayer = BetterHudAPI.inst().getHudPlayer(player.getUUID());
            
            if (hudPlayer != null) {
                // Show attack indicator
                hudPlayer.showPopup("attack_indicator");
            }
        });
        
        // Register kill handler
        PlayerKillEntityEvent.REGISTRY.register(event -> {
            ServerPlayer player = event.player();
            HudPlayer hudPlayer = BetterHudAPI.inst().getHudPlayer(player.getUUID());
            
            if (hudPlayer != null) {
                // Show kill notification
                hudPlayer.showPopup("kill_notification");
                LOGGER.info(player.getName().getString() + " killed an entity");
            }
        });
        
        LOGGER.info("My HUD Mod initialized successfully");
    }
}

fabric.mod.json

Don’t forget to declare BetterHud as a dependency:
{
  "schemaVersion": 1,
  "id": "myhudmod",
  "version": "1.0.0",
  "name": "My HUD Mod",
  "description": "Custom HUD integration with BetterHud",
  "authors": ["Your Name"],
  "contact": {},
  "license": "MIT",
  "environment": "server",
  "entrypoints": {
    "main": [
      "com.example.MyFabricHudMod"
    ]
  },
  "depends": {
    "fabricloader": ">=0.15.0",
    "fabric-api": "*",
    "minecraft": "1.21.11",
    "betterhud": "*"
  }
}

Platform Comparison

Advantages:
  • Direct Minecraft server integration
  • Custom event registry system
  • Mixin support for deep integration
  • Record-based event classes
  • Modern Java features
Best For:
  • Modded servers
  • Custom client-server communication
  • Advanced entity interactions
  • Performance-critical applications

Event Registry Pattern

Fabric uses a unique event registry pattern:
// 1. Define event as a record
public record MyCustomEvent(@NotNull ServerPlayer player, String data) 
    implements PlayerEvent<MyCustomEvent> {
    
    // 2. Create static registry
    public static final EventRegistry<MyCustomEvent> REGISTRY = new EventRegistry<>();
    
    // 3. Implement getRegistry()
    @Override
    public @NotNull EventRegistry<MyCustomEvent> getRegistry() {
        return REGISTRY;
    }
}

// 4. Register listeners
MyCustomEvent.REGISTRY.register(event -> {
    // Handle event
});

// 5. Fire event
MyCustomEvent event = new MyCustomEvent(player, "some data");
event.getRegistry().call(event);

See Also

Build docs developers (and LLMs) love