From 52b830ed2039be513ec43552b57dadc9f79ceb8b Mon Sep 17 00:00:00 2001 From: Ziggy Date: Wed, 6 Jan 2021 08:23:44 +0100 Subject: [PATCH] Added conversations framework and enough functionality to join and leave the rebellion in Anchorhead on Tatooine #12 --- pswgcommon | 2 +- .../rebel_recruiter/change_status.json | 33 ++ .../rebel_recruiter/imperial_root.json | 16 + .../rebel_recruiter/neutral_join.json | 31 ++ .../rebel_recruiter/neutral_join_accept.json | 23 ++ .../rebel_recruiter/neutral_join_decline.json | 16 + .../rebel_recruiter/neutral_root.json | 24 ++ .../rebel_recruiter/normal_root.json | 33 ++ .../conversation/rebel_recruiter/resign.json | 24 ++ .../rebel_recruiter/resign_accept.json | 23 ++ .../conversation/spawn_conversation_map.msdb | 3 + serverdata/nge/conversation/spawn_tat_3.sdb | 5 + .../conversation/ConversationIntents.kt | 51 +++ .../events/ChangePlayerFactionEvent.java | 52 +++ .../conversation/model/Conversation.java | 98 +++++ .../gameplay/conversation/model/Event.java | 34 ++ .../conversation/model/PlayerResponse.java | 47 +++ .../conversation/model/Requirement.java | 35 ++ .../requirements/FactionNameRequirement.java | 53 +++ .../FactionStatusRequirement.java | 51 +++ .../data/server_info/loader/DataLoader.kt | 36 +- .../data/server_info/loader/ServerData.kt | 2 + .../conversation/ConversationLoader.java | 210 +++++++++++ .../loader/conversation/EventParser.java | 35 ++ .../conversation/RequirementParser.java | 35 ++ .../ChangePlayerFactionEventParser.java | 42 +++ .../FactionNameRequirementParser.java | 42 +++ .../FactionStatusRequirementParser.java | 70 ++++ .../NpcConversationSelectCmdCallback.java | 42 +++ .../NpcConversationStartCmdCallback.java | 43 +++ .../NpcConversationStopCmdCallback.java | 42 +++ .../services/gameplay/GameplayManager.java | 2 + .../conversation/ConversationService.java | 338 ++++++++++++++++++ .../commands/CommandExecutionService.java | 34 ++ 34 files changed, 1618 insertions(+), 9 deletions(-) create mode 100644 serverdata/nge/conversation/rebel_recruiter/change_status.json create mode 100644 serverdata/nge/conversation/rebel_recruiter/imperial_root.json create mode 100644 serverdata/nge/conversation/rebel_recruiter/neutral_join.json create mode 100644 serverdata/nge/conversation/rebel_recruiter/neutral_join_accept.json create mode 100644 serverdata/nge/conversation/rebel_recruiter/neutral_join_decline.json create mode 100644 serverdata/nge/conversation/rebel_recruiter/neutral_root.json create mode 100644 serverdata/nge/conversation/rebel_recruiter/normal_root.json create mode 100644 serverdata/nge/conversation/rebel_recruiter/resign.json create mode 100644 serverdata/nge/conversation/rebel_recruiter/resign_accept.json create mode 100644 serverdata/nge/conversation/spawn_conversation_map.msdb create mode 100644 serverdata/nge/conversation/spawn_tat_3.sdb create mode 100644 src/main/java/com/projectswg/holocore/intents/gameplay/conversation/ConversationIntents.kt create mode 100644 src/main/java/com/projectswg/holocore/resources/gameplay/conversation/events/ChangePlayerFactionEvent.java create mode 100644 src/main/java/com/projectswg/holocore/resources/gameplay/conversation/model/Conversation.java create mode 100644 src/main/java/com/projectswg/holocore/resources/gameplay/conversation/model/Event.java create mode 100644 src/main/java/com/projectswg/holocore/resources/gameplay/conversation/model/PlayerResponse.java create mode 100644 src/main/java/com/projectswg/holocore/resources/gameplay/conversation/model/Requirement.java create mode 100644 src/main/java/com/projectswg/holocore/resources/gameplay/conversation/requirements/FactionNameRequirement.java create mode 100644 src/main/java/com/projectswg/holocore/resources/gameplay/conversation/requirements/FactionStatusRequirement.java create mode 100644 src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/ConversationLoader.java create mode 100644 src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/EventParser.java create mode 100644 src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/RequirementParser.java create mode 100644 src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/events/ChangePlayerFactionEventParser.java create mode 100644 src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/requirements/FactionNameRequirementParser.java create mode 100644 src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/requirements/FactionStatusRequirementParser.java create mode 100644 src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/conversation/NpcConversationSelectCmdCallback.java create mode 100644 src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/conversation/NpcConversationStartCmdCallback.java create mode 100644 src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/conversation/NpcConversationStopCmdCallback.java create mode 100644 src/main/java/com/projectswg/holocore/services/gameplay/conversation/ConversationService.java diff --git a/pswgcommon b/pswgcommon index cfd1d3e64..aec2c464d 160000 --- a/pswgcommon +++ b/pswgcommon @@ -1 +1 @@ -Subproject commit cfd1d3e6442dd2915ceb59d65d4cfe7392038147 +Subproject commit aec2c464dec92e5864302d3b56411ce981c2396a diff --git a/serverdata/nge/conversation/rebel_recruiter/change_status.json b/serverdata/nge/conversation/rebel_recruiter/change_status.json new file mode 100644 index 000000000..49779d2a6 --- /dev/null +++ b/serverdata/nge/conversation/rebel_recruiter/change_status.json @@ -0,0 +1,33 @@ +{ + "npcMessage": { + "file": "conversation/faction_recruiter_rebel", + "key": "s_50" + }, + "playerResponses": [ + { + "playerMessage": { + "file": "conversation/faction_recruiter_rebel", + "key": "s_74" + }, + "next": "rebel_recruiter/resign" + } + ], + "requirements": [ + { + "type": "faction_name", + "args": { + "faction": "rebel" + } + }, + { + "type": "faction_status", + "args": { + "statuses": [ + "combatant", + "special_forces" + ] + } + } + ], + "events": [] +} \ No newline at end of file diff --git a/serverdata/nge/conversation/rebel_recruiter/imperial_root.json b/serverdata/nge/conversation/rebel_recruiter/imperial_root.json new file mode 100644 index 000000000..944e44434 --- /dev/null +++ b/serverdata/nge/conversation/rebel_recruiter/imperial_root.json @@ -0,0 +1,16 @@ +{ + "npcMessage": { + "file": "conversation/faction_recruiter_rebel", + "key": "s_230" + }, + "playerResponses": [], + "requirements": [ + { + "type": "faction_name", + "args": { + "faction": "imperial" + } + } + ], + "events": [] +} \ No newline at end of file diff --git a/serverdata/nge/conversation/rebel_recruiter/neutral_join.json b/serverdata/nge/conversation/rebel_recruiter/neutral_join.json new file mode 100644 index 000000000..00f2bf062 --- /dev/null +++ b/serverdata/nge/conversation/rebel_recruiter/neutral_join.json @@ -0,0 +1,31 @@ +{ + "npcMessage": { + "file": "conversation/faction_recruiter_rebel", + "key": "s_352" + }, + "playerResponses": [ + { + "playerMessage": { + "file": "conversation/faction_recruiter_rebel", + "key": "s_354" + }, + "next": "rebel_recruiter/neutral_join_accept" + }, + { + "playerMessage": { + "file": "conversation/faction_recruiter_rebel", + "key": "s_360" + }, + "next": "rebel_recruiter/neutral_join_decline" + } + ], + "requirements": [ + { + "type": "faction_name", + "args": { + "faction": "neutral" + } + } + ], + "events": [] +} \ No newline at end of file diff --git a/serverdata/nge/conversation/rebel_recruiter/neutral_join_accept.json b/serverdata/nge/conversation/rebel_recruiter/neutral_join_accept.json new file mode 100644 index 000000000..8a37ae4c5 --- /dev/null +++ b/serverdata/nge/conversation/rebel_recruiter/neutral_join_accept.json @@ -0,0 +1,23 @@ +{ + "npcMessage": { + "file": "conversation/faction_recruiter_rebel", + "key": "s_99" + }, + "playerResponses": [], + "requirements": [ + { + "type": "faction_name", + "args": { + "faction": "neutral" + } + } + ], + "events": [ + { + "type": "faction_change", + "args": { + "faction": "rebel" + } + } + ] +} \ No newline at end of file diff --git a/serverdata/nge/conversation/rebel_recruiter/neutral_join_decline.json b/serverdata/nge/conversation/rebel_recruiter/neutral_join_decline.json new file mode 100644 index 000000000..62a66987f --- /dev/null +++ b/serverdata/nge/conversation/rebel_recruiter/neutral_join_decline.json @@ -0,0 +1,16 @@ +{ + "npcMessage": { + "file": "conversation/faction_recruiter_rebel", + "key": "s_362" + }, + "playerResponses": [], + "requirements": [ + { + "type": "faction_name", + "args": { + "faction": "neutral" + } + } + ], + "events": [] +} \ No newline at end of file diff --git a/serverdata/nge/conversation/rebel_recruiter/neutral_root.json b/serverdata/nge/conversation/rebel_recruiter/neutral_root.json new file mode 100644 index 000000000..2e4a0160b --- /dev/null +++ b/serverdata/nge/conversation/rebel_recruiter/neutral_root.json @@ -0,0 +1,24 @@ +{ + "npcMessage": { + "file": "conversation/faction_recruiter_rebel", + "key": "s_334" + }, + "playerResponses": [ + { + "playerMessage": { + "file": "conversation/faction_recruiter_rebel", + "key": "s_348" + }, + "next": "rebel_recruiter/neutral_join" + } + ], + "requirements": [ + { + "type": "faction_name", + "args": { + "faction": "neutral" + } + } + ], + "events": [] +} \ No newline at end of file diff --git a/serverdata/nge/conversation/rebel_recruiter/normal_root.json b/serverdata/nge/conversation/rebel_recruiter/normal_root.json new file mode 100644 index 000000000..17c144b1a --- /dev/null +++ b/serverdata/nge/conversation/rebel_recruiter/normal_root.json @@ -0,0 +1,33 @@ +{ + "npcMessage": { + "file": "conversation/faction_recruiter_rebel", + "key": "s_216" + }, + "playerResponses": [ + { + "playerMessage": { + "file": "conversation/faction_recruiter_rebel", + "key": "s_49" + }, + "next": "rebel_recruiter/change_status" + } + ], + "requirements": [ + { + "type": "faction_name", + "args": { + "faction": "rebel" + } + }, + { + "type": "faction_status", + "args": { + "statuses": [ + "combatant", + "special_forces" + ] + } + } + ], + "events": [] +} \ No newline at end of file diff --git a/serverdata/nge/conversation/rebel_recruiter/resign.json b/serverdata/nge/conversation/rebel_recruiter/resign.json new file mode 100644 index 000000000..8f6c30ac0 --- /dev/null +++ b/serverdata/nge/conversation/rebel_recruiter/resign.json @@ -0,0 +1,24 @@ +{ + "npcMessage": { + "file": "conversation/faction_recruiter_rebel", + "key": "s_76" + }, + "playerResponses": [ + { + "playerMessage": { + "file": "conversation/faction_recruiter_rebel", + "key": "s_78" + }, + "next": "rebel_recruiter/resign_accept" + } + ], + "requirements": [ + { + "type": "faction_name", + "args": { + "faction": "rebel" + } + } + ], + "events": [] +} \ No newline at end of file diff --git a/serverdata/nge/conversation/rebel_recruiter/resign_accept.json b/serverdata/nge/conversation/rebel_recruiter/resign_accept.json new file mode 100644 index 000000000..b6e28d6b1 --- /dev/null +++ b/serverdata/nge/conversation/rebel_recruiter/resign_accept.json @@ -0,0 +1,23 @@ +{ + "npcMessage": { + "file": "conversation/faction_recruiter_rebel", + "key": "s_80" + }, + "playerResponses": [], + "requirements": [ + { + "type": "faction_name", + "args": { + "faction": "rebel" + } + } + ], + "events": [ + { + "type": "faction_change", + "args": { + "faction": "neutral" + } + } + ] +} \ No newline at end of file diff --git a/serverdata/nge/conversation/spawn_conversation_map.msdb b/serverdata/nge/conversation/spawn_conversation_map.msdb new file mode 100644 index 000000000..0eeb2dd64 --- /dev/null +++ b/serverdata/nge/conversation/spawn_conversation_map.msdb @@ -0,0 +1,3 @@ +file enabled +TEXT BOOLEAN +spawn_tat_3.sdb TRUE \ No newline at end of file diff --git a/serverdata/nge/conversation/spawn_tat_3.sdb b/serverdata/nge/conversation/spawn_tat_3.sdb new file mode 100644 index 000000000..4a2bb9cca --- /dev/null +++ b/serverdata/nge/conversation/spawn_tat_3.sdb @@ -0,0 +1,5 @@ +spawn_id conversation_id +TEXT TEXT +spawn_tat_3 rebel_recruiter/imperial_root +spawn_tat_3 rebel_recruiter/neutral_root +spawn_tat_3 rebel_recruiter/normal_root \ No newline at end of file diff --git a/src/main/java/com/projectswg/holocore/intents/gameplay/conversation/ConversationIntents.kt b/src/main/java/com/projectswg/holocore/intents/gameplay/conversation/ConversationIntents.kt new file mode 100644 index 000000000..c305c3fc9 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/intents/gameplay/conversation/ConversationIntents.kt @@ -0,0 +1,51 @@ +/*********************************************************************************** + * Copyright (c) 2021 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ + +@file:Suppress("NOTHING_TO_INLINE") +package com.projectswg.holocore.intents.gameplay.conversation + +import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject +import com.projectswg.holocore.resources.support.objects.swg.custom.AIObject +import me.joshlarson.jlcommon.control.Intent + +data class StartConversationIntent(val starter: CreatureObject, val npc: AIObject): Intent() { + companion object { + @JvmStatic inline fun broadcast(starter: CreatureObject, npc: AIObject) = StartConversationIntent(starter, npc).broadcast() + } +} + +data class ProgressConversationIntent(val starter: CreatureObject, val selection: Int): Intent() { + companion object { + @JvmStatic inline fun broadcast(starter: CreatureObject, selection: Int) = ProgressConversationIntent(starter, selection).broadcast() + } +} + +data class StopConversationIntent(val creatureObject: CreatureObject): Intent() { + companion object { + @JvmStatic inline fun broadcast(creatureObject: CreatureObject) = StopConversationIntent(creatureObject).broadcast() + } +} \ No newline at end of file diff --git a/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/events/ChangePlayerFactionEvent.java b/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/events/ChangePlayerFactionEvent.java new file mode 100644 index 000000000..8c7a030ec --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/events/ChangePlayerFactionEvent.java @@ -0,0 +1,52 @@ +/*********************************************************************************** + * Copyright (c) 2021 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.gameplay.conversation.events; + +import com.projectswg.common.data.encodables.tangible.PvpStatus; +import com.projectswg.holocore.intents.gameplay.gcw.faction.FactionIntent; +import com.projectswg.holocore.resources.gameplay.conversation.model.Event; +import com.projectswg.holocore.resources.support.data.server_info.loader.ServerData; +import com.projectswg.holocore.resources.support.data.server_info.loader.combat.FactionLoader; +import com.projectswg.holocore.resources.support.global.player.Player; +import com.projectswg.holocore.resources.support.objects.swg.custom.AIObject; + +public class ChangePlayerFactionEvent implements Event { + + private final String factionName; + + public ChangePlayerFactionEvent(String factionName) { + this.factionName = factionName; + } + + @Override + public void trigger(Player player, AIObject npc) { + FactionLoader.Faction faction = ServerData.INSTANCE.getFactions().getFaction(factionName); + + FactionIntent.broadcastUpdateFaction(player.getCreatureObject(), faction); + FactionIntent.broadcastUpdateStatus(player.getCreatureObject(), PvpStatus.COMBATANT); + } +} diff --git a/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/model/Conversation.java b/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/model/Conversation.java new file mode 100644 index 000000000..9b3aa6f34 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/model/Conversation.java @@ -0,0 +1,98 @@ +/*********************************************************************************** + * Copyright (c) 2021 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.gameplay.conversation.model; + +import com.projectswg.common.data.encodables.oob.ProsePackage; +import com.projectswg.holocore.resources.support.global.player.Player; + +import java.util.ArrayList; +import java.util.List; + +public class Conversation { + + private final String id; + private ProsePackage npcMessage; + private final List playerResponses; + private final List events; + private final List requirements; + + public Conversation(String id) { + this.id = id; + playerResponses = new ArrayList<>(); + events = new ArrayList<>(); + requirements = new ArrayList<>(); + } + + public String getId() { + return id; + } + + public ProsePackage getNpcMessage() { + return npcMessage; + } + + public void setNpcMessage(ProsePackage npcMessage) { + this.npcMessage = npcMessage; + } + + public void addPlayerResponse(PlayerResponse playerResponse) { + playerResponses.add(playerResponse); + } + + public void addEvent(Event event) { + events.add(event); + } + + public void addRequirement(Requirement requirement) { + requirements.add(requirement); + } + + public List getPlayerResponses() { + return playerResponses; + } + + public boolean isAllowed(Player player) { + for (Requirement requirement : requirements) { + boolean available = requirement.test(player); + + if (!available) { + return false; + } + } + + return true; + } + + public List getEvents() { + return events; + } + + @Override + public String toString() { + return "Conversation{" + "id='" + id + '\'' + '}'; + } +} diff --git a/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/model/Event.java b/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/model/Event.java new file mode 100644 index 000000000..a70fb6444 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/model/Event.java @@ -0,0 +1,34 @@ +/*********************************************************************************** + * Copyright (c) 2021 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.gameplay.conversation.model; + +import com.projectswg.holocore.resources.support.global.player.Player; +import com.projectswg.holocore.resources.support.objects.swg.custom.AIObject; + +public interface Event { + void trigger(Player player, AIObject npc); +} diff --git a/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/model/PlayerResponse.java b/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/model/PlayerResponse.java new file mode 100644 index 000000000..1a2c55149 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/model/PlayerResponse.java @@ -0,0 +1,47 @@ +/*********************************************************************************** + * Copyright (c) 2021 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.gameplay.conversation.model; + +import com.projectswg.common.data.encodables.oob.ProsePackage; + +public class PlayerResponse { + private final ProsePackage prosePackage; + private final String next; + + public PlayerResponse(ProsePackage prosePackage, String next) { + this.prosePackage = prosePackage; + this.next = next; + } + + public ProsePackage getProsePackage() { + return prosePackage; + } + + public String getNext() { + return next; + } +} diff --git a/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/model/Requirement.java b/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/model/Requirement.java new file mode 100644 index 000000000..a947118e8 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/model/Requirement.java @@ -0,0 +1,35 @@ +/*********************************************************************************** + * Copyright (c) 2021 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.gameplay.conversation.model; + +import com.projectswg.holocore.resources.support.global.player.Player; + +import java.util.function.Predicate; + +public interface Requirement extends Predicate { + +} diff --git a/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/requirements/FactionNameRequirement.java b/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/requirements/FactionNameRequirement.java new file mode 100644 index 000000000..d10a4d096 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/requirements/FactionNameRequirement.java @@ -0,0 +1,53 @@ +/*********************************************************************************** + * Copyright (c) 2021 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.gameplay.conversation.requirements; + +import com.projectswg.holocore.resources.gameplay.conversation.model.Requirement; +import com.projectswg.holocore.resources.support.data.server_info.loader.ServerData; +import com.projectswg.holocore.resources.support.data.server_info.loader.combat.FactionLoader; +import com.projectswg.holocore.resources.support.global.player.Player; +import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject; + +import java.util.Objects; + +public class FactionNameRequirement implements Requirement { + + private final String factionName; + + public FactionNameRequirement(String factionName) { + this.factionName = factionName; + } + + @Override + public boolean test(Player player) { + CreatureObject creatureObject = player.getCreatureObject(); + FactionLoader.Faction currentFaction = creatureObject.getFaction(); + FactionLoader.Faction requiredFaction = ServerData.INSTANCE.getFactions().getFaction(factionName); + + return Objects.equals(currentFaction, requiredFaction); + } +} diff --git a/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/requirements/FactionStatusRequirement.java b/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/requirements/FactionStatusRequirement.java new file mode 100644 index 000000000..2943b435c --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/gameplay/conversation/requirements/FactionStatusRequirement.java @@ -0,0 +1,51 @@ +/*********************************************************************************** + * Copyright (c) 2021 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.gameplay.conversation.requirements; + +import com.projectswg.common.data.encodables.tangible.PvpStatus; +import com.projectswg.holocore.resources.gameplay.conversation.model.Requirement; +import com.projectswg.holocore.resources.support.global.player.Player; +import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject; + +import java.util.Collection; + +public class FactionStatusRequirement implements Requirement { + + private final Collection allowedPvpStatuses; + + public FactionStatusRequirement(Collection allowedPvpStatuses) { + this.allowedPvpStatuses = allowedPvpStatuses; + } + + @Override + public boolean test(Player player) { + CreatureObject creatureObject = player.getCreatureObject(); + PvpStatus pvpStatus = creatureObject.getPvpStatus(); + + return allowedPvpStatuses.contains(pvpStatus); + } +} diff --git a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/DataLoader.kt b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/DataLoader.kt index 03c53761e..e314b0fc7 100644 --- a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/DataLoader.kt +++ b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/DataLoader.kt @@ -1,15 +1,34 @@ +/*********************************************************************************** + * Copyright (c) 2021 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ package com.projectswg.holocore.resources.support.data.server_info.loader +import com.projectswg.holocore.resources.support.data.server_info.loader.conversation.ConversationLoader import com.projectswg.holocore.resources.support.data.server_info.loader.npc.* -import me.joshlarson.jlcommon.log.Log import java.io.IOException -import java.lang.ref.Reference -import java.lang.ref.SoftReference -import java.lang.ref.WeakReference -import java.util.concurrent.ConcurrentHashMap -import java.util.function.Function -import java.util.function.Supplier -import kotlin.reflect.KProperty abstract class DataLoader { @@ -61,6 +80,7 @@ abstract class DataLoader { fun terrainLevels(): TerrainLevelLoader = ServerData.terrainLevels fun noSpawnZones(): NoSpawnZoneLoader = ServerData.noSpawnZones fun gcwRegionLoader(): GcwRegionLoader = ServerData.gcwRegionLoader + fun conversationLoader(): ConversationLoader = ServerData.conversationLoader } diff --git a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/ServerData.kt b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/ServerData.kt index 99959b775..080bd109a 100644 --- a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/ServerData.kt +++ b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/ServerData.kt @@ -28,6 +28,7 @@ package com.projectswg.holocore.resources.support.data.server_info.loader import com.projectswg.holocore.resources.support.data.server_info.loader.combat.FactionLoader +import com.projectswg.holocore.resources.support.data.server_info.loader.conversation.ConversationLoader import com.projectswg.holocore.resources.support.data.server_info.loader.npc.* import me.joshlarson.jlcommon.log.Log import java.io.IOException @@ -97,6 +98,7 @@ object ServerData { val terrainLevels by SoftDataLoaderDelegate(::TerrainLevelLoader) val noSpawnZones by SoftDataLoaderDelegate(::NoSpawnZoneLoader) val gcwRegionLoader by SoftDataLoaderDelegate(::GcwRegionLoader) + val conversationLoader by SoftDataLoaderDelegate(::ConversationLoader) private class WeakDataLoaderDelegate(loaderCreator: () -> T): DataLoaderDelegate(::WeakReference, loaderCreator) private class SoftDataLoaderDelegate(loaderCreator: () -> T): DataLoaderDelegate(::SoftReference, loaderCreator) diff --git a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/ConversationLoader.java b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/ConversationLoader.java new file mode 100644 index 000000000..33b568348 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/ConversationLoader.java @@ -0,0 +1,210 @@ +/*********************************************************************************** + * Copyright (c) 2021 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.support.data.server_info.loader.conversation; + +import com.projectswg.common.data.encodables.oob.ProsePackage; +import com.projectswg.holocore.resources.gameplay.conversation.model.Conversation; +import com.projectswg.holocore.resources.gameplay.conversation.model.Event; +import com.projectswg.holocore.resources.gameplay.conversation.model.PlayerResponse; +import com.projectswg.holocore.resources.gameplay.conversation.model.Requirement; +import com.projectswg.holocore.resources.support.data.server_info.SdbLoader; +import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader; +import com.projectswg.holocore.resources.support.data.server_info.loader.conversation.events.ChangePlayerFactionEventParser; +import com.projectswg.holocore.resources.support.data.server_info.loader.conversation.requirements.FactionNameRequirementParser; +import com.projectswg.holocore.resources.support.data.server_info.loader.conversation.requirements.FactionStatusRequirementParser; +import me.joshlarson.jlcommon.log.Log; +import me.joshlarson.json.JSON; +import me.joshlarson.json.JSONObject; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.*; +import java.util.stream.Collectors; + +public class ConversationLoader extends DataLoader { + + private final Map> spawnConversationsMap; + private final Map> requirementParserMap; + private final Map> eventParserMap; + + public ConversationLoader() { + spawnConversationsMap = new HashMap<>(); + requirementParserMap = new HashMap<>(); + eventParserMap = new HashMap<>(); + } + + @Nullable + public Conversation getConversation(String conversationId) { + try { + InputStream inputStream = new FileInputStream("serverdata/nge/conversation/" + conversationId + ".json"); + JSONObject jsonObject = JSON.readObject(inputStream); + + return readConversation(conversationId, jsonObject); + } catch (Throwable t) { + Log.e("Unable to load conversation by ID %s", conversationId); + Log.e(t); + return null; + } + } + + @NotNull + public List getInitialConversations(String spawnId) { + if (!spawnConversationsMap.containsKey(spawnId)) { + return Collections.emptyList(); + } + + Collection conversationIds = spawnConversationsMap.get(spawnId); + + return conversationIds.stream() + .map(this::getConversation) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + + @NotNull + public Collection getConversationIds(String spawnId) { + return spawnConversationsMap.getOrDefault(spawnId, Collections.emptyList()); + } + + private Conversation readConversation(String conversationId, JSONObject jsonObject) { + Conversation conversation = new Conversation(conversationId); + + Map npcMessageObj = (Map) jsonObject.get("npcMessage"); + + ProsePackage npcMessage = readProsePackage(npcMessageObj); + conversation.setNpcMessage(npcMessage); + + List playerResponseObjs = (List) jsonObject.get("playerResponses"); + List playerResponses = readPlayerResponses(playerResponseObjs); + + for (PlayerResponse playerResponse : playerResponses) { + conversation.addPlayerResponse(playerResponse); + } + + List requirementObjs = (List) jsonObject.get("requirements"); + List requirements = readRequirements(requirementObjs); + + for (Requirement requirement : requirements) { + conversation.addRequirement(requirement); + } + + List eventObjs = (List) jsonObject.get("events"); + List events = readEvents(eventObjs); + + for (Event event : events) { + conversation.addEvent(event); + } + + return conversation; + } + + private ProsePackage readProsePackage(Map object) { + String file = object.get("file").toString(); + String key = object.get("key").toString(); + + return new ProsePackage(file, key); + } + + private List readPlayerResponses(List playerResponseObjs) { + List playerResponses = new ArrayList<>(); + + for (JSONObject playerResponseObj : playerResponseObjs) { + Map playerMessageRaw = (Map) playerResponseObj.get("playerMessage"); + ProsePackage prosePackage = readProsePackage(playerMessageRaw); + + String nextConversationId = (String) playerResponseObj.get("next"); + + PlayerResponse playerResponse = new PlayerResponse(prosePackage, nextConversationId); + + playerResponses.add(playerResponse); + } + + return playerResponses; + } + + private List readRequirements(List requirementObjs) { + List requirements = new ArrayList<>(); + + for (JSONObject requirementObj : requirementObjs) { + String type = (String) requirementObj.get("type"); + Map args = (Map) requirementObj.get("args"); + RequirementParser requirementParser = requirementParserMap.get(type); + Requirement requirement = requirementParser.parse(args); + + requirements.add(requirement); + } + + return requirements; + } + + private List readEvents(List eventObjs) { + List events = new ArrayList<>(); + + for (JSONObject eventObj : eventObjs) { + String type = (String) eventObj.get("type"); + Map args = (Map) eventObj.get("args"); + EventParser eventParser = eventParserMap.get(type); + Event event = eventParser.parse(args); + + events.add(event); + } + + return events; + } + + @Override + public void load() throws IOException { + initRequirementParsers(); + initEventParsers(); + loadSpawnToConversations(); + } + + private void initRequirementParsers() { + requirementParserMap.put("faction_name", new FactionNameRequirementParser()); + requirementParserMap.put("faction_status", new FactionStatusRequirementParser()); + } + + private void initEventParsers() { + eventParserMap.put("faction_change", new ChangePlayerFactionEventParser()); + } + + private void loadSpawnToConversations() throws IOException { + try (SdbLoader.SdbResultSet set = SdbLoader.load(new File("serverdata/nge/conversation/spawn_conversation_map.msdb"))) { + while (set.next()) { + String spawnId = set.getText("spawn_id"); + String conversationId = set.getText("conversation_id"); + + spawnConversationsMap.computeIfAbsent(spawnId, a -> new ArrayList<>()).add(conversationId); + } + } + } + +} diff --git a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/EventParser.java b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/EventParser.java new file mode 100644 index 000000000..c886a325c --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/EventParser.java @@ -0,0 +1,35 @@ +/*********************************************************************************** + * Copyright (c) 2018 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.support.data.server_info.loader.conversation; + +import com.projectswg.holocore.resources.gameplay.conversation.model.Event; + +import java.util.Map; + +public interface EventParser { + T parse(Map args); +} diff --git a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/RequirementParser.java b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/RequirementParser.java new file mode 100644 index 000000000..9a2857d32 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/RequirementParser.java @@ -0,0 +1,35 @@ +/*********************************************************************************** + * Copyright (c) 2018 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.support.data.server_info.loader.conversation; + +import com.projectswg.holocore.resources.gameplay.conversation.model.Requirement; + +import java.util.Map; + +public interface RequirementParser { + T parse(Map args); +} diff --git a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/events/ChangePlayerFactionEventParser.java b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/events/ChangePlayerFactionEventParser.java new file mode 100644 index 000000000..c84103c44 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/events/ChangePlayerFactionEventParser.java @@ -0,0 +1,42 @@ +/*********************************************************************************** + * Copyright (c) 2018 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.support.data.server_info.loader.conversation.events; + +import com.projectswg.holocore.resources.gameplay.conversation.events.ChangePlayerFactionEvent; +import com.projectswg.holocore.resources.support.data.server_info.loader.conversation.EventParser; + +import java.util.Map; + +public class ChangePlayerFactionEventParser implements EventParser { + + @Override + public ChangePlayerFactionEvent parse(Map args) { + String factionName = (String) args.get("faction"); + + return new ChangePlayerFactionEvent(factionName); + } +} diff --git a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/requirements/FactionNameRequirementParser.java b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/requirements/FactionNameRequirementParser.java new file mode 100644 index 000000000..2df8b5e06 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/requirements/FactionNameRequirementParser.java @@ -0,0 +1,42 @@ +/*********************************************************************************** + * Copyright (c) 2018 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.support.data.server_info.loader.conversation.requirements; + +import com.projectswg.holocore.resources.gameplay.conversation.requirements.FactionNameRequirement; +import com.projectswg.holocore.resources.support.data.server_info.loader.conversation.RequirementParser; + +import java.util.Map; + +public class FactionNameRequirementParser implements RequirementParser { + + @Override + public FactionNameRequirement parse(Map args) { + String factionName = (String) args.get("faction"); + + return new FactionNameRequirement(factionName); + } +} diff --git a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/requirements/FactionStatusRequirementParser.java b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/requirements/FactionStatusRequirementParser.java new file mode 100644 index 000000000..de88d0ad6 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/conversation/requirements/FactionStatusRequirementParser.java @@ -0,0 +1,70 @@ +/*********************************************************************************** + * Copyright (c) 2021 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.support.data.server_info.loader.conversation.requirements; + +import com.projectswg.common.data.encodables.tangible.PvpStatus; +import com.projectswg.holocore.resources.gameplay.conversation.requirements.FactionStatusRequirement; +import com.projectswg.holocore.resources.support.data.server_info.loader.conversation.RequirementParser; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class FactionStatusRequirementParser implements RequirementParser { + + private static final Map STATUS_MAP = Map.of( + "on_leave", PvpStatus.ONLEAVE, + "combatant", PvpStatus.COMBATANT, + "special_forces", PvpStatus.SPECIALFORCES + ); + + public FactionStatusRequirementParser() { + + } + + @Override + public FactionStatusRequirement parse(Map args) { + Collection statuses = (List) args.get("statuses"); + + Collection allowedPvpStatuses = statuses.stream() + .map(this::getStatusByName) + .collect(Collectors.toList()); + + return new FactionStatusRequirement(allowedPvpStatuses); + } + + private PvpStatus getStatusByName(String status) { + PvpStatus pvpStatus = STATUS_MAP.get(status); + + if (pvpStatus != null) { + return pvpStatus; + } + + throw new RuntimeException("Unknown status name " + status + ". Valid status names: " + STATUS_MAP.keySet()); + } +} diff --git a/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/conversation/NpcConversationSelectCmdCallback.java b/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/conversation/NpcConversationSelectCmdCallback.java new file mode 100644 index 000000000..81c377c80 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/conversation/NpcConversationSelectCmdCallback.java @@ -0,0 +1,42 @@ +/*********************************************************************************** + * Copyright (c) 2021 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.support.global.commands.callbacks.conversation; + +import com.projectswg.holocore.intents.gameplay.conversation.ProgressConversationIntent; +import com.projectswg.holocore.resources.support.global.commands.ICmdCallback; +import com.projectswg.holocore.resources.support.global.player.Player; +import com.projectswg.holocore.resources.support.objects.swg.SWGObject; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class NpcConversationSelectCmdCallback implements ICmdCallback { + + @Override + public void execute(@NotNull Player player, @Nullable SWGObject target, @NotNull String args) { + ProgressConversationIntent.broadcast(player.getCreatureObject(), Integer.parseInt(args)); + } +} diff --git a/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/conversation/NpcConversationStartCmdCallback.java b/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/conversation/NpcConversationStartCmdCallback.java new file mode 100644 index 000000000..c8e074ed5 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/conversation/NpcConversationStartCmdCallback.java @@ -0,0 +1,43 @@ +/*********************************************************************************** + * Copyright (c) 2021 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.support.global.commands.callbacks.conversation; + +import com.projectswg.holocore.intents.gameplay.conversation.StartConversationIntent; +import com.projectswg.holocore.resources.support.global.commands.ICmdCallback; +import com.projectswg.holocore.resources.support.global.player.Player; +import com.projectswg.holocore.resources.support.objects.swg.SWGObject; +import com.projectswg.holocore.resources.support.objects.swg.custom.AIObject; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class NpcConversationStartCmdCallback implements ICmdCallback { + + @Override + public void execute(@NotNull Player player, @Nullable SWGObject target, @NotNull String args) { + StartConversationIntent.broadcast(player.getCreatureObject(), (AIObject) target); + } +} diff --git a/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/conversation/NpcConversationStopCmdCallback.java b/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/conversation/NpcConversationStopCmdCallback.java new file mode 100644 index 000000000..7738a4df3 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/conversation/NpcConversationStopCmdCallback.java @@ -0,0 +1,42 @@ +/*********************************************************************************** + * Copyright (c) 2021 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.support.global.commands.callbacks.conversation; + +import com.projectswg.holocore.intents.gameplay.conversation.StopConversationIntent; +import com.projectswg.holocore.resources.support.global.commands.ICmdCallback; +import com.projectswg.holocore.resources.support.global.player.Player; +import com.projectswg.holocore.resources.support.objects.swg.SWGObject; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class NpcConversationStopCmdCallback implements ICmdCallback { + + @Override + public void execute(@NotNull Player player, @Nullable SWGObject target, @NotNull String args) { + StopConversationIntent.broadcast(player.getCreatureObject()); + } +} diff --git a/src/main/java/com/projectswg/holocore/services/gameplay/GameplayManager.java b/src/main/java/com/projectswg/holocore/services/gameplay/GameplayManager.java index 326f855a7..28005fadd 100644 --- a/src/main/java/com/projectswg/holocore/services/gameplay/GameplayManager.java +++ b/src/main/java/com/projectswg/holocore/services/gameplay/GameplayManager.java @@ -1,6 +1,7 @@ package com.projectswg.holocore.services.gameplay; import com.projectswg.holocore.services.gameplay.combat.CombatManager; +import com.projectswg.holocore.services.gameplay.conversation.ConversationService; import com.projectswg.holocore.services.gameplay.crafting.CraftingManager; import com.projectswg.holocore.services.gameplay.entertainment.EntertainmentManager; import com.projectswg.holocore.services.gameplay.faction.FactionManager; @@ -14,6 +15,7 @@ import me.joshlarson.jlcommon.control.ManagerStructure; @ManagerStructure(children = { CombatManager.class, + ConversationService.class, CraftingManager.class, EntertainmentManager.class, FactionManager.class, diff --git a/src/main/java/com/projectswg/holocore/services/gameplay/conversation/ConversationService.java b/src/main/java/com/projectswg/holocore/services/gameplay/conversation/ConversationService.java new file mode 100644 index 000000000..f534a840f --- /dev/null +++ b/src/main/java/com/projectswg/holocore/services/gameplay/conversation/ConversationService.java @@ -0,0 +1,338 @@ +/*********************************************************************************** + * Copyright (c) 2021 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.services.gameplay.conversation; + +import com.projectswg.common.data.encodables.oob.OutOfBandPackage; +import com.projectswg.common.data.encodables.oob.ProsePackage; +import com.projectswg.common.data.encodables.oob.StringId; +import com.projectswg.common.data.location.Location; +import com.projectswg.common.data.location.Point3D; +import com.projectswg.common.data.location.Terrain; +import com.projectswg.common.network.packets.swg.zone.object_controller.conversation.NpcConversationMessage; +import com.projectswg.common.network.packets.swg.zone.object_controller.conversation.NpcConversationOptions; +import com.projectswg.common.network.packets.swg.zone.object_controller.conversation.StartNpcConversation; +import com.projectswg.common.network.packets.swg.zone.object_controller.conversation.StopNpcConversation; +import com.projectswg.holocore.intents.gameplay.combat.EnterCombatIntent; +import com.projectswg.holocore.intents.gameplay.conversation.ProgressConversationIntent; +import com.projectswg.holocore.intents.gameplay.conversation.StartConversationIntent; +import com.projectswg.holocore.intents.gameplay.conversation.StopConversationIntent; +import com.projectswg.holocore.intents.support.objects.swg.MoveObjectIntent; +import com.projectswg.holocore.intents.support.objects.swg.ObjectCreatedIntent; +import com.projectswg.holocore.resources.gameplay.conversation.model.Conversation; +import com.projectswg.holocore.resources.gameplay.conversation.model.Event; +import com.projectswg.holocore.resources.gameplay.conversation.model.PlayerResponse; +import com.projectswg.holocore.resources.support.data.server_info.StandardLog; +import com.projectswg.holocore.resources.support.data.server_info.loader.conversation.ConversationLoader; +import com.projectswg.holocore.resources.support.data.server_info.loader.ServerData; +import com.projectswg.holocore.resources.support.global.player.Player; +import com.projectswg.holocore.resources.support.npc.spawn.Spawner; +import com.projectswg.holocore.resources.support.objects.swg.SWGObject; +import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject; +import com.projectswg.holocore.resources.support.objects.swg.custom.AIObject; +import com.projectswg.holocore.resources.support.objects.swg.tangible.OptionFlag; +import me.joshlarson.jlcommon.control.IntentHandler; +import me.joshlarson.jlcommon.control.Service; +import me.joshlarson.jlcommon.log.Log; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class ConversationService extends Service { + + private static final double ALLOWED_DISTANCE = 7.0; // Max allowed amount of distance between player and NPC before conversation is interrupted + + private final Map sessions; + + public ConversationService() { + sessions = new HashMap<>(); + } + + @IntentHandler + private void handleCombatStartedIntent(EnterCombatIntent intent) { + CreatureObject source = intent.getSource(); + CreatureObject target = intent.getTarget(); + + if (isConversing(source)) { + abortConversation(source); + } + + if (isConversing(target)) { + abortConversation(target); + } + } + + @IntentHandler + private void handleMoveObjectIntent(MoveObjectIntent intent) { + SWGObject object = intent.getObject(); + + if (!(object instanceof CreatureObject)) { + return; + } + + CreatureObject creatureObject = (CreatureObject) object; + + if (!isConversing(creatureObject)) { + return; + } + + Session session = sessions.get(creatureObject); + AIObject npc = session.getNpc(); + + if (isWithinRange(creatureObject, npc)) { + return; + } + + // At this point, the conversation should be interrupted + abortConversation(creatureObject); + } + + @IntentHandler + private void handleObjectCreatedIntent(ObjectCreatedIntent intent) { + SWGObject object = intent.getObject(); + + if (!(object instanceof AIObject)) { + return; + } + + AIObject npc = (AIObject) object; + + if (!isConversableNpc(npc)) { + return; + } + + npc.addOptionFlags(OptionFlag.CONVERSABLE); + } + + @IntentHandler + private void handleStartConversationIntent(StartConversationIntent intent) { + ConversationLoader conversationLoader = ServerData.INSTANCE.getConversationLoader(); + AIObject npc = intent.getNpc(); + CreatureObject starter = intent.getStarter(); + + Spawner spawner = npc.getSpawner(); + String spawnId = spawner.getId(); + + List conversations = conversationLoader.getInitialConversations(spawnId); + + Conversation conversation = reduce(conversations, starter.getOwner()); + + if (conversation == null) { + StandardLog.onPlayerEvent(this, starter, "No eligible conversations for spawnId %s", spawnId); + return; + } + + progressConversation(starter, npc, conversation); + + rotateNpc(npc, starter); + } + + @IntentHandler + private void handleProgressConversationIntent(ProgressConversationIntent intent) { + int selection = intent.getSelection(); + CreatureObject starter = intent.getStarter(); + + Session session = sessions.get(starter); + Conversation currentConversation = session.getConversation(); + AIObject npc = session.getNpc(); + + List filteredResponses = getFilteredResponses(starter, currentConversation); + PlayerResponse selectedResponse = filteredResponses.get(selection); + String nextConversationId = selectedResponse.getNext(); + ConversationLoader conversationLoader = ServerData.INSTANCE.getConversationLoader(); + + Conversation nextConversation = conversationLoader.getConversation(nextConversationId); + + if (nextConversation == null) { + StandardLog.onPlayerError(this, starter, "Unable to progress conversation, conversation by ID %s does not exist", nextConversationId); + return; + } + + progressConversation(starter, npc, nextConversation); + } + + @IntentHandler + private void handleStopConversationIntent(StopConversationIntent intent) { + CreatureObject creatureObject = intent.getCreatureObject(); + + if (isConversing(creatureObject)) { + abortConversation(creatureObject); + } + } + + private boolean isConversableNpc(AIObject npc) { + ConversationLoader conversationLoader = ServerData.INSTANCE.getConversationLoader(); + Spawner spawner = npc.getSpawner(); + String spawnId = spawner.getId(); + + Collection spawnConversationIds = conversationLoader.getConversationIds(spawnId); + + return !spawnConversationIds.isEmpty(); + } + + @Nullable + private Conversation reduce(List conversations, Player player) { + Conversation conversation = null; + + for (Conversation candidate : conversations) { + if (candidate.isAllowed(player)) { + conversation = candidate; + break; + } + } + + return conversation; + } + + private List getFilteredResponses(CreatureObject starter, Conversation conversation) { + List playerResponses = conversation.getPlayerResponses(); + ConversationLoader conversationLoader = ServerData.INSTANCE.getConversationLoader(); + + return playerResponses.stream() + .filter(playerResponse -> { + String nextConversationId = playerResponse.getNext(); + + if (nextConversationId == null) { + return false; + } + + Conversation nextConversation = conversationLoader.getConversation(nextConversationId); + + if (nextConversation == null) { + return false; + } + + return nextConversation.isAllowed(starter.getOwner()); + }) + .collect(Collectors.toList()); + } + + private void progressConversation(CreatureObject starter, AIObject npc, Conversation conversation) { + ProsePackage npcMessageProse = conversation.getNpcMessage(); + + List filteredResponses = getFilteredResponses(starter, conversation); + List replies = filteredResponses.stream() + .map(PlayerResponse::getProsePackage) + .map(OutOfBandPackage::new) + .peek(outOfBandPackage -> outOfBandPackage.setConversation(true)) + .collect(Collectors.toList()); + + if (!sessions.containsKey(starter)) { + starter.sendSelf(new StartNpcConversation(npc.getObjectId(), starter.getObjectId())); + } + + if (filteredResponses.isEmpty()) { + sessions.remove(starter); + starter.sendSelf(new StopNpcConversation(starter.getObjectId(), npc.getObjectId(), npcMessageProse.getBase())); + } else { + OutOfBandPackage npcMessage = new OutOfBandPackage(npcMessageProse); + npcMessage.setConversation(true); + Session session = new Session(conversation, npc); + + sessions.put(starter, session); + starter.sendSelf(new NpcConversationMessage(starter.getObjectId(), npcMessage)); + starter.sendSelf(new NpcConversationOptions(starter.getObjectId(), replies)); + } + + List events = conversation.getEvents(); + + for (Event event : events) { + try { + event.trigger(starter.getOwner(), npc); + } catch (Throwable t) { + StandardLog.onPlayerError(this, starter, "Error while triggering conversation event of type %s", event.getClass().getSimpleName()); + Log.e(t); + } + } + } + + private void rotateNpc(AIObject npc, CreatureObject starter) { + Location oldNpcWorldLocation = npc.getLocation(); + Point3D starterWorldLocation = starter.getLocation().getPosition(); + + double headingTo = oldNpcWorldLocation.getHeadingTo(starterWorldLocation); + + Location newNpcWorldLocation = new Location.LocationBuilder(oldNpcWorldLocation) + .setHeading(headingTo) + .build(); + + MoveObjectIntent.broadcast(npc, npc.getParent(), newNpcWorldLocation, 0); + } + + private void abortConversation(CreatureObject creatureObject) { + Session session = sessions.remove(creatureObject); + Conversation conversation = session.getConversation(); + AIObject npc = session.getNpc(); + ProsePackage npcMessage = conversation.getNpcMessage(); + StringId npcMessageBase = npcMessage.getBase(); + + StopNpcConversation stopNpcConversation = new StopNpcConversation(creatureObject.getObjectId(), npc.getObjectId(), npcMessageBase); + + creatureObject.sendSelf(stopNpcConversation); + } + + private boolean isConversing(CreatureObject creatureObject) { + return sessions.containsKey(creatureObject); + } + + private boolean isWithinRange(CreatureObject creature, AIObject npc) { + Location playerWorldLocation = creature.getWorldLocation(); + Location npcWorldLocation = npc.getWorldLocation(); + + Terrain playerTerrain = playerWorldLocation.getTerrain(); + Terrain npcTerrain = npcWorldLocation.getTerrain(); + + if (playerTerrain != npcTerrain) { + return false; + } + + double distance = playerWorldLocation.distanceTo(npcWorldLocation); + + return distance <= ALLOWED_DISTANCE; + } + + private static class Session { + private final Conversation conversation; + private final AIObject npc; + + public Session(Conversation conversation, AIObject npc) { + this.conversation = conversation; + this.npc = npc; + } + + public Conversation getConversation() { + return conversation; + } + + public AIObject getNpc() { + return npc; + } + } +} diff --git a/src/main/java/com/projectswg/holocore/services/support/global/commands/CommandExecutionService.java b/src/main/java/com/projectswg/holocore/services/support/global/commands/CommandExecutionService.java index b8a07bf74..7dc85706d 100644 --- a/src/main/java/com/projectswg/holocore/services/support/global/commands/CommandExecutionService.java +++ b/src/main/java/com/projectswg/holocore/services/support/global/commands/CommandExecutionService.java @@ -1,3 +1,29 @@ +/*********************************************************************************** + * Copyright (c) 2021 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ package com.projectswg.holocore.services.support.global.commands; import com.projectswg.holocore.intents.support.global.command.ExecuteCommandIntent; @@ -13,6 +39,7 @@ import com.projectswg.holocore.resources.support.global.commands.callbacks.comba import com.projectswg.holocore.resources.support.global.commands.callbacks.combat.CmdDuel; import com.projectswg.holocore.resources.support.global.commands.callbacks.combat.CmdEndDuel; import com.projectswg.holocore.resources.support.global.commands.callbacks.combat.CmdPVP; +import com.projectswg.holocore.resources.support.global.commands.callbacks.conversation.*; import com.projectswg.holocore.resources.support.global.commands.callbacks.flags.*; import com.projectswg.holocore.resources.support.global.commands.callbacks.generic.*; import com.projectswg.holocore.resources.support.global.commands.callbacks.group.*; @@ -94,6 +121,7 @@ public class CommandExecutionService extends Service { addGenericScripts(); addGroupScripts(); addSurveyScripts(); + addConversationScripts(); } private void addAdminScripts() { @@ -188,4 +216,10 @@ public class CommandExecutionService extends Service { registerCallback("requestSurvey", CmdRequestSurvey::new); } + private void addConversationScripts() { + registerCallback("npcconversationstart", NpcConversationStartCmdCallback::new); + registerCallback("npcconversationselect", NpcConversationSelectCmdCallback::new); + registerCallback("npcconversationstop", NpcConversationStopCmdCallback::new); + } + }