diff --git a/DuckovMods.sln b/DuckovMods.sln index dd6fa68..2388e59 100644 --- a/DuckovMods.sln +++ b/DuckovMods.sln @@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HideCharacter", "HideCharac EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HitFeedback", "HitFeedback\HitFeedback.csproj", "{FEA30679-27B6-4413-91A5-EB08FCD9F02B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UIFrame", "UIFrame\UIFrame.csproj", "{78BAF98F-64B2-41EB-BA04-2381E1D37AC8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +29,10 @@ Global {FEA30679-27B6-4413-91A5-EB08FCD9F02B}.Debug|Any CPU.Build.0 = Debug|Any CPU {FEA30679-27B6-4413-91A5-EB08FCD9F02B}.Release|Any CPU.ActiveCfg = Release|Any CPU {FEA30679-27B6-4413-91A5-EB08FCD9F02B}.Release|Any CPU.Build.0 = Release|Any CPU + {78BAF98F-64B2-41EB-BA04-2381E1D37AC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {78BAF98F-64B2-41EB-BA04-2381E1D37AC8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {78BAF98F-64B2-41EB-BA04-2381E1D37AC8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {78BAF98F-64B2-41EB-BA04-2381E1D37AC8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/DuckovMods.sln.DotSettings.user b/DuckovMods.sln.DotSettings.user index 7bbf89a..80fb4fb 100644 --- a/DuckovMods.sln.DotSettings.user +++ b/DuckovMods.sln.DotSettings.user @@ -4,6 +4,7 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded @@ -12,13 +13,16 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded diff --git a/HideCharacter/HideCharacter.csproj b/HideCharacter/HideCharacter.csproj index 0fe0968..7ab7c62 100644 --- a/HideCharacter/HideCharacter.csproj +++ b/HideCharacter/HideCharacter.csproj @@ -49,4 +49,8 @@ + + + + diff --git a/HideCharacter/HideCharacterComponent.cs b/HideCharacter/HideCharacterComponent.cs index d5d481a..258d417 100644 --- a/HideCharacter/HideCharacterComponent.cs +++ b/HideCharacter/HideCharacterComponent.cs @@ -12,7 +12,7 @@ namespace HideCharacter public class HideCharacterComponent : MonoBehaviour { - public HideList? hideList = new HideList(); + public bool hide { get; private set; } = false; private List rendererList = new List(); private GameObject? @@ -39,45 +39,6 @@ namespace HideCharacter LevelManager.OnLevelInitialized+=OnSceneLoaded; SceneManager.sceneUnloaded += OnSceneUnloaded; - var dllDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - var configFilePath = Path.Combine(dllDirectory, "config.json"); - if (File.Exists(configFilePath)) - { - try - { - var jsonString = File.ReadAllText(configFilePath); - hideList = JsonConvert.DeserializeObject(jsonString); - } - catch (JsonSerializationException ex) // 捕获 Newtonsoft.Json 特有的异常 - { - Debug.LogError($"JSON 反序列化错误 (Newtonsoft.Json): {ex.Message}"); - } - catch (IOException ex) - { - Debug.LogError($"文件读取错误: {ex.Message}"); - } - catch (Exception ex) - { - Debug.LogError($"加载配置文件时发生未知错误: {ex.Message}"); - } - } - else - { - Debug.LogWarning($"配置文件 '{configFilePath}' 不存在。将使用默认设置。"); - try - { - var jsonString = JsonConvert.SerializeObject(hideList, Formatting.Indented); - File.WriteAllText(configFilePath, jsonString); - } - catch (IOException ex) - { - Debug.LogError($"创建配置文件时发生错误: {ex.Message}"); - } - catch (Exception ex) - { - Debug.LogError($"创建配置文件时发生未知错误: {ex.Message}"); - } - } } private void OnDisable() @@ -205,7 +166,7 @@ namespace HideCharacter private void Update() { - if (Input.GetKeyDown(hideList?.hotkey ?? KeyCode.F5)) + if (Input.GetKeyDown(ModBehaviour.hideList?.hotkey ?? KeyCode.F5)) { hide = !hide; SetCharacterHide(hide); @@ -214,6 +175,7 @@ namespace HideCharacter public void SetCharacterHide(bool hide) { + var hideList = ModBehaviour.hideList; if (hideList != null) { tail?.SetActive(!(hide && hideList.hideTail)); diff --git a/HideCharacter/ModBehaviour.cs b/HideCharacter/ModBehaviour.cs index 891bf90..cb28a0e 100644 --- a/HideCharacter/ModBehaviour.cs +++ b/HideCharacter/ModBehaviour.cs @@ -1,5 +1,9 @@  +using System; +using System.IO; +using System.Reflection; using HarmonyLib; +using Newtonsoft.Json; using UnityEngine; using Object = UnityEngine.Object; // 确保引入 UnityEngine 命名空间 @@ -10,9 +14,18 @@ namespace HideCharacter public static HideCharacterComponent? hideHideCharacterManager=null; private const string CHILD_GAMEOBJECT_NAME = "HideCharacterManager"; - public string MOD_ID = "HideCharacter"; + public const string MOD_ID = "HideCharacter"; + public const string MOD_NAME = "隐藏角色设置"; private Harmony _harmony; + + public bool loadedConfigApi = false; + public static HideList? hideList = new HideList(); + private void Awake() + { + loadedConfigApi = Api.ModConfigAPI.Initialize(); + } + protected override void OnAfterSetup() { AddHideComponent(); @@ -21,6 +34,47 @@ namespace HideCharacter _harmony=new Harmony(MOD_ID); _harmony.PatchAll(); } + var dllDirectory = info.path; + var configFilePath = Path.Combine(dllDirectory, "config.json"); + if (File.Exists(configFilePath)) + { + try + { + var jsonString = File.ReadAllText(configFilePath); + hideList = JsonConvert.DeserializeObject(jsonString); + } + catch (JsonSerializationException ex) // 捕获 Newtonsoft.Json 特有的异常 + { + Debug.LogError($"JSON 反序列化错误 (Newtonsoft.Json): {ex.Message}"); + } + catch (IOException ex) + { + Debug.LogError($"文件读取错误: {ex.Message}"); + } + catch (Exception ex) + { + Debug.LogError($"加载配置文件时发生未知错误: {ex.Message}"); + } + } + else + { + Debug.LogWarning($"配置文件 '{configFilePath}' 不存在。将使用默认设置。"); + try + { + var jsonString = JsonConvert.SerializeObject(hideList, Formatting.Indented); + File.WriteAllText(configFilePath, jsonString); + } + catch (IOException ex) + { + Debug.LogError($"创建配置文件时发生错误: {ex.Message}"); + } + catch (Exception ex) + { + Debug.LogError($"创建配置文件时发生未知错误: {ex.Message}"); + } + } + if(Api.ModConfigAPI.IsAvailable()) + AddConfigSetting(); } protected override void OnBeforeDeactivate() @@ -48,6 +102,18 @@ namespace HideCharacter if (hideHideCharacterManager) Destroy(hideHideCharacterManager?.gameObject); } + + private void AddConfigSetting() + { + + Api.ModConfigAPI.SafeAddBoolDropdownList(MOD_NAME,"hideArmor","隐藏装备",hideList.hideArmor); + + } + + private void OnConfigChange() + { + + } } } diff --git a/HideCharacter/obj/Debug/HideCharacter.GeneratedMSBuildEditorConfig.editorconfig b/HideCharacter/obj/Debug/HideCharacter.GeneratedMSBuildEditorConfig.editorconfig index 63f724d..77304fd 100644 --- a/HideCharacter/obj/Debug/HideCharacter.GeneratedMSBuildEditorConfig.editorconfig +++ b/HideCharacter/obj/Debug/HideCharacter.GeneratedMSBuildEditorConfig.editorconfig @@ -1,6 +1,6 @@ is_global = true build_property.RootNamespace = HideCharacter -build_property.ProjectDir = D:\vs_project\DuckovMods\HideCharacter\ +build_property.ProjectDir = d:\vs_project\DuckovMods\HideCharacter\ build_property.EnableComHosting = build_property.EnableGeneratedComInterfaceComImportInterop = build_property.CsWinRTUseWindowsUIXamlProjections = false diff --git a/HideCharacter/obj/Debug/HideCharacter.assets.cache b/HideCharacter/obj/Debug/HideCharacter.assets.cache index 558bae3..7ab4973 100644 Binary files a/HideCharacter/obj/Debug/HideCharacter.assets.cache and b/HideCharacter/obj/Debug/HideCharacter.assets.cache differ diff --git a/HideCharacter/obj/Debug/HideCharacter.csproj.AssemblyReference.cache b/HideCharacter/obj/Debug/HideCharacter.csproj.AssemblyReference.cache index 3b144c9..305f460 100644 Binary files a/HideCharacter/obj/Debug/HideCharacter.csproj.AssemblyReference.cache and b/HideCharacter/obj/Debug/HideCharacter.csproj.AssemblyReference.cache differ diff --git a/HideCharacter/obj/Release/HideCharacter.AssemblyInfo.cs b/HideCharacter/obj/Release/HideCharacter.AssemblyInfo.cs index 5aaf9c3..0cb9f47 100644 --- a/HideCharacter/obj/Release/HideCharacter.AssemblyInfo.cs +++ b/HideCharacter/obj/Release/HideCharacter.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("折纸的小箱子")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Release")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.1")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.1+2af09007f967b42ac04776167f814297d14582e3")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.1+2b7943339c8fff4147e07028e81b3fff19ff0d80")] [assembly: System.Reflection.AssemblyProductAttribute("HideCharacter")] [assembly: System.Reflection.AssemblyTitleAttribute("HideCharacter")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.1")] diff --git a/HideCharacter/obj/Release/HideCharacter.AssemblyInfoInputs.cache b/HideCharacter/obj/Release/HideCharacter.AssemblyInfoInputs.cache index b46af9b..1f63b6c 100644 --- a/HideCharacter/obj/Release/HideCharacter.AssemblyInfoInputs.cache +++ b/HideCharacter/obj/Release/HideCharacter.AssemblyInfoInputs.cache @@ -1 +1 @@ -a90e2d9f75649545c1c6af7e34c572d4df6020158a0438630a9add7fb701918c +881e0b84476729ea6e67f155d7d840fd64b730af85f17eb2df102486efe4db4b diff --git a/HideCharacter/obj/Release/HideCharacter.csproj.AssemblyReference.cache b/HideCharacter/obj/Release/HideCharacter.csproj.AssemblyReference.cache index 3b144c9..305f460 100644 Binary files a/HideCharacter/obj/Release/HideCharacter.csproj.AssemblyReference.cache and b/HideCharacter/obj/Release/HideCharacter.csproj.AssemblyReference.cache differ diff --git a/HideCharacter/obj/Release/HideCharacter.csproj.CoreCompileInputs.cache b/HideCharacter/obj/Release/HideCharacter.csproj.CoreCompileInputs.cache index 3811e62..de05f33 100644 --- a/HideCharacter/obj/Release/HideCharacter.csproj.CoreCompileInputs.cache +++ b/HideCharacter/obj/Release/HideCharacter.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -e42d4e2d526b5e9021369ff53676b171dbb78a79de1d260ce81d1d37d0e46cf2 +cd9d2ad4bfd553f20993642bd029f6938ef1781f8d488fae23bb311c819125fb diff --git a/HideCharacter/obj/Release/HideCharacter.dll b/HideCharacter/obj/Release/HideCharacter.dll index 9de155b..808fe70 100644 Binary files a/HideCharacter/obj/Release/HideCharacter.dll and b/HideCharacter/obj/Release/HideCharacter.dll differ diff --git a/HitFeedback/obj/Release/HitFeedback.AssemblyInfo.cs b/HitFeedback/obj/Release/HitFeedback.AssemblyInfo.cs index 09cb1e4..bd1fb24 100644 --- a/HitFeedback/obj/Release/HitFeedback.AssemblyInfo.cs +++ b/HitFeedback/obj/Release/HitFeedback.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("HitFeedback")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Release")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+2af09007f967b42ac04776167f814297d14582e3")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+2b7943339c8fff4147e07028e81b3fff19ff0d80")] [assembly: System.Reflection.AssemblyProductAttribute("HitFeedback")] [assembly: System.Reflection.AssemblyTitleAttribute("HitFeedback")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/HitFeedback/obj/Release/HitFeedback.AssemblyInfoInputs.cache b/HitFeedback/obj/Release/HitFeedback.AssemblyInfoInputs.cache index 2be95b8..5e56970 100644 --- a/HitFeedback/obj/Release/HitFeedback.AssemblyInfoInputs.cache +++ b/HitFeedback/obj/Release/HitFeedback.AssemblyInfoInputs.cache @@ -1 +1 @@ -af2244db1221597efe6147a09f74a909205fbb96bd2548e7cd4320372ffd41b1 +1ef47fdca68bb8ba079c984a562e35f7d221eeaabc5c5290fb8b33cc52111227 diff --git a/HitFeedback/obj/Release/HitFeedback.csproj.AssemblyReference.cache b/HitFeedback/obj/Release/HitFeedback.csproj.AssemblyReference.cache index 2f0b834..1b2ae5d 100644 Binary files a/HitFeedback/obj/Release/HitFeedback.csproj.AssemblyReference.cache and b/HitFeedback/obj/Release/HitFeedback.csproj.AssemblyReference.cache differ diff --git a/SceneSnapshot/PrintTool.cs b/SceneSnapshot/PrintTool.cs index 284a555..68fb704 100644 --- a/SceneSnapshot/PrintTool.cs +++ b/SceneSnapshot/PrintTool.cs @@ -1,6 +1,8 @@ using System; +using System.Collections; using System.Collections.Generic; using System.IO; +using System.Reflection; using System.Text; using UnityEngine; using UnityEngine.EventSystems; @@ -11,6 +13,8 @@ namespace SceneSnapshot internal class PrintTool : MonoBehaviour { private const string FOLDER_NAME = "GameObjectSnapshots"; + private const int MAX_REFLECTION_DEPTH = 3; // 最大反射深度,防止循环引用或过深的对象图 + private const int MAX_COLLECTION_ELEMENTS_TO_PRINT = 5; // 集合最多打印的元素数量 private void Update() { @@ -19,7 +23,6 @@ namespace SceneSnapshot private void CaptureAndPrintSceneInfo() { - var desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); var outputFolderPath = Path.Combine(desktopPath, FOLDER_NAME); @@ -36,7 +39,7 @@ namespace SceneSnapshot Debug.LogError($"创建文件夹失败: {outputFolderPath} - {ex.Message}"); return; } - + var activeSceneName = SceneManager.GetActiveScene().name; var timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss"); var fileName = $"{activeSceneName}_FullSnapshot_{timestamp}.txt"; // 修改文件名以示区别 @@ -75,7 +78,7 @@ namespace SceneSnapshot sb.AppendLine("================================================="); - + try { File.WriteAllText(fullFilePath, sb.ToString(), Encoding.UTF8); @@ -116,7 +119,7 @@ namespace SceneSnapshot } /// - /// 尝试检测鼠标位置下方的UI元素或场景对象,并将其路径追加到StringBuilder。 + /// 尝试检测鼠标位置下方的UI元素或场景对象,并将其路径和组件信息追加到StringBuilder。 /// /// StringBuilder实例。 private void AppendMouseHoverObjectInfo(StringBuilder sb) @@ -125,8 +128,10 @@ namespace SceneSnapshot var eventDataCurrentPosition = new PointerEventData(EventSystem.current); eventDataCurrentPosition.position = new Vector2(Input.mousePosition.x, Input.mousePosition.y); var results = new List(); - - if (EventSystem.current) EventSystem.current.RaycastAll(eventDataCurrentPosition, results); + if (EventSystem.current) + { + EventSystem.current.RaycastAll(eventDataCurrentPosition, results); + } if (results.Count > 0) { @@ -134,7 +139,11 @@ namespace SceneSnapshot var uiObject = results[0].gameObject; var uiPath = GetGameObjectPath(uiObject); sb.AppendLine($"鼠标下方UI路径: {uiPath}"); - sb.AppendLine($" - 所在场景: {uiObject.scene.name}"); // 添加所在场景信息 + sb.AppendLine($" - 所在场景: {uiObject.scene.name}"); + + // 添加UI对象组件信息 + sb.AppendLine(" - UI对象组件信息:"); + AppendGameObjectComponentInfo(sb, uiObject, " "); // 增加缩进 return; } @@ -143,12 +152,15 @@ namespace SceneSnapshot { var ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; - if (Physics.Raycast(ray, out hit)) { var sceneObjectPath = GetGameObjectPath(hit.collider.gameObject); sb.AppendLine($"鼠标下方场景对象路径: {sceneObjectPath}"); - sb.AppendLine($" - 所在场景: {hit.collider.gameObject.scene.name}"); // 添加所在场景信息 + sb.AppendLine($" - 所在场景: {hit.collider.gameObject.scene.name}"); + + // 添加场景对象组件信息 + sb.AppendLine(" - 场景对象组件信息:"); + AppendGameObjectComponentInfo(sb, hit.collider.gameObject, " "); // 增加缩进 return; } } @@ -160,6 +172,299 @@ namespace SceneSnapshot sb.AppendLine("鼠标位置处没有检测到UI元素或场景对象。"); } + /// + /// 为指定的GameObject追加其所有组件的信息。 + /// + /// StringBuilder实例。 + /// 目标GameObject。 + /// 当前的缩进字符串。 + private void AppendGameObjectComponentInfo(StringBuilder sb, GameObject obj, string indent) + { + Component[] components = obj.GetComponents(); + if (components.Length == 0) + { + sb.AppendLine($"{indent} - 无组件"); + return; + } + + foreach (var component in components) + { + if (component == null) + { + sb.AppendLine($"{indent} - (空组件)"); + continue; + } + + // 尝试获取Behaviour的enabled状态 + string enabledStatus = (component is Behaviour behaviour) ? behaviour.enabled.ToString() : "N/A"; + sb.AppendLine($"{indent} - 组件: {component.GetType().Name} (Enabled: {enabledStatus})"); + AppendComponentPropertiesAndFields(sb, component, indent + " "); // 更深一层缩进,显示组件的属性/字段 + } + } + + /// + /// 利用反射为指定的组件追加其公共属性和字段的信息。 + /// + /// StringBuilder实例。 + /// 目标组件。 + /// 当前的缩进字符串。 + private void AppendComponentPropertiesAndFields(StringBuilder sb, Component component, string indent) + { + var bindingFlags = BindingFlags.Public | BindingFlags.Instance; + var componentType = component.GetType(); + // 收集所有公共实例属性和字段 + var members = new List(); + members.AddRange(componentType.GetProperties(bindingFlags)); + members.AddRange(componentType.GetFields(bindingFlags)); + bool hasPrintedAnything = false; + foreach (var member in members) + { + // 排除一些常见或特定组件上可能导致冗余或问题的属性/字段 + if (IsMemberToExclude(member, component)) continue; + object value = null; + string memberName = member.Name; + try + { + if (member is PropertyInfo pi) + { + if (pi.CanRead) // 确保属性可读 + { + value = pi.GetValue(component); + } + else + { + // 忽略不可读的属性 + continue; + } + } + else if (member is FieldInfo fi) + { + value = fi.GetValue(component); + } + } + catch (Exception ex) + { + // 捕获获取值时可能发生的异常 + sb.AppendLine($"{indent}- {memberName}: <获取失败: {ex.GetType().Name}>"); + hasPrintedAnything = true; + continue; + } + + // 格式化值进行显示,初始深度为0 + string formattedValue = FormatValueForDisplay(value, 0); + sb.AppendLine($"{indent}- {memberName}: {formattedValue}"); + hasPrintedAnything = true; + } + + if (!hasPrintedAnything) + { + sb.AppendLine($"{indent}- (无公共属性或字段)"); + } + } + + /// + /// 判断一个成员是否应该被排除在打印列表之外。 + /// 用于过滤掉冗余或可能导致深度递归的成员。 + /// + /// 要检查的MemberInfo。 + /// 该成员所属的组件实例。 + /// 如果应排除则返回true。 + private bool IsMemberToExclude(MemberInfo member, Component component) + { + // 排除从UnityEngine.Object继承的常见属性,这些通常是GameObject级别的元数据, + // 或者可能导致不必要的递归。 + // 特别是gameObject和transform,它们的类型就是GameObject和Transform,递归它们没有意义, + // 且其值就是组件所依附的GameObject和Transform,已经通过GetGameObjectPath显示了。 + switch (member.Name) + { + case "hideFlags": // Unity内部的标志,通常不需要显示 + case "name": // GameObject的名称,已在路径中显示 + case "tag": // GameObject的标签,可从GameObject直接获取 + case "layer": // GameObject的层,可从GameObject直接获取 + case "useGUILayout": // Unity内部GUI相关的,通常不作为组件值关心 + case "runInEditMode": // Unity编辑器模式相关,通常不作为组件值关心 + // 对于Component基类上的gameObject和transform属性,它们直接指向宿主对象和其Transform。 + // 打印它们本身就是重复的且可能误导(不是组件内部的独特“值”)。 + case "gameObject": + case "transform": + case "isStatic": // GameObject的isStatic状态 + return true; + } + + // 进一步过滤掉一些Unity内部或编辑器相关的属性,这些属性通常在运行时不提供有用的组件值信息。 + if (member.DeclaringType == typeof(Behaviour) || member.DeclaringType == typeof(MonoBehaviour)) + { + switch (member.Name) + { + case "isActiveAndEnabled": // 行为体的激活状态,通常与enabled一起考虑 + return true; + } + } + + return false; + } + + /// + /// 格式化对象值以进行显示,特别是针对Unity的常见类型,以避免循环打印和提供简洁输出。 + /// + /// 要格式化的值。 + /// 当前的递归深度。 + /// 格式化后的字符串。 + private string FormatValueForDisplay(object value, int currentDepth = 0) + { + if (value == null) return "null"; + Type type = value.GetType(); + // 深度限制检查:如果超过最大深度,则返回提示信息 + if (currentDepth >= MAX_REFLECTION_DEPTH) + { + // 对于集合,提供更具体一些的信息 + if (value is Array array1) return $"Array (Count: {array1.Length}, Max Depth Reached)"; + if (value is IList list1) return $"List (Count: {list1.Count}, Max Depth Reached)"; + if (value is IDictionary dictionary) return $"Dictionary (Count: {dictionary.Count}, Max Depth Reached)"; + return $"[{type.Name} (Max Depth Reached)]"; + } + + // 1. 基本类型、字符串、枚举:直接ToString() + if (type.IsPrimitive || type == typeof(string) || type.IsEnum) + { + return value.ToString(); + } + + // 2. 常见的Unity结构体:特殊格式化,避免深度递归并提供简洁输出 + if (value is Vector2 vec2) return $"({vec2.x:F2}, {vec2.y:F2})"; + if (value is Vector3 vec3) return $"({vec3.x:F2}, {vec3.y:F2}, {vec3.z:F2})"; + if (value is Vector4 vec4) return $"({vec4.x:F2}, {vec4.y:F2}, {vec4.z:F2}, {vec4.w:F2})"; + + // Quaternion默认ToString()会显示x,y,z,w,但有时EulerAngles更直观。 + if (value is Quaternion q) + return + $"Q({q.x:F2}, {q.y:F2}, {q.z:F2}, {q.w:F2}) (Euler: {q.eulerAngles.x:F2}, {q.eulerAngles.y:F2}, {q.eulerAngles.z:F2})"; + + if (value is Color color) return $"RGBA({color.r:F2}, {color.g:F2}, {color.b:F2}, {color.a:F2})"; + if (value is Rect rect) + return $"Rect(Pos:({rect.xMin:F2},{rect.yMin:F2}) Size:({rect.width:F2},{rect.height:F2}))"; + if (value is Bounds bounds) + return + $"Bounds(Center:({bounds.center.x:F2},{bounds.center.y:F2},{bounds.center.z:F2}) Extents:({bounds.extents.x:F2},{bounds.extents.y:F2},{bounds.extents.z:F2}))"; + if (value is LayerMask layerMask) + { + // LayerMask的值可能代表多个层,或一个单一层。LayerToName只能转换单一层。 + // 对于多个层,返回其原始值更有意义。 + return $"LayerMask(Value: {layerMask.value})"; + } + + // 3. GameObject/Component引用:只打印名称或类型,避免无限递归 + if (value is GameObject go) return $"GameObject:'{go.name}'"; + if (value is Component comp) + return $"Component:'{comp.GetType().Name}' on GameObject:'{comp.gameObject.name}'"; + + // 4. 集合类型:现在会打印内容,调用专门的辅助方法 + if (value is Array array) + { + return FormatCollectionForDisplay(array, currentDepth + 1); + } + + if (value is IList list) + { + return FormatCollectionForDisplay(list, currentDepth + 1); + } + + if (value is IDictionary dict) + { + return FormatCollectionForDisplay(dict, currentDepth + 1); + } + + // 对于其他不可转换为Array/IList/IDictionary的IEnumerable,但又不是字符串的类型 + if (value is IEnumerable enumerable && !(value is string)) + { + return FormatCollectionForDisplay(enumerable, currentDepth + 1); + } + + // 5. 其他复杂引用类型:只打印其类型名称,默认不深入其内部 (除非深度允许,但在深度限制前这里只会显示类型名) + return type.Name; // 例如: Material, Texture2D等,只显示类型名 + } + + /// + /// 格式化集合对象以进行显示,支持深度限制和元素数量限制。 + /// + /// 要格式化的集合。 + /// 当前的递归深度。 + /// 格式化后的集合字符串。 + private string FormatCollectionForDisplay(IEnumerable collection, int currentDepth) + { + if (collection == null) return "null collection"; + Type collectionType = collection.GetType(); + StringBuilder sb = new StringBuilder(); + // 尝试获取集合的类型名,去除可能的反引号(用于泛型类型) + string collectionTypeName = collectionType.IsGenericType + ? collectionType.Name.Substring(0, collectionType.Name.IndexOf('`')) + : collectionType.Name.Replace("[]", ""); + sb.Append(collectionTypeName); + + sb.Append(" ["); + int i = 0; + foreach (var item in collection) + { + if (i >= MAX_COLLECTION_ELEMENTS_TO_PRINT) + { + sb.Append(", ..."); + break; + } + + if (i > 0) sb.Append(", "); + if (item is DictionaryEntry entry) // 针对非泛型IDictionary + { + sb.Append( + $"{{{FormatValueForDisplay(entry.Key, currentDepth + 1)}: {FormatValueForDisplay(entry.Value, currentDepth + 1)}}}"); + } + else + { + Type itemType = item?.GetType(); + // 针对泛型IDictionary,其元素是KeyValuePair + if (itemType != null && itemType.IsGenericType && + itemType.GetGenericTypeDefinition() == typeof(KeyValuePair<,>)) + { + // 使用反射获取Key和Value属性 + PropertyInfo keyProperty = itemType.GetProperty("Key"); + PropertyInfo valueProperty = itemType.GetProperty("Value"); + if (keyProperty != null && valueProperty != null) + { + object key = keyProperty.GetValue(item); + object value = valueProperty.GetValue(item); + sb.Append( + $"{{{FormatValueForDisplay(key, currentDepth + 1)}: {FormatValueForDisplay(value, currentDepth + 1)}}}"); + } + else + { + // Fallback in case Key/Value properties aren't found + sb.Append(FormatValueForDisplay(item, currentDepth + 1)); + } + } + else + { + // 格式化普通集合元素 + sb.Append(FormatValueForDisplay(item, currentDepth + 1)); + } + } + + i++; + } + + // 尝试获取集合的实际数量 + string countInfo = "N/A"; + if (collection is ICollection c) + { + countInfo = c.Count.ToString(); + } + else if (collection is Array a) + { + countInfo = a.Length.ToString(); + } + + sb.Append($"] (Count: {countInfo})"); + return sb.ToString(); + } + /// /// 获取给定游戏对象的完整层次路径。 /// @@ -180,5 +485,6 @@ namespace SceneSnapshot return path; } + } } \ No newline at end of file diff --git a/SceneSnapshot/SceneSnapshot.csproj b/SceneSnapshot/SceneSnapshot.csproj index 39addd0..a64f2f9 100644 --- a/SceneSnapshot/SceneSnapshot.csproj +++ b/SceneSnapshot/SceneSnapshot.csproj @@ -12,7 +12,12 @@ 1.0.0 - + + D:\steam\steamapps\common\Escape from Duckov\Duckov_Data\Mods\SceneSnapshot + false + none + + False diff --git a/SceneSnapshot/bin/Release/SceneSnapshot.dll b/SceneSnapshot/bin/Release/SceneSnapshot.dll index 9a5dddd..5351299 100644 Binary files a/SceneSnapshot/bin/Release/SceneSnapshot.dll and b/SceneSnapshot/bin/Release/SceneSnapshot.dll differ diff --git a/SceneSnapshot/bin/Release/SceneSnapshot.pdb b/SceneSnapshot/bin/Release/SceneSnapshot.pdb index c67b772..3e3de12 100644 Binary files a/SceneSnapshot/bin/Release/SceneSnapshot.pdb and b/SceneSnapshot/bin/Release/SceneSnapshot.pdb differ diff --git a/SceneSnapshot/obj/Debug/SceneSnapshot.GeneratedMSBuildEditorConfig.editorconfig b/SceneSnapshot/obj/Debug/SceneSnapshot.GeneratedMSBuildEditorConfig.editorconfig index 7ec4bf6..1724fc1 100644 --- a/SceneSnapshot/obj/Debug/SceneSnapshot.GeneratedMSBuildEditorConfig.editorconfig +++ b/SceneSnapshot/obj/Debug/SceneSnapshot.GeneratedMSBuildEditorConfig.editorconfig @@ -1,6 +1,6 @@ is_global = true build_property.RootNamespace = SceneSnapshot -build_property.ProjectDir = D:\vs_project\DuckovMods\SceneSnapshot\ +build_property.ProjectDir = d:\vs_project\DuckovMods\SceneSnapshot\ build_property.EnableComHosting = build_property.EnableGeneratedComInterfaceComImportInterop = build_property.CsWinRTUseWindowsUIXamlProjections = false diff --git a/SceneSnapshot/obj/Debug/SceneSnapshot.assets.cache b/SceneSnapshot/obj/Debug/SceneSnapshot.assets.cache index 6e8413b..5bdef6f 100644 Binary files a/SceneSnapshot/obj/Debug/SceneSnapshot.assets.cache and b/SceneSnapshot/obj/Debug/SceneSnapshot.assets.cache differ diff --git a/SceneSnapshot/obj/Release/SceneSnapshot.AssemblyInfo.cs b/SceneSnapshot/obj/Release/SceneSnapshot.AssemblyInfo.cs index f90e06b..64be909 100644 --- a/SceneSnapshot/obj/Release/SceneSnapshot.AssemblyInfo.cs +++ b/SceneSnapshot/obj/Release/SceneSnapshot.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("折纸的小箱子")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Release")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+2af09007f967b42ac04776167f814297d14582e3")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+2b7943339c8fff4147e07028e81b3fff19ff0d80")] [assembly: System.Reflection.AssemblyProductAttribute("SceneSnapshot")] [assembly: System.Reflection.AssemblyTitleAttribute("SceneSnapshot")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0")] diff --git a/SceneSnapshot/obj/Release/SceneSnapshot.AssemblyInfoInputs.cache b/SceneSnapshot/obj/Release/SceneSnapshot.AssemblyInfoInputs.cache index ae46ee9..03b67a3 100644 --- a/SceneSnapshot/obj/Release/SceneSnapshot.AssemblyInfoInputs.cache +++ b/SceneSnapshot/obj/Release/SceneSnapshot.AssemblyInfoInputs.cache @@ -1 +1 @@ -059d393a593444cbbfade46bc154efc9d0e32b1f1b1636870bc8de347b95447d +2f140dae1dc23271ae8c394fe95f090beff12b9a0cf8188ff19a7e6d42bca22f diff --git a/SceneSnapshot/obj/Release/SceneSnapshot.csproj.AssemblyReference.cache b/SceneSnapshot/obj/Release/SceneSnapshot.csproj.AssemblyReference.cache index e17280e..6391f5f 100644 Binary files a/SceneSnapshot/obj/Release/SceneSnapshot.csproj.AssemblyReference.cache and b/SceneSnapshot/obj/Release/SceneSnapshot.csproj.AssemblyReference.cache differ diff --git a/SceneSnapshot/obj/Release/SceneSnapshot.csproj.FileListAbsolute.txt b/SceneSnapshot/obj/Release/SceneSnapshot.csproj.FileListAbsolute.txt index b232b9e..f3d21c6 100644 --- a/SceneSnapshot/obj/Release/SceneSnapshot.csproj.FileListAbsolute.txt +++ b/SceneSnapshot/obj/Release/SceneSnapshot.csproj.FileListAbsolute.txt @@ -8,3 +8,13 @@ D:\vs_project\ThirdPersonCamera\SceneSnapshot\obj\Release\SceneSnapshot.Assembly D:\vs_project\ThirdPersonCamera\SceneSnapshot\obj\Release\SceneSnapshot.csproj.CoreCompileInputs.cache D:\vs_project\ThirdPersonCamera\SceneSnapshot\obj\Release\SceneSnapshot.dll D:\vs_project\ThirdPersonCamera\SceneSnapshot\obj\Release\SceneSnapshot.pdb +D:\vs_project\DuckovMods\SceneSnapshot\bin\Release\SceneSnapshot.deps.json +D:\vs_project\DuckovMods\SceneSnapshot\bin\Release\SceneSnapshot.dll +D:\vs_project\DuckovMods\SceneSnapshot\bin\Release\SceneSnapshot.pdb +D:\vs_project\DuckovMods\SceneSnapshot\obj\Release\SceneSnapshot.csproj.AssemblyReference.cache +D:\vs_project\DuckovMods\SceneSnapshot\obj\Release\SceneSnapshot.GeneratedMSBuildEditorConfig.editorconfig +D:\vs_project\DuckovMods\SceneSnapshot\obj\Release\SceneSnapshot.AssemblyInfoInputs.cache +D:\vs_project\DuckovMods\SceneSnapshot\obj\Release\SceneSnapshot.AssemblyInfo.cs +D:\vs_project\DuckovMods\SceneSnapshot\obj\Release\SceneSnapshot.csproj.CoreCompileInputs.cache +D:\vs_project\DuckovMods\SceneSnapshot\obj\Release\SceneSnapshot.dll +D:\steam\steamapps\common\Escape from Duckov\Duckov_Data\Mods\SceneSnapshot\SceneSnapshot.dll diff --git a/SceneSnapshot/obj/Release/SceneSnapshot.dll b/SceneSnapshot/obj/Release/SceneSnapshot.dll index 9a5dddd..fa5efa2 100644 Binary files a/SceneSnapshot/obj/Release/SceneSnapshot.dll and b/SceneSnapshot/obj/Release/SceneSnapshot.dll differ diff --git a/SceneSnapshot/obj/Release/SceneSnapshot.pdb b/SceneSnapshot/obj/Release/SceneSnapshot.pdb deleted file mode 100644 index c67b772..0000000 Binary files a/SceneSnapshot/obj/Release/SceneSnapshot.pdb and /dev/null differ diff --git a/UIFrame/ModBehaviour.cs b/UIFrame/ModBehaviour.cs new file mode 100644 index 0000000..7964916 --- /dev/null +++ b/UIFrame/ModBehaviour.cs @@ -0,0 +1,17 @@ +using UnityEngine; + +namespace UIFrame +{ + public class ModBehaviour:Duckov.Modding.ModBehaviour + { + protected override void OnAfterSetup() + { + Debug.Log("OnAfterSetup"); + } + + protected override void OnBeforeDeactivate() + { + Debug.Log("OnBeforeDeactivate"); + } + } +} \ No newline at end of file diff --git a/UIFrame/UIFrameAPI.cs b/UIFrame/UIFrameAPI.cs new file mode 100644 index 0000000..7ca993d --- /dev/null +++ b/UIFrame/UIFrameAPI.cs @@ -0,0 +1,7 @@ +namespace UIFrame +{ + public class UIFrameAPI + { + + } +} \ No newline at end of file diff --git a/UIFrame/UIManager.cs b/UIFrame/UIManager.cs new file mode 100644 index 0000000..69328db --- /dev/null +++ b/UIFrame/UIManager.cs @@ -0,0 +1,7 @@ +namespace UIFrame +{ + public static class UIManager + { + + } +} \ No newline at end of file