diff --git a/src/main/java/com/tiedup/remake/cells/CellRegistryV2.java b/src/main/java/com/tiedup/remake/cells/CellRegistryV2.java index 91e4345..122baf1 100644 --- a/src/main/java/com/tiedup/remake/cells/CellRegistryV2.java +++ b/src/main/java/com/tiedup/remake/cells/CellRegistryV2.java @@ -670,13 +670,7 @@ public class CellRegistryV2 extends SavedData { if (server == null || ownerId == null) return; ServerPlayer owner = server.getPlayerList().getPlayer(ownerId); if (owner != null) { - String template = SystemMessageManager.getTemplate(category); - String formattedMessage = String.format(template, prisonerName); - SystemMessageManager.sendToPlayer( - owner, - category, - formattedMessage - ); + SystemMessageManager.sendTranslatable(owner, category, prisonerName); } } diff --git a/src/main/java/com/tiedup/remake/core/SystemMessageManager.java b/src/main/java/com/tiedup/remake/core/SystemMessageManager.java index f790e62..c36dd76 100644 --- a/src/main/java/com/tiedup/remake/core/SystemMessageManager.java +++ b/src/main/java/com/tiedup/remake/core/SystemMessageManager.java @@ -138,120 +138,17 @@ public class SystemMessageManager { ERROR, // Generic error } - // MESSAGE TEMPLATES + // TRANSLATION KEYS /** - * Get the raw message template for a category. - * Use this when you need to customize the message. + * Get the translation key for a category. + * Keys follow the pattern: msg.tiedup.system.<category_lowercase> * * @param category The message category - * @return The template string (may contain %s placeholders) + * @return The translation key (for use with Component.translatable) */ - public static String getTemplate(MessageCategory category) { - return getMessageTemplate(category); - } - - /** - * Get message template for a category. - * Use %s for entity name placeholder. - */ - private static String getMessageTemplate(MessageCategory category) { - return switch (category) { - // Restraint actions - case BEING_TIED -> "%s is tying you up!"; - case TIED_UP -> "%s tied you up, you can't move!"; - case BEING_GAGGED -> "%s is gagging you!"; - case GAGGED -> "%s gagged you, you can't speak!"; - case BEING_BLINDFOLDED -> "%s is blindfolding you!"; - case BLINDFOLDED -> "%s blindfolded you, you can't see!"; - case BEING_COLLARED -> "%s is putting a collar on you!"; - case COLLARED -> "%s collared you!"; - case EARPLUGS_ON -> "%s put earplugs on you!"; - case MITTENS_ON -> "%s put mittens on you!"; - case ENSLAVED -> "You have been enslaved by %s!"; - // Restraint actions (kidnapper's perspective) - case TYING_TARGET -> "You are tying %s..."; - case TIED_TARGET -> "You tied %s!"; - case GAGGING_TARGET -> "You are gagging %s..."; - case GAGGED_TARGET -> "You gagged %s!"; - case BLINDFOLDING_TARGET -> "You are blindfolding %s..."; - case BLINDFOLDED_TARGET -> "You blindfolded %s!"; - case COLLARING_TARGET -> "You are collaring %s..."; - case COLLARED_TARGET -> "You collared %s!"; - // Release actions - case UNTIED -> "%s untied you!"; - case UNGAGGED -> "%s removed your gag!"; - case UNBLINDFOLDED -> "%s removed your blindfold!"; - case UNCOLLARED -> "%s removed your collar!"; - case FREED -> "You have been freed!"; - // Struggle - case STRUGGLE_SUCCESS -> "You feel the ropes loosening..."; - case STRUGGLE_FAIL -> "You struggle against the ropes, but they hold tight."; - case STRUGGLE_BROKE_FREE -> "You broke free!"; - case STRUGGLE_SHOCKED -> "You were shocked for struggling!"; - case STRUGGLE_COLLAR_SUCCESS -> "You manage to damage the lock!"; - case STRUGGLE_COLLAR_FAIL -> "You try to reach the lock, but can't get a good grip."; - // Restrictions (Tied) - case CANT_MOVE -> "You can't move while tied!"; - case CANT_ATTACK_TIED -> "You can't attack while tied!"; - case CANT_USE_ITEM_TIED -> "You can't use items while tied!"; - case CANT_OPEN_INVENTORY -> "You can't open inventory while tied!"; - case CANT_INTERACT_TIED -> "You can't interact while tied!"; - case CANT_SPEAK -> "You can't speak while gagged!"; - case CANT_SEE -> "You can't see while blindfolded!"; - case CANT_BREAK_TIED -> "You can't break blocks while tied!"; - case CANT_PLACE_TIED -> "You can't place blocks while tied!"; - case NO_ELYTRA -> "You can't fly with elytra while tied!"; - // Restrictions (Mittens) - case CANT_ATTACK_MITTENS -> "You can't attack with mittens on!"; - case CANT_USE_ITEM_MITTENS -> "You can't use items with mittens on!"; - case CANT_INTERACT_MITTENS -> "You can't interact with mittens on!"; - case CANT_BREAK_MITTENS -> "You can't break blocks with mittens on!"; - case CANT_PLACE_MITTENS -> "You can't place blocks with mittens on!"; - // Slave system - case SLAVE_COMMAND -> "Your master commands: %s"; - case SLAVE_SHOCK -> "You've been shocked!"; - case GPS_ZONE_VIOLATION -> "You've been shocked! Return back to your allowed area!"; - case GPS_OWNER_ALERT -> "ALERT: %s is outside the safe zone!"; - case SLAVE_JOB_ASSIGNED -> "Job assigned: bring %s"; - case SLAVE_JOB_COMPLETE -> "Job complete! You are free."; - case SLAVE_JOB_FAILED -> "Job failed!"; - case SLAVE_JOB_LAST_CHANCE -> "LAST CHANCE! Next failure means death!"; - case SLAVE_JOB_KILLED -> "You were executed for failing your task."; - // Tighten - case BINDS_TIGHTENED -> "%s tightened your binds!"; - // Tools & Items - case KEY_CLAIMED -> "Key claimed and linked to %s!"; - case KEY_NOT_OWNER -> "You don't own this key!"; - case KEY_WRONG_TARGET -> "This key doesn't fit this collar!"; - case LOCATOR_CLAIMED -> "Locator claimed!"; - case LOCATOR_NOT_OWNER -> "You don't own this locator!"; - case LOCATOR_DETECTED -> "Target detected: %s"; - case SHOCKER_CLAIMED -> "Shocker claimed!"; - case SHOCKER_NOT_OWNER -> "You don't own this shocker!"; - case SHOCKER_MODE_SET -> "Shocker mode: %s"; - case SHOCKER_TRIGGERED -> "Shocked %s!"; - case RAG_DRY -> "The rag is dry - soak it first"; - case RAG_SOAKED -> "You soaked the rag with chloroform"; - case RAG_EVAPORATED -> "The chloroform has evaporated"; - // Bounty - case BOUNTY_CREATED -> "Bounty created on %s!"; - case BOUNTY_CLAIMED -> "You claimed the bounty on %s!"; - case BOUNTY_EXPIRED -> "Bounty on %s expired"; - // Cell System - case PRISONER_ARRIVED -> "%s has been placed in your cell"; - case PRISONER_ESCAPED -> "%s has escaped from your cell!"; - case PRISONER_RELEASED -> "%s has been released from your cell"; - case CELL_BREACH -> "Your cell wall has been breached!"; - case CELL_ASSIGNED -> "You have been assigned to %s's cell"; - case CELL_CREATED -> "Cell created successfully"; - case CELL_DELETED -> "Cell deleted"; - case CELL_RENAMED -> "Cell renamed to: %s"; - // Generic - case INFO -> "%s"; - case WARNING -> "%s"; - case ERROR -> "%s"; - }; + public static String getTranslationKey(MessageCategory category) { + return "msg.tiedup.system." + category.name().toLowerCase(); } /** @@ -373,11 +270,11 @@ public class SystemMessageManager { /** * Send a system message to a player's action bar. - * Uses category template with entity name. + * Uses translatable category with entity name as argument. * * @param player The player to send to * @param category The message category - * @param actor The entity performing the action (for %s replacement) + * @param actor The entity performing the action (for %1$s replacement) */ public static void sendToPlayer( Player player, @@ -387,14 +284,23 @@ public class SystemMessageManager { if (player == null) return; String actorName = actor != null ? getEntityName(actor) : "Someone"; - String message = String.format(getMessageTemplate(category), actorName); + MutableComponent component = Component.translatable( + getTranslationKey(category), actorName + ).withStyle(style -> style.withColor(getCategoryColor(category))); - sendToPlayer(player, message, getCategoryColor(category)); + player.displayClientMessage(component, true); + + TiedUpMod.LOGGER.debug( + "[SystemMessage] -> {}: {} ({})", + player.getName().getString(), + getTranslationKey(category), + actorName + ); } /** * Send a system message to a player's action bar. - * Uses category template without entity (for messages that don't need one). + * Uses translatable category without arguments. * * @param player The player to send to * @param category The message category @@ -402,12 +308,22 @@ public class SystemMessageManager { public static void sendToPlayer(Player player, MessageCategory category) { if (player == null) return; - String message = getMessageTemplate(category); - sendToPlayer(player, message, getCategoryColor(category)); + MutableComponent component = Component.translatable( + getTranslationKey(category) + ).withStyle(style -> style.withColor(getCategoryColor(category))); + + player.displayClientMessage(component, true); + + TiedUpMod.LOGGER.debug( + "[SystemMessage] -> {}: {}", + player.getName().getString(), + getTranslationKey(category) + ); } /** * Send a custom system message to a player's action bar. + * Uses literal text (for dynamic/non-translatable messages). * * @param player The player to send to * @param message The message to send @@ -420,12 +336,10 @@ public class SystemMessageManager { ) { if (player == null || message == null) return; - // Works on both client and server MutableComponent component = Component.literal(message).withStyle( style -> style.withColor(color) ); - // true = action bar (above hotbar), false = chat player.displayClientMessage(component, true); TiedUpMod.LOGGER.debug( @@ -437,6 +351,7 @@ public class SystemMessageManager { /** * Send a custom system message to a player's CHAT. + * Uses literal text (for dynamic/non-translatable messages). * * @param player The player to send to * @param message The message to send @@ -453,7 +368,6 @@ public class SystemMessageManager { style -> style.withColor(color) ); - // false = chat player.displayClientMessage(component, false); TiedUpMod.LOGGER.debug( @@ -464,19 +378,21 @@ public class SystemMessageManager { } /** - * Send a system message to a player's CHAT using a category. + * Send a system message to a player's CHAT using a translatable category. */ public static void sendChatToPlayer( Player player, MessageCategory category ) { if (player == null) return; - String message = getMessageTemplate(category); - sendChatToPlayer(player, message, getCategoryColor(category)); + MutableComponent component = Component.translatable( + getTranslationKey(category) + ).withStyle(style -> style.withColor(getCategoryColor(category))); + player.displayClientMessage(component, false); } /** - * Send a system message to a player's CHAT using a category and actor. + * Send a system message to a player's CHAT using a translatable category and actor. */ public static void sendChatToPlayer( Player player, @@ -485,8 +401,10 @@ public class SystemMessageManager { ) { if (player == null) return; String actorName = actor != null ? getEntityName(actor) : "Someone"; - String message = String.format(getMessageTemplate(category), actorName); - sendChatToPlayer(player, message, getCategoryColor(category)); + MutableComponent component = Component.translatable( + getTranslationKey(category), actorName + ).withStyle(style -> style.withColor(getCategoryColor(category))); + player.displayClientMessage(component, false); } /** @@ -494,7 +412,7 @@ public class SystemMessageManager { * * @param player The player to send to * @param category The category (for color) - * @param customMessage The custom message text + * @param customMessage The custom message text (literal, not translatable) */ public static void sendToPlayer( Player player, @@ -505,7 +423,27 @@ public class SystemMessageManager { } /** - * Send a message with resistance info appended. + * Send a translatable message with string arguments. + * Uses the category's translation key and color. + * + * @param player The player to send to + * @param category The message category + * @param args Arguments for the translation (replaces %1$s, %2$s, etc.) + */ + public static void sendTranslatable( + Player player, + MessageCategory category, + Object... args + ) { + if (player == null) return; + MutableComponent component = Component.translatable( + getTranslationKey(category), args + ).withStyle(style -> style.withColor(getCategoryColor(category))); + player.displayClientMessage(component, true); + } + + /** + * Send a translatable message with resistance info appended. * * @param player The player to send to * @param category The message category @@ -518,9 +456,13 @@ public class SystemMessageManager { ) { if (player == null) return; - String message = - getMessageTemplate(category) + " (Resistance: " + resistance + ")"; - sendToPlayer(player, message, getCategoryColor(category)); + MutableComponent component = Component.translatable( + getTranslationKey(category) + ).append( + Component.translatable("msg.tiedup.system.resistance_suffix", resistance) + ).withStyle(style -> style.withColor(getCategoryColor(category))); + + player.displayClientMessage(component, true); } // SEND METHODS - TO NEARBY PLAYERS @@ -695,15 +637,10 @@ public class SystemMessageManager { */ public static void sendJobAssigned(Player player, String itemName) { if (player == null) return; - String message = String.format( - getMessageTemplate(MessageCategory.SLAVE_JOB_ASSIGNED), - itemName - ); - sendToPlayer( - player, - message, - getCategoryColor(MessageCategory.SLAVE_JOB_ASSIGNED) - ); + MutableComponent component = Component.translatable( + getTranslationKey(MessageCategory.SLAVE_JOB_ASSIGNED), itemName + ).withStyle(style -> style.withColor(getCategoryColor(MessageCategory.SLAVE_JOB_ASSIGNED))); + player.displayClientMessage(component, true); } // UTILITY diff --git a/src/main/java/com/tiedup/remake/state/components/PlayerShockCollar.java b/src/main/java/com/tiedup/remake/state/components/PlayerShockCollar.java index 42f8b79..ceb32f5 100644 --- a/src/main/java/com/tiedup/remake/state/components/PlayerShockCollar.java +++ b/src/main/java/com/tiedup/remake/state/components/PlayerShockCollar.java @@ -15,6 +15,8 @@ import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem; import java.util.List; import java.util.UUID; import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; @@ -99,12 +101,11 @@ public class PlayerShockCollar { // HUD Message via SystemMessageManager if (messageAddon != null) { // Custom message with addon (e.g., GPS violation) - SystemMessageManager.sendToPlayer( - player, - MessageCategory.SLAVE_SHOCK, - SystemMessageManager.getTemplate(MessageCategory.SLAVE_SHOCK) + - messageAddon - ); + MutableComponent msg = Component.translatable( + SystemMessageManager.getTranslationKey(MessageCategory.SLAVE_SHOCK) + ).append(Component.literal(messageAddon)); + msg.withStyle(style -> style.withColor(ChatFormatting.RED)); + player.displayClientMessage(msg, true); } else { SystemMessageManager.sendToPlayer( player, @@ -239,11 +240,8 @@ public class PlayerShockCollar { if (!CollarHelper.shouldWarnMasters(stack)) return; - // Format: "ALERT: is outside the safe zone!" - String alertMessage = String.format( - SystemMessageManager.getTemplate(MessageCategory.GPS_OWNER_ALERT), - player.getName().getString() - ); + // Translatable: "ALERT: is outside the safe zone!" + String playerName = player.getName().getString(); for (UUID ownerId : CollarHelper.getOwners(stack)) { ServerPlayer owner = player @@ -253,8 +251,8 @@ public class PlayerShockCollar { if (owner != null) { SystemMessageManager.sendChatToPlayer( owner, - alertMessage, - ChatFormatting.RED + MessageCategory.GPS_OWNER_ALERT, + player ); } } diff --git a/src/main/resources/assets/tiedup/lang/en_us.json b/src/main/resources/assets/tiedup/lang/en_us.json index 0069fa3..8d09396 100644 --- a/src/main/resources/assets/tiedup/lang/en_us.json +++ b/src/main/resources/assets/tiedup/lang/en_us.json @@ -687,5 +687,89 @@ "gui.tiedup.status.key_info": "Key: %s", "gui.tiedup.status.no_key": "No key", "gui.tiedup.status.target_info": "Target: %s", - "gui.tiedup.status_bar": "Status bar" + "gui.tiedup.status_bar": "Status bar", + + "msg.tiedup.system.being_tied": "%1$s is tying you up!", + "msg.tiedup.system.tied_up": "%1$s tied you up, you can't move!", + "msg.tiedup.system.being_gagged": "%1$s is gagging you!", + "msg.tiedup.system.gagged": "%1$s gagged you, you can't speak!", + "msg.tiedup.system.being_blindfolded": "%1$s is blindfolding you!", + "msg.tiedup.system.blindfolded": "%1$s blindfolded you, you can't see!", + "msg.tiedup.system.being_collared": "%1$s is putting a collar on you!", + "msg.tiedup.system.collared": "%1$s collared you!", + "msg.tiedup.system.earplugs_on": "%1$s put earplugs on you!", + "msg.tiedup.system.mittens_on": "%1$s put mittens on you!", + "msg.tiedup.system.enslaved": "You have been enslaved by %1$s!", + "msg.tiedup.system.tying_target": "You are tying %1$s...", + "msg.tiedup.system.tied_target": "You tied %1$s!", + "msg.tiedup.system.gagging_target": "You are gagging %1$s...", + "msg.tiedup.system.gagged_target": "You gagged %1$s!", + "msg.tiedup.system.blindfolding_target": "You are blindfolding %1$s...", + "msg.tiedup.system.blindfolded_target": "You blindfolded %1$s!", + "msg.tiedup.system.collaring_target": "You are collaring %1$s...", + "msg.tiedup.system.collared_target": "You collared %1$s!", + "msg.tiedup.system.untied": "%1$s untied you!", + "msg.tiedup.system.ungagged": "%1$s removed your gag!", + "msg.tiedup.system.unblindfolded": "%1$s removed your blindfold!", + "msg.tiedup.system.uncollared": "%1$s removed your collar!", + "msg.tiedup.system.freed": "You have been freed!", + "msg.tiedup.system.struggle_success": "You feel the ropes loosening...", + "msg.tiedup.system.struggle_fail": "You struggle against the ropes, but they hold tight.", + "msg.tiedup.system.struggle_broke_free": "You broke free!", + "msg.tiedup.system.struggle_shocked": "You were shocked for struggling!", + "msg.tiedup.system.struggle_collar_success": "You manage to damage the lock!", + "msg.tiedup.system.struggle_collar_fail": "You try to reach the lock, but can't get a good grip.", + "msg.tiedup.system.cant_move": "You can't move while tied!", + "msg.tiedup.system.cant_attack_tied": "You can't attack while tied!", + "msg.tiedup.system.cant_use_item_tied": "You can't use items while tied!", + "msg.tiedup.system.cant_open_inventory": "You can't open inventory while tied!", + "msg.tiedup.system.cant_interact_tied": "You can't interact while tied!", + "msg.tiedup.system.cant_speak": "You can't speak while gagged!", + "msg.tiedup.system.cant_see": "You can't see while blindfolded!", + "msg.tiedup.system.cant_break_tied": "You can't break blocks while tied!", + "msg.tiedup.system.cant_place_tied": "You can't place blocks while tied!", + "msg.tiedup.system.no_elytra": "You can't fly with elytra while tied!", + "msg.tiedup.system.cant_attack_mittens": "You can't attack with mittens on!", + "msg.tiedup.system.cant_use_item_mittens": "You can't use items with mittens on!", + "msg.tiedup.system.cant_interact_mittens": "You can't interact with mittens on!", + "msg.tiedup.system.cant_break_mittens": "You can't break blocks with mittens on!", + "msg.tiedup.system.cant_place_mittens": "You can't place blocks with mittens on!", + "msg.tiedup.system.slave_command": "Your master commands: %1$s", + "msg.tiedup.system.slave_shock": "You've been shocked!", + "msg.tiedup.system.gps_zone_violation": "You've been shocked! Return back to your allowed area!", + "msg.tiedup.system.gps_owner_alert": "ALERT: %1$s is outside the safe zone!", + "msg.tiedup.system.slave_job_assigned": "Job assigned: bring %1$s", + "msg.tiedup.system.slave_job_complete": "Job complete! You are free.", + "msg.tiedup.system.slave_job_failed": "Job failed!", + "msg.tiedup.system.slave_job_last_chance": "LAST CHANCE! Next failure means death!", + "msg.tiedup.system.slave_job_killed": "You were executed for failing your task.", + "msg.tiedup.system.binds_tightened": "%1$s tightened your binds!", + "msg.tiedup.system.key_claimed": "Key claimed and linked to %1$s!", + "msg.tiedup.system.key_not_owner": "You don't own this key!", + "msg.tiedup.system.key_wrong_target": "This key doesn't fit this collar!", + "msg.tiedup.system.locator_claimed": "Locator claimed!", + "msg.tiedup.system.locator_not_owner": "You don't own this locator!", + "msg.tiedup.system.locator_detected": "Target detected: %1$s", + "msg.tiedup.system.shocker_claimed": "Shocker claimed!", + "msg.tiedup.system.shocker_not_owner": "You don't own this shocker!", + "msg.tiedup.system.shocker_mode_set": "Shocker mode: %1$s", + "msg.tiedup.system.shocker_triggered": "Shocked %1$s!", + "msg.tiedup.system.rag_dry": "The rag is dry - soak it first", + "msg.tiedup.system.rag_soaked": "You soaked the rag with chloroform", + "msg.tiedup.system.rag_evaporated": "The chloroform has evaporated", + "msg.tiedup.system.bounty_created": "Bounty created on %1$s!", + "msg.tiedup.system.bounty_claimed": "You claimed the bounty on %1$s!", + "msg.tiedup.system.bounty_expired": "Bounty on %1$s expired", + "msg.tiedup.system.prisoner_arrived": "%1$s has been placed in your cell", + "msg.tiedup.system.prisoner_escaped": "%1$s has escaped from your cell!", + "msg.tiedup.system.prisoner_released": "%1$s has been released from your cell", + "msg.tiedup.system.cell_breach": "Your cell wall has been breached!", + "msg.tiedup.system.cell_assigned": "You have been assigned to %1$s's cell", + "msg.tiedup.system.cell_created": "Cell created successfully", + "msg.tiedup.system.cell_deleted": "Cell deleted", + "msg.tiedup.system.cell_renamed": "Cell renamed to: %1$s", + "msg.tiedup.system.info": "%1$s", + "msg.tiedup.system.warning": "%1$s", + "msg.tiedup.system.error": "%1$s", + "msg.tiedup.system.resistance_suffix": " (Resistance: %1$s)" }