Jump to content

[ 1.14+ ] Change blockstate when its Raining and Not Raining.


Kikoz

Recommended Posts

Hello! I'm trying to make my custom campfire to unlit when it is raining and lit automatically when it is not raining.

This is my code, the thing is, it only works when I start the world, not otherwise. I'm still learning coding don't be harsh on me thanks!

 

	public void litWhenRaining(World worldIn, BlockPos pos) {
		      if (worldIn.rand.nextInt(10) == 1 && worldIn.isRaining()) {
		            BlockState blockstate = worldIn.getBlockState(pos);
		            worldIn.setBlockState(pos, blockstate.cycle(LIT), 1);
		         } if (worldIn.rand.nextInt(10) == 1 && !worldIn.isRaining()){
		        	 BlockState blockstate = worldIn.getBlockState(pos);
		               worldIn.setBlockState(pos, blockstate.cycle(LIT), 0);
		            }
		      }

 

Link to comment
Share on other sites

Where are you actually running your code?

If you want it to change instantly you'll have to make a ticking tile entity (see how the daylight sensor works). Since that's not good for performance, you may want to just override the Block#tick method and let it update randomly (like how farmland and leaves works).

I'm eager to learn and am prone to mistakes. Don't hesitate to tell me how I can improve.

Link to comment
Share on other sites

1 hour ago, imacatlolol said:

Where are you actually running your code?

If you want it to change instantly you'll have to make a ticking tile entity (see how the daylight sensor works). Since that's not good for performance, you may want to just override the Block#tick method and let it update randomly (like how farmland and leaves works).

Well I made the part where it changes when raining by looking at the cauldron - fillWithRain. I just need a way to make it change back when it stops raining.

Link to comment
Share on other sites

15 minutes ago, Kikoz said:

Well I made the part where it changes when raining by looking at the cauldron - fillWithRain. I just need a way to make it change back when it stops raining.

Oh! Neat, I didn't recognize that as a vanilla method.

Actually, looking at your code a little closer, you're misusing World#setBlockState and BlockState#cycle entirely. The integer parameter is for flags which are used for updating and syncing. You should use a flag of 11 for both lighting and un-lighting the block.

As for the BlockState, you should use the with method instead of cycle.

Edited by imacatlolol
Typo

I'm eager to learn and am prone to mistakes. Don't hesitate to tell me how I can improve.

Link to comment
Share on other sites

37 minutes ago, imacatlolol said:

Oh! Neat, I didn't recognize that as a vanilla method.

Actually, looking at your code a little closer, you're misusing World#setBlockState and BlockState#cycle entirely. The integer parameter is for flags which are used for updating and syncing. You should use a flag of 11 for both lighting and un-lighting the block.

As for the BlockState, you should use the with method instead of cycle.

Now after looking into Farmland, I've changed it to this:

  public void ChangeWhenClear(BlockState stateIn, World worldIn, BlockPos pos, Random rand) {
     if (!worldIn.isRaining()) {
        if (rand.nextInt(5) == 1) {
           BlockState blockstate = worldIn.getBlockState(pos);
           if (blockstate.get(LIT) == true) {
	    		  worldIn.setBlockState(pos, blockstate.with(LIT, Boolean.valueOf(false)));
	      }
        }
     }
  }

But it still is not working, the fillWithRain works well. 

Link to comment
Share on other sites

   public void ChangeWhenClear(BlockState state, World worldIn, BlockPos pos, Random rand) {
    	  
         if (!worldIn.isRainingAt(pos.up()) && rand.nextInt(5) == 1) { 
                 worldIn.setBlockState(pos, state.with(LIT, Boolean.valueOf(false)));
            }
      }

Still can't get it to work.. Am I blind?

Link to comment
Share on other sites

8 minutes ago, diesieben07 said:

Could you, idk, show that code so we can debug the problem...?

package com.spcmf.pete11.objects.custommodels;

import java.util.Random;
import java.util.stream.IntStream;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.HorizontalBlock;
import net.minecraft.block.IWaterLoggable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluids;
import net.minecraft.fluid.IFluidState;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.pathfinding.PathType;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.DirectionProperty;
import net.minecraft.state.EnumProperty;
import net.minecraft.state.StateContainer;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.Half;
import net.minecraft.state.properties.StairsShape;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.world.Explosion;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;


public class CustomCampfire extends Block implements IWaterLoggable {
   public static final DirectionProperty FACING = HorizontalBlock.HORIZONTAL_FACING;
   public static final EnumProperty<Half> HALF = BlockStateProperties.HALF;
   public static final EnumProperty<StairsShape> SHAPE = BlockStateProperties.STAIRS_SHAPE;
   public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
   
   public static final BooleanProperty LIT = BlockStateProperties.LIT;
   
   protected static final VoxelShape AABB_SLAB_TOP = Block.makeCuboidShape(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D);
   protected static final VoxelShape AABB_SLAB_BOTTOM = Block.makeCuboidShape(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D);
   
   protected static final VoxelShape NWD_CORNER = Block.makeCuboidShape(0.0D, 10.0D, 0.0D, 8.0D, 15.0D, 8.0D);
   protected static final VoxelShape SWD_CORNER = Block.makeCuboidShape(0.0D, 10.0D, 8.0D, 8.0D, 15.0D, 16.0D);
   protected static final VoxelShape NED_CORNER = Block.makeCuboidShape(8.0D, 10.0D, 0.0D, 16.0D, 15.0D, 8.0D);
   protected static final VoxelShape SED_CORNER = Block.makeCuboidShape(8.0D, 10.0D, 8.0D, 16.0D, 15.0D, 16.0D);

   protected static final VoxelShape[] SLAB_TOP_SHAPES = makeShapes(AABB_SLAB_TOP, NWD_CORNER, NED_CORNER, SWD_CORNER, SED_CORNER);
   protected static final VoxelShape[] SLAB_BOTTOM_SHAPES = makeShapes(AABB_SLAB_BOTTOM, NWD_CORNER, NED_CORNER, SWD_CORNER, SED_CORNER);
   private static final int[] field_196522_K = new int[]{12, 5, 3, 10, 14, 13, 7, 11, 13, 7, 11, 14, 8, 4, 1, 2, 4, 1, 2, 8};

   private final Block modelBlock;
   private final BlockState modelState;

   private static VoxelShape[] makeShapes(VoxelShape slabShape, VoxelShape nwCorner, VoxelShape neCorner, VoxelShape swCorner, VoxelShape seCorner) {
      return IntStream.range(0, 16).mapToObj((p_199780_5_) -> {
         return combineShapes(p_199780_5_, slabShape, nwCorner, neCorner, swCorner, seCorner);
      }).toArray((p_199778_0_) -> {
         return new VoxelShape[p_199778_0_];
      });
   }

   /**
    * combines the shapes according to the mode set in the bitfield
    */
   private static VoxelShape combineShapes(int bitfield, VoxelShape slabShape, VoxelShape nwCorner, VoxelShape neCorner, VoxelShape swCorner, VoxelShape seCorner) {
      VoxelShape voxelshape = slabShape;
      if ((bitfield & 1) != 0) {
         voxelshape = VoxelShapes.or(slabShape, nwCorner);
      }

      if ((bitfield & 2) != 0) {
         voxelshape = VoxelShapes.or(voxelshape, neCorner);
      }

      if ((bitfield & 4) != 0) {
         voxelshape = VoxelShapes.or(voxelshape, swCorner);
      }

      if ((bitfield & 8) != 0) {
         voxelshape = VoxelShapes.or(voxelshape, seCorner);
      }

      return voxelshape;
   }

   // Forge: Use the other constructor that takes a Supplier

   public CustomCampfire(BlockState state, Block.Properties properties) {
      super(properties);
      this.setDefaultState(this.stateContainer.getBaseState().with(LIT, Boolean.valueOf(false)).with(FACING, Direction.NORTH).with(HALF, Half.BOTTOM).with(SHAPE, StairsShape.STRAIGHT).with(WATERLOGGED, Boolean.valueOf(false)));
      this.modelBlock = state.getBlock();
      this.modelState = state;
      this.stateSupplier = () -> state;
   }


   
   
   public CustomCampfire(java.util.function.Supplier<BlockState> state, Block.Properties properties) {
      super(properties);
      this.setDefaultState(this.stateContainer.getBaseState().with(LIT, Boolean.valueOf(false)).with(FACING, Direction.NORTH).with(HALF, Half.BOTTOM).with(SHAPE, StairsShape.STRAIGHT).with(WATERLOGGED, Boolean.valueOf(false)));
      this.modelBlock = Blocks.AIR; // These are unused, fields are redirected
      this.modelState = Blocks.AIR.getDefaultState();
      this.stateSupplier = state;
   }

   public boolean func_220074_n(BlockState state) {
      return true;
   }
   
   /**
    * Update the provided state given the provided neighbor facing and neighbor state, returning a new state.
    * For example, fences make their connections to the passed in state if possible, and wet concrete powder immediately
    * returns its solidified counterpart.
    * Note that this method should ideally consider only the specific face passed in.
    */
   @SuppressWarnings("deprecation")
public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn, BlockPos currentPos, BlockPos facingPos) {
      if (stateIn.get(WATERLOGGED)) {
         worldIn.getPendingFluidTicks().scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickRate(worldIn));
         worldIn.getPendingBlockTicks().scheduleTick(currentPos, this, 1);
      }

      
      
      return facing.getAxis().isHorizontal() ? stateIn.with(SHAPE, getShapeProperty(stateIn, worldIn, currentPos)) : super.updatePostPlacement(stateIn, facing, facingState, worldIn, currentPos, facingPos);
   }
   

   
   public void fillWithRain(World worldIn, BlockPos pos) {
	      if (worldIn.rand.nextInt(5) == 1) {
	         float f = worldIn.getBiome(pos).func_225486_c(pos);
	         if (!(f < 0.15F)) {
	            BlockState blockstate = worldIn.getBlockState(pos);
	            if (blockstate.get(LIT) == false) {
	               worldIn.setBlockState(pos, blockstate.with(LIT, Boolean.valueOf(true)));
	            }

	         }
	      }
	   }
   
  @SuppressWarnings("deprecation")
public void tick(BlockState state, World worldIn, BlockPos pos, Random random) {
	     this.modelBlock.tick(state, worldIn, pos, random);}



  
   public void randomDisplayTick(BlockState state, World worldIn, BlockPos pos, Random rand) {
    	  
         if (!worldIn.isRainingAt(pos.up()) && rand.nextInt(5) == 1) { 
                 worldIn.setBlockState(pos, state.with(LIT, Boolean.valueOf(false)));
            }
      }
   



public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
      return (state.get(HALF) == Half.TOP ? SLAB_TOP_SHAPES : SLAB_BOTTOM_SHAPES)[field_196522_K[this.func_196511_x(state)]];
   }

   private int func_196511_x(BlockState state) {
      return state.get(SHAPE).ordinal() * 4 + state.get(FACING).getHorizontalIndex();
   }

   /**
    * Called periodically clientside on blocks near the player to show effects (like furnace fire particles). Note that
    * this method is unrelated to {@link randomTick} and {@link #needsRandomTick}, and will always be called regardless
    * of whether the block can receive random update ticks
    */
   @OnlyIn(Dist.CLIENT)
   public void animateTick(BlockState stateIn, World worldIn, BlockPos pos, Random rand) {
      this.modelBlock.animateTick(stateIn, worldIn, pos, rand);
   }

   public void onBlockClicked(BlockState state, World worldIn, BlockPos pos, PlayerEntity player) {
      this.modelState.onBlockClicked(worldIn, pos, player);
   }

   /**
    * Called after a player destroys this Block - the posiiton pos may no longer hold the state indicated.
    */
   public void onPlayerDestroy(IWorld worldIn, BlockPos pos, BlockState state) {
      this.modelBlock.onPlayerDestroy(worldIn, pos, state);
   }

   /**
    * Returns how much this block can resist explosions from the passed in entity.
    */
   public float getExplosionResistance() {
      return this.modelBlock.getExplosionResistance();
   }

   /**
    * Gets the render layer this block will render on. SOLID for solid blocks, CUTOUT or CUTOUT_MIPPED for on-off
    * transparency (glass, reeds), TRANSLUCENT for fully blended transparency (stained glass)
    */
   public BlockRenderLayer getRenderLayer() {
      return this.modelBlock.getRenderLayer();
   }

   /**
    * How many world ticks before ticking
    */
   public int tickRate(IWorldReader worldIn) {
      return this.modelBlock.tickRate(worldIn);
   }

   public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
      if (state.getBlock() != state.getBlock()) {
         this.modelState.neighborChanged(worldIn, pos, Blocks.AIR, pos, false);
         this.modelBlock.onBlockAdded(this.modelState, worldIn, pos, oldState, false);
      }
   }

   public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
      if (state.getBlock() != newState.getBlock()) {
         this.modelState.onReplaced(worldIn, pos, newState, isMoving);
      }
   }

   /**
    * Called when the given entity walks on this Block
    */
   public void onEntityWalk(World worldIn, BlockPos pos, Entity entityIn) {
      this.modelBlock.onEntityWalk(worldIn, pos, entityIn);
   }



   public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) {
      return this.modelState.onBlockActivated(worldIn, player, handIn, hit);
   }

   /**
    * Called when this Block is destroyed by an Explosion
    */
   public void onExplosionDestroy(World worldIn, BlockPos pos, Explosion explosionIn) {
      this.modelBlock.onExplosionDestroy(worldIn, pos, explosionIn);
   }

   public BlockState getStateForPlacement(BlockItemUseContext context) {
      Direction direction = context.getFace();
      BlockPos blockpos = context.getPos();
      IFluidState ifluidstate = context.getWorld().getFluidState(blockpos);
      BlockState blockstate = this.getDefaultState().with(FACING, context.getPlacementHorizontalFacing()).with(HALF, direction != Direction.DOWN && (direction == Direction.UP || !(context.getHitVec().y - (double)blockpos.getY() > 0.5D)) ? Half.BOTTOM : Half.TOP).with(WATERLOGGED, Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER));
      return blockstate.with(SHAPE, getShapeProperty(blockstate, context.getWorld(), blockpos));
   }



   /**
    * Returns a stair shape property based on the surrounding stairs from the given blockstate and position
    */
   private static StairsShape getShapeProperty(BlockState state, IBlockReader worldIn, BlockPos pos) {
      Direction direction = state.get(FACING);
      BlockState blockstate = worldIn.getBlockState(pos.offset(direction));
      if (isBlockStairs(blockstate) && state.get(HALF) == blockstate.get(HALF)) {
         Direction direction1 = blockstate.get(FACING);
         if (direction1.getAxis() != state.get(FACING).getAxis() && isDifferentStairs(state, worldIn, pos, direction1.getOpposite())) {
            if (direction1 == direction.rotateYCCW()) {
               return StairsShape.OUTER_LEFT;
            }

            return StairsShape.OUTER_RIGHT;
         }
      }

      BlockState blockstate1 = worldIn.getBlockState(pos.offset(direction.getOpposite()));
      if (isBlockStairs(blockstate1) && state.get(HALF) == blockstate1.get(HALF)) {
         Direction direction2 = blockstate1.get(FACING);
         if (direction2.getAxis() != state.get(FACING).getAxis() && isDifferentStairs(state, worldIn, pos, direction2)) {
            if (direction2 == direction.rotateYCCW()) {
               return StairsShape.INNER_LEFT;
            }

            return StairsShape.INNER_RIGHT;
         }
      }

      return StairsShape.STRAIGHT;
   }

   private static boolean isDifferentStairs(BlockState state, IBlockReader worldIn, BlockPos pos, Direction face) {
      BlockState blockstate = worldIn.getBlockState(pos.offset(face));
      return !isBlockStairs(blockstate) || blockstate.get(FACING) != state.get(FACING) || blockstate.get(HALF) != state.get(HALF);
   }

   public static boolean isBlockStairs(BlockState state) {
      return state.getBlock() instanceof CustomCampfire;
   }

   /**
    * Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the passed
    * blockstate.
    * @deprecated call via {@link IBlockState#withRotation(Rotation)} whenever possible. Implementing/overriding is
    * fine.
    */
   public BlockState rotate(BlockState state, Rotation rot) {
      return state.with(FACING, rot.rotate(state.get(FACING)));
   }

   /**
    * Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the passed
    * blockstate.
    * @deprecated call via {@link IBlockState#withMirror(Mirror)} whenever possible. Implementing/overriding is fine.
    */
   public BlockState mirror(BlockState state, Mirror mirrorIn) {
      Direction direction = state.get(FACING);
      StairsShape stairsshape = state.get(SHAPE);
      switch(mirrorIn) {
      case LEFT_RIGHT:
         if (direction.getAxis() == Direction.Axis.Z) {
            switch(stairsshape) {
            case INNER_LEFT:
               return state.rotate(Rotation.CLOCKWISE_180).with(SHAPE, StairsShape.INNER_RIGHT);
            case INNER_RIGHT:
               return state.rotate(Rotation.CLOCKWISE_180).with(SHAPE, StairsShape.INNER_LEFT);
            case OUTER_LEFT:
               return state.rotate(Rotation.CLOCKWISE_180).with(SHAPE, StairsShape.OUTER_RIGHT);
            case OUTER_RIGHT:
               return state.rotate(Rotation.CLOCKWISE_180).with(SHAPE, StairsShape.OUTER_LEFT);
            default:
               return state.rotate(Rotation.CLOCKWISE_180);
            }
         }
         break;
      case FRONT_BACK:
         if (direction.getAxis() == Direction.Axis.X) {
            switch(stairsshape) {
            case INNER_LEFT:
               return state.rotate(Rotation.CLOCKWISE_180).with(SHAPE, StairsShape.INNER_LEFT);
            case INNER_RIGHT:
               return state.rotate(Rotation.CLOCKWISE_180).with(SHAPE, StairsShape.INNER_RIGHT);
            case OUTER_LEFT:
               return state.rotate(Rotation.CLOCKWISE_180).with(SHAPE, StairsShape.OUTER_RIGHT);
            case OUTER_RIGHT:
               return state.rotate(Rotation.CLOCKWISE_180).with(SHAPE, StairsShape.OUTER_LEFT);
            case STRAIGHT:
               return state.rotate(Rotation.CLOCKWISE_180);
            }
         }
      }

      return super.mirror(state, mirrorIn);
   }

   protected void fillStateContainer(StateContainer.Builder<Block, BlockState> builder) {
      builder.add(LIT, FACING, HALF, SHAPE, WATERLOGGED);
   }

   public IFluidState getFluidState(BlockState state) {
      return state.get(WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : super.getFluidState(state);
   }

   public boolean allowsMovement(BlockState state, IBlockReader worldIn, BlockPos pos, PathType type) {
      return false;
   }

   private final java.util.function.Supplier<BlockState> stateSupplier;
   private Block getModelBlock() {
       return getModelState().getBlock();
   }
   private BlockState getModelState() {
       return stateSupplier.get();
   }
}

 

Link to comment
Share on other sites

3 minutes ago, diesieben07 said:

The code you posted does not contain the phrase "ChangeWhenClear".

Therefor this statement is incorrect:

 

Please show the place where you are actually calling this method.

I've just tried to rename it to 

   public void randomDisplayTick(BlockState state, World worldIn, BlockPos pos, Random rand) {
    	  
         if (!worldIn.isRainingAt(pos.up()) && rand.nextInt(5) == 1) { 
                 worldIn.setBlockState(pos, state.with(LIT, Boolean.valueOf(false)));
            }
      }
   

 

Link to comment
Share on other sites

2 minutes ago, diesieben07 said:

Great.

It's really helpful when you change the name of the method we are talking about from one post to the next, that really helps with following the conversation. Especially when you don't tell anyone that you have done this.

 

Again though, the code you posted contains exactly zero calls to the randomDisplayTick method (it only contains the method itself).

So again, this statement is false:

 

I'm sorry, how do I call the randomDisplayTick method?

Link to comment
Share on other sites

1 minute ago, diesieben07 said:

You must be calling it somewhere.

At least you were at some point, because otherwise it's code would never run...

Which it did though, because:

 

That means it ran at least once...

So, please use your IDE to find where you call this method.

That was meant for the fillWithRain method which works. Not for the one that should change the LIT to false.

Link to comment
Share on other sites

8 minutes ago, diesieben07 said:

Okay... well, there is no event for weather change. So you probably need a tile entity which checks every tick.

So this is not working ?   !worldIn.isRainingAt(pos.up())

Link to comment
Share on other sites

Just now, Kikoz said:

So this is not working ?   !worldIn.isRainingAt(pos.up())

Where are you calling that from?

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

Just now, Draco18s said:

Where are you calling that from?

 

26 minutes ago, Kikoz said:

I've just tried to rename it to 


   public void randomDisplayTick(BlockState state, World worldIn, BlockPos pos, Random rand) {
    	  
         if (!worldIn.isRainingAt(pos.up()) && rand.nextInt(5) == 1) { 
                 worldIn.setBlockState(pos, state.with(LIT, Boolean.valueOf(false)));
            }
      }
   

 

 

1 hour ago, Kikoz said:

package com.spcmf.pete11.objects.custommodels;

import java.util.Random;
import java.util.stream.IntStream;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.HorizontalBlock;
import net.minecraft.block.IWaterLoggable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluids;
import net.minecraft.fluid.IFluidState;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.pathfinding.PathType;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.DirectionProperty;
import net.minecraft.state.EnumProperty;
import net.minecraft.state.StateContainer;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.Half;
import net.minecraft.state.properties.StairsShape;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.world.Explosion;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;


public class CustomCampfire extends Block implements IWaterLoggable {
   public static final DirectionProperty FACING = HorizontalBlock.HORIZONTAL_FACING;
   public static final EnumProperty<Half> HALF = BlockStateProperties.HALF;
   public static final EnumProperty<StairsShape> SHAPE = BlockStateProperties.STAIRS_SHAPE;
   public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
   
   public static final BooleanProperty LIT = BlockStateProperties.LIT;
   
   protected static final VoxelShape AABB_SLAB_TOP = Block.makeCuboidShape(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D);
   protected static final VoxelShape AABB_SLAB_BOTTOM = Block.makeCuboidShape(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D);
   
   protected static final VoxelShape NWD_CORNER = Block.makeCuboidShape(0.0D, 10.0D, 0.0D, 8.0D, 15.0D, 8.0D);
   protected static final VoxelShape SWD_CORNER = Block.makeCuboidShape(0.0D, 10.0D, 8.0D, 8.0D, 15.0D, 16.0D);
   protected static final VoxelShape NED_CORNER = Block.makeCuboidShape(8.0D, 10.0D, 0.0D, 16.0D, 15.0D, 8.0D);
   protected static final VoxelShape SED_CORNER = Block.makeCuboidShape(8.0D, 10.0D, 8.0D, 16.0D, 15.0D, 16.0D);

   protected static final VoxelShape[] SLAB_TOP_SHAPES = makeShapes(AABB_SLAB_TOP, NWD_CORNER, NED_CORNER, SWD_CORNER, SED_CORNER);
   protected static final VoxelShape[] SLAB_BOTTOM_SHAPES = makeShapes(AABB_SLAB_BOTTOM, NWD_CORNER, NED_CORNER, SWD_CORNER, SED_CORNER);
   private static final int[] field_196522_K = new int[]{12, 5, 3, 10, 14, 13, 7, 11, 13, 7, 11, 14, 8, 4, 1, 2, 4, 1, 2, 8};

   private final Block modelBlock;
   private final BlockState modelState;

   private static VoxelShape[] makeShapes(VoxelShape slabShape, VoxelShape nwCorner, VoxelShape neCorner, VoxelShape swCorner, VoxelShape seCorner) {
      return IntStream.range(0, 16).mapToObj((p_199780_5_) -> {
         return combineShapes(p_199780_5_, slabShape, nwCorner, neCorner, swCorner, seCorner);
      }).toArray((p_199778_0_) -> {
         return new VoxelShape[p_199778_0_];
      });
   }

   /**
    * combines the shapes according to the mode set in the bitfield
    */
   private static VoxelShape combineShapes(int bitfield, VoxelShape slabShape, VoxelShape nwCorner, VoxelShape neCorner, VoxelShape swCorner, VoxelShape seCorner) {
      VoxelShape voxelshape = slabShape;
      if ((bitfield & 1) != 0) {
         voxelshape = VoxelShapes.or(slabShape, nwCorner);
      }

      if ((bitfield & 2) != 0) {
         voxelshape = VoxelShapes.or(voxelshape, neCorner);
      }

      if ((bitfield & 4) != 0) {
         voxelshape = VoxelShapes.or(voxelshape, swCorner);
      }

      if ((bitfield & 8) != 0) {
         voxelshape = VoxelShapes.or(voxelshape, seCorner);
      }

      return voxelshape;
   }

   // Forge: Use the other constructor that takes a Supplier

   public CustomCampfire(BlockState state, Block.Properties properties) {
      super(properties);
      this.setDefaultState(this.stateContainer.getBaseState().with(LIT, Boolean.valueOf(false)).with(FACING, Direction.NORTH).with(HALF, Half.BOTTOM).with(SHAPE, StairsShape.STRAIGHT).with(WATERLOGGED, Boolean.valueOf(false)));
      this.modelBlock = state.getBlock();
      this.modelState = state;
      this.stateSupplier = () -> state;
   }


   
   
   public CustomCampfire(java.util.function.Supplier<BlockState> state, Block.Properties properties) {
      super(properties);
      this.setDefaultState(this.stateContainer.getBaseState().with(LIT, Boolean.valueOf(false)).with(FACING, Direction.NORTH).with(HALF, Half.BOTTOM).with(SHAPE, StairsShape.STRAIGHT).with(WATERLOGGED, Boolean.valueOf(false)));
      this.modelBlock = Blocks.AIR; // These are unused, fields are redirected
      this.modelState = Blocks.AIR.getDefaultState();
      this.stateSupplier = state;
   }

   public boolean func_220074_n(BlockState state) {
      return true;
   }
   
   /**
    * Update the provided state given the provided neighbor facing and neighbor state, returning a new state.
    * For example, fences make their connections to the passed in state if possible, and wet concrete powder immediately
    * returns its solidified counterpart.
    * Note that this method should ideally consider only the specific face passed in.
    */
   @SuppressWarnings("deprecation")
public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn, BlockPos currentPos, BlockPos facingPos) {
      if (stateIn.get(WATERLOGGED)) {
         worldIn.getPendingFluidTicks().scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickRate(worldIn));
         worldIn.getPendingBlockTicks().scheduleTick(currentPos, this, 1);
      }

      
      
      return facing.getAxis().isHorizontal() ? stateIn.with(SHAPE, getShapeProperty(stateIn, worldIn, currentPos)) : super.updatePostPlacement(stateIn, facing, facingState, worldIn, currentPos, facingPos);
   }
   

   
   public void fillWithRain(World worldIn, BlockPos pos) {
	      if (worldIn.rand.nextInt(5) == 1) {
	         float f = worldIn.getBiome(pos).func_225486_c(pos);
	         if (!(f < 0.15F)) {
	            BlockState blockstate = worldIn.getBlockState(pos);
	            if (blockstate.get(LIT) == false) {
	               worldIn.setBlockState(pos, blockstate.with(LIT, Boolean.valueOf(true)));
	            }

	         }
	      }
	   }
   
  @SuppressWarnings("deprecation")
public void tick(BlockState state, World worldIn, BlockPos pos, Random random) {
	     this.modelBlock.tick(state, worldIn, pos, random);}



  
   public void randomDisplayTick(BlockState state, World worldIn, BlockPos pos, Random rand) {
    	  
         if (!worldIn.isRainingAt(pos.up()) && rand.nextInt(5) == 1) { 
                 worldIn.setBlockState(pos, state.with(LIT, Boolean.valueOf(false)));
            }
      }
   



public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
      return (state.get(HALF) == Half.TOP ? SLAB_TOP_SHAPES : SLAB_BOTTOM_SHAPES)[field_196522_K[this.func_196511_x(state)]];
   }

   private int func_196511_x(BlockState state) {
      return state.get(SHAPE).ordinal() * 4 + state.get(FACING).getHorizontalIndex();
   }

   /**
    * Called periodically clientside on blocks near the player to show effects (like furnace fire particles). Note that
    * this method is unrelated to {@link randomTick} and {@link #needsRandomTick}, and will always be called regardless
    * of whether the block can receive random update ticks
    */
   @OnlyIn(Dist.CLIENT)
   public void animateTick(BlockState stateIn, World worldIn, BlockPos pos, Random rand) {
      this.modelBlock.animateTick(stateIn, worldIn, pos, rand);
   }

   public void onBlockClicked(BlockState state, World worldIn, BlockPos pos, PlayerEntity player) {
      this.modelState.onBlockClicked(worldIn, pos, player);
   }

   /**
    * Called after a player destroys this Block - the posiiton pos may no longer hold the state indicated.
    */
   public void onPlayerDestroy(IWorld worldIn, BlockPos pos, BlockState state) {
      this.modelBlock.onPlayerDestroy(worldIn, pos, state);
   }

   /**
    * Returns how much this block can resist explosions from the passed in entity.
    */
   public float getExplosionResistance() {
      return this.modelBlock.getExplosionResistance();
   }

   /**
    * Gets the render layer this block will render on. SOLID for solid blocks, CUTOUT or CUTOUT_MIPPED for on-off
    * transparency (glass, reeds), TRANSLUCENT for fully blended transparency (stained glass)
    */
   public BlockRenderLayer getRenderLayer() {
      return this.modelBlock.getRenderLayer();
   }

   /**
    * How many world ticks before ticking
    */
   public int tickRate(IWorldReader worldIn) {
      return this.modelBlock.tickRate(worldIn);
   }

   public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
      if (state.getBlock() != state.getBlock()) {
         this.modelState.neighborChanged(worldIn, pos, Blocks.AIR, pos, false);
         this.modelBlock.onBlockAdded(this.modelState, worldIn, pos, oldState, false);
      }
   }

   public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
      if (state.getBlock() != newState.getBlock()) {
         this.modelState.onReplaced(worldIn, pos, newState, isMoving);
      }
   }

   /**
    * Called when the given entity walks on this Block
    */
   public void onEntityWalk(World worldIn, BlockPos pos, Entity entityIn) {
      this.modelBlock.onEntityWalk(worldIn, pos, entityIn);
   }



   public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) {
      return this.modelState.onBlockActivated(worldIn, player, handIn, hit);
   }

   /**
    * Called when this Block is destroyed by an Explosion
    */
   public void onExplosionDestroy(World worldIn, BlockPos pos, Explosion explosionIn) {
      this.modelBlock.onExplosionDestroy(worldIn, pos, explosionIn);
   }

   public BlockState getStateForPlacement(BlockItemUseContext context) {
      Direction direction = context.getFace();
      BlockPos blockpos = context.getPos();
      IFluidState ifluidstate = context.getWorld().getFluidState(blockpos);
      BlockState blockstate = this.getDefaultState().with(FACING, context.getPlacementHorizontalFacing()).with(HALF, direction != Direction.DOWN && (direction == Direction.UP || !(context.getHitVec().y - (double)blockpos.getY() > 0.5D)) ? Half.BOTTOM : Half.TOP).with(WATERLOGGED, Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER));
      return blockstate.with(SHAPE, getShapeProperty(blockstate, context.getWorld(), blockpos));
   }



   /**
    * Returns a stair shape property based on the surrounding stairs from the given blockstate and position
    */
   private static StairsShape getShapeProperty(BlockState state, IBlockReader worldIn, BlockPos pos) {
      Direction direction = state.get(FACING);
      BlockState blockstate = worldIn.getBlockState(pos.offset(direction));
      if (isBlockStairs(blockstate) && state.get(HALF) == blockstate.get(HALF)) {
         Direction direction1 = blockstate.get(FACING);
         if (direction1.getAxis() != state.get(FACING).getAxis() && isDifferentStairs(state, worldIn, pos, direction1.getOpposite())) {
            if (direction1 == direction.rotateYCCW()) {
               return StairsShape.OUTER_LEFT;
            }

            return StairsShape.OUTER_RIGHT;
         }
      }

      BlockState blockstate1 = worldIn.getBlockState(pos.offset(direction.getOpposite()));
      if (isBlockStairs(blockstate1) && state.get(HALF) == blockstate1.get(HALF)) {
         Direction direction2 = blockstate1.get(FACING);
         if (direction2.getAxis() != state.get(FACING).getAxis() && isDifferentStairs(state, worldIn, pos, direction2)) {
            if (direction2 == direction.rotateYCCW()) {
               return StairsShape.INNER_LEFT;
            }

            return StairsShape.INNER_RIGHT;
         }
      }

      return StairsShape.STRAIGHT;
   }

   private static boolean isDifferentStairs(BlockState state, IBlockReader worldIn, BlockPos pos, Direction face) {
      BlockState blockstate = worldIn.getBlockState(pos.offset(face));
      return !isBlockStairs(blockstate) || blockstate.get(FACING) != state.get(FACING) || blockstate.get(HALF) != state.get(HALF);
   }

   public static boolean isBlockStairs(BlockState state) {
      return state.getBlock() instanceof CustomCampfire;
   }

   /**
    * Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the passed
    * blockstate.
    * @deprecated call via {@link IBlockState#withRotation(Rotation)} whenever possible. Implementing/overriding is
    * fine.
    */
   public BlockState rotate(BlockState state, Rotation rot) {
      return state.with(FACING, rot.rotate(state.get(FACING)));
   }

   /**
    * Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the passed
    * blockstate.
    * @deprecated call via {@link IBlockState#withMirror(Mirror)} whenever possible. Implementing/overriding is fine.
    */
   public BlockState mirror(BlockState state, Mirror mirrorIn) {
      Direction direction = state.get(FACING);
      StairsShape stairsshape = state.get(SHAPE);
      switch(mirrorIn) {
      case LEFT_RIGHT:
         if (direction.getAxis() == Direction.Axis.Z) {
            switch(stairsshape) {
            case INNER_LEFT:
               return state.rotate(Rotation.CLOCKWISE_180).with(SHAPE, StairsShape.INNER_RIGHT);
            case INNER_RIGHT:
               return state.rotate(Rotation.CLOCKWISE_180).with(SHAPE, StairsShape.INNER_LEFT);
            case OUTER_LEFT:
               return state.rotate(Rotation.CLOCKWISE_180).with(SHAPE, StairsShape.OUTER_RIGHT);
            case OUTER_RIGHT:
               return state.rotate(Rotation.CLOCKWISE_180).with(SHAPE, StairsShape.OUTER_LEFT);
            default:
               return state.rotate(Rotation.CLOCKWISE_180);
            }
         }
         break;
      case FRONT_BACK:
         if (direction.getAxis() == Direction.Axis.X) {
            switch(stairsshape) {
            case INNER_LEFT:
               return state.rotate(Rotation.CLOCKWISE_180).with(SHAPE, StairsShape.INNER_LEFT);
            case INNER_RIGHT:
               return state.rotate(Rotation.CLOCKWISE_180).with(SHAPE, StairsShape.INNER_RIGHT);
            case OUTER_LEFT:
               return state.rotate(Rotation.CLOCKWISE_180).with(SHAPE, StairsShape.OUTER_RIGHT);
            case OUTER_RIGHT:
               return state.rotate(Rotation.CLOCKWISE_180).with(SHAPE, StairsShape.OUTER_LEFT);
            case STRAIGHT:
               return state.rotate(Rotation.CLOCKWISE_180);
            }
         }
      }

      return super.mirror(state, mirrorIn);
   }

   protected void fillStateContainer(StateContainer.Builder<Block, BlockState> builder) {
      builder.add(LIT, FACING, HALF, SHAPE, WATERLOGGED);
   }

   public IFluidState getFluidState(BlockState state) {
      return state.get(WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : super.getFluidState(state);
   }

   public boolean allowsMovement(BlockState state, IBlockReader worldIn, BlockPos pos, PathType type) {
      return false;
   }

   private final java.util.function.Supplier<BlockState> stateSupplier;
   private Block getModelBlock() {
       return getModelState().getBlock();
   }
   private BlockState getModelState() {
       return stateSupplier.get();
   }
}

 

 

Link to comment
Share on other sites

Ok, so:

  1. That method is only called on the client side and can't actually change the block state.
  2. That method is not called every tick. Its called randomly.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

Just now, Draco18s said:

Ok, so:

  1. That method is only called on the client side and can't actually change the block state.
  2. That method is not called every tick. Its called randomly.

1. FarmlandBlock uses it to change the block state, I just want it to randomly lit to false when it is not raining. Is there no other way to do it without a ticking entity?

 

Link to comment
Share on other sites

...noooo, it uses the tick method (updateTick from previous versions). I'm looking at it right now.

 

Which...is also called randomly or by schedule, depending on the block. Farmland is random.

 

Also also, randomDisplayTick doesn't exist any more either, its now called animateTick. Put @Override on your damn methods.

Edited by Draco18s

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

  @Override
   public void tick(BlockState state, World worldIn, BlockPos pos, Random rand) {
    	  
         if (!worldIn.isRainingAt((pos)) && rand.nextInt(1) == 1) { 
                 worldIn.setBlockState(pos, state.with(LIT, Boolean.valueOf(false)));
            }
      }
   

So this should work?

Link to comment
Share on other sites

Well.

Do you call .tickRandomly() on your BlockProperties?

If yes: then it will tick at random

If no: where are you scheduling your next tick?

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • OLXTOTO - Bandar Togel Online Dan Slot Terbesar Di Indonesia OLXTOTO telah lama dikenal sebagai salah satu bandar online terkemuka di Indonesia, terutama dalam pasar togel dan slot. Dengan reputasi yang solid dan pengalaman bertahun-tahun, OLXTOTO menawarkan platform yang aman dan andal bagi para penggemar perjudian daring. DAFTAR OLXTOTO DISINI DAFTAR OLXTOTO DISINI DAFTAR OLXTOTO DISINI Beragam Permainan Togel Sebagai bandar online terbesar di Indonesia, OLXTOTO menawarkan berbagai macam permainan togel. Mulai dari togel Singapura, togel Hongkong, hingga togel Sidney, pemain memiliki banyak pilihan untuk mencoba keberuntungan mereka. Dengan sistem yang transparan dan hasil yang adil, OLXTOTO memastikan bahwa setiap taruhan diproses dengan cepat dan tanpa keadaan. Slot Online Berkualitas Selain togel, OLXTOTO juga menawarkan berbagai permainan slot online yang menarik. Dari slot klasik hingga slot video modern, pemain dapat menemukan berbagai opsi permainan yang sesuai dengan preferensi mereka. Dengan grafis yang memukau dan fitur bonus yang menggiurkan, pengalaman bermain slot di OLXTOTO tidak akan pernah membosankan. Keamanan dan Kepuasan Pelanggan Terjamin Keamanan dan kepuasan pelanggan merupakan prioritas utama di OLXTOTO. Mereka menggunakan teknologi enkripsi terbaru untuk melindungi data pribadi dan keuangan para pemain. Tim dukungan pelanggan yang ramah dan responsif siap membantu pemain dengan setiap pertanyaan atau masalah yang mereka hadapi. Promosi dan Bonus Menarik OLXTOTO sering menawarkan promosi dan bonus menarik kepada para pemainnya. Mulai dari bonus selamat datang hingga bonus deposit, pemain memiliki kesempatan untuk meningkatkan kemenangan mereka dengan memanfaatkan berbagai penawaran yang tersedia. Penutup Dengan reputasi yang solid, beragam permainan berkualitas, dan komitmen terhadap keamanan dan kepuasan pelanggan, OLXTOTO tetap menjadi salah satu pilihan utama bagi para pecinta judi online di Indonesia. Jika Anda mencari pengalaman berjudi yang menyenangkan dan terpercaya, OLXTOTO layak dipertimbangkan.
    • I have been having a problem with minecraft forge. Any version. Everytime I try to launch it it always comes back with error code 1. I have tried launching from curseforge, from the minecraft launcher. I have also tried resetting my computer to see if that would help. It works on my other computer but that one is too old to run it properly. I have tried with and without mods aswell. Fabric works, optifine works, and MultiMC works aswell but i want to use forge. If you can help with this issue please DM on discord my # is Haole_Dawg#6676
    • Add the latest.log (logs-folder) with sites like https://paste.ee/ and paste the link to it here  
    • I have no idea how a UI mod crashed a whole world but HUGE props to you man, just saved me +2 months of progress!  
    • So i know for a fact this has been asked before but Render stuff troubles me a little and i didnt find any answer for recent version. I have a custom nausea effect. Currently i add both my nausea effect and the vanilla one for the effect. But the problem is that when I open the inventory, both are listed, while I'd only want mine to show up (both in the inv and on the GUI)   I've arrived to the GameRender (on joined/net/minecraft/client) and also found shaders on client-extra/assets/minecraft/shaders/post and client-extra/assets/minecraft/shaders/program but I'm lost. I understand that its like a regular screen, where I'd render stuff "over" the game depending on data on the server, but If someone could point to the right client and server classes that i can read to see how i can manage this or any tip would be apreciated
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.