From 3114e253ce99f6346ca89be58b552844f6e18469 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 13 Jul 2023 14:43:45 -0700
Subject: [PATCH] Fix BanList API (#9450)

---
 patches/api/Fix-BanList-API.patch    | 113 +++++++++++
 patches/server/Fix-BanList-API.patch | 288 +++++++++++++++++++++++++++
 2 files changed, 401 insertions(+)
 create mode 100644 patches/api/Fix-BanList-API.patch
 create mode 100644 patches/server/Fix-BanList-API.patch

diff --git a/patches/api/Fix-BanList-API.patch b/patches/api/Fix-BanList-API.patch
new file mode 100644
index 0000000000..dea482e583
--- /dev/null
+++ b/patches/api/Fix-BanList-API.patch
@@ -0,0 +1,113 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jake Potrebic <jake.m.potrebic@gmail.com>
+Date: Tue, 4 Jul 2023 11:27:18 -0700
+Subject: [PATCH] Fix BanList API
+
+
+diff --git a/src/main/java/org/bukkit/BanList.java b/src/main/java/org/bukkit/BanList.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/BanList.java
++++ b/src/main/java/org/bukkit/BanList.java
+@@ -0,0 +0,0 @@ public interface BanList<T> {
+      */
+     @Deprecated
+     @Nullable
+-    public BanEntry<T> getBanEntry(@NotNull String target);
++    public <E extends BanEntry<? super T>> E getBanEntry(@NotNull String target); // Paper
+ 
+     /**
+      * Gets a {@link BanEntry} by target.
+@@ -0,0 +0,0 @@ public interface BanList<T> {
+      */
+     @Deprecated
+     @Nullable
+-    public BanEntry<T> addBan(@NotNull String target, @Nullable String reason, @Nullable Date expires, @Nullable String source);
++    public <E extends BanEntry<? super T>> E addBan(@NotNull String target, @Nullable String reason, @Nullable Date expires, @Nullable String source); // Paper
+ 
+     /**
+      * Adds a ban to this list. If a previous ban exists, this will
+@@ -0,0 +0,0 @@ public interface BanList<T> {
+      * @return an immutable set containing every entry tracked by this list
+      */
+     @NotNull
+-    public Set<BanEntry<T>> getEntries();
++    public <E extends BanEntry<? super T>> Set<E> getEntries(); // Paper
+ 
+     /**
+      * Gets if a {@link BanEntry} exists for the target, indicating an active
+diff --git a/src/main/java/org/bukkit/OfflinePlayer.java b/src/main/java/org/bukkit/OfflinePlayer.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/OfflinePlayer.java
++++ b/src/main/java/org/bukkit/OfflinePlayer.java
+@@ -0,0 +0,0 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio
+      *     (updated) previous ban
+      */
+     @Nullable
+-    public BanEntry<PlayerProfile> ban(@Nullable String reason, @Nullable Date expires, @Nullable String source);
++    public <E extends BanEntry<? super com.destroystokyo.paper.profile.PlayerProfile>> E ban(@Nullable String reason, @Nullable Date expires, @Nullable String source);
+ 
+     /**
+      * Checks if this player is whitelisted or not
+diff --git a/src/main/java/org/bukkit/ban/ProfileBanList.java b/src/main/java/org/bukkit/ban/ProfileBanList.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/ban/ProfileBanList.java
++++ b/src/main/java/org/bukkit/ban/ProfileBanList.java
+@@ -0,0 +0,0 @@ import org.jetbrains.annotations.Nullable;
+ /**
+  * A {@link BanList} targeting player profile bans.
+  */
+-public interface ProfileBanList extends BanList<PlayerProfile> {
++public interface ProfileBanList extends BanList<com.destroystokyo.paper.profile.PlayerProfile> { // Paper
+ 
+     /**
+      * {@inheritDoc}
+@@ -0,0 +0,0 @@ public interface ProfileBanList extends BanList<PlayerProfile> {
+      * @return the entry for the newly created ban, or the entry for the
+      *     (updated) previous ban
+      * @throws IllegalArgumentException if ProfilePlayer has an invalid UUID
++     * @deprecated use {@link #addBan(com.destroystokyo.paper.profile.PlayerProfile, String, Date, String)}
+      */
+     @Nullable
+-    public BanEntry<PlayerProfile> addBan(@NotNull PlayerProfile target, @Nullable String reason, @Nullable Date expires, @Nullable String source);
++    // Paper start
++    @Deprecated
++    public <E extends BanEntry<? super com.destroystokyo.paper.profile.PlayerProfile>> E addBan(@NotNull PlayerProfile target, @Nullable String reason, @Nullable Date expires, @Nullable String source);
+ 
++    /**
++     * @throws IllegalArgumentException if ProfilePlayer has an invalid UUID
++     */
++    @Nullable BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(com.destroystokyo.paper.profile.@NotNull PlayerProfile target, @Nullable String reason, @Nullable Date expires, @Nullable String source);
++
++    // the 3 methods below are added to maintain compat for the PlayerProfile parameter type
++    /**
++     * @deprecated use {@link #getBanEntry(Object)}
++     */
++    @Deprecated
++    @Nullable <E extends BanEntry<? super com.destroystokyo.paper.profile.PlayerProfile>> E getBanEntry(@NotNull PlayerProfile target);
++
++    /**
++     * @deprecated use {@link #isBanned(Object)}
++     */
++    @Deprecated
++    boolean isBanned(@NotNull PlayerProfile target);
++
++    /**
++     * @deprecated use {@link #pardon(Object)}
++     */
++    @Deprecated
++    void pardon(@NotNull PlayerProfile target);
++    // Paper end
+ }
+diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/entity/Player.java
++++ b/src/main/java/org/bukkit/entity/Player.java
+@@ -0,0 +0,0 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
+      *     (updated) previous ban
+      */
+     @Nullable
+-    public BanEntry<PlayerProfile> ban(@Nullable String reason, @Nullable Date expires, @Nullable String source, boolean kickPlayer);
++    public <E extends BanEntry<? super com.destroystokyo.paper.profile.PlayerProfile>> E ban(@Nullable String reason, @Nullable Date expires, @Nullable String source, boolean kickPlayer); // Paper
+ 
+     /**
+      * Adds this user's current IP address to the {@link IpBanList}. If a previous ban exists, this will
diff --git a/patches/server/Fix-BanList-API.patch b/patches/server/Fix-BanList-API.patch
new file mode 100644
index 0000000000..1be52a9834
--- /dev/null
+++ b/patches/server/Fix-BanList-API.patch
@@ -0,0 +1,288 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jake Potrebic <jake.m.potrebic@gmail.com>
+Date: Tue, 4 Jul 2023 11:27:10 -0700
+Subject: [PATCH] Fix BanList API
+
+
+diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
++++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
+@@ -0,0 +0,0 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
+     }
+ 
+     @Override
+-    public BanEntry<PlayerProfile> ban(String reason, Date expires, String source) {
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Date expires, String source) { // Paper
+         return ((ProfileBanList) this.server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, expires, source);
+     }
+ 
+diff --git a/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanEntry.java b/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanEntry.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanEntry.java
++++ b/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanEntry.java
+@@ -0,0 +0,0 @@ import org.bukkit.BanEntry;
+ import org.bukkit.craftbukkit.profile.CraftPlayerProfile;
+ import org.bukkit.profile.PlayerProfile;
+ 
+-public final class CraftProfileBanEntry implements BanEntry<PlayerProfile> {
++public final class CraftProfileBanEntry implements BanEntry<com.destroystokyo.paper.profile.PlayerProfile> { // Paper
+     private static final Date minorDate = Date.from(Instant.parse("1899-12-31T04:00:00Z"));
+     private final UserBanList list;
+     private final GameProfile profile;
+@@ -0,0 +0,0 @@ public final class CraftProfileBanEntry implements BanEntry<PlayerProfile> {
+     }
+ 
+     @Override
+-    public PlayerProfile getBanTarget() {
+-        return new CraftPlayerProfile(this.profile);
++    public com.destroystokyo.paper.profile.PlayerProfile getBanTarget() { // Paper
++        return new com.destroystokyo.paper.profile.CraftPlayerProfile(this.profile); // Paper
+     }
+ 
+     @Override
+diff --git a/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanList.java b/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanList.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanList.java
++++ b/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanList.java
+@@ -0,0 +0,0 @@ public class CraftProfileBanList implements ProfileBanList {
+     }
+ 
+     @Override
+-    public BanEntry<PlayerProfile> getBanEntry(String target) {
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> getBanEntry(String target) { // Paper
+         Preconditions.checkArgument(target != null, "Target cannot be null");
+ 
+         return this.getBanEntry(CraftProfileBanList.getProfile(target));
+     }
+ 
+     @Override
+-    public BanEntry<PlayerProfile> getBanEntry(PlayerProfile target) {
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> getBanEntry(PlayerProfile target) { // Paper
+         Preconditions.checkArgument(target != null, "Target cannot be null");
+ 
+-        return this.getBanEntry(((CraftPlayerProfile) target).buildGameProfile());
++        return this.getBanEntry(((com.destroystokyo.paper.profile.SharedPlayerProfile) target).buildGameProfile()); // Paper
++    }
++    // Paper start
++    @Override
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> getBanEntry(final com.destroystokyo.paper.profile.PlayerProfile target) {
++        Preconditions.checkArgument(target != null, "target cannot be null");
++
++        return this.getBanEntry(((com.destroystokyo.paper.profile.SharedPlayerProfile) target).buildGameProfile());
++    }
++
++    @Override
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(final com.destroystokyo.paper.profile.PlayerProfile target, final String reason, final Date expires, final String source) {
++        Preconditions.checkArgument(target != null, "PlayerProfile cannot be null");
++        Preconditions.checkArgument(target.getId() != null, "The PlayerProfile UUID cannot be null");
++
++        return this.addBan(((com.destroystokyo.paper.profile.SharedPlayerProfile) target).buildGameProfile(), reason, expires, source);
+     }
+ 
+     @Override
+-    public BanEntry<PlayerProfile> addBan(String target, String reason, Date expires, String source) {
++    public boolean isBanned(final com.destroystokyo.paper.profile.PlayerProfile target) {
++        return this.isBanned((com.destroystokyo.paper.profile.SharedPlayerProfile) target);
++    }
++
++    @Override
++    public void pardon(final com.destroystokyo.paper.profile.PlayerProfile target) {
++        this.pardon((com.destroystokyo.paper.profile.SharedPlayerProfile) target);
++    }
++    // Paper end
++
++    @Override
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(String target, String reason, Date expires, String source) { // Paper
+         Preconditions.checkArgument(target != null, "Ban target cannot be null");
+ 
+         return this.addBan(CraftProfileBanList.getProfileByName(target), reason, expires, source);
+     }
+ 
+     @Override
+-    public BanEntry<PlayerProfile> addBan(PlayerProfile target, String reason, Date expires, String source) {
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(PlayerProfile target, String reason, Date expires, String source) { // Paper
+         Preconditions.checkArgument(target != null, "PlayerProfile cannot be null");
+         Preconditions.checkArgument(target.getUniqueId() != null, "The PlayerProfile UUID cannot be null");
+ 
+-        return this.addBan(((CraftPlayerProfile) target).buildGameProfile(), reason, expires, source);
++        return this.addBan(((com.destroystokyo.paper.profile.SharedPlayerProfile) target).buildGameProfile(), reason, expires, source); // Paper
+     }
+ 
+     @Override
+@@ -0,0 +0,0 @@ public class CraftProfileBanList implements ProfileBanList {
+     }
+ 
+     @Override
+-    public Set<BanEntry<PlayerProfile>> getEntries() {
+-        ImmutableSet.Builder<BanEntry<PlayerProfile>> builder = ImmutableSet.builder();
++    public Set<BanEntry<com.destroystokyo.paper.profile.PlayerProfile>> getEntries() { // Paper
++        ImmutableSet.Builder<BanEntry<com.destroystokyo.paper.profile.PlayerProfile>> builder = ImmutableSet.builder(); // Paper
+         for (UserBanListEntry entry : this.list.getEntries()) {
+             GameProfile profile = entry.getUser();
+             builder.add(new CraftProfileBanEntry(profile, entry, this.list));
+@@ -0,0 +0,0 @@ public class CraftProfileBanList implements ProfileBanList {
+ 
+     @Override
+     public boolean isBanned(PlayerProfile target) {
++        // Paper start
++        return this.isBanned((com.destroystokyo.paper.profile.SharedPlayerProfile) target);
++    }
++    private boolean isBanned(com.destroystokyo.paper.profile.SharedPlayerProfile target) {
++        // Paper end
+         Preconditions.checkArgument(target != null, "Target cannot be null");
+ 
+-        return this.isBanned(((CraftPlayerProfile) target).buildGameProfile());
++        return this.isBanned(target.buildGameProfile()); // Paper
+     }
+ 
+     @Override
+@@ -0,0 +0,0 @@ public class CraftProfileBanList implements ProfileBanList {
+ 
+     @Override
+     public void pardon(PlayerProfile target) {
++        // Paper start
++        this.pardon((com.destroystokyo.paper.profile.SharedPlayerProfile) target);
++    }
++    private void pardon(com.destroystokyo.paper.profile.SharedPlayerProfile target) {
++        // Paper end
+         Preconditions.checkArgument(target != null, "Target cannot be null");
+ 
+-        this.pardon(((CraftPlayerProfile) target).buildGameProfile());
++        this.pardon(target.buildGameProfile()); // Paper
+     }
+ 
+     @Override
+@@ -0,0 +0,0 @@ public class CraftProfileBanList implements ProfileBanList {
+         this.pardon(CraftProfileBanList.getProfile(target));
+     }
+ 
+-    public BanEntry<PlayerProfile> getBanEntry(GameProfile profile) {
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> getBanEntry(GameProfile profile) { // Paper
+         if (profile == null) {
+             return null;
+         }
+@@ -0,0 +0,0 @@ public class CraftProfileBanList implements ProfileBanList {
+         return new CraftProfileBanEntry(profile, entry, this.list);
+     }
+ 
+-    public BanEntry<PlayerProfile> addBan(GameProfile profile, String reason, Date expires, String source) {
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(GameProfile profile, String reason, Date expires, String source) { // Paper
+         if (profile == null) {
+             return null;
+         }
+diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
+     }
+ 
+     @Override
+-    public BanEntry<PlayerProfile> ban(String reason, Date expires, String source) {
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Date expires, String source) { // Paper
+         return this.ban(reason, expires, source, true);
+     }
+ 
+     @Override
+-    public BanEntry<PlayerProfile> ban(String reason, Date expires, String source, boolean kickPlayer) {
+-        BanEntry<PlayerProfile> banEntry = ((ProfileBanList) server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, expires, source);
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Date expires, String source, boolean kickPlayer) { // Paper
++        BanEntry<com.destroystokyo.paper.profile.PlayerProfile> banEntry = ((ProfileBanList) server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, expires, source); // Paper
+         if (kickPlayer) {
+             this.kickPlayer(reason);
+         }
+diff --git a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
++++ b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
+@@ -0,0 +0,0 @@ import org.bukkit.profile.PlayerProfile;
+ import org.bukkit.profile.PlayerTextures;
+ 
+ @SerializableAs("PlayerProfile")
+-public final class CraftPlayerProfile implements PlayerProfile, com.destroystokyo.paper.profile.SharedPlayerProfile { // Paper
++public final class CraftPlayerProfile implements PlayerProfile, com.destroystokyo.paper.profile.SharedPlayerProfile, com.destroystokyo.paper.profile.PlayerProfile { // Paper
+ 
+     @Nonnull
+     public static GameProfile validateSkullProfile(@Nonnull GameProfile gameProfile) {
+@@ -0,0 +0,0 @@ public final class CraftPlayerProfile implements PlayerProfile, com.destroystoky
+     }
+ 
+     @Override
+-    public CompletableFuture<PlayerProfile> update() {
++    public CompletableFuture update() { // Paper - have to remove generic to avoid clashing between bukkit.PlayerProfile and paper.PlayerProfile
+         return CompletableFuture.supplyAsync(this::getUpdatedProfile, Util.PROFILE_EXECUTOR); // Paper - not a good idea to use BLOCKING OPERATIONS on the worldgen executor
+     }
+ 
+@@ -0,0 +0,0 @@ public final class CraftPlayerProfile implements PlayerProfile, com.destroystoky
+         // Paper - diff on change
+         return profile;
+     }
++
++    // Paper start - This must implement our PlayerProfile so generic casts succeed from cb.CraftPlayerProfile to paper.PlayerProfile
++    // The methods don't actually have to be implemented, because the profile should immediately be cast to SharedPlayerProfile
++    @Override
++    public String setName(final String name) {
++        throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
++    }
++
++    @Override
++    public UUID getId() {
++        throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
++    }
++
++    @Override
++    public UUID setId(final UUID uuid) {
++        throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
++    }
++
++    @Override
++    public java.util.Set<com.destroystokyo.paper.profile.ProfileProperty> getProperties() {
++        throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
++    }
++
++    @Override
++    public boolean hasProperty(final String property) {
++        throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
++    }
++
++    @Override
++    public void setProperty(final com.destroystokyo.paper.profile.ProfileProperty property) {
++        throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
++    }
++
++    @Override
++    public void setProperties(final java.util.Collection<com.destroystokyo.paper.profile.ProfileProperty> properties) {
++        throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
++    }
++
++    @Override
++    public void clearProperties() {
++        throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
++    }
++
++    @Override
++    public boolean completeFromCache() {
++        throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
++    }
++
++    @Override
++    public boolean completeFromCache(final boolean onlineMode) {
++        throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
++    }
++
++    @Override
++    public boolean completeFromCache(final boolean lookupUUID, final boolean onlineMode) {
++        throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
++    }
++
++    @Override
++    public boolean complete(final boolean textures) {
++        throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
++    }
++
++    @Override
++    public boolean complete(final boolean textures, final boolean onlineMode) {
++        throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
++    }
+ }