diff --git a/DungeonShooting_Godot/excel/Role.xlsx b/DungeonShooting_Godot/excel/Role.xlsx index b02e664..3625c6a 100644 --- a/DungeonShooting_Godot/excel/Role.xlsx +++ b/DungeonShooting_Godot/excel/Role.xlsx Binary files differ diff --git a/DungeonShooting_Godot/excel/Weapon.xlsx b/DungeonShooting_Godot/excel/Weapon.xlsx index b333b3f..68c0e7a 100644 --- a/DungeonShooting_Godot/excel/Weapon.xlsx +++ b/DungeonShooting_Godot/excel/Weapon.xlsx Binary files differ diff --git a/DungeonShooting_Godot/src/config/Role.cs b/DungeonShooting_Godot/src/config/Role.cs index 9e42b44..e15d54d 100644 --- a/DungeonShooting_Godot/src/config/Role.cs +++ b/DungeonShooting_Godot/src/config/Role.cs @@ -1,3 +1,6 @@ +using System.Text.Json.Serialization; +using System.Collections.Generic; + namespace Config; public class Role @@ -6,12 +9,7 @@ /// 物体唯一id
/// 不需要添加类型前缀 /// - public string Id; + [JsonInclude] + public string Id { get; private set; } - public Role Clone() - { - var inst = new Role(); - inst.Id = Id; - return inst; - } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/config/Weapon.cs b/DungeonShooting_Godot/src/config/Weapon.cs index 535b077..c0efbca 100644 --- a/DungeonShooting_Godot/src/config/Weapon.cs +++ b/DungeonShooting_Godot/src/config/Weapon.cs @@ -1,3 +1,6 @@ +using System.Text.Json.Serialization; +using System.Collections.Generic; + namespace Config; public class Weapon @@ -6,27 +9,32 @@ /// 物体唯一id
/// 不需要添加类型前缀 /// - public string Id; + [JsonInclude] + public string Id { get; private set; } /// /// 武器 Prefab, 必须继承场景 "res://prefab/weapon/Weapon.tscn" /// - public string Prefab; + [JsonInclude] + public string Prefab { get; private set; } /// /// 重量 /// - public float Weight; + [JsonInclude] + public float Weight { get; private set; } /// /// 武器显示的名称 /// - public string Name; + [JsonInclude] + public string Name { get; private set; } /// /// 武器的图标 /// - public string Icon; + [JsonInclude] + public string Icon { get; private set; } /// /// 武器类型:
@@ -34,227 +42,217 @@ /// 2.主武器
/// 3.重型武器 ///
- public byte WeightType; + [JsonInclude] + public byte WeightType { get; private set; } /// /// 是否连续发射, 如果为false, 则每次发射都需要扣动扳机 /// - public bool ContinuousShoot; + [JsonInclude] + public bool ContinuousShoot { get; private set; } /// /// 弹夹容量 /// - public int AmmoCapacity; + [JsonInclude] + public int AmmoCapacity { get; private set; } /// /// 弹药容量上限 /// - public int MaxAmmoCapacity; + [JsonInclude] + public int MaxAmmoCapacity { get; private set; } /// /// 起始备用弹药数量 /// - public int StandbyAmmoCapacity; + [JsonInclude] + public int StandbyAmmoCapacity { get; private set; } /// /// 装弹时间, 单位: 秒 /// - public float ReloadTime; + [JsonInclude] + public float ReloadTime { get; private set; } /// /// 每粒子弹是否是单独装填, 如果是, 那么每上一发子弹的时间就是 ReloadTime, 可以做霰弹武器装填效果 /// - public bool AloneReload; + [JsonInclude] + public bool AloneReload { get; private set; } /// /// 单独装填时每次装填子弹数量, 必须要将 'AloneReload' 属性设置为 true /// - public int AloneReloadCount; + [JsonInclude] + public int AloneReloadCount { get; private set; } /// /// 单独装填的子弹时可以立即射击, 必须要将 'AloneReload' 属性设置为 true /// - public bool AloneReloadCanShoot; + [JsonInclude] + public bool AloneReloadCanShoot { get; private set; } /// /// 是否为松发开火, 也就是松开扳机才开火, 若要启用该属性, 必须将 'ContinuousShoot' 设置为 false /// - public bool LooseShoot; + [JsonInclude] + public bool LooseShoot { get; private set; } /// /// 最少需要蓄力多久才能开火, 必须将 'LooseShoot' 设置为 true /// - public float MinChargeTime; + [JsonInclude] + public float MinChargeTime { get; private set; } /// /// 连续发射最小次数, 仅当 ContinuousShoot 为 false 时生效 /// - public int MinContinuousCount; + [JsonInclude] + public int MinContinuousCount { get; private set; } /// /// 连续发射最大次数, 仅当 ContinuousShoot 为 false 时生效 /// - public int MaxContinuousCount; + [JsonInclude] + public int MaxContinuousCount { get; private set; } /// /// 按下一次扳机后需要多长时间才能再次感应按下 /// - public float TriggerInterval; + [JsonInclude] + public float TriggerInterval { get; private set; } /// /// 初始射速, 初始每分钟能开火次数 /// - public float StartFiringSpeed; + [JsonInclude] + public float StartFiringSpeed { get; private set; } /// /// 最终射速, 最终每分钟能开火次数, 仅当 ContinuousShoot 为 true 时生效 /// - public float FinalFiringSpeed; + [JsonInclude] + public float FinalFiringSpeed { get; private set; } /// /// 按下扳机并开火后射速增加速率 /// - public float FiringSpeedAddSpeed; + [JsonInclude] + public float FiringSpeedAddSpeed { get; private set; } /// /// 松开扳机后射速消散速率 /// - public float FiringSpeedBackSpeed; + [JsonInclude] + public float FiringSpeedBackSpeed { get; private set; } /// /// 单次开火发射子弹最小数量 /// - public int MinFireBulletCount; + [JsonInclude] + public int MinFireBulletCount { get; private set; } /// /// 单次开火发射子弹最大数量 /// - public int MaxFireBulletCount; + [JsonInclude] + public int MaxFireBulletCount { get; private set; } /// /// 开火前延时 /// - public float DelayedTime; + [JsonInclude] + public float DelayedTime { get; private set; } /// /// 初始散射半径 /// - public float StartScatteringRange; + [JsonInclude] + public float StartScatteringRange { get; private set; } /// /// 最终散射半径 /// - public float FinalScatteringRange; + [JsonInclude] + public float FinalScatteringRange { get; private set; } /// /// 每次发射后散射增加值 /// - public float ScatteringRangeAddValue; + [JsonInclude] + public float ScatteringRangeAddValue { get; private set; } /// /// 松开扳机后散射销退速率 /// - public float ScatteringRangeBackSpeed; + [JsonInclude] + public float ScatteringRangeBackSpeed { get; private set; } /// /// 松开扳机多久后开始销退散射值 (单位: 秒) /// - public float ScatteringRangeBackTime; + [JsonInclude] + public float ScatteringRangeBackTime { get; private set; } /// /// 子弹飞行最大距离 /// - public float MaxDistance; + [JsonInclude] + public float MaxDistance { get; private set; } /// /// 子弹飞行最小距离 /// - public float MinDistance; + [JsonInclude] + public float MinDistance { get; private set; } /// /// 最大后坐力 (仅用于开火后武器身抖动) /// - public float MaxBacklash; + [JsonInclude] + public float MaxBacklash { get; private set; } /// /// 最小后坐力 (仅用于开火后武器身抖动) /// - public float MinBacklash; + [JsonInclude] + public float MinBacklash { get; private set; } /// /// 后坐力偏移回归回归速度 /// - public float BacklashRegressionSpeed; + [JsonInclude] + public float BacklashRegressionSpeed { get; private set; } /// /// 开火后武器口上抬角度 /// - public float UpliftAngle; + [JsonInclude] + public float UpliftAngle { get; private set; } /// /// 武器默认上抬角度 /// - public float DefaultAngle; + [JsonInclude] + public float DefaultAngle { get; private set; } /// /// 开火后武器口角度恢复速度倍数 /// - public float UpliftAngleRestore; + [JsonInclude] + public float UpliftAngleRestore { get; private set; } /// /// 默认射出的子弹id /// - public string BulletId; + [JsonInclude] + public string BulletId { get; private set; } /// /// 投抛状态下物体碰撞器大小 /// - public SerializeVector2 ThrowCollisionSize; + [JsonInclude] + public SerializeVector2 ThrowCollisionSize { get; private set; } - public Weapon Clone() - { - var inst = new Weapon(); - inst.Id = Id; - inst.Prefab = Prefab; - inst.Weight = Weight; - inst.Name = Name; - inst.Icon = Icon; - inst.WeightType = WeightType; - inst.ContinuousShoot = ContinuousShoot; - inst.AmmoCapacity = AmmoCapacity; - inst.MaxAmmoCapacity = MaxAmmoCapacity; - inst.StandbyAmmoCapacity = StandbyAmmoCapacity; - inst.ReloadTime = ReloadTime; - inst.AloneReload = AloneReload; - inst.AloneReloadCount = AloneReloadCount; - inst.AloneReloadCanShoot = AloneReloadCanShoot; - inst.LooseShoot = LooseShoot; - inst.MinChargeTime = MinChargeTime; - inst.MinContinuousCount = MinContinuousCount; - inst.MaxContinuousCount = MaxContinuousCount; - inst.TriggerInterval = TriggerInterval; - inst.StartFiringSpeed = StartFiringSpeed; - inst.FinalFiringSpeed = FinalFiringSpeed; - inst.FiringSpeedAddSpeed = FiringSpeedAddSpeed; - inst.FiringSpeedBackSpeed = FiringSpeedBackSpeed; - inst.MinFireBulletCount = MinFireBulletCount; - inst.MaxFireBulletCount = MaxFireBulletCount; - inst.DelayedTime = DelayedTime; - inst.StartScatteringRange = StartScatteringRange; - inst.FinalScatteringRange = FinalScatteringRange; - inst.ScatteringRangeAddValue = ScatteringRangeAddValue; - inst.ScatteringRangeBackSpeed = ScatteringRangeBackSpeed; - inst.ScatteringRangeBackTime = ScatteringRangeBackTime; - inst.MaxDistance = MaxDistance; - inst.MinDistance = MinDistance; - inst.MaxBacklash = MaxBacklash; - inst.MinBacklash = MinBacklash; - inst.BacklashRegressionSpeed = BacklashRegressionSpeed; - inst.UpliftAngle = UpliftAngle; - inst.DefaultAngle = DefaultAngle; - inst.UpliftAngleRestore = UpliftAngleRestore; - inst.BulletId = BulletId; - inst.ThrowCollisionSize = ThrowCollisionSize; - return inst; - } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/SerializeVector2.cs b/DungeonShooting_Godot/src/framework/SerializeVector2.cs deleted file mode 100644 index 4e0a888..0000000 --- a/DungeonShooting_Godot/src/framework/SerializeVector2.cs +++ /dev/null @@ -1,59 +0,0 @@ - -using System.Text.Json.Serialization; -using Godot; - -/// -/// 可序列化的 Vector2 对象 -/// -public class SerializeVector2 -{ - public SerializeVector2(float x, float y) - { - X = x; - Y = y; - } - - public SerializeVector2(Vector2 v) - { - X = v.X; - Y = v.Y; - } - - public SerializeVector2(Vector2I v) - { - X = v.X; - Y = v.Y; - } - - public SerializeVector2(SerializeVector2 v) - { - X = v.X; - Y = v.Y; - } - - public SerializeVector2() - { - - } - - [JsonInclude] - public float X { get; private set; } - [JsonInclude] - public float Y { get; private set; } - - /// - /// 转为 Vector2 - /// - public Vector2 AsVector2() - { - return new Vector2(X, Y); - } - - /// - /// 转为 Vector2I - /// - public Vector2I AsVector2I() - { - return new Vector2I((int)X, (int)Y); - } -} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/activity/ActivityObjectTemplate.cs b/DungeonShooting_Godot/src/framework/activity/ActivityObjectTemplate.cs index 4e7ccbd..cea2ecc 100644 --- a/DungeonShooting_Godot/src/framework/activity/ActivityObjectTemplate.cs +++ b/DungeonShooting_Godot/src/framework/activity/ActivityObjectTemplate.cs @@ -124,4 +124,4 @@ // } // #endif // } -// } \ No newline at end of file +// } diff --git a/DungeonShooting_Godot/src/framework/generator/ExcelGenerator.cs b/DungeonShooting_Godot/src/framework/generator/ExcelGenerator.cs index 8b117dc..98b37aa 100644 --- a/DungeonShooting_Godot/src/framework/generator/ExcelGenerator.cs +++ b/DungeonShooting_Godot/src/framework/generator/ExcelGenerator.cs @@ -1,6 +1,7 @@ -using System.Data; +using System; +using System.Collections.Generic; using System.IO; -using System.Linq; +using System.Text.RegularExpressions; using Godot; using NPOI.XSSF.UserModel; @@ -8,86 +9,97 @@ public static class ExcelGenerator { - //关键字列表 - private static readonly string[] Keywords = - { - "abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", - "continue", "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", - "false", "finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", - "internal", "is", "lock", "long", "namespace", "new", "null", "object", "operator", "out", "override", "params", - "private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", - "stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong", - "unchecked", "unsafe", "ushort", "using", "virtual", "void", "volatile", "while" - }; - public static bool ExportExcel() { GD.Print("准备导出excel表..."); - var directoryInfo = new DirectoryInfo(GameConfig.ExcelFilePath); - if (directoryInfo.Exists) + + try { - var fileInfos = directoryInfo.GetFiles(); - foreach (var fileInfo in fileInfos) + var directoryInfo = new DirectoryInfo(GameConfig.ExcelFilePath); + if (directoryInfo.Exists) { - if (fileInfo.Extension == ".xlsx") + var fileInfos = directoryInfo.GetFiles(); + foreach (var fileInfo in fileInfos) { - GD.Print("excel表: " + fileInfo.FullName); - ReadExcel(fileInfo.FullName); + if (fileInfo.Extension == ".xlsx") + { + GD.Print("excel表: " + fileInfo.FullName); + ReadExcel(fileInfo.FullName); + } } } } + catch (Exception e) + { + GD.PrintErr(e.ToString()); + return false; + } return true; } private static void ReadExcel(string excelPath) { + var columnList = new HashSet(); + var fileName = Path.GetFileNameWithoutExtension(excelPath).FirstToUpper(); - var outStr = "namespace Config;\n\n"; + var outStr = $"using System.Text.Json.Serialization;\n"; + outStr += $"using System.Collections.Generic;\n\n"; + outStr += $"namespace Config;\n\n"; outStr += $"public class {fileName}\n{{\n"; - var cloneFuncStr = $" public {fileName} Clone()\n {{\n"; - cloneFuncStr += $" var inst = new {fileName}();\n"; var sourceFile = excelPath; //加载表数据 var workbook = new XSSFWorkbook(sourceFile); - var sheet1 = workbook.GetSheet("Sheet1"); - - //解析表 - var rowCount = sheet1.LastRowNum; - - //先解析表中的列名, 注释, 类型 - var columnCount = -1; - var names = sheet1.GetRow(0); - var descriptions = sheet1.GetRow(1); - var types = sheet1.GetRow(2); - foreach (var cell in names) + using (workbook) { - var value = cell.StringCellValue; - if (string.IsNullOrEmpty(value)) + var sheet1 = workbook.GetSheet("Sheet1"); + + //解析表 + var rowCount = sheet1.LastRowNum; + + //先解析表中的列名, 注释, 类型 + var columnCount = -1; + var names = sheet1.GetRow(0); + var descriptions = sheet1.GetRow(1); + var types = sheet1.GetRow(2); + foreach (var cell in names) { - columnCount = cell.ColumnIndex; - break; + var value = cell.StringCellValue; + if (string.IsNullOrEmpty(value)) + { + columnCount = cell.ColumnIndex; + break; + } + + value = value.FirstToUpper(); + if (!columnList.Add(value)) + { + throw new Exception($"表'{fileName}'中存在相同名称的列: '{value}'!"); + } + + outStr += $" /// \n"; + var descriptionCell = descriptions.GetCell(cell.ColumnIndex); + var description = descriptionCell.StringCellValue.Replace("\n", "
\n /// "); + var stringCellValue = types.GetCell(cell.ColumnIndex).StringCellValue; + string type; + try + { + type = ConvertToType(stringCellValue.Replace(" ", "")); + } + catch (Exception e) + { + throw new Exception($"表'{fileName}'中'{value}'这一列类型描述语法错误: {stringCellValue}"); + } + outStr += $" /// {description}\n"; + outStr += $" ///
\n"; + outStr += $" [JsonInclude]\n"; + outStr += $" public {type} {value} {{ get; private set; }}\n\n"; } - - value = value.FirstToUpper(); - - outStr += $" /// \n"; - var descriptionCell = descriptions.GetCell(cell.ColumnIndex); - var description = descriptionCell.StringCellValue.Replace("\n", "
\n /// "); - var type = TypeMapping(types.GetCell(cell.ColumnIndex).StringCellValue); - outStr += $" /// {description}\n"; - outStr += $" ///
\n"; - outStr += $" public {type} {value};\n\n"; - cloneFuncStr += $" inst.{value} = {value};\n"; + + outStr += "}"; } - cloneFuncStr += " return inst;\n"; - cloneFuncStr += " }\n"; - outStr += cloneFuncStr; - outStr += "}"; - workbook.Close(); - if (!Directory.Exists("src/config")) { Directory.CreateDirectory("src/config"); @@ -96,24 +108,40 @@ File.WriteAllText("src/config/" + fileName + ".cs", outStr); } + private static string ConvertToType(string str) + { + if (Regex.IsMatch(str, "^\\w+$")) + { + return TypeMapping(str); + } + else if (str.StartsWith('{')) + { + var tempStr = str.Substring(1, str.Length - 2); + var index = tempStr.IndexOf(':'); + if (index == -1) + { + throw new Exception("类型描述语法错误!"); + } + return "Dictionary<" + ConvertToType(tempStr.Substring(0, index)) + ", " + ConvertToType(tempStr.Substring(index + 1)) + ">"; + } + else if (str.StartsWith('[')) + { + var tempStr = str.Substring(1, str.Length - 2); + return ConvertToType(tempStr) + "[]"; + } + throw new Exception("类型描述语法错误!"); + } + private static string TypeMapping(string typeName) { switch (typeName) { case "boolean": return "bool"; - case "boolean[]": return "bool[]"; - case "vector2": return "Godot.Vector2"; - case "vector2[]": return "Godot.Vector2[]"; - case "vector3": return "Godot.Vector3"; - case "vector3[]": return "Godot.Vector3[]"; - case "color[]": return "Godot.Color[]"; + case "vector2": return "SerializeVector2"; + case "vector3": return "SerializeVector3"; + case "color": return "SerializeColor"; } return typeName; } - - public static bool IsCSharpKeyword(string str) - { - return Keywords.Contains(str); - } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/serialize/SerializeColor.cs b/DungeonShooting_Godot/src/framework/serialize/SerializeColor.cs new file mode 100644 index 0000000..983b043 --- /dev/null +++ b/DungeonShooting_Godot/src/framework/serialize/SerializeColor.cs @@ -0,0 +1,48 @@ + + +using System.Text.Json.Serialization; +using Godot; + +/// +/// 可序列化的 Color 对象 +/// +public class SerializeColor +{ + public SerializeColor(float r, float g, float b, float a) + { + R = r; + G = g; + B = b; + A = a; + } + + public SerializeColor(Color color) + { + R = color.R; + G = color.G; + B = color.B; + A = color.A; + } + + public SerializeColor() + { + } + + [JsonInclude] + public float R { get; private set; } + [JsonInclude] + public float G { get; private set; } + [JsonInclude] + public float B { get; private set; } + [JsonInclude] + public float A { get; private set; } + + /// + /// 转为 Color + /// + public Color AsColor() + { + return new Color(R, G, B, A); + } + +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/serialize/SerializeVector2.cs b/DungeonShooting_Godot/src/framework/serialize/SerializeVector2.cs new file mode 100644 index 0000000..4e0a888 --- /dev/null +++ b/DungeonShooting_Godot/src/framework/serialize/SerializeVector2.cs @@ -0,0 +1,59 @@ + +using System.Text.Json.Serialization; +using Godot; + +/// +/// 可序列化的 Vector2 对象 +/// +public class SerializeVector2 +{ + public SerializeVector2(float x, float y) + { + X = x; + Y = y; + } + + public SerializeVector2(Vector2 v) + { + X = v.X; + Y = v.Y; + } + + public SerializeVector2(Vector2I v) + { + X = v.X; + Y = v.Y; + } + + public SerializeVector2(SerializeVector2 v) + { + X = v.X; + Y = v.Y; + } + + public SerializeVector2() + { + + } + + [JsonInclude] + public float X { get; private set; } + [JsonInclude] + public float Y { get; private set; } + + /// + /// 转为 Vector2 + /// + public Vector2 AsVector2() + { + return new Vector2(X, Y); + } + + /// + /// 转为 Vector2I + /// + public Vector2I AsVector2I() + { + return new Vector2I((int)X, (int)Y); + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/serialize/SerializeVector3.cs b/DungeonShooting_Godot/src/framework/serialize/SerializeVector3.cs new file mode 100644 index 0000000..7e76a66 --- /dev/null +++ b/DungeonShooting_Godot/src/framework/serialize/SerializeVector3.cs @@ -0,0 +1,62 @@ +using System.Text.Json.Serialization; +using Godot; + +/// +/// 可序列化的 Vector3 对象 +/// +public class SerializeVector3 +{ + public SerializeVector3(float x, float y, float z) + { + X = x; + Y = y; + Z = z; + } + + public SerializeVector3(Vector3 v) + { + X = v.X; + Y = v.Y; + Z = v.Z; + } + + public SerializeVector3(Vector3I v) + { + X = v.X; + Y = v.Y; + Z = v.Z; + } + + public SerializeVector3(SerializeVector3 v) + { + X = v.X; + Y = v.Y; + } + + public SerializeVector3() + { + } + + [JsonInclude] + public float X { get; private set; } + [JsonInclude] + public float Y { get; private set; } + [JsonInclude] + public float Z { get; private set; } + + /// + /// 转为 Vector3 + /// + public Vector3 AsVector3() + { + return new Vector3(X, Y, Z); + } + + /// + /// 转为 Vector3I + /// + public Vector3I AsVector3I() + { + return new Vector3I((int)X, (int)Y, (int)Z); + } +} \ No newline at end of file