Skip to content

Commit

Permalink
Support @bridge 包分割
Browse files Browse the repository at this point in the history
  • Loading branch information
trychen committed Sep 12, 2020
1 parent af3e4f7 commit 6e44ab9
Show file tree
Hide file tree
Showing 3 changed files with 199 additions and 8 deletions.
197 changes: 189 additions & 8 deletions src/main/java/cn/mccraft/pangu/core/network/BridgeHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

public interface BridgeHandler {
Map<String, Solution> SOLUTIONS = new HashMap<>();
Expand Down Expand Up @@ -86,6 +88,9 @@ static void registerMessages(AnnotationStream<Bridge> stream) {
static void registerPacket() {
PanguCore.getNetwork().registerMessage(PacketHandler.INSTANCE, Packet.class, Network.BRIDGE_SERVER_MESSAGE, Side.SERVER);
PanguCore.getNetwork().registerMessage(PacketHandler.INSTANCE, Packet.class, Network.BRIDGE_CLIENT_MESSAGE, Side.CLIENT);

PanguCore.getNetwork().registerMessage(MultiPartPacketHandler.INSTANCE, MultiPartPacket.class, Network.BRIDGE_SERVER_MULTIPART_MESSAGE, Side.SERVER);
PanguCore.getNetwork().registerMessage(MultiPartPacketHandler.INSTANCE, MultiPartPacket.class, Network.BRIDGE_CLIENT_MULTIPART_MESSAGE, Side.CLIENT);
}

@AllArgsConstructor
Expand All @@ -112,6 +117,10 @@ public IMessage onMessage(Packet message, MessageContext ctx) {
}

IThreadListener side = Threads.side(solution.side());
if (side == null) {
PanguCore.getLogger().error("Not a valid side for @Bridge message " + message.getKey());
return null;
}
side.addScheduledTask(() -> {
try {
solution.solve(solution.side().isServer() ? ctx.getServerHandler().player : Games.player(), message.getBytes());
Expand Down Expand Up @@ -192,15 +201,32 @@ public void solve(Object[] objects) throws IOException {

// 序列化
byte[] bytes = getPersistence().serialize(getActualParameterNames(), actualParameters, actualParameterTypes, persistenceByParameterOrder);
Packet packet = new Packet(bridge.value(), bytes);
// 发包
if (side().isClient()) {
if (isWithEntityPlayerParameter())
PanguCore.getNetwork().sendTo(packet, (EntityPlayerMP) objects[0]);
else
PanguCore.getNetwork().sendToAll(packet);

if (bytes.length > 30000) {
MultiPartPacketBuffer buffer = new MultiPartPacketBuffer(bridge.value(), bytes);

for (MultiPartPacket packet : buffer.getPackets()) {
if (side().isClient()) {
if (isWithEntityPlayerParameter())
PanguCore.getNetwork().sendTo(packet, (EntityPlayerMP) objects[0]);
else
PanguCore.getNetwork().sendToAll(packet);
} else {
PanguCore.getNetwork().sendToServer(packet);
}
}
} else {
PanguCore.getNetwork().sendToServer(packet);
IMessage packet = new Packet(bridge.value(), bytes);

// 发包
if (side().isClient()) {
if (isWithEntityPlayerParameter())
PanguCore.getNetwork().sendTo(packet, (EntityPlayerMP) objects[0]);
else
PanguCore.getNetwork().sendToAll(packet);
} else {
PanguCore.getNetwork().sendToServer(packet);
}
}
}

Expand Down Expand Up @@ -247,4 +273,159 @@ public void toBytes(ByteBuf buf) {
buf.writeBytes(bytes);
}
}

@NoArgsConstructor
@AllArgsConstructor
@Data
class MultiPartPacket implements IMessage {
/**
* Unique id for every packet
*/
private UUID uuid;

/**
* Total packet size
*/
private short total;

/**
* Current packet index
*/
private short current;

private String key;
private byte[] bytes;

@Override
public void fromBytes(ByteBuf buf) {
this.uuid = new UUID(buf.readLong(), buf.readLong());

this.total = buf.readShort();
this.current = buf.readShort();

byte[] utf8Bytes = new byte[ByteBufUtils.readVarInt(buf, 4)];
buf.readBytes(utf8Bytes);
this.key = new String(utf8Bytes, StandardCharsets.UTF_8);

this.bytes = new byte[ByteBufUtils.readVarInt(buf, 4)];
buf.readBytes(bytes);
}

@Override
public void toBytes(ByteBuf buf) {
buf.writeLong(uuid.getMostSignificantBits());
buf.writeLong(uuid.getLeastSignificantBits());

buf.writeShort(total);
buf.writeShort(current);

byte[] utf8Bytes = key.getBytes(StandardCharsets.UTF_8);
ByteBufUtils.writeVarInt(buf, utf8Bytes.length, 4);
buf.writeBytes(utf8Bytes);

ByteBufUtils.writeVarInt(buf, bytes.length, 4);
buf.writeBytes(bytes);
}
}

@NoArgsConstructor
@AllArgsConstructor
@Data
class MultiPartPacketBuffer {
private MultiPartPacket[] packets;
private int size;

public MultiPartPacketBuffer(String key, byte[] bytes) {
short total = (short) ((bytes.length / 30000) + (bytes.length % 30000 > 0 ? 1 : 0));

UUID id = UUID.randomUUID();
packets = new MultiPartPacket[total];

for (short i = 0; i < total; i++) {
MultiPartPacket packet = new MultiPartPacket();

packet.setUuid(id);
packet.setCurrent(i);
packet.setTotal(total);
packet.setKey(key);
packet.setBytes(
ArrayUtils.subarray(bytes, i * 30000, Math.min(bytes.length, (i + 1) * 30000))
);

packets[i] = packet;
}
}

public MultiPartPacketBuffer(MultiPartPacket packet) {
packets = new MultiPartPacket[packet.total];
process(packet);
}

public void process(MultiPartPacket packet) {
packets[packet.getCurrent()] = packet;
size += packet.getBytes().length;
}

public boolean isComplete() {
for (MultiPartPacket packet : packets) {
if (packet == null) return false;
}
return true;
}

public byte[] getBytes() {
byte[] bytes = new byte[size];
int cursor = 0;
for (MultiPartPacket packet : packets) {
System.arraycopy(packet.bytes, 0, bytes, cursor, cursor + packet.getBytes().length);
cursor += packet.getBytes().length;
}
return bytes;
}
}

Map<UUID, MultiPartPacketBuffer> MULTI_PART_PACKET_BUFFER = new ConcurrentHashMap<>();

@AllArgsConstructor
enum MultiPartPacketHandler implements IMessageHandler<MultiPartPacket, IMessage> {
INSTANCE;

@Override
public IMessage onMessage(MultiPartPacket message, MessageContext ctx) {
Solution solution = SOLUTIONS.get(message.getKey());

// 空检测
if (solution == null) {
PanguCore.getLogger().error("Couldn't find any solution to handle @Bridge message: " + message.getKey());
return null;
}

MultiPartPacketBuffer buffer = MULTI_PART_PACKET_BUFFER.computeIfAbsent(message.getUuid(), it -> new MultiPartPacketBuffer(message));

if (!buffer.isComplete()) return null;

if (!solution.isSync()) {
try {
solution.solve(solution.side().isServer() ? ctx.getServerHandler().player : Games.player(), buffer.getBytes());
} catch (Throwable e) {
PanguCore.getLogger().error("Unable to handle @Bridge for " + message.getKey(), e);
}
return null;
}

IThreadListener side = Threads.side(solution.side());
if (side == null) {
PanguCore.getLogger().error("Not a valid side for @Bridge message " + message.getKey());
return null;
}
side.addScheduledTask(() -> {
try {
solution.solve(solution.side().isServer() ? ctx.getServerHandler().player : Games.player(), buffer.getBytes());
} catch (Throwable e) {
PanguCore.getLogger().error("Unable to handle @Bridge for " + message.getKey(), e);
}
});
return null;
}
}
}
2 changes: 2 additions & 0 deletions src/main/java/cn/mccraft/pangu/core/network/Network.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
public interface Network {
int BRIDGE_SERVER_MESSAGE = 0;
int BRIDGE_CLIENT_MESSAGE = 1;
int BRIDGE_SERVER_MULTIPART_MESSAGE = 2;
int BRIDGE_CLIENT_MULTIPART_MESSAGE = 3;

static SimpleNetworkWrapper getNetworkWrapper(Class<?> clazz) {
// finding mod instance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,12 @@ default void refresh() {
default boolean free() {
return false;
}

default int getWidth() {
return 0;
}

default int getHeight() {
return 0;
}
}

0 comments on commit 6e44ab9

Please sign in to comment.