Jelajahi Sumber

从Core Loader中挪了部分功能过来,编辑器包没下载好的时候,这些功能就必须存在

tanghai 1 tahun lalu
induk
melakukan
60b75b8154
36 mengubah file dengan 1017 tambahan dan 1 penghapusan
  1. 8 0
      Packages/cn.etetet.init/Editor/AsmdefEditor.meta
  2. 105 0
      Packages/cn.etetet.init/Editor/AsmdefEditor/AsmdefEditor.cs
  3. 11 0
      Packages/cn.etetet.init/Editor/AsmdefEditor/AsmdefEditor.cs.meta
  4. 3 1
      Packages/cn.etetet.init/Editor/ET.Init.Editor.asmdef
  5. 67 0
      Packages/cn.etetet.init/Editor/EditorResHelper.cs
  6. 3 0
      Packages/cn.etetet.init/Editor/EditorResHelper.cs.meta
  7. 107 0
      Packages/cn.etetet.init/Editor/FileHelper.cs
  8. 3 0
      Packages/cn.etetet.init/Editor/FileHelper.cs.meta
  9. 8 0
      Packages/cn.etetet.init/Editor/GlobalConfigEditor.meta
  10. 121 0
      Packages/cn.etetet.init/Editor/GlobalConfigEditor/CodeModeChangeHelper.cs
  11. 3 0
      Packages/cn.etetet.init/Editor/GlobalConfigEditor/CodeModeChangeHelper.cs.meta
  12. 68 0
      Packages/cn.etetet.init/Editor/GlobalConfigEditor/GlobalConfigEditor.cs
  13. 11 0
      Packages/cn.etetet.init/Editor/GlobalConfigEditor/GlobalConfigEditor.cs.meta
  14. 21 0
      Packages/cn.etetet.init/Editor/InitHelper.cs
  15. 3 0
      Packages/cn.etetet.init/Editor/InitHelper.cs.meta
  16. 8 0
      Packages/cn.etetet.init/Editor/LogRedirection.meta
  17. 101 0
      Packages/cn.etetet.init/Editor/LogRedirection/LogRedirection.cs
  18. 11 0
      Packages/cn.etetet.init/Editor/LogRedirection/LogRedirection.cs.meta
  19. 8 0
      Packages/cn.etetet.init/Editor/PackageConfigEditor.meta
  20. 14 0
      Packages/cn.etetet.init/Editor/PackageConfigEditor/PackageConfig.cs
  21. 11 0
      Packages/cn.etetet.init/Editor/PackageConfigEditor/PackageConfig.cs.meta
  22. 63 0
      Packages/cn.etetet.init/Editor/PackageConfigEditor/PackageConfigEditor.cs
  23. 11 0
      Packages/cn.etetet.init/Editor/PackageConfigEditor/PackageConfigEditor.cs.meta
  24. 103 0
      Packages/cn.etetet.init/Editor/ShellHelper.cs
  25. 11 0
      Packages/cn.etetet.init/Editor/ShellHelper.cs.meta
  26. 8 0
      Packages/cn.etetet.init/Editor/ToolEditor.meta
  27. 29 0
      Packages/cn.etetet.init/Editor/ToolEditor/ToolsEditor.cs
  28. 11 0
      Packages/cn.etetet.init/Editor/ToolEditor/ToolsEditor.cs.meta
  29. 5 0
      Packages/cn.etetet.init/Resources.meta
  30. 17 0
      Packages/cn.etetet.init/Resources/GlobalConfig.asset
  31. 8 0
      Packages/cn.etetet.init/Resources/GlobalConfig.asset.meta
  32. 8 0
      Packages/cn.etetet.init/Runtime.meta
  33. 3 0
      Packages/cn.etetet.init/Runtime/ET.Init.asmdef
  34. 7 0
      Packages/cn.etetet.init/Runtime/ET.Init.asmdef.meta
  35. 27 0
      Packages/cn.etetet.init/Runtime/GlobalConfig.cs
  36. 11 0
      Packages/cn.etetet.init/Runtime/GlobalConfig.cs.meta

+ 8 - 0
Packages/cn.etetet.init/Editor/AsmdefEditor.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 29360096fda48a142a3af69d1a2a1db4
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 105 - 0
Packages/cn.etetet.init/Editor/AsmdefEditor/AsmdefEditor.cs

@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using UnityEditor;
+using UnityEngine;
+
+namespace ET.Loader
+{
+    public class AssemblyDefinitionAsset
+    {
+        public string name;
+        public string rootNamespace;
+        public string[] references;
+        public string[] includePlatforms;
+        public string[] excludePlatforms;
+        public bool allowUnsafeCode;
+        public bool overrideReferences;
+        public string[] precompiledReferences;
+        public bool autoReferenced;
+        public string[] defineConstraints;
+        public string[] versionDefines;
+        public bool noEngineReferences;
+        public string[] optionalUnityReferences;
+        public string[] additionalReferences;
+        public string compilerOptions;
+    }
+
+    public class AllRefInfo
+    {
+        public Dictionary<string, HashSet<string>> References = new();
+        
+        public AllRefInfo()
+        {
+            foreach (string assName in AsmdefEditor.AssNames)
+            {
+                References[assName] = new HashSet<string>();
+            }
+        }
+    }
+    
+    public static class AsmdefEditor
+    {
+        public static readonly string[] AssNames = { "Model", "ModelView", "Hotfix", "HotfixView" };
+        public static readonly string[] PackagePaths = { "Packages", "Library/PackageCache" };
+        
+        // 自动把各个包中的引用加到Assets对应的包中去,后面搞个编辑器来编辑每个包的引用
+        [MenuItem("ET/Update Assembly Definition")]
+        public static void UpdateAssemblyDefinition()
+        {
+            AllRefInfo allRefInfo = new();
+
+            foreach (string packagePath in PackagePaths)
+            {
+                foreach (string directory in Directory.GetDirectories(packagePath, "cn.etetet.*"))
+                {
+                    foreach (string assName in AssNames)
+                    {
+                        string p = Path.Combine(directory, "Scripts/" + assName + "/asmdef.txt");
+                        if (!File.Exists(p))
+                        {
+                            continue;
+                        }
+
+                        string json = File.ReadAllText(p);
+                        try
+                        {
+                            AssemblyDefinitionAsset assemblyDefinitionAsset = JsonUtility.FromJson<AssemblyDefinitionAsset>(json);
+                            foreach (string reference in assemblyDefinitionAsset.references)
+                            {
+                                allRefInfo.References[assName].Add(reference);
+                            }
+                        }
+                        catch (Exception e)
+                        {
+                            throw new Exception($"parse json error: {p} {json}", e);
+                        }
+                    }
+                }
+            }
+
+            List<string> findRet = new List<string>();
+            foreach (string assName in AssNames)
+            {
+                findRet.Clear();
+                FileHelper.GetAllFiles(findRet, "./Packages", $"ET.{assName}.asmdef");
+                string p = findRet[0];
+                if (!File.Exists(p))
+                {
+                    throw new Exception($"not found: {p}");
+                }
+
+                string json = File.ReadAllText(p);
+                AssemblyDefinitionAsset assemblyDefinitionAsset = JsonUtility.FromJson<AssemblyDefinitionAsset>(json);
+
+                assemblyDefinitionAsset.references = allRefInfo.References[assName].ToArray();
+
+                File.WriteAllText(p, JsonUtility.ToJson(assemblyDefinitionAsset, true));
+            }
+            
+            AssetDatabase.SaveAssets();
+            AssetDatabase.Refresh();
+        }
+    }
+}

+ 11 - 0
Packages/cn.etetet.init/Editor/AsmdefEditor/AsmdefEditor.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 18bfe6d021de1174f8a5de372e9ea6ad
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 3 - 1
Packages/cn.etetet.init/Editor/ET.Init.Editor.asmdef

@@ -1,7 +1,9 @@
 {
     "name": "ET.Init.Editor",
     "rootNamespace": "",
-    "references": [],
+    "references": [
+        "ET.Init"
+    ],
     "includePlatforms": [
         "Editor"
     ],

+ 67 - 0
Packages/cn.etetet.init/Editor/EditorResHelper.cs

@@ -0,0 +1,67 @@
+using System.Collections.Generic;
+using System.IO;
+using UnityEditor;
+
+namespace ET
+{
+    public class EditorResHelper
+    {
+        public static void SaveAssets(UnityEngine.Object asset)
+        {
+            EditorUtility.SetDirty(asset);
+            AssetDatabase.SaveAssets();
+            AssetDatabase.Refresh();
+        }
+        
+        /// <summary>
+        /// 获取文件夹内所有的预制跟场景路径
+        /// </summary>
+        /// <param name="srcPath">源文件夹</param>
+        /// <param name="subDire">是否获取子文件夹</param>
+        /// <returns></returns>
+        public static List<string> GetPrefabsAndScenes(string srcPath)
+        {
+            List<string> paths = new List<string>();
+            FileHelper.GetAllFiles(paths, srcPath);
+            
+            List<string> files = new List<string>();
+            foreach (string str in paths)
+            {
+                if (str.EndsWith(".prefab") || str.EndsWith(".unity"))
+                {
+                    files.Add(str);
+                }
+            }
+            return files;
+        }
+        
+        /// <summary>
+        /// 获取文件夹内所有资源路径
+        /// </summary>
+        /// <param name="srcPath">源文件夹</param>
+        /// <param name="subDire">是否获取子文件夹</param>
+        /// <returns></returns>
+        public static List<string> GetAllResourcePath(string srcPath, bool subDire)
+        {
+            List<string> paths = new List<string>();
+            string[] files = Directory.GetFiles(srcPath);
+            foreach (string str in files)
+            {
+                if (str.EndsWith(".meta"))
+                {
+                    continue;
+                }
+                paths.Add(str);
+            }
+            if (subDire)
+            {
+                foreach (string subPath in Directory.GetDirectories(srcPath))
+                {
+                    List<string> subFiles = GetAllResourcePath(subPath, true);
+                    paths.AddRange(subFiles);
+                }
+            }
+            return paths;
+        }
+    }
+}

+ 3 - 0
Packages/cn.etetet.init/Editor/EditorResHelper.cs.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 534eee73ca004cb58dcde9e3536b8b74
+timeCreated: 1507865453

+ 107 - 0
Packages/cn.etetet.init/Editor/FileHelper.cs

@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace ET
+{
+	public static class FileHelper
+	{
+		public static List<string> GetAllFiles(string dir, string searchPattern = "*")
+		{
+			List<string> list = new List<string>();
+			GetAllFiles(list, dir, searchPattern);
+			return list;
+		}
+		
+		public static void GetAllFiles(List<string> files, string dir, string searchPattern = "*")
+		{
+			string[] fls = Directory.GetFiles(dir, searchPattern);
+			foreach (string fl in fls)
+			{
+				files.Add(fl);
+			}
+
+			string[] subDirs = Directory.GetDirectories(dir);
+			foreach (string subDir in subDirs)
+			{
+				GetAllFiles(files, subDir, searchPattern);
+			}
+		}
+		
+		public static void CleanDirectory(string dir)
+		{
+			if (!Directory.Exists(dir))
+			{
+				return;
+			}
+			foreach (string subdir in Directory.GetDirectories(dir))
+			{
+				Directory.Delete(subdir, true);		
+			}
+
+			foreach (string subFile in Directory.GetFiles(dir))
+			{
+				File.Delete(subFile);
+			}
+		}
+
+		public static void CopyDirectory(string srcDir, string tgtDir)
+		{
+			DirectoryInfo source = new DirectoryInfo(srcDir);
+			DirectoryInfo target = new DirectoryInfo(tgtDir);
+	
+			if (target.FullName.StartsWith(source.FullName, StringComparison.CurrentCultureIgnoreCase))
+			{
+				throw new Exception("父目录不能拷贝到子目录!");
+			}
+	
+			if (!source.Exists)
+			{
+				return;
+			}
+	
+			if (!target.Exists)
+			{
+				target.Create();
+			}
+	
+			FileInfo[] files = source.GetFiles();
+	
+			for (int i = 0; i < files.Length; i++)
+			{
+				File.Copy(files[i].FullName, Path.Combine(target.FullName, files[i].Name), true);
+			}
+	
+			DirectoryInfo[] dirs = source.GetDirectories();
+	
+			for (int j = 0; j < dirs.Length; j++)
+			{
+				CopyDirectory(dirs[j].FullName, Path.Combine(target.FullName, dirs[j].Name));
+			}
+		}
+		
+		public static void ReplaceExtensionName(string srcDir, string extensionName, string newExtensionName)
+		{
+			if (Directory.Exists(srcDir))
+			{
+				string[] fls = Directory.GetFiles(srcDir);
+
+				foreach (string fl in fls)
+				{
+					if (fl.EndsWith(extensionName))
+					{
+						File.Move(fl, fl.Substring(0, fl.IndexOf(extensionName)) + newExtensionName);
+						File.Delete(fl);
+					}
+				}
+
+				string[] subDirs = Directory.GetDirectories(srcDir);
+
+				foreach (string subDir in subDirs)
+				{
+					ReplaceExtensionName(subDir, extensionName, newExtensionName);
+				}
+			}
+		}
+	}
+}

+ 3 - 0
Packages/cn.etetet.init/Editor/FileHelper.cs.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 3fe9c71a958f4dacb500e378e05fc316
+timeCreated: 1718078770

+ 8 - 0
Packages/cn.etetet.init/Editor/GlobalConfigEditor.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 10ce5e5130790b9468addf1a602cf8f0
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 121 - 0
Packages/cn.etetet.init/Editor/GlobalConfigEditor/CodeModeChangeHelper.cs

@@ -0,0 +1,121 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace ET
+{
+    public static class CodeModeChangeHelper
+    {
+        private static readonly string[] moduleDirs = { "Packages", "Library/PackageCache" };
+
+        private static readonly string[] scriptDirs = { "Scripts", "CodeMode" };
+        
+        private static readonly string[] modelDirs = {"Model", "Hotfix", "ModelView", "HotfixView"};
+
+        private static readonly string[] serverDirs = { "Server", "Client", "Share", "ClientServer" };
+
+        private static readonly HashSet<string> v = new()
+        {
+            "Client/Scripts/Model/Client",
+            "Client/Scripts/Model/Share",
+            "Client/CodeMode/Model/Client",
+            "Client/Scripts/ModelView/Client",
+            "Client/Scripts/ModelView/Share",
+            "Client/CodeMode/ModelView/Client",
+            "Client/Scripts/Hotfix/Client",
+            "Client/Scripts/Hotfix/Share",
+            "Client/CodeMode/Hotfix/Client",
+            "Client/Scripts/HotfixView/Client",
+            "Client/Scripts/HotfixView/Share",
+            "Client/CodeMode/HotfixView/Client",
+
+            "Server/Scripts/Model/Server",
+            "Server/Scripts/Model/Share",
+            "Server/CodeMode/Model/Server",
+            "Server/Scripts/Hotfix/Server",
+            "Server/Scripts/Hotfix/Share",
+            "Server/CodeMode/Hotfix/Server",
+
+            "ClientServer/Scripts/Model/Client",
+            "ClientServer/Scripts/Model/Server",
+            "ClientServer/Scripts/Model/Share",
+            "ClientServer/CodeMode/Model/ClientServer",
+            "ClientServer/Scripts/ModelView/Client",
+            "ClientServer/Scripts/ModelView/Server",
+            "ClientServer/Scripts/ModelView/Share",
+            "ClientServer/CodeMode/ModelView/ClientServer",
+            "ClientServer/Scripts/Hotfix/Client",
+            "ClientServer/Scripts/Hotfix/Server",
+            "ClientServer/Scripts/Hotfix/Share",
+            "ClientServer/CodeMode/Hotfix/ClientServer",
+            "ClientServer/Scripts/HotfixView/Client",
+            "ClientServer/Scripts/HotfixView/Server",
+            "ClientServer/Scripts/HotfixView/Share",
+            "ClientServer/CodeMode/HotfixView/ClientServer"
+        };
+        
+        public static void ChangeToCodeMode(CodeMode codeMode)
+        {
+            foreach (string a in moduleDirs)
+            {
+                foreach (string moduleDir in Directory.GetDirectories(a, "cn.etetet.*"))
+                {
+                    foreach (string scriptDir in scriptDirs)
+                    {
+                        string p = Path.Combine(moduleDir, scriptDir);
+                        if (!Directory.Exists(p))
+                        {
+                            continue;
+                        }
+
+                        foreach (string modelDir in modelDirs)
+                        {
+                            string c = Path.Combine(p, modelDir);
+                            if (!Directory.Exists(c))
+                            {
+                                continue;
+                            }
+
+                            foreach (string serverDir in serverDirs)
+                            {
+                                string e = Path.Combine(c, serverDir);
+                                if (!Directory.Exists(e))
+                                {
+                                    continue;
+                                }
+
+                                HandleAssemblyReferenceFile(codeMode, moduleDir, scriptDir, modelDir, serverDir);
+                            }
+                        }
+                    }
+                }
+            }
+
+            
+        }
+
+        private static void HandleAssemblyReferenceFile(CodeMode codeMode, string moduleDir, string scriptDir, string modelDir, string serverDir)
+        {
+            string path = $"{codeMode}/{scriptDir}/{modelDir}/{serverDir}";
+            string filePath = Path.Combine(moduleDir, scriptDir, modelDir, serverDir, "AssemblyReference.asmref");
+            DeleteAssemblyReference(filePath);
+            if (v.Contains(path))
+            {
+                CreateAssemblyReference(filePath, modelDir);
+            }
+        }
+
+        private static void DeleteAssemblyReference(string path)
+        {
+            if (File.Exists(path))
+            {
+                File.Delete(path);
+            }
+        }
+        
+        private static void CreateAssemblyReference(string path, string modelDir)
+        {
+            File.WriteAllText(path, $"{{ \"reference\": \"ET.{modelDir}\" }}");
+        }
+    }
+}

+ 3 - 0
Packages/cn.etetet.init/Editor/GlobalConfigEditor/CodeModeChangeHelper.cs.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 77fe248dbd0142fda0f318d1cb0cdef8
+timeCreated: 1715699302

+ 68 - 0
Packages/cn.etetet.init/Editor/GlobalConfigEditor/GlobalConfigEditor.cs

@@ -0,0 +1,68 @@
+using System;
+using System.Linq;
+using UnityEditor;
+using UnityEngine;
+
+namespace ET
+{
+    [CustomEditor(typeof(GlobalConfig))]
+    public class GlobalConfigEditor : Editor
+    {
+        [MenuItem("ET/CodeMode Refresh")]
+        public static void Refresh()
+        {
+            GlobalConfig globalConfig = AssetDatabase.LoadAssetAtPath<GlobalConfig>("Packages/cn.etetet.init/Resources/GlobalConfig.asset");
+            CodeModeChangeHelper.ChangeToCodeMode(globalConfig.CodeMode);
+            AssetDatabase.Refresh();
+            Debug.Log("code mode refresh finish!");
+        }
+        
+        private void OnEnable()
+        {
+            GlobalConfig globalConfig = (GlobalConfig)this.target;
+            globalConfig.BuildType = EditorUserBuildSettings.development ? BuildType.Debug : BuildType.Release;
+            EditorResHelper.SaveAssets(globalConfig);
+        }
+
+        public override void OnInspectorGUI()
+        {
+            GlobalConfig globalConfig = (GlobalConfig)this.target;
+            CodeMode codeMode = (CodeMode)EditorGUILayout.EnumPopup("CodeMode", globalConfig.CodeMode);
+            if (codeMode != globalConfig.CodeMode)
+            {
+                globalConfig.CodeMode = codeMode;
+                
+                EditorResHelper.SaveAssets(globalConfig);
+                
+                CodeModeChangeHelper.ChangeToCodeMode(codeMode);
+                
+                AssetDatabase.Refresh();
+                InitHelper.ReGenerateProjectFiles();
+            }
+            
+            BuildType buildType = (BuildType)EditorGUILayout.EnumPopup("BuildType", globalConfig.BuildType);
+            if (buildType != globalConfig.BuildType)
+            {
+                globalConfig.BuildType = buildType;
+                EditorUserBuildSettings.development = globalConfig.BuildType switch
+                {
+                    BuildType.Debug => true,
+                    BuildType.Release => false,
+                    _ => throw new ArgumentOutOfRangeException()
+                };
+                EditorResHelper.SaveAssets(globalConfig);
+                AssetDatabase.Refresh();
+                InitHelper.ReGenerateProjectFiles();
+            }
+            
+            string sceneName = EditorGUILayout.TextField($"SceneName", globalConfig.SceneName);
+            if (sceneName != globalConfig.SceneName)
+            {
+                globalConfig.SceneName = sceneName;
+                EditorResHelper.SaveAssets(globalConfig);
+                AssetDatabase.Refresh();
+            }
+            
+        }
+    }
+}

+ 11 - 0
Packages/cn.etetet.init/Editor/GlobalConfigEditor/GlobalConfigEditor.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4ee994acc7f02fb42b82587aa7dc42bc
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 21 - 0
Packages/cn.etetet.init/Editor/InitHelper.cs

@@ -0,0 +1,21 @@
+using UnityEditor;
+using UnityEngine;
+
+namespace ET
+{
+    public static class InitHelper
+    {
+        [InitializeOnLoadMethod]
+        public static void ReGenerateProjectFiles()
+        {
+            Unity.CodeEditor.CodeEditor.CurrentEditor.SyncAll();
+
+            foreach (string s in FileHelper.GetAllFiles(".", "Ignore.ET*.csproj"))
+            {
+                System.IO.File.Delete(s);
+            }
+
+            Debug.Log("regenerate csproj");
+        }
+    }
+}

+ 3 - 0
Packages/cn.etetet.init/Editor/InitHelper.cs.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 54b3d57b779745868a98d8b2fe2358cf
+timeCreated: 1718079258

+ 8 - 0
Packages/cn.etetet.init/Editor/LogRedirection.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3be1c35d4fd53dd479a81cadf627f263
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 101 - 0
Packages/cn.etetet.init/Editor/LogRedirection/LogRedirection.cs

@@ -0,0 +1,101 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using UnityEditor;
+using UnityEditor.Callbacks;
+using UnityEditorInternal;
+
+namespace ET
+{
+    /// <summary>
+    /// 日志重定向相关的实用函数。
+    /// </summary>
+    internal static class LogRedirection
+    {
+        [OnOpenAsset(0)]
+        private static bool OnOpenAsset(int instanceID, int line)
+        {
+            if (line <= 0)
+            {
+                return false;
+            }
+
+            Regex logFileRegex = new(@"((Log\.cs)|(UnityLogger\.cs)|(YooLogger\.cs))");
+            string codePath = AssetDatabase.GetAssetPath(instanceID);
+            if (logFileRegex.IsMatch(codePath))
+            {
+                var content = GetStackTrace();
+                // 如果有手动输入的地址,就跳过
+                var hrefMath = Regex.Match(content, @"<a href=""(.*?)"" line=""(\w+)\"">.*?</a>");
+                if (hrefMath.Success)
+                {
+                    OpenIDE(hrefMath.Groups[1].Value, int.Parse(hrefMath.Groups[2].Value));
+                    return true;
+                }
+                
+                Match stackLineMatch = Regex.Match(content, @"\(at (.+):([0-9]+)\)");
+                while (stackLineMatch.Success)
+                {
+                    codePath = stackLineMatch.Groups[1].Value;
+                    if (!logFileRegex.IsMatch(codePath))
+                    {
+                        int matchLine = int.Parse(stackLineMatch.Groups[2].Value);
+                        OpenIDE(codePath, matchLine);
+                        return true;
+                    }
+                    stackLineMatch = stackLineMatch.NextMatch();
+                }
+            }
+            
+            return false;
+        }
+
+        private static void OpenIDE(string path, int line, int column = 0)
+        {
+            if (!Path.IsPathFullyQualified(path))
+            {
+                path = Path.GetFullPath(path);
+            }
+            // 跳转到目标代码的特定行
+            InternalEditorUtility.OpenFileAtLineExternal(path, line, column);
+        }
+
+        /// <summary>
+        /// 获取当前日志窗口选中的日志的堆栈信息。
+        /// </summary>
+        /// <returns>选中日志的堆栈信息实例。</returns>
+        private static string GetStackTrace()
+        {
+            // 通过反射获取ConsoleWindow类
+            var consoleWindowType = typeof(EditorWindow).Assembly.GetType("UnityEditor.ConsoleWindow");
+            // 获取窗口实例
+            var fieldInfo = consoleWindowType.GetField("ms_ConsoleWindow",
+                BindingFlags.Static |
+                BindingFlags.NonPublic);
+            if (fieldInfo != null)
+            {
+                var consoleInstance = fieldInfo.GetValue(null);
+                if (consoleInstance != null)
+                {
+                    if (EditorWindow.focusedWindow == (EditorWindow)consoleInstance)
+                    {
+                        // 获取m_ActiveText成员
+                        fieldInfo = consoleWindowType.GetField("m_ActiveText",
+                            BindingFlags.Instance |
+                            BindingFlags.NonPublic);
+                        // 获取m_ActiveText的值
+                        if (fieldInfo != null)
+                        {
+                            var activeText = fieldInfo.GetValue(consoleInstance).ToString();
+                            return activeText;
+                        }
+                    }
+                }
+            }
+
+            return null;
+        }
+    }
+}

+ 11 - 0
Packages/cn.etetet.init/Editor/LogRedirection/LogRedirection.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bb9b30528175c8b408a16abac17d4eb6
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Packages/cn.etetet.init/Editor/PackageConfigEditor.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 38a9c95f8a7257641899bcb1c87329b5
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 14 - 0
Packages/cn.etetet.init/Editor/PackageConfigEditor/PackageConfig.cs

@@ -0,0 +1,14 @@
+using System.IO;
+using UnityEditor;
+using UnityEngine;
+
+namespace ET
+{
+    [CreateAssetMenu(menuName = "ET/PackageConfig", fileName = "PackageConfig", order = 0)]
+    public class PackageConfig: ScriptableObject
+    {
+        public int Id;
+        public string Name;
+        public bool CreatePackageTypeFile;
+    }
+}

+ 11 - 0
Packages/cn.etetet.init/Editor/PackageConfigEditor/PackageConfig.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d54714756eb2c264a9e75f3e033bb25f
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 63 - 0
Packages/cn.etetet.init/Editor/PackageConfigEditor/PackageConfigEditor.cs

@@ -0,0 +1,63 @@
+using System.IO;
+using UnityEditor;
+using UnityEngine;
+
+namespace ET
+{
+    [CustomEditor(typeof(PackageConfig))]
+    public class PackageConfigEditor: Editor
+    {
+        [MenuItem("ET/Create All PackageType")]
+        public static void GeneratePackageTypeFile()
+        {
+            string[] packageConfigs = AssetDatabase.FindAssets("t:PackageConfig");
+            foreach (string packageConfig in packageConfigs)
+            {
+                string path = AssetDatabase.GUIDToAssetPath(packageConfig);
+                PackageConfig config = AssetDatabase.LoadAssetAtPath<PackageConfig>(path);
+                if (!config.CreatePackageTypeFile)
+                {
+                    continue;
+                }
+
+                string dir = Application.dataPath + "/../" + $"{Path.GetDirectoryName(path)}" + "/Scripts/Model/Share/";
+                CreatePackageTypeFile(dir, config);
+            }
+            Debug.Log("Generate PackageType File Finish!");
+        }
+
+        public static void CreatePackageTypeFile(string dir, PackageConfig config)
+        {
+            if (!Directory.Exists(dir))
+            {
+                Directory.CreateDirectory(dir);
+            }
+
+            using FileStream fileStream = new($"{dir}/PackageType.cs", FileMode.Create);
+            using StreamWriter streamWriter = new(fileStream);
+            streamWriter.WriteLine("namespace ET");
+            streamWriter.WriteLine("{");
+            streamWriter.WriteLine("    public static partial class PackageType");
+            streamWriter.WriteLine("    {");
+            streamWriter.WriteLine("        public const int " + config.Name + " = " + config.Id + ";");
+            streamWriter.WriteLine("    }");
+            streamWriter.WriteLine("}");
+        }
+        
+        public override void OnInspectorGUI()
+        {
+            base.OnInspectorGUI();
+            
+            if (GUILayout.Button("Create PackageType"))
+            {
+                PackageConfig packageConfig = (PackageConfig)this.target;
+                if (!packageConfig.CreatePackageTypeFile)
+                {
+                    return;
+                }
+                string path = AssetDatabase.GetAssetPath(packageConfig);
+                CreatePackageTypeFile(Path.Combine(Path.GetDirectoryName(path), "Scripts/Model/Share/"), packageConfig);
+            }
+        }
+    }
+}

+ 11 - 0
Packages/cn.etetet.init/Editor/PackageConfigEditor/PackageConfigEditor.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e1c92db51a225b247be79536be37d943
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 103 - 0
Packages/cn.etetet.init/Editor/ShellHelper.cs

@@ -0,0 +1,103 @@
+using System;
+using System.Diagnostics;
+using System.Collections.Generic;
+
+namespace ET
+{
+    public static class ShellHelper
+    {
+        public static void Run(string cmd, string workDirectory, List<string> environmentVars = null)
+        {
+            System.Diagnostics.Process process = new();
+            try
+            {
+#if UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX
+                string app = "bash";
+                string splitChar = ":";
+                string arguments = "-c";
+#elif UNITY_EDITOR_WIN
+                string app = "cmd.exe";
+                string splitChar = ";";
+                string arguments = "/c";
+#endif
+                ProcessStartInfo start = new ProcessStartInfo(app);
+
+                if (environmentVars != null)
+                {
+                    foreach (string var in environmentVars)
+                    {
+                        start.EnvironmentVariables["PATH"] += (splitChar + var);
+                    }
+                }
+
+                process.StartInfo = start;
+                start.Arguments = arguments + " \"" + cmd + "\"";
+                start.CreateNoWindow = true;
+                start.ErrorDialog = true;
+                start.UseShellExecute = false;
+                start.WorkingDirectory = workDirectory;
+
+                if (start.UseShellExecute)
+                {
+                    start.RedirectStandardOutput = false;
+                    start.RedirectStandardError = false;
+                    start.RedirectStandardInput = false;
+                }
+                else
+                {
+                    start.RedirectStandardOutput = true;
+                    start.RedirectStandardError = true;
+                    start.RedirectStandardInput = true;
+                    start.StandardOutputEncoding = System.Text.Encoding.UTF8;
+                    start.StandardErrorEncoding = System.Text.Encoding.UTF8;
+                }
+
+                bool endOutput = false;
+                bool endError = false;
+
+                process.OutputDataReceived += (sender, args) =>
+                {
+                    if (args.Data != null)
+                    {
+                        UnityEngine.Debug.Log(args.Data);
+                    }
+                    else
+                    {
+                        endOutput = true;
+                    }
+                };
+
+                process.ErrorDataReceived += (sender, args) =>
+                {
+                    if (args.Data != null)
+                    {
+                        UnityEngine.Debug.LogError(args.Data);
+                    }
+                    else
+                    {
+                        endError = true;
+                    }
+                };
+
+                process.Start();
+                process.BeginOutputReadLine();
+                process.BeginErrorReadLine();
+
+                while (!endOutput || !endError)
+                {
+                }
+
+                process.CancelOutputRead();
+                process.CancelErrorRead();
+            }
+            catch (Exception e)
+            {
+                UnityEngine.Debug.LogException(e);
+            }
+            finally
+            {
+                process.Close();
+            }
+        }
+    }
+}

+ 11 - 0
Packages/cn.etetet.init/Editor/ShellHelper.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 61f2b8fe7ecd64cb3aad11c6a350638b
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Packages/cn.etetet.init/Editor/ToolEditor.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c9f874225c3c8497c80a4cb6b07cd8df
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 29 - 0
Packages/cn.etetet.init/Editor/ToolEditor/ToolsEditor.cs

@@ -0,0 +1,29 @@
+using UnityEditor;
+
+namespace ET
+{
+    public static class ToolsEditor
+    {
+        [MenuItem("ET/ExcelExporter")]
+        public static void ExcelExporter()
+        {
+#if UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX
+            const string tools = "./Tool";
+#else
+            const string tools = "dotnet.exe";
+#endif
+            ShellHelper.Run($"{tools} ./Bin/ET.ExcelExporter.dll", "./");
+        }
+        
+        [MenuItem("ET/Proto2CS")]
+        public static void Proto2CS()
+        {
+#if UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX
+            const string tools = "./Tool";
+#else
+            const string tools = "dotnet.exe";
+#endif
+            ShellHelper.Run($"{tools} ./Bin/ET.Proto2CS.dll", "./");
+        }
+    }
+}

+ 11 - 0
Packages/cn.etetet.init/Editor/ToolEditor/ToolsEditor.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 88c74536b8a114539ae8692d663b5c31
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 5 - 0
Packages/cn.etetet.init/Resources.meta

@@ -0,0 +1,5 @@
+fileFormatVersion: 2
+guid: 5bc88e9029901a240abad149b39bbf6b
+folderAsset: yes
+DefaultImporter:
+  userData: 

+ 17 - 0
Packages/cn.etetet.init/Resources/GlobalConfig.asset

@@ -0,0 +1,17 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 36527db572638af47b03c805671cba75, type: 3}
+  m_Name: GlobalConfig
+  m_EditorClassIdentifier: 
+  CodeMode: 3
+  BuildType: 1
+  SceneName: StateSync

+ 8 - 0
Packages/cn.etetet.init/Resources/GlobalConfig.asset.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a60778dce43da574aa447ab3fcf5d9f7
+NativeFormatImporter:
+  externalObjects: {}
+  mainObjectFileID: 11400000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Packages/cn.etetet.init/Runtime.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 38f833201603c444cb0ba3a7c1020719
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 3 - 0
Packages/cn.etetet.init/Runtime/ET.Init.asmdef

@@ -0,0 +1,3 @@
+{
+	"name": "ET.Init"
+}

+ 7 - 0
Packages/cn.etetet.init/Runtime/ET.Init.asmdef.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 5cb915e4a012f304abe5d93deb24007d
+AssemblyDefinitionImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 27 - 0
Packages/cn.etetet.init/Runtime/GlobalConfig.cs

@@ -0,0 +1,27 @@
+using UnityEngine;
+
+namespace ET
+{
+    public enum CodeMode
+    {
+        Client = 1,
+        Server = 2,
+        ClientServer = 3,
+    }
+    
+    public enum BuildType
+    {
+        Debug,
+        Release,
+    }
+    
+    [CreateAssetMenu(menuName = "ET/CreateGlobalConfig", fileName = "GlobalConfig", order = 0)]
+    public class GlobalConfig: ScriptableObject
+    {
+        public CodeMode CodeMode;
+
+        public BuildType BuildType;
+
+        public string SceneName;
+    }
+}

+ 11 - 0
Packages/cn.etetet.init/Runtime/GlobalConfig.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 36527db572638af47b03c805671cba75
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: