Move patches to unapplied

This commit is contained in:
Nassim Jahnke
2024-12-12 12:22:12 +01:00
parent ff75689b08
commit 45ddf764d9
821 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
--- a/net/minecraft/server/players/BanListEntry.java
+++ b/net/minecraft/server/players/BanListEntry.java
@@ -27,7 +27,7 @@
}
protected BanListEntry(@Nullable T key, JsonObject json) {
- super(key);
+ super(BanListEntry.checkExpiry(key, json)); // CraftBukkit
Date date;
@@ -83,4 +83,22 @@
json.addProperty("expires", this.expires == null ? "forever" : BanListEntry.DATE_FORMAT.format(this.expires));
json.addProperty("reason", this.reason);
}
+
+ // CraftBukkit start
+ private static <T> T checkExpiry(T object, JsonObject jsonobject) {
+ Date expires = null;
+
+ try {
+ expires = jsonobject.has("expires") ? BanListEntry.DATE_FORMAT.parse(jsonobject.get("expires").getAsString()) : null;
+ } catch (ParseException ex) {
+ // Guess we don't have a date
+ }
+
+ if (expires == null || expires.after(new Date())) {
+ return object;
+ } else {
+ return null;
+ }
+ }
+ // CraftBukkit end
}

View File

@@ -0,0 +1,217 @@
--- a/net/minecraft/server/players/GameProfileCache.java
+++ b/net/minecraft/server/players/GameProfileCache.java
@@ -60,6 +60,11 @@
@Nullable
private Executor executor;
+ // Paper start - Fix GameProfileCache concurrency
+ protected final java.util.concurrent.locks.ReentrantLock stateLock = new java.util.concurrent.locks.ReentrantLock();
+ protected final java.util.concurrent.locks.ReentrantLock lookupLock = new java.util.concurrent.locks.ReentrantLock();
+ // Paper end - Fix GameProfileCache concurrency
+
public GameProfileCache(GameProfileRepository profileRepository, File cacheFile) {
this.profileRepository = profileRepository;
this.file = cacheFile;
@@ -67,11 +72,13 @@
}
private void safeAdd(GameProfileCache.GameProfileInfo entry) {
+ try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
GameProfile gameprofile = entry.getProfile();
entry.setLastAccess(this.getNextOperation());
this.profilesByName.put(gameprofile.getName().toLowerCase(Locale.ROOT), entry);
this.profilesByUUID.put(gameprofile.getId(), entry);
+ } finally { this.stateLock.unlock(); } // Paper - Fix GameProfileCache concurrency
}
private static Optional<GameProfile> lookupGameProfile(GameProfileRepository repository, String name) {
@@ -85,10 +92,12 @@
}
public void onProfileLookupFailed(String s1, Exception exception) {
- atomicreference.set((Object) null);
+ atomicreference.set(null); // CraftBukkit - decompile error
}
};
+ if (!org.apache.commons.lang3.StringUtils.isBlank(name) // Paper - Don't lookup a profile with a blank name
+ && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()) // Paper - Add setting for proxy online mode status
repository.findProfilesByNames(new String[]{name}, profilelookupcallback);
GameProfile gameprofile = (GameProfile) atomicreference.get();
@@ -105,7 +114,7 @@
}
private static boolean usesAuthentication() {
- return GameProfileCache.usesAuthentication;
+ return io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode(); // Paper - Add setting for proxy online mode status
}
public void add(GameProfile profile) {
@@ -117,15 +126,29 @@
GameProfileCache.GameProfileInfo usercache_usercacheentry = new GameProfileCache.GameProfileInfo(profile, date);
this.safeAdd(usercache_usercacheentry);
- this.save();
+ if( !org.spigotmc.SpigotConfig.saveUserCacheOnStopOnly ) this.save(true); // Spigot - skip saving if disabled // Paper - Perf: Async GameProfileCache saving
}
private long getNextOperation() {
return this.operationCount.incrementAndGet();
}
+ // Paper start
+ public @Nullable GameProfile getProfileIfCached(String name) {
+ try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
+ GameProfileCache.GameProfileInfo entry = this.profilesByName.get(name.toLowerCase(Locale.ROOT));
+ if (entry == null) {
+ return null;
+ }
+ entry.setLastAccess(this.getNextOperation());
+ return entry.getProfile();
+ } finally { this.stateLock.unlock(); } // Paper - Fix GameProfileCache concurrency
+ }
+ // Paper end
+
public Optional<GameProfile> get(String name) {
String s1 = name.toLowerCase(Locale.ROOT);
+ boolean stateLocked = true; try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByName.get(s1);
boolean flag = false;
@@ -141,19 +164,24 @@
if (usercache_usercacheentry != null) {
usercache_usercacheentry.setLastAccess(this.getNextOperation());
optional = Optional.of(usercache_usercacheentry.getProfile());
+ stateLocked = false; this.stateLock.unlock(); // Paper - Fix GameProfileCache concurrency
} else {
- optional = GameProfileCache.lookupGameProfile(this.profileRepository, s1);
+ stateLocked = false; this.stateLock.unlock(); // Paper - Fix GameProfileCache concurrency
+ try { this.lookupLock.lock(); // Paper - Fix GameProfileCache concurrency
+ optional = GameProfileCache.lookupGameProfile(this.profileRepository, name); // CraftBukkit - use correct case for offline players
+ } finally { this.lookupLock.unlock(); } // Paper - Fix GameProfileCache concurrency
if (optional.isPresent()) {
this.add((GameProfile) optional.get());
flag = false;
}
}
- if (flag) {
- this.save();
+ if (flag && !org.spigotmc.SpigotConfig.saveUserCacheOnStopOnly) { // Spigot - skip saving if disabled
+ this.save(true); // Paper - Perf: Async GameProfileCache saving
}
return optional;
+ } finally { if (stateLocked) { this.stateLock.unlock(); } } // Paper - Fix GameProfileCache concurrency
}
public CompletableFuture<Optional<GameProfile>> getAsync(String username) {
@@ -167,7 +195,7 @@
} else {
CompletableFuture<Optional<GameProfile>> completablefuture1 = CompletableFuture.supplyAsync(() -> {
return this.get(username);
- }, Util.backgroundExecutor().forName("getProfile")).whenCompleteAsync((optional, throwable) -> {
+ }, Util.PROFILE_EXECUTOR).whenCompleteAsync((optional, throwable) -> { // Paper - don't submit BLOCKING PROFILE LOOKUPS to the world gen thread
this.requests.remove(username);
}, this.executor);
@@ -178,6 +206,7 @@
}
public Optional<GameProfile> get(UUID uuid) {
+ try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid);
if (usercache_usercacheentry == null) {
@@ -186,6 +215,7 @@
usercache_usercacheentry.setLastAccess(this.getNextOperation());
return Optional.of(usercache_usercacheentry.getProfile());
}
+ } finally { this.stateLock.unlock(); } // Paper - Fix GameProfileCache concurrency
}
public void setExecutor(Executor executor) {
@@ -208,7 +238,7 @@
label54:
{
- ArrayList arraylist;
+ List<GameProfileCache.GameProfileInfo> arraylist; // CraftBukkit - decompile error
try {
JsonArray jsonarray = (JsonArray) this.gson.fromJson(bufferedreader, JsonArray.class);
@@ -217,7 +247,7 @@
DateFormat dateformat = GameProfileCache.createDateFormat();
jsonarray.forEach((jsonelement) -> {
- Optional optional = GameProfileCache.readGameProfile(jsonelement, dateformat);
+ Optional<GameProfileCache.GameProfileInfo> optional = GameProfileCache.readGameProfile(jsonelement, dateformat); // CraftBukkit - decompile error
Objects.requireNonNull(list);
optional.ifPresent(list::add);
@@ -250,6 +280,11 @@
}
} catch (FileNotFoundException filenotfoundexception) {
;
+ // Spigot Start
+ } catch (com.google.gson.JsonSyntaxException | NullPointerException ex) {
+ GameProfileCache.LOGGER.warn( "Usercache.json is corrupted or has bad formatting. Deleting it to prevent further issues." );
+ this.file.delete();
+ // Spigot End
} catch (JsonParseException | IOException ioexception) {
GameProfileCache.LOGGER.warn("Failed to load profile cache {}", this.file, ioexception);
}
@@ -257,14 +292,15 @@
return list;
}
- public void save() {
+ public void save(boolean asyncSave) { // Paper - Perf: Async GameProfileCache saving
JsonArray jsonarray = new JsonArray();
DateFormat dateformat = GameProfileCache.createDateFormat();
- this.getTopMRUProfiles(1000).forEach((usercache_usercacheentry) -> {
+ this.listTopMRUProfiles(org.spigotmc.SpigotConfig.userCacheCap).forEach((usercache_usercacheentry) -> { // Spigot // Paper - Fix GameProfileCache concurrency
jsonarray.add(GameProfileCache.writeGameProfile(usercache_usercacheentry, dateformat));
});
String s = this.gson.toJson(jsonarray);
+ Runnable save = () -> { // Paper - Perf: Async GameProfileCache saving
try {
BufferedWriter bufferedwriter = Files.newWriter(this.file, StandardCharsets.UTF_8);
@@ -289,13 +325,32 @@
} catch (IOException ioexception) {
;
}
+ // Paper start - Perf: Async GameProfileCache saving
+ };
+ if (asyncSave) {
+ io.papermc.paper.util.MCUtil.scheduleAsyncTask(save);
+ } else {
+ save.run();
+ }
+ // Paper end - Perf: Async GameProfileCache saving
}
private Stream<GameProfileCache.GameProfileInfo> getTopMRUProfiles(int limit) {
- return ImmutableList.copyOf(this.profilesByUUID.values()).stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit((long) limit);
+ // Paper start - Fix GameProfileCache concurrency
+ return this.listTopMRUProfiles(limit).stream();
}
+ private List<GameProfileCache.GameProfileInfo> listTopMRUProfiles(int limit) {
+ try {
+ this.stateLock.lock();
+ return this.profilesByUUID.values().stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit(limit).toList();
+ } finally {
+ this.stateLock.unlock();
+ }
+ }
+ // Paper end - Fix GameProfileCache concurrency
+
private static JsonElement writeGameProfile(GameProfileCache.GameProfileInfo entry, DateFormat dateFormat) {
JsonObject jsonobject = new JsonObject();

View File

@@ -0,0 +1,98 @@
--- a/net/minecraft/server/players/OldUsersConverter.java
+++ b/net/minecraft/server/players/OldUsersConverter.java
@@ -21,6 +21,9 @@
import java.util.UUID;
import javax.annotation.Nullable;
import net.minecraft.core.UUIDUtil;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.NbtAccounter;
+import net.minecraft.nbt.NbtIo;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.util.StringUtil;
@@ -62,7 +65,8 @@
return new String[i];
});
- if (server.usesAuthentication()) {
+ if (server.usesAuthentication() ||
+ (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode())) { // Spigot: bungee = online mode, for now. // Paper - Add setting for proxy online mode status
server.getProfileRepository().findProfilesByNames(astring, callback);
} else {
String[] astring1 = astring;
@@ -85,7 +89,7 @@
try {
gameprofilebanlist.load();
} catch (IOException ioexception) {
- OldUsersConverter.LOGGER.warn("Could not load existing file {}", gameprofilebanlist.getFile().getName(), ioexception);
+ OldUsersConverter.LOGGER.warn("Could not load existing file {}", gameprofilebanlist.getFile().getName()); // CraftBukkit - don't print stacktrace
}
}
@@ -143,7 +147,7 @@
try {
ipbanlist.load();
} catch (IOException ioexception) {
- OldUsersConverter.LOGGER.warn("Could not load existing file {}", ipbanlist.getFile().getName(), ioexception);
+ OldUsersConverter.LOGGER.warn("Could not load existing file {}", ipbanlist.getFile().getName()); // CraftBukkit - don't print stacktrace
}
}
@@ -184,7 +188,7 @@
try {
oplist.load();
} catch (IOException ioexception) {
- OldUsersConverter.LOGGER.warn("Could not load existing file {}", oplist.getFile().getName(), ioexception);
+ OldUsersConverter.LOGGER.warn("Could not load existing file {}", oplist.getFile().getName()); // CraftBukkit - don't print stacktrace
}
}
@@ -228,7 +232,7 @@
try {
whitelist.load();
} catch (IOException ioexception) {
- OldUsersConverter.LOGGER.warn("Could not load existing file {}", whitelist.getFile().getName(), ioexception);
+ OldUsersConverter.LOGGER.warn("Could not load existing file {}", whitelist.getFile().getName()); // CraftBukkit - don't print stacktrace
}
}
@@ -346,7 +350,39 @@
private void movePlayerFile(File playerDataFolder, String fileName, String uuid) {
File file5 = new File(file, fileName + ".dat");
File file6 = new File(playerDataFolder, uuid + ".dat");
+
+ // CraftBukkit start - Use old file name to seed lastKnownName
+ CompoundTag root = null;
+
+ try {
+ root = NbtIo.readCompressed(new java.io.FileInputStream(file5), NbtAccounter.unlimitedHeap());
+ } catch (Exception exception) {
+ // Paper start
+ io.papermc.paper.util.StacktraceDeobfuscator.INSTANCE.deobfuscateThrowable(exception);
+ exception.printStackTrace();
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception);
+ // Paper end
+ }
+ if (root != null) {
+ if (!root.contains("bukkit")) {
+ root.put("bukkit", new CompoundTag());
+ }
+ CompoundTag data = root.getCompound("bukkit");
+ data.putString("lastKnownName", fileName);
+
+ try {
+ NbtIo.writeCompressed(root, new java.io.FileOutputStream(file2));
+ } catch (Exception exception) {
+ // Paper start
+ io.papermc.paper.util.StacktraceDeobfuscator.INSTANCE.deobfuscateThrowable(exception);
+ exception.printStackTrace();
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception);
+ // Paper end
+ }
+ }
+ // CraftBukkit end
+
OldUsersConverter.ensureDirectoryExists(playerDataFolder);
if (!file5.renameTo(file6)) {
throw new OldUsersConverter.ConversionError("Could not convert file for " + fileName);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
--- a/net/minecraft/server/players/SleepStatus.java
+++ b/net/minecraft/server/players/SleepStatus.java
@@ -18,9 +18,12 @@
}
public boolean areEnoughDeepSleeping(int percentage, List<ServerPlayer> players) {
- int j = (int) players.stream().filter(Player::isSleepingLongEnough).count();
+ // CraftBukkit start
+ int j = (int) players.stream().filter((eh) -> { return eh.isSleepingLongEnough() || eh.fauxSleeping; }).count();
+ boolean anyDeepSleep = players.stream().anyMatch(Player::isSleepingLongEnough);
- return j >= this.sleepersNeeded(percentage);
+ return anyDeepSleep && j >= this.sleepersNeeded(percentage);
+ // CraftBukkit end
}
public int sleepersNeeded(int percentage) {
@@ -42,18 +45,24 @@
this.activePlayers = 0;
this.sleepingPlayers = 0;
Iterator iterator = players.iterator();
+ boolean anySleep = false; // CraftBukkit
while (iterator.hasNext()) {
ServerPlayer entityplayer = (ServerPlayer) iterator.next();
if (!entityplayer.isSpectator()) {
++this.activePlayers;
- if (entityplayer.isSleeping()) {
+ if (entityplayer.isSleeping() || entityplayer.fauxSleeping) { // CraftBukkit
++this.sleepingPlayers;
}
+ // CraftBukkit start
+ if (entityplayer.isSleeping()) {
+ anySleep = true;
+ }
+ // CraftBukkit end
}
}
- return (j > 0 || this.sleepingPlayers > 0) && (i != this.activePlayers || j != this.sleepingPlayers);
+ return anySleep && (j > 0 || this.sleepingPlayers > 0) && (i != this.activePlayers || j != this.sleepingPlayers); // CraftBukkit
}
}

View File

@@ -0,0 +1,96 @@
--- a/net/minecraft/server/players/StoredUserList.java
+++ b/net/minecraft/server/players/StoredUserList.java
@@ -30,7 +30,7 @@
private static final Logger LOGGER = LogUtils.getLogger();
private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create();
private final File file;
- private final Map<String, V> map = Maps.newHashMap();
+ private final Map<String, V> map = Maps.newConcurrentMap(); // Paper - Use ConcurrentHashMap in JsonList
public StoredUserList(File file) {
this.file = file;
@@ -53,8 +53,11 @@
@Nullable
public V get(K key) {
- this.removeExpired();
- return (StoredUserEntry) this.map.get(this.getKeyForUser(key));
+ // Paper start - Use ConcurrentHashMap in JsonList
+ return (V) this.map.computeIfPresent(this.getKeyForUser(key), (k, v) -> {
+ return v.hasExpired() ? null : v;
+ });
+ // Paper end - Use ConcurrentHashMap in JsonList
}
public void remove(K key) {
@@ -77,7 +80,7 @@
}
public boolean isEmpty() {
- return this.map.size() < 1;
+ return this.map.isEmpty(); // Paper - Use ConcurrentHashMap in JsonList
}
protected String getKeyForUser(K profile) {
@@ -85,29 +88,12 @@
}
protected boolean contains(K k0) {
+ this.removeExpired(); // CraftBukkit - SPIGOT-7589: Consistently remove expired entries to mirror .get(...)
return this.map.containsKey(this.getKeyForUser(k0));
}
private void removeExpired() {
- List<K> list = Lists.newArrayList();
- Iterator iterator = this.map.values().iterator();
-
- while (iterator.hasNext()) {
- V v0 = (StoredUserEntry) iterator.next();
-
- if (v0.hasExpired()) {
- list.add(v0.getUser());
- }
- }
-
- iterator = list.iterator();
-
- while (iterator.hasNext()) {
- K k0 = iterator.next();
-
- this.map.remove(this.getKeyForUser(k0));
- }
-
+ this.map.values().removeIf(StoredUserEntry::hasExpired); // Paper - Use ConcurrentHashMap in JsonList
}
protected abstract StoredUserEntry<K> createEntry(JsonObject json);
@@ -117,8 +103,9 @@
}
public void save() throws IOException {
+ this.removeExpired(); // Paper - remove expired values before saving
JsonArray jsonarray = new JsonArray();
- Stream stream = this.map.values().stream().map((jsonlistentry) -> {
+ Stream<JsonObject> stream = this.map.values().stream().map((jsonlistentry) -> { // CraftBukkit - decompile error
JsonObject jsonobject = new JsonObject();
Objects.requireNonNull(jsonlistentry);
@@ -171,9 +158,17 @@
StoredUserEntry<K> jsonlistentry = this.createEntry(jsonobject);
if (jsonlistentry.getUser() != null) {
- this.map.put(this.getKeyForUser(jsonlistentry.getUser()), jsonlistentry);
+ this.map.put(this.getKeyForUser(jsonlistentry.getUser()), (V) jsonlistentry); // CraftBukkit - decompile error
}
}
+ // Spigot Start
+ } catch ( com.google.gson.JsonParseException | NullPointerException ex )
+ {
+ org.bukkit.Bukkit.getLogger().log( java.util.logging.Level.WARNING, "Unable to read file " + this.file + ", backing it up to {0}.backup and creating new copy.", ex );
+ File backup = new File( this.file + ".backup" );
+ this.file.renameTo( backup );
+ this.file.delete();
+ // Spigot End
} catch (Throwable throwable) {
if (bufferedreader != null) {
try {

View File

@@ -0,0 +1,42 @@
--- a/net/minecraft/server/players/UserBanListEntry.java
+++ b/net/minecraft/server/players/UserBanListEntry.java
@@ -1,3 +1,4 @@
+// mc-dev import
package net.minecraft.server.players;
import com.google.gson.JsonObject;
@@ -39,20 +40,29 @@
@Nullable
private static GameProfile createGameProfile(JsonObject json) {
- if (json.has("uuid") && json.has("name")) {
+ // Spigot start
+ // this whole method has to be reworked to account for the fact Bukkit only accepts UUID bans and gives no way for usernames to be stored!
+ UUID uuid = null;
+ String name = null;
+ if (json.has("uuid")) {
String s = json.get("uuid").getAsString();
- UUID uuid;
-
try {
uuid = UUID.fromString(s);
} catch (Throwable throwable) {
- return null;
}
- return new GameProfile(uuid, json.get("name").getAsString());
+ }
+ if ( json.has("name"))
+ {
+ name = json.get("name").getAsString();
+ }
+ if ( uuid != null || name != null )
+ {
+ return new GameProfile( uuid, name );
} else {
return null;
}
+ // Spigot End
}
}

View File

@@ -0,0 +1,26 @@
--- a/net/minecraft/server/players/UserWhiteList.java
+++ b/net/minecraft/server/players/UserWhiteList.java
@@ -28,4 +28,23 @@
protected String getKeyForUser(GameProfile gameProfile) {
return gameProfile.getId().toString();
}
+ // Paper start - Add whitelist events
+ @Override
+ public void add(UserWhiteListEntry entry) {
+ if (!new io.papermc.paper.event.server.WhitelistStateUpdateEvent(com.destroystokyo.paper.profile.CraftPlayerProfile.asBukkitCopy(entry.getUser()), io.papermc.paper.event.server.WhitelistStateUpdateEvent.WhitelistStatus.ADDED).callEvent()) {
+ return;
+ }
+
+ super.add(entry);
+ }
+
+ @Override
+ public void remove(GameProfile profile) {
+ if (!new io.papermc.paper.event.server.WhitelistStateUpdateEvent(com.destroystokyo.paper.profile.CraftPlayerProfile.asBukkitCopy(profile), io.papermc.paper.event.server.WhitelistStateUpdateEvent.WhitelistStatus.REMOVED).callEvent()) {
+ return;
+ }
+
+ super.remove(profile);
+ }
+ // Paper end - Add whitelist events
}