[TUTORIAL] Detecting Collision With Block W/O PlayerMoveEvent

Discussion in 'Resources' started by Icyene, Aug 14, 2012.


[ANSWER AFTER READING] If I Were To Ask You To Do This Now, Could You?

Poll closed Aug 21, 2012.
  1. Yes

  2. Yes, but with a little help

    0 vote(s)
  3. Probably not

  4. Definetly not

    0 vote(s)
Thread Status:
Not open for further replies.
  1. Offline


    The base Block class defines a method "public void a(World world, int i, int j, int k, Entity entity, float f)" - it's responsible for passing movement events to blocks. BlockSlowSand, for example, overrides this method to multiply the given Entity's motion by 0.4 (applying the slowing effect).

    With this in mind, you can modify the behavior of any existing block.

    1. public class MyBlockSnow extends BlockSnow {
    2. {
    3. // We need to perform the same setup as in Block.java, line 186
    4. // (new BlockSnow()).c(0.1F).a(n).c("snow").g(0).d("snow")
    5. c(.2f);
    6. a(n);
    7. c("snow");
    8. g(0);
    9. d("snow");
    10. }
    12. @Override
    13. public void a(World world, int i, int j, int k, Entity entity, float f) {
    14. // Whenever an entity collides with this block, this function will be called.
    15. // Let's slow down the entity
    16. entity.motX *= 0.6;
    17. entity.motZ *= 0.6;
    18. }
    19. }

    Finally, you have to replace Minecraft's snow block definition with yours. This is quite easy in recent versions of Minecraft: there is an internal block registry which we can modify.

    1. Block.REGISTRY.a(80, "snow", new MyBlockSnow());

    Of course, different blocks have different ids (first parameter). You can reference the Block source for details.

    Finally, a note to those new to NMS hacks - you will need to reference craftbukkit.jar (instead of the normal bukkit.jar) and use the net.minecraft.server imports instead of the org.bukkit ones.
  2. Offline

    Shiny Quagsire

    I just thought I'd let anyone who wants to use this to know that 1.5.1 *did* refactor the methods, but I managed to find them:
    Method v = Block.class.getDeclaredMethod("D");
          Method p = Block.class.getDeclaredMethod("r");
          Method c = Block.class.getDeclaredMethod("c", float.class);
          Method a = Block.class.getDeclaredMethod("a", StepSound.class);
          Method k = Block.class.getDeclaredMethod("k", int.class);
    Also, some blocks only call the a method for certain entities, so my advice is to expand a different block or just the main Block class.
  3. Offline


    Anyone know if this still works?
  4. Offline


    Just spent a while testing it.. it works. But the methods changed.
  5. Offline


    I played with it for a bit, but couldn't work it out. Trying to get it to work with stationary water, any hints?
  6. Offline


    This is a nice little resource. Great work! :)
    hawkfalcon likes this.
  7. Offline


    Can anyone let me know what the new methods are? I have no idea where or how to find them.
  8. Offline


    Each and every commit since 1.5.1 where the mine craft version changed (refactor of methods), you'll need to trace those down. OR, you can look up in net.minecraft.server.v1_7_R1 for BlockSoulSand and basically find where the logic looks roughly the same as it does here.
  9. Offline


    I'm trying to play around with this. One problem is that Minecraft tried to get rid of all the block id stuff :/ So a lot of stuff has changed
  10. Offline


    True, though the method may have changed, it's still easy to get by ID in NMS (had to do so for my own projects).
  11. So in case anybody was wondering, yes, this still works with 1.7.2, although the method signature has changed (To complicate stuff a little, a method with the same signature as in the OP does still exist)
    1. public void a(World world, int i, int j, int k, Entity entity, float f)

    I have also made a very small plugin using this method, check it out here. (I am allowed to post examples, right?)
    Edit: Yes, they also changed the registry. See the plugin for how to use it.
    Edit: Also note that you do not need to use reflection when hooking into NMS Block any more :)
    toropov023, bobacadodl and Garris0n like this.
  12. Offline


    Thanks for posting a working example; was feeling guilty about not editing the post with up-to-date information :).
  13. Offline


  14. I believe it is this method: https://github.com/Bukkit/mc-dev/blob/master/net/minecraft/server/Block.java#L755 - The obfuscation mapping for that one does not seem to have changed.

    For reference/proof, here is the implementation in BlockSlowSand (aka. Soul Sand): https://github.com/Bukkit/mc-dev/blob/master/net/minecraft/server/BlockSlowSand.java#L16

    Also, your Pastebin has been removed, so I have been unable to take a look at your code. (Did you inject your block into the block registry?)
  15. Offline


    What are the new method names for 1.7.2?
  16. sipsi133 As stated my above post, a working 1.7.2 example can be found here.
  17. Offline



    I've updated the tutorial with an approach for 1.7+ servers.
    Garris0n likes this.
  18. Icyene Is it possible to cancel player move over the block (like if hes go over block, return him to the spot he were before)? and is there anyway to detect sideways collisions? so if Im running and sticking to wall...?
  19. Offline


    Icyene For some reason, this has no effect:
    entity.motX = entity.motX * 2.0;
    entity.motZ = entity.motZ * 2.0;
    and System.out.println(entity.motX or entity.motZ); returns always 0.0
  20. Offline


    Hm, I ran into the same trubbles...

    Looks like that a players movement is calculated clientside. Thats why motX/Y/X is always null (setVelocity(), jumping, explosions and some other things will be calculated serverside). So you can't handle this like that.

    You could do something like this:
    1. entity.motX += 0.2F; //Set this to whatever you wish
    2. entity.motZ += 0.2F;
    4. entity.velocityChanged = true;

    The purpose of the velocityChanged field is very easy to understand. It'll force the server to send a velocity packet to the client. Which causes the player to experiance horrible movement fails (He will be slow as hell!).

    But there are some other options! You could apply a PotionEffect of Slowing to the Player or you take a look at this post http://forums.bukkit.org/threads/class-change-the-walking-speed-of-a-livingentity.240948/.
  21. Is there a method called that detects when an entity walks INTO the block and not ONTO the block. E.g. If a player hits a wall.
  22. Offline


    It's the same method I believe.

    Judging from this, anyway.
  23. That's weird... It won't call when I walk into a stone block (I did this with stone) but will if I walk on top. I'll try testing again.

    I did some testing again, won't work. Also, cactus doesn't hurt you if you walk into it from the side (tested).

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
    Last edited by a moderator: May 27, 2016
  24. Offline


    Huh? When did that happen...
  25. No idea. I'll try walking into the side of a cactus again when I can.

    Edit: The plugin I tested this in makes players invincible when the game hasn't started, so maybe that's the reason. I'll check it.

    Okay so I did some testing and it does damage you if you walk into it from the sides although I believe this is only because it's not a full block size... meaning it detects it as walking over. I'm not sure, because this does not work for other blocks such as stone.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
    Last edited by a moderator: May 27, 2016
  26. Offline


    Hm...I can't think of a full block that does something special when you walk into it.

    I suppose you'll have to check out bounding boxes. Look around for how entities collide with walls or something.
    KingFaris11 likes this.
Thread Status:
Not open for further replies.

Share This Page