Flora registration and generation
Also, TOMATOES!
This commit is contained in:
parent
2bb8764543
commit
2c38bbd4e0
11 changed files with 353 additions and 34 deletions
|
@ -8,6 +8,7 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
|
||||
import mmm.Mmm;
|
||||
import mmm.core.api.I_FloraRegistrar;
|
||||
import mmm.core.api.I_OreGenerationRegistrar;
|
||||
import mmm.core.api.I_RecipeRegistrar;
|
||||
import mmm.core.api.I_RequiresClientInit;
|
||||
|
@ -64,6 +65,8 @@ public class CRegistry
|
|||
|
||||
private static final HashSet< I_RecipeRegistrar > RECIPE_REGISTRARS = new HashSet<>( );
|
||||
private static final HashSet< I_OreGenerationRegistrar > ORE_GEN_REGISTRARS = new HashSet<>( );
|
||||
private static final HashSet< I_FloraRegistrar > FLORA_REGISTRARS = new HashSet<>( );
|
||||
|
||||
private static final HashSet< Item > ITEMS = new HashSet< Item >( );
|
||||
private static final HashSet< Block > BLOCKS = new HashSet< Block >( );
|
||||
|
||||
|
@ -114,7 +117,7 @@ public class CRegistry
|
|||
{
|
||||
if ( CRegistry.ITEMS.add( item ) ) {
|
||||
GameRegistry.register( item );
|
||||
CRegistry.addRecipeRegistrar( item );
|
||||
CRegistry.addRegistrar( item );
|
||||
if ( item instanceof I_RequiresClientInit ) {
|
||||
CRegistry.ITEMS_CLIENT_INIT.add( item );
|
||||
}
|
||||
|
@ -139,8 +142,7 @@ public class CRegistry
|
|||
{
|
||||
if ( CRegistry.BLOCKS.add( block ) ) {
|
||||
GameRegistry.register( block );
|
||||
CRegistry.addRecipeRegistrar( block );
|
||||
CRegistry.addOreGenerationRegistrar( block );
|
||||
CRegistry.addRegistrar( block );
|
||||
if ( block instanceof I_RequiresClientPreInit ) {
|
||||
CRegistry.BLOCKS_CLIENT_PREINIT.add( block );
|
||||
}
|
||||
|
@ -186,6 +188,14 @@ public class CRegistry
|
|||
}
|
||||
|
||||
|
||||
public static void addRegistrar( final Object object )
|
||||
{
|
||||
CRegistry.addRecipeRegistrar( object );
|
||||
CRegistry.addOreGenerationRegistrar( object );
|
||||
CRegistry.addFloraRegistrar( object );
|
||||
}
|
||||
|
||||
|
||||
public static void addRecipeRegistrar( final Object object )
|
||||
{
|
||||
if ( object instanceof I_RecipeRegistrar ) {
|
||||
|
@ -202,12 +212,26 @@ public class CRegistry
|
|||
}
|
||||
|
||||
|
||||
public static void addFloraRegistrar( final Object object )
|
||||
{
|
||||
if ( object instanceof I_FloraRegistrar ) {
|
||||
CRegistry.FLORA_REGISTRARS.add( (I_FloraRegistrar) object );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Collection< I_OreGenerationRegistrar > getOreGenerationRegistrars( )
|
||||
{
|
||||
return Collections.unmodifiableCollection( CRegistry.ORE_GEN_REGISTRARS );
|
||||
}
|
||||
|
||||
|
||||
public static Collection< I_FloraRegistrar > getFloraRegistrars( )
|
||||
{
|
||||
return Collections.unmodifiableCollection( CRegistry.FLORA_REGISTRARS );
|
||||
}
|
||||
|
||||
|
||||
public static void registerRecipes( )
|
||||
{
|
||||
for ( final I_RecipeRegistrar registrar : CRegistry.RECIPE_REGISTRARS ) {
|
||||
|
|
15
src/java/mmm/core/api/I_FloraRegistrar.java
Normal file
15
src/java/mmm/core/api/I_FloraRegistrar.java
Normal file
|
@ -0,0 +1,15 @@
|
|||
package mmm.core.api;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import mmm.world.gen.WGFloraParameters;
|
||||
|
||||
|
||||
|
||||
public interface I_FloraRegistrar
|
||||
{
|
||||
|
||||
public void getFloraGeneration( List< WGFloraParameters > output );
|
||||
|
||||
}
|
15
src/java/mmm/core/api/world/I_BiomeWithFlora.java
Normal file
15
src/java/mmm/core/api/world/I_BiomeWithFlora.java
Normal file
|
@ -0,0 +1,15 @@
|
|||
package mmm.core.api.world;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import mmm.world.gen.WGFloraParameters;
|
||||
|
||||
|
||||
|
||||
public interface I_BiomeWithFlora
|
||||
{
|
||||
|
||||
public void addFloraParameters( List< WGFloraParameters > output );
|
||||
|
||||
}
|
|
@ -14,45 +14,19 @@ public interface I_LocationCheck
|
|||
|
||||
default I_LocationCheck and( final I_LocationCheck other )
|
||||
{
|
||||
final I_LocationCheck self = this;
|
||||
return new I_LocationCheck( ) {
|
||||
@Override
|
||||
public boolean checkLocation( final World world , final int chunkX , final int chunkZ ,
|
||||
final IChunkProvider provider )
|
||||
{
|
||||
return self.checkLocation( world , chunkX , chunkZ , provider )
|
||||
&& other.checkLocation( world , chunkX , chunkZ , provider );
|
||||
}
|
||||
};
|
||||
return ( w , x , z , p ) -> this.checkLocation( w , x , z , p ) && other.checkLocation( w , x , z , p );
|
||||
}
|
||||
|
||||
|
||||
default I_LocationCheck or( final I_LocationCheck other )
|
||||
{
|
||||
final I_LocationCheck self = this;
|
||||
return new I_LocationCheck( ) {
|
||||
@Override
|
||||
public boolean checkLocation( final World world , final int chunkX , final int chunkZ ,
|
||||
final IChunkProvider provider )
|
||||
{
|
||||
return self.checkLocation( world , chunkX , chunkZ , provider )
|
||||
|| other.checkLocation( world , chunkX , chunkZ , provider );
|
||||
}
|
||||
};
|
||||
return ( w , x , z , p ) -> this.checkLocation( w , x , z , p ) || other.checkLocation( w , x , z , p );
|
||||
}
|
||||
|
||||
|
||||
default I_LocationCheck invert( )
|
||||
{
|
||||
final I_LocationCheck self = this;
|
||||
return new I_LocationCheck( ) {
|
||||
@Override
|
||||
public boolean checkLocation( final World world , final int chunkX , final int chunkZ ,
|
||||
final IChunkProvider provider )
|
||||
{
|
||||
return !self.checkLocation( world , chunkX , chunkZ , provider );
|
||||
}
|
||||
};
|
||||
return ( w , x , z , p ) -> !this.checkLocation( w , x , z , p );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,9 +8,14 @@ import java.util.Random;
|
|||
import javax.annotation.Nullable;
|
||||
|
||||
import mmm.core.CRegistry;
|
||||
import mmm.core.api.I_FloraRegistrar;
|
||||
import mmm.core.api.I_RecipeRegistrar;
|
||||
import mmm.core.api.blocks.I_StateMapperProvider;
|
||||
import mmm.utils.UMaths;
|
||||
import mmm.world.WLocation;
|
||||
import mmm.world.WLocationRainfall;
|
||||
import mmm.world.WLocationTemperature;
|
||||
import mmm.world.gen.WGFloraParameters;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockBush;
|
||||
import net.minecraft.block.IGrowable;
|
||||
|
@ -40,7 +45,7 @@ import net.minecraftforge.fml.common.registry.GameRegistry;
|
|||
|
||||
|
||||
public class PTomato
|
||||
implements I_RecipeRegistrar
|
||||
implements I_RecipeRegistrar , I_FloraRegistrar
|
||||
{
|
||||
public static final PropertyInteger AGE = PropertyInteger.create( "age" , 0 , 15 );
|
||||
public static final PropertyInteger SIZE = PropertyInteger.create( "size" , 0 , 3 );
|
||||
|
@ -401,7 +406,7 @@ public class PTomato
|
|||
CRegistry.addBlock( this.CROP = new Plant( ) , null );
|
||||
this.SEEDS = PPlantsHelper.makeSeeds( "tomato" , this.CROP );
|
||||
this.FRUIT = PPlantsHelper.makeFruit( "tomato" , 2 , .15f );
|
||||
CRegistry.addRecipeRegistrar( this );
|
||||
CRegistry.addRegistrar( this );
|
||||
}
|
||||
|
||||
|
||||
|
@ -412,4 +417,23 @@ public class PTomato
|
|||
new ItemStack( this.FRUIT ) );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void getFloraGeneration( final List< WGFloraParameters > output )
|
||||
{
|
||||
output.add( new WGFloraParameters( this.WILD.getDefaultState( ) , 1 ,
|
||||
WLocation.inOverworld( )//
|
||||
.and( new WLocationTemperature( 0.4f , 1f ) ) //
|
||||
.and( new WLocationRainfall( 0.2f , 0.8f ) ) ) );
|
||||
output.add( new WGFloraParameters( this.WILD.getDefaultState( ) , 1 ,
|
||||
WLocation.inOverworld( )//
|
||||
.and( new WLocationTemperature( 0.7f , 1f ) ) //
|
||||
.and( new WLocationRainfall( 0.3f , 0.5f ) ) ) );
|
||||
output.add( new WGFloraParameters( //
|
||||
this.WILD.getDefaultState( ).withProperty( PTomato.WITH_FRUITS , true ) , 1 ,
|
||||
WLocation.inOverworld( )//
|
||||
.and( new WLocationTemperature( 0.8f , 0.9f ) ) //
|
||||
.and( new WLocationRainfall( 0.4f , 0.5f ) ) ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,11 +6,13 @@ import java.util.Random;
|
|||
import mmm.core.api.world.I_DefaultPopulateHandler;
|
||||
import mmm.core.api.world.I_TrappedBiome;
|
||||
import mmm.world.gen.WGBasalt;
|
||||
import mmm.world.gen.WGFlora;
|
||||
import mmm.world.gen.WGTrapBlocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.BiomeDesert;
|
||||
import net.minecraft.world.biome.BiomeSwamp;
|
||||
import net.minecraftforge.event.terraingen.DecorateBiomeEvent;
|
||||
import net.minecraftforge.event.terraingen.PopulateChunkEvent;
|
||||
import net.minecraftforge.fml.common.eventhandler.Event.Result;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
|
@ -19,6 +21,8 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
|||
|
||||
public class WDefaultGenWatcher
|
||||
{
|
||||
private final WGFlora floraGenerator = new WGFlora( );
|
||||
|
||||
|
||||
@SubscribeEvent
|
||||
public void onPopulate( final PopulateChunkEvent.Populate event )
|
||||
|
@ -61,4 +65,12 @@ public class WDefaultGenWatcher
|
|||
traps.generate( world , rand , bp );
|
||||
}
|
||||
|
||||
|
||||
@SubscribeEvent
|
||||
public void onBiomeDecorate( DecorateBiomeEvent.Decorate event )
|
||||
{
|
||||
if ( event.getType( ) == DecorateBiomeEvent.Decorate.EventType.GRASS ) {
|
||||
this.floraGenerator.generate( event.getWorld( ) , event.getRand( ) , event.getPos( ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ import net.minecraft.world.biome.Biome;
|
|||
|
||||
public class WLocation
|
||||
{
|
||||
private static final I_LocationCheck ANYWHERE = ( w , x , z , p ) -> true;
|
||||
|
||||
private static I_LocationCheck inOverworld;
|
||||
private static I_LocationCheck inTheNether;
|
||||
|
||||
|
@ -40,4 +42,10 @@ public class WLocation
|
|||
{
|
||||
return new WLocationInBiomeClass<>( biomeType );
|
||||
}
|
||||
|
||||
|
||||
public static I_LocationCheck anywhere( )
|
||||
{
|
||||
return WLocation.ANYWHERE;
|
||||
}
|
||||
}
|
||||
|
|
38
src/java/mmm/world/WLocationRainfall.java
Normal file
38
src/java/mmm/world/WLocationRainfall.java
Normal file
|
@ -0,0 +1,38 @@
|
|||
package mmm.world;
|
||||
|
||||
|
||||
import mmm.core.api.world.I_LocationCheck;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.chunk.IChunkProvider;
|
||||
|
||||
|
||||
|
||||
public class WLocationRainfall
|
||||
implements I_LocationCheck
|
||||
{
|
||||
public final float minRainfall;
|
||||
public final float maxRainfall;
|
||||
|
||||
|
||||
public WLocationRainfall( final float minRainfall , final float maxRainfall )
|
||||
{
|
||||
if ( maxRainfall < minRainfall ) {
|
||||
throw new IllegalArgumentException( "minimal rainfall is higher than maximal rainfall" );
|
||||
}
|
||||
this.minRainfall = minRainfall;
|
||||
this.maxRainfall = maxRainfall;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean checkLocation( final World world , final int chunkX , final int chunkZ ,
|
||||
final IChunkProvider provider )
|
||||
{
|
||||
final Biome biome = world.getBiomeGenForCoords( new BlockPos( chunkX * 16 , 0 , chunkZ * 16 ) );
|
||||
final float rf = biome.getRainfall( );
|
||||
return rf >= this.minRainfall && rf <= this.maxRainfall;
|
||||
}
|
||||
|
||||
}
|
38
src/java/mmm/world/WLocationTemperature.java
Normal file
38
src/java/mmm/world/WLocationTemperature.java
Normal file
|
@ -0,0 +1,38 @@
|
|||
package mmm.world;
|
||||
|
||||
|
||||
import mmm.core.api.world.I_LocationCheck;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.chunk.IChunkProvider;
|
||||
|
||||
|
||||
|
||||
public class WLocationTemperature
|
||||
implements I_LocationCheck
|
||||
{
|
||||
public final float minTemperature;
|
||||
public final float maxTemperature;
|
||||
|
||||
|
||||
public WLocationTemperature( final float minTemperature , final float maxTemperature )
|
||||
{
|
||||
if ( maxTemperature < minTemperature ) {
|
||||
throw new IllegalArgumentException( "minimal temperature is higher than maximal temperature" );
|
||||
}
|
||||
this.minTemperature = minTemperature;
|
||||
this.maxTemperature = maxTemperature;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean checkLocation( final World world , final int chunkX , final int chunkZ ,
|
||||
final IChunkProvider provider )
|
||||
{
|
||||
final Biome biome = world.getBiomeGenForCoords( new BlockPos( chunkX * 16 , 0 , chunkZ * 16 ) );
|
||||
final float t = biome.getTemperature( );
|
||||
return t >= this.minTemperature && t <= this.maxTemperature;
|
||||
}
|
||||
|
||||
}
|
109
src/java/mmm/world/gen/WGFlora.java
Normal file
109
src/java/mmm/world/gen/WGFlora.java
Normal file
|
@ -0,0 +1,109 @@
|
|||
package mmm.world.gen;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
import mmm.core.CRegistry;
|
||||
import mmm.core.api.I_FloraRegistrar;
|
||||
import mmm.core.api.world.I_BiomeWithFlora;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.gen.feature.WorldGenerator;
|
||||
|
||||
|
||||
|
||||
public class WGFlora
|
||||
extends WorldGenerator
|
||||
{
|
||||
|
||||
private final ArrayList< WGFloraParameters > allConditions;
|
||||
|
||||
|
||||
public WGFlora( )
|
||||
{
|
||||
final ArrayList< WGFloraParameters > conditions = new ArrayList<>( );
|
||||
for ( final I_FloraRegistrar registrar : CRegistry.getFloraRegistrars( ) ) {
|
||||
registrar.getFloraGeneration( conditions );
|
||||
}
|
||||
this.allConditions = conditions;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean generate( final World worldIn , final Random rand , final BlockPos position )
|
||||
{
|
||||
final ArrayList< WGFloraParameters > candidates = this.getValidFlora( worldIn , position );
|
||||
final int nCandidates = candidates.size( );
|
||||
if ( nCandidates == 0 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( int i = 0 ; i < nCandidates ; i++ ) {
|
||||
this.tryGenerate( worldIn , rand , position , candidates.get( i ) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private ArrayList< WGFloraParameters > getValidFlora( final World worldIn , final BlockPos position )
|
||||
{
|
||||
final ArrayList< WGFloraParameters > output = new ArrayList<>( );
|
||||
for ( final WGFloraParameters item : this.allConditions ) {
|
||||
if ( item.location.checkLocation( worldIn , position.getX( ) >> 4 , position.getZ( ) >> 4 ,
|
||||
worldIn.getChunkProvider( ) ) ) {
|
||||
output.add( item );
|
||||
}
|
||||
}
|
||||
|
||||
final Biome biome = worldIn.getBiomeGenForCoords( position );
|
||||
if ( biome instanceof I_BiomeWithFlora ) {
|
||||
( (I_BiomeWithFlora) biome ).addFloraParameters( output );
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
private void tryGenerate( final World worldIn , final Random rand , final BlockPos position ,
|
||||
final WGFloraParameters parameters )
|
||||
{
|
||||
for ( int i = 0 ; i < parameters.perChunk ; ++i ) {
|
||||
final int x = rand.nextInt( 16 ) + 8;
|
||||
final int z = rand.nextInt( 16 ) + 8;
|
||||
|
||||
final int height = worldIn.getHeight( position.add( x , 0 , z ) ).getY( ) * 2;
|
||||
if ( height <= 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.tryGeneratePlant( worldIn , rand , position.add( x , rand.nextInt( height ) , z ) , parameters );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void tryGeneratePlant( final World worldIn , final Random rand , BlockPos position ,
|
||||
final WGFloraParameters parameters )
|
||||
{
|
||||
IBlockState bs = worldIn.getBlockState( position );
|
||||
while ( ( bs.getBlock( ).isAir( bs , worldIn , position )
|
||||
|| bs.getBlock( ).isLeaves( bs , worldIn , position ) ) && position.getY( ) > 0 ) {
|
||||
position = position.down( );
|
||||
bs = worldIn.getBlockState( position );
|
||||
}
|
||||
|
||||
for ( int i = 0 ; i < 128 ; ++i ) {
|
||||
final BlockPos blockpos = position.add( //
|
||||
rand.nextInt( 8 ) - rand.nextInt( 8 ) , //
|
||||
rand.nextInt( 4 ) - rand.nextInt( 4 ) , //
|
||||
rand.nextInt( 8 ) - rand.nextInt( 8 ) );
|
||||
if ( parameters.placementCheck.test( worldIn , blockpos ) ) {
|
||||
worldIn.setBlockState( blockpos , parameters.floraType , 2 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
62
src/java/mmm/world/gen/WGFloraParameters.java
Normal file
62
src/java/mmm/world/gen/WGFloraParameters.java
Normal file
|
@ -0,0 +1,62 @@
|
|||
package mmm.world.gen;
|
||||
|
||||
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
import mmm.core.api.world.I_LocationCheck;
|
||||
import mmm.world.WLocation;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockBush;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
|
||||
|
||||
public class WGFloraParameters
|
||||
{
|
||||
|
||||
private static BiPredicate< World , BlockPos > getDefaultPlacementCheck( final IBlockState bs )
|
||||
{
|
||||
final Block block = bs.getBlock( );
|
||||
if ( block instanceof BlockBush ) {
|
||||
return ( w , p ) -> w.isAirBlock( p ) && ( (BlockBush) block ).canBlockStay( w , p , bs );
|
||||
}
|
||||
return ( w , p ) -> w.isAirBlock( p ) && !w.isAirBlock( p.down( ) );
|
||||
}
|
||||
|
||||
public final IBlockState floraType;
|
||||
public final int perChunk;
|
||||
public final I_LocationCheck location;
|
||||
public final BiPredicate< World , BlockPos > placementCheck;
|
||||
|
||||
|
||||
public WGFloraParameters( final IBlockState floraType , final int perChunk )
|
||||
{
|
||||
this( floraType , perChunk , WLocation.anywhere( ) , WGFloraParameters.getDefaultPlacementCheck( floraType ) );
|
||||
}
|
||||
|
||||
|
||||
public WGFloraParameters( final IBlockState floraType , final int perChunk ,
|
||||
final BiPredicate< World , BlockPos > placementCheck )
|
||||
{
|
||||
this( floraType , perChunk , WLocation.anywhere( ) , placementCheck );
|
||||
}
|
||||
|
||||
|
||||
public WGFloraParameters( final IBlockState floraType , final int perChunk , final I_LocationCheck location )
|
||||
{
|
||||
this( floraType , perChunk , location , WGFloraParameters.getDefaultPlacementCheck( floraType ) );
|
||||
}
|
||||
|
||||
|
||||
public WGFloraParameters( final IBlockState floraType , final int perChunk , final I_LocationCheck location ,
|
||||
final BiPredicate< World , BlockPos > placementCheck )
|
||||
{
|
||||
this.floraType = floraType;
|
||||
this.perChunk = perChunk;
|
||||
this.location = location;
|
||||
this.placementCheck = placementCheck;
|
||||
}
|
||||
|
||||
}
|
Reference in a new issue