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
- Removed "pirate" speaking style and a few <non-response> outputs
- 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
- Seperated `generateCharacter()` and `generateMessage()` functions for simplicity
### Fixed
- Fixed a regression caused by adding a "-forge" suffix to one of our builds
......
......@@ -101,8 +101,14 @@ public class ClientPackets {
ClientPlayNetworking.registerGlobalReceiver(ServerPackets.PACKET_S2C_MESSAGE, (client, handler, buffer, responseSender) -> {
// 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 sendingPlayerIdStr = 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);
int line = buffer.readInt();
String status_name = buffer.readString(32767);
......@@ -110,23 +116,24 @@ public class ClientPackets {
int friendship = buffer.readInt();
// 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
MobEntity entity = ClientEntityFinder.getEntityByUUID(client.world, entityId);
if (entity != null) {
ChatDataManager chatDataManager = ChatDataManager.getClientInstance();
EntityChatData chatData = chatDataManager.getOrCreateChatData(entity.getUuidAsString(), playerName);
EntityChatData chatData = chatDataManager.getOrCreateChatData(entity.getUuidAsString(), currentPlayerName);
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 playerData = chatData.getPlayerData(currentPlayerName);
playerData.friendship = friendship;
if (chatData.sender == ChatDataManager.ChatSender.USER && chatData.status == ChatDataManager.ChatStatus.DISPLAY) {
// 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)
......
......@@ -12,7 +12,7 @@ public class PlayerMessageManager {
private static final ConcurrentHashMap<UUID, PlayerMessage> messages = 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));
}
......
......@@ -85,7 +85,7 @@ public class ChatDataManager {
LOGGER.info("Updated chat data from UUID (" + oldUUID + ") to UUID (" + newUUID + ")");
// Broadcast to all players
ServerPackets.BroadcastPacketMessage(data);
ServerPackets.BroadcastPacketMessage(data, null);
} else {
LOGGER.info("Unable to update chat data, UUID not found: " + oldUUID);
}
......
......@@ -251,9 +251,64 @@ public class EntityChatData {
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
public void generateMessage(String userLanguage, ServerPlayerEntity player, String systemPrompt, String userMessage, boolean is_auto_message) {
this.status = ChatDataManager.ChatStatus.PENDING;
public void generateMessage(String userLanguage, ServerPlayerEntity player, String userMessage, boolean is_auto_message) {
String systemPrompt = "system-chat";
if (is_auto_message) {
// Increment an auto-generated message
this.auto_generated++;
......@@ -262,8 +317,8 @@ public class EntityChatData {
this.auto_generated = 0;
}
// Add message
this.addMessage(userMessage, ChatDataManager.ChatSender.USER, player.getDisplayName().getString(), systemPrompt);
// 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();
......@@ -274,7 +329,7 @@ public class EntityChatData {
// Get messages for player
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)
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()));
......@@ -282,16 +337,7 @@ public class EntityChatData {
// fetch HTTP response from ChatGPT
ChatGPTRequest.fetchMessageFromChatGPT(config, promptText, contextData, previousMessages, false).thenAccept(output_message -> {
if (output_message != null && systemPrompt.equals("system-character")) {
// 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")) {
if (output_message != null) {
// Chat Message: Parse message for behaviors
ParsedMessage result = MessageParser.parseMessage(output_message.replace("\n", " "));
MobEntity entity = (MobEntity)ServerEntityFinder.getEntityByUUID(player.getServerWorld(), UUID.fromString(entityId));
......@@ -479,7 +525,7 @@ public class EntityChatData {
}
// 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)
String cleanedMessage = result.getCleanedMessage();
......@@ -492,7 +538,7 @@ public class EntityChatData {
} else {
// Error / No Chat Message (Failure)
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
String errorMessage = "Help is available at discord.creaturechat.com";
......@@ -511,7 +557,7 @@ public class EntityChatData {
}
// Broadcast to all players
ServerPackets.BroadcastPacketMessage(this);
ServerPackets.BroadcastPacketMessage(this, player);
});
}
......@@ -520,11 +566,12 @@ public class EntityChatData {
}
// 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)
String truncatedMessage = message.substring(0, Math.min(message.length(), ChatDataManager.MAX_CHAR_IN_USER_MESSAGE));
// Add context-switching logic for USER messages only
String playerName = player.getDisplayName().getString();
if (sender == ChatDataManager.ChatSender.USER && previousMessages.size() > 1) {
ChatMessage lastMessage = previousMessages.get(previousMessages.size() - 1);
if (lastMessage.name == null || !lastMessage.name.equals(playerName)) { // Null-safe check
......@@ -542,19 +589,20 @@ public class EntityChatData {
// Update current message and reset line number of displayed text
this.currentMessage = truncatedMessage;
this.currentLineNumber = 0;
this.sender = sender;
// Determine status for message
if (sender == ChatDataManager.ChatSender.ASSISTANT) {
// Show new generated message
status = ChatDataManager.ChatStatus.DISPLAY;
} else if (sender == ChatDataManager.ChatSender.USER) {
// Show pending icon
} else if (sender == ChatDataManager.ChatSender.USER && systemPrompt.equals("system-chat")) {
// Only show system-chat messages above players (not system-character ones)
status = ChatDataManager.ChatStatus.DISPLAY;
} else {
status = ChatDataManager.ChatStatus.PENDING;
}
this.sender = sender;
// Broadcast to all players
if (systemPrompt.equals("system-chat")) {
ServerPackets.BroadcastPacketMessage(this);
}
ServerPackets.BroadcastPacketMessage(this, player);
}
// Get wrapped lines
......@@ -574,13 +622,13 @@ public class EntityChatData {
currentLineNumber = Math.min(Math.max(lineNumber, 0), totalLines);
// Broadcast to all players
ServerPackets.BroadcastPacketMessage(this);
ServerPackets.BroadcastPacketMessage(this, null);
}
public void setStatus(ChatDataManager.ChatStatus new_status) {
status = new_status;
// Broadcast to all players
ServerPackets.BroadcastPacketMessage(this);
ServerPackets.BroadcastPacketMessage(this, null);
}
}
\ No newline at end of file
......@@ -315,7 +315,7 @@ public class ServerPackets {
userMessageBuilder.append("They speak in '").append(userLanguage).append("' with a ").append(randomSpeakingStyle).append(" style.");
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) {
......@@ -325,11 +325,11 @@ public class ServerPackets {
// Add new message
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
public static void BroadcastPacketMessage(EntityChatData chatData) {
public static void BroadcastPacketMessage(EntityChatData chatData, ServerPlayerEntity sender) {
for (ServerWorld world : serverInstance.getWorlds()) {
UUID entityId = UUID.fromString(chatData.entityId);
MobEntity entity = (MobEntity)ServerEntityFinder.getEntityByUUID(world, entityId);
......@@ -351,8 +351,13 @@ public class ServerPackets {
// Write the entity's chat updated data
buffer.writeString(chatData.entityId);
buffer.writeString(player.getUuidAsString());
buffer.writeString(player.getDisplayName().getString());
if (sender != null) {
buffer.writeString(sender.getUuidAsString());
buffer.writeString(sender.getDisplayName().toString());
} else {
buffer.writeString("");
buffer.writeString("Unknown");
}
buffer.writeString(chatData.currentMessage);
buffer.writeInt(chatData.currentLineNumber);
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