Restricting an Area?

Discussion in 'Plugin Development' started by kampai, Oct 10, 2015.

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

    kampai

    Hey I've been having trouble with this! :mad:

    For the past few days I have been scratching my head wondering how would I restrict and area. I know this is possible with World Guard but I would like to implement this into my plugin. Would it be easier to use the World Edit API or hard code it?
     
  2. Offline

    mythbusterma

    @kampai

    Well I wouldn't hard code it, but it's pretty easy to do yourself.

    All you need is two opposite points on the cube of the area you want to define (hopefully stored as Vectors), then you can check if another Location or Vector is in the region by using Vector#isInAABB(Vector, Vector)
     
  3. Offline

    Zombie_Striker

    Why not try this:
    1. Create a Hashmap, UUIDS as the key, Locations as values
    2. Create a repeating task that loops through everyone online every 5 ticks (0.25 seconds)
    3. Inside that task, loop through all players online.
    4. Check if the players location is inside the restricted area
    5. if the player is, teleport them back to the location stored in the hashmap
    6. if the player is not inside restricted area, put them into the hashmap with their current location
    Simple and should cause that much lag on your server.
     
  4. Offline

    kampai

    Why use UUID? Wouldn't it be easier to use player since the player wouldn't be stored in the hashmap for long?

    @Zombie_Striker
    Now I have the code below how would I check if they're in the area
    Code:
       @EventHandler
       public void onBlockPlace(BlockPlaceEvent event){
            Block b = event.getBlock();
               if(b.getType() == Material.EMERALD_BLOCK ){
                  
                         Bukkit.getServer().getScheduler().scheduleAsyncRepeatingTask((Plugin) this, new Runnable() {
                             public void run() {
                                 for (Player online : Bukkit.getOnlinePlayers()) {
                                     // CHECK IF THE PLAYER IS IN THE AREA
                             }
                          }
                            
                     }, 5, 100);
             }
       }
    }
    
    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Oct 29, 2015
  5. Offline

    mythbusterma

    @kampai

    Stop using "async." Just stop it.

    Also, you can just check in the player move event and cancel it, checking if they're in the area. Like I said. If you read my post.
     
  6. Offline

    kampai

    @mythbusterma
    Yeahh sorry his method seemed easier, but now that I think about it your way of doing it is.
    This isn't working for some reason.

    Code:
         @EventHandler
             public void onPlayerMove(PlayerMoveEvent event) {
             Player player = event.getPlayer();
             Location loc = player.getLocation();
             Location coord1 = player.getLocation();
             Location coord2 = player.getLocation();
           
             coord1.setX(9);
             coord1.setZ(-11);
           
             coord2.setX(5);
             coord2.setZ(-11);
           
                 if(loc.getX() > coord1.getX() && loc.getX() < coord2.getX()){
                     if(loc.getZ() > coord1.getZ() && loc.getZ() < coord2.getZ()){
                         event.setCancelled(true);
                       
                     }
                       
                     }
         }
           
    }
     
  7. Offline

    Zombie_Striker

    @kampai
    No, Don't use PlayerMoveEvent. If the player looks left/right it will trigger this event. This is way laggier than just adding a repeating task to the onEnable.

    btw, you could always create a new location instance and convert those 6 lines into 2 (the coords1&2.setx/z)

    Also, the z is the same, and you're only checking if its LESS THAN (not less than or equal to).

    And don't cancel the event, just teleport them back.
     
  8. Offline

    kampai

    Ehh I like using 6 lines since it's easier to read. Also it's still not working. Once I get it working I will make a repeating task in my on enable :).

    Code:
        @EventHandler
        public void onPlayerMove(PlayerMoveEvent event) {
        Player player = event.getPlayer();
        Location loc = player.getLocation();
        Location coord1 = player.getLocation();
        Location coord2 = player.getLocation();
     
        coord1.setX(9);
        coord1.setZ(-11);
     
        coord2.setX(5);
        coord2.setZ(-11);
     
            if(loc.getX() >= coord1.getX() && loc.getX() <= coord2.getX()){
                if(loc.getZ() >= coord1.getZ() && loc.getZ() <= coord2.getZ()){
                   
                    player.teleport(loc);
                 
                }
                 
     
            }
            }
    }
     
  9. Offline

    Zombie_Striker

    If you mean that once you get the PlayerMoveEvent (The Event you're going to remove), then you'll move it to the task? Why not just move it to the task and work on it from there? That will save time.

    I looked at your code agin. Looks like you inverted you if statment.

    Lets say the player is at x=7, y=anything, z = -11.

    7 >= 9 ---> false, 7 <= 5 -----> false.

    Even though he is standing right in the center of the region, the if statements are canceling each other out.
     
  10. Offline

    kampai

    @Zombie_Striker
    Whoops! Meant to put it the other way around. Here's my new code. Still won't work
    Code:
            Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
                public void run() {
                    for (Player player : Bukkit.getOnlinePlayers()) {
    
                    Location loc = player.getLocation();
                    Location coord1 = player.getLocation();
                    Location coord2 = player.getLocation();
               
                    coord1.setX(5);
                    coord1.setZ(-11);
                 
                    coord2.setX(9);
                    coord2.setZ(-11);
               
                        if(loc.getX() >= coord1.getX() && loc.getX() <= coord2.getX()){
                            if(loc.getZ() >= coord1.getZ() && loc.getZ() <= coord2.getZ()){
                             
                                player.teleport(loc);      
                             
                            }
                        }
                }
                }
        }, 5, 5);
         
         }
        
     
    Last edited: Oct 10, 2015
  11. Offline

    caderape

    @kampai
    this will not work, cuz you teleport the player where he's standing, this is useless.
    You have to compare with the previous location. So create a hashmap that store the location or use playerMoveEvent with the getFrom() and getTo()
     
  12. Offline

    mythbusterma

    @kampai

    ......I know this code is extremely difficult so let's walk through it.

    Code:
    Vector minimum;
    Vector maximum;
    
    @EventHandler
    public void onMove(PlayerMoveEvent event) {
        if (event.getPlayer().getLocation().toVector().isInAABB(minimum, maximum)) {
            event.setCanceled(true);
        }
    }
    Phew, that was difficult, we almost passed 4 lines there.

    @Zombie_Striker
    I really hate when people say "oh that will be inefficent" or "that will lag" when they have no clue what they're talking about.

    It really doesn't matter. Like at all. The code we're using here is so ridiculously insignificant that it really makes no difference. Let's work this out. I'm going to assume a modern computer that runs something like an i7.

    Let's say that that using the getter methods take 15 nanoseconds (extremely generous) and we perform two of those per event. Then, that converting it to a Vector and creating a new Vector takes 50 nanoseconds (again, generous). Then, we do the math to compare if it's in an axis-aligned-bounding-box, and assume that doing some simple math and arithmetic takes say another 50 nanoseconds. Then let's say canceling the event takes around 10 nanoseconds.

    That adds up to 15o nanoseconds (give or take) for each time this method is called. Let's say your server has 1,000 players that are all moving 10 times a second (a ludicrous amount), for 10,000 PlayerMoveEvents a second. This is about 500 PlayerMoveEvents a tick, which means you will spend roughly 150 * 500 nanoseconds in this method per tick, or around 75000 nanoseconds per tick, considering each tick is required to complete in 50 milliseconds, you've used less than 1/1000th of the time available.

    TL;DR stop saying player move event is inefficient, the way you suggested is confusing and wasteful.
     
    Zombie_Striker likes this.
Thread Status:
Not open for further replies.

Share This Page