diff --git a/src/main/java/net/Indyuce/mmocore/MMOCore.java b/src/main/java/net/Indyuce/mmocore/MMOCore.java index bcdb492a..556714af 100644 --- a/src/main/java/net/Indyuce/mmocore/MMOCore.java +++ b/src/main/java/net/Indyuce/mmocore/MMOCore.java @@ -55,6 +55,7 @@ import net.Indyuce.mmocore.comp.worldguard.WorldGuardMMOLoader; import net.Indyuce.mmocore.comp.worldguard.WorldGuardRegionHandler; import net.Indyuce.mmocore.listener.BlockListener; import net.Indyuce.mmocore.listener.GoldPouchesListener; +import net.Indyuce.mmocore.listener.GuildListener; import net.Indyuce.mmocore.listener.LootableChestsListener; import net.Indyuce.mmocore.listener.PartyListener; import net.Indyuce.mmocore.listener.PlayerListener; @@ -107,7 +108,7 @@ public class MMOCore extends JavaPlugin { public RequestManager requestManager; public final AttributeManager attributeManager = new AttributeManager(); public final PartyManager partyManager = new PartyManager(); - public final GuildManager guildManager = new GuildManager(); + public GuildManager guildManager = new GuildManager(); public final QuestManager questManager = new QuestManager(); public ConfigItemManager configItems; public SkillManager skillManager; @@ -283,6 +284,7 @@ public class MMOCore extends JavaPlugin { Bukkit.getPluginManager().registerEvents(new LootableChestsListener(), this); Bukkit.getPluginManager().registerEvents(new SpellCast(), this); Bukkit.getPluginManager().registerEvents(new PartyListener(), this); + Bukkit.getPluginManager().registerEvents(new GuildListener(), this); Bukkit.getPluginManager().registerEvents(new FishingListener(), this); Bukkit.getPluginManager().registerEvents(new PlayerCollectStats(), this); @@ -337,6 +339,21 @@ public class MMOCore extends JavaPlugin { MMOCoreCommand mmoCoreCommand = new MMOCoreCommand(); getCommand("mmocore").setExecutor(mmoCoreCommand); getCommand("mmocore").setTabCompleter(mmoCoreCommand); + + if(getConfig().getBoolean("auto-save.enabled")) { + int autosave = getConfig().getInt("auto-save.interval") * 20; + new BukkitRunnable() { + public void run() { + for (PlayerData playerData : PlayerData.getAll()) { + ConfigFile config = new ConfigFile(playerData.getUniqueId()); + playerData.saveInConfig(config.getConfig()); + config.save(); + } + + guildManager.save(); + } + }.runTaskTimerAsynchronously(MMOCore.plugin, autosave, autosave); + } } public void onDisable() { @@ -347,6 +364,8 @@ public class MMOCore extends JavaPlugin { config.save(); } + guildManager.save(); + mineManager.resetRemainingBlocks(); } diff --git a/src/main/java/net/Indyuce/mmocore/api/ConfigFile.java b/src/main/java/net/Indyuce/mmocore/api/ConfigFile.java index 90ecba37..4c7a3d98 100644 --- a/src/main/java/net/Indyuce/mmocore/api/ConfigFile.java +++ b/src/main/java/net/Indyuce/mmocore/api/ConfigFile.java @@ -11,6 +11,7 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.player.social.guilds.Guild; public class ConfigFile { private final File file; @@ -25,6 +26,10 @@ public class ConfigFile { this(MMOCore.plugin, "/userdata", uuid.toString()); } + public ConfigFile(Guild guild) { + this(MMOCore.plugin, "/guilds", guild.getId()); + } + public ConfigFile(String name) { this(MMOCore.plugin, "", name); } @@ -48,4 +53,10 @@ public class ConfigFile { MMOCore.plugin.getLogger().log(Level.SEVERE, "Could not save " + name + ".yml!"); } } + + public void delete() { + if(file.exists()) + if(!file.delete()) + MMOCore.plugin.getLogger().log(Level.SEVERE, "Could not delete " + name + ".yml!"); + } } \ No newline at end of file diff --git a/src/main/java/net/Indyuce/mmocore/api/input/PlayerInput.java b/src/main/java/net/Indyuce/mmocore/api/input/PlayerInput.java index 7878e313..b2022267 100644 --- a/src/main/java/net/Indyuce/mmocore/api/input/PlayerInput.java +++ b/src/main/java/net/Indyuce/mmocore/api/input/PlayerInput.java @@ -32,7 +32,9 @@ public abstract class PlayerInput implements Listener { FRIEND_REQUEST, PARTY_INVITE, - GUILD_INVITE; + GUILD_INVITE, + GUILD_CREATION_TAG, + GUILD_CREATION_NAME; public String getLowerCaseName() { return name().toLowerCase().replace("_", "-"); diff --git a/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index b19b9868..f2465958 100644 --- a/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -112,6 +112,7 @@ public class PlayerData { this.mana = getStats().getStat(StatType.MAX_MANA); this.stamina = getStats().getStat(StatType.MAX_STAMINA); this.stellium = getStats().getStat(StatType.MAX_STELLIUM); + if (config.contains("guild")) this.guild = MMOCore.plugin.guildManager.stillInGuild(getUniqueId(), config.getString("guild")); if (config.contains("attribute")) attributes.load(config.getConfigurationSection("attribute")); if (config.contains("profession")) @@ -157,7 +158,10 @@ public class PlayerData { config.set("class", profess == null ? null : profess.getId()); config.set("waypoints", new ArrayList<>(waypoints)); config.set("friends", toStringList(friends)); - + config.set("last-login", lastLogin); + if(guild != null) config.set("guild", guild.getId()); + else config.set("guild", null); + config.set("skill", null); skills.entrySet().forEach(entry -> config.set("skill." + entry.getKey(), entry.getValue())); @@ -239,6 +243,44 @@ public class PlayerData { return playerData.values(); } + /** + * START OF EXPERIMENTAL CODE + * + * This must be more simple to do than my 2AM brain could think of... + * - Aria + */ + + private static Map offlineValues = new HashMap<>(); + public static PlayerDataOfflineValues getOfflineValues(UUID uuid) { + if(!offlineValues.containsKey(uuid)) + offlineValues.put(uuid, new PlayerDataOfflineValues(uuid)); + return offlineValues.get(uuid) ; + } + + public static class PlayerDataOfflineValues { + // Values can be added as they are needed + private final PlayerClass profess; + private final int level; + private final long lastLogin; + + public PlayerDataOfflineValues(UUID uuid) { + FileConfiguration config = new ConfigFile(uuid).getConfig(); + this.profess = MMOCore.plugin.classManager.get(config.getString("class")); + this.level = config.getInt("level"); + this.lastLogin = config.getLong("last-login"); + } + + public PlayerClass getProfess() + { return profess; } + public int getLevel() + { return level; } + public long getLastLogin() + { return lastLogin; } + } + /** + * END OF EXPERIMENTAL CODE + */ + public PlayerData setPlayer(Player player) { this.player = player; this.lastLogin = System.currentTimeMillis(); diff --git a/src/main/java/net/Indyuce/mmocore/api/player/social/guilds/Guild.java b/src/main/java/net/Indyuce/mmocore/api/player/social/guilds/Guild.java index d89cdd0c..0ee5f6cc 100644 --- a/src/main/java/net/Indyuce/mmocore/api/player/social/guilds/Guild.java +++ b/src/main/java/net/Indyuce/mmocore/api/player/social/guilds/Guild.java @@ -7,6 +7,8 @@ import java.util.Map; import java.util.UUID; import java.util.function.Consumer; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import net.Indyuce.mmocore.MMOCore; @@ -20,23 +22,24 @@ import net.Indyuce.mmocore.manager.InventoryManager; public class Guild { private final GuildMembers members = new GuildMembers(); private final Map invites = new HashMap<>(); - private String guildName; + private String guildId, guildName, guildTag; /* * owner changes when the old owner leaves guild */ - private PlayerData owner; + private UUID owner; // used to check if two parties are the same // private UUID uuid = UUID.randomUUID(); - public Guild(PlayerData owner, String name) { + public Guild(UUID owner, String name, String tag) { this.owner = owner; + this.guildId = tag.toLowerCase(); this.guildName = name; - addMember(owner); + this.guildTag = tag; } - public PlayerData getOwner() { + public UUID getOwner() { return owner; } @@ -44,6 +47,14 @@ public class Guild { return guildName; } + public String getId() { + return guildId; + } + + public String getTag() { + return guildTag; + } + public GuildMembers getMembers() { return members; } @@ -56,42 +67,63 @@ public class Guild { invites.remove(player.getUniqueId()); } - public void removeMember(PlayerData data) { - if (data.isOnline() && data.getPlayer().getOpenInventory() != null && data.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof GuildViewInventory) + //public void disband() { + //for(UUID uuid : getMembers().members) + // removeMember(uuid, true); + + + //} + + //public void removeMember(UUID uuid) + //{ removeMember(uuid, false); } + + public void removeMember(UUID uuid) {//, boolean disband) { + PlayerData data = PlayerData.get(uuid); + if (data != null && data.isOnline() && data.getPlayer().getOpenInventory() != null && data.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof GuildViewInventory) InventoryManager.GUILD_CREATION.newInventory(data).open(); - members.remove(data); - data.setGuild(null); - + members.remove(uuid); + if(data != null) data.setGuild(null); reopenInventories(); - // disband the guild if no member left - if (members.count() < 1) { - MMOCore.plugin.guildManager.unregisterGuild(this); - return; - } + //if(!disband) { - // transfer ownership - if (owner.equals(data)) { - owner = members.get(0); - MMOCore.plugin.configManager.getSimpleMessage("transfer-guild-ownership").send(owner.getPlayer()); - } + // disband the guild if no member left + if (members.count() < 1) { + MMOCore.plugin.guildManager.unregisterGuild(this); + return; + } + + // transfer ownership + if (owner.equals(uuid)) { + owner = members.get(0); + MMOCore.plugin.configManager.getSimpleMessage("transfer-guild-ownership").send(Bukkit.getPlayer(owner)); + } + //} } - public void addMember(PlayerData data) { + public void addMember(UUID uuid) { + PlayerData data = PlayerData.get(uuid); if (data.inGuild()) - data.getGuild().removeMember(data); + data.getGuild().removeMember(uuid); data.setGuild(this); - members.add(data); + members.add(uuid); reopenInventories(); } + + public void registerMember(UUID uuid) { + MMOCore.log("Registered Member"); + members.add(uuid); + } public void reopenInventories() { - for (PlayerData member : members.members) - if (member.isOnline() && member.getPlayer().getOpenInventory() != null && member.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof GuildViewInventory) + for (UUID uuid : members.members) { + PlayerData member = PlayerData.get(uuid); + if (member != null && member.isOnline() && member.getPlayer().getOpenInventory() != null && member.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof GuildViewInventory) ((PluginInventory) member.getPlayer().getOpenInventory().getTopInventory().getHolder()).open(); + } } public void sendGuildInvite(PlayerData inviter, PlayerData target) { @@ -101,31 +133,53 @@ public class Guild { MMOCore.plugin.requestManager.registerRequest(request); } + public void saveInConfig(FileConfiguration config) { + config.set("name", guildName); + config.set("tag", guildTag); + config.set("owner", owner.toString()); + + List memberList = new ArrayList<>(); + for(UUID uuid : members.members) + memberList.add(uuid.toString()); + + config.set("members", memberList); + } + public class GuildMembers { - private final List members = new ArrayList<>(); + private final List members = new ArrayList<>(); - public PlayerData get(int count) { + public UUID get(int count) { return members.get(count); } - public boolean has(PlayerData player) { + public boolean has(UUID player) { return members.contains(player); } - public void add(PlayerData player) { + public void add(UUID player) { members.add(player); } - public void remove(PlayerData player) { + public void remove(UUID player) { members.remove(player); } - public void forEach(Consumer action) { + public void forEach(Consumer action) { members.forEach(action); } public int count() { return members.size(); } + + public int countOnline() { + int online = 0; + + for(UUID member : members) + if(Bukkit.getOfflinePlayer(member).isOnline()) + online += 1; + + return online; + } } } diff --git a/src/main/java/net/Indyuce/mmocore/api/player/social/guilds/GuildInvite.java b/src/main/java/net/Indyuce/mmocore/api/player/social/guilds/GuildInvite.java index 607052fd..ecf971ef 100644 --- a/src/main/java/net/Indyuce/mmocore/api/player/social/guilds/GuildInvite.java +++ b/src/main/java/net/Indyuce/mmocore/api/player/social/guilds/GuildInvite.java @@ -1,5 +1,7 @@ package net.Indyuce.mmocore.api.player.social.guilds; +import org.bukkit.Bukkit; + import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.social.Request; @@ -30,9 +32,9 @@ public class GuildInvite extends Request { public void accept() { guild.removeLastInvite(getCreator().getPlayer()); - guild.getMembers().forEach(member -> MMOCore.plugin.configManager.getSimpleMessage("guild-joined-other", "player", target.getPlayer().getName()).send(member.getPlayer())); - MMOCore.plugin.configManager.getSimpleMessage("guild-joined", "owner", guild.getOwner().getPlayer().getName()).send(target.getPlayer()); - guild.addMember(target); + guild.getMembers().forEach(member -> MMOCore.plugin.configManager.getSimpleMessage("guild-joined-other", "player", target.getPlayer().getName()).send(Bukkit.getPlayer(member))); + MMOCore.plugin.configManager.getSimpleMessage("guild-joined", "owner", Bukkit.getPlayer(guild.getOwner()).getName()).send(target.getPlayer()); + guild.addMember(target.getUniqueId()); InventoryManager.GUILD_VIEW.newInventory(target).open(); MMOCore.plugin.requestManager.unregisterRequest(getUniqueId()); } diff --git a/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildAdmin.java b/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildAdmin.java new file mode 100644 index 00000000..3f9aa288 --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildAdmin.java @@ -0,0 +1,188 @@ +package net.Indyuce.mmocore.gui.social.guild; + +import java.util.UUID; + +import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.Sound; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryAction; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.SkullMeta; + +import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.input.PlayerInput.InputType; +import net.Indyuce.mmocore.api.item.NBTItem; +import net.Indyuce.mmocore.api.math.format.DelayFormat; +import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.gui.api.EditableInventory; +import net.Indyuce.mmocore.gui.api.GeneratedInventory; +import net.Indyuce.mmocore.gui.api.PluginInventory; +import net.Indyuce.mmocore.gui.api.item.InventoryItem; +import net.Indyuce.mmocore.gui.api.item.InventoryPlaceholderItem; +import net.Indyuce.mmocore.gui.api.item.NoPlaceholderItem; +import net.Indyuce.mmocore.gui.api.item.Placeholders; +import net.Indyuce.mmocore.version.nms.ItemTag; + +public class EditableGuildAdmin extends EditableInventory { + public EditableGuildAdmin() { + super("guild-admin"); + } + + @Override + public InventoryItem load(String function, ConfigurationSection config) { + return function.equals("member") ? new MemberItem(config) : new NoPlaceholderItem(config); + } + + public class MemberDisplayItem extends InventoryPlaceholderItem { + public MemberDisplayItem(ConfigurationSection config) { + super(config); + } + + @Override + public Placeholders getPlaceholders(PluginInventory inv, int n) { + PlayerData member = PlayerData.get(inv.getPlayerData().getGuild().getMembers().get(n)); + + Placeholders holders = new Placeholders(); + holders.register("name", member.getPlayer().getName()); + holders.register("class", member.getProfess().getName()); + holders.register("level", "" + member.getLevel()); + holders.register("since", new DelayFormat(2).format(System.currentTimeMillis() - member.getLastLogin())); + return holders; + } + + @Override + public ItemStack display(GeneratedInventory inv, int n) { + PlayerData member = PlayerData.get(inv.getPlayerData().getGuild().getMembers().get(n)); + + ItemStack disp = super.display(inv, n); + ItemMeta meta = disp.getItemMeta(); + + /* + * run async to save performance + */ + if (meta instanceof SkullMeta) { + ((SkullMeta) meta).setOwningPlayer(member.getPlayer()); + disp.setItemMeta(meta); + } + + return NBTItem.get(disp).add(new ItemTag("uuid", member.getUniqueId().toString())).toItem(); + } + } + + public class MemberItem extends InventoryItem { + private final InventoryPlaceholderItem empty; + private final MemberDisplayItem member; + + public MemberItem(ConfigurationSection config) { + super(config); + + Validate.notNull(config.contains("empty"), "Could not load empty config"); + Validate.notNull(config.contains("member"), "Could not load member config"); + + empty = new NoPlaceholderItem(config.getConfigurationSection("empty")); + member = new MemberDisplayItem(config.getConfigurationSection("member")); + } + + @Override + public ItemStack display(GeneratedInventory inv, int n) { + return inv.getPlayerData().getGuild().getMembers().count() > n ? member.display(inv, n) : empty.display(inv, n); + } + + @Override + public boolean hasDifferentDisplay() { + return true; + } + + @Override + public boolean canDisplay(GeneratedInventory inv) { + return true; + } + } + + public GeneratedInventory newInventory(PlayerData data) { + return new GuildViewInventory(data, this); + } + + public class GuildViewInventory extends GeneratedInventory { + private final int max; + + public GuildViewInventory(PlayerData playerData, EditableInventory editable) { + super(playerData, editable); + + max = editable.getByFunction("member").getSlots().size(); + } + + @Override + public String calculateName() { + return getName().replace("{max}", "" + max).replace("{players}", "" + getPlayerData().getGuild().getMembers().count()); + } + + @Override + public void whenClicked(InventoryClickEvent event, InventoryItem item) { + + if (item.getFunction().equals("leave")) { + playerData.getGuild().removeMember(playerData.getUniqueId()); + player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1); + player.closeInventory(); + return; + } + + if (item.getFunction().equals("invite")) { + + if (playerData.getGuild().getMembers().count() >= max) { + MMOCore.plugin.configManager.getSimpleMessage("guild-is-full").send(player); + player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 1); + return; + } + + MMOCore.plugin.configManager.newPlayerInput(player, InputType.GUILD_INVITE, (input) -> { + Player target = Bukkit.getPlayer(input); + if (target == null) { + MMOCore.plugin.configManager.getSimpleMessage("not-online-player", "player", input).send(player); + player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 1); + open(); + return; + } + + long remaining = playerData.getGuild().getLastInvite(target) + 60 * 2 * 1000 - System.currentTimeMillis(); + if (remaining > 0) { + MMOCore.plugin.configManager.getSimpleMessage("guild-invite-cooldown", "player", target.getName(), "cooldown", new DelayFormat().format(remaining)).send(player); + open(); + return; + } + + PlayerData targetData = PlayerData.get(target); + if (playerData.getGuild().getMembers().has(target.getUniqueId())) { + MMOCore.plugin.configManager.getSimpleMessage("already-in-guild", "player", target.getName()).send(player); + player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 1); + open(); + return; + } + + playerData.getGuild().sendGuildInvite(playerData, targetData); + MMOCore.plugin.configManager.getSimpleMessage("sent-guild-invite", "player", target.getName()).send(player); + player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1); + open(); + }); + } + + if (item.getFunction().equals("member") && event.getAction() == InventoryAction.PICKUP_HALF) { + if (!playerData.getGuild().getOwner().equals(playerData.getUniqueId())) + return; + + OfflinePlayer target = Bukkit.getOfflinePlayer(UUID.fromString(NBTItem.get(event.getCurrentItem()).getString("uuid"))); + if (target.equals(player)) + return; + + playerData.getGuild().removeMember(target.getUniqueId()); + MMOCore.plugin.configManager.getSimpleMessage("kick-from-guild", "player", target.getName()).send(player); + player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1); + } + } + } +} diff --git a/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildCreation.java b/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildCreation.java index 726ee2ec..972ca29c 100644 --- a/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildCreation.java +++ b/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildCreation.java @@ -2,15 +2,18 @@ package net.Indyuce.mmocore.gui.social.guild; import org.bukkit.Sound; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.input.PlayerInput.InputType; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.gui.api.EditableInventory; import net.Indyuce.mmocore.gui.api.GeneratedInventory; import net.Indyuce.mmocore.gui.api.item.InventoryItem; import net.Indyuce.mmocore.gui.api.item.NoPlaceholderItem; import net.Indyuce.mmocore.manager.InventoryManager; +import net.Indyuce.mmocore.manager.social.GuildManager.GuildConfiguration.NamingRules; public class EditableGuildCreation extends EditableInventory { public EditableGuildCreation() { @@ -37,9 +40,26 @@ public class EditableGuildCreation extends EditableInventory { return; if (item.getFunction().equals("create")) { - MMOCore.plugin.guildManager.newRegisteredGuild(playerData, "test"); - InventoryManager.GUILD_VIEW.newInventory(playerData).open(); - player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1); + MMOCore.plugin.configManager.newPlayerInput(player, InputType.GUILD_CREATION_TAG, (input) -> { + if(MMOCore.plugin.guildManager.getConfig().shouldUppercaseTags()) + input = input.toUpperCase(); + + if(check(player, input, MMOCore.plugin.guildManager.getConfig().getTagRules())) { + String tag = input; + + MMOCore.plugin.configManager.newPlayerInput(player, InputType.GUILD_CREATION_NAME, (name) -> { + if(check(player, name, MMOCore.plugin.guildManager.getConfig().getNameRules())) { + MMOCore.plugin.guildManager.newRegisteredGuild(playerData.getUniqueId(), name, tag); + MMOCore.plugin.guildManager.getGuild(tag.toLowerCase()).addMember(playerData.getUniqueId()); + + InventoryManager.GUILD_VIEW.newInventory(playerData).open(); + player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1); + } + }); + } + }); + + return; } if (item.getFunction().equals("back")) @@ -51,4 +71,22 @@ public class EditableGuildCreation extends EditableInventory { return getName(); } } + + public boolean check(Player player, String input, NamingRules rules) { + String reason; + + if(input.length() <= rules.getMax() && input.length() >= rules.getMin()) + if(input.matches(rules.getRegex())) + if(!MMOCore.plugin.guildManager.isRegistered(input)) + return true; + else + reason = MMOCore.plugin.configManager.getSimpleMessage("guild-creation.reasons.already-taken").message(); + else + reason = MMOCore.plugin.configManager.getSimpleMessage("guild-creation.reasons.invalid-characters").message(); + else + reason = MMOCore.plugin.configManager.getSimpleMessage("guild-creation.reasons.invalid-length", "min", "" + rules.getMin(), "max", "" + rules.getMax()).message(); + + MMOCore.plugin.configManager.getSimpleMessage("guild-creation.failed", "reason", reason).send(player); + return false; + } } diff --git a/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildView.java b/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildView.java index 0cf20e4f..20e73f26 100644 --- a/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildView.java +++ b/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildView.java @@ -19,6 +19,7 @@ import net.Indyuce.mmocore.api.input.PlayerInput.InputType; import net.Indyuce.mmocore.api.item.NBTItem; import net.Indyuce.mmocore.api.math.format.DelayFormat; import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.api.player.PlayerData.PlayerDataOfflineValues; import net.Indyuce.mmocore.gui.api.EditableInventory; import net.Indyuce.mmocore.gui.api.GeneratedInventory; import net.Indyuce.mmocore.gui.api.PluginInventory; @@ -35,7 +36,8 @@ public class EditableGuildView extends EditableInventory { @Override public InventoryItem load(String function, ConfigurationSection config) { - return function.equals("member") ? new MemberItem(config) : new NoPlaceholderItem(config); + return function.equals("member") ? new MemberItem(config) : (function.equals("next") || function.equals("previous") + || function.equals("disband") || function.equals("invite")) ? new ConditionalItem(function, config) : new NoPlaceholderItem(config); } public class MemberDisplayItem extends InventoryPlaceholderItem { @@ -45,19 +47,34 @@ public class EditableGuildView extends EditableInventory { @Override public Placeholders getPlaceholders(PluginInventory inv, int n) { - PlayerData member = inv.getPlayerData().getGuild().getMembers().get(n); - + UUID uuid = inv.getPlayerData().getGuild().getMembers().get(n); Placeholders holders = new Placeholders(); - holders.register("name", member.getPlayer().getName()); - holders.register("class", member.getProfess().getName()); - holders.register("level", "" + member.getLevel()); - holders.register("since", new DelayFormat(2).format(System.currentTimeMillis() - member.getLastLogin())); + /** + * Will never be null since a players name + * will always be recorded if they've been in a guild + */ + holders.register("name", Bukkit.getOfflinePlayer(uuid).getName()); + + if(PlayerData.get(uuid) == null) { + PlayerDataOfflineValues pdov = PlayerData.getOfflineValues(uuid); + holders.register("class", pdov.getProfess().getName()); + holders.register("level", "" + pdov.getLevel()); + holders.register("since", new DelayFormat(2).format(System.currentTimeMillis() - pdov.getLastLogin())); + } + else + { + PlayerData member = PlayerData.get(uuid); + holders.register("class", member.getProfess().getName()); + holders.register("level", "" + member.getLevel()); + holders.register("since", new DelayFormat(2).format(System.currentTimeMillis() - member.getLastLogin())); + } + return holders; } @Override public ItemStack display(GeneratedInventory inv, int n) { - PlayerData member = inv.getPlayerData().getGuild().getMembers().get(n); + UUID uuid = inv.getPlayerData().getGuild().getMembers().get(n); ItemStack disp = super.display(inv, n); ItemMeta meta = disp.getItemMeta(); @@ -66,11 +83,11 @@ public class EditableGuildView extends EditableInventory { * run async to save performance */ if (meta instanceof SkullMeta) { - ((SkullMeta) meta).setOwningPlayer(member.getPlayer()); + ((SkullMeta) meta).setOwningPlayer(Bukkit.getOfflinePlayer(uuid)); disp.setItemMeta(meta); } - return NBTItem.get(disp).add(new ItemTag("uuid", member.getUniqueId().toString())).toItem(); + return NBTItem.get(disp).add(new ItemTag("uuid", uuid.toString())).toItem(); } } @@ -90,7 +107,8 @@ public class EditableGuildView extends EditableInventory { @Override public ItemStack display(GeneratedInventory inv, int n) { - return inv.getPlayerData().getGuild().getMembers().count() > n ? member.display(inv, n) : empty.display(inv, n); + int index = n * ((GuildViewInventory) inv).getPage(); + return inv.getPlayerData().getGuild().getMembers().count() > index ? member.display(inv, index) : empty.display(inv, index); } @Override @@ -103,42 +121,94 @@ public class EditableGuildView extends EditableInventory { return true; } } + + public class ConditionalItem extends NoPlaceholderItem { + private final String function; + + public ConditionalItem(String func, ConfigurationSection config) { + super(config); + this.function = func; + } + + @Override + public ItemStack display(GeneratedInventory invpar, int n) { + GuildViewInventory inv = (GuildViewInventory) invpar; + + int maxpages = (int) Math.ceil((inv.getPlayerData().getGuild().getMembers().count() + 20) / inv.getByFunction("member").getSlots().size()); + MMOCore.log("Member Slots: " + inv.getByFunction("member").getSlots().size()); + MMOCore.log("Member Count: " + inv.getPlayerData().getGuild().getMembers().count()); + MMOCore.log("Max Pages: " + maxpages); + + if(function.equals("next") && inv.getPage() == maxpages) + return null; + if(function.equals("previous") && inv.getPage() == 1) + return null; + if((function.equals("disband") || function.equals("invite")) && !inv.getPlayerData() + .getGuild().getOwner().equals(inv.getPlayer().getUniqueId())) + return null; + return super.display(inv, n); + } + } public GeneratedInventory newInventory(PlayerData data) { return new GuildViewInventory(data, this); } public class GuildViewInventory extends GeneratedInventory { - private final int max; + private int page = 1; + private final int maxpages; public GuildViewInventory(PlayerData playerData, EditableInventory editable) { super(playerData, editable); - max = editable.getByFunction("member").getSlots().size(); + maxpages = (int) Math.ceil((playerData.getGuild().getMembers().count() + 20) / + editable.getByFunction("member").getSlots().size()); } @Override public String calculateName() { - return getName().replace("{max}", "" + max).replace("{players}", "" + getPlayerData().getGuild().getMembers().count()); + return getName() + .replace("{online_players}", "" + getPlayerData().getGuild().getMembers().countOnline()) + .replace("{page}", "" + page) + .replace("{maxpages}", "" + maxpages) + .replace("{players}", "" + getPlayerData().getGuild().getMembers().count()) + .replace("{tag}", getPlayerData().getGuild().getTag()) + .replace("{name}", getPlayerData().getGuild().getName()); } @Override public void whenClicked(InventoryClickEvent event, InventoryItem item) { - if (item.getFunction().equals("leave")) { - playerData.getGuild().removeMember(playerData); + playerData.getGuild().removeMember(playerData.getUniqueId()); player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1); player.closeInventory(); return; } + + if (item.getFunction().equals("next") && page != maxpages) + { page++; open(); return; } + if (item.getFunction().equals("previous") && page != 1) + { page--; open(); return; } + + if (item.getFunction().equals("disband")) { + if (!playerData.getGuild().getOwner().equals(playerData.getUniqueId())) + return; + MMOCore.plugin.guildManager.unregisterGuild(playerData.getGuild()); + player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1); + player.closeInventory(); + return; + } + if (item.getFunction().equals("invite")) { - - if (playerData.getGuild().getMembers().count() >= max) { + if (!playerData.getGuild().getOwner().equals(playerData.getUniqueId())) + return; + + /**if (playerData.getGuild().getMembers().count() >= max) { MMOCore.plugin.configManager.getSimpleMessage("guild-is-full").send(player); player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 1); return; - } + }*/ MMOCore.plugin.configManager.newPlayerInput(player, InputType.GUILD_INVITE, (input) -> { Player target = Bukkit.getPlayer(input); @@ -157,7 +227,7 @@ public class EditableGuildView extends EditableInventory { } PlayerData targetData = PlayerData.get(target); - if (playerData.getGuild().getMembers().has(targetData)) { + if (playerData.getGuild().getMembers().has(targetData.getUniqueId())) { MMOCore.plugin.configManager.getSimpleMessage("already-in-guild", "player", target.getName()).send(player); player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 1); open(); @@ -171,18 +241,21 @@ public class EditableGuildView extends EditableInventory { }); } - if (item.getFunction().equals("member") && event.getAction() == InventoryAction.PICKUP_HALF) { - if (!playerData.getGuild().getOwner().equals(playerData)) + if (item.getFunction().equals("member") && event.getAction() == InventoryAction.PICKUP_HALF && !NBTItem.get(event.getCurrentItem()).getString("uuid").isEmpty()) { + if (!playerData.getGuild().getOwner().equals(playerData.getUniqueId())) return; - + OfflinePlayer target = Bukkit.getOfflinePlayer(UUID.fromString(NBTItem.get(event.getCurrentItem()).getString("uuid"))); if (target.equals(player)) return; - playerData.getGuild().removeMember(PlayerData.get(target)); + playerData.getGuild().removeMember(target.getUniqueId()); MMOCore.plugin.configManager.getSimpleMessage("kick-from-guild", "player", target.getName()).send(player); player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1); } } + + public int getPage() + { return page; } } } diff --git a/src/main/java/net/Indyuce/mmocore/listener/GuildListener.java b/src/main/java/net/Indyuce/mmocore/listener/GuildListener.java index 66491228..250c20bb 100644 --- a/src/main/java/net/Indyuce/mmocore/listener/GuildListener.java +++ b/src/main/java/net/Indyuce/mmocore/listener/GuildListener.java @@ -1,6 +1,7 @@ package net.Indyuce.mmocore.listener; import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -12,10 +13,9 @@ import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.manager.ConfigManager.SimpleMessage; public class GuildListener implements Listener { - @EventHandler(priority = EventPriority.LOW) public void a(AsyncPlayerChatEvent event) { - if (!event.getMessage().startsWith(MMOCore.plugin.configManager.guildChatPrefix)) + if (!event.getMessage().startsWith(MMOCore.plugin.guildManager.getConfig().getPrefix())) return; PlayerData data = PlayerData.get(event.getPlayer()); @@ -28,14 +28,15 @@ public class GuildListener implements Listener { * running it in a delayed task is recommended */ Bukkit.getScheduler().scheduleSyncDelayedTask(MMOCore.plugin, () -> { - SimpleMessage format = MMOCore.plugin.configManager.getSimpleMessage("guild-chat", "player", data.getPlayer().getName(), "message", event.getMessage().substring(MMOCore.plugin.configManager.guildChatPrefix.length())); + SimpleMessage format = MMOCore.plugin.configManager.getSimpleMessage("guild-chat", "player", data.getPlayer().getName(), "tag", data.getGuild().getTag(), "message", event.getMessage().substring(MMOCore.plugin.guildManager.getConfig().getPrefix().length())); GuildChatEvent called = new GuildChatEvent(data, format.message()); Bukkit.getPluginManager().callEvent(called); - if (!called.isCancelled()) ; //remove - //data.getGuild().members.forEach(member -> { - //if (member.isOnline()) - // format.send(member.getPlayer()); - //}); + if (!called.isCancelled()) + data.getGuild().getMembers().forEach(member -> { + Player p = Bukkit.getPlayer(member); + if (p != null) + format.send(p); + }); }); } } diff --git a/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java b/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java index 450174b9..18771fe6 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java +++ b/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java @@ -29,7 +29,7 @@ public class ConfigManager { public float speedMalus; public boolean overrideVanillaExp, hotbarSwap; public double expPartyBuff, regenPartyBuff; - public String partyChatPrefix, guildChatPrefix; + public String partyChatPrefix; public ChatColor manaFull, manaHalf, manaEmpty, staminaFull, staminaHalf, staminaEmpty; public final DecimalFormatSymbols formatSymbols = new DecimalFormatSymbols(); @@ -88,6 +88,7 @@ public class ConfigManager { loadDefaultFile("restrictions.yml"); loadDefaultFile("chests.yml"); loadDefaultFile("commands.yml"); + loadDefaultFile("guilds.yml"); loadOptions(); } @@ -100,7 +101,6 @@ public class ConfigManager { expPartyBuff = MMOCore.plugin.getConfig().getDouble("party.buff.experience"); regenPartyBuff = MMOCore.plugin.getConfig().getDouble("party.buff.health-regen"); partyChatPrefix = MMOCore.plugin.getConfig().getString("party.chat-prefix"); - guildChatPrefix = MMOCore.plugin.getConfig().getString("guilds.chat-prefix"); formatSymbols.setDecimalSeparator(getFirstChar(MMOCore.plugin.getConfig().getString("number-format.decimal-separator"), ',')); manaFull = getColorOrDefault("mana-whole", ChatColor.BLUE); diff --git a/src/main/java/net/Indyuce/mmocore/manager/social/GuildManager.java b/src/main/java/net/Indyuce/mmocore/manager/social/GuildManager.java index 7e7a649f..9427300a 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/social/GuildManager.java +++ b/src/main/java/net/Indyuce/mmocore/manager/social/GuildManager.java @@ -1,39 +1,128 @@ package net.Indyuce.mmocore.manager.social; -import java.util.HashSet; -import java.util.Set; +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; -import net.Indyuce.mmocore.api.player.PlayerData; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.ConfigFile; import net.Indyuce.mmocore.api.player.social.guilds.Guild; import net.Indyuce.mmocore.manager.MMOManager; public class GuildManager extends MMOManager { - private final Set guilds = new HashSet<>(); + private final Map guilds = new HashMap<>(); + private GuildConfiguration config; - public void registerGuild(Guild guild) { - guilds.add(guild); - } - - public Guild newRegisteredGuild(PlayerData owner, String name) { - Guild guild = new Guild(owner, name); + public Guild newRegisteredGuild(UUID owner, String name, String tag) { + Guild guild = new Guild(owner, name, tag); registerGuild(guild); return guild; } - public boolean isRegistered(Guild guild) { - return guilds.contains(guild); + public void registerGuild(Guild guild) { + guilds.put(guild.getId(), guild); } + public boolean isRegistered(Guild guild) { + return guilds.containsValue(guild); + } + + public boolean isRegistered(String tag) { + return guilds.containsKey(tag); + } + public void unregisterGuild(Guild guild) { guild.getMembers().forEach(member -> guild.removeMember(member)); - guilds.remove(guild); + guilds.remove(guild.getId()); + + new ConfigFile(guild).delete(); } + public void save() { + for(Guild guild : guilds.values()) { + ConfigFile config = new ConfigFile(guild); + guild.saveInConfig(config.getConfig()); + config.save(); + } + } + + public GuildConfiguration getConfig() + { return config; } + @Override public void reload() { + config = new GuildConfiguration(); + + File guildsFolder = new File(MMOCore.plugin.getDataFolder(), "guilds"); + if(!guildsFolder.exists()) guildsFolder.mkdirs(); + for (File file : guildsFolder.listFiles()) { + if (!file.isDirectory() && file.getName().substring(file.getName().lastIndexOf('.')).equalsIgnoreCase(".yml")) { + FileConfiguration c = YamlConfiguration.loadConfiguration(file); + Guild guild = newRegisteredGuild(UUID.fromString(c.getString("owner")), c.getString("name"), c.getString("tag")); + for(String m : c.getStringList("members")) + guild.registerMember(UUID.fromString(m)); + } + } } @Override - public void clear() { + public void clear() { } + + public Guild getGuild(String guild) + { return guilds.get(guild); } + + public class GuildConfiguration { + private final String prefix; + private final boolean uppercaseTags; + private final NamingRules tagRules, nameRules; + + public GuildConfiguration() { + FileConfiguration config = new ConfigFile("guilds").getConfig(); + + prefix = config.getString("chat-prefix", "*"); + uppercaseTags = config.getBoolean("uppercase-tags", true); + tagRules = new NamingRules(config.getConfigurationSection("rules.tag")); + nameRules = new NamingRules(config.getConfigurationSection("rules.name")); + } + + public String getPrefix() + { return prefix; } + public boolean shouldUppercaseTags() + { return uppercaseTags; } + public NamingRules getTagRules() + { return tagRules; } + public NamingRules getNameRules() + { return nameRules; } + + public class NamingRules { + private final String regex; + private final int min, max; + + public NamingRules(ConfigurationSection config) { + regex = config.getString("matches", "[a-zA-Z-_!?]+"); + min = config.getInt("min-length", 3); + max = config.getInt("max-length", 5); + } + + public String getRegex() + { return regex; } + public int getMin() + { return min; } + public int getMax() + { return max; } + } + } + + // Used to check if player was kicked while offline + public Guild stillInGuild(UUID uuid, String id) { + Guild guild = getGuild(id); + if(guild.getMembers().has(uuid)) + return guild; + return null; } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 59bce6fa..c945fa7c 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,3 +1,11 @@ +# Auto-Save feature automatically saves +# playerdata (class, level, etc.) and +# guild data (guild names, members, etc.) +# at a set interval. +auto-save: + enabled: true + # In seconds (1800 = 30 minutes) + interval: 1800 # Wearing heavy pieces of armors reduces # your movement speed by a specific amount, @@ -59,12 +67,6 @@ party: # to talk in the party chat. chat-prefix: '@' -guilds: - - # Prefix you need to put in the chat - # to talk in the guild chat. - chat-prefix: '*' - # Enable this open to override vanilla EXP and display # level progress on the vanilla experience bar. # Requires a SERVER reload when changed. diff --git a/src/main/resources/default/gui/guild-view.yml b/src/main/resources/default/gui/guild-view.yml index 7d88dd6f..73ba77b4 100644 --- a/src/main/resources/default/gui/guild-view.yml +++ b/src/main/resources/default/gui/guild-view.yml @@ -1,6 +1,6 @@ # GUI display name -name: Guild ({players}/{max}) +name: '&0[&8{tag}&0] &8{name} &0- &8(&7{page}&8/&7{maxpages}&8)' # Number of slots in your inventory. Must be # between 9 and 54 and must be a multiple of 9. @@ -8,7 +8,7 @@ slots: 54 items: member: - slots: [10,12,14,16,28,30,32,34] + slots: [10,11,12,13,14,15,16,19,20,21,22,23,24,25,28,29,30,31,32,33,34] function: member empty: item: GRAY_STAINED_GLASS_PANE @@ -16,18 +16,41 @@ items: member: item: PLAYER_HEAD name: '&a{name}' + #leader-name: '&a{name} &c[&aLeader&c]' - Unused right now lore: - '&7Level {level} {class}' - '&7Online Since: {since}' + next: + slots: [26] + function: next + item: PLAYER_HEAD + texture: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTliZjMyOTJlMTI2YTEwNWI1NGViYTcxM2FhMWIxNTJkNTQxYTFkODkzODgyOWM1NjM2NGQxNzhlZDIyYmYifX19 + name: '&aNext Page' + lore: [] + previous: + slots: [18] + function: previous + item: PLAYER_HEAD + texture: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmQ2OWUwNmU1ZGFkZmQ4NGU1ZjNkMWMyMTA2M2YyNTUzYjJmYTk0NWVlMWQ0ZDcxNTJmZGM1NDI1YmMxMmE5In19fQ== + name: '&aPrevious Page' + lore: [] leave: - slots: [50] + slots: [49] function: leave item: REDSTONE name: '&cLeave Guild' - lore: {} + lore: [] + + #Request and Disband are only available to the Guild Leader + disband: + slots: [51] + function: disband + item: BARRIER + name: '&cDisband Guild' + lore: [] request: - slots: [48] + slots: [47] function: invite item: WRITABLE_BOOK name: '&aInvite a player..' - lore: {} \ No newline at end of file + lore: [] \ No newline at end of file diff --git a/src/main/resources/default/guilds.yml b/src/main/resources/default/guilds.yml new file mode 100644 index 00000000..77177910 --- /dev/null +++ b/src/main/resources/default/guilds.yml @@ -0,0 +1,41 @@ +# WARNING! Please note that this file will be changed +# A LOT during the different phases of Guilds. +# The layout and settings displayed here are NOT final! + +# The prefix character needed for typing in the guild chat. +# Guild Chat format can be found in 'messages.yml' +chat-prefix: "*" + +# Set to true if guild tags should automatically be +# converted to Uppercase upon creation. +uppercase-tags: true +rules: + tag: + # The tag characters must match this RegEx string + # or the guild creation will fail. + # !!! If you don't know RegEx I wouldn't mess with this! + # You can always test your expression here: https://regexr.com/ + matches: "[a-zA-Z-_!?]+" + # Minimum and Maximum lengt of a tag + min-length: 3 + max-length: 4 + name: + # The name characters must match this RegEx string + # or the guild creation will fail. + # !!! If you don't know RegEx I wouldn't mess with this! + # You can always test your expression here: https://regexr.com/ + matches: "[a-zA-Z -_!?]+" + # Minimum and Maximum lengt of a tag + min-length: 3 + max-length: 14 + + + + + +# Max allowed members +max-size: 40 + +# "Guilds 1.0 doesn't have the max members feature +# A hotfix will be out before Christmas!" +# - Aria \ No newline at end of file diff --git a/src/main/resources/default/messages.yml b/src/main/resources/default/messages.yml index d164e089..51078d21 100644 --- a/src/main/resources/default/messages.yml +++ b/src/main/resources/default/messages.yml @@ -37,10 +37,14 @@ player-input: friend-request: 'Friend name..' party-invite: 'Player name..' guild-invite: 'Player name..' + guild-creation-tag: 'Guild tag..' + guild-creation-name: 'Guild name..' chat: friend-request: '&eWrite in the chat the player name.' party-invite: '&eWrite in the chat the player you want to invite.' guild-invite: '&eWrite in the chat the player you want to invite.' + guild-creation-tag: '&eWrite in the chat the TAG of the Guild you want to create.' + guild-creation-name: '&eWrite in the chat the name of the Guild you want to create.' cancel: '&eWrite &c''cancel'' &eto cancel.' # Spell Casting @@ -111,7 +115,7 @@ kick-from-party: '&eYou successfully kicked &6{player}&e.' party-invite-cooldown: '&cPlease wait {cooldown} before inviting {player}.' # Guilds -guild-chat: '&a[Guild] {player}: {message}' +guild-chat: '&a[{tag}] {player}: {message}' sent-guild-invite: '&eYou sent a guild invite to &6{player}&e.' already-in-guild: '&c{player} is already in your guild.' guild-invite: @@ -119,12 +123,18 @@ guild-invite: - '{"text":"&6{player} &ehas invited you to their guild!"}' - '[{"text":" ","hoverEvent":{}},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/guild accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r ","hoverEvent":{}},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/guild deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]' - '{"text":""}' -guild-is-full: '&cSorry, your guild is full.' +#guild-is-full: '&cSorry, your guild is full.' -Unused right now guild-joined: '&eYou successfully joined &6{owner}&e''s guild.' guild-joined-other: '&6{player}&e joined your guild!' transfer-guild-ownership: '&eYou were transfered the guild ownership.' kick-from-guild: '&eYou successfully kicked &6{player}&e from the guild.' guild-invite-cooldown: '&cPlease wait {cooldown} before inviting {player}.' +guild-creation: + failed: "&cCouldn't create guild: {reason}" + reasons: + invalid-characters: "&eInvalid character(s)!" + invalid-length: "&eThe length must be between {min} and {max}!" + already-exists: "&eThat guild tag already exists!" # Quests already-on-quest: '&cYou are already on a quest.'