diff --git a/patches/api/0313-Add-more-LimitedRegion-API.patch b/patches/api/0313-Add-more-LimitedRegion-API.patch index 7a4193f78..292f95c89 100644 --- a/patches/api/0313-Add-more-LimitedRegion-API.patch +++ b/patches/api/0313-Add-more-LimitedRegion-API.patch @@ -4,356 +4,6 @@ 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. -+ *

-+ * 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. -+ *

-+ * 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. -+ *

-+ * Do not attempt to read from/write to this world! Doing so during generation will cause a deadlock! -+ * -+ * @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 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 spawn(@NotNull Vector location, @NotNull Class 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 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 spawn(@NotNull Vector location, @NotNull Class 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. -+ *
-+ * 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 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 spawn(@NotNull Vector location, @NotNull Class clazz, @Nullable Consumer 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. -+ *
-+ * 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 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 spawn(@NotNull Vector location, @NotNull Class clazz, @NotNull CreatureSpawnEvent.SpawnReason reason, @Nullable Consumer 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) 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. -+ *
-+ * 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 function) { -+ return spawn(loc, (Class) type.getEntityClass(), reason, function); -+ } -+ -+ @NotNull T spawn(@NotNull Vector location, @NotNull Class clazz, @Nullable Consumer 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 80fcd02e9cb5f432f21b1f68fd8266f296becaa0..41f4f9903369c85545d3ba00366c819371a536df 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(); - } - -+ -+ // 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. - *

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 diff --git a/patches/server/0682-Add-more-LimitedRegion-API.patch b/patches/server/0682-Add-more-LimitedRegion-API.patch index 904a9db1b..b8d8e5c14 100644 --- a/patches/server/0682-Add-more-LimitedRegion-API.patch +++ b/patches/server/0682-Add-more-LimitedRegion-API.patch @@ -4,128 +4,6 @@ Date: Sat, 19 Jun 2021 20:15:59 -0700 Subject: [PATCH] Add more LimitedRegion API -diff --git a/src/main/java/io/papermc/paper/world/generation/CraftProtoWorld.java b/src/main/java/io/papermc/paper/world/generation/CraftProtoWorld.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3160766243e2ce90d07f71d02c7410ff4e9d9562 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/world/generation/CraftProtoWorld.java -@@ -0,0 +1,116 @@ -+package io.papermc.paper.world.generation; -+ -+import net.minecraft.core.BlockPos; -+import net.minecraft.nbt.CompoundTag; -+import net.minecraft.server.level.WorldGenRegion; -+import net.minecraft.world.entity.Mob; -+import net.minecraft.world.entity.MobSpawnType; -+import net.minecraft.world.entity.SpawnGroupData; -+import net.minecraft.world.level.block.entity.BlockEntity; -+import org.bukkit.World; -+import org.bukkit.block.BlockState; -+import org.bukkit.block.data.BlockData; -+import org.bukkit.craftbukkit.block.CraftBlockEntityState; -+import org.bukkit.craftbukkit.block.CraftBlockState; -+import org.bukkit.craftbukkit.block.data.CraftBlockData; -+import org.bukkit.craftbukkit.inventory.CraftMetaBlockState; -+import org.bukkit.entity.Entity; -+import org.bukkit.event.entity.CreatureSpawnEvent; -+import org.bukkit.util.Vector; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+import java.util.Objects; -+import java.util.function.Consumer; -+ -+@Deprecated -+public class CraftProtoWorld implements ProtoWorld { -+ private WorldGenRegion region; -+ -+ public CraftProtoWorld(WorldGenRegion region) { -+ this.region = region; -+ } -+ -+ public void clearReference() { -+ region = null; -+ } -+ -+ @Override -+ public void setBlockData(int x, int y, int z, @NotNull BlockData data) { -+ BlockPos position = new BlockPos(x, y, z); -+ getDelegate().setBlock(position, ((CraftBlockData) data).getState(), 3); -+ } -+ -+ @Override -+ public void setBlockState(int x, int y, int z, @NotNull BlockState state) { -+ BlockPos pos = new BlockPos(x, y, z); -+ if(!state.getBlockData().matches(getDelegate().getBlockState(pos).createCraftBlockData())) { -+ throw new IllegalArgumentException("BlockData does not match! Expected " + state.getBlockData().getAsString(false) + ", got " + getDelegate().getBlockState(pos).createCraftBlockData().getAsString(false)); -+ } -+ getDelegate().getBlockEntity(pos).load(((CraftBlockEntityState) state).getSnapshotNBT()); -+ } -+ -+ @Override -+ public @NotNull BlockState getBlockState(int x, int y, int z) { -+ BlockEntity entity = getDelegate().getBlockEntity(new BlockPos(x, y, z)); -+ return CraftMetaBlockState.createBlockState(entity.getBlockState().getBukkitMaterial(), entity.saveWithFullMetadata()); -+ } -+ -+ @Override -+ public void scheduleBlockUpdate(int x, int y, int z) { -+ BlockPos position = new BlockPos(x, y, z); -+ getDelegate().scheduleTick(position, getDelegate().getBlockIfLoaded(position), 0); -+ } -+ -+ @Override -+ public void scheduleFluidUpdate(int x, int y, int z) { -+ BlockPos position = new BlockPos(x, y, z); -+ getDelegate().scheduleTick(position, getDelegate().getFluidState(position).getType(), 0); -+ } -+ -+ @Override -+ public @NotNull World getWorld() { -+ // reading/writing the returned Minecraft world causes a deadlock. -+ // By implementing this, and covering it in warnings, we're assuming people won't be stupid, and -+ // if they are stupid, they'll figure it out pretty fast. -+ return getDelegate().getMinecraftWorld().getWorld(); -+ } -+ -+ @Override -+ public @NotNull BlockData getBlockData(int x, int y, int z) { -+ return CraftBlockData.fromData(getDelegate().getBlockState(new BlockPos(x, y, z))); -+ } -+ -+ @Override -+ public int getCenterChunkX() { -+ return getDelegate().getCenter().x; -+ } -+ -+ @Override -+ public int getCenterChunkZ() { -+ return getDelegate().getCenter().z; -+ } -+ -+ @SuppressWarnings({"unchecked", "deprecation"}) -+ @Override -+ public @NotNull T spawn(@NotNull Vector location, @NotNull Class clazz, @Nullable Consumer function, CreatureSpawnEvent.@NotNull SpawnReason reason) throws IllegalArgumentException { -+ net.minecraft.world.entity.Entity entity = getDelegate().getMinecraftWorld().getWorld().createEntity(location.toLocation(getWorld()), clazz); -+ Objects.requireNonNull(entity, "Cannot spawn null entity"); -+ if (entity instanceof Mob mob) { -+ mob.finalizeSpawn(getDelegate(), getDelegate().getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.COMMAND, (SpawnGroupData) null, null); -+ } -+ -+ if (function != null) { -+ function.accept((T) entity.getBukkitEntity()); -+ } -+ -+ getDelegate().addFreshEntity(entity, reason); -+ return (T) entity.getBukkitEntity(); -+ } -+ -+ @NotNull -+ private WorldGenRegion getDelegate() { -+ return Objects.requireNonNull(region, "Cannot access ProtoWorld after generation!"); -+ } -+} -+ diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java index 94fee76f0b2145e3cf99460c407815bb32bd19d0..671ec060981790043f5685a5b647324ddfee6af2 100644 --- a/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java @@ -197,23 +75,6 @@ index 94fee76f0b2145e3cf99460c407815bb32bd19d0..671ec060981790043f5685a5b647324d + } + // Paper end } -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -index c8e81b0a5495cd138a7b7a4aed98fd64beda59aa..cb49867045b1fdd9802ec815ab6bc17a6923c822 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -@@ -205,6 +205,12 @@ public class CustomChunkGenerator extends InternalChunkGenerator { - for (BlockPos lightPosition : craftData.getLights()) { - ((ProtoChunk) chunk).addLight(new BlockPos((x << 4) + lightPosition.getX(), lightPosition.getY(), (z << 4) + lightPosition.getZ())); - } -+ -+ // Paper start -+ io.papermc.paper.world.generation.CraftProtoWorld protoWorld = new io.papermc.paper.world.generation.CraftProtoWorld(region); -+ generator.generateDecorations(protoWorld); -+ protoWorld.clearReference(); // make sure people dont try to use the ProtoWorld after we're done with it. -+ // Paper end - } - - @Override diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java index 55dd618d8421271063843c6e65dbcaceba9a33de..56f65b49e0ce55ee5aa9d929a98ea055ce27a8a1 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java