Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / generator / DungeonRoomGenerator.cs
@小李xl 小李xl on 6 Jul 2023 8 KB 解决导出exe编译报错问题
  1.  
  2. #if TOOLS
  3.  
  4. using System;
  5. using System.Collections.Generic;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Text.Json;
  9. using Godot;
  10.  
  11. namespace Generator;
  12.  
  13. /// <summary>
  14. /// 地牢房间数据生成器
  15. /// </summary>
  16. public static class DungeonRoomGenerator
  17. {
  18. /// <summary>
  19. /// 根据名称在编辑器中创建地牢的预制房间, open 表示创建完成后是否在编辑器中打开这个房间
  20. /// </summary>
  21. public static bool CreateDungeonRoom(string groupName, string roomType, string roomName, bool open = false)
  22. {
  23. try
  24. {
  25. var path = GameConfig.RoomTileDir + groupName + "/" + roomType;
  26. if (!Directory.Exists(path))
  27. {
  28. Directory.CreateDirectory(path);
  29. }
  30. //创建场景资源
  31. var prefabFile = path + "/" + roomName + ".tscn";
  32. var prefabResPath = "res://" + prefabFile;
  33. if (!Directory.Exists(GameConfig.RoomTileDir))
  34. {
  35. Directory.CreateDirectory(GameConfig.RoomTileDir);
  36. }
  37. //加载脚本资源
  38. // 这段代码在 Godot4.0.1rc1中会报错, 应该是个bug
  39. // var scriptRes = GD.Load<CSharpScript>("res://src/framework/map/DungeonRoomTemplate.cs");
  40. // var tileMap = new TileMap();
  41. // tileMap.Name = roomName;
  42. // tileMap.SetScript(scriptRes);
  43. // var scene = new PackedScene();
  44. // scene.Pack(tileMap); //报错在这一行, 报的是访问了被销毁的资源 scriptRes
  45. // ResourceSaver.Save(scene, prefabResPath);
  46. //临时处理
  47. {
  48. var tscnCode = $"[gd_scene load_steps=2 format=3]\n" +
  49. $"\n" +
  50. $"[ext_resource type=\"Script\" path=\"res://src/framework/map/DungeonRoomTemplate.cs\" id=\"dungeonRoomTemplate\"]\n" +
  51. $"\n" +
  52. $"[node name=\"{roomName}\" type=\"TileMap\"]\n" +
  53. $"format = 2\n" +
  54. $"script = ExtResource(\"dungeonRoomTemplate\")\n";
  55. File.WriteAllText(prefabFile, tscnCode);
  56. //重新保存一遍, 以让编辑器生成资源Id
  57. var scene = GD.Load<PackedScene>(prefabResPath);
  58. ResourceSaver.Save(scene, prefabResPath);
  59. }
  60.  
  61. //打包房间配置
  62. GenerateRoomConfig();
  63. //生成 UiManager_Methods.cs 代码
  64. UiManagerMethodsGenerator.Generate();
  65. //打开房间
  66. if (open)
  67. {
  68. Plugin.Plugin.Instance.GetEditorInterface().OpenSceneFromPath(prefabResPath);
  69. }
  70. }
  71. catch (Exception e)
  72. {
  73. GD.PrintErr(e.ToString());
  74. return false;
  75. }
  76. return true;
  77. }
  78. /// <summary>
  79. /// 执行生成 RoomConfig.json 操作, 返回是否执行成功
  80. /// </summary>
  81. public static bool GenerateRoomConfig()
  82. {
  83. try
  84. {
  85. //地图路径
  86. var tileDir = GameConfig.RoomTileDir;
  87. //地图描述数据路径
  88. var tileDataDir = GameConfig.RoomTileDataDir;
  89. var tileGroup = new DirectoryInfo(tileDir).GetDirectories();
  90. var tileDataGroup = new DirectoryInfo(tileDataDir).GetDirectories();
  91.  
  92. //所有地图列表
  93. var map = new Dictionary<string, FileInfo>();
  94. //地图场景
  95. foreach (var groupDir in tileGroup)
  96. {
  97. var groupName = groupDir.Name;
  98. var typeDirArray = groupDir.GetDirectories();
  99. //遍历枚举, 获取指定路径文件
  100. foreach (DungeonRoomType roomType in Enum.GetValues(typeof(DungeonRoomType)))
  101. {
  102. var typeName = DungeonRoomTemplate.DungeonRoomTypeToString(roomType);
  103.  
  104. //收集所有文件名称
  105. var tempFileDataInfos = typeDirArray.FirstOrDefault(dirInfo => dirInfo.Name == typeName);
  106. if (tempFileDataInfos != null)
  107. {
  108. foreach (var fileInfo in tempFileDataInfos.GetFiles())
  109. {
  110. if (fileInfo.Extension == ".tscn")
  111. {
  112. var pathInfo = new FileInfo(groupName, roomType, typeName, RemoveExtension(fileInfo.Name));
  113. map.TryAdd(pathInfo.GetPath(), pathInfo);
  114. }
  115. }
  116. }
  117. }
  118. }
  119.  
  120. //地图配置数据
  121. foreach (var groupDir in tileDataGroup)
  122. {
  123. var groupName = groupDir.Name;
  124. var typeDirArray = groupDir.GetDirectories();
  125. //遍历枚举, 获取指定路径文件
  126. foreach (DungeonRoomType roomType in Enum.GetValues(typeof(DungeonRoomType)))
  127. {
  128. var typeName = DungeonRoomTemplate.DungeonRoomTypeToString(roomType);
  129.  
  130. //收集所有文件名称
  131. var tempFileDataInfos = typeDirArray.FirstOrDefault(dirInfo => dirInfo.Name == typeName);
  132. if (tempFileDataInfos != null)
  133. {
  134. foreach (var fileInfo in tempFileDataInfos.GetFiles())
  135. {
  136. if (fileInfo.Extension == ".json")
  137. {
  138. var pathInfo = new FileInfo(groupName, roomType, typeName, RemoveExtension(fileInfo.Name));
  139. map.TryAdd(pathInfo.GetPath(), pathInfo);
  140. }
  141. }
  142. }
  143. }
  144. }
  145.  
  146. //剔除多余的 tile.json
  147. foreach (var item in map)
  148. {
  149. var path = item.Key;
  150. if (!File.Exists(tileDir + path + ".tscn"))
  151. {
  152. map.Remove(path);
  153. var filePath = tileDataDir + path + ".json";
  154. if (File.Exists(filePath))
  155. {
  156. GD.Print($"未找到'{tileDir + path}.tscn', 删除配置文件: {filePath}");
  157. File.Delete(filePath);
  158. }
  159. }
  160. }
  161.  
  162. //手动生成缺失的 tile.json
  163. foreach (var item in map)
  164. {
  165. if (!File.Exists(tileDataDir + item.Key + ".json"))
  166. {
  167. var tscnName = tileDir + item.Key + ".tscn";
  168. var packedScene = ResourceManager.Load<PackedScene>(tscnName, false);
  169. if (packedScene != null)
  170. {
  171. var dungeonRoomTemplate = packedScene.Instantiate<DungeonRoomTemplate>();
  172. var usedRect = dungeonRoomTemplate.GetUsedRect();
  173. var dungeonTile = new DungeonTile(dungeonRoomTemplate);
  174. dungeonTile.SetFloorAtlasCoords(new List<Vector2I>() { new Vector2I(0, 8) });
  175. //计算导航网格
  176. dungeonTile.GenerateNavigationPolygon(0);
  177. var polygonData = dungeonTile.GetPolygonData();
  178. DungeonRoomTemplate.SaveConfig(new List<DoorAreaInfo>(), usedRect.Position, usedRect.Size, polygonData.ToList(),
  179. item.Value.GroupName, item.Value.RoomType, item.Value.FileName, dungeonRoomTemplate.Weight);
  180. dungeonRoomTemplate.QueueFree();
  181. }
  182. }
  183. }
  184.  
  185. var roomGroupMap = new Dictionary<string, DungeonRoomGroup>();
  186. //var list = new List<DungeonRoomSplit>();
  187. //整合操作
  188. foreach (var item in map)
  189. {
  190. var path = item.Key;
  191. var configPath = tileDataDir + path + ".json";
  192. var split = new DungeonRoomSplit();
  193. split.ScenePath = ToResPath(tileDir + path + ".tscn");
  194. split.ConfigPath = ToResPath(configPath);
  195.  
  196. if (!roomGroupMap.TryGetValue(item.Value.GroupName, out var group))
  197. {
  198. group = new DungeonRoomGroup();
  199. group.GroupName = item.Value.GroupName;
  200. roomGroupMap.Add(group.GroupName, group);
  201. }
  202. group.GetRoomList(item.Value.RoomType).Add(split);
  203. }
  204.  
  205. //写出配置
  206. var config = new JsonSerializerOptions();
  207. config.WriteIndented = true;
  208. var text = JsonSerializer.Serialize(roomGroupMap, config);
  209. File.WriteAllText(GameConfig.RoomTileConfigFile, text);
  210.  
  211. GD.Print("地牢房间配置, 重新打包完成!");
  212. }
  213. catch (Exception e)
  214. {
  215. GD.PrintErr(e.ToString());
  216. return false;
  217. }
  218.  
  219. return true;
  220. }
  221.  
  222. private class FileInfo
  223. {
  224. public FileInfo(string groupName, DungeonRoomType roomType, string typeName, string fileName)
  225. {
  226. GroupName = groupName;
  227. RoomType = roomType;
  228. TypeName = typeName;
  229. FileName = fileName;
  230. }
  231.  
  232. public string GroupName;
  233. public DungeonRoomType RoomType;
  234. public string TypeName;
  235. public string FileName;
  236.  
  237. public string GetPath()
  238. {
  239. return GroupName + "/" + TypeName + "/" + FileName;
  240. }
  241. }
  242. private static string ToResPath(string path)
  243. {
  244. var field = path.Replace("\\", "/");
  245. return "res://" + field;
  246. }
  247.  
  248. private static string RemoveExtension(string name)
  249. {
  250. var index = name.LastIndexOf(".", StringComparison.Ordinal);
  251. if (index >= 0)
  252. {
  253. return name.Substring(0, index);
  254. }
  255.  
  256. return name;
  257. }
  258. }
  259.  
  260.  
  261. #endif