Development Assistance A better method to track player movement?

Discussion in 'Plugin Help/Development/Requests' started by BizarrePlatinum, Aug 23, 2015.

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

    BizarrePlatinum

    I am currently playing around with a parkour plugin, creating it for fun. I'm trying to track when the player moves to certain block types, and then doing stuff. For this, I am using PlayerMoveEvent. When I took an early version to my test server to make sure everything is working how I want it to, I immediately realized that PlayerMoveEvent would not work, at least not the way I am trying to use it, as the code is being fired when the cursor moves. Is there another method that I can use for this? Or a way to distinguish if the player had actually moved vs the cursor?

    Another issue I would like to address is my blocks. My start block works fine, however the other two blocks I am using appear not to be. Not really sure what has caused them to stop, they were working fine before. Not 100% on my timer either.

    Code:
    @EventHandler
        public void onWalk(PlayerMoveEvent e) {
            final Player p = e.getPlayer();
            Block b = e.getTo().add(0, -1, 0).getBlock();
           
            if(b != null) {
                if(!(e.getFrom() == e.getTo())) {
                    if(b.getType().equals(Material.WOOL)) {
                        if(b.getData() == (byte) 13 && (!(currentTime.containsKey(p)))) {
                            if(parkourList.containsKey(b.getLocation())) {
                                setupParkourInventory(p);
                                p.sendMessage(ChatColor.GREEN + "You have started parkour \"" + parkourList.get(b.getLocation()) + "\".");
                                checkpoint.put(p, b.getLocation());
                                taskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
                                    @Override
                                    public void run() {
                                        if(!(currentTime.containsKey(p))) {
                                            currentTime.put(p, .001);
                                        } else {
                                            currentTime.put(p, currentTime.get(p) + .001);
                                        }
                                    }
                                }, 0L, (long) .02);
                            }
                        }
                    } else if((b.getData() == (byte) 4) && currentTime.containsKey(p)) {
                        checkpoint.put(p, b.getLocation());
                        p.sendMessage(ChatColor.GREEN + "Checkpoint!");
                    } else if((b.getData() == (byte) 9) && currentTime.containsKey(p)) {
                        Bukkit.getScheduler().cancelTask(taskId);
                        p.sendMessage(ChatColor.GOLD + "You have finished the parkour! Your time was: " + currentTime.get(p) + ".");
                        double time = Math.round(currentTime.get(p));
                        if(!(personalRecord.containsKey(p)) || personalRecord.get(p) < time) {
                            p.sendMessage(ChatColor.GOLD + "New personal record!");
                            personalRecord.put(p, time);
                        } else {
                            p.sendMessage(ChatColor.GOLD + "You missed your personal record by " + (time - personalRecord.get(p)) + ".");
                        }
                        currentTime.remove(p);
                        clearParkourInventory(p);
                    }
                }
            }
        }
    
     
  2. Offline

    Boomer

    player move event is your only real option, unless your final target point is for example, landing on a pressure plate, in which case it would be a physical interaction event, much rarer less frequent.

    Even so, you need to find ways to escape out of the event ASAP with the least amount of computations. For example, you want to do this for players who are likely playing a parkour game - you should keep a list of them when they are playing, then the first thing you check is "is this player who threw the event playing a game? No -> Return out right away" because 99.999% of the on-move events in your server lifetime will be generated from not in that game, so you dont want to do an iota of getting and checking and calculating things that doesn't have to be done.

    Also, scheduling a REPEATING task within an event is the best way to drive your server to lag and crash horribly. You are creating a new "do this every n ticks until the server is shutdown" instance when making a repeating task.

    Also (long) of 0.2 is 0 ... the scheduler needs actual integer tick values

    You need to take a big step back and do some flowcharting for what you want to accomplish as part of a test process, and what outcomes to do. Then identify how those flow together, and find what solution is required, rather than trying to stuff a synch repeating task into the flowchart, determine what the relationship is for a given situation and it may manefest as a recursive or self-calling single task that determins if its time to stop or continue, for example.

    Define your problem on paper and it will become more evident what tests you need to perform in what order, and what information 'you already have before getting to here, that doesn't have to be gotten repeatedly' etc
     
  3. Offline

    BizarrePlatinum

    @Boomer I want the timer to be precise, what is the best way to do that? I know that the whole repeating task can lag the server quite a bit (I am starting a new one every time the block is stepped on, after all), seemed like a good idea at the time. I was using the currentTime hashmap to determine whether or not the players were in the game (#lazy), went ahead and created myself a list. Thanks for your time :).
     
  4. Offline

    Boomer

    If you want a precise time from start to end of something, save the System nanotime or millisecond time at the start, and at the end, snap that time again, compute the difference, round appropriately.

    Keep in mind that a player rotation is also the same thing as a movement, and that a player must move approximately 15 times or so before actually crossing from one block location to another. So even as it is, you are "stepping on the target block" at least 10 to 20 times to initiate something...
     
  5. Offline

    BizarrePlatinum

    @Boomer I had actually considered that while looking around the internet for a solution, couldn't quite work out how it would work in my head, got a good idea of how now. I believe I'll just change it to an interaction with pressure plates rather than remaining with PlayerMoveEvent, seems like it would be a lot easier. Thank you for your time.
     
Thread Status:
Not open for further replies.

Share This Page