I have a weird problem. Since I'm new in coding, maybe I am dumb and I don't know how can I resolve this issue, so the issue is, I have 2 commands for my discord bot, permanent mute, and temporary mute. I want to make something like a placeholder to be used in config.yml since it will be more configurable, but when I use args[], I have a weird problem, here is it :
[JDA MainWS-ReadThread] ERROR net.dv8tion.jda.api.JDA - One of the EventListeners had an uncaught exception
java.lang.ArrayIndexOutOfBoundsException: Index 2 out of bounds for length 2
at me.trashlord.bot.events.TempMuteCommand.onGuildMessageReceived(TempMuteCommand.java:34)
at net.dv8tion.jda.api.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:396)
at net.dv8tion.jda.api.hooks.InterfacedEventManager.handle(InterfacedEventManager.java:96)
at net.dv8tion.jda.internal.hooks.EventManagerProxy.handleInternally(EventManagerProxy.java:82)
at net.dv8tion.jda.internal.hooks.EventManagerProxy.handle(EventManagerProxy.java:69)
at net.dv8tion.jda.internal.JDAImpl.handleEvent(JDAImpl.java:166)
at net.dv8tion.jda.internal.handle.MessageCreateHandler.handleInternally(MessageCreateHandler.java:97)
at net.dv8tion.jda.internal.handle.SocketHandler.handle(SocketHandler.java:36)
at net.dv8tion.jda.internal.requests.WebSocketClient.onDispatch(WebSocketClient.java:921)
at net.dv8tion.jda.internal.requests.WebSocketClient.onEvent(WebSocketClient.java:808)
at net.dv8tion.jda.internal.requests.WebSocketClient.handleEvent(WebSocketClient.java:786)
at net.dv8tion.jda.internal.requests.WebSocketClient.onBinaryMessage(WebSocketClient.java:959)
at com.neovisionaries.ws.client.ListenerManager.callOnBinaryMessage(ListenerManager.java:385)
at com.neovisionaries.ws.client.ReadingThread.callOnBinaryMessage(ReadingThread.java:276)
at com.neovisionaries.ws.client.ReadingThread.handleBinaryFrame(ReadingThread.java:996)
at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:755)
at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:108)
at com.neovisionaries.ws.client.ReadingThread.runMain(ReadingThread.java:64)
at com.neovisionaries.ws.client.WebSocketThread.run(WebSocketThread.java:45)
ALSO, here is my code at those lines :
String[] args = event.getMessage().getContentRaw().split("\\s+");
String MutedMessage = ConfigManager.INSTANCE.getSetting("MutedMessage")
.replaceAll("%muteduser", args[1]);
String UnMutedMessage = ConfigManager.INSTANCE.getSetting("UnMutedMessage")
.replaceAll("%unmuteduser", args[1]);
String TempMuted1 = ConfigManager.INSTANCE.getSetting("TempMutedMSG")
.replaceAll("%tempmutedusr", String.valueOf(event.getGuild().getMemberById(args[1].replaceAll("[^\\d]+", ""))))
.replaceAll("%tempmutetime", args[2]);
if (args[0].equalsIgnoreCase(Commands.prefix + "mute")) {
if (Objects.requireNonNull(event.getMember()).hasPermission(Permission.MESSAGE_MANAGE)) {
if (args.length == 2) {
Member member = event.getGuild().getMemberById(args[1].replaceAll("[^\\d]+", ""));
Role role = event.getGuild().getRoleById(MutedRole);
if (!Objects.requireNonNull(member).getRoles().contains(role)) {
// Mute user
event.getChannel().sendMessage(MutedMessage).queue();
event.getGuild().addRoleToMember(member, Objects.requireNonNull(role)).complete();
} else {
// Unmute user
event.getChannel().sendMessage(UnMutedMessage).queue();
event.getGuild().removeRoleFromMember(member, Objects.requireNonNull(role)).complete();
}
} else if (args.length == 3) {
Member member = event.getGuild().getMemberById(args[1].replaceAll("[^\\d]+", ""));
Role role = event.getGuild().getRoleById(MutedRole);
//event.getChannel().sendMessage(TempMuted1 + " " + args[1] + " " + TempMuted2 + " " + args[2] + " " + TempMuted3).queue();
event.getChannel().sendMessage(TempMuted1).queue();
event.getGuild().addRoleToMember(Objects.requireNonNull(member), Objects.requireNonNull(role))
.complete();
// Unmute after a few seconds
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
event.getChannel().sendMessage(TempUnMuted + " " + args[1] + ".").queue();
event.getGuild().removeRoleFromMember(member, role).complete();
}
},
TimeUnit.MINUTES.toMillis(Integer.parseInt(args[2]))
);
} else {
event.getChannel().sendMessage("Incorrect syntax. Use `~mute [user mention] [time {optional}]`")
.queue();
}
}
}
}
}
the problem is you are trying to get an element from args[2], which may the array only contains 2 elements (length 2) in the following code:
String TempMuted1 = ConfigManager.INSTANCE.getSetting("TempMutedMSG")
.replaceAll("%tempmutedusr", String.valueOf(event.getGuild().getMemberById(args[1].replaceAll("[^\\d]+", ""))))
.replaceAll("%tempmutetime", args[2]);
Note that in java arrays are zero-based and indexes start from 0 to length - 1.
You can take this code inside the if-condition:
else if (args.length == 3) {
String TempMuted1 = ConfigManager.INSTANCE.getSetting("TempMutedMSG")
.replaceAll("%tempmutedusr", String.valueOf(event.getGuild().getMemberById(args[1].replaceAll("[^\\d]+", ""))))
.replaceAll("%tempmutetime", args[2]);
// your code
}
Are you sure that this line from your code:
String TempMuted1 = ConfigManager.INSTANCE.getSetting("TempMutedMSG")
.replaceAll("%tempmutedusr", String.valueOf(event.getGuild().getMemberById(args[1].replaceAll("[^\\d]+", ""))))
.replaceAll("%tempmutetime", args[2]);
args[1] and args[2] is correct?
If the length is 2, Then args[2] is looking for the 3rd value and you might not have it...
Have a further look on how length and index works for arrays.
Related
I started Java for plugin codding in minecraft. now I'm trying to add role names as prefix and show it in chat.
ArrayList<String> userRoles = new ArrayList<String>();
if(player.hasPermission("chat.rank.admin")){
userRoles.add("[Admin]");
} if(player.hasPermission("chat.rank.vip")) {
userRoles.add("[VIP]");
}
event.setFormat(userRoles<>(1) + " " + player.getDisplayName() + "§7: " + msg);
// In this line, the expected output is "[Admin] user: msg" or both [Admin] [VIP] user: msg"
// But it gives "([Admin],[VIP]) user: msg"
// I'm sure it has a simple solution but as I said, I'm new here. thanks from now
It seems like you are trying to create a list which only stores one value.
You might want to try creating a function that get the rank name of the player outside of your PlayerChatEvent listener.
Here's a demo code:
public String getPlayerRankName(Player p){
if (p.hasPermission("chat.rank.admin"))
return "[Admin]";
else if (p.hasPermission("chat.rank.vip"))
return "[VIP]";
else
return "";
}
And in your PlayerChatEvent event listener, call this function in your chat line:
event.setFormat(getPlayerRankName(event.getPlayer()) + " " + player.getDisplayName() + "§7: " + msg);
So I'm making a kick/ban command for my server and the format is /kick name reason.
I got it all working but the reason can only be 1 word and anything over that excludes it, for example /kick BattleDash hello world would say BattleDash was kicked for hello.
Here's my code:
if (cmd.getName().equalsIgnoreCase("kick") && sender instanceof Player) {
Player player = (Player) sender;
int length = args.length;
if (length >= 2) {
boolean playerFound = false;
for (Player playerToKick : Bukkit.getServer().getOnlinePlayers()) {
if(playerToKick.getName().equalsIgnoreCase(args[0])) {
playerToKick.kickPlayer(ChatColor.RED + "Kicked by Administrator " + player.getName() + "\nReason: " + args[1]);
player.sendMessage(ChatColor.RED + "[BATTLEDASHLOGS]: Kicked player " + playerToKick.getName() + "succesfully!");
break;
}
}
if (playerFound == false) {
player.sendMessage(ChatColor.RED + "[BATTLEDASHLOGS]: " + args[0] + " was not found!");
}
} else player.sendMessage(ChatColor.RED + "[BATTLEDASHLOGS]: Incorrect arguments!" + ChatColor.RED + " /kick <PlayerName> <reason>");
return true;
}
(Also if you don't include a reason it gives internal error in chat and exception occured in console)
Your code is doing that due to the way it was programmed.
If we take a look at line that takes the argument:
playerToKick.kickPlayer(ChatColor.RED + "Kicked by Administrator " + player.getName() + "\nReason: " + args[1]);
We can see that you're only using args[1]. If we see a message as an array, the problem will be clear:
At position 0 (remember arrays start at 0): BattleDash
1: hello
2: world
When you take only args[1] to your message, only hello would be used! What we need to do instead, is use all the arguments. One way to do that is like this:
// First, transform your array into a list, so it's easier to understand
List<String> arguments = new ArrayList<>(args);
String playerName = arguments.get(0); // Get the player name
arguments.remove(0); // Remove the player name from our arguments list, we don't want it in the message
String message = String.join(" ", arguments); // Combine all the other arguments into a message
I'm trying to concatenate multiple objects inside a String variable called 'update' from a 'data' array within the method 'addClient' below:
public int addClient(Object[] data) {
try {
if (((String)data[0]).trim().isEmpty() || ((String)data[1]).trim().isEmpty() || ((int)data[2] < 0) || ((int)data[3] <= 0)) {
return StatusBar.ERR_INVALID_INPUT_CODE;
}
// the line below is causing the exception
String update = "INSERT INTO Client VALUES(" + ((String)data[0]).trim() + "," + ((String)data[1]).trim() + "," + ((Integer)data[3]).intValue() + "," + ((Integer)data[4]).intValue() + "," + ((Boolean)data[2]).booleanValue() + "," + ((String)data[5]).trim() + ")";
if (statement.executeUpdate(update) != 1) {
return StatusBar.ERR_INTERNAL_CODE;
}
}
catch (Exception e) {
e.printStackTrace();
return StatusBar.ERR_INTERNAL_CODE;
}
return StatusBar.ERR_SUCCESS_CODE;
}
However when the code above executes; an exception gets raised showing the following message:
java.lang.ClassCastException: java.lang.Integer cannot be cast to
java.lang.String
at Model.addClient(Model.java:43)
The 'data' object array is obtained through the call of the following method:
public Object[] getFields() {
return new Object[]{jTextFieldName.getText(), jTextFieldAddress.getText(),
jComboBoxType.getSelectedIndex(),
jSpinnerPhone.getValue(), jSpinnerFax.getValue(),
jTextFieldWebsite.getText()};
}
I did many searches and tried many methods including String.valueOf and Integer.toString, but without any success ..
Why I'm getting such behavior? How can it be solved?
You have a lot of options casting to String.
You chose the "simple" option that will work only if the object is really a String, and you just need to down-cast it (from Object) to String.
Try using one of the following options:
new String (your-Integer-here);
(your-Integer-here).toString();
(your-Integer-here) + "";
Let me know if it's working now :)
The elements of your data array can be of any reference type. Therefore you can't cast them to String without checking their type first.
Luckily, you can simply call their toString method instead.
Change
((String)data[0])
to
data[0].toString()
Instead of casting to String, you can call .toString() method on object, if that is your intention.
You are casting your object
i.e
if (((String)data[0]).trim().isEmpty() || ((String)data[1]).trim().isEmpty() || ((int)data[2] < 0) || ((int)data[3] <= 0)) to
if (data[0].toString().trim().isEmpty() || (data[1].toString().trim().isEmpty() || ((int)data[2] < 0) || ((int)data[3] <= 0))
Assuming data[3] and data[2] are of type Integers.
*PS:You can also log the values, to make sure what the values are.
You can try as below and let me know how it goes.
private static void concater(){
String[] data={"abc","def","23","45","true","xyz"};
String update = "INSERT INTO Client VALUES(" + ((String)data[0]).trim() + "," + ((String)data[1]).trim() + "," + Integer.parseInt(data[2]) + "," +
Integer.parseInt(data[3]) + "," + Boolean.parseBoolean(data[4]) + "," + ((String)data[5]).trim() + ")";
System.out.println(update); //INSERT INTO Client VALUES(abc,def,23,45,true,xyz)
}
I am currently trying to making a custom rules plugin (for minecraft) and I am trying to see if the player has something activated which I stored in the config file. It is in the listener class (which calls the config from the main). Here is my code:
#EventHandler
public void onEvent(AsyncPlayerChatEvent e) {
Player player = e.getPlayer();
if (config.getInt("EditingLine." + player.getName().toLowerCase()) == 1) {
int line = 0;
try {
line = Integer.parseInt(e.getMessage());
} catch (Exception b) {
player.sendMessage(ChatColor.RED + "Invalid Number.");
config.set("EditingLine." + player.getName().toLowerCase(), 0);
}
if (!(line == 0)) {
config.set("EditingLine." + player.getName().toLowerCase(), 0);
config.set("EditingText." + player.getName().toLowerCase(), 1);
e.setCancelled(true);
player.sendMessage(ChatColor.GRAY + "[" + ChatColor.GOLD + "Custom Rules" + ChatColor.GRAY + "]" + ChatColor.GREEN + " Enter the text you would now like on that line.");
}
}
}
The, config.getInt() function in the if then statement currently returns nothing. This may be happening because the config in the Listener Class is actually calling a custom made config, called 'playerdata.yml' and not the actual 'config.yml'. If there is any easier way to write this script, also let me know. I'm trying to make this as simple as I can.
The answer has been solved by merging my two configuration files together.
So I have a plugin im making where they get kicked with a message. I want that message to be in color that is set in the config.yml. heres my code:
}
if (l == 2) {
settings.getData().set("" + target.getName() + "", null);
settings.saveData();
target.kickPlayer(this.getConfig().getString("BanMessage"));
target.setBanned(true);
Bukkit.getServer().broadcastMessage(ChatColor.RED + target.getName() + " " + "Has been tempbanned for 25 Minutes by " + sender.getName() + "" + "(3/3)");
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
public void run() {
target.setBanned(false);
}
}, 1500 * 20);
return true;
}
Heres my config.yml:
BanMessage: You have been temp banned for 25 Minutes
You could use ChatColor.translateAlternateColorCodes():
String kickMessage = plugin.getConfig().getString("BanMessage");
kickMessage = ChatColor.translateAlternateColorCodes('&', kickMessage);
target.kickPlayer(kickMessage);
target.setBanned(true);
You can use these color codes in your configuration file.
So, putting in &6You have been banned for &4Spamming Will give you ChatColor.GOLD + "You have been banned for " + ChatColor.DARK_RED + " Spamming"
and if you would like to make it so they get that same message whenever they join if they're banned, you can use:
#EventHandler
public void playerJoin(PlayerJoinEvent e){
if(myMethodToCheckIfAPlayerIsTempBanned(e.getPlayer()){
String msg = myMethodToGetPlayersBanMessage(e.getPlayer());
e.getPlayer().kickPlayer(msg);
}
}
This should work:
String kickMessage = this.getConfig().getString("BanMessage");
kickMessage.replaceAll("(?i)&([a-f0-9])", "\u00A7$1");
target.kickPlayer(kickMessage);
target.setBanned(true);
Then, you should be able to use these color codes in your config.
ex.
BanMessage: &3You &0have been banned &1for &425 &3minutes
will display as
You have been temp banned for 25 Minutes