Example Repository
For a complete working example, see the BetterHud-MMOCore integration plugin.Build Configuration
Gradle (Kotlin DSL)
build.gradle.kts
plugins {
kotlin("jvm") version "2.1.0"
id("com.github.johnrengelman.shadow") version "8.1.1"
}
repositories {
mavenCentral()
maven("https://repo.papermc.io/repository/maven-public/")
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT")
compileOnly("io.github.toxicity188:BetterHud-standard-api:VERSION")
compileOnly("io.github.toxicity188:BetterHud-bukkit-api:VERSION")
compileOnly("io.github.toxicity188:BetterCommand:VERSION")
}
tasks {
shadowJar {
archiveClassifier.set("")
}
}
Gradle (Groovy)
build.gradle
plugins {
id 'java'
id 'com.github.johnrengelman.shadow' version '8.1.1'
}
repositories {
mavenCentral()
maven { url 'https://repo.papermc.io/repository/maven-public/' }
}
dependencies {
compileOnly 'io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT'
compileOnly 'io.github.toxicity188:BetterHud-standard-api:VERSION'
compileOnly 'io.github.toxicity188:BetterHud-bukkit-api:VERSION'
compileOnly 'io.github.toxicity188:BetterCommand:VERSION'
}
Maven
pom.xml
<repositories>
<repository>
<id>papermc</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.21.4-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.github.toxicity188</groupId>
<artifactId>BetterHud-standard-api</artifactId>
<version>VERSION</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.github.toxicity188</groupId>
<artifactId>BetterHud-bukkit-api</artifactId>
<version>VERSION</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.github.toxicity188</groupId>
<artifactId>BetterCommand</artifactId>
<version>VERSION</version>
<scope>provided</scope>
</dependency>
</dependencies>
Plugin Setup
Main Plugin Class
BetterHudExample.java
package com.example.betterhudexample;
import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.bukkit.BukkitBootstrap;
import kr.toxicity.hud.api.manager.PlaceholderManager;
import kr.toxicity.hud.api.manager.TriggerManager;
import kr.toxicity.hud.api.player.HudPlayer;
import kr.toxicity.hud.api.placeholder.HudPlaceholder;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.util.logging.Level;
public final class BetterHudExample extends JavaPlugin {
private static BetterHudExample instance;
@Override
public void onEnable() {
instance = this;
// Check if BetterHud is loaded
if (!getServer().getPluginManager().isPluginEnabled("BetterHud")) {
getLogger().severe("BetterHud is not installed!");
getServer().getPluginManager().disablePlugin(this);
return;
}
try {
// Register custom placeholders
registerPlaceholders();
// Register custom triggers
registerTriggers();
// Register event listeners
getServer().getPluginManager().registerEvents(
new PlayerListener(),
this
);
getLogger().info("BetterHud integration enabled!");
} catch (Exception e) {
getLogger().log(Level.SEVERE, "Failed to initialize BetterHud integration", e);
getServer().getPluginManager().disablePlugin(this);
}
}
@Override
public void onDisable() {
getLogger().info("BetterHud integration disabled!");
}
private void registerPlaceholders() {
PlaceholderManager manager = BetterHudAPI.inst().getPlaceholderManager();
// Register a number placeholder
HudPlaceholder.<Number>builder()
.function((args, event) -> player -> {
// Return player's level
return ((org.bukkit.entity.Player) player.handle()).getLevel();
})
.build()
.add("player_level", manager.getNumberContainer());
// Register a string placeholder
HudPlaceholder.<String>builder()
.function((args, event) -> player -> {
org.bukkit.entity.Player bukkitPlayer =
(org.bukkit.entity.Player) player.handle();
return bukkitPlayer.getWorld().getName();
})
.build()
.add("player_world", manager.getStringContainer());
// Register a boolean placeholder
HudPlaceholder.<Boolean>builder()
.function((args, event) -> player -> {
org.bukkit.entity.Player bukkitPlayer =
(org.bukkit.entity.Player) player.handle();
return bukkitPlayer.isFlying();
})
.build()
.add("is_flying", manager.getBooleanContainer());
}
private void registerTriggers() {
TriggerManager manager = BetterHudAPI.inst().getTriggerManager();
BukkitBootstrap bootstrap = (BukkitBootstrap) BetterHudAPI.inst().getBootstrap();
// Register custom event triggers
// See PlayerListener class for event handling
}
public static BetterHudExample getInstance() {
return instance;
}
}
plugin.yml
plugin.yml
name: BetterHudExample
version: 1.0.0
main: com.example.betterhudexample.BetterHudExample
api-version: 1.21
depend: [BetterHud]
authors: [YourName]
description: Example BetterHud integration plugin
Working with Players
Getting HudPlayer Instance
import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.manager.PlayerManager;
import kr.toxicity.hud.api.player.HudPlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
public class PlayerHelper {
@Nullable
public static HudPlayer getHudPlayer(Player player) {
PlayerManager manager = BetterHudAPI.inst().getPlayerManager();
return manager.getHudPlayer(player.getUniqueId());
}
public static void disableHud(Player player) {
HudPlayer hudPlayer = getHudPlayer(player);
if (hudPlayer != null) {
hudPlayer.setHudEnabled(false);
}
}
public static void enableHud(Player player) {
HudPlayer hudPlayer = getHudPlayer(player);
if (hudPlayer != null) {
hudPlayer.setHudEnabled(true);
}
}
}
Custom Placeholders
Advanced Placeholder with Arguments
import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.placeholder.HudPlaceholder;
public class CustomPlaceholders {
public static void register() {
var manager = BetterHudAPI.inst().getPlaceholderManager();
// Placeholder with required arguments: <custom_stat_maxHealth>
HudPlaceholder.<Number>builder()
.requiredArgsLength(1) // Require 1 argument
.function((args, event) -> {
String statName = args.get(0); // Get the argument
return player -> {
org.bukkit.entity.Player p =
(org.bukkit.entity.Player) player.handle();
// Return different values based on stat name
return switch (statName.toLowerCase()) {
case "maxhealth" -> p.getMaxHealth();
case "health" -> p.getHealth();
case "food" -> (double) p.getFoodLevel();
default -> 0.0;
};
};
})
.build()
.add("custom_stat", manager.getNumberContainer());
// Placeholder using update event context
HudPlaceholder.<String>builder()
.function((args, event) -> player -> {
// Access event data from UpdateEvent
var variables = event.getVariableMap();
return variables.getOrDefault("custom_data", "default");
})
.build()
.add("event_data", manager.getStringContainer());
}
}
Event Listeners
Custom Popup Events
PlayerListener.java
package com.example.betterhudexample;
import kr.toxicity.hud.api.bukkit.event.CustomPopupEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLevelChangeEvent;
public class PlayerListener implements Listener {
@EventHandler
public void onLevelUp(PlayerLevelChangeEvent event) {
int oldLevel = event.getOldLevel();
int newLevel = event.getNewLevel();
if (newLevel > oldLevel) {
// Create custom popup event
CustomPopupEvent popupEvent = new CustomPopupEvent(
event.getPlayer(),
"level_up_popup" // Must match popup name in BetterHud config
);
// Add custom variables for the popup
popupEvent.getVariables().put("old_level", String.valueOf(oldLevel));
popupEvent.getVariables().put("new_level", String.valueOf(newLevel));
popupEvent.getVariables().put("gained", String.valueOf(newLevel - oldLevel));
// Call the event
event.getPlayer().getServer().getPluginManager().callEvent(popupEvent);
}
}
}
Showing Popups Programmatically
import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.manager.PopupManager;
import kr.toxicity.hud.api.player.HudPlayer;
import kr.toxicity.hud.api.popup.Popup;
import kr.toxicity.hud.api.update.UpdateEvent;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.Map;
public class PopupHelper {
public static void showPopup(Player player, String popupName, Map<String, String> variables) {
PlayerManager playerManager = BetterHudAPI.inst().getPlayerManager();
HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
if (hudPlayer == null) {
return; // Player not loaded
}
PopupManager popupManager = BetterHudAPI.inst().getPopupManager();
Popup popup = popupManager.getPopup(popupName);
if (popup == null) {
player.sendMessage("Popup '" + popupName + "' not found!");
return;
}
// Create update event with variables
UpdateEvent event = UpdateEvent.builder()
.variables(variables != null ? variables : new HashMap<>())
.build();
// Show the popup
try {
popup.show(hudPlayer, event);
} catch (Exception e) {
e.printStackTrace();
}
}
// Example usage
public static void showDamagePopup(Player player, double damage) {
Map<String, String> vars = new HashMap<>();
vars.put("damage", String.format("%.1f", damage));
vars.put("damage_type", "physical");
showPopup(player, "damage_indicator", vars);
}
}
Compass Points
import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.adapter.LocationWrapper;
import kr.toxicity.hud.api.player.HudPlayer;
import kr.toxicity.hud.api.player.PointedLocation;
import kr.toxicity.hud.api.player.PointedLocationProvider;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public class CompassHelper {
// Add a compass point for a specific player
public static void addCompassPoint(Player player, Location location, String name, String icon) {
PlayerManager manager = BetterHudAPI.inst().getPlayerManager();
HudPlayer hudPlayer = manager.getHudPlayer(player.getUniqueId());
if (hudPlayer != null) {
// Convert Bukkit Location to LocationWrapper
LocationWrapper wrapper = LocationWrapper.of(
location.getWorld().getName(),
location.getX(),
location.getY(),
location.getZ()
);
PointedLocation pointedLocation = PointedLocation.builder()
.location(wrapper)
.name(name)
.icon(icon)
.build();
hudPlayer.pointers().add(pointedLocation);
}
}
// Remove compass point by name
public static void removeCompassPoint(Player player, String name) {
PlayerManager manager = BetterHudAPI.inst().getPlayerManager();
HudPlayer hudPlayer = manager.getHudPlayer(player.getUniqueId());
if (hudPlayer != null) {
hudPlayer.pointers().removeIf(p -> p.getName().equals(name));
}
}
// Add global compass points for all players
public static void registerGlobalLocationProvider() {
PlayerManager manager = BetterHudAPI.inst().getPlayerManager();
manager.addLocationProvider(new PointedLocationProvider() {
@Override
public Set<PointedLocation> provide(HudPlayer player) {
// Return a set of locations for this player
Set<PointedLocation> locations = new HashSet<>();
// Example: Add spawn point
Player bukkitPlayer = (Player) player.handle();
Location spawn = bukkitPlayer.getWorld().getSpawnLocation();
locations.add(PointedLocation.builder()
.location(LocationWrapper.of(
spawn.getWorld().getName(),
spawn.getX(),
spawn.getY(),
spawn.getZ()
))
.name("Spawn")
.icon("spawn")
.build());
return locations;
}
});
}
}
Error Handling
import kr.toxicity.hud.api.BetterHudAPI;
import org.bukkit.entity.Player;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SafeHudOperations {
private static final Logger LOGGER = Logger.getLogger("BetterHudExample");
public static void safeShowPopup(Player player, String popupName) {
try {
var playerManager = BetterHudAPI.inst().getPlayerManager();
var hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
if (hudPlayer == null) {
LOGGER.warning("HudPlayer not found for " + player.getName());
return;
}
var popupManager = BetterHudAPI.inst().getPopupManager();
var popup = popupManager.getPopup(popupName);
if (popup == null) {
LOGGER.warning("Popup '" + popupName + "' not found!");
return;
}
popup.show(hudPlayer, UpdateEvent.builder().build());
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Failed to show popup to " + player.getName(), e);
}
}
}
Next Steps
Custom HUD
Learn how to create custom HUD elements
Custom Popup
Create dynamic popup notifications
Bukkit API Reference
Complete Bukkit API documentation
Standard API
Core API reference
