diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs
index 24614a86..4c057896 100644
--- a/MinecraftClient/Protocol/Handlers/Protocol18.cs
+++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs
@@ -15,7 +15,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Implementation for Minecraft 1.7.X, 1.8.X, 1.9.X, 1.10.X Protocols
///
-
class Protocol18Handler : IMinecraftCom
{
private const int MC18Version = 47;
@@ -59,7 +58,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Separate thread. Network reading loop.
///
-
private void Updater()
{
try
@@ -80,8 +78,7 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Read data from the network. Should be called on a separate thread.
///
- ///
-
+ /// FALSE if an error occured, TRUE otherwise.
private bool Update()
{
handler.OnUpdate();
@@ -106,7 +103,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// will contain packet ID
/// will contain raw packet Data
-
private void readNextPacket(ref int packetID, List packetData)
{
packetData.Clear();
@@ -133,7 +129,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Abstract incoming packet numbering
///
-
private enum PacketIncomingType
{
KeepAlive,
@@ -161,7 +156,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Packet ID
/// Protocol version
/// Abstract numbering
-
private PacketIncomingType getPacketIncomingType(int packetID, int protocol)
{
if (protocol < MC19Version)
@@ -218,7 +212,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Packet ID
/// Packet contents
/// TRUE if the packet was processed, FALSE if ignored or unknown
-
private bool handlePacket(int packetID, List packetData)
{
if (login_phase)
@@ -280,13 +273,16 @@ namespace MinecraftClient.Protocol.Handlers
double z = readNextDouble(packetData);
readData(8, packetData); //Ignore look
byte locMask = readNextByte(packetData);
- Location location = handler.GetCurrentLocation();
- location.X = (locMask & 1 << 0) != 0 ? location.X + x : x;
- location.Y = (locMask & 1 << 1) != 0 ? location.Y + y : y;
- location.Z = (locMask & 1 << 2) != 0 ? location.Z + z : z;
-
- handler.UpdateLocation(location);
+ if (protocolversion >= MC18Version)
+ {
+ Location location = handler.GetCurrentLocation();
+ location.X = (locMask & 1 << 0) != 0 ? location.X + x : x;
+ location.Y = (locMask & 1 << 1) != 0 ? location.Y + y : y;
+ location.Z = (locMask & 1 << 2) != 0 ? location.Z + z : z;
+ handler.UpdateLocation(location);
+ }
+ else handler.UpdateLocation(new Location(x, y, z));
if (protocolversion >= MC19Version)
{
@@ -302,9 +298,22 @@ namespace MinecraftClient.Protocol.Handlers
int chunkX = readNextInt(packetData);
int chunkZ = readNextInt(packetData);
bool chunksContinuous = readNextBool(packetData);
- ushort chunkMask = protocolversion >= MC19Version ? (ushort)readNextVarInt(packetData) : readNextUShort(packetData);
- int dataSize = readNextVarInt(packetData);
- ProcessChunkColumnData(chunkX, chunkZ, chunkMask, false, chunksContinuous, packetData);
+ ushort chunkMask = protocolversion >= MC19Version
+ ? (ushort)readNextVarInt(packetData)
+ : readNextUShort(packetData);
+ if (protocolversion < MC18Version)
+ {
+ ushort addBitmap = readNextUShort(packetData);
+ int compressedDataSize = readNextInt(packetData);
+ byte[] compressed = readData(compressedDataSize, packetData);
+ byte[] decompressed = ZlibUtils.Decompress(compressed);
+ ProcessChunkColumnData(chunkX, chunkZ, chunkMask, addBitmap, true, chunksContinuous, new List(decompressed));
+ }
+ else
+ {
+ int dataSize = readNextVarInt(packetData);
+ ProcessChunkColumnData(chunkX, chunkZ, chunkMask, 0, false, chunksContinuous, packetData);
+ }
}
break;
case PacketIncomingType.MultiBlockChange:
@@ -312,42 +321,90 @@ namespace MinecraftClient.Protocol.Handlers
{
int chunkX = readNextInt(packetData);
int chunkZ = readNextInt(packetData);
- int recordCount = readNextVarInt(packetData);
+ int recordCount = protocolversion < MC18Version
+ ? (int)readNextShort(packetData)
+ : readNextVarInt(packetData);
+
for (int i = 0; i < recordCount; i++)
{
- byte locationXZ = readNextByte(packetData);
+ byte locationXZ;
+ ushort blockIdMeta;
+ int blockY;
+
+ if (protocolversion < MC18Version)
+ {
+ blockIdMeta = readNextUShort(packetData);
+ blockY = (ushort)readNextByte(packetData);
+ locationXZ = readNextByte(packetData);
+ }
+ else
+ {
+ locationXZ = readNextByte(packetData);
+ blockY = (ushort)readNextByte(packetData);
+ blockIdMeta = (ushort)readNextVarInt(packetData);
+ }
+
int blockX = locationXZ >> 4;
int blockZ = locationXZ & 0x0F;
- int blockY = (ushort)readNextByte(packetData);
- Block block = new Block((ushort)readNextVarInt(packetData));
+ Block block = new Block(blockIdMeta);
handler.GetWorld().SetBlock(new Location(chunkX, chunkZ, blockX, blockY, blockZ), block);
}
}
break;
case PacketIncomingType.BlockChange:
if (Settings.TerrainAndMovements)
- handler.GetWorld().SetBlock(Location.FromLong(readNextULong(packetData)), new Block((ushort)readNextVarInt(packetData)));
+ if (protocolversion < MC18Version)
+ {
+ int blockX = readNextInt(packetData);
+ int blockY = readNextByte(packetData);
+ int blockZ = readNextInt(packetData);
+ short blockId = (short)readNextVarInt(packetData);
+ byte blockMeta = readNextByte(packetData);
+ handler.GetWorld().SetBlock(new Location(blockX, blockY, blockZ), new Block(blockId, blockMeta));
+ }
+ else handler.GetWorld().SetBlock(Location.FromLong(readNextULong(packetData)), new Block((ushort)readNextVarInt(packetData)));
break;
case PacketIncomingType.MapChunkBulk:
if (protocolversion < MC19Version && Settings.TerrainAndMovements)
{
- bool hasSkyLight = readNextBool(packetData);
- int chunkCount = readNextVarInt(packetData);
+ int chunkCount;
+ bool hasSkyLight;
+ List chunkData = packetData;
+
+ //Read global fields
+ if (protocolversion < MC18Version)
+ {
+ chunkCount = readNextShort(packetData);
+ int compressedDataSize = readNextInt(packetData);
+ hasSkyLight = readNextBool(packetData);
+ byte[] compressed = readData(compressedDataSize, packetData);
+ byte[] decompressed = ZlibUtils.Decompress(compressed);
+ chunkData = new List(decompressed);
+ }
+ else
+ {
+ hasSkyLight = readNextBool(packetData);
+ chunkCount = readNextVarInt(packetData);
+ }
//Read chunk records
int[] chunkXs = new int[chunkCount];
int[] chunkZs = new int[chunkCount];
ushort[] chunkMasks = new ushort[chunkCount];
+ ushort[] addBitmaps = new ushort[chunkCount];
for (int chunkColumnNo = 0; chunkColumnNo < chunkCount; chunkColumnNo++)
{
chunkXs[chunkColumnNo] = readNextInt(packetData);
chunkZs[chunkColumnNo] = readNextInt(packetData);
chunkMasks[chunkColumnNo] = readNextUShort(packetData);
+ addBitmaps[chunkColumnNo] = protocolversion < MC18Version
+ ? readNextUShort(packetData)
+ : (ushort)0;
}
//Process chunk records
for (int chunkColumnNo = 0; chunkColumnNo < chunkCount; chunkColumnNo++)
- ProcessChunkColumnData(chunkXs[chunkColumnNo], chunkZs[chunkColumnNo], chunkMasks[chunkColumnNo], hasSkyLight, true, packetData);
+ ProcessChunkColumnData(chunkXs[chunkColumnNo], chunkZs[chunkColumnNo], chunkMasks[chunkColumnNo], addBitmaps[chunkColumnNo], hasSkyLight, true, chunkData);
}
break;
case PacketIncomingType.UnloadChunk:
@@ -597,11 +654,11 @@ namespace MinecraftClient.Protocol.Handlers
/// Chunk X location
/// Chunk Z location
/// Chunk mask for reading data
+ /// Chunk mask for some additional 1.7 metadata
/// Contains skylight info
/// Are the chunk continuous
/// Cache for reading chunk data
-
- private void ProcessChunkColumnData(int chunkX, int chunkZ, ushort chunkMask, bool hasSkyLight, bool chunksContinuous, List cache)
+ private void ProcessChunkColumnData(int chunkX, int chunkZ, ushort chunkMask, ushort chunkMask2, bool hasSkyLight, bool chunksContinuous, List cache)
{
if (protocolversion >= MC19Version)
{
@@ -686,13 +743,16 @@ namespace MinecraftClient.Protocol.Handlers
// Don't worry about skipping remaining data since there is no useful data afterwards in 1.9
// (plus, it would require parsing the tile entity lists' NBT)
}
- else
+ else if (protocolversion >= MC18Version)
{
- // Pre 1.9 chunk format
- if (chunksContinuous && chunkMask == 0) {
+ // 1.8 chunk format
+ if (chunksContinuous && chunkMask == 0)
+ {
//Unload the entire chunk column
handler.GetWorld()[chunkX, chunkZ] = null;
- } else {
+ }
+ else
+ {
//Load chunk data from the server
for (int chunkY = 0; chunkY < ChunkColumn.ColumnSize; chunkY++)
{
@@ -733,12 +793,70 @@ namespace MinecraftClient.Protocol.Handlers
readData(Chunk.SizeX * Chunk.SizeZ, cache);
}
}
+ else
+ {
+ // 1.7 chunk format
+ if (chunksContinuous && chunkMask == 0)
+ {
+ //Unload the entire chunk column
+ handler.GetWorld()[chunkX, chunkZ] = null;
+ }
+ else
+ {
+ //Count chunk sections
+ int sectionCount = 0;
+ int addDataSectionCount = 0;
+ for (int chunkY = 0; chunkY < ChunkColumn.ColumnSize; chunkY++)
+ {
+ if ((chunkMask & (1 << chunkY)) != 0)
+ sectionCount++;
+ if ((chunkMask2 & (1 << chunkY)) != 0)
+ addDataSectionCount++;
+ }
+
+ //Read chunk data, unpacking 4-bit values into 8-bit values for block metadata
+ Queue blockTypes = new Queue(readData(Chunk.SizeX * Chunk.SizeY * Chunk.SizeZ * sectionCount, cache));
+ Queue blockMeta = new Queue();
+ foreach (byte packed in readData((Chunk.SizeX * Chunk.SizeY * Chunk.SizeZ * sectionCount) / 2, cache))
+ {
+ byte hig = (byte)(packed >> 4);
+ byte low = (byte)(packed & (byte)0x0F);
+ blockMeta.Enqueue(hig);
+ blockMeta.Enqueue(low);
+ }
+
+ //Skip data we don't need
+ readData((Chunk.SizeX * Chunk.SizeY * Chunk.SizeZ * sectionCount) / 2, cache); //Block light
+ if (hasSkyLight)
+ readData((Chunk.SizeX * Chunk.SizeY * Chunk.SizeZ * sectionCount) / 2, cache); //Sky light
+ readData((Chunk.SizeX * Chunk.SizeY * Chunk.SizeZ * addDataSectionCount) / 2, cache); //BlockAdd
+ if (chunksContinuous)
+ readData(Chunk.SizeX * Chunk.SizeZ, cache); //Biomes
+
+ //Load chunk data
+ for (int chunkY = 0; chunkY < ChunkColumn.ColumnSize; chunkY++)
+ {
+ if ((chunkMask & (1 << chunkY)) != 0)
+ {
+ Chunk chunk = new Chunk();
+
+ for (int blockY = 0; blockY < Chunk.SizeY; blockY++)
+ for (int blockZ = 0; blockZ < Chunk.SizeZ; blockZ++)
+ for (int blockX = 0; blockX < Chunk.SizeX; blockX++)
+ chunk[blockX, blockY, blockZ] = new Block(blockTypes.Dequeue(), blockMeta.Dequeue());
+
+ if (handler.GetWorld()[chunkX, chunkZ] == null)
+ handler.GetWorld()[chunkX, chunkZ] = new ChunkColumn();
+ handler.GetWorld()[chunkX, chunkZ][chunkY] = chunk;
+ }
+ }
+ }
+ }
}
///
/// Start the updating thread. Should be called after login success.
///
-
private void StartUpdating()
{
netRead = new Thread(new ThreadStart(Updater));
@@ -749,7 +867,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Disconnect from the server, cancel network reading.
///
-
public void Dispose()
{
try
@@ -768,7 +885,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Amount of bytes to read
/// The data read from the network as an array
-
private byte[] readDataRAW(int offset)
{
if (offset > 0)
@@ -790,7 +906,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Amount of bytes to read
/// Cache of bytes to read from
/// The data read from the cache as an array
-
private static byte[] readData(int offset, List cache)
{
byte[] result = cache.Take(offset).ToArray();
@@ -803,7 +918,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Cache of bytes to read from
/// The string
-
private static string readNextString(List cache)
{
int length = readNextVarInt(cache);
@@ -818,7 +932,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Read a boolean from a cache of bytes and remove it from the cache
///
/// The boolean value
-
private static bool readNextBool(List cache)
{
return readNextByte(cache) != 0x00;
@@ -828,7 +941,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Read a short integer from a cache of bytes and remove it from the cache
///
/// The short integer value
-
private static short readNextShort(List cache)
{
byte[] rawValue = readData(2, cache);
@@ -840,7 +952,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Read an integer from a cache of bytes and remove it from the cache
///
/// The integer value
-
private static int readNextInt(List cache)
{
byte[] rawValue = readData(4, cache);
@@ -852,7 +963,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Read an unsigned short integer from a cache of bytes and remove it from the cache
///
/// The unsigned short integer value
-
private static ushort readNextUShort(List cache)
{
byte[] rawValue = readData(2, cache);
@@ -864,7 +974,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Read an unsigned long integer from a cache of bytes and remove it from the cache
///
/// The unsigned long integer value
-
private static ulong readNextULong(List cache)
{
byte[] rawValue = readData(8, cache);
@@ -876,7 +985,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Read several little endian unsigned short integers at once from a cache of bytes and remove them from the cache
///
/// The unsigned short integer value
-
private static ushort[] readNextUShortsLittleEndian(int amount, List cache)
{
byte[] rawValues = readData(2 * amount, cache);
@@ -891,7 +999,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Cache of bytes to read from
/// The uuid
-
private static Guid readNextUUID(List cache)
{
return new Guid(readData(16, cache));
@@ -902,7 +1009,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Cache of bytes to read from
/// The byte array
-
private byte[] readNextByteArray(List cache)
{
int len = protocolversion >= MC18Version
@@ -915,7 +1021,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Reads a length-prefixed array of unsigned long integers and removes it from the cache
///
/// The unsigned long integer values
-
private static ulong[] readNextULongArray(List cache)
{
int len = readNextVarInt(cache);
@@ -929,7 +1034,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Read a double from a cache of bytes and remove it from the cache
///
/// The double value
-
private static double readNextDouble(List cache)
{
byte[] rawValue = readData(8, cache);
@@ -941,7 +1045,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Read an integer from the network
///
/// The integer
-
private int readNextVarIntRAW()
{
int i = 0;
@@ -964,7 +1067,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Cache of bytes to read from
/// The integer
-
private static int readNextVarInt(List cache)
{
int i = 0;
@@ -987,7 +1089,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Cache of bytes to read from
/// The int
-
private static int readNextVarShort(List cache)
{
ushort low = readNextUShort(cache);
@@ -1004,7 +1105,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Read a single byte from a cache of bytes and remove it from the cache
///
/// The byte that was read
-
private static byte readNextByte(List cache)
{
byte result = cache[0];
@@ -1017,7 +1117,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Integer to encode
/// Byte array for this integer
-
private static byte[] getVarInt(int paramInt)
{
List bytes = new List();
@@ -1035,7 +1134,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Array to process
/// Array ready to send
-
private byte[] getDouble(double number)
{
byte[] theDouble = BitConverter.GetBytes(number);
@@ -1048,7 +1146,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Array to process
/// Array ready to send
-
private byte[] getArray(byte[] array)
{
if (protocolversion < MC18Version)
@@ -1065,7 +1162,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// String to process
/// Array ready to send
-
private byte[] getString(string text)
{
byte[] bytes = Encoding.UTF8.GetBytes(text);
@@ -1078,7 +1174,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Bytes to append
/// Array containing all the data
-
private static byte[] concatBytes(params byte[][] bytes)
{
List result = new List();
@@ -1092,7 +1187,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// String to parse
/// Int parsed
-
private static int atoi(string str)
{
return int.Parse(new string(str.Trim().TakeWhile(char.IsDigit).ToArray()));
@@ -1101,7 +1195,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Network reading method. Read bytes from the socket or encrypted socket.
///
-
private void Receive(byte[] buffer, int start, int offset, SocketFlags f)
{
int read = 0;
@@ -1120,7 +1213,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Discriminator to use.
/// packet Data
-
private void SendForgeHandshakePacket(FMLHandshakeDiscriminator discriminator, byte[] data)
{
SendPluginChannelPacket("FML|HS", concatBytes(new byte[] { (byte)discriminator }, data));
@@ -1131,7 +1223,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// packet ID
/// packet Data
-
private void SendPacket(int packetID, IEnumerable packetData)
{
//The inner packet
@@ -1160,7 +1251,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Send raw data to the server. Encryption will be handled automatically.
///
/// data to send
-
private void SendRAW(byte[] buffer)
{
if (encrypted)
@@ -1174,7 +1264,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Do the Minecraft login.
///
/// True if login successful
-
public bool Login()
{
byte[] protocol_version = getVarInt(protocolversion);
@@ -1261,7 +1350,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Start network encryption. Automatically called by Login() if the server requests encryption.
///
/// True if encryption was successful
-
private bool StartEncryption(string uuid, string sessionID, byte[] token, string serverIDhash, byte[] serverKey)
{
System.Security.Cryptography.RSACryptoServiceProvider RSAService = CryptoHandler.DecodeRSAPublicKey(serverKey);
@@ -1327,7 +1415,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Message
/// True if properly sent
-
public bool SendChatMessage(string message)
{
if (String.IsNullOrEmpty(message))
@@ -1349,7 +1436,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Message
/// True if properly sent
-
public bool SendRespawnPacket()
{
try
@@ -1365,7 +1451,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Client string describing the client
/// True if brand info was successfully sent
-
public bool SendBrandInfo(string brandInfo)
{
if (String.IsNullOrEmpty(brandInfo))
@@ -1380,7 +1465,6 @@ namespace MinecraftClient.Protocol.Handlers
/// The new location of the player
/// True if the player is on the ground
/// True if the location update was successfully sent
-
public bool SendLocationUpdate(Location location, bool onGround)
{
if (Settings.TerrainAndMovements)
@@ -1388,7 +1472,12 @@ namespace MinecraftClient.Protocol.Handlers
try
{
SendPacket(protocolversion >= MC19Version ? 0x0C : 0x04, concatBytes(
- getDouble(location.X), getDouble(location.Y), getDouble(location.Z),
+ getDouble(location.X),
+ getDouble(location.Y),
+ protocolversion < MC18Version
+ ? getDouble(location.Y + 1.62)
+ : new byte[0],
+ getDouble(location.Z),
new byte[] { onGround ? (byte)1 : (byte)0 }));
return true;
}
@@ -1402,7 +1491,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Channel to send packet on
/// packet Data
-
public bool SendPluginChannelPacket(string channel, byte[] data)
{
try
@@ -1430,7 +1518,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Disconnect from the server
///
-
public void Disconnect()
{
try
@@ -1448,7 +1535,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Text behind cursor
/// Completed text
-
IEnumerable IAutoComplete.AutoComplete(string BehindCursor)
{
if (String.IsNullOrEmpty(BehindCursor))
@@ -1480,7 +1566,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Ping a Minecraft server to get information about the server
///
/// True if ping was successful
-
public static bool doPing(string host, int port, ref int protocolversion, ref ForgeInfo forgeInfo)
{
string version = "";
diff --git a/MinecraftClient/Protocol/Handlers/ZlibUtils.cs b/MinecraftClient/Protocol/Handlers/ZlibUtils.cs
index 9232e57b..8265779d 100644
--- a/MinecraftClient/Protocol/Handlers/ZlibUtils.cs
+++ b/MinecraftClient/Protocol/Handlers/ZlibUtils.cs
@@ -12,7 +12,6 @@ namespace MinecraftClient.Protocol.Handlers
/// This library is open source and provided under the Microsoft Public License.
/// More info about DotNetZip at dotnetzip.codeplex.com.
///
-
public static class ZlibUtils
{
///
@@ -20,7 +19,6 @@ namespace MinecraftClient.Protocol.Handlers
///
/// Data to compress
/// Compressed data as a byte array
-
public static byte[] Compress(byte[] to_compress)
{
ZlibStream stream = new ZlibStream(new System.IO.MemoryStream(to_compress, false), CompressionMode.Compress);
@@ -42,7 +40,6 @@ namespace MinecraftClient.Protocol.Handlers
/// Data to decompress
/// Size of the data once decompressed
/// Decompressed data as a byte array
-
public static byte[] Decompress(byte[] to_decompress, int size_uncompressed)
{
ZlibStream stream = new ZlibStream(new System.IO.MemoryStream(to_decompress, false), CompressionMode.Decompress);
@@ -51,5 +48,23 @@ namespace MinecraftClient.Protocol.Handlers
stream.Close();
return packetData_decompressed;
}
+
+ ///
+ /// Decompress a byte array into another byte array of a potentially unlimited size (!)
+ ///
+ /// Data to decompress
+ /// Decompressed data as byte array
+ public static byte[] Decompress(byte[] to_decompress)
+ {
+ ZlibStream stream = new ZlibStream(new System.IO.MemoryStream(to_decompress, false), CompressionMode.Decompress);
+ byte[] buffer = new byte[16 * 1024];
+ using (System.IO.MemoryStream decompressedBuffer = new System.IO.MemoryStream())
+ {
+ int read;
+ while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
+ decompressedBuffer.Write(buffer, 0, read);
+ return decompressedBuffer.ToArray();
+ }
+ }
}
}