feat: add anti-pvp, anti-piston, anti-fluid protections, /guild list, /guild decline, interactive clickable invites and help menu
This commit is contained in:
@@ -15,17 +15,19 @@ import org.bukkit.Location;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.Optional;
|
import java.util.*;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enregistrement et définition de la suite complète de commandes `/guild`
|
* Enregistrement et définition de la suite complète de commandes `/guild`
|
||||||
* utilisant les validateurs métier et les confirmations de **betterMcCommands**.
|
* utilisant les validateurs métier, les confirmations et les composants interactifs de **betterMcCommands**.
|
||||||
*/
|
*/
|
||||||
public class GuildCommands {
|
public class GuildCommands {
|
||||||
|
|
||||||
private static final Pattern GUILD_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9_]{3,16}$");
|
private static final Pattern GUILD_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9_]{3,16}$");
|
||||||
|
private static final int HELP_PAGE_SIZE = 8;
|
||||||
|
private static final int GUILD_LIST_PAGE_SIZE = 6;
|
||||||
|
|
||||||
private final Main plugin;
|
private final Main plugin;
|
||||||
private final GuildManager guildManager;
|
private final GuildManager guildManager;
|
||||||
@@ -56,30 +58,83 @@ public class GuildCommands {
|
|||||||
.aliases("g", "guilde", "clan")
|
.aliases("g", "guilde", "clan")
|
||||||
|
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
// Racine /guild : Affichage du panneau d'aide
|
// Racine /guild : Affichage du panneau d'aide interactif
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
.executes(context -> {
|
.executes(context -> sendHelpMenu(context, 1))
|
||||||
context.reply("<gradient:#00C9FF:#92FE9D><bold>=== SYSTÈME DE GUILDE ===</bold></gradient>");
|
|
||||||
context.reply("<yellow>/guild create <nom> [tag]</yellow> <gray>- Fonder une nouvelle guilde</gray>");
|
// -------------------------------------------------------------
|
||||||
context.reply("<yellow>/guild disband</yellow> <gray>- Dissoudre votre guilde</gray>");
|
// Sous-commande : /guild help [page]
|
||||||
context.reply("<yellow>/guild color <#hex></yellow> <gray>- Modifier la couleur hexadécimale</gray>");
|
// -------------------------------------------------------------
|
||||||
context.reply("<yellow>/guild tag <tag></yellow> <gray>- Modifier le tag court</gray>");
|
.subcommand(BetterMcCommands.subBuilder("help")
|
||||||
context.reply("<yellow>/guild invite <joueur></yellow> <gray>- Inviter un joueur</gray>");
|
.description("Afficher le menu d'aide interactif")
|
||||||
context.reply("<yellow>/guild join <guilde></yellow> <gray>- Rejoindre une guilde invitante</gray>");
|
.aliases("aide", "?")
|
||||||
context.reply("<yellow>/guild leave</yellow> <gray>- Quitter votre guilde</gray>");
|
.argument(Arguments.integer("page", 1, 10).optional().description("Numéro de page"))
|
||||||
context.reply("<yellow>/guild kick <joueur></yellow> <gray>- Expulser un membre</gray>");
|
.executes(context -> {
|
||||||
context.reply("<yellow>/guild info [guilde]</yellow> <gray>- Afficher les détails d'une guilde</gray>");
|
int page = context.getOptional("page", Integer.class).orElse(1);
|
||||||
context.reply("<yellow>/guild members [guilde]</yellow> <gray>- Liste des membres</gray>");
|
sendHelpMenu(context, page);
|
||||||
context.reply("<yellow>/guild claim</yellow> <gray>- Revendiquer le chunk actuel</gray>");
|
})
|
||||||
context.reply("<yellow>/guild unclaim</yellow> <gray>- Libérer le chunk actuel</gray>");
|
)
|
||||||
context.reply("<yellow>/guild deposit <montant></yellow> <gray>- Déposer dans la banque</gray>");
|
|
||||||
context.reply("<yellow>/guild withdraw <montant></yellow> <gray>- Retirer de la banque</gray>");
|
// -------------------------------------------------------------
|
||||||
context.reply("<yellow>/guild sethome</yellow> <gray>- Définir le point de ralliement</gray>");
|
// Sous-commande : /guild list [page]
|
||||||
context.reply("<yellow>/guild home</yellow> <gray>- Se téléporter au home de guilde</gray>");
|
// -------------------------------------------------------------
|
||||||
if (context.getSender().hasPermission("guild.admin.reload")) {
|
.subcommand(BetterMcCommands.subBuilder("list")
|
||||||
context.reply("<red>/guild reload</red> <gray>- Recharger les configurations et messages</gray>");
|
.description("Afficher la liste des guildes du serveur")
|
||||||
}
|
.aliases("liste", "top")
|
||||||
})
|
.argument(Arguments.integer("page", 1, 100).optional().description("Numéro de page"))
|
||||||
|
.executes(context -> {
|
||||||
|
int page = context.getOptional("page", Integer.class).orElse(1);
|
||||||
|
List<Guild> allGuilds = new ArrayList<>(guildManager.getAllGuilds());
|
||||||
|
|
||||||
|
if (allGuilds.isEmpty()) {
|
||||||
|
context.reply(msg.get("guild.list.empty"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trier par nombre de membres décroissant
|
||||||
|
allGuilds.sort((g1, g2) -> Integer.compare(g2.getMemberCount(), g1.getMemberCount()));
|
||||||
|
|
||||||
|
int totalGuilds = allGuilds.size();
|
||||||
|
int maxPage = (int) Math.ceil((double) totalGuilds / GUILD_LIST_PAGE_SIZE);
|
||||||
|
if (page > maxPage) page = maxPage;
|
||||||
|
if (page < 1) page = 1;
|
||||||
|
|
||||||
|
context.reply(msg.get("guild.list.header",
|
||||||
|
"{page}", String.valueOf(page),
|
||||||
|
"{max_page}", String.valueOf(maxPage)
|
||||||
|
));
|
||||||
|
|
||||||
|
int startIndex = (page - 1) * GUILD_LIST_PAGE_SIZE;
|
||||||
|
int endIndex = Math.min(startIndex + GUILD_LIST_PAGE_SIZE, totalGuilds);
|
||||||
|
|
||||||
|
for (int i = startIndex; i < endIndex; i++) {
|
||||||
|
Guild g = allGuilds.get(i);
|
||||||
|
GuildMember leader = g.getLeaderMember();
|
||||||
|
String leaderName = leader != null && leader.getOfflinePlayer() != null && leader.getOfflinePlayer().getName() != null
|
||||||
|
? leader.getOfflinePlayer().getName()
|
||||||
|
: "Inconnu";
|
||||||
|
|
||||||
|
String line = msg.get("guild.list.item",
|
||||||
|
"{index}", String.valueOf(i + 1),
|
||||||
|
"{guild}", g.getFormattedName(),
|
||||||
|
"{tag}", g.getFormattedTag(),
|
||||||
|
"{leader}", leaderName,
|
||||||
|
"{members}", String.valueOf(g.getMemberCount()),
|
||||||
|
"{claims}", String.valueOf(g.getClaimCount())
|
||||||
|
);
|
||||||
|
context.reply(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
int prevPage = Math.max(1, page - 1);
|
||||||
|
int nextPage = Math.min(maxPage, page + 1);
|
||||||
|
|
||||||
|
String pagination = msg.get("guild.list.pagination",
|
||||||
|
"{prev_page}", String.valueOf(prevPage),
|
||||||
|
"{next_page}", String.valueOf(nextPage)
|
||||||
|
);
|
||||||
|
context.reply(pagination);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
// Sous-commande : /guild create <nom> [tag]
|
// Sous-commande : /guild create <nom> [tag]
|
||||||
@@ -90,7 +145,6 @@ public class GuildCommands {
|
|||||||
.argument(Arguments.string("nom").description("Nom de la guilde (3-16 car)"))
|
.argument(Arguments.string("nom").description("Nom de la guilde (3-16 car)"))
|
||||||
.argument(Arguments.string("tag").optional().description("Tag court (ex: LEG)"))
|
.argument(Arguments.string("tag").optional().description("Tag court (ex: LEG)"))
|
||||||
|
|
||||||
// Validations dynamiques
|
|
||||||
.validate(context -> {
|
.validate(context -> {
|
||||||
if (guildManager.isInGuild(context.getPlayer().getUniqueId())) {
|
if (guildManager.isInGuild(context.getPlayer().getUniqueId())) {
|
||||||
return ValidationResult.invalid(msg.get("guild.already_in_guild"));
|
return ValidationResult.invalid(msg.get("guild.already_in_guild"));
|
||||||
@@ -136,9 +190,13 @@ public class GuildCommands {
|
|||||||
|
|
||||||
GuildResult result = guildManager.createGuild(player, name, tag, creationCost);
|
GuildResult result = guildManager.createGuild(player, name, tag, creationCost);
|
||||||
if (result.isSuccess()) {
|
if (result.isSuccess()) {
|
||||||
|
Guild createdGuild = guildManager.getGuildByName(name);
|
||||||
|
String formattedName = createdGuild != null ? createdGuild.getFormattedName() : name;
|
||||||
|
String formattedTag = createdGuild != null ? createdGuild.getFormattedTag() : "[" + tag + "]";
|
||||||
|
|
||||||
String successMsg = msg.get("guild.creation.success",
|
String successMsg = msg.get("guild.creation.success",
|
||||||
"{guild}", name,
|
"{guild}", formattedName,
|
||||||
"{tag}", tag,
|
"{tag}", formattedTag,
|
||||||
"{cost}", guildManager.getEconomyManager().format(creationCost),
|
"{cost}", guildManager.getEconomyManager().format(creationCost),
|
||||||
"{world}", loc.getWorld().getName(),
|
"{world}", loc.getWorld().getName(),
|
||||||
"{chunk_x}", String.valueOf(chunk.getX()),
|
"{chunk_x}", String.valueOf(chunk.getX()),
|
||||||
@@ -177,10 +235,10 @@ public class GuildCommands {
|
|||||||
Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
|
Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
|
||||||
if (guild == null) return;
|
if (guild == null) return;
|
||||||
|
|
||||||
String guildName = guild.getName();
|
String formattedName = guild.getFormattedName();
|
||||||
GuildResult result = guildManager.disbandGuild(player, guild);
|
GuildResult result = guildManager.disbandGuild(player, guild);
|
||||||
if (result.isSuccess()) {
|
if (result.isSuccess()) {
|
||||||
context.reply(msg.get("guild.disband.success", "{guild}", guildName));
|
context.reply(msg.get("guild.disband.success", "{guild}", formattedName));
|
||||||
} else {
|
} else {
|
||||||
context.replyError(result.getMessage());
|
context.replyError(result.getMessage());
|
||||||
}
|
}
|
||||||
@@ -222,10 +280,13 @@ public class GuildCommands {
|
|||||||
"{seconds}", String.valueOf(invite.getRemainingSeconds())
|
"{seconds}", String.valueOf(invite.getRemainingSeconds())
|
||||||
));
|
));
|
||||||
|
|
||||||
TextUtil.sendMessage(target, msg.get("guild.invite.received",
|
String interactiveMsg = msg.get("guild.invite.received_interactive",
|
||||||
"{guild}", guild.getName(),
|
"{guild}", guild.getFormattedName(),
|
||||||
|
"{tag}", guild.getFormattedTag(),
|
||||||
|
"{raw_guild}", guild.getName(),
|
||||||
"{sender}", sender.getName()
|
"{sender}", sender.getName()
|
||||||
));
|
);
|
||||||
|
TextUtil.sendMessage(target, interactiveMsg);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -255,7 +316,7 @@ public class GuildCommands {
|
|||||||
|
|
||||||
GuildInvite invite = inviteManager.getValidInvite(player, targetGuild.getId());
|
GuildInvite invite = inviteManager.getValidInvite(player, targetGuild.getId());
|
||||||
if (invite == null) {
|
if (invite == null) {
|
||||||
context.reply(msg.get("guild.invite.no_pending_invite", "{guild}", targetGuild.getName()));
|
context.reply(msg.get("guild.invite.no_pending_invite", "{guild}", targetGuild.getFormattedName()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,6 +330,44 @@ public class GuildCommands {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// Sous-commande : /guild decline <guilde>
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
.subcommand(BetterMcCommands.subBuilder("decline")
|
||||||
|
.description("Refuser une invitation de guilde reçue")
|
||||||
|
.aliases("refuser", "deny")
|
||||||
|
.playerOnly()
|
||||||
|
.argument(Arguments.string("guilde").description("Nom de la guilde"))
|
||||||
|
.executes(context -> {
|
||||||
|
Player player = context.getPlayer();
|
||||||
|
String guildName = context.getString("guilde");
|
||||||
|
Guild targetGuild = guildManager.getGuildByName(guildName);
|
||||||
|
|
||||||
|
if (targetGuild == null) {
|
||||||
|
context.reply(msg.get("guild.guild_not_found", "{guild}", guildName));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GuildInvite invite = inviteManager.getValidInvite(player, targetGuild.getId());
|
||||||
|
if (invite == null) {
|
||||||
|
context.reply(msg.get("guild.invite.no_pending_invite", "{guild}", targetGuild.getFormattedName()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inviteManager.removeInvite(player, targetGuild.getId());
|
||||||
|
context.reply(msg.get("guild.invite.declined_target", "{guild}", targetGuild.getFormattedName()));
|
||||||
|
|
||||||
|
// Notifier l'émetteur si en ligne
|
||||||
|
GuildMember leader = targetGuild.getLeaderMember();
|
||||||
|
if (leader != null && leader.getOfflinePlayer() != null && leader.getOfflinePlayer().isOnline()) {
|
||||||
|
Player leaderPlayer = leader.getOfflinePlayer().getPlayer();
|
||||||
|
if (leaderPlayer != null) {
|
||||||
|
TextUtil.sendMessage(leaderPlayer, msg.get("guild.invite.declined_sender", "{player}", player.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
// Sous-commande : /guild leave
|
// Sous-commande : /guild leave
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
@@ -295,10 +394,10 @@ public class GuildCommands {
|
|||||||
Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
|
Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
|
||||||
if (guild == null) return;
|
if (guild == null) return;
|
||||||
|
|
||||||
String guildName = guild.getName();
|
String formattedName = guild.getFormattedName();
|
||||||
GuildResult result = guildManager.leaveGuild(player, guild);
|
GuildResult result = guildManager.leaveGuild(player, guild);
|
||||||
if (result.isSuccess()) {
|
if (result.isSuccess()) {
|
||||||
context.reply(msg.get("guild.leave.success", "{guild}", guildName));
|
context.reply(msg.get("guild.leave.success", "{guild}", formattedName));
|
||||||
} else {
|
} else {
|
||||||
context.replyError(result.getMessage());
|
context.replyError(result.getMessage());
|
||||||
}
|
}
|
||||||
@@ -343,7 +442,7 @@ public class GuildCommands {
|
|||||||
GuildResult result = guildManager.kickMember(player, guild, target.getUniqueId());
|
GuildResult result = guildManager.kickMember(player, guild, target.getUniqueId());
|
||||||
if (result.isSuccess()) {
|
if (result.isSuccess()) {
|
||||||
context.reply(msg.get("guild.kick.success", "{player}", target.getName()));
|
context.reply(msg.get("guild.kick.success", "{player}", target.getName()));
|
||||||
TextUtil.sendMessage(target, msg.get("guild.kick.target_notify", "{guild}", guild.getName()));
|
TextUtil.sendMessage(target, msg.get("guild.kick.target_notify", "{guild}", guild.getFormattedName()));
|
||||||
} else {
|
} else {
|
||||||
context.replyError(result.getMessage());
|
context.replyError(result.getMessage());
|
||||||
}
|
}
|
||||||
@@ -676,7 +775,9 @@ public class GuildCommands {
|
|||||||
|
|
||||||
double nextPrice = guildManager.getPriceCalculator().calculateNextChunkPrice(targetGuild);
|
double nextPrice = guildManager.getPriceCalculator().calculateNextChunkPrice(targetGuild);
|
||||||
GuildMember leader = targetGuild.getLeaderMember();
|
GuildMember leader = targetGuild.getLeaderMember();
|
||||||
String leaderName = leader != null && leader.getOfflinePlayer() != null ? leader.getOfflinePlayer().getName() : "Inconnu";
|
String leaderName = leader != null && leader.getOfflinePlayer() != null && leader.getOfflinePlayer().getName() != null
|
||||||
|
? leader.getOfflinePlayer().getName()
|
||||||
|
: "Inconnu";
|
||||||
|
|
||||||
context.reply("<gradient:#00C9FF:#92FE9D><bold>=== INFORMATIONS DE GUILDE ===</bold></gradient>");
|
context.reply("<gradient:#00C9FF:#92FE9D><bold>=== INFORMATIONS DE GUILDE ===</bold></gradient>");
|
||||||
context.reply("<gray>Nom :</gray> " + targetGuild.getFormattedName() + " " + targetGuild.getFormattedTag());
|
context.reply("<gray>Nom :</gray> " + targetGuild.getFormattedName() + " " + targetGuild.getFormattedTag());
|
||||||
@@ -716,7 +817,7 @@ public class GuildCommands {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.reply("<gradient:#00C9FF:#92FE9D><bold>=== MEMBRES : " + targetGuild.getName() + " ===</bold></gradient>");
|
context.reply("<gradient:#00C9FF:#92FE9D><bold>=== MEMBRES : </bold></gradient>" + targetGuild.getFormattedName());
|
||||||
for (GuildRank rank : targetGuild.getRanks()) {
|
for (GuildRank rank : targetGuild.getRanks()) {
|
||||||
String membersInRank = targetGuild.getMembers().stream()
|
String membersInRank = targetGuild.getMembers().stream()
|
||||||
.filter(m -> m.getRankId().equalsIgnoreCase(rank.getId()))
|
.filter(m -> m.getRankId().equalsIgnoreCase(rank.getId()))
|
||||||
@@ -744,4 +845,70 @@ public class GuildCommands {
|
|||||||
|
|
||||||
.register();
|
.register();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Envoie le menu d'aide interactif et paginé avec tooltips au survol et suggestions de commande au clic.
|
||||||
|
*/
|
||||||
|
private void sendHelpMenu(fr.luc.bettermccommands.api.CommandContext context, int page) {
|
||||||
|
List<HelpEntry> entries = new ArrayList<>();
|
||||||
|
entries.add(new HelpEntry("/guild create <nom> [tag]", "Fonder une nouvelle guilde et revendiquer le 1er chunk", "/guild create "));
|
||||||
|
entries.add(new HelpEntry("/guild list [page]", "Afficher la liste des guildes du serveur", "/guild list "));
|
||||||
|
entries.add(new HelpEntry("/guild info [guilde]", "Afficher les statistiques détaillées d'une guilde", "/guild info "));
|
||||||
|
entries.add(new HelpEntry("/guild members [guilde]", "Afficher la liste des membres classés par rang", "/guild members "));
|
||||||
|
entries.add(new HelpEntry("/guild color <#hex>", "Modifier la couleur hexadécimale de la guilde", "/guild color "));
|
||||||
|
entries.add(new HelpEntry("/guild tag <tag>", "Modifier le tag court de la guilde (2-6 car)", "/guild tag "));
|
||||||
|
entries.add(new HelpEntry("/guild invite <joueur>", "Inviter un joueur connecté à rejoindre la guilde", "/guild invite "));
|
||||||
|
entries.add(new HelpEntry("/guild join <guilde>", "Accepter une invitation et rejoindre une guilde", "/guild join "));
|
||||||
|
entries.add(new HelpEntry("/guild decline <guilde>", "Refuser une invitation de guilde reçue", "/guild decline "));
|
||||||
|
entries.add(new HelpEntry("/guild leave", "Quitter votre guilde actuelle", "/guild leave"));
|
||||||
|
entries.add(new HelpEntry("/guild kick <joueur>", "Expulser un membre ayant un rang inférieur", "/guild kick "));
|
||||||
|
entries.add(new HelpEntry("/guild disband", "Dissoudre définitivement votre guilde (Chef uniquement)", "/guild disband"));
|
||||||
|
entries.add(new HelpEntry("/guild claim", "Revendiquer le chunk actuel pour votre guilde", "/guild claim"));
|
||||||
|
entries.add(new HelpEntry("/guild unclaim", "Libérer le chunk actuel possédé par la guilde", "/guild unclaim"));
|
||||||
|
entries.add(new HelpEntry("/guild deposit <montant>", "Déposer des fonds dans la banque de guilde", "/guild deposit "));
|
||||||
|
entries.add(new HelpEntry("/guild withdraw <montant>", "Retirer des fonds de la banque de guilde", "/guild withdraw "));
|
||||||
|
entries.add(new HelpEntry("/guild sethome", "Définir le point de ralliement de la guilde", "/guild sethome"));
|
||||||
|
entries.add(new HelpEntry("/guild home", "Se téléporter au point de ralliement de la guilde", "/guild home"));
|
||||||
|
if (context.getSender().hasPermission("guild.admin.reload")) {
|
||||||
|
entries.add(new HelpEntry("/guild reload", "Recharger les configurations et messages du plugin", "/guild reload"));
|
||||||
|
}
|
||||||
|
|
||||||
|
int totalEntries = entries.size();
|
||||||
|
int maxPage = (int) Math.ceil((double) totalEntries / HELP_PAGE_SIZE);
|
||||||
|
if (page > maxPage) page = maxPage;
|
||||||
|
if (page < 1) page = 1;
|
||||||
|
|
||||||
|
context.reply(msg.get("help.header", "{page}", String.valueOf(page), "{max_page}", String.valueOf(maxPage)));
|
||||||
|
|
||||||
|
int startIndex = (page - 1) * HELP_PAGE_SIZE;
|
||||||
|
int endIndex = Math.min(startIndex + HELP_PAGE_SIZE, totalEntries);
|
||||||
|
|
||||||
|
for (int i = startIndex; i < endIndex; i++) {
|
||||||
|
HelpEntry entry = entries.get(i);
|
||||||
|
String line = "<click:suggest_command:'" + entry.suggestCommand + "'>" +
|
||||||
|
"<hover:show_text:'<green>Cliquez pour insérer : </green><yellow>" + entry.usage + "</yellow>'>" +
|
||||||
|
"<yellow>" + entry.usage + "</yellow></hover></click> <gray>- " + entry.description + "</gray>";
|
||||||
|
context.reply(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
int prevPage = Math.max(1, page - 1);
|
||||||
|
int nextPage = Math.min(maxPage, page + 1);
|
||||||
|
|
||||||
|
String footer = "<click:run_command:'/guild help " + prevPage + "'><hover:show_text:'<yellow>Page précédente</yellow>'><aqua>[◀ Précédent]</aqua></hover></click> " +
|
||||||
|
"<dark_gray>---</dark_gray> " +
|
||||||
|
"<click:run_command:'/guild help " + nextPage + "'><hover:show_text:'<yellow>Page suivante</yellow>'><aqua>[Suivant ▶]</aqua></hover></click>";
|
||||||
|
context.reply(footer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class HelpEntry {
|
||||||
|
final String usage;
|
||||||
|
final String description;
|
||||||
|
final String suggestCommand;
|
||||||
|
|
||||||
|
HelpEntry(String usage, String description, String suggestCommand) {
|
||||||
|
this.usage = usage;
|
||||||
|
this.description = description;
|
||||||
|
this.suggestCommand = suggestCommand;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,22 +8,27 @@ import fr.luc.gamingcore.util.MessageManager;
|
|||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.ArmorStand;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.Hanging;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.entity.Projectile;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.block.Action;
|
import org.bukkit.event.block.*;
|
||||||
import org.bukkit.event.block.BlockBreakEvent;
|
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||||
import org.bukkit.event.block.BlockExplodeEvent;
|
|
||||||
import org.bukkit.event.block.BlockPlaceEvent;
|
|
||||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||||
|
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
import org.bukkit.event.player.PlayerMoveEvent;
|
import org.bukkit.event.player.PlayerMoveEvent;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Écouteur d'événements garantissant la protection territoriale des chunks de guilde contre le grief et les intrusions.
|
* Écouteur d'événements garantissant la protection territoriale complète des chunks de guilde :
|
||||||
|
* anti-grief, anti-pvp, anti-pistons transfrontaliers, anti-fluides et protection des entités/conteneurs.
|
||||||
*/
|
*/
|
||||||
public class TerritoryProtectionListener implements Listener {
|
public class TerritoryProtectionListener implements Listener {
|
||||||
|
|
||||||
@@ -63,7 +68,7 @@ public class TerritoryProtectionListener implements Listener {
|
|||||||
Guild playerGuild = guildManager.getGuildByPlayer(player.getUniqueId());
|
Guild playerGuild = guildManager.getGuildByPlayer(player.getUniqueId());
|
||||||
if (playerGuild == null || !playerGuild.getId().equals(guildAtBlock.getId())) {
|
if (playerGuild == null || !playerGuild.getId().equals(guildAtBlock.getId())) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
messageManager.sendActionBar(player, "protection.cannot_break", "{guild}", guildAtBlock.getName(), "{tag}", guildAtBlock.getTag());
|
messageManager.sendActionBar(player, "protection.cannot_break", "{guild}", guildAtBlock.getFormattedName(), "{tag}", guildAtBlock.getFormattedTag());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +100,7 @@ public class TerritoryProtectionListener implements Listener {
|
|||||||
Guild playerGuild = guildManager.getGuildByPlayer(player.getUniqueId());
|
Guild playerGuild = guildManager.getGuildByPlayer(player.getUniqueId());
|
||||||
if (playerGuild == null || !playerGuild.getId().equals(guildAtBlock.getId())) {
|
if (playerGuild == null || !playerGuild.getId().equals(guildAtBlock.getId())) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
messageManager.sendActionBar(player, "protection.cannot_build", "{guild}", guildAtBlock.getName(), "{tag}", guildAtBlock.getTag());
|
messageManager.sendActionBar(player, "protection.cannot_build", "{guild}", guildAtBlock.getFormattedName(), "{tag}", guildAtBlock.getFormattedTag());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +143,7 @@ public class TerritoryProtectionListener implements Listener {
|
|||||||
if (!isSameGuild) {
|
if (!isSameGuild) {
|
||||||
if (isContainer || isMechanism) {
|
if (isContainer || isMechanism) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
messageManager.sendActionBar(player, "protection.cannot_interact", "{guild}", guildAtBlock.getName(), "{tag}", guildAtBlock.getTag());
|
messageManager.sendActionBar(player, "protection.cannot_interact", "{guild}", guildAtBlock.getFormattedName(), "{tag}", guildAtBlock.getFormattedTag());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -153,6 +158,175 @@ public class TerritoryProtectionListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intercepte et bloque le PvP dans tous les claims de guilde.
|
||||||
|
*
|
||||||
|
* @param event L'événement EntityDamageByEntityEvent.
|
||||||
|
*/
|
||||||
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||||
|
public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
|
||||||
|
Entity victim = event.getEntity();
|
||||||
|
Entity attacker = event.getDamager();
|
||||||
|
|
||||||
|
Player attackerPlayer = null;
|
||||||
|
if (attacker instanceof Player p) {
|
||||||
|
attackerPlayer = p;
|
||||||
|
} else if (attacker instanceof Projectile proj && proj.getShooter() instanceof Player p) {
|
||||||
|
attackerPlayer = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si la victime est un joueur et qu'un joueur attaque
|
||||||
|
if (victim instanceof Player && attackerPlayer != null) {
|
||||||
|
if (attackerPlayer.hasPermission("guild.bypass")) return;
|
||||||
|
|
||||||
|
Location victimLoc = victim.getLocation();
|
||||||
|
Location attackerLoc = attackerPlayer.getLocation();
|
||||||
|
|
||||||
|
boolean victimInGuild = guildManager.isChunkClaimed(victimLoc.getWorld().getName(), victimLoc.getBlockX() >> 4, victimLoc.getBlockZ() >> 4);
|
||||||
|
boolean attackerInGuild = guildManager.isChunkClaimed(attackerLoc.getWorld().getName(), attackerLoc.getBlockX() >> 4, attackerLoc.getBlockZ() >> 4);
|
||||||
|
|
||||||
|
if (victimInGuild || attackerInGuild) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
messageManager.sendActionBar(attackerPlayer, "protection.pvp_denied");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Protéger les ArmorStands contre les dégâts des non-membres
|
||||||
|
if (victim instanceof ArmorStand && attackerPlayer != null) {
|
||||||
|
if (attackerPlayer.hasPermission("guild.bypass")) return;
|
||||||
|
|
||||||
|
Location loc = victim.getLocation();
|
||||||
|
Guild guildAtLoc = guildManager.getGuildAt(loc.getWorld().getName(), loc.getBlockX() >> 4, loc.getBlockZ() >> 4);
|
||||||
|
if (guildAtLoc != null) {
|
||||||
|
Guild playerGuild = guildManager.getGuildByPlayer(attackerPlayer.getUniqueId());
|
||||||
|
if (playerGuild == null || !playerGuild.getId().equals(guildAtLoc.getId()) || !guildAtLoc.hasPermission(attackerPlayer.getUniqueId(), GuildPermission.BREAK)) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
messageManager.sendActionBar(attackerPlayer, "protection.hanging_denied");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protège les cadres (ItemFrame) et tableaux (Painting) contre la casse par des non-membres.
|
||||||
|
*
|
||||||
|
* @param event L'événement HangingBreakByEntityEvent.
|
||||||
|
*/
|
||||||
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||||
|
public void onHangingBreak(HangingBreakByEntityEvent event) {
|
||||||
|
if (event.getRemover() instanceof Player player) {
|
||||||
|
if (player.hasPermission("guild.bypass")) return;
|
||||||
|
|
||||||
|
Hanging hanging = event.getEntity();
|
||||||
|
Location loc = hanging.getLocation();
|
||||||
|
Guild guildAtLoc = guildManager.getGuildAt(loc.getWorld().getName(), loc.getBlockX() >> 4, loc.getBlockZ() >> 4);
|
||||||
|
if (guildAtLoc != null) {
|
||||||
|
Guild playerGuild = guildManager.getGuildByPlayer(player.getUniqueId());
|
||||||
|
if (playerGuild == null || !playerGuild.getId().equals(guildAtLoc.getId()) || !guildAtLoc.hasPermission(player.getUniqueId(), GuildPermission.BREAK)) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
messageManager.sendActionBar(player, "protection.hanging_denied");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protège les interactions avec ArmorStands et cadres d'objets.
|
||||||
|
*
|
||||||
|
* @param event L'événement PlayerInteractEntityEvent.
|
||||||
|
*/
|
||||||
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||||
|
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
|
||||||
|
Entity target = event.getRightClicked();
|
||||||
|
if (target instanceof ArmorStand || target instanceof Hanging) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
if (player.hasPermission("guild.bypass")) return;
|
||||||
|
|
||||||
|
Location loc = target.getLocation();
|
||||||
|
Guild guildAtLoc = guildManager.getGuildAt(loc.getWorld().getName(), loc.getBlockX() >> 4, loc.getBlockZ() >> 4);
|
||||||
|
if (guildAtLoc != null) {
|
||||||
|
Guild playerGuild = guildManager.getGuildByPlayer(player.getUniqueId());
|
||||||
|
if (playerGuild == null || !playerGuild.getId().equals(guildAtLoc.getId()) || !guildAtLoc.hasPermission(player.getUniqueId(), GuildPermission.INTERACT)) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
messageManager.sendActionBar(player, "protection.hanging_denied");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empêche les pistons de pousser des blocs à travers les frontières d'un claim étranger.
|
||||||
|
*
|
||||||
|
* @param event L'événement BlockPistonExtendEvent.
|
||||||
|
*/
|
||||||
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||||
|
public void onPistonExtend(BlockPistonExtendEvent event) {
|
||||||
|
Block piston = event.getBlock();
|
||||||
|
String worldName = piston.getWorld().getName();
|
||||||
|
Guild guildPiston = guildManager.getGuildAt(worldName, piston.getX() >> 4, piston.getZ() >> 4);
|
||||||
|
|
||||||
|
for (Block block : event.getBlocks()) {
|
||||||
|
Block targetBlock = block.getRelative(event.getDirection());
|
||||||
|
Guild guildBlock = guildManager.getGuildAt(worldName, block.getX() >> 4, block.getZ() >> 4);
|
||||||
|
Guild guildTarget = guildManager.getGuildAt(worldName, targetBlock.getX() >> 4, targetBlock.getZ() >> 4);
|
||||||
|
|
||||||
|
// Si le piston ou les blocs déplacés traversent une frontière de guilde différente
|
||||||
|
if (!Objects.equals(guildPiston, guildBlock) || !Objects.equals(guildPiston, guildTarget)) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empêche les pistons collants de rétracter (tirer) des blocs depuis un claim étranger.
|
||||||
|
*
|
||||||
|
* @param event L'événement BlockPistonRetractEvent.
|
||||||
|
*/
|
||||||
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||||
|
public void onPistonRetract(BlockPistonRetractEvent event) {
|
||||||
|
Block piston = event.getBlock();
|
||||||
|
String worldName = piston.getWorld().getName();
|
||||||
|
Guild guildPiston = guildManager.getGuildAt(worldName, piston.getX() >> 4, piston.getZ() >> 4);
|
||||||
|
|
||||||
|
for (Block block : event.getBlocks()) {
|
||||||
|
Guild guildBlock = guildManager.getGuildAt(worldName, block.getX() >> 4, block.getZ() >> 4);
|
||||||
|
if (!Objects.equals(guildPiston, guildBlock)) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empêche l'écoulement des fluides (eau, lave) depuis l'extérieur vers un claim de guilde protégé.
|
||||||
|
*
|
||||||
|
* @param event L'événement BlockFromToEvent.
|
||||||
|
*/
|
||||||
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||||
|
public void onBlockFromTo(BlockFromToEvent event) {
|
||||||
|
Block from = event.getBlock();
|
||||||
|
Block to = event.getToBlock();
|
||||||
|
|
||||||
|
int fromChunkX = from.getX() >> 4;
|
||||||
|
int fromChunkZ = from.getZ() >> 4;
|
||||||
|
int toChunkX = to.getX() >> 4;
|
||||||
|
int toChunkZ = to.getZ() >> 4;
|
||||||
|
|
||||||
|
if (fromChunkX == toChunkX && fromChunkZ == toChunkZ) {
|
||||||
|
return; // Même chunk
|
||||||
|
}
|
||||||
|
|
||||||
|
String worldName = from.getWorld().getName();
|
||||||
|
Guild guildFrom = guildManager.getGuildAt(worldName, fromChunkX, fromChunkZ);
|
||||||
|
Guild guildTo = guildManager.getGuildAt(worldName, toChunkX, toChunkZ);
|
||||||
|
|
||||||
|
if (guildTo != null && !Objects.equals(guildFrom, guildTo)) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protège les blocs de guilde contre les explosions de créatures ou de TNT.
|
* Protège les blocs de guilde contre les explosions de créatures ou de TNT.
|
||||||
*
|
*
|
||||||
@@ -224,9 +398,9 @@ public class TerritoryProtectionListener implements Listener {
|
|||||||
Guild playerGuild = guildManager.getGuildByPlayer(player.getUniqueId());
|
Guild playerGuild = guildManager.getGuildByPlayer(player.getUniqueId());
|
||||||
boolean isOwn = playerGuild != null && playerGuild.getId().equals(currentGuild.getId());
|
boolean isOwn = playerGuild != null && playerGuild.getId().equals(currentGuild.getId());
|
||||||
if (isOwn) {
|
if (isOwn) {
|
||||||
messageManager.sendActionBar(player, "protection.territory_enter_own", "{guild}", currentGuild.getName(), "{tag}", currentGuild.getTag());
|
messageManager.sendActionBar(player, "protection.territory_enter_own", "{guild}", currentGuild.getFormattedName(), "{tag}", currentGuild.getFormattedTag());
|
||||||
} else {
|
} else {
|
||||||
messageManager.sendActionBar(player, "protection.territory_enter_other", "{guild}", currentGuild.getName(), "{tag}", currentGuild.getTag());
|
messageManager.sendActionBar(player, "protection.territory_enter_other", "{guild}", currentGuild.getFormattedName(), "{tag}", currentGuild.getFormattedTag());
|
||||||
}
|
}
|
||||||
} else if (previousGuild != null) {
|
} else if (previousGuild != null) {
|
||||||
messageManager.sendActionBar(player, "protection.territory_leave");
|
messageManager.sendActionBar(player, "protection.territory_leave");
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ public class WorldGuardManager {
|
|||||||
region.setFlag(Flags.PASSTHROUGH, StateFlag.State.DENY);
|
region.setFlag(Flags.PASSTHROUGH, StateFlag.State.DENY);
|
||||||
region.setFlag(Flags.TNT, StateFlag.State.DENY);
|
region.setFlag(Flags.TNT, StateFlag.State.DENY);
|
||||||
region.setFlag(Flags.CREEPER_EXPLOSION, StateFlag.State.DENY);
|
region.setFlag(Flags.CREEPER_EXPLOSION, StateFlag.State.DENY);
|
||||||
region.setFlag(Flags.PVP, StateFlag.State.ALLOW);
|
region.setFlag(Flags.PVP, StateFlag.State.DENY);
|
||||||
|
|
||||||
regionManager.addRegion(region);
|
regionManager.addRegion(region);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ general:
|
|||||||
no_permission: "<red>Vous n'avez pas la permission requise.</red>"
|
no_permission: "<red>Vous n'avez pas la permission requise.</red>"
|
||||||
player_not_found: "<red>Joueur introuvable ou hors ligne.</red>"
|
player_not_found: "<red>Joueur introuvable ou hors ligne.</red>"
|
||||||
reloaded: "<green>La configuration et les messages ont été rechargés avec succès !</green>"
|
reloaded: "<green>La configuration et les messages ont été rechargés avec succès !</green>"
|
||||||
|
invalid_page: "<red>Numéro de page invalide (1 à {max_page}).</red>"
|
||||||
|
|
||||||
|
help:
|
||||||
|
header: "<gradient:#00C9FF:#92FE9D><bold>=== SYSTÈME DE GUILDE (Aide {page}/{max_page}) ===</bold></gradient>"
|
||||||
|
footer: "<gray>Cliquez sur une commande pour la suggérer dans le chat.</gray>"
|
||||||
|
|
||||||
guild:
|
guild:
|
||||||
already_in_guild: "<red>Vous appartenez déjà à une guilde.</red>"
|
already_in_guild: "<red>Vous appartenez déjà à une guilde.</red>"
|
||||||
@@ -22,33 +27,35 @@ guild:
|
|||||||
creation:
|
creation:
|
||||||
insufficient_funds: "<red>Fonds insuffisants pour créer une guilde. Requis : <yellow>{cost}</yellow>.</red>"
|
insufficient_funds: "<red>Fonds insuffisants pour créer une guilde. Requis : <yellow>{cost}</yellow>.</red>"
|
||||||
chunk_already_claimed: "<red>Le chunk où vous vous trouvez est déjà revendiqué par une guilde.</red>"
|
chunk_already_claimed: "<red>Le chunk où vous vous trouvez est déjà revendiqué par une guilde.</red>"
|
||||||
confirm_prompt: "<gradient:#00C9FF:#92FE9D>[Guilde]</gradient> <yellow>Création de la guilde</yellow> <white><bold>{guild}</bold></white> <dark_gray>[{tag}]</dark_gray> :\n<gray>• Coût : <yellow>{cost}</yellow>\n• Territoire initial : <aqua>{world} ({chunk_x}, {chunk_z})</aqua>\n<gold>⚠ Exécutez à nouveau la commande pour confirmer la création !</gold>"
|
confirm_prompt: "<gradient:#00C9FF:#92FE9D>[Guilde]</gradient> <yellow>Création de la guilde</yellow> {guild} {tag} :\n<gray>• Coût : <yellow>{cost}</yellow>\n• Territoire initial : <aqua>{world} ({chunk_x}, {chunk_z})</aqua>\n<gold>⚠ Exécutez à nouveau la commande pour confirmer la création !</gold>"
|
||||||
success: "<green>Félicitations ! La guilde <white><bold>{guild}</bold></white> <dark_gray>[{tag}]</dark_gray> a été fondée !</green>\n<gray>• Coût prélevé : <yellow>{cost}</yellow>\n• Chunk initial revendiqué : <aqua>{world} [{chunk_x}, {chunk_z}]</aqua>\n• Point de ralliement (Home) défini à votre position.</gray>"
|
success: "<green>Félicitations ! La guilde {guild} {tag} a été fondée !</green>\n<gray>• Coût prélevé : <yellow>{cost}</yellow>\n• Chunk initial revendiqué : <aqua>{world} [{chunk_x}, {chunk_z}]</aqua>\n• Point de ralliement (Home) défini à votre position.</gray>"
|
||||||
|
|
||||||
disband:
|
disband:
|
||||||
not_leader: "<red>Seul le Chef de la guilde peut dissoudre la guilde.</red>"
|
not_leader: "<red>Seul le Chef de la guilde peut dissoudre la guilde.</red>"
|
||||||
confirm_prompt: "<red><bold>⚠ ATTENTION :</bold> Vous allez dissoudre définitivement la guilde <white>{guild}</white> et libérer tous ses territoires.\n<gold>Exécutez à nouveau <yellow>/guild disband</yellow> pour confirmer.</gold></red>"
|
confirm_prompt: "<red><bold>⚠ ATTENTION :</bold> Vous allez dissoudre définitivement la guilde {guild} et libérer tous ses territoires.\n<gold>Exécutez à nouveau <yellow>/guild disband</yellow> pour confirmer.</gold></red>"
|
||||||
success: "<yellow>La guilde <white><bold>{guild}</bold></white> a été dissoute avec succès.</yellow>"
|
success: "<yellow>La guilde {guild} a été dissoute avec succès.</yellow>"
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
leader_cannot_leave: "<red>En tant que Chef, vous ne pouvez pas quitter la guilde. Transférez le lead ou dissolvez la guilde.</red>"
|
leader_cannot_leave: "<red>En tant que Chef, vous ne pouvez pas quitter la guilde. Transférez le lead ou dissolvez la guilde.</red>"
|
||||||
success: "<yellow>Vous avez quitté la guilde <white>{guild}</white>.</yellow>"
|
success: "<yellow>Vous avez quitté la guilde {guild}.</yellow>"
|
||||||
|
|
||||||
kick:
|
kick:
|
||||||
cannot_kick_self: "<red>Vous ne pouvez pas vous expulser vous-même. Utilisez <yellow>/guild leave</yellow>.</red>"
|
cannot_kick_self: "<red>Vous ne pouvez pas vous expulser vous-même. Utilisez <yellow>/guild leave</yellow>.</red>"
|
||||||
insufficient_rank: "<red>Vous ne pouvez pas expulser un membre ayant un rang supérieur ou égal au vôtre.</red>"
|
insufficient_rank: "<red>Vous ne pouvez pas expulser un membre ayant un rang supérieur ou égal au vôtre.</red>"
|
||||||
no_permission: "<red>Votre rang ne vous autorise pas à expulser des membres.</red>"
|
no_permission: "<red>Votre rang ne vous autorise pas à expulser des membres.</red>"
|
||||||
success: "<yellow><white>{player}</white> a été expulsé de la guilde.</yellow>"
|
success: "<yellow><white>{player}</white> a été expulsé de la guilde.</yellow>"
|
||||||
target_notify: "<red>Vous avez été expulsé de la guilde <yellow>{guild}</yellow>.</red>"
|
target_notify: "<red>Vous avez été expulsé de la guilde {guild}.</red>"
|
||||||
|
|
||||||
invite:
|
invite:
|
||||||
no_permission: "<red>Votre rang ne vous autorise pas à envoyer des invitations.</red>"
|
no_permission: "<red>Votre rang ne vous autorise pas à envoyer des invitations.</red>"
|
||||||
cannot_invite_self: "<red>Vous ne pouvez pas vous inviter vous-même.</red>"
|
cannot_invite_self: "<red>Vous ne pouvez pas vous inviter vous-même.</red>"
|
||||||
target_already_in_guild: "<red><white>{player}</white> appartient déjà à une guilde.</red>"
|
target_already_in_guild: "<red><white>{player}</white> appartient déjà à une guilde.</red>"
|
||||||
sent: "<green>Invitation envoyée à <white>{player}</white> (Expire dans <yellow>{seconds}s</yellow>).</green>"
|
sent: "<green>Invitation envoyée à <white>{player}</white> (Expire dans <yellow>{seconds}s</yellow>).</green>"
|
||||||
received: "<gradient:#00C9FF:#92FE9D>[Guilde]</gradient> Vous avez été invité à rejoindre la guilde <white><bold>{guild}</bold></white> par <yellow>{sender}</yellow> !\n<gray>Tapez <yellow>/guild join {guild}</yellow> pour accepter.</gray>"
|
received_interactive: "<gradient:#00C9FF:#92FE9D>[Guilde]</gradient> Vous avez été invité à rejoindre la guilde {guild} {tag} par <yellow>{sender}</yellow> !\n<click:run_command:'/guild join {raw_guild}'><hover:show_text:'<green>Cliquez pour accepter l''invitation et rejoindre la guilde !</green>'><green><bold>[ ✅ ACCEPTER ]</bold></green></hover></click> <click:run_command:'/guild decline {raw_guild}'><hover:show_text:'<red>Cliquez pour refuser l''invitation.</red>'><red><bold>[ ❌ REFUSER ]</bold></red></hover></click>"
|
||||||
no_pending_invite: "<red>Vous n'avez aucune invitation valide en attente pour la guilde <yellow>{guild}</yellow>.</red>"
|
no_pending_invite: "<red>Vous n'avez aucune invitation valide en attente pour la guilde {guild}.</red>"
|
||||||
accepted: "<green>Le joueur <white>{player}</white> a rejoint la guilde !</green>"
|
accepted: "<green>Le joueur <white>{player}</white> a rejoint la guilde !</green>"
|
||||||
|
declined_sender: "<yellow><white>{player}</white> a refusé votre invitation.</yellow>"
|
||||||
|
declined_target: "<gray>Vous avez refusé l'invitation de la guilde {guild}.</gray>"
|
||||||
|
|
||||||
claim:
|
claim:
|
||||||
no_permission: "<red>Votre rang ne vous autorise pas à revendiquer des territoires.</red>"
|
no_permission: "<red>Votre rang ne vous autorise pas à revendiquer des territoires.</red>"
|
||||||
@@ -76,14 +83,24 @@ guild:
|
|||||||
not_set: "<red>Aucun home n'est défini pour votre guilde.</red>"
|
not_set: "<red>Aucun home n'est défini pour votre guilde.</red>"
|
||||||
teleport_success: "<green>Téléportation au point de ralliement de guilde réussie !</green>"
|
teleport_success: "<green>Téléportation au point de ralliement de guilde réussie !</green>"
|
||||||
|
|
||||||
|
list:
|
||||||
|
header: "<gradient:#00C9FF:#92FE9D><bold>=== LISTE DES GUILDES ({page}/{max_page}) ===</bold></gradient>"
|
||||||
|
item: "<dark_gray>#{index}</dark_gray> {guild} {tag} <dark_gray>»</dark_gray> <gray>Chef:</gray> <gold>{leader}</gold> <dark_gray>•</dark_gray> <gray>Membres:</gray> <yellow>{members}</yellow> <dark_gray>•</dark_gray> <gray>Claims:</gray> <aqua>{claims}</aqua>"
|
||||||
|
empty: "<gray>Aucune guilde n'a été créée pour le moment.</gray>"
|
||||||
|
pagination: "<click:run_command:'/guild list {prev_page}'><hover:show_text:'<yellow>Page précédente</yellow>'><aqua>[◀ Précédent]</aqua></hover></click> <dark_gray>---</dark_gray> <click:run_command:'/guild list {next_page}'><hover:show_text:'<yellow>Page suivante</yellow>'><aqua>[Suivant ▶]</aqua></hover></click>"
|
||||||
|
|
||||||
protection:
|
protection:
|
||||||
territory_enter_own: "<gray>Territoire de guilde : </gray><green><bold>{guild}</bold></green> <dark_gray>[{tag}]</dark_gray>"
|
territory_enter_own: "<gray>Territoire de guilde : </gray>{guild} {tag}"
|
||||||
territory_enter_other: "<gray>Territoire étranger : </gray><yellow><bold>{guild}</bold></yellow> <dark_gray>[{tag}]</dark_gray>"
|
territory_enter_other: "<gray>Territoire étranger : </gray>{guild} {tag}"
|
||||||
territory_leave: "<gray>Vous entrez en <green>Zone Libre</green> (Wilderness).</gray>"
|
territory_leave: "<gray>Vous entrez en <green>Zone Libre</green> (Wilderness).</gray>"
|
||||||
cannot_break: "<red>⛔ Ce territoire appartient à la guilde <yellow>{guild}</yellow> !</red>"
|
cannot_break: "<red>⛔ Ce territoire appartient à la guilde {guild} !</red>"
|
||||||
rank_cannot_break: "<red>Votre rang de guilde ne vous autorise pas à casser des blocs ici.</red>"
|
rank_cannot_break: "<red>Votre rang de guilde ne vous autorise pas à casser des blocs ici.</red>"
|
||||||
cannot_build: "<red>⛔ Ce territoire appartient à la guilde <yellow>{guild}</yellow> !</red>"
|
cannot_build: "<red>⛔ Ce territoire appartient à la guilde {guild} !</red>"
|
||||||
rank_cannot_build: "<red>Votre rang de guilde ne vous autorise pas à poser des blocs ici.</red>"
|
rank_cannot_build: "<red>Votre rang de guilde ne vous autorise pas à poser des blocs ici.</red>"
|
||||||
cannot_interact: "<red>⛔ Ce territoire appartient à la guilde <yellow>{guild}</yellow> !</red>"
|
cannot_interact: "<red>⛔ Ce territoire appartient à la guilde {guild} !</red>"
|
||||||
rank_cannot_container: "<red>Votre rang ne vous autorise pas à ouvrir les conteneurs de guilde.</red>"
|
rank_cannot_container: "<red>Votre rang ne vous autorise pas à ouvrir les conteneurs de guilde.</red>"
|
||||||
rank_cannot_interact: "<red>Votre rang ne vous autorise pas à utiliser ces mécanismes.</red>"
|
rank_cannot_interact: "<red>Votre rang ne vous autorise pas à utiliser ces mécanismes.</red>"
|
||||||
|
pvp_denied: "<red>⚔ Le combat entre joueurs (PvP) est strictement interdit sur les territoires de guilde.</red>"
|
||||||
|
piston_denied: "<red>⛔ Les pistons ne peuvent pas déplacer de blocs à travers les frontières d'un territoire de guilde.</red>"
|
||||||
|
fluid_denied: "<red>⛔ L'écoulement de fluides vers un territoire protégé est bloqué.</red>"
|
||||||
|
hanging_denied: "<red>⛔ Vous ne pouvez pas modifier ou casser les entités de décoration dans ce territoire.</red>"
|
||||||
|
|||||||
Reference in New Issue
Block a user