From c9bdfd2c3c9fb4ed2a0e23f4d4c18621ece96143 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Tue, 19 Sep 2023 19:24:53 +0200 Subject: [PATCH] provide chat options --- .../stendhal/common/constants/Events.java | 2 + .../server/core/engine/RPClassGenerator.java | 4 + .../server/entity/npc/fsm/Engine.java | 13 ++- .../server/entity/player/PlayerRPClass.java | 1 + .../server/events/ChatOptionsEvent.java | 91 +++++++++++++++++++ 5 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 src/games/stendhal/server/events/ChatOptionsEvent.java diff --git a/src/games/stendhal/common/constants/Events.java b/src/games/stendhal/common/constants/Events.java index 5a3c5404a3c..4ff0ce3c781 100644 --- a/src/games/stendhal/common/constants/Events.java +++ b/src/games/stendhal/common/constants/Events.java @@ -62,4 +62,6 @@ public final class Events { public static final String BESTIARY = Actions.BESTIARY; public static final String OUTFIT_LIST = "show_outfit_list"; + + public static final String CHAT_OPTIONS = "chat_options"; } diff --git a/src/games/stendhal/server/core/engine/RPClassGenerator.java b/src/games/stendhal/server/core/engine/RPClassGenerator.java index a083ffe994e..1d74457d268 100644 --- a/src/games/stendhal/server/core/engine/RPClassGenerator.java +++ b/src/games/stendhal/server/core/engine/RPClassGenerator.java @@ -66,6 +66,7 @@ import games.stendhal.server.events.BestiaryEvent; import games.stendhal.server.events.BuddyLoginEvent; import games.stendhal.server.events.BuddyLogoutEvent; +import games.stendhal.server.events.ChatOptionsEvent; import games.stendhal.server.events.ExamineEvent; import games.stendhal.server.events.GlobalVisualEffectEvent; import games.stendhal.server.events.GroupChangeEvent; @@ -284,6 +285,9 @@ public void createRPClassesWithoutBaking() { if (!RPClass.hasRPClass("healed")) { HealedEvent.generateRPClass(); } + if (!RPClass.hasRPClass(Events.CHAT_OPTIONS)) { + ChatOptionsEvent.generateRPClass(); + } if (!RPClass.hasRPClass(Events.IMAGE)) { ImageEffectEvent.generateRPClass(); } diff --git a/src/games/stendhal/server/entity/npc/fsm/Engine.java b/src/games/stendhal/server/entity/npc/fsm/Engine.java index ca37cff5870..9734b3d16cc 100644 --- a/src/games/stendhal/server/entity/npc/fsm/Engine.java +++ b/src/games/stendhal/server/entity/npc/fsm/Engine.java @@ -32,6 +32,7 @@ import games.stendhal.server.entity.npc.EventRaiser; import games.stendhal.server.entity.npc.SpeakerNPC; import games.stendhal.server.entity.player.Player; +import games.stendhal.server.events.ChatOptionsEvent; /** * a finite state machine. @@ -602,15 +603,17 @@ private void executeTransition(final Player player, final Sentence sentence, fin } currentState = nextState; - if (currentState == ConversationStates.ATTENDING) { - speakerNPC.setIdea("attending"); - } else if (currentState != ConversationStates.IDLE) { - speakerNPC.setIdea("awaiting"); - } + if (currentState == ConversationStates.ATTENDING) { + speakerNPC.setIdea("attending"); + } else if (currentState != ConversationStates.IDLE) { + speakerNPC.setIdea("awaiting"); + } if (trans.getAction() != null) { trans.getAction().fire(player, sentence, new EventRaiser(speakerNPC)); } + player.addEvent(new ChatOptionsEvent(speakerNPC, player, currentState)); + player.notifyWorldAboutChanges(); speakerNPC.notifyWorldAboutChanges(); } diff --git a/src/games/stendhal/server/entity/player/PlayerRPClass.java b/src/games/stendhal/server/entity/player/PlayerRPClass.java index 11a225c77f7..d309f9745a5 100644 --- a/src/games/stendhal/server/entity/player/PlayerRPClass.java +++ b/src/games/stendhal/server/entity/player/PlayerRPClass.java @@ -40,6 +40,7 @@ static void generateRPClass() { player.addAttribute("text", Type.LONG_STRING, Definition.VOLATILE); // player.addAttribute("private_text", Type.LONG_STRING, (byte) (Definition.HIDDEN | Definition.VOLATILE)); + player.addRPEvent(Events.CHAT_OPTIONS, Definition.PRIVATE); player.addRPEvent(Events.PRIVATE_TEXT, Definition.PRIVATE); player.addRPEvent(Events.PLAYER_LOGGED_ON, Definition.PRIVATE); player.addRPEvent(Events.PLAYER_LOGGED_OUT, Definition.PRIVATE); diff --git a/src/games/stendhal/server/events/ChatOptionsEvent.java b/src/games/stendhal/server/events/ChatOptionsEvent.java new file mode 100644 index 00000000000..349087d3fac --- /dev/null +++ b/src/games/stendhal/server/events/ChatOptionsEvent.java @@ -0,0 +1,91 @@ +/*************************************************************************** + * (C) Copyright 2023-2023 - Stendhal * + *************************************************************************** + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +package games.stendhal.server.events; + +import java.util.LinkedList; +import java.util.List; + +import com.google.common.base.Joiner; + +import games.stendhal.common.constants.Events; +import games.stendhal.common.parser.ConversationParser; +import games.stendhal.common.parser.Expression; +import games.stendhal.common.parser.Sentence; +import games.stendhal.server.entity.npc.ConversationStates; +import games.stendhal.server.entity.npc.SpeakerNPC; +import games.stendhal.server.entity.npc.fsm.Transition; +import games.stendhal.server.entity.player.Player; +import marauroa.common.game.Definition.Type; +import marauroa.common.game.RPClass; +import marauroa.common.game.RPEvent; + +public class ChatOptionsEvent extends RPEvent { + + private static final String NPC = "npc"; + private static final String OPTIONS = "options"; + + public ChatOptionsEvent(SpeakerNPC npc, Player player, ConversationStates currentState) { + super(Events.CHAT_OPTIONS); + put(NPC, npc.getName()); + + List chatOptions = buildChatOptions(npc, player, currentState); + put(OPTIONS, Joiner.on("|~|").join(chatOptions)); + } + + /** + * builds a list of the available chat options + * + * @param npc SpeakerNPC the player is talking to + * @param player player (to check conditions) + * @param currentState current state of the SpeakerNPC's state machine + * @return list of chat options + */ + private List buildChatOptions(SpeakerNPC npc, Player player, ConversationStates currentState) { + List res = new LinkedList<>(); + Sentence sentence = ConversationParser.parse(""); + + final List transitions = npc.getTransitions(); + for (final Transition transition : transitions) { + if (transition.getState() != currentState) { + continue; + } + + for(Expression expr : transition.getTriggers()) { + if (transition.getCondition() != null) { + if (!transition.getCondition().fire(player, sentence, npc)) { + continue; + } + } + + String trigger = expr.getNormalized(); + String options = ""; + if (trigger.equals("buy") || trigger.equals("sell") || trigger.equals("")) { + options = "params"; + } + res.add(trigger + "|*|" + trigger + "|*|" + options); + break; + } + } + + + return res; + } + + /** + * Creates the rpclass. + */ + public static void generateRPClass() { + final RPClass rpclass = new RPClass(Events.CHAT_OPTIONS); + rpclass.addAttribute(NPC, Type.STRING); + rpclass.addAttribute(OPTIONS, Type.VERY_LONG_STRING); + } +}