RuneHive-Game
Loading...
Searching...
No Matches
PacketBuilder.java
Go to the documentation of this file.
1package com.runehive.net.packet;
2
3import com.runehive.net.codec.AccessType;
4import com.runehive.net.codec.ByteModification;
5import com.runehive.net.codec.ByteOrder;
6import io.netty.buffer.ByteBuf;
7import io.netty.buffer.DefaultByteBufHolder;
8import io.netty.buffer.PooledByteBufAllocator;
9
10import static com.google.common.base.Preconditions.checkState;
11
12/**
13 * The implementation that functions as a dynamic buffer wrapper
14 * backed by a {@code ByteBuf} that is used for reading and writing data.
15 *
16 * @author lare96 <http://github.com/lare96>
17 * @author blakeman8192
18 */
19public final class PacketBuilder extends DefaultByteBufHolder {
20
21 private static final int[] BIT_MASK = new int[32];
22
23 static {
24 for (int i = 0; i < BIT_MASK.length; i++) {
25 BIT_MASK[i] = (1 << i) - 1;
26 }
27 }
28
29 private static final int DEFAULT_CAPACITY = 128;
30 private int bitPosition;
31
32 private PacketBuilder(ByteBuf buffer) {
33 super(buffer);
34 }
35
36 public static PacketBuilder alloc(int initialCapacity, int maxCapacity) {
37 return new PacketBuilder(PooledByteBufAllocator.DEFAULT.buffer(initialCapacity, maxCapacity));
38 }
39
40 public static PacketBuilder alloc(int capacity) {
41 return new PacketBuilder(PooledByteBufAllocator.DEFAULT.buffer(capacity));
42 }
43
44 public static PacketBuilder alloc() {
45 return alloc(DEFAULT_CAPACITY);
46 }
47 public static PacketBuilder wrap(ByteBuf buf) {
48 return new PacketBuilder(buf);
49 }
50
52 switch (type) {
53 case BIT:
54 bitPosition = content().writerIndex() * 8;
55 break;
56 case BYTE:
57 content().writerIndex((bitPosition + 7) / 8);
58 bitPosition = -1;
59 break;
60 }
61 return this;
62 }
63
64 public PacketBuilder writeByte(int value) {
66 return this;
67 }
68
69 public PacketBuilder writeByte(int value, ByteModification type) {
70 switch (type) {
71 case ADD:
72 value += 128;
73 break;
74 case NEG:
75 value = -value;
76 break;
77 case SUB:
78 value = 128 - value;
79 break;
80 case NONE:
81 break;
82 }
83 content().writeByte((byte) value);
84 return this;
85 }
86
87 public PacketBuilder writeBit(boolean flag) {
88 writeBits(1, flag ? 1 : 0);
89 return this;
90 }
91
92 public PacketBuilder writeBits(int amount, int value) {
93 checkState(amount >= 1 && amount <= 32, "Number of bits must be between 1 and 32 inclusive.");
94
95 int bytePos = bitPosition >> 3;
96 int bitOffset = 8 - (bitPosition & 7);
97 bitPosition = bitPosition + amount;
98 int requiredSpace = bytePos - content().writerIndex() + 1;
99 requiredSpace += (amount + 7) / 8;
100 if (content().writableBytes() < requiredSpace) {
101 content().capacity(content().capacity() + requiredSpace);
102 }
103 for (; amount > bitOffset; bitOffset = 8) {
104 byte tmp = content().getByte(bytePos);
105 tmp &= ~BIT_MASK[bitOffset];
106 tmp |= (value >> (amount - bitOffset)) & BIT_MASK[bitOffset];
107 content().setByte(bytePos++, tmp);
108 amount -= bitOffset;
109 }
110 if (amount == bitOffset) {
111 byte tmp = content().getByte(bytePos);
112 tmp &= ~BIT_MASK[bitOffset];
113 tmp |= value & BIT_MASK[bitOffset];
114 content().setByte(bytePos, tmp);
115 } else {
116 byte tmp = content().getByte(bytePos);
117 tmp &= ~(BIT_MASK[amount] << (bitOffset - amount));
118 tmp |= (value & BIT_MASK[amount]) << (bitOffset - amount);
119 content().setByte(bytePos, tmp);
120 }
121 return this;
122 }
123
124 public PacketBuilder writeBytes(byte[] from, int size) {
125 content().writeBytes(from, 0, size);
126 return this;
127 }
128
129 public PacketBuilder writeBytes(ByteBuf from) {
130 for (int i = 0; i < from.writerIndex(); i++) {
131 writeByte(from.getByte(i));
132 }
133 return this;
134 }
135
136 public PacketBuilder writeBytesReverse(byte[] data) {
137 for (int i = data.length - 1; i >= 0; i--) {
138 writeByte(data[i]);
139 }
140 return this;
141 }
142
143 public PacketBuilder writeInt(int value) {
145 return this;
146 }
147
148 public PacketBuilder writeInt(int value, ByteOrder order) {
149 writeInt(value, ByteModification.NONE, order);
150 return this;
151 }
152
153 public PacketBuilder writeInt(int value, ByteModification type) {
154 writeInt(value, type, ByteOrder.BE);
155 return this;
156 }
157
158 public PacketBuilder writeInt(int value, ByteModification type, ByteOrder order) {
159 switch (order) {
160 case BE:
161 writeByte(value >> 24);
162 writeByte(value >> 16);
163 writeByte(value >> 8);
164 writeByte(value, type);
165 break;
166 case ME:
167 writeByte(value >> 8);
168 writeByte(value, type);
169 writeByte(value >> 24);
170 writeByte(value >> 16);
171 break;
172 case IME:
173 writeByte(value >> 16);
174 writeByte(value >> 24);
175 writeByte(value, type);
176 writeByte(value >> 8);
177 break;
178 case LE:
179 writeByte(value, type);
180 writeByte(value >> 8);
181 writeByte(value >> 16);
182 writeByte(value >> 24);
183 break;
184 }
185 return this;
186 }
187
188 public PacketBuilder writeLong(long value) {
190 return this;
191 }
192
193 public PacketBuilder writeLong(long value, ByteOrder order) {
194 writeLong(value, ByteModification.NONE, order);
195 return this;
196 }
197
198 public PacketBuilder writeLong(long value, ByteModification type) {
199 writeLong(value, type, ByteOrder.BE);
200 return this;
201 }
202
203 public PacketBuilder writeLong(long value, ByteModification type, ByteOrder order) {
204 switch (order) {
205 case BE:
206 writeByte((int) (value >> 56));
207 writeByte((int) (value >> 48));
208 writeByte((int) (value >> 40));
209 writeByte((int) (value >> 32));
210 writeByte((int) (value >> 24));
211 writeByte((int) (value >> 16));
212 writeByte((int) (value >> 8));
213 writeByte((int) value, type);
214 break;
215
216 case ME:
217 throw new UnsupportedOperationException("Middle-endian long " + "is not implemented!");
218
219 case IME:
220 throw new UnsupportedOperationException("Inverse-middle-endian long is not implemented!");
221
222 case LE:
223 writeByte((int) value, type);
224 writeByte((int) (value >> 8));
225 writeByte((int) (value >> 16));
226 writeByte((int) (value >> 24));
227 writeByte((int) (value >> 32));
228 writeByte((int) (value >> 40));
229 writeByte((int) (value >> 48));
230 writeByte((int) (value >> 56));
231 break;
232
233 }
234 return this;
235 }
236
237 public PacketBuilder writeShort(int value) {
239 return this;
240 }
241
242 public PacketBuilder writeShort(int value, ByteOrder order) {
243 writeShort(value, ByteModification.NONE, order);
244 return this;
245 }
246
247 public PacketBuilder writeShort(int value, ByteModification type) {
248 writeShort(value, type, ByteOrder.BE);
249 return this;
250 }
251
252 public PacketBuilder writeShort(int value, ByteModification type, ByteOrder order) {
253 switch (order) {
254 case BE:
255 writeByte(value >> 8);
256 writeByte(value, type);
257 break;
258 case ME:
259 throw new IllegalArgumentException("Middle-endian short is " + "impossible!");
260 case IME:
261 throw new IllegalArgumentException("Inverse-middle-endian " + "short is impossible!");
262 case LE:
263 writeByte(value, type);
264 writeByte(value >> 8);
265 break;
266 default:
267 break;
268 }
269 return this;
270 }
271
272 public PacketBuilder writeString(String string) {
273 for (final byte value : string.getBytes()) {
274 writeByte(value);
275 }
276 writeByte(10);
277 return this;
278 }
279
280 public GamePacket toPacket(int opcode) {
281 return new GamePacket(opcode, PacketType.FIXED, content());
282 }
283
284 public GamePacket toPacket(int opcode, PacketType type) {
285 return new GamePacket(opcode, type, content());
286 }
287
288 public String getString() {
289 byte temp;
290 StringBuilder builder = new StringBuilder();
291 while (content().isReadable() && (temp = content().readByte()) != 10) {
292 builder.append((char) temp);
293 }
294 return builder.toString();
295 }
296
297 public PacketBuilder writeBuffer(ByteBuf buffer) {
298 this.content().writeBytes(buffer);
299 return this;
300 }
301
302 public PacketBuilder writeByteArray(byte[] bytes) {
303 content().writeBytes(bytes);
304 return this;
305 }
306
307 public PacketBuilder writeByteArray(byte[] bytes, int offset, int length) {
308 content().writeBytes(bytes, offset, length);
309 return this;
310 }
311}
Represents a single game packet.
static PacketBuilder wrap(ByteBuf buf)
PacketBuilder writeBytesReverse(byte[] data)
PacketBuilder writeBytes(byte[] from, int size)
PacketBuilder initializeAccess(AccessType type)
PacketBuilder writeInt(int value, ByteModification type, ByteOrder order)
PacketBuilder writeLong(long value)
PacketBuilder writeShort(int value, ByteModification type)
PacketBuilder writeInt(int value, ByteModification type)
PacketBuilder writeInt(int value, ByteOrder order)
PacketBuilder writeBit(boolean flag)
PacketBuilder writeLong(long value, ByteModification type, ByteOrder order)
PacketBuilder writeShort(int value, ByteOrder order)
PacketBuilder writeBytes(ByteBuf from)
PacketBuilder writeBits(int amount, int value)
PacketBuilder writeLong(long value, ByteOrder order)
PacketBuilder writeByteArray(byte[] bytes, int offset, int length)
PacketBuilder writeByteArray(byte[] bytes)
PacketBuilder writeByte(int value, ByteModification type)
static PacketBuilder alloc(int initialCapacity, int maxCapacity)
static PacketBuilder alloc(int capacity)
PacketBuilder writeShort(int value, ByteModification type, ByteOrder order)
GamePacket toPacket(int opcode, PacketType type)
PacketBuilder writeString(String string)
PacketBuilder writeLong(long value, ByteModification type)
PacketBuilder writeBuffer(ByteBuf buffer)
Represents the different forms data can be written in.
Represents RuneScape's custom value types.
Represents the order in which bytes are written.
Definition ByteOrder.java:8
BE
Represents Big-endian.
Represents a type of packet.
FIXED
A fixed size packet where the size never changes.