Прежде всего, формат этого файла .dat выглядит примерно так:
(Пробелы между символами являются символами табуляции, пробелов нет).
VNUM 1 70
NAME zts3e
INDEX 0 0 0 0 1 0
TYPE 0 1
FLAG 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
DATA 1 20 28 20 4 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0
BUFF -1 80 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
LINEDESC 1
zts4e
END
#========================================================
VNUM 2 400
NAME zts5e
INDEX 0 0 0 0 2 0
TYPE 0 1
FLAG 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
DATA 4 29 43 32 4 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0
BUFF 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
LINEDESC 1
zts6e
END
#========================================================
VNUM 3 910
NAME zts7e
INDEX 0 0 0 0 3 2
TYPE 0 1
FLAG 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
DATA 7 39 57 44 4 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0
BUFF 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
LINEDESC 1
zts8e
END
#========================================================
Когда я гуглю "Форматирование текста C #" - все, что я получаю, это как открыть текстовый файл и как написать текстовый файл в C #. Я не знаю, как искать текст внутри текстового файла. И вещи, которые я нашел, не такие продвинутые.
Так, как я могу построить парсер для этого? Добавить это в мой пользовательский DTO нет ничего сложного, но разобрать весь этот текст (потому что мне нужно преобразовать эти числа в байты, bools, shorts, int, long и некоторые другие пользовательские типы, которые я сделал.
Я действительно ценю вашу помощь, думаю, это может быть глупый вопрос, но я тоже новичок в программировании, и я не нашел много информации об этом.
Код на самом деле работает, но мне не нравится:
internal void ImportItems()
{
string fileId = $"{_folder}\\Item.dat";
string fileLang = $"{_folder}\\_code_{ConfigurationManager.AppSettings["Language"]}_Item.txt";
Dictionary<string, string> dictionaryName = new Dictionary<string, string>();
string line;
List<ItemDTO> items = new List<ItemDTO>();
using (StreamReader npcIdStream = new StreamReader(fileId, Encoding.GetEncoding(1252)))
{
ItemDTO item = new ItemDTO();
bool itemAreaBegin = false;
int itemCounter = 0;
while ((line = npcIdStream.ReadLine()) != null)
{
string[] currentLine = line.Split('\t');
if (currentLine.Length > 3 && currentLine[1] == "VNUM")
{
itemAreaBegin = true;
item.VNum = short.Parse(currentLine[2]);
item.Price = long.Parse(currentLine[3]);
}
else if (currentLine.Length > 1 && currentLine[1] == "END")
{
if (!itemAreaBegin)
{
continue;
}
if (DAOFactory.ItemDAO.FirstOrDefault(s => s.VNum.Equals(item.VNum)) == null)
{
items.Add(item);
itemCounter++;
}
item = new ItemDTO();
itemAreaBegin = false;
}
else if (currentLine.Length > 2 && currentLine[1] == "NAME")
{
item.Name = dictionaryName.TryGetValue(currentLine[2], out string name) ? name : string.Empty;
}
else if (currentLine.Length > 7 && currentLine[1] == "INDEX")
{
switch (Convert.ToByte(currentLine[2]))
{
case 4:
item.Type = InventoryType.Equipment;
break;
case 8:
item.Type = InventoryType.Equipment;
break;
case 9:
item.Type = InventoryType.Main;
break;
case 10:
item.Type = InventoryType.Etc;
break;
default:
item.Type = (InventoryType)Enum.Parse(typeof(InventoryType), currentLine[2]);
break;
}
item.ItemType = currentLine[3] != "-1" ? (ItemType)Enum.Parse(typeof(ItemType), $"{(short)item.Type}{currentLine[3]}") : ItemType.Weapon;
item.ItemSubType = Convert.ToByte(currentLine[4]);
item.EquipmentSlot = (EquipmentType)Enum.Parse(typeof(EquipmentType), currentLine[5] != "-1" ? currentLine[5] : "0");
// item.DesignId = Convert.ToInt16(currentLine[6]);
switch (item.VNum)
{
// lots of cases
case 9115:
item.Morph = 3679;
item.Speed = 21;
item.WaitDelay = 3000;
break;
default:
if (item.EquipmentSlot.Equals(EquipmentType.Amulet))
{
switch (item.VNum)
// lots of cases
case 4503:
item.EffectValue = 4544;
default:
item.EffectValue = Convert.ToInt16(currentLine[7]);
break;
}
}
else
{
item.Morph = Convert.ToInt16(currentLine[7]);
}
break;
}
}
else if (currentLine.Length > 3 && currentLine[1] == "TYPE")
{
// currentLine[2] 0-range 2-range 3-magic
item.Class = item.EquipmentSlot == EquipmentType.Fairy ? (byte)15 : Convert.ToByte(currentLine[3]);
}
else if (currentLine.Length > 3 && currentLine[1] == "FLAG")
{
item.IsSoldable = currentLine[5] == "0";
item.IsDroppable = currentLine[6] == "0";
item.IsTradable = currentLine[7] == "0";
item.IsMinilandActionable = currentLine[8] == "1";
item.IsWarehouse = currentLine[9] == "1";
item.Flag9 = currentLine[10] == "1";
item.Flag1 = currentLine[11] == "1";
item.Flag2 = currentLine[12] == "1";
item.Flag3 = currentLine[13] == "1";
item.Flag4 = currentLine[14] == "1";
item.Flag5 = currentLine[15] == "1";
item.IsColored = currentLine[16] == "1";
item.Sex = currentLine[18] == "1" ? (byte)1 : currentLine[17] == "1" ? (byte)2 : (byte)0;
//not used item.Flag6 = currentLine[19] == "1";
item.Flag6 = currentLine[20] == "1";
if (currentLine[21] == "1")
{
item.ReputPrice = item.Price;
}
item.IsHeroic = currentLine[22] == "1";
item.Flag7 = currentLine[23] == "1";
item.Flag8 = currentLine[24] == "1";
}
else if (currentLine.Length > 1 && currentLine[1] == "DATA")
{
switch (item.ItemType)
{
case ItemType.Weapon:
item.LevelMinimum = Convert.ToByte(currentLine[2]);
item.DamageMinimum = Convert.ToInt16(currentLine[3]);
item.DamageMaximum = Convert.ToInt16(currentLine[4]);
item.HitRate = Convert.ToInt16(currentLine[5]);
item.CriticalLuckRate = Convert.ToByte(currentLine[6]);
item.CriticalRate = Convert.ToInt16(currentLine[7]);
item.BasicUpgrade = Convert.ToByte(currentLine[10]);
item.MaximumAmmo = 100;
break;
case ItemType.Armor:
item.LevelMinimum = Convert.ToByte(currentLine[2]);
item.CloseDefence = Convert.ToInt16(currentLine[3]);
item.DistanceDefence = Convert.ToInt16(currentLine[4]);
item.MagicDefence = Convert.ToInt16(currentLine[5]);
item.DefenceDodge = Convert.ToInt16(currentLine[6]);
item.DistanceDefenceDodge = Convert.ToInt16(currentLine[6]);
item.BasicUpgrade = Convert.ToByte(currentLine[10]);
break;
case ItemType.Box:
switch (item.VNum)
{
// lots of cases
case 287:
item.Effect = 69;
item.EffectValue = 1;
break;
default:
item.Effect = Convert.ToInt16(currentLine[2]);
item.EffectValue = Convert.ToInt32(currentLine[3]);
item.LevelMinimum = Convert.ToByte(currentLine[4]);
break;
}
break;
case ItemType.Fashion:
item.LevelMinimum = Convert.ToByte(currentLine[2]);
item.CloseDefence = Convert.ToInt16(currentLine[3]);
item.DistanceDefence = Convert.ToInt16(currentLine[4]);
item.MagicDefence = Convert.ToInt16(currentLine[5]);
item.DefenceDodge = Convert.ToInt16(currentLine[6]);
if (item.EquipmentSlot.Equals(EquipmentType.CostumeHat) || item.EquipmentSlot.Equals(EquipmentType.CostumeSuit))
{
item.ItemValidTime = Convert.ToInt32(currentLine[13]) * 3600;
}
break;
case ItemType.Food:
item.Hp = Convert.ToInt16(currentLine[2]);
item.Mp = Convert.ToInt16(currentLine[4]);
break;
case ItemType.Jewelery:
switch (item.EquipmentSlot)
{
case EquipmentType.Amulet:
item.LevelMinimum = Convert.ToByte(currentLine[2]);
break;
case EquipmentType.Fairy:
item.Element = Convert.ToByte(currentLine[2]);
item.ElementRate = Convert.ToInt16(currentLine[3]);
break;
default:
item.LevelMinimum = Convert.ToByte(currentLine[2]);
item.MaxCellonLvl = Convert.ToByte(currentLine[3]);
item.MaxCellon = Convert.ToByte(currentLine[4]);
break;
}
break;
case ItemType.Event:
switch (item.VNum)
{
// lots of cases
default:
item.EffectValue = Convert.ToInt16(currentLine[7]);
break;
}
break;
case ItemType.Special:
switch (item.VNum)
{
// lots of cases
default:
if (item.VNum > 5891 && item.VNum < 5900 || item.VNum > 9100 && item.VNum < 9109)
{
item.Effect = 69; // imagined number as for I = √(-1), complex z = a + bi
}
else
{
item.Effect = Convert.ToInt16(currentLine[2]);
}
break;
}
switch (item.Effect)
{
case 150:
case 151:
if (Convert.ToInt32(currentLine[4]) == 1)
{
item.EffectValue = 30000;
}
else if (Convert.ToInt32(currentLine[4]) == 2)
{
item.EffectValue = 70000;
}
else if (Convert.ToInt32(currentLine[4]) == 3)
{
item.EffectValue = 180000;
}
else
{
item.EffectValue = Convert.ToInt32(currentLine[4]);
}
break;
case 204:
item.EffectValue = 10000;
break;
case 305:
item.EffectValue = Convert.ToInt32(currentLine[5]);
item.Morph = Convert.ToInt16(currentLine[4]);
break;
default:
item.EffectValue = item.EffectValue == 0 ? Convert.ToInt32(currentLine[4]) : item.EffectValue;
break;
}
item.WaitDelay = 5000;
break;
case ItemType.Magical:
if (item.VNum > 2059 && item.VNum < 2070)
{
item.Effect = 10;
}
else
{
item.Effect = Convert.ToInt16(currentLine[2]);
}
item.EffectValue = Convert.ToInt32(currentLine[4]);
break;
case ItemType.Specialist:
// item.isSpecialist = Convert.ToByte(currentLine[2]); item.Unknown = Convert.ToInt16(currentLine[3]);
item.ElementRate = Convert.ToInt16(currentLine[4]);
item.Speed = Convert.ToByte(currentLine[5]);
item.SpType = Convert.ToByte(currentLine[13]);
// item.Morph = Convert.ToInt16(currentLine[14]) + 1;
item.FireResistance = Convert.ToByte(currentLine[15]);
item.WaterResistance = Convert.ToByte(currentLine[16]);
item.LightResistance = Convert.ToByte(currentLine[17]);
item.DarkResistance = Convert.ToByte(currentLine[18]);
// item.PartnerClass = Convert.ToInt16(currentLine[19]);
item.LevelJobMinimum = Convert.ToByte(currentLine[20]);
item.ReputationMinimum = Convert.ToByte(currentLine[21]);
Dictionary<int, int> elementdic = new Dictionary<int, int> { { 0, 0 } };
if (item.FireResistance != 0)
{
elementdic.Add(1, item.FireResistance);
}
if (item.WaterResistance != 0)
{
elementdic.Add(2, item.WaterResistance);
}
if (item.LightResistance != 0)
{
elementdic.Add(3, item.LightResistance);
}
if (item.DarkResistance != 0)
{
elementdic.Add(4, item.DarkResistance);
}
item.Element = (byte)elementdic.OrderByDescending(s => s.Value).First().Key;
if (elementdic.Count > 1 && elementdic.OrderByDescending(s => s.Value).First().Value == elementdic.OrderByDescending(s => s.Value).ElementAt(1).Value)
{
item.SecondaryElement = (byte)elementdic.OrderByDescending(s => s.Value).ElementAt(1).Key;
}
// needs to be hardcoded
switch (item.VNum)
{
case 901:
item.Element = 1;
break;
case 903:
item.Element = 2;
break;
case 906:
item.Element = 3;
break;
case 909:
item.Element = 3;
break;
}
break;
case ItemType.Shell:
// item.ShellMinimumLevel = Convert.ToInt16(linesave[3]);
// item.ShellMaximumLevel = Convert.ToInt16(linesave[4]);
// item.ShellType = Convert.ToByte(linesave[5]); // 3 shells of each type
break;
case ItemType.Main:
item.Effect = Convert.ToInt16(currentLine[2]);
item.EffectValue = Convert.ToInt32(currentLine[4]);
break;
case ItemType.Upgrade:
item.Effect = Convert.ToInt16(currentLine[2]);
switch (item.VNum)
{
// UpgradeItems (needed to be hardcoded)
case 1218:
item.EffectValue = 26;
break;
case 1363:
item.EffectValue = 27;
break;
case 1364:
item.EffectValue = 28;
break;
case 5107:
item.EffectValue = 47;
break;
case 5207:
item.EffectValue = 50;
break;
case 5369:
item.EffectValue = 61;
break;
case 5519:
item.EffectValue = 60;
break;
default:
item.EffectValue = Convert.ToInt32(currentLine[4]);
break;
}
break;
case ItemType.Production:
item.Effect = Convert.ToInt16(currentLine[2]);
item.EffectValue = Convert.ToInt32(currentLine[4]);
break;
case ItemType.Map:
item.Effect = Convert.ToInt16(currentLine[2]);
item.EffectValue = Convert.ToInt32(currentLine[4]);
break;
case ItemType.Potion:
item.Hp = Convert.ToInt16(currentLine[2]);
item.Mp = Convert.ToInt16(currentLine[4]);
break;
case ItemType.Snack:
item.Hp = Convert.ToInt16(currentLine[2]);
item.Mp = Convert.ToInt16(currentLine[4]);
break;
case ItemType.Teacher:
item.Effect = Convert.ToInt16(currentLine[2]);
item.EffectValue = Convert.ToInt32(currentLine[4]);
// item.PetLoyality = Convert.ToInt16(linesave[4]); item.PetFood = Convert.ToInt16(linesave[7]);
break;
case ItemType.Part:
// nothing to parse
break;
case ItemType.Sell:
// nothing to parse
break;
case ItemType.Quest2:
// nothing to parse
break;
case ItemType.Quest1:
// nothing to parse
break;
case ItemType.Ammo:
// nothing to parse
break;
}
if (item.Type == InventoryType.Miniland)
{
item.MinilandObjectPoint = int.Parse(currentLine[2]);
item.EffectValue = short.Parse(currentLine[8]);
item.Width = Convert.ToByte(currentLine[9]);
item.Height = Convert.ToByte(currentLine[10]);
}
if (item.EquipmentSlot != EquipmentType.Boots && item.EquipmentSlot != EquipmentType.Gloves || item.Type != 0)
{
continue;
}
item.FireResistance = Convert.ToByte(currentLine[7]);
item.WaterResistance = Convert.ToByte(currentLine[8]);
item.LightResistance = Convert.ToByte(currentLine[9]);
item.DarkResistance = Convert.ToByte(currentLine[11]);
}
else if (currentLine.Length > 1 && currentLine[1] == "BUFF")
{
for (int i = 0; i < 5; i++)
{
byte type = (byte)int.Parse(currentLine[2 + 5 * i]);
if (type == 0 || type == 255)
{
continue;
}
int first = int.Parse(currentLine[3 + 5 * i]);
BCardDTO itemCard = new BCardDTO
{
ItemVNum = item.VNum,
Type = type,
SubType = (byte)((int.Parse(currentLine[5 + 5 * i]) + 1) * 10 + 1),
IsLevelScaled = Convert.ToBoolean(first % 4),
IsLevelDivided = (first % 4) == 2,
FirstData = (short)(first / 4),
SecondData = (short)(int.Parse(currentLine[4 + 5 * i]) / 4),
ThirdData = (short)(int.Parse(currentLine[6 + 5 * i]) / 4),
};
itemCards.Add(itemCard);
}
}
}
}
}
PD: Я хочу добавить, что я не могу сделать это вручную, потому что этот .dat имеет 52306 строк, и это невозможно сделать