Solved [Chat] Player can only talk every 5 seconds.

Discussion in 'Plugin Development' started by historio, Jul 21, 2013.

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

    historio

    Can some one tell me what i'm doing wrong?

    This code is supposed to only allow a player to talk every 5 seconds:

    Code:java
    1. ArrayList<Player> cooldown = new ArrayList<Player>();
    2.  
    3. @EventHandler
    4. public void OnPlayerSpam(final AsyncPlayerChatEvent e) {
    5. final Player p = e.getPlayer();
    6. if (cooldown.contains(p)) {
    7. p.sendMessage(ChatColor.RED + "You can only talk every 5 seconds");
    8. e.setCancelled(true);
    9. }
    10.  
    11. cooldown.add(p);
    12. Bukkit.getServer().getScheduler()
    13. .scheduleSyncDelayedTask((Plugin) this, new Runnable() {
    14. public void run() {
    15. cooldown.remove(p);
    16. e.setCancelled(false);
    17. }
    18. }, 100);
    19. }


    But i get this error:

    Code:
    15:24:34 [SEVERE] Could not pass event AsyncPlayerChatEvent to AdvancedKitPvP v3
    .0
    org.bukkit.event.EventException
            at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.ja
    va:427)
            at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.jav
    a:62)
            at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.j
    ava:477)
            at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.j
    ava:459)
            at net.minecraft.server.v1_6_R2.PlayerConnection.chat(PlayerConnection.j
    ava:887)
            at net.minecraft.server.v1_6_R2.PlayerConnection.a(PlayerConnection.java
    :839)
            at net.minecraft.server.v1_6_R2.Packet3Chat.handle(SourceFile:49)
            at net.minecraft.server.v1_6_R2.NetworkManager.i(NetworkManager.java:213
    )
            at net.minecraft.server.v1_6_R2.NetworkManager.c(NetworkManager.java:351
    )
            at net.minecraft.server.v1_6_R2.NetworkReaderThread.run(SourceFile:94)
    Caused by: java.lang.ClassCastException: me.historio13.AdvancedKitPvp.ChatListen
    er cannot be cast to org.bukkit.plugin.Plugin
            at me.historio13.AdvancedKitPvp.ChatListener.OnPlayerSpam(ChatListener.j
    ava:56)
            at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
            at java.lang.reflect.Method.invoke(Unknown Source)
            at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.ja
    va:425)
            ... 9 more
    Maybe this is the problem?
    Code:
    Caused by: java.lang.ClassCastException: me.historio13.AdvancedKitPvp.ChatListen
    er cannot be cast to org.bukkit.plugin.Plugin
            at me.historio13.AdvancedKitPvp.ChatListener.OnPlayerSpam(ChatListener.j
    ava:56)
            at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
            at java.lang.reflect.Method.invoke(Unknown Source)
            at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.ja
    va:425)
    P.s if i have made any spelling mistakes/grammar mistakes in this post please tell me :p
     
  2. Offline

    mineart.at

    Code:java
    1.  
    2. public void onPlayerSpam(AsyncPlayerChatEvent event) {
    3.  
    4. Player player = event.getPlayer();
    5.  
    6. if (player.hasMetadata("AntiSpam")) {
    7. if(System.currentTimeMillis() - player.getMetadata("AntiSpam").get(0).asLong() < 5000) {
    8. event.setMessage(null);
    9. player.sendMessage("§cYou can only talk every 5 seconds");
    10. }
    11. player.removeMetadata("AntiSpam", plugin);
    12. }
    13. player.setMetadata("AntiSpam", new FixedMetadataValue(plugin, System.currentTimeMillis()));
    14. }
     
  3. Offline

    CakePvP

    You're trying to cast the runnable as a plugin, which is isn't.
    Code:
    .scheduleSyncDelayedTask((Plugin) this, new Runnable() {
    Should be something like this
    Code:
    .scheduleSyncDelayedTask(Bukkit.getPluginManager().getPlugin("YOUR-PLUGIN-NAME-HERE"), new Runnable() {
    There is another way to do this though.
     
  4. Offline

    historio

    CakePvP Thanks I'll test it now :D

    CakePvP Now i get this error?
    Code:
    15:58:36 [SEVERE] Could not pass event AsyncPlayerChatEvent to AdvancedKitPvP v3
    .0
    org.bukkit.event.EventException
            at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.ja
    va:427)
            at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.jav
    a:62)
            at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.j
    ava:477)
            at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.j
    ava:459)
            at net.minecraft.server.v1_6_R2.PlayerConnection.chat(PlayerConnection.j
    ava:887)
            at net.minecraft.server.v1_6_R2.PlayerConnection.a(PlayerConnection.java
    :839)
            at net.minecraft.server.v1_6_R2.Packet3Chat.handle(SourceFile:49)
            at net.minecraft.server.v1_6_R2.NetworkManager.i(NetworkManager.java:213
    )
            at net.minecraft.server.v1_6_R2.NetworkManager.c(NetworkManager.java:351
    )
            at net.minecraft.server.v1_6_R2.NetworkReaderThread.run(SourceFile:94)
    Caused by: java.lang.IllegalArgumentException: Plugin cannot be null
            at org.apache.commons.lang.Validate.notNull(Validate.java:203)
            at org.bukkit.craftbukkit.v1_6_R2.scheduler.CraftScheduler.validate(Craf
    tScheduler.java:391)
            at org.bukkit.craftbukkit.v1_6_R2.scheduler.CraftScheduler.runTaskTimer(
    CraftScheduler.java:120)
            at org.bukkit.craftbukkit.v1_6_R2.scheduler.CraftScheduler.scheduleSyncR
    epeatingTask(CraftScheduler.java:116)
            at org.bukkit.craftbukkit.v1_6_R2.scheduler.CraftScheduler.scheduleSyncD
    elayedTask(CraftScheduler.java:100)
            at me.historio13.AdvancedKitPvp.ChatListener.OnPlayerSpam(ChatListener.j
    ava:55)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
            at java.lang.reflect.Method.invoke(Unknown Source)
            at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.ja
    va:425)
            ... 9 more
    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 3, 2016
  5. Offline

    CakePvP

    Did you put the correct plugin name? As in the one it says in the plugin.yml with the correct caps?
     
  6. Offline

    Henzz

    historio
    Store the players name in your arraylist, it's bad practice if you store the player object since it contains a fair amount of data and can cause memory leaks if not handled correctly.
     
  7. Offline

    historio

    @Hennz How would i fix this ?
     
  8. Offline

    Henzz

    historio
    Show the current code you have now, the one that outputs that error.

    Also if you were referring to using string, change the paramaterized player object to string, then append onto your arraylist.
    cooldown.add(p.getName());
     
  9. Offline

    historio

    Henzz My current code:

    Code:java
    1. @EventHandler
    2. public void OnPlayerSpam(final AsyncPlayerChatEvent e) {
    3. final Player p = e.getPlayer();
    4. if (cooldown.contains(p)) {
    5. p.sendMessage(ChatColor.RED + "You can only talk every 5 seconds");
    6. e.setCancelled(true);
    7. }
    8. cooldown.add(p);
    9. Bukkit.getServer()
    10. .getScheduler()
    11. .scheduleSyncDelayedTask(
    12. Bukkit.getPluginManager().getPlugin("AdvancedKitPvp"),
    13. new Runnable() {
    14. public void run() {
    15. cooldown.remove(p);
    16. e.setCancelled(false);
    17. }
    18. }, 100);
    19. }


    Henzz

    Can you explain more about "Also if you were referring to using string, change the paramaterized player object to string, then append onto your arraylist." I'm still learning java and I'm not really sure how i would do any of that Sorry.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 3, 2016
  10. Offline

    psanker

    historio What he's saying is rather than having an ArrayList<Player> with stored references to Player instances, create an ArrayList<String> that stores the names of the players and just query Bukkit. E.g. :

    Code:java
    1. private final ArrayList<String> playerList = new ArrayList<String>();
    2.  
    3. public void aMethod()
    4. {
    5. for (String name : playerList) {
    6. Player p = Bukkit.getPlayer(name);
    7.  
    8. if (p != null) { // Useful check to see if the player is offline as well!
    9. /* Do stuff */
    10. }
    11. }
    12. }
     
  11. Offline

    historio

    psanker Like this ?

    Code:java
    1. private final ArrayList<String> playerList = new ArrayList<String>();
    2.  
    3. public void aMethod() {
    4. for (String name : playerList) {
    5. Player p = Bukkit.getPlayer(name);
    6.  
    7. if (p != null) {
    8. if(!p.isOnline());
    9. }
    10. }
    11. }
     
  12. Offline

    xTrollxDudex

    Henzz
    Ketchup man! No offense :D
    historio CakePvP
    You should probably be passing the plugin variable, not by getting a plugin from API because that's better in practice. It's a bit complex though.

    First what you will do is put this at the top of the listener class.
    PHP:
    Main plugin;
    public 
    Listener(Main plugin){
    this.plugin plugin;
    }
    Now what you want to do is change all occurrences of "Main" into the actual main class name. And change "Listener" to the listener class name, or what should be the name of the class the constructor(public Listener(...){...) is contained in.

    Now in the main class, you would register like so
    PHP:
    getServer(),getPluginManager().registerEvents(new Listener(this), this);
    Listener would be replaced by listener name of course
     
  13. Offline

    psanker

    historio not quite. The Bukkit.getPlayer() method will return null if the player is offline. That's what I meant. Checking if the player is NOT null will ensure that you have the most up-to-date Player instance for said player AND that he/she is online.
     
  14. Offline

    historio

    xTrollxDudex *OffTopic* I like this :D

    I wrote a plugin for you!
    PHP:
    public class SwagPlugin extends JavaPlugin{
    public void onEnable(){getServer().shutdown();}
    }
    Your welcome :D
     
  15. Offline

    NetherResident

    You are storing the player back into cooldown, even if their is already in there. That will make it so their in there multiple times, and removed once per 5 seconds. So if they chat 12 times in a row, it will take 60 seconds to be able to chat again, not 5.
     
  16. Offline

    historio

    xTrollxDudex Umm
    psanker Where does this go in my code/How to I link this to my code?


    P.S Sorry for not understanding D:

    @NetherResident I know what you mean but how would i do this?

    P.s I'll say this again i'm still learning java Sorry.

    Bump Can anyone else help me?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 3, 2016
  17. Offline

    njb_said

    A more efficient way is to use a hashmap with String and Long as its value and key
    Runnables can sometimes not be a good idea

    also CakePvP
    HAI! ;)
     
  18. Offline

    xTrollxDudex

    historio
    You have a number of things to fix, first off, pass a plugin variable instead of a getPlugin method.
    Second, you should make the runnable 100L not 100 or declare a seperate field with a long value.
    PHP:
    long delay 100;
    Now you can use "delay" in the place of 100.

    Also this is just a suggestion, you should use an else if or else but thats just me, you dont have to use it.
     
  19. Offline

    afistofirony

    historio This might work:

    Code:
    public class MyPlugin extends JavaPlugin {
        
        HashMap<String, Long> lastChatted = new HashMap<String, Long>();
     
         public long getLastChatted (Player p) {
             if (lastChatted.containsKey(p.getName())) {
                 return lastChatted.get(p.getName());
          } else {
                 lastChatted.put(p.getName(), 0L);
                 return lastChatted.get(p.getName());
            }
       }
     
        public void setLastChatted (Player p) {
            lastChatted.remove(p.getName());
            lastChatted.put(p.getName(), System.currentTimeMillis());
        }
     
        public void onEnable () {
            getServer().getPluginManager().registerEvents(new ChatListener(this), this);
        }
    }
    Code:
    public class ChatListener implements Listener {
        
        MyPlugin instance;
        
        public ChatListener (MyPlugin instance) {
            this.instance = instance;
        }
     
        @EventHandler
        public void onChat (AsyncPlayerChatEvent event) {
            long lastTalked = instance.getLastChatted(event.getPlayer());
            if (System.currentTimeMillis() - lastTalked < 5000) {
                sender.sendMessage(ChatColor.RED + "You may only talk once every five seconds.");
                event.setCancelled(true);
         } else {
                instance.setLastChatted(event.getPlayer());
             }
        }
    }
     
  20. Offline

    CakePvP


    That was the other way I was talking about, But as you can see, it took alot to type so I left it ^.^
     
    xTrollxDudex likes this.
  21. Offline

    njb_said

    May want to cast to long
     
  22. Offline

    historio

    Thanks guys this now works :D
     
  23. Offline

    skore87

    I'm a little surprised no one mentioned that the chat is ran on a separate thread and you would want thread safety outside of it =\...

    You could do this in a few ways but one is to initialize your arraylist with Collections.synchronizedList() or even use the deprecated Vector as it is synchronized. Though both are only so effective and have their drawbacks.

    You should look at synchronization in java. Here's a good explanation.
     
Thread Status:
Not open for further replies.

Share This Page