diff --git a/paper-api/src/main/java/io/papermc/paper/event/packet/PlayerBiomesLoadEvent.java b/paper-api/src/main/java/io/papermc/paper/event/packet/PlayerBiomesLoadEvent.java new file mode 100644 index 0000000000..96408581b2 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/event/packet/PlayerBiomesLoadEvent.java @@ -0,0 +1,78 @@ +package io.papermc.paper.event.packet; + +import org.bukkit.BiomesSnapshot; +import org.bukkit.Chunk; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.world.ChunkEvent; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.NullMarked; + +/** + * Is called when a {@link Player} receives {@link org.bukkit.block.Biome}s + *
+ * Can for example be used for replacing Biomes when the player receives the Biome list. + *
+ * Should only be used for packet/clientside related stuff. + * Not intended for modifying server side state. + */ +@NullMarked +public class PlayerBiomesLoadEvent extends ChunkEvent { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final Player player; + private @Nullable BiomesSnapshot biomesSnapshot; + + @ApiStatus.Internal + public PlayerBiomesLoadEvent(final Player player, Chunk chunk) { + super(chunk); + this.player = player; + } + + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } + + /** + * Returns the player that is receiving the biomes + * + * @return the player + */ + public Player getPlayer() { + return player; + } + + /** + * Returns a biomes snapshot for the given chunk, by default it won't be set. + * + * @return biome snapshot if one is set + */ + public @Nullable BiomesSnapshot getBiomeSnapshot() { + return biomesSnapshot; + } + + /** + * Sets the biome snapshot for the given chunk that will be sent as an override to the player + * + * @param biomesSnapshot the biome override + */ + public void setBiomeSnapshot(@Nullable final BiomesSnapshot biomesSnapshot) { + this.biomesSnapshot = biomesSnapshot; + } + + /** + * Returns if chunk biomes were overridden + * + * @return true if override was made, else false + */ + public boolean hasOverrides() { + return biomesSnapshot != null; + } +} diff --git a/paper-api/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java b/paper-api/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java index 2815c5802e..26a361de3e 100644 --- a/paper-api/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java +++ b/paper-api/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java @@ -16,7 +16,7 @@ import org.jspecify.annotations.NullMarked; * Not intended for modifying server side state. */ @NullMarked -public class PlayerChunkLoadEvent extends ChunkEvent { +public class PlayerChunkLoadEvent extends PlayerBiomesLoadEvent { private static final HandlerList HANDLER_LIST = new HandlerList(); @@ -24,7 +24,7 @@ public class PlayerChunkLoadEvent extends ChunkEvent { @ApiStatus.Internal public PlayerChunkLoadEvent(final Chunk chunk, final Player player) { - super(chunk); + super(player, chunk); this.player = player; } diff --git a/paper-api/src/main/java/org/bukkit/BiomesSnapshot.java b/paper-api/src/main/java/org/bukkit/BiomesSnapshot.java new file mode 100644 index 0000000000..8fff8be090 --- /dev/null +++ b/paper-api/src/main/java/org/bukkit/BiomesSnapshot.java @@ -0,0 +1,73 @@ +package org.bukkit; + +import org.bukkit.block.Biome; +import org.jspecify.annotations.NullMarked; + +/** + * Represents a static, thread-safe snapshot of chunk of biomes. + *
+ * Purpose is to allow clean, efficient copy of a biome data to be made, and
+ * then handed off for processing in another thread
+ */
+@NullMarked
+public interface BiomesSnapshot {
+
+ /**
+ * Gets the X-coordinate of this chunk
+ *
+ * @return X-coordinate
+ */
+ int getX();
+
+ /**
+ * Gets the Z-coordinate of this chunk
+ *
+ * @return Z-coordinate
+ */
+ int getZ();
+
+ /**
+ * Gets name of the world containing this chunk
+ *
+ * @return Parent World Name
+ */
+ String getWorldName();
+
+ /**
+ * Get biome at given coordinates
+ *
+ * @param x X-coordinate (0-15)
+ * @param y Y-coordinate (world minHeight (inclusive) - world maxHeight (exclusive))
+ * @param z Z-coordinate (0-15)
+ * @return Biome at given coordinate
+ */
+ Biome getBiome(int x, int y, int z);
+
+ /**
+ * Get biome at given coordinates
+ *
+ * @param x X-coordinate (0-15)
+ * @param y Y-coordinate (world minHeight (inclusive) - world maxHeight (exclusive))
+ * @param z Z-coordinate (0-15)
+ * @param biome the biome to set at the give coordinate
+ */
+ void setBiome(int x, int y, int z, Biome biome);
+
+ /**
+ * Get raw biome temperature at given coordinates
+ *
+ * @param x X-coordinate (0-15)
+ * @param y Y-coordinate (world minHeight (inclusive) - world maxHeight (exclusive))
+ * @param z Z-coordinate (0-15)
+ * @return temperature at given coordinate
+ */
+ double getRawBiomeTemperature(int x, int y, int z);
+
+ /**
+ * Tests if this chunk contains the specified biome.
+ *
+ * @param biome biome to test
+ * @return if the biome is contained within
+ */
+ boolean contains(Biome biome);
+}
diff --git a/paper-api/src/main/java/org/bukkit/ChunkSnapshot.java b/paper-api/src/main/java/org/bukkit/ChunkSnapshot.java
index 725d7944ce..edcdb21219 100644
--- a/paper-api/src/main/java/org/bukkit/ChunkSnapshot.java
+++ b/paper-api/src/main/java/org/bukkit/ChunkSnapshot.java
@@ -10,29 +10,7 @@ import org.jetbrains.annotations.NotNull;
* Purpose is to allow clean, efficient copy of a chunk data to be made, and
* then handed off for processing in another thread (e.g. map rendering)
*/
-public interface ChunkSnapshot {
-
- /**
- * Gets the X-coordinate of this chunk
- *
- * @return X-coordinate
- */
- int getX();
-
- /**
- * Gets the Z-coordinate of this chunk
- *
- * @return Z-coordinate
- */
- int getZ();
-
- /**
- * Gets name of the world containing this chunk
- *
- * @return Parent World Name
- */
- @NotNull
- String getWorldName();
+public interface ChunkSnapshot extends BiomesSnapshot {
/**
* Get block type for block at corresponding coordinate in the chunk
@@ -110,17 +88,6 @@ public interface ChunkSnapshot {
@Deprecated(since = "1.15")
Biome getBiome(int x, int z);
- /**
- * Get biome at given coordinates
- *
- * @param x X-coordinate (0-15)
- * @param y Y-coordinate (world minHeight (inclusive) - world maxHeight (exclusive))
- * @param z Z-coordinate (0-15)
- * @return Biome at given coordinate
- */
- @NotNull
- Biome getBiome(int x, int y, int z);
-
/**
* Get raw biome temperature at given coordinates
*
@@ -132,16 +99,6 @@ public interface ChunkSnapshot {
@Deprecated(since = "1.15")
double getRawBiomeTemperature(int x, int z);
- /**
- * Get raw biome temperature at given coordinates
- *
- * @param x X-coordinate (0-15)
- * @param y Y-coordinate (world minHeight (inclusive) - world maxHeight (exclusive))
- * @param z Z-coordinate (0-15)
- * @return temperature at given coordinate
- */
- double getRawBiomeTemperature(int x, int y, int z);
-
/**
* Get world full time when chunk snapshot was captured
*
@@ -164,12 +121,4 @@ public interface ChunkSnapshot {
* @return if the block is contained within
*/
boolean contains(@NotNull BlockData block);
-
- /**
- * Tests if this chunk contains the specified biome.
- *
- * @param biome biome to test
- * @return if the biome is contained within
- */
- boolean contains(@NotNull Biome biome);
}
diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftBiomesSnapshot.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftBiomesSnapshot.java
new file mode 100644
index 0000000000..b33c682472
--- /dev/null
+++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftBiomesSnapshot.java
@@ -0,0 +1,105 @@
+package org.bukkit.craftbukkit;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicates;
+import java.util.Objects;
+import java.util.function.Predicate;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.Holder;
+import net.minecraft.core.Registry;
+import net.minecraft.world.level.chunk.PalettedContainer;
+import net.minecraft.world.level.chunk.PalettedContainerRO;
+import org.bukkit.BiomesSnapshot;
+import org.bukkit.block.Biome;
+import org.bukkit.craftbukkit.block.CraftBiome;
+import org.jspecify.annotations.NullMarked;
+
+@NullMarked
+public class CraftBiomesSnapshot implements BiomesSnapshot {
+
+ private final int x, z;
+ private final String worldname;
+ private final int minHeight, maxHeight, seaLevel;
+ private final Registry