Per instance thread is now the default, added a configurable cooldown for player position refresh

This commit is contained in:
themode 2020-11-18 05:13:49 +01:00
parent 2405b7ae6f
commit 553a280993
5 changed files with 44 additions and 31 deletions

View File

@ -3,7 +3,7 @@ package net.minestom.server;
import net.minestom.server.entity.EntityManager;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.InstanceManager;
import net.minestom.server.thread.PerGroupChunkProvider;
import net.minestom.server.thread.PerInstanceThreadProvider;
import net.minestom.server.thread.ThreadProvider;
import net.minestom.server.utils.thread.MinestomThread;
import net.minestom.server.utils.validate.Check;
@ -33,7 +33,8 @@ public final class UpdateManager {
{
// DEFAULT THREAD PROVIDER
threadProvider = new PerGroupChunkProvider();
//threadProvider = new PerGroupChunkProvider();
threadProvider = new PerInstanceThreadProvider();
}
/**

View File

@ -31,7 +31,9 @@ import net.minestom.server.utils.callback.OptionalCallback;
import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.entity.EntityUtils;
import net.minestom.server.utils.player.PlayerUtils;
import net.minestom.server.utils.time.CooldownUtils;
import net.minestom.server.utils.time.TimeUnit;
import net.minestom.server.utils.time.UpdateOption;
import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -103,9 +105,9 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
private long lastUpdate;
private final EntityType entityType;
// Network synchronization
private static final long SYNCHRONIZATION_DELAY = 1500; // In ms
private long lastSynchronizationTime;
// Network synchronization, send the absolute position of the entity each X milliseconds
private static final UpdateOption SYNCHRONIZATION_COOLDOWN = new UpdateOption(1500, TimeUnit.MILLISECOND);
private long lastAbsoluteSynchronizationTime;
// Events
private final Map<Class<? extends Event>, Collection<EventCallback>> eventCallbacks = new ConcurrentHashMap<>();
@ -543,8 +545,8 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
}
// Scheduled synchronization
if (time - lastSynchronizationTime >= SYNCHRONIZATION_DELAY) {
lastSynchronizationTime = time;
if (!CooldownUtils.hasCooldown(time, lastAbsoluteSynchronizationTime, SYNCHRONIZATION_COOLDOWN)) {
this.lastAbsoluteSynchronizationTime = time;
sendSynchronization();
}
@ -672,7 +674,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
*/
@Nullable
public Chunk getChunk() {
return instance.getChunkAt(lastX, lastZ);
return instance.getChunkAt(position.getX(), position.getZ());
}
/**
@ -1354,7 +1356,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
* Asks for a synchronization (position) to happen during next entity tick.
*/
public void askSynchronization() {
this.lastSynchronizationTime = 0;
this.lastAbsoluteSynchronizationTime = 0;
}
private boolean shouldUpdate(long time) {

View File

@ -1,5 +1,6 @@
package net.minestom.server.entity;
import io.netty.channel.Channel;
import net.minestom.server.MinecraftServer;
import net.minestom.server.advancements.AdvancementTab;
import net.minestom.server.attribute.Attribute;
@ -131,6 +132,11 @@ public class Player extends LivingEntity implements CommandSender {
private byte targetStage; // The current stage of the target block, only if multi player breaking is disabled
private final Set<Player> targetBreakers = new HashSet<>(1); // Only used if multi player breaking is disabled, contains only this player
// Position synchronization with viewers
protected UpdateOption playerSynchronizationCooldown = new UpdateOption(2, TimeUnit.TICK);
private long lastPlayerSynchronizationTime;
private float lastPlayerSyncX, lastPlayerSyncY, lastPlayerSyncZ, lastPlayerSyncYaw, lastPlayerSyncPitch;
// Experience orb pickup
protected UpdateOption experiencePickupCooldown = new UpdateOption(10, TimeUnit.TICK);
private long lastExperiencePickupCheckTime;
@ -301,7 +307,8 @@ public class Player extends LivingEntity implements CommandSender {
// Flush all pending packets
if (PlayerUtils.isNettyClient(this)) {
((NettyPlayerConnection) playerConnection).getChannel().flush();
Channel channel = ((NettyPlayerConnection) playerConnection).getChannel();
channel.eventLoop().execute(() -> channel.flush());
}
// Network tick verification
@ -412,9 +419,11 @@ public class Player extends LivingEntity implements CommandSender {
callEvent(PlayerTickEvent.class, playerTickEvent);
// Multiplayer sync
final boolean positionChanged = position.getX() != lastX || position.getY() != lastY || position.getZ() != lastZ;
final boolean viewChanged = position.getYaw() != lastYaw || position.getPitch() != lastPitch;
if (!viewers.isEmpty()) {
final boolean positionChanged = position.getX() != lastPlayerSyncX || position.getY() != lastPlayerSyncY || position.getZ() != lastPlayerSyncZ;
final boolean viewChanged = position.getYaw() != lastPlayerSyncYaw || position.getPitch() != lastPlayerSyncPitch;
if (!viewers.isEmpty() && !CooldownUtils.hasCooldown(time, lastPlayerSynchronizationTime, playerSynchronizationCooldown)) {
this.lastPlayerSynchronizationTime = time;
if (positionChanged || viewChanged) {
// Player moved since last time
@ -423,9 +432,9 @@ public class Player extends LivingEntity implements CommandSender {
if (positionChanged && viewChanged) {
EntityPositionAndRotationPacket entityPositionAndRotationPacket = new EntityPositionAndRotationPacket();
entityPositionAndRotationPacket.entityId = getEntityId();
entityPositionAndRotationPacket.deltaX = (short) ((position.getX() * 32 - lastX * 32) * 128);
entityPositionAndRotationPacket.deltaY = (short) ((position.getY() * 32 - lastY * 32) * 128);
entityPositionAndRotationPacket.deltaZ = (short) ((position.getZ() * 32 - lastZ * 32) * 128);
entityPositionAndRotationPacket.deltaX = (short) ((position.getX() * 32 - lastPlayerSyncX * 32) * 128);
entityPositionAndRotationPacket.deltaY = (short) ((position.getY() * 32 - lastPlayerSyncY * 32) * 128);
entityPositionAndRotationPacket.deltaZ = (short) ((position.getZ() * 32 - lastPlayerSyncZ * 32) * 128);
entityPositionAndRotationPacket.yaw = position.getYaw();
entityPositionAndRotationPacket.pitch = position.getPitch();
entityPositionAndRotationPacket.onGround = onGround;
@ -434,9 +443,9 @@ public class Player extends LivingEntity implements CommandSender {
} else if (positionChanged) {
EntityPositionPacket entityPositionPacket = new EntityPositionPacket();
entityPositionPacket.entityId = getEntityId();
entityPositionPacket.deltaX = (short) ((position.getX() * 32 - lastX * 32) * 128);
entityPositionPacket.deltaY = (short) ((position.getY() * 32 - lastY * 32) * 128);
entityPositionPacket.deltaZ = (short) ((position.getZ() * 32 - lastZ * 32) * 128);
entityPositionPacket.deltaX = (short) ((position.getX() * 32 - lastPlayerSyncX * 32) * 128);
entityPositionPacket.deltaY = (short) ((position.getY() * 32 - lastPlayerSyncY * 32) * 128);
entityPositionPacket.deltaZ = (short) ((position.getZ() * 32 - lastPlayerSyncZ * 32) * 128);
entityPositionPacket.onGround = onGround;
updatePacket = entityPositionPacket;
@ -472,16 +481,17 @@ public class Player extends LivingEntity implements CommandSender {
entityMovementPacket.entityId = getEntityId();
sendPacketToViewers(entityMovementPacket);
}
}
if (positionChanged) {
lastX = position.getX();
lastY = position.getY();
lastZ = position.getZ();
}
if (viewChanged) {
lastYaw = position.getYaw();
lastPitch = position.getPitch();
// Update sync data
if (positionChanged) {
lastPlayerSyncX = position.getX();
lastPlayerSyncY = position.getY();
lastPlayerSyncZ = position.getZ();
}
if (viewChanged) {
lastPlayerSyncYaw = position.getYaw();
lastPlayerSyncPitch = position.getPitch();
}
}
}

View File

@ -33,7 +33,7 @@ public class PacketCompressor extends ByteToMessageCodec<ByteBuf> {
private final byte[] buffer = new byte[8192];
private final Deflater deflater = new Deflater(3);
private final Deflater deflater = new Deflater();
private final Inflater inflater = new Inflater();
public PacketCompressor(int threshold) {

View File

@ -57,7 +57,7 @@ public class NettyPlayerConnection extends PlayerConnection {
}
/**
* Sets the encryption key and add the channels to the pipeline.
* Sets the encryption key and add the codecs to the pipeline.
*
* @param secretKey the secret key to use in the encryption
* @throws IllegalStateException if encryption is already enabled for this connection
@ -70,7 +70,7 @@ public class NettyPlayerConnection extends PlayerConnection {
}
/**
* Enables compression and add a new channel to the pipeline.
* Enables compression and add a new codec to the pipeline.
*
* @param threshold the threshold for a packet to be compressible
* @throws IllegalStateException if encryption is already enabled for this connection