Merge pull request #300 from madsboddum/12

Added conversations framework and enough functionality to join and le…
This commit is contained in:
Josh Larson
2021-01-06 17:44:22 -06:00
committed by GitHub
34 changed files with 1618 additions and 9 deletions

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
@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()
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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);
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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<PlayerResponse> playerResponses;
private final List<Event> events;
private final List<Requirement> 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<PlayerResponse> 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<Event> getEvents() {
return events;
}
@Override
public String toString() {
return "Conversation{" + "id='" + id + '\'' + '}';
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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);
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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;
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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<Player> {
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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);
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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<PvpStatus> allowedPvpStatuses;
public FactionStatusRequirement(Collection<PvpStatus> allowedPvpStatuses) {
this.allowedPvpStatuses = allowedPvpStatuses;
}
@Override
public boolean test(Player player) {
CreatureObject creatureObject = player.getCreatureObject();
PvpStatus pvpStatus = creatureObject.getPvpStatus();
return allowedPvpStatuses.contains(pvpStatus);
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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
}

View File

@@ -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<T: DataLoader>(loaderCreator: () -> T): DataLoaderDelegate<T>(::WeakReference, loaderCreator)
private class SoftDataLoaderDelegate<T: DataLoader>(loaderCreator: () -> T): DataLoaderDelegate<T>(::SoftReference, loaderCreator)

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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<String, Collection<String>> spawnConversationsMap;
private final Map<String, RequirementParser<? extends Requirement>> requirementParserMap;
private final Map<String, EventParser<? extends Event>> 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<Conversation> getInitialConversations(String spawnId) {
if (!spawnConversationsMap.containsKey(spawnId)) {
return Collections.emptyList();
}
Collection<String> conversationIds = spawnConversationsMap.get(spawnId);
return conversationIds.stream()
.map(this::getConversation)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
@NotNull
public Collection<String> getConversationIds(String spawnId) {
return spawnConversationsMap.getOrDefault(spawnId, Collections.emptyList());
}
private Conversation readConversation(String conversationId, JSONObject jsonObject) {
Conversation conversation = new Conversation(conversationId);
Map<String, Object> npcMessageObj = (Map<String, Object>) jsonObject.get("npcMessage");
ProsePackage npcMessage = readProsePackage(npcMessageObj);
conversation.setNpcMessage(npcMessage);
List<JSONObject> playerResponseObjs = (List<JSONObject>) jsonObject.get("playerResponses");
List<PlayerResponse> playerResponses = readPlayerResponses(playerResponseObjs);
for (PlayerResponse playerResponse : playerResponses) {
conversation.addPlayerResponse(playerResponse);
}
List<JSONObject> requirementObjs = (List<JSONObject>) jsonObject.get("requirements");
List<Requirement> requirements = readRequirements(requirementObjs);
for (Requirement requirement : requirements) {
conversation.addRequirement(requirement);
}
List<JSONObject> eventObjs = (List<JSONObject>) jsonObject.get("events");
List<Event> events = readEvents(eventObjs);
for (Event event : events) {
conversation.addEvent(event);
}
return conversation;
}
private ProsePackage readProsePackage(Map<String, Object> object) {
String file = object.get("file").toString();
String key = object.get("key").toString();
return new ProsePackage(file, key);
}
private List<PlayerResponse> readPlayerResponses(List<JSONObject> playerResponseObjs) {
List<PlayerResponse> playerResponses = new ArrayList<>();
for (JSONObject playerResponseObj : playerResponseObjs) {
Map<String, Object> playerMessageRaw = (Map<String, Object>) 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<Requirement> readRequirements(List<JSONObject> requirementObjs) {
List<Requirement> requirements = new ArrayList<>();
for (JSONObject requirementObj : requirementObjs) {
String type = (String) requirementObj.get("type");
Map<String, Object> args = (Map<String, Object>) requirementObj.get("args");
RequirementParser<? extends Requirement> requirementParser = requirementParserMap.get(type);
Requirement requirement = requirementParser.parse(args);
requirements.add(requirement);
}
return requirements;
}
private List<Event> readEvents(List<JSONObject> eventObjs) {
List<Event> events = new ArrayList<>();
for (JSONObject eventObj : eventObjs) {
String type = (String) eventObj.get("type");
Map<String, Object> args = (Map<String, Object>) eventObj.get("args");
EventParser<? extends Event> 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);
}
}
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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 extends Event> {
T parse(Map<String, Object> args);
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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 extends Requirement> {
T parse(Map<String, Object> args);
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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<ChangePlayerFactionEvent> {
@Override
public ChangePlayerFactionEvent parse(Map<String, Object> args) {
String factionName = (String) args.get("faction");
return new ChangePlayerFactionEvent(factionName);
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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<FactionNameRequirement> {
@Override
public FactionNameRequirement parse(Map<String, Object> args) {
String factionName = (String) args.get("faction");
return new FactionNameRequirement(factionName);
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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<FactionStatusRequirement> {
private static final Map<String, PvpStatus> STATUS_MAP = Map.of(
"on_leave", PvpStatus.ONLEAVE,
"combatant", PvpStatus.COMBATANT,
"special_forces", PvpStatus.SPECIALFORCES
);
public FactionStatusRequirementParser() {
}
@Override
public FactionStatusRequirement parse(Map<String, Object> args) {
Collection<String> statuses = (List<String>) args.get("statuses");
Collection<PvpStatus> 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());
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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));
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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);
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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());
}
}

View File

@@ -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,

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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<CreatureObject, Session> 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<Conversation> 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<PlayerResponse> 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<String> spawnConversationIds = conversationLoader.getConversationIds(spawnId);
return !spawnConversationIds.isEmpty();
}
@Nullable
private Conversation reduce(List<Conversation> conversations, Player player) {
Conversation conversation = null;
for (Conversation candidate : conversations) {
if (candidate.isAllowed(player)) {
conversation = candidate;
break;
}
}
return conversation;
}
private List<PlayerResponse> getFilteredResponses(CreatureObject starter, Conversation conversation) {
List<PlayerResponse> 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<PlayerResponse> filteredResponses = getFilteredResponses(starter, conversation);
List<OutOfBandPackage> 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<Event> 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;
}
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
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);
}
}