diff --git a/patches/api/0319-Add-Feature-Stage-API.patch b/patches/api/0319-Add-more-LimitedRegion-API.patch similarity index 70% rename from patches/api/0319-Add-Feature-Stage-API.patch rename to patches/api/0319-Add-more-LimitedRegion-API.patch index c7db5c3e46..59b90be21a 100644 --- a/patches/api/0319-Add-Feature-Stage-API.patch +++ b/patches/api/0319-Add-more-LimitedRegion-API.patch @@ -1,15 +1,15 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 19 Jun 2021 20:15:29 -0700 -Subject: [PATCH] Add Feature Stage API +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..f3b465d3883547d53e55183c2a4e22c63525a787 +index 0000000000000000000000000000000000000000..edf8d0ae398f123ab25cb7954df07f6020454dd4 --- /dev/null +++ b/src/main/java/io/papermc/paper/world/generation/ProtoWorld.java -@@ -0,0 +1,313 @@ +@@ -0,0 +1,319 @@ +package io.papermc.paper.world.generation; + +import org.bukkit.World; @@ -18,13 +18,15 @@ index 0000000000000000000000000000000000000000..f3b465d3883547d53e55183c2a4e22c6 +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. @@ -36,7 +38,11 @@ index 0000000000000000000000000000000000000000..f3b465d3883547d53e55183c2a4e22c6 + *

+ * 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}. @@ -324,10 +330,10 @@ index 0000000000000000000000000000000000000000..f3b465d3883547d53e55183c2a4e22c6 + @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 0667315e2bd10254aef59c2a6bcceee9d927b6d5..5cf3f8875753b0293ea56b65a64f0075b03257c3 100644 +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,19 @@ public abstract class ChunkGenerator { +@@ -343,6 +343,20 @@ public abstract class ChunkGenerator { return new ArrayList(); } @@ -337,8 +343,9 @@ index 0667315e2bd10254aef59c2a6bcceee9d927b6d5..5cf3f8875753b0293ea56b65a64f0075 + * 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)} + */ -+ @SuppressWarnings("unused") ++ @Deprecated(forRemoval = true) + public void generateDecorations(@NotNull io.papermc.paper.world.generation.ProtoWorld world) { + // Do nothing by default to maintain compatibility with existing generators. + } @@ -347,3 +354,157 @@ index 0667315e2bd10254aef59c2a6bcceee9d927b6d5..5cf3f8875753b0293ea56b65a64f0075 /** * 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 0428f210866587997d3e73dbb6ae4770f3c44ed5..3bd9f092d9ae38c2d91abdc522d6a8d94b4b8212 100644 +--- a/src/main/java/org/bukkit/generator/LimitedRegion.java ++++ b/src/main/java/org/bukkit/generator/LimitedRegion.java +@@ -2,6 +2,12 @@ package org.bukkit.generator; + + import org.bukkit.Location; + import org.bukkit.RegionAccessor; ++// 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; + + /** +@@ -42,4 +48,136 @@ public interface LimitedRegion extends RegionAccessor { + * @return true if the coordinates are in the region, otherwise false. + */ + boolean isInRegion(int x, int y, int z); ++ ++ // 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. ++ *

++ * 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 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 + } diff --git a/patches/server/0709-Add-Feature-Generation-API.patch b/patches/server/0709-Add-more-LimitedRegion-API.patch similarity index 82% rename from patches/server/0709-Add-Feature-Generation-API.patch rename to patches/server/0709-Add-more-LimitedRegion-API.patch index c5424f59f0..24aae8f22b 100644 --- a/patches/server/0709-Add-Feature-Generation-API.patch +++ b/patches/server/0709-Add-more-LimitedRegion-API.patch @@ -1,15 +1,15 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 19 Jun 2021 20:15:59 -0700 -Subject: [PATCH] Add Feature Generation API +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..69b17fe56f28f8978abc3f363a9e805d7c7b007a +index 0000000000000000000000000000000000000000..ccb6b20b5f56c3bacdc6bd384931986cf804f06a --- /dev/null +++ b/src/main/java/io/papermc/paper/world/generation/CraftProtoWorld.java -@@ -0,0 +1,115 @@ +@@ -0,0 +1,116 @@ +package io.papermc.paper.world.generation; + +import net.minecraft.core.BlockPos; @@ -35,6 +35,7 @@ index 0000000000000000000000000000000000000000..69b17fe56f28f8978abc3f363a9e805d +import java.util.Objects; +import java.util.function.Consumer; + ++@Deprecated +public class CraftProtoWorld implements ProtoWorld { + private WorldGenRegion region; + @@ -125,6 +126,85 @@ index 0000000000000000000000000000000000000000..69b17fe56f28f8978abc3f363a9e805d + } +} + +diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java +index 8f968ed09b960c2e4aca2fa6aba20aae00456ea8..0d23d2be7829b62391dc1313b0f20762002c1d34 100644 +--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java ++++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftLimitedRegion.java +@@ -6,6 +6,7 @@ import java.util.ArrayList; + import java.util.Collection; + import java.util.List; + import java.util.Random; ++import net.minecraft.core.BlockPos; // Paper + import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.WorldGenRegion; + import net.minecraft.world.entity.EntityType; +@@ -134,7 +135,10 @@ public class CraftLimitedRegion extends CraftRegionAccessor implements LimitedRe + @Override + public BlockState getBlockState(int x, int y, int z) { + Preconditions.checkArgument(this.isInRegion(x, y, z), "Coordinates %s, %s, %s are not in the region", x, y, z); +- return super.getBlockState(x, y, z); ++ // Paper start ++ net.minecraft.world.level.block.entity.BlockEntity entity = getHandle().getBlockEntity(new BlockPos(x, y, z)); ++ return org.bukkit.craftbukkit.inventory.CraftMetaBlockState.createBlockState(entity.getBlockState().getBukkitMaterial(), entity.save(new CompoundTag())); ++ // Paper end + } + + @Override +@@ -152,7 +156,7 @@ public class CraftLimitedRegion extends CraftRegionAccessor implements LimitedRe + @Override + public void setBlockData(int x, int y, int z, BlockData blockData) { + Preconditions.checkArgument(this.isInRegion(x, y, z), "Coordinates %s, %s, %s are not in the region", x, y, z); +- super.setBlockData(x, y, z, blockData); ++ getHandle().setBlock(new BlockPos(x, y, z), ((org.bukkit.craftbukkit.block.data.CraftBlockData) blockData).getState(), 3); // Paper + } + + @Override +@@ -182,4 +186,45 @@ public class CraftLimitedRegion extends CraftRegionAccessor implements LimitedRe + public void addEntityToWorld(net.minecraft.world.entity.Entity entity, CreatureSpawnEvent.SpawnReason reason) { + this.entities.add(entity); + } ++ ++ // Paper start ++ @Override ++ public void setBlockState(int x, int y, int z, BlockState state) { ++ BlockPos pos = new BlockPos(x, y, z); ++ if (!state.getBlockData().matches(getHandle().getBlockState(pos).createCraftBlockData())) { ++ throw new IllegalArgumentException("BlockData does not match! Expected " + state.getBlockData().getAsString(false) + ", got " + getHandle().getBlockState(pos).createCraftBlockData().getAsString(false)); ++ } ++ getHandle().getBlockEntity(pos).load(((org.bukkit.craftbukkit.block.CraftBlockEntityState) state).getSnapshotNBT()); ++ } ++ ++ @Override ++ public void scheduleBlockUpdate(int x, int y, int z) { ++ BlockPos position = new BlockPos(x, y, z); ++ getHandle().getBlockTicks().scheduleTick(position, getHandle().getBlockIfLoaded(position), 0); ++ } ++ ++ @Override ++ public void scheduleFluidUpdate(int x, int y, int z) { ++ BlockPos position = new BlockPos(x, y, z); ++ getHandle().getLiquidTicks().scheduleTick(position, getHandle().getFluidState(position).getType(), 0); ++ } ++ ++ @Override ++ public 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 getHandle().getMinecraftWorld().getWorld(); ++ } ++ ++ @Override ++ public int getCenterChunkX() { ++ return centerChunkX; ++ } ++ ++ @Override ++ public int getCenterChunkZ() { ++ return centerChunkZ; ++ } ++ // 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 98461949badc8a708c1e7e2f225a93e8d1ca5822..4fa8cce0818a8e461330fc29021e6ff65cb67125 100644 --- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java