Use fastutil for viewable packets

Signed-off-by: TheMode <themode@outlook.fr>
This commit is contained in:
TheMode 2021-10-15 06:17:48 +02:00
parent ca6fbe4d09
commit 0bd519c894
2 changed files with 38 additions and 28 deletions

View File

@ -1152,20 +1152,19 @@ public class Entity implements Viewable, Tickable, TagHandler, PermissionHandler
final double distanceZ = Math.abs(position.z() - lastSyncedPosition.z());
final boolean positionChange = (distanceX + distanceY + distanceZ) > 0;
final Player player = this instanceof Player ? (Player) this : null;
final Chunk chunk = getChunk();
if (distanceX > 8 || distanceY > 8 || distanceZ > 8) {
PacketUtils.prepareViewablePacket(chunk, new EntityTeleportPacket(getEntityId(), position, isOnGround()), player);
PacketUtils.prepareViewablePacket(chunk, new EntityTeleportPacket(getEntityId(), position, isOnGround()), this);
} else if (positionChange && viewChange) {
PacketUtils.prepareViewablePacket(chunk, EntityPositionAndRotationPacket.getPacket(getEntityId(), position,
lastSyncedPosition, isOnGround()), player);
lastSyncedPosition, isOnGround()), this);
// Fix head rotation
PacketUtils.prepareViewablePacket(chunk, new EntityHeadLookPacket(getEntityId(), position.yaw()), player);
PacketUtils.prepareViewablePacket(chunk, new EntityHeadLookPacket(getEntityId(), position.yaw()), this);
} else if (positionChange) {
PacketUtils.prepareViewablePacket(chunk, EntityPositionPacket.getPacket(getEntityId(), position, lastSyncedPosition, onGround), player);
PacketUtils.prepareViewablePacket(chunk, EntityPositionPacket.getPacket(getEntityId(), position, lastSyncedPosition, onGround), this);
} else if (viewChange) {
PacketUtils.prepareViewablePacket(chunk, new EntityHeadLookPacket(getEntityId(), position.yaw()), player);
PacketUtils.prepareViewablePacket(chunk, new EntityRotationPacket(getEntityId(), position.yaw(), position.pitch(), onGround), player);
PacketUtils.prepareViewablePacket(chunk, new EntityHeadLookPacket(getEntityId(), position.yaw()), this);
PacketUtils.prepareViewablePacket(chunk, new EntityRotationPacket(getEntityId(), position.yaw(), position.pitch(), onGround), this);
}
this.lastAbsoluteSynchronizationTime = System.currentTimeMillis();
this.lastSyncedPosition = position;
@ -1193,8 +1192,9 @@ public class Entity implements Viewable, Tickable, TagHandler, PermissionHandler
/**
* Sets the X,Z coordinate of the passenger to the X,Z coordinate of this vehicle
* and sets the Y coordinate of the passenger to the Y coordinate of this vehicle + {@link #getPassengerHeightOffset()}
*
* @param newPosition The X,Y,Z position of this vehicle
* @param passenger The passenger to be moved
* @param passenger The passenger to be moved
*/
private void updatePassengerPosition(Point newPosition, Entity passenger) {
final Pos oldPassengerPos = passenger.position;
@ -1410,7 +1410,7 @@ public class Entity implements Viewable, Tickable, TagHandler, PermissionHandler
protected void synchronizePosition(boolean includeSelf) {
final Pos posCache = this.position;
final ServerPacket packet = new EntityTeleportPacket(getEntityId(), posCache, isOnGround());
PacketUtils.prepareViewablePacket(currentChunk, packet, this instanceof Player ? (Player) this : null);
PacketUtils.prepareViewablePacket(currentChunk, packet, this);
this.lastAbsoluteSynchronizationTime = System.currentTimeMillis();
this.lastSyncedPosition = posCache;
}

View File

@ -1,12 +1,16 @@
package net.minestom.server.utils;
import it.unimi.dsi.fastutil.ints.IntIntPair;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import it.unimi.dsi.fastutil.longs.LongList;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.audience.ForwardingAudience;
import net.minestom.server.MinecraftServer;
import net.minestom.server.Viewable;
import net.minestom.server.adventure.MinestomAdventure;
import net.minestom.server.adventure.audience.PacketGroupingAudience;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.Player;
import net.minestom.server.listener.manager.PacketListenerManager;
import net.minestom.server.network.packet.FramedPacket;
@ -26,7 +30,10 @@ import org.jetbrains.annotations.Nullable;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.WeakHashMap;
import java.util.function.Consumer;
import java.util.zip.Deflater;
@ -147,17 +154,17 @@ public final class PacketUtils {
@ApiStatus.Experimental
public static void prepareViewablePacket(@NotNull Viewable viewable, @NotNull ServerPacket serverPacket,
@Nullable Player player) {
if (player != null && !player.isAutoViewable()) {
@Nullable Entity entity) {
if (entity != null && !entity.isAutoViewable()) {
// Operation cannot be optimized
player.sendPacketToViewers(serverPacket);
entity.sendPacketToViewers(serverPacket);
return;
}
ViewableStorage viewableStorage;
synchronized (VIEWABLE_STORAGE_MAP) {
viewableStorage = VIEWABLE_STORAGE_MAP.computeIfAbsent(viewable, ViewableStorage::new);
}
viewableStorage.append(serverPacket, player != null ? player.getPlayerConnection() : null);
viewableStorage.append(serverPacket, entity instanceof Player ? (Player) entity : null);
}
@ApiStatus.Experimental
@ -234,7 +241,8 @@ public final class PacketUtils {
private static final class ViewableStorage {
private final WeakReference<Viewable> viewable;
private final Map<PlayerConnection, List<IntIntPair>> entityIdMap = new HashMap<>();
// Player id -> list of offsets to ignore (32:32 bits)
private final Int2ObjectMap<LongList> entityIdMap = new Int2ObjectOpenHashMap<>();
private final BinaryBuffer buffer = PooledBuffers.get();
private ViewableStorage(Viewable viewable) {
@ -242,20 +250,21 @@ public final class PacketUtils {
PooledBuffers.registerBuffer(this, buffer);
}
private synchronized void append(ServerPacket serverPacket, PlayerConnection connection) {
private synchronized void append(ServerPacket serverPacket, Player player) {
final ByteBuffer framedPacket = createFramedPacket(serverPacket).flip();
final int packetSize = framedPacket.limit();
if (packetSize >= buffer.capacity()) {
process(new SingleEntry(framedPacket, connection));
process(new SingleEntry(framedPacket, player));
return;
}
if (!buffer.canWrite(packetSize)) process(null);
final int start = buffer.writerOffset();
buffer.write(framedPacket);
final int end = buffer.writerOffset();
if (connection != null) {
List<IntIntPair> list = entityIdMap.computeIfAbsent(connection, con -> new ArrayList<>());
list.add(IntIntPair.of(start, end));
if (player != null) {
final long offsets = (long) start << 32 | end & 0xFFFFFFFFL;
LongList list = entityIdMap.computeIfAbsent(player.getEntityId(), id -> new LongArrayList());
list.add(offsets);
}
}
@ -274,15 +283,16 @@ public final class PacketUtils {
};
int lastWrite = 0;
final List<IntIntPair> pairs = entityIdMap.get(connection);
final LongList pairs = entityIdMap.get(player.getEntityId());
if (pairs != null) {
for (IntIntPair pair : pairs) {
final int start = pair.leftInt();
for (long offsets : pairs) {
final int start = (int) (offsets >> 32);
final int end = (int) offsets;
if (start != lastWrite) {
ByteBuffer slice = buffer.asByteBuffer(lastWrite, start - lastWrite);
writer.accept(slice);
}
lastWrite = pair.rightInt();
lastWrite = end;
}
}
// Write remaining
@ -293,7 +303,7 @@ public final class PacketUtils {
}
// Handle single entry
if (singleEntry != null && !Objects.equals(singleEntry.exception, connection)) {
if (singleEntry != null && !Objects.equals(singleEntry.exception, player)) {
writer.accept(singleEntry.buffer.position(0));
}
}
@ -307,9 +317,9 @@ public final class PacketUtils {
private static final class SingleEntry {
private final ByteBuffer buffer;
private final PlayerConnection exception;
private final Player exception;
public SingleEntry(ByteBuffer buffer, PlayerConnection exception) {
public SingleEntry(ByteBuffer buffer, Player exception) {
this.buffer = buffer;
this.exception = exception;
}