Paper/patches/api/0318-Add-more-LimitedRegion-API.patch
Nassim Jahnke ca708a0944
Updated Upstream (Bukkit/CraftBukkit/Spigot) (#6539)
Upstream has released updates that appear to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
ed7bba95 SPIGOT-6547: Chunk#getEntities() doesn't return all entities immediately after chunk load
d99a585c SPIGOT-6719: Add getTileEntities() to LimitedRegion

CraftBukkit Changes:
422cec08 Rebuild patch
15f27fc7 SPIGOT-6547: Chunk#getEntities() doesn't return all entities immediately after chunk load
cbd747af SPIGOT-6719: Add getTileEntities() to LimitedRegion

Spigot Changes:
6c1c1b26 Rebuild patches
2021-09-01 14:03:36 +02:00

512 lines
19 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: dfsek <dfsek@protonmail.com>
Date: Sat, 19 Jun 2021 20:15:29 -0700
Subject: [PATCH] Add more LimitedRegion API
diff --git a/src/main/java/io/papermc/paper/world/generation/ProtoWorld.java b/src/main/java/io/papermc/paper/world/generation/ProtoWorld.java
new file mode 100644
index 0000000000000000000000000000000000000000..edf8d0ae398f123ab25cb7954df07f6020454dd4
--- /dev/null
+++ b/src/main/java/io/papermc/paper/world/generation/ProtoWorld.java
@@ -0,0 +1,319 @@
+package io.papermc.paper.world.generation;
+
+import org.bukkit.World;
+import org.bukkit.block.BlockState;
+import org.bukkit.block.data.BlockData;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.EntityType;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+import org.bukkit.generator.LimitedRegion;
+import org.bukkit.generator.WorldInfo;
+import org.bukkit.util.Vector;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Random;
+import java.util.function.Consumer;
+
+/**
+ * Represents a small grid of chunks in a {@link World}
+ * with rudimentary block and entity access, for use during world generation.
+ * <p>
+ * A ProtoWorld is guaranteed read/write access to a 3x3 grid of chunks,
+ * but may have access to a grid as large as 17x17. It is safest to assume
+ * that there is only read/write access to 3x3 chunks. Some chunks outside
+ * of the 3x3 area may be readable but not writable.
+ * <p>
+ * ProtoWorlds should not be stored! After they are used during
+ * chunk generation they should be disposed of.
+ *
+ * @see org.bukkit.generator.BlockPopulator#populate(WorldInfo, Random, int, int, LimitedRegion)
+ * @deprecated see {@link org.bukkit.RegionAccessor} and {@link org.bukkit.generator.LimitedRegion}
+ */
+@Deprecated(forRemoval = true)
+public interface ProtoWorld {
+ /**
+ * Sets the block at (x, y, z) to the provided {@link BlockData}.
+ *
+ * @param x X coordinate in this ProtoWorld
+ * @param y Y coordinate in this ProtoWorld
+ * @param z Z coordinate in this ProtoWorld
+ * @param data {@link BlockData} to set the block at the provided coordinates to.
+ */
+ void setBlockData(int x, int y, int z, @NotNull BlockData data);
+
+ /**
+ * Sets the block at a vector location to the provided {@link BlockData}.
+ *
+ * @param vector {@link Vector} representing the position of the block to set.
+ * @param data {@link BlockData} to set the block at the provided coordinates to.
+ */
+ default void setBlockData(@NotNull Vector vector, @NotNull BlockData data) {
+ setBlockData(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ(), data);
+ }
+
+ /**
+ * Sets the {@link BlockState} at a location.
+ *
+ * @param x X coordinate.
+ * @param y Y coordinate.
+ * @param z Z coordinate.
+ * @param state The block state.
+ */
+ void setBlockState(int x, int y, int z, @NotNull BlockState state);
+
+ /**
+ * Sets the {@link BlockState} at a location.
+ *
+ * @param location Location to set block state.
+ * @param state The block state.
+ */
+ default void setBlockState(@NotNull Vector location, @NotNull BlockState state) {
+ setBlockState(location.getBlockX(), location.getBlockY(), location.getBlockZ(), state);
+ }
+
+ /**
+ * Gets the {@link BlockState} at a location.
+ *
+ * @param x X coordinate.
+ * @param y Y coordinate.
+ * @param z Z coordinate.
+ * @return The block state.
+ */
+ @NotNull
+ BlockState getBlockState(int x, int y, int z);
+
+ /**
+ * Gets the {@link BlockState} at a location.
+ *
+ * @param location Location to get block state from.
+ * @return The block state.
+ */
+ @NotNull
+ default BlockState getBlockState(@NotNull Vector location) {
+ return getBlockState(location.getBlockX(), location.getBlockY(), location.getBlockZ());
+ }
+
+ /**
+ * Schedule a block update at (x, y, z).
+ *
+ * @param x X coordinate in this ProtoWorld
+ * @param y Y coordinate in this ProtoWorld
+ * @param z Z coordinate in this ProtoWorld
+ */
+ void scheduleBlockUpdate(int x, int y, int z);
+
+ /**
+ * Schedule a block update at a vector location
+ *
+ * @param location {@link Vector} representing the position of the block to update.
+ */
+ default void scheduleBlockUpdate(@NotNull Vector location) {
+ scheduleBlockUpdate(location.getBlockX(), location.getBlockY(), location.getBlockZ());
+ }
+
+ /**
+ * Schedule a fluid update at (x, y, z).
+ *
+ * @param x X coordinate in this ProtoWorld
+ * @param y Y coordinate in this ProtoWorld
+ * @param z Z coordinate in this ProtoWorld
+ */
+ void scheduleFluidUpdate(int x, int y, int z);
+
+ /**
+ * Schedule a fluid update at a vector location
+ *
+ * @param location {@link Vector} representing the position of the block to update.
+ */
+ default void scheduleFluidUpdate(@NotNull Vector location) {
+ scheduleFluidUpdate(location.getBlockX(), location.getBlockY(), location.getBlockZ());
+ }
+
+ /**
+ * Get the {@link World} object this ProtoWorld represents.
+ * <p>
+ * Do <b>not</b> attempt to read from/write to this world! Doing so during generation <b>will cause a deadlock!</b>
+ *
+ * @return The {@link World} object that this ProtoWorld represents.
+ */
+ @NotNull
+ World getWorld();
+
+
+ /**
+ * Get the {@link BlockData} of the block at the provided coordinates.
+ *
+ * @param x X coordinate in this ProtoWorld
+ * @param y Y coordinate in this ProtoWorld
+ * @param z Z coordinate in this ProtoWorld
+ * @return {@link BlockData} at the coordinates
+ */
+ @NotNull
+ BlockData getBlockData(int x, int y, int z);
+
+ /**
+ * Get the {@link BlockData} of the block at the provided coordinates.
+ *
+ * @param vector {@link Vector} representing the position of the block to get.
+ * @return {@link BlockData} at the coordinates
+ */
+ @NotNull
+ default BlockData getBlockData(@NotNull Vector vector) {
+ return getBlockData(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
+ }
+
+ /**
+ * Get the X-coordinate of the chunk in the center of this ProtoWorld
+ *
+ * @return The center chunk's X coordinate.
+ */
+ int getCenterChunkX();
+
+ /**
+ * Get the X-coordinate of the block in the center of this {@link ProtoWorld}
+ *
+ * @return The center chunk's X coordinate.
+ */
+ default int getCenterBlockX() {
+ return getCenterChunkX() << 4;
+ }
+
+ /**
+ * Get the Z-coordinate of the chunk in the center of this {@link ProtoWorld}
+ *
+ * @return The center chunk's Z coordinate.
+ */
+ int getCenterChunkZ();
+
+ /**
+ * Get the Z-coordinate of the block in the center of this {@link ProtoWorld}
+ *
+ * @return The center chunk's Z coordinate.
+ */
+ default int getCenterBlockZ() {
+ return getCenterChunkZ() << 4;
+ }
+
+ /**
+ * Creates an entity at the location represented by the given {@link Vector}
+ *
+ * @param loc The {@link Vector} representing the location to spawn the entity
+ * @param type The entity to spawn
+ * @return Resulting Entity of this method
+ */
+ @NotNull
+ default Entity spawnEntity(@NotNull Vector loc, @NotNull EntityType type) {
+ return spawn(loc, type.getEntityClass(), CreatureSpawnEvent.SpawnReason.DEFAULT);
+ }
+
+ /**
+ * Spawn an entity of a specific class at location represented by the given {@link Vector}
+ *
+ * @param location The {@link Vector} representing the location to spawn the entity at
+ * @param clazz The class of the {@link Entity} to spawn
+ * @param <T> The class of the {@link Entity} to spawn
+ * @return An instance of the spawned {@link Entity}
+ * @throws IllegalArgumentException if either parameter is null or the
+ * {@link Entity} requested cannot be spawned
+ */
+ @NotNull
+ default <T extends Entity> T spawn(@NotNull Vector location, @NotNull Class<T> clazz) throws IllegalArgumentException {
+ return spawn(location, clazz, CreatureSpawnEvent.SpawnReason.DEFAULT, null);
+ }
+
+ /**
+ * Spawn an entity of a specific class at location represented by the given {@link Vector}
+ *
+ * @param location The {@link Vector} representing the location to spawn the entity at
+ * @param clazz The class of the {@link Entity} to spawn
+ * @param <T> The class of the {@link Entity} to spawn
+ * @param reason The reason for the entity's spawn.
+ * @return An instance of the spawned {@link Entity}
+ * @throws IllegalArgumentException if either parameter is null or the
+ * {@link Entity} requested cannot be spawned
+ */
+ @NotNull
+ default <T extends Entity> T spawn(@NotNull Vector location, @NotNull Class<T> clazz, @NotNull CreatureSpawnEvent.SpawnReason reason) throws IllegalArgumentException {
+ return spawn(location, clazz, reason, null);
+ }
+
+ /**
+ * Spawn an entity of a specific class at the location represented by the given {@link Vector}, with
+ * the supplied function run before the entity is added to the world.
+ * <br>
+ * Note that when the function is run, the entity will not be actually in
+ * the world. Any operation involving such as teleporting the entity is undefined
+ * until after this function returns.
+ *
+ * @param location The {@link Vector} representing the location to spawn the entity at
+ * @param clazz The class of the {@link Entity} to spawn
+ * @param function The function to be run before the entity is spawned.
+ * @param <T> The class of the {@link Entity} to spawn
+ * @return An instance of the spawned {@link Entity}
+ * @throws IllegalArgumentException if either parameter is null or the
+ * {@link Entity} requested cannot be spawned
+ */
+ @NotNull
+ default <T extends Entity> T spawn(@NotNull Vector location, @NotNull Class<T> clazz, @Nullable Consumer<T> function) throws IllegalArgumentException {
+ return spawn(location, clazz, CreatureSpawnEvent.SpawnReason.CUSTOM, function);
+ }
+
+ /**
+ * Spawn an entity of a specific class at the location represented by the given {@link Vector}, with
+ * the supplied function run before the entity is added to the world.
+ * <br>
+ * Note that when the function is run, the entity will not be actually in
+ * the world. Any operation involving such as teleporting the entity is undefined
+ * until after this function returns.
+ *
+ * @param location The {@link Vector} representing the location to spawn the entity at
+ * @param clazz The class of the {@link Entity} to spawn
+ * @param reason The reason for the entity's spawn.
+ * @param function The function to be run before the entity is spawned.
+ * @param <T> The class of the {@link Entity} to spawn
+ * @return An instance of the spawned {@link Entity}
+ * @throws IllegalArgumentException if either parameter is null or the
+ * {@link Entity} requested cannot be spawned
+ */
+ @NotNull
+ default <T extends Entity> T spawn(@NotNull Vector location, @NotNull Class<T> clazz, @NotNull CreatureSpawnEvent.SpawnReason reason, @Nullable Consumer<T> function) throws IllegalArgumentException {
+ return spawn(location, clazz, function, reason);
+ }
+
+ /**
+ * Creates an entity at the location represented by the given {@link Vector}
+ *
+ * @param loc The {@link Vector} representing the location to spawn the entity
+ * @param type The entity to spawn
+ * @param reason The reason for the entity's spawn.
+ * @return Resulting Entity of this method
+ */
+ @SuppressWarnings("unchecked")
+ @NotNull
+ default Entity spawnEntity(@NotNull Vector loc, @NotNull EntityType type, @NotNull CreatureSpawnEvent.SpawnReason reason) {
+ return spawn(loc, (Class<Entity>) type.getEntityClass(), reason, null);
+ }
+
+ /**
+ * Creates an entity at the location represented by the given {@link Vector}, with
+ * the supplied function run before the entity is added to the world.
+ * <br>
+ * Note that when the function is run, the entity will not be actually in
+ * the world. Any operation involving such as teleporting the entity is undefined
+ * until after this function returns.
+ *
+ * @param loc The {@link Vector} representing the location to spawn the entity
+ * @param type The entity to spawn
+ * @param reason The reason for the entity's spawn.
+ * @param function The function to be run before the entity is spawned.
+ * @return Resulting Entity of this method
+ */
+ @SuppressWarnings("unchecked")
+ @NotNull
+ default Entity spawnEntity(@NotNull Vector loc, @NotNull EntityType type, @NotNull CreatureSpawnEvent.SpawnReason reason, @Nullable Consumer<Entity> function) {
+ return spawn(loc, (Class<Entity>) type.getEntityClass(), reason, function);
+ }
+
+ @NotNull <T extends Entity> T spawn(@NotNull Vector location, @NotNull Class<T> clazz, @Nullable Consumer<T> function, @NotNull CreatureSpawnEvent.SpawnReason reason) throws IllegalArgumentException;
+}
diff --git a/src/main/java/org/bukkit/generator/ChunkGenerator.java b/src/main/java/org/bukkit/generator/ChunkGenerator.java
index 0667315e2bd10254aef59c2a6bcceee9d927b6d5..e96d8877f73de12a56a2b36e32381a0b48bce297 100644
--- a/src/main/java/org/bukkit/generator/ChunkGenerator.java
+++ b/src/main/java/org/bukkit/generator/ChunkGenerator.java
@@ -343,6 +343,20 @@ public abstract class ChunkGenerator {
return new ArrayList<BlockPopulator>();
}
+
+ // Paper start
+ /**
+ * Generate decorations in a chunk, with quick access to its neighbors.
+ *
+ * @param world ProtoWorld to generate decorations with.
+ * @deprecated use and override {@link BlockPopulator#populate(WorldInfo, Random, int, int, LimitedRegion)}
+ */
+ @Deprecated(forRemoval = true)
+ public void generateDecorations(@NotNull io.papermc.paper.world.generation.ProtoWorld world) {
+ // Do nothing by default to maintain compatibility with existing generators.
+ }
+ // Paper end
+
/**
* Gets a fixed spawn location to use for a given world.
* <p>
diff --git a/src/main/java/org/bukkit/generator/LimitedRegion.java b/src/main/java/org/bukkit/generator/LimitedRegion.java
index 85faeeeef908243aa5f172284784e7e67995ebfb..e0b249d328f7671894cea94bc00d54ab54aacd36 100644
--- a/src/main/java/org/bukkit/generator/LimitedRegion.java
+++ b/src/main/java/org/bukkit/generator/LimitedRegion.java
@@ -4,6 +4,12 @@ import java.util.List;
import org.bukkit.Location;
import org.bukkit.RegionAccessor;
import org.bukkit.block.BlockState;
+// Paper start
+import org.bukkit.World;
+import org.bukkit.block.BlockState;
+import org.bukkit.block.data.BlockData;
+import org.bukkit.util.Vector;
+// Paper end
import org.jetbrains.annotations.NotNull;
/**
@@ -53,4 +59,137 @@ public interface LimitedRegion extends RegionAccessor {
*/
@NotNull
List<BlockState> getTileEntities();
+
+
+ // Paper start
+ /**
+ * Sets the block at a vector location to the provided {@link BlockData}.
+ *
+ * @param vector {@link Vector} representing the position of the block to set.
+ * @param data {@link BlockData} to set the block at the provided coordinates to.
+ */
+ default void setBlockData(@NotNull Vector vector, @NotNull BlockData data) {
+ setBlockData(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ(), data);
+ }
+
+ /**
+ * Sets the {@link BlockState} at a location.
+ *
+ * @param x X coordinate.
+ * @param y Y coordinate.
+ * @param z Z coordinate.
+ * @param state The block state.
+ */
+ void setBlockState(int x, int y, int z, @NotNull BlockState state);
+
+ /**
+ * Sets the {@link BlockState} at a location.
+ *
+ * @param location Location to set block state.
+ * @param state The block state.
+ */
+ default void setBlockState(@NotNull Vector location, @NotNull BlockState state) {
+ setBlockState(location.getBlockX(), location.getBlockY(), location.getBlockZ(), state);
+ }
+
+ /**
+ * Gets the {@link BlockState} at a location.
+ *
+ * @param location Location to get block state from.
+ * @return The block state.
+ */
+ @NotNull
+ default BlockState getBlockState(@NotNull Vector location) {
+ return getBlockState(location.getBlockX(), location.getBlockY(), location.getBlockZ());
+ }
+
+ /**
+ * Schedules a block update at (x, y, z).
+ *
+ * @param x X coordinate
+ * @param y Y coordinate
+ * @param z Z coordinate
+ */
+ void scheduleBlockUpdate(int x, int y, int z);
+
+ /**
+ * Schedules a block update at a vector location.
+ *
+ * @param location {@link Vector} representing the position of the block to update.
+ */
+ default void scheduleBlockUpdate(@NotNull Vector location) {
+ scheduleBlockUpdate(location.getBlockX(), location.getBlockY(), location.getBlockZ());
+ }
+
+ /**
+ * Schedules a fluid update at (x, y, z).
+ *
+ * @param x X coordinate
+ * @param y Y coordinate
+ * @param z Z coordinate
+ */
+ void scheduleFluidUpdate(int x, int y, int z);
+
+ /**
+ * Schedules a fluid update at a vector location.
+ *
+ * @param location {@link Vector} representing the position of the block to update.
+ */
+ default void scheduleFluidUpdate(@NotNull Vector location) {
+ scheduleFluidUpdate(location.getBlockX(), location.getBlockY(), location.getBlockZ());
+ }
+
+ /**
+ * Gets the {@link World} object this region represents.
+ * <p>
+ * Do <b>not</b> attempt to read from/write to this world! Doing so during generation <b>will cause a deadlock!</b>
+ *
+ * @return The {@link World} object that this region represents.
+ */
+ @NotNull
+ World getWorld();
+
+ /**
+ * Gets the {@link BlockData} of the block at the provided coordinates.
+ *
+ * @param vector {@link Vector} representing the position of the block to get.
+ * @return {@link BlockData} at the coordinates
+ */
+ @NotNull
+ default BlockData getBlockData(@NotNull Vector vector) {
+ return getBlockData(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
+ }
+
+ /**
+ * Gets the X-coordinate of the chunk in the center of the region.
+ *
+ * @return The center chunk's X coordinate.
+ */
+ int getCenterChunkX();
+
+ /**
+ * Gets the X-coordinate of the block in the center of the region.
+ *
+ * @return The center chunk's X coordinate.
+ */
+ default int getCenterBlockX() {
+ return getCenterChunkX() << 4;
+ }
+
+ /**
+ * Gets the Z-coordinate of the chunk in the center of the region.
+ *
+ * @return The center chunk's Z coordinate.
+ */
+ int getCenterChunkZ();
+
+ /**
+ * Gets the Z-coordinate of the block in the center of the region.
+ *
+ * @return The center chunk's Z coordinate.
+ */
+ default int getCenterBlockZ() {
+ return getCenterChunkZ() << 4;
+ }
+ // Paper end
}