Solved How to get the block a player is sneaking on

Discussion in 'Plugin Development' started by JRL1004, Jun 25, 2015.

Thread Status:
Not open for further replies.
  1. Offline

    JRL1004

    So, I had a mini-game plugin in the past called Timber that would slowly "degrade" the type of wood block a player was standing on over time until the block eventually broke. A way of cheating this system was to sneak on a block and hold your player over a block of air via the power of minecraft logic. Now I am making a similar mini-game plugin but I cannot for the life of me think of how to get the block that the player is currently using to hold his/herself up. Can anyone help me out by providing a method to get the cube that the player is crouching off of or offer some links I can look at for insight into how to create my own method for identifying which cube they are using?

    Show Spoiler

    [​IMG]
    In this image, I am technically suspended in the air because I am on the very edge of the stone block to my left. Bukkit, however, will say that the block below me is air because I am far enough to the side that, as for as my location is concerned, there is nothing below me.
     
  2. Short version
    What you do is you get the bounding box of the player, and you grow it on the y axis, and then you check if that bounding box collides with the bounding box of the blocks that the player could be crouching on. I think this will be a good way to see what blocks you're crouching on.

    Long version
    In the nms Entity class you have the getBoundingBox() method. This will return a AxisAlignedBB. Then you can do the grow method in the Ax class and grow it on the y axis (this way when you check for the collision the blocks below will be counted, you only need to grow about 0.1 I think. Using the grow method will create a new instance, and won't change the current instance). then you get the blocks below the player that he could crouch on, and then you do
    Code:
    net.minecraft.server.VERSION.Block.getById(id)
    , to get a block version from the id of the block. then you have in that class the method a(World w, BlockPosition bp, IBlockData ibd), you use that to get the bounding box of the block. World w can be null because it's not used, BlockPosition bp is just initialized like the vector class of bukkit and you add the x y z of the block, and IBlockData ibd can just be null, because nothing is done with that. When having the boundingbox of that block, you can use b (AxisAlignedBB) to see if the bounding box of the block and the player (that you have grown) is colliding, and if it is, that's the block you're crouching on. If not, you just check if for all the other blocks that he could crouch on.
    I hope this wasn't too much confusing, and you can just ask question about what I said.

    I apologize in advance for my English because it's not my native language.
    If I made any mistakes, please tell me in a nice way, with explanation so that I can learn from my mistakes.
     
  3. Offline

    Xerox262

    Psst, there's an event for people toggling their sneak

    Code:java
    1. @EventHandler
    2. private void sneak(PlayerToggleSneakEvent e) {
    3. if(isInGame(e.getPlayer()))
    4. if(e.isSneaking())
    5. e.setCancelled(true);
    6. }
     
  4. Offline

    JRL1004

    @Bram0101 I'm working on a class to go through all the NMS stuff needed to attempt this method of checking for the block but I have run into a comprehension issue with your explanation. When you say to get the blocks that the player could crouch on, what do you mean by that? Just return all the blocks in the 3 * 3 * 1 plane parallel to the plane that the player is crouching on?
    Show Spoiler
    If the player is represented by '0', the all the cubes marked as '#' would be valid?
    ###
    #0#
    ###

    EDIT: Also ran into this issue with the method you described:
    Show Spoiler
    [​IMG]



    @Xerox262 I would just cancel that event if not for three issues:
    1) Cancelling the event can cause a bit of jitteriness and other nonsense for the client (especially if you have an anticheat plugin installed) as the server say the player is not crouching but the client may still believe it is (and/or visa-versa).
    2) I would like for players to be able to sneak if they so choose
    3) As explained in #1, the client may not understand that it is not sneaking. This means that, since block movement is handled client-side, a player could still theoretically move to where they are hovering over air again and thus bring the issue I am trying to address back to its full glory.
     
    Last edited: Jun 26, 2015
  5. Yes, just the blocks around and below the player.

    What you can do to remove this, is to cast the first null to 'net.minecraft.server.VERSION.World' and the second null to 'net.minecraft.server.VERSION.IBlockData'. This hopefully remove the ambiguous from it. The problem is that there are multiple a methods all needing different arguments, and passing in null can be almost all of the arguments, so java doesn't know which one to take, so casting it to the right class should help it.
     
  6. Offline

    JRL1004

    @Bram0101 I've gone and made a method to try and do this based on the information you provided. The method looks like this:
    Show Spoiler
    [​IMG]

    I'm not entirely sure as to if it will work yet but, if not then it may just need some minor tinkering. Thank you for you assistance. If it works, I'll change this thread to solved.

    So, a bit of side information for anyone who wants to do something similar: Make sure you use EntityPlayer for the player's nms class before getting the bounding box. I tried to make it more versatile and use CraftEntity so that all entities would be valid and it caused NullPointerExceptions.

    Edit: Proof it works
    http://imgur.com/a/D83Nx

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 12, 2016
Thread Status:
Not open for further replies.

Share This Page