public static void LoadUOP(string path) { var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); var streamReader = new BinaryReader(stream); // Head Information Start if (streamReader.ReadInt32() != 0x0050594D) // Not a UOP Files { return; } if (streamReader.ReadInt32() > 5) // Bad Version { return; } // Multi ID List Array Start UOPHash.BuildChunkIDs(out var chunkIds); // Multi ID List Array End streamReader.ReadUInt32(); // format timestamp? 0xFD23EC43 var startAddress = streamReader.ReadInt64(); streamReader.ReadInt32(); streamReader.ReadInt32(); stream.Seek(startAddress, SeekOrigin.Begin); // Head Information End long nextBlock; do { var blockFileCount = streamReader.ReadInt32(); nextBlock = streamReader.ReadInt64(); var index = 0; do { var offset = streamReader.ReadInt64(); var headerSize = streamReader.ReadInt32(); // header length var compressedSize = streamReader.ReadInt32(); // compressed size var decompressedSize = streamReader.ReadInt32(); // decompressed size var filehash = streamReader.ReadUInt64(); // filename hash (HashLittle2) streamReader.ReadUInt32(); var compressionMethod = streamReader.ReadInt16(); // compression method (0 = none, 1 = zlib) index++; if (offset == 0 || decompressedSize == 0 || filehash == 0x126D1E99DDEDEE0A) // Exclude housing.bin { continue; } chunkIds.TryGetValue(filehash, out var chunkID); var position = stream.Position; // save current position stream.Seek(offset + headerSize, SeekOrigin.Begin); Span <byte> sourceData = new byte[compressedSize]; if (stream.Read(sourceData) != compressedSize) { continue; } Span <byte> data; if (compressionMethod == 1) { data = new byte[decompressedSize]; Zlib.Unpack(data, ref decompressedSize, sourceData, compressedSize); } else { data = sourceData; } var tileList = new List <MultiTileEntry>(); // Skip the first 4 bytes var reader = new BufferReader <byte>(data); reader.Advance(4); // ??? reader.TryReadLittleEndian(out uint count); for (uint i = 0; i < count; i++) { reader.TryReadLittleEndian(out ushort itemid); reader.TryReadLittleEndian(out short x); reader.TryReadLittleEndian(out short y); reader.TryReadLittleEndian(out short z); reader.TryReadLittleEndian(out ushort flagValue); var tileFlag = flagValue switch { 1 => TileFlag.None, 257 => TileFlag.Generic, _ => TileFlag.Background // 0 }; reader.TryReadLittleEndian(out uint clilocsCount); reader.Advance(clilocsCount * 4); // bypass binary block tileList.Add(new MultiTileEntry(itemid, x, y, z, tileFlag)); } Components[chunkID] = new MultiComponentList(tileList); stream.Seek(position, SeekOrigin.Begin); // back to position } while (index < blockFileCount); } while (stream.Seek(nextBlock, SeekOrigin.Begin) != 0); }