first commit
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
package com.bitnix.dirtguilds;
|
||||
|
||||
import com.bitnix.dirtguilds.command.DirtGuildsCommand;
|
||||
import com.bitnix.dirtguilds.data.DatabaseManager;
|
||||
import com.bitnix.dirtguilds.guild.GuildManager;
|
||||
import com.bitnix.dirtguilds.hook.EconomyHook;
|
||||
import com.bitnix.dirtguilds.listener.ChatListener;
|
||||
import com.bitnix.dirtguilds.listener.GuildFriendlyFireListener;
|
||||
import com.bitnix.dirtguilds.listener.GuiListener;
|
||||
import com.bitnix.dirtguilds.util.MessageUtil;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class DirtGuildsPlugin extends JavaPlugin {
|
||||
|
||||
private DatabaseManager databaseManager;
|
||||
private GuildManager guildManager;
|
||||
private MessageUtil messageUtil;
|
||||
private EconomyHook economyHook;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
saveDefaultConfig();
|
||||
|
||||
this.messageUtil = new MessageUtil(this);
|
||||
|
||||
this.economyHook = new EconomyHook(this);
|
||||
boolean economyEnabled = this.economyHook.setup();
|
||||
if (economyEnabled) {
|
||||
getLogger().info("Vault economy hooked successfully.");
|
||||
} else {
|
||||
getLogger().warning("Vault economy not found. Guild bank will run in internal-only mode.");
|
||||
}
|
||||
|
||||
this.databaseManager = new DatabaseManager(this);
|
||||
this.databaseManager.initialize();
|
||||
|
||||
this.guildManager = new GuildManager(this, this.databaseManager);
|
||||
this.guildManager.loadAll();
|
||||
|
||||
DirtGuildsCommand command = new DirtGuildsCommand(this);
|
||||
if (getCommand("dirtguilds") != null) {
|
||||
getCommand("dirtguilds").setExecutor(command);
|
||||
getCommand("dirtguilds").setTabCompleter(command);
|
||||
}
|
||||
|
||||
getServer().getPluginManager().registerEvents(new GuiListener(this), this);
|
||||
getServer().getPluginManager().registerEvents(new ChatListener(this), this);
|
||||
getServer().getPluginManager().registerEvents(new GuildFriendlyFireListener(this), this);
|
||||
|
||||
getLogger().info("DirtGuilds enabled.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
getServer().getScheduler().cancelTasks(this);
|
||||
|
||||
if (guildManager != null) {
|
||||
guildManager.shutdown();
|
||||
}
|
||||
|
||||
if (databaseManager != null) {
|
||||
databaseManager.close();
|
||||
}
|
||||
|
||||
getLogger().info("DirtGuilds disabled.");
|
||||
}
|
||||
|
||||
public DatabaseManager getDatabaseManager() {
|
||||
return databaseManager;
|
||||
}
|
||||
|
||||
public GuildManager getGuildManager() {
|
||||
return guildManager;
|
||||
}
|
||||
|
||||
public MessageUtil getMessageUtil() {
|
||||
return messageUtil;
|
||||
}
|
||||
|
||||
public EconomyHook getEconomyHook() {
|
||||
return economyHook;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,667 @@
|
||||
package com.bitnix.dirtguilds.command;
|
||||
|
||||
import com.bitnix.dirtguilds.DirtGuildsPlugin;
|
||||
import com.bitnix.dirtguilds.guild.Guild;
|
||||
import com.bitnix.dirtguilds.guild.GuildInvite;
|
||||
import com.bitnix.dirtguilds.gui.GuildLevelsMenu;
|
||||
import com.bitnix.dirtguilds.gui.GuildMainMenu;
|
||||
import com.bitnix.dirtguilds.gui.GuildMembersMenu;
|
||||
import com.bitnix.dirtguilds.gui.GuildVaultMenu;
|
||||
import com.bitnix.dirtguilds.util.MessageUtil;
|
||||
import net.milkbowl.vault.economy.EconomyResponse;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
public class DirtGuildsCommand implements TabExecutor, TabCompleter {
|
||||
|
||||
private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#,##0.00");
|
||||
|
||||
private final DirtGuildsPlugin plugin;
|
||||
|
||||
public DirtGuildsCommand(DirtGuildsPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
plugin.getMessageUtil().send(sender, "messages.players-only");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("dirtguilds.use")) {
|
||||
plugin.getMessageUtil().send(player, "messages.no-permission");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
new GuildMainMenu(plugin).open(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
String sub = args[0].toLowerCase(Locale.ROOT);
|
||||
Guild guild = plugin.getGuildManager().getGuildByPlayer(player.getUniqueId());
|
||||
|
||||
switch (sub) {
|
||||
case "create" -> {
|
||||
if (guild != null) {
|
||||
plugin.getMessageUtil().send(player, "messages.already-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 2) {
|
||||
plugin.getMessageUtil().sendRaw(player, "<red>Usage: /" + label + " create <name></red>");
|
||||
return true;
|
||||
}
|
||||
|
||||
String name = args[1];
|
||||
int min = plugin.getConfig().getInt("settings.min-name-length", 3);
|
||||
int max = plugin.getConfig().getInt("settings.max-name-length", 16);
|
||||
|
||||
if (name.length() < min || name.length() > max || !name.matches("[A-Za-z0-9_]+")) {
|
||||
plugin.getMessageUtil().send(player, "messages.invalid-name");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (plugin.getGuildManager().guildNameExists(name)) {
|
||||
plugin.getMessageUtil().send(player, "messages.name-taken");
|
||||
return true;
|
||||
}
|
||||
|
||||
Guild created = plugin.getGuildManager().createGuild(player.getUniqueId(), name);
|
||||
plugin.getMessageUtil().send(player, "messages.guild-created", "%guild%", created.getName());
|
||||
return true;
|
||||
}
|
||||
|
||||
case "invite" -> {
|
||||
if (guild == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.not-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!guild.canManage(player.getUniqueId()) && !guild.getOwner().equals(player.getUniqueId())) {
|
||||
plugin.getMessageUtil().send(player, "messages.no-permission");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 2) {
|
||||
plugin.getMessageUtil().sendRaw(player, "<red>Usage: /" + label + " invite <player></red>");
|
||||
return true;
|
||||
}
|
||||
|
||||
Player target = Bukkit.getPlayerExact(args[1]);
|
||||
if (target == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.player-not-found");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (plugin.getGuildManager().isInGuild(target.getUniqueId())) {
|
||||
plugin.getMessageUtil().send(player, "messages.target-already-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
plugin.getGuildManager().createInvite(target.getUniqueId(), player.getUniqueId(), guild);
|
||||
plugin.getMessageUtil().send(player, "messages.invite-sent", "%player%", target.getName());
|
||||
plugin.getMessageUtil().send(target, "messages.invite-received", "%guild%", guild.getName());
|
||||
return true;
|
||||
}
|
||||
|
||||
case "accept", "join" -> {
|
||||
if (guild != null) {
|
||||
plugin.getMessageUtil().send(player, "messages.already-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 2) {
|
||||
plugin.getMessageUtil().sendRaw(player, "<red>Usage: /" + label + " accept <guild></red>");
|
||||
return true;
|
||||
}
|
||||
|
||||
Guild targetGuild = plugin.getGuildManager().getGuildByName(args[1]);
|
||||
if (targetGuild == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.guild-not-found");
|
||||
return true;
|
||||
}
|
||||
|
||||
GuildInvite invite = plugin.getGuildManager().getInvite(player.getUniqueId(), targetGuild.getId());
|
||||
if (invite == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.no-invite");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (invite.isExpired()) {
|
||||
plugin.getGuildManager().removeInvite(player.getUniqueId(), targetGuild.getId());
|
||||
plugin.getMessageUtil().send(player, "messages.invite-expired");
|
||||
return true;
|
||||
}
|
||||
|
||||
plugin.getGuildManager().addMember(targetGuild, player.getUniqueId());
|
||||
plugin.getGuildManager().removeInvite(player.getUniqueId(), targetGuild.getId());
|
||||
|
||||
plugin.getMessageUtil().send(player, "messages.joined-guild", "%guild%", targetGuild.getName());
|
||||
|
||||
for (Player online : Bukkit.getOnlinePlayers()) {
|
||||
Guild onlineGuild = plugin.getGuildManager().getGuildByPlayer(online.getUniqueId());
|
||||
if (onlineGuild != null && onlineGuild.getId().equals(targetGuild.getId())) {
|
||||
plugin.getMessageUtil().send(online, "messages.member-joined", "%player%", player.getName());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case "leave" -> {
|
||||
if (guild == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.not-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (guild.getOwner().equals(player.getUniqueId())) {
|
||||
plugin.getGuildManager().deleteGuild(guild);
|
||||
plugin.getMessageUtil().send(player, "messages.guild-deleted", "%guild%", guild.getName());
|
||||
return true;
|
||||
}
|
||||
|
||||
plugin.getGuildManager().removeMember(guild, player.getUniqueId());
|
||||
plugin.getMessageUtil().send(player, "messages.left-guild");
|
||||
|
||||
for (Player online : Bukkit.getOnlinePlayers()) {
|
||||
Guild onlineGuild = plugin.getGuildManager().getGuildByPlayer(online.getUniqueId());
|
||||
if (onlineGuild != null && onlineGuild.getId().equals(guild.getId())) {
|
||||
plugin.getMessageUtil().send(online, "messages.member-left", "%player%", player.getName());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case "rename" -> {
|
||||
if (guild == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.not-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!guild.getOwner().equals(player.getUniqueId())) {
|
||||
plugin.getMessageUtil().send(player, "messages.must-be-owner");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 2) {
|
||||
plugin.getMessageUtil().sendRaw(player, "<red>Usage: /" + label + " rename <name></red>");
|
||||
return true;
|
||||
}
|
||||
|
||||
String newName = args[1];
|
||||
int min = plugin.getConfig().getInt("settings.min-name-length", 3);
|
||||
int max = plugin.getConfig().getInt("settings.max-name-length", 16);
|
||||
|
||||
if (newName.length() < min || newName.length() > max || !newName.matches("[A-Za-z0-9_]+")) {
|
||||
plugin.getMessageUtil().send(player, "messages.invalid-name");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!guild.getName().equalsIgnoreCase(newName) && plugin.getGuildManager().guildNameExists(newName)) {
|
||||
plugin.getMessageUtil().send(player, "messages.name-taken");
|
||||
return true;
|
||||
}
|
||||
|
||||
plugin.getGuildManager().renameGuild(guild, newName);
|
||||
plugin.getMessageUtil().send(player, "messages.guild-renamed", "%guild%", newName);
|
||||
return true;
|
||||
}
|
||||
|
||||
case "prefix" -> {
|
||||
if (guild == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.not-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!guild.canManage(player.getUniqueId()) && !guild.getOwner().equals(player.getUniqueId())) {
|
||||
plugin.getMessageUtil().send(player, "messages.no-permission");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 2) {
|
||||
plugin.getMessageUtil().sendRaw(player, "<red>Usage: /" + label + " prefix <text></red>");
|
||||
return true;
|
||||
}
|
||||
|
||||
String prefix = args[1];
|
||||
plugin.getGuildManager().setPrefix(guild, prefix);
|
||||
plugin.getMessageUtil().send(player, "messages.prefix-updated");
|
||||
return true;
|
||||
}
|
||||
|
||||
case "ff", "friendlyfire", "pvp" -> {
|
||||
if (guild == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.not-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!guild.canManage(player.getUniqueId()) && !guild.getOwner().equals(player.getUniqueId())) {
|
||||
plugin.getMessageUtil().send(player, "messages.no-permission");
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean enabled = !guild.isFriendlyFire();
|
||||
plugin.getGuildManager().setFriendlyFire(guild, enabled);
|
||||
|
||||
if (enabled) {
|
||||
plugin.getMessageUtil().send(player, "messages.friendly-fire-enabled");
|
||||
} else {
|
||||
plugin.getMessageUtil().send(player, "messages.friendly-fire-disabled");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case "chat" -> {
|
||||
if (guild == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.not-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean enabled = !plugin.getGuildManager().isGuildChatEnabled(player.getUniqueId());
|
||||
plugin.getGuildManager().setGuildChatEnabled(player.getUniqueId(), enabled);
|
||||
|
||||
if (enabled) {
|
||||
plugin.getMessageUtil().send(player, "messages.guild-chat-enabled");
|
||||
} else {
|
||||
plugin.getMessageUtil().send(player, "messages.guild-chat-disabled");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case "bank" -> {
|
||||
if (guild == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.not-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length == 1) {
|
||||
player.sendMessage(MessageUtil.mm(plugin.getMessageUtil().format("messages.prefix") + "<yellow>Use /guild bank deposit <amount> or /guild bank withdraw <amount></yellow>"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 3) {
|
||||
plugin.getMessageUtil().sendRaw(player, "<red>Usage: /" + label + " bank <deposit|withdraw> <amount></red>");
|
||||
return true;
|
||||
}
|
||||
|
||||
String action = args[1].toLowerCase(Locale.ROOT);
|
||||
double amount;
|
||||
|
||||
try {
|
||||
amount = Double.parseDouble(args[2]);
|
||||
} catch (NumberFormatException exception) {
|
||||
plugin.getMessageUtil().send(player, "messages.bank-invalid-amount");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (amount <= 0) {
|
||||
plugin.getMessageUtil().send(player, "messages.bank-invalid-amount");
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean useVault = plugin.getConfig().getBoolean("settings.bank.use-vault", true);
|
||||
|
||||
if (action.equals("deposit")) {
|
||||
if (useVault) {
|
||||
if (!plugin.getEconomyHook().isAvailable()) {
|
||||
plugin.getMessageUtil().send(player, "messages.bank-vault-unavailable");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (plugin.getEconomyHook().getEconomy().getBalance(player) < amount) {
|
||||
plugin.getMessageUtil().send(player, "messages.bank-player-insufficient-funds");
|
||||
return true;
|
||||
}
|
||||
|
||||
EconomyResponse response = plugin.getEconomyHook().getEconomy().withdrawPlayer(player, amount);
|
||||
if (!response.transactionSuccess()) {
|
||||
plugin.getMessageUtil().send(player, "messages.bank-player-insufficient-funds");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getGuildManager().deposit(guild, amount);
|
||||
plugin.getMessageUtil().send(player, "messages.bank-deposit", "%amount%", DECIMAL_FORMAT.format(amount));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action.equals("withdraw")) {
|
||||
if (!guild.canManage(player.getUniqueId()) && !guild.getOwner().equals(player.getUniqueId())) {
|
||||
plugin.getMessageUtil().send(player, "messages.no-permission");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!plugin.getGuildManager().withdraw(guild, amount)) {
|
||||
plugin.getMessageUtil().send(player, "messages.bank-insufficient-funds");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (useVault) {
|
||||
if (!plugin.getEconomyHook().isAvailable()) {
|
||||
plugin.getGuildManager().deposit(guild, amount);
|
||||
plugin.getMessageUtil().send(player, "messages.bank-vault-unavailable");
|
||||
return true;
|
||||
}
|
||||
|
||||
EconomyResponse response = plugin.getEconomyHook().getEconomy().depositPlayer(player, amount);
|
||||
if (!response.transactionSuccess()) {
|
||||
plugin.getGuildManager().deposit(guild, amount);
|
||||
plugin.getMessageUtil().send(player, "messages.bank-vault-unavailable");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getMessageUtil().send(player, "messages.bank-withdraw", "%amount%", DECIMAL_FORMAT.format(amount));
|
||||
return true;
|
||||
}
|
||||
|
||||
plugin.getMessageUtil().sendRaw(player, "<red>Usage: /" + label + " bank <deposit|withdraw> <amount></red>");
|
||||
return true;
|
||||
}
|
||||
|
||||
case "vault" -> {
|
||||
if (guild == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.not-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
new GuildVaultMenu(plugin).open(player, guild);
|
||||
return true;
|
||||
}
|
||||
|
||||
case "levels", "level" -> {
|
||||
if (guild == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.not-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
new GuildLevelsMenu(plugin).open(player, guild);
|
||||
return true;
|
||||
}
|
||||
|
||||
case "members" -> {
|
||||
if (guild == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.not-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
new GuildMembersMenu(plugin).open(player, guild);
|
||||
return true;
|
||||
}
|
||||
|
||||
case "promote" -> {
|
||||
if (guild == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.not-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!guild.canManage(player.getUniqueId()) && !guild.getOwner().equals(player.getUniqueId())) {
|
||||
plugin.getMessageUtil().send(player, "messages.no-permission");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 2) {
|
||||
plugin.getMessageUtil().sendRaw(player, "<red>Usage: /" + label + " promote <player></red>");
|
||||
return true;
|
||||
}
|
||||
|
||||
OfflinePlayer target = Bukkit.getOfflinePlayer(args[1]);
|
||||
UUID targetUuid = target.getUniqueId();
|
||||
|
||||
if (!guild.isMember(targetUuid) || targetUuid.equals(guild.getOwner())) {
|
||||
plugin.getMessageUtil().send(player, "messages.player-not-found");
|
||||
return true;
|
||||
}
|
||||
|
||||
String current = guild.getRank(targetUuid).toUpperCase();
|
||||
String next = switch (current) {
|
||||
case "MEMBER" -> "MOD";
|
||||
case "MOD" -> "ADMIN";
|
||||
default -> "ADMIN";
|
||||
};
|
||||
|
||||
plugin.getGuildManager().setMemberRank(guild, targetUuid, next);
|
||||
String name = target.getName() == null ? targetUuid.toString() : target.getName();
|
||||
plugin.getMessageUtil().send(player, "messages.rank-updated", "%player%", name, "%rank%", next);
|
||||
return true;
|
||||
}
|
||||
|
||||
case "demote" -> {
|
||||
if (guild == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.not-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!guild.canManage(player.getUniqueId()) && !guild.getOwner().equals(player.getUniqueId())) {
|
||||
plugin.getMessageUtil().send(player, "messages.no-permission");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 2) {
|
||||
plugin.getMessageUtil().sendRaw(player, "<red>Usage: /" + label + " demote <player></red>");
|
||||
return true;
|
||||
}
|
||||
|
||||
OfflinePlayer target = Bukkit.getOfflinePlayer(args[1]);
|
||||
UUID targetUuid = target.getUniqueId();
|
||||
|
||||
if (!guild.isMember(targetUuid) || targetUuid.equals(guild.getOwner())) {
|
||||
plugin.getMessageUtil().send(player, "messages.player-not-found");
|
||||
return true;
|
||||
}
|
||||
|
||||
String current = guild.getRank(targetUuid).toUpperCase();
|
||||
String next = switch (current) {
|
||||
case "ADMIN" -> "MOD";
|
||||
case "MOD" -> "MEMBER";
|
||||
default -> "MEMBER";
|
||||
};
|
||||
|
||||
plugin.getGuildManager().setMemberRank(guild, targetUuid, next);
|
||||
String name = target.getName() == null ? targetUuid.toString() : target.getName();
|
||||
plugin.getMessageUtil().send(player, "messages.rank-updated", "%player%", name, "%rank%", next);
|
||||
return true;
|
||||
}
|
||||
|
||||
case "kick" -> {
|
||||
if (guild == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.not-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!guild.canManage(player.getUniqueId()) && !guild.getOwner().equals(player.getUniqueId())) {
|
||||
plugin.getMessageUtil().send(player, "messages.no-permission");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 2) {
|
||||
plugin.getMessageUtil().sendRaw(player, "<red>Usage: /" + label + " kick <player></red>");
|
||||
return true;
|
||||
}
|
||||
|
||||
OfflinePlayer target = Bukkit.getOfflinePlayer(args[1]);
|
||||
UUID targetUuid = target.getUniqueId();
|
||||
|
||||
if (!guild.isMember(targetUuid) || targetUuid.equals(guild.getOwner())) {
|
||||
plugin.getMessageUtil().send(player, "messages.player-not-found");
|
||||
return true;
|
||||
}
|
||||
|
||||
plugin.getGuildManager().removeMember(guild, targetUuid);
|
||||
String name = target.getName() == null ? targetUuid.toString() : target.getName();
|
||||
plugin.getMessageUtil().sendRaw(player, plugin.getMessageUtil().format("messages.prefix") + "<red>Kicked <yellow>" + name + "</yellow> from the guild.</red>");
|
||||
return true;
|
||||
}
|
||||
|
||||
case "tp" -> {
|
||||
if (guild == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.not-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 2) {
|
||||
plugin.getMessageUtil().sendRaw(player, "<red>Usage: /" + label + " tp <player></red>");
|
||||
return true;
|
||||
}
|
||||
|
||||
Player target = Bukkit.getPlayerExact(args[1]);
|
||||
if (target == null || !guild.isMember(target.getUniqueId())) {
|
||||
plugin.getMessageUtil().send(player, "messages.teleport-offline");
|
||||
return true;
|
||||
}
|
||||
|
||||
player.teleport(target.getLocation());
|
||||
plugin.getMessageUtil().send(player, "messages.teleport-success", "%player%", target.getName());
|
||||
return true;
|
||||
}
|
||||
|
||||
case "inv", "inventory" -> {
|
||||
if (guild == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.not-in-guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!guild.canManage(player.getUniqueId()) && !guild.getOwner().equals(player.getUniqueId())) {
|
||||
plugin.getMessageUtil().send(player, "messages.no-permission");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 2) {
|
||||
plugin.getMessageUtil().sendRaw(player, "<red>Usage: /" + label + " inventory <player></red>");
|
||||
return true;
|
||||
}
|
||||
|
||||
Player target = Bukkit.getPlayerExact(args[1]);
|
||||
if (target == null || !guild.isMember(target.getUniqueId())) {
|
||||
plugin.getMessageUtil().send(player, "messages.player-not-found");
|
||||
return true;
|
||||
}
|
||||
|
||||
Inventory copy = Bukkit.createInventory(null, 54, MessageUtil.mm("<gold>Inventory: " + target.getName() + "</gold>"));
|
||||
copy.setContents(target.getInventory().getContents());
|
||||
player.openInventory(copy);
|
||||
plugin.getMessageUtil().send(player, "messages.inventory-opened", "%player%", target.getName());
|
||||
return true;
|
||||
}
|
||||
|
||||
case "reload" -> {
|
||||
if (!player.hasPermission("dirtguilds.admin")) {
|
||||
plugin.getMessageUtil().send(player, "messages.no-permission");
|
||||
return true;
|
||||
}
|
||||
|
||||
plugin.reloadConfig();
|
||||
plugin.getMessageUtil().send(player, "messages.reload");
|
||||
return true;
|
||||
}
|
||||
|
||||
default -> {
|
||||
plugin.getMessageUtil().send(player, "messages.unknown-command");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
|
||||
if (args.length == 1) {
|
||||
suggestions.add("create");
|
||||
suggestions.add("invite");
|
||||
suggestions.add("accept");
|
||||
suggestions.add("join");
|
||||
suggestions.add("leave");
|
||||
suggestions.add("rename");
|
||||
suggestions.add("prefix");
|
||||
suggestions.add("chat");
|
||||
suggestions.add("pvp");
|
||||
suggestions.add("bank");
|
||||
suggestions.add("vault");
|
||||
suggestions.add("level");
|
||||
suggestions.add("members");
|
||||
suggestions.add("promote");
|
||||
suggestions.add("demote");
|
||||
suggestions.add("kick");
|
||||
suggestions.add("tp");
|
||||
suggestions.add("inventory");
|
||||
suggestions.add("reload");
|
||||
return filter(suggestions, args[0]);
|
||||
}
|
||||
|
||||
if (args.length == 2 && args[0].equalsIgnoreCase("invite")) {
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
suggestions.add(player.getName());
|
||||
}
|
||||
return filter(suggestions, args[1]);
|
||||
}
|
||||
|
||||
if (args.length == 2 && (args[0].equalsIgnoreCase("accept") || args[0].equalsIgnoreCase("join"))) {
|
||||
for (Guild guild : plugin.getGuildManager().getAllGuilds()) {
|
||||
suggestions.add(guild.getName());
|
||||
}
|
||||
return filter(suggestions, args[1]);
|
||||
}
|
||||
|
||||
if (args.length == 2 && args[0].equalsIgnoreCase("bank")) {
|
||||
suggestions.add("deposit");
|
||||
suggestions.add("withdraw");
|
||||
return filter(suggestions, args[1]);
|
||||
}
|
||||
|
||||
if (args.length == 3 && args[0].equalsIgnoreCase("bank")) {
|
||||
suggestions.add("100");
|
||||
suggestions.add("500");
|
||||
suggestions.add("1000");
|
||||
suggestions.add("5000");
|
||||
return filter(suggestions, args[2]);
|
||||
}
|
||||
|
||||
if (args.length == 2 && isMemberTargetSubcommand(args[0]) && sender instanceof Player player) {
|
||||
Guild guild = plugin.getGuildManager().getGuildByPlayer(player.getUniqueId());
|
||||
if (guild != null) {
|
||||
for (UUID uuid : guild.getMemberRanks().keySet()) {
|
||||
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid);
|
||||
if (offlinePlayer.getName() != null) {
|
||||
suggestions.add(offlinePlayer.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
return filter(suggestions, args[1]);
|
||||
}
|
||||
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
private boolean isMemberTargetSubcommand(String input) {
|
||||
String lower = input.toLowerCase(Locale.ROOT);
|
||||
return lower.equals("promote")
|
||||
|| lower.equals("demote")
|
||||
|| lower.equals("kick")
|
||||
|| lower.equals("tp")
|
||||
|| lower.equals("inventory")
|
||||
|| lower.equals("inv");
|
||||
}
|
||||
|
||||
private List<String> filter(List<String> input, String token) {
|
||||
String lower = token.toLowerCase(Locale.ROOT);
|
||||
return input.stream()
|
||||
.filter(value -> value.toLowerCase(Locale.ROOT).startsWith(lower))
|
||||
.distinct()
|
||||
.sorted()
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.bitnix.dirtguilds.data;
|
||||
|
||||
import com.bitnix.dirtguilds.DirtGuildsPlugin;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
public class DatabaseManager {
|
||||
|
||||
private final DirtGuildsPlugin plugin;
|
||||
private HikariDataSource dataSource;
|
||||
|
||||
public DatabaseManager(DirtGuildsPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
String type = plugin.getConfig().getString("database.type", "SQLITE").toUpperCase();
|
||||
|
||||
HikariConfig config = new HikariConfig();
|
||||
|
||||
if (type.equals("MYSQL")) {
|
||||
String host = plugin.getConfig().getString("database.mysql.host");
|
||||
int port = plugin.getConfig().getInt("database.mysql.port");
|
||||
String database = plugin.getConfig().getString("database.mysql.database");
|
||||
String username = plugin.getConfig().getString("database.mysql.username");
|
||||
String password = plugin.getConfig().getString("database.mysql.password");
|
||||
String properties = plugin.getConfig().getString("database.mysql.properties", "");
|
||||
|
||||
config.setJdbcUrl("jdbc:mysql://" + host + ":" + port + "/" + database + properties);
|
||||
config.setUsername(username);
|
||||
config.setPassword(password);
|
||||
config.setMaximumPoolSize(10);
|
||||
} else {
|
||||
String fileName = plugin.getConfig().getString("database.sqlite.file", "guilds.db");
|
||||
File dbFile = new File(plugin.getDataFolder(), fileName);
|
||||
|
||||
if (!plugin.getDataFolder().exists()) {
|
||||
plugin.getDataFolder().mkdirs();
|
||||
}
|
||||
|
||||
config.setJdbcUrl("jdbc:sqlite:" + dbFile.getAbsolutePath());
|
||||
config.setMaximumPoolSize(1);
|
||||
}
|
||||
|
||||
config.setPoolName("DirtGuildsPool");
|
||||
this.dataSource = new HikariDataSource(config);
|
||||
|
||||
createTables();
|
||||
}
|
||||
|
||||
private void createTables() {
|
||||
try (Connection connection = getConnection(); Statement statement = connection.createStatement()) {
|
||||
statement.executeUpdate("""
|
||||
CREATE TABLE IF NOT EXISTS guilds (
|
||||
id VARCHAR(36) PRIMARY KEY,
|
||||
name VARCHAR(32) NOT NULL UNIQUE,
|
||||
prefix VARCHAR(64) NOT NULL,
|
||||
owner VARCHAR(36) NOT NULL,
|
||||
level INT NOT NULL,
|
||||
bank_balance DOUBLE NOT NULL,
|
||||
friendly_fire BOOLEAN NOT NULL
|
||||
)
|
||||
""");
|
||||
|
||||
statement.executeUpdate("""
|
||||
CREATE TABLE IF NOT EXISTS guild_members (
|
||||
guild_id VARCHAR(36) NOT NULL,
|
||||
player_uuid VARCHAR(36) NOT NULL,
|
||||
rank_name VARCHAR(32) NOT NULL,
|
||||
PRIMARY KEY (guild_id, player_uuid)
|
||||
)
|
||||
""");
|
||||
|
||||
statement.executeUpdate("""
|
||||
CREATE TABLE IF NOT EXISTS guild_vault_items (
|
||||
guild_id VARCHAR(36) NOT NULL,
|
||||
slot_index INT NOT NULL,
|
||||
item_data TEXT NOT NULL,
|
||||
PRIMARY KEY (guild_id, slot_index)
|
||||
)
|
||||
""");
|
||||
} catch (SQLException exception) {
|
||||
throw new RuntimeException("Failed to create database tables", exception);
|
||||
}
|
||||
}
|
||||
|
||||
public Connection getConnection() throws SQLException {
|
||||
return dataSource.getConnection();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (dataSource != null && !dataSource.isClosed()) {
|
||||
dataSource.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.bitnix.dirtguilds.gui;
|
||||
|
||||
import com.bitnix.dirtguilds.DirtGuildsPlugin;
|
||||
import com.bitnix.dirtguilds.guild.Guild;
|
||||
import com.bitnix.dirtguilds.util.MessageUtil;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GuildBankMenu {
|
||||
|
||||
private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#,##0.00");
|
||||
|
||||
private final DirtGuildsPlugin plugin;
|
||||
|
||||
public GuildBankMenu(DirtGuildsPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void open(Player player, Guild guild) {
|
||||
String title = plugin.getConfig().getString("gui.bank.title", "<gold>Guild Bank</gold>");
|
||||
int size = plugin.getConfig().getInt("gui.bank.size", 27);
|
||||
|
||||
Inventory inventory = Bukkit.createInventory(null, size, MessageUtil.mm(title));
|
||||
|
||||
inventory.setItem(11, createItem(Material.LIME_DYE, "<green>Deposit 100</green>", List.of(
|
||||
"<gray>Click to deposit <green>100</green> into the guild bank.</gray>"
|
||||
)));
|
||||
|
||||
inventory.setItem(13, createItem(Material.GOLD_INGOT, "<gold>Bank Balance</gold>", List.of(
|
||||
"<gray>Current Balance:</gray> <green>" + DECIMAL_FORMAT.format(guild.getBankBalance()) + "</green>"
|
||||
)));
|
||||
|
||||
inventory.setItem(15, createItem(Material.RED_DYE, "<red>Withdraw 100</red>", List.of(
|
||||
"<gray>Click to withdraw <red>100</red> from the guild bank.</gray>"
|
||||
)));
|
||||
|
||||
inventory.setItem(22, createItem(Material.ARROW, "<yellow>Back</yellow>", List.of(
|
||||
"<gray>Return to the main guild menu.</gray>"
|
||||
)));
|
||||
|
||||
player.openInventory(inventory);
|
||||
}
|
||||
|
||||
private ItemStack createItem(Material material, String name, List<String> loreLines) {
|
||||
ItemStack item = new ItemStack(material);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
|
||||
if (meta != null) {
|
||||
meta.displayName(plugin.getMessageUtil().parse(name));
|
||||
|
||||
List<Component> lore = new ArrayList<>();
|
||||
for (String line : loreLines) {
|
||||
lore.add(plugin.getMessageUtil().parse(line));
|
||||
}
|
||||
|
||||
meta.lore(lore);
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.bitnix.dirtguilds.gui;
|
||||
|
||||
import com.bitnix.dirtguilds.DirtGuildsPlugin;
|
||||
import com.bitnix.dirtguilds.guild.Guild;
|
||||
import com.bitnix.dirtguilds.util.MessageUtil;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GuildLevelsMenu {
|
||||
|
||||
private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#,##0.00");
|
||||
|
||||
private final DirtGuildsPlugin plugin;
|
||||
|
||||
public GuildLevelsMenu(DirtGuildsPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void open(Player player, Guild guild) {
|
||||
String title = plugin.getConfig().getString("gui.levels.title", "<gold>Guild Levels</gold>");
|
||||
int size = plugin.getConfig().getInt("gui.levels.size", 27);
|
||||
|
||||
Inventory inventory = Bukkit.createInventory(null, size, MessageUtil.mm(title));
|
||||
|
||||
int currentLevel = guild.getLevel();
|
||||
int maxLevel = plugin.getGuildManager().getMaxConfiguredLevel();
|
||||
double nextCost = plugin.getGuildManager().getNextLevelCost(guild);
|
||||
|
||||
inventory.setItem(11, createItem(Material.EXPERIENCE_BOTTLE, "<gold>Current Level</gold>", List.of(
|
||||
"<gray>Level:</gray> <yellow>" + currentLevel + "</yellow>",
|
||||
"<gray>Vault Slots:</gray> <yellow>" + guild.getVaultContents().length + "</yellow>"
|
||||
)));
|
||||
|
||||
if (currentLevel >= maxLevel || nextCost < 0) {
|
||||
inventory.setItem(13, createItem(Material.BARRIER, "<red>Max Level</red>", List.of(
|
||||
"<gray>Your guild is already max level.</gray>"
|
||||
)));
|
||||
} else {
|
||||
int nextVaultSlots = plugin.getGuildManager().getVaultSizeForLevel(currentLevel + 1);
|
||||
inventory.setItem(13, createItem(Material.EMERALD, "<green>Upgrade Guild</green>", List.of(
|
||||
"<gray>Next Level:</gray> <yellow>" + (currentLevel + 1) + "</yellow>",
|
||||
"<gray>Cost:</gray> <green>" + DECIMAL_FORMAT.format(nextCost) + "</green>",
|
||||
"<gray>Vault Slots:</gray> <yellow>" + nextVaultSlots + "</yellow>",
|
||||
"<gray>Click to upgrade</gray>"
|
||||
)));
|
||||
}
|
||||
|
||||
inventory.setItem(22, createItem(Material.ARROW, "<yellow>Back</yellow>", List.of(
|
||||
"<gray>Return to the main menu.</gray>"
|
||||
)));
|
||||
|
||||
player.openInventory(inventory);
|
||||
}
|
||||
|
||||
private ItemStack createItem(Material material, String name, List<String> loreLines) {
|
||||
ItemStack item = new ItemStack(material);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
|
||||
if (meta != null) {
|
||||
meta.displayName(plugin.getMessageUtil().parse(name));
|
||||
|
||||
List<Component> lore = new ArrayList<>();
|
||||
for (String line : loreLines) {
|
||||
lore.add(plugin.getMessageUtil().parse(line));
|
||||
}
|
||||
|
||||
meta.lore(lore);
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.bitnix.dirtguilds.gui;
|
||||
|
||||
import com.bitnix.dirtguilds.DirtGuildsPlugin;
|
||||
import com.bitnix.dirtguilds.guild.Guild;
|
||||
import com.bitnix.dirtguilds.util.MessageUtil;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GuildMainMenu {
|
||||
|
||||
private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#,##0.00");
|
||||
|
||||
private final DirtGuildsPlugin plugin;
|
||||
|
||||
public GuildMainMenu(DirtGuildsPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void open(Player player) {
|
||||
String title = plugin.getConfig().getString("gui.main.title", "<gold>DirtGuilds</gold>");
|
||||
int size = plugin.getConfig().getInt("gui.main.size", 27);
|
||||
|
||||
Inventory inventory = Bukkit.createInventory(null, size, MessageUtil.mm(title));
|
||||
Guild guild = plugin.getGuildManager().getGuildByPlayer(player.getUniqueId());
|
||||
|
||||
if (guild == null) {
|
||||
inventory.setItem(11, createItem(Material.EMERALD, "<green>Create Guild</green>", List.of(
|
||||
"<gray>Use:</gray> <white>/guild create <name></white>"
|
||||
)));
|
||||
inventory.setItem(15, createItem(Material.WRITABLE_BOOK, "<yellow>Join Guild</yellow>", List.of(
|
||||
"<gray>Use:</gray> <white>/guild accept <guild></white>"
|
||||
)));
|
||||
} else {
|
||||
inventory.setItem(10, createItem(Material.NAME_TAG, "<gold>Guild Info</gold>", List.of(
|
||||
"<gray>Name:</gray> <yellow>" + guild.getName() + "</yellow>",
|
||||
"<gray>Prefix:</gray> <yellow>" + guild.getPrefix() + "</yellow>",
|
||||
"<gray>Level:</gray> <yellow>" + guild.getLevel() + "</yellow>",
|
||||
"<gray>Owner:</gray> <yellow>" + Bukkit.getOfflinePlayer(guild.getOwner()).getName() + "</yellow>"
|
||||
)));
|
||||
|
||||
inventory.setItem(11, createItem(Material.CHEST, "<gold>Guild Bank</gold>", List.of(
|
||||
"<gray>Balance:</gray> <green>" + DECIMAL_FORMAT.format(guild.getBankBalance()) + "</green>",
|
||||
"<gray>Click to open bank menu.</gray>"
|
||||
)));
|
||||
|
||||
inventory.setItem(12, createItem(Material.BARREL, "<gold>Guild Vault</gold>", List.of(
|
||||
"<gray>Slots:</gray> <yellow>" + guild.getVaultContents().length + "</yellow>",
|
||||
"<gray>Click to open guild vault.</gray>"
|
||||
)));
|
||||
|
||||
inventory.setItem(13, createItem(Material.EXPERIENCE_BOTTLE, "<gold>Guild Levels</gold>", List.of(
|
||||
"<gray>Current Level:</gray> <yellow>" + guild.getLevel() + "</yellow>",
|
||||
"<gray>Click to view upgrades.</gray>"
|
||||
)));
|
||||
|
||||
inventory.setItem(14, createItem(Material.IRON_SWORD, "<gold>Friendly Fire</gold>", List.of(
|
||||
guild.isFriendlyFire() ? "<green>Enabled</green>" : "<red>Disabled</red>",
|
||||
"<gray>Click to toggle</gray>"
|
||||
)));
|
||||
|
||||
inventory.setItem(15, createItem(Material.PLAYER_HEAD, "<gold>Members</gold>", List.of(
|
||||
"<gray>Members:</gray> <yellow>" + guild.getMemberRanks().size() + "</yellow>",
|
||||
"<gray>Click to view members</gray>"
|
||||
)));
|
||||
|
||||
inventory.setItem(16, createItem(Material.PAPER, "<gold>Guild Chat</gold>", List.of(
|
||||
plugin.getGuildManager().isGuildChatEnabled(player.getUniqueId()) ? "<green>Enabled</green>" : "<red>Disabled</red>",
|
||||
"<gray>Click to toggle guild chat</gray>"
|
||||
)));
|
||||
}
|
||||
|
||||
player.openInventory(inventory);
|
||||
}
|
||||
|
||||
private ItemStack createItem(Material material, String name, List<String> loreLines) {
|
||||
ItemStack item = new ItemStack(material);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
|
||||
if (meta != null) {
|
||||
meta.displayName(plugin.getMessageUtil().parse(name));
|
||||
|
||||
List<Component> lore = new ArrayList<>();
|
||||
for (String line : loreLines) {
|
||||
lore.add(plugin.getMessageUtil().parse(line));
|
||||
}
|
||||
meta.lore(lore);
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.bitnix.dirtguilds.gui;
|
||||
|
||||
import com.bitnix.dirtguilds.DirtGuildsPlugin;
|
||||
import com.bitnix.dirtguilds.guild.Guild;
|
||||
import com.bitnix.dirtguilds.util.MessageUtil;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class GuildMemberManageMenu {
|
||||
|
||||
private final DirtGuildsPlugin plugin;
|
||||
|
||||
public GuildMemberManageMenu(DirtGuildsPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void open(Player viewer, Guild guild, UUID targetUuid) {
|
||||
String title = plugin.getConfig().getString("gui.member-manage.title", "<gold>Manage Member</gold>");
|
||||
int size = plugin.getConfig().getInt("gui.member-manage.size", 27);
|
||||
|
||||
Inventory inventory = Bukkit.createInventory(null, size, MessageUtil.mm(title));
|
||||
|
||||
OfflinePlayer target = Bukkit.getOfflinePlayer(targetUuid);
|
||||
String name = target.getName() == null ? targetUuid.toString() : target.getName();
|
||||
String rank = guild.getRank(targetUuid);
|
||||
|
||||
inventory.setItem(10, createItem(Material.ENDER_PEARL, "<green>Teleport</green>", List.of(
|
||||
"<gray>Teleport to:</gray> <yellow>" + name + "</yellow>"
|
||||
)));
|
||||
|
||||
inventory.setItem(12, createItem(Material.CHEST, "<gold>View Inventory</gold>", List.of(
|
||||
"<gray>Open inventory of:</gray> <yellow>" + name + "</yellow>"
|
||||
)));
|
||||
|
||||
inventory.setItem(14, createItem(Material.NAME_TAG, "<yellow>Cycle Rank</yellow>", List.of(
|
||||
"<gray>Current Rank:</gray> <yellow>" + rank + "</yellow>",
|
||||
"<gray>Click to cycle rank.</gray>"
|
||||
)));
|
||||
|
||||
inventory.setItem(16, createItem(Material.BARRIER, "<red>Kick Member</red>", List.of(
|
||||
"<gray>Remove:</gray> <yellow>" + name + "</yellow>"
|
||||
)));
|
||||
|
||||
inventory.setItem(22, createItem(Material.ARROW, "<yellow>Back</yellow>", List.of(
|
||||
"<gray>Return to members menu.</gray>"
|
||||
)));
|
||||
|
||||
viewer.openInventory(inventory);
|
||||
}
|
||||
|
||||
private ItemStack createItem(Material material, String name, List<String> loreLines) {
|
||||
ItemStack item = new ItemStack(material);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
|
||||
if (meta != null) {
|
||||
meta.displayName(plugin.getMessageUtil().parse(name));
|
||||
|
||||
List<Component> lore = new ArrayList<>();
|
||||
for (String line : loreLines) {
|
||||
lore.add(plugin.getMessageUtil().parse(line));
|
||||
}
|
||||
|
||||
meta.lore(lore);
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.bitnix.dirtguilds.gui;
|
||||
|
||||
import com.bitnix.dirtguilds.DirtGuildsPlugin;
|
||||
import com.bitnix.dirtguilds.guild.Guild;
|
||||
import com.bitnix.dirtguilds.util.MessageUtil;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class GuildMembersMenu {
|
||||
|
||||
private final DirtGuildsPlugin plugin;
|
||||
|
||||
public GuildMembersMenu(DirtGuildsPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void open(Player viewer, Guild guild) {
|
||||
String title = plugin.getConfig().getString("gui.members.title", "<gold>Guild Members</gold>");
|
||||
int size = plugin.getConfig().getInt("gui.members.size", 54);
|
||||
|
||||
Inventory inventory = Bukkit.createInventory(null, size, MessageUtil.mm(title));
|
||||
|
||||
List<UUID> members = new ArrayList<>(guild.getMemberRanks().keySet());
|
||||
members.sort(Comparator.comparing(uuid -> {
|
||||
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid);
|
||||
String name = offlinePlayer.getName();
|
||||
return name == null ? uuid.toString() : name.toLowerCase();
|
||||
}));
|
||||
|
||||
int slot = 0;
|
||||
for (UUID memberId : members) {
|
||||
if (slot >= size - 9) {
|
||||
break;
|
||||
}
|
||||
|
||||
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(memberId);
|
||||
inventory.setItem(slot, createMemberHead(guild, offlinePlayer));
|
||||
slot++;
|
||||
}
|
||||
|
||||
inventory.setItem(size - 5, createBackItem());
|
||||
viewer.openInventory(inventory);
|
||||
}
|
||||
|
||||
private ItemStack createMemberHead(Guild guild, OfflinePlayer offlinePlayer) {
|
||||
ItemStack item = new ItemStack(Material.PLAYER_HEAD);
|
||||
SkullMeta meta = (SkullMeta) item.getItemMeta();
|
||||
|
||||
if (meta != null) {
|
||||
meta.setOwningPlayer(offlinePlayer);
|
||||
|
||||
String playerName = offlinePlayer.getName() == null ? offlinePlayer.getUniqueId().toString() : offlinePlayer.getName();
|
||||
boolean owner = offlinePlayer.getUniqueId().equals(guild.getOwner());
|
||||
boolean online = offlinePlayer.isOnline();
|
||||
String rank = guild.getRank(offlinePlayer.getUniqueId());
|
||||
|
||||
meta.displayName(plugin.getMessageUtil().parse(
|
||||
(owner ? "<gold>" : "<yellow>") + playerName + (owner ? " <gray>(Owner)</gray>" : "")
|
||||
));
|
||||
|
||||
List<Component> lore = new ArrayList<>();
|
||||
lore.add(plugin.getMessageUtil().parse("<gray>Status:</gray> " + (online ? "<green>Online</green>" : "<red>Offline</red>")));
|
||||
lore.add(plugin.getMessageUtil().parse("<gray>Rank:</gray> <yellow>" + rank + "</yellow>"));
|
||||
lore.add(plugin.getMessageUtil().parse("<dark_gray>UUID:" + offlinePlayer.getUniqueId() + "</dark_gray>"));
|
||||
lore.add(plugin.getMessageUtil().parse("<gray>Click to manage member.</gray>"));
|
||||
|
||||
meta.lore(lore);
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
private ItemStack createBackItem() {
|
||||
ItemStack item = new ItemStack(Material.ARROW);
|
||||
var meta = item.getItemMeta();
|
||||
if (meta != null) {
|
||||
meta.displayName(plugin.getMessageUtil().parse("<yellow>Back</yellow>"));
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.bitnix.dirtguilds.gui;
|
||||
|
||||
import com.bitnix.dirtguilds.DirtGuildsPlugin;
|
||||
import com.bitnix.dirtguilds.guild.Guild;
|
||||
import com.bitnix.dirtguilds.util.MessageUtil;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class GuildVaultMenu {
|
||||
|
||||
private final DirtGuildsPlugin plugin;
|
||||
|
||||
public GuildVaultMenu(DirtGuildsPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void open(Player player, Guild guild) {
|
||||
String title = plugin.getConfig().getString("gui.vault.title", "<gold>Guild Vault</gold>");
|
||||
int size = guild.getVaultContents().length;
|
||||
|
||||
Inventory inventory = Bukkit.createInventory(player, size, MessageUtil.mm(title));
|
||||
ItemStack[] contents = guild.getVaultContents();
|
||||
|
||||
for (int i = 0; i < Math.min(size, contents.length); i++) {
|
||||
inventory.setItem(i, contents[i]);
|
||||
}
|
||||
|
||||
player.openInventory(inventory);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package com.bitnix.dirtguilds.guild;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Guild {
|
||||
|
||||
private final UUID id;
|
||||
private String name;
|
||||
private String prefix;
|
||||
private UUID owner;
|
||||
private int level;
|
||||
private double bankBalance;
|
||||
private boolean friendlyFire;
|
||||
private final Map<UUID, String> memberRanks;
|
||||
private ItemStack[] vaultContents;
|
||||
|
||||
public Guild(UUID id, String name, String prefix, UUID owner, int level, double bankBalance, boolean friendlyFire, Map<UUID, String> memberRanks, ItemStack[] vaultContents) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.prefix = prefix;
|
||||
this.owner = owner;
|
||||
this.level = level;
|
||||
this.bankBalance = bankBalance;
|
||||
this.friendlyFire = friendlyFire;
|
||||
this.memberRanks = new HashMap<>(memberRanks);
|
||||
this.memberRanks.put(owner, "OWNER");
|
||||
this.vaultContents = vaultContents == null ? new ItemStack[9] : vaultContents;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public UUID getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(UUID owner) {
|
||||
this.owner = owner;
|
||||
this.memberRanks.put(owner, "OWNER");
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public void setLevel(int level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public double getBankBalance() {
|
||||
return bankBalance;
|
||||
}
|
||||
|
||||
public void setBankBalance(double bankBalance) {
|
||||
this.bankBalance = bankBalance;
|
||||
}
|
||||
|
||||
public boolean isFriendlyFire() {
|
||||
return friendlyFire;
|
||||
}
|
||||
|
||||
public void setFriendlyFire(boolean friendlyFire) {
|
||||
this.friendlyFire = friendlyFire;
|
||||
}
|
||||
|
||||
public Map<UUID, String> getMemberRanks() {
|
||||
return memberRanks;
|
||||
}
|
||||
|
||||
public boolean isMember(UUID uuid) {
|
||||
return memberRanks.containsKey(uuid);
|
||||
}
|
||||
|
||||
public void addMember(UUID uuid) {
|
||||
memberRanks.putIfAbsent(uuid, "MEMBER");
|
||||
}
|
||||
|
||||
public void removeMember(UUID uuid) {
|
||||
memberRanks.remove(uuid);
|
||||
}
|
||||
|
||||
public String getRank(UUID uuid) {
|
||||
return memberRanks.getOrDefault(uuid, "MEMBER");
|
||||
}
|
||||
|
||||
public void setRank(UUID uuid, String rank) {
|
||||
memberRanks.put(uuid, rank);
|
||||
}
|
||||
|
||||
public boolean canManage(UUID uuid) {
|
||||
String rank = getRank(uuid).toUpperCase();
|
||||
return uuid.equals(owner) || rank.equals("OWNER") || rank.equals("ADMIN") || rank.equals("MOD");
|
||||
}
|
||||
|
||||
public ItemStack[] getVaultContents() {
|
||||
return vaultContents;
|
||||
}
|
||||
|
||||
public void setVaultContents(ItemStack[] vaultContents) {
|
||||
this.vaultContents = vaultContents;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.bitnix.dirtguilds.guild;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class GuildInvite {
|
||||
|
||||
private final UUID guildId;
|
||||
private final UUID target;
|
||||
private final UUID inviter;
|
||||
private final long expiresAt;
|
||||
|
||||
public GuildInvite(UUID guildId, UUID target, UUID inviter, long expiresAt) {
|
||||
this.guildId = guildId;
|
||||
this.target = target;
|
||||
this.inviter = inviter;
|
||||
this.expiresAt = expiresAt;
|
||||
}
|
||||
|
||||
public UUID getGuildId() {
|
||||
return guildId;
|
||||
}
|
||||
|
||||
public UUID getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public UUID getInviter() {
|
||||
return inviter;
|
||||
}
|
||||
|
||||
public long getExpiresAt() {
|
||||
return expiresAt;
|
||||
}
|
||||
|
||||
public boolean isExpired() {
|
||||
return System.currentTimeMillis() > expiresAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,479 @@
|
||||
package com.bitnix.dirtguilds.guild;
|
||||
|
||||
import com.bitnix.dirtguilds.DirtGuildsPlugin;
|
||||
import com.bitnix.dirtguilds.data.DatabaseManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.io.BukkitObjectInputStream;
|
||||
import org.bukkit.util.io.BukkitObjectOutputStream;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.Base64;
|
||||
|
||||
public class GuildManager {
|
||||
|
||||
private final DirtGuildsPlugin plugin;
|
||||
private final DatabaseManager databaseManager;
|
||||
|
||||
private final Map<UUID, Guild> guildsById;
|
||||
private final Map<String, UUID> guildIdsByLowerName;
|
||||
private final Map<UUID, UUID> playerGuildMap;
|
||||
private final Map<UUID, List<GuildInvite>> invitesByTarget;
|
||||
private final Set<UUID> guildChatEnabled;
|
||||
|
||||
public GuildManager(DirtGuildsPlugin plugin, DatabaseManager databaseManager) {
|
||||
this.plugin = plugin;
|
||||
this.databaseManager = databaseManager;
|
||||
this.guildsById = new ConcurrentHashMap<>();
|
||||
this.guildIdsByLowerName = new ConcurrentHashMap<>();
|
||||
this.playerGuildMap = new ConcurrentHashMap<>();
|
||||
this.invitesByTarget = new ConcurrentHashMap<>();
|
||||
this.guildChatEnabled = ConcurrentHashMap.newKeySet();
|
||||
}
|
||||
|
||||
public void loadAll() {
|
||||
guildsById.clear();
|
||||
guildIdsByLowerName.clear();
|
||||
playerGuildMap.clear();
|
||||
invitesByTarget.clear();
|
||||
guildChatEnabled.clear();
|
||||
|
||||
try (Connection connection = databaseManager.getConnection()) {
|
||||
Map<UUID, Map<UUID, String>> memberMap = new HashMap<>();
|
||||
Map<UUID, ItemStack[]> vaultMap = new HashMap<>();
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement("SELECT guild_id, player_uuid, rank_name FROM guild_members");
|
||||
ResultSet resultSet = statement.executeQuery()) {
|
||||
while (resultSet.next()) {
|
||||
UUID guildId = UUID.fromString(resultSet.getString("guild_id"));
|
||||
UUID playerUuid = UUID.fromString(resultSet.getString("player_uuid"));
|
||||
String rankName = resultSet.getString("rank_name");
|
||||
|
||||
memberMap.computeIfAbsent(guildId, ignored -> new HashMap<>()).put(playerUuid, rankName);
|
||||
playerGuildMap.put(playerUuid, guildId);
|
||||
}
|
||||
}
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement("SELECT guild_id, slot_index, item_data FROM guild_vault_items");
|
||||
ResultSet resultSet = statement.executeQuery()) {
|
||||
while (resultSet.next()) {
|
||||
UUID guildId = UUID.fromString(resultSet.getString("guild_id"));
|
||||
int slot = resultSet.getInt("slot_index");
|
||||
String itemData = resultSet.getString("item_data");
|
||||
|
||||
ItemStack[] contents = vaultMap.computeIfAbsent(guildId, ignored -> new ItemStack[54]);
|
||||
contents[slot] = deserializeItem(itemData);
|
||||
}
|
||||
}
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement("SELECT * FROM guilds");
|
||||
ResultSet resultSet = statement.executeQuery()) {
|
||||
while (resultSet.next()) {
|
||||
UUID id = UUID.fromString(resultSet.getString("id"));
|
||||
String name = resultSet.getString("name");
|
||||
String prefix = resultSet.getString("prefix");
|
||||
UUID owner = UUID.fromString(resultSet.getString("owner"));
|
||||
int level = resultSet.getInt("level");
|
||||
double bankBalance = resultSet.getDouble("bank_balance");
|
||||
boolean friendlyFire = resultSet.getBoolean("friendly_fire");
|
||||
|
||||
ItemStack[] vault = vaultMap.getOrDefault(id, new ItemStack[getVaultSizeForLevel(level)]);
|
||||
Guild guild = new Guild(
|
||||
id,
|
||||
name,
|
||||
prefix,
|
||||
owner,
|
||||
level,
|
||||
bankBalance,
|
||||
friendlyFire,
|
||||
memberMap.getOrDefault(id, new HashMap<>()),
|
||||
normalizeVault(vault, getVaultSizeForLevel(level))
|
||||
);
|
||||
|
||||
guildsById.put(id, guild);
|
||||
guildIdsByLowerName.put(name.toLowerCase(Locale.ROOT), id);
|
||||
|
||||
for (UUID member : guild.getMemberRanks().keySet()) {
|
||||
playerGuildMap.put(member, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
throw new RuntimeException("Failed to load guild data", exception);
|
||||
}
|
||||
}
|
||||
|
||||
public Guild getGuildByPlayer(UUID playerUuid) {
|
||||
UUID guildId = playerGuildMap.get(playerUuid);
|
||||
return guildId == null ? null : guildsById.get(guildId);
|
||||
}
|
||||
|
||||
public Guild getGuildByName(String name) {
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
UUID guildId = guildIdsByLowerName.get(name.toLowerCase(Locale.ROOT));
|
||||
return guildId == null ? null : guildsById.get(guildId);
|
||||
}
|
||||
|
||||
public Guild getGuildById(UUID guildId) {
|
||||
return guildsById.get(guildId);
|
||||
}
|
||||
|
||||
public boolean isInGuild(UUID playerUuid) {
|
||||
return playerGuildMap.containsKey(playerUuid);
|
||||
}
|
||||
|
||||
public boolean guildNameExists(String name) {
|
||||
return guildIdsByLowerName.containsKey(name.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
public Guild createGuild(UUID owner, String name) {
|
||||
UUID guildId = UUID.randomUUID();
|
||||
int defaultLevel = plugin.getConfig().getInt("settings.levels.default-level", 1);
|
||||
int vaultSize = getVaultSizeForLevel(defaultLevel);
|
||||
|
||||
Guild guild = new Guild(
|
||||
guildId,
|
||||
name,
|
||||
name,
|
||||
owner,
|
||||
defaultLevel,
|
||||
0.0D,
|
||||
plugin.getConfig().getBoolean("settings.default-friendly-fire", false),
|
||||
new HashMap<>(),
|
||||
new ItemStack[vaultSize]
|
||||
);
|
||||
|
||||
guildsById.put(guildId, guild);
|
||||
guildIdsByLowerName.put(name.toLowerCase(Locale.ROOT), guildId);
|
||||
playerGuildMap.put(owner, guildId);
|
||||
|
||||
saveGuild(guild);
|
||||
saveMembers(guild);
|
||||
saveVault(guild);
|
||||
return guild;
|
||||
}
|
||||
|
||||
public void deleteGuild(Guild guild) {
|
||||
guildsById.remove(guild.getId());
|
||||
guildIdsByLowerName.remove(guild.getName().toLowerCase(Locale.ROOT));
|
||||
|
||||
for (UUID member : new HashSet<>(guild.getMemberRanks().keySet())) {
|
||||
playerGuildMap.remove(member);
|
||||
guildChatEnabled.remove(member);
|
||||
}
|
||||
|
||||
invitesByTarget.values().forEach(list -> list.removeIf(invite -> invite.getGuildId().equals(guild.getId())));
|
||||
|
||||
try (Connection connection = databaseManager.getConnection()) {
|
||||
try (PreparedStatement statement = connection.prepareStatement("DELETE FROM guild_members WHERE guild_id = ?")) {
|
||||
statement.setString(1, guild.getId().toString());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement("DELETE FROM guild_vault_items WHERE guild_id = ?")) {
|
||||
statement.setString(1, guild.getId().toString());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement("DELETE FROM guilds WHERE id = ?")) {
|
||||
statement.setString(1, guild.getId().toString());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
} catch (SQLException exception) {
|
||||
throw new RuntimeException("Failed to delete guild", exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void renameGuild(Guild guild, String newName) {
|
||||
guildIdsByLowerName.remove(guild.getName().toLowerCase(Locale.ROOT));
|
||||
guild.setName(newName);
|
||||
guildIdsByLowerName.put(newName.toLowerCase(Locale.ROOT), guild.getId());
|
||||
saveGuild(guild);
|
||||
}
|
||||
|
||||
public void setPrefix(Guild guild, String prefix) {
|
||||
guild.setPrefix(prefix);
|
||||
saveGuild(guild);
|
||||
}
|
||||
|
||||
public void setFriendlyFire(Guild guild, boolean enabled) {
|
||||
guild.setFriendlyFire(enabled);
|
||||
saveGuild(guild);
|
||||
}
|
||||
|
||||
public void addMember(Guild guild, UUID playerUuid) {
|
||||
guild.addMember(playerUuid);
|
||||
playerGuildMap.put(playerUuid, guild.getId());
|
||||
saveMembers(guild);
|
||||
}
|
||||
|
||||
public void removeMember(Guild guild, UUID playerUuid) {
|
||||
guild.removeMember(playerUuid);
|
||||
playerGuildMap.remove(playerUuid);
|
||||
guildChatEnabled.remove(playerUuid);
|
||||
saveMembers(guild);
|
||||
}
|
||||
|
||||
public void setMemberRank(Guild guild, UUID playerUuid, String rank) {
|
||||
guild.setRank(playerUuid, rank);
|
||||
saveMembers(guild);
|
||||
}
|
||||
|
||||
public void transferOwnership(Guild guild, UUID newOwner) {
|
||||
guild.setOwner(newOwner);
|
||||
guild.setRank(newOwner, "OWNER");
|
||||
playerGuildMap.put(newOwner, guild.getId());
|
||||
saveGuild(guild);
|
||||
saveMembers(guild);
|
||||
}
|
||||
|
||||
public void deposit(Guild guild, double amount) {
|
||||
guild.setBankBalance(guild.getBankBalance() + amount);
|
||||
saveGuild(guild);
|
||||
}
|
||||
|
||||
public boolean withdraw(Guild guild, double amount) {
|
||||
if (guild.getBankBalance() < amount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
guild.setBankBalance(guild.getBankBalance() - amount);
|
||||
saveGuild(guild);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean upgradeLevel(Guild guild) {
|
||||
int nextLevel = guild.getLevel() + 1;
|
||||
ConfigurationSection levelSection = plugin.getConfig().getConfigurationSection("settings.levels.levels." + nextLevel);
|
||||
if (levelSection == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double cost = levelSection.getDouble("cost", 0.0D);
|
||||
if (guild.getBankBalance() < cost) {
|
||||
return false;
|
||||
}
|
||||
|
||||
guild.setBankBalance(guild.getBankBalance() - cost);
|
||||
guild.setLevel(nextLevel);
|
||||
guild.setVaultContents(normalizeVault(guild.getVaultContents(), getVaultSizeForLevel(nextLevel)));
|
||||
saveGuild(guild);
|
||||
saveVault(guild);
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getMaxConfiguredLevel() {
|
||||
ConfigurationSection section = plugin.getConfig().getConfigurationSection("settings.levels.levels");
|
||||
if (section == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int max = 1;
|
||||
for (String key : section.getKeys(false)) {
|
||||
try {
|
||||
max = Math.max(max, Integer.parseInt(key));
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
public int getVaultSizeForLevel(int level) {
|
||||
int configured = plugin.getConfig().getInt("settings.levels.levels." + level + ".vault-slots",
|
||||
plugin.getConfig().getInt("settings.vault.default-size", 9));
|
||||
|
||||
configured = Math.max(9, configured);
|
||||
configured = Math.min(plugin.getConfig().getInt("settings.vault.max-size", 54), configured);
|
||||
|
||||
int remainder = configured % 9;
|
||||
if (remainder != 0) {
|
||||
configured += (9 - remainder);
|
||||
}
|
||||
|
||||
return Math.max(9, Math.min(54, configured));
|
||||
}
|
||||
|
||||
public double getNextLevelCost(Guild guild) {
|
||||
return plugin.getConfig().getDouble("settings.levels.levels." + (guild.getLevel() + 1) + ".cost", -1.0D);
|
||||
}
|
||||
|
||||
public void createInvite(UUID target, UUID inviter, Guild guild) {
|
||||
long expiresAt = System.currentTimeMillis() + (plugin.getConfig().getLong("settings.invite-expire-seconds", 120L) * 1000L);
|
||||
GuildInvite invite = new GuildInvite(guild.getId(), target, inviter, expiresAt);
|
||||
invitesByTarget.computeIfAbsent(target, ignored -> new ArrayList<>()).removeIf(existing -> existing.getGuildId().equals(guild.getId()));
|
||||
invitesByTarget.computeIfAbsent(target, ignored -> new ArrayList<>()).add(invite);
|
||||
}
|
||||
|
||||
public GuildInvite getInvite(UUID target, UUID guildId) {
|
||||
List<GuildInvite> invites = invitesByTarget.get(target);
|
||||
if (invites == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
invites.removeIf(GuildInvite::isExpired);
|
||||
|
||||
for (GuildInvite invite : invites) {
|
||||
if (invite.getGuildId().equals(guildId)) {
|
||||
return invite;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void removeInvite(UUID target, UUID guildId) {
|
||||
List<GuildInvite> invites = invitesByTarget.get(target);
|
||||
if (invites == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
invites.removeIf(invite -> invite.getGuildId().equals(guildId));
|
||||
if (invites.isEmpty()) {
|
||||
invitesByTarget.remove(target);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isGuildChatEnabled(UUID playerUuid) {
|
||||
return guildChatEnabled.contains(playerUuid);
|
||||
}
|
||||
|
||||
public void setGuildChatEnabled(UUID playerUuid, boolean enabled) {
|
||||
if (enabled) {
|
||||
guildChatEnabled.add(playerUuid);
|
||||
} else {
|
||||
guildChatEnabled.remove(playerUuid);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveVaultFromInventory(Guild guild, Inventory inventory) {
|
||||
ItemStack[] contents = new ItemStack[inventory.getSize()];
|
||||
for (int i = 0; i < inventory.getSize(); i++) {
|
||||
contents[i] = inventory.getItem(i);
|
||||
}
|
||||
guild.setVaultContents(contents);
|
||||
saveVault(guild);
|
||||
}
|
||||
|
||||
public Collection<Guild> getAllGuilds() {
|
||||
return Collections.unmodifiableCollection(guildsById.values());
|
||||
}
|
||||
|
||||
private void saveGuild(Guild guild) {
|
||||
try (Connection connection = databaseManager.getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement("""
|
||||
INSERT INTO guilds (id, name, prefix, owner, level, bank_balance, friendly_fire)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(id) DO UPDATE SET
|
||||
name = excluded.name,
|
||||
prefix = excluded.prefix,
|
||||
owner = excluded.owner,
|
||||
level = excluded.level,
|
||||
bank_balance = excluded.bank_balance,
|
||||
friendly_fire = excluded.friendly_fire
|
||||
""")) {
|
||||
|
||||
statement.setString(1, guild.getId().toString());
|
||||
statement.setString(2, guild.getName());
|
||||
statement.setString(3, guild.getPrefix());
|
||||
statement.setString(4, guild.getOwner().toString());
|
||||
statement.setInt(5, guild.getLevel());
|
||||
statement.setDouble(6, guild.getBankBalance());
|
||||
statement.setBoolean(7, guild.isFriendlyFire());
|
||||
statement.executeUpdate();
|
||||
} catch (SQLException exception) {
|
||||
throw new RuntimeException("Failed to save guild", exception);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveMembers(Guild guild) {
|
||||
try (Connection connection = databaseManager.getConnection()) {
|
||||
try (PreparedStatement delete = connection.prepareStatement("DELETE FROM guild_members WHERE guild_id = ?")) {
|
||||
delete.setString(1, guild.getId().toString());
|
||||
delete.executeUpdate();
|
||||
}
|
||||
|
||||
try (PreparedStatement insert = connection.prepareStatement("INSERT INTO guild_members (guild_id, player_uuid, rank_name) VALUES (?, ?, ?)")) {
|
||||
for (Map.Entry<UUID, String> entry : guild.getMemberRanks().entrySet()) {
|
||||
insert.setString(1, guild.getId().toString());
|
||||
insert.setString(2, entry.getKey().toString());
|
||||
insert.setString(3, entry.getValue());
|
||||
insert.addBatch();
|
||||
}
|
||||
insert.executeBatch();
|
||||
}
|
||||
} catch (SQLException exception) {
|
||||
throw new RuntimeException("Failed to save guild members", exception);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveVault(Guild guild) {
|
||||
try (Connection connection = databaseManager.getConnection()) {
|
||||
try (PreparedStatement delete = connection.prepareStatement("DELETE FROM guild_vault_items WHERE guild_id = ?")) {
|
||||
delete.setString(1, guild.getId().toString());
|
||||
delete.executeUpdate();
|
||||
}
|
||||
|
||||
try (PreparedStatement insert = connection.prepareStatement("INSERT INTO guild_vault_items (guild_id, slot_index, item_data) VALUES (?, ?, ?)")) {
|
||||
ItemStack[] contents = guild.getVaultContents();
|
||||
for (int i = 0; i < contents.length; i++) {
|
||||
ItemStack item = contents[i];
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
insert.setString(1, guild.getId().toString());
|
||||
insert.setInt(2, i);
|
||||
insert.setString(3, serializeItem(item));
|
||||
insert.addBatch();
|
||||
}
|
||||
insert.executeBatch();
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
throw new RuntimeException("Failed to save guild vault", exception);
|
||||
}
|
||||
}
|
||||
|
||||
private String serializeItem(ItemStack item) throws Exception {
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream);
|
||||
dataOutput.writeObject(item);
|
||||
dataOutput.close();
|
||||
return Base64.getEncoder().encodeToString(outputStream.toByteArray());
|
||||
}
|
||||
|
||||
private ItemStack deserializeItem(String data) throws Exception {
|
||||
byte[] bytes = Base64.getDecoder().decode(data);
|
||||
BukkitObjectInputStream dataInput = new BukkitObjectInputStream(new ByteArrayInputStream(bytes));
|
||||
ItemStack item = (ItemStack) dataInput.readObject();
|
||||
dataInput.close();
|
||||
return item;
|
||||
}
|
||||
|
||||
private ItemStack[] normalizeVault(ItemStack[] original, int newSize) {
|
||||
ItemStack[] normalized = new ItemStack[newSize];
|
||||
if (original != null) {
|
||||
System.arraycopy(original, 0, normalized, 0, Math.min(original.length, newSize));
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
invitesByTarget.clear();
|
||||
guildChatEnabled.clear();
|
||||
guildsById.clear();
|
||||
guildIdsByLowerName.clear();
|
||||
playerGuildMap.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.bitnix.dirtguilds.hook;
|
||||
|
||||
import com.bitnix.dirtguilds.DirtGuildsPlugin;
|
||||
import net.milkbowl.vault.economy.Economy;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
|
||||
public class EconomyHook {
|
||||
|
||||
private final DirtGuildsPlugin plugin;
|
||||
private Economy economy;
|
||||
|
||||
public EconomyHook(DirtGuildsPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public boolean setup() {
|
||||
if (Bukkit.getPluginManager().getPlugin("Vault") == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RegisteredServiceProvider<Economy> provider = Bukkit.getServicesManager().getRegistration(Economy.class);
|
||||
if (provider == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.economy = provider.getProvider();
|
||||
return this.economy != null;
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return economy != null;
|
||||
}
|
||||
|
||||
public Economy getEconomy() {
|
||||
return economy;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.bitnix.dirtguilds.listener;
|
||||
|
||||
import com.bitnix.dirtguilds.DirtGuildsPlugin;
|
||||
import com.bitnix.dirtguilds.guild.Guild;
|
||||
import io.papermc.paper.event.player.AsyncChatEvent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class ChatListener implements Listener {
|
||||
|
||||
private final DirtGuildsPlugin plugin;
|
||||
|
||||
public ChatListener(DirtGuildsPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onChat(AsyncChatEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (!plugin.getGuildManager().isGuildChatEnabled(player.getUniqueId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
Guild guild = plugin.getGuildManager().getGuildByPlayer(player.getUniqueId());
|
||||
if (guild == null) {
|
||||
plugin.getGuildManager().setGuildChatEnabled(player.getUniqueId(), false);
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
Component message = event.message();
|
||||
Component format = plugin.getMessageUtil().parse(
|
||||
"<gray>[<gold>Guild</gold>]</gray> <yellow>" + guild.getPrefix() + "</yellow> <white>" + player.getName() + "</white><gray>:</gray> "
|
||||
);
|
||||
|
||||
for (Player online : Bukkit.getOnlinePlayers()) {
|
||||
Guild targetGuild = plugin.getGuildManager().getGuildByPlayer(online.getUniqueId());
|
||||
if (targetGuild != null && targetGuild.getId().equals(guild.getId())) {
|
||||
online.sendMessage(format.append(message));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
package com.bitnix.dirtguilds.listener;
|
||||
|
||||
import com.bitnix.dirtguilds.DirtGuildsPlugin;
|
||||
import com.bitnix.dirtguilds.gui.GuildBankMenu;
|
||||
import com.bitnix.dirtguilds.gui.GuildLevelsMenu;
|
||||
import com.bitnix.dirtguilds.gui.GuildMainMenu;
|
||||
import com.bitnix.dirtguilds.gui.GuildMemberManageMenu;
|
||||
import com.bitnix.dirtguilds.gui.GuildMembersMenu;
|
||||
import com.bitnix.dirtguilds.gui.GuildVaultMenu;
|
||||
import com.bitnix.dirtguilds.guild.Guild;
|
||||
import com.bitnix.dirtguilds.util.MessageUtil;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class GuiListener implements Listener {
|
||||
|
||||
private final DirtGuildsPlugin plugin;
|
||||
private final PlainTextComponentSerializer plainText;
|
||||
private final Map<UUID, UUID> selectedMemberTargets;
|
||||
|
||||
public GuiListener(DirtGuildsPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.plainText = PlainTextComponentSerializer.plainText();
|
||||
this.selectedMemberTargets = new HashMap<>();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
if (!(event.getWhoClicked() instanceof Player player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String openedTitle = plainText.serialize(event.getView().title());
|
||||
String mainTitle = title("gui.main.title", "<gold>DirtGuilds</gold>");
|
||||
String membersTitle = title("gui.members.title", "<gold>Guild Members</gold>");
|
||||
String memberManageTitle = title("gui.member-manage.title", "<gold>Manage Member</gold>");
|
||||
String bankTitle = title("gui.bank.title", "<gold>Guild Bank</gold>");
|
||||
String vaultTitle = title("gui.vault.title", "<gold>Guild Vault</gold>");
|
||||
String levelsTitle = title("gui.levels.title", "<gold>Guild Levels</gold>");
|
||||
|
||||
if (openedTitle.equals(mainTitle)) {
|
||||
handleMainMenuClick(event, player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (openedTitle.equals(membersTitle)) {
|
||||
handleMembersMenuClick(event, player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (openedTitle.equals(memberManageTitle)) {
|
||||
handleMemberManageMenuClick(event, player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (openedTitle.equals(bankTitle)) {
|
||||
handleBankMenuClick(event, player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (openedTitle.equals(vaultTitle)) {
|
||||
handleVaultMenuClick(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (openedTitle.equals(levelsTitle)) {
|
||||
handleLevelsMenuClick(event, player);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClose(InventoryCloseEvent event) {
|
||||
HumanEntity human = event.getPlayer();
|
||||
if (!(human instanceof Player player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String openedTitle = plainText.serialize(event.getView().title());
|
||||
String vaultTitle = title("gui.vault.title", "<gold>Guild Vault</gold>");
|
||||
|
||||
if (!openedTitle.equals(vaultTitle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Guild guild = plugin.getGuildManager().getGuildByPlayer(player.getUniqueId());
|
||||
if (guild == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.getGuildManager().saveVaultFromInventory(guild, event.getInventory());
|
||||
}
|
||||
|
||||
private void handleMainMenuClick(InventoryClickEvent event, Player player) {
|
||||
event.setCancelled(true);
|
||||
|
||||
if (event.getCurrentItem() == null || event.getCurrentItem().getType().isAir()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Guild guild = plugin.getGuildManager().getGuildByPlayer(player.getUniqueId());
|
||||
|
||||
switch (event.getCurrentItem().getType()) {
|
||||
case EMERALD -> plugin.getMessageUtil().sendRaw(player, "<yellow>Use /guild create <name></yellow>");
|
||||
case WRITABLE_BOOK -> plugin.getMessageUtil().sendRaw(player, "<yellow>Use /guild accept <guild></yellow>");
|
||||
case CHEST -> {
|
||||
if (guild != null) {
|
||||
new GuildBankMenu(plugin).open(player, guild);
|
||||
}
|
||||
}
|
||||
case BARREL -> {
|
||||
if (guild != null) {
|
||||
new GuildVaultMenu(plugin).open(player, guild);
|
||||
}
|
||||
}
|
||||
case EXPERIENCE_BOTTLE -> {
|
||||
if (guild != null) {
|
||||
new GuildLevelsMenu(plugin).open(player, guild);
|
||||
}
|
||||
}
|
||||
case IRON_SWORD -> {
|
||||
if (guild != null) {
|
||||
player.closeInventory();
|
||||
player.performCommand("guild pvp");
|
||||
}
|
||||
}
|
||||
case PLAYER_HEAD -> {
|
||||
if (guild != null) {
|
||||
new GuildMembersMenu(plugin).open(player, guild);
|
||||
}
|
||||
}
|
||||
case PAPER -> {
|
||||
if (guild != null) {
|
||||
player.closeInventory();
|
||||
player.performCommand("guild chat");
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMembersMenuClick(InventoryClickEvent event, Player player) {
|
||||
event.setCancelled(true);
|
||||
|
||||
if (event.getCurrentItem() == null || event.getCurrentItem().getType().isAir()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Guild guild = plugin.getGuildManager().getGuildByPlayer(player.getUniqueId());
|
||||
if (guild == null) {
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getCurrentItem().getType() == Material.ARROW) {
|
||||
new GuildMainMenu(plugin).open(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getCurrentItem().getType() != Material.PLAYER_HEAD) {
|
||||
return;
|
||||
}
|
||||
|
||||
UUID targetUuid = extractUuidFromItem(event.getCurrentItem().getItemMeta());
|
||||
if (targetUuid == null || !guild.isMember(targetUuid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectedMemberTargets.put(player.getUniqueId(), targetUuid);
|
||||
new GuildMemberManageMenu(plugin).open(player, guild, targetUuid);
|
||||
}
|
||||
|
||||
private void handleMemberManageMenuClick(InventoryClickEvent event, Player player) {
|
||||
event.setCancelled(true);
|
||||
|
||||
if (event.getCurrentItem() == null || event.getCurrentItem().getType().isAir()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Guild guild = plugin.getGuildManager().getGuildByPlayer(player.getUniqueId());
|
||||
if (guild == null) {
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
UUID targetUuid = selectedMemberTargets.get(player.getUniqueId());
|
||||
if (targetUuid == null || !guild.isMember(targetUuid)) {
|
||||
new GuildMembersMenu(plugin).open(player, guild);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!guild.canManage(player.getUniqueId()) && !guild.getOwner().equals(player.getUniqueId())) {
|
||||
plugin.getMessageUtil().send(player, "messages.no-permission");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.getCurrentItem().getType()) {
|
||||
case ENDER_PEARL -> {
|
||||
Player target = Bukkit.getPlayer(targetUuid);
|
||||
if (target == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.teleport-offline");
|
||||
return;
|
||||
}
|
||||
|
||||
player.teleport(target.getLocation());
|
||||
plugin.getMessageUtil().send(player, "messages.teleport-success", "%player%", target.getName());
|
||||
}
|
||||
|
||||
case CHEST -> {
|
||||
Player target = Bukkit.getPlayer(targetUuid);
|
||||
if (target == null) {
|
||||
plugin.getMessageUtil().send(player, "messages.teleport-offline");
|
||||
return;
|
||||
}
|
||||
|
||||
Inventory copy = Bukkit.createInventory(null, 54, MessageUtil.mm("<gold>Inventory: " + target.getName() + "</gold>"));
|
||||
copy.setContents(target.getInventory().getContents());
|
||||
player.openInventory(copy);
|
||||
plugin.getMessageUtil().send(player, "messages.inventory-opened", "%player%", target.getName());
|
||||
}
|
||||
|
||||
case NAME_TAG -> {
|
||||
if (targetUuid.equals(guild.getOwner())) {
|
||||
return;
|
||||
}
|
||||
|
||||
String current = guild.getRank(targetUuid).toUpperCase();
|
||||
String next = switch (current) {
|
||||
case "MEMBER" -> "MOD";
|
||||
case "MOD" -> "ADMIN";
|
||||
case "ADMIN" -> "MEMBER";
|
||||
default -> "MEMBER";
|
||||
};
|
||||
|
||||
plugin.getGuildManager().setMemberRank(guild, targetUuid, next);
|
||||
OfflinePlayer target = Bukkit.getOfflinePlayer(targetUuid);
|
||||
String name = target.getName() == null ? targetUuid.toString() : target.getName();
|
||||
plugin.getMessageUtil().send(player, "messages.rank-updated", "%player%", name, "%rank%", next);
|
||||
new GuildMemberManageMenu(plugin).open(player, guild, targetUuid);
|
||||
}
|
||||
|
||||
case BARRIER -> {
|
||||
if (targetUuid.equals(guild.getOwner())) {
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.getGuildManager().removeMember(guild, targetUuid);
|
||||
selectedMemberTargets.remove(player.getUniqueId());
|
||||
new GuildMembersMenu(plugin).open(player, guild);
|
||||
}
|
||||
|
||||
case ARROW -> new GuildMembersMenu(plugin).open(player, guild);
|
||||
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleBankMenuClick(InventoryClickEvent event, Player player) {
|
||||
event.setCancelled(true);
|
||||
|
||||
if (event.getCurrentItem() == null || event.getCurrentItem().getType().isAir()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Guild guild = plugin.getGuildManager().getGuildByPlayer(player.getUniqueId());
|
||||
if (guild == null) {
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.getCurrentItem().getType()) {
|
||||
case LIME_DYE -> {
|
||||
player.closeInventory();
|
||||
player.performCommand("guild bank deposit 100");
|
||||
}
|
||||
case RED_DYE -> {
|
||||
player.closeInventory();
|
||||
player.performCommand("guild bank withdraw 100");
|
||||
}
|
||||
case ARROW -> new GuildMainMenu(plugin).open(player);
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleVaultMenuClick(InventoryClickEvent event) {
|
||||
// Guild vault should be editable, so do not cancel.
|
||||
}
|
||||
|
||||
private void handleLevelsMenuClick(InventoryClickEvent event, Player player) {
|
||||
event.setCancelled(true);
|
||||
|
||||
if (event.getCurrentItem() == null || event.getCurrentItem().getType().isAir()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Guild guild = plugin.getGuildManager().getGuildByPlayer(player.getUniqueId());
|
||||
if (guild == null) {
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.getCurrentItem().getType()) {
|
||||
case EMERALD -> {
|
||||
if (!guild.canManage(player.getUniqueId()) && !guild.getOwner().equals(player.getUniqueId())) {
|
||||
plugin.getMessageUtil().send(player, "messages.no-permission");
|
||||
return;
|
||||
}
|
||||
|
||||
int oldLevel = guild.getLevel();
|
||||
boolean success = plugin.getGuildManager().upgradeLevel(guild);
|
||||
|
||||
if (!success) {
|
||||
if (oldLevel >= plugin.getGuildManager().getMaxConfiguredLevel()) {
|
||||
plugin.getMessageUtil().send(player, "messages.level-maxed");
|
||||
} else {
|
||||
plugin.getMessageUtil().send(player, "messages.level-not-enough-money");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.getMessageUtil().send(player, "messages.level-upgraded", "%level%", String.valueOf(guild.getLevel()));
|
||||
new GuildLevelsMenu(plugin).open(player, guild);
|
||||
}
|
||||
case ARROW -> new GuildMainMenu(plugin).open(player);
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private UUID extractUuidFromItem(ItemMeta meta) {
|
||||
if (meta == null || meta.lore() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<String> loreLines = meta.lore().stream().map(plainText::serialize).toList();
|
||||
for (String line : loreLines) {
|
||||
if (line.startsWith("UUID:")) {
|
||||
try {
|
||||
return UUID.fromString(line.substring("UUID:".length()).trim());
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String title(String path, String fallback) {
|
||||
return plainText.serialize(MessageUtil.mm(plugin.getConfig().getString(path, fallback)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.bitnix.dirtguilds.listener;
|
||||
|
||||
import com.bitnix.dirtguilds.DirtGuildsPlugin;
|
||||
import com.bitnix.dirtguilds.guild.Guild;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
|
||||
public class GuildFriendlyFireListener implements Listener {
|
||||
|
||||
private final DirtGuildsPlugin plugin;
|
||||
|
||||
public GuildFriendlyFireListener(DirtGuildsPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDamage(EntityDamageByEntityEvent event) {
|
||||
Player attacker = getPlayer(event.getDamager());
|
||||
Player victim = getPlayer(event.getEntity());
|
||||
|
||||
if (attacker == null || victim == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Guild attackerGuild = plugin.getGuildManager().getGuildByPlayer(attacker.getUniqueId());
|
||||
Guild victimGuild = plugin.getGuildManager().getGuildByPlayer(victim.getUniqueId());
|
||||
|
||||
if (attackerGuild == null || victimGuild == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!attackerGuild.getId().equals(victimGuild.getId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!attackerGuild.isFriendlyFire()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
private Player getPlayer(Entity entity) {
|
||||
if (entity instanceof Player player) {
|
||||
return player;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.bitnix.dirtguilds.util;
|
||||
|
||||
import com.bitnix.dirtguilds.DirtGuildsPlugin;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class MessageUtil {
|
||||
|
||||
private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage();
|
||||
|
||||
private final DirtGuildsPlugin plugin;
|
||||
|
||||
public MessageUtil(DirtGuildsPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public static Component mm(String text) {
|
||||
if (text == null) {
|
||||
text = "";
|
||||
}
|
||||
return MINI_MESSAGE.deserialize(text);
|
||||
}
|
||||
|
||||
public Component parse(String text) {
|
||||
return mm(text);
|
||||
}
|
||||
|
||||
public String raw(String path) {
|
||||
return plugin.getConfig().getString(path, "");
|
||||
}
|
||||
|
||||
public String format(String path, String... replacements) {
|
||||
String text = raw(path);
|
||||
|
||||
for (int i = 0; i + 1 < replacements.length; i += 2) {
|
||||
text = text.replace(replacements[i], replacements[i + 1]);
|
||||
}
|
||||
|
||||
return raw("messages.prefix") + text;
|
||||
}
|
||||
|
||||
public void send(CommandSender sender, String path, String... replacements) {
|
||||
sender.sendMessage(parse(format(path, replacements)));
|
||||
}
|
||||
|
||||
public void sendRaw(CommandSender sender, String text) {
|
||||
sender.sendMessage(parse(text));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
database:
|
||||
type: SQLITE # SQLITE or MYSQL
|
||||
|
||||
sqlite:
|
||||
file: guilds.db
|
||||
|
||||
mysql:
|
||||
host: localhost
|
||||
port: 3306
|
||||
database: dirtguilds
|
||||
username: root
|
||||
password: change-me
|
||||
properties: "?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC"
|
||||
|
||||
settings:
|
||||
invite-expire-seconds: 120
|
||||
default-friendly-fire: false
|
||||
max-name-length: 16
|
||||
min-name-length: 3
|
||||
|
||||
bank:
|
||||
enabled: true
|
||||
use-vault: true
|
||||
|
||||
vault:
|
||||
default-size: 9
|
||||
max-size: 54
|
||||
|
||||
levels:
|
||||
enabled: true
|
||||
default-level: 1
|
||||
levels:
|
||||
1:
|
||||
cost: 0
|
||||
vault-slots: 9
|
||||
2:
|
||||
cost: 1000
|
||||
vault-slots: 18
|
||||
3:
|
||||
cost: 5000
|
||||
vault-slots: 27
|
||||
4:
|
||||
cost: 15000
|
||||
vault-slots: 36
|
||||
5:
|
||||
cost: 50000
|
||||
vault-slots: 54
|
||||
|
||||
messages:
|
||||
prefix: "<gray>[<gold>DirtGuilds</gold>]</gray> "
|
||||
|
||||
no-permission: "<red>You do not have permission.</red>"
|
||||
players-only: "<red>Only players may use this command.</red>"
|
||||
unknown-command: "<red>Unknown subcommand.</red>"
|
||||
reload: "<green>DirtGuilds reloaded.</green>"
|
||||
prefix-updated: "<green>Guild prefix updated.</green>"
|
||||
|
||||
guild-created: "<green>Guild <yellow>%guild%</yellow> created.</green>"
|
||||
guild-deleted: "<red>Guild <yellow>%guild%</yellow> deleted.</red>"
|
||||
guild-renamed: "<green>Guild renamed to <yellow>%guild%</yellow>.</green>"
|
||||
joined-guild: "<green>You joined <yellow>%guild%</yellow>.</green>"
|
||||
left-guild: "<yellow>You left your guild.</yellow>"
|
||||
already-in-guild: "<red>You are already in a guild.</red>"
|
||||
not-in-guild: "<red>You are not in a guild.</red>"
|
||||
guild-not-found: "<red>Guild not found.</red>"
|
||||
player-not-found: "<red>Player not found.</red>"
|
||||
invite-sent: "<green>Invite sent to <yellow>%player%</yellow>.</green>"
|
||||
invite-received: "<green>You were invited to join <yellow>%guild%</yellow>. Use <white>/guild accept %guild%</white>.</green>"
|
||||
no-invite: "<red>You do not have an invite for that guild.</red>"
|
||||
member-joined: "<green><yellow>%player%</yellow> joined the guild.</green>"
|
||||
member-left: "<yellow><yellow>%player%</yellow> left the guild.</yellow>"
|
||||
invalid-name: "<red>That guild name is invalid.</red>"
|
||||
name-taken: "<red>That guild name is already taken.</red>"
|
||||
must-be-owner: "<red>You must be the guild owner.</red>"
|
||||
must-be-in-guild: "<red>You must be in a guild.</red>"
|
||||
target-already-in-guild: "<red>That player is already in a guild.</red>"
|
||||
invite-expired: "<red>That invite has expired.</red>"
|
||||
friendly-fire-enabled: "<green>Guild friendly fire enabled.</green>"
|
||||
friendly-fire-disabled: "<yellow>Guild friendly fire disabled.</yellow>"
|
||||
guild-chat-enabled: "<green>Guild chat enabled.</green>"
|
||||
guild-chat-disabled: "<yellow>Guild chat disabled.</yellow>"
|
||||
|
||||
bank-deposit: "<green>Deposited <yellow>%amount%</yellow> to guild bank.</green>"
|
||||
bank-withdraw: "<green>Withdrew <yellow>%amount%</yellow> from guild bank.</green>"
|
||||
bank-invalid-amount: "<red>Invalid amount.</red>"
|
||||
bank-insufficient-funds: "<red>Your guild bank does not have enough funds.</red>"
|
||||
bank-player-insufficient-funds: "<red>You do not have enough money.</red>"
|
||||
bank-vault-unavailable: "<red>Vault economy is not available.</red>"
|
||||
|
||||
level-upgraded: "<green>Your guild upgraded to level <yellow>%level%</yellow>.</green>"
|
||||
level-maxed: "<red>Your guild is already at max level.</red>"
|
||||
level-not-enough-money: "<red>Your guild bank does not have enough money to level up.</red>"
|
||||
|
||||
teleport-success: "<green>Teleported to <yellow>%player%</yellow>.</green>"
|
||||
teleport-offline: "<red>That member is offline.</red>"
|
||||
inventory-opened: "<green>Opened inventory of <yellow>%player%</yellow>.</green>"
|
||||
|
||||
rank-updated: "<green>Updated rank for <yellow>%player%</yellow> to <yellow>%rank%</yellow>.</green>"
|
||||
|
||||
gui:
|
||||
main:
|
||||
title: "<gold>DirtGuilds</gold>"
|
||||
size: 27
|
||||
|
||||
members:
|
||||
title: "<gold>Guild Members</gold>"
|
||||
size: 54
|
||||
|
||||
member-manage:
|
||||
title: "<gold>Manage Member</gold>"
|
||||
size: 27
|
||||
|
||||
bank:
|
||||
title: "<gold>Guild Bank</gold>"
|
||||
size: 27
|
||||
|
||||
vault:
|
||||
title: "<gold>Guild Vault</gold>"
|
||||
size: 54
|
||||
|
||||
levels:
|
||||
title: "<gold>Guild Levels</gold>"
|
||||
size: 27
|
||||
@@ -0,0 +1,22 @@
|
||||
name: DirtGuilds
|
||||
version: 1.0.0
|
||||
main: com.bitnix.dirtguilds.DirtGuildsPlugin
|
||||
api-version: '1.21'
|
||||
authors: [bitnix]
|
||||
description: GUI-driven guilds plugin for Paper
|
||||
softdepend: [PlaceholderAPI, Vault]
|
||||
|
||||
commands:
|
||||
dirtguilds:
|
||||
description: Main DirtGuilds command
|
||||
usage: /dirtguilds
|
||||
aliases: [dg, guild, guilds]
|
||||
|
||||
permissions:
|
||||
dirtguilds.use:
|
||||
description: Allows use of DirtGuilds
|
||||
default: true
|
||||
|
||||
dirtguilds.admin:
|
||||
description: DirtGuilds admin permission
|
||||
default: op
|
||||
Reference in New Issue
Block a user