package rtg.world.biome.deco; import java.util.Random; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; import net.minecraft.world.gen.feature.WorldGenerator; import rtg.api.util.WorldUtil; import rtg.api.world.RTGWorld; import rtg.world.biome.realistic.RealisticBiomeBase; import rtg.world.gen.feature.WorldGenLog; /** * @author WhichOnesPink */ public class DecoFallenTree extends DecoBase { private int loops; private DecoFallenTree.Distribution distribution; // Parameter object for noise calculations. private LogCondition logCondition; // Enum for the various conditions/chances for log gen. private float logConditionNoise; // Only applies to a noise-related LogCondition. private int logConditionChance; // Only applies to a chance-related LogCondition. private int maxY; // Height restriction. private IBlockState logBlock; private IBlockState leavesBlock; private int minSize; // Min log height (only used with certain log presets) private int maxSize; // Max log height (only used with certain log presets) private IBlockState[] randomLogBlocks; public DecoFallenTree() { super(); /** * Default values. * These can be overridden when configuring the Deco object in the realistic biome. */ this.setLoops(1); this.setDistribution(new DecoFallenTree.Distribution(100f, 5f, 0.8f)); this.setLogCondition(LogCondition.NOISE_GREATER_AND_RANDOM_CHANCE); this.setLogConditionNoise(0f); this.setLogConditionChance(1); this.setMaxY(80); this.setLogBlock(Blocks.LOG.getDefaultState()); this.setLeavesBlock(Blocks.LEAVES.getDefaultState()); this.setMinSize(2); this.setMaxSize(4); this.randomLogBlocks = new IBlockState[]{}; this.addDecoTypes(DecoType.FALLEN_TREE); } public DecoFallenTree(DecoFallenTree source) { this(); this.setLoops(source.loops); this.setDistribution(source.distribution); this.setLogCondition(source.logCondition); this.setLogConditionNoise(source.logConditionNoise); this.setLogConditionChance(source.logConditionChance); this.setMaxY(source.maxY); this.setLogBlock(source.logBlock); this.setLeavesBlock(source.leavesBlock); this.setMinSize(source.minSize); this.setMaxSize(source.maxSize); this.randomLogBlocks = source.randomLogBlocks; } @Override public void generate(RealisticBiomeBase biome, RTGWorld rtgWorld, Random rand, int worldX, int worldZ, float strength, float river, boolean hasPlacedVillageBlocks) { if (this.allowed) { float noise = rtgWorld.simplex.noise2(worldX / this.distribution.noiseDivisor, worldZ / this.distribution.noiseDivisor) * this.distribution.noiseFactor + this.distribution.noiseAddend; WorldUtil worldUtil = new WorldUtil(rtgWorld.world); //Do we want to choose a random log? if (this.randomLogBlocks.length > 0) { this.setLogBlock(this.randomLogBlocks[rand.nextInt(this.randomLogBlocks.length)]); } WorldGenerator worldGenerator = null; int finalSize = 4; if (this.maxSize > this.minSize) { finalSize = this.minSize + rand.nextInt(this.maxSize - this.minSize); worldGenerator = new WorldGenLog(this.logBlock, this.leavesBlock, finalSize); } else if (this.maxSize == this.minSize) { finalSize = this.minSize; worldGenerator = new WorldGenLog(this.logBlock, this.leavesBlock, finalSize); } else { worldGenerator = new WorldGenLog(this.logBlock, this.leavesBlock, finalSize); } for (int i = 0; i < this.loops; i++) { if (isValidLogCondition(noise, strength, rand)) { int x22 = worldX + rand.nextInt(16);// + 8; int z22 = worldZ + rand.nextInt(16);// + 8; int y22 = rtgWorld.world.getHeight(new BlockPos(x22, 0, z22)).getY(); if (y22 <= this.maxY) { // If we're in a village, check to make sure the log has extra room to grow to avoid corrupting the village. if (hasPlacedVillageBlocks) { if (!worldUtil.isSurroundedByBlock(Blocks.AIR.getDefaultState(), finalSize, WorldUtil.SurroundCheckType.CARDINAL, rand, x22, y22, z22)) { return; } } worldGenerator.generate(rtgWorld.world, rand, new BlockPos(x22, y22, z22)); } } } } } public boolean isValidLogCondition(float noise, float strength, Random rand) { switch (this.logCondition) { case ALWAYS_GENERATE: return true; case RANDOM_CHANCE: return (rand.nextInt(this.logConditionChance) == 0); case NOISE_GREATER_AND_RANDOM_CHANCE: return (noise > this.logConditionNoise && rand.nextInt(this.logConditionChance) == 0); case NOISE_LESS_AND_RANDOM_CHANCE: return (noise < this.logConditionNoise && rand.nextInt(this.logConditionChance) == 0); case X_DIVIDED_BY_STRENGTH: return (rand.nextInt((int) (this.logConditionNoise / strength)) == 0); default: return false; } } public enum LogCondition { ALWAYS_GENERATE, RANDOM_CHANCE, NOISE_GREATER_AND_RANDOM_CHANCE, NOISE_LESS_AND_RANDOM_CHANCE, X_DIVIDED_BY_STRENGTH; } /** * Parameter object for noise calculations. * <p> * simplex.noise2(chunkX / noiseDivisor, chunkY / noiseDivisor) * noiseFactor + noiseAddend; * * @author WhichOnesPink * @author Zeno410 */ public static class Distribution { private float noiseDivisor; private float noiseFactor; private float noiseAddend; public Distribution(float noiseDivisor, float noiseFactor, float noiseAddend) { this.noiseDivisor = noiseDivisor; this.noiseFactor = noiseFactor; this.noiseAddend = noiseAddend; } public float getNoiseDivisor() { return noiseDivisor; } public Distribution setNoiseDivisor(float noiseDivisor) { this.noiseDivisor = noiseDivisor; return this; } public float getNoiseFactor() { return noiseFactor; } public Distribution setNoiseFactor(float noiseFactor) { this.noiseFactor = noiseFactor; return this; } public float getNoiseAddend() { return noiseAddend; } public Distribution setNoiseAddend(float noiseAddend) { this.noiseAddend = noiseAddend; return this; } } public int getLoops() { return loops; } public DecoFallenTree setLoops(int loops) { this.loops = loops; return this; } public Distribution getDistribution() { return distribution; } public DecoFallenTree setDistribution(Distribution distribution) { this.distribution = distribution; return this; } public LogCondition getLogCondition() { return logCondition; } public DecoFallenTree setLogCondition(LogCondition logCondition) { this.logCondition = logCondition; return this; } public float getLogConditionNoise() { return logConditionNoise; } public DecoFallenTree setLogConditionNoise(float logConditionNoise) { this.logConditionNoise = logConditionNoise; return this; } public int getLogConditionChance() { return logConditionChance; } public DecoFallenTree setLogConditionChance(int logConditionChance) { this.logConditionChance = logConditionChance; return this; } public int getMaxY() { return maxY; } public DecoFallenTree setMaxY(int maxY) { this.maxY = maxY; return this; } public IBlockState getLogBlock() { return logBlock; } public DecoFallenTree setLogBlock(IBlockState logBlock) { this.logBlock = logBlock; return this; } public IBlockState getLeavesBlock() { return leavesBlock; } public DecoFallenTree setLeavesBlock(IBlockState leavesBlock) { this.leavesBlock = leavesBlock; return this; } public int getMinSize() { return minSize; } public DecoFallenTree setMinSize(int minSize) { this.minSize = minSize; return this; } public int getMaxSize() { return maxSize; } public DecoFallenTree setMaxSize(int maxSize) { this.maxSize = maxSize; return this; } public IBlockState[] getRandomLogBlocks() { return randomLogBlocks; } public DecoFallenTree setRandomLogBlocks(IBlockState[] randomLogBlocks) { this.randomLogBlocks = randomLogBlocks; return this; } }