From 86669fb6e808b0708a053965e50b802165716f94 Mon Sep 17 00:00:00 2001 From: Daniel Mills Date: Sat, 5 Sep 2020 23:14:59 -0400 Subject: [PATCH] Terrain Data --- src/main/java/com/volmit/iris/Iris.java | 25 +++ .../gen/bindings/BukkitTerrainProvider.java | 15 +- .../iris/gen/bindings/IrisBiomeStorage.java | 77 ++++++++ .../iris/gen/bindings/IrisTerrainChunk.java | 180 ++++++++++++++++++ .../iris/gen/bindings/TerrainChunk.java | 117 ++++++++++++ .../iris/gen/bindings/TerrainProvider.java | 6 +- .../com/volmit/iris/util/IrisMathHelper.java | 18 +- 7 files changed, 421 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/volmit/iris/gen/bindings/IrisBiomeStorage.java create mode 100644 src/main/java/com/volmit/iris/gen/bindings/IrisTerrainChunk.java create mode 100644 src/main/java/com/volmit/iris/gen/bindings/TerrainChunk.java diff --git a/src/main/java/com/volmit/iris/Iris.java b/src/main/java/com/volmit/iris/Iris.java index 05d697aa2..4c3f9bc74 100644 --- a/src/main/java/com/volmit/iris/Iris.java +++ b/src/main/java/com/volmit/iris/Iris.java @@ -4,6 +4,7 @@ import java.io.BufferedInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.net.URL; import org.bstats.bukkit.Metrics; @@ -11,6 +12,7 @@ import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; +import org.bukkit.craftbukkit.v1_16_R2.CraftServer; import org.bukkit.event.HandlerList; import org.bukkit.generator.ChunkGenerator; import org.bukkit.plugin.Plugin; @@ -35,6 +37,7 @@ import com.volmit.iris.util.IrisPostBlockFilter; import com.volmit.iris.util.J; import com.volmit.iris.util.KList; import com.volmit.iris.util.MortarPlugin; +import com.volmit.iris.util.NMSVersion; import com.volmit.iris.util.Permission; public class Iris extends MortarPlugin @@ -47,6 +50,7 @@ public class Iris extends MortarPlugin public static WandManager wand; public static StructureManager struct; public static IrisBoardManager board; + public static String nmsTag = findNMSTag(); public static MultiverseCoreLink linkMultiverseCore; private static IrisLock lock = new IrisLock("Iris"); public static boolean customModels = doesSupportCustomModels(); @@ -66,6 +70,22 @@ public class Iris extends MortarPlugin lowMemoryMode = Runtime.getRuntime().maxMemory() < 4 * 1000 * 1000 * 1000; } + private static String findNMSTag() + { + try + { + return Bukkit.getServer().getClass().getCanonicalName().split("\\Q.\\E")[3]; + } + + catch(Throwable e) + { + Iris.error("Failed to determine server nms version!"); + e.printStackTrace(); + } + + return "UNKNOWN NMS VERSION"; + } + private static boolean doesSupport3DBiomes() { int v = Integer.valueOf(Bukkit.getBukkitVersion().split("\\Q-\\E")[0].split("\\Q.\\E")[1]); @@ -370,4 +390,9 @@ public class Iris extends MortarPlugin Iris.verbose("* This version of minecraft does not support entity awareness."); } } + + public static String nmsTag() + { + return nmsTag; + } } diff --git a/src/main/java/com/volmit/iris/gen/bindings/BukkitTerrainProvider.java b/src/main/java/com/volmit/iris/gen/bindings/BukkitTerrainProvider.java index e2b9fae20..c110f0b86 100644 --- a/src/main/java/com/volmit/iris/gen/bindings/BukkitTerrainProvider.java +++ b/src/main/java/com/volmit/iris/gen/bindings/BukkitTerrainProvider.java @@ -3,7 +3,6 @@ package com.volmit.iris.gen.bindings; import java.util.List; import java.util.Random; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.generator.BlockPopulator; @@ -19,19 +18,25 @@ public abstract class BukkitTerrainProvider extends ChunkGenerator implements Te } @Override - public abstract void generate(Random random, int x, int z, BiomeGrid biome, ChunkData data); + public abstract void generate(Random random, int x, int z, TerrainChunk chunk); @Override public ChunkData generateChunkData(World world, Random random, int x, int z, BiomeGrid biome) { - ChunkData data = Bukkit.getServer().createChunkData(world); - generate(random, x, z, biome, data); - return data; + TerrainChunk terrain = TerrainChunk.create(world); + generate(random, x, z, terrain); + return terrain; } @Override public abstract boolean canSpawn(World world, int x, int z); + @Override + public boolean canSpawnDefault(World world, int x, int z) + { + return super.canSpawn(world, x, z); + } + @Override public abstract List getDefaultPopulators(World world); diff --git a/src/main/java/com/volmit/iris/gen/bindings/IrisBiomeStorage.java b/src/main/java/com/volmit/iris/gen/bindings/IrisBiomeStorage.java new file mode 100644 index 000000000..3a562edcb --- /dev/null +++ b/src/main/java/com/volmit/iris/gen/bindings/IrisBiomeStorage.java @@ -0,0 +1,77 @@ +package com.volmit.iris.gen.bindings; + +import org.bukkit.block.Biome; +import org.bukkit.generator.ChunkGenerator.BiomeGrid; + +import com.volmit.iris.util.IrisMathHelper; + +public class IrisBiomeStorage +{ + private static final int e; + private static final int f; + public static final int a; + public static final int b; + public static final int c; + private final Biome[] g; + + static + { + e = (int) Math.round(Math.log(16.0) / Math.log(2.0)) - 2; + f = (int) Math.round(Math.log(256.0) / Math.log(2.0)) - 2; + a = 1 << IrisBiomeStorage.e + IrisBiomeStorage.e + IrisBiomeStorage.f; + b = (1 << IrisBiomeStorage.e) - 1; + c = (1 << IrisBiomeStorage.f) - 1; + } + + public IrisBiomeStorage(final Biome[] aBiome) + { + this.g = aBiome; + } + + public IrisBiomeStorage() + { + this(new Biome[IrisBiomeStorage.a]); + } + + public IrisBiomeStorage b() + { + return new IrisBiomeStorage(this.g.clone()); + } + + public void inject(BiomeGrid grid) + { + for(int i = 0; i < 256; i++) + { + for(int j = 0; j < 16; j++) + { + for(int k = 0; k < 16; k++) + { + Biome b = getBiome(j, i, k); + + if(b == null || b.equals(Biome.THE_VOID)) + { + continue; + } + + grid.setBiome(j, i, k, b); + } + } + } + } + + public Biome getBiome(final int x, final int y, final int z) + { + final int l = x & IrisBiomeStorage.b; + final int i2 = IrisMathHelper.clamp(y, 0, IrisBiomeStorage.c); + final int j2 = z & IrisBiomeStorage.b; + return this.g[i2 << IrisBiomeStorage.e + IrisBiomeStorage.e | j2 << IrisBiomeStorage.e | l]; + } + + public void setBiome(final int x, final int y, final int z, final Biome biome) + { + final int l = x & IrisBiomeStorage.b; + final int i2 = IrisMathHelper.clamp(y, 0, IrisBiomeStorage.c); + final int j2 = z & IrisBiomeStorage.b; + this.g[i2 << IrisBiomeStorage.e + IrisBiomeStorage.e | j2 << IrisBiomeStorage.e | l] = biome; + } +} \ No newline at end of file diff --git a/src/main/java/com/volmit/iris/gen/bindings/IrisTerrainChunk.java b/src/main/java/com/volmit/iris/gen/bindings/IrisTerrainChunk.java new file mode 100644 index 000000000..b88c65381 --- /dev/null +++ b/src/main/java/com/volmit/iris/gen/bindings/IrisTerrainChunk.java @@ -0,0 +1,180 @@ +package com.volmit.iris.gen.bindings; + +import java.lang.reflect.Constructor; + +import org.bukkit.Material; +import org.bukkit.block.Biome; +import org.bukkit.block.data.BlockData; +import org.bukkit.generator.ChunkGenerator.ChunkData; +import org.bukkit.material.MaterialData; + +import com.volmit.iris.Iris; + +@SuppressWarnings("deprecation") +public class IrisTerrainChunk implements TerrainChunk +{ + private final Biome[] biome2D; + private final IrisBiomeStorage biome3D; + private final ChunkData rawChunkData; + private final Constructor construct = buildConstruct(); + + public IrisTerrainChunk(int maxHeight) + { + rawChunkData = createChunkData(maxHeight); + biome2D = Iris.biome3d ? null : new Biome[256]; + biome3D = Iris.biome3d ? new IrisBiomeStorage() : null; + } + + private Constructor buildConstruct() + { + try + { + Class chunkDatazz = Class.forName("org.bukkit.craftbukkit." + Iris.nmsTag() + ".generator.CraftChunkData"); + Constructor construct = chunkDatazz.getConstructor(int.class); + construct.setAccessible(true); + return construct; + } + + catch(Throwable e) + { + Iris.error("Failed create construct for ChunkData(int)"); + e.printStackTrace(); + } + + return null; + } + + private ChunkData createChunkData(int maxHeight) + { + try + { + return (ChunkData) construct.newInstance(maxHeight); + } + + catch(Throwable e) + { + e.printStackTrace(); + } + + return null; + } + + @Override + public Biome getBiome(int x, int z) + { + if(biome2D != null) + { + return biome2D[(z << 4) | x]; + } + + return biome3D.getBiome(x, 0, z); + } + + @Override + public Biome getBiome(int x, int y, int z) + { + if(biome2D != null) + { + return biome2D[(z << 4) | x]; + } + + return biome3D.getBiome(x, y, z); + } + + @Override + public void setBiome(int x, int z, Biome bio) + { + if(biome2D != null) + { + biome2D[(z << 4) | x] = bio; + return; + } + + biome3D.setBiome(x, 0, z, bio); + } + + @Override + public void setBiome(int x, int y, int z, Biome bio) + { + if(biome2D != null) + { + biome2D[(z << 4) | x] = bio; + return; + } + + biome3D.setBiome(x, y, z, bio); + } + + @Override + public int getMaxHeight() + { + return rawChunkData.getMaxHeight(); + } + + @Override + public void setBlock(int x, int y, int z, BlockData blockData) + { + rawChunkData.setBlock(x, y, z, blockData); + } + + @Override + public BlockData getBlockData(int x, int y, int z) + { + return rawChunkData.getBlockData(x, y, z); + } + + @Deprecated + @Override + public void setBlock(int x, int y, int z, Material material) + { + rawChunkData.setBlock(x, y, z, material); + } + + @Deprecated + @Override + public void setBlock(int x, int y, int z, MaterialData material) + { + rawChunkData.setBlock(x, y, z, material); + } + + @Deprecated + @Override + public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, Material material) + { + rawChunkData.setRegion(xMin, yMin, zMin, xMax, yMax, zMax, material); + } + + @Deprecated + @Override + public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, MaterialData material) + { + rawChunkData.setRegion(xMin, yMin, zMin, xMax, yMax, zMax, material); + } + + @Override + public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, BlockData blockData) + { + rawChunkData.setRegion(xMin, yMin, zMin, xMax, yMax, zMax, blockData); + } + + @Deprecated + @Override + public Material getType(int x, int y, int z) + { + return rawChunkData.getType(x, y, z); + } + + @Deprecated + @Override + public MaterialData getTypeAndData(int x, int y, int z) + { + return rawChunkData.getTypeAndData(x, y, z); + } + + @Deprecated + @Override + public byte getData(int x, int y, int z) + { + return rawChunkData.getData(x, y, z); + } +} diff --git a/src/main/java/com/volmit/iris/gen/bindings/TerrainChunk.java b/src/main/java/com/volmit/iris/gen/bindings/TerrainChunk.java new file mode 100644 index 000000000..dd67b449c --- /dev/null +++ b/src/main/java/com/volmit/iris/gen/bindings/TerrainChunk.java @@ -0,0 +1,117 @@ +package com.volmit.iris.gen.bindings; + +import org.bukkit.World; +import org.bukkit.block.Biome; +import org.bukkit.block.data.BlockData; +import org.bukkit.generator.ChunkGenerator.BiomeGrid; +import org.bukkit.generator.ChunkGenerator.ChunkData; + +public interface TerrainChunk extends BiomeGrid, ChunkData +{ + public static TerrainChunk create(World world) + { + return create(world.getMaxHeight()); + } + + public static TerrainChunk create(int maxHeight) + { + return new IrisTerrainChunk(maxHeight); + } + + /** + * Get biome at x, z within chunk being generated + * + * @param x + * - 0-15 + * @param z + * - 0-15 + * @return Biome value + * @deprecated biomes are now 3-dimensional + */ + @Deprecated + Biome getBiome(int x, int z); + + /** + * Get biome at x, z within chunk being generated + * + * @param x + * - 0-15 + * @param y + * - 0-255 + * @param z + * - 0-15 + * @return Biome value + */ + Biome getBiome(int x, int y, int z); + + /** + * Set biome at x, z within chunk being generated + * + * @param x + * - 0-15 + * @param z + * - 0-15 + * @param bio + * - Biome value + * @deprecated biomes are now 3-dimensional + */ + @Deprecated + void setBiome(int x, int z, Biome bio); + + /** + * Set biome at x, z within chunk being generated + * + * @param x + * - 0-15 + * @param y + * - 0-255 + * @param z + * - 0-15 + * @param bio + * - Biome value + */ + void setBiome(int x, int y, int z, Biome bio); + + /** + * Get the maximum height for the chunk. + * + * Setting blocks at or above this height will do nothing. + * + * @return the maximum height + */ + public int getMaxHeight(); + + /** + * Set the block at x,y,z in the chunk data to material. + * + * Setting blocks outside the chunk's bounds does nothing. + * + * @param x + * the x location in the chunk from 0-15 inclusive + * @param y + * the y location in the chunk from 0 (inclusive) - maxHeight + * (exclusive) + * @param z + * the z location in the chunk from 0-15 inclusive + * @param blockData + * the type to set the block to + */ + public void setBlock(int x, int y, int z, BlockData blockData); + + /** + * Get the type and data of the block at x, y, z. + * + * Getting blocks outside the chunk's bounds returns air. + * + * @param x + * the x location in the chunk from 0-15 inclusive + * @param y + * the y location in the chunk from 0 (inclusive) - maxHeight + * (exclusive) + * @param z + * the z location in the chunk from 0-15 inclusive + * @return the data of the block or the BlockData for air if x, y or z are + * outside the chunk's bounds + */ + public BlockData getBlockData(int x, int y, int z); +} diff --git a/src/main/java/com/volmit/iris/gen/bindings/TerrainProvider.java b/src/main/java/com/volmit/iris/gen/bindings/TerrainProvider.java index fa38302ee..cd3ba8bbc 100644 --- a/src/main/java/com/volmit/iris/gen/bindings/TerrainProvider.java +++ b/src/main/java/com/volmit/iris/gen/bindings/TerrainProvider.java @@ -6,17 +6,17 @@ import java.util.Random; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.generator.BlockPopulator; -import org.bukkit.generator.ChunkGenerator.BiomeGrid; -import org.bukkit.generator.ChunkGenerator.ChunkData; public interface TerrainProvider { public TerrainTarget getTarget(); - public void generate(Random random, int x, int z, BiomeGrid biome, ChunkData data); + public void generate(Random random, int x, int z, TerrainChunk chunk); public boolean canSpawn(World world, int x, int z); + public boolean canSpawnDefault(World world, int x, int z); + public List getDefaultPopulators(World world); public Location getFixedSpawnLocation(World world, Random random); diff --git a/src/main/java/com/volmit/iris/util/IrisMathHelper.java b/src/main/java/com/volmit/iris/util/IrisMathHelper.java index e1a930234..8f775c5c7 100644 --- a/src/main/java/com/volmit/iris/util/IrisMathHelper.java +++ b/src/main/java/com/volmit/iris/util/IrisMathHelper.java @@ -4,7 +4,7 @@ import java.util.Random; import java.util.UUID; import java.util.function.IntPredicate; -public class MathHelper +public class IrisMathHelper { public static final float a; private static final Random c; @@ -260,7 +260,7 @@ public class MathHelper public static int e(int var0) { var0 = (d(var0) ? var0 : c(var0)); - return MathHelper.d[(int) (var0 * 125613361L >> 27) & 0x1F]; + return IrisMathHelper.d[(int) (var0 * 125613361L >> 27) & 0x1F]; } public static int f(final int var0) @@ -316,7 +316,7 @@ public class MathHelper public static UUID a() { - return a(MathHelper.c); + return a(IrisMathHelper.c); } public static double c(final double var0, final double var2, final double var4) @@ -351,11 +351,11 @@ public class MathHelper final double var7 = i(var3); var2 *= var7; var0 *= var7; - final double var8 = MathHelper.e + var0; + final double var8 = IrisMathHelper.e + var0; final int var9 = (int) Double.doubleToRawLongBits(var8); - final double var10 = MathHelper.f[var9]; - final double var11 = MathHelper.g[var9]; - final double var12 = var8 - MathHelper.e; + final double var10 = IrisMathHelper.f[var9]; + final double var11 = IrisMathHelper.g[var9]; + final double var12 = var8 - IrisMathHelper.e; final double var13 = var0 * var11 - var2 * var12; final double var14 = (6.0 + var13 * var13) * var13 * 0.16666666666666666; double var15 = var10 + var14; @@ -544,8 +544,8 @@ public class MathHelper { final double var3 = var2 / 256.0; final double var4 = Math.asin(var3); - MathHelper.g[var2] = Math.cos(var4); - MathHelper.f[var2] = var4; + IrisMathHelper.g[var2] = Math.cos(var4); + IrisMathHelper.f[var2] = var4; } } } \ No newline at end of file