Solved Plugin wont stop duplicated chat

Discussion in 'Plugin Development' started by BushGamingYT, Jan 23, 2019.

Thread Status:
Not open for further replies.
  1. I have attempted to make a plugin that sees if a player says something and says the exact thing again then stops the message and tells them they said that already but it gives me this error in console:
    Code:
    [18:12:16] [Async Chat Thread - #1/ERROR]: Could not pass event AsyncPlayerChatEvent to NoDupeChat v1.0
    org.bukkit.event.EventException: null
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:309) ~[Spigot.jar:git-Spigot-518206a-a5b9c7b]
        at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62) ~[Spigot.jar:git-Spigot-518206a-a5b9c7b]
        at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:500) [Spigot.jar:git-Spigot-518206a-a5b9c7b]
        at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:482) [Spigot.jar:git-Spigot-518206a-a5b9c7b]
        at net.minecraft.server.v1_13_R2.PlayerConnection.chat(PlayerConnection.java:1563) [Spigot.jar:git-Spigot-518206a-a5b9c7b]
        at net.minecraft.server.v1_13_R2.PlayerConnection.a(PlayerConnection.java:1501) [Spigot.jar:git-Spigot-518206a-a5b9c7b]
        at net.minecraft.server.v1_13_R2.PacketPlayInChat$1.run(PacketPlayInChat.java:39) [Spigot.jar:git-Spigot-518206a-a5b9c7b]
        at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_191]
        at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_191]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:1.8.0_191]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:1.8.0_191]
        at java.lang.Thread.run(Unknown Source) [?:1.8.0_191]
    Caused by: java.lang.Error: Unresolved compilation problem: 
        Incompatible operand types String and Boolean
    
        at com.nodupechat.plugin.Main.onChat(Main.java:24) ~[?:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_191]
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_191]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_191]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_191]
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:305) ~[Spigot.jar:git-Spigot-518206a-a5b9c7b]
        ... 11 more
    
    
    This is my code:
    Code:
    package com.nodupechat.plugin;
    
    import java.util.HashMap;
    
    import org.bukkit.ChatColor;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.AsyncPlayerChatEvent;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class Main extends JavaPlugin implements Listener {
       
        @Override
        public void onEnable() {
            org.bukkit.Bukkit.getPluginManager().registerEvents(this, this);
        }
       
        HashMap<String, Boolean> Chat = new HashMap<String, Boolean>();
        @EventHandler
        public void onChat(AsyncPlayerChatEvent e) {
            String Message = e.getMessage();
            if(Message == Chat.getOrDefault(Message, true)) {
                Player player = e.getPlayer();
                player.sendMessage(ChatColor.GOLD + "You cannot say the same message twice");
            }
            Chat.put(Message, true);
        }
    }
    
     
  2. Offline

    The_Spaceman

    first of all: When Message does not exist in the map the getOrDefault returns the boolean true, you check if Message (String) equals to true (boolean)

    and if some body else has said some thing it will be put in the map and somebody else can say it again...
    you should make a HashMap<UUID, ArrayList<String>> and put the uuid of the player in the map with the message.
    when you check if that player has said it you should use map.getOrDefault(player.getUUID(), new ArrayList<>()).contains(message);
    this way all the messages are saved under the players ownership and not global.
    to set the message
    ArrayList<String> list = map.getOrDefault(player.getUUID(), new ArrayList<>());
    list.add(message);
    map.put(player.getUUID(), list);

    if you have any questions about this please ask
     
  3. @The_Spaceman I got to "to set the message" and then I do not know what to do with everything under it
    What I have done so far:
    Code:
    package com.nodupechat.plugin;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.UUID;
    
    import org.bukkit.ChatColor;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.AsyncPlayerChatEvent;
    import org.bukkit.event.player.PlayerJoinEvent;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class Main extends JavaPlugin implements Listener {
     
        @Override
        public void onEnable() {
            org.bukkit.Bukkit.getPluginManager().registerEvents(this, this);
        }
     
        HashMap<UUID, ArrayList<String>> Chat = new HashMap<UUID, ArrayList<String>>();
        @EventHandler
        public void onChat(AsyncPlayerChatEvent e) {
            Player player = e.getPlayer();
            String Message = e.getMessage();
            if(e.getMessage() == Chat.getOrDefault(player.getUniqueId(), new ArrayList<>()).contains(Message)); {
                player.sendMessage(ChatColor.GOLD + "You cannot say the same message twice");
            }
            Chat.put(player.getUniqueId(), list);
        }
        @EventHandler
        public void onJoin(PlayerJoinEvent e) {
            Player player = e.getPlayer();
            Chat.put(player.getUniqueId(), list);
        }
    
    }
    
     
    Last edited: Jan 23, 2019
  4. Offline

    The_Spaceman

    you are still checking if a boolean equals a string, remove the 'e.getMessage() =='

    the Chat.getOrDefault checks if it was said
     
  5. @The_Spaceman ok so it is changed but what should i do with these:
     
  6. Offline

    The_Spaceman

    ArrayList<String> list = map.getOrDefault(player.getUUID(), new ArrayList<>());
    list.add(message);
    map.put(player.getUUID(), list);

    these 3 lines are a set. when the message hasn't been said use this

    if (Chat.getOrDefault(player.getUniqueId(), new ArrayList<>()).contains(Message)) {
    //code
    } else {
    ArrayList<String> list = map.getOrDefault(player.getUUID(), new ArrayList<>());
    list.add(message);
    map.put(player.getUUID(), list);
    }
     
  7. @The_Spaceman ok but now what should i do the the onplayerjoin event?
    Code:
    package com.nodupechat.plugin;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.UUID;
    
    import org.bukkit.ChatColor;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.AsyncPlayerChatEvent;
    import org.bukkit.event.player.PlayerJoinEvent;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class Main extends JavaPlugin implements Listener {
       
        @Override
        public void onEnable() {
            org.bukkit.Bukkit.getPluginManager().registerEvents(this, this);
        }
       
        HashMap<UUID, ArrayList<String>> Chat = new HashMap<UUID, ArrayList<String>>();
        @EventHandler
        public void onChat(AsyncPlayerChatEvent e) {
            Player player = e.getPlayer();
            String Message = e.getMessage();
            if(Chat.getOrDefault(player.getUniqueId(), new ArrayList<>()).contains(Message)) {
                player.sendMessage(ChatColor.GOLD + "You cannot say the same message twice");
            } else {
                ArrayList<String> list = Chat.getOrDefault(player.getUniqueId(), new ArrayList<>());
                list.add(Message);
                Chat.put(player.getUniqueId(), list);
            }
        }
        @EventHandler
        public void onJoin(PlayerJoinEvent e) {
            Player player = e.getPlayer();
            Chat.put(player.getUniqueId(), list);
        }
    
    }
    
     
  8. Offline

    The_Spaceman

    that is not needed, the getOrDefault catches if the player isn't in the map.
    when a key isn't in the map it will return null when using HashMap.get(), but when using HashMap.getOrDefault() when the key isn't in the map it will return the second argument, and in this case a new ArrayList
     
  9. @The_Spaceman thank you so much but 1 last question, how do you make it so it does not show their message if they said it twice or more
     
  10. Offline

    KarimAKL

  11. @KarimAKL or @The_Spaceman , i just realise that when a player writes something then says it again it stops them from saying it (which I want) but when they say something else then go back to what they originally said it does not let them say it
     
  12. Offline

    KarimAKL

    @BushGamingYT The map only needs one message per player. (the most recent message)
    Remove all other messages.
     
  13. @KarimAKL i have no clue how
     
    Last edited: Jan 23, 2019
  14. Offline

    KarimAKL

    @BushGamingYT Make the map <UUID, String> instead of <UUID, List<String>> and just set the string when the player types.
     
  15. @KarimAKL it does not seem to work and I got confused because of other bits of my code
    This is my code without what you just said:
    Code:
    package com.nodupechat.plugin;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.UUID;
    
    import org.bukkit.ChatColor;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.AsyncPlayerChatEvent;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class Main extends JavaPlugin implements Listener {
       
        @Override
        public void onEnable() {
            org.bukkit.Bukkit.getPluginManager().registerEvents(this, this);
        }
       
        HashMap<UUID, ArrayList<String>> Chat = new HashMap<UUID, ArrayList<String>>();
        @EventHandler
        public void onChat(AsyncPlayerChatEvent e) {
            Player player = e.getPlayer();
            String Message = e.getMessage();
            if(Chat.getOrDefault(player.getUniqueId(), new ArrayList<>()).contains(Message)) {
                e.setCancelled(true);
                player.sendMessage(ChatColor.GOLD + "You cannot say the same message twice");
            }
            ArrayList<String> list = Chat.getOrDefault(player.getUniqueId(), new ArrayList<>());
            list.remove(Message);
            list.add(Message);
            Chat.put(player.getUniqueId(), list);
        }
    }
    
    Do you know how to implement it into my code? or more/other ways to do it?
     
  16. Offline

    KarimAKL

    @BushGamingYT
    1. Change the 'Chat' map you have to HashMap<UUID, String> instead of HashMap<UUID, ArrayList<String>>
    2. In your 'onChat' event check if the map contains the player's uuid and if it does then cancel the event and send them a message, after that put the player's uuid with the message into the map.
     
  17. @KarimAKL I know how to do the fast 1 but not the second
    Updated code:
    Code:
    package com.nodupechat.plugin;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.UUID;
    
    import org.bukkit.ChatColor;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.AsyncPlayerChatEvent;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class Main extends JavaPlugin implements Listener {
       
        @Override
        public void onEnable() {
            org.bukkit.Bukkit.getPluginManager().registerEvents(this, this);
        }
       
        HashMap<UUID, String> Chat = new HashMap<UUID, String>();
        @EventHandler
        public void onChat(AsyncPlayerChatEvent e) {
            Player player = e.getPlayer();
            String Message = e.getMessage();
            if(Chat.getOrDefault(player.getUniqueId(), new ArrayList<>()).contains(Message)) {
                e.setCancelled(true);
                player.sendMessage(ChatColor.GOLD + "You cannot say the same message twice");
            }
            ArrayList<String> list = Chat.getOrDefault(player.getUniqueId(), new ArrayList<>());
            list.remove(Message);
            list.add(Message);
            Chat.put(player.getUniqueId(), list);
        }
    }
    
    
    also after I changed the hashmap other areas have been getting errors:
    [​IMG]
     
  18. Offline

    The_Spaceman

    you have edited the values of the map, so you have to edit the rest of your code to work with just a String in stead of an ArrayList

    line 27: Message.equals(Chat.get(player.getUniqueID()))
    the map does not contain an ArrayList anymore, now you can check it more directly
    line 31-34: Chat.put(player.getUniqueID(), Message)
    you don't have to put an ArrayList in the map, you can put the Message in the map with the UUID of the player
     
  19. @The_Spaceman Ok I will but why do I do 'Message = UUID?' ('Message.equals(Chat.get(player.getUniqueID()))')
    also, did I do it right?:
    Code:
    package com.nodupechat.plugin;
    
    import java.util.HashMap;
    import java.util.UUID;
    
    import org.bukkit.ChatColor;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.AsyncPlayerChatEvent;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class Main extends JavaPlugin implements Listener {
       
        @Override
        public void onEnable() {
            org.bukkit.Bukkit.getPluginManager().registerEvents(this, this);
        }
       
        HashMap<UUID, String> Chat = new HashMap<UUID, String>();
        @EventHandler
        public void onChat(AsyncPlayerChatEvent e) {
            Player player = e.getPlayer();
            String Message = e.getMessage();
            if(Message.equals(Chat.get(player.getUniqueId()))) {
                e.setCancelled(true);
                player.sendMessage(ChatColor.GOLD + "You cannot say the same message twice");
            }
            Chat.put(player.getUniqueId(), Message);
        }
    }
    
    
     
  20. Offline

    The_Spaceman

    you don't, you are getting the value from the map, if there is an value the .get() returns the last message (because you put the message in the map below) and if there isn't a value in the map it returns null. When you check if Message equals 2 things can happen:
    1: there is a value in the map -> it checks if Message equals the value from the map
    2: there isn't a value in the map -> the map returns null and you check if Message equals null, which is always false
     
  21. @The_Spaceman but is there not 2 values in the map (UUID and String) but in the code you put 'Message = UUID' when should it not be 'Message = Message' (second message is from Chat) or 'Message + player.UUID = Message + UUID'
     
  22. Offline

    The_Spaceman

    the UUID is the key, and the value is stored in the map with that key.

    When your put an object in a map you have to give a value. those two are linked.
    example:
    Map<UUID, String> map = new HashMap<>();
    map.put(player.getUUID(), "someString");

    map.get(player.getUUID());
    the map.get function will return "someString" because "someString" is stored under the UUID of that player

    Show Spoiler

    HashMap<Integer, String> map = new HashMap<>();
    map.put(1, "first string");
    map.put(2, "second string");
    map.put(1, "third string");

    visualization of the map:
    1 -> "first string"
    2 -> "second string"
    3 -> "third string"

    map.get(1) returns: "first string"
    map.get(2) returns: "second string"
    map.get(3) returns: "third string"


    so when you put the message in the map you will save it under the players uuid.
    when you use map.get(player.getUUID()) it will return the message you put in the map

    you get it now?
     
  23. @The_Spaceman yes but 1 last thing. What if you want to get the number by putting the string? will it work? like

    "First" -> 1

    map.get("First")
     
  24. Offline

    The_Spaceman

    yes, if you use a HashMap<String, Integer>

    and you even can create HashMap<?, HashMap<?,?> (a HashMap inside a HashMap), this can be useful... but you don't need this for now
     
  25. @The_Spaceman Ok thank you so much and the plugin works :D
     
  26. Offline

    The_Spaceman

    no problem, I once started on this site and I still use it, so its great that I can return the favor to other people
     
    BushGamingYT likes this.
  27. :D
     
Thread Status:
Not open for further replies.

Share This Page