9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-29 11:59:24 +00:00

Fix configurable username validation (#551)

* Configurable vanilla username check

* Mark remove all checks as experimental

* More sanity check

* Sanitize name for Purpur AFK system

* [ci/skip] add comment

* Allow old players to join

* Cleanup patch

* [ci/skip] Update patch name
This commit is contained in:
Creeam
2025-11-23 23:38:45 +14:00
committed by GitHub
parent f2a6120c85
commit 2080a06b30
17 changed files with 237 additions and 123 deletions

View File

@@ -0,0 +1,145 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
Date: Wed, 12 Oct 2022 14:36:58 -0400
Subject: [PATCH] Configurable vanilla username check
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index fb585637383db4592f97f0c9040ffa86afb43c6a..29417442b9379779a078e8fc819035120ddf0108 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -2466,7 +2466,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
if (this.level().purpurConfig.idleTimeoutUpdateTabList) {
String scoreboardName = getScoreboardName();
String playerListName = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().serialize(getBukkitEntity().playerListName());
- String[] split = playerListName.split(scoreboardName);
+ String[] split = playerListName.split(java.util.regex.Pattern.quote(scoreboardName)); // Leaf - Vanilla username check - Sanitize name input
String prefix = (split.length > 0 ? split[0] : "").replace(org.purpurmc.purpur.PurpurConfig.afkTabListPrefix, "");
String suffix = (split.length > 1 ? split[1] : "").replace(org.purpurmc.purpur.PurpurConfig.afkTabListSuffix, "");
if (afk) {
diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
index 6d320ed179393e47398c44f2ba2b2285016f349e..0e7a4d6a3b33a8bd9eebd854b87af269cbec6ea6 100644
--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
@@ -163,10 +163,15 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
public void handleHello(ServerboundHelloPacket packet) {
Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet");
// Paper start - Validate usernames
- if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()
+ if (!org.dreeam.leaf.config.modules.misc.VanillaUsernameCheck.removeAllCheck // Leaf - Remove vanilla username check
+ && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()
&& io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.performUsernameValidation
&& !this.iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation) {
- Validate.validState(StringUtil.isReasonablePlayerName(packet.name()), "Invalid characters in username");
+ // Leaf start - Vanilla username check
+ if (!org.dreeam.leaf.config.modules.misc.VanillaUsernameCheck.allowOldPlayersJoin) {
+ Validate.validState(StringUtil.isReasonablePlayerName(packet.name()), "Invalid characters in username");
+ }
+ // Leaf end - Vanilla username check
}
this.requestedUuid = packet.profileId();
// Paper end - Validate usernames
@@ -194,6 +199,15 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
authenticatorPool.execute(() -> {
try {
GameProfile gameprofile = ServerLoginPacketListenerImpl.this.createOfflineProfile(ServerLoginPacketListenerImpl.this.requestedUsername); // Spigot
+ // Leaf start - Vanilla username check
+ if (org.dreeam.leaf.config.modules.misc.VanillaUsernameCheck.allowOldPlayersJoin) {
+ if (server.playerDataStorage.load(gameprofile.getName(), gameprofile.getId().toString(), gameprofile.getId(), net.minecraft.util.ProblemReporter.DISCARDING).orElse(null) != null) {
+ server.getPlayerList().playedPlayers.add(packet.name());
+ } else {
+ Validate.validState(StringUtil.isReasonablePlayerName(packet.name()), "Invalid characters in username");
+ }
+ }
+ // Leaf end - Vanilla username check
gameprofile = ServerLoginPacketListenerImpl.this.callPlayerPreLoginEvents(gameprofile); // Paper - Add more fields to AsyncPlayerPreLoginEvent
ServerLoginPacketListenerImpl.LOGGER.info("UUID of player {} is {}", gameprofile.getName(), gameprofile.getId());
diff --git a/net/minecraft/server/players/GameProfileCache.java b/net/minecraft/server/players/GameProfileCache.java
index 066f84df5c31242ab542932f1e243369d0e766e2..4faa87d18c2e55d6320f9e8ec91862b9e58d26b5 100644
--- a/net/minecraft/server/players/GameProfileCache.java
+++ b/net/minecraft/server/players/GameProfileCache.java
@@ -75,7 +75,7 @@ public class GameProfileCache {
}
private static Optional<GameProfile> lookupGameProfile(GameProfileRepository profileRepo, String name) {
- if (!StringUtil.isValidPlayerName(name)) {
+ if (!StringUtil.isValidPlayerName(name, false)) { // Leaf start - Remove vanilla username check - Directly return, skip unnecessary following logic
return createUnknownProfile(name);
} else {
final boolean shouldLookup = !org.apache.commons.lang3.StringUtils.isBlank(name) // Paper - Don't lookup a profile with a blank name
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 6396083993d248683b887774d2db3f3f03825033..fbf4e548f4377c7155a3a02c3b679a0322ed6bc0 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -136,6 +136,7 @@ public abstract class PlayerList {
private org.bukkit.craftbukkit.CraftServer cserver;
private final Map<String,ServerPlayer> playersByName = new java.util.HashMap<>();
public @Nullable String collideRuleTeamName; // Paper - Configurable player collision
+ public final List<String> playedPlayers = new java.util.concurrent.CopyOnWriteArrayList<>(); // Leaf - Vanilla username check
public PlayerList(MinecraftServer server, LayeredRegistryAccess<RegistryLayer> registries, PlayerDataStorage playerIo, int maxPlayers) {
this.cserver = server.server = new org.bukkit.craftbukkit.CraftServer((net.minecraft.server.dedicated.DedicatedServer) server, this);
@@ -594,6 +595,7 @@ public abstract class PlayerList {
player.getAdvancements().stopListening();
this.players.remove(player);
this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
+ if (org.dreeam.leaf.config.modules.misc.VanillaUsernameCheck.allowOldPlayersJoin) this.playedPlayers.remove(player.getGameProfile().getName()); // Leaf - Vanilla username check
this.removeFromSendAllPlayerInfoBuckets(player); // Gale - Purpur - spread out sending all player info
this.server.getCustomBossEvents().onPlayerDisconnect(player);
UUID uuid = player.getUUID();
diff --git a/net/minecraft/util/StringUtil.java b/net/minecraft/util/StringUtil.java
index c3a99fe7b49858bc0ca9a7f800b0db40465f6901..2f8a5d0b94b548dfc62f2c40bf10218d34c17574 100644
--- a/net/minecraft/util/StringUtil.java
+++ b/net/minecraft/util/StringUtil.java
@@ -64,6 +64,16 @@ public class StringUtil {
}
public static boolean isValidPlayerName(String playerName) {
+ // Leaf start - Remove vanilla username check
+ return isValidPlayerName(playerName, org.dreeam.leaf.config.modules.misc.VanillaUsernameCheck.removeAllCheck);
+ }
+ public static boolean isValidPlayerNameVanilla(String playerName) {
+ return playerName.length() <= 16 && playerName.chars().filter(i -> i <= 32 || i >= 127).findAny().isEmpty();
+ }
+ public static boolean isValidPlayerName(String playerName, boolean bypassCheck) {
+ if (bypassCheck) return playerName.length() <= 16;
+ if (true) return isReasonablePlayerName(playerName); // Leaf - Fix Purpur username validation config
+ // Leaf end - Remove vanilla username check
return playerName.length() <= 16 && playerName.chars().filter(i -> i <= 32 || i >= 127).findAny().isEmpty();
}
@@ -87,7 +97,12 @@ public class StringUtil {
// Paper start - Username validation
public static boolean isReasonablePlayerName(final String name) {
- if (true) return org.purpurmc.purpur.PurpurConfig.usernameValidCharactersPattern.matcher(name).matches(); // Purpur - Configurable valid characters for usernames
+ // Leaf start - Vanilla username check
+ if (true) {
+ if (org.dreeam.leaf.config.modules.misc.VanillaUsernameCheck.allowOldPlayersJoin && net.minecraft.server.MinecraftServer.getServer().getPlayerList().playedPlayers.contains(name)) return true;
+ return org.purpurmc.purpur.PurpurConfig.usernameValidCharactersPattern.matcher(name).matches() && name.length() <= 16; // Purpur - Configurable valid characters for usernames // Leaf - Fix Purpur username validation config - Add length check
+ }
+ // Leaf end - Vanilla username check
if (name.isEmpty() || name.length() > 16) {
return false;
}
diff --git a/net/minecraft/world/item/component/ResolvableProfile.java b/net/minecraft/world/item/component/ResolvableProfile.java
index 48517612ff40c83069a52b817a1af9e6ef180db5..5e6441196a697be73f79e4776209791627a5ecc2 100644
--- a/net/minecraft/world/item/component/ResolvableProfile.java
+++ b/net/minecraft/world/item/component/ResolvableProfile.java
@@ -39,6 +39,15 @@ public record ResolvableProfile(Optional<String> name, Optional<UUID> id, Proper
ResolvableProfile::new
);
+ // Leaf start - Vanilla username check - Enforce skull validation
+ public ResolvableProfile {
+ name = sanitizePlayerName(name);
+ }
+ private static Optional<String> sanitizePlayerName(Optional<String> name) {
+ return org.dreeam.leaf.config.modules.misc.VanillaUsernameCheck.enforceSkullValidation && !net.minecraft.util.StringUtil.isValidPlayerNameVanilla(name.orElse("NULL_OWNER")) ? Optional.of("INVALID_OWNER") : name;
+ }
+ // Leaf end - Vanilla username check - Enforce skull validation
+
public ResolvableProfile(Optional<String> name, Optional<UUID> id, PropertyMap properties) {
this(name, id, properties, createGameProfile(id, name, properties));
}

View File

@@ -1,50 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
Date: Wed, 12 Oct 2022 14:36:58 -0400
Subject: [PATCH] Remove vanilla username check
diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
index 6d320ed179393e47398c44f2ba2b2285016f349e..79534beb5f4a3427078541fda287d9c950999c96 100644
--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
@@ -163,7 +163,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
public void handleHello(ServerboundHelloPacket packet) {
Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet");
// Paper start - Validate usernames
- if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()
+ if (!org.dreeam.leaf.config.modules.misc.RemoveVanillaUsernameCheck.enabled // Leaf - Remove vanilla username check
+ && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()
&& io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.performUsernameValidation
&& !this.iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation) {
Validate.validState(StringUtil.isReasonablePlayerName(packet.name()), "Invalid characters in username");
diff --git a/net/minecraft/server/players/GameProfileCache.java b/net/minecraft/server/players/GameProfileCache.java
index 066f84df5c31242ab542932f1e243369d0e766e2..4faa87d18c2e55d6320f9e8ec91862b9e58d26b5 100644
--- a/net/minecraft/server/players/GameProfileCache.java
+++ b/net/minecraft/server/players/GameProfileCache.java
@@ -75,7 +75,7 @@ public class GameProfileCache {
}
private static Optional<GameProfile> lookupGameProfile(GameProfileRepository profileRepo, String name) {
- if (!StringUtil.isValidPlayerName(name)) {
+ if (!StringUtil.isValidPlayerName(name, false)) { // Leaf start - Remove vanilla username check - Directly return, skip unnecessary following logic
return createUnknownProfile(name);
} else {
final boolean shouldLookup = !org.apache.commons.lang3.StringUtils.isBlank(name) // Paper - Don't lookup a profile with a blank name
diff --git a/net/minecraft/util/StringUtil.java b/net/minecraft/util/StringUtil.java
index c3a99fe7b49858bc0ca9a7f800b0db40465f6901..863c62f076723a4c71a1d07bdc9cc8f9f1739886 100644
--- a/net/minecraft/util/StringUtil.java
+++ b/net/minecraft/util/StringUtil.java
@@ -64,6 +64,12 @@ public class StringUtil {
}
public static boolean isValidPlayerName(String playerName) {
+ // Leaf start - Remove vanilla username check
+ return isValidPlayerName(playerName, org.dreeam.leaf.config.modules.misc.RemoveVanillaUsernameCheck.enabled);
+ }
+ public static boolean isValidPlayerName(String playerName, boolean bypassCheck) {
+ if (bypassCheck) return playerName.length() <= 16;
+ // Leaf end- Remove vanilla username check
return playerName.length() <= 16 && playerName.chars().filter(i -> i <= 32 || i >= 127).findAny().isEmpty();
}

View File

@@ -9,7 +9,7 @@ Original project: https://github.com/Cryptite/Slice
Co-authored-by: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com>
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index fb585637383db4592f97f0c9040ffa86afb43c6a..880bf83929e636872eeb53c5c3ec9357972267db 100644
index 29417442b9379779a078e8fc819035120ddf0108..359f4e5bd5784ca87753c35e69fa11910f6bd1bb 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -431,6 +431,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -21,10 +21,10 @@ index fb585637383db4592f97f0c9040ffa86afb43c6a..880bf83929e636872eeb53c5c3ec9357
// Paper start - rewrite chunk system
private ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader;
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 6396083993d248683b887774d2db3f3f03825033..c315655501aa79333c4a1c5b58382f186df5f7a1 100644
index fbf4e548f4377c7155a3a02c3b679a0322ed6bc0..54be45060a4e822a3a6c50190218e8fbd2963ab6 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -759,11 +759,11 @@ public abstract class PlayerList {
@@ -761,11 +761,11 @@ public abstract class PlayerList {
byte b = (byte)(keepInventory ? 1 : 0);
ServerLevel serverLevel = serverPlayer.level();
LevelData levelData = serverLevel.getLevelData();
@@ -38,7 +38,7 @@ index 6396083993d248683b887774d2db3f3f03825033..c315655501aa79333c4a1c5b58382f18
serverPlayer.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getSharedSpawnPos(), level.getSharedSpawnAngle()));
serverPlayer.connection.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked()));
serverPlayer.connection
@@ -851,6 +851,8 @@ public abstract class PlayerList {
@@ -853,6 +853,8 @@ public abstract class PlayerList {
return serverPlayer;
}

View File

@@ -37,7 +37,7 @@ index fb263fa1f30a7dfcb7ec2656abfb38e5fe88eac9..56fd1ed7ccaf96e7eedea60fbdbf7f93
};
}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 7d301ae8d024608d294738f4a967a9b752f91e8a..2b689b167e5bf2721c9700c365904027f7486d6b 100644
index d12a91455a9d3d910a41f56d6256854bbb7a45b2..899fdbbfc833147e6c604a0baeef824538c53b70 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1739,6 +1739,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -50,7 +50,7 @@ index 7d301ae8d024608d294738f4a967a9b752f91e8a..2b689b167e5bf2721c9700c365904027
this.tickables.get(i).run();
}
diff --git a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
index c5ed0843fdcb066d7fa0aa3075796333862ad923..c04772c15842a07e57d28a979bdceb1fe7547d61 100644
index e2265ea4bfffa17082357575616948459f0f4885..3afb9910966bd77368b385edb3c76e9cb97b8524 100644
--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
@@ -64,6 +64,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
@@ -97,10 +97,10 @@ index c5ed0843fdcb066d7fa0aa3075796333862ad923..c04772c15842a07e57d28a979bdceb1f
bridge.removeChannel(channel);
}
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index c315655501aa79333c4a1c5b58382f186df5f7a1..8724b03cbe22492c17d8d8c60fbd06d60a32925a 100644
index 54be45060a4e822a3a6c50190218e8fbd2963ab6..104e5f443ec211da492af4256c90711d3d35c2bd 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -346,6 +346,8 @@ public abstract class PlayerList {
@@ -347,6 +347,8 @@ public abstract class PlayerList {
player.didPlayerJoinEvent = true; // Gale - EMC - do not process chat/commands before player has joined
@@ -109,7 +109,7 @@ index c315655501aa79333c4a1c5b58382f186df5f7a1..8724b03cbe22492c17d8d8c60fbd06d6
final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
@@ -525,6 +527,7 @@ public abstract class PlayerList {
@@ -526,6 +528,7 @@ public abstract class PlayerList {
return this.remove(player, net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? player.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(player.getDisplayName())));
}
public @Nullable net.kyori.adventure.text.Component remove(ServerPlayer player, net.kyori.adventure.text.Component leaveMessage) {
@@ -117,7 +117,7 @@ index c315655501aa79333c4a1c5b58382f186df5f7a1..8724b03cbe22492c17d8d8c60fbd06d6
// Paper end - Fix kick event leave message not being sent
org.purpurmc.purpur.task.BossBarTask.removeFromAll(player.getBukkitEntity()); // Purpur - Implement TPSBar
ServerLevel serverLevel = player.level();
@@ -1496,6 +1499,7 @@ public abstract class PlayerList {
@@ -1498,6 +1501,7 @@ public abstract class PlayerList {
serverPlayer.connection.send(clientboundUpdateRecipesPacket);
serverPlayer.getRecipeBook().sendInitialRecipeBook(serverPlayer);
}

View File

@@ -9,10 +9,10 @@ Original project: https://github.com/LeavesMC/Leaves
This patch is Powered by Xaero Map
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 8724b03cbe22492c17d8d8c60fbd06d60a32925a..a2d5b58eef4b6def8032d2421f8f3d34e64cb70e 100644
index 104e5f443ec211da492af4256c90711d3d35c2bd..76785d9b11593cc9304e3d16962ddddba2ff8834 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -1206,6 +1206,7 @@ public abstract class PlayerList {
@@ -1208,6 +1208,7 @@ public abstract class PlayerList {
player.connection.send(new ClientboundInitializeBorderPacket(worldBorder));
player.connection.send(new ClientboundSetTimePacket(level.getGameTime(), level.getDayTime(), level.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)));
player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getSharedSpawnPos(), level.getSharedSpawnAngle()));

View File

@@ -342,7 +342,7 @@ index 1d128d0613d92eb95a753be33a1134c857d0e388..c50cb9bfcd06ec54c0a43d013aa074fb
ServerLevel.this.updateSleepingPlayerList();
}
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index a2d5b58eef4b6def8032d2421f8f3d34e64cb70e..5812f425870c8db5a48d3717bba40ff6ace2f0c6 100644
index 76785d9b11593cc9304e3d16962ddddba2ff8834..e0ae31621ececc54b9e38e524c2b56ffb02949a1 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -131,6 +131,7 @@ public abstract class PlayerList {
@@ -353,7 +353,7 @@ index a2d5b58eef4b6def8032d2421f8f3d34e64cb70e..5812f425870c8db5a48d3717bba40ff6
// CraftBukkit start
private org.bukkit.craftbukkit.CraftServer cserver;
@@ -149,6 +150,112 @@ public abstract class PlayerList {
@@ -150,6 +151,112 @@ public abstract class PlayerList {
abstract public void loadAndSaveFiles(); // Paper - fix converting txt to json file; moved from DedicatedPlayerList constructor
@@ -466,7 +466,7 @@ index a2d5b58eef4b6def8032d2421f8f3d34e64cb70e..5812f425870c8db5a48d3717bba40ff6
public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie cookie) {
player.isRealPlayer = true; // Paper
player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed
@@ -318,6 +425,7 @@ public abstract class PlayerList {
@@ -319,6 +426,7 @@ public abstract class PlayerList {
// player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below
this.players.add(player);
@@ -474,7 +474,7 @@ index a2d5b58eef4b6def8032d2421f8f3d34e64cb70e..5812f425870c8db5a48d3717bba40ff6
this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot
this.playersByUUID.put(player.getUUID(), player);
this.addToSendAllPlayerInfoBuckets(player); // Gale - Purpur - spread out sending all player info
@@ -508,6 +616,7 @@ public abstract class PlayerList {
@@ -509,6 +617,7 @@ public abstract class PlayerList {
}
protected void save(ServerPlayer player) {
@@ -482,7 +482,7 @@ index a2d5b58eef4b6def8032d2421f8f3d34e64cb70e..5812f425870c8db5a48d3717bba40ff6
if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit
player.lastSave = MinecraftServer.currentTick; // Paper - Incremental chunk and player saving
this.playerIo.save(player);
@@ -522,6 +631,43 @@ public abstract class PlayerList {
@@ -523,6 +632,43 @@ public abstract class PlayerList {
}
}
@@ -526,15 +526,15 @@ index a2d5b58eef4b6def8032d2421f8f3d34e64cb70e..5812f425870c8db5a48d3717bba40ff6
public @Nullable net.kyori.adventure.text.Component remove(ServerPlayer player) { // CraftBukkit - return string // Paper - return Component
// Paper start - Fix kick event leave message not being sent
return this.remove(player, net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? player.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(player.getDisplayName())));
@@ -596,6 +742,7 @@ public abstract class PlayerList {
@@ -597,6 +743,7 @@ public abstract class PlayerList {
player.retireScheduler(); // Paper - Folia schedulers
player.getAdvancements().stopListening();
this.players.remove(player);
+ this.realPlayers.remove(player); // Leaves - replay api
this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
if (org.dreeam.leaf.config.modules.misc.VanillaUsernameCheck.allowOldPlayersJoin) this.playedPlayers.remove(player.getGameProfile().getName()); // Leaf - Vanilla username check
this.removeFromSendAllPlayerInfoBuckets(player); // Gale - Purpur - spread out sending all player info
this.server.getCustomBossEvents().onPlayerDisconnect(player);
@@ -1009,10 +1156,10 @@ public abstract class PlayerList {
@@ -1011,10 +1158,10 @@ public abstract class PlayerList {
}
public String[] getPlayerNamesArray() {
@@ -548,7 +548,7 @@ index a2d5b58eef4b6def8032d2421f8f3d34e64cb70e..5812f425870c8db5a48d3717bba40ff6
}
return strings;
@@ -1092,7 +1239,7 @@ public abstract class PlayerList {
@@ -1094,7 +1241,7 @@ public abstract class PlayerList {
// Paper start - whitelist verify event / login event
public LoginResult canBypassFullServerLogin(final GameProfile profile, final LoginResult currentResult) {

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Remove useless creating stats json bases on player name logic
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 5812f425870c8db5a48d3717bba40ff6ace2f0c6..f86560200a8625c82961683198541e52c02d7e7f 100644
index e0ae31621ececc54b9e38e524c2b56ffb02949a1..b2dc262b0b5af75f8f6f5447aa9c21527b65205a 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -1546,6 +1546,8 @@ public abstract class PlayerList {
@@ -1548,6 +1548,8 @@ public abstract class PlayerList {
if (serverStatsCounter == null) {
File file = this.server.getWorldPath(LevelResource.PLAYER_STATS_DIR).toFile();
File file1 = new File(file, uuid + ".json");
@@ -17,7 +17,7 @@ index 5812f425870c8db5a48d3717bba40ff6ace2f0c6..f86560200a8625c82961683198541e52
if (!file1.exists()) {
File file2 = new File(file, displayName + ".json"); // CraftBukkit
Path path = file2.toPath();
@@ -1553,6 +1555,8 @@ public abstract class PlayerList {
@@ -1555,6 +1557,8 @@ public abstract class PlayerList {
file2.renameTo(file1);
}
}

View File

@@ -19,7 +19,7 @@ index 287c0936930ff4f3ca6dc2a4cbfc796a120fe4c0..3f32da75ee0a8a993b54e4156f7e4be9
org.purpurmc.purpur.command.DemoCommand.register(this.dispatcher); // Purpur - Add demo command
org.purpurmc.purpur.command.PingCommand.register(this.dispatcher); // Purpur - Add ping command
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 880bf83929e636872eeb53c5c3ec9357972267db..37fe4bbc117c434293689c0a4a1e79e07cff7fd6 100644
index 359f4e5bd5784ca87753c35e69fa11910f6bd1bb..b6f51f001453c8f375a24c1595cec5ba2359c492 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -2434,6 +2434,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -152,10 +152,10 @@ index 2e504082ba5d68874b2d56baa8676b840caf1abe..e61ff0c5051a855e10310d4e6f76d79e
synchronized (this.lastSeenMessages) {
Optional var10000;
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index f86560200a8625c82961683198541e52c02d7e7f..cd7e2e7bdfff90b7147de20dd44fdf2709c4c28f 100644
index b2dc262b0b5af75f8f6f5447aa9c21527b65205a..75fa881f063890874adcc09cb8057804c486497d 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -676,6 +676,7 @@ public abstract class PlayerList {
@@ -677,6 +677,7 @@ public abstract class PlayerList {
org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerLeave(player); // Leaves - protocol
// Paper end - Fix kick event leave message not being sent
org.purpurmc.purpur.task.BossBarTask.removeFromAll(player.getBukkitEntity()); // Purpur - Implement TPSBar

View File

@@ -138,10 +138,10 @@ index 3afb9910966bd77368b385edb3c76e9cb97b8524..f6aec052d8c76df7cb0b734893a85783
if (packet == null || this.processedDisconnect) { // Spigot
return;
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index cd7e2e7bdfff90b7147de20dd44fdf2709c4c28f..f09c1472d465de94b16e958ec7051f34aae7402f 100644
index 75fa881f063890874adcc09cb8057804c486497d..a2ed0ab09a4fc12b2088cc8594b2ce374feb91fd 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -1506,7 +1506,7 @@ public abstract class PlayerList {
@@ -1508,7 +1508,7 @@ public abstract class PlayerList {
public void broadcastChatMessage(PlayerChatMessage message, Predicate<ServerPlayer> shouldFilterMessageTo, @Nullable ServerPlayer sender, ChatType.Bound boundChatType, @Nullable Function<net.kyori.adventure.audience.Audience, Component> unsignedFunction) {
// Paper end
boolean flag = this.verifyChatTrusted(message);
@@ -150,7 +150,7 @@ index cd7e2e7bdfff90b7147de20dd44fdf2709c4c28f..f09c1472d465de94b16e958ec7051f34
OutgoingChatMessage outgoingChatMessage = OutgoingChatMessage.create(message);
boolean flag1 = false;
@@ -1531,6 +1531,7 @@ public abstract class PlayerList {
@@ -1533,6 +1533,7 @@ public abstract class PlayerList {
}
public boolean verifyChatTrusted(PlayerChatMessage message) {

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Configurable connection message
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index f09c1472d465de94b16e958ec7051f34aae7402f..74bbc98c700ac6c6065cf1de4d5486ac39cf0efb 100644
index a2ed0ab09a4fc12b2088cc8594b2ce374feb91fd..d37cd1b23249fed5aeea035f03d3222a027573a8 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -445,7 +445,7 @@ public abstract class PlayerList {
@@ -446,7 +446,7 @@ public abstract class PlayerList {
// Ensure that player inventory is populated with its viewer
player.containerMenu.transferTo(player.containerMenu, bukkitPlayer);
@@ -17,7 +17,7 @@ index f09c1472d465de94b16e958ec7051f34aae7402f..74bbc98c700ac6c6065cf1de4d5486ac
this.cserver.getPluginManager().callEvent(playerJoinEvent);
if (!player.connection.isAcceptingMessages()) {
@@ -458,7 +458,7 @@ public abstract class PlayerList {
@@ -459,7 +459,7 @@ public abstract class PlayerList {
final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
@@ -26,7 +26,7 @@ index f09c1472d465de94b16e958ec7051f34aae7402f..74bbc98c700ac6c6065cf1de4d5486ac
joinMessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(jm); // Paper - Adventure
this.server.getPlayerList().broadcastSystemMessage(joinMessage, false); // Paper - Adventure
}
@@ -685,7 +685,7 @@ public abstract class PlayerList {
@@ -686,7 +686,7 @@ public abstract class PlayerList {
player.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper - Inventory close reason
}
@@ -35,7 +35,7 @@ index f09c1472d465de94b16e958ec7051f34aae7402f..74bbc98c700ac6c6065cf1de4d5486ac
this.cserver.getPluginManager().callEvent(playerQuitEvent);
player.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());
@@ -1659,4 +1659,40 @@ public abstract class PlayerList {
@@ -1661,4 +1661,40 @@ public abstract class PlayerList {
public boolean isAllowCommandsForAllPlayers() {
return this.allowCommandsForAllPlayers;
}

View File

@@ -6,10 +6,10 @@ Subject: [PATCH] Do not place player if the server is full
Fix https://github.com/PaperMC/Paper/issues/10668
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 74bbc98c700ac6c6065cf1de4d5486ac39cf0efb..837fed1c7786d6d3397f70d910cace4cdf2223ce 100644
index d37cd1b23249fed5aeea035f03d3222a027573a8..972a504905e573bc2c9a8f320f7c8aca86873d06 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -349,6 +349,13 @@ public abstract class PlayerList {
@@ -350,6 +350,13 @@ public abstract class PlayerList {
return;
}
// Gale end - MultiPaper - do not place player in world if kicked before being spawned in
@@ -23,7 +23,7 @@ index 74bbc98c700ac6c6065cf1de4d5486ac39cf0efb..837fed1c7786d6d3397f70d910cace4c
org.bukkit.Location loc = ev.getSpawnLocation();
serverLevel = ((org.bukkit.craftbukkit.CraftWorld) loc.getWorld()).getHandle();
@@ -1240,7 +1247,7 @@ public abstract class PlayerList {
@@ -1242,7 +1249,7 @@ public abstract class PlayerList {
// Paper start - whitelist verify event / login event
public LoginResult canBypassFullServerLogin(final GameProfile profile, final LoginResult currentResult) {

View File

@@ -625,7 +625,7 @@ index 073dec29d48b5ab8dd379a1e66a0de6ef101ca1f..e0bd79a371e2c2d370518ae1b9c31064
// Paper start - extra debug info
if (entity.valid) {
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index b8f5cc4540c4a992ae4cf5673886ce6107eb82a8..b8c59df25999183985538ade4e58e01eb9b5b586 100644
index b507065ed1dded25bdc1293014854cab340f4cd6..63d0f915439f9fe22cf6e435a3578b96ce5b990c 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -463,6 +463,8 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -679,10 +679,10 @@ index b8f5cc4540c4a992ae4cf5673886ce6107eb82a8..b8c59df25999183985538ade4e58e01e
// Paper end - Inventory close reason
this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId));
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 837fed1c7786d6d3397f70d910cace4cdf2223ce..8f5d037fcd307b88abfae13e590e987200114b8a 100644
index 972a504905e573bc2c9a8f320f7c8aca86873d06..09da54b32e88b1476dfe80d7924a9847da360d55 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -257,6 +257,7 @@ public abstract class PlayerList {
@@ -258,6 +258,7 @@ public abstract class PlayerList {
// Leaves end - replay mod api
public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie cookie) {
@@ -690,7 +690,7 @@ index 837fed1c7786d6d3397f70d910cace4cdf2223ce..8f5d037fcd307b88abfae13e590e9872
player.isRealPlayer = true; // Paper
player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed
GameProfile gameProfile = player.getGameProfile();
@@ -852,6 +853,15 @@ public abstract class PlayerList {
@@ -854,6 +855,15 @@ public abstract class PlayerList {
}
public ServerPlayer respawn(ServerPlayer player, boolean keepInventory, Entity.RemovalReason reason, @Nullable org.bukkit.event.player.PlayerRespawnEvent.RespawnReason eventReason, @Nullable org.bukkit.Location location) {
@@ -706,7 +706,7 @@ index 837fed1c7786d6d3397f70d910cace4cdf2223ce..8f5d037fcd307b88abfae13e590e9872
player.stopRiding(); // CraftBukkit
this.players.remove(player);
this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
@@ -863,6 +873,7 @@ public abstract class PlayerList {
@@ -865,6 +875,7 @@ public abstract class PlayerList {
ServerPlayer serverPlayer = player;
Level fromWorld = player.level();
player.wonGame = false;

View File

@@ -27,10 +27,10 @@ index 525f29f3ecd7eb12e3d7447898005d3a6d62c093..24f0d13922748eb8a96fd83f14204984
public static final int GENERATED_TICKET_LEVEL = ChunkHolderManager.FULL_LOADED_TICKET_LEVEL;
public static final int LOADED_TICKET_LEVEL = ChunkTaskScheduler.getTicketLevel(ChunkStatus.EMPTY);
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 8f5d037fcd307b88abfae13e590e987200114b8a..e0ca8832b08009bfd6ad906143acd10400b96eb6 100644
index 09da54b32e88b1476dfe80d7924a9847da360d55..a04a3d63db443c25c23353df46591249496e0ded 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -440,6 +440,13 @@ public abstract class PlayerList {
@@ -441,6 +441,13 @@ public abstract class PlayerList {
// this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player))); // CraftBukkit - replaced with loop below
// Paper start - Fire PlayerJoinEvent when Player is actually ready; correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks
player.supressTrackerForLogin = true;

View File

@@ -34,7 +34,7 @@ index d3c6f7f78d895cca4abe1da79abb595c51449afc..7306a3273adf5bfa8ebdec42b7aedf36
for (int i = 0; i < this.tickables.size(); i++) {
this.tickables.get(i).run();
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index b8c59df25999183985538ade4e58e01eb9b5b586..1ac4ad7e9adf9840951d6d22c3a49e072eb3183f 100644
index 63d0f915439f9fe22cf6e435a3578b96ce5b990c..750df3a1c3b8305945b3c70b97bee5214a6d110c 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -810,6 +810,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -63,10 +63,10 @@ index f6aec052d8c76df7cb0b734893a857832a4d29b1..751a73384a6c4c57bf100c040da807e6
final byte[] data = discardedPayload.data();
try {
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index e0ca8832b08009bfd6ad906143acd10400b96eb6..178085c71bb5fee0818a8ce88bf1e36a107a4dd1 100644
index a04a3d63db443c25c23353df46591249496e0ded..37c67a41685056f866fe8b4bb71519f5a13326cb 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -689,6 +689,7 @@ public abstract class PlayerList {
@@ -690,6 +690,7 @@ public abstract class PlayerList {
}
public @Nullable net.kyori.adventure.text.Component remove(ServerPlayer player, net.kyori.adventure.text.Component leaveMessage) {
org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerLeave(player); // Leaves - protocol

View File

@@ -110,10 +110,10 @@ index 7f3379a617932f1e0b0344df75566d2dc6612359..99d9d5048440e535ed6be33df39bf7ae
try {
PlayerList playerList = this.server.getPlayerList();
diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
index f68923c5f6fbecd8f1c10a30dbd06ed0dfee8b84..4fe2fbe7b8329a0507ac94f42b0db78038c566d8 100644
index 970c6f20a3e995dc1b82c3fbabd6ab01a51f22c0..35e8ac5e7a2e4719d407bdc61579d0bc14cc4712 100644
--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
@@ -416,11 +416,31 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
@@ -429,11 +429,31 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
this.disconnect(ServerCommonPacketListenerImpl.DISCONNECT_UNEXPECTED_QUERY);
}

View File

@@ -1,23 +0,0 @@
package org.dreeam.leaf.config.modules.misc;
import org.dreeam.leaf.config.ConfigModules;
import org.dreeam.leaf.config.EnumConfigCategory;
public class RemoveVanillaUsernameCheck extends ConfigModules {
public String getBasePath() {
return EnumConfigCategory.MISC.getBaseKeyName() + ".remove-vanilla-username-check";
}
public static boolean enabled = false;
@Override
public void onLoaded() {
enabled = config.getBoolean(getBasePath(), enabled, config.pickStringRegionBased("""
Remove Vanilla username check,
allowing all characters as username.""",
"""
移除原版的用户名验证,
让所有字符均可作为玩家名."""));
}
}

View File

@@ -0,0 +1,42 @@
package org.dreeam.leaf.config.modules.misc;
import org.dreeam.leaf.config.ConfigModules;
import org.dreeam.leaf.config.EnumConfigCategory;
import org.dreeam.leaf.config.annotations.Experimental;
public class VanillaUsernameCheck extends ConfigModules {
public String getBasePath() {
return EnumConfigCategory.MISC.getBaseKeyName() + ".vanilla-username-check";
}
@Experimental
public static boolean removeAllCheck = false;
public static boolean enforceSkullValidation = true;
@Experimental
public static boolean allowOldPlayersJoin = false;
@Override
public void onLoaded() {
removeAllCheck = config.getBoolean(getBasePath() + ".remove-all-check", removeAllCheck, config.pickStringRegionBased("""
Remove Vanilla username check,
allowing all characters as username.
WARNING: UNSAFE, USE AT YOUR OWN RISK!""",
"""
移除原版的用户名验证,
让所有字符均可作为玩家名.
警告: 完全移除验证非常不安全, 使用风险自负!"""));
enforceSkullValidation = config.getBoolean(getBasePath() + ".enforce-skull-validation", enforceSkullValidation, config.pickStringRegionBased("""
Enforce skull validation,
preventing skulls with invalid names from disconnecting the client.""",
"""
强制启用头颅验证,
避免所有者带有特殊字符的头颅导致客户端掉线."""));
allowOldPlayersJoin = config.getBoolean(getBasePath() + ".allow-old-players-join", allowOldPlayersJoin, config.pickStringRegionBased("""
Allow old players to join the server after the username regex is changed,
even if their names don't meet the new requirements.""",
"""
允许老玩家加入修改用户名验证正则后的服务器,
即使他们的用户名不满足修改后的正则."""));
}
}