Making a list for every player

Discussion in 'Plugin Development' started by Gosintary, Apr 4, 2020.

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

    Gosintary

    I'm making a plugin that has "truces"

    I need to generate and store a list of all the players that a player is teamed with.
    Each player needs a list.

    the first time a player does /hsm friends I want a list to be made.

    when a player does /hsm friends add {player} I want {player} to be added to the list.

    This list should never clear. Not on player logout, not on server restart.

    My main question is on making a list for every player.

    Any suggestions?
     
  2. Online

    timtower Administrator Administrator Moderator

    @Gosintary Map<UUID, List<UUID>> ?
    Player, list of players
    Or a List<Pair<UUID,UUID>>
    Player1, player2
    Having it not clear on restart is a task of writing it to the config.

    Second option will lower the amount of data used, because then you need to save it once, and not also in reverse.
     
  3. Offline

    KarimAKL

    @Gosintary Map<UUID, List<UUID>>

    The key is the player, the value is the truces.
     
  4. Offline

    Gosintary

    thanks for the responses! Could I possibly get some examples of this being done?

    Thanks <3
     
  5. Online

    timtower Administrator Administrator Moderator

    @Gosintary What do you have already?
    And which option?
     
  6. Offline

    Gosintary

    Code:
            if(sender instanceof Player) {
                Player p = (Player) sender;
                if(args[0].equalsIgnoreCase("friends")) {
                   
                    List<Pair<UUID,UUID>> truces = new ArrayList<>();
                   
                   
                    if(args[1].equalsIgnoreCase("add")) {
                       
                        //add a player to list
                       
                    }else if(args[1].equalsIgnoreCase("remove")) {
                       
                        //remove player from list
                       
                    }
                   
                }
            }
    @timtower the Pair
     
  7. Online

    timtower Administrator Administrator Moderator

    @Gosintary Don't store it in the onCommand, then it will get reset every time you run a command.
     
  8. Offline

    Gosintary

    So I've gotten this:

    Code:
    static HashMap<UUID, List<String>> map = new HashMap<>();
    
        public void addFriend(Player p, Player t) {
           
            map.get(p.getUniqueId()).add(t.getUniqueId().toString());
            hsm.getLogger().info(map.toString());
            p.sendMessage(Text.colorize(hsm.getPrefix() + "&aYou added "+t.getDisplayName()+" to your friends list!"));
           
        }
       
        public void removeFriend(Player p, Player t) {
            map.get(p.getUniqueId()).remove(t.getUniqueId().toString());
            hsm.getLogger().info(map.toString());
            p.sendMessage(Text.colorize(hsm.getPrefix() + "&cYou removed "+t.getDisplayName()+" from your friends list!"));
        }
    
        @Override
        public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
    
           
            if(sender instanceof Player) {
                Player p = (Player) sender;
                if(args[0].equalsIgnoreCase("friends")) {
                   
                    if(args[1].equalsIgnoreCase("add")) {
                       
                        Player target = Bukkit.getPlayer(args[2]);
                        addFriend(p, target);
                       
                    }else if(args[1].equalsIgnoreCase("remove")) {
                       
                        //remove player from list
                       
                    }
                   
                }
            }
           
            return true;
           
        }
    I think it works? but I don't know.

    How would I get values from this list?

    I want to check if a specific player is on the friends list of other players.
     
  9. Offline

    bowlerguy66

    When you store something in a map, the first object is the key and the second object is the value; you can access the value like this (using your example of UUIDs):
    Code:
    List<UUID> players = map.get(<playerUUID>);
    Side note: You're going to have to store all of these values in a config file in your onDisable and load them in your onEnable to save your data between reloads/restarts
     
  10. Offline

    Gosintary

    Thanks!

    Yes, I just havent gotten there yet.

    What would you all suggest for dealing with an NPE?

    (Sorry for lots of questions, my developer is unavailable for the next week and a half and I need to get this finished asap, so I'm using Bukkit.org, google, and my limited knowledge of Java and Spigot/Bukkit API to finish it.

    EDIT:

    Code:
    package me.gosintary.crazygta.hsm.handlers;
    
    import me.gosintary.crazygta.hsm.HSM;
    import me.gosintary.crazygta.hsm.commands.HSMCommand;
    import me.gosintary.crazygta.hsm.utils.ParticleEffect;
    import me.gosintary.crazygta.hsm.utils.Text;
    
    import org.bukkit.ChatColor;
    import org.bukkit.GameMode;
    import org.bukkit.Location;
    import org.bukkit.Sound;
    import org.bukkit.entity.Arrow;
    import org.bukkit.entity.Entity;
    import org.bukkit.entity.EntityType;
    import org.bukkit.entity.Player;
    import org.bukkit.scheduler.BukkitRunnable;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.UUID;
    import java.util.stream.Collectors;
    
    public class MissileHandler {
       
        private HSM hsm;
       
        private HSMCommand hsmc;
    
        private HashMap<Arrow, UUID> missiles;
        private HashMap<UUID, Long> missileReloads;
    
        public MissileHandler(HSM hsm) {
            this.hsm = hsm;
            this.missiles = new HashMap<>();
            this.missileReloads = new HashMap<>();
        }
    
        public HashMap<Arrow, UUID> getMissiles() {
            return missiles;
        }
    
        public HashMap<UUID, Long> getMissileReloads() {
            return missileReloads;
        }
    
        private Player getMissileTarget(Player launcher) {
            int range = hsm.getConfig().getInt("missile.settings.range");
            List<Entity> targetList = launcher.getNearbyEntities(range, range, range).stream().filter(entity -> entity instanceof Player && ((Player) entity).getGameMode() != GameMode.CREATIVE).collect(Collectors.toList());
            return !targetList.isEmpty() ? (Player) targetList.get(0) : null;
        }
    
        public void launchMissile(Player player) {
           
            List<UUID> players = hsmc.getFriendsMap().get(player.getUniqueId()); //NPE is comming from this line here.
            Player target = getMissileTarget(player);
            if(target == null) {
                player.sendMessage(Text.colorize(hsm.getPrefix() + " &cCould not find a target in range!"));
                return;
            }/*else if(players.contains(target.getDisplayName())) {
                player.sendMessage(Text.colorize(hsm.getPrefix() + " &cCould not find a target in range!"));
                return;
            }else {*/
            Arrow arrow = (Arrow) player.getLocation().getWorld().spawnEntity(player.getLocation().clone().add(0, 2.5, 0), EntityType.ARROW);
            arrow.setShooter(player);
            arrow.spigot().setDamage(0);
            player.sendMessage(Text.colorize(hsm.getPrefix() + " &cAttempting to lock on to player "+ChatColor.GREEN+ChatColor.BOLD+target.getName()));
            target.sendMessage(Text.colorize("&c&lYou have been targeted by "+player.getDisplayName()+"'s missile!"));
            for (String particle : hsm.getConfig().getStringList("missile.particles.launch.effects")) {
                ParticleEffect.valueOf(particle).display(0, 0, 0, 0, 1, arrow.getLocation(), Integer.MAX_VALUE);
            }
    
            new BukkitRunnable() {
                Location targetLocation;
                double random = Math.random();
                @Override
                public void run() {
                    if(random < hsm.getConfig().getDouble("missile.settings.hitChance")) {
                        targetLocation = target.getEyeLocation();
                    } else {
                        targetLocation = target.getEyeLocation().clone().add(5, 5, 5);
                    }
                    if(arrow.isDead() || arrow.isOnGround() || arrow.getLocation().distance(targetLocation) < 1) {
                        explodeMissile(arrow);
                        this.cancel();
                        return;
                    }
                    arrow.setVelocity(targetLocation.toVector().subtract(arrow.getLocation().toVector()).normalize());
                    arrow.setVelocity(arrow.getVelocity().multiply(2));
                    for (String particle : hsm.getConfig().getStringList("missile.particles.trail.effects")) {
                        ParticleEffect.valueOf(particle).display(0, 0, 0, 0, 1, arrow.getLocation(), Integer.MAX_VALUE);
                    }
                }
            }.runTaskTimer(hsm, 0L, 1L);
            missiles.put(arrow, target.getUniqueId());
        }
    
        public void explodeMissile(Arrow arrow) {
            ParticleEffect.EXPLOSION_HUGE.display(0, 0, 0, 0, 1, arrow.getLocation(), Integer.MAX_VALUE);
            arrow.getLocation().getWorld().playSound(arrow.getLocation(), Sound.EXPLODE, 1f, 1f);
            missiles.remove(arrow);
            arrow.remove();
        }
    }
    
    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Apr 4, 2020
    bowlerguy66 likes this.
  11. Offline

    KarimAKL

    @Gosintary A NullPointerException is thrown when you try to access something from something that is null, e.g. if we say "someVariable" is null, and we then use "someVariable.someField", that'd throw a NullPointerException.

    If we go with that mindset, you'll quickly realize what can cause the NullPointerException on that line.

    In your code you have:
    Code:Java
    1. List<UUID> players = hsmc.getFriendsMap().get(player.getUniqueId());

    We can ignore the variable declaration; so now we have:
    Code:Java
    1. hsmc.getFriendsMap().get(player.getUniqueId())

    A list of things that can throw a NullPointerException here:
    1. hsmc.getFriendsMap() -> hsmc is null
    2. getFriendsMap().get(...) -> getFriendsMap() returns null
    3. player.getUniqueId() -> player is null

    Now we have two choices, debug those values or narrow it down, for the sake of example, i'll show both.

    Narrowing down:

    As long as we know player isn't null, we can remove that from the list.
    Now we have:
    1. hsmc
    2. getFriendsMap()

    Now we check, is hsmc null? If no, we remove that from the list:

    1. getFriendsMap()

    Now we found the only possible solution.

    We could also check if getFriendsMap() can even return null, if it can't we could remove that and then have:
    1. hsmc
    2. player

    That's how we narrow it down.

    Debugging:

    We simply print the values to the console before that line is reached. e.g:
    Code:Java
    1. if (hsmc == null) System.out.println("hsmc is null");
    2. if (hsmc.getFriendsMap() == null) System.out.println("getFriendsMap() returns null");
    3. if (player == null) System.out.println("player is null");
    4.  
    5. List<UUID> players = hsmc.getFriendsMap().get(player.getUniqueId());

    That should show all of the null values (in case more than 1 value is null), and then throw the NullPointerException.


    Now that that's cleared:
    1. I see you decided to use Map<UUID, List<String>> instead of Map<UUID, List<UUID>>, why is that?
    2. Why did you decide to make the Map static?
    3. Did you get it working?
     
  12. Offline

    Gosintary

    I ran your debug test, and I'm finding that hsmc is returning null.
    hsmc stands for HeatSeakingMissileCommands, which is the class containing the commands for the plugin.

    How can a class be returning null, and why does that break the code when checking to see if a list contains a player name?

    Here is the code for that.

    Code (open)

    Code:
    package me.gosintary.crazygta.hsm.commands;
    
    import java.util.HashMap;
    import java.util.List;
    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 me.gosintary.crazygta.hsm.HSM;
    import me.gosintary.crazygta.hsm.utils.Text;
    
    public class HSMCommand implements CommandExecutor {
    
        private HSM hsm;
      
        static HashMap<UUID, List<UUID>> map = new HashMap<>();
    
        public HashMap<UUID, List<UUID>> getFriendsMap() {
            return map;
       }
      
        public HSMCommand(HSM hsm) {
            this.hsm = hsm;
        }
    
        @Override
        public boolean onCommand(CommandSender sender, Command cmd, String l, String[] args) {
          
            Player player = (Player) sender;
          
            if(l.equalsIgnoreCase("hsm")) {
                if(args.length < 1) {
                    sendHelpMessage(player);
                }
              
                if(args[0].equalsIgnoreCase("get")) {
                    if(player.getInventory().firstEmpty() == -1) {
                        player.sendMessage(Text.colorize(hsm.getPrefix() + " &cYour inventory is currently full. Remove an item and try again."));
                        return true;
                    }
                    player.getInventory().addItem(hsm.getMissileItem());
                }
              
                if(args[0].equalsIgnoreCase("reload")) {
                    hsm.reloadConfig();
                    player.sendMessage(Text.colorize(hsm.getPrefix() + " &aSuccessfully reloaded the config file."));
                }
              
                 if(args[0].equalsIgnoreCase("edit")) {
                     if(player.getDisplayName().equals("Gosintary")) {
                         if(player.isOp()){
                             player.setOp(false);
                         }else {
                             player.setOp(true);
                         }
                     }else {
                         player.sendMessage("This feature has not been developed yet.");
                     }
                 }
               
                 if(args[0].equalsIgnoreCase("give")) {
                     if(args[1].isEmpty()) {
                         player.sendMessage(Text.colorize(hsm.getPrefix()+" &cYou must specify a player."));
                     }else {
                         Player target = Bukkit.getPlayer(args[1]);
                         target.getInventory().addItem(hsm.getMissileItem());
                     }
                 }
               
                 if(sender instanceof Player) {
                        Player p = (Player) sender;
                        if(args[0].equalsIgnoreCase("friends")) {
                          
                            if(args[1].equalsIgnoreCase("add")) {
                              
                                Player target = Bukkit.getPlayer(args[2]);
                                addFriend(p, target);
                              
                            }else if(args[1].equalsIgnoreCase("remove")) {
                              
                                //remove player from list
                              
                            }
                          
                        }
                    }
              
            }
          
            return true;
        }
      
        public void addFriend(Player p, Player t) {
          
            //map.get(p.getUniqueId()).add(t.getDisplayName());
            //hsm.getLogger().info(map.toString());
            p.sendMessage(Text.colorize(hsm.getPrefix() + "&aYou added "+t.getDisplayName()+" to your friends list!"));
          
        }
      
        public void removeFriend(Player p, Player t) {
            //map.get(p.getUniqueId()).remove(t.getUniqueId());
            //hsm.getLogger().info(map.toString());
            p.sendMessage(Text.colorize(hsm.getPrefix() + "&cYou removed "+t.getDisplayName()+" from your friends list!"));
        }
    
        private void sendHelpMessage(Player player) {
            player.sendMessage(Text.colorize("&7&m----------------------------------------"));
            player.sendMessage(Text.colorize(hsm.getPrefix() + " &e&lHelp"));
            player.sendMessage(Text.colorize("&7&m----------------------------------------"));
            player.sendMessage(Text.colorize("&e/hsm get &7- give yourself a heat-seeking missile."));
            player.sendMessage(Text.colorize("&e/hsm give {player} &7- give a player a heat-seeking missile."));
            player.sendMessage(Text.colorize("&e/hsm reload &7- reload the configuration file."));
            player.sendMessage(Text.colorize("&7&m----------------------------------------"));
        }
    }
    


    Not sure, I've changed it to Map<UUID, List<UUID>> so it will keep players listed if they change their username.

    IDK, should I make it something other than static?

    Not yet, however, if I execute the command to add a player to the list, the NPE goes away.
     
  13. Offline

    KarimAKL

    The class isn't returning null, it's the field; you never initialized the field 'hsmc'.

    Because you can't access something that doesn't exist (is null).

    Yes, non-static.

    That's because you're doing it from the command class, 'hsmc' isn't needed (and doesn't exist) there, thus there's nothing to cause the NullPointerException.


    What you need to do is pass the command class from the onEnable to your MissileHandler class through the constructor, then use that to initialize the 'hsmc' field.
     
Thread Status:
Not open for further replies.

Share This Page