From 06e4a1c8be8d9e8c7d495ef09faaa59b59ab4995 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 28 Oct 2024 15:47:55 +0000 Subject: [PATCH] Fixed packet errors in multiplayer and close a memory leak --- .../network/track/DataTrackerManager.java | 12 ++++-- .../network/track/MsgTrackedValues.java | 39 ++++++++++++++++--- .../network/track/TrackableDataType.java | 2 - .../util/serialization/PacketCodecUtils.java | 20 +++++----- 4 files changed, 51 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/network/track/DataTrackerManager.java b/src/main/java/com/minelittlepony/unicopia/network/track/DataTrackerManager.java index 6e94e424..cba80adc 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/track/DataTrackerManager.java +++ b/src/main/java/com/minelittlepony/unicopia/network/track/DataTrackerManager.java @@ -44,11 +44,13 @@ public class DataTrackerManager { packetEmitters.add((sender, initial) -> { var update = initial ? tracker.getInitialPairs(lookup) : tracker.getDirtyPairs(lookup); if (update.isPresent()) { - sender.accept(Channel.SERVER_TRACKED_ENTITY_DATA.toPacket(new MsgTrackedValues( + try (var payload = new MsgTrackedValues( entity.getId(), Optional.empty(), update - ))); + )) { + sender.accept(Channel.SERVER_TRACKED_ENTITY_DATA.toPacket(payload)); + } } }); return tracker; @@ -60,11 +62,13 @@ public class DataTrackerManager { packetEmitters.add((sender, initial) -> { var update = initial ? tracker.getInitialPairs(lookup) : tracker.getDirtyPairs(lookup); if (update.isPresent()) { - sender.accept(Channel.SERVER_TRACKED_ENTITY_DATA.toPacket(new MsgTrackedValues( + try (var payload = new MsgTrackedValues( entity.getId(), update, Optional.empty() - ))); + )) { + sender.accept(Channel.SERVER_TRACKED_ENTITY_DATA.toPacket(payload)); + } } }); return tracker; diff --git a/src/main/java/com/minelittlepony/unicopia/network/track/MsgTrackedValues.java b/src/main/java/com/minelittlepony/unicopia/network/track/MsgTrackedValues.java index a176756d..e5dabcee 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/track/MsgTrackedValues.java +++ b/src/main/java/com/minelittlepony/unicopia/network/track/MsgTrackedValues.java @@ -1,5 +1,6 @@ package com.minelittlepony.unicopia.network.track; +import java.io.Closeable; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -24,7 +25,7 @@ public record MsgTrackedValues( int owner, Optional updatedObjects, Optional updatedTrackers -) implements Handled { +) implements Handled, AutoCloseable { public static final PacketCodec PACKET_CODEC = PacketCodec.tuple( PacketCodecs.INTEGER, MsgTrackedValues::owner, PacketCodecs.optional(TrackerObjects.PACKET_CODEC), MsgTrackedValues::updatedObjects, @@ -34,22 +35,33 @@ public record MsgTrackedValues( @Override public void handle(PlayerEntity sender) { - Entity entity = sender.getWorld().getEntityById(owner); - if (entity instanceof Trackable trackable) { - trackable.getDataTrackers().load(this); + try (this) { + Entity entity = sender.getWorld().getEntityById(owner); + if (entity instanceof Trackable trackable) { + trackable.getDataTrackers().load(this); + } } } - public record TrackerObjects(int id, Set removedValues, Map values) { + public record TrackerObjects(int id, Set removedValues, Map values) implements Closeable { public static final PacketCodec PACKET_CODEC = PacketCodec.tuple( PacketCodecs.INTEGER, TrackerObjects::id, Uuids.PACKET_CODEC.collect(PacketCodecs.toCollection(HashSet::new)), TrackerObjects::removedValues, PacketCodecs.map(HashMap::new, Uuids.PACKET_CODEC, PacketCodecUtils.REGISTRY_BUFFER), TrackerObjects::values, TrackerObjects::new ); + + @Override + public void close() { + values.values().forEach(buf -> { + if (buf.refCnt() > 0) { + buf.release(); + } + }); + } } - public record TrackerEntries(int id, boolean wipe, List> values, Map objects) { + public record TrackerEntries(int id, boolean wipe, List> values, Map objects) implements Closeable { public static final PacketCodec PACKET_CODEC = PacketCodec.tuple( PacketCodecs.INTEGER, TrackerEntries::id, PacketCodecs.BOOL, TrackerEntries::wipe, @@ -57,5 +69,20 @@ public record MsgTrackedValues( PacketCodecs.map(HashMap::new, PacketCodecs.INTEGER, PacketCodecUtils.REGISTRY_BUFFER), TrackerEntries::objects, TrackerEntries::new ); + + @Override + public void close() { + objects.values().forEach(buf -> { + if (buf.refCnt() > 0) { + buf.release(); + } + }); + } + } + + @Override + public void close() { + updatedObjects.ifPresent(TrackerObjects::close); + updatedObjects.ifPresent(TrackerObjects::close); } } diff --git a/src/main/java/com/minelittlepony/unicopia/network/track/TrackableDataType.java b/src/main/java/com/minelittlepony/unicopia/network/track/TrackableDataType.java index f48947ef..7f08c698 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/track/TrackableDataType.java +++ b/src/main/java/com/minelittlepony/unicopia/network/track/TrackableDataType.java @@ -13,7 +13,6 @@ import java.util.concurrent.atomic.AtomicReference; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; import net.minecraft.network.RegistryByteBuf; import net.minecraft.network.codec.PacketCodec; import net.minecraft.network.codec.PacketCodecs; @@ -36,7 +35,6 @@ public record TrackableDataType(int id, PacketCodec UUID = of(Identifier.of("uuid"), Uuids.PACKET_CODEC); public static final TrackableDataType NBT = of(Identifier.of("nbt"), PacketCodecs.NBT_COMPOUND); public static final TrackableDataType COMPRESSED_NBT = of(Identifier.of("compressed_nbt"), PacketCodecs.NBT_COMPOUND); - public static final TrackableDataType> RAW_BYTES = of(Identifier.of("raw_bytes"), PacketCodecUtils.OPTIONAL_BUFFER); public static final TrackableDataType> OPTIONAL_POS = of(Identifier.of("optional_pos"), PacketCodecUtils.OPTIONAL_POS); public static final TrackableDataType> OPTIONAL_VECTOR = of(Identifier.of("optional_vector"), PacketCodecUtils.OPTIONAL_VECTOR); diff --git a/src/main/java/com/minelittlepony/unicopia/util/serialization/PacketCodecUtils.java b/src/main/java/com/minelittlepony/unicopia/util/serialization/PacketCodecUtils.java index 0832e68a..ed88e7f4 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/serialization/PacketCodecUtils.java +++ b/src/main/java/com/minelittlepony/unicopia/util/serialization/PacketCodecUtils.java @@ -9,6 +9,7 @@ import java.util.function.Function; import java.util.function.IntFunction; import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import net.minecraft.network.PacketByteBuf; import net.minecraft.network.RegistryByteBuf; import net.minecraft.network.codec.PacketCodec; @@ -20,17 +21,16 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; public interface PacketCodecUtils { - PacketCodec BUFFER = PacketCodec.of((bytes, buffer) -> { - buffer.writeInt(bytes.writerIndex()); - buffer.writeBytes(bytes); - }, buffer -> new PacketByteBuf(buffer.readBytes(buffer.readInt()))); - PacketCodec> OPTIONAL_BUFFER = PacketCodecs.optional(BUFFER); - PacketCodec REGISTRY_BUFFER = PacketCodec.of((bytes, buffer) -> { - buffer.writeInt(bytes.writerIndex()); - buffer.writeBytes(bytes); - }, buffer -> new RegistryByteBuf(buffer.readBytes(buffer.readInt()), buffer.getRegistryManager())); - PacketCodec> OPTIONAL_REGISTRY_BUFFER = PacketCodecs.optional(REGISTRY_BUFFER); + int length = bytes.readableBytes(); + buffer.writeInt(length); + if (length > 0) { + buffer.writeBytes(bytes, 0, length); + } + }, buffer -> { + int length = buffer.readInt(); + return new RegistryByteBuf(length > 0 ? buffer.readBytes(length) : Unpooled.EMPTY_BUFFER, buffer.getRegistryManager()); + }); PacketCodec> REGISTRY_KEY = PacketCodec.tuple( Identifier.PACKET_CODEC, RegistryKey::getRegistry,