feat(guild): add custom HEX color & tag modification system with commands and formatting

This commit is contained in:
2026-08-20 18:14:38 +02:00
parent 62b239b9cd
commit a668fc1e2f
5 changed files with 220 additions and 16 deletions
@@ -62,6 +62,8 @@ public class GuildCommands {
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>");
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>");
context.reply("<yellow>/guild invite <joueur></yellow> <gray>- Inviter un joueur</gray>");
context.reply("<yellow>/guild join <guilde></yellow> <gray>- Rejoindre une guilde invitante</gray>");
context.reply("<yellow>/guild leave</yellow> <gray>- Quitter votre guilde</gray>");
@@ -486,7 +488,8 @@ public class GuildCommands {
String leaderName = leader != null && leader.getOfflinePlayer() != null ? leader.getOfflinePlayer().getName() : "Inconnu";
context.reply("<gradient:#00C9FF:#92FE9D><bold>=== INFORMATIONS DE GUILDE ===</bold></gradient>");
context.reply("<gray>Nom :</gray> <white><bold>" + targetGuild.getName() + "</bold></white> <dark_gray>[" + targetGuild.getTag() + "]</dark_gray>");
context.reply("<gray>Nom :</gray> " + targetGuild.getFormattedName() + " " + targetGuild.getFormattedTag());
context.reply("<gray>Couleur :</gray> <color:" + targetGuild.getColor() + ">" + targetGuild.getColor() + " ■</color>");
context.reply("<gray>Chef :</gray> <gold>" + leaderName + "</gold>");
context.reply("<gray>Membres :</gray> <yellow>" + targetGuild.getMemberCount() + "</yellow>");
context.reply("<gray>Banque :</gray> <green>" + guildManager.getEconomyManager().format(targetGuild.getBalance()) + "</green>");
@@ -494,6 +497,65 @@ public class GuildCommands {
})
)
// -------------------------------------------------------------
// Sous-commande : /guild color <#hex>
// -------------------------------------------------------------
.subcommand(BetterMcCommands.subBuilder("color")
.description("Changer la couleur hexadécimale de votre guilde")
.aliases("couleur")
.playerOnly()
.argument(Arguments.string("hex").description("Code couleur hexadécimal (ex: #FF5555)"))
.validate(context -> guildManager.isInGuild(context.getPlayer().getUniqueId()),
msg.get("guild.not_in_guild"))
.validate(context -> {
Guild g = guildManager.getGuildByPlayer(context.getPlayer().getUniqueId());
return g != null && g.hasPermission(context.getPlayer().getUniqueId(), GuildPermission.MANAGE_GUILD);
}, "<red>Votre rang ne vous autorise pas à modifier les informations de la guilde.</red>")
.validate(context -> context.getString("hex").matches("^#[0-9a-fA-F]{6}$"),
"<red>Format de couleur invalide ! Utilisez un code hexadécimal à 6 caractères (ex: <yellow>#00FFAA</yellow> ou <yellow>#FF5555</yellow>).</red>")
.executes(context -> {
Player player = context.getPlayer();
Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
String hex = context.getString("hex");
GuildResult result = guildManager.setGuildColor(player, guild, hex);
if (result.isSuccess()) {
context.replySuccess(result.getMessage());
} else {
context.replyError(result.getMessage());
}
})
)
// -------------------------------------------------------------
// Sous-commande : /guild tag <nouveau_tag>
// -------------------------------------------------------------
.subcommand(BetterMcCommands.subBuilder("tag")
.description("Changer le tag court de votre guilde")
.playerOnly()
.argument(Arguments.string("tag").description("Nouveau tag (2-6 car)"))
.validate(context -> guildManager.isInGuild(context.getPlayer().getUniqueId()),
msg.get("guild.not_in_guild"))
.validate(context -> {
Guild g = guildManager.getGuildByPlayer(context.getPlayer().getUniqueId());
return g != null && g.hasPermission(context.getPlayer().getUniqueId(), GuildPermission.MANAGE_GUILD);
}, "<red>Votre rang ne vous autorise pas à modifier les informations de la guilde.</red>")
.validate(context -> context.getString("tag").matches("^[a-zA-Z0-9_]{2,6}$"),
"<red>Le tag doit comporter entre 2 et 6 caractères alphanumériques.</red>")
.executes(context -> {
Player player = context.getPlayer();
Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
String newTag = context.getString("tag");
GuildResult result = guildManager.setGuildTag(player, guild, newTag);
if (result.isSuccess()) {
context.replySuccess(result.getMessage());
} else {
context.replyError(result.getMessage());
}
})
)
// -------------------------------------------------------------
// Sous-commande : /guild members [guilde]
// -------------------------------------------------------------
@@ -88,6 +88,7 @@ public class DatabaseManager {
"id VARCHAR(36) PRIMARY KEY, " +
"name VARCHAR(16) NOT NULL UNIQUE, " +
"tag VARCHAR(6), " +
"color VARCHAR(7) NOT NULL DEFAULT '#00C9FF', " +
"description VARCHAR(128), " +
"balance DOUBLE NOT NULL DEFAULT 0.0, " +
"home_world VARCHAR(64), " +
@@ -99,6 +100,13 @@ public class DatabaseManager {
"created_at BIGINT NOT NULL" +
");");
// Migration : ajout de la colonne color si elle n'existe pas
try {
stmt.executeUpdate("ALTER TABLE guilds ADD COLUMN color VARCHAR(7) DEFAULT '#00C9FF'");
} catch (SQLException ignored) {
// La colonne existe déjà
}
// Table des rangs de guilde
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS guild_ranks (" +
"id VARCHAR(64) NOT NULL, " +
@@ -45,11 +45,16 @@ public class GuildRepository {
UUID id = UUID.fromString(rs.getString("id"));
String name = rs.getString("name");
String tag = rs.getString("tag");
String color = "#00C9FF";
try {
color = rs.getString("color");
if (color == null || color.isEmpty()) color = "#00C9FF";
} catch (SQLException ignored) {}
String description = rs.getString("description");
double balance = rs.getDouble("balance");
long createdAt = rs.getLong("created_at");
Guild guild = new Guild(id, name, tag, description, balance, createdAt);
Guild guild = new Guild(id, name, tag, color, description, balance, createdAt);
String homeWorld = rs.getString("home_world");
if (homeWorld != null && !homeWorld.isEmpty()) {
@@ -165,21 +170,22 @@ public class GuildRepository {
* @throws SQLException En cas d'échec SQL.
*/
public void saveGuild(Guild guild) throws SQLException {
String sql = "INSERT OR REPLACE INTO guilds (id, name, tag, description, balance, home_world, home_x, home_y, home_z, home_yaw, home_pitch, created_at) " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
String sql = "INSERT OR REPLACE INTO guilds (id, name, tag, color, description, balance, home_world, home_x, home_y, home_z, home_yaw, home_pitch, created_at) " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
try (PreparedStatement ps = databaseManager.getConnection().prepareStatement(sql)) {
ps.setString(1, guild.getId().toString());
ps.setString(2, guild.getName());
ps.setString(3, guild.getTag());
ps.setString(4, guild.getDescription());
ps.setDouble(5, guild.getBalance());
ps.setString(6, guild.getHomeWorld());
ps.setDouble(7, guild.getHomeX());
ps.setDouble(8, guild.getHomeY());
ps.setDouble(9, guild.getHomeZ());
ps.setFloat(10, guild.getHomeYaw());
ps.setFloat(11, guild.getHomePitch());
ps.setLong(12, guild.getCreatedAt());
ps.setString(4, guild.getColor());
ps.setString(5, guild.getDescription());
ps.setDouble(6, guild.getBalance());
ps.setString(7, guild.getHomeWorld());
ps.setDouble(8, guild.getHomeX());
ps.setDouble(9, guild.getHomeY());
ps.setDouble(10, guild.getHomeZ());
ps.setFloat(11, guild.getHomeYaw());
ps.setFloat(12, guild.getHomePitch());
ps.setLong(13, guild.getCreatedAt());
ps.executeUpdate();
}
}
@@ -90,6 +90,20 @@ public class GuildManager {
* @return GuildResult indiquant le succès ou la raison de l'échec.
*/
public GuildResult createGuild(Player creator, String name, String tag, double creationCost) {
return createGuild(creator, name, tag, "#00C9FF", creationCost);
}
/**
* Crée une nouvelle guilde pour un joueur avec prélèvement financier, couleur personnalisée et claim initial.
*
* @param creator Le joueur fondateur.
* @param name Nom de la guilde (3 à 16 caractères alphanumériques).
* @param tag Tag court optionnel (ex: "LEG").
* @param color Couleur hexadécimale (ex: "#00C9FF").
* @param creationCost Coût financier requis pour la création.
* @return GuildResult indiquant le succès ou la raison de l'échec.
*/
public GuildResult createGuild(Player creator, String name, String tag, String color, double creationCost) {
if (creator == null) {
return GuildResult.failure("Joueur invalide.");
}
@@ -133,7 +147,7 @@ public class GuildManager {
// 6. Instancier la nouvelle guilde
UUID guildId = UUID.randomUUID();
Guild guild = new Guild(guildId, name, tag, "Guilde fondée par " + creator.getName(), 0.0, System.currentTimeMillis());
Guild guild = new Guild(guildId, name, tag, color, "Guilde fondée par " + creator.getName(), 0.0, System.currentTimeMillis());
// 7. Configurer les rangs par défaut
GuildRank leaderRank = new GuildRank("leader", guildId, "Chef", 100, false, EnumSet.allOf(GuildPermission.class));
@@ -359,6 +373,64 @@ public class GuildManager {
return GuildResult.success("Le rang du membre a été mis à jour vers <white>" + newRank.getName() + "</white>.");
}
// ==========================================
// PERSONNALISATION (COULEUR & TAG)
// ==========================================
/**
* Modifie la couleur hexadécimale de la guilde.
*
* @param actor Le joueur initiateur de la commande.
* @param guild La guilde concernée.
* @param hexColor Le code couleur hexadécimal (ex: "#FF5555").
* @return GuildResult.
*/
public GuildResult setGuildColor(Player actor, Guild guild, String hexColor) {
if (actor == null || guild == null || hexColor == null) {
return GuildResult.failure("Paramètres invalides.");
}
if (!guild.hasPermission(actor.getUniqueId(), GuildPermission.MANAGE_GUILD)) {
return GuildResult.failure("Votre rang ne vous autorise pas à modifier les paramètres de la guilde.");
}
if (!hexColor.matches("^#[0-9a-fA-F]{6}$")) {
return GuildResult.failure("Format de couleur invalide. Utilisez un code hexadécimal valide à 6 caractères (ex: #00FFAA ou #FF5555).");
}
guild.setColor(hexColor);
repository.saveGuildAsync(guild);
return GuildResult.success("La couleur de la guilde a été changée pour <color:" + hexColor + ">" + hexColor + "</color> !");
}
/**
* Modifie le tag court de la guilde.
*
* @param actor Le joueur initiateur.
* @param guild La guilde concernée.
* @param newTag Le nouveau tag (2 à 6 caractères alphanumériques).
* @return GuildResult.
*/
public GuildResult setGuildTag(Player actor, Guild guild, String newTag) {
if (actor == null || guild == null || newTag == null) {
return GuildResult.failure("Paramètres invalides.");
}
if (!guild.hasPermission(actor.getUniqueId(), GuildPermission.MANAGE_GUILD)) {
return GuildResult.failure("Votre rang ne vous autorise pas à modifier les paramètres de la guilde.");
}
if (!newTag.matches("^[a-zA-Z0-9_]{2,6}$")) {
return GuildResult.failure("Le tag doit comporter entre 2 et 6 caractères alphanumériques.");
}
guild.setTag(newTag.toUpperCase());
repository.saveGuildAsync(guild);
return GuildResult.success("Le tag de la guilde a été changé pour " + guild.getFormattedTag() + " !");
}
// ==========================================
// GESTION DES CLAIMS (TERRITOIRES)
// ==========================================
@@ -17,6 +17,7 @@ public class Guild {
private final UUID id;
private String name;
private String tag;
private String color;
private String description;
private double balance;
@@ -36,24 +37,40 @@ public class Guild {
private final List<GuildClaim> claims = new CopyOnWriteArrayList<>();
/**
* Constructeur complet d'une guilde.
* Constructeur complet d'une guilde avec couleur personnalisée.
*
* @param id Identifiant unique UUID de la guilde.
* @param name Nom de la guilde (ex: "Imperium").
* @param tag Tag/Sigle court de la guilde (ex: "IMP").
* @param color Couleur principale en code hexadécimal (ex: "#00C9FF").
* @param description Description textuelle de la guilde.
* @param balance Solde bancaire initial de la guilde.
* @param createdAt Date et heure de création en millisecondes.
*/
public Guild(UUID id, String name, String tag, String description, double balance, long createdAt) {
public Guild(UUID id, String name, String tag, String color, String description, double balance, long createdAt) {
this.id = Objects.requireNonNull(id, "L'UUID de la guilde ne peut pas être nul.");
this.name = Objects.requireNonNull(name, "Le nom de la guilde ne peut pas être nul.");
this.tag = tag != null ? tag : "";
this.color = color != null && color.startsWith("#") ? color : "#00C9FF";
this.description = description != null ? description : "Une nouvelle guilde prometteuse.";
this.balance = Math.max(0.0, balance);
this.createdAt = createdAt > 0 ? createdAt : System.currentTimeMillis();
}
/**
* Constructeur surchargé utilisant la couleur par défaut.
*
* @param id Identifiant unique UUID de la guilde.
* @param name Nom de la guilde.
* @param tag Tag court.
* @param description Description.
* @param balance Solde bancaire.
* @param createdAt Timestamp de création.
*/
public Guild(UUID id, String name, String tag, String description, double balance, long createdAt) {
this(id, name, tag, "#00C9FF", description, balance, createdAt);
}
/**
* Obtient l'identifiant unique UUID de la guilde.
*
@@ -99,6 +116,45 @@ public class Guild {
this.tag = tag != null ? tag : "";
}
/**
* Obtient la couleur hexadécimale de la guilde (ex: "#00C9FF").
*
* @return Le code couleur HEX.
*/
public String getColor() {
return color != null ? color : "#00C9FF";
}
/**
* Modifie la couleur hexadécimale de la guilde.
*
* @param color Le code couleur hexadécimal (ex: "#FF5555").
*/
public void setColor(String color) {
if (color != null && color.startsWith("#")) {
this.color = color.toUpperCase();
}
}
/**
* Obtient le tag formaté avec la couleur hexadécimale de la guilde (MiniMessage).
*
* @return Le tag stylisé (ex: "<color:#00C9FF>[IMP]</color>").
*/
public String getFormattedTag() {
if (tag == null || tag.isEmpty()) return "";
return "<color:" + getColor() + ">[" + tag + "]</color>";
}
/**
* Obtient le nom formaté en gras avec la couleur hexadécimale de la guilde.
*
* @return Le nom stylisé.
*/
public String getFormattedName() {
return "<color:" + getColor() + "><bold>" + name + "</bold></color>";
}
/**
* Obtient la description textuelle de la guilde.
*