From b1aa8fdd5e65b78059447500f662a9e2ef1c4bbd Mon Sep 17 00:00:00 2001 From: boy0001 Date: Fri, 27 Mar 2015 18:15:41 +1100 Subject: [PATCH] Trying to make external generators easier to make. --- .../plot/commands/Copy.java | 2 +- .../plot/generator/ClassicPlotManager.java | 18 ++-- .../plot/generator/HybridGen.java | 6 +- .../plot/object/PlotGenerator.java | 89 ++++++++++++++++++- .../plot/object/PlotPopulator.java | 72 +++++++++++++++ .../plot/object/PseudoRandom.java | 10 +-- .../plot/util/ChunkManager.java | 3 + 7 files changed, 180 insertions(+), 20 deletions(-) create mode 100644 PlotSquared/src/main/java/com/intellectualcrafters/plot/object/PlotPopulator.java diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/Copy.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/Copy.java index ba31cfc75..67d9598c2 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/Copy.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/commands/Copy.java @@ -48,7 +48,7 @@ public class Copy extends SubCommand { final Location loc = plr.getLocation(); final Plot plot1 = MainUtil.getPlot(loc); if (plot1 == null) { - return !sendMessage(plr, C.NOT_IN_PLOT); + return !MainUtil.sendMessage(plr, C.NOT_IN_PLOT); } if (!plot1.isAdded(plr.getUUID()) && !plr.hasPermission(Permissions.ADMIN)) { MainUtil.sendMessage(plr, C.NO_PLOT_PERMS); diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/ClassicPlotManager.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/ClassicPlotManager.java index a15bad233..4b8a53554 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/ClassicPlotManager.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/ClassicPlotManager.java @@ -61,12 +61,13 @@ public abstract class ClassicPlotManager extends SquarePlotManager { final int[] zl = new int[size]; final PlotBlock[] bl = new PlotBlock[size]; int i = 0; + PseudoRandom random = new PseudoRandom(); for (x = bottom.getX(); x <= (top.getX() - 1); x++) { for (int y = 1; y <= dpw.WALL_HEIGHT; y++) { xl[i] = x; zl[i] = z; yl[i] = y; - bl[i] = blocks[PseudoRandom.random(blocks.length)]; + bl[i] = blocks[random.random(blocks.length)]; i++; } } @@ -76,7 +77,7 @@ public abstract class ClassicPlotManager extends SquarePlotManager { xl[i] = x; zl[i] = z; yl[i] = y; - bl[i] = blocks[PseudoRandom.random(blocks.length)]; + bl[i] = blocks[random.random(blocks.length)]; i++; } } @@ -86,7 +87,7 @@ public abstract class ClassicPlotManager extends SquarePlotManager { xl[i] = x; zl[i] = z; yl[i] = y; - bl[i] = blocks[PseudoRandom.random(blocks.length)]; + bl[i] = blocks[random.random(blocks.length)]; i++; } } @@ -96,7 +97,7 @@ public abstract class ClassicPlotManager extends SquarePlotManager { xl[i] = x; zl[i] = z; yl[i] = y; - bl[i] = blocks[PseudoRandom.random(blocks.length)]; + bl[i] = blocks[random.random(blocks.length)]; i++; } } @@ -121,12 +122,13 @@ public abstract class ClassicPlotManager extends SquarePlotManager { int x, z; z = bottom.getZ(); int i = 0; + PseudoRandom random = new PseudoRandom(); final int y = dpw.WALL_HEIGHT + 1; for (x = bottom.getX(); x <= (top.getX() - 1); x++) { xl[i] = x; zl[i] = z; yl[i] = y; - bl[i] = blocks[PseudoRandom.random(blocks.length)]; + bl[i] = blocks[random.random(blocks.length)]; i++; } x = top.getX(); @@ -134,7 +136,7 @@ public abstract class ClassicPlotManager extends SquarePlotManager { xl[i] = x; zl[i] = z; yl[i] = y; - bl[i] = blocks[PseudoRandom.random(blocks.length)]; + bl[i] = blocks[random.random(blocks.length)]; i++; } z = top.getZ(); @@ -142,7 +144,7 @@ public abstract class ClassicPlotManager extends SquarePlotManager { xl[i] = x; zl[i] = z; yl[i] = y; - bl[i] = blocks[PseudoRandom.random(blocks.length)]; + bl[i] = blocks[random.random(blocks.length)]; i++; } x = bottom.getX(); @@ -150,7 +152,7 @@ public abstract class ClassicPlotManager extends SquarePlotManager { xl[i] = x; zl[i] = z; yl[i] = y; - bl[i] = blocks[PseudoRandom.random(blocks.length)]; + bl[i] = blocks[random.random(blocks.length)]; i++; } BlockManager.setBlocks(plotworld.worldname, xl, yl, zl, bl); diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridGen.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridGen.java index 9fae1fac5..3b7d1ed2a 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridGen.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/generator/HybridGen.java @@ -31,11 +31,13 @@ import org.bukkit.Location; import org.bukkit.World; import org.bukkit.block.Biome; import org.bukkit.generator.BlockPopulator; +import org.bukkit.generator.ChunkGenerator.BiomeGrid; import com.intellectualcrafters.plot.object.PlotGenerator; import com.intellectualcrafters.plot.object.PlotLoc; import com.intellectualcrafters.plot.object.PlotManager; import com.intellectualcrafters.plot.object.PlotWorld; +import com.intellectualcrafters.plot.object.PseudoRandom; import com.intellectualcrafters.plot.object.RegionWrapper; import com.intellectualcrafters.plot.util.ChunkManager; @@ -217,7 +219,7 @@ public class HybridGen extends PlotGenerator { * generator */ @Override - public short[][] generateExtBlockSections(final World world, final Random random, final int cx, final int cz, final BiomeGrid biomes) { + public short[][] generateChunk(final World world, RegionWrapper plot, final PseudoRandom random, final int cx, final int cz, final BiomeGrid biomes, final short[][] result) { if (this.doState) { final int prime = 13; int h = 1; @@ -225,7 +227,6 @@ public class HybridGen extends PlotGenerator { h = (prime * h) + cz; this.state = h; } - this.result = new short[this.maxY / 16][]; if (this.plotworld.PLOT_BEDROCK) { for (short x = 0; x < 16; x++) { for (short z = 0; z < 16; z++) { @@ -233,7 +234,6 @@ public class HybridGen extends PlotGenerator { } } } - final RegionWrapper plot = ChunkManager.CURRENT_PLOT_CLEAR; if (plot != null) { final int X = cx << 4; final int Z = cz << 4; diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/PlotGenerator.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/PlotGenerator.java index 7296708cd..0f1a447c3 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/PlotGenerator.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/PlotGenerator.java @@ -20,16 +20,26 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// package com.intellectualcrafters.plot.object; +import java.util.HashMap; import java.util.List; +import java.util.Map.Entry; +import java.util.Random; import org.bukkit.World; +import org.bukkit.block.Biome; import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.ChunkGenerator; import com.intellectualcrafters.plot.PlotSquared; +import com.intellectualcrafters.plot.util.ChunkManager; public abstract class PlotGenerator extends ChunkGenerator { + private short[][] result; + private int X; + private int Z; + private PseudoRandom random = new PseudoRandom(); + @Override public List getDefaultPopulators(World world) { PlotSquared.loadWorld(world.getName(), this); @@ -54,13 +64,86 @@ public abstract class PlotGenerator extends ChunkGenerator { return getPopulators(world.getName()); } + @Override + public short[][] generateExtBlockSections(final World world, final Random r, final int cx, final int cz, final BiomeGrid biomes) { + final int prime = 13; + int h = 1; + h = (prime * h) + cx; + h = (prime * h) + cz; + this.random.state = h; + this.result = new short[256 / 16][]; + PlotWorld plotworld = PlotSquared.getPlotWorld(world.getName()); + Biome biome = Biome.valueOf(plotworld.PLOT_BIOME); + if (ChunkManager.FORCE_PASTE) { + X = cx << 4; + Z = cz << 4; + for (short x = 0; x < 16; x++) { + for (short z = 0; z < 16; z++) { + if (biomes != null) { + biomes.setBiome(x, z, biome); + } + final PlotLoc loc = new PlotLoc((short) (X + x), (short) (Z + z)); + final HashMap blocks = ChunkManager.GENERATE_BLOCKS.get(loc); + for (final Entry entry : blocks.entrySet()) { + setBlock(x, entry.getKey(), z, entry.getValue()); + } + } + } + return this.result; + } + this.result = generateChunk(world, ChunkManager.CURRENT_PLOT_CLEAR, random, cx, cz, biomes, result); + if (ChunkManager.CURRENT_PLOT_CLEAR != null) { + PlotLoc loc; + for (Entry> entry : ChunkManager.GENERATE_BLOCKS.entrySet()) { + for (Entry entry2 : entry.getValue().entrySet()) { + loc = entry.getKey(); + setBlock(loc.x, entry2.getKey(), loc.z, entry2.getValue()); + } + } + } + return result; + } + + private void setBlock(final int x, final int y, final int z, final short blkid) { + if (result[y >> 4] == null) { + result[y >> 4] = new short[4096]; + } + result[y >> 4][((y & 0xF) << 8) | (z << 4) | x] = blkid; + } + + public boolean contains(final RegionWrapper plot, final int x, final int z) { + int xx = X + x; + int zz = Z + z; + return ((xx >= plot.minX) && (xx <= plot.maxX) && (zz >= plot.minZ) && (zz <= plot.maxZ)); + } + + /** + * random is a optimized random number generator.
+ * - Change the state to have the same chunk random each time it generates
+ * requiredRegion If a plot is being regenerated, you are only required to generate content in this area
+ * - use the contains(RegionWrapper, x, z) method to check if the region contains a location
+ * - You can ignore this if you do not want to further optimize your generator
+ * - will be null if no restrictions are set
+ * result is the standard 2D block data array used for generation
+ * biomes is the standard BiomeGrid used for generation + * + * @param world + * @param random + * @param cx + * @param cz + * @param requiredRegion + * @param biomes + * @param result + * @return + */ + public abstract short[][] generateChunk(final World world, RegionWrapper requiredRegion, final PseudoRandom random, final int cx, final int cz, final BiomeGrid biomes, final short[][] result); + public abstract List getPopulators(String world); public abstract void init(PlotWorld plotworld); - + public abstract PlotWorld getNewPlotWorld(final String world); public abstract PlotManager getPlotManager(); - - + } diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/PlotPopulator.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/PlotPopulator.java new file mode 100644 index 000000000..03374a4af --- /dev/null +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/PlotPopulator.java @@ -0,0 +1,72 @@ +package com.intellectualcrafters.plot.object; + +import java.util.HashMap; +import java.util.Random; +import java.util.Map.Entry; + +import org.bukkit.Chunk; +import org.bukkit.World; +import org.bukkit.generator.BlockPopulator; + +import com.intellectualcrafters.plot.util.ChunkManager; +import com.intellectualcrafters.plot.util.bukkit.BukkitUtil; + +public abstract class PlotPopulator extends BlockPopulator{ + + private int X; + private int Z; + private World world; + + @Override + public void populate(World world, Random rand, Chunk chunk) { + this.world = world; + this.X = chunk.getX() << 4; + this.Z = chunk.getZ() << 4; + + if (ChunkManager.FORCE_PASTE) { + for (short x = 0; x < 16; x++) { + for (short z = 0; z < 16; z++) { + final PlotLoc loc = new PlotLoc((short) (X + x), (short) (Z + z)); + final HashMap blocks = ChunkManager.GENERATE_DATA.get(loc); + for (final Entry entry : blocks.entrySet()) { + setBlock(x, entry.getKey(), z, entry.getValue()); + } + } + } + return; + } + + } + + public abstract void populate(World world, RegionWrapper requiredRegion, PseudoRandom random, int cx, int cz); + + /** + * Set the id and data at a location (x, y, z) must be between [0,15], [0,255], [0,15] + * @param x + * @param y + * @param z + * @param id + * @param data + */ + public void setBlock(int x, int y, int z, short id, byte data) { + BukkitUtil.setBlock(world, X + x, y, Z + z, id, data); + } + + /** + * Set the data at a location (x, y, z) must be between [0,15], [0,255], [0,15] + * @param x + * @param y + * @param z + * @param data + */ + public void setBlock(int x, int y, int z, byte data) { + world.getBlockAt(X + x, y, Z + z).setTypeId(data); + } + + public boolean contains(final RegionWrapper plot, final int x, final int z) { + int xx = X + x; + int zz = Z + z; + return ((xx >= plot.minX) && (xx <= plot.maxX) && (zz >= plot.minZ) && (zz <= plot.maxZ)); + } + +} diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/PseudoRandom.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/PseudoRandom.java index 17190cefe..66e68ea2e 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/PseudoRandom.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/object/PseudoRandom.java @@ -1,22 +1,22 @@ package com.intellectualcrafters.plot.object; public class PseudoRandom { - private static long state = 1; - - public static long nextLong() { + public long state = 1; + + public long nextLong() { final long a = state; state = xorShift64(a); return a; } - public static long xorShift64(long a) { + public long xorShift64(long a) { a ^= (a << 21); a ^= (a >>> 35); a ^= (a << 4); return a; } - public static int random(final int n) { + public int random(final int n) { if (n == 1) { return 0; } diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/ChunkManager.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/ChunkManager.java index 8a36782c4..6a3910552 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/ChunkManager.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/ChunkManager.java @@ -11,8 +11,11 @@ import com.intellectualcrafters.plot.object.PlotLoc; import com.intellectualcrafters.plot.object.RegionWrapper; public abstract class ChunkManager { + public static ChunkManager manager = null; public static RegionWrapper CURRENT_PLOT_CLEAR = null; + public static boolean FORCE_PASTE = false; + public static HashMap> GENERATE_BLOCKS = new HashMap<>(); public static HashMap> GENERATE_DATA = new HashMap<>();