From eb16333a44ed7649709d6e469db1263451a53026 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= <tseeker@nocternity.net>
Date: Wed, 20 Jul 2016 21:09:10 +0200
Subject: [PATCH] Improved abstration for flora parameters

---
 src/java/mmm/core/api/I_FloraRegistrar.java   |  4 +-
 .../mmm/core/api/world/I_BiomeWithFlora.java  |  4 +-
 .../mmm/core/api/world/I_FloraParameters.java | 28 ++++++++++
 src/java/mmm/plants/PTomato.java              |  9 ++--
 src/java/mmm/world/gen/WGFlora.java           | 30 ++++++-----
 src/java/mmm/world/gen/WGFloraParameters.java | 54 +++++++++++++++++--
 6 files changed, 101 insertions(+), 28 deletions(-)
 create mode 100644 src/java/mmm/core/api/world/I_FloraParameters.java

diff --git a/src/java/mmm/core/api/I_FloraRegistrar.java b/src/java/mmm/core/api/I_FloraRegistrar.java
index 722c32d..6e0f2b9 100644
--- a/src/java/mmm/core/api/I_FloraRegistrar.java
+++ b/src/java/mmm/core/api/I_FloraRegistrar.java
@@ -3,13 +3,13 @@ package mmm.core.api;
 
 import java.util.List;
 
-import mmm.world.gen.WGFloraParameters;
+import mmm.core.api.world.I_FloraParameters;
 
 
 
 public interface I_FloraRegistrar
 {
 
-	public void getFloraGeneration( List< WGFloraParameters > output );
+	public void getFloraGeneration( List< I_FloraParameters > output );
 
 }
diff --git a/src/java/mmm/core/api/world/I_BiomeWithFlora.java b/src/java/mmm/core/api/world/I_BiomeWithFlora.java
index ca3be90..7055515 100644
--- a/src/java/mmm/core/api/world/I_BiomeWithFlora.java
+++ b/src/java/mmm/core/api/world/I_BiomeWithFlora.java
@@ -3,13 +3,11 @@ package mmm.core.api.world;
 
 import java.util.List;
 
-import mmm.world.gen.WGFloraParameters;
-
 
 
 public interface I_BiomeWithFlora
 {
 
-	public void addFloraParameters( List< WGFloraParameters > output );
+	public void addFloraParameters( List< I_FloraParameters > output );
 
 }
diff --git a/src/java/mmm/core/api/world/I_FloraParameters.java b/src/java/mmm/core/api/world/I_FloraParameters.java
new file mode 100644
index 0000000..7baff15
--- /dev/null
+++ b/src/java/mmm/core/api/world/I_FloraParameters.java
@@ -0,0 +1,28 @@
+package mmm.core.api.world;
+
+
+import java.util.Random;
+
+import net.minecraft.block.state.IBlockState;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.World;
+
+
+
+public interface I_FloraParameters
+{
+
+	public IBlockState getBlockState( World world , BlockPos pos , Random random );
+
+
+	public boolean canPlaceInChunk( World world , BlockPos pos );
+
+
+	public int getAmountPerChunk( World world , BlockPos pos , Random random );
+
+
+	public int getPlacementAttempts( World world , BlockPos pos , Random random );
+
+
+	public boolean canPlace( World world , BlockPos pos , Random random );
+}
diff --git a/src/java/mmm/plants/PTomato.java b/src/java/mmm/plants/PTomato.java
index 8586cef..66e53bb 100644
--- a/src/java/mmm/plants/PTomato.java
+++ b/src/java/mmm/plants/PTomato.java
@@ -11,6 +11,7 @@ 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.core.api.world.I_FloraParameters;
 import mmm.utils.UMaths;
 import mmm.world.WLocation;
 import mmm.world.WLocationRainfall;
@@ -419,18 +420,18 @@ public class PTomato
 
 
 	@Override
-	public void getFloraGeneration( final List< WGFloraParameters > output )
+	public void getFloraGeneration( final List< I_FloraParameters > output )
 	{
-		output.add( new WGFloraParameters( this.WILD.getDefaultState( ) , 1 ,
+		output.add( new WGFloraParameters( this.WILD.getDefaultState( ) , 0.2f ,
 				WLocation.inOverworld( )//
 						.and( new WLocationTemperature( 0.4f , 1f ) ) //
 						.and( new WLocationRainfall( 0.2f , 0.8f ) ) ) );
-		output.add( new WGFloraParameters( this.WILD.getDefaultState( ) , 1 ,
+		output.add( new WGFloraParameters( this.WILD.getDefaultState( ) , 0.6f ,
 				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 ,
+				this.WILD.getDefaultState( ).withProperty( PTomato.WITH_FRUITS , true ) , 0.3f ,
 				WLocation.inOverworld( )//
 						.and( new WLocationTemperature( 0.8f , 0.9f ) ) //
 						.and( new WLocationRainfall( 0.4f , 0.5f ) ) ) );
diff --git a/src/java/mmm/world/gen/WGFlora.java b/src/java/mmm/world/gen/WGFlora.java
index 141b2b5..713d263 100644
--- a/src/java/mmm/world/gen/WGFlora.java
+++ b/src/java/mmm/world/gen/WGFlora.java
@@ -7,6 +7,7 @@ import java.util.Random;
 import mmm.core.CRegistry;
 import mmm.core.api.I_FloraRegistrar;
 import mmm.core.api.world.I_BiomeWithFlora;
+import mmm.core.api.world.I_FloraParameters;
 import net.minecraft.block.state.IBlockState;
 import net.minecraft.util.math.BlockPos;
 import net.minecraft.world.World;
@@ -19,12 +20,12 @@ public class WGFlora
 		extends WorldGenerator
 {
 
-	private final ArrayList< WGFloraParameters > allConditions;
+	private final ArrayList< I_FloraParameters > allConditions;
 
 
 	public WGFlora( )
 	{
-		final ArrayList< WGFloraParameters > conditions = new ArrayList<>( );
+		final ArrayList< I_FloraParameters > conditions = new ArrayList<>( );
 		for ( final I_FloraRegistrar registrar : CRegistry.getFloraRegistrars( ) ) {
 			registrar.getFloraGeneration( conditions );
 		}
@@ -35,7 +36,7 @@ public class WGFlora
 	@Override
 	public boolean generate( final World worldIn , final Random rand , final BlockPos position )
 	{
-		final ArrayList< WGFloraParameters > candidates = this.getValidFlora( worldIn , position );
+		final ArrayList< I_FloraParameters > candidates = this.getValidFlora( worldIn , position );
 		final int nCandidates = candidates.size( );
 		if ( nCandidates == 0 ) {
 			return false;
@@ -48,12 +49,11 @@ public class WGFlora
 	}
 
 
-	private ArrayList< WGFloraParameters > getValidFlora( final World worldIn , final BlockPos position )
+	private ArrayList< I_FloraParameters > 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( ) ) ) {
+		final ArrayList< I_FloraParameters > output = new ArrayList<>( );
+		for ( final I_FloraParameters item : this.allConditions ) {
+			if ( item.canPlaceInChunk( worldIn , position ) ) {
 				output.add( item );
 			}
 		}
@@ -68,9 +68,10 @@ public class WGFlora
 
 
 	private void tryGenerate( final World worldIn , final Random rand , final BlockPos position ,
-			final WGFloraParameters parameters )
+			final I_FloraParameters parameters )
 	{
-		for ( int i = 0 ; i < parameters.perChunk ; ++i ) {
+		final int pc = parameters.getAmountPerChunk( worldIn , position , rand );
+		for ( int i = 0 ; i < pc ; ++i ) {
 			final int x = rand.nextInt( 16 ) + 8;
 			final int z = rand.nextInt( 16 ) + 8;
 
@@ -85,7 +86,7 @@ public class WGFlora
 
 
 	private void tryGeneratePlant( final World worldIn , final Random rand , BlockPos position ,
-			final WGFloraParameters parameters )
+			final I_FloraParameters parameters )
 	{
 		IBlockState bs = worldIn.getBlockState( position );
 		while ( ( bs.getBlock( ).isAir( bs , worldIn , position )
@@ -94,13 +95,14 @@ public class WGFlora
 			bs = worldIn.getBlockState( position );
 		}
 
-		for ( int i = 0 ; i < 128 ; ++i ) {
+		final int attempts = parameters.getPlacementAttempts( worldIn , position , rand );
+		for ( int i = 0 ; i < attempts ; ++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 );
+			if ( parameters.canPlace( worldIn , blockpos , rand ) ) {
+				worldIn.setBlockState( blockpos , parameters.getBlockState( worldIn , blockpos , rand ) , 2 );
 				break;
 			}
 		}
diff --git a/src/java/mmm/world/gen/WGFloraParameters.java b/src/java/mmm/world/gen/WGFloraParameters.java
index 0dff406..f3cb77b 100644
--- a/src/java/mmm/world/gen/WGFloraParameters.java
+++ b/src/java/mmm/world/gen/WGFloraParameters.java
@@ -1,19 +1,23 @@
 package mmm.world.gen;
 
 
+import java.util.Random;
 import java.util.function.BiPredicate;
 
+import mmm.core.api.world.I_FloraParameters;
 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.util.math.MathHelper;
 import net.minecraft.world.World;
 
 
 
 public class WGFloraParameters
+		implements I_FloraParameters
 {
 
 	private static BiPredicate< World , BlockPos > getDefaultPlacementCheck( final IBlockState bs )
@@ -26,31 +30,31 @@ public class WGFloraParameters
 	}
 
 	public final IBlockState floraType;
-	public final int perChunk;
+	public final float perChunk;
 	public final I_LocationCheck location;
 	public final BiPredicate< World , BlockPos > placementCheck;
 
 
-	public WGFloraParameters( final IBlockState floraType , final int perChunk )
+	public WGFloraParameters( final IBlockState floraType , final float perChunk )
 	{
 		this( floraType , perChunk , WLocation.anywhere( ) , WGFloraParameters.getDefaultPlacementCheck( floraType ) );
 	}
 
 
-	public WGFloraParameters( final IBlockState floraType , final int perChunk ,
+	public WGFloraParameters( final IBlockState floraType , final float perChunk ,
 			final BiPredicate< World , BlockPos > placementCheck )
 	{
 		this( floraType , perChunk , WLocation.anywhere( ) , placementCheck );
 	}
 
 
-	public WGFloraParameters( final IBlockState floraType , final int perChunk , final I_LocationCheck location )
+	public WGFloraParameters( final IBlockState floraType , final float perChunk , final I_LocationCheck location )
 	{
 		this( floraType , perChunk , location , WGFloraParameters.getDefaultPlacementCheck( floraType ) );
 	}
 
 
-	public WGFloraParameters( final IBlockState floraType , final int perChunk , final I_LocationCheck location ,
+	public WGFloraParameters( final IBlockState floraType , final float perChunk , final I_LocationCheck location ,
 			final BiPredicate< World , BlockPos > placementCheck )
 	{
 		this.floraType = floraType;
@@ -59,4 +63,44 @@ public class WGFloraParameters
 		this.placementCheck = placementCheck;
 	}
 
+
+	@Override
+	public IBlockState getBlockState( final World world , final BlockPos pos , final Random random )
+	{
+		return this.floraType;
+	}
+
+
+	@Override
+	public boolean canPlaceInChunk( World world , BlockPos pos )
+	{
+		return this.location.checkLocation( world , pos.getX( ) >> 4 , pos.getZ( ) >> 4 , world.getChunkProvider( ) );
+	}
+
+
+	@Override
+	public int getAmountPerChunk( final World world , final BlockPos pos , final Random random )
+	{
+		int pc = MathHelper.floor_float( this.perChunk );
+		final float remainder = this.perChunk - pc;
+		if ( remainder != 0 && random.nextFloat( ) < remainder ) {
+			pc++;
+		}
+		return pc;
+	}
+
+
+	@Override
+	public int getPlacementAttempts( final World world , final BlockPos pos , final Random random )
+	{
+		return 128;
+	}
+
+
+	@Override
+	public boolean canPlace( final World world , final BlockPos pos , final Random random )
+	{
+		return this.placementCheck.test( world , pos );
+	}
+
 }