• 欢迎加入MineBBS QQ讨论群:点击查看所有的官方讨论群
  • 我们将于近期对服务器进行迁移,服务可能中断至多2日。请各位安排好自己的访问计划,造成不便敬请谅解!
  • MineBBS入站考试已经上线!想要成为【正式会员】解锁更多功能吗?快来参与吧!【点我去看】
[1.21-26.2小游戏]村庄保卫战 - PraxVillageDefense

原创 付费 闭源 [1.21-26.2小游戏]村庄保卫战 - PraxVillageDefense 2.0.0

请登录后获取
版权类型
原创
插件中文名称
村庄保卫战
插件英文名称
PraxVillageDefense
原帖地址
#
支持的核心(服务端)
  1. Spigot
  2. Paper
  3. Folia
  4. Purpur
语言支持
中文(简体)
前置组件
Vault:https://modrinth.com/plugin/vault-2.0-economy-plugins(推荐)
MultiVerse-Core:https://modrinth.com/plugin/multiverse-core
DecentHolograms:https://modrinth.com/plugin/decentholograms
(非必需)Mythicmobs:https://modrinth.com/plugin/mythicmobs
(非必需)QualityArmory:https://modrinth.com/plugin/qualityarmory
适配版本(Java)
  1. 最新版本
  2. 26.x
  3. 1.21
[MD] # Villager Defense - Developer & Admin Documentation ## 目录 1. [功能总览](#1-功能总览) 2. [服务端兼容性](#2-服务端兼容性) 3. [软依赖](#3-软依赖) 4. [命令列表](#4-命令列表) 5. [管理员 GUI 指南](#5-管理员-gui-指南) 6. [选定套装系统](#6-选定套装系统) 7. [自定义套装系统](#7-自定义套装系统) 8. [API 参考](#8-api-参考) 9. [ChestCommands 集成](#9-chestcommands-集成) 10. [配置文件参考](#10-配置文件参考) 11. [构建指南](#11-构建指南) 12. [开发者扩展指南](#12-开发者扩展指南) --- ## 1. 功能总览 Villager Defense 是一款多模块 Minecraft Spigot/Paper 插件,支持版本 1.21.x 与 26.x 全版本(Minecraft 1.21.1 ~ 26.1.x)。 ### 核心系统 | 系统 | 说明 | |------|------| | 竞技场管理 | 创建/编辑/管理多个独立竞技场 | | 套装系统 | 24 个预定义套装(技能/赠礼/效果)+ 自定义套装 | | 怪物系统 | 22 种怪物类型 + MythicMobs 联动 | | 商店系统 | 默认/自定义/附魔/消耗品商店 | | 挑战系统 | 局内挑战选项 | | 成就系统 | 基于统计的成就追踪 | | 难度系统 | 动态难度调整 | | 水晶货币 | 全局水晶(`crystalBalance`),用于购买自定义套装等 | | 玩家数据 | 玩家统计、平衡、套装等级、签到状态持久化 | | **选定套装** | **玩家可预设默认套装,加入时自动装备** | | **自定义套装** | **管理员可通过 GUI 创建自定义套装(水晶购买)** | | **每日签到** | **`/vd sign` 每日领取水晶奖励(config 可配)** | | **MythicMobs** | **与 MythicMobs 自定义怪物联动** | | **怪物 AI** | **可配置的怪物行为系统** | | **礼包码** | **`/kit <礼包码>` 兑换钻石/套装;支持每日礼包、限时礼包、全服公告** | | **积分商店** | **击杀怪物获得积分,可在 `/vd shop` 兑换钻石/套装/物品** | | **怪物词缀** | **精英怪随机携带词缀(急速/护盾/爆炸/传送/吸血/燃烧)** | | **观战模式** | **死亡/淘汰后留在场内以旁观者模式观战(竞技场可配)** | | **成就解锁套装** | **达成指定成就自动解锁自定义套装(config 可配)** | | **防护塔系统** | **6 种防御塔(箭/闪电/爆炸/火焰/冰霜/治疗),手持绿宝石右键方块直接建造,塔实体可视化(盔甲架+图标+名称)** | | **塔链协同** | **相邻同类型塔互相叠加加成;减速怪被火焰塔命中触发熔毁联动(伤害提升)** | | **塔升级** | **塔主右键塔消耗绿宝石升级,等级线性提升伤害/射程并缩短冷却,塔名显示 Lv.N** | | **村民职业体系** | **村民随机获得职业,存活期间为周围玩家提供职业光环** | | **好奇村民** | **按概率生成的村民带【好奇】标签,主动跟随附近玩家;可右键驱离(有冷却与代价),驱离致死重罚民心** | | **波次惩罚** | **村民死亡叠加村庄绝望层数,后续怪物属性等比提升** | | **村庄民心** | **完美防守提升民心、村民死亡降低民心,民心越高波次/胜利奖励倍率越高(正向机制)** | | **幸存者奖励** | **完美防守 / 胜利幸存村民的绿宝石奖励** | | **怪物适应性进化** | **持续用同种伤害击杀后,新怪物获得该伤害抗性,逼迫混合塔型/武器** | | **悬赏精英波** | **每隔 N 波出现悬赏目标(高血+★标记),击杀后全队获得绿宝石大奖与增益** | | **回收站** | **原公共箱子改为回收站:放入物品供其他玩家取用,每波结束自动清空** | | **村民内鬼** | **每只村民小概率为隐藏内鬼:持续给附近玩家施加减益,可被攻击,击杀提升民心+全队增益** | | **村庄节日** | **随机波次触发节日波:全场奖励加成 + 村民烟花粒子** | | **怪物进化线** | **塔型级进化:同一塔型杀怪越多,怪物对该塔型抗性越高** | | **股票式投资** | **`/vd bank` 波间存取宝石,存款按波计息,利率随民心波动** | ### 已实现的增强功能 - **Leaf 服务端兼容** — 经过测试的兼容性 - **Folia 支持** — `folia-supported: true`,调度器适配层(全局/区域/异步) - **ChestCommands 集成** — 通过 API 和命令集成 - **怪物自定义属性** — 全局/逐怪属性倍率、难度缩放(22 种怪物) - **怪物 AI 设置** — 目标更新间隔、搜索范围、优先攻击村民、破门(地面挖掘/飞行撞门,独立 30 秒冷却) - **怪物词缀系统** — 波次越高精英怪携带词缀概率越高(急速/护盾/爆炸/传送/吸血/燃烧) - **精英词缀互动** — 爆炸怪死亡留下灼烧地面、剧毒怪死亡留下毒素云(AreaEffectCloud 自动消散) - **远程攻击触发词缀** — 骷髅射出的箭命中目标同样触发吸血/点燃等词缀(`Projectile` 攻击者分支) - **村民死亡复仇** — 村民倒下后激怒周围怪物(速度+力量狂暴) - **波次生成粒子特效** — 每只怪物生成时在出生点播放传送门/烟雾粒子 - **多语言支持** — en_US / zh_CN - **游戏结束自动清场** — 游戏结束瞬间清除竞技场内所有生物(怪物/村民/宠物/掉落物),防止残留到下一局 - **实时倒计时** — 开始游戏倒计时通过 ActionBar 实时显示,并修复重复倒计时 Bug - **全套 AI 寻路** — 原版与 MythicMobs 敌人都使用改进的寻路 AI(上楼梯、追踪村民 X/Z、飞行怪空中追击) - **绿宝石线程安全** — `VDPlayer.addGems` / `canAfford` 加 `synchronized` 锁,消除 Folia 多区域线程下的 read-modify-write 竞态 - **全员村民仇恨** — 所有竞技场怪物(含 MythicMobs 精英与词缀召唤的仆从)都会优先攻击村民;`monsterAI.enabled` 默认开启 - **幻翼固定伤害** — 幻翼攻击力基准值固定为 2(难度加成仍作为修饰符叠加) - **宠物击杀归属** — 铁傀儡/狼击杀怪物时,绿宝石与击杀数直接结算给其召唤者 - **中途入场补偿** — 非回归的迟到玩家获得场上所有玩家绿宝石余额平均值的 75%(`economy.lateJoinGemPercent`);回归(掉线保护恢复)玩家不获得 - **入场选套装** — 中途加入的玩家进入前可打开套装选择菜单选择套装;回归玩家自动跳过选择、恢复掉线前装备 - **难度水晶加成** — 竞技场难度标签(简单~噩梦)使最终水晶结算额外 +10%/级(噩梦 +40%) - **假死防护** — 修复部分怪物/村民血量归零后"假死抽搐、无法强制杀死"(吸收/恢复类词缀复活、死亡事件异常兜底;村民另设实体级假死守护任务) - **禁用合成表** — 竞技场内玩家禁止合成任何物品(`disableCrafting.enabled`),防止合成非法物品 - **QA 枪械防护** — QA 枪械攻击蜜蜂(召唤物)等无伤害目标不再刷钱(击杀结算前校验取消状态 + 排除召唤物) - **召唤物伤害修复** — 召唤物被怪物攻击恢复正常掉血(环境伤害处理器不再误拦截实体攻击) - **好奇村民** — 部分村民按 `villagers.curiousChance` 概率获得【好奇】标签并主动跟随玩家;右键可驱离(`scareDurationSeconds` 内不再跟随、造成 `scareDamage` 伤害、每玩家 `expelCooldownSeconds` 冷却);驱离致死按 `morale.expelKillPenalty` 重罚民心 - **信息板(InfoBoard)** — 竞技场入口处的浮字公告栏,仅展示简要玩法介绍,`/vd admin infoBoard` 管理 - **绿宝石建造塔** — 手持绿宝石右键方块打开建造菜单,6 种塔直接消耗绿宝石建造(原为商店购买塔物品,现为直接建造) - **难度缩放怪物数量** — 竞技场难度系数现在也会缩放每波怪物生成数量(简单 ×0.6、普通 ×1.0、困难 ×1.15、噩梦 ×1.3),难度 1 不再与难度 3 生成一样多的怪物。此前怪物数量完全不受难度影响,导致低难度显得过于拥挤。 - **入场合管理面板空指针防护** — 玩家在(延迟执行的)入场流程中掉线时,跳过发放选择物品而非抛出 `NullPointerException`;`/vd admin` 不再崩溃(也不再误报为"语言文件"问题)。 --- ## 2. 服务端兼容性 ### 支持的服务器软件 | 服务器 | 版本范围 | 状态 | |--------|---------|------| | Spigot | 1.21.x - 26.x | 完全支持 | | Paper | 1.21.x - 26.x | 完全支持 | | **Leaf** | 1.21.x - 26.x | **已验证兼容** | | Purpur | 1.21.x - 26.x | 完全支持(Paper 分支) | | **Folia** | 1.21.x+ | **受支持**(`folia-supported: true`) | ### Folia 兼容性说明 插件声明 `folia-supported: true`,并通过 `SchedulerUtils` 调度器适配层支持 Folia: 1. **全局调度** — 基于 `GlobalRegionScheduler` 2. **区域调度** — 基于 `RegionScheduler`(`scheduleRegionTask`,延迟 ≥1 tick 用 `runDelayed`,0 tick 用 `run`) 3. **异步调度** — 基于 `AsyncScheduler` 4. 普通服务端自动回退到 Bukkit `Scheduler` ### Leaf 兼容性说明 Leaf 是基于 Paper 的性能优化分支。插件通过以下方式确保兼容: 1. **软依赖声明** — plugin.yml 中声明 `Leaf` 为可选的软依赖 2. **API 级别 API** — 仅使用 Bukkit/Spigot 公开 API,不依赖私有实现 3. **NMS 版本检测** — 通过 `Bukkit.getBukkitVersion()` 解析版本,而非依赖服务端包名 4. **反射加载** — NMS 管理器通过反射创建,避免直接类引用 支持的 Minecraft 版本 → NMS 模块映射(1.21.x 与 26.x 全版本): - 1.21.0 / 1.21.1 → `v1_21_R1`(`nms/v1_21_r1`) - 1.21.2 / 1.21.3 → `v1_21_R2`(`nms/v1_21_r2`) - 1.21.4 → `v1_21_R3`(`nms/v1_21_r3`) - 1.21.5 / 1.21.6 → `v1_21_R4`(`nms/v1_21_r4`) - 1.21.7 / 1.21.8 → `v1_21_R5`(`nms/v1_21_r5`) - 26.x(26.0 ~ 26.1.x)→ `v1_26_R1`(`nms/v1_26_r1`,纯 Mojmap 无版本包结构) > 跨版本 API 兼容:`Attribute` 常量在 1.21.2+ 去掉了 `GENERIC_` 前缀(如 `MAX_HEALTH` / `GENERIC_MAX_HEALTH`),插件通过 `Attributes` 工具类在运行时按服务端版本回退解析,同一份 JAR 兼容全部 1.21.x 与 26.x。 --- ## 3. 软依赖 插件支持以下可选的软依赖: | 插件 | 用途 | 必需 | |------|------|------| | PlaceholderAPI | PAPI 变量扩展 | 否 | | MythicMobs | 自定义怪物联动 | 否 | | WorldGuard | 世界区域保护 | 否 | | WorldEdit | 建筑工具 | 否 | | Multiverse-Core | 多世界支持 | 否 | | **ChestCommands** | **菜单联动,提供 [vd] 动作** | 否 | | **Leaf** | **性能优化服务端兼容** | 否 | --- ## 4. 命令列表 ### 玩家命令 | 命令 | 描述 | 权限 | |------|------|------| | `/vd admin` | 打开管理面板 | `vd.use` | | `/vd help` | 查看帮助信息 | 无 | | `/vd leave` | 离开当前游戏 | 无 | | `/vd stats [player]` | 查看玩家统计 | 无 | | `/vd kits` | 查看玩家套装 | 无 | | `/vd defaultkit` | 打开默认套装选择菜单 | 无 | | `/vd join` | 以 Phantom 套装加入满人竞技场 | 无 | | `/vd achievements` | 查看成就 | 无 | | `/vd sign` | 领取每日签到奖励(水晶 + 连续签到加成,config 可配) | 无 | | `/vd crystals <player> <amount>` | 修改玩家水晶余额(**不能给自己**) | `vd.crystals` | | `/vd die` | 在游戏中自杀 | 无 | | `/vd shop` | 打开积分商店(用击杀获得的积分兑换奖励) | 无 | | `/vd bank [deposit\|withdraw] <数量>` | 股票式投资:波间存取绿宝石,存款按波计息(利率随民心) | 无 | | `/kit <礼包码>` | 兑换礼包码(钻石/套装) | 无 | | `/kit daily` | 领取每日礼包(每天一次,奖励由管理员配置的 DAILY 礼包决定) | 无 | ### 管理命令 | 命令 | 描述 | 权限 | |------|------|------| | `/vd admin lobby` | 管理大厅 | `vd.admin` | | `/vd admin infoBoard` | 管理信息板 | `vd.admin` | | `/vd admin leaderboard` | 管理排行榜 | `vd.admin` | | `/vd admin arena` | 管理竞技场 | `vd.admin` | | `/vd start [arena]` | 强制开始游戏 | `vd.start` | | `/vd end [arena]` | 强制结束游戏 | `vd.admin` | | `/vd delay [arena]` | 重置等待倒计时 | `vd.start` | | `/vd fix` | 修复/更新配置文件 | `vd.admin` | | `/vd debug <level>` | 设置调试级别 | `vd.admin` | | `/vd reload` | 重载插件数据 | `vd.admin` | --- ## 5. 管理员 GUI 指南 ### 主菜单导航结构 ``` MAIN_MENU ├── Lobby Settings ├── Info Boards ├── Leaderboards │ ├── Total Kills / Top Kills / Total Gems │ ├── Top Balance / Top Wave │ └── Crystals (水晶排行榜,DIAMOND 按钮) ← 新增 ├── Arenas │ └── [Arena Name] │ ├── Game Settings │ │ ├── Allowed Kits │ │ ├── Player Settings │ │ └── ... │ ├── Mob Settings │ │ ├── Monster Customization ← 新增 │ │ │ ├── Global Health/Damage/Speed │ │ │ ├── Difficulty Scaling │ │ │ └── Per-Mob Settings (22种怪物, 翻页) │ │ ├── Monster AI ← 新增 │ │ │ ├── Target Update Interval │ │ │ ├── Villager Search Range │ │ │ └── Prioritize Villagers Toggle │ │ └── MythicMobs Integration ← 新增 │ │ └── Enable/Disable Toggle │ └── ... ├── Server Settings (COMMAND_BLOCK) ← 新增 ├── Keep Inventory Toggle ├── Auto Open Arenas Toggle └── Reload Plugin Button ├── 礼包设置 (GOLD_INGOT) ← 新增 │ ├── 新建礼包 │ └── [礼包码] 编辑 │ ├── 礼包码重命名 │ ├── 钻石数量 │ ├── 给予套装(原版或自定义,含未开放的) │ ├── 总使用次数(-1 无限) │ ├── 每人限用 │ ├── 使用统计 │ ├── 过期时间(0 永久 / N 天后过期) │ ├── 领取全服公告(开关) │ ├── 每日礼包(开关,/kit daily 领取) │ └── 删除礼包 └── 积分商店设置 (EMERALD) ← 新增 ├── 新建兑换项 └── [兑换项] 编辑 ├── 兑换类型(钻石 / 套装 / 物品) ├── 价值(数量或套装名,含未开放的自定义套装) ├── 所需积分 ├── 物品类型(仅物品型,Material 名称) └── 删除兑换项 ``` ### 自定义套装管理入口 ``` MAIN_MENU → Arenas → [Arena] → Game Settings → Custom Kits (新增) ``` 或在 `Mob Settings` 页面的导航栏中也提供了快捷入口。 ### 玩家默认套装选择 在游戏中,玩家可以: 1. 输入 `/vd defaultkit` 打开默认套装菜单 2. 点击任意已拥有的套装将其设为默认 3. 点击"无套装"按钮清除默认选择 4. 下次加入任意竞技场时自动装备该套装 ### 防护塔建造(游戏内) 玩家在游戏中可以直接消耗**绿宝石余额**建造防御塔,无需先购买物品: 1. 手持绿宝石(`EMERALD`)右键任意方块(需在竞技场边界内) 2. 弹出**建造菜单**(`TURRET_BUILD_MENU`),展示全部 6 种塔的属性与造价 3. 点击选中的塔 → 扣除对应绿宝石并立即生成塔 | 塔类型 | 图标 | 行为 | 造价 | |--------|------|------|------| | 箭塔(ARROW) | DISPENSER | 自动射击附近怪物 | 400 | | 闪电塔(LIGHTNING) | LIGHTNING_ROD | 对最近怪物降下闪电,无视护甲的高额单体伤害 | 500 | | 爆炸陷阱(BOMB) | TNT | 怪物靠近后自毁范围伤害 | 600 | | 火焰塔(FLAME) | BLAZE_POWDER | 周期性点燃并灼烧 | 700 | | 冰霜塔(FROST) | ICE | 强烈减速(冻结) | 800 | | 治疗塔(HEALING) | GOLDEN_APPLE | 为附近村民/玩家/铁傀儡回血 | 900 | 行为细节: - 每座塔生成一个**可视化盔甲架标记**:头顶佩戴类型图标、显示金色塔名,一眼可辨 - 余额不足时提示"买不起"并**自动关闭菜单** - 每名玩家最多同时放置 `turrets.capPerPlayer`(默认 3)座塔 - 绿宝石不足/塔数上限的扣费顺序保证:**先检查、后放置、成功才扣费**,不会误扣 - `VDPlayer.addGems` / `canAfford` 已加 `synchronized` 锁,快速双击或跨区域线程并发时不会重复扣费、余额不会变负 ### 逐怪设置(Per-Mob Settings) `Arenas → [Arena] → Mob Settings → Monster Customization → Per-Mob Settings` 支持对 **22 种怪物** 单独配置生命/伤害/速度倍率等(翻页浏览): | 怪物代码 | 名称 | 怪物代码 | 名称 | |---------|------|---------|------| | `zomb` | Zombie | `blze` | Blaze | | `husk` | Husk | `ghst` | Ghast | | `wskl` | Wither Skeleton | `pill` | Pillager | | `brut` | Piglin Brute | `slim` | Slime | | `vind` | Vindicator | `mslm` | Magma Cube | | `spid` | Spider | `crpr` | Creeper | | `cspd` | Cave Spider | `phtm` | Phantom | | `wtch` | Witch | `evok` | Evoker | | `skel` | Skeleton | `hgln` | Zoglin | | `stry` | Stray | `rvgr` | Ravager | | `drwd` | Drowned | `w` | Wither | 每个怪物的编辑界面顶部会显示 **"正在编辑"(NAME_TAG)指示按钮**,标明当前编辑的怪物名称与代码,避免混淆(例如 `正在编辑: Zombie (zomb)`)。怪物代码与 `spawnTables/*.yml` 中使用的代码一致,逐怪修改可正确生效。 --- ## 6. 选定套装系统 ### 工作原理 选定套装系统允许玩家预先设定一个"默认套装": 1. 玩家使用 `/vd defaultkit` 或 ChestCommands 菜单打开选择界面 2. 选择已拥有的套装作为默认 3. 数据持久化到 `playerData.yml`(`<UUID>.selectedKit` 路径) 4. 玩家加入竞技场时自动装备选定的套装 ### 数据存储 选定套装数据存储在 `playerData.yml`: ```yaml <player-uuid>: selectedKit: "Mage" # 套装名称 kits: ... ``` ### 相关类 | 类 | 说明 | |------|------| | `VDPlayer` | `selectedKitName` 字段 + getter/setter | | `PlayerManager` | `saveSelectedKit()` / `loadSelectedKit()` | | `Inventories.createPlayerDefaultKitsMenu(Player)` | 默认套装选择 GUI | | `VillagerDefenseAPI.openDefaultKitMenu(Player)` | API 入口 | --- ## 7. 自定义套装系统 ### 功能概述 管理员可以在管理 GUI 中创建和管理自定义套装: - 自定义名称和图标 - **水晶价格**(0 = 免费;购买扣除玩家 `crystalBalance`,非绿宝石) - 自定义武器(最多 36 个槽位,多页 GUI) - 自定义护甲(靴子、护腿、胸甲、头盔) - 自定义药水效果(类型、持续时间、等级) - 启用/禁用切换 - 多页管理界面 ### 可见性与购买 - 自定义套装在所有套装界面中均可见:`/vd kits` 玩家套装界面、`/vd defaultkit` 默认套装界面、竞技场大厅/局内选择界面、管理员界面 - 管理员编辑界面中价格以 **水晶(DIAMOND 图标)** 为单位显示与设置 - 玩家购买时扣除 `playerData.yml` 中的 `crystalBalance`(水晶余额),不足则提示无法购买 - 价格持久化在 `custom_kits.yml` 的 `price` 字段,重载/保存不会丢失 ### 数据存储 自定义套装存储在独立的 `custom_kits.yml` 文件中: ```yaml kits: <kit-id>: name: "My Custom Kit" price: 500 # 水晶价格(0 = 免费) icon: <base64 encoded ItemStack> description: - "Line 1" - "Line 2" armor: - <boots> - <leggings> - <chestplate> - <helmet> items: - <item 0> # 热键栏槽位 0 - <item 1> ... effects: - type: "SPEED" duration: 600 amplifier: 1 ambient: true particles: true icon: true enabled: true ``` ### 相关类 | 类 | 说明 | |------|------| | `CustomKit` | 自定义套装数据模型 | | `CustomKitManager` | 自定义套装管理器(CRUD + 持久化) | | `Inventories.createAdminCustomKitsMenu(int page)` | 管理员套装列表 GUI(分页) | | `Inventories.createAdminCustomKitEditMenu(String kitId)` | 编辑单一套装 GUI | | `Inventories.createAdminCustomKitWeaponsMenu(String kitId, int page)` | 武器编辑器(多页) | | `Inventories.createAdminCustomKitEffectsMenu(String kitId, int page)` | 效果编辑器 | ### GUI 操作流程 1. **套装列表** — `ADMIN_CUSTOM_KITS_MENU` - 每页显示 18 个套装 - 点击套装进入编辑 - "创建"按钮生成新的空套装 2. **套装编辑** — `ADMIN_CUSTOM_KIT_EDIT_MENU` - 图标预览(点击更换提示) - 名称显示(点击重命名提示) - **价格设置(水晶)**(点击输入价格) - 启用/禁用切换 - 三个子编辑器入口:武器、护甲、效果 3. **武器编辑器** — `ADMIN_CUSTOM_KIT_WEAPONS_MENU` - 每页 12 个槽位,3 页共 36 槽位 - 将物品从鼠标拖放到槽位设置 - 右键点击清除槽位 4. **效果编辑器** — `ADMIN_CUSTOM_KIT_EFFECTS_MENU` - 显示已有效果列表 - 点击效果移除 - 添加效果通过命令 --- ## 8. API 参考 ### `VillagerDefenseAPI` **包路径**: `me.theguyhere.villagerdefense.plugin.api.VillagerDefenseAPI` ```java // 打开默认套装选择菜单 public static void openDefaultKitMenu(Player player) // 设置玩家默认套装 public static boolean setPlayerDefaultKit(Player player, String kitName) // 获取自定义套装数量 public static int getCustomKitCount() // 打开管理自定义套装列表菜单 public static void openAdminCustomKitsMenu(Player player, int page) // 检查自定义套装是否存在 public static boolean customKitExists(String kitId) // 重载自定义套装配置 public static void reloadCustomKits() // 保存自定义套装配置 public static void saveCustomKits() // 打开主管理菜单 public static void openAdminMenu(Player player) ``` ### `CustomKitManager` **包路径**: `me.theguyhere.villagerdefense.plugin.game.models.kits.CustomKitManager` ```java // 初始化(插件启动时自动调用) public static void init(JavaPlugin plugin) // 从文件重载所有自定义套装 public static void reload() // 保存所有自定义套装到文件 public static void save() // 根据 ID 获取自定义套装 public static CustomKit getKit(String id) // 获取所有自定义套装 public static Collection<CustomKit> getAllKits() // 添加或更新自定义套装 public static void addKit(CustomKit kit) // 删除自定义套装 public static void removeKit(String id) // 检查套装是否存在 public static boolean kitExists(String id) // 获取套装数量 public static int getKitCount() ``` ### `CustomKit` **包路径**: `me.theguyhere.villagerdefense.plugin.game.models.kits.CustomKit` ```java // 构造方法 public CustomKit(String name, ItemStack icon) // Getter/Setter public String getId() public String getName() public void setName(String name) public ItemStack getIcon() public void setIcon(ItemStack icon) public List<String> getDescription() public void setDescription(List<String> desc) public ItemStack[] getArmor() // [boots, leggings, chestplate, helmet] public void setArmor(ItemStack[] armor) public List<ItemStack> getItems() public void setItem(int slot, ItemStack item) public List<PotionEffect> getEffects() public void setEffects(List<PotionEffect> effects) public boolean isEnabled() public void setEnabled(boolean enabled) public int getPrice() // 水晶价格(0 = 免费) public void setPrice(int price) // 序列化 public Map<String, Object> serialize() // 反序列化 public static CustomKit deserialize(Map<String, Object> data) ``` ### `ChestCommandsHook` **包路径**: `me.theguyhere.villagerdefense.plugin.api.ChestCommandsHook` ```java // 初始化钩子(插件启动时自动调用) public static void init() // 检查 ChestCommands 是否已连接 public static boolean isEnabled() // 执行 VD 动作 public static void executeAction(Player player, String action) // 获取 ChestCommands 插件实例 public static Plugin getChestCommands() ``` ### `PlayerManager` (新增持久化方法) ```java // 保存玩家选定套装 public static void saveSelectedKit(VDPlayer vdPlayer) // 加载玩家选定套装 public static String loadSelectedKit(Player player) ``` ### `GiftCodeManager` **包路径**: `me.theguyhere.villagerdefense.plugin.tools.GiftCodeManager` ```java // 初始化(插件启动时自动调用) public static void init() // 查询 public static List<String> getAllCodes() public static boolean codeExists(String code) public static int getDiamonds(String code) public static String getKitName(String code) public static int getMaxUses(String code) public static int getUses(String code) public static int getPerPlayer(String code) public static long getExpiry(String code) // 毫秒时间戳,0 = 永久 public static boolean isExpired(String code) public static boolean hasBroadcast(String code) public static boolean isDailyCode(String code) // 管理 public static void createCode(String code, int diamonds, String kitName, int maxUses, int perPlayer) public static void deleteCode(String code) public static void renameCode(String oldCode, String newCode) public static void setDiamonds(String code, int value) public static void setKit(String code, String kitName) public static void setMaxUses(String code, int value) public static void setPerPlayer(String code, int value) public static void setExpiry(String code, long expiry) public static void setBroadcast(String code, boolean broadcast) public static void setDaily(String code, boolean daily) // 领取 public static boolean redeem(Player player, String code) public static int redeemDaily(Player player) // /kit daily,返回状态码 ``` ### `PointsManager` **包路径**: `me.theguyhere.villagerdefense.plugin.tools.PointsManager` ```java public static int getPoints(Player player) public static int getPoints(String uuid) public static void addPoints(Player player, int amount) public static void setPoints(Player player, int amount) public static boolean spendPoints(Player player, int cost) // 余额不足返回 false 且不扣款 ``` ### `PointsShopManager` **包路径**: `me.theguyhere.villagerdefense.plugin.tools.PointsShopManager` ```java // 查询 public static List<Integer> getAllItems() public static boolean itemExists(int id) public static String getType(int id) // diamond / kit / item public static int getValue(int id) // 数量(或套装名存储于 material) public static int getCost(int id) // 所需积分 public static String getMaterial(int id) // item: Material 名;kit: 套装名 // 管理 public static int createItem(String type, int value, int cost, String material) public static void updateItem(int id, String type, int value, int cost, String material) public static void deleteItem(int id) // 兑换(1 成功 / 0 失败) public static int redeem(Player player, int id) ``` ### `MonsterAffix` **包路径**: `me.theguyhere.villagerdefense.plugin.game.models.MonsterAffix` ```java public static boolean isEnabled() public static List<String> getAffixes(LivingEntity ent) // 读取实体词缀(metadata VD_AFFIX) public static boolean hasAffix(LivingEntity ent, String name) public static void applyRandomAffixes(LivingEntity entity, Arena arena) public static void tickAffix(Mob mob, Arena arena) // 护盾恢复 / 传送,实体级任务驱动 public static void onAttack(Mob mob, LivingEntity victim) // 吸血 / 点燃 public static void onDeath(LivingEntity entity) // 死亡爆炸 + 死亡地面效果 ``` 支持词缀:`speed`(急速)、`shield`(护盾)、`explosive`(爆炸)、`teleport`(传送)、`lifesteal`(吸血)、`fire`(燃烧)。 **精英词缀互动(死亡地面效果)**:`explosive` 怪死亡后在原地留下灼烧地面(`fire` 类型,火焰粒子 + 伤害),`poison` 怪死亡后留下毒素云(绿色粒子 + 剧毒效果),通过 `AreaEffectCloud` 实现(自动消散,无需清理任务)。同一区域最多同时存在 3 片,配置见 `affixes.groundEffects`。 ### `VillagerProfession` **包路径**: `me.theguyhere.villagerdefense.plugin.game.models.VillagerProfession` ```java // 为村民按 config 概率随机分配职业,并注册实体级光环任务(村民死亡自动失效) public static void assign(Arena arena, Villager villager) // 在名称/血条后追加职业标签(供血条刷新时保留职业显示) public static String withProfessionTag(LivingEntity entity, String baseName) ``` 支持职业(`villagerProfession.pool`): | 职业代码 | 名称 | 光环效果 | |---------|------|---------| | `farmer` | 农夫 | 饱和度 | | `cleric` | 牧师 | 生命恢复 | | `blacksmith` | 铁匠 | 抗性提升 | | `librarian` | 图书管理员 | 速度提升 | 职业村民存活期间持续为周围玩家(`villagerProfession.radius`)施加光环,村民倒下后光环立即失效。 ### `Mobs`(好奇村民 / 生成) **包路径**: `me.theguyhere.villagerdefense.plugin.game.models.Mobs` ```java // 生成村民:赋职业(VillagerProfession.assign)+ 按概率打上好奇标记 VD_CURIOUS // 并注册实体级跟随任务(村民失效自动取消) public static void setVillager(Arena arena, Villager villager) // 在名称/血条后追加【好奇】标签(血条刷新时保留),非好奇村民原样返回 public static String withCuriousTag(LivingEntity entity, String baseName) ``` **好奇村民机制**(配置 `villagers` 段,详见第 10 章): - **生成**:`setVillager` 中按 `villagers.curiousChance` 概率(0~1,默认 0.2)决定是否赋予 `VD_CURIOUS` 标记。只有命中的村民才: - 名字追加 **【好奇】** 标签(血条刷新通过 `withCuriousTag` 保留) - 注册实体级跟随任务(`curiousIntervalTicks` 间隔刷新,默认 60 秒一次),跟随 24 格内最近的有效玩家;已贴近 3 格内不重复寻路;优先走管理员预设路径,失败退回直线导航(`curiousFollowSpeed` 悠闲速度) - **右键驱离**(`GameListener.expelCuriousVillager`,`PlayerInteractEntityEvent`):玩家右键好奇村民将其驱离—— - 驱离后村民打上 `VD_EXPELLED` 标记并受到 `villagers.scareDamage` 伤害(默认 5 点,可能致死) - 村民在 `villagers.scareDurationSeconds`(默认 120 秒)内不再跟随玩家(`VD_SCARED` 冷却) - 每位玩家的驱离有 `villagers.expelCooldownSeconds`(默认 240 秒)冷却 - **驱离致死惩罚**:村民带 `VD_EXPELLED` 死亡时按 `morale.expelKillPenalty`(默认 10)扣民心,高于普通村民死亡的 `morale.villagerDeathPenalty`(默认 8) - 好奇与职业相互独立:一只村民可同时是【好奇】且带职业 ### `TurretManager` / `TurretType` **包路径**: `me.theguyhere.villagerdefense.plugin.game.models.turrets.TurretManager` / `...turrets.TurretType` ```java // 每名玩家可同时放置的塔数量上限(turrets.capPerPlayer) public static int getCap() // 塔可升级到的最高等级(turrets.maxLevel) public static int getMaxLevel() // 将塔从当前等级升级到下一级所需绿宝石(turrets.upgradeBaseCost * level) public static int getUpgradeCost(TurretType type, int currentLevel) // 尝试升级塔:校验余额并扣费、提升等级、更新可视化标记(成功返回 true) public static boolean upgradeTurret(Arena arena, Player owner, Turret turret) // 根据物品显示名识别塔类型(覆盖全部 6 种塔) public static TurretType getTurretType(ItemStack item) // 放置塔:生成可视化盔甲架标记 + 注册区域驱动任务,上限已满返回 false public static boolean placeTurret(Arena arena, Player owner, TurretType type, Location loc) ``` `TurretType` 枚举:`ARROW` / `LIGHTNING` / `BOMB` / `FLAME` / `FROST` / `HEALING`。 **直接建造流程**:手持绿宝石右键方块(`GameListener`,需在竞技场边界内)→ 记录目标位置到玩家 metadata `VD_BUILD_LOC` → `Inventories.createTurretBuildMenu(Arena)` 打开建造菜单 → 点击塔(`InventoryListener.TURRET_BUILD_MENU` 分支)→ `canAfford` 检查 → `placeTurret` → 成功才 `addGems(-cost)` 扣费。余额不足提示后自动关闭菜单;塔数上限失败不扣费。 **塔升级流程**:塔主右键塔(`GameListener.onTurretInteract`,检测 `PlayerInteractAtEntityEvent` + ArmorStand 上的 `turret`/`VD` metadata)→ 满级/余额不足分别提示 → `upgradeTurret` 扣费升级。 **塔链协同**(塔 tick 内自动生效): - `countSameTypeNearby`:统计相邻 `turrets.synergy.range` 格内同类型塔 - 同类型协同:伤害/治疗 × `(1 + 相邻塔数 × bonusPerLevel)`;减速等级 +1/级 - **熔毁联动**:带 SLOWNESS 效果的怪物被火焰塔命中,伤害 × `meltdownMultiplier` - 等级缩放:伤害/治疗 ×1.2^(level-1),射程 ×1.1^(level-1),冷却 ×0.9^(level-1) ### `Arena`(波次惩罚 / 幸存者奖励相关) **包路径**: `me.theguyhere.villagerdefense.plugin.game.models.arenas.Arena` ```java // 村庄绝望(波次惩罚)状态 public int getVillagersKilledThisWave() // 本波已死亡村民数 public void incrementVillagersKilledThisWave() // 村民死亡时 +1 public void resetVillagersKilledThisWave() // 新波开始清零 public int getDespairStacks() // 当前绝望层数 public int addDespair() // 叠加绝望(上限 despair.maxStacks) public void clearDespair() // 游戏重置时清零 public double getDespairMultiplier() // 1 + 层数 * despair.perStackMultiplier ``` - 村民每死 1 名:绝望层数 +1,全场广播(`messages.villageDespair`) - 新生成的原版与 MythicMobs 怪物按 `getDespairMultiplier()` 等比放大 MaxHealth/AttackDamage(`Mobs.applyDespairScaling`) - 新波开始 `resetVillagersKilledThisWave()`,用于"完美防守"判定(本波死亡数为 0) - 完美防守奖励 `survivorReward.perfectDefenseBonus`;游戏胜利按幸存村民数奖励 `survivorReward.winVillagerBonus` ### `Arena`(村庄民心 / 适应性进化 / 悬赏波相关) **包路径**: `me.theguyhere.villagerdefense.plugin.game.models.arenas.Arena` ```java // 村庄民心(正向机制,0~100) public int getMorale() // 当前民心值 public void addMorale(int change) // 调整民心(上限 morale.maxMorale) public double getMoraleMultiplier() // 1 + (民心/上限) * morale.rewardMultiplier // 怪物适应性进化(伤害类型: fire/arrow/explosion/magic) public void countAdaptation(String type) // 记录一次该类型击杀 public int getAdaptationLevel(String type) // 当前抗性等级(击杀数/阈值,封顶 maxLevel) public double getAdaptationResistance(String type) // 抗性减免比例(level * resistancePerLevel) public void resetAdaptation() // 新局清零 // 悬赏精英波 public boolean isBountyWave() public void setBountyWave(boolean bountyWave) public boolean consumeBounty() // 悬赏波第一只普通怪消耗名额(成为悬赏目标) ``` - **民心**:村民死亡 -`morale.villagerDeathPenalty`(`GameListener`),完美防守 +`morale.perfectWaveGain`(`ArenaListener`);波次清怪奖励与胜利幸存奖励按 `getMoraleMultiplier()` 缩放 - **适应性**:`GameListener.onMobKill` 按 `getLastDamageCause()` 计数;`Mobs.applyAdaptationResistance` 给新怪打 `VD_ADAPT_<TYPE>` metadata;`GameListener.onHurt(EntityDamageEvent)` 按等级减免伤害(上限 80%) - **悬赏波**:`ArenaListener.onWaveStart` 在 `currentWave % bounty.everyNWaves == 0` 时开启并广播;`Mobs.setMinion` 中 `consumeBounty()` 命中时标记 `VD_BOUNTY`(血量 ×1.5、名字加 `messages.bountyTag`);击杀奖励见 `GameListener.onMobKill` ### `VDPlayer`(线程安全) **包路径**: `me.theguyhere.villagerdefense.plugin.game.models.players.VDPlayer` ```java // 以下两个方法已声明为 synchronized,对同一实例的余额读写互斥, // 消除 Folia 多区域线程(怪物击杀线程 vs 玩家点击线程)下的 read-modify-write 竞态 public synchronized void addGems(int change) // 正数增加、负数扣除(Vault 绑定则同步到 Vault) public synchronized boolean canAfford(int cost) // 余额是否足够(Vault 绑定则读取 Vault 余额) ``` 建造/购买扣费顺序保证:先 `canAfford` → 再放置/校验 → **成功才 `addGems(-cost)`**,快速双击不会重复扣费、余额不会变负。 --- ## 9. ChestCommands 集成 ### 概述 插件通过 `ChestCommandsHook` 类提供与 ChestCommands 的集成。当检测到 ChestCommands 插件时,自动注册 [vd] 动作类型。 ### 在 ChestCommands 菜单中使用 在 ChestCommands 菜单配置中,使用 `[vd] <action>` 动作: ```yaml # 打开默认套装选择菜单 example_item: material: DIAMOND name: "&b选择默认套装" lore: - "&7点击选择你的默认套装" actions: - "[vd] defaultkit" # 打开管理面板 admin_item: material: COMMAND_BLOCK name: "&c管理面板" lore: - "&7点击打开管理面板" actions: - "[vd] admin" # 打开自定义套装管理 custom_kits_item: material: CHEST name: "&6管理自定义套装" lore: - "&7点击管理自定义套装" actions: - "[vd] customkits" ``` ### 可用动作列表 | 动作 | 说明 | |------|------| | `[vd] defaultkit` | 打开默认套装选择菜单 | | `[vd] admin` | 打开管理面板主菜单 | | `[vd] customkits` | 打开自定义套装管理菜单 | ### 通过 PlaceholderAPI 集成 插件提供以下 PAPI 变量(可用于 ChestCommands 菜单显示): | 变量 | 说明 | |------|------| | `%villagerdefense_selectedkit%` | 玩家当前选定的默认套装名 | | `%villagerdefense_arena_<name>_status%` | 竞技场状态 | | `%villagerdefense_arena_<name>_players%` | 竞技场玩家数 | | `%villagerdefense_crystals%` | 玩家水晶余额 | | `%villagerdefense_kills%` | 玩家总击杀数 | | `%villagerdefense_topwave%` | 玩家最高波次 | --- ## 10. 配置文件参考 ### `config.yml` 主要配置文件,新增的配置段: ```yaml # 怪物自定义属性设置 monsterSettings: enabled: false globalHealthMultiplier: 1.0 globalDamageMultiplier: 1.0 globalSpeedMultiplier: 1.0 difficultyScalingMultiplier: 1.0 perMob: zomb: health: 1.0 damage: 1.0 speed: 1.0 babyChance: 1.0 equipmentBoost: 0 # 怪物 AI 设置 monsterAI: enabled: true targetUpdateInterval: 3 villagerSearchRange: 30 prioritizeVillagers: true doorBreaking: true # 怪物会破坏门(地面挖掘 / 飞行撞门) doorBreakCooldown: 30 # 破门冷却(秒),每只怪独立计时 # 怪物词缀设置 affixes: enabled: true # 是否启用词缀 chance: 0.15 # 精英怪携带词缀概率(0.0-1.0) maxPerMob: 2 # 每只怪最多词缀数 blindDurationTicks: 50 # 致盲词缀失明时长(tick,上限 200) # 精英词缀互动:携带特定词缀的怪物死亡后留下地面效果区域 groundEffects: enabled: true # 是否启用死亡地面效果 fireRadius: 3 # 爆炸怪灼烧地面半径(方块) fireDurationTicks: 200 # 灼烧地面持续时长(tick) poisonRadius: 3 # 剧毒怪毒素云半径(方块) poisonDurationTicks: 200 # 毒素云持续时长(tick) # 波次惩罚(村庄绝望):村民死亡叠加绝望层数,后续生成怪物属性等比提升 despair: enabled: true # 是否启用波次惩罚 maxStacks: 10 # 绝望层数上限 perStackMultiplier: 0.05 # 每层绝望的怪物属性加成(1 + 层数 * 系数) # 幸存者奖励 survivorReward: perfectDefense: true # 完美防守:本波无村民死亡则奖励 perfectDefenseBonus: 50 # 完美防守奖励绿宝石数 winVillagerBonus: 15 # 游戏胜利时每名幸存村民奖励绿宝石数 # 村庄民心系统(正向机制) morale: enabled: true # 是否启用 initialMorale: 50 # 每局初始民心 maxMorale: 100 # 民心上限 perfectWaveGain: 5 # 完美防守时民心提升量 villagerDeathPenalty: 8 # 村民死亡时民心下降量 expelKillPenalty: 10 # 玩家驱离【好奇】村民致死的额外民心惩罚 rewardMultiplier: 0.5 # 满民心时奖励倍率加成(1 ~ 1+0.5) # 怪物适应性进化 adaptation: enabled: true # 是否启用 threshold: 6 # 每击杀 N 只同来源怪物升一级抗性 maxLevel: 2 # 抗性等级上限 resistancePerLevel: 0.2 # 每级抗性的伤害减免比例 # 悬赏精英波 bounty: everyNWaves: 5 # 每隔 N 波出现悬赏目标 reward: 150 # 击杀悬赏目标的全队绿宝石奖励 # 村庄节日 festival: enabled: true # 是否启用节日波 chance: 0.15 # 每波触发概率(0.0-1.0) gemMultiplier: 0.5 # 节日波奖励额外加成(0.5 = +50%) # 村民生成节奏与特殊属性(好奇村民) villagers: # 每隔多少回合生成一批村民(2 = 每两回合一批) spawnIntervalWaves: 6 # 每批生成的村民数量 perInterval: 4 # 村民带【好奇】属性的概率(0.0 - 1.0,0.1 = 10%) curiousChance: 0.1 # 【好奇】村民刷新跟随目标玩家的间隔(tick,1200 = 每 60 秒一次,其余时间自由闲逛) curiousIntervalTicks: 1200 # 【好奇】村民跟随玩家的移动速度倍率(1.0 = 正常速度,0.8 = 悠闲半速) curiousFollowSpeed: 0.8 # 右键驱离【好奇】村民:驱离后指定秒数内不再跟随玩家,但会对该村民造成伤害 # (0 表示不启用驱离功能) scareDurationSeconds: 120 # 每玩家驱离【好奇】村民的冷却秒数(0 = 无冷却) expelCooldownSeconds: 240 # 驱离【好奇】村民对其造成的伤害(伤害可能致死村民) scareDamage: 5 # 村民死亡后的深红色腐蚀云:踏入的玩家受到缓慢 I、虚弱 II、中毒 I deathCloud: enabled: true radius: 3 durationTicks: 60 # 村民内鬼:隐藏内鬼持续给附近玩家施加减益,可被攻击,击杀提升民心+全队增益 mole: enabled: true # 是否启用内鬼机制 chance: 0.05 # 每只村民成为内鬼的概率(0.05 = 5%) debuffIntervalTicks: 100 # 减益施加间隔(tick) debuffRadius: 10 # 减益作用半径(方块) killMoraleBonus: 15 # 击杀内鬼的民心提升 killBuffDurationTicks: 300 # 击杀后全队增益时长(tick,300 = 15 秒) # 村民职业体系:村民随机获得职业,存活期间为周围玩家提供光环 villagerProfession: enabled: true # 是否启用职业体系 chance: 0.8 # 村民获得职业的概率(0.0-1.0) pool: # 职业池(farmer/cleric/blacksmith/librarian) - farmer - cleric - blacksmith - librarian radius: 30 # 光环作用半径(方块) intervalTicks: 60 # 光环刷新间隔(tick) amplifier: 0 # 光环药水效果等级(0 = 一级) # 防护塔系统设置 turrets: enabled: true # 是否启用防御塔/陷阱系统 capPerPlayer: 3 # 每名玩家同时最多放置的塔数量 tickInterval: 5 # 塔行为刷新周期(tick) # 箭塔 arrowRange: 12 arrowDamage: 4 arrowCooldownTicks: 30 arrowKnockback: 1 # 闪电塔 lightningRange: 10 # 射程 lightningDamage: 12 # 单体伤害(无视护甲) lightningCooldownTicks: 40 # 攻击间隔(tick) # 爆炸陷阱 bombTriggerRange: 2.5 bombPower: 2 bombDamage: 10 bombDamageRange: 6 # 火焰塔 flameRange: 7 # 射程 flameDamage: 2 # 每次灼烧伤害 flameFireTicks: 40 # 点燃时长(tick) flameIntervalTicks: 20 # 灼烧间隔(tick) # 冰霜塔 frostRange: 7 # 射程 frostDurationTicks: 80 # 冻结时长(tick) frostAmplifier: 3 # 减速等级 # 治疗塔 healRange: 8 # 作用半径 healAmount: 2 # 每次治疗量 healIntervalTicks: 20 # 治疗间隔(tick) # 塔升级系统 maxLevel: 3 # 塔最高等级 upgradeBaseCost: 300 # 升级基础花费(费用 = 基础价 × 当前等级) # 塔链协同 synergy: enabled: true # 是否启用 range: 3 # 相邻判定半径(方块) bonusPerLevel: 0.25 # 每座相邻同类型塔的加成(伤害/治疗倍率) meltdownMultiplier: 1.5 # 熔毁联动:减速怪被火焰塔命中的额外伤害倍率 # 成就解锁套装映射(达成成就自动解锁自定义套装) achievementKitRewards: # 成就ID: 自定义套装名称 # topKills9: "精英战士" # 游戏节奏 shopUpgradeWaves: 10 # 商店每 N 波升级 intermissionTime: 15 # 波次间休息秒数 # 经济设置 economy: waveInterestRate: 0.05 # 波次利息 killStreakInterval: 5 # 连杀加成间隔 killStreakBonus: 2 # 连杀奖励基础值 vaultBinding: true # 绿宝石与 Vault 经济绑定 lateJoinGemPercent: 0.75 # 中途入场补偿比例(原局内玩家平均值的百分比,0.75 = 75%) bank: # 股票式投资(/vd bank) enabled: true # 是否启用银行 baseRate: 0.03 # 每波基础利率(实际利率 = 基础利率 × 民心倍率) # 禁用合成表(竞技场内玩家禁止合成,防止合成非法物品) disableCrafting: enabled: true # 是否禁用竞技场内玩家的合成 # 目标波次(护送/据点) objectiveWaves: enabled: true # 是否启用目标波次系统 startWave: 4 # 从第几波开始可能触发 interval: 5 # 每隔多少波触发一次 escortReward: 200 # 护送目标奖励(绿宝石) escortHighlightCenter: true # 护送波高亮村庄中心点 escortArrivalRadius: 3.0 # VIP 村民到达中心多少格内视为完成 escortFailMoralePenalty: 15 # 护送失败(VIP 死亡)民心惩罚 # MythicMobs 联动设置 mythicMobsIntegration: mode: 3 mixChance: 0.4 mobMappings: zomb: "CustomZombie" skel: "CustomSkeleton" bossMappings: w: "MythicWitherBoss" # 每日签到设置(/vd sign) signIn: enabled: true # 是否启用每日签到 reward: 50 # 每次签到奖励的水晶数量 ``` ### 新增玩法机制(26.1.2) 以下机制不新增配置项,行为固定在代码中(部分受上表既有配置控制): #### 全员村民仇恨 - 所有竞技场怪物都会主动攻击村民,包括:原版怪物、MythicMobs 精英/Boss、以及词缀「召唤」产生的仆从。 - 机制:每只怪物生成时注册实体级 AI 任务(`MonsterAI.attachEntityAITask`),在怪物自身区域线程上周期性执行 `MonsterAI.tickMonster`;村民优先模式(`monsterAI.prioritizeVillagers: true`)下怪物会优先追击最近村民,仅玩家进入 5 格内才会临时转移仇恨。 - `monsterAI.enabled` 默认值为 `true`(缺省配置时也默认开启)。 #### 幻翼固定伤害 - `Mobs.setPhantom` 将幻翼攻击力基准值覆写为 2(原版为 6);波次/难度加成仍作为属性修饰符叠加。 #### 宠物击杀奖励归属 - 玩家召唤的狼(`Wolf`)或铁傀儡(`IronGolem`)击杀怪物时,绿宝石奖励、击杀计数、经验、击杀连击均直接结算给**召唤者**(而非宠物)。 - 实现:铁傀儡生成时记录 `VD_OWNER` 元数据(召唤者 UUID);狼通过原版 `getOwner()` 获取主人。宠物击杀统计在 `GameListener.onMobKillByPlayer` 中按召唤者结算。 - 注意:铁傀儡生成 API 签名已改为 `Mobs.setGolem(Main plugin, Arena arena, Player owner, IronGolem golem)`。 #### 中途入场补偿 - 游戏进行中(允许迟到加入的竞技场)加入的非回归玩家,在入场时获得**场上所有其他玩家当前绿宝石余额平均值的 75%**(`int` 向下取整,余额为 0 时不发放)。比例由 `economy.lateJoinGemPercent` 配置(默认 0.75,0 = 关闭,1 = 与原平均值相同)。 - 「回归玩家」(掉线保护生效、回到同一竞技场)**不获得**该补偿,改为恢复掉线前保存的绿宝石余额与全部物品(`disconnectProtection` 配置,见上)。 #### 入场选择套装 - 中途加入的非回归玩家进入竞技场后会**先打开套装选择菜单**,选择(或直接关闭)后自动发放该局装备(`Tasks.giveItems`)。 - 回归玩家跳过选择,直接恢复掉线前的装备。 - 实现:加入时给玩家打上 `VD_PENDING_LOADOUT` 元数据并打开 `SELECT_KITS_MENU`;`InventoryListener.onClose` 在菜单关闭时检测该标记并发放装备。 #### 难度水晶加成 - 游戏结束(胜利/失败)结算水晶时,按竞技场难度标签额外加成:每级难度 +10%,四档难度对应: | 难度标签 | 难度倍率 | 水晶加成 | |----------|---------|---------| | Easy(简单) | 1 | +10% | | Medium(普通) | 2 | +20% | | Hard(困难) | 3 | +30% | | Insane(噩梦) | 4 | +40% | - 加成基数 = 基础结算水晶(波次 + 击杀 + 绿宝石折算),与挑战加成(`bonus`)独立计算、一并发放,通知文案显示 `基础 (+挑战加成+难度加成)`。 #### 假死防护 - 修复「部分生物血量归零后进入假死状态不断抽搐、无法强制杀死」的问题,三层防护: 1. 死亡事件(`EntityDeathEvent`)处理器整体 try/catch 兜底,任何异常都不会中断实体正常死亡移除流程; 2. 受伤结算时若基础血量将被打到 0,立即解除吸收值(护盾/悬赏护盾),保证致死一击真正致死; 3. `MonsterAI.tickMonster` / `MonsterAffix.tickAffix` 检测到血量 ≤ 0 的存活实体时,解除吸收并补上致死伤害(不再被「护盾」「再生」词缀复活)。 - 后果:精英怪(含护盾/悬赏词缀)的致死一击不再被吸收值"无限拖延",战斗手感更稳定。 #### 村民假死防护 - 同样的「倒地抽搐、无法死亡」问题也会发生在村民身上。`Mobs.setVillager` 现在为每名村民注册实体级假死守护任务(每 20 tick 检查一次):一旦检测到血量 ≤ 0 却仍存活的村民,先解除吸收值并补上致死伤害,兜底直接 `remove()`,保证村民一定能被正常移除(死亡结算、绝望/民心惩罚不再卡住)。 #### 召唤物伤害规则修复 - 修复「部分召唤物被怪物攻击后不掉血」:`GameListener.onSummonEnvironmentDamage` 之前把**所有** `EntityDamageEvent`(含实体攻击子类)一律取消,导致怪物近战/弹射物伤害也被误拦截。 - 现在环境伤害处理器只处理环境来源(坠落/岩浆/火焰/溺水/窒息/仙人掌/雷击/中毒/凋零等);`EntityDamageByEntityEvent` 交给 `onFriendlyFire` 判定,怪物及怪物弹射物可正常伤害召唤物,玩家/友好误伤仍被拦截。 #### QA 枪械无伤刷钱防护 - 修复「QA 枪械攻击蜜蜂(召唤物)无伤害却刷钱」:`GameListener.onMobKillByPlayer` 现在(1)在结算击杀奖励前检查事件是否已被取消(召唤物保护会取消该伤害);(2)将村民与全部玩家召唤物(狼/铁傀儡/雪傀儡/蜜蜂/猫)排除出「可击杀怪物」判定,杜绝把召唤物当怪物结算绿宝石/击杀数。 #### 村民等级显示修复 - 修复村民升级后名字累积显示「Lv2 Lv3 Lv4 Lv5」:`Mobs.withGrowthTag` / `withCuriousTag` 在追加标签前先剥离旧有的同类标签(等级标签 /【好奇】标签与好感爱心),做到幂等,波次升级与喂食好感不再叠加重复标签。 #### 怪物词缀致盲时长上限 - 致盲词缀(`blind`)造成的失明时长改为 `affixes.blindDurationTicks` 配置(默认 50 tick = 2.5 秒),并硬性上限 200 tick(10 秒),避免数值异常导致失明「永久保留」。 #### 禁用合成表 - 新增 `CraftingListener`:竞技场内玩家(等待/进行中)禁止合成任何物品(工作台与背包合成均拦截),防止绕过绿宝石经济与套装系统合成非法物品。由 `disableCrafting.enabled`(默认 `true`)控制,仅作用于竞技场内玩家。 #### 护送波(VIP 村民)重做 - VIP 村民现在会**高亮村庄中心点**(粒子光束提示,`objectiveWaves.escortHighlightCenter`,默认开启)。 - VIP 村民会**指定锁定一名活跃玩家作为护送者**并单独提示该玩家;其余玩家收到含护送者名字的提示。 - VIP 村民会**一直跟随该护送者**(护送者离线/离开时退回朝村庄中心直行),直到被带到村庄中心后**消失**并结算全队奖励。到达判定半径由 `objectiveWaves.escortArrivalRadius` 配置(默认 3 格)。 ### `custom_kits.yml` 自定义套装数据文件(自动创建,无需手动编辑): - 路径:`plugins/VillagerDefense/custom_kits.yml` - 通过管理员 GUI 自动管理 - 所有 ItemStack 数据使用 Base64 编码 - 每个套装包含 `price` 字段(水晶价格,0 = 免费) ### `playerData.yml` 玩家数据文件: - `selectedKit` 键存储玩家默认套装名(通过 `/vd defaultkit` 自动管理) - `crystalBalance` 键存储玩家水晶余额(通过 `/vd crystals` / `/vd sign` / 购买自定义套装管理) - `lastSignIn` 键存储最近签到日期(`yyyy-MM-dd`,通过 `/vd sign` 管理) - `points` 键存储玩家积分(通过击杀怪物获得,`/vd shop` 消费) - `dailyGift` 键存储最近领取每日礼包日期(`yyyy-MM-dd`,通过 `/kit daily` 管理) - `customKits.<id>` 键存储已解锁的自定义套装(购买 / 礼包 / 成就 / 积分商店都会写入) ```yaml <player-uuid>: selectedKit: "Mage" # 默认套装名 crystalBalance: 500 # 水晶余额 lastSignIn: "2026-08-04" # 最近签到日期 points: 120 # 积分余额(/vd shop 消费) dailyGift: "2026-08-12" # 最近领取每日礼包日期 kits: ... customKits: my_custom_kit: true ``` ### `giftcodes.yml` 礼包码数据文件(自动创建,通过主菜单 → 礼包设置 管理): ```yaml codes: <code>: # 礼包码(大写) diamonds: 100 # 赠送钻石 kit: "精英战士" # 赠送套装名(原版或自定义,含未开放;可空) maxUses: -1 # 总使用次数(-1 = 无限) perPlayer: 1 # 每人限用次数 uses: 0 # 已使用次数 expires: 0 # 过期时间戳(毫秒,0 = 永久) broadcast: false # 领取时全服公告 daily: false # 每日礼包标记(启用后 /kit daily 可领取) ``` - 内置 `DAILY` 码用于 `/kit daily`:玩家每天可领取一次(按玩家记录,不占用总次数) ### `pointsShop.yml` 积分商店兑换项数据文件(自动创建,通过主菜单 → 积分商店设置 管理): ```yaml items: <id>: type: "diamond" # diamond / kit / item value: 10 # 数量(diamond/item)或套装名(kit) cost: 10 # 所需积分 material: "DIAMOND" # item 类型的 Material 名称 / kit 类型的套装名 ``` --- ## 11. 构建指南 ### 环境要求 - Java 25+(`maven.compiler.source/target = 25`) - Maven 3.6+ ### 构建命令 ```bash # 完整构建所有模块 mvn clean install # 仅构建插件模块 mvn clean install -pl plugin # 快速编译(不运行测试) mvn compile -pl plugin -q # 打包完整插件 JAR mvn clean package -pl plugin ``` ### 输出 JAR 构建输出位于 `plugin/target/VillagerDefense-2.0.0.jar` ### NMS 模块说明 插件支持 Minecraft 1.21.x 与 26.x 全版本,使用多 NMS 子模块(打包时全部 shade 进单一 JAR,运行时按服务端版本反射加载): - 1.21.1 → `nms/v1_21_r1`、1.21.2/3 → `nms/v1_21_r2`、1.21.4 → `nms/v1_21_r3` - 1.21.5/6 → `nms/v1_21_r4`、1.21.7/8 → `nms/v1_21_r5` - 26.x → `nms/v1_26_r1`(纯 Mojmap,无版本包结构,适配 `ClientboundAddEntityPacket` 与 `Vec3.LP_STREAM_CODEC`) - 版本选择逻辑位于 `NMSVersion.java`,通过 `Bukkit.getBukkitVersion()` 解析并映射到对应 NMS 管理器 --- ## 12. 开发者扩展指南 ### 添加新的套装类型 ```java // 1. 在 Kit.java 中添加静态工厂方法 public static Kit myNewKit() { // 遵循现有 Kit 模式 } // 2. 在 LanguageManager.Kits 中注册语言字段 // 3. 在 en_US.yml / zh_CN.yml 中添加语言字符串 // 4. 在 Inventories.createSelectKitsMenu() 中添加 GUI 按钮 ``` ### 集成自定义商店物品 ```java // 使用 ItemManager 创建物品 ItemStack myItem = ItemManager.createItem( Material.DIAMOND_SWORD, "&bMy Custom Sword", "&7A custom sword for VD" ); // 在 Inventories.createCustomShopMenu() 中添加 ``` ### 扩展自定义套装系统 ```java // 通过 API 创建自定义套装 CustomKit kit = new CustomKit("Special Kit", new ItemStack(Material.DIAMOND_CHESTPLATE)); kit.setItem(0, new ItemStack(Material.DIAMOND_SWORD)); // 热键栏槽 0 kit.setItem(1, new ItemStack(Material.COOKED_BEEF, 16)); // 热键栏槽 1 kit.setDescription(Arrays.asList("Line 1", "Line 2")); kit.setEnabled(true); CustomKitManager.addKit(kit); CustomKitManager.save(); ``` ### 注册新的 ChestCommands 动作 ```java // 在 ChestCommandsHook.executeAction() 中添加新 case case "myaction": // 执行自定义逻辑 break; ``` ### 事件监听 插件使用 Bukkit 事件系统。监听自定义事件: ```java @EventHandler public void onJoin(JoinArenaEvent event) { Arena arena = event.getArena(); Player player = event.getPlayer(); // 自定义逻辑 } ``` 可用的事件: - `JoinArenaEvent` — 玩家加入竞技场 - `LeaveArenaEvent` — 玩家离开竞技场 - `GameEndEvent` — 游戏结束 - `WaveEndEvent` — 波次结束 - `StartGameEvent` — 游戏开始 --- *文档版本: 2.0.0* *最后更新: 2026-08-21* [/MD]
作者
Xiaochengsweet233
查看
61
首次发布
最后更新

评分

0.00 星 0 次评分

最新更新

  1. 插件架构以及玩法升级

    # 更新日志 (Changelog) ## 2.0.0 · 多版本支持与元数据批次 ### 🎉 版本与元数据 - **插件版本 26.1.2 → 2.0.0**:`plugin.yml`...
后退
顶部 底部