promotional bannermobile promotional banner

Cassaforte

An Hytale API to easily integrate other plugins economies, chats and permissions

Cassaforte

Overview

Cassaforte offers a clean abstraction layer for Hytale plugins, inspired by VaultAPI for Bukkit. It allows plugins to interact with economy, permission, and chat systems through a unified interface, regardless of the underlying implementation.

Plugins using Cassaforte

Features

  • Service Registry: Centralized registration and retrieval of service implementations
  • Economy API: Balance management, deposits, withdrawals, and bank support
  • Permission API: Player and group permission management
  • Chat API: Prefix/suffix formatting and player/group info nodes
  • UUID-based identification: Full offline player support
  • Thread-safe: Atomic operations for reliable concurrent access
  • Zero dependencies: Pure Java with no runtime dependencies
  • First-wins policy: Only first registration succeeds, preventing accidental overwrites

Installation

Add Cassaforte as a dependency in your Gradle project:

dependencyResolutionManagement {
        repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
        repositories {
            mavenCentral()
            maven { url 'https://jitpack.io' }
        }
    }

dependencies {
    compileOnly("it.cassaforte:api:v0.1.2")
}

Architecture

Cassaforte uses a service registry pattern where plugin implementations register themselves, and consumer plugins retrieve these implementations transparently.

┌─────────────────────────────────────────────────────────────┐
│                      Cassaforte API                         │
│                                                              │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │   Economy    │  │  Permission  │  │     Chat     │      │
│  │   Interface  │  │   Interface  │  │   Interface  │      │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘      │
│         │                 │                 │                │
│         └─────────────────┴─────────────────┘                │
│                           │                                  │
│                   ┌───────┴────────┐                         │
│                   │ Cassaforte     │                         │
│                   │ Service Registry│                        │
│                   └────────────────┘                         │
└─────────────────────────────────────────────────────────────┘
                            │
          ┌─────────────────┴─────────────────┐
          │                                   │
┌─────────────────────┐           ┌─────────────────────┐
│  Economy Plugin     │           │  Consumer Plugin    │
│  (Registers impl)   │           │  (Retrieves impl)   │
└─────────────────────┘           └─────────────────────┘

Usage

For Service Implementers

If you're creating an economy, permission, or chat plugin, implement the interface and register it with Cassaforte:

import com.hypixel.hytale.server.core.plugin.JavaPlugin;
import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
import it.cassaforte.api.Cassaforte;
import it.cassaforte.api.economy.AbstractEconomy;
import it.cassaforte.api.economy.EconomyResponse;
import javax.annotation.Nonnull;
import java.util.UUID;

public class MyEconomyPlugin extends AbstractEconomy {
    private static MyEconomyPlugin instance;

    public MyEconomyPlugin(@Nonnull JavaPluginInit init) {
        super(init);
        instance = this;
    }

    public static MyEconomyPlugin get() {
        return instance;
    }

    @Override
    protected void setup() {
        // Register this economy implementation with Cassaforte
        boolean registered = Cassaforte.registerEconomy(this);
        if (!registered) {
            getLogger().warning("Another economy is already registered!");
            return;
        }
        getLogger().info("Economy registered successfully!");
    }

    @Override
    protected void shutdown() {
        // Clean up resources if needed
    }

    // Implement required economy methods
    @Override
    public EconomyResponse depositPlayer(UUID playerId, double amount) {
        // Your implementation
        return new EconomyResponse(amount, newBalance, EconomyResponse.ResponseType.SUCCESS);
    }

    @Override
    public double getBalance(UUID playerId) {
        // Your implementation
        return 0.0;
    }

    // ... implement other required methods
}

For Service Consumers

If you're using an economy, permission, or chat service in your plugin, retrieve the registered implementation through Cassaforte:

import com.hypixel.hytale.server.core.plugin.JavaPlugin;
import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
import it.cassaforte.api.Cassaforte;
import it.cassaforte.api.economy.Economy;
import it.cassaforte.api.permission.Permission;
import it.cassaforte.api.chat.Chat;
import javax.annotation.Nonnull;

public class MyPlugin extends JavaPlugin {
    private Economy economy;
    private Permission permission;
    private Chat chat;

    public MyPlugin(@Nonnull JavaPluginInit init) {
        super(init);
    }

    @Override
    protected void setup() {
        // Retrieve registered services
        economy = Cassaforte.getEconomy();
        permission = Cassaforte.getPermission();
        chat = Cassaforte.getChat();

        // Check if services are available
        if (economy != null && economy.isEnabled()) {
            getLogger().info("Economy service available: " + economy.getName());
        } else {
            getLogger().warning("No economy service available");
        }

        if (permission != null && permission.isEnabled()) {
            getLogger().info("Permission service available: " + permission.getName());
        } else {
            getLogger().warning("No permission service available");
        }

        if (chat != null) {
            getLogger().info("Chat service available");
        }
    }

    public void giveMoney(UUID playerId, double amount) {
        if (economy != null && economy.isEnabled()) {
            var response = economy.depositPlayer(playerId, amount);
            if (response.transactionSuccess()) {
                getLogger().info("Deposited " + amount + " to player");
            }
        } else {
            getLogger().warning("Cannot deposit: Economy not available");
        }
    }

    public boolean checkPermission(UUID playerId, String node) {
        if (permission != null && permission.isEnabled()) {
            return permission.playerHas(playerId, node);
        }
        return false;
    }

    public String formatPlayerName(UUID playerId, String playerName) {
        if (chat != null) {
            String prefix = chat.getPlayerPrefix(playerId, "");
            String suffix = chat.getPlayerSuffix(playerId, "");
            return prefix + playerName + suffix;
        }
        return playerName;
    }
}

Using Hytale Plugin Manager

You can also retrieve Cassaforte directly through the Hytale Plugin Manager:

import com.hypixel.hytale.server.core.plugin.PluginManager;
import com.hypixel.hytale.common.plugin.PluginIdentifier;
import it.cassaforte.api.Cassaforte;

public class MyPlugin extends JavaPlugin {

    @Override
    protected void setup() {
        // Method 1: Direct static access (recommended)
        Economy economy = Cassaforte.getEconomy();
        if (economy != null) {
            getLogger().info("Economy: " + economy.getName());
        }

        // Method 2: Access via PluginManager to get the plugin instance
        PluginManager pm = PluginManager.get();
        PluginIdentifier cassaforteId = new PluginIdentifier("it.cassaforte", "Cassaforte");

        if (pm.hasPlugin(cassaforteId)) {
            getLogger().info("Cassaforte plugin is loaded");
            // Services are accessed through Cassaforte static methods
            Economy economy2 = Cassaforte.getEconomy();
            Permission permission = Cassaforte.getPermission();
            Chat chat = Cassaforte.getChat();
        }
    }
}

API Reference

Cassaforte Registry

The it.cassaforte.api.Cassaforte class provides static methods for service registration and retrieval.

Registration Methods

// Register an economy implementation (returns false if already registered)
boolean success = Cassaforte.registerEconomy(Economy economy);

// Register a permission implementation
boolean success = Cassaforte.registerPermission(Permission permission);

// Register a chat implementation
boolean success = Cassaforte.registerChat(Chat chat);

Retrieval Methods

// Get registered economy (null if none registered)
Economy economy = Cassaforte.getEconomy();

// Get registered permission (null if none registered)
Permission permission = Cassaforte.getPermission();

// Get registered chat (null if none registered)
Chat chat = Cassaforte.getChat();

Economy API

import it.cassaforte.api.economy.Economy;
import it.cassaforte.api.economy.EconomyResponse;
import java.util.UUID;

// Check if player has an account
boolean hasAccount = economy.hasAccount(playerId);

// Get player balance
double balance = economy.getBalance(playerId);

// Deposit money
EconomyResponse response = economy.depositPlayer(playerId, 100.0);
if (response.transactionSuccess()) {
    // Success - new balance: response.balance
}

// Withdraw money
EconomyResponse response = economy.withdrawPlayer(playerId, 50.0);

// Check if player can afford
boolean canAfford = economy.has(playerId, 75.0);

// Bank operations (if supported)
if (economy.hasBankSupport()) {
    economy.createBank("MyBank", playerId);
    double bankBalance = economy.bankBalance("MyBank");
}

// Format currency
String formatted = economy.format(1000.50); // "$1,000.50"

Permission API

import it.cassaforte.api.permission.Permission;
import java.util.UUID;

// Player permissions
boolean hasPerm = permission.playerHas(playerId, "essentials.tp");
permission.playerAdd(playerId, "essentials.tp");
permission.playerRemove(playerId, "essentials.tp");

// Group permissions
boolean groupHas = permission.groupHas("admin", "essentials.*");
permission.groupAdd("admin", "essentials.*");
permission.groupRemove("admin", "essentials.*");

// Group membership
boolean inGroup = permission.playerInGroup(playerId, "vip");
permission.playerAddGroup(playerId, "vip");
permission.playerRemoveGroup(playerId, "vip");

// Get player's groups
List<String> groups = permission.getPlayerGroups(playerId);
String primaryGroup = permission.getPrimaryGroup(playerId);

Chat API

import it.cassaforte.api.chat.Chat;
import java.util.UUID;

// Player prefix/suffix
String prefix = chat.getPlayerPrefix(playerId, "");
String suffix = chat.getPlayerSuffix(playerId, "");
chat.setPlayerPrefix(playerId, "[Admin] ");
chat.setPlayerSuffix(playerId, " *");

// Group prefix/suffix
String groupPrefix = chat.getGroupPrefix("vip", "");
chat.setGroupPrefix("vip", "[VIP] ");

// Info nodes (metadata storage)
chat.setPlayerInfoString(playerId, "nickname", "Player1");
String nickname = chat.getPlayerInfoString(playerId, "nickname", "");

chat.setPlayerInfoInteger(playerId, "kills", 100);
int kills = chat.getPlayerInfoInteger(playerId, "kills", 0);

Project Structure

it.cassaforte.api/
├── Cassaforte.java               # Central service registry
├── economy/
│   ├── Economy.java              # Main economy interface
│   ├── AbstractEconomy.java      # Base implementation with defaults
│   └── EconomyResponse.java      # Operation response wrapper
├── permission/
│   └── Permission.java           # Permission and group management
└── chat/
    └── Chat.java                 # Chat formatting and metadata

Thread Safety

All Cassaforte registry methods are thread-safe. Registration uses atomic compare-and-set operations to ensure that only the first registration succeeds. Retrieval operations are lock-free and safe to call from any thread.

Best Practices

  1. Register Early: Always register your service in setup() or start() to ensure it's available before other plugins need it
  2. Handle Null Returns: Always check for null when retrieving services - they may not be registered
  3. Check isEnabled(): Verify isEnabled() before using economy or permission services
  4. Use Static Accessors: Provide a static getInstance() method in your plugin for easy access by other plugins
  5. Graceful Degradation: Your plugin should work even when optional services are unavailable

Building

./gradlew build

The build produces:

  • jar - Standard JAR with dependencies
  • shadowJar - Fat JAR with shaded dependencies (Gson relocated)

Requirements

  • Java 21+
  • Gradle 9.0+
  • Hytale Server API (compile-only)

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Inspired By

This project is inspired by VaultAPI for Bukkit/Minecraft, adapted for the Hytale platform.

The Cassaforte Team

profile avatar
Owner
  • 4
    Followers
  • 2
    Projects
  • 1.7K
    Downloads

More from Cava99

  • Towny3D project image

    Towny3D

    • 1.1K
    • Mods

    A high-performance 3D land protection plugin for Hytale servers. Features town/nation management, plot claims, PvP control, and advanced permission systems with Kotlin coroutines and spatial indexing.

    • 1.1K
    • March 22, 2026
    • Mods
    • +4
  • Towny3D project image

    Towny3D

    • 1.1K
    • Mods

    A high-performance 3D land protection plugin for Hytale servers. Features town/nation management, plot claims, PvP control, and advanced permission systems with Kotlin coroutines and spatial indexing.

    • 1.1K
    • March 22, 2026
    • Mods
    • +4