package net.glowstone.generator; import net.glowstone.GlowChunk; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.ChunkGenerator; import org.bukkit.util.noise.OctaveGenerator; import java.util.*; /** * Base chunk generator class. */ public abstract class GlowChunkGenerator extends ChunkGenerator { // distinct from GlowChunk.DEPTH, only used in the wgen protected static final int WORLD_DEPTH = 128; private static final Set<Material> noSpawnFloors = new HashSet<>(Arrays.asList(Material.FIRE, Material.CACTUS, Material.LEAVES)); private final Map<String, Map<String, OctaveGenerator>> octaveCache = new HashMap<>(); private final List<BlockPopulator> populators; protected GlowChunkGenerator(BlockPopulator... args) { populators = Arrays.asList(args); } /** * @param world The world to create OctaveGenerators for * @param octaves The map to put the OctaveGenerators into */ protected void createWorldOctaves(World world, Map<String, OctaveGenerator> octaves) { } /** * @param world The world to look for in the cache * @return A map of {@link OctaveGenerator}s created by {@link #createWorldOctaves(World, Map)} */ protected final Map<String, OctaveGenerator> getWorldOctaves(World world) { if (octaveCache.get(world.getName()) == null) { Map<String, OctaveGenerator> octaves = new HashMap<>(); createWorldOctaves(world, octaves); octaveCache.put(world.getName(), octaves); return octaves; } return octaveCache.get(world.getName()); } /** * Create a new byte[] buffer of the proper size. * @param fill The Material to fill with. * @return A new filled byte[16 * 16 * 128]; */ protected byte[] start(Material fill) { if (fill == null) { throw new IllegalArgumentException("Invalid block type!"); } byte[] data = new byte[GlowChunk.HEIGHT * GlowChunk.WIDTH * WORLD_DEPTH]; Arrays.fill(data, (byte) fill.getId()); return data; } /** * Set the given block to the given type. * @param data The buffer to write to. * @param x The chunk X coordinate. * @param y The Y coordinate. * @param z The chunk Z coordinate. * @param id The block type. */ protected void set(byte[] data, int x, int y, int z, Material id) { if (data == null) { throw new IllegalStateException(); } if (id == null) { throw new IllegalArgumentException("Unknown block type!"); } if (x < 0 || y < 0 || z < 0 || x >= GlowChunk.HEIGHT || y >= GlowChunk.DEPTH || z >= GlowChunk.WIDTH) { return; } data[(x * 16 + z) * 128 + y] = (byte) id.getId(); } /** * Get the given block type. * @param data The buffer to read from. * @param x The chunk X coordinate. * @param y The Y coordinate. * @param z The chunk Z coordinate. * @return The type of block at the location. */ protected Material get(byte[] data, int x, int y, int z) { if (data == null) { throw new IllegalStateException(); } if (x < 0 || y < 0 || z < 0 || x >= GlowChunk.HEIGHT || y >= GlowChunk.DEPTH || z >= GlowChunk.WIDTH) { return Material.AIR; } return Material.getMaterial(data[(x * 16 + z) * 128 + y]); } @Override public final List<BlockPopulator> getDefaultPopulators(World world) { return populators; } @Override public boolean canSpawn(World world, int x, int z) { Block block = world.getHighestBlockAt(x, z).getRelative(BlockFace.DOWN); return !block.isLiquid() && !block.isEmpty() && !noSpawnFloors.contains(block.getType()); } public short[][] generateExtBlockSectionsWithData(World world, Random random, int x, int z, BiomeGrid biomes) { return null; } }