[Solved] Testing if a player can see a block

Discussion in 'Plugin Development' started by Jogy34, Sep 2, 2012.

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

    Jogy34

    I have searched the forums for this and couldn't find anything on it.

    I want to test to see if a player is able to see a certain block. I don't want to test to see if they are looking at the block just if it is in their vision.

    The best I have come up with is testing the player's yaw/pitch against where they are in accordance to the block; however, this doesn't account for any obstructing blocks. I could go with this but I want to see if anyone has anything better than this.
     
  2. Offline

    MrFigg

    Only thing I can think of is using a BlockIterator to go through all the blocks between the player and the block in question, and check if any of them aren't air. This wouldn't be perfect though, as I'm sure there's bound to be some angles that will throw false positives and false negatives. Maybe after playing around with the different faces of the block in question you might get some better results, but bottom line I don't think bukkit was made with this in mind.
     
  3. Offline

    jamietech

  4. Offline

    md_5

  5. Offline

    CorrieKay

    Is this how this works too?
     
  6. Offline

    md_5

    Not quite sure, the actual Minecraft part of that algorithm is very complex.
     
  7. Offline

    MrFigg

    Huh, I didn't know about LivingEntity.hasLineOfSight(). The description implies it can handle the peripheral vision needed by Jogy34 quite nicely. That'll be useful in the future. The problem is it can only take another entity as a param. I suppose you could spawn an entity on each empty block face of the block in question, check line of sight to each of them, then de-spawn the entities. But it's getting overly complicated at this point.
     
  8. Offline

    Ammar Askar

    If you don't mind poking into Craftbukkit/n.m.s you can use vanilla ray tracing, I wrapped it up into a convenient little method

    Code:java
    1. public boolean canSee(Player player, Location loc2) {
    2. Location loc1 = player.getLocation();
    3. return ((CraftWorld)loc1.getWorld()).getHandle().a(Vec3D.a().create(loc1.getX(), loc1.getY() + player.getEyeHeight(), loc1.getZ()), Vec3D.a().create(loc2.getX(), loc2.getY(), loc2.getZ())) == null;
    4. }


    Here's a usage example:
    Code:java
    1. if (canSee(player, block.getLocation())) {
    2. player.sendMessage("You can see the block " + this.block.getType());
    3. } else {
    4. player.sendMessage("You can't see the block " + this.block.getType());
    5. }
     
    desht and MrFigg like this.
  9. Offline

    Jogy34

    Thanks to everyone. Your suggestions will come in handy. I have a few last questions though:
    First: the getLineOfSight() method take in a HashSet of Bytes for the block ids that are transparent. A Byte only goes up to 63 I think so what if I wanted to put in glass panes which are id 102?
    Second: the getLineOfSight() method does take into account the player's peripheral vision right?

    md_5
    MrFigg
     
  10. Offline

    MrFigg

    The default max size of a Byte according to docs.oracle.com is 2 to the 7th minus 1. So nothing to worry about there. Unfortunately LivingEntity.getLineOfSight() iterates through the blocks in line with the players reticle, so no, it doesn't take peripheral vision into account. Only LivingEntity.hasLineOfSight() does, and that needs an Entity to work.

    The closest thing to a workable solution for you seems to be what Ammar Askar posted. Though I don't think that takes glass and such into account. I'm honestly not familiar enough with NMS to give any helpful input on in.
     
  11. Offline

    Jogy34

    @Ammar Askar I have no clue what you are doing would you mind explaining it?
     
  12. Offline

    Jnorr44

    Yes it does, Glass and other transparent blocks are part of the class "BlockHalfTransparent" which extends Block.


    Jogy34 basically, he is finding the players' eye height, and finding if the block is within the view area of the player.
     
  13. Offline

    MrFigg

    Oh, cool. I didn't see BlockHalfTransparent in his post and still haven't learned what does what in the obfuscated NMS code, so I just assumed.

    So apparently the code Ammar Askar posted should work for you (Jogy34) as is. To use it (and any other net.minecraft.server classes) you just have to reference the craftbukkit.jar (full server) the same way you would reference the bukkit.jar (api) and it should work fine.
     
  14. Offline

    Jnorr44

    The most useful page in the world: :D
    https://github.com/Bukkit/mc-dev/tree/master/net/minecraft/server
     
  15. Offline

    md_5

    Byte goes up to 0xFF (255)
     
  16. Offline

    Ammar Askar

    Looks like MrFigg's got you covered on how to use it but here's a brief explanation on how it works:

    The Vec3D.a().create() created two 3d vectors from a vector pool. The a(Vec3D vec3d, Vec3D vec3d1) method in the World class then runs a ray trace from the first vector to the second. Ray tracing does some mathematical magic to determine if the two vectors can "see" each other.
     
  17. Offline

    Njol

    Isn't 0xFF -1?

    Also is it possible to use NMS's raytracing to get the exact targeted block of a player (i.e. taking half blocks etc. into account)?
     
  18. Offline

    md_5

    Depends how you look at it, but for all intensive purposes, no. (0xFF as an int is -1)
     
  19. Offline

    Njol

    0xFF as a byte is -1, otherwise it's 255 ;) (Just because you stated that bytes go up to 255 which they don't)
     
  20. Offline

    desht

    Err, yes they do :)

    8 bits can represent the decimal values 0 .. 255 (hex 0x00 .. 0xFF). 255 (0xFF) is indeed equivalent to -1 when represented as a signed byte in two's complement arithmetic.
     
  21. Offline

    md_5

    Correct, otherwise explain how a byte packet header can deduce the id of Packet 0xFF Kick.
     
  22. Offline

    Jogy34

    Ammar Askar Thank you so much. It works nearly perfectly and I wouldn't have been able to come up with anything even close to this.
     
  23. Offline

    Jogy34

    Ammar Askar The code broke as of 1.4. The error I'm getting is saying that the a() method is non-static now. Do you (or anyone else) know how to fix it?
     
  24. Offline

    iZanax

    Had the same issue with some other Vec3D code.
    its now:
    a( //Code
    instead of
    a().create( //code

    *Worked in my case
     
Thread Status:
Not open for further replies.

Share This Page