保险箱

保险箱

一个Hytale API,用于轻松集成其他插件的经济系统、聊天和权限管理

图书馆

Cassaforte

JitPack

概述

Cassaforte 为 Hytale 插件提供了一个简洁的抽象层,灵感来自 Bukkit 的 VaultAPI。它允许插件通过统一接口与经济、权限和聊天系统交互,而无需关心底层实现。

使用 Cassaforte 的插件

功能特性

  • 服务注册表:集中注册和获取服务实现
  • 经济 API:余额管理、存款、取款和银行支持
  • 权限 API:玩家和群组权限管理
  • 聊天 API:前缀/后缀格式化和玩家/群组信息节点
  • 基于 UUID 的识别:完整支持离线玩家
  • 线程安全:原子操作确保可靠的并发访问
  • 零依赖:纯 Java 实现,无运行时依赖
  • 先注册优先策略:仅第一次注册成功,防止意外覆盖

安装

在 Gradle 项目中添加 Cassaforte 作为依赖:

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

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

架构

Cassaforte 采用服务注册模式,插件实现者注册自身,消费插件透明获取这些实现。

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

使用方法

服务实现者

如果您正在创建经济、权限或聊天插件,请实现接口并向 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() {
        // 向 Cassaforte 注册此经济实现
        boolean registered = Cassaforte.registerEconomy(this);
        if (!registered) {
            getLogger().warning("已有其他经济实现被注册!");
            return;
        }
        getLogger().info("经济实现注册成功!");
    }

    @Override
    protected void shutdown() {
        // 如有需要,清理资源
    }

    // 实现必要的经济方法
    @Override
    public EconomyResponse depositPlayer(UUID playerId, double amount) {
        // 您的实现
        return new EconomyResponse(amount, newBalance, EconomyResponse.ResponseType.SUCCESS);
    }

    @Override
    public double getBalance(UUID playerId) {
        // 您的实现
        return 0.0;
    }

    // ... 实现其他必要方法
}

服务消费者

如果您在插件中使用经济、权限或聊天服务,请通过 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() {
        // 获取已注册的服务
        economy = Cassaforte.getEconomy();
        permission = Cassaforte.getPermission();
        chat = Cassaforte.getChat();

        // 检查服务是否可用
        if (economy != null && economy.isEnabled()) {
            getLogger().info("经济服务可用:" + economy.getName());
        } else {
            getLogger().warning("没有可用的经济服务");
        }

        if (permission != null && permission.isEnabled()) {
            getLogger().info("权限服务可用:" + permission.getName());
        } else {
            getLogger().warning("没有可用的权限服务");
        }

        if (chat != null) {
            getLogger().info("聊天服务可用");
        }
    }

    public void giveMoney(UUID playerId, double amount) {
        if (economy != null && economy.isEnabled()) {
            var response = economy.depositPlayer(playerId, amount);
            if (response.transactionSuccess()) {
                getLogger().info("已向玩家存入 " + amount + " 单位货币");
            }
        } else {
            getLogger().warning("无法存入:经济服务不可用");
        }
    }

    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;
    }
}

使用 Hytale 插件管理器

您也可以通过 Hytale 插件管理器直接获取 Cassaforte:

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() {
        // 方法 1:直接静态访问(推荐)
        Economy economy = Cassaforte.getEconomy();
        if (economy != null) {
            getLogger().info("经济:" + economy.getName());
        }

        // 方法 2:通过 PluginManager 获取插件实例
        PluginManager pm = PluginManager.get();
        PluginIdentifier cassaforteId = new PluginIdentifier("it.cassaforte", "Cassaforte");

        if (pm.hasPlugin(cassaforteId)) {
            getLogger().info("Cassaforte 插件已加载");
            // 服务通过 Cassaforte 静态方法访问
            Economy economy2 = Cassaforte.getEconomy();
            Permission permission = Cassaforte.getPermission();
            Chat chat = Cassaforte.getChat();
        }
    }
}

API 参考

Cassaforte 注册表

it.cassaforte.api.Cassaforte 类提供了服务注册和获取的静态方法。

注册方法

// 注册经济实现(如果已注册则返回 false)
boolean success = Cassaforte.registerEconomy(Economy economy);

// 注册权限实现
boolean success = Cassaforte.registerPermission(Permission permission);

// 注册聊天实现
boolean success = Cassaforte.registerChat(Chat chat);

获取方法

// 获取已注册的经济服务(未注册时返回 null)
Economy economy = Cassaforte.getEconomy();

// 获取已注册的权限服务(未注册时返回 null)
Permission permission = Cassaforte.getPermission();

// 获取已注册的聊天服务(未注册时返回 null)
Chat chat = Cassaforte.getChat();

经济 API

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

// 检查玩家是否有账户
boolean hasAccount = economy.hasAccount(playerId);

// 获取玩家余额
double balance = economy.getBalance(playerId);

// 存款
EconomyResponse response = economy.depositPlayer(playerId, 100.0);
if (response.transactionSuccess()) {
    // 成功 - 新余额:response.balance
}

// 取款
EconomyResponse response = economy.withdrawPlayer(playerId, 50.0);

// 检查玩家是否足够余额
boolean canAfford = economy.has(playerId, 75.0);

// 银行操作(如果支持)
if (economy.hasBankSupport()) {
    economy.createBank("MyBank", playerId);
    double bankBalance = economy.bankBalance("MyBank");
}

// 格式化货币
String formatted = economy.format(1000.50); // "$1,000.50"

权限 API

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

// 玩家权限
boolean hasPerm = permission.playerHas(playerId, "essentials.tp");
permission.playerAdd(playerId, "essentials.tp");
permission.playerRemove(playerId, "essentials.tp");

// 群组权限
boolean groupHas = permission.groupHas("admin", "essentials.*");
permission.groupAdd("admin", "essentials.*");
permission.groupRemove("admin", "essentials.*");

// 群组成员资格
boolean inGroup = permission.playerInGroup(playerId, "vip");
permission.playerAddGroup(playerId, "vip");
permission.playerRemoveGroup(playerId, "vip");

// 获取玩家所属群组
List<String> groups = permission.getPlayerGroups(playerId);
String primaryGroup = permission.getPrimaryGroup(playerId);

聊天 API

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

// 玩家前缀/后缀
String prefix = chat.getPlayerPrefix(playerId, "");
String suffix = chat.getPlayerSuffix(playerId, "");
chat.setPlayerPrefix(playerId, "[Admin] ");
chat.setPlayerSuffix(playerId, " *");

// 群组前缀/后缀
String groupPrefix = chat.getGroupPrefix("vip", "");
chat.setGroupPrefix("vip", "[VIP] ");

// 信息节点(元数据存储)
chat.setPlayerInfoString(playerId, "nickname", "Player1");
String nickname = chat.getPlayerInfoString(playerId, "nickname", "");

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

项目结构

it.cassaforte.api/
├── Cassaforte.java               # 中央服务注册表
├── economy/
│   ├── Economy.java              # 主要经济接口
│   ├── AbstractEconomy.java      # 带默认值的基类实现
│   └── EconomyResponse.java      # 操作响应包装器
├── permission/
│   └── Permission.java           # 权限和群组管理
└── chat/
    └── Chat.java                 # 聊天格式和元数据

线程安全

所有 Cassaforte 注册方法都是线程安全的。注册使用原子比较并交换操作,确保只有第一次注册成功。获取操作是无锁的,可从任何线程安全调用。

最佳实践

  1. 尽早注册:始终在 setup()start() 中注册您的服务,确保在其他插件需要之前可用
  2. 处理空值返回:获取服务时始终检查空值——它们可能未被注册
  3. 检查 isEnabled():在使用经济或权限服务前验证 isEnabled()
  4. 使用静态访问器:在插件中提供静态 getInstance() 方法,方便其他插件访问
  5. 优雅降级:即使可选服务不可用,您的插件也应正常工作

构建

./gradlew build

构建产出:

  • jar - 包含依赖的标准 JAR
  • shadowJar - 包含遮蔽依赖的胖 JAR(Gson 已重定位)

要求

  • Java 21+
  • Gradle 9.0+
  • Hytale 服务器 API(仅编译时)

许可证

MIT

贡献

欢迎贡献!请随时提交拉取请求。

灵感来源

本项目灵感来源于 Bukkit/Minecraft 平台的 VaultAPI,并根据 Hytale 平台进行了适配。