1
This commit is contained in:
@@ -19,6 +19,7 @@ using Assets.MyGame.Scripts.Net.APIResponses.GameConfig_SubClass;
|
||||
using Assets.MyGame.Scripts.Net.WebResponses;
|
||||
using cfg;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
@@ -173,6 +174,16 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
|
||||
/// <summary>特殊 Boss</summary>
|
||||
public Dictionary<string, MonsterContral> fishDatas_hashCodekey_TS_Boss = new Dictionary<string, MonsterContral>();
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// 击杀消息幂等去重(fishId|killtime → 处理时刻)
|
||||
// 服务端可能对同一次击杀下发多条 RoomKillNotice(掉落推送之外的重复/重发),
|
||||
// 同 fishId+killtime 只处理第一条,防止重复克隆爆奖特效/重复出 bjEndUI;
|
||||
// MultiDeath(星际巡航等多次死亡玩法)每段 killtime 不同,不受影响。
|
||||
// ----------------------------------------------------------------
|
||||
private readonly Dictionary<string, float> _handledKillKeys = new Dictionary<string, float>();
|
||||
private readonly List<string> _expiredKillKeys = new List<string>();
|
||||
private const float KillDedupKeepSeconds = 60f; // 键保鲜期(秒),超时清理防字典增长
|
||||
|
||||
#if UNITY_EDITOR
|
||||
// ⭐ 编辑器调试 List:与上方字典同步,方便在 Inspector 查看当前场上活鱼
|
||||
public List<MonsterContral> fishList_All = new List<MonsterContral>();
|
||||
@@ -1961,15 +1972,40 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
|
||||
// 第二条与击杀消息同 fishId/killtime/gold,但只有 drop、没有 param。
|
||||
// Boss 鱼 DieFish 是延迟回收(字典未即时移除),第二条若按击杀再处理一次:
|
||||
// ① not-self 模式下 _pending[key] 被覆盖 → 前一个"爆奖中"BJEndUI 失去引用、永久残留在座位上;
|
||||
// ② 重复克隆爆奖特效、重复走 DieFish → 特效/音效/爆奖双份。
|
||||
// ② 重复克隆爆奖特效、重复走 DieFish → 特效/音效/爆奖双份(两个 Event 实例各出一次 bjEndUI)。
|
||||
// 客户端目前没有掉落弹窗逻辑(见 RoomKillNotice.drop 注释),直接跳过;将来做掉落 UI 时在此处理。
|
||||
if (killFish.drop != null && killFish.param == null)
|
||||
// ⚠️ param 是 JToken:JSON "param":null 会被反序列化成 JValue(Null)(Type==JTokenType.Null),
|
||||
// 不能只判 C# null(与 BossKillParam.cs 的判空写法保持一致),否则第二条漏拦 → 重复爆奖。
|
||||
if (killFish.drop != null
|
||||
&& (killFish.param == null || killFish.param.Type == JTokenType.Null))
|
||||
{
|
||||
NetLog.Log($"[CreateFishManager] 掉落道具推送(跳过击杀处理):fishId={killFish.fishId} " +
|
||||
$"prop={killFish.drop.propNumber}×{killFish.drop.count}");
|
||||
return;
|
||||
}
|
||||
|
||||
// ⭐ 击杀消息幂等去重(第二道锁):同 fishId+killtime+beishu+gold 已处理过 → 判为同一次击杀的
|
||||
// 重复/重发消息,直接跳过,防止重复走击杀流程(重复克隆爆奖特效 → 两个 Event 实例各出一次
|
||||
// bjEndUI = 重复显示爆奖标志)。
|
||||
// ⚠️ 掉落推送(param 为空)已在上面被拦、不会记录键,避免"掉落先到"时误挡真正的击杀消息;
|
||||
// MultiDeath(星际巡航等多次死亡玩法)同一秒内多段的 killtime 可能相同,但各段 beishu/gold
|
||||
// 不同,键里带上二者后正常放行。
|
||||
string killKey = killFish.fishId + "|" + killFish.killtime + "|" + killFish.beishu + "|" + killFish.gold;
|
||||
if (_handledKillKeys.ContainsKey(killKey))
|
||||
{
|
||||
NetLog.Log($"[CreateFishManager] 重复击杀消息(跳过):key={killKey}");
|
||||
return;
|
||||
}
|
||||
_handledKillKeys[killKey] = Time.unscaledTime;
|
||||
if (_handledKillKeys.Count >= 64) // 顺手清理过期键,防字典增长
|
||||
{
|
||||
float nowTime = Time.unscaledTime;
|
||||
_expiredKillKeys.Clear();
|
||||
foreach (var kv in _handledKillKeys)
|
||||
if (nowTime - kv.Value > KillDedupKeepSeconds) _expiredKillKeys.Add(kv.Key);
|
||||
foreach (var k in _expiredKillKeys) _handledKillKeys.Remove(k);
|
||||
}
|
||||
|
||||
NetLog.Log($"[CreateFishManager] 杀鱼延迟:{DateTimeOffset.Now.ToUnixTimeSeconds() - killFish.timespan}s");
|
||||
SitPosData sitData = null; //击杀玩家座位数据
|
||||
foreach (var item in currGameType.list_Sits)
|
||||
|
||||
Reference in New Issue
Block a user