Supply external conversation hooks, part 42

This commit is contained in:
PikaMug 2021-07-23 03:37:26 -04:00
parent 7f9ca56c30
commit 3e481a8214
5 changed files with 315 additions and 145 deletions

View File

@ -19,8 +19,8 @@ import me.blackvein.quests.actions.Action;
import me.blackvein.quests.actions.ActionFactory; import me.blackvein.quests.actions.ActionFactory;
import me.blackvein.quests.conditions.Condition; import me.blackvein.quests.conditions.Condition;
import me.blackvein.quests.conditions.ConditionFactory; import me.blackvein.quests.conditions.ConditionFactory;
import me.blackvein.quests.convo.QuestsStringPrompt; import me.blackvein.quests.convo.misc.MiscStringPrompt;
import me.blackvein.quests.convo.npcs.NpcOfferQuestPrompt; import me.blackvein.quests.convo.misc.NpcOfferQuestPrompt;
import me.blackvein.quests.events.misc.MiscPostQuestAcceptEvent; import me.blackvein.quests.events.misc.MiscPostQuestAcceptEvent;
import me.blackvein.quests.exceptions.ActionFormatException; import me.blackvein.quests.exceptions.ActionFormatException;
import me.blackvein.quests.exceptions.ConditionFormatException; import me.blackvein.quests.exceptions.ConditionFormatException;
@ -215,7 +215,7 @@ public class Quests extends JavaPlugin implements ConversationAbandonedListener
this.npcConversationFactory = new ConversationFactory(this).withModality(false) this.npcConversationFactory = new ConversationFactory(this).withModality(false)
.withFirstPrompt(new NpcOfferQuestPrompt()).withTimeout(settings.getAcceptTimeout()) .withFirstPrompt(new NpcOfferQuestPrompt()).withTimeout(settings.getAcceptTimeout())
.withLocalEcho(false).addConversationAbandonedListener(this); .withLocalEcho(false).addConversationAbandonedListener(this);
// 10 - Register listeners // 10 - Register listeners
getServer().getPluginManager().registerEvents(blockListener, this); getServer().getPluginManager().registerEvents(blockListener, this);
getServer().getPluginManager().registerEvents(itemListener, this); getServer().getPluginManager().registerEvents(itemListener, this);
@ -563,7 +563,17 @@ public class Quests extends JavaPlugin implements ConversationAbandonedListener
} }
} }
public class QuestAcceptPrompt extends QuestsStringPrompt { public class QuestAcceptPrompt extends MiscStringPrompt {
private ConversationContext cc;
public QuestAcceptPrompt() {
super(null);
}
public QuestAcceptPrompt(final ConversationContext context) {
super(context);
}
private final int size = 2; private final int size = 2;
@ -603,11 +613,13 @@ public class Quests extends JavaPlugin implements ConversationAbandonedListener
@Override @Override
public @Nonnull String getPromptText(final ConversationContext context) { public @Nonnull String getPromptText(final ConversationContext context) {
this.cc = context;
final MiscPostQuestAcceptEvent event = new MiscPostQuestAcceptEvent(context, this); final MiscPostQuestAcceptEvent event = new MiscPostQuestAcceptEvent(context, this);
getServer().getPluginManager().callEvent(event); getServer().getPluginManager().callEvent(event);
return ChatColor.YELLOW + getQueryText(context) + " " + ChatColor.GREEN return ChatColor.YELLOW + getQueryText(context) + " " + ChatColor.GREEN
+ getSelectionText(context, 1) + " / " + getSelectionText(context, 2); + getSelectionText(context, 1) + ChatColor.RESET + " / " + getSelectionText(context, 2);
} }
@Override @Override
@ -650,7 +662,7 @@ public class Quests extends JavaPlugin implements ConversationAbandonedListener
.replace("<yes>", Lang.get(player, "yesWord")) .replace("<yes>", Lang.get(player, "yesWord"))
.replace("<no>", Lang.get(player, "noWord")); .replace("<no>", Lang.get(player, "noWord"));
Lang.send(player, ChatColor.RED + msg); Lang.send(player, ChatColor.RED + msg);
return new QuestAcceptPrompt(); return new QuestAcceptPrompt(context);
} }
} }
} }

View File

@ -0,0 +1,44 @@
/*******************************************************************************************************
* Copyright (c) 2014 PikaMug and contributors. All rights reserved.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************************************/
package me.blackvein.quests.convo.misc;
import me.blackvein.quests.convo.QuestsNumericPrompt;
import org.bukkit.ChatColor;
import org.bukkit.conversations.ConversationContext;
public abstract class MiscNumericPrompt extends QuestsNumericPrompt {
private final ConversationContext context;
public MiscNumericPrompt(final ConversationContext context) {
this.context = context;
}
@Override
public String getName() {
return getClass().getSimpleName();
}
public ConversationContext getConversationContext() {
return context;
}
public abstract int getSize();
public abstract String getTitle(ConversationContext context);
public abstract ChatColor getNumberColor(ConversationContext context, int number);
public abstract String getSelectionText(ConversationContext context, int number);
public abstract String getAdditionalText(ConversationContext context, int number);
}

View File

@ -0,0 +1,39 @@
/*******************************************************************************************************
* Copyright (c) 2014 PikaMug and contributors. All rights reserved.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************************************/
package me.blackvein.quests.convo.misc;
import me.blackvein.quests.convo.QuestsStringPrompt;
import org.bukkit.conversations.ConversationContext;
public abstract class MiscStringPrompt extends QuestsStringPrompt {
private final ConversationContext context;
public MiscStringPrompt(final ConversationContext context) {
this.context = context;
}
@Override
public String getName() {
return getClass().getSimpleName();
}
public ConversationContext getConversationContext() {
return context;
}
public abstract int getSize();
public abstract String getTitle(ConversationContext context);
public abstract String getQueryText(ConversationContext context);
}

View File

@ -1,137 +1,212 @@
/******************************************************************************************************* /*******************************************************************************************************
* Copyright (c) 2014 PikaMug and contributors. All rights reserved. * Copyright (c) 2014 PikaMug and contributors. All rights reserved.
* *
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************************************/ *******************************************************************************************************/
package me.blackvein.quests.convo.npcs; package me.blackvein.quests.convo.misc;
import me.blackvein.quests.Quest; import me.blackvein.quests.Quest;
import me.blackvein.quests.Quester; import me.blackvein.quests.Quester;
import me.blackvein.quests.Quests; import me.blackvein.quests.Quests;
import me.blackvein.quests.convo.QuestsStringPrompt; import me.blackvein.quests.events.misc.MiscPostNpcOfferQuestEvent;
import me.blackvein.quests.events.misc.MiscPostNpcOfferQuestEvent; import me.blackvein.quests.util.Lang;
import me.blackvein.quests.util.Lang; import org.bukkit.ChatColor;
import org.bukkit.ChatColor; import org.bukkit.conversations.ConversationContext;
import org.bukkit.conversations.ConversationContext; import org.bukkit.conversations.Prompt;
import org.bukkit.conversations.Prompt; import org.bukkit.entity.Player;
import org.bukkit.entity.Player;
import javax.annotation.Nonnull;
import javax.annotation.Nonnull; import java.text.MessageFormat;
import java.text.MessageFormat; import java.util.LinkedList;
import java.util.LinkedList;
public class NpcOfferQuestPrompt extends MiscStringPrompt {
public class NpcOfferQuestPrompt extends QuestsStringPrompt {
private ConversationContext cc;
public String getQueryText(final ConversationContext context) {
return Lang.get("questNPCListTitle"); public NpcOfferQuestPrompt() {
} super(null);
}
@SuppressWarnings("unchecked")
@Override public NpcOfferQuestPrompt(ConversationContext context) {
public @Nonnull String getPromptText(final ConversationContext context) { super(context);
final Quests plugin = (Quests)context.getPlugin(); }
final LinkedList<Quest> quests = (LinkedList<Quest>) context.getSessionData("npcQuests");
final String npc = (String) context.getSessionData("npc"); @Override
if (plugin == null || quests == null || npc == null) { public ConversationContext getConversationContext() {
return ChatColor.RED + "Bad offer"; return cc;
} }
final MiscPostNpcOfferQuestEvent event = new MiscPostNpcOfferQuestEvent(context, this); private int size = 3;
plugin.getServer().getPluginManager().callEvent(event);
@Override
final Quester quester = plugin.getQuester(((Player) context.getForWhom()).getUniqueId()); public int getSize() {
final String text = getQueryText(context).replace("<npc>", npc); return size;
String menu = text + "\n"; }
for (int i = 1; i <= quests.size(); i++) {
final Quest quest = quests.get(i - 1); @Override
if (quester.getCompletedQuests().contains(quest)) { public String getTitle(final ConversationContext context) {
menu += ChatColor.DARK_GREEN + "" + ChatColor.BOLD + "" + i + ". " + ChatColor.RESET + "" final String npc = (String) context.getSessionData("npc");
+ ChatColor.GREEN + "" + ChatColor.ITALIC + quest.getName() + ChatColor.RESET + "" return Lang.get("questNPCListTitle").replace("<npc>", npc);
+ ChatColor.GREEN + " " + Lang.get("redoCompleted") + "\n"; }
} else {
menu += ChatColor.GOLD + "" + ChatColor.BOLD + "" + i + ". " + ChatColor.RESET + "" + ChatColor.YELLOW @SuppressWarnings("unchecked")
+ "" + ChatColor.ITALIC + quest.getName() + "\n"; public ChatColor getNumberColor(final ConversationContext context, final int number) {
} final Quests plugin = (Quests)context.getPlugin();
} final LinkedList<Quest> quests = (LinkedList<Quest>) context.getSessionData("npcQuests");
menu += ChatColor.GOLD + "" + ChatColor.BOLD + "" + (quests.size() + 1) + ". " + ChatColor.RESET + "" final Quester quester = plugin.getQuester(((Player) context.getForWhom()).getUniqueId());
+ ChatColor.GRAY + Lang.get("cancel") + "\n"; if (quests != null && number > 0) {
menu += ChatColor.WHITE + Lang.get("enterAnOption"); if (number < (quests.size() + 1)) {
return menu; final Quest quest = quests.get(number - 1);
} if (quester.getCompletedQuests().contains(quest)) {
return ChatColor.GREEN;
@SuppressWarnings("unchecked") } else {
@Override return ChatColor.GOLD;
public Prompt acceptInput(final ConversationContext context, final String input) { }
final Quests plugin = (Quests)context.getPlugin(); } else if (number == (quests.size() + 1)) {
final LinkedList<Quest> quests = (LinkedList<Quest>) context.getSessionData("npcQuests"); //return ChatColor.RED;
if (plugin == null || quests == null) { return ChatColor.GOLD;
return Prompt.END_OF_CONVERSATION; }
} }
final Quester quester = plugin.getQuester(((Player) context.getForWhom()).getUniqueId()); return null;
int numInput = -1; }
try {
numInput = Integer.parseInt(input); @SuppressWarnings("unchecked")
} catch (final NumberFormatException e) { public String getSelectionText(final ConversationContext context, final int number) {
// Continue final Quests plugin = (Quests)context.getPlugin();
} final LinkedList<Quest> quests = (LinkedList<Quest>) context.getSessionData("npcQuests");
if (input.equalsIgnoreCase(Lang.get("cancel")) || numInput == (quests.size() + 1)) { final Quester quester = plugin.getQuester(((Player) context.getForWhom()).getUniqueId());
context.getForWhom().sendRawMessage(ChatColor.YELLOW + Lang.get("cancelled")); if (quests != null && number > 0) {
return Prompt.END_OF_CONVERSATION; if (number < (quests.size() + 1)) {
} else { final Quest quest = quests.get(number - 1);
Quest q = null; if (quester.getCompletedQuests().contains(quest)) {
for (final Quest quest : quests) { return ChatColor.GREEN + "" + ChatColor.ITALIC + quest.getName();
if (quest.getName().equalsIgnoreCase(input)) { } else {
q = quest; return ChatColor.YELLOW + "" + ChatColor.ITALIC + quest.getName();
break; }
} } else if (number == (quests.size() + 1)) {
} return ChatColor.GRAY + Lang.get("cancel");
if (q == null) { }
for (final Quest quest : quests) { }
if (numInput == (quests.indexOf(quest) + 1)) { return null;
q = quest; }
break;
} @SuppressWarnings("unchecked")
} public String getAdditionalText(final ConversationContext context, final int number) {
} final Quests plugin = (Quests)context.getPlugin();
if (q == null) { final LinkedList<Quest> quests = (LinkedList<Quest>) context.getSessionData("npcQuests");
for (final Quest quest : quests) { final Quester quester = plugin.getQuester(((Player) context.getForWhom()).getUniqueId());
if (quest.getName().toLowerCase().contains(input.toLowerCase())) { if (quests != null && number > 0) {
q = quest; if (number < (quests.size() + 1)) {
break; final Quest quest = quests.get(number - 1);
} if (quester.getCompletedQuests().contains(quest)) {
} return ChatColor.GREEN + "" + Lang.get("redoCompleted");
} }
if (q == null) { }
context.getForWhom().sendRawMessage(ChatColor.RED + Lang.get("invalidOption")); }
return new NpcOfferQuestPrompt(); return "";
} else { }
final Player player = quester.getPlayer();
if (quester.canAcceptOffer(q, true)) { public String getQueryText(final ConversationContext context) {
quester.setQuestIdToTake(q.getId()); return Lang.get("enterAnOption");
for (final String msg : extracted(plugin, quester).split("<br>")) { }
player.sendMessage(msg);
} @SuppressWarnings("unchecked")
if (!plugin.getSettings().canAskConfirmation()) { @Override
quester.takeQuest(q, false); public @Nonnull String getPromptText(final ConversationContext context) {
} else { this.cc = context;
plugin.getConversationFactory().buildConversation(player).begin(); final Quests plugin = (Quests)context.getPlugin();
} final LinkedList<Quest> quests = (LinkedList<Quest>) context.getSessionData("npcQuests");
} final String npc = (String) context.getSessionData("npc");
return Prompt.END_OF_CONVERSATION; if (plugin == null || quests == null || npc == null) {
} return ChatColor.YELLOW + Lang.get("unknownError");
} }
}
final MiscPostNpcOfferQuestEvent event = new MiscPostNpcOfferQuestEvent(context, this);
private String extracted(final Quests plugin, final Quester quester) { plugin.getServer().getPluginManager().callEvent(event);
final Quest quest = plugin.getQuestById(quester.getQuestIdToTake());
return MessageFormat.format("{0}- {1}{2}{3} -\n\n{4}{5}\n", ChatColor.GOLD, ChatColor.DARK_PURPLE, String text = ChatColor.WHITE + getTitle(context);
quest.getName(), ChatColor.GOLD, ChatColor.RESET, quest.getDescription()); size = quests.size();
} for (int i = 1; i <= size + 1; i++) {
} text += "\n" + getNumberColor(context, i) + "" + ChatColor.BOLD + i + ". " + ChatColor.RESET
+ getSelectionText(context, i) + " " + getAdditionalText(context, i);
}
text += "\n" + ChatColor.WHITE + getQueryText(context);
return text;
}
@SuppressWarnings("unchecked")
@Override
public Prompt acceptInput(final ConversationContext context, final String input) {
final Quests plugin = (Quests)context.getPlugin();
final LinkedList<Quest> quests = (LinkedList<Quest>) context.getSessionData("npcQuests");
if (plugin == null || quests == null) {
return Prompt.END_OF_CONVERSATION;
}
final Quester quester = plugin.getQuester(((Player) context.getForWhom()).getUniqueId());
int numInput = -1;
try {
numInput = Integer.parseInt(input);
} catch (final NumberFormatException e) {
// Continue
}
if (input.equalsIgnoreCase(Lang.get("cancel")) || numInput == (quests.size() + 1)) {
context.getForWhom().sendRawMessage(ChatColor.YELLOW + Lang.get("cancelled"));
return Prompt.END_OF_CONVERSATION;
} else {
Quest q = null;
for (final Quest quest : quests) {
if (quest.getName().equalsIgnoreCase(input)) {
q = quest;
break;
}
}
if (q == null) {
for (final Quest quest : quests) {
if (numInput == (quests.indexOf(quest) + 1)) {
q = quest;
break;
}
}
}
if (q == null) {
for (final Quest quest : quests) {
if (quest.getName().toLowerCase().contains(input.toLowerCase())) {
q = quest;
break;
}
}
}
if (q == null) {
context.getForWhom().sendRawMessage(ChatColor.RED + Lang.get("invalidOption"));
return new NpcOfferQuestPrompt(context);
} else {
final Player player = quester.getPlayer();
if (quester.canAcceptOffer(q, true)) {
quester.setQuestIdToTake(q.getId());
for (final String msg : extracted(plugin, quester).split("<br>")) {
player.sendMessage(msg);
}
if (!plugin.getSettings().canAskConfirmation()) {
quester.takeQuest(q, false);
} else {
plugin.getConversationFactory().buildConversation(player).begin();
}
}
return Prompt.END_OF_CONVERSATION;
}
}
}
private String extracted(final Quests plugin, final Quester quester) {
final Quest quest = plugin.getQuestById(quester.getQuestIdToTake());
return MessageFormat.format("{0}- {1}{2}{3} -\n\n{4}{5}\n", ChatColor.GOLD, ChatColor.DARK_PURPLE,
quest.getName(), ChatColor.GOLD, ChatColor.RESET, quest.getDescription());
}
}

View File

@ -46,7 +46,7 @@ public class StageMenuPrompt extends QuestsEditorNumericPrompt {
public ChatColor getNumberColor(final ConversationContext context, final int number) { public ChatColor getNumberColor(final ConversationContext context, final int number) {
final int stages = getStages(context); final int stages = getStages(context);
if (number > 0) { if (number > 0) {
if (number < (stages + 1) && number > 0) { if (number < (stages + 1)) {
return ChatColor.BLUE; return ChatColor.BLUE;
} else if (number == (stages + 1)) { } else if (number == (stages + 1)) {
return ChatColor.BLUE; return ChatColor.BLUE;
@ -95,7 +95,7 @@ public class StageMenuPrompt extends QuestsEditorNumericPrompt {
final int i = input.intValue(); final int i = input.intValue();
final int stages = getStages(context); final int stages = getStages(context);
if (i > 0) { if (i > 0) {
if (i < (stages + 1) && i > 0) { if (i < (stages + 1)) {
return new StageMainPrompt((i), context); return new StageMainPrompt((i), context);
} else if (i == (stages + 1)) { } else if (i == (stages + 1)) {
return new StageMainPrompt((stages + 1), context); return new StageMainPrompt((stages + 1), context);