Began work on the Origin Valley, trees currently generate
This commit is contained in:
parent
3a24ac037f
commit
ab961ba89b
17 changed files with 664 additions and 58 deletions
|
@ -17,4 +17,5 @@ public class BOPBiomes
|
|||
public static Optional<BiomeGenBase> alps = Optional.absent();
|
||||
public static Optional<BiomeGenBase> arctic = Optional.absent();
|
||||
public static Optional<BiomeGenBase> crag = Optional.absent();
|
||||
public static Optional<BiomeGenBase> originValley = Optional.absent();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -47,7 +47,9 @@ public enum GeneratorStage
|
|||
@SerializedName("tree")
|
||||
TREE(Decorate.EventType.TREE),
|
||||
@SerializedName("post")
|
||||
POST(null);
|
||||
POST(null),
|
||||
@SerializedName("parent")
|
||||
PARENT(null);
|
||||
|
||||
private Decorate.EventType decorateType;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ import com.google.gson.JsonSerializationContext;
|
|||
public interface IGenerator
|
||||
{
|
||||
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 setStage(GeneratorStage stage);
|
||||
|
|
|
@ -24,7 +24,7 @@ public class BiomeGenCrag extends BOPBiome
|
|||
{
|
||||
this.setHeight(biomeHeight);
|
||||
this.setColor(5209457);
|
||||
this.setTemperatureRainfall(2.0F, 0.0F);
|
||||
this.setTemperatureRainfall(1.0F, 0.0F);
|
||||
|
||||
this.addWeight(BiomeType.COOL, 3);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -112,30 +112,34 @@ public class BlockBOPGrass extends BlockGrass implements IBOPBlock
|
|||
@Override
|
||||
public boolean canSustainPlant(IBlockAccess world, BlockPos pos, EnumFacing direction, net.minecraftforge.common.IPlantable plantable)
|
||||
{
|
||||
|
||||
|
||||
IBlockState state = world.getBlockState(pos);
|
||||
net.minecraftforge.common.EnumPlantType plantType = plantable.getPlantType(world, pos.offset(direction));
|
||||
|
||||
switch ((BOPGrassType) state.getValue(VARIANT))
|
||||
//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)
|
||||
{
|
||||
// smoldering grass supports no plants
|
||||
switch ((BOPGrassType) state.getValue(VARIANT))
|
||||
{
|
||||
// smoldering grass supports no plants
|
||||
case SMOLDERING:
|
||||
return false;
|
||||
|
||||
// origin grass supports all plants (including crop type - no need for hoe)
|
||||
|
||||
// origin grass supports all plants (including crop type - no need for hoe)
|
||||
case ORIGIN:
|
||||
return true;
|
||||
|
||||
// overgrown_netherrack supports Nether plants in addition to the defaults
|
||||
|
||||
// overgrown_netherrack supports Nether plants in addition to the defaults
|
||||
case OVERGROWN_NETHERRACK:
|
||||
if (plantType == net.minecraftforge.common.EnumPlantType.Nether) {return true;}
|
||||
break;
|
||||
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
switch (plantType)
|
||||
{
|
||||
}
|
||||
|
||||
switch (plantType)
|
||||
{
|
||||
// support desert and plains plants
|
||||
case Desert: case Plains: return true;
|
||||
// support cave plants
|
||||
|
@ -143,15 +147,18 @@ public class BlockBOPGrass extends BlockGrass implements IBOPBlock
|
|||
// support beach plants if there's water alongside
|
||||
case Beach:
|
||||
return (
|
||||
world.getBlockState(pos.east()).getBlock().getMaterial() == Material.water ||
|
||||
world.getBlockState(pos.west()).getBlock().getMaterial() == Material.water ||
|
||||
world.getBlockState(pos.north()).getBlock().getMaterial() == Material.water ||
|
||||
world.getBlockState(pos.south()).getBlock().getMaterial() == Material.water
|
||||
);
|
||||
// don't support nether plants, water plants, or crops (require farmland), or anything else by default
|
||||
world.getBlockState(pos.east()).getBlock().getMaterial() == Material.water ||
|
||||
world.getBlockState(pos.west()).getBlock().getMaterial() == Material.water ||
|
||||
world.getBlockState(pos.north()).getBlock().getMaterial() == Material.water ||
|
||||
world.getBlockState(pos.south()).getBlock().getMaterial() == Material.water
|
||||
);
|
||||
// don't support nether plants, water plants, or crops (require farmland), or anything else by default
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return super.canSustainPlant(world, pos, direction, plantable);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -15,7 +15,9 @@ import net.minecraft.world.World;
|
|||
import net.minecraft.world.biome.BiomeGenBase;
|
||||
import net.minecraftforge.event.terraingen.DecorateBiomeEvent;
|
||||
import net.minecraftforge.event.terraingen.DecorateBiomeEvent.Decorate;
|
||||
import net.minecraftforge.fml.common.eventhandler.Event.Result;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import biomesoplenty.api.biome.BiomeOwner;
|
||||
import biomesoplenty.api.biome.IExtendedBiome;
|
||||
import biomesoplenty.api.biome.generation.GenerationManager;
|
||||
import biomesoplenty.api.biome.generation.GeneratorStage;
|
||||
|
@ -35,7 +37,9 @@ public class DecorateBiomeEventHandler
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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));
|
||||
IExtendedBiome extendedBiome = ExtendedBiomeRegistry.getExtension(biome);
|
||||
|
@ -58,6 +62,17 @@ public class DecorateBiomeEventHandler
|
|||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.apache.commons.io.FileUtils;
|
|||
import biomesoplenty.common.biome.overworld.BiomeGenAlps;
|
||||
import biomesoplenty.common.biome.overworld.BiomeGenArctic;
|
||||
import biomesoplenty.common.biome.overworld.BiomeGenCrag;
|
||||
import biomesoplenty.common.biome.overworld.BiomeGenOriginValley;
|
||||
import biomesoplenty.common.command.BOPCommand;
|
||||
import biomesoplenty.common.util.config.JsonBiome;
|
||||
import biomesoplenty.common.world.WorldTypeBOP;
|
||||
|
@ -47,6 +48,7 @@ public class ModBiomes
|
|||
alps = registerBiome(new BiomeGenAlps().setBiomeName("Alps"), "alps");
|
||||
arctic = registerBiome(new BiomeGenArctic().setBiomeName("Arctic"), "arctic");
|
||||
crag = registerBiome(new BiomeGenCrag().setBiomeName("Crag"), "crag");
|
||||
originValley = registerBiome(new BiomeGenOriginValley().setBiomeName("Origin Valley"), "origin_valley");
|
||||
}
|
||||
|
||||
private static void registerExternalBiomes()
|
||||
|
|
|
@ -11,6 +11,8 @@ package biomesoplenty.common.init;
|
|||
import static biomesoplenty.api.biome.generation.GeneratorRegistry.registerGenerator;
|
||||
import biomesoplenty.common.world.feature.GeneratorOreCluster;
|
||||
import biomesoplenty.common.world.feature.GeneratorOreSingle;
|
||||
import biomesoplenty.common.world.feature.tree.GeneratorBasicTree;
|
||||
import biomesoplenty.common.world.feature.tree.GeneratorWeighted;
|
||||
|
||||
public class ModGenerators
|
||||
{
|
||||
|
@ -18,5 +20,7 @@ public class ModGenerators
|
|||
{
|
||||
registerGenerator("ore_single", GeneratorOreSingle.class);
|
||||
registerGenerator("ore_cluster", GeneratorOreCluster.class);
|
||||
registerGenerator("weighted", GeneratorWeighted.class);
|
||||
registerGenerator("basic_tree", GeneratorBasicTree.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -60,8 +60,8 @@ public class GeneratorTypeAdaptor implements JsonSerializer<IGenerator>, JsonDes
|
|||
generator = (IGenerator)generatorClass.newInstance();
|
||||
|
||||
Type generatorStageType = new TypeToken<GeneratorStage>() {}.getType();
|
||||
String generatorStageName = jsonObject.get("stage").getAsString();
|
||||
GeneratorStage generatorStage = (GeneratorStage)context.deserialize(jsonObject.get("stage"), generatorStageType);
|
||||
String generatorStageName = jsonObject.get("stage") != null ? jsonObject.get("stage").getAsString() : null;
|
||||
|
||||
if (generatorStage == null)
|
||||
{
|
||||
|
|
|
@ -12,7 +12,11 @@ import java.util.Random;
|
|||
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import biomesoplenty.api.biome.generation.CustomizableGenerator;
|
||||
import biomesoplenty.common.util.biome.GeneratorUtils;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
|
@ -29,8 +33,10 @@ public abstract class GeneratorOreBase extends CustomizableGenerator
|
|||
protected GeneratorOreBase(int amountPerChunk, int minHeight, int maxHeight)
|
||||
{
|
||||
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
|
||||
|
@ -59,33 +65,8 @@ public abstract class GeneratorOreBase extends CustomizableGenerator
|
|||
int minHeight = json.get("min_height").getAsInt();
|
||||
int maxHeight = json.get("max_height").getAsInt();
|
||||
|
||||
validateMinMaxHeight(minHeight, maxHeight);
|
||||
}
|
||||
|
||||
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;
|
||||
Pair<Integer, Integer> heights = GeneratorUtils.validateMinMaxHeight(minHeight, maxHeight);
|
||||
this.minHeight = heights.getLeft();
|
||||
this.maxHeight = heights.getRight();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,9 +33,9 @@ public class GeneratorOreCluster extends GeneratorOreBase
|
|||
}
|
||||
|
||||
@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
|
||||
|
|
|
@ -39,12 +39,14 @@ public class GeneratorOreSingle extends GeneratorOreBase
|
|||
}
|
||||
|
||||
@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))
|
||||
{
|
||||
world.setBlockState(pos, this.state, 2);
|
||||
return world.setBlockState(pos, this.state, 2);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue