
Eclipse Core Client
Cobblmeon Eclipse服务器客户端增强模组
Eclipse Core Client
一个用于 Cobblemon 的客户端伴侣模组,支持高级多人对战格式,包括合作突袭战。
功能特性
- 多人突袭支持 - 支持 1-4 名玩家合作对抗单个强大对手
- 目标选择系统覆盖 - 允许在非标准对战格式中正确选择目标
- 对战阵营整理 - 在对战界面中正确显示盟友和敌人
- 双打/三打特殊机制修复 - 防止在单个回合内多次使用相同的对战特殊机制(Mega 进化、太晶化、Z 招式、极巨化)
环境要求
- Minecraft 1.21.1
- Fabric Loader 0.16.5+
- Fabric API
- Fabric Language Kotlin
- Cobblemon 1.7.1+
安装方法
- 下载并将其放入客户端的
mods文件夹 - 此模组仅限客户端 - 它通过自定义数据包与兼容的服务器模组进行通信
面向模组开发者
有兴趣为 Cobblemon 创建自己的突袭或多人对战模组吗?以下是你需要了解的信息:
核心挑战
Cobblemon 的对战系统是为 1v1 和 2v2 格式设计的。要创建突袭战(4v1、3v1 等),你需要解决几个问题:
- 对战创建 - 如何开始一场一方有 4 名玩家的对战?
- 目标选择 - 当相邻规则不允许时,玩家如何瞄准单个 Boss?
- 阵营显示 - 当客户端期望标准格式时,如何正确显示盟友?
- Showdown 兼容性 - 如何让 Showdown 接受非标准的队伍配置?
服务器端:开始多人对战
查看 Cobblemon 的 BattleBuilder 和 BattleRegistry。关键类:
BattleBuilder- 使用参与者和对战格式创建对战BattleActor- 代表参与者(玩家或 NPC)BattleFormat- 定义对战规则(单打、双打等)PokemonBattle- 当前对战的实例
对于突袭战,你将需要在一侧放置多个 BattleActor 实例。研究 Cobblemon 如何处理双打 - 这是多人对战的基础。
Showdown 层
Cobblemon 使用 Pokemon Showdown 来处理对战逻辑。对战通过以下方式创建:
BattleRegistry.startBattle(format, side1Actors, side2Actors)
Showdown 以“pack strings”的形式接收队伍数据 - 这是 Pokemon 的紧凑表示形式。该格式在 Showdown 的源码中有文档记录。关键要点:Showdown 的 fPokemon 格式包括种族、等级、招式、特性等。
对于突袭 Boss,请考虑:
- 如何给一只 Pokemon 更多有效生命值?
- 如何让一只 Pokemon 承受多个攻击者的攻击?
- 当 Showdown 计算对“缩放”目标造成的伤害时会发生什么?
客户端:目标选择问题
在标准双打中,Pokemon 只能瞄准相邻的槽位。在 4v1 突袭战中,所有玩家都需要瞄准单个 Boss。
客户端使用 ActiveClientBattlePokemon.getAdjacent() 来确定有效目标。此方法会检查位置并根据对战格式返回有效目标。
Eclipse Core Client 通过以下方式解决此问题:
- 拦截目标请求
- 覆盖突袭格式的相邻性计算
- 通过自定义数据包通信突袭配置
数据包通信
Fabric 网络允许在服务器和客户端之间发送自定义数据包:
// 服务器端:注册并发送
PayloadTypeRegistry.playS2C().register(...)
ServerPlayNetworking.send(player, payload)// 客户端:注册接收器
ClientPlayNetworking.registerGlobalReceiver(...)
你的数据包应告知客户端:
- 这是突袭战吗?
- 有多少玩家参与?
- Boss 在哪一方?
客户端需要在对战界面渲染之前获取此信息,以便正确组织阵营。
Showdown 修改(高级)
Cobblemon 将 Showdown 解压到 ./showdown/。位于 sim/ 目录中的 JavaScript 文件控制对战机制:
battle.js- 主对战循环和回合处理pokemon.js- Pokemon 状态、HP、PP 管理side.js- 阵营管理和槽位处理battle-actions.js- 招式执行和伤害计算
对于突袭机制,你可能需要修改以下内容:
- 对 Boss 的伤害计算方式
- PP 的追踪方式(Boss 拥有无限 PP?)
- 多目标招式的结算方式
- Boss 针对多个目标执行行动的方式
使用 Mixin 混入 GraalShowdownUnbundler.attemptUnbundle() 可以在解压后修补文件。
Mixin 目标参考
客户端(用于目标选择和显示修复):
ActiveClientBattlePokemon- 目标选择和相邻性BattleMoveSelection- 招式选择界面ClientBattle- 阵营组织
服务器端(用于对战创建):
BattleBuilder- 对战初始化BattleActor- 参与者行为NPCBattleActor- NPC 特定逻辑
开始开发
- 创建一个基本的服务器模组,能够开始一场双打对战
- 在一方添加第三个玩家 - 观察会出现什么问题
- 研究错误以理解限制条件
- 逐层实现修复(Showdown → 服务器 → 客户端)
从“双打可用”到“4v1 突袭可用”的旅程将让你全面了解 Cobblemon 的对战系统。
Eclipse 数据包协议
希望你的服务器模组与 Eclipse Core Client 兼容?请实现以下数据包:
数据包 1:客户端握手(客户端 → 服务器)
频道: eclipse_raids:client_handshake
当安装 Eclipse Core Client 的玩家加入你的服务器时,他们会发送此数据包。
| 字段 | 类型 | 描述 |
|---|---|---|
| protocolVersion | Int | 客户端协议版本(当前为 2) |
Kotlin 编解码器:
buf.writeInt(protocolVersion)
// 读取:buf.readInt()
使用此信息来追踪哪些玩家已安装客户端模组。阻止未安装模组的玩家参与突袭。
数据包 2:握手确认(服务器 → 客户端)
频道: eclipse_raids:handshake_ack
发送此数据包以确认客户端已被识别。
| 字段 | 类型 | 描述 |
|---|---|---|
| raidsEnabled | Boolean | 此服务器是否启用了突袭功能 |
| message | String | 状态消息(显示在客户端日志中) |
Kotlin 编解码器:
buf.writeBoolean(raidsEnabled)
buf.writeString(message)
数据包 3:突袭阵营配置(服务器 → 客户端)
频道: eclipse_raids:raid_side_config
这是关键数据包。在开始突袭后发送此数据包,告知客户端哪些参与者是盟友,哪些是敌人。
| 字段 | 类型 | 描述 |
|---|---|---|
| battleId | UUID | 来自 PokemonBattle.battleId 的对战 UUID |
| allyShowdownIds | List<String> | 玩家方的 Showdown ID(例如 ["p1", "p3", "p5", "p7"]) |
| enemyShowdownIds | List<String> | Boss 方的 Showdown ID(例如 ["p2"]) |
Kotlin 编解码器:
// 写入
buf.writeUuid(battleId)
buf.writeInt(allyShowdownIds.size)
allyShowdownIds.forEach { buf.writeString(it) }
buf.writeInt(enemyShowdownIds.size)
enemyShowdownIds.forEach { buf.writeString(it) }// 读取
val battleId = buf.readUuid()
val allyCount = buf.readInt()
val allyIds = (0 until allyCount).map { buf.readString() }
val enemyCount = buf.readInt()
val enemyIds = (0 until enemyCount).map { buf.readString() }
Showdown ID 命名规则
Showdown 根据对战位置分配 ID:
- p1, p3, p5, p7 - 一方使用奇数(用于玩家)
- p2, p4, p6, p8 - 另一方使用偶数(用于 Boss)
在 4v1 突袭中:
- 玩家 1 → p1
- 玩家 2 → p3
- 玩家 3 → p5
- 玩家 4 → p7
- Boss → p2
何时发送 RaidSideConfig
时机至关重要。请在以下时机发送数据包:
- 在
BattleRegistry.startBattle()返回之后 - 在玩家打开对战界面之前(他们有大约 1-2 秒的时间)
建议:立即发送,然后在 3 秒(60 tick)后再次发送作为安全措施,以防客户端当时未准备好。
// 对战开始后立即发送
for (player in players) {
ServerPlayNetworking.send(player, RaidSideConfigPayload(battle.battleId, allyIds, enemyIds))
}// 安全措施 - 3 秒后重新发送
Scheduler.schedule(60) {
for (player in players) {
ServerPlayNetworking.send(player, RaidSideConfigPayload(battle.battleId, allyIds, enemyIds))
}
}
客户端的处理方式
当 Eclipse Core Client 接收到 RaidSideConfigPayload 时:
- 找到与
battleId匹配的活动ClientBattle - 从双方收集所有
ClientBattleActor - 重新组织它们:盟友 →
side1,敌人 →side2 - 设置
isInRaidBattle = true(启用目标选择覆盖)
这样修复了:
- Pokemon 出现在错误的视觉侧
- 玩家无法瞄准 Boss(相邻性覆盖生效)
Payload 类(Fabric 1.21.1)
// 在你的模组初始化器中注册
PayloadTypeRegistry.playC2S().register(ClientHandshakePayload.ID, ClientHandshakePayload.CODEC)
PayloadTypeRegistry.playS2C().register(HandshakeAckPayload.ID, HandshakeAckPayload.CODEC)
PayloadTypeRegistry.playS2C().register(RaidSideConfigPayload.ID, RaidSideConfigPayload.CODEC)// 处理传入的握手
ServerPlayNetworking.registerGlobalReceiver(ClientHandshakePayload.ID) { payload, context ->
val player = context.player()
// 追踪该玩家已安装客户端模组
// 发送确认数据包
}
没有此客户端模组时
如果玩家没有安装 Eclipse Core Client:
- 普通的 1v1 和 2v2 对战可以正常工作
- 突袭对战会出现目标选择问题(玩家无法选择 Boss)
- Pokemon 可能在视觉上出现在错误的阵营
通过检查你的握手追踪记录,阻止未安装客户端模组的玩家参与突袭。
兼容性
此模组旨在与实现 Eclipse 数据包协议的服务器端突袭模组配合使用。如果没有兼容的服务器模组,它会在双打/三打对战中充当被动的特殊机制修复工具。
支持
此模组按现状提供,用于与兼容的 Eclipse 服务器模组配合使用。
正在加载版本记录…
正在加载评论…
评论在新手盒子客户端中发表,这里同步展示。