Solved Change block when no one is looking at it

Discussion in 'Plugin Development' started by Failplease, Jan 9, 2014.

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

    Failplease

    I know that you can use a PlayerMoveEvent to change a block when a player is not looking at it, but how would I change it when everyone is not looking at it, not just individual players?

    My code makes it so if a player does not look at a block, then it is stone, but when they do look at it it is cobblestone. What happens is that when one player is looking at it and the other isn't, the block keeps glitching between stone and cobblestone.

    So I want it so that if at least one player is looking at the block, then it is cobblestone. If no one at all looks at it, the block is stone.

    Any help would be appreciated. :)
     
  2. Offline

    JRL1004

    Failplease Make a repeating task to check through all the players on the server every X ticks and if no players are looking at the block then make it stone. If you try and make the check every time PME fires, you will just lag the server to death (depending on if you iterate through all the players or not and how many players are online).
     
  3. Offline

    Failplease

    JRL1004
    Ok, but how do I make it not run every time PME fires?
     
  4. Offline

    JRL1004

    Failplease As I stated previously, use a SyncRepeatingTask every X ticks and when the task triggers have it iterate through all the online players. For each player check if they can see the block, if they can then you know not to change it, otherwise you can change it.
     
  5. Offline

    Failplease

    JRL1004
    Ok, but is there any way that I can reduce lag even more by making the repeating task only run when someone is moving?
     
  6. Offline

    JRL1004

    @FailpleaseYou don't really need to do that. Repeating tasks are about as efficient as you can get for this (unless you make it Async, which I do not recommend). if you want it to only run when a person is moving then you will still need to use PME (which in turn will cause more lag). As for making the task itself lag less, just increase the ticks in between (bigger numbers = less lag but also less updates of the block(s)).
     
  7. Offline

    Failplease

    JRL1004
    Ok this sounds kind of dumb, but where do I put the repeating task in my code? I can't just put it in the class without it being in an EventHandler or a method, right?
     
  8. Offline

    JRL1004

    Failplease The task can go anywhere you want, but regardless of where you put it (beit a method or event or command or anything else) make sure you only call it ONCE. Calling it more than once will result in multiple copies of the same task running at the same time.
     
  9. Offline

    Failplease

    JRL1004
    I think I'm brain dead tonight, how would I iterate through the online players and check if all of them are not looking at the block? Because when you use a for loop, it only does things for that one player before moving on to the next... So how would I do this (or am I just confused)?
     
  10. Offline

    JRL1004

    Failplease So I made this really quick, I am not sure if it works 100% but you could at least test it.
    Code:java
    1. public static final boolean isBlockSeen(Block block)
    2. {
    3. Player[] online = Bukkit.getOnlinePlayers();
    4. if (online.length == 0)
    5. return false; // How can someone see it if nobody is online?
    6. Location sLoc = block.getLocation().add(0.5, 0.5, 0.5); // Gets the
    7. // exact
    8. // middle of
    9. // the block
    10. FallingBlock fB = block.getWorld().spawnFallingBlock(sLoc,
    11. block.getTypeId(), block.getData()); // Create a fake block
    12. // real quick so we
    13. // can check easier
    14. for (Player player : online)
    15. {
    16. if (player.hasLineOfSight(fB))
    17. { // You can only see if a player can see an entity, not a block
    18. System.out.println("Block seen by: " + player.getName()); // Debug
    19. // message
    20. fB.remove();
    21. return true;
    22. }
    23. }
    24. fB.remove();
    25. return false;
    26. }
     
  11. Offline

    Failplease

    JRL1004
    The falling block approach doesn't work. It gets spawned and all, but it doesn't detect me looking at it. I think it's because the block that it is spawning in "blocks" your view of the falling block.

    And getTargetBlock() is all bugged, so I'm not going to use that.
    Any other suggestions?
     
  12. You could check the bounds of the player, etc. Or you can use player.getTargetBlock
     
  13. Offline

    JRL1004

    Louis1234567890987654321 *Facepalm*
    You could try spawning the entity on each of the non-block sides of what you are checking and see if the player can see any of those entities.
     
  14. *facepalm*

    Spawning entities will cause more lag. Why not make use of some logic and check the blocks using bounds or something?
     
  15. Offline

    xBlackLightx

    JRL1004 Using the LivingEntity.hasLineOfSite()? That would work but its getting a bit complicated. I found another answer that may work for you. I can't take credit for it, @Ammar_Askar wrote this.
    Failplease
    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.  
    3. Location loc1 = player.getLocation();
    4.  
    5. 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; }

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

    Then I believe all you would have to do, is put the if statement inside a repeating task with whatever time you want. Longer time = less resources used but less updates. shorter time = more resources but more updates. :)

    LeoFSU
    *FACEPALM*
    I can't think of anything else to say to this.
     
  16. That is not unhelpful. That is helpful and it helps devs increase the understanding of bukkit API.
     
  17. Offline

    xBlackLightx

    Louis1234567890987654321 He is talking about my comment in reply to him saying to use F5 to look behind you. It is completely unrelated to this thread and for that matter, unrelated to anything having to do with any form of plugin development. LeoFSU And in reply to you saying "It would be nice if you could stop posting unhelpful content like that and instead focus on the thread.", I just posted a long message with very helpful information, and, in contrast, you have posted nothing contributing to the conversation, so I would appreciate if you refrain from further comment unless you have something worthwhile to say.
     
  18. Offline

    JRL1004

    Louis1234567890987654321 To check each boundary of the block would actually cause more lag than just creating an FallingBlock entity and checking if the player can see it (especially since FallingBlocks do not have any AI (Like pathfinding)). As for@xBlackLightx 's method, it is tru that it will not work if the player is in F5 mode but who goes about a server in Skycam (double -F5 mode)?
     
  19. Offline

    Failplease

    Louis1234567890987654321 JRL1004 xBlackLightx
    Thanks for all your help! I realized that getTargetBlock() was not bugged, it was just that I used the operator && instead of || in one of my if statements...

    Anyway, I will try your method xBlackLightx.

    (And I don't really care about F5 lol)
     
  20. Checking if the player can see it = checking the bounds (its same, but 1 more entity causes more lag)
     
Thread Status:
Not open for further replies.

Share This Page