Dr_Derek
Dr_Derek

Reputation: 55

Bukkit - Finding the Player's Name in the YAML

I have this plugin, and it basically players are able to create parties. The data for them are stored in a YAML File.

parties:
  mynewparteh:
    name: MyNewParteh
    leader: Dr_Derek
    balance: 0
    policies:
    - Default policy
    members:
    - Dr_Derek

I want to make it so when the party leader runs '/party delete', for an example, it would check what party they are a member of, first of all, and if they are leader.

The problem is, I do not know how to check if a player's name belongs to a list of members in a party without specifying the party itself?

                        int partyListLength = config.getConfigurationSection("parties").getKeys(false).size();
                        String[] partyList = config.getConfigurationSection("parties").getKeys(false).toArray(new String[partyListLength]);
                        for (int i = 0; i < partyListLength; i++)
                        {
                            if (config.getString("parties."+partyList[i]+".leader") == player.getName())
                            {
                                    player.sendMessage(ChatColor.GREEN + "Party deleted!");
                                    config.set("parties."+partyList[i], null);
                                    saveConfig();

                            }
                        }

In esscense, I've been suggested to use getConfigurationSection(), and I attempt to convert the set to an array, I then use a for loop to go through all of the data and check for the player's name. The problem is in the console, I get ArrayIndexOutOfBoundsException, so obviously there is an issue converting the set to an array, and I need an array in order to work with indexes. How can I get around this?

From console:

[20:50:03] [Server thread/ERROR]: null
org.bukkit.command.CommandException: Unhandled exception executing command 'party' in plugin Parties v1.0
    at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46) ~[craftbukkit.jar:git-Spigot-b8f6402-a646500]
    at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:181) ~[craftbukkit.jar:git-Spigot-b8f6402-a646500]
    at org.bukkit.craftbukkit.v1_8_R1.CraftServer.dispatchCommand(CraftServer.java:642) ~[craftbukkit.jar:git-Spigot-b8f6402-a646500]
    at net.minecraft.server.v1_8_R1.PlayerConnection.handleCommand(PlayerConnection.java:1105) [craftbukkit.jar:git-Spigot-b8f6402-a646500]
    at net.minecraft.server.v1_8_R1.PlayerConnection.a(PlayerConnection.java:940) [craftbukkit.jar:git-Spigot-b8f6402-a646500]
    at net.minecraft.server.v1_8_R1.PacketPlayInChat.a(PacketPlayInChat.java:26) [craftbukkit.jar:git-Spigot-b8f6402-a646500]
    at net.minecraft.server.v1_8_R1.PacketPlayInChat.a(PacketPlayInChat.java:53) [craftbukkit.jar:git-Spigot-b8f6402-a646500]
    at net.minecraft.server.v1_8_R1.PacketHandleTask.run(SourceFile:13) [craftbukkit.jar:git-Spigot-b8f6402-a646500]
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_40]
    at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_40]
    at net.minecraft.server.v1_8_R1.MinecraftServer.z(MinecraftServer.java:683) [craftbukkit.jar:git-Spigot-b8f6402-a646500]
    at net.minecraft.server.v1_8_R1.DedicatedServer.z(DedicatedServer.java:316) [craftbukkit.jar:git-Spigot-b8f6402-a646500]
    at net.minecraft.server.v1_8_R1.MinecraftServer.y(MinecraftServer.java:623) [craftbukkit.jar:git-Spigot-b8f6402-a646500]
    at net.minecraft.server.v1_8_R1.MinecraftServer.run(MinecraftServer.java:526) [craftbukkit.jar:git-Spigot-b8f6402-a646500]
    at java.lang.Thread.run(Unknown Source) [?:1.8.0_40]
Caused by: java.lang.ArrayIndexOutOfBoundsException: 1
    at me.penghst.Parties.Main.onCommand(Main.java:212) ~[?:?]
    at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44)

Upvotes: 0

Views: 1254

Answers (2)

Nick Fulton
Nick Fulton

Reputation: 333

Another place where you might get this error, is if you send a command from the console, that assumes, without checking, that you are a player. For example:

public boolean onCommand(CommandSender sender, Command command, String commandLabel, String[] args) {
    String cmd = command.getName();
    if (cmd.equalsIgnoreCase("hello") {
        Player p = (Player) sender;
        p.sendMessage("Hi!");
    }
    return true;
}

This will throw an CommandException if you attempt the command "hello" from the console. You didn't show the rest of your code, but I've had problems with that in the past, so it could be what's wrong.

Upvotes: 0

Pokechu22
Pokechu22

Reputation: 5046

One of the main issues in your code is that you're attempting to compare the leader's name using == - that doesn't do what you might expect in java. Instead, you should use .equals.

Additionally, you don't need an array to search through this (although an array would work, it's not needed). Instead, you can use the for each loop, which is written as for (type name : collection). This works directly off of the Set returned by getKeys.

With both of these changes, you could do this to simply delete a party.

for (String partyName : config.getConfigurationSection("parties").getKeys(false))
{
    if (config.getString("parties." + partyName + ".leader").equals(player.getName()))
    {
        player.sendMessage(ChatColor.GREEN + "Party " + partyName + " deleted!");
        config.set("parties." + partyName, null);
        saveConfig();
    }
}

However, for a more general case, here's a method that gets the name of a party owned by a player:

/**
 * Gets the name of the party owned by the given player.
 * 
 * @returns The name of the party owned by the given player, or null if they don't own a party.
 */
public String getPartyOwnedByPlayer(Player player) {
    // If you've got a Configuration as a local variable, you can remove this line.
    Configuration config = getConfig();

    // Iterate through all of the party names using a for each loop.
    for (String partyName : config.getConfigurationSection("parties").getKeys(false))
    {
        // Check if the owner of the given party is the player.
        if (config.getString("parties." + partyName + ".leader").equals(player.getName()))
        {
            // Return the name of that party.
            return partyName;
        }
    }

    // The player didn't own a party.
    return null;
}

And to use that method to delete a party, you'd do something like this:

String ownedPartyName = getPartyOwnedByPlayer(player);
if (ownedPartyName != null) {
    player.sendMessage(ChatColor.GREEN + "Party " + partyName + " deleted!");
    config.set("parties." + ownedPartyName, null);
} else {
    player.sendMessage(ChatColor.RED + "You don't own a party!");
}

Note that I'm assuming that a player can only own one party. If you expect players to own more than one party, you'll need to change your code slightly (this might also apply if you can have a player be a member of multiple parties and want to loop up what party they are in).

/**
 * Gets the names of all parties owned by the given player.
 * 
 * @returns A list of names of the parties owned by the given player, or an empty if they don't own any parties.
 */
public List<String> getPartiesOwnedByPlayer(Player player) {
    // If you've got a Configuration as a local variable, you can remove this line.
    Configuration config = getConfig();

    // Create a new list - make sure you have imported java.util.List and java.util.ArrayList
    List<String> ownedParties = new ArrayList<String>();

    // Iterate through all of the party names using a for each loop.
    for (String partyName : config.getConfigurationSection("parties").getKeys(false))
    {
        // Check if the owner of the given party is the player.
        if (config.getString("parties." + partyName + ".leader").equals(player.getName()))
        {
            // Add that party name to the list.
            ownedParties.add(partyName);
        }
    }

    // Return the list of parties owned by that player.
    return ownedParties;
}

This returns a List that can be (among other things) iterated through with a for each loop.

To use the modified version of that method to delete all parties owned by a player, you'd do something like this:

List<String> ownedParties = getPartiesOwnedByPlayer(player);
if (ownedParties.isEmpty()) {
    player.sendMessage(ChatColor.RED + "You don't own any parties!");
} else {
    for (String partyName : ownedParties) {
        player.sendMessage(ChatColor.GREEN + "Party " + partyName + " deleted!");
        config.set("parties." + ownedPartyName, null);
    }
}

As a final note, you should use the player's unique ID rather than their name when storing them if you want to deal with username changes. Simply changing the calls to player.getName() to player.getUniqueId().toString() (using getUniqueId()) will fix this (though if you're ever displaying the name to a player, you'll want to leave it as player.getName()).

Upvotes: 1

Related Questions