using SanAndreasUnity.Importing.Archive; using SanAndreasUnity.Importing.Items.Placements; using System.Collections.Generic; using System.IO; using System.Linq; using UnityEngine; namespace SanAndreasUnity.Importing.Items { public static class Item { private static readonly List _zones = new List(); private static readonly List _enexes = new List(); public static IReadOnlyList Enexes => _enexes; private static readonly Dictionary _definitions = new Dictionary(); private static readonly Dictionary> _placements = new Dictionary>(); public static void ReadLoadList(string path) { var ws = new[] { ' ', '\t' }; using (var reader = File.OpenText(path)) { string line; while ((line = reader.ReadLine()) != null) { line = line.Trim(); if (line.Length == 0) continue; if (line.StartsWith("#")) continue; var index = line.IndexOfAny(ws); if (index == -1) continue; var type = line.Substring(0, index); var args = line.Substring(index).TrimStart(); args = args.Replace("DATA\\MAPS\\", "data/maps/"); args = args.Replace(".IDE", ".ide"); args = args.Replace(".IPL", ".ipl"); args = args.Replace('\\', Path.DirectorySeparatorChar); switch (type.ToLower()) { case "ide": ReadIde(args); break; case "ipl": ReadIpl(args); break; } } } } public static void ReadIde(string path) { var file = new ItemFile(path); foreach (var obj in file.GetItems().OfType()) { if (_definitions.ContainsKey(obj.Id)) { Debug.LogWarning($"Definition with id {obj.Id} already exists, skipping it"); } else { _definitions.Add(obj.Id, obj); } } } public static void ReadIpl(string path) { var file = new ItemFile(ArchiveManager.GetCaseSensitiveFilePath(Path.GetFileName(path))); foreach (var zone in file.GetSection("zone")) { _zones.Add(zone); } foreach (var enex in file.GetSection("enex")) { _enexes.Add(enex); } var insts = file.GetSection("inst"); var list = new List(); list.AddRange(insts); var cars = new List(file.GetSection("cars")); string streamFormat = Path.GetFileNameWithoutExtension(path).ToLower() + "_stream{0}.ipl"; int missed = 0; for (int i = 0; ; ++i) { string streamFileName = string.Format(streamFormat, i); if (!ArchiveManager.FileExists(streamFileName)) { ++missed; if (missed > 10) break; continue; } file = new ItemFile(ArchiveManager.ReadFile(streamFileName)); list.AddRange(file.GetSection("inst")); cars.AddRange(file.GetSection("cars")); } list.ResolveLod(); int lastCell = -1; foreach (var inst in list) { int cell = inst.InteriorLevel; if (lastCell != cell && !_placements.ContainsKey(lastCell = cell)) { _placements.Add(cell, new List()); } _placements[cell].Add(inst); } if (!_placements.ContainsKey(0)) { _placements.Add(0, new List()); } _placements[0].AddRange(cars.Cast()); } public static TDefinition GetDefinition(int id) where TDefinition : class, IObjectDefinition { return _definitions.TryGetValue(id, out IObjectDefinition objectDefinition) ? (TDefinition) objectDefinition : null; } public static TDefinition GetDefinitionOrThrow(int id) where TDefinition : Definition, IObjectDefinition { var def = GetDefinition(id); if (null == def) throw new System.Exception($"Failed to find definition of type {typeof(TDefinition).Name} with id {id}"); return def; } public static IEnumerable GetDefinitions() where TDefinition : Definition { return _definitions.Values.OfType(); } public static int GetNumDefinitions() where TDefinition : Definition { return _definitions.Count (pair => pair.Value is TDefinition); } public static IEnumerable GetPlacements(params int[] cellIds) where TPlacement : Placement { return cellIds.SelectMany(x => _placements.ContainsKey(x) ? _placements[x].OfType() : Enumerable.Empty()); } } }