Search code examples
javabukkit

Only the first value of a list is being tested


My problem is, that only the first value of a list inside my config.yml is "valid" for testing. Imagine a for loop, that tests a list with three values: "FirstString", "SecondString" and "ThirdString". If it finds a set String, like "SecondString", then do something. My for loop only tests the first value. So, in my example, it would never find "SecondString", even tough it is in the list. I hope you understand my problem, even tough I am kinda bad at explaining my problems.

Stym.java (main class):

import org.bukkit.plugin.java.JavaPlugin;

public class Stym extends JavaPlugin {

    @Override
    public void onEnable() {
        getConfig().options().copyDefaults(true);
        saveConfig();
        registerCommands();

    }

    public void registerCommands() {
        GroupCommand groupCommandClass = new GroupCommand(this);
        getCommand("GROUP").setExecutor(groupCommandClass);

    }

    public boolean isGroup(String groupName, String playerName) {
        if(groupName.equalsIgnoreCase("LEATHER")) {
            for(String ironPlayerName : getConfig().getStringList("groups.iron")) {
                if(!ironPlayerName.equals(playerName)) {
                    for(String diamondPlayerName : getConfig().getStringList("groups.diamond")) {
                        if(!diamondPlayerName.equals(playerName)) {
                            return true;

                        } else {
                            return false;

                        }

                    }

                } else {
                    return false;

                }

            }

        } else if(groupName.equalsIgnoreCase("IRON")) {
            for(String ironPlayerName : getConfig().getStringList("groups.iron")) {
                if(ironPlayerName.equals(playerName)) {
                    return true;

                } else {
                    return false;

                }

            }

        } else if(groupName.equalsIgnoreCase("DIAMOND")) {
            for(String diamondPlayerName : getConfig().getStringList("groups.diamond")) {
                if(diamondPlayerName.equals(playerName)) {
                    return true;

                } else {
                    return false;

                }

            }

        }

        return false;

    }

}

GroupCommand (executing class):

import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

public class GroupCommand implements CommandExecutor {

    Stym stym;

    GroupCommand(Stym stymClass) {
        stym = stymClass;

    }

    @Override
    public boolean onCommand(CommandSender sender, Command command,
            String label, String[] arguments) {
        if(arguments.length == 0) {
            if(sender instanceof Player) {
                if(!sender.isOp()) {
                    if(stym.isGroup("LEATHER", sender.getName())) {
                        sender.sendMessage("You are made out of leather!");
                        return true;

                    } else if(stym.isGroup("IRON", sender.getName())) {
                        sender.sendMessage("You are made out of iron!");
                        return true;

                    } else if(stym.isGroup("DIAMOND", sender.getName())) {
                        sender.sendMessage("You are made out of diamond!");
                        return true;

                    } else {
                        sender.sendMessage("You are a cyborg!");
                        return true;

                    }

                } else {
                    sender.sendMessage("You are an operator!");
                    return true;

                }

            } else {
                sender.sendMessage("You are a god!");
                return true;

            }

        } else if(arguments.length == 1) {
            if(stym.isGroup("LEATHER", arguments[0])) {
                sender.sendMessage(arguments[0] + " " + "is made out of leather!");
                return true;

            } else if(stym.isGroup("IRON", arguments[0])) {
                sender.sendMessage(arguments[0] + " " + "is made out of iron!");
                return true;

            } else if(stym.isGroup("DIAMOND", arguments[0])) {
                sender.sendMessage(arguments[0] + " " + "is made out of diamond!");
                return true;

            } else {
                sender.sendMessage(arguments[0] + " " + "is a cyborg!");
                return true;

            }

        } else {
            sender.sendMessage("Not supported yet!");
            return true;

        }

    }

}

plugin.yml:

name: Stym
main: Stym
version: 1.3.3.7
commands:
  group:
    description: Some fancy description
    usage: /group or /group <player_name>

config.yml:

groups:
  iron:
    - Player //Works well and will find
    - Another_Player // Won't find
  diamond:
    - Rich_Player //Works well and will find

Solution

  • I think this just comes down to some logic errors. As far as I can tell from your code, a player is in the "leather" group if and only if he is in neither the iron player nor the diamond player list. A player is in the "iron" group if the iron player list contains their name and in the "diamond" group if the diamond player list contains their name. All this requires are some checks to see if a given string can be found in a specific array/list.

    Your for loops check whether any of the Strings contained inside the arrays match playerName, which is going in the right direction, but your method returns false if any, even the first element it encounters does not equal playerName.

    If we have a list: {"Player", "Notch", "Jeb_"}, and we wanted to know whether the String "Notch" is contained in it, your code would return false because the first element it encounters ("Player") does not equal "Notch". This doesn't make sense for a piece of code that is supposed to look whether any of the elements in the list match a given value.

    If you were dealing with arrays you could write your own little general method that checks whether a given String is inside an array like so:

    public static boolean contains(String value, String[] array) {
        for (String element : array) { // For each element in array
            if (element.equals(value)) { // If we have found the matching element -> return true (we don't need to keep looking)
                return false;
            }
        }
        return false; // No match was found -> return false
    }
    

    In this code, if the current element we are traversing matches the string we are looking for, we can immediately return true, breaking out of the loop. The method only returns false if all elements have been traversed and we couldn't find a single match.

    Since you're dealing with List<String>s in the context of config files you can simply use the contains(String) method to check whether the list of player names contains a certain name, all the while shortening your code and making it easier to read.

    Your method could look something like this, which should work:

    public boolean isGroup(String groupName, String playerName) {
    
        List<String> ironPlayers = getConfig().getStringList("groups.iron"); // Get list of names in iron group
        List<String> diamondPlayers = getConfig().getStringList("groups.diamond"); // Get list of names in diamond group
    
        boolean isIron = ironPlayers.contains(playerName); // Boolean value whether playerName is in iron group
        boolean isDiamond = diamondPlayers.contains(playerName); // Boolean value whether playerName is in diamond group
    
        if (groupName.equalsIgnoreCase("LEATHER") && !isIron && !isDiamond) {
            // Return true for leather if the player name is not in the iron and diamond group
            return true; 
        } else if (groupName.equalsIgnoreCase("IRON") && isIron && !isDiamond) {
            // Return true for iron if the player name is in the iron group but not in the diamond group
            return true;
        } else if (groupName.equalsIgnoreCase("DIAMOND") && !isIron && isDiamond) {
            // Return true for diamond if the player name is in the diamond group but not in the iron group
            return true;
        }
        return false; // In any other case return false (player could be in both lists, or invalid groupName)
    }