All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bukkit.conversations.Conversation Maven / Gradle / Ivy

package org.bukkit.conversations;

import org.bukkit.plugin.Plugin;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * The Conversation class is responsible for tracking the current state of a
 * conversation, displaying prompts to the user, and dispatching the user's
 * response to the appropriate place. Conversation objects are not typically
 * instantiated directly. Instead a {@link ConversationFactory} is used to
 * construct identical conversations on demand.
 * 

* Conversation flow consists of a directed graph of {@link Prompt} objects. * Each time a prompt gets input from the user, it must return the next prompt * in the graph. Since each Prompt chooses the next Prompt, complex * conversation trees can be implemented where the nature of the player's * response directs the flow of the conversation. *

* Each conversation has a {@link ConversationPrefix} that prepends all output * from the conversation to the player. The ConversationPrefix can be used to * display the plugin name or conversation status as the conversation evolves. *

* Each conversation has a timeout measured in the number of inactive seconds * to wait before abandoning the conversation. If the inactivity timeout is * reached, the conversation is abandoned and the user's incoming and outgoing * chat is returned to normal. *

* You should not construct a conversation manually. Instead, use the {@link * ConversationFactory} for access to all available options. */ public class Conversation { protected Prompt currentPrompt; protected ConversationContext context; protected boolean modal; protected boolean localEchoEnabled; protected ConversationPrefix prefix; protected List cancellers; protected List abandonedListeners; private final Prompt firstPrompt; private boolean abandoned; /** * Initializes a new Conversation. * * @param plugin The plugin that owns this conversation. * @param forWhom The entity for whom this conversation is mediating. * @param firstPrompt The first prompt in the conversation graph. */ public Conversation(Plugin plugin, Conversable forWhom, Prompt firstPrompt) { this(plugin, forWhom, firstPrompt, new HashMap()); } /** * Initializes a new Conversation. * * @param plugin The plugin that owns this conversation. * @param forWhom The entity for whom this conversation is mediating. * @param firstPrompt The first prompt in the conversation graph. * @param initialSessionData Any initial values to put in the conversation * context sessionData map. */ public Conversation(Plugin plugin, Conversable forWhom, Prompt firstPrompt, Map initialSessionData) { this.firstPrompt = firstPrompt; this.context = new ConversationContext(plugin, forWhom, initialSessionData); this.modal = true; this.localEchoEnabled = true; this.prefix = new NullConversationPrefix(); this.cancellers = new ArrayList(); this.abandonedListeners = new ArrayList(); } /** * Gets the entity for whom this conversation is mediating. * * @return The entity. */ public Conversable getForWhom() { return context.getForWhom(); } /** * Gets the modality of this conversation. If a conversation is modal, all * messages directed to the player are suppressed for the duration of the * conversation. * * @return The conversation modality. */ public boolean isModal() { return modal; } /** * Sets the modality of this conversation. If a conversation is modal, * all messages directed to the player are suppressed for the duration of * the conversation. * * @param modal The new conversation modality. */ void setModal(boolean modal) { this.modal = modal; } /** * Gets the status of local echo for this conversation. If local echo is * enabled, any text submitted to a conversation gets echoed back into the * submitter's chat window. * * @return The status of local echo. */ public boolean isLocalEchoEnabled() { return localEchoEnabled; } /** * Sets the status of local echo for this conversation. If local echo is * enabled, any text submitted to a conversation gets echoed back into the * submitter's chat window. * * @param localEchoEnabled The status of local echo. */ public void setLocalEchoEnabled(boolean localEchoEnabled) { this.localEchoEnabled = localEchoEnabled; } /** * Gets the {@link ConversationPrefix} that prepends all output from this * conversation. * * @return The ConversationPrefix in use. */ public ConversationPrefix getPrefix() { return prefix; } /** * Sets the {@link ConversationPrefix} that prepends all output from this * conversation. * * @param prefix The ConversationPrefix to use. */ void setPrefix(ConversationPrefix prefix) { this.prefix = prefix; } /** * Adds a {@link ConversationCanceller} to the cancellers collection. * * @param canceller The {@link ConversationCanceller} to add. */ void addConversationCanceller(ConversationCanceller canceller) { canceller.setConversation(this); this.cancellers.add(canceller); } /** * Gets the list of {@link ConversationCanceller}s * * @return The list. */ public List getCancellers() { return cancellers; } /** * Returns the Conversation's {@link ConversationContext}. * * @return The ConversationContext. */ public ConversationContext getContext() { return context; } /** * Displays the first prompt of this conversation and begins redirecting * the user's chat responses. */ public void begin() { if (currentPrompt == null) { abandoned = false; currentPrompt = firstPrompt; context.getForWhom().beginConversation(this); } } /** * Returns Returns the current state of the conversation. * * @return The current state of the conversation. */ public ConversationState getState() { if (currentPrompt != null) { return ConversationState.STARTED; } else if (abandoned) { return ConversationState.ABANDONED; } else { return ConversationState.UNSTARTED; } } /** * Passes player input into the current prompt. The next prompt (as * determined by the current prompt) is then displayed to the user. * * @param input The user's chat text. */ public void acceptInput(String input) { try { // Spigot if (currentPrompt != null) { // Echo the user's input if (localEchoEnabled) { context.getForWhom().sendRawMessage(prefix.getPrefix(context) + input); } // Test for conversation abandonment based on input for (ConversationCanceller canceller : cancellers) { if (canceller.cancelBasedOnInput(context, input)) { abandon(new ConversationAbandonedEvent(this, canceller)); return; } } // Not abandoned, output the next prompt currentPrompt = currentPrompt.acceptInput(context, input); outputNextPrompt(); } // Spigot Start } catch (Throwable t) { org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.SEVERE, "Error handling conversation prompt", t); } // Spigot End } /** * Adds a {@link ConversationAbandonedListener}. * * @param listener The listener to add. */ public synchronized void addConversationAbandonedListener(ConversationAbandonedListener listener) { abandonedListeners.add(listener); } /** * Removes a {@link ConversationAbandonedListener}. * * @param listener The listener to remove. */ public synchronized void removeConversationAbandonedListener(ConversationAbandonedListener listener) { abandonedListeners.remove(listener); } /** * Abandons and resets the current conversation. Restores the user's * normal chat behavior. */ public void abandon() { abandon(new ConversationAbandonedEvent(this, new ManuallyAbandonedConversationCanceller())); } /** * Abandons and resets the current conversation. Restores the user's * normal chat behavior. * * @param details Details about why the conversation was abandoned */ public synchronized void abandon(ConversationAbandonedEvent details) { if (!abandoned) { abandoned = true; currentPrompt = null; context.getForWhom().abandonConversation(this); for (ConversationAbandonedListener listener : abandonedListeners) { listener.conversationAbandoned(details); } } } /** * Displays the next user prompt and abandons the conversation if the next * prompt is null. */ public void outputNextPrompt() { if (currentPrompt == null) { abandon(new ConversationAbandonedEvent(this)); } else { context.getForWhom().sendRawMessage(prefix.getPrefix(context) + currentPrompt.getPromptText(context)); if (!currentPrompt.blocksForInput(context)) { currentPrompt = currentPrompt.acceptInput(context, null); outputNextPrompt(); } } } public enum ConversationState { UNSTARTED, STARTED, ABANDONED } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy