Solved Checking if player "is in certain area"

Discussion in 'Plugin Development' started by Xp10d3, May 14, 2021.

  1. Offline

    Xp10d3

    This is a bit complicated to explain since I created my own API and am not using any portal plugin, but basically I want to check if the player "scores". On my server, there are goals and if one player falls through it, they score. I handle scoring entirely by myself, however, I have an issue in that sometimes the player scores, sometimes they don't. It seems quite random. I double checked my numbers, and they are indeed correct. But is this an issue with how I'm coding it, or is it truly the numbers?

    Relavant code:
    Code:java
    1.  
    2. if (p.getWorld().getName().contains("TreeHouse") && p.getLocation().getY() < 88.5) {
    3. if ((p.getLocation().getX() >= -34 && p.getLocation().getX() <= -30) && (p.getLocation().getZ() <= 2 && p.getLocation().getZ() >= -2)) {
    4. BridgeAPI.score(p);
    5. }
    6. }
    7.  


    Entire method (ignore the messy code lol):
    Code:java
    1.  
    2. @EventHandler
    3. public void onMove(PlayerMoveEvent event) {
    4. Player p = event.getPlayer();
    5. if (event.getPlayer().getLocation().getY() < 84) { // For void deaths
    6. String arenaName = p.getWorld().getName().replaceAll("[^A-Za-z]","");
    7.  
    8. List<BlockFace> faces = Arrays.asList(BlockFace.SOUTH, BlockFace.WEST, BlockFace.NORTH, BlockFace.EAST); // For forcibly facing the player to a certain direction
    9.  
    10. Player secPlayer = Bukkit.getPlayer(BridgeAPI.players.get(p.getName()));
    11. if (BridgeAPI.blue.contains(p.getName())) { // If on blue team
    12. BridgeMap loc1 = BridgeAPI.map.get(arenaName);
    13. Location loc = loc1.location1;
    14. BlockFace face = BlockFace.EAST;
    15. int index = faces.indexOf(face);
    16. loc.setYaw(index * 90);
    17. loc.setWorld(p.getWorld());
    18. p.teleport(loc);
    19. secPlayer.sendMessage(ChatColor.BLUE + p.getName() + ChatColor.GRAY + " died.");
    20. secPlayer.playSound(secPlayer.getLocation(), Sound.ORB_PICKUP, 1, 10); // Death sound
    21. p.sendMessage(ChatColor.BLUE + p.getName() + ChatColor.GRAY + " died.");
    22. } else if (BridgeAPI.red.contains(p.getName())){ // If on red team
    23. BridgeMap loc1 = BridgeAPI.map.get(arenaName);
    24. Location loc = loc1.location2;
    25. BlockFace face = BlockFace.WEST;
    26. int index = faces.indexOf(face);
    27. loc.setYaw(index * 90);
    28. loc.setWorld(p.getWorld());
    29. p.teleport(loc);
    30. secPlayer.sendMessage(ChatColor.RED + p.getName() + ChatColor.GRAY + " died.");
    31. secPlayer.playSound(secPlayer.getLocation(), Sound.ORB_PICKUP, 1, 10);
    32. p.sendMessage(ChatColor.RED + p.getName() + ChatColor.GRAY + " died.");
    33. }
    34. p.setHealth(20.0); // Set their health to full
    35. BridgeAPI.giveInv(p); // Give appropriate items
    36. }
    37.  
    38.  
    39. // Scoring (where I have issues)
    40. /** TODO
    41.   * Fix issues with scoring, clean up code
    42.   */
    43. if (BridgeAPI.red.contains(p.getName())) {
    44. if (p.getWorld().getName().contains("TreeHouse") && p.getLocation().getY() < 88.5) {
    45. if ((p.getLocation().getX() >= -34 && p.getLocation().getX() <= -30) && (p.getLocation().getZ() <= 2 && p.getLocation().getZ() >= -2)) {
    46. BridgeAPI.score(p);
    47. }
    48. }
    49.  
    50. if (p.getWorld().getName().contains("Mineshaft") && p.getLocation().getY() < 82.5) {
    51. if ((p.getLocation().getX() >= 67 && p.getLocation().getX() <= 65) && (p.getLocation().getZ() <= -24 && p.getLocation().getZ() >= -26)) {
    52. BridgeAPI.score(p);
    53. }
    54. }
    55. }
    56. if (BridgeAPI.blue.contains(p.getName())) {
    57. if (p.getWorld().getName().contains("TreeHouse") && p.getLocation().getY() < 82.5) {
    58. if ((p.getLocation().getX() >= 30 && p.getLocation().getX() <= 34) && (p.getLocation().getZ() <= 2 && p.getLocation().getZ() >= -2)) {
    59. BridgeAPI.score(p);
    60. }
    61. }
    62.  
    63. if (p.getWorld().getName().contains("Mineshaft") && p.getLocation().getY() < 82.5) {
    64. if ((p.getLocation().getX() >= -24 && p.getLocation().getX() <= -22) && (p.getLocation().getZ() <= -24 && p.getLocation().getZ() >= -26)) {
    65. BridgeAPI.score(p);
    66. }
    67. }
    68. }
    69. }
    70.  
     
  2. Offline

    KarimAKL

    @Xp10d3 Have you tried printing the numbers while you are falling through the goals?
     
  3. Offline

    Strahan

    I was wondering how I would do it if I wasn't leveraging WorldGuard, and I came up with this:
    Code:
    @EventHandler
    public void onPlayerMove(PlayerMoveEvent e) {
      if (e.getFrom().getBlockX() == e.getTo().getBlockX() &&
          e.getFrom().getBlockY() == e.getTo().getBlockY() &&
          e.getFrom().getBlockZ() == e.getTo().getBlockZ()) return;
    
      Player p = e.getPlayer();
      Location loc1 = (Location)getConfig().get("loc1");
      Location loc2 = (Location)getConfig().get("loc2");
      if (loc1 == null || loc2 == null) return;
    
      p.sendMessage("You are " + (isInRegion(p.getLocation(), loc1, loc2)?"":"not ") + "in the region");
    }
    
    private boolean isInRegion(Location source, Location bound1, Location bound2) {
      return source.getX() >= Math.min(bound1.getX(), bound2.getX()) &&
          source.getY() >= Math.min(bound1.getY(), bound2.getY()) &&
          source.getZ() >= Math.min(bound1.getZ(), bound2.getZ()) &&
          source.getX() <= Math.max(bound1.getX(), bound2.getX()) &&
          source.getY() <= Math.max(bound1.getY(), bound2.getY()) &&
          source.getZ() <= Math.max(bound1.getZ(), bound2.getZ()); 
    }
    PS yes I know there is a getLocation() in modern Spigot, but I test in 1.8 because it's loads soooo fast ;)
     
    Xp10d3 likes this.
  4. Offline

    Xp10d3

    No; I can try and do that when I get back home.

    Ooh, thank you! Should've thought to use Math.min and Math.max lol thanks. I'll test when I get back home rq

    Edit: @Strahan what is loc1 and loc2? I'm a tiny bit confused. I inputted the values into a config, but it didn't register when I tried to go through the goal.
    Code:java
    1.  
    2. @EventHandler
    3. public void onPlayerMove(PlayerMoveEvent e) {
    4. if (e.getFrom().getBlockX() == e.getTo().getBlockX() && e.getFrom().getBlockY() == e.getTo().getBlockY() && e.getFrom().getBlockZ() == e.getTo().getBlockZ()) return;
    5.  
    6. Player p = e.getPlayer();
    7. String arenaName = p.getWorld().getName().replaceAll("[^A-Za-z]","");
    8. double y = core.getConfig().getDouble("scoring." + arenaName + ".y");
    9. double redx1 = core.getConfig().getDouble("scoring." + arenaName + ".red.x1");
    10. double redx2 = core.getConfig().getDouble("scoring." + arenaName + ".red.x2");
    11. double redz1 = core.getConfig().getDouble("scoring." + arenaName + ".red.z1");
    12. double redz2 = core.getConfig().getDouble("scoring." + arenaName + ".red.z2");
    13.  
    14. Location loc1 = new Location(Bukkit.getWorld(arenaName), redx1, y, redz1);
    15. Location loc2 = new Location(Bukkit.getWorld(arenaName), redx2, y, redz2);
    16. if (loc1 == null || loc2 == null) return;
    17.  
    18. p.sendMessage("You are " + (BridgeAPI.isInRegion(p.getLocation(), loc1, loc2)?"":"not ") + "in the region");
    19. }
    20.  

    Config:
    Code:
    scoring:
      TreeHouse:
        y: 85
        red:
          x1: -34
          x2: -30
          z1: -2
          z2: 2
    
     
    Last edited: May 14, 2021
  5. Offline

    Xp10d3

  6. Offline

    davidclue

    Are these supposed to be world-specific? Maybe try to just use a location for the goals and use
    Code:
    if (location.distance(player.getLocation()) < 2)
    To check if they reach the goal.
     
  7. Offline

    KarimAKL

    You should always use #distanceSquared(Location) instead of #distance(Location).
    The reason is that #distance(Location) calls and returns the square root of #distanceSquared(Location).
    The problem with that is that getting the square root of a number is a performance-heavy task.
     
  8. Offline

    davidclue

    Yeah do what
    @KarimAKL said but regardless I don't know why you're using a PlayerMoveEvent because that is very performance heavy for the number of calculations you're already doing. Use a repeating task instead.
     
  9. Offline

    Strahan

    loc1 and loc2 define the upper left and lower right bounds of the cuboid in which you want to detect entry.

    While there are many examples out there of people doing things in PME they shouldn't, simply comparing the values of some variables is hardly performance heavy. Especially if one remembers to filter the event so your code only runs when someone actually traverses a block in the world.
     
  10. Offline

    Xp10d3

    The goal is a not one location/block. I've attached kinda what it looks like (sorry that it's so small; pixel art is easiest).
    EDIT: And yes it's world specific, but I can get the world.

    Tbh idrk either. I kinda wanted to post this mostly cause I know about the performance issues and that there's definitely a better way to do this.

    Ohhh I see. Thanks that makes a lot more sense.
     

    Attached Files:

  11. Offline

    Xp10d3

    Sorry for the late reply; works perfectly :D Marking as solved
     
    Strahan and KarimAKL like this.

Share This Page