Commit f2366fa3 by Jonathan Thomas

More fixes for regressions related to player message bubbles. Seperated…

More fixes for regressions related to player message bubbles. Seperated `generateCharacter()` and `generateMessage()` functions for simplicity
parent 68db47af
Pipeline #13208 passed with stages
in 2 minutes 6 seconds
...@@ -22,6 +22,7 @@ All notable changes to **CreatureChat** are documented in this file. The format ...@@ -22,6 +22,7 @@ All notable changes to **CreatureChat** are documented in this file. The format
- Removed "pirate" speaking style and a few <non-response> outputs - Removed "pirate" speaking style and a few <non-response> outputs
- Passive entities no longer emit damage particles when attacking, they emit custom attack particles - Passive entities no longer emit damage particles when attacking, they emit custom attack particles
- Protect now auto sets friendship to 1 (if <= 0), to prevent entity from attacking and protecting at the same time - Protect now auto sets friendship to 1 (if <= 0), to prevent entity from attacking and protecting at the same time
- Seperated `generateCharacter()` and `generateMessage()` functions for simplicity
### Fixed ### Fixed
- Fixed a regression caused by adding a "-forge" suffix to one of our builds - Fixed a regression caused by adding a "-forge" suffix to one of our builds
......
...@@ -101,8 +101,14 @@ public class ClientPackets { ...@@ -101,8 +101,14 @@ public class ClientPackets {
ClientPlayNetworking.registerGlobalReceiver(ServerPackets.PACKET_S2C_MESSAGE, (client, handler, buffer, responseSender) -> { ClientPlayNetworking.registerGlobalReceiver(ServerPackets.PACKET_S2C_MESSAGE, (client, handler, buffer, responseSender) -> {
// Read the data from the server packet // Read the data from the server packet
UUID entityId = UUID.fromString(buffer.readString()); UUID entityId = UUID.fromString(buffer.readString());
UUID playerId = UUID.fromString(buffer.readString()); String sendingPlayerIdStr = buffer.readString(32767);
String playerName = buffer.readString(32767); String senderPlayerName = buffer.readString(32767);
UUID senderPlayerId;
if (!sendingPlayerIdStr.isEmpty()) {
senderPlayerId = UUID.fromString(sendingPlayerIdStr);
} else {
senderPlayerId = null;
}
String message = buffer.readString(32767); String message = buffer.readString(32767);
int line = buffer.readInt(); int line = buffer.readInt();
String status_name = buffer.readString(32767); String status_name = buffer.readString(32767);
...@@ -110,23 +116,24 @@ public class ClientPackets { ...@@ -110,23 +116,24 @@ public class ClientPackets {
int friendship = buffer.readInt(); int friendship = buffer.readInt();
// Update the chat data manager on the client-side // Update the chat data manager on the client-side
String currentPlayerName = client.player.getDisplayName().toString();
client.execute(() -> { // Make sure to run on the client thread client.execute(() -> { // Make sure to run on the client thread
MobEntity entity = ClientEntityFinder.getEntityByUUID(client.world, entityId); MobEntity entity = ClientEntityFinder.getEntityByUUID(client.world, entityId);
if (entity != null) { if (entity != null) {
ChatDataManager chatDataManager = ChatDataManager.getClientInstance(); ChatDataManager chatDataManager = ChatDataManager.getClientInstance();
EntityChatData chatData = chatDataManager.getOrCreateChatData(entity.getUuidAsString(), playerName); EntityChatData chatData = chatDataManager.getOrCreateChatData(entity.getUuidAsString(), currentPlayerName);
if (!message.isEmpty()) { if (!message.isEmpty()) {
chatData.currentMessage = message; chatData.currentMessage = message;
} }
chatData.currentLineNumber = line; chatData.currentLineNumber = line;
chatData.status = ChatDataManager.ChatStatus.valueOf(status_name); chatData.status = ChatDataManager.ChatStatus.valueOf(status_name);
chatData.sender = ChatDataManager.ChatSender.valueOf(sender_name); chatData.sender = ChatDataManager.ChatSender.valueOf(sender_name);
PlayerData playerData = chatData.getPlayerData(playerName); PlayerData playerData = chatData.getPlayerData(currentPlayerName);
playerData.friendship = friendship; playerData.friendship = friendship;
if (chatData.sender == ChatDataManager.ChatSender.USER && chatData.status == ChatDataManager.ChatStatus.DISPLAY) { if (chatData.sender == ChatDataManager.ChatSender.USER && chatData.status == ChatDataManager.ChatStatus.DISPLAY) {
// Add player message to queue for rendering // Add player message to queue for rendering
PlayerMessageManager.addMessage(playerId, playerName, chatData.currentMessage, ChatDataManager.TICKS_TO_DISPLAY_USER_MESSAGE); PlayerMessageManager.addMessage(senderPlayerId, chatData.currentMessage, senderPlayerName, ChatDataManager.TICKS_TO_DISPLAY_USER_MESSAGE);
} }
// Play sound with volume based on distance (from player or entity) // Play sound with volume based on distance (from player or entity)
......
...@@ -12,7 +12,7 @@ public class PlayerMessageManager { ...@@ -12,7 +12,7 @@ public class PlayerMessageManager {
private static final ConcurrentHashMap<UUID, PlayerMessage> messages = new ConcurrentHashMap<>(); private static final ConcurrentHashMap<UUID, PlayerMessage> messages = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<UUID, Boolean> openChatUIs = new ConcurrentHashMap<>(); private static final ConcurrentHashMap<UUID, Boolean> openChatUIs = new ConcurrentHashMap<>();
public static void addMessage(UUID playerUUID, String playerName, String messageText, int ticks) { public static void addMessage(UUID playerUUID, String messageText, String playerName, int ticks) {
messages.put(playerUUID, new PlayerMessage(playerUUID.toString(), playerName, messageText, ticks)); messages.put(playerUUID, new PlayerMessage(playerUUID.toString(), playerName, messageText, ticks));
} }
......
...@@ -85,7 +85,7 @@ public class ChatDataManager { ...@@ -85,7 +85,7 @@ public class ChatDataManager {
LOGGER.info("Updated chat data from UUID (" + oldUUID + ") to UUID (" + newUUID + ")"); LOGGER.info("Updated chat data from UUID (" + oldUUID + ") to UUID (" + newUUID + ")");
// Broadcast to all players // Broadcast to all players
ServerPackets.BroadcastPacketMessage(data); ServerPackets.BroadcastPacketMessage(data, null);
} else { } else {
LOGGER.info("Unable to update chat data, UUID not found: " + oldUUID); LOGGER.info("Unable to update chat data, UUID not found: " + oldUUID);
} }
......
...@@ -251,9 +251,64 @@ public class EntityChatData { ...@@ -251,9 +251,64 @@ public class EntityChatData {
return contextData; return contextData;
} }
// Generate a new character
public void generateCharacter(String userLanguage, ServerPlayerEntity player, String userMessage, boolean is_auto_message) {
String systemPrompt = "system-character";
if (is_auto_message) {
// Increment an auto-generated message
this.auto_generated++;
} else {
// Reset auto-generated counter
this.auto_generated = 0;
}
// Add USER Message
this.addMessage(userMessage, ChatDataManager.ChatSender.USER, player, systemPrompt);
// Get config (api key, url, settings)
ConfigurationHandler.Config config = new ConfigurationHandler(ServerPackets.serverInstance).loadConfig();
String promptText = ChatPrompt.loadPromptFromResource(ServerPackets.serverInstance.getResourceManager(), systemPrompt);
// Add PLAYER context information
Map<String, String> contextData = getPlayerContext(player, userLanguage, config);
// fetch HTTP response from ChatGPT
ChatGPTRequest.fetchMessageFromChatGPT(config, promptText, contextData, previousMessages, false).thenAccept(output_message -> {
if (output_message != null) {
// Character Sheet: Remove system-character message from previous messages
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, systemPrompt);
} else {
// Error / No Chat Message (Failure)
String randomErrorMessage = Randomizer.getRandomMessage(Randomizer.RandomType.ERROR);
this.addMessage(randomErrorMessage, ChatDataManager.ChatSender.ASSISTANT, player, systemPrompt);
// Determine error message to display
String errorMessage = "Help is available at discord.creaturechat.com";
if (!ChatGPTRequest.lastErrorMessage.isEmpty()) {
errorMessage = "Error: " + truncateString(ChatGPTRequest.lastErrorMessage, 55) + "\n" + errorMessage;
}
// Send clickable error message
ServerPackets.SendClickableError(player,
errorMessage, "http://discord.creaturechat.com");
// Clear history (if no character sheet was generated)
if (characterSheet.isEmpty()) {
previousMessages.clear();
}
}
});
}
// Generate greeting // Generate greeting
public void generateMessage(String userLanguage, ServerPlayerEntity player, String systemPrompt, String userMessage, boolean is_auto_message) { public void generateMessage(String userLanguage, ServerPlayerEntity player, String userMessage, boolean is_auto_message) {
this.status = ChatDataManager.ChatStatus.PENDING; String systemPrompt = "system-chat";
if (is_auto_message) { if (is_auto_message) {
// Increment an auto-generated message // Increment an auto-generated message
this.auto_generated++; this.auto_generated++;
...@@ -262,8 +317,8 @@ public class EntityChatData { ...@@ -262,8 +317,8 @@ public class EntityChatData {
this.auto_generated = 0; this.auto_generated = 0;
} }
// Add message // Add USER Message
this.addMessage(userMessage, ChatDataManager.ChatSender.USER, player.getDisplayName().getString(), systemPrompt); this.addMessage(userMessage, ChatDataManager.ChatSender.USER, player, systemPrompt);
// Get config (api key, url, settings) // Get config (api key, url, settings)
ConfigurationHandler.Config config = new ConfigurationHandler(ServerPackets.serverInstance).loadConfig(); ConfigurationHandler.Config config = new ConfigurationHandler(ServerPackets.serverInstance).loadConfig();
...@@ -274,7 +329,7 @@ public class EntityChatData { ...@@ -274,7 +329,7 @@ public class EntityChatData {
// Get messages for player // Get messages for player
PlayerData playerData = this.getPlayerData(player.getDisplayName().getString()); PlayerData playerData = this.getPlayerData(player.getDisplayName().getString());
if (previousMessages.size() == 1 && systemPrompt.equals("system-chat")) { if (previousMessages.size() == 1) {
// No messages exist yet for this player (start with normal greeting) // 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", " "); String shortGreeting = Optional.ofNullable(getCharacterProp("short greeting")).filter(s -> !s.isEmpty()).orElse(Randomizer.getRandomMessage(Randomizer.RandomType.NO_RESPONSE)).replace("\n", " ");
previousMessages.add(0, new ChatMessage(shortGreeting, ChatDataManager.ChatSender.ASSISTANT, player.getDisplayName().getString())); previousMessages.add(0, new ChatMessage(shortGreeting, ChatDataManager.ChatSender.ASSISTANT, player.getDisplayName().getString()));
...@@ -282,16 +337,7 @@ public class EntityChatData { ...@@ -282,16 +337,7 @@ public class EntityChatData {
// fetch HTTP response from ChatGPT // fetch HTTP response from ChatGPT
ChatGPTRequest.fetchMessageFromChatGPT(config, promptText, contextData, previousMessages, false).thenAccept(output_message -> { ChatGPTRequest.fetchMessageFromChatGPT(config, promptText, contextData, previousMessages, false).thenAccept(output_message -> {
if (output_message != null && systemPrompt.equals("system-character")) { if (output_message != null) {
// Character Sheet: Remove system-character message from previous messages
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.getDisplayName().getString(), systemPrompt);
} else if (output_message != null && systemPrompt.equals("system-chat")) {
// Chat Message: Parse message for behaviors // Chat Message: Parse message for behaviors
ParsedMessage result = MessageParser.parseMessage(output_message.replace("\n", " ")); ParsedMessage result = MessageParser.parseMessage(output_message.replace("\n", " "));
MobEntity entity = (MobEntity)ServerEntityFinder.getEntityByUUID(player.getServerWorld(), UUID.fromString(entityId)); MobEntity entity = (MobEntity)ServerEntityFinder.getEntityByUUID(player.getServerWorld(), UUID.fromString(entityId));
...@@ -479,7 +525,7 @@ public class EntityChatData { ...@@ -479,7 +525,7 @@ public class EntityChatData {
} }
// Add ASSISTANT message to history // Add ASSISTANT message to history
this.addMessage(result.getOriginalMessage(), ChatDataManager.ChatSender.ASSISTANT, player.getDisplayName().getString(), systemPrompt); this.addMessage(result.getOriginalMessage(), ChatDataManager.ChatSender.ASSISTANT, player, systemPrompt);
// Get cleaned message (i.e. no <BEHAVIOR> strings) // Get cleaned message (i.e. no <BEHAVIOR> strings)
String cleanedMessage = result.getCleanedMessage(); String cleanedMessage = result.getCleanedMessage();
...@@ -492,7 +538,7 @@ public class EntityChatData { ...@@ -492,7 +538,7 @@ public class EntityChatData {
} else { } else {
// Error / No Chat Message (Failure) // Error / No Chat Message (Failure)
String randomErrorMessage = Randomizer.getRandomMessage(Randomizer.RandomType.ERROR); String randomErrorMessage = Randomizer.getRandomMessage(Randomizer.RandomType.ERROR);
this.addMessage(randomErrorMessage, ChatDataManager.ChatSender.ASSISTANT, player.getDisplayName().getString(), systemPrompt); this.addMessage(randomErrorMessage, ChatDataManager.ChatSender.ASSISTANT, player, systemPrompt);
// Determine error message to display // Determine error message to display
String errorMessage = "Help is available at discord.creaturechat.com"; String errorMessage = "Help is available at discord.creaturechat.com";
...@@ -511,7 +557,7 @@ public class EntityChatData { ...@@ -511,7 +557,7 @@ public class EntityChatData {
} }
// Broadcast to all players // Broadcast to all players
ServerPackets.BroadcastPacketMessage(this); ServerPackets.BroadcastPacketMessage(this, player);
}); });
} }
...@@ -520,11 +566,12 @@ public class EntityChatData { ...@@ -520,11 +566,12 @@ public class EntityChatData {
} }
// Add a message to the history and update the current message // Add a message to the history and update the current message
public void addMessage(String message, ChatDataManager.ChatSender sender, String playerName, String systemPrompt) { public void addMessage(String message, ChatDataManager.ChatSender sender, ServerPlayerEntity player, String systemPrompt) {
// Truncate message (prevent crazy long messages... just in case) // Truncate message (prevent crazy long messages... just in case)
String truncatedMessage = message.substring(0, Math.min(message.length(), ChatDataManager.MAX_CHAR_IN_USER_MESSAGE)); String truncatedMessage = message.substring(0, Math.min(message.length(), ChatDataManager.MAX_CHAR_IN_USER_MESSAGE));
// Add context-switching logic for USER messages only // Add context-switching logic for USER messages only
String playerName = player.getDisplayName().getString();
if (sender == ChatDataManager.ChatSender.USER && previousMessages.size() > 1) { if (sender == ChatDataManager.ChatSender.USER && previousMessages.size() > 1) {
ChatMessage lastMessage = previousMessages.get(previousMessages.size() - 1); ChatMessage lastMessage = previousMessages.get(previousMessages.size() - 1);
if (lastMessage.name == null || !lastMessage.name.equals(playerName)) { // Null-safe check if (lastMessage.name == null || !lastMessage.name.equals(playerName)) { // Null-safe check
...@@ -542,19 +589,20 @@ public class EntityChatData { ...@@ -542,19 +589,20 @@ public class EntityChatData {
// Update current message and reset line number of displayed text // Update current message and reset line number of displayed text
this.currentMessage = truncatedMessage; this.currentMessage = truncatedMessage;
this.currentLineNumber = 0; this.currentLineNumber = 0;
this.sender = sender;
// Determine status for message
if (sender == ChatDataManager.ChatSender.ASSISTANT) { if (sender == ChatDataManager.ChatSender.ASSISTANT) {
// Show new generated message
status = ChatDataManager.ChatStatus.DISPLAY; status = ChatDataManager.ChatStatus.DISPLAY;
} else if (sender == ChatDataManager.ChatSender.USER) { } else if (sender == ChatDataManager.ChatSender.USER && systemPrompt.equals("system-chat")) {
// Show pending icon // Only show system-chat messages above players (not system-character ones)
status = ChatDataManager.ChatStatus.DISPLAY;
} else {
status = ChatDataManager.ChatStatus.PENDING; status = ChatDataManager.ChatStatus.PENDING;
} }
this.sender = sender;
// Broadcast to all players // Broadcast to all players
if (systemPrompt.equals("system-chat")) { ServerPackets.BroadcastPacketMessage(this, player);
ServerPackets.BroadcastPacketMessage(this);
}
} }
// Get wrapped lines // Get wrapped lines
...@@ -574,13 +622,13 @@ public class EntityChatData { ...@@ -574,13 +622,13 @@ public class EntityChatData {
currentLineNumber = Math.min(Math.max(lineNumber, 0), totalLines); currentLineNumber = Math.min(Math.max(lineNumber, 0), totalLines);
// Broadcast to all players // Broadcast to all players
ServerPackets.BroadcastPacketMessage(this); ServerPackets.BroadcastPacketMessage(this, null);
} }
public void setStatus(ChatDataManager.ChatStatus new_status) { public void setStatus(ChatDataManager.ChatStatus new_status) {
status = new_status; status = new_status;
// Broadcast to all players // Broadcast to all players
ServerPackets.BroadcastPacketMessage(this); ServerPackets.BroadcastPacketMessage(this, null);
} }
} }
\ No newline at end of file
...@@ -315,7 +315,7 @@ public class ServerPackets { ...@@ -315,7 +315,7 @@ public class ServerPackets {
userMessageBuilder.append("They speak in '").append(userLanguage).append("' with a ").append(randomSpeakingStyle).append(" style."); userMessageBuilder.append("They speak in '").append(userLanguage).append("' with a ").append(randomSpeakingStyle).append(" style.");
LOGGER.info(userMessageBuilder.toString()); LOGGER.info(userMessageBuilder.toString());
chatData.generateMessage(userLanguage, player, "system-character", userMessageBuilder.toString(), false); chatData.generateCharacter(userLanguage, player, userMessageBuilder.toString(), false);
} }
public static void generate_chat(String userLanguage, EntityChatData chatData, ServerPlayerEntity player, MobEntity entity, String message, boolean is_auto_message) { public static void generate_chat(String userLanguage, EntityChatData chatData, ServerPlayerEntity player, MobEntity entity, String message, boolean is_auto_message) {
...@@ -325,11 +325,11 @@ public class ServerPackets { ...@@ -325,11 +325,11 @@ public class ServerPackets {
// Add new message // Add new message
LOGGER.info("Player message received: " + message + " | Entity: " + entity.getType().toString()); LOGGER.info("Player message received: " + message + " | Entity: " + entity.getType().toString());
chatData.generateMessage(userLanguage, player, "system-chat", message, is_auto_message); chatData.generateMessage(userLanguage, player, message, is_auto_message);
} }
// Send new message to all connected players // Send new message to all connected players
public static void BroadcastPacketMessage(EntityChatData chatData) { public static void BroadcastPacketMessage(EntityChatData chatData, ServerPlayerEntity sender) {
for (ServerWorld world : serverInstance.getWorlds()) { for (ServerWorld world : serverInstance.getWorlds()) {
UUID entityId = UUID.fromString(chatData.entityId); UUID entityId = UUID.fromString(chatData.entityId);
MobEntity entity = (MobEntity)ServerEntityFinder.getEntityByUUID(world, entityId); MobEntity entity = (MobEntity)ServerEntityFinder.getEntityByUUID(world, entityId);
...@@ -351,8 +351,13 @@ public class ServerPackets { ...@@ -351,8 +351,13 @@ public class ServerPackets {
// Write the entity's chat updated data // Write the entity's chat updated data
buffer.writeString(chatData.entityId); buffer.writeString(chatData.entityId);
buffer.writeString(player.getUuidAsString()); if (sender != null) {
buffer.writeString(player.getDisplayName().getString()); buffer.writeString(sender.getUuidAsString());
buffer.writeString(sender.getDisplayName().toString());
} else {
buffer.writeString("");
buffer.writeString("Unknown");
}
buffer.writeString(chatData.currentMessage); buffer.writeString(chatData.currentMessage);
buffer.writeInt(chatData.currentLineNumber); buffer.writeInt(chatData.currentLineNumber);
buffer.writeString(chatData.status.toString()); buffer.writeString(chatData.status.toString());
......
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