*Might be an informative thread, can move if needed mods*
Jagex added a new compression method to their RuneScape client called LZMA.
Code:
UNCOMPRESSED = new Compression("UNCOMPRESSED", 0);
BZIP2 = new Compression("BZIP2", 1);
GZIP = new Compression("GZIP", 2);
LZMA = new Compression("LZMA", 3);
here is a decompressor i wrote if you want to add to your server.
Code:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import SevenZip.Compression.LZMA.Decoder;
/**
* @author _jordan <[email protected]>
*/
public final class LZMADecompressor {
/**
* Starts the decompression for LZMA.
*
* @param buffer The buffer.
* @param length The compression length.
*/
public static void decompressLZMA(InputStream buffer, int length) {
try {
ByteArrayInputStream input = new ByteArrayInputStream(buffer.getBuffer());
input.skip(buffer.getOffset());
decompress(input, length);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Decompresses data with the LZMA algorithm.
*
* @param input The created input stream wrapped around the initial buffer.
* @param length The compression length.
* @throws IOException
*/
private static void decompress(ByteArrayInputStream input, int length) throws IOException {
Decoder decoder = new Decoder();
byte[] properties = new byte[5];
if (input.read(properties, 0, 5) != 5) {
throw new IOException("LZMA: Bad input.");
}
ByteArrayOutputStream output = new ByteArrayOutputStream(length);
synchronized (decoder) {
if (!decoder.SetDecoderProperties(properties)) {
throw new IOException("LZMA: Bad properties.");
}
decoder.Code(input, output, length);
}
}
}
this library was ported over from another language so be prepared for that, here's a used method as example
Code:
public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream, long outSize) throws IOException {
m_RangeDecoder.SetStream(inStream);
m_OutWindow.SetStream(outStream);
Init();
int state = Base.StateInit();
int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
long nowPos64 = 0;
byte prevByte = 0;
while (outSize < 0 || nowPos64 < outSize) {
int posState = (int) nowPos64 & m_PosStateMask;
if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) {
LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int) nowPos64, prevByte);
if (!Base.StateIsCharState(state))
prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0));
else
prevByte = decoder2.DecodeNormal(m_RangeDecoder);
m_OutWindow.PutByte(prevByte);
state = Base.StateUpdateChar(state);
nowPos64++;
} else {
int len;
if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1) {
len = 0;
if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0) {
if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) {
state = Base.StateUpdateShortRep(state);
len = 1;
}
} else {
int distance;
if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0)
distance = rep1;
else {
if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0)
distance = rep2;
else {
distance = rep3;
rep3 = rep2;
}
rep2 = rep1;
}
rep1 = rep0;
rep0 = distance;
}
if (len == 0) {
len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;
state = Base.StateUpdateRep(state);
}
} else {
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);
state = Base.StateUpdateMatch(state);
int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);
if (posSlot >= Base.kStartPosModelIndex) {
int numDirectBits = (posSlot >> 1) - 1;
rep0 = ((2 | (posSlot & 1)) << numDirectBits);
if (posSlot < Base.kEndPosModelIndex)
rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);
else {
rep0 += (m_RangeDecoder.DecodeDirectBits(numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits);
rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
if (rep0 < 0) {
if (rep0 == -1)
break;
return false;
}
}
} else
rep0 = posSlot;
}
if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) {
// m_OutWindow.Flush();
return false;
}
m_OutWindow.CopyBlock(rep0, len);
nowPos64 += len;
prevByte = m_OutWindow.GetByte(0);
}
}
m_OutWindow.Flush();
m_OutWindow.ReleaseStream();
m_RangeDecoder.ReleaseStream();
return true;
}
Code:
case Constants.LZMA_COMPRESSION:
length = stream.readInt();
if (length <= 0) {
data = null;
break;
}
checkRevision(compressedLength, archive, stream.getOffset());
LZMADecompressor.decompressLZMA(stream, compressedLength);
break;
uses dragonkk's library.
also download this library and add to your build path
https://mega.nz/#!wt90GBCI!gu_HDuf98...nNulS9rJz_M0Ns
if you prefer maven, here is a repo i found, not sure if it works though
Code:
<dependency>
<groupId>com.github.jponge</groupId>
<artifactId>lzma-java</artifactId>
<version>1.3</version>
</dependency>
im releasing because i can share information that i find/write. plus only people that i know of have this added for the new revisions are Cjay and I.
Originally Posted by
Sir Tom
From what I understand jponge is no longer supported, but there is XZ for Java which can be found here
http://tukaani.org/xz/java.html
You can find it on maven central
Code:
<dependency>
<groupId>org.tukaani</groupId>
<artifactId>xz</artifactId>
<version>1.6</version>
</dependency>