Solved TPA Plugin

Discussion in 'Plugin Development' started by spatziempire, Jan 13, 2019.

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

    spatziempire

    Hey, I'm trying to make a "tpa" plugin, so a player sends a teleportation request to target and the target can accept the teleport request with the command /tpaccept or deny it with the command /tpdeny. If he accepts, the sender of the teleport request gets teleported to the target. I know the code is really not good,
    but I still want to get it to work.

    I'm putting the sender with the target into a hashmap to check at the command /tpaccept if there even is a request. So the actuall problem is that it says always there is no request. Where's my mistake? What do I need to change?

    Here's the code:
    Code:
    package de.patrick.colonia.commands;
    
    import java.util.HashMap;
    
    import org.bukkit.Bukkit;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Player;
    
    import de.patrick.colonia.main.Main;
    
    public class TPA implements CommandExecutor {
       
        private HashMap<Player, Player> request = new HashMap<>();
       
        public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
            if (sender instanceof Player) {
                Player player = (Player) sender;
                if (command.getName().equalsIgnoreCase("tpa")) {
                    if (args.length == 1) {
                        Player target = Bukkit.getPlayer(args[0]);
                        if (target == null)
                            player.sendMessage("The player isn't online.");
                        else if (Main.economy.has(player, 200)) {
                            request.put(target, player);
                            player.sendMessage("You sent a teleport request to " + target.getName() + ".");
                            Main.economy.withdrawPlayer(player, 200);
                            target.sendMessage(player.getName() + " sent a teleport request to you.");
                        }
                        else
                            player.sendMessage("You don't have enough money.");
                    }
                    else
                        player.sendMessage("Usage: /tpa <player>");   
                }
                if (command.getName().equalsIgnoreCase("tpaccept")) {
                    if (request.get(player) == null)
                        player.sendMessage("There's no request to accept.");
                    else {
                        ((Player)request.get(player)).teleport(player);
                        player.sendMessage("You were teleported to " + ((Player)this.request.get(player)).getName() +  ".");
                        ((Player)request.get(player)).sendMessage(player.getName() + "was teleported to you.");
                        request.remove(player);
                    }   
                }
                if (command.getName().equalsIgnoreCase("tpdeny")) {
                    if (request.get(player) == null)
                        player.sendMessage("There's no request to deny.");
                    else {
                        player.sendMessage("Your request was denied.");
                        ((Player)request.get(player)).sendMessage("You denied.");
                        request.remove(player);
                    }
                }   
            }
            else
                sender.sendMessage("You must be a player.");
            return false;
        }
    }
    
    Regards
     
  2. @spatziempire

    The most likely reason that this doesn't work is that the Player class doesn't override the hashCode method properly. The best way to solve this is to use a Map<UUID,UUID> and to put the uuids of the players in the map. You can obtain the uuid of a player with player.getUniqueID().
    That will also solve memory waste problems later on.
     
  3. Offline

    spatziempire

    I tried it now with uuids and player names. Both didn't worked.
     
  4. Try
    if(request.contains(player) {...

    Or containsKey() I'm not pretty sure
     
  5. Offline

    KarimAKL

    @DerDonut 'containsKey()' for a map, 'contains()' for a list.
     
  6. Offline

    spatziempire

    Doesn't work. Still got the same problem.
    Here's the actuall code:
    Code:
    package de.patrick.colonia.commands;
    
    import java.util.HashMap;
    
    import org.bukkit.Bukkit;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Player;
    
    import de.patrick.colonia.main.Main;
    
    public class TpaCommand implements CommandExecutor {
       
        private HashMap<String, String> requests= new HashMap<>();
       
        public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
            if (sender instanceof Player) {
                Player player = (Player) sender;
                if (command.getName().equalsIgnoreCase("tpa")) {
                    if (player.hasPermission("tpa.send")) {
                        if (args.length == 1) {
                            Player target = Bukkit.getPlayer(args[0]);
                            if (target == null)
                                player.sendMessage("The player isn't online.");
                            else {
                                if (Main.economy.has(player, 200)) {
                                    player.sendMessage("You sent to " + target.getName() + "  a teleport request.");
                                    target.sendMessage(player.getName() + " sent a teleport request.");
                                    requests.put(target.getName(), player.getName());
                                }
                                else
                                    player.sendMessage("You don't have enough money.");
                            }
                        }
                        else                       
                            player.sendMessage("Usage: /tpa <player>");                                                       
                    }
                    else
                        player.sendMessage("You aren't allowed to do this.");
                }
                if (command.getName().equalsIgnoreCase("tpaccept")) {
                    if (requests.containsKey(player.getName())) {
                        player.sendMessage("You accepted the teleport request.");
                        Bukkit.getPlayer(requests.get(player.getName())).teleport(player);
                        requests.remove(player.getName());
                    }
                    else {
                        Bukkit.getPlayer(requests.get(player.getName())).sendMessage("test");
                        player.sendMessage("There's not teleport request.");
                    }               
                }
                if (command.getName().equalsIgnoreCase("tpdeny")) {
                    if (requests.containsKey(player.getName())) {
                        player.sendMessage("You denied the request.");
                        requests.remove(player.getName());
                    }
                    else
                        player.sendMessage("Usage: /tpa <player>");               
                }
            }
            else
                sender.sendMessage("You must be a player.");
    
            return false;
        }
    }
    
    I also changed the Hashmap key and value. They're now strings which save the players' names. This should save some RAM.
    Then I tried to send a message to the sender of /tpa <player> with
    Bukkit.getPlayer(requests.get(player.getName())).sendMessage("test");.

    Didn't work. Just an error. Maybe someone got a idea how to send messages instead to the sender of /tpa?

    Regards
     
  7. What does the error say?
     
  8. Offline

    spatziempire

    Code:
    [20:54:19 ERROR]: null
    org.bukkit.command.CommandException: Unhandled exception executing command 'tpaccept' in plugin Colonia v1.0
            at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46) ~[spigot.jar:git-Spigot-f56e2e7-98b862a]
            at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:139) ~[spigot.jar:git-Spigot-f56e2e7-98b862a]
            at org.bukkit.craftbukkit.v1_13_R2.CraftServer.dispatchCommand(CraftServer.java:702) ~[spigot.jar:git-Spigot-f56e2e7-98b862a]
            at net.minecraft.server.v1_13_R2.PlayerConnection.handleCommand(PlayerConnection.java:1636) ~[spigot.jar:git-Spigot-f56e2e7-98b862a]
            at net.minecraft.server.v1_13_R2.PlayerConnection.a(PlayerConnection.java:1476) ~[spigot.jar:git-Spigot-f56e2e7-98b862a]
            at net.minecraft.server.v1_13_R2.PacketPlayInChat.a(PacketPlayInChat.java:45) ~[spigot.jar:git-Spigot-f56e2e7-98b862a]
            at net.minecraft.server.v1_13_R2.PacketPlayInChat.a(PacketPlayInChat.java:1) ~[spigot.jar:git-Spigot-f56e2e7-98b862a]
            at net.minecraft.server.v1_13_R2.PlayerConnectionUtils.a(SourceFile:10) ~[spigot.jar:git-Spigot-f56e2e7-98b862a]
            at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_192]
            at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_192]
            at net.minecraft.server.v1_13_R2.SystemUtils.a(SourceFile:199) [spigot.jar:git-Spigot-f56e2e7-98b862a]
            at net.minecraft.server.v1_13_R2.MinecraftServer.b(MinecraftServer.java:896) [spigot.jar:git-Spigot-f56e2e7-98b862a]
            at net.minecraft.server.v1_13_R2.DedicatedServer.b(DedicatedServer.java:417) [spigot.jar:git-Spigot-f56e2e7-98b862a]
            at net.minecraft.server.v1_13_R2.MinecraftServer.a(MinecraftServer.java:831) [spigot.jar:git-Spigot-f56e2e7-98b862a]
            at net.minecraft.server.v1_13_R2.MinecraftServer.run(MinecraftServer.java:729) [spigot.jar:git-Spigot-f56e2e7-98b862a]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_192]
    Caused by: java.lang.IllegalArgumentException: Name cannot be null
            at org.apache.commons.lang.Validate.notNull(Validate.java:192) ~[spigot.jar:git-Spigot-f56e2e7-98b862a]
            at org.bukkit.craftbukkit.v1_13_R2.CraftServer.getPlayer(CraftServer.java:463) ~[spigot.jar:git-Spigot-f56e2e7-98b862a]
            at org.bukkit.Bukkit.getPlayer(Bukkit.java:374) ~[spigot.jar:git-Spigot-f56e2e7-98b862a]
            at de.patrick.colonia.commands.TpaCommand.onCommand(TpaCommand.java:49) ~[?:?]
            at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[spigot.jar:git-Spigot-f56e2e7-98b862a]
            ... 15 more
     
  9. Offline

    KarimAKL

    @spatziempire I think 'requests.get(player.getName())' is null. Also i would recommend the player's UUID and not name.
     
  10. Offline

    spatziempire

    Okay, gonna change it and then try to use uuids. But that doesn't fix the first problem.
     
  11. Offline

    KarimAKL

    @spatziempire You are checking if the map contains the player and then you have an else statement, in that else statement you are trying to get the player.

    Code:Java
    1. if (command.getName().equalsIgnoreCase("tpaccept")) {
    2. if (requests.containsKey(player.getName())) {
    3. player.sendMessage("You accepted the teleport request.");
    4. Bukkit.getPlayer(requests.get(player.getName())).teleport(player);
    5. requests.remove(player.getName());
    6. }
    7. else {
    8. Bukkit.getPlayer(requests.get(player.getName())).sendMessage("test");
    9. player.sendMessage("There's not teleport request.");
    10. }
    11. }

    You are trying to get the player at the first line in the else statement. (after knowing the map doesn't contain the player)
     
  12. Offline

    spatziempire

    I see, stupid mistake. Changed it, here's the code:
    Code:
    package de.patrick.colonia.commands;
    
    import java.util.HashMap;
    import java.util.UUID;
    
    import org.bukkit.Bukkit;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Player;
    
    import de.patrick.colonia.main.Main;
    
    public class TpaCommand implements CommandExecutor {
       
        private HashMap<UUID, UUID> requests = new HashMap<>();
    
        public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
            if(!(sender instanceof Player)) {
                sender.sendMessage("You must be a player.");
                return true;           
            }           
            Player player = (Player) sender;
            if (command.getName().equalsIgnoreCase("tpa")) {
                if (!player.hasPermission("tpa.sent")) {
                    player.sendMessage("You aren't allowed to do this.");
                    return true;
                }
                if (args.length != 1) {
                    player.sendMessage("Usage: /tpa <player>");
                    return true;           
                }
                if (!(Main.economy.has(player, 200))) {
                    player.sendMessage("You don't have enough money.");
                    return true;
                }
                Player target = Bukkit.getPlayer(args[0]);
                if (target != null) {
                    requests.put(target.getUniqueId(), player.getUniqueId());
                    player.sendMessage("You sent a teleport request to " + target.getName() + ".");
                    target.sendMessage(player.getName() + " sent a teleport request to you.");   
                    return true;
                }
                player.sendMessage("The player is offline.");                                       
            }
            if (command.getName().equalsIgnoreCase("tpaccept")) {
                if (requests.get(player.getUniqueId()) != null) {
                    player.sendMessage("You accepted the teleport request.");
                    Bukkit.getPlayer(requests.get(player.getUniqueId())).sendMessage("It works!");
                    requests.remove(player.getUniqueId());
                    return true;
                }
                player.sendMessage("There's no request to accept.");
            }
            if (command.getName().equalsIgnoreCase("tpdeny")) {
                if (requests.get(player.getUniqueId()) != null) {
                    player.sendMessage("You denied the teleport request.");
                    Bukkit.getPlayer(requests.get(player.getUniqueId())).sendMessage("It works!");
                    requests.remove(player.getUniqueId());
                    return true;
                }
                player.sendMessage("There's no request to deny.");
            }       
            return false;
        }   
    }
    
    But there's still the problem remaining, that it says everytime that there's no request to accept/to deny. I already used something like if (requests.get(player.getUniqueId()) != null) { //do something } in other commands and it worked great.
     
  13. Offline

    KarimAKL

    @spatziempire Have you tried 'if (requests.containsKey(player.getUniqueId()))' instead of 'if (requests.get(player.getUniqueId()) != null)'? I don't know if that would change anything but it's worth a try.
     
  14. Offline

    spatziempire

    Yes, already tried. The issue might have something to do with adding the player to hashmap..?
     
  15. Offline

    KarimAKL

    @spatziempire Maybe, try printing message to the console in the "/tpa" section.
    Something like this:
    Code:Java
    1. if (command.getName().equalsIgnoreCase("tpa")) {
    2. System.out.println("Test 1");
    3. if (!player.hasPermission("tpa.sent")) {
    4. player.sendMessage("You aren't allowed to do this.");
    5. return true;
    6. }
    7. System.out.println("Test 2");
    8. if (args.length != 1) {
    9. player.sendMessage("Usage: /tpa <player>");
    10. return true;
    11. }
    12. System.out.println("Test 3");
    13. if (!(Main.economy.has(player, 200))) {
    14. player.sendMessage("You don't have enough money.");
    15. return true;
    16. }
    17. System.out.println("Test 4");
    18. Player target = Bukkit.getPlayer(args[0]);
    19. if (target != null) {
    20. requests.put(target.getUniqueId(), player.getUniqueId());
    21. player.sendMessage("You sent a teleport request to " + target.getName() + ".");
    22. target.sendMessage(player.getName() + " sent a teleport request to you.");
    23. return true;
    24. }
    25. System.out.println("Test 5");
    26. player.sendMessage("The player is offline.");
    27. }

    Then check if it stops anywhere.
     
  16. Offline

    spatziempire

    It stops nowhere. It happens exactly as it should.
     
    Last edited: Jan 20, 2019
  17. maybe try printing the content of the hashmap when doing /tpaccept
     
    KarimAKL likes this.
  18. Offline

    spatziempire

    Like this? System.out.println(requests.get(player.getUniqueId()));
    It just prints null, so there must be something wrong when I'm adding the player to the HashMap, but what?
     
  19. Offline

    KarimAKL

    @spatziempire Are you creating a new map somewhere? Also to print the contents of a map you can do something like this:
    Code:Java
    1. for (Entry<UUID, UUID> entry : map.entrySet()) {
    2. System.out.println("Key: "+entry.getKey()+" Value: "+entry.getValue());
    3. }
     
  20. Offline

    spatziempire

    After the tpa command it prints the right uuids, so that seems to be working. When I try to print the same after the tpaccept command, nothing gets printed. I'm using another private hashmap in another class in another command.
     
  21. Offline

    KarimAKL

    @spatziempire If it's in different classes then make the map public.
     
  22. Offline

    spatziempire

    Hey! I made the hashmap static and it works!
    Here's the final code:
    Code:
    package de.patrick.colonia.commands;
    
    import java.util.HashMap;
    import java.util.UUID;
    
    import org.bukkit.Bukkit;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Player;
    
    import de.patrick.colonia.main.Main;
    import de.patrick.colonia.other.Vault;
    
    public class TpaCommand implements CommandExecutor {
      
        private static HashMap<UUID, UUID> requests = new HashMap<>();
    
        public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
            if(!(sender instanceof Player)) {
                sender.sendMessage(Main.prefix + "§cYou must be a player.");
                return true;          
            }  
            Player player = (Player) sender;
            if (command.getName().equalsIgnoreCase("tpa")) {
                if (!player.hasPermission("tpa.sent")) {
                    player.sendMessage(Main.prefix + "§cYou aren't allowed to do this.");
                    return true;
                }
                if (args.length != 1) {
                    player.sendMessage(Main.prefix + "§7Usage: /tpa <player>");
                    return true;          
                }
                if (!(Vault.economy.has(player, 200))) {
                    player.sendMessage(Main.prefix + "§cYou don't have enough money.");
                    return true;
                }
                Player target = Bukkit.getPlayer(args[0]);
                if (target != null) {
                    requests.put(target.getUniqueId(), player.getUniqueId());
                    player.sendMessage(Main.prefix + "§7You sent a teleport request to " + target.getName() + ".");
                    target.sendMessage(Main.prefix + "§7" + player.getName() + " sent a teleport request to you.");  
                    return true;
                }
                player.sendMessage(Main.prefix + "§cThe player is offline.");                                      
            }
            if (command.getName().equalsIgnoreCase("tpaccept")) {
                if (requests.containsKey(player.getUniqueId())) {
                    player.sendMessage(Main.prefix + "§7You accepted the teleport request.");
                    Bukkit.getPlayer(requests.get(player.getUniqueId())).sendMessage(Main.prefix + "§7" +  player.getName() + " accepted the teleport request.");
                    Bukkit.getPlayer(requests.get(player.getUniqueId())).teleport(player);
                    requests.remove(player.getUniqueId());
                    return true;
                }
                player.sendMessage(Main.prefix + "§cThere's no request to accept.");
            }
            if (command.getName().equalsIgnoreCase("tpdeny")) {
                if (requests.containsKey(player.getUniqueId())) {
                    player.sendMessage(Main.prefix + "§7You denied the teleport request.");
                    Bukkit.getPlayer(requests.get(player.getUniqueId())).sendMessage(Main.prefix + "§7" +  player.getName() + " denied the teleport request.");
                    requests.remove(player.getUniqueId());
                    return true;
                }
                player.sendMessage(Main.prefix + "§cThere's no request to deny.");
            }      
            return false;
        }  
    }
    
    @KarimAKL and @DerDonut Thank you so much! I really appreciate your help!
     
    Last edited: Jan 20, 2019
Thread Status:
Not open for further replies.

Share This Page