Commit 1e55dcba by Jonathan Thomas

Improved error handling to prevent broken "..." pending chat status. (HTTP and…

Improved error handling to prevent broken "..." pending chat status. (HTTP and message processing is more protected). Removed randomized error messages from chat history (so it doesn't break the chat history when an error is shown)
parent a5fb3933
Pipeline #13344 passed with stages
in 2 minutes 28 seconds
......@@ -11,11 +11,13 @@ All notable changes to **CreatureChat** are documented in this file. The format
### Changed
- Broadcasting and receiving chat messages now ignores if the UUID is valid (to keep data synced)
- Improved error handling to prevent broken "..." pending chat status. (HTTP and message processing is more protected)
### Fixed
- Bees no longer forget their chat data when entering/leaving hives (writeNbt & readNbt modified)
- Vexes no longer take damage when chat data exists
- Wandering Trader no longer despawns if it has chat data
- Removed randomized error messages from chat history (so it doesn't break the chat history when an error is shown)
## [1.3.0] - 2025-01-14
......
......@@ -196,6 +196,7 @@ public class ChatGPTRequest {
lastErrorMessage = cleanError;
} catch (Exception e) {
LOGGER.error("Failed to read error response", e);
lastErrorMessage = "Failed to read error response: " + e.getMessage();
}
return null;
} else {
......@@ -214,12 +215,16 @@ public class ChatGPTRequest {
if (chatGPTResponse != null && chatGPTResponse.choices != null && !chatGPTResponse.choices.isEmpty()) {
String content = chatGPTResponse.choices.get(0).message.content;
return content;
} else {
lastErrorMessage = "Failed to parse response from LLM";
return null;
}
}
} catch (IOException e) {
LOGGER.error("Failed to fetch message from ChatGPT", e);
} catch (Exception e) {
LOGGER.error("Failed to request message from LLM", e);
lastErrorMessage = "Failed to request message from LLM: " + e.getMessage();
return null;
}
return null; // If there was an error or no response, return null
});
}
}
......
......@@ -273,34 +273,41 @@ public class EntityChatData {
// 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();
try {
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 {
// No valid LLM response
throw new RuntimeException(ChatGPTRequest.lastErrorMessage);
}
// 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);
} catch (Exception e) {
// Log the exception for debugging
LOGGER.error("Error processing LLM response", e);
} 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;
// Remove the error message from history to prevent it from affecting future ChatGPT requests
if (!previousMessages.isEmpty()) {
previousMessages.remove(previousMessages.size() - 1);
}
// 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();
String errorMessage = "Error: ";
if (e.getMessage() != null && !e.getMessage().isEmpty()) {
errorMessage += truncateString(e.getMessage(), 55) + "\n";
}
errorMessage += "Help is available at discord.creaturechat.com";
ServerPackets.SendClickableError(player, errorMessage, "http://discord.creaturechat.com");
}
});
}
......@@ -336,236 +343,242 @@ public class EntityChatData {
// fetch HTTP response from ChatGPT
ChatGPTRequest.fetchMessageFromChatGPT(config, promptText, contextData, previousMessages, false).thenAccept(output_message -> {
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));
// Determine entity's default speed
// Some Entities (i.e. Axolotl) set this incorrectly... so adjusting in the SpeedControls class
float entitySpeed = SpeedControls.getMaxSpeed(entity);
float entitySpeedMedium = MathHelper.clamp(entitySpeed * 1.15F, 0.5f, 1.15f);
float entitySpeedFast = MathHelper.clamp(entitySpeed * 1.3F, 0.5f, 1.3f);
// Apply behaviors (if any)
for (Behavior behavior : result.getBehaviors()) {
LOGGER.info("Behavior: " + behavior.getName() + (behavior.getArgument() != null ?
", Argument: " + behavior.getArgument() : ""));
// Apply behaviors to entity
if (behavior.getName().equals("FOLLOW")) {
FollowPlayerGoal followGoal = new FollowPlayerGoal(player, entity, entitySpeedMedium);
EntityBehaviorManager.removeGoal(entity, TalkPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, FleePlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, AttackPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, LeadPlayerGoal.class);
EntityBehaviorManager.addGoal(entity, followGoal, GoalPriority.FOLLOW_PLAYER);
if (playerData.friendship >= 0) {
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, FOLLOW_FRIEND_PARTICLE, 0.5, 1);
} else {
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, FOLLOW_ENEMY_PARTICLE, 0.5, 1);
}
try {
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));
// Determine entity's default speed
// Some Entities (i.e. Axolotl) set this incorrectly... so adjusting in the SpeedControls class
float entitySpeed = SpeedControls.getMaxSpeed(entity);
float entitySpeedMedium = MathHelper.clamp(entitySpeed * 1.15F, 0.5f, 1.15f);
float entitySpeedFast = MathHelper.clamp(entitySpeed * 1.3F, 0.5f, 1.3f);
// Apply behaviors (if any)
for (Behavior behavior : result.getBehaviors()) {
LOGGER.info("Behavior: " + behavior.getName() + (behavior.getArgument() != null ?
", Argument: " + behavior.getArgument() : ""));
// Apply behaviors to entity
if (behavior.getName().equals("FOLLOW")) {
FollowPlayerGoal followGoal = new FollowPlayerGoal(player, entity, entitySpeedMedium);
EntityBehaviorManager.removeGoal(entity, TalkPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, FleePlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, AttackPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, LeadPlayerGoal.class);
EntityBehaviorManager.addGoal(entity, followGoal, GoalPriority.FOLLOW_PLAYER);
if (playerData.friendship >= 0) {
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, FOLLOW_FRIEND_PARTICLE, 0.5, 1);
} else {
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, FOLLOW_ENEMY_PARTICLE, 0.5, 1);
}
} else if (behavior.getName().equals("UNFOLLOW")) {
EntityBehaviorManager.removeGoal(entity, FollowPlayerGoal.class);
} else if (behavior.getName().equals("FLEE")) {
float fleeDistance = 40F;
FleePlayerGoal fleeGoal = new FleePlayerGoal(player, entity, entitySpeedFast, fleeDistance);
EntityBehaviorManager.removeGoal(entity, TalkPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, FollowPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, AttackPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, ProtectPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, LeadPlayerGoal.class);
EntityBehaviorManager.addGoal(entity, fleeGoal, GoalPriority.FLEE_PLAYER);
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, FLEE_PARTICLE, 0.5, 1);
} else if (behavior.getName().equals("UNFLEE")) {
EntityBehaviorManager.removeGoal(entity, FleePlayerGoal.class);
} else if (behavior.getName().equals("ATTACK")) {
AttackPlayerGoal attackGoal = new AttackPlayerGoal(player, entity, entitySpeedFast);
EntityBehaviorManager.removeGoal(entity, TalkPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, FollowPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, FleePlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, ProtectPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, LeadPlayerGoal.class);
EntityBehaviorManager.addGoal(entity, attackGoal, GoalPriority.ATTACK_PLAYER);
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, FLEE_PARTICLE, 0.5, 1);
} else if (behavior.getName().equals("PROTECT")) {
if (playerData.friendship <= 0) {
// force friendship to prevent entity from attacking player when protecting
playerData.friendship = 1;
}
ProtectPlayerGoal protectGoal = new ProtectPlayerGoal(player, entity, 1.0);
EntityBehaviorManager.removeGoal(entity, TalkPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, FleePlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, AttackPlayerGoal.class);
EntityBehaviorManager.addGoal(entity, protectGoal, GoalPriority.PROTECT_PLAYER);
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, PROTECT_PARTICLE, 0.5, 1);
} else if (behavior.getName().equals("UNPROTECT")) {
EntityBehaviorManager.removeGoal(entity, ProtectPlayerGoal.class);
} else if (behavior.getName().equals("LEAD")) {
LeadPlayerGoal leadGoal = new LeadPlayerGoal(player, entity, entitySpeedMedium);
EntityBehaviorManager.removeGoal(entity, FollowPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, FleePlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, AttackPlayerGoal.class);
EntityBehaviorManager.addGoal(entity, leadGoal, GoalPriority.LEAD_PLAYER);
if (playerData.friendship >= 0) {
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, LEAD_FRIEND_PARTICLE, 0.5, 1);
} else {
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, LEAD_ENEMY_PARTICLE, 0.5, 1);
}
} else if (behavior.getName().equals("UNLEAD")) {
EntityBehaviorManager.removeGoal(entity, LeadPlayerGoal.class);
} else if (behavior.getName().equals("UNFOLLOW")) {
EntityBehaviorManager.removeGoal(entity, FollowPlayerGoal.class);
} else if (behavior.getName().equals("FRIENDSHIP")) {
int new_friendship = Math.max(-3, Math.min(3, behavior.getArgument()));
} else if (behavior.getName().equals("FLEE")) {
float fleeDistance = 40F;
FleePlayerGoal fleeGoal = new FleePlayerGoal(player, entity, entitySpeedFast, fleeDistance);
EntityBehaviorManager.removeGoal(entity, TalkPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, FollowPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, AttackPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, ProtectPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, LeadPlayerGoal.class);
EntityBehaviorManager.addGoal(entity, fleeGoal, GoalPriority.FLEE_PLAYER);
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, FLEE_PARTICLE, 0.5, 1);
// Does friendship improve?
if (new_friendship > playerData.friendship) {
// Stop any attack/flee if friendship improves
} else if (behavior.getName().equals("UNFLEE")) {
EntityBehaviorManager.removeGoal(entity, FleePlayerGoal.class);
} else if (behavior.getName().equals("ATTACK")) {
AttackPlayerGoal attackGoal = new AttackPlayerGoal(player, entity, entitySpeedFast);
EntityBehaviorManager.removeGoal(entity, TalkPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, FollowPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, FleePlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, ProtectPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, LeadPlayerGoal.class);
EntityBehaviorManager.addGoal(entity, attackGoal, GoalPriority.ATTACK_PLAYER);
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, FLEE_PARTICLE, 0.5, 1);
} else if (behavior.getName().equals("PROTECT")) {
if (playerData.friendship <= 0) {
// force friendship to prevent entity from attacking player when protecting
playerData.friendship = 1;
}
ProtectPlayerGoal protectGoal = new ProtectPlayerGoal(player, entity, 1.0);
EntityBehaviorManager.removeGoal(entity, TalkPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, FleePlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, AttackPlayerGoal.class);
EntityBehaviorManager.addGoal(entity, protectGoal, GoalPriority.PROTECT_PLAYER);
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, PROTECT_PARTICLE, 0.5, 1);
} else if (behavior.getName().equals("UNPROTECT")) {
EntityBehaviorManager.removeGoal(entity, ProtectPlayerGoal.class);
if (entity instanceof WitherEntity && new_friendship == 3) {
// Best friend a Nether and get a NETHER_STAR
WitherEntity wither = (WitherEntity) entity;
((WitherEntityAccessor) wither).callDropEquipment(entity.getWorld().getDamageSources().generic(), 1, true);
entity.getWorld().playSound(entity, entity.getBlockPos(), SoundEvents.ENTITY_WITHER_DEATH, SoundCategory.PLAYERS, 0.3F, 1.0F);
} else if (behavior.getName().equals("LEAD")) {
LeadPlayerGoal leadGoal = new LeadPlayerGoal(player, entity, entitySpeedMedium);
EntityBehaviorManager.removeGoal(entity, FollowPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, FleePlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, AttackPlayerGoal.class);
EntityBehaviorManager.addGoal(entity, leadGoal, GoalPriority.LEAD_PLAYER);
if (playerData.friendship >= 0) {
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, LEAD_FRIEND_PARTICLE, 0.5, 1);
} else {
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, LEAD_ENEMY_PARTICLE, 0.5, 1);
}
} else if (behavior.getName().equals("UNLEAD")) {
EntityBehaviorManager.removeGoal(entity, LeadPlayerGoal.class);
} else if (behavior.getName().equals("FRIENDSHIP")) {
int new_friendship = Math.max(-3, Math.min(3, behavior.getArgument()));
// Does friendship improve?
if (new_friendship > playerData.friendship) {
// Stop any attack/flee if friendship improves
EntityBehaviorManager.removeGoal(entity, FleePlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, AttackPlayerGoal.class);
if (entity instanceof WitherEntity && new_friendship == 3) {
// Best friend a Nether and get a NETHER_STAR
WitherEntity wither = (WitherEntity) entity;
((WitherEntityAccessor) wither).callDropEquipment(entity.getWorld().getDamageSources().generic(), 1, true);
entity.getWorld().playSound(entity, entity.getBlockPos(), SoundEvents.ENTITY_WITHER_DEATH, SoundCategory.PLAYERS, 0.3F, 1.0F);
}
if (entity instanceof EnderDragonEntity && new_friendship == 3) {
// Trigger end of game (friendship always wins!)
EnderDragonEntity dragon = (EnderDragonEntity) entity;
if (entity instanceof EnderDragonEntity && new_friendship == 3) {
// Trigger end of game (friendship always wins!)
EnderDragonEntity dragon = (EnderDragonEntity) entity;
// Emit particles & sound
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, HEART_BIG_PARTICLE, 3, 200);
entity.getWorld().playSound(entity, entity.getBlockPos(), SoundEvents.ENTITY_ENDER_DRAGON_DEATH, SoundCategory.PLAYERS, 0.3F, 1.0F);
entity.getWorld().playSound(entity, entity.getBlockPos(), SoundEvents.UI_TOAST_CHALLENGE_COMPLETE, SoundCategory.PLAYERS, 0.5F, 1.0F);
// Emit particles & sound
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, HEART_BIG_PARTICLE, 3, 200);
entity.getWorld().playSound(entity, entity.getBlockPos(), SoundEvents.ENTITY_ENDER_DRAGON_DEATH, SoundCategory.PLAYERS, 0.3F, 1.0F);
entity.getWorld().playSound(entity, entity.getBlockPos(), SoundEvents.UI_TOAST_CHALLENGE_COMPLETE, SoundCategory.PLAYERS, 0.5F, 1.0F);
// Check if the game rule for mob loot is enabled
boolean doMobLoot = entity.getWorld().getGameRules().getBoolean(GameRules.DO_MOB_LOOT);
// Check if the game rule for mob loot is enabled
boolean doMobLoot = entity.getWorld().getGameRules().getBoolean(GameRules.DO_MOB_LOOT);
// If this is the first time the dragon is 'befriended', adjust the XP
int baseXP = 500;
if (dragon.getFight() != null && !dragon.getFight().hasPreviouslyKilled()) {
baseXP = 12000;
}
// If this is the first time the dragon is 'befriended', adjust the XP
int baseXP = 500;
if (dragon.getFight() != null && !dragon.getFight().hasPreviouslyKilled()) {
baseXP = 12000;
}
// If the world is a server world and mob loot is enabled, spawn XP orbs
if (entity.getWorld() instanceof ServerWorld && doMobLoot) {
// Loop to spawn XP orbs
for (int j = 1; j <= 11; j++) {
float xpFraction = (j == 11) ? 0.2F : 0.08F;
int xpAmount = MathHelper.floor((float)baseXP * xpFraction);
ExperienceOrbEntity.spawn((ServerWorld)entity.getWorld(), entity.getPos(), xpAmount);
// If the world is a server world and mob loot is enabled, spawn XP orbs
if (entity.getWorld() instanceof ServerWorld && doMobLoot) {
// Loop to spawn XP orbs
for (int j = 1; j <= 11; j++) {
float xpFraction = (j == 11) ? 0.2F : 0.08F;
int xpAmount = MathHelper.floor((float) baseXP * xpFraction);
ExperienceOrbEntity.spawn((ServerWorld) entity.getWorld(), entity.getPos(), xpAmount);
}
}
}
// Mark fight as over
dragon.getFight().dragonKilled(dragon);
// Mark fight as over
dragon.getFight().dragonKilled(dragon);
}
}
}
// Merchant deals (if friendship changes with a Villager
if (entity instanceof VillagerEntity && playerData.friendship != new_friendship) {
VillagerEntityAccessor villager = (VillagerEntityAccessor) entity;
switch (new_friendship) {
case 3:
villager.getGossip().startGossip(player.getUuid(), VillageGossipType.MAJOR_POSITIVE, 20);
villager.getGossip().startGossip(player.getUuid(), VillageGossipType.MINOR_POSITIVE, 25);
break;
case 2:
villager.getGossip().startGossip(player.getUuid(), VillageGossipType.MINOR_POSITIVE, 25);
break;
case 1:
villager.getGossip().startGossip(player.getUuid(), VillageGossipType.MINOR_POSITIVE, 10);
break;
case -1:
villager.getGossip().startGossip(player.getUuid(), VillageGossipType.MINOR_NEGATIVE, 10);
break;
case -2:
villager.getGossip().startGossip(player.getUuid(), VillageGossipType.MINOR_NEGATIVE, 25);
break;
case -3:
villager.getGossip().startGossip(player.getUuid(), VillageGossipType.MAJOR_NEGATIVE, 20);
villager.getGossip().startGossip(player.getUuid(), VillageGossipType.MINOR_NEGATIVE, 25);
break;
// Merchant deals (if friendship changes with a Villager
if (entity instanceof VillagerEntity && playerData.friendship != new_friendship) {
VillagerEntityAccessor villager = (VillagerEntityAccessor) entity;
switch (new_friendship) {
case 3:
villager.getGossip().startGossip(player.getUuid(), VillageGossipType.MAJOR_POSITIVE, 20);
villager.getGossip().startGossip(player.getUuid(), VillageGossipType.MINOR_POSITIVE, 25);
break;
case 2:
villager.getGossip().startGossip(player.getUuid(), VillageGossipType.MINOR_POSITIVE, 25);
break;
case 1:
villager.getGossip().startGossip(player.getUuid(), VillageGossipType.MINOR_POSITIVE, 10);
break;
case -1:
villager.getGossip().startGossip(player.getUuid(), VillageGossipType.MINOR_NEGATIVE, 10);
break;
case -2:
villager.getGossip().startGossip(player.getUuid(), VillageGossipType.MINOR_NEGATIVE, 25);
break;
case -3:
villager.getGossip().startGossip(player.getUuid(), VillageGossipType.MAJOR_NEGATIVE, 20);
villager.getGossip().startGossip(player.getUuid(), VillageGossipType.MINOR_NEGATIVE, 25);
break;
}
}
}
// Tame best friends and un-tame worst enemies
if (entity instanceof TameableEntity && playerData.friendship != new_friendship) {
TameableEntity tamableEntity = (TameableEntity) entity;
if (new_friendship == 3 && !tamableEntity.isTamed()) {
tamableEntity.setOwner(player);
} else if (new_friendship == -3 && tamableEntity.isTamed()) {
tamableEntity.setTamed(false);
tamableEntity.setOwnerUuid(null);
// Tame best friends and un-tame worst enemies
if (entity instanceof TameableEntity && playerData.friendship != new_friendship) {
TameableEntity tamableEntity = (TameableEntity) entity;
if (new_friendship == 3 && !tamableEntity.isTamed()) {
tamableEntity.setOwner(player);
} else if (new_friendship == -3 && tamableEntity.isTamed()) {
tamableEntity.setTamed(false);
tamableEntity.setOwnerUuid(null);
}
}
}
// Emit friendship particles
if (playerData.friendship != new_friendship) {
int friendDiff = new_friendship - playerData.friendship;
if (friendDiff > 0) {
// Heart particles
if (new_friendship == 3) {
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, HEART_BIG_PARTICLE, 0.5, 10);
} else {
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, HEART_SMALL_PARTICLE, 0.1, 1);
}
// Emit friendship particles
if (playerData.friendship != new_friendship) {
int friendDiff = new_friendship - playerData.friendship;
if (friendDiff > 0) {
// Heart particles
if (new_friendship == 3) {
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, HEART_BIG_PARTICLE, 0.5, 10);
} else {
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, HEART_SMALL_PARTICLE, 0.1, 1);
}
} else if (friendDiff < 0) {
// Fire particles
if (new_friendship == -3) {
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, FIRE_BIG_PARTICLE, 0.5, 10);
} else {
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, FIRE_SMALL_PARTICLE, 0.1, 1);
} else if (friendDiff < 0) {
// Fire particles
if (new_friendship == -3) {
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, FIRE_BIG_PARTICLE, 0.5, 10);
} else {
ParticleEmitter.emitCreatureParticle((ServerWorld) entity.getWorld(), entity, FIRE_SMALL_PARTICLE, 0.1, 1);
}
}
}
playerData.friendship = new_friendship;
}
}
playerData.friendship = new_friendship;
// Get cleaned message (i.e. no <BEHAVIOR> strings)
String cleanedMessage = result.getCleanedMessage();
if (cleanedMessage.isEmpty()) {
cleanedMessage = Randomizer.getRandomMessage(Randomizer.RandomType.NO_RESPONSE);
}
}
// Get cleaned message (i.e. no <BEHAVIOR> strings)
String cleanedMessage = result.getCleanedMessage();
if (cleanedMessage.isEmpty()) {
cleanedMessage = Randomizer.getRandomMessage(Randomizer.RandomType.NO_RESPONSE);
}
// Add ASSISTANT message to history
this.addMessage(cleanedMessage, ChatDataManager.ChatSender.ASSISTANT, player, systemPrompt);
// Add ASSISTANT message to history
this.addMessage(cleanedMessage, ChatDataManager.ChatSender.ASSISTANT, player, systemPrompt);
// Update the last entry in previousMessages to use the original message
this.previousMessages.set(this.previousMessages.size() - 1,
new ChatMessage(result.getOriginalMessage(), ChatDataManager.ChatSender.ASSISTANT, player.getDisplayName().getString()));
// Update the last entry in previousMessages to use the original message
this.previousMessages.set(this.previousMessages.size() - 1,
new ChatMessage(result.getOriginalMessage(), ChatDataManager.ChatSender.ASSISTANT, player.getDisplayName().getString()));
} else {
// No valid LLM response
throw new RuntimeException(ChatGPTRequest.lastErrorMessage);
}
} catch (Exception e) {
// Log the exception for debugging
LOGGER.error("Error processing LLM response", e);
} 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;
// Remove the error message from history to prevent it from affecting future ChatGPT requests
if (!previousMessages.isEmpty()) {
previousMessages.remove(previousMessages.size() - 1);
}
// 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();
String errorMessage = "Error: ";
if (e.getMessage() != null && !e.getMessage().isEmpty()) {
errorMessage += truncateString(e.getMessage(), 55) + "\n";
}
errorMessage += "Help is available at discord.creaturechat.com";
ServerPackets.SendClickableError(player, errorMessage, "http://discord.creaturechat.com");
}
});
}
......
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