公会与组队
社交是网游留客的另一根支柱——有朋友在,玩家舍不得走。公会(长期组织)和组队(临时协作)是两种粒度的社交系统。
公会系统
数据结构
公会本身是独立实体(不只是玩家身上一个字段):
java
public class Guild {
private UUID id; // 公会唯一ID
private String name; // 公会名
private UUID leader; // 会长
private Set<UUID> members; // 成员
private int level = 1; // 公会等级
private double fund = 0; // 公会资金
private Location base; // 公会领地/基地
}玩家身上记所属公会:
java
public class PlayerData {
private UUID guildId; // null 表示无公会
}管理两套存储
- 公会表:
Map<UUID, Guild>,按公会 ID 查 - 玩家→公会:
Map<UUID, UUID>(玩家ID→公会ID),快速查玩家属哪个公会
java
public class GuildManager {
private final Map<UUID, Guild> guilds = new HashMap<>();
private final Map<UUID, UUID> playerGuild = new HashMap<>();
public Guild getGuild(UUID playerId) {
UUID gid = playerGuild.get(playerId);
return gid == null ? null : guilds.get(gid);
}
}核心命令
| 命令 | 功能 |
|---|---|
/guild create <名> | 创建(扣费用、查重名) |
/guild invite <玩家> | 邀请(发请求,对方确认) |
/guild accept/deny | 接受/拒绝邀请 |
/guild kick <玩家> | 踢人(仅会长/管理) |
/guild leave | 退会(会长不能直接退,要先转让) |
/guild disband | 解散(仅会长) |
/guild info | 查看公会信息 |
邀请要用确认机制
别 invite 直接加人。发个请求,对方 /guild accept 才入会——否则会被恶意拉人。请求要存起来(带过期时间)。
权限分级
公会内部分权限:
- 会长:所有权限
- 副会长:踢人、邀请、改设置
- 成员:基础功能
用权限位或角色枚举:
java
public enum GuildRole { LEADER, OFFICER, MEMBER; }每个操作检查调用者角色够不够。
公会玩法
光有组织不够,得有集体目标:
- 公会资金:成员贡献,用于升级公会
- 公会领地:公会专属区块,外人不能进/破坏(接 WorldGuard 或自己圈地)
- 公会战:公会间对抗
- 公会福利:成员共享经验加成、商店折扣
组队系统
组队是临时协作,比公会轻量。
数据结构
java
public class Party {
private UUID leader;
private List<UUID> members = new ArrayList<>();
private boolean shareExp = true; // 共享经验
private boolean shareLoot = false; // 轮流拾取
}核心命令
/party invite <玩家>— 邀请/party accept— 加入/party leave— 离队/party disband— 解散(队长)
经验共享
组队打怪经验平分(且有组队加成鼓励社交):
java
@EventHandler
public void onMobDeath(EntityDeathEvent e) {
Player killer = e.getEntity().getKiller();
if (killer == null) return;
Party party = partyManager.getParty(killer.getUniqueId());
if (party == null) {
addExp(killer.getUniqueId(), reward); // 单人
} else {
// 组队:经验 ×加成 ÷人数
double total = reward * 1.2; // 组队 20% 加成
double per = total / party.getMembers().size();
for (UUID id : party.getMembers()) {
addExp(id, per);
}
}
}距离限制
防挂机蹭经验
组队共享经验要加距离判断——玩家得在击杀点附近才能分到,否则有人挂机蹭全队经验:
java
for (UUID id : party.getMembers()) {
Player m = Bukkit.getPlayer(id);
if (m != null && m.getWorld().equals(killer.getWorld())
&& m.getLocation().distance(killer.getLocation()) <= 50) {
addExp(id, per);
}
}退出与离线处理
- 玩家离线:公会数据保留(离线成员仍在公会),组队可设"离线超时自动踢"
- 玩家退服时:若他是队长,自动转让队长给最早入队的成员
常见坑
- 重名公会:创建时按名查重(大小写不敏感)
- 并发邀请:同一玩家被多人邀请,accept 时要明确接受哪个
- 数据一致性:玩家退会要同时更新
playerGuild和guild.members两边,别漏一边 - 公会被解散时:要通知所有在线成员、清理成员的
guildId
下一篇排行榜与成就。
