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> 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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
@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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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