fix: begin join game sequence only after client acks configuration finish

This commit is contained in:
mworzala 2023-12-24 12:52:19 -05:00 committed by Matt Worzala
parent 89c57bfac6
commit 197daae608
7 changed files with 81 additions and 27 deletions

View File

@ -19,11 +19,15 @@ public class AsyncPlayerConfigurationEvent implements PlayerEvent {
private final Player player;
private final boolean isFirstConfig;
private Instance spawningInstance = null;
private boolean sendRegistryData;
private Instance spawningInstance;
public AsyncPlayerConfigurationEvent(@NotNull Player player, boolean isFirstConfig) {
this.player = player;
this.isFirstConfig = isFirstConfig;
this.sendRegistryData = isFirstConfig;
this.spawningInstance = null;
}
@Override
@ -38,6 +42,14 @@ public class AsyncPlayerConfigurationEvent implements PlayerEvent {
return isFirstConfig;
}
public boolean willSendRegistryData() {
return sendRegistryData;
}
public void setSendRegistryData(boolean sendRegistryData) {
this.sendRegistryData = sendRegistryData;
}
public @Nullable Instance getSpawningInstance() {
return spawningInstance;
}

View File

@ -6,12 +6,10 @@ import net.minestom.server.network.ConnectionManager;
import net.minestom.server.network.packet.client.play.ClientConfigurationAckPacket;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.ForkJoinPool;
public class PlayConfigListener {
private static final ConnectionManager CONNECTION_MANAGER = MinecraftServer.getConnectionManager();
public static void configAckListener(@NotNull ClientConfigurationAckPacket packet, @NotNull Player player) {
CONNECTION_MANAGER.transitionConfigToPlay(player, false);
CONNECTION_MANAGER.doConfiguration(player, false);
}
}

View File

@ -8,12 +8,14 @@ import net.minestom.server.listener.common.KeepAliveListener;
import net.minestom.server.listener.common.PluginMessageListener;
import net.minestom.server.listener.common.ResourcePackListener;
import net.minestom.server.listener.common.SettingsListener;
import net.minestom.server.listener.preplay.ConfigListener;
import net.minestom.server.listener.preplay.HandshakeListener;
import net.minestom.server.listener.preplay.LoginListener;
import net.minestom.server.listener.preplay.StatusListener;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.network.packet.client.common.*;
import net.minestom.server.network.packet.client.configuration.ClientFinishConfigurationPacket;
import net.minestom.server.network.packet.client.handshake.ClientHandshakePacket;
import net.minestom.server.network.packet.client.login.ClientEncryptionResponsePacket;
import net.minestom.server.network.packet.client.login.ClientLoginAcknowledgedPacket;
@ -56,6 +58,7 @@ public final class PacketListenerManager {
setConfigurationListener(ClientKeepAlivePacket.class, KeepAliveListener::listener);
setConfigurationListener(ClientPongPacket.class, (packet, player) -> {/* empty */});
setConfigurationListener(ClientResourcePackStatusPacket.class, ResourcePackListener::listener);
setConfigurationListener(ClientFinishConfigurationPacket.class, ConfigListener::finishConfigListener);
setPlayListener(ClientKeepAlivePacket.class, KeepAliveListener::listener);
setPlayListener(ClientCommandChatPacket.class, ChatMessageListener::commandChatListener);
@ -90,6 +93,7 @@ public final class PacketListenerManager {
setPlayListener(ClientAdvancementTabPacket.class, AdvancementTabListener::listener);
setPlayListener(ClientSpectatePacket.class, SpectateListener::listener);
setPlayListener(ClientEditBookPacket.class, BookListener::listener);
setPlayListener(ClientChatSessionUpdatePacket.class, (packet, player) -> {/* empty */});
}
/**

View File

@ -0,0 +1,16 @@
package net.minestom.server.listener.preplay;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Player;
import net.minestom.server.network.ConnectionManager;
import net.minestom.server.network.packet.client.configuration.ClientFinishConfigurationPacket;
import net.minestom.server.network.packet.client.play.ClientConfigurationAckPacket;
import org.jetbrains.annotations.NotNull;
public final class ConfigListener {
private static final ConnectionManager CONNECTION_MANAGER = MinecraftServer.getConnectionManager();
public static void finishConfigListener(@NotNull ClientFinishConfigurationPacket packet, @NotNull Player player) {
CONNECTION_MANAGER.transitionConfigToPlay(player);
}
}

View File

@ -219,23 +219,23 @@ public final class LoginListener {
public static void loginAckListener(@NotNull ClientLoginAcknowledgedPacket ignored, @NotNull PlayerConnection connection) {
final Player player = Objects.requireNonNull(connection.getPlayer());
// Registry data
var registry = new HashMap<String, NBT>();
registry.put("minecraft:chat_type", Messenger.chatRegistry());
registry.put("minecraft:dimension_type", MinecraftServer.getDimensionTypeManager().toNBT());
registry.put("minecraft:worldgen/biome", MinecraftServer.getBiomeManager().toNBT());
registry.put("minecraft:damage_type", DamageType.getNBT());
connection.sendPacket(new RegistryDataPacket(NBT.Compound(registry)));
// Tags
connection.sendPacket(TagsPacket.DEFAULT_TAGS);
// Server Brand
connection.sendPacket(PluginMessagePacket.getBrandPacket());
// Enter configuration phase (for the first time)
CONNECTION_MANAGER.transitionConfigToPlay(player, true);
CONNECTION_MANAGER.doConfiguration(player, true);
// // Registry data
// var registry = new HashMap<String, NBT>();
// registry.put("minecraft:chat_type", Messenger.chatRegistry());
// registry.put("minecraft:dimension_type", MinecraftServer.getDimensionTypeManager().toNBT());
// registry.put("minecraft:worldgen/biome", MinecraftServer.getBiomeManager().toNBT());
// registry.put("minecraft:damage_type", DamageType.getNBT());
// connection.sendPacket(new RegistryDataPacket(NBT.Compound(registry)));
//
// // Tags
// connection.sendPacket(TagsPacket.DEFAULT_TAGS);
//
// // Server Brand
// connection.sendPacket(PluginMessagePacket.getBrandPacket());
//
// // Enter configuration phase (for the first time)
// CONNECTION_MANAGER.transitionConfigToPlay(player, true);
}
}

View File

@ -4,13 +4,18 @@ import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Player;
import net.minestom.server.entity.damage.DamageType;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.AsyncPlayerConfigurationEvent;
import net.minestom.server.event.player.AsyncPlayerPreLoginEvent;
import net.minestom.server.instance.Instance;
import net.minestom.server.message.Messenger;
import net.minestom.server.network.packet.client.login.ClientLoginStartPacket;
import net.minestom.server.network.packet.server.common.KeepAlivePacket;
import net.minestom.server.network.packet.server.common.PluginMessagePacket;
import net.minestom.server.network.packet.server.common.TagsPacket;
import net.minestom.server.network.packet.server.configuration.FinishConfigurationPacket;
import net.minestom.server.network.packet.server.configuration.RegistryDataPacket;
import net.minestom.server.network.packet.server.login.LoginSuccessPacket;
import net.minestom.server.network.packet.server.play.StartConfigurationPacket;
import net.minestom.server.network.player.PlayerConnection;
@ -24,6 +29,9 @@ import org.jctools.queues.MpscUnboundedArrayQueue;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.CompletableFuture;
@ -35,6 +43,8 @@ import java.util.function.Function;
* Manages the connected clients.
*/
public final class ConnectionManager {
private static final Logger logger = LoggerFactory.getLogger(ConnectionManager.class);
private static final long KEEP_ALIVE_DELAY = 10_000;
private static final long KEEP_ALIVE_KICK = 30_000;
private static final Component TIMEOUT_TEXT = Component.text("Timeout", NamedTextColor.RED);
@ -268,21 +278,38 @@ public final class ConnectionManager {
}
@ApiStatus.Internal
public void transitionConfigToPlay(@NotNull Player player, boolean isFirstConfig) {
// Call the event and spawn the player.
public void doConfiguration(@NotNull Player player, boolean isFirstConfig) {
AsyncUtils.runAsync(() -> {
player.sendPacket(PluginMessagePacket.getBrandPacket());
var event = new AsyncPlayerConfigurationEvent(player, isFirstConfig);
EventDispatcher.call(event);
final Instance spawningInstance = event.getSpawningInstance();
Check.notNull(spawningInstance, "You need to specify a spawning instance in the AsyncPlayerConfigurationEvent");
// Registry data (if it should be sent)
if (event.willSendRegistryData()) {
var registry = new HashMap<String, NBT>();
registry.put("minecraft:chat_type", Messenger.chatRegistry());
registry.put("minecraft:dimension_type", MinecraftServer.getDimensionTypeManager().toNBT());
registry.put("minecraft:worldgen/biome", MinecraftServer.getBiomeManager().toNBT());
registry.put("minecraft:damage_type", DamageType.getNBT());
player.sendPacket(new RegistryDataPacket(NBT.Compound(registry)));
player.sendPacket(TagsPacket.DEFAULT_TAGS);
}
player.setPendingInstance(spawningInstance);
this.waitingPlayers.relaxedOffer(player);
player.sendPacket(new FinishConfigurationPacket());
});
}
@ApiStatus.Internal
public void transitionConfigToPlay(@NotNull Player player) {
this.waitingPlayers.relaxedOffer(player);
}
/**
* Removes a {@link Player} from the players list.
* <p>

View File

@ -13,9 +13,6 @@ import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.network.packet.client.handshake.ClientHandshakePacket;
import net.minestom.server.network.packet.server.*;
import net.minestom.server.network.packet.server.login.SetCompressionPacket;
import net.minestom.server.network.packet.server.play.ChunkDataPacket;
import net.minestom.server.network.packet.server.play.TimeUpdatePacket;
import net.minestom.server.network.packet.server.play.UpdateLightPacket;
import net.minestom.server.network.socket.Worker;
import net.minestom.server.utils.ObjectPool;
import net.minestom.server.utils.PacketUtils;