Havea generator + a few fixes
This commit is contained in:
parent
40af906c16
commit
304323d949
7 changed files with 324 additions and 32 deletions
198
src/java/mmm/materials/A_MTreeGenerator.java
Normal file
198
src/java/mmm/materials/A_MTreeGenerator.java
Normal 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 );
|
||||
|
||||
}
|
78
src/java/mmm/materials/MHeveaGenerator.java
Normal file
78
src/java/mmm/materials/MHeveaGenerator.java
Normal 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 );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -65,10 +65,7 @@ public class MLeaves
|
|||
@Override
|
||||
public Item getItemDropped( final IBlockState state , final Random rand , final int fortune )
|
||||
{
|
||||
// LOL NO FIXME
|
||||
// Should be
|
||||
// return Item.getItemFromBlock( this.wood.SAPLING );
|
||||
return Item.getItemFromBlock( Blocks.SAPLING );
|
||||
return Item.getItemFromBlock( this.wood.SAPLING );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import net.minecraft.block.material.Material;
|
|||
import net.minecraft.block.properties.PropertyInteger;
|
||||
import net.minecraft.block.state.BlockStateContainer;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.BlockRenderLayer;
|
||||
|
@ -41,6 +42,7 @@ public class MSapling
|
|||
this.setTickRandomly( true );
|
||||
this.setHardness( 0f );
|
||||
this.setSoundType( SoundType.PLANT );
|
||||
this.setCreativeTab( CreativeTabs.DECORATIONS );
|
||||
|
||||
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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
if ( this.wood.canSaplingStay( worldIn , pos , state ) ) {
|
||||
if ( this.wood.canSaplingStay( worldIn , pos ) ) {
|
||||
return true;
|
||||
}
|
||||
this.dropBlockAsItem( worldIn , pos , state , 0 );
|
||||
|
|
|
@ -12,9 +12,11 @@ import net.minecraft.init.Blocks;
|
|||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.gen.feature.WorldGenAbstractTree;
|
||||
import net.minecraftforge.common.IPlantable;
|
||||
import net.minecraftforge.fml.common.registry.GameRegistry;
|
||||
|
||||
|
||||
|
@ -24,7 +26,7 @@ public class MWood
|
|||
{
|
||||
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;
|
||||
|
@ -43,7 +45,7 @@ public class MWood
|
|||
private int fruitDropChance = 0;
|
||||
private Item fruit = null;
|
||||
|
||||
private int saplingGrowthStages = 1;
|
||||
private int saplingGrowthStages = 2;
|
||||
private float bonemealChance = .45f;
|
||||
private float growthChance = .142f;
|
||||
private int growthMinLight = 9;
|
||||
|
@ -51,10 +53,12 @@ public class MWood
|
|||
private I_SaplingChecker saplingCheck = new I_SaplingChecker( ) {
|
||||
|
||||
@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( );
|
||||
return down == Blocks.GLASS || down == Blocks.DIRT;
|
||||
final BlockPos soilPos = pos.down( );
|
||||
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;
|
||||
if ( generator != null ) {
|
||||
generator.setWood( this );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public MWood setBigTreeGenerator( final WorldGenAbstractTree generator )
|
||||
public MWood setBigTreeGenerator( final A_MTreeGenerator generator )
|
||||
{
|
||||
this.genBig = generator;
|
||||
this.genBigChance = .1f;
|
||||
return this;
|
||||
return this.setBigTreeGenerator( generator , .1f );
|
||||
}
|
||||
|
||||
|
||||
public MWood setBigTreeGenerator( final WorldGenAbstractTree generator , final float chance )
|
||||
public MWood setBigTreeGenerator( final A_MTreeGenerator generator , final float chance )
|
||||
{
|
||||
this.genBig = generator;
|
||||
this.genBigChance = chance;
|
||||
if ( generator != null ) {
|
||||
generator.setWood( this );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public MWood setMegaTreeGenerator( final WorldGenAbstractTree generator )
|
||||
public MWood setMegaTreeGenerator( final A_MTreeGenerator generator )
|
||||
{
|
||||
this.genMega = generator;
|
||||
if ( generator != null ) {
|
||||
generator.setWood( this );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -181,13 +192,17 @@ public class MWood
|
|||
public MWood register( )
|
||||
{
|
||||
URegistry.addBlock( this.LOG );
|
||||
Blocks.FIRE.setFireInfo( this.LOG , this.baseFireEncouragement , this.baseFlammability );
|
||||
|
||||
URegistry.addBlock( this.LEAVES );
|
||||
Blocks.FIRE.setFireInfo( this.LEAVES , this.baseFireEncouragement * 6 , this.baseFlammability * 12 );
|
||||
|
||||
URegistry.addBlock( this.PLANKS );
|
||||
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 );
|
||||
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 ) {
|
||||
return this.saplingCheck.canSaplingStay( worldIn , pos , state );
|
||||
return this.saplingCheck.canSaplingStay( worldIn , pos );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -97,6 +97,7 @@ public class Materials
|
|||
WOOD_HEVEA = new MWood( "hevea" ) //
|
||||
.setBarkColor( MapColor.GRAY ) //
|
||||
.setBaseFireInfo( 5 , 8 ) //
|
||||
.setTreeGenerator( new MHeveaGenerator( true ) ) //
|
||||
.register( );
|
||||
|
||||
// Items that do not correspond to metals or ores
|
||||
|
|
|
@ -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;
|
||||
if ( block instanceof I_UColoredBlock ) {
|
||||
|
@ -139,11 +139,11 @@ public class URegistry
|
|||
item = new ItemBlock( block );
|
||||
}
|
||||
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 ) ) {
|
||||
GameRegistry.register( block );
|
||||
|
@ -161,6 +161,7 @@ public class URegistry
|
|||
URegistry.addItem( blockItem , registerItemModel );
|
||||
}
|
||||
}
|
||||
return blockItem;
|
||||
}
|
||||
|
||||
|
||||
|
|
Reference in a new issue