Commit d71248da by Jonathan Thomas

Refactor messages back to a single List<ChatMessage>, but now with a "name"…

Refactor messages back to a single List<ChatMessage>, but now with a "name" attribute based on Player's display name. This will more easily allow for filtering the list of messages by player name, and also allow for more role playing (i.e. changing nick on a server can change your friendship / message history).
parent 7717d5ac
Pipeline #12984 passed with stages
in 2 minutes 0 seconds
......@@ -102,6 +102,7 @@ public class ClientPackets {
// Read the data from the server packet
UUID entityId = UUID.fromString(buffer.readString());
UUID playerId = UUID.fromString(buffer.readString());
String playerName =buffer.readString(32767);
String message = buffer.readString(32767);
int line = buffer.readInt();
String status_name = buffer.readString(32767);
......@@ -114,13 +115,13 @@ public class ClientPackets {
if (entity != null) {
ChatDataManager chatDataManager = ChatDataManager.getClientInstance();
EntityChatData chatData = chatDataManager.getOrCreateChatData(entity.getUuidAsString(), playerId.toString());
PlayerData playerData = chatData.getPlayerData(playerId.toString());
if (!message.isEmpty()) {
chatData.currentMessage = message;
}
chatData.currentLineNumber = line;
chatData.status = ChatDataManager.ChatStatus.valueOf(status_name);
chatData.sender = ChatDataManager.ChatSender.valueOf(sender_name);
PlayerData playerData = chatData.getPlayerData(playerName);
playerData.friendship = friendship;
if (chatData.sender == ChatDataManager.ChatSender.USER) {
......
......@@ -480,7 +480,7 @@ public class BubbleRenderer {
PlayerData playerData = null;
if (entity instanceof MobEntity) {
chatData = ChatDataManager.getClientInstance().getOrCreateChatData(entity.getUuidAsString(), player.getUuidAsString());
playerData = chatData.getPlayerData(player.getUuidAsString());
playerData = chatData.getPlayerData(player.getDisplayName().getString());
} else if (entity instanceof PlayerEntity) {
chatData = PlayerMessageManager.getMessage(entity.getUuid());
}
......
......@@ -93,11 +93,11 @@ public class ChatDataManager {
}
// Save chat data to file
public String GetLightChatData(UUID playerId) {
public String GetLightChatData(String playerName) {
try {
// Create "light" version of entire chat data HashMap
HashMap<String, EntityChatDataLight> lightVersionMap = new HashMap<>();
this.entityChatDataMap.forEach((id, entityChatData) -> lightVersionMap.put(id, entityChatData.toLightVersion(playerId)));
this.entityChatDataMap.forEach((name, entityChatData) -> lightVersionMap.put(name, entityChatData.toLightVersion(playerName)));
return GSON.toJson(lightVersionMap);
} catch (Exception e) {
// Handle exceptions
......
......@@ -5,12 +5,14 @@ package com.owlmaddie.chat;
*/
public class ChatMessage {
public String message;
public String name;
public ChatDataManager.ChatSender sender;
public Long timestamp;
public ChatMessage(String message, ChatDataManager.ChatSender sender) {
public ChatMessage(String message, ChatDataManager.ChatSender sender, String playerName) {
this.message = message;
this.sender = sender;
this.name = playerName;
this.timestamp = System.currentTimeMillis();
}
}
\ No newline at end of file
......@@ -50,15 +50,12 @@ public class EntityChatData {
public String characterSheet;
public ChatDataManager.ChatSender sender;
public int auto_generated;
public List<ChatMessage> previousMessages;
@SerializedName("playerId")
@Expose(serialize = false)
private String legacyPlayerId;
@SerializedName("previousMessages")
@Expose(serialize = false)
public List<ChatMessage> legacyMessages;
@SerializedName("friendship")
@Expose(serialize = false)
public Integer legacyFriendship;
......@@ -78,9 +75,10 @@ public class EntityChatData {
this.status = ChatDataManager.ChatStatus.NONE;
this.sender = ChatDataManager.ChatSender.USER;
this.auto_generated = 0;
this.previousMessages = new ArrayList<>();
// Old, unused migrated properties
this.legacyPlayerId = null;
this.legacyMessages = null;
this.legacyFriendship = null;
}
......@@ -99,22 +97,23 @@ public class EntityChatData {
// Ensure the blank player data entry exists
PlayerData blankPlayerData = this.players.computeIfAbsent("", k -> new PlayerData());
// Migrate the old data to the blank player and assign timestamps if missing
if (this.legacyMessages != null) {
this.legacyMessages.forEach(message -> message.timestamp =
message.timestamp != null ? message.timestamp : System.currentTimeMillis());
blankPlayerData.messages.addAll(this.legacyMessages);
// Update the previousMessages arraylist and add timestamps if missing
if (this.previousMessages != null) {
for (ChatMessage message : this.previousMessages) {
if (message.timestamp == null) {
message.timestamp = System.currentTimeMillis();
}
}
}
blankPlayerData.friendship = this.legacyFriendship;
// Clean up old player data
this.legacyPlayerId = null;
this.legacyMessages = null;
this.legacyFriendship = null;
}
// Get the player data (or fallback to the blank player)
public PlayerData getPlayerData(String playerId) {
public PlayerData getPlayerData(String playerName) {
if (this.players == null) {
return new PlayerData();
}
......@@ -124,21 +123,29 @@ public class EntityChatData {
// If a blank migrated legacy entity is found, always return this
return this.players.get("");
} else if (this.players.containsKey(playerId)) {
} else if (this.players.containsKey(playerName)) {
// Return a specific player's data
return this.players.get(playerId);
return this.players.get(playerName);
} else {
// Return a blank player data
PlayerData newPlayerData = new PlayerData();
this.players.put(playerId, newPlayerData);
this.players.put(playerName, newPlayerData);
return newPlayerData;
}
}
// Get a filtered list of ChatMessages by a particular name (plus any messages with null or empty names)
// For example, if chat data is migrated before 'name' was stored, we want those message to be visible by everyone.
public ArrayList<ChatMessage> getMessagesByName(String playerName) {
return this.previousMessages.stream()
.filter(message -> message.name == null || message.name.isEmpty() || message.name.equals(playerName))
.collect(Collectors.toCollection(ArrayList::new));
}
// Generate light version of chat data (no previous messages)
public EntityChatDataLight toLightVersion(UUID playerId) {
return new EntityChatDataLight(this, playerId);
public EntityChatDataLight toLightVersion(String playerName) {
return new EntityChatDataLight(this, playerName);
}
public String getCharacterProp(String propertyName) {
......@@ -225,7 +232,7 @@ public class EntityChatData {
contextData.put("entity_skills", getCharacterProp("Skills"));
contextData.put("entity_background", getCharacterProp("Background"));
PlayerData playerData = this.getPlayerData(player.getUuidAsString());
PlayerData playerData = this.getPlayerData(player.getDisplayName().getString());
if (playerData != null) {
contextData.put("entity_friendship", String.valueOf(playerData.friendship));
} else {
......@@ -247,7 +254,7 @@ public class EntityChatData {
}
// Add message
this.addMessage(userMessage, ChatDataManager.ChatSender.USER, player.getUuid());
this.addMessage(userMessage, ChatDataManager.ChatSender.USER, player.getDisplayName().getString());
// Add PLAYER context information
Map<String, String> contextData = getPlayerContext(player, userLanguage);
......@@ -256,24 +263,27 @@ public class EntityChatData {
ConfigurationHandler.Config config = new ConfigurationHandler(ServerPackets.serverInstance).loadConfig();
String promptText = ChatPrompt.loadPromptFromResource(ServerPackets.serverInstance.getResourceManager(), systemPrompt);
// Get all message (filtered by player)
List<ChatMessage> playerMessages = getMessagesByName(player.getDisplayName().getString());
// Get messages for player
PlayerData playerData = this.getPlayerData(player.getUuidAsString());
if (playerData.messages.size() == 1 && systemPrompt.equals("system-chat")) {
PlayerData playerData = this.getPlayerData(player.getDisplayName().getString());
if (playerMessages.size() == 1 && systemPrompt.equals("system-chat")) {
// No messages exist yet for this player (start with normal greeting)
String shortGreeting = Optional.ofNullable(getCharacterProp("short greeting")).filter(s -> !s.isEmpty()).orElse(Randomizer.getRandomMessage(Randomizer.RandomType.NO_RESPONSE)).replace("\n", " ");
playerData.messages.add(0, new ChatMessage(shortGreeting, ChatDataManager.ChatSender.ASSISTANT));
previousMessages.add(0, new ChatMessage(shortGreeting, ChatDataManager.ChatSender.ASSISTANT, player.getDisplayName().getString()));
}
// fetch HTTP response from ChatGPT
ChatGPTRequest.fetchMessageFromChatGPT(config, promptText, contextData, playerData.messages, false).thenAccept(output_message -> {
ChatGPTRequest.fetchMessageFromChatGPT(config, promptText, contextData, playerMessages, false).thenAccept(output_message -> {
if (output_message != null && systemPrompt.equals("system-character")) {
// Character Sheet: Remove system-character message from previous messages
playerData.messages.clear();
previousMessages.clear();
// Add NEW CHARACTER sheet & greeting
this.characterSheet = output_message;
String shortGreeting = Optional.ofNullable(getCharacterProp("short greeting")).filter(s -> !s.isEmpty()).orElse(Randomizer.getRandomMessage(Randomizer.RandomType.NO_RESPONSE)).replace("\n", " ");
this.addMessage(shortGreeting, ChatDataManager.ChatSender.ASSISTANT, player.getUuid());
this.addMessage(shortGreeting, ChatDataManager.ChatSender.ASSISTANT, player.getDisplayName().getString());
} else if (output_message != null && systemPrompt.equals("system-chat")) {
// Chat Message: Parse message for behaviors
......@@ -463,7 +473,7 @@ public class EntityChatData {
}
// Add ASSISTANT message to history
this.addMessage(result.getOriginalMessage(), ChatDataManager.ChatSender.ASSISTANT, player.getUuid());
this.addMessage(result.getOriginalMessage(), ChatDataManager.ChatSender.ASSISTANT, player.getDisplayName().getString());
// Get cleaned message (i.e. no <BEHAVIOR> strings)
String cleanedMessage = result.getCleanedMessage();
......@@ -476,7 +486,7 @@ public class EntityChatData {
} else {
// Error / No Chat Message (Failure)
String randomErrorMessage = Randomizer.getRandomMessage(Randomizer.RandomType.ERROR);
this.addMessage(randomErrorMessage, ChatDataManager.ChatSender.ASSISTANT, player.getUuid());
this.addMessage(randomErrorMessage, ChatDataManager.ChatSender.ASSISTANT, player.getDisplayName().getString());
// Determine error message to display
String errorMessage = "Help is available at discord.creaturechat.com";
......@@ -490,7 +500,7 @@ public class EntityChatData {
// Clear history (if no character sheet was generated)
if (characterSheet.isEmpty()) {
playerData.messages.clear();
previousMessages.clear();
}
}
......@@ -504,15 +514,12 @@ public class EntityChatData {
}
// Add a message to the history and update the current message
public void addMessage(String message, ChatDataManager.ChatSender messageSender, UUID playerId) {
public void addMessage(String message, ChatDataManager.ChatSender messageSender, String playerName) {
// Truncate message (prevent crazy long messages... just in case)
String truncatedMessage = message.substring(0, Math.min(message.length(), ChatDataManager.MAX_CHAR_IN_USER_MESSAGE));
// Get or create player data
PlayerData playerData = getPlayerData(playerId.toString());
// Add message to history
playerData.messages.add(new ChatMessage(truncatedMessage, messageSender));
previousMessages.add(new ChatMessage(truncatedMessage, messageSender, playerName));
// Set new message and reset line number of displayed text
currentMessage = truncatedMessage;
......
......@@ -18,7 +18,7 @@ public class EntityChatDataLight {
public Map<String, PlayerData> players;
// Constructor to initialize the light version from the full version
public EntityChatDataLight(EntityChatData fullData, UUID playerId) {
public EntityChatDataLight(EntityChatData fullData, String playerName) {
this.entityId = fullData.entityId;
this.currentMessage = fullData.currentMessage;
this.currentLineNumber = fullData.currentLineNumber;
......@@ -27,8 +27,7 @@ public class EntityChatDataLight {
// Initialize the players map and add only the current player's data
this.players = new HashMap<>();
String playerIdStr = playerId.toString();
PlayerData playerData = fullData.getPlayerData(playerId.toString());
this.players.put(playerIdStr, playerData);
PlayerData playerData = fullData.getPlayerData(playerName);
this.players.put(playerName, playerData);
}
}
\ No newline at end of file
package com.owlmaddie.chat;
import java.util.ArrayList;
import java.util.List;
public class PlayerData {
public List<ChatMessage> messages;
public int friendship;
public PlayerData() {
this.messages = new ArrayList<>();
this.friendship = 0;
}
}
\ No newline at end of file
......@@ -33,7 +33,7 @@ public class MixinLivingEntity {
if (target instanceof PlayerEntity) {
LivingEntity thisEntity = (LivingEntity) (Object) this;
EntityChatData entityData = getChatData(thisEntity, (PlayerEntity) target);
PlayerData playerData = entityData.getPlayerData(target.getUuidAsString());
PlayerData playerData = entityData.getPlayerData(target.getDisplayName().getString());
if (playerData.friendship > 0) {
// Friendly creatures can't target a player
cir.setReturnValue(false);
......
......@@ -55,7 +55,7 @@ public class MixinMobEntity {
// Get chat data for entity
ChatDataManager chatDataManager = ChatDataManager.getServerInstance();
EntityChatData entityData = chatDataManager.getOrCreateChatData(thisEntity.getUuidAsString(), player.getUuidAsString());
PlayerData playerData = entityData.getPlayerData(player.getUuidAsString());
PlayerData playerData = entityData.getPlayerData(player.getDisplayName().getString());
// Check if the player successfully interacts with an item
if (player instanceof ServerPlayerEntity) {
......
......@@ -198,7 +198,7 @@ public class ServerPackets {
LOGGER.info("Server send compressed, chunked login message packets to player: " + player.getName().getString());
// Get lite JSON data & compress to byte array
String chatDataJSON = ChatDataManager.getServerInstance().GetLightChatData(player.getUuid());
String chatDataJSON = ChatDataManager.getServerInstance().GetLightChatData(player.getDisplayName().getString());
byte[] compressedData = Compression.compressString(chatDataJSON);
if (compressedData == null) {
LOGGER.error("Failed to compress chat data.");
......@@ -346,12 +346,13 @@ public class ServerPackets {
// Iterate over all players and send the packet
for (ServerPlayerEntity player : serverInstance.getPlayerManager().getPlayerList()) {
PlayerData playerData = chatData.getPlayerData(player.getUuidAsString());
PlayerData playerData = chatData.getPlayerData(player.getDisplayName().getString());
PacketByteBuf buffer = new PacketByteBuf(Unpooled.buffer());
// Write the entity's chat updated data
buffer.writeString(chatData.entityId);
buffer.writeString(player.getUuidAsString());
buffer.writeString(player.getDisplayName().getString());
buffer.writeString(chatData.currentMessage);
buffer.writeInt(chatData.currentLineNumber);
buffer.writeString(chatData.status.toString());
......
......@@ -203,7 +203,7 @@ public class BehaviorTests {
// Add test message
for (String message : messages) {
entityTestData.addMessage(message, ChatDataManager.ChatSender.USER);
entityTestData.addMessage(message, ChatDataManager.ChatSender.USER, "TestPlayer1");
}
// Get prompt
......
......@@ -60,12 +60,12 @@ public class EntityTestData {
}
// Add a message to the history and update the current message
public void addMessage(String message, ChatDataManager.ChatSender messageSender) {
public void addMessage(String message, ChatDataManager.ChatSender messageSender, String playerName) {
// Truncate message (prevent crazy long messages... just in case)
String truncatedMessage = message.substring(0, Math.min(message.length(), ChatDataManager.MAX_CHAR_IN_USER_MESSAGE));
// Add message to history
previousMessages.add(new ChatMessage(truncatedMessage, messageSender));
previousMessages.add(new ChatMessage(truncatedMessage, messageSender, playerName));
// Set new message and reset line number of displayed text
currentMessage = truncatedMessage;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment