Skip to content

公会与组队 ​

社交是网游留客的另一根支柱——有朋友在,玩家舍不得走。公会(长期组织)和组队(临时协作)是两种粒度的社交系统。

公会系统 ​

数据结构 ​

公会本身是独立实体(不只是玩家身上一个字段):

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

下一篇排行榜与成就。