001    package org.bukkit.conversations;
002    
003    import org.bukkit.Server;
004    import org.bukkit.plugin.Plugin;
005    
006    /**
007     * An InactivityConversationCanceller will cancel a {@link Conversation} after
008     * a period of inactivity by the user.
009     */
010    public class InactivityConversationCanceller implements ConversationCanceller {
011        protected Plugin plugin;
012        protected int timeoutSeconds;
013        protected Conversation conversation;
014        private int taskId = -1;
015    
016        /**
017         * Creates an InactivityConversationCanceller.
018         *
019         * @param plugin The owning plugin.
020         * @param timeoutSeconds The number of seconds of inactivity to wait.
021         */
022        public InactivityConversationCanceller(Plugin plugin, int timeoutSeconds) {
023            this.plugin = plugin;
024            this.timeoutSeconds = timeoutSeconds;
025        }
026    
027        public void setConversation(Conversation conversation) {
028            this.conversation = conversation;
029            startTimer();
030        }
031    
032        public boolean cancelBasedOnInput(ConversationContext context, String input) {
033            // Reset the inactivity timer
034            stopTimer();
035            startTimer();
036            return false;
037        }
038    
039        public ConversationCanceller clone() {
040            return new InactivityConversationCanceller(plugin, timeoutSeconds);
041        }
042    
043        /**
044         * Starts an inactivity timer.
045         */
046        private void startTimer() {
047            taskId = plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
048                public void run() {
049                    if (conversation.getState() == Conversation.ConversationState.UNSTARTED) {
050                        startTimer();
051                    } else if (conversation.getState() ==  Conversation.ConversationState.STARTED) {
052                        cancelling(conversation);
053                        conversation.abandon(new ConversationAbandonedEvent(conversation, InactivityConversationCanceller.this));
054                    }
055                }
056            }, timeoutSeconds * 20);
057        }
058    
059        /**
060         * Stops the active inactivity timer.
061         */
062        private void stopTimer() {
063            if (taskId != -1) {
064                plugin.getServer().getScheduler().cancelTask(taskId);
065                taskId = -1;
066            }
067        }
068    
069        /**
070         * Subclasses of InactivityConversationCanceller can override this method
071         * to take additional actions when the inactivity timer abandons the
072         * conversation.
073         *
074         * @param conversation The conversation being abandoned.
075         */
076        protected void cancelling(Conversation conversation) {
077    
078        }
079    }