[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

    75.0%
  2. Yes, but with a little help

    0 vote(s)
    0.0%
  3. Probably not

    25.0%
  4. Definetly not

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

    Icyene

    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.

    Code:java
    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. }
    11.  
    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.

    Code:Java
    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:
    Code:
    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

    the_merciless

    Anyone know if this still works?
     
  4. Offline

    ZeusAllMighty11 Retired Staff


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

    the_merciless

    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

    DSH105 Retired Staff

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

    the_merciless

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

    gabizou

    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

    bobacadodl

    gabizou
    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

    gabizou

    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. Offline

    xxyy98

    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)
    Code:java
    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

    Icyene

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

    iZanax

  14. Offline

    xxyy98

    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

    sipsi133

    What are the new method names for 1.7.2?
     
  16. Offline

    xxyy98

    sipsi133 As stated my above post, a working 1.7.2 example can be found here.
     
  17. Offline

    Icyene

    sipsi133
    xxyy98

    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

    sipsi133

    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

    Qukie

    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:
    Code:java
    1. entity.motX += 0.2F; //Set this to whatever you wish
    2. entity.motZ += 0.2F;
    3.  
    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. Offline

    KingFaris11

    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

    Garris0n

    It's the same method I believe.

    Judging from this, anyway.
     
  23. Offline

    KingFaris11

    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

    Garris0n

    Huh? When did that happen...
     
  25. Offline

    KingFaris11

    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.

    Garris0n
    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

    Garris0n

    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