Get keyboard input from player after event

Discussion in 'Plugin Development' started by asb1230, Jan 21, 2013.

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

    asb1230

    In the plugin I am writing, I have an eventhandler which handles a blockPlaceEvent. Once a player places a block, I need to get keyboard input from the player, i.e., the player will type "yes" or "no," but I can't figure out how to do this. It seems like I would have to have a command executor for it. Your advice is appreciated.
     
    GrandmaJam likes this.
  2. Offline

    JayzaSapphire

    PlayerChatEvent, check what they say, if "yes" or "no" then cancel it so no one can see their response and continue with what you need to do.
     
    asb1230 likes this.
  3. Offline

    caseif

    Keyboard input is client-side, and thus you can't listen for it. Sorry. :/

    //EDIT: Never mind, I didn't completely read the post. Yes, please listen to the person above me. :D
     
    asb1230 likes this.
  4. Offline

    danthonywalker

    You can use an AsyncPlayerChatEvent

    then

    event.getMessage().equals("yes");

    or alternatively no, if you wish. Your going to have to store the players username for a short amount of time so you can tell if it's the correct player doing the event.
     
  5. Offline

    asb1230

    So what's the difference between AsyncPlayerChatEvent and PlayerChatEvent?
     
    Drew1080 likes this.
  6. Offline

    JayzaSapphire

    Async is ment to work while the server is lagging because it's not on the main thread, i ment to say Async.
     
  7. Offline

    asb1230

    Awesome thanks. I know very little about that thread stuff, but it's enough to know what you mean. If anybody wants to go into detail explaining it or post a link to someone else who has, that would be cool.
     
  8. Offline

    danthonywalker

    Async is called when a player AND ONLY THE PLAYER issues that event, not the server. For example, if the server is broadcasting a message that's not Async, that's Sync, but it's when the player types something and it's only them then it calls Async. Always check to make sure it's Async though, event.isAsyncrounous (spelled it wrong, but you get it)
     
  9. Offline

    asb1230

    Firstly, wouldn't a blockPlaceEvent then be considered async since the player issues that event? Secondly, why do you have to check if the event is asynchronous if the event is AsyncPlayerChatEvent? Wouldn't that event have to be async?

    Oh and also, can I put the eventhandler for the chat in the middle of the block of code that is the evenhandler for the block place event?

    It turns out I can't. This is a far more interesting problem than I suspected.

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

    danthonywalker

    I don't know anymore than you do, but all I know is if you read up on the API Docs but an AsyncChatEvent is only called if the player is the one calling it, and only the player. You want to check if it's async incase something accidentally doesn't work. Most of the time it will, but in that very very unlikely chance something does go wrong, it will stop itself before it crashes the entire thread, but scratch that, it only calls if it's Async so I don't think you have to worry about it in this case.
     
  11. Offline

    asb1230

    So this is the general structure of the eventhandler:

    Code:
    onBlockPlaceEvent
        if (player placed block in specific area)
            ask the player a yes or no question
            if (player said yes)
                do something
            if (player said no)
                do something else
    

    How do I get their text response after the yes or no question? I can't put a chat event handler right smack in the middle of there.
     
  12. Offline

    JayzaSapphire

    asb1230

    You would have you store the player's name (not the player) inside a list of some sort, i prefer arraylist, and then create a new event (outside of your blockplaceevent) then check if the arraylist contains said players name and continue to do whatever you are planning on doing.
     
  13. Offline

    desht

    Also not mentioned in this thread: don't use PlayerChatEvent at all. It's there only for backwards compatibility, i.e. to allow older plugins which haven't updated yet to work. You'll get a deprecation warning both at compile-time and run-time if you try to use PlayerChatEvent in your plugin, because it has a significant performance impact.

    AsyncPlayerChatEvent is the only way to go for new plugins, and you need to be aware that your event handler is running in a different thread. So avoid any use of the Bukkit API from that event handler (if you need to make API calls, schedule a sync delayed task from your event handler).

    Also, the only async events in Bukkit (at this time) are AsyncPlayerChatEvent and AsyncPlayerPreLoginEvent, since those events are fired from separate threads in the CraftBukkit server. Every other event is fired from the main server thread.

    The appropriate data structure here would be a Set (HashSet), not a list. (Actually a HashMap may be best for this problem - see my post after this one).

    This is event-driven programming, so you're right that you can't stick one event handler inside another. You have to maintain some kind of state in your plugin, and this is how I'd suggest doing it:
    1. In your BlockPlaceEvent handler, do your specific-area check, and if so, message the player the yes-or-no question. You also record the player name at this point, and I'd suggest recording the time of the event too (System.currentTimeMillis() is useful here). To do this, maintain a HashMap<String,Long> which maps a player name to the time of the event.
    2. In your AsyncPlayerChatEvent, you can check if the sending player is in your HashMap, and if so, proceed to process the yes/no answer. Note thread-safety as I mentioned in my previous response. The reason for recording the time of the event is that you may want a timeout - i.e. if the player hasn't answered within a given time, assume a default answer. (This will avoid surprises if the player doesn't respond immediately, then answers "yes" or "no" to some unrelated question an hour later). Also remember to remove the player from the HashMap at this point.
    I'd suggest making a separate class for this - implement Listener, add the above two event handlers, and add the HashMap as a field of the class. Then you instantiate the class from your main plugin class when you register it as an event listener.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 31, 2016
Thread Status:
Not open for further replies.

Share This Page