mirror of
https://github.com/Minestom/Minestom.git
synced 2024-11-05 02:10:24 +01:00
feat: cleanup, remove ConnectionManager#getOnlinePlayers
This commit is contained in:
parent
50b868229a
commit
8a75e9e986
@ -177,8 +177,7 @@ public class PlayerInit {
|
||||
|
||||
BenchmarkManager benchmarkManager = MinecraftServer.getBenchmarkManager();
|
||||
MinecraftServer.getSchedulerManager().buildTask(() -> {
|
||||
Collection<Player> players = MinecraftServer.getConnectionManager().getOnlinePlayers();
|
||||
if (players.isEmpty())
|
||||
if (MinecraftServer.getConnectionManager().getOnlinePlayerCount() != 0)
|
||||
return;
|
||||
|
||||
long ramUsage = benchmarkManager.getUsedMemory();
|
||||
|
@ -9,7 +9,7 @@ public class ConfigCommand extends Command {
|
||||
|
||||
setDefaultExecutor((sender, context) -> {
|
||||
if (!(sender instanceof Player player)) return;
|
||||
player.startConfigurationPhase2();
|
||||
player.startConfigurationPhase();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,10 @@ import net.minestom.server.command.CommandSender;
|
||||
import net.minestom.server.command.builder.Command;
|
||||
import net.minestom.server.command.builder.CommandContext;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class PlayersCommand extends Command {
|
||||
|
||||
@ -17,20 +19,20 @@ public class PlayersCommand extends Command {
|
||||
}
|
||||
|
||||
private void usage(CommandSender sender, CommandContext context) {
|
||||
final Collection<Player> players = MinecraftServer.getConnectionManager().getOnlinePlayers();
|
||||
final var players = List.copyOf(MinecraftServer.getConnectionManager().getPlayers());
|
||||
final int playerCount = players.size();
|
||||
sender.sendMessage(Component.text("Total players: " + playerCount));
|
||||
|
||||
final int limit = 15;
|
||||
if (playerCount <= limit) {
|
||||
for (final Player player : players) {
|
||||
sender.sendMessage(Component.text(player.getUsername()));
|
||||
}
|
||||
} else {
|
||||
for (final Player player : players.stream().limit(limit).toList()) {
|
||||
sender.sendMessage(Component.text(player.getUsername()));
|
||||
}
|
||||
sender.sendMessage(Component.text("..."));
|
||||
for (int i = 0; i < Math.min(limit, playerCount); i++) {
|
||||
final var player = players.get(i);
|
||||
var msg = Component.text(player.getUsername());
|
||||
if (player.getPlayerConnection().getServerState() == ConnectionState.CONFIGURATION)
|
||||
msg = msg.append(Component.text(" (config)"));
|
||||
sender.sendMessage(msg);
|
||||
}
|
||||
|
||||
if (playerCount > limit) sender.sendMessage(Component.text("..."));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ public final class MinecraftServer {
|
||||
*/
|
||||
public static void setBrandName(@NotNull String brandName) {
|
||||
MinecraftServer.brandName = brandName;
|
||||
PacketUtils.broadcastPacket(PluginMessagePacket.getBrandPacket());
|
||||
PacketUtils.broadcastPlayPacket(PluginMessagePacket.getBrandPacket());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,7 +123,7 @@ public final class MinecraftServer {
|
||||
*/
|
||||
public static void setDifficulty(@NotNull Difficulty difficulty) {
|
||||
MinecraftServer.difficulty = difficulty;
|
||||
PacketUtils.broadcastPacket(new ServerDifficultyPacket(difficulty, true));
|
||||
PacketUtils.broadcastPlayPacket(new ServerDifficultyPacket(difficulty, true));
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
|
@ -5,6 +5,7 @@ import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
@ -41,7 +42,7 @@ public class Audiences {
|
||||
* @return all audience members
|
||||
*/
|
||||
public static @NotNull Audience all() {
|
||||
return Audience.audience(audience.server, audience.customs());
|
||||
return Audience.audience(audience.server(), audience.customs());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -50,7 +51,7 @@ public class Audiences {
|
||||
* @return all players
|
||||
*/
|
||||
public static @NotNull Audience players() {
|
||||
return audience.players;
|
||||
return audience.players();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -60,7 +61,8 @@ public class Audiences {
|
||||
* @return all players matching the predicate
|
||||
*/
|
||||
public static @NotNull Audience players(@NotNull Predicate<Player> filter) {
|
||||
return PacketGroupingAudience.of(MinecraftServer.getConnectionManager().getOnlinePlayers().stream().filter(filter).toList());
|
||||
return PacketGroupingAudience.of(MinecraftServer.getConnectionManager().getPlayers(ConnectionState.PLAY)
|
||||
.stream().filter(filter).toList());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -78,7 +80,7 @@ public class Audiences {
|
||||
* @return the audience of all players and the console
|
||||
*/
|
||||
public static @NotNull Audience server() {
|
||||
return audience.server;
|
||||
return audience.server();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,6 +5,7 @@ import net.kyori.adventure.key.Key;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.command.ConsoleSender;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -35,12 +36,12 @@ class IterableAudienceProvider implements AudienceProvider<Iterable<? extends Au
|
||||
|
||||
@Override
|
||||
public @NotNull Iterable<? extends Audience> players() {
|
||||
return MinecraftServer.getConnectionManager().getOnlinePlayers();
|
||||
return MinecraftServer.getConnectionManager().getPlayers(ConnectionState.PLAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterable<? extends Audience> players(@NotNull Predicate<Player> filter) {
|
||||
return MinecraftServer.getConnectionManager().getOnlinePlayers().stream().filter(filter).toList();
|
||||
return MinecraftServer.getConnectionManager().getPlayers(ConnectionState.PLAY).stream().filter(filter).toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -4,6 +4,7 @@ import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
@ -15,8 +16,6 @@ import java.util.function.Predicate;
|
||||
class SingleAudienceProvider implements AudienceProvider<Audience> {
|
||||
|
||||
protected final IterableAudienceProvider collection = new IterableAudienceProvider();
|
||||
protected final Audience players = PacketGroupingAudience.of(MinecraftServer.getConnectionManager().getOnlinePlayers());
|
||||
protected final Audience server = Audience.audience(this.players, MinecraftServer.getCommandManager().getConsoleSender());
|
||||
|
||||
protected SingleAudienceProvider() {
|
||||
}
|
||||
@ -32,17 +31,18 @@ class SingleAudienceProvider implements AudienceProvider<Audience> {
|
||||
|
||||
@Override
|
||||
public @NotNull Audience all() {
|
||||
return Audience.audience(this.server, this.customs());
|
||||
return Audience.audience(this.server(), this.customs());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Audience players() {
|
||||
return this.players;
|
||||
return PacketGroupingAudience.of(MinecraftServer.getConnectionManager().getPlayers(ConnectionState.PLAY));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Audience players(@NotNull Predicate<Player> filter) {
|
||||
return PacketGroupingAudience.of(MinecraftServer.getConnectionManager().getOnlinePlayers().stream().filter(filter).toList());
|
||||
return PacketGroupingAudience.of(MinecraftServer.getConnectionManager().getPlayers(ConnectionState.PLAY)
|
||||
.stream().filter(filter).toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -52,7 +52,7 @@ class SingleAudienceProvider implements AudienceProvider<Audience> {
|
||||
|
||||
@Override
|
||||
public @NotNull Audience server() {
|
||||
return this.server;
|
||||
return Audience.audience(players(), MinecraftServer.getCommandManager().getConsoleSender());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,12 +57,9 @@ import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import net.minestom.server.network.PlayerProvider;
|
||||
import net.minestom.server.network.packet.client.ClientPacket;
|
||||
import net.minestom.server.network.packet.server.CachedPacket;
|
||||
import net.minestom.server.network.packet.server.SendablePacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.network.packet.server.common.*;
|
||||
import net.minestom.server.network.packet.server.configuration.FinishConfigurationPacket;
|
||||
import net.minestom.server.network.packet.server.login.LoginDisconnectPacket;
|
||||
import net.minestom.server.network.packet.server.play.*;
|
||||
import net.minestom.server.network.packet.server.play.data.DeathLocation;
|
||||
@ -134,6 +131,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
private Component displayName;
|
||||
private PlayerSkin skin;
|
||||
|
||||
private Instance pendingInstance = null;
|
||||
private DimensionType dimensionType;
|
||||
private GameMode gameMode;
|
||||
private DeathLocation deathLocation;
|
||||
@ -254,17 +252,25 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
metadata.setNotifyAboutChanges(false);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void setPendingInstance(@NotNull Instance pendingInstance) {
|
||||
// I(mattw) am not a big fan of this function, but somehow we need to store
|
||||
// the instance and i didn't like a record in ConnectionManager either.
|
||||
this.pendingInstance = pendingInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when the player is created.
|
||||
* Init the player and spawn him.
|
||||
* <p>
|
||||
* WARNING: executed in the main update thread
|
||||
* UNSAFE: Only meant to be used when a socket player connects through the server.
|
||||
*
|
||||
* @param spawnInstance the player spawn instance (defined in {@link AsyncPlayerConfigurationEvent})
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public CompletableFuture<Void> UNSAFE_init(@NotNull Instance spawnInstance) {
|
||||
public CompletableFuture<Void> UNSAFE_init() {
|
||||
final Instance spawnInstance = this.pendingInstance;
|
||||
this.pendingInstance = null;
|
||||
|
||||
this.removed = false;
|
||||
this.dimensionType = spawnInstance.getDimensionType();
|
||||
|
||||
@ -297,9 +303,10 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
EventDispatcher.call(skinInitEvent);
|
||||
this.skin = skinInitEvent.getSkin();
|
||||
// FIXME: when using Geyser, this line remove the skin of the client
|
||||
PacketUtils.broadcastPacket(getAddPlayerToList());
|
||||
PacketUtils.broadcastPlayPacket(getAddPlayerToList());
|
||||
|
||||
for (var player : MinecraftServer.getConnectionManager().getOnlinePlayers()) {
|
||||
var connectionManager = MinecraftServer.getConnectionManager();
|
||||
for (var player : connectionManager.getPlayers(ConnectionState.PLAY)) {
|
||||
if (player != this) {
|
||||
sendPacket(player.getAddPlayerToList());
|
||||
if (player.displayName != null) {
|
||||
@ -356,63 +363,15 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
* <p>This will result in them being removed from the current instance, player list, etc.</p>
|
||||
*/
|
||||
public void startConfigurationPhase() {
|
||||
boolean isFirstConfig = true;
|
||||
Check.stateCondition(playerConnection.getClientState() != ConnectionState.PLAY,
|
||||
"Player must be in the play state for reconfiguration.");
|
||||
|
||||
// If the player is currently in the play state, we need to put them back in configuration.
|
||||
if (playerConnection.getClientState() == ConnectionState.PLAY) {
|
||||
remove(false);
|
||||
sendPacket(new StartConfigurationPacket());
|
||||
} else {
|
||||
// Sanity check that they are already in configuration.
|
||||
// On first join, they will already be in the config state when this is called.
|
||||
assert playerConnection.getClientState() == ConnectionState.CONFIGURATION;
|
||||
}
|
||||
// Remove the player, then send them back to configuration
|
||||
remove(false);
|
||||
|
||||
// Call the event and spawn the player.
|
||||
AsyncUtils.runAsync(() -> {
|
||||
System.out.println("CALL EVENT");
|
||||
var event = new AsyncPlayerConfigurationEvent(this, isFirstConfig);
|
||||
EventDispatcher.call(event);
|
||||
var connectionManager = MinecraftServer.getConnectionManager();
|
||||
connectionManager.transitionPlayToConfig(this);
|
||||
|
||||
System.out.println("FINISHED EVENT");
|
||||
final Instance spawningInstance = event.getSpawningInstance();
|
||||
Check.notNull(spawningInstance, "You need to specify a spawning instance in the AsyncPlayerConfigurationEvent");
|
||||
|
||||
MinecraftServer.getConnectionManager().startPlayState(this, event.getSpawningInstance());
|
||||
sendPacket(new FinishConfigurationPacket());
|
||||
System.out.println("SENT CHANGE PACKET");
|
||||
});
|
||||
}
|
||||
|
||||
public void startConfigurationPhase2() {
|
||||
boolean isFirstConfig = true;
|
||||
|
||||
// If the player is currently in the play state, we need to put them back in configuration.
|
||||
if (playerConnection.getClientState() == ConnectionState.PLAY) {
|
||||
remove(false);
|
||||
System.out.println("SEND REENTER");
|
||||
MinecraftServer.getConnectionManager().transitionPlayToConfig(this);
|
||||
sendPacket(new StartConfigurationPacket());
|
||||
} else {
|
||||
// Sanity check that they are already in configuration.
|
||||
// On first join, they will already be in the config state when this is called.
|
||||
assert playerConnection.getClientState() == ConnectionState.CONFIGURATION;
|
||||
}
|
||||
|
||||
// Call the event and spawn the player.
|
||||
// AsyncUtils.runAsync(() -> {
|
||||
// System.out.println("CALL EVENT");
|
||||
// var event = new AsyncPlayerConfigurationEvent(this, isFirstConfig);
|
||||
// EventDispatcher.call(event);
|
||||
//
|
||||
// System.out.println("FINISHED EVENT");
|
||||
// final Instance spawningInstance = event.getSpawningInstance();
|
||||
// Check.notNull(spawningInstance, "You need to specify a spawning instance in the AsyncPlayerConfigurationEvent");
|
||||
//
|
||||
// MinecraftServer.getConnectionManager().startPlayState(this, event.getSpawningInstance());
|
||||
// sendPacket(new FinishConfigurationPacket());
|
||||
// System.out.println("SENT CHANGE PACKET");
|
||||
// });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -427,6 +386,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
public void update(long time) {
|
||||
// Process received packets
|
||||
interpretPacketQueue();
|
||||
// It is possible to be removed during packet processing, if thats the case exit immediately.
|
||||
if (isRemoved()) return;
|
||||
|
||||
super.update(time); // Super update (item pickup/fire management)
|
||||
@ -626,7 +586,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
// Clear all viewable chunks
|
||||
ChunkUtils.forChunksInRange(chunkX, chunkZ, MinecraftServer.getChunkViewDistance(), chunkRemover);
|
||||
// Remove from the tab-list
|
||||
PacketUtils.broadcastPacket(getRemovePlayerToList());
|
||||
PacketUtils.broadcastPlayPacket(getRemovePlayerToList());
|
||||
|
||||
// Prevent the player from being stuck in loading screen, or just unable to interact with the server
|
||||
// This should be considered as a bug, since the player will ultimately time out anyway.
|
||||
@ -1126,7 +1086,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
*/
|
||||
public void setDisplayName(@Nullable Component displayName) {
|
||||
this.displayName = displayName;
|
||||
PacketUtils.broadcastPacket(new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME, infoEntry()));
|
||||
PacketUtils.broadcastPlayPacket(new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME, infoEntry()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1168,11 +1128,11 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
|
||||
{
|
||||
// Remove player
|
||||
PacketUtils.broadcastPacket(removePlayerPacket);
|
||||
PacketUtils.broadcastPlayPacket(removePlayerPacket);
|
||||
sendPacketToViewers(destroyEntitiesPacket);
|
||||
|
||||
// Show player again
|
||||
PacketUtils.broadcastPacket(addPlayerPacket);
|
||||
PacketUtils.broadcastPlayPacket(addPlayerPacket);
|
||||
getViewers().forEach(player -> showPlayer(player.getPlayerConnection()));
|
||||
}
|
||||
|
||||
@ -1507,7 +1467,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
// Condition to prevent sending the packets before spawning the player
|
||||
if (isActive()) {
|
||||
sendPacket(new ChangeGameStatePacket(ChangeGameStatePacket.Reason.CHANGE_GAMEMODE, gameMode.id()));
|
||||
PacketUtils.broadcastPacket(new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, infoEntry()));
|
||||
PacketUtils.broadcastPlayPacket(new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, infoEntry()));
|
||||
}
|
||||
|
||||
// The client updates their abilities based on the GameMode as follows
|
||||
@ -2004,7 +1964,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
public void refreshLatency(int latency) {
|
||||
this.latency = latency;
|
||||
if (getPlayerConnection().getServerState() == ConnectionState.PLAY) {
|
||||
PacketUtils.broadcastPacket(new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.UPDATE_LATENCY, infoEntry()));
|
||||
PacketUtils.broadcastPlayPacket(new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.UPDATE_LATENCY, infoEntry()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,8 @@ public class FakePlayer extends Player implements NavigableEntity {
|
||||
}).build();
|
||||
MinecraftServer.getGlobalEventHandler().addListener(spawnListener);
|
||||
}
|
||||
CONNECTION_MANAGER.startConfigurationState(this);
|
||||
|
||||
CONNECTION_MANAGER.transitionLoginToConfig(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -21,7 +21,7 @@ public class BasicQueryResponse implements Writeable {
|
||||
this.motd = "A Minestom Server";
|
||||
this.gametype = "SMP";
|
||||
this.map = "world";
|
||||
this.numPlayers = String.valueOf(MinecraftServer.getConnectionManager().getOnlinePlayers().size());
|
||||
this.numPlayers = String.valueOf(MinecraftServer.getConnectionManager().getOnlinePlayerCount());
|
||||
this.maxPlayers = String.valueOf(Integer.parseInt(this.numPlayers) + 1);
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
package net.minestom.server.extras.query.response;
|
||||
|
||||
import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.extras.query.Query;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import net.minestom.server.utils.binary.Writeable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -13,7 +15,7 @@ import java.util.*;
|
||||
* A full query response containing a dynamic set of responses.
|
||||
*/
|
||||
public class FullQueryResponse implements Writeable {
|
||||
private static final PlainComponentSerializer PLAIN = PlainComponentSerializer.plain();
|
||||
private static final PlainTextComponentSerializer PLAIN = PlainTextComponentSerializer.plainText();
|
||||
private static final byte[] PADDING_10 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
PADDING_11 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
@ -31,7 +33,7 @@ public class FullQueryResponse implements Writeable {
|
||||
this.kv.put(key.getKey(), key.getValue());
|
||||
}
|
||||
|
||||
this.players = MinecraftServer.getConnectionManager().getOnlinePlayers()
|
||||
this.players = MinecraftServer.getConnectionManager().getPlayers(ConnectionState.PLAY)
|
||||
.stream()
|
||||
.map(player -> PLAIN.serialize(player.getName()))
|
||||
.toList();
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.minestom.server.extras.query.response;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@ -18,8 +19,8 @@ public enum QueryKey {
|
||||
VERSION(() -> MinecraftServer.VERSION_NAME),
|
||||
PLUGINS(FullQueryResponse::generatePluginsValue),
|
||||
MAP(() -> "world"),
|
||||
NUM_PLAYERS("numplayers", () -> String.valueOf(MinecraftServer.getConnectionManager().getOnlinePlayers().size())),
|
||||
MAX_PLAYERS("maxplayers", () -> String.valueOf(MinecraftServer.getConnectionManager().getOnlinePlayers().size() + 1)),
|
||||
NUM_PLAYERS("numplayers", () -> String.valueOf(MinecraftServer.getConnectionManager().getOnlinePlayerCount())),
|
||||
MAX_PLAYERS("maxplayers", () -> String.valueOf(MinecraftServer.getConnectionManager().getOnlinePlayerCount() + 1)),
|
||||
HOST_PORT("hostport", () -> String.valueOf(MinecraftServer.getServer().getPort())),
|
||||
HOST_IP("hostip", () -> Objects.requireNonNullElse(MinecraftServer.getServer().getAddress(), "localhost"));
|
||||
|
||||
|
@ -10,6 +10,7 @@ import net.minestom.server.event.player.PlayerChatEvent;
|
||||
import net.minestom.server.message.ChatPosition;
|
||||
import net.minestom.server.message.Messenger;
|
||||
import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import net.minestom.server.network.packet.client.play.ClientChatMessagePacket;
|
||||
import net.minestom.server.network.packet.client.play.ClientCommandChatPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -38,7 +39,7 @@ public class ChatMessageListener {
|
||||
return;
|
||||
}
|
||||
|
||||
final Collection<Player> players = CONNECTION_MANAGER.getOnlinePlayers();
|
||||
final Collection<Player> players = CONNECTION_MANAGER.getPlayers(ConnectionState.PLAY);
|
||||
PlayerChatEvent playerChatEvent = new PlayerChatEvent(player, players, () -> buildDefaultChatMessage(player, message), message);
|
||||
|
||||
// Call the event
|
||||
|
@ -1,23 +1,17 @@
|
||||
package net.minestom.server.listener;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.entity.Player;
|
||||
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) {
|
||||
// player.startConfigurationPhase();
|
||||
System.out.println("PLAYER HAS REENTERED CONFIGURATION PHASE!!!!!" + player.getUsername());
|
||||
ForkJoinPool.commonPool().execute(() -> {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
player.startConfigurationPhase();
|
||||
});
|
||||
CONNECTION_MANAGER.transitionConfigToPlay(player, false);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ public final class KeepAliveListener {
|
||||
private static final Component KICK_MESSAGE = Component.text("Bad Keep Alive packet", NamedTextColor.RED);
|
||||
|
||||
public static void listener(ClientKeepAlivePacket packet, Player player) {
|
||||
System.out.println("KEEP ALIVE LISTENER");
|
||||
final long packetId = packet.id();
|
||||
if (packetId != player.getLastKeepAlive()) {
|
||||
player.kick(KICK_MESSAGE);
|
||||
|
@ -89,7 +89,7 @@ public final class LoginListener {
|
||||
final UUID playerUuid = bungee && isSocketConnection ?
|
||||
((PlayerSocketConnection) connection).gameProfile().uuid() :
|
||||
CONNECTION_MANAGER.getPlayerConnectionUuid(connection, packet.username());
|
||||
CONNECTION_MANAGER.startConfigurationState(connection, playerUuid, packet.username());
|
||||
CONNECTION_MANAGER.createPlayer(connection, playerUuid, packet.username());
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,7 +155,7 @@ public final class LoginListener {
|
||||
final String profileName = gameProfile.get("name").getAsString();
|
||||
|
||||
MinecraftServer.LOGGER.info("UUID of player {} is {}", loginUsername, profileUUID);
|
||||
CONNECTION_MANAGER.startConfigurationState(connection, profileUUID, profileName);
|
||||
CONNECTION_MANAGER.createPlayer(connection, profileUUID, profileName);
|
||||
List<GameProfile.Property> propertyList = new ArrayList<>();
|
||||
for (JsonElement element : gameProfile.get("properties").getAsJsonArray()) {
|
||||
JsonObject object = element.getAsJsonObject();
|
||||
@ -208,7 +208,7 @@ public final class LoginListener {
|
||||
if (success) {
|
||||
socketConnection.setRemoteAddress(socketAddress);
|
||||
socketConnection.UNSAFE_setProfile(gameProfile);
|
||||
CONNECTION_MANAGER.startConfigurationState(connection, gameProfile.uuid(), gameProfile.name());
|
||||
CONNECTION_MANAGER.createPlayer(connection, gameProfile.uuid(), gameProfile.name());
|
||||
} else {
|
||||
LoginDisconnectPacket disconnectPacket = new LoginDisconnectPacket(INVALID_PROXY_RESPONSE);
|
||||
socketConnection.sendPacket(disconnectPacket);
|
||||
@ -219,7 +219,6 @@ public final class LoginListener {
|
||||
|
||||
public static void loginAckListener(@NotNull ClientLoginAcknowledgedPacket ignored, @NotNull PlayerConnection connection) {
|
||||
final Player player = Objects.requireNonNull(connection.getPlayer());
|
||||
CONNECTION_MANAGER.registerPlayer(player);
|
||||
|
||||
// Registry data
|
||||
var registry = new HashMap<String, NBT>();
|
||||
@ -236,7 +235,7 @@ public final class LoginListener {
|
||||
connection.sendPacket(PluginMessagePacket.getBrandPacket());
|
||||
|
||||
// Enter configuration phase (for the first time)
|
||||
player.startConfigurationPhase();
|
||||
CONNECTION_MANAGER.transitionConfigToPlay(player, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,16 +5,20 @@ import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.entity.Player;
|
||||
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.network.packet.client.login.ClientLoginStartPacket;
|
||||
import net.minestom.server.network.packet.server.common.KeepAlivePacket;
|
||||
import net.minestom.server.network.packet.server.configuration.FinishConfigurationPacket;
|
||||
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;
|
||||
import net.minestom.server.network.player.PlayerSocketConnection;
|
||||
import net.minestom.server.utils.StringUtils;
|
||||
import net.minestom.server.utils.async.AsyncUtils;
|
||||
import net.minestom.server.utils.debug.DebugUtils;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jctools.queues.MessagePassingQueue;
|
||||
import org.jctools.queues.MpscUnboundedArrayQueue;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@ -35,16 +39,16 @@ public final class ConnectionManager {
|
||||
private static final long KEEP_ALIVE_KICK = 30_000;
|
||||
private static final Component TIMEOUT_TEXT = Component.text("Timeout", NamedTextColor.RED);
|
||||
|
||||
private record PendingPlayer(@NotNull Player player, @NotNull Instance instance) {
|
||||
}
|
||||
|
||||
private final MessagePassingQueue<PendingPlayer> waitingPlayers = new MpscUnboundedArrayQueue<>(64);
|
||||
private final Set<Player> configurationPlayers = new CopyOnWriteArraySet<>();
|
||||
private final Set<Player> players = new CopyOnWriteArraySet<>();
|
||||
private final Set<Player> unmodifiablePlayers = Collections.unmodifiableSet(players);
|
||||
|
||||
// All players once their Player object has been instantiated.
|
||||
private final Map<PlayerConnection, Player> connectionPlayerMap = new ConcurrentHashMap<>();
|
||||
// Players waiting to be spawned (post configuration state)
|
||||
private final MessagePassingQueue<Player> waitingPlayers = new MpscUnboundedArrayQueue<>(64);
|
||||
// Players in configuration state
|
||||
private final Set<Player> configurationPlayers = new CopyOnWriteArraySet<>();
|
||||
// Players in play state
|
||||
private final Set<Player> playPlayers = new CopyOnWriteArraySet<>();
|
||||
|
||||
|
||||
// The uuid provider once a player login
|
||||
private volatile UuidProvider uuidProvider = (playerConnection, username) -> UUID.randomUUID();
|
||||
@ -52,27 +56,44 @@ public final class ConnectionManager {
|
||||
private volatile PlayerProvider playerProvider = Player::new;
|
||||
|
||||
/**
|
||||
* Gets all online players.
|
||||
* Gets the number of "online" players, eg for the query response.
|
||||
*
|
||||
* @return an unmodifiable collection containing all the online players
|
||||
* @apiNote Only includes players in the play state, not players in configuration.
|
||||
*/
|
||||
public @NotNull Collection<@NotNull Player> getOnlinePlayers() {
|
||||
return unmodifiablePlayers;
|
||||
public int getOnlinePlayerCount() {
|
||||
return playPlayers.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets online players filtered by state.
|
||||
* Gets players filtered by state.
|
||||
*
|
||||
* <p>States before login are not considered online, and will result in nothing being returned.</p>
|
||||
* @param states The state(s) to return players, if empty all players (play and config) are returned.
|
||||
* <b>Only</b> {@link ConnectionState#CONFIGURATION} and {@link ConnectionState#PLAY} are valid.
|
||||
*
|
||||
* @return An unmodifiable collection containing the filtered players.
|
||||
* @apiNote The returned collection has no defined update behavior relative to the state of the server,
|
||||
* so it should be refetched whenever used, rather than kept and reused.
|
||||
*/
|
||||
public @NotNull Collection<@NotNull Player> getPlayers(@NotNull ConnectionState... state) {
|
||||
// connectionPlayerMap.values().stream()
|
||||
// .filter()
|
||||
return List.of();
|
||||
public @NotNull Collection<@NotNull Player> getPlayers(@NotNull ConnectionState... states) {
|
||||
boolean play = false, config = false;
|
||||
for (var state : states) {
|
||||
switch (state) {
|
||||
case PLAY -> play = true;
|
||||
case CONFIGURATION -> config = true;
|
||||
default -> throw new IllegalArgumentException("Cannot fetch players in " + state + "!");
|
||||
}
|
||||
}
|
||||
|
||||
if (config && !play) { // Only play
|
||||
return Collections.unmodifiableCollection(configurationPlayers);
|
||||
} else if (!config && play) { // Only configuration
|
||||
return Collections.unmodifiableCollection(playPlayers);
|
||||
} else { // Both or neither was specified
|
||||
final var players = new ArrayList<Player>(playPlayers.size() + configurationPlayers.size());
|
||||
players.addAll(configurationPlayers);
|
||||
players.addAll(playPlayers);
|
||||
return Collections.unmodifiableCollection(players);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,11 +111,13 @@ public final class ConnectionManager {
|
||||
* <p>
|
||||
* This can cause issue if two or more players have the same username.
|
||||
*
|
||||
* @param username the player username (ignoreCase)
|
||||
* @param username the player username (case-insensitive)
|
||||
* @param states The state(s) to return players, if empty all players (play and config) are returned.
|
||||
* <b>Only</b> {@link ConnectionState#CONFIGURATION} and {@link ConnectionState#PLAY} are valid.
|
||||
* @return the first player who validate the username condition, null if none was found
|
||||
*/
|
||||
public @Nullable Player getPlayer(@NotNull String username) {
|
||||
for (Player player : getOnlinePlayers()) {
|
||||
public @Nullable Player getPlayer(@NotNull String username, @NotNull ConnectionState... states) {
|
||||
for (Player player : getPlayers(states)) {
|
||||
if (player.getUsername().equalsIgnoreCase(username))
|
||||
return player;
|
||||
}
|
||||
@ -107,10 +130,12 @@ public final class ConnectionManager {
|
||||
* This can cause issue if two or more players have the same UUID.
|
||||
*
|
||||
* @param uuid the player UUID
|
||||
* @param states The state(s) to return players, if empty all players (play and config) are returned.
|
||||
* <b>Only</b> {@link ConnectionState#CONFIGURATION} and {@link ConnectionState#PLAY} are valid.
|
||||
* @return the first player who validate the UUID condition, null if none was found
|
||||
*/
|
||||
public @Nullable Player getPlayer(@NotNull UUID uuid) {
|
||||
for (Player player : getOnlinePlayers()) {
|
||||
public @Nullable Player getPlayer(@NotNull UUID uuid, @NotNull ConnectionState... states) {
|
||||
for (Player player : getPlayers(states)) {
|
||||
if (player.getUuid().equals(uuid))
|
||||
return player;
|
||||
}
|
||||
@ -121,9 +146,11 @@ public final class ConnectionManager {
|
||||
* Finds the closest player matching a given username.
|
||||
*
|
||||
* @param username the player username (can be partial)
|
||||
* @param states The state(s) to return players, if empty all players (play and config) are returned.
|
||||
* <b>Only</b> {@link ConnectionState#CONFIGURATION} and {@link ConnectionState#PLAY} are valid.
|
||||
* @return the closest match, null if no players are online
|
||||
*/
|
||||
public @Nullable Player findPlayer(@NotNull String username) {
|
||||
public @Nullable Player findPlayer(@NotNull String username, @NotNull ConnectionState... states) {
|
||||
Player exact = getPlayer(username);
|
||||
if (exact != null) return exact;
|
||||
final String username1 = username.toLowerCase(Locale.ROOT);
|
||||
@ -132,8 +159,7 @@ public final class ConnectionManager {
|
||||
final String username2 = player.getUsername().toLowerCase(Locale.ROOT);
|
||||
return StringUtils.jaroWinklerScore(username1, username2);
|
||||
};
|
||||
return getOnlinePlayers()
|
||||
.stream()
|
||||
return getPlayers(states).stream()
|
||||
.min(Comparator.comparingDouble(distanceFunction::apply))
|
||||
.filter(player -> distanceFunction.apply(player) > 0)
|
||||
.orElse(null);
|
||||
@ -186,73 +212,35 @@ public final class ConnectionManager {
|
||||
return playerProvider;
|
||||
}
|
||||
|
||||
//todo REDONE TRANSITIONS
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void transitionLoginToConfig(@NotNull Player player) {
|
||||
configurationPlayers.add(player);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void transitionConfigToPlay(@NotNull Player player) {
|
||||
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void transitionPlayToConfig(@NotNull Player player) {
|
||||
configurationPlayers.add(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link Player} to the players list.
|
||||
* <p>
|
||||
* Used during connection, you shouldn't have to do it manually.
|
||||
*
|
||||
* @param player the player
|
||||
* Creates a player object and begins the transition from the login state to the config state.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public synchronized void registerPlayer(@NotNull Player player) {
|
||||
this.players.add(player);
|
||||
this.connectionPlayerMap.put(player.getPlayerConnection(), player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a {@link Player} from the players list.
|
||||
* <p>
|
||||
* Used during disconnection, you shouldn't have to do it manually.
|
||||
*
|
||||
* @param connection the player connection
|
||||
* @see PlayerConnection#disconnect() to properly disconnect a player
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public synchronized void removePlayer(@NotNull PlayerConnection connection) {
|
||||
final Player player = this.connectionPlayerMap.remove(connection);
|
||||
if (player == null) return;
|
||||
this.players.remove(player);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public @NotNull Player startConfigurationState(@NotNull PlayerConnection connection,
|
||||
@NotNull UUID uuid, @NotNull String username) {
|
||||
public @NotNull Player createPlayer(@NotNull PlayerConnection connection, @NotNull UUID uuid, @NotNull String username) {
|
||||
final Player player = playerProvider.createPlayer(uuid, username, connection);
|
||||
startConfigurationState(player);
|
||||
this.connectionPlayerMap.put(connection, player);
|
||||
transitionLoginToConfig(player);
|
||||
return player;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public CompletableFuture<Void> startConfigurationState(@NotNull Player player) {
|
||||
return AsyncUtils.runAsync(() -> {
|
||||
public void transitionLoginToConfig(@NotNull Player player) {
|
||||
AsyncUtils.runAsync(() -> {
|
||||
final PlayerConnection playerConnection = player.getPlayerConnection();
|
||||
|
||||
// Compression
|
||||
if (playerConnection instanceof PlayerSocketConnection socketConnection) {
|
||||
final int threshold = MinecraftServer.getCompressionThreshold();
|
||||
if (threshold > 0) socketConnection.startCompression();
|
||||
}
|
||||
|
||||
// Call pre login event
|
||||
AsyncPlayerPreLoginEvent asyncPlayerPreLoginEvent = new AsyncPlayerPreLoginEvent(player);
|
||||
EventDispatcher.call(asyncPlayerPreLoginEvent);
|
||||
if (!player.isOnline())
|
||||
return; // Player has been kicked
|
||||
|
||||
// Change UUID/Username based on the event
|
||||
{
|
||||
final String eventUsername = asyncPlayerPreLoginEvent.getUsername();
|
||||
@ -273,42 +261,74 @@ public final class ConnectionManager {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void startPlayState(@NotNull Player player, @NotNull Instance instance) {
|
||||
this.waitingPlayers.relaxedOffer(new PendingPlayer(player, instance));
|
||||
public void transitionPlayToConfig(@NotNull Player player) {
|
||||
player.sendPacket(new StartConfigurationPacket());
|
||||
configurationPlayers.add(player);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void transitionConfigToPlay(@NotNull Player player, boolean isFirstConfig) {
|
||||
// Call the event and spawn the player.
|
||||
AsyncUtils.runAsync(() -> {
|
||||
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");
|
||||
|
||||
player.setPendingInstance(spawningInstance);
|
||||
this.waitingPlayers.relaxedOffer(player);
|
||||
player.sendPacket(new FinishConfigurationPacket());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a {@link Player} from the players list.
|
||||
* <p>
|
||||
* Used during disconnection, you shouldn't have to do it manually.
|
||||
*
|
||||
* @param connection the player connection
|
||||
* @see PlayerConnection#disconnect() to properly disconnect a player
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public synchronized void removePlayer(@NotNull PlayerConnection connection) {
|
||||
final Player player = this.connectionPlayerMap.remove(connection);
|
||||
if (player == null) return;
|
||||
this.configurationPlayers.remove(player);
|
||||
this.playPlayers.remove(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdowns the connection manager by kicking all the currently connected players.
|
||||
*/
|
||||
public synchronized void shutdown() {
|
||||
this.players.clear();
|
||||
this.configurationPlayers.clear();
|
||||
this.playPlayers.clear();
|
||||
this.connectionPlayerMap.clear();
|
||||
}
|
||||
|
||||
public void tick(long tickStart) {
|
||||
// Let waiting players into their instances
|
||||
updateWaitingPlayers();
|
||||
handleKeepAlive(tickStart);
|
||||
|
||||
// Send keep alive packets
|
||||
handleKeepAlive(configurationPlayers, tickStart);
|
||||
handleKeepAlive(playPlayers, tickStart);
|
||||
|
||||
// Interpret packets for configuration players
|
||||
for (var player : configurationPlayers) {
|
||||
// System.out.println("CONFIG INTERPRET: " + player.getUsername());
|
||||
|
||||
//todo we are required to do this because when we wait for the config ack packet we are not in an instance so not ticking.
|
||||
// but then once we switch to config the packets must be eval-ed immediately because we are in an instance. What if we change
|
||||
// the protocol state swap to happen immediately when the packet is read, not when its processed?
|
||||
player.interpretPacketQueue();
|
||||
}
|
||||
configurationPlayers.forEach(Player::interpretPacketQueue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects waiting players.
|
||||
*/
|
||||
private void updateWaitingPlayers() {
|
||||
this.waitingPlayers.drain(pp -> {
|
||||
configurationPlayers.remove(pp.player);
|
||||
this.waitingPlayers.drain(player -> {
|
||||
configurationPlayers.remove(player);
|
||||
playPlayers.add(player);
|
||||
|
||||
// Spawn the player at Player#getRespawnPoint
|
||||
CompletableFuture<Void> spawnFuture = pp.player.UNSAFE_init(pp.instance);
|
||||
CompletableFuture<Void> spawnFuture = player.UNSAFE_init();
|
||||
|
||||
// Required to get the exact moment the player spawns
|
||||
if (DebugUtils.INSIDE_TEST) spawnFuture.join();
|
||||
@ -320,10 +340,9 @@ public final class ConnectionManager {
|
||||
*
|
||||
* @param tickStart the time of the update in milliseconds, forwarded to the packet
|
||||
*/
|
||||
private void handleKeepAlive(long tickStart) {
|
||||
//todo need to send keep alives for config players also!!
|
||||
private void handleKeepAlive(@NotNull Collection<Player> playerGroup, long tickStart) {
|
||||
final KeepAlivePacket keepAlivePacket = new KeepAlivePacket(tickStart);
|
||||
for (Player player : getOnlinePlayers()) {
|
||||
for (Player player : playerGroup) {
|
||||
final long lastKeepAlive = tickStart - player.getLastKeepAlive();
|
||||
if (lastKeepAlive > KEEP_ALIVE_DELAY && player.didAnswerKeepAlive()) {
|
||||
player.refreshKeepAlive(tickStart);
|
||||
|
@ -53,10 +53,8 @@ public class PacketProcessor {
|
||||
}
|
||||
|
||||
public ClientPacket process(@NotNull PlayerConnection connection, int packetId, ByteBuffer body) {
|
||||
// System.out.println("READ: " + connection.getClientState() + " " + packetId);
|
||||
final ClientPacket packet = create(connection.getClientState(), packetId, body);
|
||||
final ConnectionState state = connection.getClientState();
|
||||
// System.out.println("READ2: " + state + " " + packet.getClass().getSimpleName());
|
||||
|
||||
// If the packet intends to switch state, do it now.
|
||||
// Since packets are processed next tick for players, we have to switch immediately.
|
||||
@ -67,7 +65,9 @@ public class PacketProcessor {
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
// Process all pre-config packets immediately
|
||||
case HANDSHAKE, STATUS, LOGIN -> packetListenerManager.processClientPacket(state, packet, connection);
|
||||
// Process config and play packets on the next tick
|
||||
case CONFIGURATION, PLAY -> {
|
||||
final Player player = connection.getPlayer();
|
||||
assert player != null;
|
||||
|
@ -7,6 +7,8 @@ import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.server.ServerListPingEvent;
|
||||
import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import net.minestom.server.utils.identity.NamedAndIdentified;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -37,7 +39,7 @@ public class ResponseData {
|
||||
this.entries = new ArrayList<>();
|
||||
this.version = MinecraftServer.VERSION_NAME;
|
||||
this.protocol = MinecraftServer.PROTOCOL_VERSION;
|
||||
this.online = MinecraftServer.getConnectionManager().getOnlinePlayers().size();
|
||||
this.online = MinecraftServer.getConnectionManager().getOnlinePlayerCount();
|
||||
this.maxPlayer = this.online + 1;
|
||||
this.description = DEFAULT_DESCRIPTION;
|
||||
this.favicon = "";
|
||||
|
@ -128,7 +128,7 @@ public class Team implements PacketGroupingAudience {
|
||||
final TeamsPacket addPlayerPacket = new TeamsPacket(teamName,
|
||||
new TeamsPacket.AddEntitiesToTeamAction(toAdd));
|
||||
// Sends to all online players the add player packet
|
||||
PacketUtils.broadcastPacket(addPlayerPacket);
|
||||
PacketUtils.broadcastPlayPacket(addPlayerPacket);
|
||||
|
||||
// invalidate player members
|
||||
this.isPlayerMembersUpToDate = false;
|
||||
@ -159,7 +159,7 @@ public class Team implements PacketGroupingAudience {
|
||||
final TeamsPacket removePlayerPacket = new TeamsPacket(teamName,
|
||||
new TeamsPacket.RemoveEntitiesToTeamAction(toRemove));
|
||||
// Sends to all online player the remove player packet
|
||||
PacketUtils.broadcastPacket(removePlayerPacket);
|
||||
PacketUtils.broadcastPlayPacket(removePlayerPacket);
|
||||
|
||||
// Removes the member from the team
|
||||
this.members.removeAll(toRemove);
|
||||
@ -463,7 +463,7 @@ public class Team implements PacketGroupingAudience {
|
||||
public void sendUpdatePacket() {
|
||||
final var info = new TeamsPacket.UpdateTeamAction(teamDisplayName, friendlyFlags,
|
||||
nameTagVisibility, collisionRule, teamColor, prefix, suffix);
|
||||
PacketUtils.broadcastPacket(new TeamsPacket(teamName, info));
|
||||
PacketUtils.broadcastPlayPacket(new TeamsPacket(teamName, info));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -37,7 +37,7 @@ public final class TeamManager {
|
||||
*/
|
||||
protected void registerNewTeam(@NotNull Team team) {
|
||||
this.teams.add(team);
|
||||
PacketUtils.broadcastPacket(team.createTeamsCreationPacket());
|
||||
PacketUtils.broadcastPlayPacket(team.createTeamsCreationPacket());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -60,7 +60,7 @@ public final class TeamManager {
|
||||
*/
|
||||
public boolean deleteTeam(@NotNull Team team) {
|
||||
// Sends to all online players a team destroy packet
|
||||
PacketUtils.broadcastPacket(team.createTeamDestructionPacket());
|
||||
PacketUtils.broadcastPlayPacket(team.createTeamDestructionPacket());
|
||||
return this.teams.remove(team);
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ public final class PacketUtils {
|
||||
* Checks if the {@link ServerPacket} is suitable to be wrapped into a {@link CachedPacket}.
|
||||
* Note: {@link ComponentHoldingServerPacket}s are not translated inside a {@link CachedPacket}.
|
||||
*
|
||||
* @see CachedPacket#body()
|
||||
* @see CachedPacket#body(ConnectionState)
|
||||
* @see PlayerSocketConnection#writePacketSync(SendablePacket, boolean)
|
||||
*/
|
||||
static boolean shouldUseCachePacket(final @NotNull ServerPacket packet) {
|
||||
@ -153,8 +153,8 @@ public final class PacketUtils {
|
||||
sendGroupedPacket(players, packet, player -> true);
|
||||
}
|
||||
|
||||
public static void broadcastPacket(@NotNull ServerPacket packet) {
|
||||
sendGroupedPacket(MinecraftServer.getConnectionManager().getOnlinePlayers(), packet);
|
||||
public static void broadcastPlayPacket(@NotNull ServerPacket packet) {
|
||||
sendGroupedPacket(MinecraftServer.getConnectionManager().getPlayers(ConnectionState.PLAY), packet);
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
|
@ -11,6 +11,8 @@ import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.GameMode;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import net.minestom.server.utils.MathUtils;
|
||||
import net.minestom.server.utils.math.IntRange;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
@ -27,6 +29,7 @@ import java.util.concurrent.ThreadLocalRandom;
|
||||
* It is based on the target selectors used in commands.
|
||||
*/
|
||||
public class EntityFinder {
|
||||
private static final ConnectionManager CONNECTION_MANAGER = MinecraftServer.getConnectionManager();
|
||||
|
||||
private TargetSelector targetSelector;
|
||||
|
||||
@ -307,8 +310,7 @@ public class EntityFinder {
|
||||
private static @NotNull List<@NotNull Entity> findTarget(@Nullable Instance instance,
|
||||
@NotNull TargetSelector targetSelector,
|
||||
@NotNull Point startPosition, @Nullable Entity self) {
|
||||
final var players = instance != null ?
|
||||
instance.getPlayers() : MinecraftServer.getConnectionManager().getOnlinePlayers();
|
||||
final var players = instance != null ? instance.getPlayers() : CONNECTION_MANAGER.getPlayers(ConnectionState.PLAY);
|
||||
if (targetSelector == TargetSelector.NEAREST_PLAYER) {
|
||||
return players.stream()
|
||||
.min(Comparator.comparingDouble(p -> p.getPosition().distanceSquared(startPosition)))
|
||||
|
@ -40,7 +40,7 @@ final class TestConnectionImpl implements TestConnection {
|
||||
event.getPlayer().setRespawnPoint(pos);
|
||||
});
|
||||
|
||||
return process.connection().startConfigurationState(player, true)
|
||||
return process.connection().createPlayer(player, true)
|
||||
.thenApply(unused -> {
|
||||
process.connection().updateWaitingPlayers();
|
||||
return player;
|
||||
|
Loading…
Reference in New Issue
Block a user