
CannaTaleEconomy
服务器范围内的经济核心(SQLite)。
CannaTaleEconomy
CannaTaleEconomy 是 CannaTale Hytale 服务器生态系统的经济核心。它提供基于 SQLite 的持久化余额系统、玩家和管理员命令、可配置的薪水系统(包括 VIP 等级)以及可供其他模组调用的公共 API。
功能特点
核心
- 使用 SQLite (
economy.db) 持久化存储余额 - 使用整数型货币 (
Long),避免浮点数舍入问题 - 通过数据库事务实现原子转账
- 为
/baltop提供排行榜查询
命令
- 玩家:
/balance,/baltop,/pay,/paycheck - 管理员:
/money set|give|take(单一权限节点)
薪水系统(VIP 覆盖)
- 可配置的间隔时间和金额
- VIP 权限节点:
cannatale.economy.vip - VIP 玩家使用
/paycheck时只获得paycheckAmountVip(忽略普通paycheckAmount)
公共 API 钩子
- 其他模组可调用
EconomyApi来读取/修改余额、转账、排行榜、格式化及薪水领取 - 设计在服务器线程中调用(与命令/事件相同)
安装
- 构建插件 jar 文件(参见构建章节)。
- 将
build/libs/中的非精简 jar 文件复制到你的服务器模组文件夹(例如:HytaleServer/mods/)。 - 启动服务器。
- 首次运行时,Economy 会在插件数据目录中生成其数据文件:
config.jsoneconomy.db
配置(config.json)
Economy 在首次运行时创建 config.json。
当前配置项:
startingBalance(Long)
新玩家的初始余额。paycheckAmount(Long)
默认薪水金额(非 VIP)。paycheckAmountVip(Long)
VIP 薪水金额。仅当玩家拥有cannatale.economy.vip权限时使用。paycheckIntervalMinutes(Long)
两个等级的共享薪水冷却时间(分钟)。balTopLimit(Int)/baltop显示的条目数量。schemaVersion(Int)
内部版本号,用于未来数据库迁移。
VIP 行为
如果玩家拥有 cannatale.economy.vip 权限,/paycheck 只发放 paycheckAmountVip,忽略 paycheckAmount。
权限
管理员(所有 /money 命令)
cannatale.economy.admin
VIP 薪水等级
cannatale.economy.vip
命令
根帮助
/economy/ec(别名)
显示格式化的命令列表。
玩家命令
/balance
显示你的余额。
/balance [player]
显示另一名玩家的余额。
示例:
/balance/balance Xion28080
/baltop
显示最高余额(默认前 10 名,可通过 balTopLimit 配置)。
示例:
/baltop
/pay <player> <amount>
向另一名玩家付款。
- 金额必须 > 0
- 发送者必须有足够的余额
- 转账是原子操作
示例:
/pay Bob 250
/paycheck
领取你的薪水。
- 受冷却时间限制:
paycheckIntervalMinutes - VIP 玩家只获得
paycheckAmountVip
示例:
/paycheck
如果尚未就绪,你将看到一条消息,显示距离下次领取的剩余时间。
管理员命令(需要 cannatale.economy.admin)
/money set <player> <amount>
设置玩家的余额。
/money give <player> <amount>
增加玩家的余额。
/money take <player> <amount>
减少玩家的余额(金额被扣除,而非转账)。
- 最低为 0(不允许负余额)
示例:
/money set Bob 1000/money give Bob 250/money take Bob 500
在线玩家注意(ArgTypes.PLAYER_REF)
多个命令使用 ArgTypes.PLAYER_REF,这通常解析为在线玩家:
/pay/money set|give|take/balance --player=<name>(如果参数解析为 PLAYER_REF)
如果需要离线支持(设置/检查不在线的玩家),Economy 可以通过配置文件存储或名称→UUID 缓存来扩展,以解析 UUID。
数据库
SQLite 文件:
economy.db
模式(概念性):
- 表
balancesuuid(TEXT PRIMARY KEY)name(TEXT)balance(INTEGER)last_paycheck_claim_ms(INTEGER)
注意:
- 金额存储为整数 (Long)
- 转账使用事务以避免部分更新
公共 API 钩子(已声明)
API 位置
包:
org.omeganode.cannataleeconomy.api
主要接口:
EconomyApi
注册器:
EconomyApiRegistry
其他模组如何获取 API
import org.omeganode.cannataleeconomy.api.EconomyApiRegistry
val econ = EconomyApiRegistry.get() ?: return // Economy 未加载/未注册
EconomyApi — 方法和钩子(精确)
所有货币金额均为整数 Long 值。
大多数方法接受 nameForCreate,以便在账户缺失时按需创建。
package org.omeganode.cannataleeconomy.api
import org.omeganode.cannataleconomy.data.EconomyConfig
import org.omeganode.cannataleconomy.db.TopBalanceEntry
import org.omeganode.cannataleconomy.services.PaycheckService
import java.util.UUID
interface EconomyApi {
fun getConfig(): EconomyConfig
fun ensure(uuid: UUID, nameForCreate: String)
/** 如果账户不存在则返回初始余额(不会创建账户)。 */
fun getBalance(uuid: UUID): Long
/** 返回余额,必要时创建账户。 */
fun getBalance(uuid: UUID, nameForCreate: String): Long
fun setBalance(uuid: UUID, nameForCreate: String, amount: Long)
fun give(uuid: UUID, nameForCreate: String, amount: Long)
/**
* 从玩家余额中扣除最多 [amount](最低为 0)。
* @return 扣除后的新余额。
*/
fun take(uuid: UUID, nameForCreate: String, amount: Long): Long
/**
* 将 [amount] 从一名玩家转账给另一名玩家。
* @return 成功返回 true,发送者余额不足或金额 <= 0 时返回 false。
*/
fun transfer(fromUuid: UUID, fromName: String, toUuid: UUID, toName: String, amount: Long): Boolean
fun top(limit: Int): List<TopBalanceEntry>
/** 使用 Economy 所用的服务器区域规则格式化带逗号的数字。 */
fun format(amount: Long): String
/** 领取薪水。如果 isVip=true,仅使用 paycheckAmountVip。 */
fun claimPaycheck(uuid: UUID, nameForCreate: String, isVip: Boolean): PaycheckService.ClaimResult
}
其他模组的 API 示例
读取余额(不创建账户)
val bal = econ.getBalance(playerUuid)
读取余额(缺失时创建账户)
val bal = econ.getBalance(playerUuid, playerName)
增加 / 扣除 / 设置
econ.give(playerUuid, playerName, 500)
val newBal = econ.take(playerUuid, playerName, 250)
econ.setBalance(playerUuid, playerName, 1000)
转账
val ok = econ.transfer(fromUuid, fromName, toUuid, toName, 200)
排行榜
val top = econ.top(10)
格式化
val formatted = econ.format(1234567) // "1,234,567"
领取薪水(VIP 感知)
val isVip = sender.hasPermission("cannatale.economy.vip")
val result = econ.claimPaycheck(playerUuid, playerName, isVip)
故障排除
运行时 SQLite 驱动程序错误
如果你看到:
No suitable driver found for jdbc:sqlite:...
你很可能部署了错误的 jar 文件。
解决方法:
- 部署
build/libs/中的非精简 jar 文件 - 从服务器模组文件夹中移除旧的 Economy jar 文件
- 重启服务器
正在加载版本记录…
正在加载评论…
评论在新手盒子客户端中发表,这里同步展示。