mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-29 12:37:42 +01:00
Per instance thread is now the default, added a configurable cooldown for player position refresh
This commit is contained in:
parent
2405b7ae6f
commit
553a280993
@ -3,7 +3,7 @@ package net.minestom.server;
|
|||||||
import net.minestom.server.entity.EntityManager;
|
import net.minestom.server.entity.EntityManager;
|
||||||
import net.minestom.server.instance.Instance;
|
import net.minestom.server.instance.Instance;
|
||||||
import net.minestom.server.instance.InstanceManager;
|
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.thread.ThreadProvider;
|
||||||
import net.minestom.server.utils.thread.MinestomThread;
|
import net.minestom.server.utils.thread.MinestomThread;
|
||||||
import net.minestom.server.utils.validate.Check;
|
import net.minestom.server.utils.validate.Check;
|
||||||
@ -33,7 +33,8 @@ public final class UpdateManager {
|
|||||||
|
|
||||||
{
|
{
|
||||||
// DEFAULT THREAD PROVIDER
|
// DEFAULT THREAD PROVIDER
|
||||||
threadProvider = new PerGroupChunkProvider();
|
//threadProvider = new PerGroupChunkProvider();
|
||||||
|
threadProvider = new PerInstanceThreadProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,7 +31,9 @@ import net.minestom.server.utils.callback.OptionalCallback;
|
|||||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||||
import net.minestom.server.utils.entity.EntityUtils;
|
import net.minestom.server.utils.entity.EntityUtils;
|
||||||
import net.minestom.server.utils.player.PlayerUtils;
|
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.TimeUnit;
|
||||||
|
import net.minestom.server.utils.time.UpdateOption;
|
||||||
import net.minestom.server.utils.validate.Check;
|
import net.minestom.server.utils.validate.Check;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@ -103,9 +105,9 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
|
|||||||
private long lastUpdate;
|
private long lastUpdate;
|
||||||
private final EntityType entityType;
|
private final EntityType entityType;
|
||||||
|
|
||||||
// Network synchronization
|
// Network synchronization, send the absolute position of the entity each X milliseconds
|
||||||
private static final long SYNCHRONIZATION_DELAY = 1500; // In ms
|
private static final UpdateOption SYNCHRONIZATION_COOLDOWN = new UpdateOption(1500, TimeUnit.MILLISECOND);
|
||||||
private long lastSynchronizationTime;
|
private long lastAbsoluteSynchronizationTime;
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
private final Map<Class<? extends Event>, Collection<EventCallback>> eventCallbacks = new ConcurrentHashMap<>();
|
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
|
// Scheduled synchronization
|
||||||
if (time - lastSynchronizationTime >= SYNCHRONIZATION_DELAY) {
|
if (!CooldownUtils.hasCooldown(time, lastAbsoluteSynchronizationTime, SYNCHRONIZATION_COOLDOWN)) {
|
||||||
lastSynchronizationTime = time;
|
this.lastAbsoluteSynchronizationTime = time;
|
||||||
sendSynchronization();
|
sendSynchronization();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -672,7 +674,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
|
|||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public Chunk getChunk() {
|
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.
|
* Asks for a synchronization (position) to happen during next entity tick.
|
||||||
*/
|
*/
|
||||||
public void askSynchronization() {
|
public void askSynchronization() {
|
||||||
this.lastSynchronizationTime = 0;
|
this.lastAbsoluteSynchronizationTime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldUpdate(long time) {
|
private boolean shouldUpdate(long time) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.minestom.server.entity;
|
package net.minestom.server.entity;
|
||||||
|
|
||||||
|
import io.netty.channel.Channel;
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.advancements.AdvancementTab;
|
import net.minestom.server.advancements.AdvancementTab;
|
||||||
import net.minestom.server.attribute.Attribute;
|
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 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
|
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
|
// Experience orb pickup
|
||||||
protected UpdateOption experiencePickupCooldown = new UpdateOption(10, TimeUnit.TICK);
|
protected UpdateOption experiencePickupCooldown = new UpdateOption(10, TimeUnit.TICK);
|
||||||
private long lastExperiencePickupCheckTime;
|
private long lastExperiencePickupCheckTime;
|
||||||
@ -301,7 +307,8 @@ public class Player extends LivingEntity implements CommandSender {
|
|||||||
|
|
||||||
// Flush all pending packets
|
// Flush all pending packets
|
||||||
if (PlayerUtils.isNettyClient(this)) {
|
if (PlayerUtils.isNettyClient(this)) {
|
||||||
((NettyPlayerConnection) playerConnection).getChannel().flush();
|
Channel channel = ((NettyPlayerConnection) playerConnection).getChannel();
|
||||||
|
channel.eventLoop().execute(() -> channel.flush());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Network tick verification
|
// Network tick verification
|
||||||
@ -412,9 +419,11 @@ public class Player extends LivingEntity implements CommandSender {
|
|||||||
callEvent(PlayerTickEvent.class, playerTickEvent);
|
callEvent(PlayerTickEvent.class, playerTickEvent);
|
||||||
|
|
||||||
// Multiplayer sync
|
// Multiplayer sync
|
||||||
final boolean positionChanged = position.getX() != lastX || position.getY() != lastY || position.getZ() != lastZ;
|
final boolean positionChanged = position.getX() != lastPlayerSyncX || position.getY() != lastPlayerSyncY || position.getZ() != lastPlayerSyncZ;
|
||||||
final boolean viewChanged = position.getYaw() != lastYaw || position.getPitch() != lastPitch;
|
final boolean viewChanged = position.getYaw() != lastPlayerSyncYaw || position.getPitch() != lastPlayerSyncPitch;
|
||||||
if (!viewers.isEmpty()) {
|
if (!viewers.isEmpty() && !CooldownUtils.hasCooldown(time, lastPlayerSynchronizationTime, playerSynchronizationCooldown)) {
|
||||||
|
this.lastPlayerSynchronizationTime = time;
|
||||||
|
|
||||||
if (positionChanged || viewChanged) {
|
if (positionChanged || viewChanged) {
|
||||||
// Player moved since last time
|
// Player moved since last time
|
||||||
|
|
||||||
@ -423,9 +432,9 @@ public class Player extends LivingEntity implements CommandSender {
|
|||||||
if (positionChanged && viewChanged) {
|
if (positionChanged && viewChanged) {
|
||||||
EntityPositionAndRotationPacket entityPositionAndRotationPacket = new EntityPositionAndRotationPacket();
|
EntityPositionAndRotationPacket entityPositionAndRotationPacket = new EntityPositionAndRotationPacket();
|
||||||
entityPositionAndRotationPacket.entityId = getEntityId();
|
entityPositionAndRotationPacket.entityId = getEntityId();
|
||||||
entityPositionAndRotationPacket.deltaX = (short) ((position.getX() * 32 - lastX * 32) * 128);
|
entityPositionAndRotationPacket.deltaX = (short) ((position.getX() * 32 - lastPlayerSyncX * 32) * 128);
|
||||||
entityPositionAndRotationPacket.deltaY = (short) ((position.getY() * 32 - lastY * 32) * 128);
|
entityPositionAndRotationPacket.deltaY = (short) ((position.getY() * 32 - lastPlayerSyncY * 32) * 128);
|
||||||
entityPositionAndRotationPacket.deltaZ = (short) ((position.getZ() * 32 - lastZ * 32) * 128);
|
entityPositionAndRotationPacket.deltaZ = (short) ((position.getZ() * 32 - lastPlayerSyncZ * 32) * 128);
|
||||||
entityPositionAndRotationPacket.yaw = position.getYaw();
|
entityPositionAndRotationPacket.yaw = position.getYaw();
|
||||||
entityPositionAndRotationPacket.pitch = position.getPitch();
|
entityPositionAndRotationPacket.pitch = position.getPitch();
|
||||||
entityPositionAndRotationPacket.onGround = onGround;
|
entityPositionAndRotationPacket.onGround = onGround;
|
||||||
@ -434,9 +443,9 @@ public class Player extends LivingEntity implements CommandSender {
|
|||||||
} else if (positionChanged) {
|
} else if (positionChanged) {
|
||||||
EntityPositionPacket entityPositionPacket = new EntityPositionPacket();
|
EntityPositionPacket entityPositionPacket = new EntityPositionPacket();
|
||||||
entityPositionPacket.entityId = getEntityId();
|
entityPositionPacket.entityId = getEntityId();
|
||||||
entityPositionPacket.deltaX = (short) ((position.getX() * 32 - lastX * 32) * 128);
|
entityPositionPacket.deltaX = (short) ((position.getX() * 32 - lastPlayerSyncX * 32) * 128);
|
||||||
entityPositionPacket.deltaY = (short) ((position.getY() * 32 - lastY * 32) * 128);
|
entityPositionPacket.deltaY = (short) ((position.getY() * 32 - lastPlayerSyncY * 32) * 128);
|
||||||
entityPositionPacket.deltaZ = (short) ((position.getZ() * 32 - lastZ * 32) * 128);
|
entityPositionPacket.deltaZ = (short) ((position.getZ() * 32 - lastPlayerSyncZ * 32) * 128);
|
||||||
entityPositionPacket.onGround = onGround;
|
entityPositionPacket.onGround = onGround;
|
||||||
|
|
||||||
updatePacket = entityPositionPacket;
|
updatePacket = entityPositionPacket;
|
||||||
@ -472,16 +481,17 @@ public class Player extends LivingEntity implements CommandSender {
|
|||||||
entityMovementPacket.entityId = getEntityId();
|
entityMovementPacket.entityId = getEntityId();
|
||||||
sendPacketToViewers(entityMovementPacket);
|
sendPacketToViewers(entityMovementPacket);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
// Update sync data
|
||||||
if (positionChanged) {
|
if (positionChanged) {
|
||||||
lastX = position.getX();
|
lastPlayerSyncX = position.getX();
|
||||||
lastY = position.getY();
|
lastPlayerSyncY = position.getY();
|
||||||
lastZ = position.getZ();
|
lastPlayerSyncZ = position.getZ();
|
||||||
}
|
}
|
||||||
if (viewChanged) {
|
if (viewChanged) {
|
||||||
lastYaw = position.getYaw();
|
lastPlayerSyncYaw = position.getYaw();
|
||||||
lastPitch = position.getPitch();
|
lastPlayerSyncPitch = position.getPitch();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ public class PacketCompressor extends ByteToMessageCodec<ByteBuf> {
|
|||||||
|
|
||||||
private final byte[] buffer = new byte[8192];
|
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();
|
private final Inflater inflater = new Inflater();
|
||||||
|
|
||||||
public PacketCompressor(int threshold) {
|
public PacketCompressor(int threshold) {
|
||||||
|
@ -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
|
* @param secretKey the secret key to use in the encryption
|
||||||
* @throws IllegalStateException if encryption is already enabled for this connection
|
* @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
|
* @param threshold the threshold for a packet to be compressible
|
||||||
* @throws IllegalStateException if encryption is already enabled for this connection
|
* @throws IllegalStateException if encryption is already enabled for this connection
|
||||||
|
Loading…
Reference in New Issue
Block a user