Error with spectator to survival mode

Discussion in 'Plugin Development' started by Michel_2001, May 30, 2018.

Thread Status:
Not open for further replies.
  1. Hi, I want to make an timer of 5 seconds (int made earlier) if it's counting down you have to be in spectator mode, which works. When the timer is 0 you have to be set back in survival mode. This doesn't work, it's bugging you have a head with no body, you can't move. Can someone help me with a fix?

    Code:
    public void onPlayerDeath(PlayerDeathEvent e) {
            player = e.getEntity();
            if (player.hasPermission("respawn.wait")) {
                player.setGameMode(GameMode.SPECTATOR);
    
                taskID = plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable() {
                    public void run() {
                        if (timer > 0) {
                            timer--;
                        } else if (timer == 0) {
                            plugin.getServer().getScheduler().cancelTask(taskID);
                            player.setGameMode(GameMode.SURVIVAL);
                            timer = 5;
                        }
                    }
                }, 0L, 20L);
            }
        }
     
  2. Offline

    Zombie_Striker

    @Michel_2001
    Don't use task IDs. If you need a task to be cancelable, use BukkitRunnables (instead of regular Runnables) and call the cancel() method.

    Also, don't store the entity in a field. If multiple players die at once, only the last player will ever be able to get out of the timer.

    Main problem: You cannot call bukkit methods in an Async task. Simply put, you should only use async tasks when sending or recieving information from another program. If you're doing something for the game, make it sync.
     
  3. Thank you! It almost works now. The only thing is, you said I can't store the player entity in a field, which makes sense. How do I make it so that more players can die at the same time and still all have a separate timer. I can't change gamemode on the entity itself. And I can't check permissions and send messages if it's now a player. I have this now:

    Code:
    @EventHandler
        public void onPlayerDeath(PlayerDeathEvent e) {
            Player player = e.getEntity();
            if (player.hasPermission("respawn.wait")) {
                player.setGameMode(GameMode.SPECTATOR);
                new BukkitRunnable() {
                    @Override
                    public void run() {
                        if (timer > 0) {
                            timer--;
                        } else if (timer == 0) {
                            player.setGameMode(GameMode.SURVIVAL);
                            timer = 5;
                            this.cancel();
                        }
                    }
                }.runTaskTimer(plugin, 0L, 20L);
     
  4. Offline

    Zombie_Striker

    @Michel_2001
    There shouldn't be a need to store the player instance. As long as you make 'player' final, the bukkit runnable should be able to get the player instance from the event and keep it until it runs.

    If you need to store the player instance for something else, use HashMaps to link the player with the BukkitTask (which is the task created by using the BukkitRunnable)
     
  5. I've tried many variants of this but this is what most of the time happens: First player dies after 7 seconds gamemode survival. While the first player is in the 7 seconds, a second player dies. The second player has to wait 7 seconds + the remaining seconds of the first one. It doesn't make just a separate Runnable with a new player.
    Code:
    @EventHandler
        public void onPlayerDeath(PlayerDeathEvent e) {
            test++;
            final Player player = e.getEntity();
            timer = plugin.getConfig().getInt("Waiting Time");
            if (player.hasPermission("respawn.wait")) {
                player.setGameMode(GameMode.SPECTATOR);
                new BukkitRunnable() {
                    @Override
                    public void run() {
                        final Player p = e.getEntity();
                        if (timer > 0) {
                            p.sendMessage(ChatColor.GOLD + Integer.toString(timer));
                            p.sendMessage(Integer.toString(test) + " TEST TEST TEST");
                            timer--;
                        } else if (timer == 0) {
                            p.setGameMode(GameMode.SURVIVAL);
                            timer = plugin.getConfig().getInt("Waiting Time");
                            this.cancel();
                        }
                    }
                }.runTaskTimer(plugin, 0L, 20L);
            }
        }
     
  6. From the looks of it, you’re using a single timer stored by the listener. Every time a player dies this same timer will get changed and decreased by the runnables. Use separate timers for each player and it should work.
     
  7. I'm trying to do that, I've indeed figured out that it's the same timer being updated. But since PlayerDeath is for every player its just the same event. Maybe I should make a method which runs everytime a player time, maybe it can have separate timers then
     
Thread Status:
Not open for further replies.

Share This Page