RECENT NEWS
📢 𝟑𝟎% Discount for all ads only this month ❄️

RS LZMA Compression

Secret Agent
power_settings_new
Seen 11 months ago
Mithril Warrior (20/30)
Mithril Warrior
0
0
0
20 Posts
Posts
0
Warning level
0
Likes
0
Dislikes
Joined: 2022-04-24

*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_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.

Quote Originally Posted by Sir Tom View Post
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>
00
  • Like
Reactions: