diff --git a/patches/api/Missing-Entity-API.patch b/patches/api/Missing-Entity-API.patch
index e36baa1d03..ea3ea5d81b 100644
--- a/patches/api/Missing-Entity-API.patch
+++ b/patches/api/Missing-Entity-API.patch
@@ -63,62 +63,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    SchoolableFish getSchoolLeader();
 +
 +}
-diff --git a/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntry.java b/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntry.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntry.java
-@@ -0,0 +0,0 @@
-+package io.papermc.paper.potion;
-+
-+import org.bukkit.potion.PotionEffectType;
-+import org.jetbrains.annotations.Contract;
-+import org.jetbrains.annotations.NotNull;
-+
-+/**
-+ * Represents a {@link PotionEffectType} paired with a duration.
-+ */
-+public sealed interface SuspiciousEffectEntry permits SuspiciousEffectEntryImpl {
-+
-+    /**
-+      * Gets the effect type.
-+     *
-+      * @return type
-+      */
-+    @NotNull PotionEffectType effect();
-+
-+    /**
-+      * Gets the duration for this effect instance.
-+      *
-+      * @return duration (in ticks)
-+      */
-+    int duration();
-+
-+    /**
-+     * Creates a new instance of SuspiciousEffectEntry.
-+     *
-+     * @param effectType effect type
-+     * @param duration duration (in ticks)
-+     * @return new instance of an entry
-+     */
-+    @Contract(value = "_, _ -> new", pure = true)
-+    static @NotNull SuspiciousEffectEntry create(final @NotNull PotionEffectType effectType, final int duration) {
-+        return new SuspiciousEffectEntryImpl(effectType, duration);
-+    }
-+}
-diff --git a/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntryImpl.java b/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntryImpl.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntryImpl.java
-@@ -0,0 +0,0 @@
-+package io.papermc.paper.potion;
-+
-+import org.bukkit.potion.PotionEffectType;
-+import org.jetbrains.annotations.NotNull;
-+
-+record SuspiciousEffectEntryImpl(@NotNull PotionEffectType effect, int duration) implements SuspiciousEffectEntry {
-+}
 diff --git a/src/main/java/org/bukkit/entity/AbstractHorse.java b/src/main/java/org/bukkit/entity/AbstractHorse.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/entity/AbstractHorse.java
@@ -719,86 +663,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * @see #isAggressive()
 +     */
 +    void setAggressive(boolean aggressive);
-+    // Paper end
- }
-diff --git a/src/main/java/org/bukkit/entity/MushroomCow.java b/src/main/java/org/bukkit/entity/MushroomCow.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/entity/MushroomCow.java
-+++ b/src/main/java/org/bukkit/entity/MushroomCow.java
-@@ -0,0 +0,0 @@ public interface MushroomCow extends Cow {
-          */
-         BROWN;
-     }
-+    // Paper start
-+    /**
-+     * Gets how long the effect applied to stew
-+     * from this mushroom cow is.
-+     *
-+     * @return duration of the effect (in ticks)
-+     * @deprecated Mushroom cows can now hold multiple effects, use {@link #getStewEffects()}
-+     */
-+    @Deprecated(forRemoval = true)
-+    @org.jetbrains.annotations.Contract("-> fail")
-+    default int getStewEffectDuration() {
-+        throw new UnsupportedOperationException("Mushroom cows can now hold multiple effects. Use #getStewEffects");
-+    }
-+
-+    /**
-+     * Sets how long the effect applied to stew
-+     * from this mushroom cow is.
-+     *
-+     * @param duration duration of the effect (in ticks)
-+     * @deprecated Mushroom cows can now hold multiple effects, use {@link #setStewEffects(java.util.List)}
-+     */
-+    @Deprecated(forRemoval = true)
-+    @org.jetbrains.annotations.Contract("_ -> fail")
-+    default void setStewEffectDuration(int duration) {
-+        throw new UnsupportedOperationException("Mushroom cows can now hold multiple effects. Use #setStewEffects");
-+    }
-+
-+    /**
-+     * Gets the type of effect applied to stew
-+     * from this mushroom cow is.
-+     *
-+     * @return effect type, or null if an effect is currently not set
-+     * @deprecated Mushroom cows can now hold multiple effects, use {@link #getStewEffects()}
-+     * @throws UnsupportedOperationException
-+     */
-+    @Deprecated(forRemoval = true)
-+    @org.jetbrains.annotations.Contract("-> fail")
-+    default org.bukkit.potion.PotionEffectType getStewEffectType() {
-+        throw new UnsupportedOperationException("Mushroom cows can now hold multiple effects. Use #getStewEffects");
-+    }
-+
-+    /**
-+     * Sets the type of effect applied to stew
-+     * from this mushroom cow is.
-+     *
-+     * @param type new effect type
-+     *             or null if this cow does not give effects
-+     * @deprecated Mushroom cows can now hold multiple effects, use {@link #setStewEffects(java.util.List)}
-+     * @throws UnsupportedOperationException
-+     */
-+    @Deprecated(forRemoval = true)
-+    @org.jetbrains.annotations.Contract("_ -> fail")
-+    default void setStewEffect(@org.jetbrains.annotations.Nullable org.bukkit.potion.PotionEffectType type) {
-+        throw new UnsupportedOperationException("Mushroom cows can now hold multiple effects. Use #setStewEffects");
-+    }
-+
-+    /**
-+     * Returns an immutable collection of the effects applied to stew
-+     * items for this mushroom cow.
-+     *
-+     * @return immutable effect entry collection
-+     */
-+    java.util.@NotNull @org.jetbrains.annotations.Unmodifiable List<io.papermc.paper.potion.SuspiciousEffectEntry> getStewEffects();
-+
-+    /**
-+     * Sets effects applied to stew items for this mushroom cow.
-+     *
-+     * @param effects effect entry list
-+     */
-+    void setStewEffects(java.util.@NotNull List<io.papermc.paper.potion.SuspiciousEffectEntry> effects);
 +    // Paper end
  }
 diff --git a/src/main/java/org/bukkit/entity/Panda.java b/src/main/java/org/bukkit/entity/Panda.java
diff --git a/patches/api/Suspicious-Effect-Entry-API.patch b/patches/api/Suspicious-Effect-Entry-API.patch
new file mode 100644
index 0000000000..a5413e860d
--- /dev/null
+++ b/patches/api/Suspicious-Effect-Entry-API.patch
@@ -0,0 +1,215 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
+Date: Sun, 3 Mar 2024 19:45:52 +0100
+Subject: [PATCH] Suspicious Effect Entry API
+
+Exposes a new suspicious effect entry type that properly represents
+storable effects in the context of suspicious effects as they only
+define the potion effect type and duration.
+
+This differentiates them from the existing PotionEffect API found in
+bukkit and hence clarifies that storable values in the parts of the API
+in which it replaces PotionEffect.
+
+Co-authored-by: Yannick Lamprecht <yannicklamprecht@live.de>
+
+diff --git a/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntry.java b/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntry.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntry.java
+@@ -0,0 +0,0 @@
++package io.papermc.paper.potion;
++
++import org.bukkit.potion.PotionEffectType;
++import org.jetbrains.annotations.Contract;
++import org.jetbrains.annotations.NotNull;
++
++/**
++ * Represents a {@link PotionEffectType} paired with a duration.
++ */
++public sealed interface SuspiciousEffectEntry permits SuspiciousEffectEntryImpl {
++
++    /**
++      * Gets the effect type.
++     *
++      * @return type
++      */
++    @NotNull PotionEffectType effect();
++
++    /**
++      * Gets the duration for this effect instance.
++      *
++      * @return duration (in ticks)
++      */
++    int duration();
++
++    /**
++     * Creates a new instance of SuspiciousEffectEntry.
++     *
++     * @param effectType effect type
++     * @param duration duration (in ticks)
++     * @return new instance of an entry
++     */
++    @Contract(value = "_, _ -> new", pure = true)
++    static @NotNull SuspiciousEffectEntry create(final @NotNull PotionEffectType effectType, final int duration) {
++        return new SuspiciousEffectEntryImpl(effectType, duration);
++    }
++}
+diff --git a/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntryImpl.java b/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntryImpl.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/potion/SuspiciousEffectEntryImpl.java
+@@ -0,0 +0,0 @@
++package io.papermc.paper.potion;
++
++import org.bukkit.potion.PotionEffectType;
++import org.jetbrains.annotations.NotNull;
++
++record SuspiciousEffectEntryImpl(@NotNull PotionEffectType effect, int duration) implements SuspiciousEffectEntry {
++}
+diff --git a/src/main/java/org/bukkit/entity/MushroomCow.java b/src/main/java/org/bukkit/entity/MushroomCow.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/entity/MushroomCow.java
++++ b/src/main/java/org/bukkit/entity/MushroomCow.java
+@@ -0,0 +0,0 @@ public interface MushroomCow extends Cow, io.papermc.paper.entity.Shearable { //
+      * Adds a custom potion effect to be applied to the next suspicious stew
+      * received from milking this {@link MushroomCow}.
+      *
++     * @deprecated use {@link #addEffectToNextStew(io.papermc.paper.potion.SuspiciousEffectEntry, boolean)} as PotionEffect suggests that all attributes are used. In fact, only the PotionEffectType and the duration are used.
+      * @param effect the potion effect to add
+      * @param overwrite true if any existing effect of the same type should be
+      * overwritten
+      * @return true if the effects to be applied to the suspicious stew changed
+      * as a result of this call
+      */
++    @Deprecated(forRemoval = true) // Paper - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
+     boolean addEffectToNextStew(@NotNull PotionEffect effect, boolean overwrite);
+ 
++    // Paper start - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
++    /**
++     * Adds a suspicious effect entry to be applied to the next suspicious stew
++     * received from milking this {@link MushroomCow}.
++     *
++     * @param suspiciousEffectEntry the suspicious effect entry to add
++     * @param overwrite true if any existing effect of the same type should be
++     * overwritten
++     * @return true if the effects to be applied to the suspicious stew changed
++     * as a result of this call
++     */
++    boolean addEffectToNextStew(@NotNull io.papermc.paper.potion.SuspiciousEffectEntry suspiciousEffectEntry, boolean overwrite);
++    // Paper end - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
++
+     /**
+      * Removes a custom potion effect from being applied to the next suspicious
+      * stew received from milking this {@link MushroomCow}.
+@@ -0,0 +0,0 @@ public interface MushroomCow extends Cow, io.papermc.paper.entity.Shearable { //
+          */
+         BROWN;
+     }
++    // Paper start
++    /**
++     * Gets how long the effect applied to stew
++     * from this mushroom cow is.
++     *
++     * @return duration of the effect (in ticks)
++     * @deprecated Mushroom cows can now hold multiple effects, use {@link #getStewEffects()}
++     */
++    @Deprecated(forRemoval = true)
++    @org.jetbrains.annotations.Contract("-> fail")
++    default int getStewEffectDuration() {
++        throw new UnsupportedOperationException("Mushroom cows can now hold multiple effects. Use #getStewEffects");
++    }
++
++    /**
++     * Sets how long the effect applied to stew
++     * from this mushroom cow is.
++     *
++     * @param duration duration of the effect (in ticks)
++     * @deprecated Mushroom cows can now hold multiple effects, use {@link #setStewEffects(java.util.List)}
++     */
++    @Deprecated(forRemoval = true)
++    @org.jetbrains.annotations.Contract("_ -> fail")
++    default void setStewEffectDuration(int duration) {
++        throw new UnsupportedOperationException("Mushroom cows can now hold multiple effects. Use #setStewEffects");
++    }
++
++    /**
++     * Gets the type of effect applied to stew
++     * from this mushroom cow is.
++     *
++     * @return effect type, or null if an effect is currently not set
++     * @deprecated Mushroom cows can now hold multiple effects, use {@link #getStewEffects()}
++     * @throws UnsupportedOperationException
++     */
++    @Deprecated(forRemoval = true)
++    @org.jetbrains.annotations.Contract("-> fail")
++    default org.bukkit.potion.PotionEffectType getStewEffectType() {
++        throw new UnsupportedOperationException("Mushroom cows can now hold multiple effects. Use #getStewEffects");
++    }
++
++    /**
++     * Sets the type of effect applied to stew
++     * from this mushroom cow is.
++     *
++     * @param type new effect type
++     *             or null if this cow does not give effects
++     * @deprecated Mushroom cows can now hold multiple effects, use {@link #setStewEffects(java.util.List)}
++     * @throws UnsupportedOperationException
++     */
++    @Deprecated(forRemoval = true)
++    @org.jetbrains.annotations.Contract("_ -> fail")
++    default void setStewEffect(@org.jetbrains.annotations.Nullable org.bukkit.potion.PotionEffectType type) {
++        throw new UnsupportedOperationException("Mushroom cows can now hold multiple effects. Use #setStewEffects");
++    }
++
++    /**
++     * Returns an immutable collection of the effects applied to stew
++     * items for this mushroom cow.
++     *
++     * @return immutable effect entry collection
++     */
++    java.util.@NotNull @org.jetbrains.annotations.Unmodifiable List<io.papermc.paper.potion.SuspiciousEffectEntry> getStewEffects();
++
++    /**
++     * Sets effects applied to stew items for this mushroom cow.
++     *
++     * @param effects effect entry list
++     */
++    void setStewEffects(java.util.@NotNull List<io.papermc.paper.potion.SuspiciousEffectEntry> effects);
++    // Paper end
+ }
+diff --git a/src/main/java/org/bukkit/inventory/meta/SuspiciousStewMeta.java b/src/main/java/org/bukkit/inventory/meta/SuspiciousStewMeta.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/inventory/meta/SuspiciousStewMeta.java
++++ b/src/main/java/org/bukkit/inventory/meta/SuspiciousStewMeta.java
+@@ -0,0 +0,0 @@ public interface SuspiciousStewMeta extends ItemMeta {
+     /**
+      * Adds a custom potion effect to this suspicious stew.
+      *
++     * @deprecated use {@link #addCustomEffect(io.papermc.paper.potion.SuspiciousEffectEntry, boolean)} as PotionEffect suggests that all attributes are used. In fact, only the PotionEffectType and the duration are used.
+      * @param effect the potion effect to add
+      * @param overwrite true if any existing effect of the same type should be
+      * overwritten
+      * @return true if the suspicious stew meta changed as a result of this call
+      */
++    @Deprecated // Paper - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
+     boolean addCustomEffect(@NotNull PotionEffect effect, boolean overwrite);
+ 
++    // Paper start - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
++    /**
++     * Adds a custom potion effect to this suspicious stew.
++     *
++     * @param suspiciousEffectEntry the suspicious effect entry to add
++     * @param overwrite true if any existing effect of the same type should be
++     * overwritten
++     * @return true if the suspicious stew meta changed as a result of this call
++     * as a result of this call
++     */
++    boolean addCustomEffect(@NotNull io.papermc.paper.potion.SuspiciousEffectEntry suspiciousEffectEntry, boolean overwrite);
++    // Paper end - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
++
+     /**
+      * Removes a custom potion effect from this suspicious stew.
+      *
diff --git a/patches/server/Basic-PlayerProfile-API.patch b/patches/server/Basic-PlayerProfile-API.patch
index 66d2a760dc..960fb904d0 100644
--- a/patches/server/Basic-PlayerProfile-API.patch
+++ b/patches/server/Basic-PlayerProfile-API.patch
@@ -554,9 +554,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
 +import com.destroystokyo.paper.profile.CraftPlayerProfile;
 +import com.destroystokyo.paper.profile.PlayerProfile;
+ import com.google.common.collect.ImmutableList;
  import com.google.common.util.concurrent.ThreadFactoryBuilder;
  import io.papermc.paper.math.BlockPosition;
- import io.papermc.paper.math.FinePosition;
 @@ -0,0 +0,0 @@ import net.minecraft.world.level.ClipContext;
  import net.minecraft.world.level.Level;
  import net.minecraft.world.phys.Vec3;
diff --git a/patches/server/Catch-JsonParseException-in-entity-and-block-entity-.patch b/patches/server/Catch-JsonParseException-in-entity-and-block-entity-.patch
index 95b8bc59df..8e3244f36a 100644
--- a/patches/server/Catch-JsonParseException-in-entity-and-block-entity-.patch
+++ b/patches/server/Catch-JsonParseException-in-entity-and-block-entity-.patch
@@ -17,8 +17,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/io/papermc/paper/util/MCUtil.java
 +++ b/src/main/java/io/papermc/paper/util/MCUtil.java
 @@ -0,0 +0,0 @@ public final class MCUtil {
-     public static int getTicketLevelFor(net.minecraft.world.level.chunk.ChunkStatus status) {
-         return net.minecraft.server.level.ChunkMap.MAX_VIEW_DISTANCE + net.minecraft.world.level.chunk.ChunkStatus.getDistance(status);
+ 
+         return builder.build();
      }
 +
 +    @Nullable
diff --git a/patches/server/MC-Utils.patch b/patches/server/MC-Utils.patch
index 85a8e3bbf8..64a7a55535 100644
--- a/patches/server/MC-Utils.patch
+++ b/patches/server/MC-Utils.patch
@@ -3488,6 +3488,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 @@ -0,0 +0,0 @@
 +package io.papermc.paper.util;
 +
++import com.google.common.collect.ImmutableList;
 +import com.google.common.util.concurrent.ThreadFactoryBuilder;
 +import io.papermc.paper.math.BlockPosition;
 +import io.papermc.paper.math.FinePosition;
@@ -3509,6 +3510,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +import org.bukkit.block.BlockFace;
 +import org.bukkit.craftbukkit.CraftWorld;
 +import org.bukkit.craftbukkit.util.Waitable;
++import org.jetbrains.annotations.NotNull;
 +import org.spigotmc.AsyncCatcher;
 +
 +import javax.annotation.Nonnull;
@@ -3524,6 +3526,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +import java.util.concurrent.atomic.AtomicBoolean;
 +import java.util.function.BiConsumer;
 +import java.util.function.Consumer;
++import java.util.function.Predicate;
 +import java.util.function.Supplier;
 +
 +public final class MCUtil {
@@ -4013,6 +4016,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    public static int getTicketLevelFor(net.minecraft.world.level.chunk.ChunkStatus status) {
 +        return net.minecraft.server.level.ChunkMap.MAX_VIEW_DISTANCE + net.minecraft.world.level.chunk.ChunkStatus.getDistance(status);
 +    }
++
++    @NotNull
++    public static <T> List<T> copyListAndAdd(@NotNull final List<T> original,
++                                             @NotNull final T newElement) {
++        return ImmutableList.<T>builderWithExpectedSize(original.size() + 1)
++            .addAll(original)
++            .add(newElement)
++            .build();
++    }
++
++    @NotNull
++    public static <T> List<T> copyListAndRemoveIf(@NotNull final List<T> original,
++                                                  @NotNull final Predicate<T> removalPredicate) {
++        final ImmutableList.Builder<T> builder = ImmutableList.builderWithExpectedSize(original.size());
++        for (int i = 0; i < original.size(); i++) {
++            final T value = original.get(i);
++            if (removalPredicate.test(value)) continue;
++
++            builder.add(value);
++        }
++
++        return builder.build();
++    }
 +}
 diff --git a/src/main/java/io/papermc/paper/util/StackWalkerUtil.java b/src/main/java/io/papermc/paper/util/StackWalkerUtil.java
 new file mode 100644
diff --git a/patches/server/Missing-Entity-API.patch b/patches/server/Missing-Entity-API.patch
index 5fb528e878..ad4a041c50 100644
--- a/patches/server/Missing-Entity-API.patch
+++ b/patches/server/Missing-Entity-API.patch
@@ -848,54 +848,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +    // Paper end
  }
-diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java
-+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java
-@@ -0,0 +0,0 @@ public class CraftMushroomCow extends CraftCow implements MushroomCow {
-         this.getHandle().setVariant(net.minecraft.world.entity.animal.MushroomCow.MushroomType.values()[variant.ordinal()]);
-     }
- 
-+    // Paper start
-+    @Override
-+    public java.util.List<io.papermc.paper.potion.SuspiciousEffectEntry> getStewEffects() {
-+        if (this.getHandle().stewEffects == null) {
-+            return java.util.List.of();
-+        }
-+
-+        java.util.List<io.papermc.paper.potion.SuspiciousEffectEntry> nmsPairs = new java.util.ArrayList<>(this.getHandle().stewEffects.size());
-+        for (final net.minecraft.world.level.block.SuspiciousEffectHolder.EffectEntry effect : this.getHandle().stewEffects) {
-+            nmsPairs.add(io.papermc.paper.potion.SuspiciousEffectEntry.create(
-+                org.bukkit.craftbukkit.potion.CraftPotionEffectType.minecraftToBukkit(effect.effect()),
-+                effect.duration()
-+            ));
-+        }
-+
-+        return java.util.Collections.unmodifiableList(nmsPairs);
-+    }
-+
-+    @Override
-+    public void setStewEffects(final java.util.List<io.papermc.paper.potion.SuspiciousEffectEntry> effects) {
-+        if (effects.isEmpty()) {
-+            this.getHandle().stewEffects = null;
-+            return;
-+        }
-+
-+        java.util.List<net.minecraft.world.level.block.SuspiciousEffectHolder.EffectEntry> nmsPairs = new java.util.ArrayList<>(effects.size());
-+        for (final io.papermc.paper.potion.SuspiciousEffectEntry effect : effects) {
-+            nmsPairs.add(new net.minecraft.world.level.block.SuspiciousEffectHolder.EffectEntry(
-+                org.bukkit.craftbukkit.potion.CraftPotionEffectType.bukkitToMinecraft(effect.effect()),
-+                effect.duration()
-+            ));
-+        }
-+
-+        this.getHandle().stewEffects = nmsPairs;
-+    }
-+    // Paper end
-+
-     @Override
-     public String toString() {
-         return "CraftMushroomCow";
 diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPanda.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPanda.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPanda.java
diff --git a/patches/server/Suspicious-Effect-Entry-API.patch b/patches/server/Suspicious-Effect-Entry-API.patch
new file mode 100644
index 0000000000..3e9eabf028
--- /dev/null
+++ b/patches/server/Suspicious-Effect-Entry-API.patch
@@ -0,0 +1,247 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
+Date: Sun, 3 Mar 2024 19:43:40 +0100
+Subject: [PATCH] Suspicious Effect Entry API
+
+Exposes a new suspicious effect entry type that properly represents
+storable effects in the context of suspicious effects as they only
+define the potion effect type and duration.
+
+This differentiates them from the existing PotionEffect API found in
+bukkit and hence clarifies that storable values in the parts of the API
+in which it replaces PotionEffect.
+
+Co-authored-by: Yannick Lamprecht <yannicklamprecht@live.de>
+
+diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java
++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java
+@@ -0,0 +0,0 @@ public class CraftMushroomCow extends CraftCow implements MushroomCow, io.paperm
+         return ImmutableList.of();
+     }
+ 
++    // Paper start - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
+     @Override
+     public boolean addEffectToNextStew(PotionEffect potionEffect, boolean overwrite) {
+         Preconditions.checkArgument(potionEffect != null, "PotionEffect cannot be null");
+-        MobEffectInstance minecraftPotionEffect = CraftPotionUtil.fromBukkit(potionEffect);
+-        if (!overwrite && this.hasEffectForNextStew(potionEffect.getType())) {
++        return addEffectToNextStew(io.papermc.paper.potion.SuspiciousEffectEntry.create(potionEffect.getType(), potionEffect.getDuration()), overwrite);
++    }
++
++    @Override
++    public boolean addEffectToNextStew(io.papermc.paper.potion.SuspiciousEffectEntry suspiciousEffectEntry, boolean overwrite) {
++        Preconditions.checkArgument(suspiciousEffectEntry != null, "SuspiciousEffectEntry cannot be null");
++        MobEffect minecraftPotionEffect = CraftPotionEffectType.bukkitToMinecraft(suspiciousEffectEntry.effect());
++        if (!overwrite && this.hasEffectForNextStew(suspiciousEffectEntry.effect())) {
+             return false;
+         }
++        SuspiciousEffectHolder.EffectEntry recordSuspiciousEffect = new SuspiciousEffectHolder.EffectEntry(minecraftPotionEffect, suspiciousEffectEntry.duration());
++        this.removeEffectFromNextStew(suspiciousEffectEntry.effect()); // Avoid duplicates of effects
++        // Paper start - fix modification of immutable stew effects list
+         if (this.getHandle().stewEffects == null) {
+-            this.getHandle().stewEffects = new ArrayList<>();
++            this.getHandle().stewEffects = List.of(recordSuspiciousEffect);
++        } else {
++            this.getHandle().stewEffects = io.papermc.paper.util.MCUtil.copyListAndAdd(this.getHandle().stewEffects, recordSuspiciousEffect);
+         }
+-        SuspiciousEffectHolder.EffectEntry recordSuspiciousEffect = new SuspiciousEffectHolder.EffectEntry(minecraftPotionEffect.getEffect(), minecraftPotionEffect.getDuration());
+-        this.removeEffectFromNextStew(potionEffect.getType()); // Avoid duplicates of effects
+-        return this.getHandle().stewEffects.add(recordSuspiciousEffect);
++        // Paper end - fix modification of immutable stew effects list
++        return true;
+     }
++    // Paper end - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
+ 
+     @Override
+     public boolean removeEffectFromNextStew(PotionEffectType potionEffectType) {
+@@ -0,0 +0,0 @@ public class CraftMushroomCow extends CraftCow implements MushroomCow, io.paperm
+             return false;
+         }
+         MobEffect minecraftPotionEffectType = CraftPotionEffectType.bukkitToMinecraft(potionEffectType);
+-        return this.getHandle().stewEffects.removeIf(recordSuspiciousEffect -> recordSuspiciousEffect.effect().equals(minecraftPotionEffectType));
++        // Paper start - fix modification of immutable stew effects list
++        if (this.getHandle().stewEffects == null) return false;
++
++        final int oldSize = this.getHandle().stewEffects.size();
++        this.getHandle().stewEffects = io.papermc.paper.util.MCUtil.copyListAndRemoveIf(
++            this.getHandle().stewEffects, s -> java.util.Objects.equals(s.effect(), minecraftPotionEffectType)
++        );
++
++        final int newSize = this.getHandle().stewEffects.size();
++        if (newSize == 0) {
++            this.getHandle().stewEffects = null; // Null the empty list, mojang expect this
++        }
++
++        return oldSize != newSize; // Yield back if the size changed, implying an object was removed.
++        // Paper end - fix modification of immutable stew effects list
+     }
+ 
+     @Override
+@@ -0,0 +0,0 @@ public class CraftMushroomCow extends CraftCow implements MushroomCow, io.paperm
+         this.getHandle().setVariant(net.minecraft.world.entity.animal.MushroomCow.MushroomType.values()[variant.ordinal()]);
+     }
+ 
++    // Paper start
++    @Override
++    public java.util.List<io.papermc.paper.potion.SuspiciousEffectEntry> getStewEffects() {
++        if (this.getHandle().stewEffects == null) {
++            return java.util.List.of();
++        }
++
++        java.util.List<io.papermc.paper.potion.SuspiciousEffectEntry> nmsPairs = new java.util.ArrayList<>(this.getHandle().stewEffects.size());
++        for (final net.minecraft.world.level.block.SuspiciousEffectHolder.EffectEntry effect : this.getHandle().stewEffects) {
++            nmsPairs.add(io.papermc.paper.potion.SuspiciousEffectEntry.create(
++                org.bukkit.craftbukkit.potion.CraftPotionEffectType.minecraftToBukkit(effect.effect()),
++                effect.duration()
++            ));
++        }
++
++        return java.util.Collections.unmodifiableList(nmsPairs);
++    }
++
++    @Override
++    public void setStewEffects(final java.util.List<io.papermc.paper.potion.SuspiciousEffectEntry> effects) {
++        if (effects.isEmpty()) {
++            this.getHandle().stewEffects = null;
++            return;
++        }
++
++        java.util.List<net.minecraft.world.level.block.SuspiciousEffectHolder.EffectEntry> nmsPairs = new java.util.ArrayList<>(effects.size());
++        for (final io.papermc.paper.potion.SuspiciousEffectEntry effect : effects) {
++            nmsPairs.add(new net.minecraft.world.level.block.SuspiciousEffectHolder.EffectEntry(
++                org.bukkit.craftbukkit.potion.CraftPotionEffectType.bukkitToMinecraft(effect.effect()),
++                effect.duration()
++            ));
++        }
++
++        this.getHandle().stewEffects = nmsPairs;
++    }
++    // Paper end
++
+     @Override
+     public String toString() {
+         return "CraftMushroomCow";
+diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSuspiciousStew.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSuspiciousStew.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSuspiciousStew.java
++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSuspiciousStew.java
+@@ -0,0 +0,0 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
+     static final ItemMetaKey EFFECTS = new ItemMetaKey("effects", "effects");
+     static final ItemMetaKey ID = new ItemMetaKey("id", "id");
+ 
+-    private List<PotionEffect> customEffects;
++    private List<io.papermc.paper.potion.SuspiciousEffectEntry> customEffects; // Paper - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
+ 
+     CraftMetaSuspiciousStew(CraftMetaItem meta) {
+         super(meta);
+@@ -0,0 +0,0 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
+                     duration = net.minecraft.world.item.SuspiciousStewItem.DEFAULT_DURATION;
+                 }
+                 // Paper end start - default duration is 160
+-                this.customEffects.add(new PotionEffect(type, duration, 0));
++                this.customEffects.add(io.papermc.paper.potion.SuspiciousEffectEntry.create(type, duration)); // Paper - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
+             }
+         }
+     }
+@@ -0,0 +0,0 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
+             ListTag effectList = new ListTag();
+             tag.put(CraftMetaSuspiciousStew.EFFECTS.NBT, effectList);
+ 
+-            for (PotionEffect effect : this.customEffects) {
++            // Paper start - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
++            for (io.papermc.paper.potion.SuspiciousEffectEntry effect : this.customEffects) {
+                 CompoundTag effectData = new CompoundTag();
+-                effectData.putString(CraftMetaSuspiciousStew.ID.NBT, effect.getType().getKey().toString());
+-                if (effect.getDuration() != net.minecraft.world.item.SuspiciousStewItem.DEFAULT_DURATION) effectData.putInt(CraftMetaSuspiciousStew.DURATION.NBT, effect.getDuration()); // Paper - don't save duration if it's the default value
++                effectData.putString(CraftMetaSuspiciousStew.ID.NBT, effect.effect().getKey().toString());
++                if (effect.duration() != net.minecraft.world.item.SuspiciousStewItem.DEFAULT_DURATION) effectData.putInt(CraftMetaSuspiciousStew.DURATION.NBT, effect.duration()); // Paper - don't save duration if it's the default value
+                 effectList.add(effectData);
+             }
++            // Paper end - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
+         }
+     }
+ 
+@@ -0,0 +0,0 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
+     @Override
+     public List<PotionEffect> getCustomEffects() {
+         if (this.hasCustomEffects()) {
+-            return ImmutableList.copyOf(this.customEffects);
++            return this.customEffects.stream().map(suspiciousEffectEntry -> suspiciousEffectEntry.effect().createEffect(suspiciousEffectEntry.duration(), 0)).toList(); // Paper - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
+         }
+         return ImmutableList.of();
+     }
+@@ -0,0 +0,0 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
+     @Override
+     public boolean addCustomEffect(PotionEffect effect, boolean overwrite) {
+         Preconditions.checkArgument(effect != null, "Potion effect cannot be null");
++        return addCustomEffect(io.papermc.paper.potion.SuspiciousEffectEntry.create(effect.getType(), effect.getDuration()), overwrite); // Paper - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
++    }
+ 
+-        int index = this.indexOfEffect(effect.getType());
++    // Paper start - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
++    @Override
++    public boolean addCustomEffect(final io.papermc.paper.potion.SuspiciousEffectEntry suspiciousEffectEntry, final boolean overwrite) {
++        Preconditions.checkArgument(suspiciousEffectEntry != null, "Suspicious effect entry cannot be null");
++        int index = this.indexOfEffect(suspiciousEffectEntry.effect());
+         if (index != -1) {
+             if (overwrite) {
+-                PotionEffect old = this.customEffects.get(index);
+-                if (old.getDuration() == effect.getDuration()) {
++                io.papermc.paper.potion.SuspiciousEffectEntry old = this.customEffects.get(index);
++                if (old.duration() == suspiciousEffectEntry.duration()) {
+                     return false;
+                 }
+-                this.customEffects.set(index, effect);
++                this.customEffects.set(index, suspiciousEffectEntry);
+                 return true;
+             } else {
+                 return false;
+@@ -0,0 +0,0 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
+             if (this.customEffects == null) {
+                 this.customEffects = new ArrayList<>();
+             }
+-            this.customEffects.add(effect);
++            this.customEffects.add(suspiciousEffectEntry);
+             return true;
+         }
+     }
++    // Paper end - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
+ 
+     @Override
+     public boolean removeCustomEffect(PotionEffectType type) {
+@@ -0,0 +0,0 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
+         }
+ 
+         boolean changed = false;
+-        Iterator<PotionEffect> iterator = this.customEffects.iterator();
++        // Paper start - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
++        Iterator<io.papermc.paper.potion.SuspiciousEffectEntry> iterator = this.customEffects.iterator();
+         while (iterator.hasNext()) {
+-            PotionEffect effect = iterator.next();
+-            if (type.equals(effect.getType())) {
++            io.papermc.paper.potion.SuspiciousEffectEntry effect = iterator.next();
++            if (type.equals(effect.effect())) {
++        // Paper end - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
+                 iterator.remove();
+                 changed = true;
+             }
+@@ -0,0 +0,0 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
+         }
+ 
+         for (int i = 0; i < this.customEffects.size(); i++) {
+-            if (this.customEffects.get(i).getType().equals(type)) {
++            if (this.customEffects.get(i).effect().equals(type)) { // Paper - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
+                 return i;
+             }
+         }
+@@ -0,0 +0,0 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
+         super.serialize(builder);
+ 
+         if (this.hasCustomEffects()) {
+-            builder.put(CraftMetaSuspiciousStew.EFFECTS.BUKKIT, ImmutableList.copyOf(this.customEffects));
++            builder.put(CraftMetaSuspiciousStew.EFFECTS.BUKKIT, ImmutableList.copyOf(com.google.common.collect.Lists.transform(this.customEffects, s -> new PotionEffect(s.effect(), s.duration(), 0)))); // Paper - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta - convert back to potion effect for bukkit legacy item serialisation to maintain backwards compatibility for the written format.
+         }
+ 
+         return builder;