From 45be40b1b68f441f525d571ec6715f1170d8c581 Mon Sep 17 00:00:00 2001 From: Poy <75265787+NoltoxGit@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:35:39 +0200 Subject: [PATCH 1/6] =?UTF-8?q?=F0=9F=90=9B=20Restore=20legacy=20color=20c?= =?UTF-8?q?ompatibility?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Support legacy ampersand, section sign and hex colors alongside MiniMessage. - Preserve native tags, click arguments, URLs and bundled MiniMessage configurations. - Render private message colors using sender permissions and retain compatibility across chat, broadcast and mail. - Update the changelog to clarify backward compatibility. --- .../api/messages/MessageHelper.java | 79 ++++++++++++++++++- changelog.md | 2 +- .../essentials/messages/MessageLoader.java | 3 +- .../modules/kit/KitInventoryHolder.java | 3 +- .../zutils/utils/paper/PaperComponent.java | 17 ++-- .../zutils/utils/paper/PaperUtils.java | 5 +- 6 files changed, 94 insertions(+), 15 deletions(-) diff --git a/API/src/main/java/fr/maxlego08/essentials/api/messages/MessageHelper.java b/API/src/main/java/fr/maxlego08/essentials/api/messages/MessageHelper.java index 1fbfeeb0..d95a8c61 100644 --- a/API/src/main/java/fr/maxlego08/essentials/api/messages/MessageHelper.java +++ b/API/src/main/java/fr/maxlego08/essentials/api/messages/MessageHelper.java @@ -6,14 +6,87 @@ import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import java.util.List; +import java.util.Map; import java.util.Random; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class MessageHelper { private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + private static final Pattern COLOR_PATTERN = Pattern.compile( + "(<(?:\"(?:\\\\.|[^\"\\\\])*\"|'(?:\\\\.|[^'\\\\])*'|[^<>\"'])*>|(?i:https?://)[^\\s<>]+)" + + "|(§[xX](?:§[0-9a-fA-F]){6})" + + "|(? COLORS_MAPPINGS = Map.ofEntries( + Map.entry('0', "black"), + Map.entry('1', "dark_blue"), + Map.entry('2', "dark_green"), + Map.entry('3', "dark_aqua"), + Map.entry('4', "dark_red"), + Map.entry('5', "dark_purple"), + Map.entry('6', "gold"), + Map.entry('7', "gray"), + Map.entry('8', "dark_gray"), + Map.entry('9', "blue"), + Map.entry('a', "green"), + Map.entry('b', "aqua"), + Map.entry('c', "red"), + Map.entry('d', "light_purple"), + Map.entry('e', "yellow"), + Map.entry('f', "white"), + Map.entry('k', "obfuscated"), + Map.entry('l', "bold"), + Map.entry('m', "strikethrough"), + Map.entry('n', "underlined"), + Map.entry('o', "italic"), + Map.entry('r', "reset") + ); + + /** + * Converts legacy colors to MiniMessage tags so existing configurations remain readable. + * MiniMessage tags, click arguments and URLs are preserved; hover text is converted separately. + * + * @param message text containing MiniMessage, legacy colors or both + * @return text ready to deserialize with MiniMessage + */ + public static String colorMiniMessage(String message) { + Matcher matcher = COLOR_PATTERN.matcher(message); + StringBuilder result = new StringBuilder(); + while (matcher.find()) { + String replacement = matcher.group(); + if (matcher.group(1) != null) { + String prefix = " 0 && message.charAt(start - 1) == '\\') start--; + boolean escaped = (matcher.start() - start) % 2 != 0; + if (!escaped && replacement.regionMatches(true, 0, prefix, 0, prefix.length())) { + String text = replacement.substring(prefix.length(), replacement.length() - 1); + String converted = colorMiniMessage(text); + if (!text.equals(converted)) { + if (!text.startsWith("'") && !text.startsWith("\"")) { + converted = "\"" + converted.replace("\\", "\\\\").replace("\"", "\\\"") + "\""; + } + replacement = replacement.substring(0, prefix.length()) + converted + ">"; + } + } + } else if (matcher.group(2) != null) { + replacement = "<#" + matcher.group(2).substring(2).replace("§", "") + ">"; + } else if (matcher.group(3) != null) { + replacement = "<#" + matcher.group(3) + ">"; + } else { + replacement = "<" + COLORS_MAPPINGS.get(Character.toLowerCase(matcher.group(4).charAt(0))) + ">"; + } + matcher.appendReplacement(result, Matcher.quoteReplacement(replacement)); + } + matcher.appendTail(result); + return result.toString(); + } + public static int getStringLength(String message) { - return getStringLength(MiniMessage.miniMessage().deserialize(message), false); + return getStringLength(MiniMessage.miniMessage().deserialize(colorMiniMessage(message)), false); } private static int getStringLength(Component component, boolean inheritedBold) { @@ -32,11 +105,11 @@ private static int getStringLength(Component component, boolean inheritedBold) { } public static String getPlainText(String input) { - return PlainTextComponentSerializer.plainText().serialize(MiniMessage.miniMessage().deserialize(input)); + return PlainTextComponentSerializer.plainText().serialize(MiniMessage.miniMessage().deserialize(colorMiniMessage(input))); } /** - * @deprecated Use {@link #getPlainText(String)}. MiniMessage formatting is stripped from the input. + * @deprecated Use {@link #getPlainText(String)}. MiniMessage and legacy formatting are stripped from the input. */ @Deprecated(forRemoval = false) public static String removeColorCodes(String input) { diff --git a/changelog.md b/changelog.md index 3f97dc45..32fb37ec 100644 --- a/changelog.md +++ b/changelog.md @@ -35,7 +35,7 @@ - Unified item lookup and suggestions for give, mailbox and vault commands; feedback uses translated item names and preserves custom names - Fixed custom item delivery to offline mail recipients and stale custom items after reloads - Use the published zMenu **1.1.2.0** API for skulls and kit conversion/saving; the local JAR remains required for item persistence and sound helpers -- Migrated messages and configuration examples to native MiniMessage hex colors, including scoreboard animations; existing files must replace legacy `&`, `§` and bare hex color codes +- Migrated bundled messages and configuration examples to MiniMessage; legacy `&`, `§` and hex color codes remain supported in existing configurations and player messages - Fixed MiniMessage text serialization, italic formatting and bold text alignment, and preserved click events with Adventure `5.x` - Fixed feedback placeholders, duplicate Death Message registration, version comparisons and incomplete downloads; existing `command-enchant-error-enchant` messages must use `%enchant%` - Updated Gradle to `9.8.2`, Shadow to `9.6.1` and paperweight to `2.0.0-beta.24`; centralized dependency versions and retained Java 21 for common code and Java 25 for 26.x NMS diff --git a/src/main/java/fr/maxlego08/essentials/messages/MessageLoader.java b/src/main/java/fr/maxlego08/essentials/messages/MessageLoader.java index 28a1ec86..faff3d88 100644 --- a/src/main/java/fr/maxlego08/essentials/messages/MessageLoader.java +++ b/src/main/java/fr/maxlego08/essentials/messages/MessageLoader.java @@ -4,6 +4,7 @@ import fr.maxlego08.essentials.api.ConfigurationFile; import fr.maxlego08.essentials.api.messages.EssentialsMessage; import fr.maxlego08.essentials.api.messages.Message; +import fr.maxlego08.essentials.api.messages.MessageHelper; import fr.maxlego08.essentials.api.messages.MessageType; import fr.maxlego08.essentials.api.messages.messages.BossBarMessage; import fr.maxlego08.essentials.api.messages.messages.ClassicMessage; @@ -229,7 +230,7 @@ private void loadMessages(YamlConfiguration configuration) { } private String replaceMessagesColors(String message) { - return this.plugin.getConfiguration().getMessageColors().stream().reduce(message, (msg, color) -> msg.replace(color.key(), ""), (msg1, msg2) -> msg1); + return this.plugin.getConfiguration().getMessageColors().stream().reduce(message, (msg, color) -> msg.replace(color.key(), MessageHelper.colorMiniMessage(color.color())), (msg1, msg2) -> msg1); } private List getMessage(Map map) { diff --git a/src/main/java/fr/maxlego08/essentials/module/modules/kit/KitInventoryHolder.java b/src/main/java/fr/maxlego08/essentials/module/modules/kit/KitInventoryHolder.java index 674f5484..81a1afc6 100644 --- a/src/main/java/fr/maxlego08/essentials/module/modules/kit/KitInventoryHolder.java +++ b/src/main/java/fr/maxlego08/essentials/module/modules/kit/KitInventoryHolder.java @@ -1,6 +1,7 @@ package fr.maxlego08.essentials.module.modules.kit; import fr.maxlego08.essentials.api.kit.Kit; +import fr.maxlego08.essentials.api.messages.MessageHelper; import fr.maxlego08.menu.api.MenuItemStack; import net.kyori.adventure.text.minimessage.MiniMessage; import org.bukkit.Bukkit; @@ -18,7 +19,7 @@ public class KitInventoryHolder implements InventoryHolder { public KitInventoryHolder(Player player, Kit kit) { this.player = player; this.kit = kit; - this.inventory = Bukkit.createInventory(this, 54, MiniMessage.miniMessage().deserialize("Kit Editor: " + kit.getName())); + this.inventory = Bukkit.createInventory(this, 54, MiniMessage.miniMessage().deserialize(MessageHelper.colorMiniMessage("Kit Editor: " + kit.getName()))); for (int index = 0; index != Math.min(54, kit.getMenuItemStacks().size()); index++) { MenuItemStack menuItemStack = kit.getMenuItemStacks().get(index); diff --git a/src/main/java/fr/maxlego08/essentials/zutils/utils/paper/PaperComponent.java b/src/main/java/fr/maxlego08/essentials/zutils/utils/paper/PaperComponent.java index 44b12f50..7a74dc40 100644 --- a/src/main/java/fr/maxlego08/essentials/zutils/utils/paper/PaperComponent.java +++ b/src/main/java/fr/maxlego08/essentials/zutils/utils/paper/PaperComponent.java @@ -4,6 +4,7 @@ import fr.maxlego08.essentials.api.cache.SimpleCache; import fr.maxlego08.essentials.api.commands.Permission; import fr.maxlego08.essentials.api.messages.Message; +import fr.maxlego08.essentials.api.messages.MessageHelper; import fr.maxlego08.essentials.api.messages.messages.BossBarMessage; import fr.maxlego08.essentials.api.messages.messages.TitleMessage; import fr.maxlego08.essentials.api.utils.TagPermission; @@ -94,18 +95,18 @@ public void update(ItemMeta itemMeta, List lore, Player offlinePlayer) { @Override public Inventory createInventory(String inventoryName, int size, InventoryHolder inventoryHolder) { - Component component = this.cache.get(inventoryName, () -> this.MINI_MESSAGE.deserialize(inventoryName)); + Component component = this.cache.get(inventoryName, () -> this.MINI_MESSAGE.deserialize(MessageHelper.colorMiniMessage(inventoryName))); return Bukkit.createInventory(inventoryHolder, size, component); } @Override public Component getComponent(String message) { - return this.cache.get(message, () -> this.MINI_MESSAGE.deserialize(message)); + return this.cache.get(message, () -> this.MINI_MESSAGE.deserialize(MessageHelper.colorMiniMessage(message))); } @Override public Component getComponent(String message, TagResolver tagResolver) { - return this.MINI_MESSAGE.deserialize(message, tagResolver); + return this.MINI_MESSAGE.deserialize(MessageHelper.colorMiniMessage(message), tagResolver); } @Override @@ -131,21 +132,21 @@ private TagResolver getTagResolver(Player player, TagResolver... tagResolvers) { public Component translateText(Player player, String message, TagResolver... tagResolvers) { var tagResolver = getTagResolver(player, tagResolvers); - return MiniMessage.builder().tags(tagResolver).build().deserialize(message); + return MiniMessage.builder().tags(tagResolver).build().deserialize(MessageHelper.colorMiniMessage(message)); } @Override public void sendActionBar(Player sender, String message) { - Component component = this.cache.get(message, () -> this.MINI_MESSAGE.deserialize(message)); + Component component = this.cache.get(message, () -> this.MINI_MESSAGE.deserialize(MessageHelper.colorMiniMessage(message))); sender.sendActionBar(component); } @Override public void sendMessage(CommandSender sender, String message) { if (sender instanceof Player player) { - sender.sendMessage(this.MINI_MESSAGE.deserialize(papi(message, player))); + sender.sendMessage(this.MINI_MESSAGE.deserialize(MessageHelper.colorMiniMessage(papi(message, player)))); } else { - Component component = this.cache.get(message, () -> this.MINI_MESSAGE.deserialize(message)); + Component component = this.cache.get(message, () -> this.MINI_MESSAGE.deserialize(MessageHelper.colorMiniMessage(message))); sender.sendMessage(component); } } @@ -223,7 +224,7 @@ public void changeSignColor(SignChangeEvent event) { if (line == null) continue; var plainText = plainTextSerializer.serialize(line); - event.line(i, miniMessage.deserialize(plainText)); + event.line(i, miniMessage.deserialize(MessageHelper.colorMiniMessage(plainText))); } } } diff --git a/src/main/java/fr/maxlego08/essentials/zutils/utils/paper/PaperUtils.java b/src/main/java/fr/maxlego08/essentials/zutils/utils/paper/PaperUtils.java index 559983ce..8b3ee346 100644 --- a/src/main/java/fr/maxlego08/essentials/zutils/utils/paper/PaperUtils.java +++ b/src/main/java/fr/maxlego08/essentials/zutils/utils/paper/PaperUtils.java @@ -8,6 +8,7 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.tag.Tag; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerLoginEvent; @@ -33,6 +34,8 @@ public void disallow(PlayerLoginEvent event, PlayerLoginEvent.Result result, Mes public void sendPrivateMessage(User user, PrivateMessage privateMessage, Message message, String content) { PaperComponent paperComponent = (PaperComponent) this.componentMessage; var messageAsString = papi(getMessage(message.getMessageAsString(), "%target%", privateMessage.username()), user.getPlayer()); - user.getPlayer().sendMessage(paperComponent.getComponent(messageAsString, TagResolver.resolver("message", Tag.inserting(Component.text(content))))); + Player sender = message == Message.COMMAND_MESSAGE_OTHER ? Bukkit.getPlayer(privateMessage.uuid()) : user.getPlayer(); + Component component = sender == null ? Component.text(content) : paperComponent.translateText(sender, content); + user.getPlayer().sendMessage(paperComponent.getComponent(messageAsString, TagResolver.resolver("message", Tag.inserting(component)))); } } From 5579e157a9cfec23e84cc580a23efc155d41ed5a Mon Sep 17 00:00:00 2001 From: Poy <75265787+NoltoxGit@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:38:23 +0200 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=91=B7=20Fix=20build=20artifact=20dis?= =?UTF-8?q?covery?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Configure the GroupeZ build workflow to find plugin JARs in target/. --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1ebeba2a..58f16006 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,6 +21,7 @@ jobs: uses: GroupeZ-dev/actions/.github/workflows/build.yml@main with: project-name: "zEssentials" + artifact-glob: "target/*.jar" publish: true project-to-publish: "API:publish" discord-avatar-url: "https://groupez.dev/storage/images/325.png" From bda66cc288f5fe44e081755ebf8e9b5b5f765774 Mon Sep 17 00:00:00 2001 From: Poy <75265787+NoltoxGit@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:45:07 +0200 Subject: [PATCH 3/6] =?UTF-8?q?=F0=9F=91=B7=20Align=20the=20build=20workfl?= =?UTF-8?q?ow=20with=20zMenu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Pin the GroupeZ workflow to v1.0.0 and explicitly select Java 25. - Preserve main branch runs and filter dependency updates from build changelogs. - Follow the shared workflow permission configuration and retain target/*.jar artifact discovery. --- .github/workflows/build.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 58f16006..184e8988 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,24 +7,23 @@ on: types: [ opened, synchronize, reopened ] workflow_dispatch: -permissions: - contents: read - packages: write concurrency: group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true + cancel-in-progress: ${{ github.ref_name != 'main' }} jobs: build: name: Build and Publish zEssentials - uses: GroupeZ-dev/actions/.github/workflows/build.yml@main + uses: GroupeZ-dev/actions/.github/workflows/build.yml@v1.0.0 with: project-name: "zEssentials" - artifact-glob: "target/*.jar" + java-version: '25' publish: true project-to-publish: "API:publish" discord-avatar-url: "https://groupez.dev/storage/images/325.png" + artifact-glob: "target/*.jar" + changelog-exclude-pattern: '^[a-f0-9]+\s+(build|chore)\(deps\)' secrets: WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }} MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} From 89fd3fb7ebcde577de24f71ed13da052076b9826 Mon Sep 17 00:00:00 2001 From: Poy <75265787+NoltoxGit@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:53:01 +0200 Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=91=B7=20Restore=20build=20workflow?= =?UTF-8?q?=20permissions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Explicitly grant contents read and packages write permissions to the reusable GroupeZ workflow. - Fix workflow validation when repository defaults only allow packages read access. --- .github/workflows/build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 184e8988..89f63e6d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,6 +8,10 @@ on: workflow_dispatch: +permissions: + contents: read + packages: write + concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.ref_name != 'main' }} From d2d6ff87e043e20c52ae49055c8dadd35f30f460 Mon Sep 17 00:00:00 2001 From: Poy <75265787+NoltoxGit@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:53:01 +0200 Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=93=9D=20Changes=20to=20the=20=20?= =?UTF-8?q?=C2=AB=20todolist=20=C2=BB=20section=20in=20the=20changelog.md?= =?UTF-8?q?=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 184e8988..89f63e6d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,6 +8,10 @@ on: workflow_dispatch: +permissions: + contents: read + packages: write + concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.ref_name != 'main' }} From dcac622272e8087724082d5a64f3858ed9c98011 Mon Sep 17 00:00:00 2001 From: Noltox Date: Sat, 24 Oct 2026 18:41:56 +0200 Subject: [PATCH 6/6] =?UTF-8?q?=F0=9F=93=9D=20Revise=20changelog=20with=20?= =?UTF-8?q?new=20features=20and=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Updated the changelog with new features and improvements, including support for commands, permissions, holograms, and more. --- changelog.md | 57 +++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/changelog.md b/changelog.md index 32fb37ec..5661605b 100644 --- a/changelog.md +++ b/changelog.md @@ -1,31 +1,34 @@ # Idées : -- Ajouter un broadcast de message centré avec le support des `\n` pour ajouter plusieurs lignes -- Ajouter une option pour désactiver la tabulation des joueurs hors ligne -- Ajouter un placeholder pour transformer les caractères en lettre spécial -- Ajouter une commande type `/oplist` pour afficher la liste des opérateurs du serveur (**ISSUE:** https://github.com/Maxlego08/zEssentials/issues/4) -- Améliorer la commande `/nightvision` pour qu'elle soit persistente lors d'un kill et de déconnexion/reconnexion du joueur (**ISSUE:** https://github.com/Maxlego08/zEssentials/issues/4) -- Ajouter la possibilité d'utiliser la commande `/invsee` sur les joueurs hors ligne -- Ajouter la commande `/nick` pour changer le pseudo d'un joueur (**ISSUE:** https://github.com/Maxlego08/zEssentials/issues/161) - - Rajouter une permission pour limiter l'utilisation des couleurs - - Rajouter une permission pour que le pseudo à l'output du /nick (raw) soit le même (sans prendre en compte les couleurs) que le pseudo initial -- Grosse refonte des hologrammes : - - Rajouter les hologrammes à double face (**ISSUE:** https://github.com/Maxlego08/zEssentials/issues/27) - - Rajouter les hologrammes "cliquables" avec une hitbox pour créer des interactions - - Rajouter les hologrammes avec de la pagination (**ISSUE:** https://github.com/Maxlego08/zEssentials/issues/40) - - Ajouter une API complète pour que les développeurs puissent se hook à zEssentials pour créer leurs hologrammes -- Rajouter la commande `/signedit` pour éditer une pancarte juste en la regardant -- Utiliser les dialogs là où c'est possible dans les versions récentes (entrer du texte...) -- Faire en sorte que si le NMS d'une version n'est pas encore ajouté, ça fallback vers la version précédente disponible -- Ajouter un module de TAB (**ISSUE:** https://github.com/Maxlego08/zEssentials/issues/147) -- Ajouter un module pour pour désactiver l'apparition des phantoms pour un joueur (**ISSUE:** https://github.com/Maxlego08/zEssentials/issues/147) -- Ajouter deux nouvelles permissions distinctes pour désactiver la perte d'inventaire et la perte d'expérience à la mort du joueur -- Ajouter un module de fly temporaire avec une commande pour give/take du temps -- Dans le module du chat, rajouter deux nouveaux placeholders pour montrer le contenu de son inventaire et le contenu de son coffre de l'ender (**ISSUE:** https://github.com/Maxlego08/zEssentials/issues/127) -- Dans les informations au démarrage, indiquer la liste des modules qui sont activés/désactivés -- Ajouter la commande `/zessentials modules` pour connaître la liste des modules qui sont activés/désactivés -- Ajouter pleinement le support de "VaultUnlocked: https://github.com/TheNewEconomy/VaultUnlocked" -- Lorsqu'un module est désactivé, faire en sorte qu'il soit complètement désactiver sur le serveur (commandes, status, checks...) +- Ajouter un broadcast centré, avec la prise en charge de `\n` pour afficher plusieurs lignes. +- Ajouter une option pour exclure les joueurs hors ligne de la tabulation. +- Ajouter un placeholder pour convertir le texte en lettres stylisées (smallcaps). +- Ajouter une commande `/oplist` pour consulter la liste des opérateurs du serveur ([issue #4](https://github.com/Maxlego08/zEssentials/issues/4)). +- Conserver l'effet de vision nocturne après la mort et la reconnexion du joueur ([issue #4](https://github.com/Maxlego08/zEssentials/issues/4)). +- Permettre à la commande `/invsee` et `/endersee` d'afficher l'inventaire des joueurs hors ligne. +- Ajouter une commande `/nick` pour modifier le pseudo d'un joueur ([issue #161](https://github.com/Maxlego08/zEssentials/issues/161)). + - Ajouter une permission pour limiter l'utilisation des couleurs dans les pseudos. + - Ajouter une permission pour afficher le pseudo d'origine sans tenir compte des couleurs. +- Revoir le système d'hologrammes : + - Ajouter l'affichage double face ([issue #27](https://github.com/Maxlego08/zEssentials/issues/27)). + - Ajouter des zones cliquables permettant de déclencher des interactions. + - Ajouter la pagination ([issue #40](https://github.com/Maxlego08/zEssentials/issues/40)). + - Fournir une API permettant aux développeurs de créer leurs propres hologrammes. +- Ajouter une commande `/signedit` pour modifier la pancarte visée. +- Utiliser les dialogs de zMenu lorsque c'est possible, notamment pour les champs de saisie et les curseurs. +- Prévoir un fallback vers le NMS de la version précédente lorsqu'aucun module n'existe pour la version du serveur. +- Ajouter un module de TAB configurable ([issue #147](https://github.com/Maxlego08/zEssentials/issues/147)). +- Ajouter une option permettant à chaque joueur de désactiver l'apparition des phantoms ([issue #147](https://github.com/Maxlego08/zEssentials/issues/147)). +- Ajouter des permissions distinctes pour conserver l'inventaire et l'expérience à la mort. +- Vérifier le fonctionnement du module de fly temporaire. +- Ajouter au chat des placeholders affichant l'inventaire et le coffre de l'Ender du joueur ([issue #127](https://github.com/Maxlego08/zEssentials/issues/127)). +- Ajouter `/zessentials modules` pour afficher les modules activés et désactivés. +- Afficher l'état des modules au démarrage du plugin. +- Désactiver complètement les modules désactivés, y compris leurs commandes et leurs vérifications. +- Compléter la prise en charge de [VaultUnlocked](https://github.com/TheNewEconomy/VaultUnlocked) en utilisant ses méthodes optimisées. +- Vérifier le fonctionnement de zEssentials sur Folia. +- Ajouter une commande pour créer des bossbars personnalisées et configurer leur couleur, leur style, leur texte et leur durée. +- Ajouter un système de récompenses fondé sur le temps de jeu, avec des gains périodiques ou uniques. # Unreleased @@ -746,4 +749,4 @@ economies: # 1.0.0.1 - Added the command `/ess convert CMI`, allows converting the database from CMI to zEssentials. - Documentation: https://zessentials.groupez.dev/getting-started/convert#cmi \ No newline at end of file + Documentation: https://zessentials.groupez.dev/getting-started/convert#cmi