Solved Check if players z and x have increased in an X amount of time

Discussion in 'Plugin Development' started by someguyonthestreet, May 20, 2015.

Thread Status:
Not open for further replies.
  1. The title says it all.
    I'm trying ot check if a player's X and Z have increased in a certain amount of time (1 second).

    Code:
    Code:
    @EventHandler
        public void onSpeed(final PlayerMoveEvent event) {
            final Player player = event.getPlayer();
           
            if (player.getLocation().subtract(0, 1, 0).getBlock().getType() != Material.AIR || player.getLocation().subtract(0, 1, 0).getBlock().getType() != Material.WATER || player.getLocation().subtract(0, 1, 0).getBlock().getType() != Material.STATIONARY_WATER) {
                if (player.getGameMode() != GameMode.CREATIVE) {
                    Bukkit.getScheduler().scheduleSyncDelayedTask(Main.get(), new Runnable() {
                        public void run() {
                            if (event.getFrom().getX() != event.getTo().getX() || event.getFrom().getZ() != event.getTo().getZ()) {
                                   
                                    if (event.getFrom().getX() - event.getTo().getX() >= 7 || event.getFrom().getY() - event.getTo().getY() >= 7) {
                                        player.sendMessage("hacking");
                                   
                                }
               
                            }
                        }
                    }, 1 * 20L);
                }
            }
           
        }
    I know that event.getFrom().getX() != event.getTo().getX() will detect if a player move a block but I need to check if they moved 7+ blocks or something like so.

    EDIT by Timtower: merged posts
     
    Last edited by a moderator: May 21, 2015
  2. Offline

    mine-care

    @someguyonthestreet You need to store those values somewhere, store them, and after the X ammount of time check if they changed compared to the new ones. A tip: don't use shedulers and tasks if it is gonna be on a mass scale. Instead process time in miliseconds (System.currentTimeMins()) :- )

    PS. as i noticed you want to make a plugin to disable speed cheat? if so, dont forget that speed potions, and player speed can affect your tool.
     
  3. @someguyonthestreet What if they move, and then teleport within a second? You'll think they're hacking.
     
  4. @mine-care * System.currentTimeMillis()
    @AdamQpzm you can listen for a teleportevent and if the player has been teleported you can set a flag
    @someguyonthestreet
    1. safe current x and z value of the player
    2. wait for x amount of time (multiple ways, i ll explain later)
    3. check after waiting if current x and z of the player != old x and z of the player
    4. if boolean is true do your stuff

    Ways to wait for x amount of time:

    1. Call Thread.sleep(millis)
    this methods stops the current thread for the amount of time given as milliseconds. not recommended if you are still in a thread of the server, because it stops the whole server for your amount of time. if you got a seperate thread running its fine

    2. Run a schedular
    you can run a bukkitschedular (google how to do it or search in forum, there are many solutions for it you can look up on). this is practicly a seperate thread which repeats a task as often as you tell it to and waits after every executed task a given amount of time. this would be a good solution for you if you want to check a few times if a player moved or also permannently. you can tell the schedular how often it should check and how long it shall wait between the checks

    3. busy waiting
    you get the current systemtime (System.currentTimeMillis()), save it in a variable and start a while loop, which loops until the saved value is equal or smaller than System.currentTimeMillis() - yourAmountOfTimeInMilliseconds. This way is easy and works always. but it blocks the current thread (like Thread.sleep(...) does) and is kinda unifficient. But the perfect solution if you only want to check once if a player moved and if you are not on a serverthread

    4. listen to event
    listen to the playermovedevent. every time a player moved, you take his x and z and save them into variables. at the same timepoint, you save the value of System.currentTimeMillis() into a variable. you also check at the same time the last x, z and value of System.currentTimeMillis() against the new ones. if the x and z changed and the old value of System.currentTimeMillis() isnt at least smaller about the amount of the given waitngtime, you know that the player moved during the last x secs/millisecs/whatever. Works always, works fine. Is not the most efficent way to do it but deffenetly not inefficient. Also if your waitingtime is for example a second, you dont know every second if the player moved. you only know it when then player starts moving, because the event wont be called if the player doesn't move. so it could happen (for example when being afk) that you will know after 30 minutes that a player didn't move when he came back and moved again

    Choose your way :)
    PS: sorry for bad explanations, english is not my native language as you might have recognized :D

    Edit: added a 4th way
     
    Last edited: May 21, 2015
  5. I was referring more to his current approach, where he just tries to check whether they've moved 7 blocks away :)
     
  6. @Shmobi Thanks for describing it in great description, but all I really am looking for is checking if the player moved 7 blocks in a second. But I haven't really used System.currentTimeMillis() so it might be challenging for me to do it that way even though it seems to be better than a schedular

    @Shmobi @AdamQpzm
    This is what I have so far, but I need help checking if the player moved 7 blocks.
    http://hastebin.com/pepiwohago.avrasm

    I also wrote this, but I'm not sure if this will work (I am also changed the movedBlocks to 0 on the teleport event)
    http://hastebin.com/ojolajiqaz.avrasm

    EDIT by Timtower: merged posts
     
    Last edited by a moderator: May 21, 2015
  7. Offline

    Zombie_Striker

    You should try using a runnable, instead of using a event that is triggered at the slightest move of the head (using more memory). With runnables, you can select the amount of time you want to check (e.g. 1 second == 20Long) and then compare distances. Try using something like this.

    Code:
    public HashMap<UUID,Location> LocationFromSecondAgo = new HashMap<Integer,Location>();// stores players location from one second ago
    
    int maxSpeed = 10; // ten blocks is max blocks you can run before it looks like hacking lets say.
    
    //In the runnable
    public void run(){
       for(Player p : getServer().getonLinePlayers()){
             int x = p.getLocation().getX - LocationFromSecondAgo.get(p.getUnqueID).getX;
             int z = p.getLocation().getZ - LocationFromSecondAgo.get(p.getUnqueID).getZ;
    //lets say the Z now is 100, but the Z from a second ago was 98, then z will equal 2;
    
    // if the Z now is 98, but before was 100, this would invent the number from -2 to a 2;
             if(x < 0) x = -(x);
              if(z < 0) z = -(z);
             if(x+z >= maxSpeed){
                hackKick(p); // create a method for kicking hackers
            }
        }
    }
     
  8. Offline

    mine-care

    @Shmobi I typed it by phone xD i am used to misstypes :p
    @Zombie_Striker Please avoid spoonfeeding, most people simpyl copy-paste it and gain nuthing out of it.
     
  9. @mine-care
    I'm not going to even use @Zombie_Striker's code because I don't understand it and if it gives an error I won't be able to fix it. Plus All I need to know if my method will work because I do have checks if the players x/z have been changed which would mean they are moving a block instead of moving there head.
     
  10. @someguyonthestreet ok so look, i will explain how to use system.currenttimemillis(). At the end of this i recommend you a solution, so read it :p
    @all please don't cry at me for spoonfeeding, it isn't!

    The method currentTimeMillis() of the class System returns a value of the type long, which represents the current system time. That means that you can save the timepoint of calling this method in a variable. That's easy, you can do that by doing this:
    Code:
    long time = System.currentTimeMillis();
    To save the timepoint of the last call of a method inside a calss, you would need to define a member of the class (private field) in which you save this value every time the method is called. This would look in a simple class like this:
    Save timepoint of method call - Code (open)
    Code:
    public class SomeClass{
    
    private long lastMethodCall;
    
    public void someMethod(){
      lastMethodCall = System.currentTimeMillis();
      // execute your stuff here
    }
    
    }

    Since we know how to get the current time and when the last call of the method was, we can calculate the time between the methodcalls. As you can guess, because it is logic, System.currentTimeMillis() will return with every call a higher value, because time does go forwards and never backwards. So to find out, how much time went over between two method calls, we substract the longvalue of our last method call (which we saved in our member/variable) of the current systemtime. This will give us the time between two calls in millisekonds. Would look like this:
    Get time between methodcalls - Code (open)
    Code:
    public class SomeClass{
    
    private long lastMethodCall;
    
    public void someMethod(){
      long timeBetweenCalls = System.currentTimeMillis() - lastMethodCall; // calculating the time between the calls
      System.out.println("Time between this and last call in millis: "+timeBetweenCalls); // printing the result
      lastMethodCall = System.currentTimeMillis(); // setting the new time for this call
      // execute your stuff here
    }
    
    }

    So now where we know how to calculate the time between two method calls, we can simply check if a specific amount of time went over since the last method call. Just like this:
    Check time between methodcalls - Code (open)
    Code:
    public class SomeClass{
    
    private long lastMethodCall;
    private long specificAmountOfTime = 1000; // 1 second
    
    public void someMethod(){
      long timeBetweenCalls = System.currentTimeMillis() - lastMethodCall; // calculating the time between the calls
      if(timeBetweenCalls>=specificAmountOfTime){  // executes the method only if there went enough time over between the calls
       System.out.println("The last methodcall is at least "+specificAmountOfTime+" ago"); // printing the result
       lastMethodCall = System.currentTimeMillis(); // setting the new time only if the method will be executed
       // execute your stuff here
      }
    }
    
    }

    And there you go, now you know how to use System.currentTimeMillis() and how to calculate the time between two timepoints by using it.

    But in your case, i would recommend using a schedular. Because as somebody already said, the event is thrown a lot of times, even if the player didn't leave the block he is standing on. So a schedular which runs with a delay of a second between its tasks would be a good solution. For checking if a player moved 7 blocks i would use player.getLocation().getBlockX() and getBlockY(). Save those values every second in a variable (just like with the systemtime in the example) and check if (newX - oldX >=7 || newY - oldY >=7). This will tell you if the player moved 7 blocks.
    BUT: this only works in one direction. if the player moves in the right direction, his y and x can become smaller. then you would also have to check for -7.

    Also did you think about explosions and stuff? they can push a player. Also for example a sword with the pushing enchantment (sorry idk the exact name but it exists) could push a player over this distance and trigger your "hacker code".
     
Thread Status:
Not open for further replies.

Share This Page