Fix obvious packet corruption

This commit is contained in:
TheMode 2021-08-25 13:54:09 +02:00
parent 5e18f48a1b
commit e185bca468
1 changed files with 19 additions and 35 deletions

View File

@ -235,30 +235,28 @@ public final class PacketUtils {
private static final Map<Viewable, ViewableStorage> VIEWABLE_STORAGE_MAP = new ConcurrentHashMap<>(); private static final Map<Viewable, ViewableStorage> VIEWABLE_STORAGE_MAP = new ConcurrentHashMap<>();
private static class ViewableStorage { private static final class ViewableStorage {
private final Viewable viewable; private final Viewable viewable;
private final Entry entry = new ViewableStorage.Entry(); private final Map<PlayerConnection, List<IntIntPair>> entityIdMap = new HashMap<>();
private final BinaryBuffer buffer = BinaryBuffer.ofSize(Server.SOCKET_BUFFER_SIZE);
private ViewableStorage(Viewable viewable) { private ViewableStorage(Viewable viewable) {
this.viewable = viewable; this.viewable = viewable;
} }
private synchronized void append(PlayerConnection playerConnection, ServerPacket serverPacket) { private synchronized void append(PlayerConnection playerConnection, ServerPacket serverPacket) {
BinaryBuffer buffer = entry.buffer;
final ByteBuffer framedPacket = createFramedPacket(serverPacket).flip(); final ByteBuffer framedPacket = createFramedPacket(serverPacket).flip();
if (!buffer.canWrite(framedPacket.limit())) process(); if (!buffer.canWrite(framedPacket.limit())) process();
final int start = buffer.writerOffset(); final int start = buffer.writerOffset();
buffer.write(framedPacket); this.buffer.write(framedPacket);
final int end = buffer.writerOffset(); final int end = buffer.writerOffset();
if (playerConnection != null) { if (playerConnection != null) {
List<IntIntPair> list = entry.entityIdMap.computeIfAbsent(playerConnection, playerConnection1 -> new ArrayList<>()); List<IntIntPair> list = entityIdMap.computeIfAbsent(playerConnection, con -> new ArrayList<>());
list.add(IntIntPair.of(start, end)); list.add(IntIntPair.of(start, end));
} }
} }
private synchronized void process() { private synchronized void process() {
BinaryBuffer buffer = entry.buffer;
final Set<Player> viewers = viewable.getViewers(); final Set<Player> viewers = viewable.getViewers();
if (viewers.isEmpty()) return; if (viewers.isEmpty()) return;
for (Player player : viewers) { for (Player player : viewers) {
@ -269,44 +267,30 @@ public final class PacketUtils {
// TODO for non-socket connection // TODO for non-socket connection
}; };
final List<IntIntPair> pairs = entry.entityIdMap.get(connection); int lastWrite = 0;
if (pairs != null) { final List<IntIntPair> pairs = entityIdMap.get(connection);
// Player should not be sent at least one packet, ignore ranges if (pairs != null && !pairs.isEmpty()) {
int lastWrite = 0;
for (IntIntPair pair : pairs) { for (IntIntPair pair : pairs) {
final int start = pair.leftInt(); final int start = pair.leftInt();
if (start > lastWrite) { if (start != lastWrite) {
ByteBuffer slice = buffer.asByteBuffer(lastWrite, start); ByteBuffer slice = buffer.asByteBuffer(lastWrite, start);
slice.position(slice.limit()); slice.position(slice.limit());
writer.accept(slice); writer.accept(slice);
} }
lastWrite = pair.rightInt(); lastWrite = pair.rightInt();
} }
// Write remaining }
final int remaining = buffer.writerOffset() - lastWrite; // Write remaining
if (remaining > 0) { final int remaining = buffer.writerOffset() - lastWrite;
ByteBuffer remainSlice = buffer.asByteBuffer(lastWrite, remaining); if (remaining > 0) {
remainSlice.position(remaining); ByteBuffer remainSlice = buffer.asByteBuffer(lastWrite, remaining);
writer.accept(remainSlice); remainSlice.position(remainSlice.limit());
} writer.accept(remainSlice);
} else {
// Send full buffer
ByteBuffer result = buffer.asByteBuffer(0, buffer.writerOffset());
result.position(result.limit());
writer.accept(result);
} }
} }
this.entry.reset(); // Clear state
} this.entityIdMap.clear();
this.buffer.clear();
private static class Entry {
private final Map<PlayerConnection, List<IntIntPair>> entityIdMap = new ConcurrentHashMap<>();
private final BinaryBuffer buffer = BinaryBuffer.ofSize(Server.SOCKET_BUFFER_SIZE);
void reset() {
this.entityIdMap.clear();
this.buffer.clear();
}
} }
} }