diff --git a/2006Scape Server/plugins/plugin/buttons/DialogueOptions.java b/2006Scape Server/plugins/plugin/buttons/DialogueOptions.java new file mode 100644 index 000000000..30bc0c999 --- /dev/null +++ b/2006Scape Server/plugins/plugin/buttons/DialogueOptions.java @@ -0,0 +1,53 @@ +package plugin.buttons; + +import com.rs2.event.SubscribesTo; +import com.rs2.event.impl.ButtonActionEvent; +import com.rs2.game.dialog.Dialogue; +import com.rs2.game.players.Player; + +@SubscribesTo(ButtonActionEvent.class) +public final class DialogueOptions extends ButtonClick { + + @Override + protected void execute(Player player, ButtonActionEvent event) { + switch (event.getButton()) { + + // First Option (Option Interfaces 2, 3, 4, and 5) + case 9157: + case 9167: + case 9178: + case 9190: + player.getDialogueFactory().executeOption(0, player.getOptionDialogue()); + break; + // Second Option (Option Interfaces 2, 3, 4, and 5) + case 9158: + case 9168: + case 9179: + case 9191: + player.getDialogueFactory().executeOption(1, player.getOptionDialogue()); + break; + // Third Option (Option Interfaces 3, 4, and 5) + case 9169: + case 9180: + case 9192: + player.getDialogueFactory().executeOption(2, player.getOptionDialogue()); + break; + // Fourth Option (Option Interfaces 4 and 5) + case 9181: + case 9193: + player.getDialogueFactory().executeOption(3, player.getOptionDialogue()); + break; + // Fifth Option (Option Interface 5) + case 9194: + player.getDialogueFactory().executeOption(4, player.getOptionDialogue()); + break; + + } + } + + @Override + public boolean test(ButtonActionEvent event) { + return Dialogue.isDialogueButton(event.getButton()); + } + +} diff --git a/2006Scape Server/plugins/plugin/npc/shopkeeper/FirstClick.java b/2006Scape Server/plugins/plugin/npc/shopkeeper/FirstClick.java new file mode 100644 index 000000000..060ca5e60 --- /dev/null +++ b/2006Scape Server/plugins/plugin/npc/shopkeeper/FirstClick.java @@ -0,0 +1,28 @@ +package plugin.npc.shopkeeper; + +import com.rs2.event.EventContext; +import com.rs2.event.EventSubscriber; +import com.rs2.event.SubscribesTo; +import com.rs2.event.impl.NpcFirstClickEvent; +import com.rs2.game.players.Player; + +import static com.rs2.game.content.StaticNpcList.SHOP_KEEPER_528; + +@SubscribesTo(NpcFirstClickEvent.class) +public final class FirstClick implements EventSubscriber { + + @Override + public void subscribe(EventContext context, Player player, NpcFirstClickEvent event) { + if (player.playerRights == 3) { + player.getPacketSender().sendMessage("[click= npc], [type = first], [id= " + event.getNpc() + "], [Type= " + event.getNpc() + "]"); + } + + switch (event.getNpc()) { + + case SHOP_KEEPER_528: + player.getDialogueFactory().sendDialogue(new GeneralStoreDialogue()); + break; + } + } + +} diff --git a/2006Scape Server/plugins/plugin/npc/shopkeeper/GeneralStoreDialogue.java b/2006Scape Server/plugins/plugin/npc/shopkeeper/GeneralStoreDialogue.java new file mode 100644 index 000000000..8cc9f07da --- /dev/null +++ b/2006Scape Server/plugins/plugin/npc/shopkeeper/GeneralStoreDialogue.java @@ -0,0 +1,22 @@ +package plugin.npc.shopkeeper; + +import com.rs2.game.dialog.Dialogue; +import com.rs2.game.dialog.DialogueFactory; + + +public final class GeneralStoreDialogue extends Dialogue { + @Override + public void sendDialogues(DialogueFactory factory) { + factory.getPlayer().dialoguePlugin = true; + factory.sendNpcChat("Can I help you at all?") + .sendOption("Yes please. What are you selling?", () -> { + factory.onAction(() -> { + factory.getPlayer().getShopAssistant().openShop(88); + }); + }, "No thanks.", () -> { + factory.sendPlayerChat("No thanks."); + }).execute(); + } + +} + diff --git a/2006Scape Server/src/main/java/com/rs2/game/dialog/Chainable.java b/2006Scape Server/src/main/java/com/rs2/game/dialog/Chainable.java new file mode 100644 index 000000000..811a66080 --- /dev/null +++ b/2006Scape Server/src/main/java/com/rs2/game/dialog/Chainable.java @@ -0,0 +1,13 @@ +package com.rs2.game.dialog; + +import java.util.function.Consumer; + +/** + * The chain-able interface that allows implementing dialogue factories the ability to chain together. + * + * @author Vult-R + */ +public interface Chainable extends Consumer { + +} + diff --git a/2006Scape Server/src/main/java/com/rs2/game/dialog/Dialogue.java b/2006Scape Server/src/main/java/com/rs2/game/dialog/Dialogue.java new file mode 100644 index 000000000..9bf60d7a6 --- /dev/null +++ b/2006Scape Server/src/main/java/com/rs2/game/dialog/Dialogue.java @@ -0,0 +1,45 @@ +package com.rs2.game.dialog; + +import com.google.common.collect.ImmutableList; +import com.rs2.game.players.Player; + +/** + * Represents an abstract dialogue, in which extending classes will be able to construct and send dialogues + * to a player. + * + * @author Vult-R + */ +public abstract class Dialogue { + + private static Player player; + + /** + * The action buttons responsible for dialogues. + */ + public static final ImmutableList DIALOGUE_BUTTONS = ImmutableList.of(9157, 9167, 9178, 9190, + 9158, 9168, 9179, 9191, 9169, 9180, 9192, 9181, 9193, 9194); + + /** + * Sends a player a dialogue. + * + * @param factory + * The factory for this dialogue. + */ + public abstract void sendDialogues(DialogueFactory factory); + + /** + * Checks if the button triggered is an optional dialogue button. + * + * @param button + * The index of the button being checked. + * + * @return The result of the operation. + */ + public static final boolean isDialogueButton(int button) { + if (player.dialoguePlugin) { + return DIALOGUE_BUTTONS.stream().anyMatch(search -> search == button); + } else { + return false; + } + } +} diff --git a/2006Scape Server/src/main/java/com/rs2/game/dialog/DialogueFactory.java b/2006Scape Server/src/main/java/com/rs2/game/dialog/DialogueFactory.java new file mode 100644 index 000000000..b4f5afc3d --- /dev/null +++ b/2006Scape Server/src/main/java/com/rs2/game/dialog/DialogueFactory.java @@ -0,0 +1,754 @@ +package com.rs2.game.dialog; + +import com.rs2.Constants; +import com.rs2.game.npcs.NPCDefinition; +import com.rs2.game.npcs.Npc; +import com.rs2.game.players.Player; +import com.rs2.util.LoggerUtils; +import com.rs2.util.Misc; +import org.apollo.cache.def.NpcDefinition; + +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Objects; +import java.util.Optional; +import java.util.Queue; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Represents a factory class that contains important functions for building dialogues. + * + * @author Vult-R + */ +public final class DialogueFactory { + + /** + * The single logger for this class. + */ + private static final Logger logger = LoggerUtils.getLogger(DialogueFactory.class); + + /** + * The queue of dialogues in this factory. + */ + private final Queue chain = new ArrayDeque<>(); + + /** + * The maximum length of a single line of dialogue. + */ + private static final int MAXIMUM_LENGTH = 100; + + /** + * The player who owns this factory. + */ + private final Player player; + + /** + * The flag that denotes dialogue is active. + */ + private boolean active; + + /** + * The next action in the dialogue chain. + */ + private Optional nextAction = Optional.empty(); + + /** + * Creates a new {@link DialogueFactory}. + * + * @param player + * The player who owns this factory. + */ + public DialogueFactory(Player player) { + this.player = player; + } + + /** + * Sends a player a dialogue. + * + * @param dialogue + * The dialogue to sent. + */ + public final DialogueFactory sendDialogue(Dialogue dialogue) { + player.setDialogue(Optional.of(dialogue)); + dialogue.sendDialogues(this); + return this; + } + + /** + * Sets an {@code action} so this action can be executed after dialogues are done. + * + * @param action + * The action to set. + * + * @return The instance of this factory. + */ + public final DialogueFactory onAction(Runnable action) { + setNextAction(Optional.of(action)); + return this; + } + + /** + * Accepts the next dialogue in the chain. + * + * @return The instance of this factory. + */ + public DialogueFactory onNext() { + if (getChain().peek() != null) { + Chainable chain = getChain().poll(); + + chain.accept(this); + } else { + player.getPacketSender().closeAllWindows(); + } + return this; + } + + /** + * Executes an {@code option} for a {@code player}. + * + * @param type + * The type of option. + * + * @param option + * The option to execute. + */ + public final void executeOption(int type, Optional option) { + if (option != null) { + option.ifPresent($it -> $it.getActions().get(type).run()); + execute(); + } + } + + /** + * Clears the current dialogue {@code chain}. + * + * @return The instance of this factory. + */ + public void clear() { + chain.clear(); + nextAction = Optional.empty(); + player.setDialogue(Optional.empty()); + player.setOptionDialogue(Optional.empty()); + setActive(false); + } + + /** + * Appends a {@code chain} to this factory. + * + * @return The instance of this factory. + */ + private final DialogueFactory append(Chainable chain) { + this.chain.add(chain); + return this; + } + + /** + * Gets the current chain. + * + * @return The queue of dialogues. + */ + public final Queue getChain() { + return chain; + } + + /** + * Retrieves the next dialogue in the chain and executes it. + * + * @return The instance of this factory. + */ + public final DialogueFactory execute() { + // check to see if there are anymore dialogues. + if (getChain().peek() != null) { + + // there is so, grab the next dialogue. + Chainable entry = getChain().poll(); + + // is this an option dialogue? + if (entry instanceof OptionDialogue) { + OptionDialogue option = (OptionDialogue) entry; + player.setOptionDialogue(Optional.of(option)); + } + setActive(true); + // whatever dialogue it is, accept it. + entry.accept(this); + } else { + // there are no dialogues in this chain. + + // is there an action? + if (getNextAction().isPresent()) { + // there is so, execute it. + getNextAction().ifPresent($it -> $it.run()); + // we just used this action so empty it so it can't be used again. + setNextAction(Optional.empty()); + return this; + } + setActive(false); + // there are no more dialogues, so clear the screen. + player.getPacketSender().closeAllWindows(); + player.talkingNpc = -1; + player.nextChat = 0; + } + return this; + } + + /** + * Retrieves the next dialogue in the chain and executes it. + * + * @return The instance of this factory. + */ + public final DialogueFactory executeNoClose() { + // check to see if there are anymore dialogues. + if (getChain().peek() != null) { + + // there is so, grab the next dialogue. + Chainable entry = getChain().poll(); + + // is this an option dialogue? + if (entry instanceof OptionDialogue) { + OptionDialogue option = (OptionDialogue) entry; + player.setOptionDialogue(Optional.of(option)); + } + setActive(true); + // whatever dialogue it is, accept it. + entry.accept(this); + } else { + // there are no dialogues in this chain. + + // is there an action? + if (getNextAction().isPresent()) { + // there is so, execute it. + getNextAction().ifPresent($it -> $it.run()); + // we just used this action so empty it so it can't be used again. + setNextAction(Optional.empty()); + return this; + } + setActive(false); + player.talkingNpc = -1; + player.nextChat = 0; + } + return this; + } + + /** + * Appends keywords to an existing dialogue text. + * + * @param line + * The line to check for a keyword. + */ + private final String appendKeywords(String line) { + // If the line contains #username, replace with a formatted player name. + if (line.contains("")) { + line = line.replaceAll("", Misc.formatPlayerName((player.playerName))); + } + if (line.contains("")) { + line = line.replaceAll("", Constants.SERVER_NAME); + } + + return line; + } + + /** + * Appends a {@link PlayerDialogue} to the current dialogue chain. + * + * @param lines + * The dialogue of the player talking. + * + * @return The instance of this factory. + */ + public final DialogueFactory sendPlayerChat(String... lines) { + return append(new PlayerDialogue(lines)); + } + + /** + * Appends a {@link PlayerDialogue} to the current dialogue chain. + * + * @param lines + * The dialogue of the player talking. + * + * @param expression + * The expression of this dialogue. + * + * @return The instance of this factory. + */ + public final DialogueFactory sendPlayerChat(Expression expression, String... lines) { + return append(new PlayerDialogue(expression, lines)); + } + + /** + * Sends a dialogue with a player talking. + * + * @param dialogue + * The player dialogue. + * + * @return The instance of this factory. + */ + final DialogueFactory sendPlayerChat(PlayerDialogue dialogue) { + Expression expression = dialogue.getExpression(); + String[] lines = dialogue.getLines(); + + validateLength(lines); + switch (lines.length) { + case 1: + player.getPacketSender().sendDialogueAnimation(969, expression.getId()); + player.getPacketSender().sendString(Misc.formatPlayerName(player.playerName), 970); + player.getPacketSender().sendString(appendKeywords(lines[0]), 971); + player.getPacketSender().sendPlayerDialogueHead(969); + player.getPacketSender().sendChatInterface(968); + break; + + case 2: + player.getPacketSender().sendDialogueAnimation(974, expression.getId()); + player.getPacketSender().sendString(Misc.formatPlayerName(player.playerName), 975); + player.getPacketSender().sendString(appendKeywords(lines[0]), 976); + player.getPacketSender().sendString(appendKeywords(lines[1]), 977); + player.getPacketSender().sendPlayerDialogueHead(974); + player.getPacketSender().sendChatInterface(973); + break; + + case 3: + player.getPacketSender().sendDialogueAnimation(980, expression.getId()); + player.getPacketSender().sendString(Misc.formatPlayerName(player.playerName), 981); + player.getPacketSender().sendString(appendKeywords(lines[0]), 982); + player.getPacketSender().sendString(appendKeywords(lines[1]), 983); + player.getPacketSender().sendString(appendKeywords(lines[2]), 984); + player.getPacketSender().sendPlayerDialogueHead(980); + player.getPacketSender().sendChatInterface(979); + break; + + case 4: + player.getPacketSender().sendDialogueAnimation(987, expression.getId()); + player.getPacketSender().sendString(Misc.formatPlayerName(player.playerName), 988); + player.getPacketSender().sendString(appendKeywords(lines[0]), 989); + player.getPacketSender().sendString(appendKeywords(lines[1]), 990); + player.getPacketSender().sendString(appendKeywords(lines[2]), 991); + player.getPacketSender().sendString(appendKeywords(lines[3]), 992); + player.getPacketSender().sendPlayerDialogueHead(987); + player.getPacketSender().sendChatInterface(986); + break; + + default: + logger.log(Level.SEVERE, String.format("Invalid player dialogue line length: %s", lines.length)); + break; + } + return this; + } + + /** + * Appends an npc dialogue. + * + * @param lines + * The text of this dialogue. + * + * @return The instance of this factory. + */ + public final DialogueFactory sendNpcChat(String... lines) { + return append(new NpcDialogue(lines)); + } + + /** + * Appends an {@link NpcDialogue} to the current dialogue chain. + * + * @param expression + * The expression of this npc. + * + * @param lines + * The text of this dialogue. + * + * @return The instance of this factory. + */ + public final DialogueFactory sendNpcChat(Expression expression, String... lines) { + if (player.getNpcs() != null) { //TODO + int id = player.npcType; + return append(new NpcDialogue(id, expression, lines)); + } + return append(new NpcDialogue(expression, lines)); + } + + /** + * Appends an {@link NpcDialogue} to the current dialogue chain. + * + * @param id + * The id of this npc. + * + * @param lines + * The text of this dialogue. + * + * @return The instance of this factory. + */ + public final DialogueFactory sendNpcChat(int id, String... lines) { + return append(new NpcDialogue(id, Expression.DEFAULT, lines)); + } + + /** + * Appends an {@link NpcDialogue} to the current dialogue chain. + * + * @param id + * The id of this npc. + * + * @param expression + * The expression of this npc. + * + * @param lines + * The text of this dialogue. + * + * @return The instance of this factory. + */ + public final DialogueFactory sendNpcChat(int id, Expression expression, String... lines) { + return append(new NpcDialogue(id, expression, lines)); + } + + /** + * Sends a dialogue with a npc talking. + * + * @param dialogue + * The dialogue. + * + * @return The instance of this factory. + */ + final DialogueFactory sendNpcChat(NpcDialogue dialogue) { + Expression expression = dialogue.getExpression(); + String[] lines = dialogue.getLines(); + validateLength(lines); + + final NPCDefinition mob = NPCDefinition.forId(player.npcType); + + if (mob == null) { + return this; + } + + switch (lines.length) { + case 1: + player.getPacketSender().sendDialogueAnimation(4883, expression.getId()); + player.getPacketSender().sendString(mob.getName(), 4884); + player.getPacketSender().sendString(appendKeywords(lines[0]), 4885); + player.getPacketSender().sendNPCDialogueHead(player.npcType, 4883); + player.getPacketSender().sendChatInterface(4882); + break; + + case 2: + player.getPacketSender().sendDialogueAnimation(4888, expression.getId()); + player.getPacketSender().sendString(mob.getName(), 4889); + player.getPacketSender().sendString(appendKeywords(lines[0]), 4890); + player.getPacketSender().sendString(appendKeywords(lines[1]), 4891); + player.getPacketSender().sendNPCDialogueHead(player.npcType, 4888); + player.getPacketSender().sendChatInterface(4887); + break; + + case 3: + player.getPacketSender().sendDialogueAnimation(4894, expression.getId()); + player.getPacketSender().sendString(mob.getName(), 4895); + player.getPacketSender().sendString(appendKeywords(lines[0]), 4896); + player.getPacketSender().sendString(appendKeywords(lines[1]), 4897); + player.getPacketSender().sendString(appendKeywords(lines[2]), 4898); + player.getPacketSender().sendNPCDialogueHead(player.npcType, 4894); + player.getPacketSender().sendChatInterface(4893); + break; + + case 4: + player.getPacketSender().sendDialogueAnimation(4901, expression.getId()); + player.getPacketSender().sendString(mob.getName(), 4902); + player.getPacketSender().sendString(appendKeywords(lines[0]), 4903); + player.getPacketSender().sendString(appendKeywords(lines[1]), 4904); + player.getPacketSender().sendString(appendKeywords(lines[2]), 4905); + player.getPacketSender().sendString(appendKeywords(lines[3]), 4906); + player.getPacketSender().sendNPCDialogueHead(player.npcType, 4901); + player.getPacketSender().sendChatInterface(4900); + break; + + default: + logger.log(Level.SEVERE, + String.format("Invalid npc dialogue line length: %s", lines.length)); + break; + } + return this; + } + + /** + * Appends the {@link OptionDialogue} onto the current dialogue chain. + * + * @param option1 + * The text for the first option. + * + * @param action1 + * The action for the first action. + * + * @param option2 + * The text for the second option. + * + * @param action2 + * The action for the second action. + */ + public final DialogueFactory sendOption(String option1, Runnable action1, String option2, Runnable action2) { + return append(new OptionDialogue(option1, action1, option2, action2)); + } + + /** + * Appends the {@link OptionDialogue} onto the current dialogue chain. + * + * @param option1 + * The text for the first option. + * + * @param action1 + * The action for the first action. + * + * @param option2 + * The text for the second option. + * + * @param action2 + * The action for the second action. + * + * @param option3 + * The text for the third option. + * + * @param action3 + * The action for the third action. + */ + public final DialogueFactory sendOption(String option1, Runnable action1, String option2, Runnable action2, String option3, Runnable action3) { + return append(new OptionDialogue(option1, action1, option2, action2, option3, action3)); + } + + /** + * Appends the {@link OptionDialogue} onto the current dialogue chain. + * + * @param option1 + * The text for the first option. + * + * @param action1 + * The action for the first action. + * + * @param option2 + * The text for the second option. + * + * @param action2 + * The action for the second action. + * + * @param option3 + * The text for the third option. + * + * @param action3 + * The action for the third action. + * + * @param option4 + * The text for the four option. + * + * @param action4 + * The action for the four action. + */ + public final DialogueFactory sendOption(String option1, Runnable action1, String option2, Runnable action2, String option3, Runnable action3, String option4, Runnable action4) { + return append(new OptionDialogue(option1, action1, option2, action2, option3, action3, option4, action4)); + } + + /** + * Appends the {@link OptionDialogue} onto the current dialogue chain. + * + * @param option1 + * The text for the first option. + * + * @param action1 + * The action for the first action. + * + * @param option2 + * The text for the second option. + * + * @param action2 + * The action for the second action. + * + * @param option3 + * The text for the third option. + * + * @param action3 + * The action for the third action. + * + * @param option4 + * The text for the four option. + * + * @param action4 + * The action for the four action. + * + * @param option5 + * The text for the fifth option. + * + * @param action5 + * The action for the fifth action. + */ + public final DialogueFactory sendOption(String option1, Runnable action1, String option2, Runnable action2, String option3, Runnable action3, String option4, Runnable action4, String option5, Runnable action5) { + return append(new OptionDialogue(option1, action1, option2, action2, option3, action3, option4, action4, option5, action5)); + } + + /** + * Sends a dialogue with options. + * + * @param dialogue + * The dialogue. + * + * @return The instance of this factory. + */ + final DialogueFactory sendOption(OptionDialogue dialogue) { + String[] options = dialogue.getLines(); + validateLength(options); + switch (options.length) { + case 2: + player.getPacketSender().sendString("Select an Option", 2460); + player.getPacketSender().sendString(options[0], 2461); + player.getPacketSender().sendString(options[1], 2462); + player.getPacketSender().sendChatInterface(2459); + return this; + + case 3: + player.getPacketSender().sendString("Select an Option", 2470); + player.getPacketSender().sendString(options[0], 2471); + player.getPacketSender().sendString(options[1], 2472); + player.getPacketSender().sendString(options[2], 2473); + player.getPacketSender().sendChatInterface(2469); + return this; + + case 4: + player.getPacketSender().sendString("Select an Option", 2481); + player.getPacketSender().sendString(options[0], 2482); + player.getPacketSender().sendString(options[1], 2483); + player.getPacketSender().sendString(options[2], 2484); + player.getPacketSender().sendString(options[3], 2485); + player.getPacketSender().sendChatInterface(2480); + return this; + + case 5: + player.getPacketSender().sendString("Select an Option", 2493); + player.getPacketSender().sendString(options[0], 2494); + player.getPacketSender().sendString(options[1], 2495); + player.getPacketSender().sendString(options[2], 2496); + player.getPacketSender().sendString(options[3], 2497); + player.getPacketSender().sendString(options[4], 2498); + player.getPacketSender().sendChatInterface(2492); + return this; + } + return this; + } + + /** + * Appends a {@link StatementDialogue} to the current dialogue chain. + * + * @param lines + * The text for this statement. + * + * @return The instance of this factory. + */ + public final DialogueFactory sendStatement(String... lines) { + validateLength(lines); + append(new StatementDialogue(lines)); + return this; + } + + /** + * Sends a player a statement dialogue. + * + * @param dialogue + * The statement dialogue. + */ + final DialogueFactory sendStatement(StatementDialogue dialogue) { + validateLength(dialogue.getLines()); + switch (dialogue.getLines().length) { + + case 1: + player.getPacketSender().sendString(dialogue.getLines()[0], 357); + player.getPacketSender().sendString("Click here to continue", 358); + player.getPacketSender().sendChatInterface(356); + break; + case 2: + player.getPacketSender().sendString(dialogue.getLines()[0], 360); + player.getPacketSender().sendString(dialogue.getLines()[1], 361); + player.getPacketSender().sendString("Click here to continue", 362); + player.getPacketSender().sendChatInterface(359); + break; + case 3: + player.getPacketSender().sendString(dialogue.getLines()[0], 364); + player.getPacketSender().sendString(dialogue.getLines()[1], 365); + player.getPacketSender().sendString(dialogue.getLines()[2], 366); + player.getPacketSender().sendString("Click here to continue", 367); + player.getPacketSender().sendChatInterface(363); + break; + case 4: + player.getPacketSender().sendString(dialogue.getLines()[0], 369); + player.getPacketSender().sendString(dialogue.getLines()[1], 370); + player.getPacketSender().sendString(dialogue.getLines()[2], 371); + player.getPacketSender().sendString(dialogue.getLines()[3], 372); + player.getPacketSender().sendString("Click here to continue", 373); + player.getPacketSender().sendChatInterface(368); + break; + case 5: + player.getPacketSender().sendString(dialogue.getLines()[0], 375); + player.getPacketSender().sendString(dialogue.getLines()[1], 376); + player.getPacketSender().sendString(dialogue.getLines()[2], 377); + player.getPacketSender().sendString(dialogue.getLines()[3], 378); + player.getPacketSender().sendString(dialogue.getLines()[4], 379); + player.getPacketSender().sendString("Click here to continue", 380); + player.getPacketSender().sendChatInterface(374); + default: + logger.log(Level.SEVERE, String.format("Invalid statement dialogue line length: %s", + dialogue.getLines().length)); + break; + } + return this; + } + + /** + * The method that validates the length of {@code text}. + * + * @param text + * the text that will be validated. + * @throws IllegalStateException + * if any lines of the text exceed a certain length. + */ + private final void validateLength(String... text) { + if (Arrays.stream(text).filter(Objects::nonNull).anyMatch(s -> s.length() > MAXIMUM_LENGTH)) { + throw new IllegalStateException("Dialogue length too long, maximum length is: " + MAXIMUM_LENGTH); + } + } + + /** + * The player that owns this factory. + * + * @return The player. + */ + public Player getPlayer() { + return player; + } + + /** + * Gets the {@link Optional} describing the next action in the dialogue chain. + * + * @return The optional describing the next action. + */ + public Optional getNextAction() { + return nextAction; + } + + /** + * Sets the next action in the dialogue chain. + * + * @param nextAction + * The action to set. + */ + public void setNextAction(Optional nextAction) { + this.nextAction = nextAction; + } + + /** + * Determines if dialogues are currently open. + */ + public boolean isActive() { + return active; + } + + /** + * Sets the flag that indicates dialogues are present. + * + * @param active + * The flag to set. + */ + public void setActive(boolean active) { + this.active = active; + } + +} + diff --git a/2006Scape Server/src/main/java/com/rs2/game/dialog/Expression.java b/2006Scape Server/src/main/java/com/rs2/game/dialog/Expression.java new file mode 100644 index 000000000..faf865373 --- /dev/null +++ b/2006Scape Server/src/main/java/com/rs2/game/dialog/Expression.java @@ -0,0 +1,81 @@ +package com.rs2.game.dialog; + +/* +Copyright (c) 2010-2011 Graham Edgecombe +Copyright (c) 2011-2016 Major and other apollo contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * Represents the expressions of entities for dialogue. + * + * @author Vult-R + */ +public enum Expression { + HAPPY(588), + ANXIOUS(589), + CALM_TALK(590), + DEFAULT(591), + EVIL(592), + BAD(593), + WICKED(594), + ANNOYED(595), + DISTRESSED(596), + AFFLICTED(597), + DRUNK_LEFT(600), + DRUNK_RIGHT(601), + NOT_INTERESTED(602), + SLEEPY(603), + PLAIN_EVIL(604), + LAUGH(605), + SNIGGER(606), + HAVE_FUN(607), + GUFFAW(608), + EVIL_LAUGH_SHORT(609), + SLIGHTLY_SAD(610), + SAD(599), + VERY_SAD(611), + ON_ONE_HAND(612), + ALMOST_CRYING(598), + NEARLY_CRYING(613), + ANGRY(614), + FURIOUS(615), + ENRAGED(616), + MAD(617); + + /** + * The id for this expression. + */ + private final int expression; + + /** + * Creates a new {@link Expression}. + * + * @param expression + * The id for this expression. + */ + private Expression(int expression) { + this.expression = expression; + } + + /** + * Gets the id for this expression. + * + * @return The id of this expression. + */ + public final int getId() { + return expression; + } +} + diff --git a/2006Scape Server/src/main/java/com/rs2/game/dialog/NpcDialogue.java b/2006Scape Server/src/main/java/com/rs2/game/dialog/NpcDialogue.java new file mode 100644 index 000000000..0a8d48f0e --- /dev/null +++ b/2006Scape Server/src/main/java/com/rs2/game/dialog/NpcDialogue.java @@ -0,0 +1,112 @@ +package com.rs2.game.dialog; + +/** + * The {@link Chainable} implementation that represents dialogue in which an NPC is talking. + * + * @author Vult-R + */ +public final class NpcDialogue implements Chainable { + + /** + * The id of this npc. + */ + private int id = -1; + + /** + * The expression of this NPC. + */ + private final Expression expression; + + /** + * The text for this dialogue. + */ + private final String[] lines; + + /** + * Creates a new {@link NpcDialogue} + * + * @param lines + * The text for this dialogue. + */ + public NpcDialogue(String... lines) { + this(Expression.DEFAULT, lines); + } + + /** + * Creates a new {@link NpcDialogue} + * + * @param expression + * The expression of this npc. + * + * @param lines + * The text for this dialogue. + */ + public NpcDialogue(Expression expression, String... lines) { + this.expression = expression; + this.lines = lines; + } + + /** + * Creates a new {@link NpcDialogue} + * + * @param id + * The id of this npc. + * + * @param lines + * The text for this dialogue. + */ + public NpcDialogue(int id, String... lines) { + this(id, Expression.DEFAULT, lines); + } + + /** + * Creates a new {@link NpcDialogue} + * + * @param id + * The id of this npc. + * + * @param expression + * The expression of this npc. + * + * @param lines + * The text for this dialogue. + */ + public NpcDialogue(int id, Expression expression, String... lines) { + this.id = id; + this.expression = expression; + this.lines = lines; + } + + /** + * Gets the id of this npc. + * + * @return The id of this npc. + */ + public int getId() { + return id; + } + + /** + * Gets the expression of this npc. + * + * @return The expression. + */ + public Expression getExpression() { + return expression; + } + + /** + * Gets the text for this dialogue. + * + * @return The text. + */ + public String[] getLines() { + return lines; + } + + @Override + public void accept(DialogueFactory factory) { + factory.sendNpcChat(this); + } +} + diff --git a/2006Scape Server/src/main/java/com/rs2/game/dialog/OptionDialogue.java b/2006Scape Server/src/main/java/com/rs2/game/dialog/OptionDialogue.java new file mode 100644 index 000000000..20edecf6f --- /dev/null +++ b/2006Scape Server/src/main/java/com/rs2/game/dialog/OptionDialogue.java @@ -0,0 +1,171 @@ +package com.rs2.game.dialog; + +import java.util.ArrayList; +import java.util.List; + +/** + * The {@link Chainable} implementation that represents a dialogue in which options are given to the player. + * + * @author Vult-R + */ +public final class OptionDialogue implements Chainable { + + /** + * The text for this dialogue. + */ + private final String[] lines; + + /** + * The list of actions for this dialogue. + */ + private final List actions = new ArrayList<>(); + + /** + * Creates a new {@link OptionDialogue}. + * + * @param option1 + * The text for the first option. + * + * @param action1 + * The action for the first action. + * + * @param option2 + * The text for the second option. + * + * @param action2 + * The action for the second action. + */ + public OptionDialogue(String option1, Runnable action1, String option2, Runnable action2) { + lines = new String[] { option1, option2 }; + actions.add(action1); + actions.add(action2); + } + + /** + * Creates a new {@link OptionDialogue}. + * + * @param option1 + * The text for the first option. + * + * @param action1 + * The action for the first action. + * + * @param option2 + * The text for the second option. + * + * @param action2 + * The action for the second action. + * + * @param option3 + * The text for the third option. + * + * @param action3 + * The action for the third action. + */ + public OptionDialogue(String option1, Runnable action1, String option2, Runnable action2, String option3, Runnable action3) { + lines = new String[] { option1, option2, option3 }; + actions.add(action1); + actions.add(action2); + actions.add(action3); + } + + /** + * Creates a new {@link OptionDialogue}. + * + * @param option1 + * The text for the first option. + * + * @param action1 + * The action for the first action. + * + * @param option2 + * The text for the second option. + * + * @param action2 + * The action for the second action. + * + * @param option3 + * The text for the third option. + * + * @param action3 + * The action for the third action. + * + * @param option4 + * The text for the four option. + * + * @param action4 + * The action for the four action. + */ + public OptionDialogue(String option1, Runnable action1, String option2, Runnable action2, String option3, Runnable action3, String option4, Runnable action4) { + lines = new String[] { option1, option2, option3, option4 }; + actions.add(action1); + actions.add(action2); + actions.add(action3); + actions.add(action4); + } + + /** + * Creates a new {@link OptionDialogue}. + * + * @param option1 + * The text for the first option. + * + * @param action1 + * The action for the first action. + * + * @param option2 + * The text for the second option. + * + * @param action2 + * The action for the second action. + * + * @param option3 + * The text for the third option. + * + * @param action3 + * The action for the third action. + * + * @param option4 + * The text for the four option. + * + * @param action4 + * The action for the four action. + * + * @param option5 + * The text for the fifth option. + * + * @param action5 + * The action for the fifth action. + */ + public OptionDialogue(String option1, Runnable action1, String option2, Runnable action2, String option3, Runnable action3, String option4, Runnable action4, String option5, Runnable action5) { + lines = new String[] { option1, option2, option3, option4, option5 }; + actions.add(action1); + actions.add(action2); + actions.add(action3); + actions.add(action4); + actions.add(action5); + } + + @Override + public void accept(DialogueFactory factory) { + factory.sendOption(this); + } + + /** + * Gets the text for this dialogue. + * + * @return The text. + */ + public String[] getLines() { + return lines; + } + + /** + * Gets the list of actions for this dialogue. + * + * @return The list of actions. + */ + public List getActions() { + return actions; + } +} \ No newline at end of file diff --git a/2006Scape Server/src/main/java/com/rs2/game/dialog/PlayerDialogue.java b/2006Scape Server/src/main/java/com/rs2/game/dialog/PlayerDialogue.java new file mode 100644 index 000000000..90dcee003 --- /dev/null +++ b/2006Scape Server/src/main/java/com/rs2/game/dialog/PlayerDialogue.java @@ -0,0 +1,67 @@ +package com.rs2.game.dialog; + +/** + * A {@link Chainable} implementation that represents a player talking. + * + * @author Vult-R + */ +public class PlayerDialogue implements Chainable { + + /** + * The expression of this player. + */ + private final Expression expression; + + /** + * The text for this dialogue. + */ + private final String[] lines; + + /** + * Creates a new {@link PlayerDialogue} with a default expression of {@code DEFAULT}. + * + * @param lines + * The text for this dialogue. + */ + public PlayerDialogue(String... lines) { + this(Expression.DEFAULT, lines); + } + + /** + * Creates a new {@link PlayerDialogue}. + * + * @param expression + * The expression for this dialogue. + * + * @param lines + * The text for this dialogue. + */ + public PlayerDialogue(Expression expression, String... lines) { + this.expression = expression; + this.lines = lines; + } + + /** + * Gets the expression of this player. + * + * @return The expression of this player. + */ + public Expression getExpression() { + return expression; + } + + /** + * Gets the text for this dialogue. + * + * @return The text. + */ + public String[] getLines() { + return lines; + } + + @Override + public void accept(DialogueFactory factory) { + factory.sendPlayerChat(this); + } +} + diff --git a/2006Scape Server/src/main/java/com/rs2/game/dialog/StatementDialogue.java b/2006Scape Server/src/main/java/com/rs2/game/dialog/StatementDialogue.java new file mode 100644 index 000000000..713593373 --- /dev/null +++ b/2006Scape Server/src/main/java/com/rs2/game/dialog/StatementDialogue.java @@ -0,0 +1,41 @@ +package com.rs2.game.dialog; + +/** + * The {@link Chainable} implementation that represents a dialogue with a single statement; which has no models on the dialogue. + * + * @author Vult-R + */ +public class StatementDialogue implements Chainable { + + /** + * The text for this dialogue. + */ + private final String[] lines; + + /** + * Creates a new {@link StatementDialogue}. + * + * @param lines + * The text for this dialogue. + */ + public StatementDialogue(String... lines) { + this.lines = lines; + } + + + @Override + public void accept(DialogueFactory factory) { + factory.sendStatement(this); + } + + /** + * Gets the text on this dialogue. + * + * @return The text. + */ + public String[] getLines() { + return lines; + } + +} + diff --git a/2006Scape Server/src/main/java/com/rs2/game/dialogues/Dialogue.java b/2006Scape Server/src/main/java/com/rs2/game/dialogues/Dialogue.java index 2e02e0fb4..b53a7ca4f 100644 --- a/2006Scape Server/src/main/java/com/rs2/game/dialogues/Dialogue.java +++ b/2006Scape Server/src/main/java/com/rs2/game/dialogues/Dialogue.java @@ -12,6 +12,13 @@ public class Dialogue implements PacketType { @Override public void processPacket(Player c, Packet packet) { + + if (c.dialoguePlugin) { + // New Dialogue System + c.getDialogueFactory().execute(); + return; + } + if (c.nextChat > 0) { c.getDialogueHandler().sendDialogues(c.nextChat, c.talkingNpc); } else { diff --git a/2006Scape Server/src/main/java/com/rs2/game/dialogues/DialogueHandler.java b/2006Scape Server/src/main/java/com/rs2/game/dialogues/DialogueHandler.java index df8c21528..21e2473b0 100644 --- a/2006Scape Server/src/main/java/com/rs2/game/dialogues/DialogueHandler.java +++ b/2006Scape Server/src/main/java/com/rs2/game/dialogues/DialogueHandler.java @@ -44,6 +44,7 @@ public void setNextDialogue(int id) { } public void sendDialogues(int dialogue, int npcId) { + player.dialoguePlugin = false; player.talkingNpc = npcId; switch (dialogue) { case 0: diff --git a/2006Scape Server/src/main/java/com/rs2/game/players/Player.java b/2006Scape Server/src/main/java/com/rs2/game/players/Player.java index 46fd3c615..eaa957be5 100644 --- a/2006Scape Server/src/main/java/com/rs2/game/players/Player.java +++ b/2006Scape Server/src/main/java/com/rs2/game/players/Player.java @@ -37,6 +37,9 @@ import com.rs2.game.content.skills.smithing.SmithingInterface; import com.rs2.game.content.traveling.DesertCactus; import com.rs2.game.content.traveling.DesertHeat; +import com.rs2.game.dialog.Dialogue; +import com.rs2.game.dialog.DialogueFactory; +import com.rs2.game.dialog.OptionDialogue; import com.rs2.game.dialogues.DialogueHandler; import com.rs2.game.globalworldobjects.DoubleGates; import com.rs2.game.globalworldobjects.GateHandler; @@ -78,7 +81,8 @@ public abstract class Player { public String lastConnectedFrom; public int xpRate = 1; public String discordCode; - private Compost compost = new Compost(this); + public boolean dialoguePlugin; + private Compost compost = new Compost(this); private Allotments allotment = new Allotments(this); private Flowers flower = new Flowers(this); private Herbs herb = new Herbs(this); @@ -423,6 +427,34 @@ public Inventory getInventory() { private Inventory inventory = new Inventory(this); + private DialogueFactory dialogueFactory = new DialogueFactory(this); + private Optional dialogue = Optional.empty(); + private Optional optionDialogue; + + public DialogueFactory getDialogueFactory() { + return dialogueFactory; + } + + public void setDialogueFactory(DialogueFactory dialogueFactory) { + this.dialogueFactory = dialogueFactory; + } + + public Optional getOptionDialogue() { + return optionDialogue; + } + + public void setOptionDialogue(Optional optionDialogue) { + this.optionDialogue = optionDialogue; + } + + public Optional getDialogue() { + return dialogue; + } + + public void setDialogue(final Optional dialogue) { + this.dialogue = dialogue; + } + private int tempInteger; public boolean tempBoolean; @@ -471,7 +503,7 @@ public void endCurrentTask() { private Map interfaceText = new HashMap(); - public class TinterfaceText { + public class TinterfaceText { public int id; public String currentState; diff --git a/2006Scape Server/src/main/java/com/rs2/game/shops/Shops.java b/2006Scape Server/src/main/java/com/rs2/game/shops/Shops.java index 1c030c4d2..6f6b84f2e 100644 --- a/2006Scape Server/src/main/java/com/rs2/game/shops/Shops.java +++ b/2006Scape Server/src/main/java/com/rs2/game/shops/Shops.java @@ -36,7 +36,7 @@ public enum Shop { SHOP77(CHADWELL, 78), SHOP78(BANDIT_SHOPKEEPER, 79), SHOP79(FIDELIO, 80), SHOP80(ARHEIN, 81), SHOP81(SHOP_KEEPER_522, 82), SHOP82(SHOP_ASSISTANT_523, 82), SHOP83(SHOP_KEEPER_524, 83), SHOP84(SHOP_ASSISTANT_525, 83), SHOP85(SHOP_KEEPER_526, 84), SHOP86(SHOP_ASSISTANT_527, 84), SHOP87(GUNSLIK, 85), SHOP88(JOSSIK, 86), - SHOP89(EUDAV, 87), SHOP90(SHOP_KEEPER_528, 88), SHOP91(SHOP_ASSISTANT_529, 88), SHOP92(RAZMIRE_KEELGAN, 89), + SHOP89(EUDAV, 87), SHOP91(SHOP_ASSISTANT_529, 88), SHOP92(RAZMIRE_KEELGAN, 89), SHOP93(KAZGAR, 90), SHOP94(ARNOLD_LYDSPOR, 91), SHOP95(MARKET_SELLER, 92), SHOP96(GHOST_SHOPKEEPER, 93), SHOP97(SIGMUND_THE_MERCHANT, 94), SHOP98(SHOP_KEEPER_530, 95), SHOP99(SHOP_ASSISTANT_531, 95), SHOP100(OBLI, 96), SHOP101(JIMINUA, 97), SHOP102(BOLKOY, 98), SHOP103(QUARTERMASTER, 99), SHOP104(SHOP_KEEPER_532, 100), diff --git a/2006Scape Server/src/main/java/com/rs2/net/packets/impl/Walking.java b/2006Scape Server/src/main/java/com/rs2/net/packets/impl/Walking.java index ce14ce171..1a87fbd10 100644 --- a/2006Scape Server/src/main/java/com/rs2/net/packets/impl/Walking.java +++ b/2006Scape Server/src/main/java/com/rs2/net/packets/impl/Walking.java @@ -73,6 +73,7 @@ public void processPacket(Player player, Packet packet) { if (player.closeTutorialInterface == false && player.tutorialProgress == 36) { player.getDialogueHandler().sendDialogues(3116, player.npcType); } + player.getDialogue().ifPresent(it -> player.getDialogueFactory().clear()); if (player.gliderOpen) { player.gliderOpen = false; }