2021-06-20 06:48:30 +02:00
|
|
|
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 Feature Stage API
|
|
|
|
|
|
|
|
|
2021-06-20 07:02:27 +02:00
|
|
|
diff --git a/src/main/java/io/papermc/paper/world/generation/ProtoWorld.java b/src/main/java/io/papermc/paper/world/generation/ProtoWorld.java
|
2021-06-20 06:48:30 +02:00
|
|
|
new file mode 100644
|
2021-07-07 12:23:16 +02:00
|
|
|
index 0000000000000000000000000000000000000000..f3b465d3883547d53e55183c2a4e22c63525a787
|
2021-06-20 06:48:30 +02:00
|
|
|
--- /dev/null
|
2021-06-20 07:02:27 +02:00
|
|
|
+++ b/src/main/java/io/papermc/paper/world/generation/ProtoWorld.java
|
2021-07-07 12:23:16 +02:00
|
|
|
@@ -0,0 +1,313 @@
|
2021-06-20 07:02:27 +02:00
|
|
|
+package io.papermc.paper.world.generation;
|
2021-06-20 06:48:30 +02:00
|
|
|
+
|
|
|
|
+import org.bukkit.World;
|
2021-07-07 12:23:16 +02:00
|
|
|
+import org.bukkit.block.BlockState;
|
2021-06-20 06:48:30 +02:00
|
|
|
+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.util.Vector;
|
|
|
|
+import org.jetbrains.annotations.NotNull;
|
|
|
|
+import org.jetbrains.annotations.Nullable;
|
|
|
|
+
|
|
|
|
+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.
|
|
|
|
+ */
|
|
|
|
+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);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
2021-07-07 12:23:16 +02:00
|
|
|
+ * 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());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
2021-06-20 06:48:30 +02:00
|
|
|
+ * 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();
|
|
|
|
+
|
|
|
|
+ /**
|
2021-07-07 12:23:16 +02:00
|
|
|
+ * Get the X-coordinate of the block in the center of this {@link ProtoWorld}
|
2021-06-20 06:48:30 +02:00
|
|
|
+ *
|
|
|
|
+ * @return The center chunk's X coordinate.
|
|
|
|
+ */
|
|
|
|
+ default int getCenterBlockX() {
|
|
|
|
+ return getCenterChunkX() << 4;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
2021-07-07 12:23:16 +02:00
|
|
|
+ * Get the Z-coordinate of the chunk in the center of this {@link ProtoWorld}
|
2021-06-20 06:48:30 +02:00
|
|
|
+ *
|
|
|
|
+ * @return The center chunk's Z coordinate.
|
|
|
|
+ */
|
|
|
|
+ int getCenterChunkZ();
|
|
|
|
+
|
|
|
|
+ /**
|
2021-07-07 12:23:16 +02:00
|
|
|
+ * Get the Z-coordinate of the block in the center of this {@link ProtoWorld}
|
2021-06-20 06:48:30 +02:00
|
|
|
+ *
|
|
|
|
+ * @return The center chunk's Z coordinate.
|
|
|
|
+ */
|
|
|
|
+ default int getCenterBlockZ() {
|
|
|
|
+ return getCenterChunkZ() << 4;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
2021-07-07 12:23:16 +02:00
|
|
|
+ * Creates an entity at the location represented by the given {@link Vector}
|
2021-06-20 06:48:30 +02:00
|
|
|
+ *
|
|
|
|
+ * @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);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
2021-07-07 12:23:16 +02:00
|
|
|
+ * Creates an entity at the location represented by the given {@link Vector}
|
2021-06-20 06:48:30 +02:00
|
|
|
+ *
|
|
|
|
+ * @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);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
2021-07-07 12:23:16 +02:00
|
|
|
+ * Creates an entity at the location represented by the given {@link Vector}, with
|
2021-06-20 06:48:30 +02:00
|
|
|
+ * 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
|
2021-06-20 07:02:27 +02:00
|
|
|
index 244a8a93c35d5a84e17672ff745051587bca384c..e547f324790ca27dfb85b030988fc03bfc6107f1 100644
|
2021-06-20 06:48:30 +02:00
|
|
|
--- a/src/main/java/org/bukkit/generator/ChunkGenerator.java
|
|
|
|
+++ b/src/main/java/org/bukkit/generator/ChunkGenerator.java
|
|
|
|
@@ -161,6 +161,19 @@ 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.
|
|
|
|
+ */
|
|
|
|
+ @SuppressWarnings("unused")
|
2021-06-20 07:02:27 +02:00
|
|
|
+ public void generateDecorations(@NotNull io.papermc.paper.world.generation.ProtoWorld world) {
|
2021-06-20 06:48:30 +02:00
|
|
|
+ // Do nothing by default to maintain compatibility with existing generators.
|
|
|
|
+ }
|
|
|
|
+ // Paper end
|
|
|
|
+
|
|
|
|
/**
|
|
|
|
* Gets a fixed spawn location to use for a given world.
|
|
|
|
* <p>
|