Havea generator + a few fixes

This commit is contained in:
Emmanuel BENOîT 2016-07-09 16:20:00 +02:00
parent 40af906c16
commit 304323d949
7 changed files with 324 additions and 32 deletions

View file

@ -0,0 +1,198 @@
package mmm.materials;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.WorldGenAbstractTree;
public abstract class A_MTreeGenerator
extends WorldGenAbstractTree
{
public static class RuntimeData
{
public final BlockPos corner;
public final int xSize;
public final int zSize;
public final int height;
protected boolean mustBeEmpty[];
protected IBlockState blocks[];
public RuntimeData( final BlockPos centre , final int radius , final int height )
{
this( centre.add( -radius , 0 , -radius ) , radius * 2 + 1 , radius * 2 + 1 , height );
}
public RuntimeData( final BlockPos corner , final int xSize , final int zSize , final int height )
{
this.corner = corner;
this.xSize = xSize;
this.zSize = zSize;
this.height = height;
}
private void allocateData( )
{
this.mustBeEmpty = new boolean[ this.xSize * this.zSize * this.height ];
this.blocks = new IBlockState[ this.xSize * this.zSize * this.height ];
}
protected int getOffset( final int i , final int j , final int k )
{
return i + this.xSize * ( j + this.height * k );
}
public boolean mustBeEmpty( final int i , final int j , final int k )
{
return this.mustBeEmpty[ this.getOffset( i , j , k ) ];
}
public IBlockState getBlockState( final int i , final int j , final int k )
{
return this.blocks[ this.getOffset( i , j , k ) ];
}
public void setBlock( final int i , final int j , final int k , final Block block , final boolean mustBeEmpty )
{
this.setBlock( i , j , k , block.getDefaultState( ) , mustBeEmpty );
}
public void setBlock( final int i , final int j , final int k , final IBlockState block ,
final boolean mustBeEmpty )
{
final int offset = this.getOffset( i , j , k );
this.blocks[ offset ] = block;
this.mustBeEmpty[ offset ] = mustBeEmpty;
}
public void clearBlock( final int i , final int j , final int k )
{
final int offset = this.getOffset( i , j , k );
this.blocks[ offset ] = null;
this.mustBeEmpty[ offset ] = false;
}
public void removeCornerLeaves( final Random rand , final IBlockState leaves , final int startY ,
final int endY , final float chance )
{
for ( int y = startY ; y <= endY ; y++ ) {
for ( int x = 0 ; x < this.xSize ; x++ ) {
for ( int z = 0 ; z < this.zSize ; z++ ) {
final IBlockState bs = this.getBlockState( x , y , z );
if ( bs != leaves ) {
continue;
}
final boolean xp = this.isEmpty( x + 1 , y , z );
final boolean xn = this.isEmpty( x - 1 , y , z );
final boolean yp = this.isEmpty( x , y + 1 , z );
final boolean yn = this.isEmpty( x , y - 1 , z );
final boolean zp = this.isEmpty( x , y , z + 1 );
final boolean zn = this.isEmpty( x , y , z - 1 );
if ( xp ^ xn && yp ^ yn && zp ^ zn && rand.nextFloat( ) < chance ) {
this.clearBlock( x , y , z );
}
}
}
}
}
private boolean isEmpty( final int x , final int y , final int z )
{
if ( x < 0 || x >= this.xSize || y < 0 || y >= this.height || z < 0 || z >= this.zSize ) {
return true;
}
final IBlockState bs = this.getBlockState( x , y , z );
return bs == null || bs.getMaterial( ) == Material.AIR;
}
}
private MWood wood;
public A_MTreeGenerator( final boolean notify )
{
super( notify );
}
public MWood getWood( )
{
return this.wood;
}
void setWood( final MWood wood )
{
this.wood = wood;
}
@Override
public boolean generate( final World worldIn , final Random rand , final BlockPos position )
{
if ( position.getY( ) < 1 || !this.wood.canSaplingStay( worldIn , position ) ) {
return false;
}
final RuntimeData rtd = this.determineTreeSize( position , rand );
if ( rtd == null || position.getY( ) + 1 + rtd.height > 256 ) {
return false;
}
rtd.allocateData( );
this.generateTreeBlocks( rtd , rand );
final BlockPos.MutableBlockPos mbp = new BlockPos.MutableBlockPos( );
for ( int i = 0 ; i < rtd.xSize ; i++ ) {
for ( int j = 0 ; j < rtd.height ; j++ ) {
for ( int k = 0 ; k < rtd.zSize ; k++ ) {
if ( !rtd.mustBeEmpty( i , j , k ) ) {
continue;
}
mbp.setPos( rtd.corner.getX( ) + i , rtd.corner.getY( ) + j , rtd.corner.getZ( ) + k );
if ( !this.isReplaceable( worldIn , mbp ) ) {
return false;
}
}
}
}
for ( int i = 0 ; i < rtd.xSize ; i++ ) {
for ( int j = 0 ; j < rtd.height ; j++ ) {
for ( int k = 0 ; k < rtd.zSize ; k++ ) {
final IBlockState state = rtd.getBlockState( i , j , k );
if ( state != null ) {
final BlockPos blockPos = rtd.corner.add( i , j , k );
this.setBlockAndNotifyAdequately( worldIn , blockPos , state );
}
}
}
}
return true;
}
protected abstract RuntimeData determineTreeSize( BlockPos position , Random rand );
protected abstract void generateTreeBlocks( RuntimeData rtd , Random rand );
}

View file

@ -0,0 +1,78 @@
package mmm.materials;
import java.util.Random;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.math.BlockPos;
public class MHeveaGenerator
extends A_MTreeGenerator
{
public MHeveaGenerator( final boolean notify )
{
super( notify );
}
@Override
protected RuntimeData determineTreeSize( final BlockPos position , final Random rand )
{
final int leavesHeight = rand.nextInt( 2 ) + 2;
final int totalHeight = 1 + rand.nextInt( 2 ) + leavesHeight * 5 / 2;
return new RuntimeData( position , leavesHeight , totalHeight );
}
@Override
protected void generateTreeBlocks( final RuntimeData rtd , final Random rand )
{
final int leavesHeight = ( rtd.xSize - 1 ) / 2;
final int totalLeavesHeight = leavesHeight * 5 / 2;
final int trunkBottom = rtd.height - totalLeavesHeight;
final int lowerPart = trunkBottom + leavesHeight * 2;
final int centre = leavesHeight;
final int trunkHeight = Math.max( trunkBottom + 1 , rtd.height - ( 1 + rand.nextInt( leavesHeight ) ) );
// Lower part of the leaves
IBlockState leaves = this.getWood( ).LEAVES.getDefaultState( ).withProperty( MLeaves.CHECK_DECAY , false );
for ( int y = trunkBottom , i = 0 ; y < lowerPart ; y++ , i++ ) {
final int radius = ( i >> 1 ) + 1;
final int rSquare = radius * radius + ( i & 1 );
for ( int x = -radius ; x <= radius ; x++ ) {
for ( int z = -radius ; z <= radius ; z++ ) {
if ( ( x != 0 || z != 0 ) && x * x + z * z <= rSquare ) {
rtd.setBlock( centre + x , y , centre + z , leaves , false );
}
}
}
}
// Higher part of the leaves
for ( int y = lowerPart , radius = leavesHeight - 1 ; y < rtd.height ; y++ , radius -= 2 ) {
if ( radius <= 0 ) {
radius = 1;
}
final int rSquare = radius * radius + 1;
for ( int x = -radius ; x <= radius ; x++ ) {
for ( int z = -radius ; z <= radius ; z++ ) {
if ( ( x != centre || z != centre || y >= trunkHeight ) && x * x + z * z <= rSquare ) {
rtd.setBlock( centre + x , y , centre + z , leaves , y == rtd.height - 1 );
}
}
}
}
// Randomly remove leaves from corners
rtd.removeCornerLeaves( rand , leaves , trunkBottom , rtd.height - 1 , .4f );
// Trunk
for ( int y = 0 ; y < trunkHeight ; y++ ) {
rtd.setBlock( centre , y , centre , this.getWood( ).LOG , true );
}
}
}

View file

@ -65,10 +65,7 @@ public class MLeaves
@Override @Override
public Item getItemDropped( final IBlockState state , final Random rand , final int fortune ) public Item getItemDropped( final IBlockState state , final Random rand , final int fortune )
{ {
// LOL NO FIXME return Item.getItemFromBlock( this.wood.SAPLING );
// Should be
// return Item.getItemFromBlock( this.wood.SAPLING );
return Item.getItemFromBlock( Blocks.SAPLING );
} }

View file

@ -11,6 +11,7 @@ import net.minecraft.block.material.Material;
import net.minecraft.block.properties.PropertyInteger; import net.minecraft.block.properties.PropertyInteger;
import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.BlockRenderLayer;
@ -41,6 +42,7 @@ public class MSapling
this.setTickRandomly( true ); this.setTickRandomly( true );
this.setHardness( 0f ); this.setHardness( 0f );
this.setSoundType( SoundType.PLANT ); this.setSoundType( SoundType.PLANT );
this.setCreativeTab( CreativeTabs.DECORATIONS );
this.setDefaultState( this.blockState.getBaseState( ).withProperty( MSapling.STAGE , 0 ) ); this.setDefaultState( this.blockState.getBaseState( ).withProperty( MSapling.STAGE , 0 ) );
@ -171,7 +173,7 @@ public class MSapling
public boolean canReplace( final World world , final BlockPos pos , final EnumFacing side , final ItemStack stack ) public boolean canReplace( final World world , final BlockPos pos , final EnumFacing side , final ItemStack stack )
{ {
return world.getBlockState( pos ).getBlock( ).isReplaceable( world , pos ) return world.getBlockState( pos ).getBlock( ).isReplaceable( world , pos )
&& this.wood.canSaplingStay( world , pos , this.getStateFromMeta( stack.getMetadata( ) ) ); && this.wood.canSaplingStay( world , pos );
} }
@ -196,7 +198,7 @@ public class MSapling
private boolean checkUproot( final World worldIn , final BlockPos pos , final IBlockState state ) private boolean checkUproot( final World worldIn , final BlockPos pos , final IBlockState state )
{ {
if ( this.wood.canSaplingStay( worldIn , pos , state ) ) { if ( this.wood.canSaplingStay( worldIn , pos ) ) {
return true; return true;
} }
this.dropBlockAsItem( worldIn , pos , state , 0 ); this.dropBlockAsItem( worldIn , pos , state , 0 );

View file

@ -12,9 +12,11 @@ import net.minecraft.init.Blocks;
import net.minecraft.init.Items; import net.minecraft.init.Items;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.gen.feature.WorldGenAbstractTree; import net.minecraft.world.gen.feature.WorldGenAbstractTree;
import net.minecraftforge.common.IPlantable;
import net.minecraftforge.fml.common.registry.GameRegistry; import net.minecraftforge.fml.common.registry.GameRegistry;
@ -24,7 +26,7 @@ public class MWood
{ {
public static interface I_SaplingChecker public static interface I_SaplingChecker
{ {
public boolean canSaplingStay( World worldIn , BlockPos pos , IBlockState state ); public boolean canSaplingStay( World worldIn , BlockPos pos );
} }
public final String NAME; public final String NAME;
@ -43,7 +45,7 @@ public class MWood
private int fruitDropChance = 0; private int fruitDropChance = 0;
private Item fruit = null; private Item fruit = null;
private int saplingGrowthStages = 1; private int saplingGrowthStages = 2;
private float bonemealChance = .45f; private float bonemealChance = .45f;
private float growthChance = .142f; private float growthChance = .142f;
private int growthMinLight = 9; private int growthMinLight = 9;
@ -51,10 +53,12 @@ public class MWood
private I_SaplingChecker saplingCheck = new I_SaplingChecker( ) { private I_SaplingChecker saplingCheck = new I_SaplingChecker( ) {
@Override @Override
public boolean canSaplingStay( final World worldIn , final BlockPos pos , final IBlockState state ) public boolean canSaplingStay( final World worldIn , final BlockPos pos )
{ {
final Block down = worldIn.getBlockState( pos.down( ) ).getBlock( ); final BlockPos soilPos = pos.down( );
return down == Blocks.GLASS || down == Blocks.DIRT; final IBlockState soilState = worldIn.getBlockState( soilPos );
final Block down = soilState.getBlock( );
return down.canSustainPlant( soilState , worldIn , soilPos , EnumFacing.UP , (IPlantable) Blocks.SAPLING );
} }
}; };
@ -148,32 +152,39 @@ public class MWood
} }
public MWood setTreeGenerator( final WorldGenAbstractTree generator ) public MWood setTreeGenerator( final A_MTreeGenerator generator )
{ {
this.genNormal = generator; this.genNormal = generator;
if ( generator != null ) {
generator.setWood( this );
}
return this; return this;
} }
public MWood setBigTreeGenerator( final WorldGenAbstractTree generator ) public MWood setBigTreeGenerator( final A_MTreeGenerator generator )
{ {
this.genBig = generator; return this.setBigTreeGenerator( generator , .1f );
this.genBigChance = .1f;
return this;
} }
public MWood setBigTreeGenerator( final WorldGenAbstractTree generator , final float chance ) public MWood setBigTreeGenerator( final A_MTreeGenerator generator , final float chance )
{ {
this.genBig = generator; this.genBig = generator;
this.genBigChance = chance; this.genBigChance = chance;
if ( generator != null ) {
generator.setWood( this );
}
return this; return this;
} }
public MWood setMegaTreeGenerator( final WorldGenAbstractTree generator ) public MWood setMegaTreeGenerator( final A_MTreeGenerator generator )
{ {
this.genMega = generator; this.genMega = generator;
if ( generator != null ) {
generator.setWood( this );
}
return this; return this;
} }
@ -181,13 +192,17 @@ public class MWood
public MWood register( ) public MWood register( )
{ {
URegistry.addBlock( this.LOG ); URegistry.addBlock( this.LOG );
Blocks.FIRE.setFireInfo( this.LOG , this.baseFireEncouragement , this.baseFlammability );
URegistry.addBlock( this.LEAVES ); URegistry.addBlock( this.LEAVES );
Blocks.FIRE.setFireInfo( this.LEAVES , this.baseFireEncouragement * 6 , this.baseFlammability * 12 );
URegistry.addBlock( this.PLANKS ); URegistry.addBlock( this.PLANKS );
Blocks.FIRE.setFireInfo( this.PLANKS , this.baseFireEncouragement , this.baseFlammability * 4 ); final Item sapling = URegistry.addBlock( this.SAPLING );
if ( this.baseFlammability != 0 ) {
Blocks.FIRE.setFireInfo( this.LOG , this.baseFireEncouragement , this.baseFlammability );
Blocks.FIRE.setFireInfo( this.LEAVES , this.baseFireEncouragement * 6 , this.baseFlammability * 12 );
Blocks.FIRE.setFireInfo( this.PLANKS , this.baseFireEncouragement , this.baseFlammability * 4 );
Blocks.FIRE.setFireInfo( this.SAPLING , this.baseFireEncouragement * 2 , this.baseFlammability * 8 );
URegistry.setFuel( sapling , this.baseFlammability * 30 );
}
URegistry.addRecipeRegistrar( this ); URegistry.addRecipeRegistrar( this );
return this; return this;
@ -248,10 +263,10 @@ public class MWood
} }
public boolean canSaplingStay( final World worldIn , final BlockPos pos , final IBlockState state ) public boolean canSaplingStay( final World worldIn , final BlockPos pos )
{ {
if ( this.saplingCheck != null ) { if ( this.saplingCheck != null ) {
return this.saplingCheck.canSaplingStay( worldIn , pos , state ); return this.saplingCheck.canSaplingStay( worldIn , pos );
} }
return true; return true;
} }

View file

@ -97,6 +97,7 @@ public class Materials
WOOD_HEVEA = new MWood( "hevea" ) // WOOD_HEVEA = new MWood( "hevea" ) //
.setBarkColor( MapColor.GRAY ) // .setBarkColor( MapColor.GRAY ) //
.setBaseFireInfo( 5 , 8 ) // .setBaseFireInfo( 5 , 8 ) //
.setTreeGenerator( new MHeveaGenerator( true ) ) //
.register( ); .register( );
// Items that do not correspond to metals or ores // Items that do not correspond to metals or ores

View file

@ -118,19 +118,19 @@ public class URegistry
} }
public static void addBlock( final Block block ) public static Item addBlock( final Block block )
{ {
URegistry.addBlock( block , true ); return URegistry.addBlock( block , true );
} }
public static void addBlock( final Block block , final Item blockItem ) public static Item addBlock( final Block block , final Item blockItem )
{ {
URegistry.addBlock( block , blockItem , true ); return URegistry.addBlock( block , blockItem , true );
} }
public static void addBlock( final Block block , final boolean registerItemModel ) public static Item addBlock( final Block block , final boolean registerItemModel )
{ {
Item item; Item item;
if ( block instanceof I_UColoredBlock ) { if ( block instanceof I_UColoredBlock ) {
@ -139,11 +139,11 @@ public class URegistry
item = new ItemBlock( block ); item = new ItemBlock( block );
} }
item.setRegistryName( block.getRegistryName( ) ); item.setRegistryName( block.getRegistryName( ) );
URegistry.addBlock( block , item , registerItemModel ); return URegistry.addBlock( block , item , registerItemModel );
} }
public static void addBlock( final Block block , final Item blockItem , final boolean registerItemModel ) public static Item addBlock( final Block block , final Item blockItem , final boolean registerItemModel )
{ {
if ( URegistry.BLOCKS.add( block ) ) { if ( URegistry.BLOCKS.add( block ) ) {
GameRegistry.register( block ); GameRegistry.register( block );
@ -161,6 +161,7 @@ public class URegistry
URegistry.addItem( blockItem , registerItemModel ); URegistry.addItem( blockItem , registerItemModel );
} }
} }
return blockItem;
} }