feat(worldguard): integrate WorldGuard 7 cuboid claims with automatic member synchronization
This commit is contained in:
@@ -31,6 +31,7 @@ public final class Main extends JavaPlugin {
|
||||
private DatabaseManager databaseManager;
|
||||
private GuildRepository guildRepository;
|
||||
private EconomyManager economyManager;
|
||||
private fr.luc.gamingcore.worldguard.WorldGuardManager worldGuardManager;
|
||||
private GuildManager guildManager;
|
||||
private BetterMcCommands betterMcCommands;
|
||||
|
||||
@@ -50,24 +51,27 @@ public final class Main extends JavaPlugin {
|
||||
setupWorldGuard();
|
||||
setupEconomy();
|
||||
|
||||
// 3. Initialiser la couche de données SQLite
|
||||
// 3. Initialiser le gestionnaire WorldGuard
|
||||
this.worldGuardManager = new fr.luc.gamingcore.worldguard.WorldGuardManager(this);
|
||||
|
||||
// 4. Initialiser la couche de données SQLite
|
||||
this.databaseManager = new DatabaseManager(this);
|
||||
this.databaseManager.initialize();
|
||||
this.guildRepository = new GuildRepository(this, databaseManager);
|
||||
|
||||
// 4. Initialiser la couche économique
|
||||
// 5. Initialiser la couche économique
|
||||
this.economyManager = new EconomyManager(this);
|
||||
|
||||
// 5. Initialiser le service métier GuildManager et charger les données
|
||||
this.guildManager = new GuildManager(this, guildRepository, economyManager);
|
||||
// 6. Initialiser le service métier GuildManager et charger les données
|
||||
this.guildManager = new GuildManager(this, guildRepository, economyManager, worldGuardManager);
|
||||
loadConfigSettings();
|
||||
this.guildManager.loadData();
|
||||
|
||||
// 6. Initialiser le framework betterMcCommands et enregistrer les commandes
|
||||
// 7. Initialiser le framework betterMcCommands et enregistrer les commandes
|
||||
this.betterMcCommands = BetterMcCommands.create(this);
|
||||
new GuildCommands(this, guildManager).register();
|
||||
|
||||
// 7. Enregistrer les écouteurs d'événements
|
||||
// 8. Enregistrer les écouteurs d'événements
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
pm.registerEvents(new TerritoryProtectionListener(this), this);
|
||||
|
||||
@@ -216,6 +220,15 @@ public final class Main extends JavaPlugin {
|
||||
return databaseManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtient le gestionnaire WorldGuard.
|
||||
*
|
||||
* @return L'instance WorldGuardManager.
|
||||
*/
|
||||
public fr.luc.gamingcore.worldguard.WorldGuardManager getWorldGuardManager() {
|
||||
return worldGuardManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtient le référentiel de persistance des guildes.
|
||||
*
|
||||
|
||||
@@ -24,6 +24,7 @@ public class GuildManager {
|
||||
private final Main plugin;
|
||||
private final GuildRepository repository;
|
||||
private final EconomyManager economyManager;
|
||||
private final fr.luc.gamingcore.worldguard.WorldGuardManager worldGuardManager;
|
||||
private final ChunkPriceCalculator priceCalculator;
|
||||
private final InviteManager inviteManager;
|
||||
|
||||
@@ -34,22 +35,35 @@ public class GuildManager {
|
||||
private final Map<String, UUID> chunkGuildMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Constructeur du GuildManager.
|
||||
* Constructeur complet du GuildManager avec WorldGuardManager.
|
||||
*
|
||||
* @param plugin Instance du plugin principal.
|
||||
* @param repository Référentiel de persistance des données.
|
||||
* @param economyManager Gestionnaire de l'économie Vault.
|
||||
* @param worldGuardManager Gestionnaire des régions WorldGuard.
|
||||
*/
|
||||
public GuildManager(Main plugin, GuildRepository repository, EconomyManager economyManager, fr.luc.gamingcore.worldguard.WorldGuardManager worldGuardManager) {
|
||||
this.plugin = plugin;
|
||||
this.repository = repository;
|
||||
this.economyManager = economyManager;
|
||||
this.worldGuardManager = worldGuardManager;
|
||||
this.priceCalculator = new ChunkPriceCalculator();
|
||||
this.inviteManager = new InviteManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur de compatibilité du GuildManager.
|
||||
*
|
||||
* @param plugin Instance du plugin principal.
|
||||
* @param repository Référentiel de persistance des données.
|
||||
* @param economyManager Gestionnaire de l'économie Vault.
|
||||
*/
|
||||
public GuildManager(Main plugin, GuildRepository repository, EconomyManager economyManager) {
|
||||
this.plugin = plugin;
|
||||
this.repository = repository;
|
||||
this.economyManager = economyManager;
|
||||
this.priceCalculator = new ChunkPriceCalculator();
|
||||
this.inviteManager = new InviteManager();
|
||||
this(plugin, repository, economyManager, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Charge l'ensemble des données de la base en mémoire et reconstruit les index de recherche.
|
||||
* Charge l'ensemble des données de la base en mémoire et reconstruit les index de recherche et régions WorldGuard.
|
||||
*/
|
||||
public void loadData() {
|
||||
guildsById.clear();
|
||||
@@ -62,6 +76,10 @@ public class GuildManager {
|
||||
indexGuild(guild);
|
||||
}
|
||||
|
||||
if (worldGuardManager != null) {
|
||||
worldGuardManager.syncAllGuilds(guildsById.values());
|
||||
}
|
||||
|
||||
plugin.getLogger().info("Charges " + guildsById.size() + " guildes (" + playerGuildMap.size() + " membres, " + chunkGuildMap.size() + " claims).");
|
||||
}
|
||||
|
||||
@@ -183,6 +201,11 @@ public class GuildManager {
|
||||
repository.saveMemberAsync(founder);
|
||||
repository.saveClaimAsync(initialClaim);
|
||||
|
||||
// 11. Créer la région WorldGuard
|
||||
if (worldGuardManager != null) {
|
||||
worldGuardManager.createOrUpdateRegion(guild, loc.getWorld(), chunkX, chunkZ);
|
||||
}
|
||||
|
||||
return GuildResult.success("La guilde <white><bold>" + name + "</bold></white> a été créée avec succès !");
|
||||
}
|
||||
|
||||
@@ -210,6 +233,11 @@ public class GuildManager {
|
||||
return GuildResult.failure("Seul le Chef de la guilde peut dissoudre la guilde.");
|
||||
}
|
||||
|
||||
// Supprimer toutes les régions WorldGuard associées
|
||||
if (worldGuardManager != null) {
|
||||
worldGuardManager.removeGuildRegions(guild);
|
||||
}
|
||||
|
||||
// Désindexer la guilde
|
||||
unindexGuild(guild);
|
||||
|
||||
@@ -249,6 +277,11 @@ public class GuildManager {
|
||||
playerGuildMap.put(player.getUniqueId(), guild.getId());
|
||||
repository.saveMemberAsync(member);
|
||||
|
||||
// Synchroniser WorldGuard
|
||||
if (worldGuardManager != null) {
|
||||
worldGuardManager.syncGuildMembers(guild);
|
||||
}
|
||||
|
||||
return GuildResult.success("Le joueur <white>" + player.getName() + "</white> a rejoint la guilde !");
|
||||
}
|
||||
|
||||
@@ -288,6 +321,11 @@ public class GuildManager {
|
||||
playerGuildMap.remove(targetUuid);
|
||||
repository.deleteMemberAsync(targetUuid);
|
||||
|
||||
// Synchroniser WorldGuard
|
||||
if (worldGuardManager != null) {
|
||||
worldGuardManager.syncGuildMembers(guild);
|
||||
}
|
||||
|
||||
return GuildResult.success("Le membre a été expulsé de la guilde.");
|
||||
}
|
||||
|
||||
@@ -317,6 +355,11 @@ public class GuildManager {
|
||||
playerGuildMap.remove(player.getUniqueId());
|
||||
repository.deleteMemberAsync(player.getUniqueId());
|
||||
|
||||
// Synchroniser WorldGuard
|
||||
if (worldGuardManager != null) {
|
||||
worldGuardManager.syncGuildMembers(guild);
|
||||
}
|
||||
|
||||
return GuildResult.success("Vous avez quitté la guilde.");
|
||||
}
|
||||
|
||||
@@ -370,6 +413,11 @@ public class GuildManager {
|
||||
targetMember.setRankId(newRank.getId());
|
||||
repository.saveMemberAsync(targetMember);
|
||||
|
||||
// Synchroniser WorldGuard (au cas où le chef a changé)
|
||||
if (worldGuardManager != null) {
|
||||
worldGuardManager.syncGuildMembers(guild);
|
||||
}
|
||||
|
||||
return GuildResult.success("Le rang du membre a été mis à jour vers <white>" + newRank.getName() + "</white>.");
|
||||
}
|
||||
|
||||
@@ -480,6 +528,11 @@ public class GuildManager {
|
||||
repository.saveGuildAsync(guild);
|
||||
repository.saveClaimAsync(claim);
|
||||
|
||||
// 7. Créer la région WorldGuard
|
||||
if (worldGuardManager != null) {
|
||||
worldGuardManager.createOrUpdateRegion(guild, world, chunkX, chunkZ);
|
||||
}
|
||||
|
||||
return GuildResult.success("Chunk revendiqué avec succès pour <yellow>" + economyManager.format(price) + "</yellow> ! (Total: " + guild.getClaimCount() + " chunks)");
|
||||
}
|
||||
|
||||
@@ -515,7 +568,12 @@ public class GuildManager {
|
||||
return GuildResult.failure("Vous ne pouvez pas abandonner le dernier chunk de votre guilde.");
|
||||
}
|
||||
|
||||
// 4. Supprimer le claim
|
||||
// 4. Supprimer la région WorldGuard
|
||||
if (worldGuardManager != null) {
|
||||
worldGuardManager.removeRegion(guild, world, chunkX, chunkZ);
|
||||
}
|
||||
|
||||
// 5. Supprimer le claim
|
||||
guild.removeClaim(worldName, chunkX, chunkZ);
|
||||
chunkGuildMap.remove(getChunkKey(worldName, chunkX, chunkZ));
|
||||
repository.deleteClaimAsync(worldName, chunkX, chunkZ);
|
||||
@@ -646,6 +704,10 @@ public class GuildManager {
|
||||
return inviteManager;
|
||||
}
|
||||
|
||||
public fr.luc.gamingcore.worldguard.WorldGuardManager getWorldGuardManager() {
|
||||
return worldGuardManager;
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// MÉTHODES INTERNES D'INDEXATION
|
||||
// ==========================================
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
package fr.luc.gamingcore.worldguard;
|
||||
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldguard.WorldGuard;
|
||||
import com.sk89q.worldguard.protection.flags.Flags;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import com.sk89q.worldguard.protection.regions.RegionContainer;
|
||||
import fr.luc.gamingcore.Main;
|
||||
import fr.luc.gamingcore.model.Guild;
|
||||
import fr.luc.gamingcore.model.GuildClaim;
|
||||
import fr.luc.gamingcore.model.GuildMember;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* Service d'intégration avec WorldGuard 7 pour la création, la protection et la synchronisation des régions de claim.
|
||||
*/
|
||||
public class WorldGuardManager {
|
||||
|
||||
private final Main plugin;
|
||||
private final RegionContainer regionContainer;
|
||||
private final boolean enabled;
|
||||
|
||||
/**
|
||||
* Constructeur du WorldGuardManager.
|
||||
*
|
||||
* @param plugin L'instance principale de GamingCore.
|
||||
*/
|
||||
public WorldGuardManager(Main plugin) {
|
||||
this.plugin = Objects.requireNonNull(plugin, "plugin cannot be null");
|
||||
RegionContainer container = null;
|
||||
boolean isEnabled = false;
|
||||
|
||||
try {
|
||||
if (Bukkit.getPluginManager().getPlugin("WorldGuard") != null) {
|
||||
container = WorldGuard.getInstance().getPlatform().getRegionContainer();
|
||||
isEnabled = (container != null);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
plugin.getLogger().log(Level.WARNING, "Erreur lors de l'initialisation de WorldGuardManager : " + t.getMessage());
|
||||
}
|
||||
|
||||
this.regionContainer = container;
|
||||
this.enabled = isEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indique si l'intégration WorldGuard est active.
|
||||
*
|
||||
* @return true si WorldGuard est chargé et fonctionnel.
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return enabled && regionContainer != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Génère l'identifiant unique WorldGuard d'une région de claim pour un chunk donné.
|
||||
*
|
||||
* @param guild La guilde propriétaire.
|
||||
* @param chunkX Coordonnée X du chunk.
|
||||
* @param chunkZ Coordonnée Z du chunk.
|
||||
* @return L'identifiant normalisé de la région (ex: "guild_a1b2c3d4_12_-4").
|
||||
*/
|
||||
public String getRegionId(Guild guild, int chunkX, int chunkZ) {
|
||||
String cleanId = guild.getId().toString().replace("-", "").substring(0, 12);
|
||||
return "guild_" + cleanId + "_" + chunkX + "_" + chunkZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtient le gestionnaire de régions WorldGuard pour un monde Bukkit donné.
|
||||
*
|
||||
* @param world Le monde Bukkit.
|
||||
* @return L'instance RegionManager ou null si indisponible.
|
||||
*/
|
||||
public RegionManager getRegionManager(World world) {
|
||||
if (!isEnabled() || world == null) return null;
|
||||
return regionContainer.get(BukkitAdapter.adapt(world));
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée ou met à jour la région WorldGuard associée à un claim territorial de guilde.
|
||||
* Les membres de la guilde sont enregistrés en tant que membres de la région (permettant la pose/casse de blocs et l'ouverture de coffres).
|
||||
*
|
||||
* @param guild La guilde propriétaire.
|
||||
* @param world Le monde Bukkit dans lequel se situe le claim.
|
||||
* @param chunkX Coordonnée X du chunk.
|
||||
* @param chunkZ Coordonnée Z du chunk.
|
||||
* @return La région protégée créée ou mise à jour, ou null en cas d'échec.
|
||||
*/
|
||||
public ProtectedRegion createOrUpdateRegion(Guild guild, World world, int chunkX, int chunkZ) {
|
||||
if (!isEnabled() || guild == null || world == null) return null;
|
||||
|
||||
RegionManager regionManager = getRegionManager(world);
|
||||
if (regionManager == null) return null;
|
||||
|
||||
String regionId = getRegionId(guild, chunkX, chunkZ);
|
||||
ProtectedRegion region = regionManager.getRegion(regionId);
|
||||
|
||||
int minX = chunkX * 16;
|
||||
int minZ = chunkZ * 16;
|
||||
int maxX = minX + 15;
|
||||
int maxZ = minZ + 15;
|
||||
int minY = world.getMinHeight();
|
||||
int maxY = world.getMaxHeight() - 1;
|
||||
|
||||
BlockVector3 min = BlockVector3.at(minX, minY, minZ);
|
||||
BlockVector3 max = BlockVector3.at(maxX, maxY, maxZ);
|
||||
|
||||
if (region == null) {
|
||||
region = new ProtectedCuboidRegion(regionId, min, max);
|
||||
region.setPriority(plugin.getConfig().getInt("worldguard.region_priority", 10));
|
||||
|
||||
// Flags WorldGuard
|
||||
region.setFlag(Flags.PASSTHROUGH, StateFlag.State.DENY);
|
||||
region.setFlag(Flags.TNT, StateFlag.State.DENY);
|
||||
region.setFlag(Flags.CREEPER_EXPLOSION, StateFlag.State.DENY);
|
||||
region.setFlag(Flags.PVP, StateFlag.State.ALLOW);
|
||||
|
||||
regionManager.addRegion(region);
|
||||
}
|
||||
|
||||
// Synchroniser les membres et propriétaires
|
||||
syncRegionMembers(guild, region);
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime la région WorldGuard correspondant à un chunk précis.
|
||||
*
|
||||
* @param guild La guilde propriétaire.
|
||||
* @param world Le monde du chunk.
|
||||
* @param chunkX Coordonnée X.
|
||||
* @param chunkZ Coordonnée Z.
|
||||
* @return true si la région a été supprimée.
|
||||
*/
|
||||
public boolean removeRegion(Guild guild, World world, int chunkX, int chunkZ) {
|
||||
if (!isEnabled() || guild == null || world == null) return false;
|
||||
|
||||
RegionManager regionManager = getRegionManager(world);
|
||||
if (regionManager == null) return false;
|
||||
|
||||
String regionId = getRegionId(guild, chunkX, chunkZ);
|
||||
return regionManager.removeRegion(regionId) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime toutes les régions WorldGuard appartenant à une guilde dans tous les mondes (utilisé lors du disband).
|
||||
*
|
||||
* @param guild La guilde dissoute.
|
||||
*/
|
||||
public void removeGuildRegions(Guild guild) {
|
||||
if (!isEnabled() || guild == null) return;
|
||||
|
||||
for (GuildClaim claim : guild.getClaims()) {
|
||||
World world = Bukkit.getWorld(claim.getWorldName());
|
||||
if (world != null) {
|
||||
removeRegion(guild, world, claim.getChunkX(), claim.getChunkZ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronise la liste des membres et propriétaires sur toutes les régions WorldGuard d'une guilde.
|
||||
* Doit être appelée à chaque ajout, retrait ou modification de membre.
|
||||
*
|
||||
* @param guild La guilde à synchroniser.
|
||||
*/
|
||||
public void syncGuildMembers(Guild guild) {
|
||||
if (!isEnabled() || guild == null) return;
|
||||
|
||||
for (GuildClaim claim : guild.getClaims()) {
|
||||
World world = Bukkit.getWorld(claim.getWorldName());
|
||||
if (world == null) continue;
|
||||
|
||||
RegionManager regionManager = getRegionManager(world);
|
||||
if (regionManager == null) continue;
|
||||
|
||||
String regionId = getRegionId(guild, claim.getChunkX(), claim.getChunkZ());
|
||||
ProtectedRegion region = regionManager.getRegion(regionId);
|
||||
|
||||
if (region == null) {
|
||||
// Si la région n'existe pas encore, la créer
|
||||
createOrUpdateRegion(guild, world, claim.getChunkX(), claim.getChunkZ());
|
||||
} else {
|
||||
syncRegionMembers(guild, region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronise tous les claims et membres de l'intégralité des guildes dans WorldGuard au démarrage du serveur.
|
||||
*
|
||||
* @param guilds Collection des guildes chargées en mémoire.
|
||||
*/
|
||||
public void syncAllGuilds(Collection<Guild> guilds) {
|
||||
if (!isEnabled() || guilds == null) return;
|
||||
|
||||
int totalRegions = 0;
|
||||
for (Guild guild : guilds) {
|
||||
for (GuildClaim claim : guild.getClaims()) {
|
||||
World world = Bukkit.getWorld(claim.getWorldName());
|
||||
if (world != null) {
|
||||
createOrUpdateRegion(guild, world, claim.getChunkX(), claim.getChunkZ());
|
||||
totalRegions++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getLogger().info("WorldGuard: Synchronisation de " + totalRegions + " regions territoriales de guilde terminee avec succes !");
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour les domaines de membres et d'owners d'une région WorldGuard à partir de la guilde.
|
||||
*
|
||||
* @param guild La guilde source.
|
||||
* @param region La région WorldGuard cible.
|
||||
*/
|
||||
private void syncRegionMembers(Guild guild, ProtectedRegion region) {
|
||||
// 1. Mise à jour des propriétaires (Chef de guilde)
|
||||
region.getOwners().clear();
|
||||
GuildMember leader = guild.getLeaderMember();
|
||||
if (leader != null) {
|
||||
region.getOwners().addPlayer(leader.getPlayerUuid());
|
||||
}
|
||||
|
||||
// 2. Mise à jour des membres (Tous les membres de la guilde)
|
||||
region.getMembers().clear();
|
||||
for (GuildMember member : guild.getMembers()) {
|
||||
region.getMembers().addPlayer(member.getPlayerUuid());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,4 +57,16 @@ public class GuildModelTest {
|
||||
assertFalse(guild.hasPermission(memberUuid, GuildPermission.CLAIM));
|
||||
assertFalse(guild.hasPermission(memberUuid, GuildPermission.BANK_WITHDRAW));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGuildColorAndTagFormatting() {
|
||||
assertEquals("#00C9FF", guild.getColor());
|
||||
assertEquals("<color:#00C9FF>[VAL]</color>", guild.getFormattedTag());
|
||||
assertEquals("<color:#00C9FF><bold>Valhalla</bold></color>", guild.getFormattedName());
|
||||
|
||||
guild.setColor("#FF5555");
|
||||
guild.setTag("VALH");
|
||||
assertEquals("#FF5555", guild.getColor());
|
||||
assertEquals("<color:#FF5555>[VALH]</color>", guild.getFormattedTag());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user