Began work on the Origin Valley, trees currently generate

This commit is contained in:
Adubbz 2015-04-08 22:53:06 +10:00
parent 3a24ac037f
commit ab961ba89b
17 changed files with 664 additions and 58 deletions

View file

@ -17,4 +17,5 @@ public class BOPBiomes
public static Optional<BiomeGenBase> alps = Optional.absent(); public static Optional<BiomeGenBase> alps = Optional.absent();
public static Optional<BiomeGenBase> arctic = Optional.absent(); public static Optional<BiomeGenBase> arctic = Optional.absent();
public static Optional<BiomeGenBase> crag = Optional.absent(); public static Optional<BiomeGenBase> crag = Optional.absent();
public static Optional<BiomeGenBase> originValley = Optional.absent();
} }

View file

@ -0,0 +1,74 @@
/*******************************************************************************
* Copyright 2015, the Biomes O' Plenty Team
*
* This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License.
*
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/.
******************************************************************************/
package biomesoplenty.api.biome.generation;
import java.util.Random;
import net.minecraft.util.BlockPos;
import net.minecraft.util.WeightedRandom;
import net.minecraft.world.World;
public abstract class CustomizableWeightedGenerator extends WeightedRandom.Item implements IGenerator
{
private final String identifier;
private String name;
private GeneratorStage stage;
protected CustomizableWeightedGenerator()
{
this(-1);
}
protected CustomizableWeightedGenerator(int weight)
{
super(weight);
this.identifier = GeneratorRegistry.getIdentifier((Class<? extends IGenerator>)this.getClass());
this.stage = GeneratorStage.PARENT;
if (this.identifier == null)
{
throw new RuntimeException("The identifier for " + this.getClass().getCanonicalName() + " cannot be null!");
}
}
//Scattering should be handled in GeneratorWeighted
@Override
public final void scatter(World world, Random random, BlockPos pos) {}
@Override
public void setName(String name)
{
this.name = name;
}
@Override
public void setStage(GeneratorStage stage)
{
this.stage = stage;
}
@Override
public String getName()
{
return this.name;
}
@Override
public GeneratorStage getStage()
{
return this.stage;
}
@Override
public final String getIdentifier()
{
return this.identifier;
}
}

View file

@ -47,7 +47,9 @@ public enum GeneratorStage
@SerializedName("tree") @SerializedName("tree")
TREE(Decorate.EventType.TREE), TREE(Decorate.EventType.TREE),
@SerializedName("post") @SerializedName("post")
POST(null); POST(null),
@SerializedName("parent")
PARENT(null);
private Decorate.EventType decorateType; private Decorate.EventType decorateType;

View file

@ -20,7 +20,7 @@ import com.google.gson.JsonSerializationContext;
public interface IGenerator public interface IGenerator
{ {
public void scatter(World world, Random random, BlockPos pos); public void scatter(World world, Random random, BlockPos pos);
public void generate(World world, Random random, BlockPos pos); public boolean generate(World world, Random random, BlockPos pos);
public void setName(String name); public void setName(String name);
public void setStage(GeneratorStage stage); public void setStage(GeneratorStage stage);

View file

@ -24,7 +24,7 @@ public class BiomeGenCrag extends BOPBiome
{ {
this.setHeight(biomeHeight); this.setHeight(biomeHeight);
this.setColor(5209457); this.setColor(5209457);
this.setTemperatureRainfall(2.0F, 0.0F); this.setTemperatureRainfall(1.0F, 0.0F);
this.addWeight(BiomeType.COOL, 3); this.addWeight(BiomeType.COOL, 3);

View file

@ -0,0 +1,67 @@
/*******************************************************************************
* Copyright 2015, the Biomes O' Plenty Team
*
* This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License.
*
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/.
******************************************************************************/
package biomesoplenty.common.biome.overworld;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraftforge.common.BiomeManager.BiomeType;
import biomesoplenty.api.biome.BOPBiome;
import biomesoplenty.api.biome.generation.GeneratorStage;
import biomesoplenty.api.block.BOPBlocks;
import biomesoplenty.api.block.BOPTreeEnums.AllTrees;
import biomesoplenty.common.block.BlockBOPGrass;
import biomesoplenty.common.block.BlockBOPLeaves;
import biomesoplenty.common.block.BlockBOPLeaves2;
import biomesoplenty.common.block.BlockBOPGrass.BOPGrassType;
import biomesoplenty.common.config.MiscConfigurationHandler;
import biomesoplenty.common.world.feature.tree.GeneratorBasicTree;
import biomesoplenty.common.world.feature.tree.GeneratorWeighted;
public class BiomeGenOriginValley extends BOPBiome
{
private static final Height biomeHeight = new Height(0.1F, 0.3F);
public BiomeGenOriginValley()
{
this.setHeight(biomeHeight);
this.setColor(10341485);
this.setTemperatureRainfall(0.7F, 0.8F);
this.addWeight(BiomeType.WARM, 1);
this.topBlock = BOPBlocks.grass.getDefaultState().withProperty(BlockBOPGrass.VARIANT, BOPGrassType.ORIGIN);
GeneratorWeighted treeGenerator = new GeneratorWeighted(4);
treeGenerator.add(new GeneratorBasicTree(1, false, 5, 8, Blocks.log.getDefaultState(),
BOPBlocks.leaves_2.getDefaultState().withProperty(BlockBOPLeaves.getVariantProperty(BlockBOPLeaves2.PAGENUM), AllTrees.ORIGIN)));
this.addGenerator("trees", GeneratorStage.TREE, treeGenerator);
}
@Override
public int getGrassColorAtPos(BlockPos pos)
{
return 10682207;
}
@Override
public int getFoliageColorAtPos(BlockPos pos)
{
return 3866368;
}
@Override
public int getSkyColorByTemp(float temperature)
{
if (MiscConfigurationHandler.skyColors)
return 8441086;
return super.getSkyColorByTemp(temperature);
}
}

View file

@ -116,6 +116,10 @@ public class BlockBOPGrass extends BlockGrass implements IBOPBlock
IBlockState state = world.getBlockState(pos); IBlockState state = world.getBlockState(pos);
net.minecraftforge.common.EnumPlantType plantType = plantable.getPlantType(world, pos.offset(direction)); net.minecraftforge.common.EnumPlantType plantType = plantable.getPlantType(world, pos.offset(direction));
//Forge calls this method regardless of whether the block is infact ours, so we have to check this
//(Somewhat illogical, I know)
if (state.getBlock() == this)
{
switch ((BOPGrassType) state.getValue(VARIANT)) switch ((BOPGrassType) state.getValue(VARIANT))
{ {
// smoldering grass supports no plants // smoldering grass supports no plants
@ -154,6 +158,9 @@ public class BlockBOPGrass extends BlockGrass implements IBOPBlock
} }
} }
return super.canSustainPlant(world, pos, direction, plantable);
}
@Override @Override
public boolean isFireSource(World world, BlockPos pos, EnumFacing side) public boolean isFireSource(World world, BlockPos pos, EnumFacing side)

View file

@ -15,7 +15,9 @@ import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeGenBase; import net.minecraft.world.biome.BiomeGenBase;
import net.minecraftforge.event.terraingen.DecorateBiomeEvent; import net.minecraftforge.event.terraingen.DecorateBiomeEvent;
import net.minecraftforge.event.terraingen.DecorateBiomeEvent.Decorate; import net.minecraftforge.event.terraingen.DecorateBiomeEvent.Decorate;
import net.minecraftforge.fml.common.eventhandler.Event.Result;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import biomesoplenty.api.biome.BiomeOwner;
import biomesoplenty.api.biome.IExtendedBiome; import biomesoplenty.api.biome.IExtendedBiome;
import biomesoplenty.api.biome.generation.GenerationManager; import biomesoplenty.api.biome.generation.GenerationManager;
import biomesoplenty.api.biome.generation.GeneratorStage; import biomesoplenty.api.biome.generation.GeneratorStage;
@ -35,7 +37,9 @@ public class DecorateBiomeEventHandler
{ {
if (event.type != Decorate.EventType.CUSTOM) if (event.type != Decorate.EventType.CUSTOM)
{ {
runGeneratorStage(event.world, event.rand, event.pos, GeneratorStage.mapDecorateType(event.type)); boolean allow = runGeneratorStage(event.world, event.rand, event.pos, GeneratorStage.mapDecorateType(event.type));
event.setResult(allow ? Result.ALLOW : Result.DENY);
} }
} }
@ -45,7 +49,7 @@ public class DecorateBiomeEventHandler
runGeneratorStage(event.world, event.rand, event.pos, GeneratorStage.POST); runGeneratorStage(event.world, event.rand, event.pos, GeneratorStage.POST);
} }
private static void runGeneratorStage(World world, Random random, BlockPos pos, GeneratorStage stage) private static boolean runGeneratorStage(World world, Random random, BlockPos pos, GeneratorStage stage)
{ {
BiomeGenBase biome = world.getBiomeGenForCoords(pos.add(16, 0, 16)); BiomeGenBase biome = world.getBiomeGenForCoords(pos.add(16, 0, 16));
IExtendedBiome extendedBiome = ExtendedBiomeRegistry.getExtension(biome); IExtendedBiome extendedBiome = ExtendedBiomeRegistry.getExtension(biome);
@ -58,6 +62,17 @@ public class DecorateBiomeEventHandler
{ {
generator.scatter(world, random, pos); generator.scatter(world, random, pos);
} }
//Biomes should explicitly allow for the following by defining their own generators
if (extendedBiome.getBiomeOwner() == BiomeOwner.BIOMESOPLENTY)
{
if (stage == GeneratorStage.PUMPKIN)
{
return false;
} }
} }
} }
return true;
}
}

View file

@ -20,6 +20,7 @@ import org.apache.commons.io.FileUtils;
import biomesoplenty.common.biome.overworld.BiomeGenAlps; import biomesoplenty.common.biome.overworld.BiomeGenAlps;
import biomesoplenty.common.biome.overworld.BiomeGenArctic; import biomesoplenty.common.biome.overworld.BiomeGenArctic;
import biomesoplenty.common.biome.overworld.BiomeGenCrag; import biomesoplenty.common.biome.overworld.BiomeGenCrag;
import biomesoplenty.common.biome.overworld.BiomeGenOriginValley;
import biomesoplenty.common.command.BOPCommand; import biomesoplenty.common.command.BOPCommand;
import biomesoplenty.common.util.config.JsonBiome; import biomesoplenty.common.util.config.JsonBiome;
import biomesoplenty.common.world.WorldTypeBOP; import biomesoplenty.common.world.WorldTypeBOP;
@ -47,6 +48,7 @@ public class ModBiomes
alps = registerBiome(new BiomeGenAlps().setBiomeName("Alps"), "alps"); alps = registerBiome(new BiomeGenAlps().setBiomeName("Alps"), "alps");
arctic = registerBiome(new BiomeGenArctic().setBiomeName("Arctic"), "arctic"); arctic = registerBiome(new BiomeGenArctic().setBiomeName("Arctic"), "arctic");
crag = registerBiome(new BiomeGenCrag().setBiomeName("Crag"), "crag"); crag = registerBiome(new BiomeGenCrag().setBiomeName("Crag"), "crag");
originValley = registerBiome(new BiomeGenOriginValley().setBiomeName("Origin Valley"), "origin_valley");
} }
private static void registerExternalBiomes() private static void registerExternalBiomes()

View file

@ -11,6 +11,8 @@ package biomesoplenty.common.init;
import static biomesoplenty.api.biome.generation.GeneratorRegistry.registerGenerator; import static biomesoplenty.api.biome.generation.GeneratorRegistry.registerGenerator;
import biomesoplenty.common.world.feature.GeneratorOreCluster; import biomesoplenty.common.world.feature.GeneratorOreCluster;
import biomesoplenty.common.world.feature.GeneratorOreSingle; import biomesoplenty.common.world.feature.GeneratorOreSingle;
import biomesoplenty.common.world.feature.tree.GeneratorBasicTree;
import biomesoplenty.common.world.feature.tree.GeneratorWeighted;
public class ModGenerators public class ModGenerators
{ {
@ -18,5 +20,7 @@ public class ModGenerators
{ {
registerGenerator("ore_single", GeneratorOreSingle.class); registerGenerator("ore_single", GeneratorOreSingle.class);
registerGenerator("ore_cluster", GeneratorOreCluster.class); registerGenerator("ore_cluster", GeneratorOreCluster.class);
registerGenerator("weighted", GeneratorWeighted.class);
registerGenerator("basic_tree", GeneratorBasicTree.class);
} }
} }

View file

@ -0,0 +1,58 @@
/*******************************************************************************
* Copyright 2015, the Biomes O' Plenty Team
*
* This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License.
*
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/.
******************************************************************************/
package biomesoplenty.common.util.biome;
import org.apache.commons.lang3.tuple.Pair;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
public class GeneratorUtils
{
public static Pair<Integer, Integer> validateMinMaxHeight(int minHeight, int maxHeight)
{
if (maxHeight < minHeight)
{
//Swap min and max height so that max is higher than min
int prevMinHeight = minHeight;
minHeight = maxHeight;
maxHeight = prevMinHeight;
}
else if (maxHeight == minHeight)
{
if (minHeight < 255)
{
//Increase max height to be higher than min height
++maxHeight;
}
else
{
//Decrease min height so that max is higher
--minHeight;
}
}
return Pair.of(minHeight, maxHeight);
}
public static boolean isBlockTreeReplacable(Block block)
{
return block.getMaterial() == Material.air || block.getMaterial() == Material.leaves || block == Blocks.grass || block == Blocks.dirt || block == Blocks.log || block == Blocks.log2 || block == Blocks.sapling || block == Blocks.vine;
}
public static boolean canTreeReplace(World world, BlockPos pos)
{
IBlockState state = world.getBlockState(pos);
return state.getBlock().isAir(world, pos) || state.getBlock().isLeaves(world, pos) || state.getBlock().isWood(world, pos) || isBlockTreeReplacable(state.getBlock());
}
}

View file

@ -60,8 +60,8 @@ public class GeneratorTypeAdaptor implements JsonSerializer<IGenerator>, JsonDes
generator = (IGenerator)generatorClass.newInstance(); generator = (IGenerator)generatorClass.newInstance();
Type generatorStageType = new TypeToken<GeneratorStage>() {}.getType(); Type generatorStageType = new TypeToken<GeneratorStage>() {}.getType();
String generatorStageName = jsonObject.get("stage").getAsString();
GeneratorStage generatorStage = (GeneratorStage)context.deserialize(jsonObject.get("stage"), generatorStageType); GeneratorStage generatorStage = (GeneratorStage)context.deserialize(jsonObject.get("stage"), generatorStageType);
String generatorStageName = jsonObject.get("stage") != null ? jsonObject.get("stage").getAsString() : null;
if (generatorStage == null) if (generatorStage == null)
{ {

View file

@ -12,7 +12,11 @@ import java.util.Random;
import net.minecraft.util.BlockPos; import net.minecraft.util.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import org.apache.commons.lang3.tuple.Pair;
import biomesoplenty.api.biome.generation.CustomizableGenerator; import biomesoplenty.api.biome.generation.CustomizableGenerator;
import biomesoplenty.common.util.biome.GeneratorUtils;
import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
@ -29,8 +33,10 @@ public abstract class GeneratorOreBase extends CustomizableGenerator
protected GeneratorOreBase(int amountPerChunk, int minHeight, int maxHeight) protected GeneratorOreBase(int amountPerChunk, int minHeight, int maxHeight)
{ {
this.amountPerChunk = amountPerChunk; this.amountPerChunk = amountPerChunk;
this.minHeight = minHeight;
this.maxHeight = maxHeight; Pair<Integer, Integer> heights = GeneratorUtils.validateMinMaxHeight(minHeight, maxHeight);
this.minHeight = heights.getLeft();
this.maxHeight = heights.getRight();
} }
@Override @Override
@ -59,33 +65,8 @@ public abstract class GeneratorOreBase extends CustomizableGenerator
int minHeight = json.get("min_height").getAsInt(); int minHeight = json.get("min_height").getAsInt();
int maxHeight = json.get("max_height").getAsInt(); int maxHeight = json.get("max_height").getAsInt();
validateMinMaxHeight(minHeight, maxHeight); Pair<Integer, Integer> heights = GeneratorUtils.validateMinMaxHeight(minHeight, maxHeight);
} this.minHeight = heights.getLeft();
this.maxHeight = heights.getRight();
protected void validateMinMaxHeight(int minHeight, int maxHeight)
{
if (maxHeight < minHeight)
{
//Swap min and max height so that max is higher than min
int prevMinHeight = minHeight;
minHeight = maxHeight;
maxHeight = prevMinHeight;
}
else if (maxHeight == minHeight)
{
if (minHeight < 255)
{
//Increase max height to be higher than min height
++maxHeight;
}
else
{
//Decrease min height so that max is higher
--minHeight;
}
}
this.minHeight = minHeight;
this.maxHeight = maxHeight;
} }
} }

View file

@ -33,9 +33,9 @@ public class GeneratorOreCluster extends GeneratorOreBase
} }
@Override @Override
public void generate(World world, Random random, BlockPos pos) public boolean generate(World world, Random random, BlockPos pos)
{ {
this.generator.generate(world, random, pos); return this.generator.generate(world, random, pos);
} }
@Override @Override

View file

@ -39,12 +39,14 @@ public class GeneratorOreSingle extends GeneratorOreBase
} }
@Override @Override
public void generate(World world, Random random, BlockPos pos) public boolean generate(World world, Random random, BlockPos pos)
{ {
if (world.getBlockState(pos).getBlock().isReplaceableOreGen(world, pos, this.replace)) if (world.getBlockState(pos).getBlock().isReplaceableOreGen(world, pos, this.replace))
{ {
world.setBlockState(pos, this.state, 2); return world.setBlockState(pos, this.state, 2);
} }
return false;
} }
@Override @Override

View file

@ -0,0 +1,316 @@
/*******************************************************************************
* Copyright 2015, the Biomes O' Plenty Team
*
* This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License.
*
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/.
******************************************************************************/
package biomesoplenty.common.world.feature.tree;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.BlockSapling;
import net.minecraft.block.BlockVine;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.World;
import org.apache.commons.lang3.tuple.Pair;
import biomesoplenty.api.biome.generation.CustomizableWeightedGenerator;
import biomesoplenty.common.util.biome.GeneratorUtils;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
public class GeneratorBasicTree extends CustomizableWeightedGenerator
{
private boolean updateNeighbours;
private int minHeight;
private int maxHeight;
private IBlockState log;
private IBlockState leaves;
private IBlockState vine;
public GeneratorBasicTree() {}
public GeneratorBasicTree(int weight, boolean updateNeighbours, int minHeight, int maxHeight, IBlockState log, IBlockState leaves, IBlockState vine)
{
super(weight);
this.updateNeighbours = updateNeighbours;
Pair<Integer, Integer> heights = GeneratorUtils.validateMinMaxHeight(minHeight, maxHeight);
this.minHeight = heights.getLeft();
this.maxHeight = heights.getRight();
this.log = log;
this.leaves = leaves;
this.vine = vine;
}
public GeneratorBasicTree(int weight, boolean updateNeighbours, int minHeight, int maxHeight, IBlockState log, IBlockState leaves)
{
this(weight, updateNeighbours, minHeight, maxHeight, log, leaves, null);
}
@Override
public boolean generate(World world, Random random, BlockPos pos)
{
int height = random.nextInt(this.maxHeight - this.minHeight) + this.minHeight;
boolean hasSpace = true;
//Generate only if we are above the lowest bedrock level (1) and reach less than the world height
//There must be a gap of 1 between the top leaf block and the world height
if (pos.getY() >= 1 && pos.getY() + height + 1 <= 256)
{
int radius;
for (int y = pos.getY(); y <= pos.getY() + 1 + height; y++)
{
radius = 1;
//Don't check for space on the first level, if we are a sapling then there will
//already be a block here (the sapling itself)
if (y == pos.getY())
{
radius = 0;
}
//At and above the top log block, require a radius of 2 to be empty
if (y >= pos.getY() + 1 + height - 2)
{
radius = 2;
}
for (int x = pos.getX() - radius; x <= pos.getX() + radius && hasSpace; ++x)
{
for (int z = pos.getZ() - radius; z <= pos.getZ() + radius && hasSpace; ++z)
{
if (y >= 0 && y < 256)
{
if (!GeneratorUtils.canTreeReplace(world, new BlockPos(x, y, z)))
{
hasSpace = false;
}
}
else
{
hasSpace = false;
}
}
}
}
if (!hasSpace)
{
return false;
}
else
{
BlockPos soilPos = pos.down();
Block soil = world.getBlockState(soilPos).getBlock();
boolean isSoil = soil.canSustainPlant(world, soilPos, EnumFacing.UP, (BlockSapling)Blocks.sapling);
if (isSoil && pos.getY() < 256 - height - 1)
{
soil.onPlantGrow(world, soilPos, pos);
int leavesLayers = 3;
//Generates leaves at the top of the tree, going one block above the top log (<= rather than <)
for (int y = pos.getY() + height - leavesLayers; y <= pos.getY() + height; y++)
{
//Determines the distance from the top of the tree as a negative number
int currentLayer = y - (pos.getY() + height);
//Uses integer division truncation (-3 / 2 = -1, -2 / 2 = -1) to reduce
//the radius closer to the top of the tree. (2, 2, 1, 1)
int leavesRadius = 1 - currentLayer / 2;
for (int x = pos.getX() - leavesRadius; x <= pos.getX() + leavesRadius; x++)
{
int xDiff = x - pos.getX();
for (int z = pos.getZ() - leavesRadius; z <= pos.getZ() + leavesRadius; ++z)
{
int zDiff = z - pos.getZ();
//Randomly prevent the generation of leaves on the corners of each layer
//If the layer is the top layer, never generate the corners
if (Math.abs(xDiff) != leavesRadius || Math.abs(zDiff) != leavesRadius || random.nextInt(2) != 0 && currentLayer != 0)
{
BlockPos leavesPos = new BlockPos(x, y, z);
Block block = world.getBlockState(leavesPos).getBlock();
if (block.isAir(world, leavesPos) || block.isLeaves(world, leavesPos) || block.getMaterial() == Material.vine)
{
this.setBlockAndNotifyAdequately(world, leavesPos, this.leaves);
}
}
}
}
}
//Create the trunk from the bottom up, using < to ensure it is covered with one layer of leaves
for (int layer = 0; layer < height; ++layer)
{
BlockPos blockpos2 = pos.up(layer);
Block block2 = world.getBlockState(blockpos2).getBlock();
if (block2.isAir(world, blockpos2) || block2.isLeaves(world, blockpos2) || block2.getMaterial() == Material.vine)
{
this.setBlockAndNotifyAdequately(world, pos.up(layer), this.log);
//If vines are enabled, randomly cover the sides of the trunk with vines from the bottom up
if (this.vine != null && layer > 0)
{
if (random.nextInt(3) > 0 && world.isAirBlock(pos.add(-1, layer, 0)))
{
this.setBlockAndNotifyAdequately(world, pos.add(-1, layer, 0), this.getVineStateForSide(EnumFacing.EAST));
}
if (random.nextInt(3) > 0 && world.isAirBlock(pos.add(1, layer, 0)))
{
this.setBlockAndNotifyAdequately(world, pos.add(1, layer, 0), this.getVineStateForSide(EnumFacing.WEST));
}
if (random.nextInt(3) > 0 && world.isAirBlock(pos.add(0, layer, -1)))
{
this.setBlockAndNotifyAdequately(world, pos.add(0, layer, -1), this.getVineStateForSide(EnumFacing.SOUTH));
}
if (random.nextInt(3) > 0 && world.isAirBlock(pos.add(0, layer, 1)))
{
this.setBlockAndNotifyAdequately(world, pos.add(0, layer, 1), this.getVineStateForSide(EnumFacing.NORTH));
}
}
}
}
if (this.vine != null)
{
for (int y = pos.getY() - leavesLayers + height; y <= pos.getY() + height; y++)
{
//Determines the distance from the top of the tree as a negative number
int currentLayer = y - (pos.getY() + height);
//Uses integer division truncation (-3 / 2 = -1, -2 / 2 = -1) to reduce
//the radius closer to the top of the tree. (3, 3, 2, 2)
int leavesRadius = 2 - currentLayer / 2;
for (int x = pos.getX() - leavesRadius; x <= pos.getX() + leavesRadius; x++)
{
for (int z = pos.getZ() - leavesRadius; z <= pos.getZ() + leavesRadius; z++)
{
BlockPos blockpos3 = new BlockPos(x, y, z);
//Surround leaves on the edge of the tree with vines and extend them downwards
if (world.getBlockState(blockpos3).getBlock().isLeaves(world, blockpos3))
{
BlockPos westPos = blockpos3.west();
BlockPos eastPos = blockpos3.east();
BlockPos northPos = blockpos3.north();
BlockPos southPos = blockpos3.south();
if (random.nextInt(4) == 0 && world.getBlockState(westPos).getBlock().isAir(world, westPos))
{
this.extendVines(world, westPos, EnumFacing.EAST);
}
if (random.nextInt(4) == 0 && world.getBlockState(eastPos).getBlock().isAir(world, eastPos))
{
this.extendVines(world, eastPos, EnumFacing.WEST);
}
if (random.nextInt(4) == 0 && world.getBlockState(northPos).getBlock().isAir(world, northPos))
{
this.extendVines(world, northPos, EnumFacing.SOUTH);
}
if (random.nextInt(4) == 0 && world.getBlockState(southPos).getBlock().isAir(world, southPos))
{
this.extendVines(world, southPos, EnumFacing.NORTH);
}
}
}
}
}
}
return true;
}
else
{
return false;
}
}
}
else
{
return false;
}
}
private IBlockState getVineStateForSide(EnumFacing side)
{
return this.vine.withProperty(BlockVine.getPropertyFor(side), Boolean.valueOf(true));
}
private void extendVines(World world, BlockPos pos, EnumFacing side)
{
IBlockState vineState = this.getVineStateForSide(side);
this.setBlockAndNotifyAdequately(world, pos, vineState);
int length = 4;
//Extend vine downwards for a maximum of 4 blocks
for (pos = pos.down(); world.getBlockState(pos).getBlock().isAir(world, pos) && length > 0; length--)
{
this.setBlockAndNotifyAdequately(world, pos, vineState);
pos = pos.down();
}
}
private void setBlockAndNotifyAdequately(World world, BlockPos pos, IBlockState state)
{
if (this.updateNeighbours)
{
world.setBlockState(pos, state, 3);
}
else
{
world.setBlockState(pos, state, 2);
}
}
@Override
public void writeToJson(JsonObject json, JsonSerializationContext context)
{
json.addProperty("weight", this.itemWeight);
json.addProperty("update_neighbours", this.updateNeighbours);
json.addProperty("min_height", this.minHeight);
json.addProperty("max_height", this.maxHeight);
json.add("log_state", context.serialize(this.log));
json.add("leaves_state", context.serialize(this.leaves));
json.add("vine_state", context.serialize(this.vine));
}
@Override
public void readFromJson(JsonObject json, JsonDeserializationContext context)
{
this.itemWeight = json.get("weight").getAsInt();
this.updateNeighbours = json.get("update_neighbours").getAsBoolean();
Pair<Integer, Integer> heights = GeneratorUtils.validateMinMaxHeight(minHeight, maxHeight);
this.minHeight = heights.getLeft();
this.maxHeight = heights.getRight();
this.log = context.deserialize(json.get("log_state"), IBlockState.class);
this.leaves = context.deserialize(json.get("leaves_state"), IBlockState.class);
this.vine = context.deserialize(json.get("vine_state"), IBlockState.class);
}
}

View file

@ -0,0 +1,77 @@
/*******************************************************************************
* Copyright 2015, the Biomes O' Plenty Team
*
* This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License.
*
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/.
******************************************************************************/
package biomesoplenty.common.world.feature.tree;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import net.minecraft.util.BlockPos;
import net.minecraft.util.WeightedRandom;
import net.minecraft.world.World;
import biomesoplenty.api.biome.generation.CustomizableGenerator;
import biomesoplenty.api.biome.generation.CustomizableWeightedGenerator;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.reflect.TypeToken;
public class GeneratorWeighted extends CustomizableGenerator
{
private int amountPerChunk;
private List<CustomizableWeightedGenerator> weightedEntries = new ArrayList<CustomizableWeightedGenerator>();
public GeneratorWeighted() {}
public GeneratorWeighted(int amountPerChunk)
{
this.amountPerChunk = amountPerChunk;
}
public void add(CustomizableWeightedGenerator entry)
{
this.weightedEntries.add(entry);
}
@Override
public void scatter(World world, Random random, BlockPos pos)
{
for (int i = 0; i < this.amountPerChunk; i++)
{
int x = random.nextInt(16) + 8;
int z = random.nextInt(16) + 8;
BlockPos genPos = world.getHeight(pos.add(x, 0, z));
generate(world, random, genPos);
}
}
@Override
public boolean generate(World world, Random random, BlockPos pos)
{
CustomizableWeightedGenerator generator = (CustomizableWeightedGenerator)WeightedRandom.getRandomItem(random, this.weightedEntries);
return generator.generate(world, random, pos);
}
@Override
public void writeToJson(JsonObject json, JsonSerializationContext context)
{
json.addProperty("amount_per_chunk", this.amountPerChunk);
json.add("entries", context.serialize(this.weightedEntries));
}
@Override
public void readFromJson(JsonObject json, JsonDeserializationContext context)
{
this.amountPerChunk = json.get("amount_per_chunk").getAsInt();
this.weightedEntries = context.deserialize(json.get("entries"), new TypeToken<List<CustomizableWeightedGenerator>>() {}.getType());
}
}