diff --git a/paper-api/src/main/java/org/bukkit/Server.java b/paper-api/src/main/java/org/bukkit/Server.java index 8cdbc67732..c0bb9fe13e 100644 --- a/paper-api/src/main/java/org/bukkit/Server.java +++ b/paper-api/src/main/java/org/bukkit/Server.java @@ -1,5 +1,6 @@ package org.bukkit; +import org.bukkit.generator.ChunkGenerator; import com.avaje.ebean.config.ServerConfig; import org.bukkit.entity.Player; import org.bukkit.inventory.Recipe; @@ -164,6 +165,31 @@ public interface Server { */ public World createWorld(String name, World.Environment environment, long seed); + /** + * Creates or loads a world with the given name. + * If the world is already loaded, it will just return the equivalent of + * getWorld(name) + * + * @param name Name of the world to load + * @param environment Environment type of the world + * @param generator ChunkGenerator to use in the construction of the new world + * @return Newly created or loaded World + */ + public World createWorld(String name, World.Environment environment, ChunkGenerator generator); + + /** + * Creates or loads a world with the given name. + * If the world is already loaded, it will just return the equivalent of + * getWorld(name) + * + * @param name Name of the world to load + * @param environment Environment type of the world + * @param seed Seed value to create the world with + * @param generator ChunkGenerator to use in the construction of the new world + * @return Newly created or loaded World + */ + public World createWorld(String name, World.Environment environment, long seed, ChunkGenerator generator); + /** * Gets the world with the given name * diff --git a/paper-api/src/main/java/org/bukkit/World.java b/paper-api/src/main/java/org/bukkit/World.java index 0aca6a23e4..16a3f3e8be 100644 --- a/paper-api/src/main/java/org/bukkit/World.java +++ b/paper-api/src/main/java/org/bukkit/World.java @@ -1,10 +1,12 @@ package org.bukkit; +import org.bukkit.generator.ChunkGenerator; import java.util.HashMap; import java.util.List; import java.util.Map; import org.bukkit.block.Block; import org.bukkit.entity.*; +import org.bukkit.generator.BlockPopulator; import org.bukkit.inventory.ItemStack; import org.bukkit.util.Vector; @@ -503,11 +505,25 @@ public interface World { */ public void setPVP(boolean pvp); + /** + * Gets the chunk generator for this world + * + * @return ChunkGenerator associated with this world + */ + public ChunkGenerator getGenerator(); + /** * Saves world to disk */ public void save(); + /** + * Gets a list of all applied {@link BlockPopulator}s for this World + * + * @return List containing any or none BlockPopulators + */ + public List getPopulators(); + /** * Represents various map environment types that a world may be */ diff --git a/paper-api/src/main/java/org/bukkit/event/Event.java b/paper-api/src/main/java/org/bukkit/event/Event.java index acd71adc65..f48a0b4c90 100644 --- a/paper-api/src/main/java/org/bukkit/event/Event.java +++ b/paper-api/src/main/java/org/bukkit/event/Event.java @@ -471,6 +471,10 @@ public abstract class Event implements Serializable { * */ WORLD_SAVE (Category.WORLD), + /** + * Called when a World is initializing + */ + WORLD_INIT (Category.WORLD), /** * Called when a World is loaded */ diff --git a/paper-api/src/main/java/org/bukkit/event/world/WorldInitEvent.java b/paper-api/src/main/java/org/bukkit/event/world/WorldInitEvent.java new file mode 100644 index 0000000000..4fb5c38278 --- /dev/null +++ b/paper-api/src/main/java/org/bukkit/event/world/WorldInitEvent.java @@ -0,0 +1,9 @@ +package org.bukkit.event.world; + +import org.bukkit.World; + +public class WorldInitEvent extends WorldEvent { + public WorldInitEvent(World world) { + super(Type.WORLD_INIT, world); + } +} diff --git a/paper-api/src/main/java/org/bukkit/event/world/WorldListener.java b/paper-api/src/main/java/org/bukkit/event/world/WorldListener.java index 262facc4a9..0363820aa1 100644 --- a/paper-api/src/main/java/org/bukkit/event/world/WorldListener.java +++ b/paper-api/src/main/java/org/bukkit/event/world/WorldListener.java @@ -39,6 +39,14 @@ public class WorldListener implements Listener { throw new AuthorNagException("onWorldSave has been replaced with a new signature, (WorldSaveEvent)"); } + /** + * Called when a World is initializing + * + * @param event Relevant event details + */ + public void onWorldInit(WorldInitEvent event) { + } + /** * Called when a World is loaded * diff --git a/paper-api/src/main/java/org/bukkit/generator/BlockPopulator.java b/paper-api/src/main/java/org/bukkit/generator/BlockPopulator.java new file mode 100644 index 0000000000..fff9f9a144 --- /dev/null +++ b/paper-api/src/main/java/org/bukkit/generator/BlockPopulator.java @@ -0,0 +1,20 @@ +package org.bukkit.generator; + +import java.util.Random; +import org.bukkit.Chunk; +import org.bukkit.World; + +/** + * A block populator is responsible for generating a small area of blocks. + * For example, generating glowstone inside the nether or generating dungeons full of treasure + */ +public interface BlockPopulator { + /** + * Populates an area of blocks at or around the given chunk + * + * @param world The world to generate in + * @param random The random generator to use + * @param chunk The chunk to generate for + */ + public void populate(World world, Random random, Chunk source); +} diff --git a/paper-api/src/main/java/org/bukkit/generator/ChunkGenerator.java b/paper-api/src/main/java/org/bukkit/generator/ChunkGenerator.java new file mode 100644 index 0000000000..1e98051aaf --- /dev/null +++ b/paper-api/src/main/java/org/bukkit/generator/ChunkGenerator.java @@ -0,0 +1,54 @@ +package org.bukkit.generator; + +import java.util.List; +import java.util.Random; +import org.bukkit.World; + +/** + * A chunk generator is responsible for the initial shaping of an entire chunk. + * For example, the nether chunk generator should shape netherrack and soulsand + */ +public interface ChunkGenerator { + /** + * Shapes the chunk for the given coordinates.
+ *
+ * This method should return a byte[32768] in the following format: + *
+     * for (int x = 0; x < 16; x++) {
+     *     for (int z = 0; z < 16; z++) {
+     *         for (int y = 0; y < 128; y++) {
+     *             // result[(x * 16 + z) * 128 + y] = ??;
+     *         }
+     *     }
+     * }
+     * 
+ * + * Note that this method should never attempt to get the Chunk at + * the passed coordinates, as doing so may cause an infinite loop + * + * @param world The world this chunk will be used for + * @param random The random generator to use + * @param x The X-coordinate of the chunk + * @param z The Z-coordinate of the chunk + * @return byte[] containing the types for each block created by this generator + */ + public byte[] generate(World world, Random random, int x, int z); + + /** + * Tests if the specified location is valid for a natural spawn position + * + * @param world The world we're testing on + * @param x X-coordinate of the block to test + * @param z Z-coordinate of the block to test + * @return true if the location is valid, otherwise false + */ + public boolean canSpawn(World world, int x, int z); + + /** + * Gets a list of default {@link BlockPopulator}s to apply to a given world + * + * @param world World to apply to + * @return List containing any amount of BlockPopulators + */ + public List getDefaultPopulators(World world); +} diff --git a/paper-api/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/paper-api/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java index 4448cbaf7d..72742cbd75 100644 --- a/paper-api/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +++ b/paper-api/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java @@ -541,6 +541,13 @@ public final class JavaPluginLoader implements PluginLoader { } }; + case WORLD_INIT: + return new EventExecutor() { + public void execute(Listener listener, Event event) { + ((WorldListener) listener).onWorldInit((WorldInitEvent) event); + } + }; + case WORLD_LOAD: return new EventExecutor() { public void execute(Listener listener, Event event) {