为什么用云公会
公会插件看起来就是「建公会、拉人、存钱」,难的是那些多人同时操作的时候:两个副会长同时提领,资金会不会变成负数?公会只剩一个空位,两个人同时点加入会不会超员? 两个子服上的成员同时打开仓库,物品会不会复制?下面逐项说明云公会怎么处理这些情况。
重点一览
| 需求 | CloudGuild 云公会 |
|---|---|
| 扣公会资金 | 一条 UPDATE … SET funds = funds - ? WHERE id = ? AND funds >= ?,不够就影响 0 行、直接失败,不会变成负数 |
| 人数上限 | 人数检查写在加人的同一条条件更新里;成员表以玩家 UUID 为主键,一个玩家不可能同时在两个公会 |
| 跨服 | 只用 MySQL:变动写进事件表,其他子服每秒读取一次,不需要 Redis、也不需要在代理端安装插件 |
| 主线程 | 所有数据库操作都在独立线程池;变量、伤害判断只读内存缓存 |
| 公会聊天 / 任务 / 增益 | 全部内置,增益直接使用原版药水与原版属性 |
| 职位 | 职位数量、权重、人数上限、每项权限都能在 config.yml 自定义 |
| 共享仓库 | 每一页同一时间只有一个人能打开,所有子服共用一把锁 |
每一笔资金、每一个名额都由数据库一步判定
云公会里所有「会扣东西」或「有上限」的操作,都是一条带条件的更新或一个数据库事务,影响 0 行就是失败,不会先读再写:
| 操作 | 在同一步里检查的条件 |
|---|---|
| 提领、改名、发公告、升级增益、宣战 | 公会资金 ≥ 花费 |
| 升级公会 | 目前等级没变、资金 ≥ 花费、活跃 ≥ 需求、成员数 ≥ 需求 |
| 加入公会(申请通过、邀请、直接加入) | 公会还存在、玩家还没有公会、成员数 < 上限 |
| 升职 / 降职 / 指定职位 | 对方的职位没有被别人先改掉、新职位的人数没满 |
| 商店购买 | 贡献 ≥ 价格、本期购买次数 < 限购(同一个事务,任一项不满足整笔还原) |
| 存钱 | 存钱的人还是这个公会的成员(不是的话,扣掉的钱退回) |
| 审核申请 | 两位管理同时点「同意」,只有一位拿得到这份申请 |
| 每日签到 | 同一天只会成功一次,跨服也一样 |
MySQL 在多个子服同时写入时偶尔会回报死锁,云公会会自动把整个事务重做(最多 5 次),玩家只会看到成功或失败,不会看到一半的结果。
只要 MySQL 就能跨服
多个子服连同一个数据库,sync.enabled: auto 就会自动开启跨服同步:
- 每个变动(公会资料、成员、聊天、同盟、增益、战争、公告、提示消息)写进数据库的事件表,其他子服每
sync.interval-ticks(默认 20 tick = 1 秒)读取一次。 - 玩家不在线时变动也不会漏掉:上线时直接从数据库读取最新资料;另外每 60 秒整批刷新一次缓存。
- 不需要 Redis,也不需要 BungeeCord 插件消息频道(只有「跨服回据点」时用代理端的
Connect把玩家送过去)。 - 每日结算(维护费与活跃衰减)、任务奖励、公会战开战与结算公告,都由第一个抢到的子服执行一次,不会重复。
详见 跨服设置。
不占主线程
- 所有 SQL 都在插件自己的数据库线程池执行,结果再回到玩家所在的线程处理(Folia 使用对应的区域调度器)。
- 全部公会、在线成员、同盟关系、增益与进行中的战争都放在内存缓存里,PlaceholderAPI 变量只读缓存;排行榜的排序结果额外缓存 5 秒,计分板每秒读很多次排行变量也没有负担。
- 任务进度先在内存里累积,每 5 秒用一个事务写入一次,挖矿、打怪这种高频事件不会每次都写数据库。
- 需要读数据库的菜单(成员列表、银行记录、任务进度……)先在后台载入,再在玩家的线程画出来。
功能全部内置
| 功能 | 云公会的做法 |
|---|---|
| 公会聊天 | /cg c 公会频道、/cg ac 同盟频道、聊天开头打 # 直接发到公会,跨服即时;管理员可以监听,见 聊天与公告 |
| 公会任务 | 击杀、挖掘、放置、钓鱼、存钱、签到、在线 7 种类型,每日 / 每周重置,全员累积、只发一次奖励,见 公会任务 |
| 公会增益 | 原版药水效果(无限时间)与原版属性修饰(最大生命、攻击伤害……),不需要 AttributePlus 之类的属性插件,见 公会增益 |
| 公会商店 | 用个人贡献兑换物品或执行指令,可以限购;管理员手拿物品一条指令上架,见 公会商店 |
| 公会仓库 | 每页一把全服共用的锁,见 公会仓库 |
| 公会据点 | 依等级可以有好几个据点,跨服传送,见 公会据点 |
| 公会战 | 宣战 → 准备时间 → 开战计分 → 自动结算,见 同盟、敌对与公会战 |
增益给过哪些效果会记在玩家身上,离开公会、重开服务器后都能正确移除,不会误删信标或药水等其他来源的效果。
自定义职 位,每项权限分开设
职位写在 config.yml 的 ranks:名称、权重、人数上限、权限清单都能改,想要「财务」「外交官」这种只开放部分权限的职位,加一段就好。
权限共有 16 项(邀请、审核、踢人、升职、降职、公告、据点、升级、设定、外交、宣战、增益、提领、仓库、商店、任务),见 职位与等级。
- 只能管理权重比自己低的成员。
- 两位管理同时改同一个人的职位时,只有一位会成功,另一位提示「资料刚被其他人修改了」。
共享仓库不会复制物品
公会仓库的每一页,同一时间只有一位成员能打开,这把锁放在数据库里,所有子服共用:
- 别人(包括别的子服上的人)正在用这一页时,提示「這頁倉庫有其他成員正在使用(可能在其他子服)」。
- 每次打开都用新的锁代号,连点或关掉马上再开,也拿不到还没存回的那一把锁。
- 打开期间每 20 秒延长一次锁;子服当机时锁 60 秒后自动失效,重开时也会放掉自己留下的锁。
- 锁已经失效(例如数据库中断太久,锁过期后被别人拿走)时,仓库会被关闭、这次的变更不会写入,避免盖掉别人的变更;这次放进去的物品退还给玩家,不会凭空消失。
玩家文字不能夹带指令
申请留言、公告、公会介绍、公会聊天这些玩家自己输入的文字,< > \ 一律换成全角字符,玩家写不出 MiniMessage 的点击、悬停标签,无法伪造「点一下就执行指令」的消息。见 玩家文字的安全处理。
宣战制公会战
公会战不是「随时可以互砍」,而是有明确的开始与结束:宣战(扣公会资金)→ 准备时间 → 开战(双方成员互相击杀计分,任何子服都算)→ 时间到自动结算。 胜方得到奖励资金、活跃,并从败方资金抢走一定百分比;平手不发奖励。不能对同盟宣战,同一对公会之间有宣战冷却。见 同盟、敌对与公会战。
云界面画面
装了 云界面 CloudUI 时,/cg 打开全屏的公会主页:左边是公会资讯与升级进度,中间是成员名册,右边是签到、银行、商店、任务等功能按钮。
签到、升级、切换聊天频道、回据点直接在画面上完成。见 云界面公会。