private static void LoadStringData(TSettings settings) { var path = Path.Combine(settings.GamePath, Dictionary); using var packageStream = File.OpenRead(path); using var packageReader = new BinaryReader(packageStream); var package = UltimaPackage.FromReader(packageReader); var file = package.GetBlocks(packageReader).Single().GetFiles(packageReader).Single(); file.GetData(packageReader, (reader, total) => { reader.ReadBytes(0x10); var current = 0x10; while (current < total) { var length = reader.ReadInt16(); var bytes = reader.ReadBytes(length); var name = System.Text.Encoding.ASCII.GetString(bytes).Split('%').First(); settings.StringData.Add(name); current += 2 + length; } }); }
private static void LoadCsvDocuments(TSettings settings) { settings.CsvDocuments.Clear(); var path = Path.Combine(settings.GamePath, GameData); using var packageStream = File.OpenRead(path); using var packageReader = new BinaryReader(packageStream); var package = UltimaPackage.FromReader(packageReader); var buffer = new byte[100]; foreach (var file in package.GetBlocks(packageReader).SelectMany(b => b.GetFiles(packageReader))) { file.GetData(packageReader, (reader, total) => { using var text = new StreamReader(reader.BaseStream, leaveOpen: true); var lines = new List <string>(); string line; while ((line = text.ReadLine()) != null) { if (line.StartsWith('#')) { continue; } lines.Add(line); } settings.CsvDocuments.Add(file.FileNameHash, new TCsvDocument { Header = lines.First().Split(','), Data = lines .Skip(1) .Select(l => l.Split(',')) .SelectMany(inner => inner.Select((item, index) => new { item, index })) .GroupBy(i => i.index, i => i.item) .Select(g => g.ToArray()) .ToArray() }); }); } }
/*public static void LoadCliLoc(TSettings settings) * { * var localization = new Dictionary<uint, string>(); * * var path = Path.Combine(settings.GamePath, Localization); * * var package = new MythicPackage(path); * * var file = package.Blocks.Single().Files.First(); * * var bytes = file.Unpack(path); * * using var stream = new MemoryStream(bytes); * * using var reader = new BinaryReader(stream); * * stream.Seek(0x6, SeekOrigin.Begin); * * while (stream.Position < stream.Length) * { * var key = reader.ReadUInt32(); * * stream.Seek(1, SeekOrigin.Current); * * var length = reader.ReadUInt16(); * * bytes = reader.ReadBytes(length); * * var text = System.Text.Encoding.UTF8.GetString(bytes); * * localization.Add(key, text); * } * }*/ private static void LoadTileArts(TSettings settings) { var path = Path.Combine(settings.GamePath, TileArt); using var packageStream = File.OpenRead(path); using var packageReader = new BinaryReader(packageStream); var package = UltimaPackage.FromReader(packageReader); var buffer = new byte[100]; foreach (var file in package.GetBlocks(packageReader).SelectMany(b => b.GetFiles(packageReader))) { file.GetData(packageReader, (reader, total) => { reader.ReadInt16(); var index = reader.ReadInt32(); var name = settings.StringData[index > 0 ? index - 1 : 0]; var id = reader.ReadUInt16(); reader.BaseStream.Read(buffer, 0, 51); var flags = reader.ReadUInt64(); reader.BaseStream.Read(buffer, 0, 48); var count = reader.ReadByte(); var properties = new Dictionary <byte, int>(); for (var i = 0; i < count; i++) { properties[reader.ReadByte()] = reader.ReadInt32(); } if (!properties.TryGetValue(0, out var weight)) { weight = 0; } if (!properties.TryGetValue(3, out var height)) { height = 0; } if (!properties.TryGetValue(6, out var layer)) { layer = 0; } settings.TileArts.Add(id, new TTileArt { Graphic = id, Name = name, Flags = flags, Weight = (ushort)weight, Height = height, Layer = (byte)layer }); }); } }
public static void Import(BinaryReader uopReader, BinaryWriter uopWriter, string mapPath, string indexPath, string staticsPath, string radarPath, bool mulInMemory = false, Action <int> progress = null) { using var mapStream = mulInMemory ? new MemoryStream(File.ReadAllBytes(mapPath)) : (Stream)File.OpenRead(mapPath); using var mapReader = new BinaryReader(mapStream); using var indexStream = mulInMemory ? new MemoryStream(File.ReadAllBytes(indexPath)) : (Stream)File.OpenRead(indexPath); using var indexReader = new BinaryReader(indexStream); using var staticsStream = mulInMemory ? new MemoryStream(File.ReadAllBytes(staticsPath)) : (Stream)File.OpenRead(staticsPath); using var staticsReader = new BinaryReader(staticsStream); using var radarStream = mulInMemory ? new MemoryStream(File.ReadAllBytes(radarPath)) : (Stream)File.OpenRead(radarPath); using var radarReader = new BinaryReader(radarStream); var package = UltimaPackage.FromReader(uopReader); var(width, height, facet) = (0, 0, 0); var firstBlock = package.GetBlocks(uopReader).First(); var firstTwoFiles = firstBlock.GetFiles(uopReader).Take(2).ToArray(); firstTwoFiles[0].GetData(uopReader, (r, _) => { height = r.ReadInt32(); width = r.ReadInt32(); }); firstTwoFiles[1].GetData(uopReader, (r, _) => facet = r.ReadByte()); package.ToWriter(uopReader, uopWriter, (width, height, facet, mapReader, indexReader, staticsReader, radarReader, progress), (w, b, f, s) => { if (b == 0 && f == 0) { return(false); } var delimiters = new List <Action <byte> >(); var statics = new Dictionary <int, Dictionary <(int x, int y), List <(ushort value, sbyte altitude, ushort unknown, ushort hue)> > >(); var mapBlockId = 100 * b + f - 1; s.progress?.Invoke(100 * (mapBlockId + 1) / (width * height / 4096)); for (var k = 0; k < 4096; k++) { var(x, y) = GetCoordinatesFromUopIndex(mapBlockId, k, s.height); var(mulMapBlock, mulBlockIndex) = GetMulIndexFromCoordinates(x, y, s.height); var mulOffset = mulMapBlock * 4 + 4 + mulMapBlock * 64 * 3 + mulBlockIndex * 3; if (mulOffset >= s.mapReader.BaseStream.Length) { return(false); } s.mapReader.BaseStream.Seek(mulOffset, SeekOrigin.Begin); WriteTile(s.mapReader.ReadUInt16(), s.mapReader.ReadSByte()); void WriteTile(ushort value, sbyte altitude) { ushort graphic = 0; byte unknown = 0; if (TileCollection.Values.TryGetValue(value, out var val)) { graphic = val.Item1; unknown = val.Item2; } if (k == 0) { w.Write((byte)s.facet); w.Write((ushort)mapBlockId); } else { w.Write((byte)0); w.Write((byte)0); } w.Write(altitude); w.Write(graphic); w.Write(unknown); w.Write((byte)(value & 0xFF)); w.Write((byte)(value >> 8)); } delimiters.Clear(); if (x % 64 == 0) { AddDelimiter(x - 1, y, 0); } if (x % 64 == 0 && y % 64 == 0) { AddDelimiter(x - 1, y - 1, 1); } if (y % 64 == 0) { AddDelimiter(x, y - 1, 2); } if ((x + 1) % 64 == 0) { AddDelimiter(x + 1, y, 3); } if ((x + 1) % 64 == 0 && (y + 1) % 64 == 0) { AddDelimiter(x + 1, y + 1, 4); } if ((y + 1) % 64 == 0) { AddDelimiter(x, y + 1, 5); } if (x % 64 == 0 && (y + 1) % 64 == 0) { AddDelimiter(x - 1, y + 1, 6); } if (y % 64 == 0 && (x + 1) % 64 == 0) { AddDelimiter(x + 1, y - 1, 7); } for (var l = 0; l < delimiters.Count; l++) { if (l == 0) { delimiters[l].Invoke((byte)delimiters.Count); } else { delimiters[l].Invoke(0); } } void AddDelimiter(int refX, int refY, byte direction) { if (refX < 0 || refY < 0) { return; } var(refMulMapBlock, refMulBlockIndex) = GetMulIndexFromCoordinates(refX, refY, s.height); var refMulOffset = refMulMapBlock * 4 + 4 + refMulMapBlock * 64 * 3 + refMulBlockIndex * 3; if (refMulOffset >= s.mapReader.BaseStream.Length) { return; } delimiters.Add(c => WriteDelimiter(refMulOffset, direction, c)); } void WriteDelimiter(int refMulOffset, byte direction, byte count) { s.mapReader.BaseStream.Seek(refMulOffset, SeekOrigin.Begin); var value = s.mapReader.ReadUInt16(); var altitude = s.mapReader.ReadSByte(); ushort graphic = 0; byte unknown = 0; if (TileCollection.Values.TryGetValue(value, out var val)) { graphic = val.Item1; unknown = val.Item2; } w.Write(count); w.Write(direction); w.Write(altitude); w.Write(graphic); w.Write(unknown); } if (!statics.TryGetValue(mulMapBlock, out var blockStatics)) { ReadBlockStatics(); } void ReadBlockStatics() { statics[mulMapBlock] = blockStatics = new Dictionary <(int x, int y), List <(ushort value, sbyte altitude, ushort unknown, ushort hue)> >(); s.indexReader.BaseStream.Seek(mulMapBlock * 12, SeekOrigin.Begin); var indexValue = s.indexReader.ReadInt32(); var staticsEnd = indexValue + s.indexReader.ReadInt32(); s.indexReader.ReadInt32(); if (indexValue == -1) { return; } s.staticsReader.BaseStream.Seek(indexValue, SeekOrigin.Begin); while (true) { if (s.staticsReader.BaseStream.Position == staticsEnd) { break; } var staticsValue = s.staticsReader.ReadUInt16(); s.radarReader.BaseStream.Seek(0x4000 + staticsValue, SeekOrigin.Begin); var(staticX, staticY) = GetCoordinatesFromMulIndex(mulMapBlock, s.staticsReader.ReadByte() + 8 * s.staticsReader.ReadByte(), s.height); var tileStatics = blockStatics.TryGetValue((staticX, staticY), out var entry) ? entry : blockStatics[(staticX, staticY)] = new List <(ushort value, sbyte altitude, ushort unknown, ushort hue)>(); var current = (staticsValue, s.staticsReader.ReadSByte(), s.staticsReader.ReadUInt16(), s.radarReader.ReadUInt16()); if (!StaticCollection.Values.Contains(staticsValue)) { continue; } tileStatics.Add(current); } }