123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- //------------------------------------------------------------
- // Game Framework
- // Copyright © 2013-2021 Jiang Yin. All rights reserved.
- // Homepage: https://gameframework.cn/
- // Feedback: mailto:ellan@gameframework.cn
- //------------------------------------------------------------
- using GameFramework;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text;
- using UnityEngine;
- namespace MetaClient.Editor.DataTableTools
- {
- public sealed partial class DataTableProcessor
- {
- private const string CommentLineSeparator = "#";
- private static readonly char[] DataSplitSeparators = new char[] { '\t' };
- private static readonly char[] DataTrimSeparators = new char[] { '\"' };
- private readonly string[] m_NameRow;
- private readonly string[] m_TypeRow;
- private readonly string[] m_DefaultValueRow;
- private readonly string[] m_CommentRow;
- private readonly int m_ContentStartRow;
- private readonly int m_IdColumn;
- private readonly DataProcessor[] m_DataProcessor;
- private readonly string[][] m_RawValues;
- private readonly string[] m_Strings;
- private string m_CodeTemplate;
- private DataTableCodeGenerator m_CodeGenerator;
- public DataTableProcessor(string dataTableFileName, Encoding encoding, int nameRow, int typeRow, int? defaultValueRow, int? commentRow, int contentStartRow, int idColumn)
- {
- if (string.IsNullOrEmpty(dataTableFileName))
- {
- throw new GameFrameworkException("Data table file name is invalid.");
- }
- if (!dataTableFileName.EndsWith(".txt", StringComparison.Ordinal))
- {
- throw new GameFrameworkException(Utility.Text.Format("Data table file '{0}' is not a txt.", dataTableFileName));
- }
- if (!File.Exists(dataTableFileName))
- {
- throw new GameFrameworkException(Utility.Text.Format("Data table file '{0}' is not exist.", dataTableFileName));
- }
- string[] lines = File.ReadAllLines(dataTableFileName, encoding);
- int rawRowCount = lines.Length;
- int rawColumnCount = 0;
- List<string[]> rawValues = new List<string[]>();
- for (int i = 0; i < lines.Length; i++)
- {
- string[] rawValue = lines[i].Split(DataSplitSeparators);
- for (int j = 0; j < rawValue.Length; j++)
- {
- rawValue[j] = rawValue[j].Trim(DataTrimSeparators);
- }
- if (i == 0)
- {
- rawColumnCount = rawValue.Length;
- }
- else if (rawValue.Length != rawColumnCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Data table file '{0}', raw Column is '{2}', but line '{1}' column is '{3}'.", dataTableFileName, i, rawColumnCount, rawValue.Length));
- }
- rawValues.Add(rawValue);
- }
- m_RawValues = rawValues.ToArray();
- if (nameRow < 0)
- {
- throw new GameFrameworkException(Utility.Text.Format("Name row '{0}' is invalid.", nameRow));
- }
- if (typeRow < 0)
- {
- throw new GameFrameworkException(Utility.Text.Format("Type row '{0}' is invalid.", typeRow));
- }
- if (contentStartRow < 0)
- {
- throw new GameFrameworkException(Utility.Text.Format("Content start row '{0}' is invalid.", contentStartRow));
- }
- if (idColumn < 0)
- {
- throw new GameFrameworkException(Utility.Text.Format("Id column '{0}' is invalid.", idColumn));
- }
- if (nameRow >= rawRowCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Name row '{0}' >= raw row count '{1}' is not allow.", nameRow, rawRowCount));
- }
- if (typeRow >= rawRowCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Type row '{0}' >= raw row count '{1}' is not allow.", typeRow, rawRowCount));
- }
- if (defaultValueRow.HasValue && defaultValueRow.Value >= rawRowCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Default value row '{0}' >= raw row count '{1}' is not allow.", defaultValueRow.Value, rawRowCount));
- }
- if (commentRow.HasValue && commentRow.Value >= rawRowCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Comment row '{0}' >= raw row count '{1}' is not allow.", commentRow.Value, rawRowCount));
- }
- if (contentStartRow > rawRowCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Content start row '{0}' > raw row count '{1}' is not allow.", contentStartRow, rawRowCount));
- }
- if (idColumn >= rawColumnCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Id column '{0}' >= raw column count '{1}' is not allow.", idColumn, rawColumnCount));
- }
- m_NameRow = m_RawValues[nameRow];
- m_TypeRow = m_RawValues[typeRow];
- m_DefaultValueRow = defaultValueRow.HasValue ? m_RawValues[defaultValueRow.Value] : null;
- m_CommentRow = commentRow.HasValue ? m_RawValues[commentRow.Value] : null;
- m_ContentStartRow = contentStartRow;
- m_IdColumn = idColumn;
- m_DataProcessor = new DataProcessor[rawColumnCount];
- for (int i = 0; i < rawColumnCount; i++)
- {
- if (i == IdColumn)
- {
- m_DataProcessor[i] = DataProcessorUtility.GetDataProcessor("id");
- }
- else
- {
- m_DataProcessor[i] = DataProcessorUtility.GetDataProcessor(m_TypeRow[i]);
- }
- }
- Dictionary<string, int> strings = new Dictionary<string, int>(StringComparer.Ordinal);
- for (int i = contentStartRow; i < rawRowCount; i++)
- {
- if (IsCommentRow(i))
- {
- continue;
- }
- for (int j = 0; j < rawColumnCount; j++)
- {
- if (m_DataProcessor[j].LanguageKeyword != "string")
- {
- continue;
- }
- string str = m_RawValues[i][j];
- if (strings.ContainsKey(str))
- {
- strings[str]++;
- }
- else
- {
- strings[str] = 1;
- }
- }
- }
- m_Strings = strings.OrderBy(value => value.Key).OrderByDescending(value => value.Value).Select(value => value.Key).ToArray();
- m_CodeTemplate = null;
- m_CodeGenerator = null;
- }
- public int RawRowCount
- {
- get
- {
- return m_RawValues.Length;
- }
- }
- public int RawColumnCount
- {
- get
- {
- return m_RawValues.Length > 0 ? m_RawValues[0].Length : 0;
- }
- }
- public int StringCount
- {
- get
- {
- return m_Strings.Length;
- }
- }
- public int ContentStartRow
- {
- get
- {
- return m_ContentStartRow;
- }
- }
- public int IdColumn
- {
- get
- {
- return m_IdColumn;
- }
- }
- public bool IsIdColumn(int rawColumn)
- {
- if (rawColumn < 0 || rawColumn >= RawColumnCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn));
- }
- return m_DataProcessor[rawColumn].IsId;
- }
- public bool IsCommentRow(int rawRow)
- {
- if (rawRow < 0 || rawRow >= RawRowCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Raw row '{0}' is out of range.", rawRow));
- }
- return GetValue(rawRow, 0).StartsWith(CommentLineSeparator, StringComparison.Ordinal);
- }
- public bool IsCommentColumn(int rawColumn)
- {
- if (rawColumn < 0 || rawColumn >= RawColumnCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn));
- }
- return string.IsNullOrEmpty(GetName(rawColumn)) || m_DataProcessor[rawColumn].IsComment;
- }
- public string GetName(int rawColumn)
- {
- if (rawColumn < 0 || rawColumn >= RawColumnCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn));
- }
- if (IsIdColumn(rawColumn))
- {
- return "Id";
- }
- return m_NameRow[rawColumn];
- }
- public bool IsSystem(int rawColumn)
- {
- if (rawColumn < 0 || rawColumn >= RawColumnCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn));
- }
- return m_DataProcessor[rawColumn].IsSystem;
- }
- public System.Type GetType(int rawColumn)
- {
- if (rawColumn < 0 || rawColumn >= RawColumnCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn));
- }
- return m_DataProcessor[rawColumn].Type;
- }
- public string GetLanguageKeyword(int rawColumn)
- {
- if (rawColumn < 0 || rawColumn >= RawColumnCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn));
- }
- return m_DataProcessor[rawColumn].LanguageKeyword;
- }
- public string GetDefaultValue(int rawColumn)
- {
- if (rawColumn < 0 || rawColumn >= RawColumnCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn));
- }
- return m_DefaultValueRow != null ? m_DefaultValueRow[rawColumn] : null;
- }
- public string GetComment(int rawColumn)
- {
- if (rawColumn < 0 || rawColumn >= RawColumnCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn));
- }
- return m_CommentRow != null ? m_CommentRow[rawColumn] : null;
- }
- public string GetValue(int rawRow, int rawColumn)
- {
- if (rawRow < 0 || rawRow >= RawRowCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Raw row '{0}' is out of range.", rawRow));
- }
- if (rawColumn < 0 || rawColumn >= RawColumnCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn));
- }
- return m_RawValues[rawRow][rawColumn];
- }
- public string GetString(int index)
- {
- if (index < 0 || index >= StringCount)
- {
- throw new GameFrameworkException(Utility.Text.Format("String index '{0}' is out of range.", index));
- }
- return m_Strings[index];
- }
- public int GetStringIndex(string str)
- {
- for (int i = 0; i < StringCount; i++)
- {
- if (m_Strings[i] == str)
- {
- return i;
- }
- }
- return -1;
- }
- public bool GenerateDataFile(string outputFileName)
- {
- if (string.IsNullOrEmpty(outputFileName))
- {
- throw new GameFrameworkException("Output file name is invalid.");
- }
- try
- {
- using (FileStream fileStream = new FileStream(outputFileName, FileMode.Create, FileAccess.Write))
- {
- using (BinaryWriter binaryWriter = new BinaryWriter(fileStream, Encoding.UTF8))
- {
- for (int rawRow = ContentStartRow; rawRow < RawRowCount; rawRow++)
- {
- if (IsCommentRow(rawRow))
- {
- continue;
- }
- byte[] bytes = GetRowBytes(outputFileName, rawRow);
- binaryWriter.Write7BitEncodedInt32(bytes.Length);
- binaryWriter.Write(bytes);
- }
- }
- }
- Debug.Log(Utility.Text.Format("Parse data table '{0}' success.", outputFileName));
- return true;
- }
- catch (Exception exception)
- {
- Debug.LogError(Utility.Text.Format("Parse data table '{0}' failure, exception is '{1}'.", outputFileName, exception));
- return false;
- }
- }
- public bool SetCodeTemplate(string codeTemplateFileName, Encoding encoding)
- {
- try
- {
- m_CodeTemplate = File.ReadAllText(codeTemplateFileName, encoding);
- Debug.Log(Utility.Text.Format("Set code template '{0}' success.", codeTemplateFileName));
- return true;
- }
- catch (Exception exception)
- {
- Debug.LogError(Utility.Text.Format("Set code template '{0}' failure, exception is '{1}'.", codeTemplateFileName, exception));
- return false;
- }
- }
- public void SetCodeGenerator(DataTableCodeGenerator codeGenerator)
- {
- m_CodeGenerator = codeGenerator;
- }
- public bool GenerateCodeFile(string outputFileName, Encoding encoding, object userData = null)
- {
- if (string.IsNullOrEmpty(m_CodeTemplate))
- {
- throw new GameFrameworkException("You must set code template first.");
- }
- if (string.IsNullOrEmpty(outputFileName))
- {
- throw new GameFrameworkException("Output file name is invalid.");
- }
- try
- {
- StringBuilder stringBuilder = new StringBuilder(m_CodeTemplate);
- if (m_CodeGenerator != null)
- {
- m_CodeGenerator(this, stringBuilder, userData);
- }
- using (FileStream fileStream = new FileStream(outputFileName, FileMode.Create, FileAccess.Write))
- {
- using (StreamWriter stream = new StreamWriter(fileStream, encoding))
- {
- stream.Write(stringBuilder.ToString());
- }
- }
- Debug.Log(Utility.Text.Format("Generate code file '{0}' success.", outputFileName));
- return true;
- }
- catch (Exception exception)
- {
- Debug.LogError(Utility.Text.Format("Generate code file '{0}' failure, exception is '{1}'.", outputFileName, exception));
- return false;
- }
- }
- private byte[] GetRowBytes(string outputFileName, int rawRow)
- {
- using (MemoryStream memoryStream = new MemoryStream())
- {
- using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream, Encoding.UTF8))
- {
- for (int rawColumn = 0; rawColumn < RawColumnCount; rawColumn++)
- {
- if (IsCommentColumn(rawColumn))
- {
- continue;
- }
- try
- {
- m_DataProcessor[rawColumn].WriteToStream(this, binaryWriter, GetValue(rawRow, rawColumn));
- }
- catch
- {
- if (m_DataProcessor[rawColumn].IsId || string.IsNullOrEmpty(GetDefaultValue(rawColumn)))
- {
- Debug.LogError(Utility.Text.Format("Parse raw value failure. OutputFileName='{0}' RawRow='{1}' RowColumn='{2}' Name='{3}' Type='{4}' RawValue='{5}'", outputFileName, rawRow, rawColumn, GetName(rawColumn), GetLanguageKeyword(rawColumn), GetValue(rawRow, rawColumn)));
- return null;
- }
- else
- {
- Debug.LogWarning(Utility.Text.Format("Parse raw value failure, will try default value. OutputFileName='{0}' RawRow='{1}' RowColumn='{2}' Name='{3}' Type='{4}' RawValue='{5}'", outputFileName, rawRow, rawColumn, GetName(rawColumn), GetLanguageKeyword(rawColumn), GetValue(rawRow, rawColumn)));
- try
- {
- m_DataProcessor[rawColumn].WriteToStream(this, binaryWriter, GetDefaultValue(rawColumn));
- }
- catch
- {
- Debug.LogError(Utility.Text.Format("Parse default value failure. OutputFileName='{0}' RawRow='{1}' RowColumn='{2}' Name='{3}' Type='{4}' RawValue='{5}'", outputFileName, rawRow, rawColumn, GetName(rawColumn), GetLanguageKeyword(rawColumn), GetComment(rawColumn)));
- return null;
- }
- }
- }
- }
- return memoryStream.ToArray();
- }
- }
- }
- }
- }
|