hch
2025-12-31 4debfee66e8d8aabd179e2f8a61c7ca5ce62af3d
Main/System/Settlement/BattleSettlementManager.cs
@@ -1,13 +1,18 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LitJson;
using UnityEngine;
public partial class BattleSettlementManager : GameSystemManager<BattleSettlementManager>
{
    //结算后需清除 <battleName,JsonData>
    Dictionary<string, JsonData> battleSettlementDic = new Dictionary<string, JsonData>();
    Dictionary<string, JsonData> battleAwardDic = new Dictionary<string, JsonData>();   //B431 另外通报奖励
    // public string notifyGuid = string.Empty;
@@ -28,6 +33,7 @@
    public void OnBeforePlayerDataInitialize()
    {
        battleSettlementDic.Clear();
        battleAwardDic.Clear();
    }
    public void AddPop(string battleName, int result)
@@ -35,17 +41,17 @@
        bool isWin = result == 1;
        switch (battleName)
        {
            case "ArenaBattleField":
                PopupWindowsProcessor.Instance.Add(isWin ? "ArenaBattleVictoryWin" : "ArenaBattleFailWin", false);
            case BattleConst.ArenaBattleField:
                PopupWindowsProcessor.Instance.Add(isWin ? "ArenaBattleVictoryWin" : "ArenaBattleFailWin", false, BattleConst.ArenaBattleField);
                break;
            case "BoneBattleField":
                PopupWindowsProcessor.Instance.Add(isWin ? "BoneBattleVictoryWin" : "BoneBattleFailWin", false);
            case BattleConst.BoneBattleField:
                PopupWindowsProcessor.Instance.Add(isWin ? "BoneBattleVictoryWin" : "BoneBattleFailWin", false, BattleConst.BoneBattleField);
                break;
            case "TianziBillboradBattleField":
                PopupWindowsProcessor.Instance.Add("TianziBillboradVictoryWin", false);
            case BattleConst.TianziBillboradBattleField:
                PopupWindowsProcessor.Instance.Add("TianziBillboradVictoryWin", false, BattleConst.TianziBillboradBattleField);
                break;
            default:
                PopupWindowsProcessor.Instance.Add(isWin ? "BattleVictoryWin" : "BattleFailWin", false);
                PopupWindowsProcessor.Instance.Add(isWin ? "BattleVictoryWin" : "BattleFailWin", false, BattleConst.StoryBossBattleField);
                break;
        }
    }
@@ -55,7 +61,7 @@
        bool isWin = result == 1;
        switch (battleName)
        {
            case "ArenaBattleField":
            case BattleConst.ArenaBattleField:
                if (isWin)
                {
                    UIManager.Instance.OpenWindow<ArenaBattleVictoryWin>();
@@ -65,7 +71,7 @@
                    UIManager.Instance.OpenWindow<ArenaBattleFailWin>();
                }
                break;
            case "BoneBattleField":
            case BattleConst.BoneBattleField:
                if (isWin)
                {
                    UIManager.Instance.OpenWindow<BoneBattleVictoryWin>();
@@ -75,7 +81,7 @@
                    UIManager.Instance.OpenWindow<BoneBattleFailWin>();
                }
                break;
            case "TianziBillboradBattleField":
            case BattleConst.TianziBillboradBattleField:
                TianziBillboradManager.Instance.isSweepVictory = false;
                UIManager.Instance.OpenWindow<TianziBillboradVictoryWin>();
                break;
@@ -90,6 +96,11 @@
                }
                break;
        }
        if (isWin)
        {
            SoundPlayer.Instance.PlayUIAudio(57);
        }
    }
    //"Msg":{"itemInfo":[{"ItemID":5,"Count":2},{"ItemID":3,"Count":40}],"winFaction":1,"statInfo":{"1":{"1":{"1":{"NPCID":0,"DefHurt":727,"CureHP":0,"AtkHurt":1891,"ObjID":1,"HeroID":530004},"3":{"NPCID":0,"DefHurt":483,"CureHP":1511,"AtkHurt":782,"ObjID":6,"HeroID":520001},"2":{"NPCID":0,"DefHurt":953,"CureHP":0,"AtkHurt":1712,"ObjID":5,"HeroID":510003}}},"2":{"1":{"1":{"NPCID":10101091,"DefHurt":638,"CureHP":0,"AtkHurt":140,"ObjID":2,"HeroID":610001},"3":{"NPCID":10101092,"DefHurt":625,"CureHP":0,"AtkHurt":126,"ObjID":3,"HeroID":610001},"5":{"NPCID":10101093,"DefHurt":3122,"CureHP":0,"AtkHurt":1897,"ObjID":4,"HeroID":510003}}}}}
@@ -97,11 +108,29 @@
    {
        if (string.Empty == _guid)
            return;
        Debug.Log($"OnBattleEnd 结算 guid {_guid}");
        var battle = BattleManager.Instance.GetBattleField(_guid);
        if (battle == null)
            return;
        var battleName = battle.ToString();
        battleSettlementDic[battleName] = _data;
        try
        {
            battleSettlementDic[battleName] = _data;
            if (battleAwardDic.ContainsKey(battleName))
            {
                //合并战报和结算数据
                JsonData extendData = battleAwardDic[battleName];
                foreach (var key in extendData.Keys)
                {
                    _data[key] = extendData[key];
                }
            }
        }
        catch (Exception e)
        {
            Debug.LogError(e.ToString());
        }
        string activeBattleName = BattleManager.Instance.GetActiveBattleName();
@@ -124,6 +153,7 @@
    public void WinShowOver(string battleName)
    {
        battleSettlementDic.Remove(battleName);
        battleAwardDic.Remove(battleName);
        var battle = BattleManager.Instance.GetActiveBattleFieldByName(battleName);
        if (battle != null)
@@ -138,5 +168,255 @@
        }
        return battleSettlementDic[battleName];
    }
    public JsonData GetBattleSettlementByMapID(int mapID)
    {
        if (BattleConst.mapIDToBattleNameDic.ContainsKey(mapID))
        {
            return GetBattleSettlement(BattleConst.mapIDToBattleNameDic[mapID]);
        }
        return null;
    }
    public void UpdateSettlementData(HB431_tagSCTurnFightRet netData)
    {
        // 先获得战斗结果,如果需要展示战斗,则请求战报 (如有些跳过战斗表现直接结算)
        bool needBattleData = true;
        var guid = UIHelper.ServerStringTrim(netData.GUID);
        var mapID = (int)netData.MapID;
        JsonData extendData2 = JsonMapper.ToObject(netData.AwardMsg);
        battleAwardDic[BattleConst.mapIDToBattleNameDic[mapID]] = extendData2;
        if (needBattleData)
        {
            Debug.Log("战斗时序 收到B431 并请求下载战报" + Time.time);
            var date = UIHelper.ServerStringTrim(netData.PathDate);
            RequestTurnFightData(guid, date, mapID);
        }
        else
        {
            JsonData extendData1 = JsonMapper.ToObject(netData.BatStatMsg);
            JsonData turnFightStateData = new JsonData();
            foreach (var key in extendData1.Keys)
            {
                turnFightStateData[key] = extendData1[key];
            }
            foreach (var key in extendData2.Keys)
            {
                turnFightStateData[key] = extendData2[key];
            }
            EventBroadcast.Instance.Broadcast<string, JsonData>(EventName.BATTLE_END, guid, turnFightStateData);
        }
    }
    public void RequestTurnFightData(string guid, string date, int mapID)
    {
        //mobile.secondworld.net.cn:53080\S9006\20251202\3042602\5b11338f-cf2c-11f0-a0a0-000c29b22418.tfr
        var serverID = UIHelper.GetServerIDByAccount(PlayerDatas.Instance.baseData.AccID);
        var url = ServerListCenter.Instance.GetServerUrl(serverID);
        string assetVersionUrl = string.Empty;
        if (string.IsNullOrEmpty(date))
        {
            //公共战报  路径: C:\TurnFightReport\S服务器编号\功能地图ID\战报GUID
            assetVersionUrl = $"{url}/S{serverID}/{mapID}/{guid}.tfr";
        }
        else
        {
            //个人战报  路径: C:\TurnFightReport\S服务器编号\日期\玩家ID\功能地图ID\战报GUID
            assetVersionUrl = $"{url}/S{serverID}/{date}/{PlayerDatas.Instance.baseData.PlayerID}/{mapID}/{guid}.tfr";
        }
        Debug.Log($"请求战报: {assetVersionUrl}");
        HttpRequestEx.UnityWebRequestTurnFightGet(assetVersionUrl, guid, 3, OnGetTurnFightData);
    }
    void OnGetTurnFightData(bool _ok, string guid, byte[] _result)
    {
        if (_ok)
        {
            ReadTurnFightInfo(_result);
        }
        else
        {
            Debug.Log($"请求战报失败");
            UIManager.Instance.CloseWindow<MapLoadingWin>();
        }
    }
    //战报存储的是B430封包,所以需要转发B430封包
    private void ReadTurnFightInfo(byte[] vBytes)
    {
        try
        {
            byte[] vPackBytes = vBytes;
            GameNetPackBasic vNetpack;
            byte[] vCmdBytes = new byte[2];
            ServerType socketType = ServerType.B430;
            Array.Copy(vPackBytes, 0, vCmdBytes, 0, 2);
            var cmd = (ushort)((ushort)(vCmdBytes[0] << 8) + vCmdBytes[1]);
            // 处理主工程的封包
            if (PackageRegedit.Contain(cmd))
            {
                vNetpack = PackageRegedit.TransPack(socketType, cmd, vPackBytes);
                if (vNetpack != null)
                {
                    GameNetSystem.Instance.PushPackage(vNetpack, socketType);
                }
            }
        }
        catch (Exception ex)
        {
            Debug.LogErrorFormat("ReadTurnFightInfo 分析战报异常:{0}", ex);
        }
    }
    #region 战斗结果详情
    public BattleDetailMsg msg = new BattleDetailMsg();
    public string BattleDetailBattleName = string.Empty;
    public string BattleDetailMyName = string.Empty;
    public string BattleDetailEnemyName = string.Empty;
    public void OpenBattleDetailWin(string battleName)
    {
        if (UIManager.Instance.IsOpened<BattleDetailWin>())
            return;
        JsonData battleSettlement = GetBattleSettlement(battleName);
        if (battleSettlement == null)
            return;
        msg = ParserBattleDetail(battleSettlement);
        if (msg == null)
            return;
        BattleDetailBattleName = battleName;
        UIManager.Instance.OpenWindow<BattleDetailWin>();
    }
    //战斗结果详情界面获取 我方发起的战斗的中敌方名字
    public string GetBattleDetailEnemyNameByMyStart(string battleName)
    {
        string detailName = string.Empty;
        BattleField battleField = BattleManager.Instance.GetActiveBattleFieldByName(battleName);
        if (battleField == null)
            return detailName;
        switch (battleName)
        {
            // 敌方名字是Boss名字
            case BattleConst.StoryBossBattleField:
            case BattleConst.BoneBattleField:
            case BattleConst.TianziBillboradBattleField:
                BattleObject bossBattleObject = battleField.FindBoss();
                if (bossBattleObject == null || bossBattleObject.teamHero == null)
                    return detailName;
                detailName = bossBattleObject.teamHero.name;
                break;
            // 敌方名字是对方玩家名字
            case BattleConst.ArenaBattleField:
                if (!ArenaManager.Instance.TryGetPlayerInfo(ArenaManager.Instance.atkPlayerId, out ArenaMatchInfo info) || info == null)
                    return detailName;
                detailName = info.PlayerName;
                break;
        }
        return detailName;
    }
    public BattleDetailMsg ParserBattleDetail(JsonData jsonMsg)
    {
        if (jsonMsg == null)
            return null;
        try
        {
            string jsonStr = jsonMsg.ToJson();
            BattleDetailMsg result = JsonMapper.ToObject<BattleDetailMsg>(jsonStr);
            return result;
        }
        catch (Exception ex)
        {
            Debug.Log("解析战斗数据异常: " + ex.Message);
        }
        return null;
    }
    // 左蓝右红
    // 目前玩家主动发起的阵容一定是1,对方是 2, 如果是那种系统自动打的,一般1-左,2-右
    public string GetFaction(bool isBlue)
    {
        return isBlue ? "1" : "2";
    }
    public List<BattleDetailHeroInfo> GetHeroInfoByFaction(BattleDetailMsg msg, string faction)
    {
        if (msg == null || msg.statInfo.IsNullOrEmpty())
            return null;
        int winFaction = msg.winFaction;    // 获胜阵营
        Dictionary<string, Dictionary<string, BattleDetailHeroInfo>> lineupInfo = new Dictionary<string, Dictionary<string, BattleDetailHeroInfo>>();
        if (!msg.statInfo.TryGetValue(faction, out lineupInfo) || lineupInfo.IsNullOrEmpty())
            return null;
        var lineupInfoKeyList = lineupInfo.Keys.ToList();
        if (lineupInfoKeyList.IsNullOrEmpty())
            return null;
        // 目前只取第一个阵容的信息
        string key = lineupInfoKeyList[0];
        if (!lineupInfo.TryGetValue(key, out var heroInfoDict) || heroInfoDict.IsNullOrEmpty())
            return null;
        var heroInfoKeyList = heroInfoDict.Keys.ToList();
        heroInfoKeyList = heroInfoKeyList
            .OrderBy(key => int.Parse(key)) // 将字符串键解析为整数后进行排序
            .ToList(); // 将排序后的结果转回 List<string>
        List<BattleDetailHeroInfo> res = new List<BattleDetailHeroInfo>();
        foreach (var heroInfoKey in heroInfoKeyList)
        {
            if (!heroInfoDict.TryGetValue(heroInfoKey, out var heroInfo))
                continue;
            res.Add(heroInfo);
        }
        return res;
    }
    #endregion
}
public class BattleDetailMsg
{
    public List<BattleDetailRewardItem> itemInfo;
    public int winFaction;
    // 对应 "statInfo"
    // 结构:<阵营编号, <阵容编号, <站位编号, 武将数据>>>
    // 注意:JSON中的键 "1", "2" 是字符串,所以字典 Key 用 string
    public Dictionary<string, Dictionary<string, Dictionary<string, BattleDetailHeroInfo>>> statInfo;
}
public class BattleDetailHeroInfo
{
    public int ObjID;   // 实例ID
    public int HeroID;  // 玩家阵容武将ID
    public int NPCID;   // NPCID
    public int LV;      // 武将等级
    public int Star;      // 武将星级
    public int Skin;      // 武将皮肤ID
    public long DefHurt; // 总承伤
    public long CureHP;  // 总治疗
    public long AtkHurt; // 总输出
    public int Dead;      // 是否阵亡
}
public class BattleDetailRewardItem
{
    public int ItemID;
    public int Count;
}