三国卡牌客户端基础资源仓库
yyl
2026-02-09 a968d6ab57f24218a1f1de143a5a7461e887d884
模拟发包
1个文件已修改
439 ■■■■■ 已修改文件
Assets/Editor/UI/GMQuickPlayingEditor.cs 439 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/UI/GMQuickPlayingEditor.cs
@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Reflection;
public class GMQuickPlayingEditor : EditorWindow
{
@@ -22,6 +23,14 @@
    private List<string> gmCommandHistory = new List<string>(); // 存储历史GM命令
    private const int maxGmMessages = 50; // 最多保存50条消息
    private const int maxGmHistory = 30; // 最多保存30条历史命令
    // 模拟发包工具相关
    private bool showPacketSimulator = false; // 显示模拟发包工具
    private Vector2 packetScrollPosition; // 包字段滚动位置
    private string packetClassName = ""; // 输入的包类名
    private System.Type currentPacketType = null; // 当前包类型
    private object currentPacketInstance = null; // 当前包实例
    private Dictionary<FieldInfo, object> fieldValues = new Dictionary<FieldInfo, object>(); // 存储字段值
    
    // 战报相关
    private string reportFilePath = "";
@@ -79,6 +88,12 @@
        // 显示GM面板开关
        GUILayout.Label("显示GM", GUILayout.Width(100));
        showGmPanel = EditorGUILayout.Toggle(showGmPanel, GUILayout.Width(20));
        GUILayout.Space(20);
        // 显示模拟发包工具开关
        GUILayout.Label("模拟发包工具", GUILayout.Width(100));
        showPacketSimulator = EditorGUILayout.Toggle(showPacketSimulator, GUILayout.Width(20));
        
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();
@@ -286,6 +301,23 @@
        EditorGUILayout.LabelField("⚠ 添加物品最好跟服务器确认过物品的存在后再添加", warningStyle);
        
        GUILayout.EndVertical();
        }
        // ========== 中间面板 - 模拟发包工具 ==========
        if (showPacketSimulator)
        {
            // 分割线
            if (showGmPanel)
            {
                GUILayout.Box("", GUILayout.Width(2), GUILayout.ExpandHeight(true));
            }
            float packetWidth = showBattleInfo ? position.width * 0.35f : (showGmPanel ? position.width * 0.4f : position.width - 20);
            GUILayout.BeginVertical("box", GUILayout.Width(packetWidth));
            DrawPacketSimulator();
            GUILayout.EndVertical();
        }
        
        // ========== 右侧面板 - 战场信息 ==========
@@ -824,4 +856,411 @@
        battleField.ForceFinish();
        
    }
    // ========== 模拟发包工具相关方法 ==========
    private void DrawPacketSimulator()
    {
        GUILayout.Label("📦 模拟发包工具", EditorStyles.boldLabel);
        GUILayout.Space(5);
        // 包名输入区域
        GUILayout.BeginVertical("box");
        GUILayout.Label("包类名(例如:HB301_tagCSLoginReq)", EditorStyles.miniBoldLabel);
        GUILayout.BeginHorizontal();
        string newPacketClassName = EditorGUILayout.TextField(packetClassName);
        // 检测包名是否改变
        if (newPacketClassName != packetClassName)
        {
            packetClassName = newPacketClassName;
            // 清空当前包信息
            currentPacketType = null;
            currentPacketInstance = null;
            fieldValues.Clear();
        }
        if (GUILayout.Button("加载包", GUILayout.Width(80)))
        {
            LoadPacketType();
        }
        GUILayout.EndHorizontal();
        GUILayout.EndVertical();
        GUILayout.Space(10);
        // 包字段显示和编辑区域
        if (currentPacketType != null && currentPacketInstance != null)
        {
            GUILayout.BeginVertical("box");
            GUILayout.Label($"📋 包字段 - {currentPacketType.Name}", EditorStyles.boldLabel);
            packetScrollPosition = GUILayout.BeginScrollView(packetScrollPosition, GUILayout.ExpandHeight(true));
            DrawPacketFields();
            GUILayout.EndScrollView();
            GUILayout.EndVertical();
            GUILayout.Space(10);
            // 操作按钮
            GUILayout.BeginHorizontal();
            // 发送按钮(绿色)
            GUI.backgroundColor = new Color(0.5f, 1f, 0.5f);
            if (GUILayout.Button("✉ 发送包", GUILayout.Height(35)))
            {
                SendPacket();
            }
            GUI.backgroundColor = Color.white;
            GUILayout.Space(10);
            // 清空按钮(橙色)
            GUI.backgroundColor = new Color(1f, 0.8f, 0.4f);
            if (GUILayout.Button("🗑 清空字段", GUILayout.Height(35)))
            {
                ClearPacketFields();
            }
            GUI.backgroundColor = Color.white;
            GUILayout.EndHorizontal();
        }
        else
        {
            GUILayout.FlexibleSpace();
            GUIStyle hintStyle = new GUIStyle(EditorStyles.helpBox);
            hintStyle.normal.textColor = new Color(0.7f, 0.7f, 0.7f);
            hintStyle.fontSize = 12;
            hintStyle.alignment = TextAnchor.MiddleCenter;
            hintStyle.wordWrap = true;
            GUILayout.Label("💡 输入包类名后点击\"加载包\"按钮\n即可自动识别并编辑包的所有字段", hintStyle, GUILayout.Height(80));
            GUILayout.FlexibleSpace();
        }
    }
    private void LoadPacketType()
    {
        if (string.IsNullOrEmpty(packetClassName))
        {
            Debug.LogWarning("包类名不能为空");
            return;
        }
        try
        {
            // 尝试在所有已加载的程序集中查找类型
            System.Type foundType = null;
            foreach (var assembly in System.AppDomain.CurrentDomain.GetAssemblies())
            {
                foundType = assembly.GetType(packetClassName);
                if (foundType != null)
                    break;
            }
            if (foundType == null)
            {
                Debug.LogError($"未找到类型: {packetClassName},请检查类名是否正确(区分大小写)");
                return;
            }
            // 检查是否继承自 GameNetPackBasic
            if (!typeof(GameNetPackBasic).IsAssignableFrom(foundType))
            {
                Debug.LogError($"类型 {packetClassName} 不是 GameNetPackBasic 的子类");
                return;
            }
            currentPacketType = foundType;
            currentPacketInstance = System.Activator.CreateInstance(foundType);
            fieldValues.Clear();
            // 初始化字段值
            var fields = GetAllFields(foundType);
            foreach (var field in fields)
            {
                object defaultValue = field.GetValue(currentPacketInstance);
                fieldValues[field] = defaultValue;
            }
            Debug.Log($"成功加载包: {foundType.Name},共 {fields.Count} 个字段");
        }
        catch (System.Exception e)
        {
            Debug.LogError($"加载包类型失败: {e.Message}");
            currentPacketType = null;
            currentPacketInstance = null;
            fieldValues.Clear();
        }
    }
    private List<FieldInfo> GetAllFields(System.Type type)
    {
        List<FieldInfo> fields = new List<FieldInfo>();
        // 只获取当前类声明的字段,不包括父类字段
        FieldInfo[] typeFields = type.GetFields(
            BindingFlags.Public |
            BindingFlags.NonPublic |
            BindingFlags.Instance |
            BindingFlags.DeclaredOnly);
        foreach (var field in typeFields)
        {
            // 排除编译器生成的字段
            if (!field.Name.Contains("<") && !field.Name.Contains(">"))
            {
                fields.Add(field);
            }
        }
        return fields;
    }
    private void DrawPacketFields()
    {
        var fields = GetAllFields(currentPacketType);
        foreach (var field in fields)
        {
            GUILayout.BeginVertical("box");
            // 字段名称和类型
            GUILayout.BeginHorizontal();
            GUILayout.Label(field.Name, EditorStyles.boldLabel, GUILayout.Width(150));
            GUILayout.Label($"({field.FieldType.Name})", EditorStyles.miniLabel);
            GUILayout.EndHorizontal();
            // 字段值编辑
            if (!fieldValues.ContainsKey(field))
            {
                fieldValues[field] = field.GetValue(currentPacketInstance);
            }
            object newValue = DrawFieldValue(field, fieldValues[field]);
            if (newValue != null || field.FieldType.IsClass)
            {
                fieldValues[field] = newValue;
                field.SetValue(currentPacketInstance, newValue);
            }
            GUILayout.EndVertical();
            GUILayout.Space(3);
        }
    }
    private object DrawFieldValue(FieldInfo field, object currentValue)
    {
        System.Type fieldType = field.FieldType;
        try
        {
            // 基本类型
            if (fieldType == typeof(int))
            {
                return EditorGUILayout.IntField((int)(currentValue ?? 0));
            }
            else if (fieldType == typeof(uint))
            {
                return (uint)EditorGUILayout.LongField((uint)(currentValue ?? 0));
            }
            else if (fieldType == typeof(long))
            {
                return EditorGUILayout.LongField((long)(currentValue ?? 0L));
            }
            else if (fieldType == typeof(ulong))
            {
                long val = EditorGUILayout.LongField((long)(ulong)(currentValue ?? 0UL));
                return (ulong)System.Math.Max(0, val);
            }
            else if (fieldType == typeof(short))
            {
                return (short)EditorGUILayout.IntField((short)(currentValue ?? (short)0));
            }
            else if (fieldType == typeof(ushort))
            {
                return (ushort)EditorGUILayout.IntField((ushort)(currentValue ?? (ushort)0));
            }
            else if (fieldType == typeof(byte))
            {
                return (byte)EditorGUILayout.IntField((byte)(currentValue ?? (byte)0));
            }
            else if (fieldType == typeof(sbyte))
            {
                return (sbyte)EditorGUILayout.IntField((sbyte)(currentValue ?? (sbyte)0));
            }
            else if (fieldType == typeof(float))
            {
                return EditorGUILayout.FloatField((float)(currentValue ?? 0f));
            }
            else if (fieldType == typeof(double))
            {
                return EditorGUILayout.DoubleField((double)(currentValue ?? 0.0));
            }
            else if (fieldType == typeof(bool))
            {
                return EditorGUILayout.Toggle((bool)(currentValue ?? false));
            }
            else if (fieldType == typeof(string))
            {
                return EditorGUILayout.TextField((string)(currentValue ?? ""));
            }
            // List 类型
            else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(List<>))
            {
                System.Type elementType = fieldType.GetGenericArguments()[0];
                var list = currentValue as System.Collections.IList;
                if (list == null)
                {
                    list = (System.Collections.IList)System.Activator.CreateInstance(fieldType);
                }
                GUILayout.BeginHorizontal();
                GUILayout.Label($"Count: {list.Count}", GUILayout.Width(80));
                if (GUILayout.Button("➕", GUILayout.Width(30)))
                {
                    object newElement = GetDefaultValue(elementType);
                    list.Add(newElement);
                }
                if (list.Count > 0 && GUILayout.Button("➖", GUILayout.Width(30)))
                {
                    list.RemoveAt(list.Count - 1);
                }
                GUILayout.EndHorizontal();
                return list;
            }
            // 数组类型
            else if (fieldType.IsArray)
            {
                var array = currentValue as System.Array;
                int length = array != null ? array.Length : 0;
                GUILayout.Label($"Array Length: {length}", EditorStyles.miniLabel);
                return currentValue;
            }
            // 枚举类型
            else if (fieldType.IsEnum)
            {
                return EditorGUILayout.EnumPopup((System.Enum)(currentValue ?? System.Enum.GetValues(fieldType).GetValue(0)));
            }
            // 其他复杂类型
            else
            {
                GUILayout.Label("(复杂类型,请在代码中设置)", EditorStyles.miniLabel);
                return currentValue;
            }
        }
        catch (System.Exception e)
        {
            GUILayout.Label($"(编辑错误: {e.Message})", EditorStyles.miniLabel);
            return currentValue;
        }
    }
    private object GetDefaultValue(System.Type type)
    {
        if (type.IsValueType)
        {
            return System.Activator.CreateInstance(type);
        }
        else if (type == typeof(string))
        {
            return "";
        }
        else
        {
            try
            {
                return System.Activator.CreateInstance(type);
            }
            catch
            {
                return null;
            }
        }
    }
    private void SendPacket()
    {
        if (currentPacketInstance == null)
        {
            Debug.LogWarning("没有可发送的包实例");
            return;
        }
        if (!Application.isPlaying)
        {
            Debug.LogError("只能在运行时发送包");
            EditorUtility.DisplayDialog("错误", "只能在运行时发送网络包!", "确定");
            return;
        }
        try
        {
            var packet = currentPacketInstance as GameNetPackBasic;
            if (packet != null)
            {
                GameNetSystem.Instance.SendInfo(packet);
                Debug.Log($"✅ 成功发送包: {currentPacketType.Name}");
                // 显示发送的详细信息
                var fields = GetAllFields(currentPacketType);
                string fieldInfo = "字段值:\n";
                foreach (var field in fields)
                {
                    object value = field.GetValue(packet);
                    fieldInfo += $"  {field.Name} = {value}\n";
                }
                Debug.Log(fieldInfo);
            }
            else
            {
                Debug.LogError("包实例不是 GameNetPackBasic 类型");
            }
        }
        catch (System.Exception e)
        {
            Debug.LogError($"发送包失败: {e.Message}\n{e.StackTrace}");
            EditorUtility.DisplayDialog("发送失败", $"发送包时出错:\n{e.Message}", "确定");
        }
    }
    private void ClearPacketFields()
    {
        if (currentPacketInstance == null)
        {
            return;
        }
        try
        {
            // 重新创建实例
            currentPacketInstance = System.Activator.CreateInstance(currentPacketType);
            fieldValues.Clear();
            // 重新初始化字段值
            var fields = GetAllFields(currentPacketType);
            foreach (var field in fields)
            {
                object defaultValue = field.GetValue(currentPacketInstance);
                fieldValues[field] = defaultValue;
            }
            Debug.Log("已清空所有字段");
        }
        catch (System.Exception e)
        {
            Debug.LogError($"清空字段失败: {e.Message}");
        }
    }
}