(Zlib.MaxPackSize(stairsPerBuffer * stairsLength) + 4) * stairsCount; // 22602 public static byte[] CreateHouseDesignStateDetailed(uint serial, int revision, MultiComponentList components) { var xMin = components.Min.X; var yMin = components.Min.Y; var xMax = components.Max.X; var yMax = components.Max.Y; var tiles = components.List; const int totalPlaneLength = planeLength * planeCount; const int stairsBufferLength = stairsPerBuffer * stairsLength; const int maxUnpackedSize = totalPlaneLength + stairsBufferLength * stairsCount; using var inflatedWriter = new SpanWriter(maxUnpackedSize); Span <bool> planesUsed = stackalloc bool[9]; var index = 0; var stairsIndex = totalPlaneLength; var totalStairsUsed = 0; var width = xMax - xMin + 1; var height = yMax - yMin + 1; for (var i = 0; i < tiles.Length; ++i) { var mte = tiles[i]; var x = mte.OffsetX - xMin; var y = mte.OffsetY - yMin; int z = mte.OffsetZ; var floor = TileData.ItemTable[mte.ItemId & TileData.MaxItemValue].Height <= 0; int plane = z switch { 0 => 0, 7 => 1, 27 => 2, 47 => 3, 67 => 4, _ => - 1 }; if (plane > -1) { int size; if (plane == 0) { size = height; } else if (floor) { size = height - 2; x -= 1; y -= 1; } else { size = height - 1; plane += 4; } index = (x * size + y) * 2; if (x >= 0 && y >= 0 && y < size && index + 1 < 0x400) { var planeUsed = planesUsed[plane]; if (!planeUsed) { inflatedWriter.Seek(plane * planeLength, SeekOrigin.Begin); inflatedWriter.Clear(planeLength); planesUsed[plane] = true; } inflatedWriter.Seek(index, SeekOrigin.Begin); inflatedWriter.Write(mte.ItemId); continue; } } inflatedWriter.Seek(stairsIndex, SeekOrigin.Begin); inflatedWriter.Write(mte.ItemId); inflatedWriter.Write((byte)mte.OffsetX); inflatedWriter.Write((byte)mte.OffsetY); inflatedWriter.Write((byte)mte.OffsetZ); stairsIndex = inflatedWriter.Position; totalStairsUsed++; } var buffer = GC.AllocateUninitializedArray <byte>(maxPacketLength); var writer = new SpanWriter(buffer); writer.Write((byte)0xD8); // Packet ID writer.Seek(2, SeekOrigin.Current); // Length writer.Write((byte)0x03); // Compression Type writer.Write((byte)0x00); // Unknown writer.Write(serial); writer.Write(revision); writer.Write((short)tiles.Length); writer.Seek(3, SeekOrigin.Current); // Buffer Length, Plane Count var totalPlanes = 0; var totalLength = 1; // includes plane count for (var i = 0; i < planeCount; i++) { if (!planesUsed[i]) { inflatedWriter.Seek(planeCount, SeekOrigin.Current); continue; } int size = i switch { 0 => width * height * 2, < 5 => (width - 1) * (height - 2) * 2, _ => width * (height - 1) * 2 }; var source = inflatedWriter.RawBuffer.Slice(i * planeLength, size); writer.Write((byte)(0x20 | i)); WritePacked(source, ref writer, out int destLength); totalLength += 4 + destLength; totalPlanes++; } index = 0; while (totalStairsUsed > 0) { var count = Math.Min(stairsPerBuffer, totalStairsUsed); totalStairsUsed -= count; var start = totalPlaneLength + index * stairsLength; var size = count * 5; var source = inflatedWriter.RawBuffer.Slice(start, size); writer.Write((byte)(9 + index++)); WritePacked(source, ref writer, out int destLength); totalLength += 4 + destLength; totalPlanes++; } writer.Seek(15, SeekOrigin.Begin); writer.Write((short)totalLength); writer.Write((byte)totalPlanes); writer.WritePacketLength(); // TODO: Avoid this somehow. Array.Resize(ref buffer, writer.BytesWritten); return(buffer); }