mirror of
https://github.com/jie65535/GrasscutterCommandGenerator.git
synced 2025-10-22 20:09:46 +08:00
Add Resources update tool
This commit is contained in:
13
Source/GrasscutterTools/Game/Data/Excels/AchievementData.cs
Normal file
13
Source/GrasscutterTools/Game/Data/Excels/AchievementData.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GrasscutterTools.Game.Data.Excels
|
||||
{
|
||||
[ResourceType("AchievementExcelConfigData.json")]
|
||||
internal class AchievementData : GameResource
|
||||
{
|
||||
[JsonProperty("isDisuse")]
|
||||
public bool IsDisuse { get; set; }
|
||||
|
||||
public bool IsUsed => !IsDisuse;
|
||||
}
|
||||
}
|
11
Source/GrasscutterTools/Game/Data/Excels/AvatarData.cs
Normal file
11
Source/GrasscutterTools/Game/Data/Excels/AvatarData.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GrasscutterTools.Game.Data.Excels
|
||||
{
|
||||
[ResourceType("AvatarExcelConfigData.json")]
|
||||
internal class AvatarData : GameResource
|
||||
{
|
||||
[JsonProperty("qualityType")]
|
||||
public string QualityType { get; set; }
|
||||
}
|
||||
}
|
7
Source/GrasscutterTools/Game/Data/Excels/DungeonData.cs
Normal file
7
Source/GrasscutterTools/Game/Data/Excels/DungeonData.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace GrasscutterTools.Game.Data.Excels
|
||||
{
|
||||
[ResourceType("DungeonExcelConfigData.json")]
|
||||
internal class DungeonData : GameResource
|
||||
{
|
||||
}
|
||||
}
|
13
Source/GrasscutterTools/Game/Data/Excels/GadgetData.cs
Normal file
13
Source/GrasscutterTools/Game/Data/Excels/GadgetData.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GrasscutterTools.Game.Data.Excels
|
||||
{
|
||||
[ResourceType("GadgetExcelConfigData.json")]
|
||||
internal class GadgetData
|
||||
{
|
||||
}
|
||||
}
|
14
Source/GrasscutterTools/Game/Data/Excels/HomeWorldBgmData.cs
Normal file
14
Source/GrasscutterTools/Game/Data/Excels/HomeWorldBgmData.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GrasscutterTools.Game.Data.Excels
|
||||
{
|
||||
[ResourceType("HomeWorldBgmExcelConfigData.json")]
|
||||
internal class HomeWorldBgmData : GameResource
|
||||
{
|
||||
[JsonProperty("homeBgmId")]
|
||||
public override int Id { get; set; }
|
||||
|
||||
[JsonProperty("bgmNameTextMapHash")]
|
||||
public long BgmNameTextMapHash { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
namespace GrasscutterTools.Game.Data.Excels
|
||||
{
|
||||
[ResourceType("HomeWorldFurnitureExcelConfigData.json")]
|
||||
internal class HomeWorldFurnitureData : GameResource
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GrasscutterTools.Game.Data.Excels
|
||||
{
|
||||
[ResourceType("MainQuestExcelConfigData.json")]
|
||||
internal class MainQuestData : GameResource
|
||||
{
|
||||
}
|
||||
}
|
22
Source/GrasscutterTools/Game/Data/Excels/MaterialData.cs
Normal file
22
Source/GrasscutterTools/Game/Data/Excels/MaterialData.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
using GrasscutterTools.Game.Inventory;
|
||||
using GrasscutterTools.Game.Props;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace GrasscutterTools.Game.Data.Excels
|
||||
{
|
||||
[ResourceType("MaterialExcelConfigData.json")]
|
||||
internal class MaterialData : GameResource
|
||||
{
|
||||
[JsonProperty("itemType"), JsonConverter(typeof(StringEnumConverter))]
|
||||
public ItemType ItemType { get; set; }
|
||||
|
||||
[JsonProperty("materialType"), JsonConverter(typeof(StringEnumConverter))]
|
||||
public MaterialType MaterialType { get; set; }
|
||||
|
||||
[JsonProperty("itemUse")]
|
||||
public List<ItemUseData> ItemUse { get; set; }
|
||||
}
|
||||
}
|
15
Source/GrasscutterTools/Game/Data/Excels/MonsterData.cs
Normal file
15
Source/GrasscutterTools/Game/Data/Excels/MonsterData.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using GrasscutterTools.Game.Props;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GrasscutterTools.Game.Data.Excels
|
||||
{
|
||||
[ResourceType("MonsterExcelConfigData.json")]
|
||||
internal class MonsterData : GameResource
|
||||
{
|
||||
[JsonProperty("monsterName")]
|
||||
public string MonsterName { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public MonsterType Type { get; set; }
|
||||
}
|
||||
}
|
17
Source/GrasscutterTools/Game/Data/Excels/QuestData.cs
Normal file
17
Source/GrasscutterTools/Game/Data/Excels/QuestData.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GrasscutterTools.Game.Data.Excels
|
||||
{
|
||||
[ResourceType("QuestExcelConfigData.json")]
|
||||
internal class QuestData : GameResource
|
||||
{
|
||||
[JsonProperty("subId")]
|
||||
public override int Id { get; set; }
|
||||
|
||||
[JsonProperty("mainId")]
|
||||
public int MainId { get; set; }
|
||||
|
||||
[JsonProperty("order")]
|
||||
public int Order { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
namespace GrasscutterTools.Game.Data.Excels
|
||||
{
|
||||
[ResourceType("ReliquaryExcelConfigData.json")]
|
||||
internal class ReliquaryData : GameResource
|
||||
{
|
||||
}
|
||||
}
|
15
Source/GrasscutterTools/Game/Data/Excels/SceneData.cs
Normal file
15
Source/GrasscutterTools/Game/Data/Excels/SceneData.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using GrasscutterTools.Game.Props;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GrasscutterTools.Game.Data.Excels
|
||||
{
|
||||
[ResourceType("SceneExcelConfigData.json")]
|
||||
internal class SceneData : GameResource
|
||||
{
|
||||
[JsonProperty("type")]
|
||||
public SceneType SceneType { get; set; }
|
||||
|
||||
[JsonProperty("scriptData")]
|
||||
public string ScriptData { get; set; }
|
||||
}
|
||||
}
|
11
Source/GrasscutterTools/Game/Data/Excels/WeaponData.cs
Normal file
11
Source/GrasscutterTools/Game/Data/Excels/WeaponData.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GrasscutterTools.Game.Data.Excels
|
||||
{
|
||||
[ResourceType("WeaponExcelConfigData.json")]
|
||||
internal class WeaponData : GameResource
|
||||
{
|
||||
[JsonProperty("rankLevel")]
|
||||
public int RankLevel { get; set; }
|
||||
}
|
||||
}
|
19
Source/GrasscutterTools/Game/Data/GameResource.cs
Normal file
19
Source/GrasscutterTools/Game/Data/GameResource.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GrasscutterTools.Game.Data
|
||||
{
|
||||
internal abstract class GameResource
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public virtual int Id { get; set; }
|
||||
|
||||
[JsonProperty("nameTextMapHash")]
|
||||
public long NameTextMapHash { get; set; }
|
||||
|
||||
[JsonProperty("titleTextMapHash")]
|
||||
public string TitleTextMapHash { get; set; }
|
||||
|
||||
[JsonProperty("descTextMapHash")]
|
||||
public long DescTextMapHash { get; set; }
|
||||
}
|
||||
}
|
249
Source/GrasscutterTools/Game/Data/GameResources.cs
Normal file
249
Source/GrasscutterTools/Game/Data/GameResources.cs
Normal file
@@ -0,0 +1,249 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using GrasscutterTools.Game.Data.Excels;
|
||||
using GrasscutterTools.Game.Inventory;
|
||||
using GrasscutterTools.Game.Props;
|
||||
using GrasscutterTools.Utils;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GrasscutterTools.Game.Data
|
||||
{
|
||||
internal class GameResources
|
||||
{
|
||||
public Dictionary<int, AchievementData> AchievementData { get; set; }
|
||||
|
||||
public Dictionary<int, AvatarData> AvatarData { get; set; }
|
||||
|
||||
public Dictionary<int, HomeWorldBgmData> HomeWorldBgmData { get; set; }
|
||||
|
||||
public Dictionary<int, DungeonData> DungeonData { get; set; }
|
||||
|
||||
public Dictionary<int, HomeWorldFurnitureData> HomeWorldFurnitureData { get; set; }
|
||||
|
||||
public Dictionary<int, MainQuestData> MainQuestData { get; set; }
|
||||
|
||||
public Dictionary<int, QuestData> QuestData { get; set; }
|
||||
|
||||
public Dictionary<int, MaterialData> MaterialData { get; set; }
|
||||
|
||||
public Dictionary<int, MonsterData> MonsterData { get; set; }
|
||||
|
||||
public Dictionary<int, ReliquaryData> ReliquaryData { get; set; }
|
||||
|
||||
public Dictionary<int, SceneData> SceneData { get; set; }
|
||||
|
||||
public Dictionary<int, WeaponData> WeaponData { get; set; }
|
||||
|
||||
public TextMapData TextMapData { get; set; }
|
||||
|
||||
|
||||
|
||||
public GameResources(string resourcesDirPath, TextMapData textMapData)
|
||||
{
|
||||
TextMapData = textMapData;
|
||||
|
||||
var properties = typeof(GameResources).GetProperties();
|
||||
foreach (var property in properties)
|
||||
{
|
||||
var type = property.PropertyType;
|
||||
if (!type.IsGenericType) continue;
|
||||
var gameResourceType = type.GetGenericArguments()[1];
|
||||
var attributes = (ResourceTypeAttribute[])gameResourceType.GetCustomAttributes(typeof(ResourceTypeAttribute), true);
|
||||
if (attributes.Length < 1) continue;
|
||||
var dataFile = Path.Combine(resourcesDirPath, "ExcelBinOutput", attributes[0].Name);
|
||||
var data = LoadDataFile(gameResourceType, dataFile);
|
||||
property.SetValue(this, data, null);
|
||||
}
|
||||
|
||||
|
||||
var illegalWeaponIds = new SparseSet(
|
||||
"10000-10008, 11411, 11506-11508, 12505, 12506, 12508, 12509," +
|
||||
"13503, 13506, 14411, 14503, 14505, 14508, 15504-15506, 20001");
|
||||
foreach (var id in WeaponData.Keys.Where(id => illegalWeaponIds.Contains(id)).ToList())
|
||||
WeaponData.Remove(id);
|
||||
|
||||
var illegalRelicIds = new SparseSet(
|
||||
"20002, 20004, 23300-24825"
|
||||
);
|
||||
//var illegalRelicIds = new SparseSet(
|
||||
// "20001, 23300-23340, 23383-23385, 78310-78554, 99310-99554"
|
||||
//);
|
||||
foreach (var id in ReliquaryData.Keys.Where(id => illegalRelicIds.Contains(id)).ToList())
|
||||
ReliquaryData.Remove(id);
|
||||
|
||||
var illegalItemIds = new SparseSet(
|
||||
"3004-3008, 3018-3022"
|
||||
);
|
||||
//var illegalItemIds = new SparseSet(
|
||||
// "3004-3008, 3018-3022, 100086, 100087, 100100-101000, 101106-101110, 101306, 101500-104000," +
|
||||
// "105001, 105004, 106000-107000, 107011, 108000, 109000-110000," +
|
||||
// "115000-130000, 200200-200899, 220050, 220054"
|
||||
//);
|
||||
foreach (var id in MaterialData.Keys.Where(id => illegalItemIds.Contains(id)).ToList())
|
||||
MaterialData.Remove(id);
|
||||
|
||||
foreach (var id in AvatarData.Keys.Where(id => id < 10000002 || id >= 11000000).ToList())
|
||||
AvatarData.Remove(id);
|
||||
}
|
||||
|
||||
private static object LoadDataFile(Type type, string path)
|
||||
{
|
||||
var list = (IList)JsonConvert.DeserializeObject(File.ReadAllText(path), typeof(List<>).MakeGenericType(type));
|
||||
if (list == null) return null;
|
||||
|
||||
var dicType = typeof(Dictionary<,>).MakeGenericType(typeof(int), type);
|
||||
var dic = (IDictionary)Activator.CreateInstance(dicType);
|
||||
foreach (GameResource gameResource in list)
|
||||
dic.Add(gameResource.Id, gameResource);
|
||||
return dic;
|
||||
}
|
||||
|
||||
private Dictionary<string, string> Languages = new Dictionary<string, string>
|
||||
{
|
||||
["zh-cn"] = "TextMapCHS",
|
||||
["zh-tw"] = "TextMapCHT",
|
||||
["en-us"] = "TextMapEN",
|
||||
["ru-ru"] = "TextMapRU",
|
||||
};
|
||||
|
||||
public void ConvertResources(string projectResourcesDir)
|
||||
{
|
||||
var currentCultureInfo = Thread.CurrentThread.CurrentUICulture;
|
||||
try
|
||||
{
|
||||
var sb = new StringBuilder(MaterialData.Count * 24);
|
||||
foreach (var language in Languages)
|
||||
{
|
||||
var dir = Path.Combine(projectResourcesDir, language.Key);
|
||||
TextMapData.LoadTextMap(TextMapData.TextMapFilePaths[Array.IndexOf(TextMapData.TextMapFiles, language.Value)]);
|
||||
|
||||
Thread.CurrentThread.CurrentUICulture = new CultureInfo(language.Key);
|
||||
GameData.LoadResources();
|
||||
|
||||
File.WriteAllLines(
|
||||
Path.Combine(dir, "Achievement.txt"),
|
||||
AchievementData.Values.Where(it => it.IsUsed)
|
||||
.Select(it => $"{it.Id}:{TextMapData.GetText(it.TitleTextMapHash.ToString())} - {TextMapData.GetText(it.DescTextMapHash.ToString())}"),
|
||||
Encoding.UTF8);
|
||||
|
||||
File.WriteAllLines(
|
||||
Path.Combine(dir, "Artifact.txt"),
|
||||
ReliquaryData.Values.OrderBy(it => it.Id).Select(it => $"{it.Id}:{TextMapData.GetText(it.NameTextMapHash.ToString())}"),
|
||||
Encoding.UTF8);
|
||||
|
||||
File.WriteAllLines(
|
||||
Path.Combine(dir, "Avatar.txt"),
|
||||
MaterialData.Values
|
||||
.Where(it => it.MaterialType == MaterialType.MATERIAL_AVATAR)
|
||||
.Select(it => $"{it.Id}:{TextMapData.GetText(it.NameTextMapHash.ToString())}"),
|
||||
Encoding.UTF8);
|
||||
|
||||
File.WriteAllLines(
|
||||
Path.Combine(dir, "Dungeon.txt"),
|
||||
DungeonData.Values.Select(it => $"{it.Id}:{TextMapData.GetText(it.NameTextMapHash.ToString())}"),
|
||||
Encoding.UTF8);
|
||||
|
||||
sb.Clear();
|
||||
foreach (var itemTypes in MaterialData.Values.GroupBy(it => it.ItemType))
|
||||
{
|
||||
sb.Append("// ").AppendLine(itemTypes.Key.ToTranslatedString(language.Key));
|
||||
if (itemTypes.Key == ItemType.ITEM_MATERIAL)
|
||||
{
|
||||
foreach (var m in itemTypes
|
||||
.GroupBy(it => it.MaterialType)
|
||||
.Where(it => it.Key != MaterialType.MATERIAL_NONE)
|
||||
.OrderBy(it => it.Average(m => m.Id)))
|
||||
{
|
||||
sb.Append("// ").AppendLine(m.Key.ToTranslatedString(language.Key));
|
||||
|
||||
if (m.Key == MaterialType.MATERIAL_BGM)
|
||||
{
|
||||
foreach (var materialData in m)
|
||||
sb.AppendFormat("{0}:{1} - {2}",
|
||||
materialData.Id,
|
||||
TextMapData.GetText(materialData.NameTextMapHash.ToString()),
|
||||
TextMapData.GetText(HomeWorldBgmData[int.Parse(materialData.ItemUse[0].UseParam[0])].BgmNameTextMapHash.ToString())
|
||||
).AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var materialData in m)
|
||||
sb.AppendFormat("{0}:{1}", materialData.Id, TextMapData.GetText(materialData.NameTextMapHash.ToString())).AppendLine();
|
||||
}
|
||||
sb.AppendLine();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var materialData in itemTypes)
|
||||
sb.AppendFormat("{0}:{1}", materialData.Id, TextMapData.GetText(materialData.NameTextMapHash.ToString())).AppendLine();
|
||||
sb.AppendLine();
|
||||
}
|
||||
}
|
||||
|
||||
sb.Append("// ").AppendLine(ItemType.ITEM_FURNITURE.ToTranslatedString(language.Key));
|
||||
foreach (var value in HomeWorldFurnitureData.Values)
|
||||
sb.AppendFormat("{0}:{1}", value.Id, TextMapData.GetText(value.NameTextMapHash.ToString())).AppendLine();
|
||||
|
||||
File.WriteAllText(Path.Combine(dir, "Item.txt"), sb.ToString(), Encoding.UTF8);
|
||||
|
||||
|
||||
sb.Clear();
|
||||
foreach (var monsterType in MonsterData.Values.OrderBy(it => it.Id)
|
||||
.GroupBy(it => it.Type)
|
||||
.OrderBy(it => it.Key))
|
||||
{
|
||||
sb.Append("// ").AppendLine(monsterType.Key.ToTranslatedString(language.Key));
|
||||
foreach (var monsterData in monsterType)
|
||||
{
|
||||
if (TextMapData.TryGetText(monsterData.NameTextMapHash.ToString(), out var text))
|
||||
{
|
||||
sb.AppendFormat("{0}:{1}", monsterData.Id, text);
|
||||
}
|
||||
else
|
||||
{
|
||||
var name = GameData.Monsters[monsterData.Id];
|
||||
if (name == ItemMap.EmptyName)
|
||||
sb.AppendFormat("{0}:{1} - {2}", monsterData.Id, monsterData.MonsterName, text);
|
||||
else
|
||||
sb.AppendFormat("{0}:{1}", monsterData.Id, name);
|
||||
}
|
||||
sb.AppendLine();
|
||||
}
|
||||
sb.AppendLine();
|
||||
}
|
||||
File.WriteAllText(
|
||||
Path.Combine(dir, "Monsters.txt"),
|
||||
sb.ToString(),
|
||||
Encoding.UTF8);
|
||||
|
||||
File.WriteAllLines(
|
||||
Path.Combine(dir, "Quest.txt"),
|
||||
QuestData.Values.OrderBy(it => it.Id).Select(it => $"{it.Id}:{TextMapData.GetText(MainQuestData[it.MainId].TitleTextMapHash)} - {TextMapData.GetText(it.DescTextMapHash.ToString())}"),
|
||||
Encoding.UTF8);
|
||||
|
||||
//File.WriteAllLines(
|
||||
// Path.Combine(dir, "Scene.txt"),
|
||||
// SceneData.Values.Select(it => $"{it.Id}:{it.ScriptData}"),
|
||||
// Encoding.UTF8);
|
||||
|
||||
File.WriteAllLines(
|
||||
Path.Combine(dir, "Weapon.txt"),
|
||||
WeaponData.Values.Select(it => $"{it.Id}:{TextMapData.GetText(it.NameTextMapHash.ToString())}"),
|
||||
Encoding.UTF8);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Thread.CurrentThread.CurrentUICulture = currentCultureInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
15
Source/GrasscutterTools/Game/Data/ResourceTypeAttribute.cs
Normal file
15
Source/GrasscutterTools/Game/Data/ResourceTypeAttribute.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace GrasscutterTools.Game.Data
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
||||
public class ResourceTypeAttribute : Attribute
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public ResourceTypeAttribute(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user