From 2c9189905539cf7ad7fab4b85bad66f4967439df Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:09 +0400 Subject: [PATCH 01/19] Add MiniMessage support to CoreProtectAPI chat logger --- .../java/net/coreprotect/CoreProtectAPI.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/main/java/net/coreprotect/CoreProtectAPI.java b/src/main/java/net/coreprotect/CoreProtectAPI.java index 757427b..c1bfd25 100755 --- a/src/main/java/net/coreprotect/CoreProtectAPI.java +++ b/src/main/java/net/coreprotect/CoreProtectAPI.java @@ -7,6 +7,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -235,6 +236,30 @@ public class CoreProtectAPI extends Queue { return true; } + /** + * Logs a componentized chat message for a player. + * + * @param player + * The player who sent the message + * @param component + * The chat message + * @return True if the message was logged + */ + public boolean logChat(Player player, Component component) { + if (!isEnabledForPlayer(player) || !Config.getConfig(player.getWorld()).PLAYER_MESSAGES) { + return false; + } + + if (component == null) { + return false; + } + + long timestamp = System.currentTimeMillis() / 1000L; + // TODO: proper implementation + Queue.queuePlayerChat(player, component.insertion(), timestamp); + return true; + } + /** * Logs a command executed by a player. * From 38c557fa12e4a494465326c91d5135ac416f850b Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:09 +0400 Subject: [PATCH 02/19] Allow logging chat messages with CommandSender --- .../java/net/coreprotect/CoreProtectAPI.java | 33 ++++++++----------- .../java/net/coreprotect/consumer/Queue.java | 9 +++++ 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/main/java/net/coreprotect/CoreProtectAPI.java b/src/main/java/net/coreprotect/CoreProtectAPI.java index c1bfd25..9080189 100755 --- a/src/main/java/net/coreprotect/CoreProtectAPI.java +++ b/src/main/java/net/coreprotect/CoreProtectAPI.java @@ -15,6 +15,7 @@ import org.bukkit.Server; import org.bukkit.block.Block; import org.bukkit.block.BlockState; import org.bukkit.block.data.BlockData; +import org.bukkit.command.CommandSender; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; @@ -216,15 +217,19 @@ public class CoreProtectAPI extends Queue { /** * Logs a chat message for a player. * - * @param player + * @param sender * The player who sent the message * @param message * The chat message * @return True if the message was logged */ - public boolean logChat(Player player, String message) { - if (!isEnabledForPlayer(player) || !Config.getConfig(player.getWorld()).PLAYER_MESSAGES) { - return false; + public boolean logChat(CommandSender sender, String message) { + Player player = null; + if (sender instanceof Player) { + player = (Player) sender; + if (!isEnabledForPlayer(player) || !Config.getConfig(player.getWorld()).PLAYER_MESSAGES) { + return false; + } } if (message == null || message.isEmpty() || message.startsWith("/")) { @@ -232,32 +237,22 @@ public class CoreProtectAPI extends Queue { } long timestamp = System.currentTimeMillis() / 1000L; - Queue.queuePlayerChat(player, message, timestamp); + if(player == null) Queue.queueChat(sender, message, timestamp); + else Queue.queuePlayerChat(player, message, timestamp); return true; } /** * Logs a componentized chat message for a player. * - * @param player + * @param sender * The player who sent the message * @param component * The chat message * @return True if the message was logged */ - public boolean logChat(Player player, Component component) { - if (!isEnabledForPlayer(player) || !Config.getConfig(player.getWorld()).PLAYER_MESSAGES) { - return false; - } - - if (component == null) { - return false; - } - - long timestamp = System.currentTimeMillis() / 1000L; - // TODO: proper implementation - Queue.queuePlayerChat(player, component.insertion(), timestamp); - return true; + public boolean logChat(CommandSender sender, Component component) { + return logChat(sender, component.insertion()); } /** diff --git a/src/main/java/net/coreprotect/consumer/Queue.java b/src/main/java/net/coreprotect/consumer/Queue.java index 8ef2d71..5a6407f 100755 --- a/src/main/java/net/coreprotect/consumer/Queue.java +++ b/src/main/java/net/coreprotect/consumer/Queue.java @@ -13,6 +13,7 @@ import org.bukkit.block.data.Bisected; import org.bukkit.block.data.Bisected.Half; import org.bukkit.block.data.type.Bed; import org.bukkit.block.data.type.Bed.Part; +import org.bukkit.command.CommandSender; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -303,6 +304,14 @@ public class Queue { queueStandardData(consumerId, currentConsumer, new String[] { player.getName(), null }, new Object[] { timestamp, player.getLocation().clone() }); } + protected static void queueChat(CommandSender sender, String message, long timestamp) { + int currentConsumer = Consumer.currentConsumer; + int consumerId = Consumer.newConsumerId(currentConsumer); + addConsumer(currentConsumer, new Object[] { consumerId, Process.PLAYER_CHAT, null, 0, null, 0, 0, null }); + Consumer.consumerStrings.get(currentConsumer).put(consumerId, message); + queueStandardData(consumerId, currentConsumer, new String[] { sender.getName(), null }, new Object[] { timestamp, null }); + } + protected static void queuePlayerCommand(Player player, String message, long timestamp) { int currentConsumer = Consumer.currentConsumer; int consumerId = Consumer.newConsumerId(currentConsumer); From fcf4d4301091db9b0887e11aa6ed5529a9a8be88 Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:09 +0400 Subject: [PATCH 03/19] Actually serialize components into MiniMessage --- src/main/java/net/coreprotect/CoreProtectAPI.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/coreprotect/CoreProtectAPI.java b/src/main/java/net/coreprotect/CoreProtectAPI.java index 9080189..46806ee 100755 --- a/src/main/java/net/coreprotect/CoreProtectAPI.java +++ b/src/main/java/net/coreprotect/CoreProtectAPI.java @@ -7,7 +7,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.serializer.json.JSONComponentSerializer; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -252,7 +256,15 @@ public class CoreProtectAPI extends Queue { * @return True if the message was logged */ public boolean logChat(CommandSender sender, Component component) { - return logChat(sender, component.insertion()); + return logChat(sender, MiniMessage.miniMessage().serialize(component)); + } + // API Stub + public boolean logChat(Player sender, String message) { + return logChat((CommandSender) sender, message); + } + // API Stub + public boolean logChat(Player sender, Component component) { + return logChat(sender, MiniMessage.miniMessage().serialize(component)); } /** From ab0a01b12f43623d2d7fb03357815017a9b3cdeb Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:09 +0400 Subject: [PATCH 04/19] Add MaterialUtils#asTranslatable to convert Material to the MiniMessage key --- src/main/java/net/coreprotect/utility/MaterialUtils.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/net/coreprotect/utility/MaterialUtils.java b/src/main/java/net/coreprotect/utility/MaterialUtils.java index 25129cd..9f92848 100644 --- a/src/main/java/net/coreprotect/utility/MaterialUtils.java +++ b/src/main/java/net/coreprotect/utility/MaterialUtils.java @@ -3,6 +3,7 @@ package net.coreprotect.utility; import java.util.Locale; import java.util.Set; +import org.bukkit.Bukkit; import org.bukkit.Material; import net.coreprotect.config.ConfigHandler; @@ -213,4 +214,9 @@ public class MaterialUtils extends Queue { return isInventory ? 2 : 1; } } + + // Griefus + public static String asTranslatable(Material material) { + return ""; + } } From e743be761560257373d558299302d4e9b6aab69d Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:09 +0400 Subject: [PATCH 05/19] Add EntityUtils#asTranslatable to convert EntityType to the MiniMessage key Yes --- src/main/java/net/coreprotect/utility/EntityUtils.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/net/coreprotect/utility/EntityUtils.java b/src/main/java/net/coreprotect/utility/EntityUtils.java index 7e1ab37..79ceff5 100644 --- a/src/main/java/net/coreprotect/utility/EntityUtils.java +++ b/src/main/java/net/coreprotect/utility/EntityUtils.java @@ -137,4 +137,8 @@ public class EntityUtils extends Queue { return result; } + + public static String asTranslatable(EntityType type){ + return ""; + } } From edf08fc750eca434078641599243ec04740268ee Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:09 +0400 Subject: [PATCH 06/19] Translate item/block/entity names in lookups/inspector results --- .../command/lookup/StandardLookupThread.java | 20 +++++++++++--- .../database/lookup/BlockLookup.java | 27 ++++++++++++------- .../lookup/ChestTransactionLookup.java | 5 ++++ .../database/lookup/InteractionLookup.java | 5 ++++ 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/main/java/net/coreprotect/command/lookup/StandardLookupThread.java b/src/main/java/net/coreprotect/command/lookup/StandardLookupThread.java index a833ba0..fb78926 100644 --- a/src/main/java/net/coreprotect/command/lookup/StandardLookupThread.java +++ b/src/main/java/net/coreprotect/command/lookup/StandardLookupThread.java @@ -286,7 +286,11 @@ public class StandardLookupThread implements Runnable { String rbd = ((Integer.parseInt(data[8]) == 2 || Integer.parseInt(data[8]) == 3) ? Color.STRIKETHROUGH : ""); String timeago = ChatUtils.getTimeSince(Integer.parseInt(time), unixtimestamp, true); Material blockType = ItemUtils.itemFilter(MaterialUtils.getType(dtype), (Integer.parseInt(data[13]) == 0)); - String dname = StringUtils.nameFilter(blockType.name().toLowerCase(Locale.ROOT), ddata); + + // Griefus begin + //String dname = StringUtils.nameFilter(blockType.name().toLowerCase(Locale.ROOT), ddata); + String dname = MaterialUtils.asTranslatable(blockType); + // Griefus end byte[] metadata = data[11] == null ? null : data[11].getBytes(StandardCharsets.ISO_8859_1); String tooltip = ItemUtils.getEnchantments(metadata, dtype, amount); @@ -362,13 +366,19 @@ public class StandardLookupThread implements Runnable { isPlayer = true; } else { - dname = EntityUtils.getEntityType(dtype).name(); + // Griefus begin + // dname = EntityUtils.getEntityType(dtype).name(); + dname = EntityUtils.asTranslatable(EntityUtils.getEntityType(dtype)); + // Griefus end } } else { - dname = MaterialUtils.getType(dtype).name().toLowerCase(Locale.ROOT); - dname = StringUtils.nameFilter(dname, ddata); + // Griefus begin + //dname = MaterialUtils.getType(dtype).name().toLowerCase(Locale.ROOT); + //dname = StringUtils.nameFilter(dname, ddata); + dname = MaterialUtils.asTranslatable(MaterialUtils.getType(dtype)); } + /* if (dname.length() > 0 && !isPlayer) { dname = "minecraft:" + dname.toLowerCase(Locale.ROOT) + ""; } @@ -378,6 +388,8 @@ public class StandardLookupThread implements Runnable { String[] blockNameSplit = dname.split(":"); dname = blockNameSplit[1]; } + */ + // Griefus end // Functions.sendMessage(player2, timeago+" " + ChatColors.WHITE + "- " + ChatColors.DARK_AQUA+rbd+""+dplayer+" " + ChatColors.WHITE+rbd+""+a+" " + ChatColors.DARK_AQUA+rbd+"#"+dtype+ChatColors.WHITE + ". " + ChatColors.GREY + "(x"+x+"/y"+y+"/z"+z+")"); diff --git a/src/main/java/net/coreprotect/database/lookup/BlockLookup.java b/src/main/java/net/coreprotect/database/lookup/BlockLookup.java index 5603df1..97470f4 100644 --- a/src/main/java/net/coreprotect/database/lookup/BlockLookup.java +++ b/src/main/java/net/coreprotect/database/lookup/BlockLookup.java @@ -109,24 +109,30 @@ public class BlockLookup { String target; if (resultAction == 3) { - target = EntityUtils.getEntityType(resultType).name(); + // Griefus begin + //target = EntityUtils.getEntityType(resultType).name(); + target = EntityUtils.asTranslatable(EntityUtils.getEntityType(resultType)); + // Griefus end } else { Material resultMaterial = MaterialUtils.getType(resultType); if (resultMaterial == null) { resultMaterial = Material.AIR; } - target = StringUtils.nameFilter(resultMaterial.name().toLowerCase(Locale.ROOT), resultData); - target = "minecraft:" + target.toLowerCase(Locale.ROOT); + // Griefus begin + //target = StringUtils.nameFilter(resultMaterial.name().toLowerCase(Locale.ROOT), resultData); + //target = "minecraft:" + target.toLowerCase(Locale.ROOT); + target = MaterialUtils.asTranslatable(resultMaterial); } - if (target.length() > 0) { + /*if (target.length() > 0) { target = "" + target + ""; - } + }*/ - // Hide "minecraft:" for now. - if (target.startsWith("minecraft:")) { + // Hide "minecraft:" for now. - do not!! + /*if (target.startsWith("minecraft:")) { target = target.split(":")[1]; - } + } */ + // Griefus end resultTextBuilder.append(timeAgo + " " + tag + " ").append(Phrase.build(phrase, Color.DARK_AQUA + rbFormat + resultUser + Color.WHITE + rbFormat, Color.DARK_AQUA + rbFormat + target + Color.WHITE, selector)).append("\n"); PluginChannelListener.getInstance().sendData(commandSender, resultTime, phrase, selector, resultUser, target, -1, x, y, z, worldId, rbFormat, false, tag.contains("+")); @@ -150,7 +156,10 @@ public class BlockLookup { // resultText = Color.WHITE + "No block data found at " + Color.ITALIC + "x" + x + "/y" + y + "/z" + z + "."; resultText = Phrase.build(Phrase.NO_DATA_LOCATION, Selector.FIRST); if (!blockName.equals("air") && !blockName.equals("cave_air")) { - resultText = Phrase.build(Phrase.NO_DATA, Color.ITALIC + block.getType().name().toLowerCase(Locale.ROOT) + Color.WHITE) + "\n"; + // Griefus begin + //resultText = Phrase.build(Phrase.NO_DATA, Color.ITALIC + block.getType().name().toLowerCase(Locale.ROOT) + Color.WHITE) + "\n"; + resultText = Phrase.build(Phrase.NO_DATA, Color.ITALIC + MaterialUtils.asTranslatable(block.getType()) + Color.WHITE) + "\n"; + // Griefus end } } } diff --git a/src/main/java/net/coreprotect/database/lookup/ChestTransactionLookup.java b/src/main/java/net/coreprotect/database/lookup/ChestTransactionLookup.java index 8119a99..cbad978 100644 --- a/src/main/java/net/coreprotect/database/lookup/ChestTransactionLookup.java +++ b/src/main/java/net/coreprotect/database/lookup/ChestTransactionLookup.java @@ -112,6 +112,9 @@ public class ChestTransactionLookup { if (resultMaterial == null) { resultMaterial = Material.AIR; } + // Griefus begin + String target = MaterialUtils.asTranslatable(resultMaterial); + /* String target = resultMaterial.name().toLowerCase(Locale.ROOT); target = StringUtils.nameFilter(target, resultData); if (target.length() > 0) { @@ -122,6 +125,8 @@ public class ChestTransactionLookup { if (target.startsWith("minecraft:")) { target = target.split(":")[1]; } + */ + // Griefus end result.add(new StringBuilder(timeAgo + " " + tag + " " + Phrase.build(Phrase.LOOKUP_CONTAINER, Color.DARK_AQUA + rbFormat + resultUser + Color.WHITE + rbFormat, "x" + resultAmount, ChatUtils.createTooltip(Color.DARK_AQUA + rbFormat + target, tooltip) + Color.WHITE, selector)).toString()); PluginChannelListener.getInstance().sendData(commandSender, resultTime, Phrase.LOOKUP_CONTAINER, selector, resultUser, target, resultAmount, x, y, z, worldId, rbFormat, true, tag.contains("+")); diff --git a/src/main/java/net/coreprotect/database/lookup/InteractionLookup.java b/src/main/java/net/coreprotect/database/lookup/InteractionLookup.java index 20333aa..781ca03 100644 --- a/src/main/java/net/coreprotect/database/lookup/InteractionLookup.java +++ b/src/main/java/net/coreprotect/database/lookup/InteractionLookup.java @@ -100,6 +100,9 @@ public class InteractionLookup { if (resultMaterial == null) { resultMaterial = Material.AIR; } + // Griefus begin + String target = MaterialUtils.asTranslatable(resultMaterial); + /* String target = resultMaterial.name().toLowerCase(Locale.ROOT); target = StringUtils.nameFilter(target, resultData); if (target.length() > 0) { @@ -110,6 +113,8 @@ public class InteractionLookup { if (target.startsWith("minecraft:")) { target = target.split(":")[1]; } + */ + // Griefus end resultBuilder.append(timeAgo + " " + Color.WHITE + "- ").append(Phrase.build(Phrase.LOOKUP_INTERACTION, Color.DARK_AQUA + rbFormat + resultUser + Color.WHITE + rbFormat, Color.DARK_AQUA + rbFormat + target + Color.WHITE, Selector.FIRST)).append("\n"); PluginChannelListener.getInstance().sendData(commandSender, resultTime, Phrase.LOOKUP_INTERACTION, Selector.FIRST, resultUser, target, -1, x, y, z, worldId, rbFormat, false, false); From 173bed6a1079704eee2941cd7d69c913204b64c5 Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:09 +0400 Subject: [PATCH 07/19] Add inspector mode shortcut command (/coi|/gusi) --- .../java/net/coreprotect/command/CommandHandler.java | 8 ++++++++ src/main/resources/plugin.yml | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/main/java/net/coreprotect/command/CommandHandler.java b/src/main/java/net/coreprotect/command/CommandHandler.java index 50f9ba8..baf05c4 100755 --- a/src/main/java/net/coreprotect/command/CommandHandler.java +++ b/src/main/java/net/coreprotect/command/CommandHandler.java @@ -25,6 +25,14 @@ public class CommandHandler implements CommandExecutor { public boolean onCommand(CommandSender user, Command command, String commandLabel, String[] argumentArray) { String commandName = command.getName().toLowerCase(Locale.ROOT); + // Griefus begin + if (commandName.equals("coi") || commandName.equals("gusi")) { + boolean permission = user.hasPermission("coreprotect.inspect"); + InspectCommand.runCommand(user, permission, argumentArray); + return true; + } + // Griefus end + if (commandName.equals("core") || commandName.equals("coreprotect") || commandName.equals("co") || commandName.equals("griefus") || commandName.equals("gus")) { int resultc = argumentArray.length; if (resultc > -1) { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 7816f51..dd41707 100755 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -35,6 +35,16 @@ commands: permission: coreprotect.griefus permission-message: §3Griefus §f- You do not have permission to do that. usage: / + coi: + description: Inspector mode shortcut + permission: coreprotect.inspect + permission-message: §3Griefus §f- You do not have permission to do that. + usage: / + gusi: + description: Inspector mode shortcut + permission: coreprotect.inspect + permission-message: §3Griefus §f- You do not have permission to do that. + usage: / permissions: coreprotect.*: description: Gives access to all Griefus actions and commands From 5533e55aa78e370db067a82b9dc1f559c40f01db Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:41 +0400 Subject: [PATCH 08/19] Add MiniMessage support to CoreProtectAPI chat logger --- .../java/net/coreprotect/CoreProtectAPI.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/main/java/net/coreprotect/CoreProtectAPI.java b/src/main/java/net/coreprotect/CoreProtectAPI.java index 757427b..c1bfd25 100755 --- a/src/main/java/net/coreprotect/CoreProtectAPI.java +++ b/src/main/java/net/coreprotect/CoreProtectAPI.java @@ -7,6 +7,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -235,6 +236,30 @@ public class CoreProtectAPI extends Queue { return true; } + /** + * Logs a componentized chat message for a player. + * + * @param player + * The player who sent the message + * @param component + * The chat message + * @return True if the message was logged + */ + public boolean logChat(Player player, Component component) { + if (!isEnabledForPlayer(player) || !Config.getConfig(player.getWorld()).PLAYER_MESSAGES) { + return false; + } + + if (component == null) { + return false; + } + + long timestamp = System.currentTimeMillis() / 1000L; + // TODO: proper implementation + Queue.queuePlayerChat(player, component.insertion(), timestamp); + return true; + } + /** * Logs a command executed by a player. * From a79fa4d26804c316060bec78b07ec2ae4e64ad7c Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:41 +0400 Subject: [PATCH 09/19] Allow logging chat messages with CommandSender --- .../java/net/coreprotect/CoreProtectAPI.java | 33 ++++++++----------- .../java/net/coreprotect/consumer/Queue.java | 9 +++++ 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/main/java/net/coreprotect/CoreProtectAPI.java b/src/main/java/net/coreprotect/CoreProtectAPI.java index c1bfd25..9080189 100755 --- a/src/main/java/net/coreprotect/CoreProtectAPI.java +++ b/src/main/java/net/coreprotect/CoreProtectAPI.java @@ -15,6 +15,7 @@ import org.bukkit.Server; import org.bukkit.block.Block; import org.bukkit.block.BlockState; import org.bukkit.block.data.BlockData; +import org.bukkit.command.CommandSender; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; @@ -216,15 +217,19 @@ public class CoreProtectAPI extends Queue { /** * Logs a chat message for a player. * - * @param player + * @param sender * The player who sent the message * @param message * The chat message * @return True if the message was logged */ - public boolean logChat(Player player, String message) { - if (!isEnabledForPlayer(player) || !Config.getConfig(player.getWorld()).PLAYER_MESSAGES) { - return false; + public boolean logChat(CommandSender sender, String message) { + Player player = null; + if (sender instanceof Player) { + player = (Player) sender; + if (!isEnabledForPlayer(player) || !Config.getConfig(player.getWorld()).PLAYER_MESSAGES) { + return false; + } } if (message == null || message.isEmpty() || message.startsWith("/")) { @@ -232,32 +237,22 @@ public class CoreProtectAPI extends Queue { } long timestamp = System.currentTimeMillis() / 1000L; - Queue.queuePlayerChat(player, message, timestamp); + if(player == null) Queue.queueChat(sender, message, timestamp); + else Queue.queuePlayerChat(player, message, timestamp); return true; } /** * Logs a componentized chat message for a player. * - * @param player + * @param sender * The player who sent the message * @param component * The chat message * @return True if the message was logged */ - public boolean logChat(Player player, Component component) { - if (!isEnabledForPlayer(player) || !Config.getConfig(player.getWorld()).PLAYER_MESSAGES) { - return false; - } - - if (component == null) { - return false; - } - - long timestamp = System.currentTimeMillis() / 1000L; - // TODO: proper implementation - Queue.queuePlayerChat(player, component.insertion(), timestamp); - return true; + public boolean logChat(CommandSender sender, Component component) { + return logChat(sender, component.insertion()); } /** diff --git a/src/main/java/net/coreprotect/consumer/Queue.java b/src/main/java/net/coreprotect/consumer/Queue.java index 8ef2d71..5a6407f 100755 --- a/src/main/java/net/coreprotect/consumer/Queue.java +++ b/src/main/java/net/coreprotect/consumer/Queue.java @@ -13,6 +13,7 @@ import org.bukkit.block.data.Bisected; import org.bukkit.block.data.Bisected.Half; import org.bukkit.block.data.type.Bed; import org.bukkit.block.data.type.Bed.Part; +import org.bukkit.command.CommandSender; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -303,6 +304,14 @@ public class Queue { queueStandardData(consumerId, currentConsumer, new String[] { player.getName(), null }, new Object[] { timestamp, player.getLocation().clone() }); } + protected static void queueChat(CommandSender sender, String message, long timestamp) { + int currentConsumer = Consumer.currentConsumer; + int consumerId = Consumer.newConsumerId(currentConsumer); + addConsumer(currentConsumer, new Object[] { consumerId, Process.PLAYER_CHAT, null, 0, null, 0, 0, null }); + Consumer.consumerStrings.get(currentConsumer).put(consumerId, message); + queueStandardData(consumerId, currentConsumer, new String[] { sender.getName(), null }, new Object[] { timestamp, null }); + } + protected static void queuePlayerCommand(Player player, String message, long timestamp) { int currentConsumer = Consumer.currentConsumer; int consumerId = Consumer.newConsumerId(currentConsumer); From 981f5ecefc417ba57324e4685db855520ebe982d Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:41 +0400 Subject: [PATCH 10/19] Actually serialize components into MiniMessage --- src/main/java/net/coreprotect/CoreProtectAPI.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/coreprotect/CoreProtectAPI.java b/src/main/java/net/coreprotect/CoreProtectAPI.java index 9080189..46806ee 100755 --- a/src/main/java/net/coreprotect/CoreProtectAPI.java +++ b/src/main/java/net/coreprotect/CoreProtectAPI.java @@ -7,7 +7,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.serializer.json.JSONComponentSerializer; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -252,7 +256,15 @@ public class CoreProtectAPI extends Queue { * @return True if the message was logged */ public boolean logChat(CommandSender sender, Component component) { - return logChat(sender, component.insertion()); + return logChat(sender, MiniMessage.miniMessage().serialize(component)); + } + // API Stub + public boolean logChat(Player sender, String message) { + return logChat((CommandSender) sender, message); + } + // API Stub + public boolean logChat(Player sender, Component component) { + return logChat(sender, MiniMessage.miniMessage().serialize(component)); } /** From 29d698b38f6ce4eae70776fe3595432215d5bf0c Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:41 +0400 Subject: [PATCH 11/19] Add makeHeader method to build VanillaCrafts-like chat headers --- src/main/java/net/coreprotect/utility/StringUtils.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/net/coreprotect/utility/StringUtils.java b/src/main/java/net/coreprotect/utility/StringUtils.java index aa38b1f..bc7d7b9 100644 --- a/src/main/java/net/coreprotect/utility/StringUtils.java +++ b/src/main/java/net/coreprotect/utility/StringUtils.java @@ -135,4 +135,9 @@ public class StringUtils { } return list.toArray(new Integer[list.size()]); } + + // VanillaCrafts + public static String makeHeader(String header) { + return "=============== " + header + " ==============="; + } } \ No newline at end of file From 8e727c5f3bf59834a50c974f9340c554d37a97ee Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:41 +0400 Subject: [PATCH 12/19] Add VanillaCrafts style page navigation --- .../net/coreprotect/utility/ChatUtils.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/main/java/net/coreprotect/utility/ChatUtils.java b/src/main/java/net/coreprotect/utility/ChatUtils.java index 865a5f9..37acdec 100644 --- a/src/main/java/net/coreprotect/utility/ChatUtils.java +++ b/src/main/java/net/coreprotect/utility/ChatUtils.java @@ -2,6 +2,11 @@ package net.coreprotect.utility; import net.coreprotect.language.Phrase; import net.coreprotect.language.Selector; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.minimessage.MiniMessage; import org.bukkit.command.ConsoleCommandSender; @@ -143,6 +148,57 @@ public class ChatUtils { return message.append(Color.WHITE + backArrow + Color.DARK_AQUA + Phrase.build(Phrase.LOOKUP_PAGE, Color.WHITE + page + "/" + totalPages) + nextArrow + pagination).toString(); } + public static String getPageNavigationVC(String command, int page, int totalPages) { + if (totalPages < 1) + return ""; + Component separator = Component.text(" | ", NamedTextColor.DARK_GRAY, TextDecoration.BOLD); + String backButtonText = "[назад]"; + String nextButtonText = "[далее]"; + + HoverEvent backButtonHover = HoverEvent + .showText(Component.text("Нажмите, чтобы перейти на предыдущую страницу", NamedTextColor.RED)); + HoverEvent nextButtonHover = HoverEvent + .showText(Component.text("Нажмите, чтобы перейти на следующую страницу", NamedTextColor.GREEN)); + + ClickEvent backButtonClick = ClickEvent.runCommand("/" + command + " l " + (page - 1)); + ClickEvent nextButtonClick = ClickEvent.runCommand("/" + command + " l " + (page + 1)); + + + Component backButton; + if (page > 1) { + backButton = Component.text(backButtonText) + .color(NamedTextColor.RED) + .hoverEvent(backButtonHover) + .clickEvent(backButtonClick); + } else { + backButton = Component.text(backButtonText) + .color(NamedTextColor.GRAY) + .decorate(TextDecoration.ITALIC); + } + + Component nextButton; + if (page < totalPages) { + nextButton = Component.text(nextButtonText) + .color(NamedTextColor.GREEN) + .hoverEvent(nextButtonHover) + .clickEvent(nextButtonClick); + } else { + nextButton = Component.text(nextButtonText) + .color(NamedTextColor.GRAY) + .decorate(TextDecoration.ITALIC); + } + + Component pageCounter = Component.text(page + "/" + totalPages, NamedTextColor.GRAY); + + Component navigation = Component.empty() + .append(backButton) + .append(separator) + .append(pageCounter) + .append(separator) + .append(nextButton); + return MiniMessage.miniMessage().serialize(navigation); + } + public static String getTimeSince(long resultTime, long currentTime, boolean component) { StringBuilder message = new StringBuilder(); double timeSince = currentTime - (resultTime + 0.00); From 52f3e8929d2a139ff0a1c41ca47c84b44f379210 Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:41 +0400 Subject: [PATCH 13/19] Improve Russian localization --- lang/ru.yml | 330 ++++++++++++++++++++++++++-------------------------- 1 file changed, 165 insertions(+), 165 deletions(-) diff --git a/lang/ru.yml b/lang/ru.yml index bee1016..baaf33e 100644 --- a/lang/ru.yml +++ b/lang/ru.yml @@ -1,202 +1,202 @@ # CoreProtect Language File (ru) -ACTION_NOT_SUPPORTED: "Данное действие не поддерживается этой командой." +ACTION_NOT_SUPPORTED: "Данное действие не поддерживается этой командой" AMOUNT_BLOCK: "{0} {блок|блоков}" AMOUNT_CHUNK: "{0} {чанк|чанков}" AMOUNT_ENTITY: "{0} {существо|существ}" AMOUNT_ITEM: "{0} {предмет|предметов}" -API_TEST: "Тест API прошёл успешно!" -CACHE_ERROR: "ВНИМАНИЕ: Ошибка при проверке кеша {0}." -CACHE_RELOAD: "Принудительная перезагрузка кеша {отображения|мира} из базы данных." -CHECK_CONFIG: "Пожалуйста, проверьте config.yml" -COMMAND_CONSOLE: "Пожалуйста, запустите команду из консоли." -COMMAND_NOT_FOUND: "Команда «{0}» не найдена." -COMMAND_THROTTLED: "Подождите немного и попробуйте еще раз." -CONSUMER_ERROR: "Обработка потребительской очереди уже {приостановлено|возобновлено}." -CONSUMER_TOGGLED: "Обработка очереди потребителей была {приостановлено|возобновлено}." +API_TEST: "Тест API прошёл успешно!" +CACHE_ERROR: "ВНИМАНИЕ: Ошибка при проверке кеша {0}" +CACHE_RELOAD: "Принудительная перезагрузка кеша {отображения|мира} из базы данных" +CHECK_CONFIG: "Пожалуйста, проверьте config.yml" +COMMAND_CONSOLE: "Пожалуйста, запустите команду из консоли" +COMMAND_NOT_FOUND: "Команда «{0}» не найдена" +COMMAND_THROTTLED: "Подождите немного и попробуйте еще раз" +CONSUMER_ERROR: "Обработка потребительской очереди уже {приостановлено|возобновлено}" +CONSUMER_TOGGLED: "Обработка очереди потребителей {приостановлена|возобновлена}" CONTAINER_HEADER: "Контейнерные транзакции" -DATABASE_BUSY: "База данных занята. Пожалуйста, повторите попытку позже." -DATABASE_INDEX_ERROR: "Невозможно проверить индексы базы данных." -DATABASE_LOCKED_1: "База данных заблокирована. Подождите около 15 секунд..." -DATABASE_LOCKED_2: "База данных уже используется. Пожалуйста, попробуйте еще раз." -DATABASE_LOCKED_3: "Чтобы отключить блокировку базы данных, установите «database-lock: false»." -DATABASE_LOCKED_4: "Отключение блокировки базы данных может привести к повреждению данных." -DATABASE_UNREACHABLE: "База данных недоступна. Удаление данных и завершение работы." -DEVELOPMENT_BRANCH: "Обнаружена ветвь разработки, скрипты исправлений пропущены." -DIRT_BLOCK: "Под вами установлен блок грязи." +DATABASE_BUSY: "База данных занята, повторите попытку позже" +DATABASE_INDEX_ERROR: "Невозможно проверить индексы базы данных" +DATABASE_LOCKED_1: "База данных заблокирована, подождите около 15 секунд..." +DATABASE_LOCKED_2: "База данных уже используется, попробуйте еще раз" +DATABASE_LOCKED_3: "Чтобы отключить блокировку базы данных, установите «database-lock: false»" +DATABASE_LOCKED_4: "Отключение блокировки базы данных может привести к повреждению данных" +DATABASE_UNREACHABLE: "База данных недоступна. Удаление данных и завершение работы" +DEVELOPMENT_BRANCH: "Обнаружена ветвь разработки, скрипты исправлений пропущены" +DIRT_BLOCK: "Под вами установлен блок грязи" DISABLE_SUCCESS: "{0} был успешно отключён!" -ENABLE_FAILED: "{0} не удалось запустить." +ENABLE_FAILED: "{0} не удалось запустить" ENABLE_SUCCESS: "{0} был успешно запущен!" ENJOY_COREPROTECT: "Нравится {0}? Присоединяйтесь к нашему Discord!" -FINISHING_CONVERSION: "Завершение преобразования данных. Пожалуйста, подождите..." -FINISHING_LOGGING: "Завершение регистрации данных. Пожалуйста, подождите..." +FINISHING_CONVERSION: "Завершение преобразования данных. Пожалуйста, подождите..." +FINISHING_LOGGING: "Завершение регистрации данных. Пожалуйста, подождите..." FIRST_VERSION: "Исходная БД: {0}" -GLOBAL_LOOKUP: "Не указывайте радиус для глобального поиска." -GLOBAL_ROLLBACK: "Используйте «{0}», чтобы сделать {откат|восстановление} глобально" -HELP_ACTION_1: "Ограничьте поиск определенным действием." +GLOBAL_LOOKUP: "Радиус для глобального поиска не требуется" +GLOBAL_ROLLBACK: "Используйте «{0}», чтобы сделать {откат|восстановление} глобально" +HELP_ACTION_1: "Ограничьте поиск определенным действием" HELP_ACTION_2: "Например: [a:block], [a:+block], [a:-block] [a:click], [a:container], [a:inventory], [a:item], [a:kill], [a:chat], [a:command], [a:sign], [a:session], [a:username]" -HELP_COMMAND: "Показать дополнительную информацию." -HELP_EXCLUDE_1: "Исключите блоки/пользователей." +HELP_COMMAND: "Показать дополнительную информацию" +HELP_EXCLUDE_1: "Исключите блоки/пользователей" HELP_EXCLUDE_2: "Например: [e:stone], [e:Notch], [e:stone,Notch]" -HELP_HEADER: "{0} Помощь" -HELP_INCLUDE_1: "Включите определенные блоки/сущности." +HELP_HEADER: "Помощь по командам (отслеживание действий)" +HELP_INCLUDE_1: "Включите определенные блоки/сущности" HELP_INCLUDE_2: "Например: [i:stone], [i:zombie], [i:stone,wood,bedrock]" -HELP_INSPECT_1: "С включенным режимом инспектора вы можете сделать следующее:" -HELP_INSPECT_2: "Щелкните левой кнопкой мыши по блоку, чтобы увидеть, кто разместил этот блок.." -HELP_INSPECT_3: "Щелкните блок правой кнопкой мыши, чтобы увидеть, какой соседний блок был сломан.." -HELP_INSPECT_4: "Поместите блок, чтобы увидеть, какой блок был сломан в этом месте." -HELP_INSPECT_5: "Поместите блок в жидкость (и т.п.), чтобы увидеть, кто его поместил." -HELP_INSPECT_6: "Щелкните правой кнопкой мыши дверь, сундук и т.д., чтобы узнать, кто последний использовал их." -HELP_INSPECT_7: "Подсказка: Вы можете использовать «/co i» для быстрого переключения режима инспектора." -HELP_INSPECT_COMMAND: "Включает или выключает режим инспектора блоков." -HELP_LIST: "Отображает список всех команд." -HELP_LOOKUP_1: "Команда быстрого доступа." -HELP_LOOKUP_2: "Используйте после проверки блока для просмотра журналов." -HELP_LOOKUP_COMMAND: "Глобальный поиск данных блоков." -HELP_NO_INFO: "Информация о команде «{0}» не найдена." -HELP_PARAMETER: "Пожалуйста, просмотрите «{0}» для получения подробной информации о параметрах." -HELP_PARAMS_1: "Выполните {поиск|откат|восстановление}." -HELP_PARAMS_2: "Укажите пользователей для {поиска|отката|восстановления}." -HELP_PARAMS_3: "Укажите время для {поиска|отката|восстановления}." -HELP_PARAMS_4: "Укажите область радиуса, чтобы ограничить {поиск|откат|восстановление}." -HELP_PARAMS_5: "Ограничьте {поиск|откат|восстановление} определенным действием." -HELP_PARAMS_6: "Включите определенные блоки/объекты в {поиск|откат|восстановление}." -HELP_PARAMS_7: "Исключите блоки/пользователей из {поиска|отката|восстановления}." -HELP_PURGE_1: "Удалить данные старше указанного времени." -HELP_PURGE_2: "Например, «{0}» удалит все данные старше одного месяца и сохранит данные только за последние 30 дней." -HELP_PURGE_COMMAND: "Удалит старые данные блока." -HELP_RADIUS_1: "Укажите радиус области." +HELP_INSPECT_1: "С включенным режимом CHECKER вы можете сделать следующее:" +HELP_INSPECT_2: "Щелкните левой кнопкой мыши по блоку, чтобы увидеть, кто разместил этот блок" +HELP_INSPECT_3: "Щелкните блок правой кнопкой мыши, чтобы увидеть, какой соседний блок был сломан" +HELP_INSPECT_4: "Поместите блок, чтобы увидеть, какой блок был сломан в этом месте" +HELP_INSPECT_5: "Поместите блок в жидкость (и т.п.), чтобы увидеть, кто его поместил" +HELP_INSPECT_6: "Щелкните правой кнопкой мыши дверь, сундук и т.д., чтобы узнать, кто последний использовал их" +HELP_INSPECT_7: "Подсказка: Вы можете использовать «/co i» для быстрого переключения режима CHECKER" +HELP_INSPECT_COMMAND: "Включает или выключает режим проверки логов (CHECKER)" +HELP_LIST: "Отображает список всех команд" +HELP_LOOKUP_1: "Команда быстрого доступа" +HELP_LOOKUP_2: "Используйте после проверки блока для просмотра журналов" +HELP_LOOKUP_COMMAND: "Глобальный поиск данных блоков" +HELP_NO_INFO: "Информация о команде «{0}» не найдена" +HELP_PARAMETER: "Пожалуйста, просмотрите «{0}» для получения подробной информации о параметрах" +HELP_PARAMS_1: "Выполните {поиск|откат|восстановление}" +HELP_PARAMS_2: "Укажите пользователей для {поиска|отката|восстановления}" +HELP_PARAMS_3: "Укажите время для {поиска|отката|восстановления}" +HELP_PARAMS_4: "Укажите область радиуса, чтобы ограничить {поиск|откат|восстановление}" +HELP_PARAMS_5: "Ограничьте {поиск|откат|восстановление} определенным действием" +HELP_PARAMS_6: "Включите определенные блоки/объекты в {поиск|откат|восстановление}" +HELP_PARAMS_7: "Исключите блоки/пользователей из {поиска|отката|восстановления}" +HELP_PURGE_1: "Удалить данные старше указанного времени" +HELP_PURGE_2: "Например, «{0}» удалит все данные старше одного месяца и сохранит данные только за последние 30 дней" +HELP_PURGE_COMMAND: "Удалит старые данные блока" +HELP_RADIUS_1: "Укажите радиус области" HELP_RADIUS_2: "Например: [r:10] (Внесёт изменения только в пределах 10 блоков от вас)" -HELP_RELOAD_COMMAND: "Перезагружает файл конфигурации." -HELP_RESTORE_COMMAND: "Восстановит данные блока." -HELP_ROLLBACK_COMMAND: "Откатит данные блока." -HELP_STATUS: "Просмотр статуса плагина и информации о версии." -HELP_STATUS_COMMAND: "Отображает статус плагина." -HELP_TELEPORT: "Телепорт в локацию." -HELP_TIME_1: "Укажите время поиска." +HELP_RELOAD_COMMAND: "Перезагружает файл конфигурации" +HELP_RESTORE_COMMAND: "Отмена отката действий" +HELP_ROLLBACK_COMMAND: "Откат действий" +HELP_STATUS: "Просмотр статуса плагина и информации о версии" +HELP_STATUS_COMMAND: "Отображает статус плагина" +HELP_TELEPORT: "Телепорт в локацию" +HELP_TIME_1: "Укажите время поиска" HELP_TIME_2: "Например: [t:2w,5d,7h,2m,10s], [t:5d2h], [t:2.50h]" -HELP_USER_1: "Укажите пользовател(я/ей) для поиска." +HELP_USER_1: "Укажите пользовател(я/ей) для поиска" HELP_USER_2: "Например: [u:Notch], [u:Notch,#enderman]" -INCOMPATIBLE_ACTION: "«{0}» нельзя использовать с этим действием." -INSPECTOR_ERROR: "Режим инспектора уже {включён|выключен}." -INSPECTOR_TOGGLED: "Режим инспектора теперь {включён|выключен}." -INTEGRATION_ERROR: "Невозможно {инициализировать|отключить} регистрацию {0}." -INTEGRATION_SUCCESS: "{0} регистрация успешно {инициализирована|отключена}." -INTEGRATION_VERSION: "Обнаружена недопустимая версия {0}." +INCOMPATIBLE_ACTION: "«{0}» нельзя использовать с этим действием" +INSPECTOR_ERROR: "Режим CHECKER уже {включён|выключен}" +INSPECTOR_TOGGLED: "Режим CHECKER {включён|выключен}" +INTEGRATION_ERROR: "Невозможно {инициализировать|отключить} регистрацию {0}" +INTEGRATION_SUCCESS: "{0} регистрация успешно {инициализирована|отключена}" +INTEGRATION_VERSION: "Обнаружена недопустимая версия {0}" INTERACTIONS_HEADER: "Взаимодействие с игроками" -INVALID_ACTION: "Это недопустимое действие." -INVALID_BRANCH_1: "Неверная версия плагина (ветка не задана)." -INVALID_BRANCH_2: "Чтобы продолжить, установите ветку проекта на «development»." -INVALID_BRANCH_3: "Запуск кода который находится в разработке может привести к повреждению данных." -INVALID_CONTAINER: "Пожалуйста, сначала проверьте действующий контейнер." -INVALID_DONATION_KEY: "Недействительный ключ пожертвования." -INVALID_INCLUDE: "«{0}» неверное имя блока/сущности." -INVALID_INCLUDE_COMBO: "Это недопустимая комбинация блока/сущности." -INVALID_RADIUS: "Пожалуйста, введите допустимый радиус." -INVALID_SELECTION: "Выбор {0} не найден." -INVALID_USERNAME: "«{0}» неверное имя пользователя." -INVALID_WORLD: "Укажите действительный мир." +INVALID_ACTION: "Это недопустимое действие" +INVALID_BRANCH_1: "Неверная версия плагина (ветка не задана)" +INVALID_BRANCH_2: "Чтобы продолжить, установите ветку проекта на «development»" +INVALID_BRANCH_3: "Запуск кода который находится в разработке может привести к повреждению данных" +INVALID_CONTAINER: "Пожалуйста, сначала проверьте действующий контейнер" +INVALID_DONATION_KEY: "Недействительный ключ пожертвования" +INVALID_INCLUDE: "«{0}» неверное имя блока/сущности" +INVALID_INCLUDE_COMBO: "Недопустимая комбинация блока/сущности" +INVALID_RADIUS: "Пожалуйста, введите допустимый радиус." +INVALID_SELECTION: "Выбор {0} не найден" +INVALID_USERNAME: "«{0}» неверное имя пользователя." +INVALID_WORLD: "Укажите действительный мир" LATEST_VERSION: "Последняя версия: {0}" LINK_DISCORD: "Discord: {0}" LINK_DOWNLOAD: "Загрузить: {0}" LINK_PATREON: "Patreon: {0}" LINK_WIKI_BLOCK: "Названия блоков: {0}" LINK_WIKI_ENTITY: "Названия сущностей: {0}" -LOGGING_ITEMS: "{0} предметы регистрируются. Пожалуйста, подождите..." -LOGGING_TIME_LIMIT: "Достигнуто ограничение по времени регистрации. Удаление данных и завершение работы." -LOOKUP_BLOCK: "{0} {поставил|сломал} {1}." -LOOKUP_CONTAINER: "{0} {добавил|забрал} {1} {2}." +LOGGING_ITEMS: "{0} предметы регистрируются. Пожалуйста, подождите..." +LOGGING_TIME_LIMIT: "Достигнуто ограничение по времени регистрации. Удаление данных и завершение работы" +LOOKUP_BLOCK: "{0} {поставил|сломал} {1}" +LOOKUP_CONTAINER: "{0} {положил|забрал} {1} {2}" LOOKUP_HEADER: "{0} Результаты поиска" -LOOKUP_INTERACTION: "{0} {нажал|убил} {1}." -LOOKUP_ITEM: "{0} {подобрал|выкинул} {1} {2}." -LOOKUP_LOGIN: "{0} {вошёл|вышел}." +LOOKUP_INTERACTION: "{0} {нажал|убил} {1}" +LOOKUP_ITEM: "{0} {подобрал|выкинул} {1} {2}" +LOOKUP_LOGIN: "{0} {вошёл|вышел}" LOOKUP_PAGE: "Страница {0}" -LOOKUP_PROJECTILE: "{0} {бросил|выстрелил} {1} {2}." -LOOKUP_ROWS_FOUND: "{0} {строка|строк} найдено." -LOOKUP_SEARCHING: "Ведётся поиск. Пожалуйста подождите..." -LOOKUP_STORAGE: "{0} {положил|забрал} {1} {2}." -LOOKUP_TIME: "{0} назад" -LOOKUP_USERNAME: "{0} зарегистрирован как {1}." -MAXIMUM_RADIUS: "Максимальный радиус для {поиска|отката|восстановления} - {0}." -MISSING_ACTION_USER: "Чтобы использовать это действие, укажите пользователя." -MISSING_LOOKUP_TIME: "Пожалуйста, укажите количество времени, чтобы использовать {поиск|откат|восстановление}." -MISSING_LOOKUP_USER: "Укажите пользователя или {блок|радиус} для поиска." -MISSING_PARAMETERS: "Пожалуйста используйте «{0}»." -MISSING_ROLLBACK_RADIUS: "Вы не указали радиус {отката|восстановления}." -MISSING_ROLLBACK_USER: "Вы не указали пользователя для {отката|восстановления}." -MYSQL_UNAVAILABLE: "Невозможно подключиться к серверу MySQL." -NO_DATA: "Данные не найдены в {0}." -NO_DATA_LOCATION: "В этом месте {данные|транзакции|взаимодействия|сообщения} не обнаружены.." -NO_PERMISSION: "У вас нет прав чтобы сделать это." -NO_RESULTS: "Результаты не найдены." -NO_RESULTS_PAGE: "Для этой страницы {результатов|данных} не найдено." -NO_ROLLBACK: "{Ожидаемый|Предыдущий} откат/восстановление не найдены." -PATCH_INTERRUPTED: "Обновление прервано. Попробую снова при перезапуске." -PATCH_OUTDATED_1: "Невозможно обновить базы данных старше {0}." -PATCH_OUTDATED_2: "Пожалуйста, обновите поддерживаемую версию CoreProtect." -PATCH_PROCESSING: "Обработка новых данных. Пожалуйста, подождите..." -PATCH_SKIP_UPDATE: "{Пропущена таблица|Пропущен индекс} {обновление|создание|удаление} в {0}." -PATCH_STARTED: "Выполняется обновление {0}. Пожалуйста, подождите..." -PATCH_SUCCESS: "Успешно обновлен до {0}." -PATCH_UPGRADING: "Выполняется обновление базы данных. Пожалуйста, подождите..." -PLEASE_SELECT: "Пожалуйста выберите: «{0}» или «{1}»." -PREVIEW_CANCELLED: "Предварительный просмотр отменен." -PREVIEW_CANCELLING: "Отмена предварительного просмотра..." -PREVIEW_IN_GAME: "Предварительный просмотр откатов доступен только в игре." -PREVIEW_TRANSACTION: "Вы не можете просмотреть {контейнер|инвентарь} транзакции." -PURGE_ABORTED: "Очистка не удалась. База данных может быть повреждена." -PURGE_ERROR: "Невозможно обработать данные {0}!" -PURGE_FAILED: "Очистка не удалась. Пожалуйста, повторите попытку позже." -PURGE_IN_PROGRESS: "Выполняется чистка. Пожалуйста, повторите попытку позже." -PURGE_MINIMUM_TIME: "Удалить можно только данные старше {0} {дней|часов}." -PURGE_NOTICE_1: "Учтите, что это может занять некоторое время." -PURGE_NOTICE_2: "Не перезагружайте сервер до завершения." -PURGE_OPTIMIZING: "Оптимизация базы данных. Пожалуйста, подождите..." -PURGE_PROCESSING: "Обработка данных {0}..." -PURGE_REPAIRING: "Попытка исправления. Это может занять некоторое время..." -PURGE_ROWS: "{0} {строка|строки} данных очищены." -PURGE_STARTED: "Очистка данных началась «{0}»." -PURGE_SUCCESS: "Очистка данных прошла успешно." -RELOAD_STARTED: "Перезагрузка конфигурации - подождите." -RELOAD_SUCCESS: "Конфигурация успешно перезагружена." -ROLLBACK_ABORTED: "Откат или восстановление прерваны." -ROLLBACK_CHUNKS_FOUND: "Найдено {0} {чанк|чанков} для изменения." -ROLLBACK_CHUNKS_MODIFIED: "Изменено {0}/{1} {чанк|чанков}." -ROLLBACK_COMPLETED: "{Откат|Восстановление|Предварительный просмотр} завершен для «{0}»." -ROLLBACK_EXCLUDED_USERS: "{Исключен пользователь|Исключены пользователи}: «{0}»." -ROLLBACK_INCLUDE: "{Включён|Исключён} {блок|сущность|цель} {типа|типов}: «{0}»." -ROLLBACK_IN_PROGRESS: "Откат/восстановление уже выполняется." -ROLLBACK_LENGTH: "Заняло времени: {0} {секунду|секунд}." -ROLLBACK_MODIFIED: "{Изменено|Изменены} {0}." -ROLLBACK_RADIUS: "Радиус: {0} {блок|блоков}." -ROLLBACK_SELECTION: "Радиус установлен «{0}»." -ROLLBACK_STARTED: "{Откат|Восстановление|Предварительный просмотр} начат «{0}»." -ROLLBACK_TIME: "Временной интервал: {0}." -ROLLBACK_WORLD_ACTION: "Только {мир|действие} «{0}»." +LOOKUP_PROJECTILE: "{0} {бросил|выстрелил} {1} {2}" +LOOKUP_ROWS_FOUND: "{0} {строка|строк} найдено" +LOOKUP_SEARCHING: "Поиск данных, подождите..." +LOOKUP_STORAGE: "{0} {положил|забрал} {1} {2}" +LOOKUP_TIME: "{0} назад" +LOOKUP_USERNAME: "{0} зарегистрирован как {1}" +MAXIMUM_RADIUS: "Максимальный радиус для {поиска|отката|восстановления} - {0}" +MISSING_ACTION_USER: "Чтобы использовать это действие, укажите пользователя" +MISSING_LOOKUP_TIME: "Пожалуйста, укажите количество времени, чтобы использовать {поиск|откат|восстановление}" +MISSING_LOOKUP_USER: "Укажите пользователя или {блок|радиус} для поиска" +MISSING_PARAMETERS: "Пожалуйста используйте «{0}»" +MISSING_ROLLBACK_RADIUS: "Вы не указали радиус {отката|восстановления}" +MISSING_ROLLBACK_USER: "Вы не указали пользователя для {отката|восстановления}" +MYSQL_UNAVAILABLE: "Невозможно подключиться к серверу MySQL" +NO_DATA: "Данные не найдены в {0}" +NO_DATA_LOCATION: "В этом месте {данные|транзакции|взаимодействия|сообщения} не обнаружены" +NO_PERMISSION: "Нет доступа!" +NO_RESULTS: "Результаты не найдены" +NO_RESULTS_PAGE: "Для этой страницы {результатов|данных} не найдено" +NO_ROLLBACK: "{Ожидаемый|Предыдущий} откат/восстановление не найдены" +PATCH_INTERRUPTED: "Обновление прервано. Попробую снова при перезапуске..." +PATCH_OUTDATED_1: "Невозможно обновить базы данных старше {0}" +PATCH_OUTDATED_2: "Пожалуйста, обновите поддерживаемую версию Griefus" +PATCH_PROCESSING: "Обработка новых данных. Пожалуйста, подождите..." +PATCH_SKIP_UPDATE: "{Пропущена таблица|Пропущен индекс} {обновление|создание|удаление} в {0}" +PATCH_STARTED: "Выполняется обновление {0}. Пожалуйста, подождите..." +PATCH_SUCCESS: "Успешно обновлен до {0}" +PATCH_UPGRADING: "Выполняется обновление базы данных. Пожалуйста, подождите..." +PLEASE_SELECT: "Пожалуйста выберите: «{0}» или «{1}»" +PREVIEW_CANCELLED: "Предварительный просмотр отменен" +PREVIEW_CANCELLING: "Отмена предварительного просмотра..." +PREVIEW_IN_GAME: "Предварительный просмотр откатов доступен только в игре" +PREVIEW_TRANSACTION: "Вы не можете просмотреть {контейнер|инвентарь} транзакции" +PURGE_ABORTED: "Очистка не удалась. База данных может быть повреждена" +PURGE_ERROR: "Невозможно обработать данные {0}!" +PURGE_FAILED: "Очистка не удалась. Пожалуйста, повторите попытку позже" +PURGE_IN_PROGRESS: "Выполняется чистка. Пожалуйста, повторите попытку позже" +PURGE_MINIMUM_TIME: "Удалить можно только данные старше {0} {дней|часов}" +PURGE_NOTICE_1: "Учтите, что это может занять некоторое время" +PURGE_NOTICE_2: "Не перезагружайте сервер до завершения" +PURGE_OPTIMIZING: "Оптимизация базы данных. Пожалуйста, подождите..." +PURGE_PROCESSING: "Обработка данных {0}..." +PURGE_REPAIRING: "Попытка исправления. Это может занять некоторое время..." +PURGE_ROWS: "{0} {строка|строки} данных очищены" +PURGE_STARTED: "Очистка данных началась «{0}»" +PURGE_SUCCESS: "Очистка данных прошла успешно" +RELOAD_STARTED: "Перезагрузка конфигурации, подождите..." +RELOAD_SUCCESS: "Конфигурация успешно перезагружена" +ROLLBACK_ABORTED: "Откат или восстановление прерваны" +ROLLBACK_CHUNKS_FOUND: "Найдено {0} {чанк|чанков} для изменения" +ROLLBACK_CHUNKS_MODIFIED: "Изменено {0}/{1} {чанк|чанков}" +ROLLBACK_COMPLETED: "{Откат|Восстановление|Предварительный просмотр} завершен для «{0}»" +ROLLBACK_EXCLUDED_USERS: "{Исключен пользователь|Исключены пользователи}: «{0}»" +ROLLBACK_INCLUDE: "{Включён|Исключён} {блок|сущность|цель} {типа|типов}: «{0}»" +ROLLBACK_IN_PROGRESS: "Откат/восстановление уже выполняется" +ROLLBACK_LENGTH: "Заняло времени: {0} {секунду|секунд}" +ROLLBACK_MODIFIED: "{Изменено|Изменены} {0}" +ROLLBACK_RADIUS: "Радиус: {0} {блок|блоков}" +ROLLBACK_SELECTION: "Радиус установлен «{0}»" +ROLLBACK_STARTED: "{Откат|Восстановление|Предварительный просмотр} начат «{0}»" +ROLLBACK_TIME: "Временной интервал: {0}" +ROLLBACK_WORLD_ACTION: "Только {мир|действие} «{0}»" SIGN_HEADER: "Сообщения на табличке" -STATUS_CONSUMER: "Потребитель: {0} {предмет|предметы} в очереди." +STATUS_CONSUMER: "Потребитель: {0} {предмет|предметы} в очереди" STATUS_DATABASE: "База данных: Использует {0}." -STATUS_INTEGRATION: "{0}: Интеграция {включена|отключена}." +STATUS_INTEGRATION: "{0}: Интеграция {включена|отключена}" STATUS_LICENSE: "Лицензия: {0}" STATUS_VERSION: "Версия: {0}" -TELEPORTED: "Телепортирование в {0}." -TELEPORTED_SAFETY: "Телепортируем вас в безопасное место." -TELEPORT_PLAYERS: "Команду телепортации могут использовать только игроки." +TELEPORTED: "Телепортирование в {0}..." +TELEPORTED_SAFETY: "Телепортируем вас в безопасное место" +TELEPORT_PLAYERS: "Команду телепортации могут использовать только игроки" TIME_DAYS: "{0} {дня|дней}" TIME_HOURS: "{0} {час|часов}" TIME_MINUTES: "{0} {минута|минут}" TIME_SECONDS: "{0} {секунда|секунд}" -TIME_UNITS: "{/m|/h|/d}" +TIME_UNITS: "{ мин.| ч.| д.}" TIME_WEEKS: "{0} {неделя|недель}" -UPDATE_ERROR: "Произошла ошибка при проверке обновлений." +UPDATE_ERROR: "Произошла ошибка при проверке обновлений" UPDATE_HEADER: "{0} Обновление" -UPDATE_NOTICE: "Примечание: теперь доступен {0}." -UPGRADE_IN_PROGRESS: "Выполняется обновление. Пожалуйста, повторите попытку позже." -USER_NOT_FOUND: "Пользователь «{0}» не найден." -USER_OFFLINE: "Пользователь \"{0}\" не в сети." -USING_MYSQL: "Для хранения данных используется MySQL." -USING_SQLITE: "Для хранения данных используется SQLite." -VALID_DONATION_KEY: "Действующий ключ пожертвования." +UPDATE_NOTICE: "Примечание: теперь доступен {0}" +UPGRADE_IN_PROGRESS: "Выполняется обновление. Пожалуйста, повторите попытку позже" +USER_NOT_FOUND: "Пользователь «{0}» не найден" +USER_OFFLINE: "Пользователь \"{0}\" не в сети" +USING_MYSQL: "Для хранения данных используется MySQL" +USING_SQLITE: "Для хранения данных используется SQLite" +VALID_DONATION_KEY: "Действующий ключ пожертвования" VERSION_NOTICE: "Версия {0} уже доступна!" -VERSION_REQUIRED: "{0} {1} или выше требуется." -WORLD_NOT_FOUND: "Мир «{0}» не найден." +VERSION_REQUIRED: "{0} {1} или выше требуется" +WORLD_NOT_FOUND: "Мир «{0}» не найден" From 1a09bd59c0f784b3cb3447a050e00dd0997941e0 Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:41 +0400 Subject: [PATCH 14/19] Add VanillaCrafts style coordinates and teleport buttons --- .../java/net/coreprotect/utility/ChatUtils.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/net/coreprotect/utility/ChatUtils.java b/src/main/java/net/coreprotect/utility/ChatUtils.java index 37acdec..496ab48 100644 --- a/src/main/java/net/coreprotect/utility/ChatUtils.java +++ b/src/main/java/net/coreprotect/utility/ChatUtils.java @@ -8,6 +8,7 @@ import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.minimessage.MiniMessage; +import org.bukkit.Bukkit; import org.bukkit.command.ConsoleCommandSender; import java.text.DecimalFormat; @@ -47,6 +48,19 @@ public class ChatUtils { return message.append("").toString(); // griefus } + public static String getShowCoordinatesButton(int x, int y, int z) { + return "" + x + " " + + "Y: " + y + " " + + "Z: " + z + " " + + "\">[координаты]"; + } + public static String getTeleportButton(int worldId, int x, int y, int z) { + // May break if worldId index is outdated + return "[телепортироваться]"; + } + public static String getPageNavigation(String command, int page, int totalPages) { StringBuilder message = new StringBuilder(); From 695cd1ade714ce1750ff6027614ad3bb6bbdfeb1 Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:41 +0400 Subject: [PATCH 15/19] Add MaterialUtils#asTranslatable to convert Material to the MiniMessage key --- src/main/java/net/coreprotect/utility/MaterialUtils.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/net/coreprotect/utility/MaterialUtils.java b/src/main/java/net/coreprotect/utility/MaterialUtils.java index 25129cd..9f92848 100644 --- a/src/main/java/net/coreprotect/utility/MaterialUtils.java +++ b/src/main/java/net/coreprotect/utility/MaterialUtils.java @@ -3,6 +3,7 @@ package net.coreprotect.utility; import java.util.Locale; import java.util.Set; +import org.bukkit.Bukkit; import org.bukkit.Material; import net.coreprotect.config.ConfigHandler; @@ -213,4 +214,9 @@ public class MaterialUtils extends Queue { return isInventory ? 2 : 1; } } + + // Griefus + public static String asTranslatable(Material material) { + return ""; + } } From 877ffe501598ebef63e9fc31d38cd5e55add569a Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:41 +0400 Subject: [PATCH 16/19] Use VanillaCrafts styling in lookup/inspector results --- .../command/lookup/StandardLookupThread.java | 27 ++++++++++--------- .../database/lookup/BlockLookup.java | 15 +++++++---- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/main/java/net/coreprotect/command/lookup/StandardLookupThread.java b/src/main/java/net/coreprotect/command/lookup/StandardLookupThread.java index a833ba0..f40aad2 100644 --- a/src/main/java/net/coreprotect/command/lookup/StandardLookupThread.java +++ b/src/main/java/net/coreprotect/command/lookup/StandardLookupThread.java @@ -109,6 +109,8 @@ public class StandardLookupThread implements Runnable { ConfigHandler.lookupAlist.put(player.getName(), actions); ConfigHandler.lookupRadius.put(player.getName(), radius); + String separator = Color.DARK_GREY + '-'; + if (connection != null) { Statement statement = connection.createStatement(); String baduser = ""; @@ -195,14 +197,15 @@ public class StandardLookupThread implements Runnable { else if (pageStart < rows) { List lookupList = Lookup.performPartialLookup(statement, player, uuidList, userList, blockList, excludedBlocks, excludedUsers, actions, finalLocation, radius, rowData, timeStart, timeEnd, (int) pageStart, displayResults, restrict_world, true); - Chat.sendMessage(player, Color.WHITE + "----- " + Color.DARK_AQUA + Phrase.build(Phrase.LOOKUP_HEADER, "Griefus" + Color.WHITE + " | " + Color.DARK_AQUA) + Color.WHITE + " -----"); + // Chat.sendMessage(player, Color.WHITE + "----- " + Color.DARK_AQUA + Phrase.build(Phrase.LOOKUP_HEADER, "Griefus" + Color.WHITE + " | " + Color.DARK_AQUA) + Color.WHITE + " -----"); + Chat.sendComponent(player, StringUtils.makeHeader("LOGS")); if (actions.contains(6) || actions.contains(7)) { // Chat/command for (String[] data : lookupList) { String time = data[0]; String dplayer = data[1]; String message = data[2]; String timeago = ChatUtils.getTimeSince(Integer.parseInt(time), unixtimestamp, true); - Chat.sendComponent(player, timeago + " " + Color.WHITE + "- " + Color.DARK_AQUA + dplayer + ": " + Color.WHITE, message); + Chat.sendComponent(player, "| " + timeago + " " + Color.WHITE + "- " + message); if (PluginChannelHandshakeListener.getInstance().isPluginChannelPlayer(player)) { int wid = Integer.parseInt(data[3]); int dataX = Integer.parseInt(data[4]); @@ -232,7 +235,7 @@ public class StandardLookupThread implements Runnable { } String tag = (action != 0 ? Color.GREEN + "+" : Color.RED + "-"); - Chat.sendComponent(player, timeago + " " + tag + " " + Color.DARK_AQUA + Phrase.build(Phrase.LOOKUP_LOGIN, Color.DARK_AQUA + dplayer + Color.WHITE, (action != 0 ? Selector.FIRST : Selector.SECOND))); + Chat.sendComponent(player, "| " + timeago + " " + tag + " " + Color.DARK_AQUA + Phrase.build(Phrase.LOOKUP_LOGIN, Color.DARK_AQUA + dplayer + Color.WHITE, (action != 0 ? Selector.FIRST : Selector.SECOND))); Chat.sendComponent(player, Color.WHITE + leftPadding + Color.GREY + "^ " + ChatUtils.getCoordinates(command.getName(), wid, dataX, dataY, dataZ, true, true) + ""); PluginChannelListener.getInstance().sendInfoData(player, Integer.parseInt(time), Phrase.LOOKUP_LOGIN, (action != 0 ? Selector.FIRST : Selector.SECOND), dplayer, -1, dataX, dataY, dataZ, wid); } @@ -266,8 +269,8 @@ public class StandardLookupThread implements Runnable { leftPadding = leftPadding + Color.WHITE + Strings.padStart("", (timeLength - 50) / 4, ' '); } - Chat.sendComponent(player, timeago + " " + Color.WHITE + "- " + Color.DARK_AQUA + dplayer + ": " + Color.WHITE, message); - Chat.sendComponent(player, Color.WHITE + leftPadding + Color.GREY + "^ " + ChatUtils.getCoordinates(command.getName(), wid, dataX, dataY, dataZ, true, true) + ""); + Chat.sendComponent(player,"| " + timeago + " " + Color.WHITE + "- " + Color.DARK_AQUA + dplayer + ": " + Color.WHITE, message); + Chat.sendComponent(player, Color.RESET + leftPadding + ChatUtils.getShowCoordinatesButton(dataX, dataY, dataZ) + " " + ChatUtils.getTeleportButton(wid, dataX, dataY, dataZ)); PluginChannelListener.getInstance().sendMessageData(player, Integer.parseInt(time), dplayer, message, true, dataX, dataY, dataZ, wid); } } @@ -317,7 +320,7 @@ public class StandardLookupThread implements Runnable { tag = (daction == 0 ? Color.GREEN + "+" : Color.RED + "-"); } - Chat.sendComponent(player, timeago + " " + tag + " " + Phrase.build(Phrase.LOOKUP_CONTAINER, Color.DARK_AQUA + rbd + dplayer + Color.WHITE + rbd, "x" + amount, ChatUtils.createTooltip(Color.DARK_AQUA + rbd + dname, tooltip) + Color.WHITE, selector)); + Chat.sendComponent(player, "| " + timeago + " " + separator + " " + Phrase.build(Phrase.LOOKUP_CONTAINER, Color.WHITE + Color.BOLD + rbd + dplayer + Color.RESET + rbd, "x" + amount, ChatUtils.createTooltip(Color.GOLD + rbd + dname, tooltip) + Color.WHITE, selector)); PluginChannelListener.getInstance().sendData(player, Integer.parseInt(time), Phrase.LOOKUP_CONTAINER, selector, dplayer, dname, amount, dataX, dataY, dataZ, wid, rbd, true, tag.contains("+")); } } @@ -413,7 +416,7 @@ public class StandardLookupThread implements Runnable { action = "a:container"; } - Chat.sendComponent(player, timeago + " " + tag + " " + Phrase.build(phrase, Color.DARK_AQUA + rbd + dplayer + Color.WHITE + rbd, "x" + amount, ChatUtils.createTooltip(Color.DARK_AQUA + rbd + dname, tooltip) + Color.WHITE, selector)); + Chat.sendComponent(player, "|" + timeago + " " + separator + " " + Phrase.build(phrase, Color.WHITE + Color.BOLD + rbd + dplayer + Color.RESET + rbd, "x" + amount, ChatUtils.createTooltip(Color.GOLD + rbd + dname, tooltip) + Color.WHITE, selector)); PluginChannelListener.getInstance().sendData(player, Integer.parseInt(time), phrase, selector, dplayer, dname, (tag.contains("+") ? 1 : -1), dataX, dataY, dataZ, wid, rbd, action.contains("container"), tag.contains("+")); } else { @@ -429,20 +432,20 @@ public class StandardLookupThread implements Runnable { tag = (daction != 0 ? Color.GREEN + "+" : Color.RED + "-"); } - Chat.sendComponent(player, timeago + " " + tag + " " + Phrase.build(phrase, Color.DARK_AQUA + rbd + dplayer + Color.WHITE + rbd, Color.DARK_AQUA + rbd + dname + Color.WHITE, selector)); + Chat.sendComponent(player, timeago + " " + separator + " " + Phrase.build(phrase, Color.WHITE + Color.BOLD + rbd + dplayer + Color.RESET + rbd, Color.GOLD + rbd + dname + Color.WHITE, selector)); PluginChannelListener.getInstance().sendData(player, Integer.parseInt(time), phrase, selector, dplayer, dname, (tag.contains("+") ? 1 : -1), dataX, dataY, dataZ, wid, rbd, false, tag.contains("+")); } action = (actions.size() == 0 ? " (" + action + ")" : ""); - Chat.sendComponent(player, Color.WHITE + leftPadding + Color.GREY + "^ " + ChatUtils.getCoordinates(command.getName(), wid, dataX, dataY, dataZ, true, true) + Color.GREY + Color.ITALIC + action); + Chat.sendComponent(player, Color.RESET + leftPadding + ChatUtils.getShowCoordinatesButton(dataX, dataY, dataZ) + " " + ChatUtils.getTeleportButton(wid, dataX, dataY, dataZ)); } } if (rows > displayResults) { int total_pages = (int) Math.ceil(rows / (displayResults + 0.0)); - if (actions.contains(6) || actions.contains(7) || actions.contains(9) || (actions.contains(4) && actions.contains(11))) { + /* if (actions.contains(6) || actions.contains(7) || actions.contains(9) || (actions.contains(4) && actions.contains(11))) { Chat.sendMessage(player, "-----"); - } - Chat.sendComponent(player, ChatUtils.getPageNavigation(command.getName(), page, total_pages)); + } */ + Chat.sendComponent(player, ChatUtils.getPageNavigationVC(command.getName(), page, total_pages)); } } else if (rows > 0) { diff --git a/src/main/java/net/coreprotect/database/lookup/BlockLookup.java b/src/main/java/net/coreprotect/database/lookup/BlockLookup.java index 5603df1..df385be 100644 --- a/src/main/java/net/coreprotect/database/lookup/BlockLookup.java +++ b/src/main/java/net/coreprotect/database/lookup/BlockLookup.java @@ -84,13 +84,19 @@ public class BlockLookup { String timeAgo = ChatUtils.getTimeSince(resultTime, time, true); if (!found) { - resultTextBuilder = new StringBuilder(Color.WHITE + "----- " + Color.DARK_AQUA + "Griefus " + Color.WHITE + "----- " + ChatUtils.getCoordinates(command, worldId, x, y, z, false, false) + "\n"); + // resultTextBuilder = new StringBuilder(Color.WHITE + "----- " + Color.DARK_AQUA + "Griefus " + Color.WHITE + "----- " + ChatUtils.getCoordinates(command, worldId, x, y, z, false, false) + "\n"); + // Lookup/Checker header + resultTextBuilder = new StringBuilder(StringUtils.makeHeader("CHECKER") + + " " + ChatUtils.getShowCoordinatesButton(x, y, z) + + (commandSender.hasPermission("coreprotect.teleport") ? " " + // TODO: change teleport permission key + ChatUtils.getTeleportButton(worldId, x, y, z) : "") + "\n"); } found = true; Phrase phrase = Phrase.LOOKUP_BLOCK; String selector = Selector.FIRST; String tag = Color.WHITE + "-"; + String separator = Color.DARK_GREY + "-"; if (resultAction == 2 || resultAction == 3) { phrase = Phrase.LOOKUP_INTERACTION; // {clicked|killed} selector = (resultAction != 3 ? Selector.FIRST : Selector.SECOND); @@ -128,7 +134,7 @@ public class BlockLookup { target = target.split(":")[1]; } - resultTextBuilder.append(timeAgo + " " + tag + " ").append(Phrase.build(phrase, Color.DARK_AQUA + rbFormat + resultUser + Color.WHITE + rbFormat, Color.DARK_AQUA + rbFormat + target + Color.WHITE, selector)).append("\n"); + resultTextBuilder.append(timeAgo + " " + separator + " ").append(Phrase.build(phrase, Color.WHITE + Color.BOLD + rbFormat + resultUser + Color.RESET + rbFormat, Color.GOLD + rbFormat + target + Color.WHITE, selector)).append("\n"); PluginChannelListener.getInstance().sendData(commandSender, resultTime, phrase, selector, resultUser, target, -1, x, y, z, worldId, rbFormat, false, tag.contains("+")); } @@ -137,9 +143,8 @@ public class BlockLookup { if (found) { if (count > limit) { - String pageInfo = Color.WHITE + "-----\n"; - pageInfo = pageInfo + ChatUtils.getPageNavigation(command, page, totalPages) + "\n"; - resultText = resultText + pageInfo; + // String pageInfo = Color.WHITE + "-----\n"; + resultText = resultText + ChatUtils.getPageNavigationVC(command, page, totalPages) + "\n"; } } else { From d0fe67d9884c0b09e67bef889143b519635eda0e Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:41 +0400 Subject: [PATCH 17/19] Add EntityUtils#asTranslatable to convert EntityType to the MiniMessage key Yes --- src/main/java/net/coreprotect/utility/EntityUtils.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/net/coreprotect/utility/EntityUtils.java b/src/main/java/net/coreprotect/utility/EntityUtils.java index 7e1ab37..79ceff5 100644 --- a/src/main/java/net/coreprotect/utility/EntityUtils.java +++ b/src/main/java/net/coreprotect/utility/EntityUtils.java @@ -137,4 +137,8 @@ public class EntityUtils extends Queue { return result; } + + public static String asTranslatable(EntityType type){ + return ""; + } } From 540525fee2d6279b99b5bf2ca281b575fb1089f7 Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:41 +0400 Subject: [PATCH 18/19] Translate item/block/entity names in lookups/inspector results --- .../command/lookup/StandardLookupThread.java | 20 +++++++++++--- .../database/lookup/BlockLookup.java | 27 ++++++++++++------- .../lookup/ChestTransactionLookup.java | 5 ++++ .../database/lookup/InteractionLookup.java | 5 ++++ 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/main/java/net/coreprotect/command/lookup/StandardLookupThread.java b/src/main/java/net/coreprotect/command/lookup/StandardLookupThread.java index f40aad2..cf74887 100644 --- a/src/main/java/net/coreprotect/command/lookup/StandardLookupThread.java +++ b/src/main/java/net/coreprotect/command/lookup/StandardLookupThread.java @@ -289,7 +289,11 @@ public class StandardLookupThread implements Runnable { String rbd = ((Integer.parseInt(data[8]) == 2 || Integer.parseInt(data[8]) == 3) ? Color.STRIKETHROUGH : ""); String timeago = ChatUtils.getTimeSince(Integer.parseInt(time), unixtimestamp, true); Material blockType = ItemUtils.itemFilter(MaterialUtils.getType(dtype), (Integer.parseInt(data[13]) == 0)); - String dname = StringUtils.nameFilter(blockType.name().toLowerCase(Locale.ROOT), ddata); + + // Griefus begin + //String dname = StringUtils.nameFilter(blockType.name().toLowerCase(Locale.ROOT), ddata); + String dname = MaterialUtils.asTranslatable(blockType); + // Griefus end byte[] metadata = data[11] == null ? null : data[11].getBytes(StandardCharsets.ISO_8859_1); String tooltip = ItemUtils.getEnchantments(metadata, dtype, amount); @@ -365,13 +369,19 @@ public class StandardLookupThread implements Runnable { isPlayer = true; } else { - dname = EntityUtils.getEntityType(dtype).name(); + // Griefus begin + // dname = EntityUtils.getEntityType(dtype).name(); + dname = EntityUtils.asTranslatable(EntityUtils.getEntityType(dtype)); + // Griefus end } } else { - dname = MaterialUtils.getType(dtype).name().toLowerCase(Locale.ROOT); - dname = StringUtils.nameFilter(dname, ddata); + // Griefus begin + //dname = MaterialUtils.getType(dtype).name().toLowerCase(Locale.ROOT); + //dname = StringUtils.nameFilter(dname, ddata); + dname = MaterialUtils.asTranslatable(MaterialUtils.getType(dtype)); } + /* if (dname.length() > 0 && !isPlayer) { dname = "minecraft:" + dname.toLowerCase(Locale.ROOT) + ""; } @@ -381,6 +391,8 @@ public class StandardLookupThread implements Runnable { String[] blockNameSplit = dname.split(":"); dname = blockNameSplit[1]; } + */ + // Griefus end // Functions.sendMessage(player2, timeago+" " + ChatColors.WHITE + "- " + ChatColors.DARK_AQUA+rbd+""+dplayer+" " + ChatColors.WHITE+rbd+""+a+" " + ChatColors.DARK_AQUA+rbd+"#"+dtype+ChatColors.WHITE + ". " + ChatColors.GREY + "(x"+x+"/y"+y+"/z"+z+")"); diff --git a/src/main/java/net/coreprotect/database/lookup/BlockLookup.java b/src/main/java/net/coreprotect/database/lookup/BlockLookup.java index df385be..0422577 100644 --- a/src/main/java/net/coreprotect/database/lookup/BlockLookup.java +++ b/src/main/java/net/coreprotect/database/lookup/BlockLookup.java @@ -115,24 +115,30 @@ public class BlockLookup { String target; if (resultAction == 3) { - target = EntityUtils.getEntityType(resultType).name(); + // Griefus begin + //target = EntityUtils.getEntityType(resultType).name(); + target = EntityUtils.asTranslatable(EntityUtils.getEntityType(resultType)); + // Griefus end } else { Material resultMaterial = MaterialUtils.getType(resultType); if (resultMaterial == null) { resultMaterial = Material.AIR; } - target = StringUtils.nameFilter(resultMaterial.name().toLowerCase(Locale.ROOT), resultData); - target = "minecraft:" + target.toLowerCase(Locale.ROOT); + // Griefus begin + //target = StringUtils.nameFilter(resultMaterial.name().toLowerCase(Locale.ROOT), resultData); + //target = "minecraft:" + target.toLowerCase(Locale.ROOT); + target = MaterialUtils.asTranslatable(resultMaterial); } - if (target.length() > 0) { + /*if (target.length() > 0) { target = "" + target + ""; - } + }*/ - // Hide "minecraft:" for now. - if (target.startsWith("minecraft:")) { + // Hide "minecraft:" for now. - do not!! + /*if (target.startsWith("minecraft:")) { target = target.split(":")[1]; - } + } */ + // Griefus end resultTextBuilder.append(timeAgo + " " + separator + " ").append(Phrase.build(phrase, Color.WHITE + Color.BOLD + rbFormat + resultUser + Color.RESET + rbFormat, Color.GOLD + rbFormat + target + Color.WHITE, selector)).append("\n"); PluginChannelListener.getInstance().sendData(commandSender, resultTime, phrase, selector, resultUser, target, -1, x, y, z, worldId, rbFormat, false, tag.contains("+")); @@ -155,7 +161,10 @@ public class BlockLookup { // resultText = Color.WHITE + "No block data found at " + Color.ITALIC + "x" + x + "/y" + y + "/z" + z + "."; resultText = Phrase.build(Phrase.NO_DATA_LOCATION, Selector.FIRST); if (!blockName.equals("air") && !blockName.equals("cave_air")) { - resultText = Phrase.build(Phrase.NO_DATA, Color.ITALIC + block.getType().name().toLowerCase(Locale.ROOT) + Color.WHITE) + "\n"; + // Griefus begin + //resultText = Phrase.build(Phrase.NO_DATA, Color.ITALIC + block.getType().name().toLowerCase(Locale.ROOT) + Color.WHITE) + "\n"; + resultText = Phrase.build(Phrase.NO_DATA, Color.ITALIC + MaterialUtils.asTranslatable(block.getType()) + Color.WHITE) + "\n"; + // Griefus end } } } diff --git a/src/main/java/net/coreprotect/database/lookup/ChestTransactionLookup.java b/src/main/java/net/coreprotect/database/lookup/ChestTransactionLookup.java index 8119a99..cbad978 100644 --- a/src/main/java/net/coreprotect/database/lookup/ChestTransactionLookup.java +++ b/src/main/java/net/coreprotect/database/lookup/ChestTransactionLookup.java @@ -112,6 +112,9 @@ public class ChestTransactionLookup { if (resultMaterial == null) { resultMaterial = Material.AIR; } + // Griefus begin + String target = MaterialUtils.asTranslatable(resultMaterial); + /* String target = resultMaterial.name().toLowerCase(Locale.ROOT); target = StringUtils.nameFilter(target, resultData); if (target.length() > 0) { @@ -122,6 +125,8 @@ public class ChestTransactionLookup { if (target.startsWith("minecraft:")) { target = target.split(":")[1]; } + */ + // Griefus end result.add(new StringBuilder(timeAgo + " " + tag + " " + Phrase.build(Phrase.LOOKUP_CONTAINER, Color.DARK_AQUA + rbFormat + resultUser + Color.WHITE + rbFormat, "x" + resultAmount, ChatUtils.createTooltip(Color.DARK_AQUA + rbFormat + target, tooltip) + Color.WHITE, selector)).toString()); PluginChannelListener.getInstance().sendData(commandSender, resultTime, Phrase.LOOKUP_CONTAINER, selector, resultUser, target, resultAmount, x, y, z, worldId, rbFormat, true, tag.contains("+")); diff --git a/src/main/java/net/coreprotect/database/lookup/InteractionLookup.java b/src/main/java/net/coreprotect/database/lookup/InteractionLookup.java index 20333aa..781ca03 100644 --- a/src/main/java/net/coreprotect/database/lookup/InteractionLookup.java +++ b/src/main/java/net/coreprotect/database/lookup/InteractionLookup.java @@ -100,6 +100,9 @@ public class InteractionLookup { if (resultMaterial == null) { resultMaterial = Material.AIR; } + // Griefus begin + String target = MaterialUtils.asTranslatable(resultMaterial); + /* String target = resultMaterial.name().toLowerCase(Locale.ROOT); target = StringUtils.nameFilter(target, resultData); if (target.length() > 0) { @@ -110,6 +113,8 @@ public class InteractionLookup { if (target.startsWith("minecraft:")) { target = target.split(":")[1]; } + */ + // Griefus end resultBuilder.append(timeAgo + " " + Color.WHITE + "- ").append(Phrase.build(Phrase.LOOKUP_INTERACTION, Color.DARK_AQUA + rbFormat + resultUser + Color.WHITE + rbFormat, Color.DARK_AQUA + rbFormat + target + Color.WHITE, Selector.FIRST)).append("\n"); PluginChannelListener.getInstance().sendData(commandSender, resultTime, Phrase.LOOKUP_INTERACTION, Selector.FIRST, resultUser, target, -1, x, y, z, worldId, rbFormat, false, false); From 220b32693455a1870375a168449ad2588ab05fad Mon Sep 17 00:00:00 2001 From: whitebelyash Date: Sun, 8 Feb 2026 22:04:41 +0400 Subject: [PATCH 19/19] Add inspector mode shortcut command (/coi|/gusi) --- .../java/net/coreprotect/command/CommandHandler.java | 8 ++++++++ src/main/resources/plugin.yml | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/main/java/net/coreprotect/command/CommandHandler.java b/src/main/java/net/coreprotect/command/CommandHandler.java index 50f9ba8..baf05c4 100755 --- a/src/main/java/net/coreprotect/command/CommandHandler.java +++ b/src/main/java/net/coreprotect/command/CommandHandler.java @@ -25,6 +25,14 @@ public class CommandHandler implements CommandExecutor { public boolean onCommand(CommandSender user, Command command, String commandLabel, String[] argumentArray) { String commandName = command.getName().toLowerCase(Locale.ROOT); + // Griefus begin + if (commandName.equals("coi") || commandName.equals("gusi")) { + boolean permission = user.hasPermission("coreprotect.inspect"); + InspectCommand.runCommand(user, permission, argumentArray); + return true; + } + // Griefus end + if (commandName.equals("core") || commandName.equals("coreprotect") || commandName.equals("co") || commandName.equals("griefus") || commandName.equals("gus")) { int resultc = argumentArray.length; if (resultc > -1) { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 7816f51..dd41707 100755 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -35,6 +35,16 @@ commands: permission: coreprotect.griefus permission-message: §3Griefus §f- You do not have permission to do that. usage: / + coi: + description: Inspector mode shortcut + permission: coreprotect.inspect + permission-message: §3Griefus §f- You do not have permission to do that. + usage: / + gusi: + description: Inspector mode shortcut + permission: coreprotect.inspect + permission-message: §3Griefus §f- You do not have permission to do that. + usage: / permissions: coreprotect.*: description: Gives access to all Griefus actions and commands