mirror of
https://github.com/Melledy/LunarCore.git
synced 2025-12-14 06:14:45 +01:00
Optimize BasePacket to directly write to the proto sink
This commit is contained in:
@@ -16,6 +16,7 @@ import it.unimi.dsi.fastutil.ints.Int2LongOpenHashMap;
|
||||
import kcp.highway.Ukcp;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import us.hebi.quickbuf.ProtoMessage;
|
||||
|
||||
@Getter
|
||||
public class GameSession {
|
||||
@@ -176,7 +177,7 @@ public class GameSession {
|
||||
// Log
|
||||
if (LunarCore.getConfig().getLogOptions().packets) {
|
||||
if (!(LunarCore.getConfig().getLogOptions().filterLoopingPackets && CmdIdUtils.LOOP_PACKETS.contains(cmdId))) {
|
||||
logPacket("RECV", cmdId, null);
|
||||
logPacket("RECV", cmdId, Utils.EMPTY_BYTE_ARRAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,6 +190,10 @@ public class GameSession {
|
||||
buf.release();
|
||||
}
|
||||
}
|
||||
|
||||
public void logPacket(String sendOrRecv, int opcode, ProtoMessage<?> payload) {
|
||||
logPacket(sendOrRecv, opcode, payload != null ? payload.toByteArray() : Utils.EMPTY_BYTE_ARRAY);
|
||||
}
|
||||
|
||||
public void logPacket(String sendOrRecv, int opcode, byte[] payload) {
|
||||
LunarCore.getLogger().info(sendOrRecv + ": " + CmdIdUtils.getCmdIdName(opcode) + " (" + opcode + ")" + System.lineSeparator() + Utils.bytesToHex(payload));
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package emu.lunarcore.server.packet;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import emu.lunarcore.util.Utils;
|
||||
import lombok.Getter;
|
||||
import us.hebi.quickbuf.ProtoMessage;
|
||||
import us.hebi.quickbuf.ProtoSink;
|
||||
import us.hebi.quickbuf.ProtoSource;
|
||||
|
||||
@Getter
|
||||
public class BasePacket {
|
||||
@@ -12,67 +14,119 @@ public class BasePacket {
|
||||
public static final int TAIL_CONST = 0xd7a152c8;
|
||||
|
||||
private int cmdId;
|
||||
private byte[] data;
|
||||
private ProtoMessage<?> data;
|
||||
|
||||
public BasePacket(int cmdId) {
|
||||
this.cmdId = cmdId;
|
||||
}
|
||||
|
||||
public BasePacket(int cmdId, byte[] data) {
|
||||
this.cmdId = cmdId;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void setCmdId(int cmdId) {
|
||||
this.cmdId = cmdId;
|
||||
}
|
||||
|
||||
|
||||
public void setData(byte[] data) {
|
||||
this.data = data;
|
||||
this.data = new RawProto(data);
|
||||
}
|
||||
|
||||
public void setData(ProtoMessage<?> proto) {
|
||||
this.data = proto.toByteArray();
|
||||
this.data = proto;
|
||||
}
|
||||
|
||||
public byte[] build() {
|
||||
if (getData() == null) {
|
||||
this.data = new byte[0];
|
||||
// Setup
|
||||
int protoSize = 0;
|
||||
|
||||
// Set proto message size
|
||||
if (this.data != null) {
|
||||
protoSize = this.data.getSerializedSize();
|
||||
}
|
||||
|
||||
// Create proto sink
|
||||
byte[] packet = new byte[16 + protoSize];
|
||||
ProtoSink output = ProtoSink.newInstance(packet, 0, packet.length);
|
||||
|
||||
try {
|
||||
// Write packet header
|
||||
this.writeUint32(output, HEADER_CONST);
|
||||
this.writeUint16(output, cmdId);
|
||||
this.writeUint16(output, 0);
|
||||
this.writeUint32(output, protoSize);
|
||||
|
||||
// Write protobuf message
|
||||
if (this.data != null) {
|
||||
this.data.writeTo(output);
|
||||
}
|
||||
|
||||
// Write packet footer
|
||||
this.writeUint32(output, TAIL_CONST);
|
||||
} catch (Exception e) {
|
||||
// Should never happen
|
||||
}
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(4 + 2 + 4 + getData().length + 4);
|
||||
|
||||
this.writeUint32(baos, HEADER_CONST);
|
||||
this.writeUint16(baos, cmdId);
|
||||
this.writeUint16(baos, 0); // Empty header
|
||||
this.writeUint32(baos, data.length);
|
||||
this.writeBytes(baos, data);
|
||||
this.writeUint32(baos, TAIL_CONST);
|
||||
|
||||
byte[] packet = baos.toByteArray();
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
private void writeUint16(ByteArrayOutputStream baos, int i) {
|
||||
private void writeUint16(ProtoSink out, int i) throws Exception {
|
||||
// Unsigned short
|
||||
baos.write((byte) ((i >>> 8) & 0xFF));
|
||||
baos.write((byte) (i & 0xFF));
|
||||
out.writeRawByte((byte) ((i >>> 8) & 0xFF));
|
||||
out.writeRawByte((byte) (i & 0xFF));
|
||||
}
|
||||
|
||||
private void writeUint32(ByteArrayOutputStream baos, int i) {
|
||||
private void writeUint32(ProtoSink out, int i) throws Exception {
|
||||
// Unsigned int (long)
|
||||
baos.write((byte) ((i >>> 24) & 0xFF));
|
||||
baos.write((byte) ((i >>> 16) & 0xFF));
|
||||
baos.write((byte) ((i >>> 8) & 0xFF));
|
||||
baos.write((byte) (i & 0xFF));
|
||||
out.writeRawByte((byte) ((i >>> 24) & 0xFF));
|
||||
out.writeRawByte((byte) ((i >>> 16) & 0xFF));
|
||||
out.writeRawByte((byte) ((i >>> 8) & 0xFF));
|
||||
out.writeRawByte((byte) (i & 0xFF));
|
||||
}
|
||||
|
||||
private void writeBytes(ByteArrayOutputStream baos, byte[] bytes) {
|
||||
try {
|
||||
baos.write(bytes);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
/**
|
||||
* A byte array wrapped in a ProtoMessage object
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static class RawProto extends ProtoMessage {
|
||||
private byte[] data;
|
||||
|
||||
public RawProto(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtoMessage copyFrom(ProtoMessage other) {
|
||||
data = other.toByteArray();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtoMessage clear() {
|
||||
data = Utils.EMPTY_BYTE_ARRAY;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int computeSerializedSize() {
|
||||
return data.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(ProtoSink output) throws IOException {
|
||||
output.writeRawBytes(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtoMessage mergeFrom(ProtoSource input) throws IOException {
|
||||
return this; // Skip
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return false; // Skip
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtoMessage clone() {
|
||||
return null; // Skip
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,14 @@ import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class Utils {
|
||||
private static final char[] HEX_ARRAY = "0123456789abcdef".toCharArray();
|
||||
|
||||
|
||||
public static final Object EMPTY_OBJECT = new Object();
|
||||
public static final int[] EMPTY_ARRAY = new int[0];
|
||||
public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
|
||||
public static final String EMPTY_STRING = "";
|
||||
|
||||
public static String bytesToHex(byte[] bytes) {
|
||||
if (bytes == null) return "";
|
||||
if (bytes == null || bytes.length == 0) return EMPTY_STRING;
|
||||
char[] hexChars = new char[bytes.length * 2];
|
||||
for (int j = 0; j < bytes.length; j++) {
|
||||
int v = bytes[j] & 0xFF;
|
||||
|
||||
Reference in New Issue
Block a user