RandomForge（随机熔炉）使用说明 v1.1.1
==========================================

作者：非小酋啊、Hy3、WorkBuddy
适用版本：Terraria 1.4.5.6 / TShock 6.1 / .NET 9.0
插件文件：RandomForge.dll
配置文件（已合并为单一文件）：
  · RandomForge.json   —— 内含「随机事件」「随机掉落」「随机礼物」三节，首次启动自动生成

（v1.1.1 起不再拆分三份配置；旧的 RandomMayhem.json / RandomMancer.json / 随机礼物.json
 会在首次启动时自动合并迁移进 RandomForge.json，迁移后旧文件可手动删除。）


------------------------------------------------
〇、这是什么（关于"缝合"）
------------------------------------------------
RandomForge（随机熔炉）是把三个插件缝在一起的合体版本：

  · RandomMayhem（随机事件）v1.1.3
  · RandomMancer（随机掉落）v0.1.2
  · RandomGift（随机礼物）v1.0.0（原作者：答辩）

现在只占一个插件槽位，启动一次加载全部功能，配置也统一收纳进 **一个** RandomForge.json。


------------------------------------------------
一、配置文件（单一 RandomForge.json）
------------------------------------------------
结构如下（三个子节直接复用原有配置，键名仍为中文）：

{
  "随机事件": { ... 原 RandomMayhem.json 全部内容 ... },
  "随机掉落": { ... 原 RandomMancer.json 全部内容 ... },
  "随机礼物": { "是否启用": true, "间隔分钟": 5, "物品数量": 1, "提示消息": "……" }
}

  · 修改后使用 TShock 原生 /reload 即可整体生效（随机事件池、随机掉落黑名单、礼物定时器一并刷新）。
  · /rmtile、/rmnpc、/rmchest、/rmfish 四个开关指令的改动也写入同一个 RandomForge.json。
  · 首次启动时若检测到旧版拆分配置，会自动合并迁移并生成 RandomForge.json，无需手动搬运。


------------------------------------------------
二、触发机制
------------------------------------------------
合体后包含三套触发逻辑，互不干扰：

【随机事件】—— 主循环 Main.Update（每 tick）
  · 遍历在线玩家，先判定"玩家是否真的在做事情"（移动 / 攻击 / 使用道具 /
    蓄力拉弓 / 使用钩爪），站着发呆 → 不触发。
  · 活跃玩家按冷却限流 + 全局概率掷骰，命中后从 7 大类随机事件中按权重抽取一个执行。

【随机掉落】—— 四大来源的事件钩子
  · 物块破坏（挖矿/拆物块）、生物死亡、开宝箱、钓鱼钓上来 时触发随机掉落。

【随机礼物】—— 定时器的定时触发
  · 每隔「间隔分钟」分钟，给所有已登录玩家各发放「物品数量」个随机物品，并提示一句消息。

三套逻辑注册在同一个插件实例里，共用一套防御性 try-catch 兜底。


------------------------------------------------
三、指令一览
------------------------------------------------
/请求投资        （别名：/touzi、/invest）
  向你的【主背包】（仅 0~49 栏）发放一把带 [轻] 前缀的铜镐（Copper Pickaxe）。
  对所有玩家开放，无需权限节点；主背包满则提示"背包空间不足"。

/rmtile   [on/off]   —— 物块破坏随机掉落 开/关
/rmnpc    [on/off]   —— 生物随机掉落 开/关
/rmchest  [on/off]   —— 宝箱随机掉落 开/关
/rmfish   [on/off]   —— 钓鱼随机掉落 开/关
  以上四个均为开关指令，不带参数直接输入可查看当前状态；修改后立即在内存生效，
  并写入 RandomForge.json（/reload 后持久化）。

/reload
  原生指令。整体重载 RandomForge.json（随机事件 + 随机掉落 + 随机礼物），
  刷新全部缓存、随机池、权重预构建数组，并重启动时器，无需重启服务器。


------------------------------------------------
四、随机事件分类（共 7 类，按权重随机）
------------------------------------------------
1) 生物召唤
     在玩家附近召唤敌人 / Boss / 友好生物 / 城镇 NPC。支持"生物黑名单"过滤。
2) 物品变化
     按子行为权重：给予物品、减少物品、更改堆叠数量、更换物品 ID、随机合法修饰词。
     支持"物品黑名单"（默认已屏蔽 71/72/73 三类钱币）。
3) 血量蓝量变化
     按子行为权重：改变当前血量、当前蓝量、血量上限、蓝量上限。
     上限受 TShock config.json 的 MaxHP / MaxMP 硬限制；默认"扣血致死"关闭。
4) 插件额外弹幕
     由本插件生成的额外弹幕，owner 设为玩家自身，遵循同队免伤规则。
     受"弹幕黑名单/白名单"限制。
5) 增益减益
     随机施加增益或减益，单次最多数量可配，持续时间随机。支持"Buff黑名单"过滤。
6) 方块变化
     在玩家附近随机放置 / 移除 / 替换方块（按子行为权重）。
     · 安全约束：默认方块黑名单屏蔽箱子/祭坛/机关/巨石/炸药/地雷/蜂巢等 15 种关键方块。
     · 不破坏背景墙。放置/替换使用 TileID 1~200 范围内的方块。单次最多 20 格，半径 ≤5。
7) 天灾事件（带独立冷却，默认 300 秒）
     · 流星雨 / 陨石雨 / 巨石雨（所有在线玩家上方落巨石）/ 暴雨 / 暴雪 / 沙尘暴。


------------------------------------------------
五、随机掉落分类（四大来源）
------------------------------------------------
1) 物块破坏随机   —— 挖矿/拆物块时，按概率额外（或完全）掉落随机物品
2) 生物随机       —— 所有 NPC（敌对怪、友好生物、Boss）死亡时，按概率额外（或完全）掉落随机物品
3) 宝箱随机       —— 打开宝箱时箱内内容被随机化（每个宝箱只随机化一次，重复打开内容一致）
4) 钓鱼随机       —— 钓上来的物品纯随机（声纳药水也会显示随机物品）

每个来源都有独立的开关、掉落概率、随机黑名单；所有来源的"随机物品"还可统一配置
最小/最大堆叠、是否允许钱币。

【重要】Boss 类始终保留原掉落（含宝藏袋），即使开启"阻止原掉落"也只会在原掉落之外
额外叠加随机物品，绝不吞掉 Boss 掉落。


------------------------------------------------
六、随机礼物（定时给在线玩家发随机物品）
------------------------------------------------
由「随机礼物」插件（原作者：答辩）并入，配置在 RandomForge.json 的「随机礼物」一节：

  · 是否启用    —— 总开关（默认 true）
  · 间隔分钟    —— 每隔多少分钟发放一次（默认 5）
  · 物品数量    —— 每次给每位玩家发放几个随机物品（默认 1）
  · 提示消息    —— 发放时向玩家显示的提示前缀

机制说明：
  · 使用 System.Timers.Timer 定时触发；回调运行在线程池线程，内部通过
    Main.QueueMainThreadAction 回到游戏主线程再操作玩家，避免跨线程异常。
  · 只发给已登录（IsLoggedIn）的在线玩家，每人发放一个 1~6144 范围内的随机物品 ID，
    并发送提示消息（含物品名）。
  · 不做钱币/黑名单过滤（与原「随机礼物」行为一致）；如不需要某个物品，可在配置里
    关闭「是否启用」或调大「间隔分钟」。
  · 修改 RandomForge.json 后使用 /reload 即可重启动时器生效。


------------------------------------------------
七、稳定性说明（继承自三个前身的所有加固 + 本次修复）
------------------------------------------------
· 【加载健壮性】Initialize 对 Main.player 为 null 或长度异常做了空值守卫；
  随机池构建整体包裹 try-catch，遇异常仅降级（对应类型事件不触发），绝不让插件初始化失败。
· 【★ 加载顺序修复（v1.1.1）】原代码在"构建随机池"之前就构建了事件权重数组，
  导致彼时随机池为空，生物召唤 / 物品变化 / 弹幕 / 增益 / 方块 五类事件权重被判定为 0，
  **这五类事件永远不会触发**（只有血量蓝量和天灾会触发）。现修正为"先 BuildPools 再
  RefreshCaches"，启动日志会打印"已启用 7 类事件"，可供一眼确认全部事件已就绪。
· 【SyncSlot 修正】物品同步包 NetMessage.SendData(MsgID=5 / PlayerSlot) 参数顺序已修正为
  （number=玩家索引, number2=槽位）。这是此前生产事故的精确根因：参数写反会向客户端发送
  指向错误玩家/槽位的非法物品同步包，导致该玩家客户端崩溃/断线，并可能因状态错乱而无法
  重新连入，甚至使服务器主线程异常卡死在重启流程。
· 【主循环加固】Main.Update 每 tick 处理逻辑整体包裹 try-catch，且当 Main.player 长度
  与内部冷却数组长度不一致时自动安全重建，杜绝未捕获异常外泄。
· 【子行为加权修复】方块变化事件此前加权抽取结果被丢弃（永远只执行"放置方块"），现已正确
  按权重随机抽中子行为。
· 【随机掉落钩子兜底】物块破坏 / 生物死亡 / 开箱 / 钓鱼判定 / 钓鱼给物品 五个钩子全部包裹
  try-catch；异常只记录日志、不外泄，且对"阻止原掉落"类钩子出错时会复位 ContinueExecution，
  即"宁可放过原版掉落，也绝不因为异常把玩家本该掉的东西吞掉"。
· 【随机礼物兜底】定时器回调内部对每位玩家单独 try-catch，单名玩家发放异常不影响他人；
  间隔分钟非法（≤0）或关闭时不会启动定时器，避免 Timer 抛异常；所有配置读写均带容错。
· 该插件不直接修改世界文件，也不与 TShock 原生 /i（给予物品）指令交互。


------------------------------------------------
八、更新日志
------------------------------------------------
v1.1.1（配置合一 + 修复事件触发顺序 bug）
  · 三份拆分配置（RandomMayhem.json / RandomMancer.json / 随机礼物.json）合并为单一
    RandomForge.json，内含「随机事件」「随机掉落」「随机礼物」三节；旧拆分配置首次启动
    时自动合并迁移，无需手动搬运。/rmxxx 开关与 /reload 均作用于该单一文件。
  · 修复历史遗留的加载顺序 bug：原代码在"构建随机池"之前就构建事件权重数组，导致生物召唤 /
    物品变化 / 弹幕 / 增益 / 方块 五类事件因随机池为空而永不触发（仅血量蓝量与天灾会触发）。
    现改为先 BuildPools 再 RefreshCaches，启动日志明示"已启用 7 类事件"，确认全部就绪。
  · 插件版本升至 v1.1.1。

v1.1.0（缝合第三名成员：随机礼物）
  · 将 RandomGift（随机礼物 v1.0.0，原作者：答辩）并入：定时给所有在线玩家发放随机物品。
  · 新增独立配置 随机礼物.json。/reload 同时重载三套配置并重启动时器。

v1.0.0（缝合首发）
  · 将 RandomMayhem（随机事件 v1.1.3）与 RandomMancer（随机掉落 v0.1.2）合并为单一插件
    RandomForge（随机熔炉），只占一个插件槽位，保留两份独立配置文件。
  · 完整保留全部指令与两个前身的全部稳定性加固。

（以下为三个前身在合并前各自的最后版本要点，供溯源）
  RandomMayhem v1.1.3：加载路径加固。
  RandomMancer v0.1.2：五大事件钩子全部加防御性 try-catch 兜底。
  RandomGift v1.0.0（原作者：答辩）：定时给在线玩家发放随机物品。
