Embetter our coniferous trees (especially the large ones)
This commit is contained in:
parent
79ca5bfa1a
commit
6bec3aeeb1
4 changed files with 117 additions and 65 deletions
|
@ -8,6 +8,7 @@
|
|||
|
||||
package biomesoplenty.common.util.biome;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
@ -16,6 +17,8 @@ import com.google.gson.JsonDeserializationContext;
|
|||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import net.minecraft.block.BlockLog;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
@ -102,4 +105,19 @@ public class GeneratorUtils
|
|||
}
|
||||
|
||||
|
||||
// Given a blockstate for some block which has an axis orientation (such as logs), try to determine the axis property
|
||||
public static IProperty getAxisProperty(IBlockState log)
|
||||
{
|
||||
for (Object property : log.getProperties().keySet())
|
||||
{
|
||||
Collection allowedValues = ((IProperty)property).getAllowedValues();
|
||||
if (allowedValues.contains(BlockLog.EnumAxis.X) && allowedValues.contains(BlockLog.EnumAxis.Y) && allowedValues.contains(BlockLog.EnumAxis.Z))
|
||||
{
|
||||
return(IProperty)property;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
package biomesoplenty.common.world.feature;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.block.BlockLog;
|
||||
|
@ -23,6 +22,7 @@ import net.minecraft.util.BlockPos;
|
|||
import net.minecraft.world.World;
|
||||
import biomesoplenty.common.block.BlockBOPLog;
|
||||
import biomesoplenty.common.enums.BOPWoods;
|
||||
import biomesoplenty.common.util.biome.GeneratorUtils;
|
||||
import biomesoplenty.common.util.biome.GeneratorUtils.ScatterYMethod;
|
||||
import biomesoplenty.common.util.block.BlockQuery.BlockQueryMaterial;
|
||||
import biomesoplenty.common.util.block.BlockQuery.IBlockPosQuery;
|
||||
|
@ -76,30 +76,12 @@ public class GeneratorLogs extends GeneratorReplacing
|
|||
public GeneratorLogs(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState with, ScatterYMethod scatterYMethod, int minLength, int maxLength)
|
||||
{
|
||||
super(amountPerChunk, placeOn, replace, with, scatterYMethod);
|
||||
this.axisProperty = getAxisProperty(with);
|
||||
if (this.axisProperty == null)
|
||||
{
|
||||
throw new RuntimeException("Block state " + with + " has no axis property with X and Z values - is it actually a log?");
|
||||
}
|
||||
this.axisProperty = GeneratorUtils.getAxisProperty(with);
|
||||
this.minLength = minLength;
|
||||
this.maxLength = maxLength;
|
||||
|
||||
}
|
||||
|
||||
// Find the property of the block state which stores axis values
|
||||
public static IProperty getAxisProperty(IBlockState log)
|
||||
{
|
||||
for (Object property : log.getProperties().keySet())
|
||||
{
|
||||
Collection allowedValues = ((IProperty)property).getAllowedValues();
|
||||
if (allowedValues.contains(BlockLog.EnumAxis.X) && allowedValues.contains(BlockLog.EnumAxis.Z))
|
||||
{
|
||||
return(IProperty)property;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean generate(World world, Random random, BlockPos pos)
|
||||
|
@ -110,11 +92,12 @@ public class GeneratorLogs extends GeneratorReplacing
|
|||
// choose random direction and target length
|
||||
BlockLog.EnumAxis direction = (random.nextInt(2) == 0) ? BlockLog.EnumAxis.X : BlockLog.EnumAxis.Z;
|
||||
int length = this.minLength + random.nextInt(this.maxLength - this.minLength);
|
||||
IBlockState state = (this.axisProperty == null) ? this.with : this.with.withProperty(this.axisProperty, direction);
|
||||
|
||||
// keep placing logs along the chosen direction (as long as the block beneath is suitable)
|
||||
while(length > 0 && this.replace.matches(world, pos) && this.placeOn.matches(world, pos.down()))
|
||||
{
|
||||
world.setBlockState(pos, this.with.withProperty(this.axisProperty, direction));
|
||||
world.setBlockState(pos, state);
|
||||
pos = (direction == BlockLog.EnumAxis.X) ? pos.east() : pos.north();
|
||||
length--;
|
||||
}
|
||||
|
@ -126,18 +109,8 @@ public class GeneratorLogs extends GeneratorReplacing
|
|||
public void configure(IConfigObj conf)
|
||||
{
|
||||
this.amountPerChunk = conf.getFloat("amountPerChunk", this.amountPerChunk);
|
||||
IBlockState with = conf.getBlockState("with", null);
|
||||
if (with != null)
|
||||
{
|
||||
IProperty axisProperty = getAxisProperty(with);
|
||||
if (axisProperty == null)
|
||||
{
|
||||
conf.addMessage("log", "Block state " + with + " has no axis property with X and Z values - is it actually a log?");
|
||||
} else {
|
||||
this.with = with;
|
||||
this.axisProperty = axisProperty;
|
||||
}
|
||||
}
|
||||
this.with = conf.getBlockState("with", this.with);
|
||||
this.axisProperty = GeneratorUtils.getAxisProperty(with);
|
||||
this.minLength = conf.getInt("minLength", this.minLength);
|
||||
this.maxLength = conf.getInt("maxLength", this.maxLength);
|
||||
this.placeOn = conf.getBlockPosQuery("placeOn", this.placeOn);
|
||||
|
|
|
@ -19,6 +19,7 @@ import net.minecraft.block.BlockPlanks;
|
|||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
|
@ -51,19 +52,12 @@ public class GeneratorTaigaTree extends GeneratorTreeBase
|
|||
|
||||
}
|
||||
|
||||
private int trunkStart;
|
||||
private int trunkEnd;
|
||||
private int trunkWidth;
|
||||
|
||||
public GeneratorTaigaTree(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState log, IBlockState leaves, IBlockState vine, int minHeight, int maxHeight, int trunkWidth)
|
||||
{
|
||||
super(amountPerChunk, placeOn, replace, log, leaves, vine, minHeight, maxHeight);
|
||||
this.setTrunkWidth(trunkWidth);
|
||||
}
|
||||
|
||||
private void setTrunkWidth(int trunkWidth)
|
||||
{
|
||||
this.trunkStart = MathHelper.ceiling_double_int(0.25D - trunkWidth / 2.0D);
|
||||
this.trunkEnd = MathHelper.floor_double(0.25D + trunkWidth / 2.0D);
|
||||
this.trunkWidth = trunkWidth;
|
||||
}
|
||||
|
||||
public boolean checkSpace(World world, BlockPos pos, int baseHeight, int height)
|
||||
|
@ -71,9 +65,13 @@ public class GeneratorTaigaTree extends GeneratorTreeBase
|
|||
for (int y = 0; y <= height; y++)
|
||||
{
|
||||
|
||||
int trunkWidth = (this.trunkWidth * (height - y) / height) + 1;
|
||||
int trunkStart = MathHelper.ceiling_double_int(0.25D - trunkWidth / 2.0D);
|
||||
int trunkEnd = MathHelper.floor_double(0.25D + trunkWidth / 2.0D);
|
||||
|
||||
// require 3x3 for the leaves, 1x1 for the trunk
|
||||
int start = (y <= baseHeight ? this.trunkStart : this.trunkStart - 1);
|
||||
int end = (y <= baseHeight ? this.trunkEnd : this.trunkEnd + 1);
|
||||
int start = (y <= baseHeight ? trunkStart : trunkStart - 1);
|
||||
int end = (y <= baseHeight ? trunkEnd : trunkEnd + 1);
|
||||
|
||||
for (int x = start; x <= end; x++)
|
||||
{
|
||||
|
@ -92,10 +90,10 @@ public class GeneratorTaigaTree extends GeneratorTreeBase
|
|||
}
|
||||
|
||||
// generates a layer of leafs
|
||||
public void generateLeafLayer(World world, Random rand, BlockPos pos, int leavesRadius)
|
||||
public void generateLeafLayer(World world, Random rand, BlockPos pos, int leavesRadius, int trunkStart, int trunkEnd)
|
||||
{
|
||||
int start = this.trunkStart - leavesRadius;
|
||||
int end = this.trunkEnd + leavesRadius;
|
||||
int start = trunkStart - leavesRadius;
|
||||
int end = trunkEnd + leavesRadius;
|
||||
|
||||
for (int x = start; x <= end; x++)
|
||||
{
|
||||
|
@ -103,10 +101,38 @@ public class GeneratorTaigaTree extends GeneratorTreeBase
|
|||
{
|
||||
// skip corners
|
||||
if ((leavesRadius > 0 ) && (x == start || x == end) && (z == start || z == end)) {continue;}
|
||||
int distFromTrunk = (x < 0 ? this.trunkStart - x : x - this.trunkEnd) + (z < 0 ? this.trunkStart - z : z - this.trunkEnd);
|
||||
int distFromTrunk = (x < 0 ? trunkStart - x : x - trunkEnd) + (z < 0 ? trunkStart - z : z - trunkEnd);
|
||||
|
||||
// set leaves as long as it's not too far from the trunk to survive
|
||||
if (distFromTrunk <=4) {this.setLeaves(world, pos.add(x, 0, z));}
|
||||
if (distFromTrunk < 4 || (distFromTrunk == 4 && rand.nextInt(2) == 0))
|
||||
{
|
||||
this.setLeaves(world, pos.add(x, 0, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void generateBranch(World world, Random rand, BlockPos pos, EnumFacing direction, int length)
|
||||
{
|
||||
EnumFacing.Axis axis = direction.getAxis();
|
||||
EnumFacing sideways = direction.rotateY();
|
||||
for (int i = 1; i <= length; i++)
|
||||
{
|
||||
BlockPos pos1 = pos.offset(direction, i);
|
||||
int r = (i == 1 || i == length) ? 1 : 2;
|
||||
for (int j = -r; j <= r; j++)
|
||||
{
|
||||
if (i < length || rand.nextInt(2) == 0)
|
||||
{
|
||||
this.setLeaves(world, pos1.offset(sideways, j));
|
||||
}
|
||||
}
|
||||
if (length - i > 2)
|
||||
{
|
||||
this.setLeaves(world, pos1.up());
|
||||
this.setLeaves(world, pos1.up().offset(sideways, -1));
|
||||
this.setLeaves(world, pos1.up().offset(sideways, 1));
|
||||
this.setLog(world, pos1, axis);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -127,10 +153,9 @@ public class GeneratorTaigaTree extends GeneratorTreeBase
|
|||
|
||||
// Choose heights
|
||||
int height = GeneratorUtils.nextIntBetween(random, this.minHeight, this.maxHeight);
|
||||
int baseHeight = GeneratorUtils.nextIntBetween(random, height / 6, height / 3);
|
||||
int baseHeight = GeneratorUtils.nextIntBetween(random, height / 5, height / 3);
|
||||
int leavesHeight = height - baseHeight;
|
||||
if (leavesHeight < 3) {return false;}
|
||||
int leavesMaxRadius = (leavesHeight > 6 ? 3 : 2);
|
||||
|
||||
if (!this.checkSpace(world, startPos.up(), baseHeight, height))
|
||||
{
|
||||
|
@ -146,19 +171,41 @@ public class GeneratorTaigaTree extends GeneratorTreeBase
|
|||
pos.down();
|
||||
|
||||
// Add layers of leaves
|
||||
int localMinRadius = 0;
|
||||
int radius = 0;
|
||||
int localMaxRadius = 1;
|
||||
for (int i = 0; i < leavesHeight; i++)
|
||||
{
|
||||
this.generateLeafLayer(world, random, pos, radius);
|
||||
if (radius < localMaxRadius)
|
||||
|
||||
int trunkWidth = (this.trunkWidth * i / height) + 1;
|
||||
int trunkStart = MathHelper.ceiling_double_int(0.25D - trunkWidth / 2.0D);
|
||||
int trunkEnd = MathHelper.floor_double(0.25D + trunkWidth / 2.0D);
|
||||
|
||||
|
||||
int radius = Math.min(Math.min((i + 2) / 3, 3 + (leavesHeight - i)), 6);
|
||||
if (radius == 0)
|
||||
{
|
||||
radius++;
|
||||
} else {
|
||||
radius = localMinRadius;
|
||||
if (localMinRadius == 0) {localMinRadius = 1;}
|
||||
if (localMaxRadius < leavesMaxRadius) {localMaxRadius++;}
|
||||
this.setLeaves(world, pos);
|
||||
}
|
||||
else if (radius < 4)
|
||||
{
|
||||
// for smallish radius, do simple leaf layers
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
this.generateLeafLayer(world, random, pos, radius, trunkStart, trunkEnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.generateLeafLayer(world, random, pos, radius / 2, trunkStart, trunkEnd);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// for bigger radius, need branches
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
this.generateBranch(world, random, pos.add(trunkStart, 0, trunkStart), EnumFacing.NORTH, radius);
|
||||
this.generateBranch(world, random, pos.add(trunkEnd, 0, trunkStart), EnumFacing.EAST, radius);
|
||||
this.generateBranch(world, random, pos.add(trunkEnd, 0, trunkEnd), EnumFacing.SOUTH, radius);
|
||||
this.generateBranch(world, random, pos.add(trunkStart, 0, trunkEnd), EnumFacing.WEST, radius);
|
||||
}
|
||||
}
|
||||
pos = pos.down();
|
||||
}
|
||||
|
@ -166,9 +213,13 @@ public class GeneratorTaigaTree extends GeneratorTreeBase
|
|||
// Generate the trunk
|
||||
for (int y = 0; y < height - 1; y++)
|
||||
{
|
||||
for (int x = this.trunkStart; x <= this.trunkEnd; x++)
|
||||
int trunkWidth = (this.trunkWidth * (height - y) / height) + 1;
|
||||
int trunkStart = MathHelper.ceiling_double_int(0.25D - trunkWidth / 2.0D);
|
||||
int trunkEnd = MathHelper.floor_double(0.25D + trunkWidth / 2.0D);
|
||||
|
||||
for (int x = trunkStart; x <= trunkEnd; x++)
|
||||
{
|
||||
for (int z = this.trunkStart; z <= this.trunkEnd; z++)
|
||||
for (int z = trunkStart; z <= trunkEnd; z++)
|
||||
{
|
||||
this.setLog(world, startPos.add(x, y, z));
|
||||
}
|
||||
|
@ -190,7 +241,7 @@ public class GeneratorTaigaTree extends GeneratorTreeBase
|
|||
this.log = conf.getBlockState("logState", this.log);
|
||||
this.leaves = conf.getBlockState("leavesState", this.leaves);
|
||||
this.vine = conf.getBlockState("vinesState", this.vine);
|
||||
this.setTrunkWidth(conf.getInt("trunkWidth", this.trunkEnd - this.trunkStart));
|
||||
this.trunkWidth = conf.getInt("trunkWidth", this.trunkWidth);
|
||||
}
|
||||
|
||||
}
|
|
@ -11,6 +11,7 @@ package biomesoplenty.common.world.feature.tree;
|
|||
import java.util.Random;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockLog;
|
||||
import net.minecraft.block.BlockNewLeaf;
|
||||
import net.minecraft.block.BlockNewLog;
|
||||
import net.minecraft.block.BlockOldLeaf;
|
||||
|
@ -18,6 +19,7 @@ import net.minecraft.block.BlockOldLog;
|
|||
import net.minecraft.block.BlockPlanks;
|
||||
import net.minecraft.block.BlockVine;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.BlockPos;
|
||||
|
@ -45,6 +47,7 @@ public abstract class GeneratorTreeBase extends BOPGeneratorBase
|
|||
protected IBlockState vine;
|
||||
protected int minHeight;
|
||||
protected int maxHeight;
|
||||
protected IProperty logAxisProperty;
|
||||
|
||||
protected GeneratorTreeBase(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState log, IBlockState leaves, IBlockState vine, int minHeight, int maxHeight) {
|
||||
super(amountPerChunk);
|
||||
|
@ -55,6 +58,7 @@ public abstract class GeneratorTreeBase extends BOPGeneratorBase
|
|||
this.vine = vine;
|
||||
this.minHeight = minHeight;
|
||||
this.maxHeight = maxHeight;
|
||||
this.logAxisProperty = GeneratorUtils.getAxisProperty(log);
|
||||
}
|
||||
|
||||
protected static abstract class InnerBuilder<T extends InnerBuilder<T, G>, G extends GeneratorTreeBase> extends BOPGeneratorBase.InnerBuilder<T, G>
|
||||
|
@ -139,9 +143,15 @@ public abstract class GeneratorTreeBase extends BOPGeneratorBase
|
|||
|
||||
public boolean setLog(World world, BlockPos pos)
|
||||
{
|
||||
return this.setLog(world, pos, null);
|
||||
}
|
||||
|
||||
public boolean setLog(World world, BlockPos pos, EnumFacing.Axis axis)
|
||||
{
|
||||
IBlockState directedLog = (axis != null && this.logAxisProperty != null) ? this.log.withProperty(this.logAxisProperty, BlockLog.EnumAxis.fromFacingAxis(axis)) : this.log;
|
||||
if (this.replace.matches(world, pos))
|
||||
{
|
||||
world.setBlockState(pos, this.log, 2);
|
||||
world.setBlockState(pos, directedLog, 2);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
Loading…
Reference in a new issue