mirror of
https://github.com/Melledy/LunarCore.git
synced 2025-12-14 14:24:37 +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 kcp.highway.Ukcp;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import us.hebi.quickbuf.ProtoMessage;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class GameSession {
|
public class GameSession {
|
||||||
@@ -176,7 +177,7 @@ public class GameSession {
|
|||||||
// Log
|
// Log
|
||||||
if (LunarCore.getConfig().getLogOptions().packets) {
|
if (LunarCore.getConfig().getLogOptions().packets) {
|
||||||
if (!(LunarCore.getConfig().getLogOptions().filterLoopingPackets && CmdIdUtils.LOOP_PACKETS.contains(cmdId))) {
|
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();
|
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) {
|
public void logPacket(String sendOrRecv, int opcode, byte[] payload) {
|
||||||
LunarCore.getLogger().info(sendOrRecv + ": " + CmdIdUtils.getCmdIdName(opcode) + " (" + opcode + ")" + System.lineSeparator() + Utils.bytesToHex(payload));
|
LunarCore.getLogger().info(sendOrRecv + ": " + CmdIdUtils.getCmdIdName(opcode) + " (" + opcode + ")" + System.lineSeparator() + Utils.bytesToHex(payload));
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package emu.lunarcore.server.packet;
|
package emu.lunarcore.server.packet;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import emu.lunarcore.util.Utils;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import us.hebi.quickbuf.ProtoMessage;
|
import us.hebi.quickbuf.ProtoMessage;
|
||||||
|
import us.hebi.quickbuf.ProtoSink;
|
||||||
|
import us.hebi.quickbuf.ProtoSource;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class BasePacket {
|
public class BasePacket {
|
||||||
@@ -12,67 +14,119 @@ public class BasePacket {
|
|||||||
public static final int TAIL_CONST = 0xd7a152c8;
|
public static final int TAIL_CONST = 0xd7a152c8;
|
||||||
|
|
||||||
private int cmdId;
|
private int cmdId;
|
||||||
private byte[] data;
|
private ProtoMessage<?> data;
|
||||||
|
|
||||||
public BasePacket(int cmdId) {
|
public BasePacket(int cmdId) {
|
||||||
this.cmdId = cmdId;
|
this.cmdId = cmdId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BasePacket(int cmdId, byte[] data) {
|
|
||||||
this.cmdId = cmdId;
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCmdId(int cmdId) {
|
public void setCmdId(int cmdId) {
|
||||||
this.cmdId = cmdId;
|
this.cmdId = cmdId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setData(byte[] data) {
|
public void setData(byte[] data) {
|
||||||
this.data = data;
|
this.data = new RawProto(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setData(ProtoMessage<?> proto) {
|
public void setData(ProtoMessage<?> proto) {
|
||||||
this.data = proto.toByteArray();
|
this.data = proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] build() {
|
public byte[] build() {
|
||||||
if (getData() == null) {
|
// Setup
|
||||||
this.data = new byte[0];
|
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;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeUint16(ByteArrayOutputStream baos, int i) {
|
private void writeUint16(ProtoSink out, int i) throws Exception {
|
||||||
// Unsigned short
|
// Unsigned short
|
||||||
baos.write((byte) ((i >>> 8) & 0xFF));
|
out.writeRawByte((byte) ((i >>> 8) & 0xFF));
|
||||||
baos.write((byte) (i & 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)
|
// Unsigned int (long)
|
||||||
baos.write((byte) ((i >>> 24) & 0xFF));
|
out.writeRawByte((byte) ((i >>> 24) & 0xFF));
|
||||||
baos.write((byte) ((i >>> 16) & 0xFF));
|
out.writeRawByte((byte) ((i >>> 16) & 0xFF));
|
||||||
baos.write((byte) ((i >>> 8) & 0xFF));
|
out.writeRawByte((byte) ((i >>> 8) & 0xFF));
|
||||||
baos.write((byte) (i & 0xFF));
|
out.writeRawByte((byte) (i & 0xFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeBytes(ByteArrayOutputStream baos, byte[] bytes) {
|
/**
|
||||||
try {
|
* A byte array wrapped in a ProtoMessage object
|
||||||
baos.write(bytes);
|
*/
|
||||||
} catch (IOException e) {
|
@SuppressWarnings("rawtypes")
|
||||||
e.printStackTrace();
|
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 {
|
public class Utils {
|
||||||
private static final char[] HEX_ARRAY = "0123456789abcdef".toCharArray();
|
private static final char[] HEX_ARRAY = "0123456789abcdef".toCharArray();
|
||||||
|
|
||||||
public static final Object EMPTY_OBJECT = new Object();
|
public static final Object EMPTY_OBJECT = new Object();
|
||||||
public static final int[] EMPTY_ARRAY = new int[0];
|
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 final String EMPTY_STRING = "";
|
||||||
|
|
||||||
public static String bytesToHex(byte[] bytes) {
|
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];
|
char[] hexChars = new char[bytes.length * 2];
|
||||||
for (int j = 0; j < bytes.length; j++) {
|
for (int j = 0; j < bytes.length; j++) {
|
||||||
int v = bytes[j] & 0xFF;
|
int v = bytes[j] & 0xFF;
|
||||||
|
|||||||
Reference in New Issue
Block a user