Jump to content

[1.14.4] How can I make my leaves check for logs diagonally?


X Squishling X

Recommended Posts

I have a palm tree where some leaves stick out diagonally.  I'm wondering what the best way to make the leaves support this is? 

I have tried to override the updateDistance method like so:

private static BlockState updateDistance(BlockState p_208493_0_, IWorld p_208493_1_, BlockPos p_208493_2_) {
        int i = 7;

        try (BlockPos.PooledMutableBlockPos blockpos$pooledmutableblockpos = BlockPos.PooledMutableBlockPos.retain()) {
            loop:
            for (int k = -1; k < 2; k++) {
                for (int l = -1; l < 2; l++) {
                    for (int m = -1; m < 2; m++) {
                        if (k == 0 && l == 0 && m == 0) break loop;
                        BlockPos pos = new BlockPos(blockpos$pooledmutableblockpos.getX() + k, blockpos$pooledmutableblockpos.getY() + l, blockpos$pooledmutableblockpos.getZ() + m);

                        i = Math.min(i, getDistance(p_208493_1_.getBlockState(pos)) + 1);
                        if (i == 1) break loop;
                    }
                }
            }
        }

        return p_208493_0_.with(DISTANCE, Integer.valueOf(i));
    }

But this just makes my leaves decay even next to the log (it is a vanilla spruce log so the log shouldn't matter).

 

How could I make it support my palm tree? The 'fronds' are about 4-5 blocks long, for reference and some are diagonal.

Link to comment
Share on other sites

That code only checks for raw distance, it doesn't care if that is orthogonal or straight.

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

20 hours ago, X Squishling X said:

if (k == 0 && l == 0 && m == 0) break loop;

I don't like this line. I know what the attempt was doing, but it inadvertently skips several positions. Change the break loop to continue.

 

20 hours ago, X Squishling X said:

if (i == 1) break loop;

I don't like this either, because this keeps looping over new positions, but will always fall back to this line (because distance can't ever be less than 0, and that value gets a +1 before taking the minimum of it and i, so i can't ever be lower than 1).

 

Move the label loop: down below the loops. You know, making it do what the vanilla code does: actually exit the loop.

 

Unrelated to your issue, but:

20 hours ago, X Squishling X said:

BlockPos pos = new BlockPos(blockpos$pooledmutableblockpos.getX()...

You do know what a mutable BlockPos is, right?

It means you can modify it. Vanilla does this to avoid creating a bunch of short-lived BlockPos objects and there you are going "fuck it."

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

I know what a mutable block position is, but I've had issues with them in the past so I decided to do this.  The reason I am asking for help on this is because I want to know the correct way to do it.  I get what you are saying on the other things, but some of it was left over from vanilla where I just tried to edit it, such as the '+ 1' check.

 

Am I looking at the right method?  The vanilla code is hard to read sometimes with the lack of comments, and the weird names I assume come from decompiling the code.

This is also my first time working with 1.14, although I am sure the leaves aren't very different in 1.12.

 

Oh, and it doesn't work if I move the label below because I get an error that at the time of the break 'loop' wasn't defined.

Edited by X Squishling X
Corrected details
Link to comment
Share on other sites

17 hours ago, X Squishling X said:

I know what a mutable block position is, but I've had issues with them in the past so I decided to do this.

Then you should stick with BlockPos all the way instead of using BlockPos::PooledMutableBlockPos.

 

On 12/20/2019 at 2:10 AM, X Squishling X said:

return p_208493_0_.with(DISTANCE, Integer.valueOf(i));

You can utilize the compiler's auto-boxing.

 

On 12/20/2019 at 2:10 AM, X Squishling X said:

But this just makes my leaves decay even next to the log (it is a vanilla spruce log so the log shouldn't matter).

This is due to how you are breaking out of the loop everytime all axes are 0. Refer to Draco18s' post above.

 

On 12/20/2019 at 10:58 PM, Draco18s said:

Move the label loop: down below the loops. You know, making it do what the vanilla code does: actually exit the loop.

I might be missing something, but I think that OP's label is in the correct place. It is labeling the outmost loop of the 3 axes, which is to be broken if a log is found in the range of 1.

Edited by DavidM

Some tips:

Spoiler

Modder Support:

Spoiler

1. Do not follow tutorials on YouTube, especially TechnoVision (previously called Loremaster) and HarryTalks, due to their promotion of bad practice and usage of outdated code.

2. Always post your code.

3. Never copy and paste code. You won't learn anything from doing that.

4. 

Quote

Programming via Eclipse's hotfixes will get you nowhere

5. Learn to use your IDE, especially the debugger.

6.

Quote

The "picture that's worth 1000 words" only works if there's an obvious problem or a freehand red circle around it.

Support & Bug Reports:

Spoiler

1. Read the EAQ before asking for help. Remember to provide the appropriate log(s).

2. Versions below 1.11 are no longer supported due to their age. Update to a modern version of Minecraft to receive support.

 

 

Link to comment
Share on other sites

I belive I have fixed it, this is for everyone else that finds this thread:


This is the update distance method I have created.  I loop through every block in a 3x3 cube around the block, ignoring (0, 0, 0) because that is the block itself (continue will just skip to the next cycle of the loop).  I now add these offsets (-1 to 1) to the position to get the blocks around the leaves block.

 

I then set i to the min (it takes the lower) of the distance of this block plus one (because this leaves block is one block over).  i is 7 usually, so this means a max range for checking of 7, but you can change that although that also means you will have to change the 7 in multiple places in the code.  The get distance method handles what block this is and getting the distance property.

 

If the distance is 1 (or less) we exit.  This is because it means we are right next to a log, and otherwise we will keep on searching in case we find another, shorter distance.

 

Finally, we return a block state with the distance property set to the value of i, aka our distance.

    private static BlockState updateDistance(BlockState p_208493_0_, IWorld p_208493_1_, BlockPos p_208493_2_) {
        int i = 7;

        try (BlockPos.PooledMutableBlockPos pos = PooledMutableBlockPos.retain().setPos(p_208493_2_)) {
            loop:
            for (int k = -1; k < 2; k++) {
                for (int l = -1; l < 2; l++) {
                    for (int m = -1; m < 2; m++) {
                        if (k == 0 && l == 0 && m == 0) continue;
                        pos.setPos(p_208493_2_.getX() + k, p_208493_2_.getY() + l, p_208493_2_.getZ() + m);

                        i = Math.min(i, getDistance(p_208493_1_.getBlockState(pos)) + 1);
                        if (i <= 1) break loop;
                    }
                }
            }

        }

        return p_208493_0_.with(DISTANCE, Integer.valueOf(i));
    }

 

For our leaves to work properly, we will also need to update the distance method to ensure it works with our leaves class:

    private static int getDistance(BlockState neighbor) {
        if (BlockTags.LOGS.contains(neighbor.getBlock())) {
            return 0;
        } else {
            return (neighbor.getBlock() instanceof LeavesBlock || neighbor.getBlock() instanceof CustomLeaves) ? neighbor.get(DISTANCE) : 7;
        }
    }

 

All other methods in the leaves class are copied from LeavesBlock, so you will have to copy the contents of that.

 

Warning: Because we can't edit the normal leaves block class without a core mod, normal leaves won't be able to see that our leaves exist, and so therefore will only work if a normal leaves block is connected to the log.  This is usually not an issue, because almost always only one type of leaves is connected to a log.

Edited by X Squishling X
Corrected code
Link to comment
Share on other sites

Your code won't work as intended currently as you are offsetting the same pos by values relative to the original position:

4 minutes ago, X Squishling X said:

pos.setPos(pos.getX() + k, pos.getY() + l, pos.getZ() + m);

Instead of adding to the previous pos value, you should add to the position of the leaves block.

Some tips:

Spoiler

Modder Support:

Spoiler

1. Do not follow tutorials on YouTube, especially TechnoVision (previously called Loremaster) and HarryTalks, due to their promotion of bad practice and usage of outdated code.

2. Always post your code.

3. Never copy and paste code. You won't learn anything from doing that.

4. 

Quote

Programming via Eclipse's hotfixes will get you nowhere

5. Learn to use your IDE, especially the debugger.

6.

Quote

The "picture that's worth 1000 words" only works if there's an obvious problem or a freehand red circle around it.

Support & Bug Reports:

Spoiler

1. Read the EAQ before asking for help. Remember to provide the appropriate log(s).

2. Versions below 1.11 are no longer supported due to their age. Update to a modern version of Minecraft to receive support.

 

 

Link to comment
Share on other sites

6 hours ago, DavidM said:

I might be missing something, but I think that OP's label is in the correct place. It is labeling the outmost loop of the 3 axes, which is to be broken if a log is found in the range of 1.

Ah, you're correct. I was thinking of goto-labels.

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

After testing, this updated code still seems to only work horizontally.  Does anyone know what's wrong with it?  I also updated to this line:

if (Math.min(i, getDistance(world.getBlockState(pos)) + 1) < i) i = Math.min(i, getDistance(world.getBlockState(pos)) + 1);

Which should take the lowest distance, to see if this could fix something.

 

What else can I try?  Multiple people have told me they really want me to keep my current leaves design.

Link to comment
Share on other sites

Post your updated code.

Some tips:

Spoiler

Modder Support:

Spoiler

1. Do not follow tutorials on YouTube, especially TechnoVision (previously called Loremaster) and HarryTalks, due to their promotion of bad practice and usage of outdated code.

2. Always post your code.

3. Never copy and paste code. You won't learn anything from doing that.

4. 

Quote

Programming via Eclipse's hotfixes will get you nowhere

5. Learn to use your IDE, especially the debugger.

6.

Quote

The "picture that's worth 1000 words" only works if there's an obvious problem or a freehand red circle around it.

Support & Bug Reports:

Spoiler

1. Read the EAQ before asking for help. Remember to provide the appropriate log(s).

2. Versions below 1.11 are no longer supported due to their age. Update to a modern version of Minecraft to receive support.

 

 

Link to comment
Share on other sites

41 minutes ago, X Squishling X said:

if (Math.min(i, getDistance(world.getBlockState(pos)) + 1) < i) i = Math.min(i, getDistance(world.getBlockState(pos)) + 1);

Which should take the lowest distance, to see if this could fix something.

This is equivalent to

i = Math.min(i, getDistance(...));

; no if statement is needed.

 

I can’t figure out how to add quotes to my previous post via editing...

Some tips:

Spoiler

Modder Support:

Spoiler

1. Do not follow tutorials on YouTube, especially TechnoVision (previously called Loremaster) and HarryTalks, due to their promotion of bad practice and usage of outdated code.

2. Always post your code.

3. Never copy and paste code. You won't learn anything from doing that.

4. 

Quote

Programming via Eclipse's hotfixes will get you nowhere

5. Learn to use your IDE, especially the debugger.

6.

Quote

The "picture that's worth 1000 words" only works if there's an obvious problem or a freehand red circle around it.

Support & Bug Reports:

Spoiler

1. Read the EAQ before asking for help. Remember to provide the appropriate log(s).

2. Versions below 1.11 are no longer supported due to their age. Update to a modern version of Minecraft to receive support.

 

 

Link to comment
Share on other sites

    private static BlockState updateDistance(BlockState blockState, IWorld world, BlockPos blockPos) {
        int i = distance;

        try (BlockPos.PooledMutableBlockPos pos = PooledMutableBlockPos.retain().setPos(blockPos)) {
            loop:
            for (int k = -1; k < 2; k++) {
                for (int l = -1; l < 2; l++) {
                    for (int m = -1; m < 2; m++) {
                        if (k == 0 && l == 0 && m == 0) continue;
                        pos.setPos(blockPos.getX() + k, blockPos.getY() + l, blockPos.getZ() + m);

                        i = Math.min(i, getDistance(world.getBlockState(pos)) + 1);
                        if (i <= 1) break loop;
                    }
                }
            }

        }

        return blockState.with(DISTANCE, Integer.valueOf(i));
    }

distance is 7, I just did this so I can easily control it.

  • Like 1
Link to comment
Share on other sites

  • 5 months later...

Sorry if i'm resurrecting this topic, but i'm looking exactly for a solution very similar to that.

 

I tried to adapt to my logic, but i'm doing something wrong.
Basically, i need to verify if there's at least one of an array of blocks around my Custom Block.
 

package com.ouroboros.plantae.objects.blocks;

import java.util.Random;
import javax.annotation.Nullable;
import com.ouroboros.plantae.init.BlockInit;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.IFluidState;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.tags.FluidTags;
import net.minecraft.tags.Tag;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.server.ServerWorld;

public class VibraniumBlock extends Block {

	public VibraniumBlock(Block.Properties properties) {
		super(properties);
	}
	
	/**
	 * Change the block
	 */
	@Override
    public void func_225534_a_(BlockState blockState, ServerWorld serverWorld, BlockPos blockPos, Random random) {
    	boolean absorbingHeat = 
    			this.isNearBy(serverWorld, blockPos, FluidTags.LAVA) ||
		    	this.isNearBy(serverWorld, serverWorld, blockPos, Blocks.MAGMA_BLOCK);
    	
    	boolean losingHeat = 
    			this.isNearBy(serverWorld, blockPos, FluidTags.WATER) ||
    			this.isNearBy(serverWorld, serverWorld, blockPos, Blocks.ICE, Blocks.BLUE_ICE, Blocks.FROSTED_ICE ,Blocks.PACKED_ICE, Blocks.SNOW);
    	
		if(absorbingHeat && losingHeat) {
			serverWorld.setBlockState(blockPos, BlockInit.vibranium_block.getDefaultState(), 2);
		}
		else if(absorbingHeat) {
    		serverWorld.setBlockState(blockPos, BlockInit.vibranium_heated_block.getDefaultState(), 2);
		}
    	else if(losingHeat) {
			//serverWorld.setBlockState(blockPos, BlockInit.vibranium_frozen_block.getDefaultState(), 2);
    	}
	}
    	

	@Override @Nullable
	public BlockState getStateForPlacement(BlockItemUseContext context) {
		scheduleTick(context.getWorld(), context.getPos());
	   
		return this.getDefaultState();
	}
    
    /**
	 * 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.
	 */
    @Override
	public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn, BlockPos currentPos, BlockPos facingPos) {
    	scheduleTick(worldIn, currentPos);

    	return stateIn;
	}
   
	private void scheduleTick(IWorld worldIn, BlockPos currentPos) {
		if(this.isNearBy(worldIn, currentPos, FluidTags.LAVA))
			worldIn.getPendingBlockTicks().scheduleTick(currentPos, this, 60 + worldIn.getRandom().nextInt(40));
	}
	
	/**
	 * Verify if the current block is near by facing some fluid
	 */
    protected boolean isNearBy(IBlockReader blockReader, BlockPos blockPos, Tag<Fluid> fluid) {
    	IFluidState iFluidState;
    	
    	for(Direction direction : Direction.values()) {
          iFluidState = blockReader.getFluidState(blockPos.offset(direction));
          
          if(iFluidState.isTagged(fluid))
        	  return true;
       }
       return false;
    }
    
    /**
     * Verify if the current block is near by facing some block
     */
    protected boolean isNearBy(ServerWorld serverWorld, IBlockReader blockReader, BlockPos blockPos, Block ...arBlocks) {
    	BlockState blockState;
    	
    	for(Direction direction : Direction.values()) {
    		blockState = blockReader.getBlockState(blockPos.offset(direction));
    		
    		for(Block block: arBlocks) {
	    		//TODO: Verify if, at least, one of the blocks are placed around this block
    		}
    	}
    	return false;
    }
}

 

Edited by Kriptarus
Link to comment
Share on other sites

Which part are you having problems with?

Do you need help comparing blocks? (your TODO)

Do you need help checking diagonals? (the thread title)

Something else?

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

On 6/7/2020 at 8:09 PM, Draco18s said:

Which part are you having problems with?

Do you need help comparing blocks? (your TODO)

Do you need help checking diagonals? (the thread title)

Something else?

Both of then.

I need to undertand how to check all blocks around (including diagonals), and compare if they are equal to one of the blocks in the array. (my TODO)

 

Probably i'll need to check diagonals for fluids as well... (the overloaded method)

 

Edited by Kriptarus
Link to comment
Share on other sites

Comparing blocks is as easy as world.getBlockState().getBlock() == aBlock. You have an array, use a loop or other array lookup convenience method.

Checking diagonals means you want to check a volume not a direction so you should use BlockPos.getAllInBox().

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

/**
 * Verify if the current block is near by some block
 */
protected boolean isNearBy(IBlockReader blockReader, BlockPos blockPos, List<Block> arBlocks) {
  Stream<BlockPos> blocksAround = BlockPos.getAllInBox(
  	new BlockPos(blockPos.getX() -1, blockPos.getY() -1, blockPos.getZ() -1), 
  	new BlockPos(blockPos.getX() +1, blockPos.getY() +1, blockPos.getZ() +1));

  long count = blocksAround.filter(ba -> arBlocks.contains(blockReader.getBlockState(ba).getBlock())).count();

  return count > 0;
}

 

I looked around about getAllInBox(), seems that the two parameters are the beginning and end of the volume.

About comparing blocks, it was so simple that a didn't think on that.  ._.

 

Thanks!

Edited by Kriptarus
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



×
×
  • Create New...

Important Information

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