Jump to content

Is the block under the cross hairs a door?


fuzzybat23

Recommended Posts

I found some old code for detecting if the block you're looking at is a door:

public boolean isDoor(PlayerInteractEvent event)
{
	BlockDoor door = (BlockDoor)Blocks.wooden_door;
	BlockLocation loc = BlockLocation.get(event.world, event.x, event.y, event.z);

	if((event.action == Action.RIGHT_CLICK_BLOCK) && (loc.getBlock() == door))
		return true;
}

 

Of course this is out dated as BlockLocation is no longer used.  That and Blocks.wooden_door doesn't exist anymore either.  For an updated version of this, does this look about right?

 

public void onDoorInteract(PlayerInteractEvent event)
{
  Minecraft mc = Minecraft.getMinecraft();
  BlockPos blockpos = mc.objectMouseOver.getBlockPos();
  Block block = event.getEntityPlayer().getEntityWorld().getBlockState(blockpos).getBlock();
  
  //call return if block isn't a door
  if((event.action != Action.RIGHT_CLICK_BLOCK) || !(WoodenDoor(block)))
    return;
  
  //Do stuff if it is a door
   
}
                           
public boolean WoodenDoor(Block block)
{
    BlockDoor[] doors = {(BlockDoor) Blocks.ACACIA_DOOR, (BlockDoor) Blocks.BIRCH_DOOR, (BlockDoor) Blocks.DARK_OAK_DOOR,
            (BlockDoor) Blocks.JUNGLE_DOOR, (BlockDoor) Blocks.OAK_DOOR, (BlockDoor) Blocks.SPRUCE_DOOR};

    for(BlockDoor door : doors)
    { if(block == door) return true; }
  
    return false;
}

 

Also, event.action != Action.RIGHT_CLICK_BLOCK doesn't seem to exist since 1.8, either.  Does anyone know how to do this in the current 1.12 environment?

Link to comment
Share on other sites

12 hours ago, fuzzybat23 said:

Also, event.action != Action.RIGHT_CLICK_BLOCK doesn't seem to exist since 1.8, either.  Does anyone know how to do this in the current 1.12 environment?

Why don't you catch the RightClickBlock event directly instead and check if the clicked block is a door?

Don't blame me if i always ask for your help. I just want to learn to be better :)

Link to comment
Share on other sites

Ok.. I managed to find something about PlayerInteractEvent.RightClickBlock after lots of google digging xD  I did managed to get it to register when I right click, but it doesn't seem to want to correctly check if it's a door or not, now.

 

Edited by fuzzybat23
Link to comment
Share on other sites

    @SubscribeEvent
    public void onDoorInteract(PlayerInteractEvent.RightClickBlock event)
    {
        EntityPlayer player = event.getEntityPlayer();
        BlockPos blockpos = event.getPos().offset(event.getFace());
        Block block = player.getEntityWorld().getBlockState(blockpos).getBlock();

        logger.info("Begin check if it's a door...");
        if( isWoodenDoor(block))
            logger.info("It's a door!");

    }

    public static boolean isWoodenDoor(Block block)
    {
        if(block == Blocks.ACACIA_DOOR || block == Blocks.DARK_OAK_DOOR || block == Blocks.BIRCH_DOOR ||
                    block == Blocks.JUNGLE_DOOR || block == Blocks.OAK_DOOR || block == Blocks.SPRUCE_DOOR)
                return true;
        return false;
    }

 

Link to comment
Share on other sites

 BlockPos blockpos = event.getPos().offset(event.getFace());

What? I don't understand what are you trying to do there. To get the position of where the player right clicked you have the hitVec variable in the event. So to get the block you should do this

	Block block = event.getWorld().getBlockState(new BlockPos(event.getHitVec().x, event.getHitVec().y, event.getHitVec().z)).getBlock();

Don't blame me if i always ask for your help. I just want to learn to be better :)

Link to comment
Share on other sites

5 minutes ago, JimiIT92 said:

 BlockPos blockpos = event.getPos().offset(event.getFace());

What? I don't understand what are you trying to do there. To get the position of where the player right clicked you have the hitVec variable in the event. So to get the block you should do this


	Block block = event.getWorld().getBlockState(new BlockPos(event.getHitVec().x, event.getHitVec().y, event.getHitVec().z)).getBlock();

getHitVec is the position on the block that the player clicked (in the range 0-1), not the position of the block in the world. 

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

I think I figured this one out.  I ended up using this code and tested it and it worked just fine, letting me know if what I clicked on was a door and if it wasn't.  I've even gotten it to distinguish between the different kinds of doors.

    @SubscribeEvent
    public void onBlockInteract(PlayerInteractEvent.RightClickBlock event)
    {
        Minecraft mc = Minecraft.getMinecraft();
        EntityPlayer player = event.getEntityPlayer();
        BlockPos pos = mc.objectMouseOver.getBlockPos();
        Block block = player.getEntityWorld().getBlockState(pos).getBlock();
        IBlockState state = player.getEntityWorld().getBlockState(pos);

        logger.info("Begin check if it's a door...");
        if( isWoodenDoor(block))
            logger.info("It's a door!" + WoodenDoor.whichDoor(block));

    }

    public static boolean isWoodenDoor(Block block)
    {
        if(block == Blocks.ACACIA_DOOR || block == Blocks.BIRCH_DOOR || block == Blocks.DARK_OAK_DOOR ||
                    block == Blocks.JUNGLE_DOOR || block == Blocks.OAK_DOOR || block == Blocks.SPRUCE_DOOR)
                return true;
        return false;
    }

    public static BlockDoor whichDoor(Block block)
    {
        if(block == Blocks.ACACIA_DOOR)
            return Blocks.ACACIA_DOOR;
        if(block == Blocks.BIRCH_DOOR)
            return Blocks.BIRCH_DOOR;
        if(block == Blocks.DARK_OAK_DOOR)
            return Blocks.DARK_OAK_DOOR;
        if(block == Blocks.JUNGLE_DOOR)
            return Blocks.JUNGLE_DOOR;
        if(block == Blocks.OAK_DOOR)
            return Blocks.OAK_DOOR;
        if(block == Blocks.SPRUCE_DOOR)
            return Blocks.SPRUCE_DOOR;

        return null;
    }

 

Link to comment
Share on other sites

1 hour ago, Choonster said:

getHitVec is the position on the block that the player clicked (in the range 0-1), not the position of the block in the world. 

Actually i use that in my mod to detect when a player uses a flint and steel on an unlit torch and it returns almost the coordinates of the torch. I've done a test right now, the torch was at {x=-7, y=84, z=19}, the getHitVec returned me this {x=-6.399999976158142, y=84.39314504887278, z=19.46219003009727}. Is this a recent change or i just something that shouldn't happen?
By the way you can just do this

event.getWorld().getBlockState(event.getPos()).getBlock()


And it will tell you what block the player has right clicked 

Edited by JimiIT92

Don't blame me if i always ask for your help. I just want to learn to be better :)

Link to comment
Share on other sites

I know almost noth9ing about gethitvec, but based on those different xyz values, the torch will of course be on whole numbers.  7, 84 and 19.  The gethitvec is probably returning the exact area within the bounding box that you clicked on, which can't possibly be whole numbers?

Link to comment
Share on other sites

I must have confused getHitVec with the hitX/Y/Z arguments of Block#onBlockActivated, which I'm pretty sure are between 0 and 1.

 

I don't have my IDE in front of me, so I might be mistaken (again).

 

Edit: The hitX/Y/Z arguments of Block#onBlockActivated are between 0 and 1.

Edited by Choonster

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

See, when people say use an instance of BlockDoor, that just confuses the hell out of me -.-  I live in a world of examples.  Unless an example is given, then something like what you said is completely lost to me xD  Anyway, for what i'm working on, the first step was being able to identify the block being interacted with, in this case by right click, as a door.  Not just as a door, but as a wooden door.  Since iron doors fall into the category of BlockDoor, I just can't run a generic test to say "Is it a door?  Yup."  No, it has to be "Is it an Acacia door, a jungle door, a dark oak door, a birch door, an oak door or a spruce door?  Yes."  A few versions ago, pre 1.9 I think, all you had to check was wooden_door, but now wooden_door only pertains to oak doors, where they should have given oak doors their own name in code and kept wooden_doors as a check for all wood type doors.

Link to comment
Share on other sites

Second phase of what I'm doing is determining if an adjacent block contains a door.  In other words, two doors side by side.  Then figure out if those doors are mirror to each other, and when one of the two is right clicked, it will send a door toggle to the other opening it automatically.  Say you're standing in the world facing north and you place a door in front of you.  It's hinges are facing east.  You place a door next to it one block to the west.  It's hinges are facing west.  You have a set of proper double doors now.

Link to comment
Share on other sites

Mmmm, so instead of this:

    public static boolean isWoodenDoor(Block block)
    {
        if(block == Blocks.ACACIA_DOOR || block == Blocks.BIRCH_DOOR || block == Blocks.DARK_OAK_DOOR ||
                    block == Blocks.JUNGLE_DOOR || block == Blocks.OAK_DOOR || block == Blocks.SPRUCE_DOOR)
                return true;
        return false;
    }

 

Use something like this?

    public static boolean isWoodenDoor(IBlockState state)
    {
        if(state.getBlock() instanceof BlockDoor && state.getMaterial() == Material.WOOD)
                return true;
        return false;
    }

 

Link to comment
Share on other sites

Also, does this look about right as far as looping through the enumfacing?  Passing in the right click event to generate the new target block, using offset(facing) to offset targetblock from block.

    public void checkForDoors(PlayerInteractEvent.RightClickBlock event, Block block)
    {
        for(EnumFacing facing : EnumFacing.HORIZONTALS)
        {
            Block targetblock = event.getWorld().getBlockState(event.getPos().offset(facing)).getBlock();
            if(targetblock == block)
                //Do stuff if block that is offset to original block is same as original block
        }
    }

 

Link to comment
Share on other sites

You said that the hinge is on the top half of the door, and the hinge side is used to determine if the doors face each other, right?  I found this in an older mod, but I'm not sure what the updated code would look like.  I know that this is definitely outdated, though, but from what I can tell it did exactly that.  Determined if it was the upper or lower part of the door being interacted with and set a door variable to the top portion.

    Block blockBottom = block.getRelative(BlockFace.DOWN);
    Block blockTop = block.getRelative(BlockFace.UP);
    Block blockNearBottom = blockBottom.getRelative(BlockFace.NORTH);
    Block blockNearTop = blockTop.getRelative(BlockFace.NORTH);
    Door door = (Door)block.getState().getData();
    Door doorTop = (Door)block.getState().getData();
    Door doorBottom = (Door)block.getState().getData();
    Door doorNearBottom = (Door)block.getState().getData();
    Door doorNearTop = (Door)block.getState().getData();
    if (door.isTopHalf()) {
      blockTop = block;
      doorTop = door;
      doorBottom = (Door)blockBottom.getState().getData();
    } else {
      blockBottom = block;
      doorBottom = door;
      doorTop = (Door)blockTop.getState().getData();
    }

I don't think getRelative exists anymore, and Door isn't a type anymore, it's now BlockDoor.

Link to comment
Share on other sites

That code looks like it's from a Bukkit plugin (or a plugin for a similar system) rather than an old Forge mod.

 

You need to use IBlockState#getValue to get the values of the various properties stored in the BlockDoor class from the state. This will tell you the door's facing and hinge position 

 

diesieben07 explained which properties you need and which block to get their values from earlier in the thread.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

I was rooting around through BlockDoor.java looking for something unrelated and I saw a few snippets that sparked inspiration.  Ran and tested this and it seems to work just fine :D

public static boolean isDoubleDoor(World world, BlockPos pos, EnumFacing offsetPos)
    {
        String RIGHT = "RIGHT";
        String LEFT = "LEFT";
        boolean flag = false;
        IBlockState targetState = world.getBlockState(pos);
        Block targetBlock = targetState.getBlock();

        IBlockState offsetState = world.getBlockState(pos.offset(offsetPos));
        Block offsetBlock = offsetState.getBlock();

        //Get correct blockState, including hinge, for targeted door.

        if(targetState.getValue(BlockDoor.HALF) == BlockDoor.EnumDoorHalf.LOWER)
            if(targetState.getBlock() == targetBlock)
                targetState = world.getBlockState(pos.up());
        BlockDoor.EnumHingePosition targetHinge = targetState.getValue(BlockDoor.HINGE);

        //get correct blockState, including hinge, for offset door.
        
        if(offsetState.getValue(BlockDoor.HALF) == BlockDoor.EnumDoorHalf.LOWER)
            if(offsetState.getBlock() == offsetBlock)
                offsetState = world.getBlockState(pos.offset(offsetPos).up());
        BlockDoor.EnumHingePosition offsetHinge = offsetState.getValue(BlockDoor.HINGE);

        logger.info("(targetHinge)(name)" + targetHinge.name() + "=? (offsetHinge)(name)" + offsetHinge.name() );

        if(((targetHinge.name() == RIGHT) && (offsetHinge.name() == LEFT)) || ((targetHinge.name() == LEFT) && (offsetHinge.name() == RIGHT)))
            flag = true;

        return flag;
    }

 

First checks if it's the lower half of the door and if so, resets the blockState to the upper half.  Then it grabs the side of the door the hinge is on and checks if hinges on the two doors are on the opposite outer sides.

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.

×
×
  • Create New...

Important Information

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