Quote fromSecret Agent on April 24, 2022, 3:56 pm
*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 <citellumrsps@gmail.com> */ 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_M0Nsif 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.
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.htmlYou can find it on maven central
Code:<dependency> <groupId>org.tukaani</groupId> <artifactId>xz</artifactId> <version>1.6</version> </dependency>
*Might be an informative thread, can move if needed mods*
Jagex added a new compression method to their RuneScape client called LZMA.
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.
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import SevenZip.Compression.LZMA.Decoder;
/**
* @author _jordan <citellumrsps@gmail.com>
*/
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
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;
}
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
<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.
You can find it on maven central
<dependency>
<groupId>org.tukaani</groupId>
<artifactId>xz</artifactId>
<version>1.6</version>
</dependency>