Skip to main content
The Velocity API provides platform-specific integration for BetterHud on Velocity proxy servers.

Installation

repositories {
    mavenCentral()
}

dependencies {
    compileOnly("io.github.toxicity188:BetterHud-standard-api:VERSION")
    compileOnly("io.github.toxicity188:BetterHud-velocity-api:VERSION")
    compileOnly("io.github.toxicity188:BetterCommand:VERSION")
}
Check Maven Central for the latest version.

Platform Support

BetterHud supports Velocity versions:
  • Velocity 3.3.x
  • Velocity 3.4.x
Velocity is a proxy server and has limited HUD capabilities compared to Bukkit or Fabric. BetterHud on Velocity primarily handles player data synchronization across backend servers.

Core Classes

VelocityBootstrap

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

public interface VelocityBootstrap extends BetterHudBootstrap {
    @Override
    default boolean isFolia() {
        return false;
    }
    
    @Override
    default boolean isPaper() {
        return false;
    }
    
    @Override
    default boolean isVelocity() {
        return true;
    }
    
    @Override
    default boolean isFabric() {
        return false;
    }
}
Platform Detection:
import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.velocity.VelocityBootstrap;

public class MyVelocityPlugin {
    public void onEnable() {
        if (BetterHudAPI.inst().bootstrap() instanceof VelocityBootstrap velocity) {
            // Running on Velocity
            logger.info("BetterHud running on Velocity proxy");
        }
    }
}

Usage Patterns

Basic Plugin Integration

Here’s how to integrate BetterHud into a Velocity plugin:
import com.google.inject.Inject;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.ProxyServer;
import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.velocity.VelocityBootstrap;
import org.slf4j.Logger;

import java.nio.file.Path;

@Plugin(
    id = "myhudplugin",
    name = "My HUD Plugin",
    version = "1.0.0",
    dependencies = {@Dependency(id = "betterhud")}
)
public class MyVelocityHudPlugin {
    
    private final ProxyServer server;
    private final Logger logger;
    private final Path dataDirectory;
    
    @Inject
    public MyVelocityHudPlugin(ProxyServer server, Logger logger, 
                               @DataDirectory Path dataDirectory) {
        this.server = server;
        this.logger = logger;
        this.dataDirectory = dataDirectory;
    }
    
    @Subscribe
    public void onProxyInitialization(ProxyInitializeEvent event) {
        // Access BetterHud API
        VelocityBootstrap bootstrap = (VelocityBootstrap) BetterHudAPI.inst().bootstrap();
        
        logger.info("Initializing with BetterHud on Velocity");
        logger.info("Is Velocity: " + bootstrap.isVelocity());
    }
}

Player Data Management

Since Velocity is a proxy, player HUD data is managed differently:
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.PostLoginEvent;
import com.velocitypowered.api.event.connection.DisconnectEvent;
import com.velocitypowered.api.proxy.Player;
import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.player.HudPlayer;

public class VelocityPlayerHandler {
    
    @Subscribe
    public void onPlayerJoin(PostLoginEvent event) {
        Player player = event.getPlayer();
        
        // Get HUD player data
        HudPlayer hudPlayer = BetterHudAPI.inst().getHudPlayer(player.getUniqueId());
        if (hudPlayer != null) {
            logger.info("HUD data loaded for " + player.getUsername());
        }
    }
    
    @Subscribe
    public void onPlayerQuit(DisconnectEvent event) {
        Player player = event.getPlayer();
        
        // HUD data is automatically cleaned up
        logger.info("Player " + player.getUsername() + " disconnected");
    }
}

Platform Comparison

Velocity has different capabilities compared to backend server platforms:
Capabilities:
  • Cross-server player data synchronization
  • Proxy-level HUD management
  • Limited event system
Limitations:
  • No direct world/entity access
  • Cannot render HUD elements directly
  • Requires backend servers for full functionality
Use Cases:
  • Multi-server networks
  • Global HUD state management
  • Player data persistence across servers

Network Architecture

When using BetterHud on Velocity in a multi-server network:
┌─────────────┐
│   Velocity  │ ← BetterHud Velocity API
│    Proxy    │   (Player data sync)
└──────┬──────┘

       ├───────────┬───────────┐
       │           │           │
   ┌───▼───┐   ┌──▼────┐  ┌──▼────┐
   │Lobby  │   │Survival│  │Minigames│
   │Server │   │ Server │  │ Server  │
   └───────┘   └────────┘  └────────┘
   BetterHud   BetterHud   BetterHud
   (Bukkit)    (Bukkit)    (Bukkit)
Data Flow:
  1. Player connects to Velocity proxy
  2. Velocity loads global HUD profile
  3. Player switches to backend server (e.g., Lobby)
  4. Backend server receives HUD data from Velocity
  5. Server-specific HUD elements are applied

Configuration

Velocity-specific configuration considerations:
# velocity.toml (Velocity proxy config)
[betterhud]
# Sync player HUD data across backend servers
sync-player-data = true

# Cache duration for player data (in seconds)
data-cache-duration = 300

# Enable debug logging
debug = false

Complete Example

A complete Velocity plugin using BetterHud:
import com.google.inject.Inject;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.PostLoginEvent;
import com.velocitypowered.api.event.connection.DisconnectEvent;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.ProxyServer;
import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.player.HudPlayer;
import kr.toxicity.hud.api.velocity.VelocityBootstrap;
import org.slf4j.Logger;

import java.nio.file.Path;

@Plugin(
    id = "networkhuds",
    name = "Network HUDs",
    version = "1.0.0",
    dependencies = {@Dependency(id = "betterhud")}
)
public class NetworkHudPlugin {
    
    private final ProxyServer server;
    private final Logger logger;
    
    @Inject
    public NetworkHudPlugin(ProxyServer server, Logger logger) {
        this.server = server;
        this.logger = logger;
    }
    
    @Subscribe
    public void onProxyInitialization(ProxyInitializeEvent event) {
        VelocityBootstrap bootstrap = (VelocityBootstrap) BetterHudAPI.inst().bootstrap();
        logger.info("Network HUD Plugin enabled on Velocity");
    }
    
    @Subscribe
    public void onPlayerJoin(PostLoginEvent event) {
        var player = event.getPlayer();
        
        // Load or create HUD player data
        HudPlayer hudPlayer = BetterHudAPI.inst().getHudPlayer(player.getUniqueId());
        
        if (hudPlayer != null) {
            logger.info("Loaded HUD data for " + player.getUsername());
        } else {
            logger.warn("Failed to load HUD data for " + player.getUsername());
        }
    }
    
    @Subscribe
    public void onPlayerDisconnect(DisconnectEvent event) {
        var player = event.getPlayer();
        logger.info("Cleaning up HUD data for " + player.getUsername());
    }
}

See Also

Build docs developers (and LLMs) love