using FLCompanionByDvurechensky.Data; using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace FLCompanionByDvurechensky.Services { /// /// Сервис глобальной работы системы /// public class SystemService { /// /// Все данные системы /// public Dictionary UniverseSystemsData { get; set; } /// /// Список баз /// public Dictionary UniverseBasesData { get; set; } /// /// ID Систнем /// public List SystemsID { get; set; } /// /// Список предметов в игре /// public List Equipments { get; set; } /// /// ID системы - Список зон добычи ископаемых /// public Dictionary> SysAsteroids { get; set; } /// /// ID - Name системы /// public Dictionary SystemNamesID { get; set; } /// /// Name - Id систем /// public Dictionary SystemsNameId { get; set; } /// /// Cписок контейнеров /// public List Loadouts { get; set; } /// /// Список путей от систем до систем /// public List HollRoads { get; set; } /// /// Массив очищенных айдишников систем для ComboBox /// public string[] ArraySystemsCombobox { get; set; } /// /// Обрабатывать русские наименования в алгоритмах /// public bool IsRussian { get; set; } [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)] private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName); [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern int LoadString(IntPtr hInstance, int ID, StringBuilder lpBuffer, int nBufferMax); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool FreeLibrary(IntPtr hModule); private LogService LogService { get; set; } private string BaseId { get; set; } private string SystemID { get; set; } private int SurptiseNick_ID { get; set; } /// /// Конструктор /// /// использование русского языка(TODO: по умолчанию только он) /// экземпляр сервиса логирования public SystemService(bool isRussian, LogService logService) { UniverseSystemsData = new Dictionary(); UniverseBasesData = new Dictionary(); SystemNamesID = new Dictionary(); SystemsNameId = new Dictionary(); SysAsteroids = new Dictionary>(); Equipments = new List(); SystemsID = new List(); Loadouts = new List(); HollRoads = new List(); IsRussian = isRussian; LogService = logService; } /// /// Получение и обработка информации /// /// Список систем /// Выбор пути старта /// Выбор точки остановки /// Выбор оборудования для поиска /// Экземпляр сервиса логирования public void GetInfo(ComboBox systems, ComboBox roadStart, ComboBox roadStop, ComboBox equipments, LogService logService) { try { var stopwatch = new Stopwatch(); Task.Factory.StartNew(delegate () { Parallel.Invoke(() => GetAllSystems(), () => GetAllEquipments(equipments), () => GetAllAsteroids(), () => GetAllLoadouts(), () => GetAllBases(roadStart, roadStop, systems)); }); } catch (Exception exception) { logService.ErrorLogEvent(exception.Message); } } /// /// Получение списка грузов /// /// /// private void GetLoadout(string line) { if (line.Contains("nickname =")) { SurptiseNick_ID++; var nickName = (line.Substring(10, line.Length - 10)).Trim().ToLower(); Loadouts.Add(new Loadout() { Name = nickName }); } if (line.Contains("archetype =")) { var arch = (line.Substring(11, line.Length - 11)).Trim().ToLower(); Loadouts[SurptiseNick_ID - 1].Archetype = arch; } if (line.Contains("cargo =")) { var cargoNameCount = (line.Substring(7, line.Length - 7)).Trim().ToLower(); var name = cargoNameCount.Substring(0, cargoNameCount.IndexOf(',')); var count = cargoNameCount.Substring(cargoNameCount.IndexOf(',') + 1, cargoNameCount.Length - (cargoNameCount.IndexOf(',') + 1)); int.TryParse(count, out int res); Loadouts[SurptiseNick_ID - 1].Cargo.Add(new Cargo() { Name = name, Count = res }); } } /// /// Получение информации о системе /// /// строка с данными private void GetSystemDataToFile(string line) { if (line.Contains("nickname")) { SystemID = (line.Substring(10, line.Length - 10)).Trim().ToLower(); UniverseSystemsData.Add(SystemID, new UniverseSystem() { Id = SystemID }); } if (line.Contains("strid_name")) { var dll_name = (line.Substring(12, line.Length - 12)).Trim(); UniverseSystemsData[SystemID].DLL_Name = dll_name; var id = SystemID.ToLower(); string name = string.Empty; if (SystemNamesID.ContainsKey(id)) name = SystemNamesID[id]; else name = id; UniverseSystemsData[SystemID].Name = name; } if (line.Contains("visit")) { var visit = (line.Substring(7, line.Length - 7)).Trim(); UniverseSystemsData[SystemID].Visit = int.Parse(visit); } if (line.Contains("ids_info")) { var dll_ids_name = (line.Substring(10, line.Length - 10)).Trim(); UniverseSystemsData[SystemID].DLL_InfoCard = dll_ids_name; } if (line.Contains("file")) { var file = (line.Substring(6, line.Length - 6)).Trim(); UniverseSystemsData[SystemID].INI = file; GetSystemInfo(SystemID); } if (line.Contains("NavMapScale")) { var nav = (line.Substring(13, line.Length - 13)).Trim(); IFormatProvider formatter = new NumberFormatInfo { NumberDecimalSeparator = "." }; UniverseSystemsData[SystemID].NavMapScale = double.Parse(nav, formatter); } } /// /// Получение списка баз системы /// /// строка с информацией private void GetBaseDataToFile(string line) { if (line.Contains("nickname")) { BaseId = (line.Substring(10, line.Length - 10)).Trim().ToLower(); UniverseBasesData.Add(BaseId, new UniverseBase() { Id = BaseId }); } if (line.Contains("strid_name")) { var dll_name = (line.Substring(12, line.Length - 12)).Trim(); if (dll_name.Contains(";")) dll_name = dll_name.Substring(0, dll_name.IndexOf(';')); UniverseBasesData[BaseId].DLL_Name = dll_name; var names = GetNameSystem(int.Parse(dll_name), BaseId); foreach (var name in names) { UniverseBasesData[BaseId].Name += name + " | "; } } } /// /// Читает конфигурационный файл системы /// /// ID системы private void GetSystemInfo(string systemId) { var sr = new StreamReader(UniverseSystemsData[systemId].INI); var data = sr.ReadLine(); var Object = false; var Zone = false; while (data != null) { if (data.Contains("Object")) { Object = true; Zone = false; if (UniverseSystemsData[systemId].Objects == null) UniverseSystemsData[systemId].Objects = new List(); } if (data.Contains("Zone")) { Object = false; Zone = true; } if (Object) { if (data.Contains("nickname")) { var id_name = (data.Substring(10, data.Length - 10)).Trim(); UniverseSystemsData[systemId].Objects.Add(new ObjectSystem() { ID = id_name }); } if (data.Contains("pos =")) { var position = (data.Substring(5, data.Length - 5)).Trim(); if (position.Contains(";")) position = (position.Substring(0, position.IndexOf(';')).Trim()); int[] pos = position.Split(',').Select(n => { int val = 0; n = n.Trim(); var state = int.TryParse(n, out val); if (state == false) { double td = 0; if (n.Contains('.')) { IFormatProvider formatter = new NumberFormatInfo { NumberDecimalSeparator = "." }; td = double.Parse(n, formatter); int i = (int)Math.Round(td, MidpointRounding.AwayFromZero); val = i; return val; } else { File.AppendAllText("log.txt", "Error Parse Position - " + position + " - " + UniverseSystemsData[systemId].INI + "\n"); return 0; } } else return val; }).ToArray(); if(pos == null) { LogService.ErrorLogEvent(systemId); } else UniverseSystemsData[systemId].Objects[UniverseSystemsData[systemId].Objects.Count - 1].Pos = pos; } if (data.Contains("base =")) { var baseID = (data.Substring(6, data.Length - 6)).Trim(); UniverseSystemsData[systemId].Objects[UniverseSystemsData[systemId].Objects.Count - 1].BaseID = baseID; } if (data.Contains("ids_name =")) { var idsName = (data.Substring(10, data.Length - 10)).Trim(); UniverseSystemsData[systemId].Objects[UniverseSystemsData[systemId].Objects.Count - 1].IdsName = idsName; } if (data.Contains("archetype =")) { var archetype = (data.Substring(11, data.Length - 11)).Trim(); UniverseSystemsData[systemId].Objects[UniverseSystemsData[systemId].Objects.Count - 1].Archetype = archetype; } if (data.Contains("loadout =")) { var loadout = (data.Substring(9, data.Length - 9)).Trim(); UniverseSystemsData[systemId].Objects[UniverseSystemsData[systemId].Objects.Count - 1].Loadout = loadout; } if (data.Contains("goto =") && !data.Contains(';')) { var loadout = (data.Substring(6, data.Length - 6)).Trim().ToLower(); var idS = loadout.Substring(0, loadout.IndexOf(',')); var nameS = SystemNamesID[idS]; UniverseSystemsData[systemId].Objects[UniverseSystemsData[systemId].Objects.Count - 1].Goto = nameS; UniverseSystemsData[systemId].Objects[UniverseSystemsData[systemId].Objects.Count - 1].GotoID = idS; } } if(Zone) { if (data.Contains("nickname =")) { var id_name = (data.Substring(10, data.Length - 10)).Trim(); UniverseSystemsData[systemId].Zones.Add(new ZoneSystem() { ID = id_name }); } if (data.Contains("pos =")) { var position = (data.Substring(5, data.Length - 5)).Trim(); if (position.Contains(";")) position = (position.Substring(0, position.IndexOf(';')).Trim()); int[] pos = position.Split(',').Select(n => { var val = 0; n = n.Trim(); var state = int.TryParse(n, out val); if (state == false) { double td = 0; if (n.Contains('.')) { IFormatProvider formatter = new NumberFormatInfo { NumberDecimalSeparator = "." }; td = double.Parse(n, formatter); int i = (int)Math.Round(td, MidpointRounding.AwayFromZero); val = i; return val; } else { File.AppendAllText("log.txt", "Error Parse Position - " + position + " - " + UniverseSystemsData[systemId].INI + "\n"); return 0; } } else return val; }).ToArray(); if (pos == null) { LogService.ErrorLogEvent(systemId); } else UniverseSystemsData[systemId].Zones[UniverseSystemsData[systemId].Zones.Count - 1].Pos = pos; } } data = sr.ReadLine(); } } /// /// Получение человекочитаемого наименования /// /// идентификатор элемента объекта /// идентификатор объекта /// список наименований public List GetNameSystem(int id, string baseId) { string[] dlls = new string[] { "NameResources.dll", "SBM.dll", "SBM2.dll", "SBM3.dll" }; var names = new List(); foreach(string dll in dlls) { string name = ExtractStringFromDLL(dll, id); if (!string.IsNullOrEmpty(name)) { if(!names.Contains(name)) { names.Add(name); } } } if(names.Count == 0) { names.Add("НЕТ НАЗВАНИЙ"); LogService.ErrorLogEvent($"[Имя объекта системы][{baseId}] id: " + id + " - не содержит названия"); } return names; } /// /// Обновление содержимого ключевых элементов Combobox /// private void LoadComboboxData(ComboBox roadStart, ComboBox roadStop, ComboBox systems) { int resultCountSystem = 0; var countCurrSys = 0; ArraySystemsCombobox = new string[UniverseSystemsData.Count]; var dirInfoSystems = new DirectoryInfo("SYSTEMS"); var dirInfoArray = dirInfoSystems.GetDirectories(); //формирую список идентификаторов систем foreach (var dirInfo in dirInfoArray) { var dirName = dirInfo.ToString().ToLower(); if (UniverseSystemsData.ContainsKey(dirName)) { resultCountSystem++; var roadStartData = new ComboBoxItem(); roadStartData.Text = (string.IsNullOrEmpty(UniverseSystemsData[dirName].Name) ? UniverseSystemsData[dirName].Id : UniverseSystemsData[dirName].Name); roadStartData.ID = UniverseSystemsData[dirName].Id; roadStart.BeginInvoke(new Action(() => { roadStart.Items.Add(roadStartData); roadStart.SelectedIndex = 0; })); var roadStopData = new ComboBoxItem(); roadStopData.Text = (string.IsNullOrEmpty(UniverseSystemsData[dirName].Name) ? UniverseSystemsData[dirName].Id : UniverseSystemsData[dirName].Name); roadStopData.ID = UniverseSystemsData[dirName].Id; roadStop.BeginInvoke(new Action(() => { roadStop.Items.Add(roadStopData); if(roadStop.Items.Count >= 2) roadStop.SelectedIndex = 1; })); if (UniverseSystemsData[dirName].Name.Length == 0) { systems.BeginInvoke(new Action(() => { systems.Items.Add(UniverseSystemsData[dirName].Id); })); } else { systems.BeginInvoke(new Action(() => { systems.Items.Add(UniverseSystemsData[dirName].Name + " | " + UniverseSystemsData[dirName].Id); systems.SelectedIndex = 0; })); } ArraySystemsCombobox[countCurrSys] = dirName; countCurrSys++; SystemsID.Add(UniverseSystemsData[dirName].Id); } else { resultCountSystem++; LogService.ErrorWarningEvent("[" + resultCountSystem + "] " + dirName + " - не является системой..."); } } ArraySystemsCombobox = ArraySystemsCombobox.Where(x => x != null).ToArray(); LogService.LogEvent("Обновление данных в интерфейсе о системах завершено"); LoadRoute(); } /// /// Обработка маршрутов между системами (все гиперпереходы) /// private void LoadRoute() { foreach (var sys in ArraySystemsCombobox) { foreach (var elem in UniverseSystemsData[sys].Objects.FindAll((el) => !el.ID.Contains('=') && el.ID.ToLower().Contains(sys.ToLower() + "_to"))) { var name = elem.ID; var destiny = name.Substring(name.IndexOf('_') + 4, name.Length - 4 - sys.Length); if (destiny.IndexOf('_') != -1) destiny = destiny.Substring(0, destiny.IndexOf('_')); //проверяем goto if (elem.GotoID == null || elem.GotoID.ToLower().Contains(sys.ToLower())) continue; var res = sys.ToLower() + "=" + elem.GotoID.ToLower(); if (!res.Contains("police01")) HollRoads.Add(res); } HollRoads.Add("aod01=hu04"); //система ангелов тьмы HollRoads.Add("hu04=aod01"); //система ангелов тьмы HollRoads.Add("dream_system01=hi03"); //система грёз HollRoads.Add("hi03=dream_system01"); //система грёз } //формирование словаря для маршрутизации в русском переводе for (int i = 0; i < ArraySystemsCombobox.Length; i++) { if (!SystemsNameId.ContainsKey(UniverseSystemsData[ArraySystemsCombobox[i]].Name)) SystemsNameId.Add(UniverseSystemsData[ArraySystemsCombobox[i]].Name, ArraySystemsCombobox[i]); else LogService.LogEvent(UniverseSystemsData[ArraySystemsCombobox[i]].Name); } LogService.LogEvent("Список маршрутов определён и обновлён в интерфейсе"); } /// /// Чтение списка баз и информации о системе /// private void GetAllBases(ComboBox roadStart, ComboBox roadStop, ComboBox systems) { using (var reader = new StreamReader("universe.ini")) { var line = string.Empty; bool systemState = false, baseState = false; while ((line = reader.ReadLine()) != null) { if (!string.IsNullOrEmpty(line)) { if (line.Contains("[system]")) { systemState = true; baseState = false; } if (line.Contains("[Base]")) { systemState = false; baseState = true; } if (systemState) GetSystemDataToFile(line); if (baseState) GetBaseDataToFile(line); } } } LogService.LogEvent($"Вcя информация о {UniverseSystemsData.Count} системах игры прочитана"); LogService.LogEvent($"Все базы игры прочитаны: {UniverseBasesData.Count}"); LoadComboboxData(roadStart, roadStop, systems); } /// /// Получает список грузов /// private void GetAllLoadouts() { //получаю список грузов using (var reader = new StreamReader("loadouts.ini")) { var line = string.Empty; bool load = false; while ((line = reader.ReadLine()) != null) { if (!string.IsNullOrEmpty(line)) { line = line.ToLower(); if (line.Contains("[loadout]")) load = true; if (load) GetLoadout(line); } } } LogService.LogEvent($"Все грузы игры прочитаны: {Loadouts.Count}"); } /// /// Получение списка систем /// private void GetAllSystems() { using (var reader = new StreamReader("systems.ini")) { var line = string.Empty; while ((line = reader.ReadLine()) != null) { if (!string.IsNullOrEmpty(line)) { var idS = line.Substring(0, line.IndexOf('=')); var nameS = line.Substring(line.IndexOf('=') + 1); SystemNamesID.Add(idS, nameS); } } } LogService.LogEvent($"Все системы игры прочитаны: {SystemNamesID.Count}"); } /// /// Получаение всех наименований оборудования в игре /// private void GetAllEquipments(ComboBox equipments) { using (var reader = new StreamReader("equipments.ini")) { var line = string.Empty; while ((line = reader.ReadLine()) != null) { if (!string.IsNullOrEmpty(line)) { var tmp1 = line.Substring(line.IndexOf(',') + 1, line.Length - (line.IndexOf(',') + 1)); var tmp2 = tmp1.Substring(tmp1.IndexOf(',') + 1, tmp1.Length - (tmp1.IndexOf(',') + 1)); var tmp3 = tmp2.Substring(tmp2.IndexOf(',') + 1, tmp2.Length - (tmp2.IndexOf(',') + 1)); var tmp4 = tmp3.Substring(tmp3.IndexOf(',') + 1, tmp3.Length - (tmp3.IndexOf(',') + 1)); var Id = tmp4.Substring(0, tmp4.IndexOf(',')).Trim(); var tmp5 = tmp4.Substring(tmp4.IndexOf(',') + 1, tmp4.Length - (tmp4.IndexOf(',') + 1)); var Name = tmp5.Substring(0, tmp5.IndexOf(',')).Trim(); Equipments.Add(new Equipment() { Id = Id, Name = Name }); } } } LogService.LogEvent($"Всё оброрудование игры прочитано: {Equipments.Count}"); } /// /// Получаение всех данных по астероидным полям /// private void GetAllAsteroids() { var dirInfoSystems = new DirectoryInfo("ASTEROIDS"); var files = dirInfoSystems.GetFiles(); foreach(var file in files) { if (!file.Name.Contains('_')) continue; var idSys = file.Name.Substring(0, file.Name.IndexOf('_')); var path = Path.Combine("ASTEROIDS", file.Name); //получаю список груза using (var reader = new StreamReader(path)) { var line = string.Empty; bool loot = false; var nameZone = string.Empty; while ((line = reader.ReadLine()) != null) { if (!string.IsNullOrEmpty(line)) { if (line.Contains("[LootableZone]")) loot = true; if (line.Contains("[TexturePanels]")) loot = false; if (loot) { //Id зоны if(line.Contains("zone =")) { nameZone = line.Substring(line.IndexOf('=') + 1, line.Length - (line.IndexOf('=') + 1)).Trim(); } //Груз астероида if(line.Contains("asteroid_loot_commodity =")) { var lootes = line.Substring(line.IndexOf('=') + 1, line.Length - (line.IndexOf('=') + 1)).Trim(); //Если система с таким ID существует, то заполняем инфу в неё if (SysAsteroids.ContainsKey(idSys)) { SysAsteroids[idSys].Add(new LootableZone() { LootId = lootes.ToLower(), ZoneName = nameZone.ToLower() }); } else //создаём такую систему со своими зонами астероидов { SysAsteroids.Add(idSys, new List() { new LootableZone() { LootId = lootes.ToLower(), ZoneName = nameZone.ToLower() }}); } } } } } } } LogService.LogEvent($"Все астероидные поля прочитаны: {SysAsteroids.Count}"); } /// /// Чтение элемента из DLL /// /// Адрес до файла /// Номер элемента /// строка с данными private string ExtractStringFromDLL(string file, int number) { var lib = LoadLibrary(file); var resultBuilder = new StringBuilder(2048); LoadString(lib, number, resultBuilder, resultBuilder.Capacity); FreeLibrary(lib); return resultBuilder.ToString(); } } }