diff --git a/src/main/java/net/Indyuce/mmocore/MMOCore.java b/src/main/java/net/Indyuce/mmocore/MMOCore.java index 53c3f22e..37ff382e 100644 --- a/src/main/java/net/Indyuce/mmocore/MMOCore.java +++ b/src/main/java/net/Indyuce/mmocore/MMOCore.java @@ -21,6 +21,7 @@ import net.Indyuce.mmocore.command.AttributesCommand; import net.Indyuce.mmocore.command.ClassCommand; import net.Indyuce.mmocore.command.DepositCommand; import net.Indyuce.mmocore.command.FriendsCommand; +import net.Indyuce.mmocore.command.GuildCommand; import net.Indyuce.mmocore.command.MMOCoreCommand; import net.Indyuce.mmocore.command.PartyCommand; import net.Indyuce.mmocore.command.PlayerStatsCommand; @@ -84,6 +85,7 @@ import net.Indyuce.mmocore.manager.profession.FishingManager; import net.Indyuce.mmocore.manager.profession.ProfessionManager; import net.Indyuce.mmocore.manager.profession.SmithingManager; import net.Indyuce.mmocore.manager.social.BoosterManager; +import net.Indyuce.mmocore.manager.social.GuildManager; import net.Indyuce.mmocore.manager.social.PartyManager; import net.Indyuce.mmocore.manager.social.RequestManager; import net.Indyuce.mmocore.version.ServerVersion; @@ -104,6 +106,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 final QuestManager questManager = new QuestManager(); public ConfigItemManager configItems; public SkillManager skillManager; @@ -298,6 +301,7 @@ public class MMOCore extends JavaPlugin { commandMap.register("mmocore", new SkillsCommand(config.getConfigurationSection("skills"))); commandMap.register("mmocore", new FriendsCommand(config.getConfigurationSection("friends"))); commandMap.register("mmocore", new PartyCommand(config.getConfigurationSection("party"))); + commandMap.register("mmocore", new GuildCommand(config.getConfigurationSection("guild"))); if (hasEconomy() && economy.isValid()) { commandMap.register("mmocore", new WithdrawCommand(config.getConfigurationSection("withdraw"))); @@ -338,6 +342,9 @@ public class MMOCore extends JavaPlugin { partyManager.clear(); partyManager.reload(); + guildManager.clear(); + guildManager.reload(); + attributeManager.clear(); attributeManager.reload(); diff --git a/src/main/java/net/Indyuce/mmocore/api/event/social/GuildChatEvent.java b/src/main/java/net/Indyuce/mmocore/api/event/social/GuildChatEvent.java new file mode 100644 index 00000000..00f767b2 --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/api/event/social/GuildChatEvent.java @@ -0,0 +1,54 @@ +package net.Indyuce.mmocore.api.event.social; + +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; + +import net.Indyuce.mmocore.api.event.PlayerDataEvent; +import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.api.player.social.guilds.Guild; + +public class GuildChatEvent extends PlayerDataEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + + private final Guild guild; + + private boolean cancelled; + private String message; + + public GuildChatEvent(PlayerData playerData, String message) { + super(playerData); + this.guild = playerData.getGuild(); + this.message = message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public Guild getGuild() { + return guild; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} 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 59ddf71d..7878e313 100644 --- a/src/main/java/net/Indyuce/mmocore/api/input/PlayerInput.java +++ b/src/main/java/net/Indyuce/mmocore/api/input/PlayerInput.java @@ -31,7 +31,8 @@ public abstract class PlayerInput implements Listener { public enum InputType { FRIEND_REQUEST, - PARTY_INVITE; + PARTY_INVITE, + GUILD_INVITE; 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 c37e8144..d80cc0bc 100644 --- a/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -39,6 +39,7 @@ import net.Indyuce.mmocore.api.player.profess.SavedClassInformation; import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource; import net.Indyuce.mmocore.api.player.social.FriendRequest; import net.Indyuce.mmocore.api.player.social.Party; +import net.Indyuce.mmocore.api.player.social.guilds.Guild; import net.Indyuce.mmocore.api.player.stats.PlayerStats; import net.Indyuce.mmocore.api.player.stats.StatType; import net.Indyuce.mmocore.api.skill.Skill; @@ -70,6 +71,7 @@ public class PlayerData { private final Set waypoints = new HashSet<>(); private List friends; private Party party; + private Guild guild; private final List boundSkills = new ArrayList<>(); private final PlayerAttributes attributes = new PlayerAttributes(this); @@ -277,6 +279,10 @@ public class PlayerData { return party; } + public Guild getGuild() { + return guild; + } + public int getClassPoints() { return classPoints; } @@ -301,6 +307,10 @@ public class PlayerData { return party != null; } + public boolean inGuild() { + return guild != null; + } + public boolean isOnline() { return player.isOnline(); } @@ -402,6 +412,10 @@ public class PlayerData { this.party = party; } + public void setGuild(Guild guild) { + this.guild = guild; + } + public void log(Level level, String message) { MMOCore.plugin.getLogger().log(level, "[Userdata:" + player.getName() + "] " + message); } 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 new file mode 100644 index 00000000..d8aa55d4 --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/api/player/social/guilds/Guild.java @@ -0,0 +1,139 @@ +package net.Indyuce.mmocore.api.player.social.guilds; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Consumer; + +import org.bukkit.entity.Player; + +import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.ConfigMessage; +import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.api.player.social.Request; +import net.Indyuce.mmocore.gui.api.PluginInventory; +import net.Indyuce.mmocore.gui.social.guild.EditableGuildView.GuildViewInventory; +import net.Indyuce.mmocore.manager.InventoryManager; + +public class Guild { + private final GuildMembers members = new GuildMembers(); + private final Map invites = new HashMap<>(); + private String guildName; + + /* + * owner changes when the old owner leaves guild + */ + private PlayerData owner; + + // used to check if two parties are the same + // private UUID uuid = UUID.randomUUID(); + + public Guild(PlayerData owner, String name) { + this.owner = owner; + this.guildName = name; + addMember(owner); + } + + public PlayerData getOwner() { + return owner; + } + + public String getName() { + return guildName; + } + + public GuildMembers getMembers() { + return members; + } + + public long getLastInvite(Player player) { + return invites.containsKey(player.getUniqueId()) ? invites.get(player.getUniqueId()) : 0; + } + + public void removeLastInvite(Player player) { + invites.remove(player.getUniqueId()); + } + + public void removeMember(PlayerData data) { + if (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); + + reopenInventories(); + + // disband the guild if no member left + if (members.count() < 1) { + MMOCore.plugin.guildManager.unregisterGuild(this); + return; + } + + // transfer ownership + if (owner.equals(data)) { + owner = members.get(0); + owner.getPlayer().sendMessage(MMOCore.plugin.configManager.getSimpleMessage("transfer-guild-ownership")); + } + } + + public void addMember(PlayerData data) { + if (data.inGuild()) + data.getGuild().removeMember(data); + + data.setGuild(this); + members.add(data); + + reopenInventories(); + } + + public void reopenInventories() { + for (PlayerData member : members.members) + if (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) { + invites.put(target.getUniqueId(), System.currentTimeMillis()); + Request request = new GuildInvite(this, inviter, target); + new ConfigMessage("guild-invite").addPlaceholders("player", inviter.getPlayer().getName(), "uuid", request.getUniqueId().toString()).sendAsJSon(target.getPlayer()); + MMOCore.plugin.requestManager.registerRequest(request); + } + + public class GuildMembers { + private final List members = new ArrayList<>(); + + public PlayerData get(int count) { + return members.get(count); + } + + public boolean has(PlayerData player) { + return members.contains(player); + } + + public void add(PlayerData player) { + members.add(player); + + refreshAttributes(); + } + + public void remove(PlayerData player) { + members.remove(player); + + refreshAttributes(); + } + + public void forEach(Consumer action) { + members.forEach(action); + } + + public int count() { + return members.size(); + } + + public void refreshAttributes() { + members.forEach(member -> refreshAttributes()); + } + } +} 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 new file mode 100644 index 00000000..d0ce3cd4 --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/api/player/social/guilds/GuildInvite.java @@ -0,0 +1,39 @@ +package net.Indyuce.mmocore.api.player.social.guilds; + +import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.api.player.social.Request; +import net.Indyuce.mmocore.manager.InventoryManager; + +public class GuildInvite extends Request { + private final PlayerData target; + private final Guild guild; + + public GuildInvite(Guild guild, PlayerData creator, PlayerData target) { + super(creator); + + this.guild = guild; + this.target = target; + } + + public Guild getGuild() { + return guild; + } + + public PlayerData getPlayer() { + return target; + } + + public void deny() { + MMOCore.plugin.requestManager.unregisterRequest(getUniqueId()); + } + + public void accept() { + guild.removeLastInvite(getCreator().getPlayer()); + guild.getMembers().forEach(member -> member.getPlayer().sendMessage(MMOCore.plugin.configManager.getSimpleMessage("guild-joined-other", "player", target.getPlayer().getName()))); + target.getPlayer().sendMessage(MMOCore.plugin.configManager.getSimpleMessage("guild-joined", "owner", guild.getOwner().getPlayer().getName())); + guild.addMember(target); + InventoryManager.GUILD_VIEW.newInventory(target).open(); + MMOCore.plugin.requestManager.unregisterRequest(getUniqueId()); + } +} \ No newline at end of file diff --git a/src/main/java/net/Indyuce/mmocore/command/GuildCommand.java b/src/main/java/net/Indyuce/mmocore/command/GuildCommand.java new file mode 100644 index 00000000..1e56db1e --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/command/GuildCommand.java @@ -0,0 +1,70 @@ +package net.Indyuce.mmocore.command; + +import java.util.UUID; + +import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.command.defaults.BukkitCommand; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; + +import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.api.player.social.Request; +import net.Indyuce.mmocore.api.player.social.guilds.GuildInvite; +import net.Indyuce.mmocore.manager.InventoryManager; + +public class GuildCommand extends BukkitCommand { + + public GuildCommand(ConfigurationSection config) { + super(config.getString("main")); + + setAliases(config.getStringList("aliases")); + setDescription("Opens the guilds menu."); + } + + @Override + public boolean execute(CommandSender sender, String label, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage(ChatColor.RED + "This command is for players only."); + return true; + } + + if (args.length > 1) { + UUID uuid; + try { + uuid = UUID.fromString(args[1]); + } catch (Exception e) { + return true; + } + + Request request = MMOCore.plugin.requestManager.getRequest(uuid); + if (request == null || !(request instanceof GuildInvite)) + return true; + + if (request.isTimedOut()) { + MMOCore.plugin.requestManager.unregisterRequest(uuid); + return true; + } + + if (!MMOCore.plugin.guildManager.isRegistered(((GuildInvite) request).getGuild())) { + MMOCore.plugin.requestManager.unregisterRequest(uuid); + return true; + } + + if (args[0].equalsIgnoreCase("accept")) + ((GuildInvite) request).accept(); + if (args[0].equalsIgnoreCase("deny")) + ((GuildInvite) request).deny(); + return true; + } + + PlayerData data = PlayerData.get((OfflinePlayer) sender); + if (data.inGuild()) + InventoryManager.GUILD_VIEW.newInventory(data).open(); + else + InventoryManager.GUILD_CREATION.newInventory(data).open(); + return true; + } +} 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 new file mode 100644 index 00000000..726ee2ec --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildCreation.java @@ -0,0 +1,54 @@ +package net.Indyuce.mmocore.gui.social.guild; + +import org.bukkit.Sound; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.event.inventory.InventoryClickEvent; + +import net.Indyuce.mmocore.MMOCore; +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; + +public class EditableGuildCreation extends EditableInventory { + public EditableGuildCreation() { + super("guild-creation"); + } + + @Override + public InventoryItem load(String function, ConfigurationSection config) { + return new NoPlaceholderItem(config); + } + + public GeneratedInventory newInventory(PlayerData data) { + return new GuildCreationInventory(data, this); + } + + public class GuildCreationInventory extends GeneratedInventory { + public GuildCreationInventory(PlayerData playerData, EditableInventory editable) { + super(playerData, editable); + } + + @Override + public void whenClicked(InventoryClickEvent event, InventoryItem item) { + if (event.getInventory() != event.getClickedInventory()) + 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); + } + + if (item.getFunction().equals("back")) + player.closeInventory(); + } + + @Override + public String calculateName() { + return getName(); + } + } +} 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 new file mode 100644 index 00000000..c38d25c4 --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildView.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 EditableGuildView extends EditableInventory { + public EditableGuildView() { + super("guild-view"); + } + + @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 = 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 = 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); + 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) { + player.sendMessage(MMOCore.plugin.configManager.getSimpleMessage("guild-is-full")); + 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) { + player.sendMessage(MMOCore.plugin.configManager.getSimpleMessage("not-online-player", "player", input)); + 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) { + player.sendMessage(MMOCore.plugin.configManager.getSimpleMessage("guild-invite-cooldown", "player", target.getName(), "cooldown", new DelayFormat().format(remaining))); + open(); + return; + } + + PlayerData targetData = PlayerData.get(target); + if (playerData.getGuild().getMembers().has(targetData)) { + player.sendMessage(MMOCore.plugin.configManager.getSimpleMessage("already-in-guild", "player", target.getName())); + player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 1); + open(); + return; + } + + playerData.getGuild().sendGuildInvite(playerData, targetData); + player.sendMessage(MMOCore.plugin.configManager.getSimpleMessage("sent-guild-invite", "player", target.getName())); + 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)) + return; + + OfflinePlayer target = Bukkit.getOfflinePlayer(UUID.fromString(NBTItem.get(event.getCurrentItem()).getString("uuid"))); + if (target.equals(player)) + return; + + playerData.getGuild().removeMember(PlayerData.get(target)); + player.sendMessage(MMOCore.plugin.configManager.getSimpleMessage("kick-from-guild", "player", target.getName())); + player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1); + } + } + } +} diff --git a/src/main/java/net/Indyuce/mmocore/listener/GuildListener.java b/src/main/java/net/Indyuce/mmocore/listener/GuildListener.java new file mode 100644 index 00000000..c2dcdd5f --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/listener/GuildListener.java @@ -0,0 +1,40 @@ +package net.Indyuce.mmocore.listener; + +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; + +import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.event.social.GuildChatEvent; +import net.Indyuce.mmocore.api.player.PlayerData; + +public class GuildListener implements Listener { + + @EventHandler(priority = EventPriority.LOW) + public void a(AsyncPlayerChatEvent event) { + if (!event.getMessage().startsWith(MMOCore.plugin.configManager.guildChatPrefix)) + return; + + PlayerData data = PlayerData.get(event.getPlayer()); + if (!data.hasParty()) + return; + + event.setCancelled(true); + + /* + * running it in a delayed task is recommended + */ + Bukkit.getScheduler().scheduleSyncDelayedTask(MMOCore.plugin, () -> { + String format = MMOCore.plugin.configManager.getSimpleMessage("guild-chat", "player", data.getPlayer().getName(), "message", event.getMessage().substring(MMOCore.plugin.configManager.guildChatPrefix.length())); + GuildChatEvent called = new GuildChatEvent(data, format); + Bukkit.getPluginManager().callEvent(called); + if (!called.isCancelled()) ; //remove + //data.getGuild().members.forEach(member -> { + //if (member.isOnline()) + // member.getPlayer().sendMessage(format); + //}); + }); + } +} diff --git a/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java b/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java index 85ffa4cc..832152e5 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java +++ b/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java @@ -28,7 +28,7 @@ public class ConfigManager { public float speedMalus; public boolean overrideVanillaExp, hotbarSwap; public double expPartyBuff, regenPartyBuff; - public String partyChatPrefix; + public String partyChatPrefix, guildChatPrefix; public ChatColor manaFull, manaHalf, manaEmpty, staminaFull, staminaHalf, staminaEmpty; private final DecimalFormatSymbols formatSymbols = new DecimalFormatSymbols(); @@ -99,6 +99,7 @@ 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/InventoryManager.java b/src/main/java/net/Indyuce/mmocore/manager/InventoryManager.java index a85f6ea7..eda90dd9 100644 --- a/src/main/java/net/Indyuce/mmocore/manager/InventoryManager.java +++ b/src/main/java/net/Indyuce/mmocore/manager/InventoryManager.java @@ -18,6 +18,8 @@ import net.Indyuce.mmocore.gui.WaypointViewer; import net.Indyuce.mmocore.gui.api.EditableInventory; import net.Indyuce.mmocore.gui.social.friend.EditableFriendList; import net.Indyuce.mmocore.gui.social.friend.EditableFriendRemoval; +import net.Indyuce.mmocore.gui.social.guild.EditableGuildCreation; +import net.Indyuce.mmocore.gui.social.guild.EditableGuildView; import net.Indyuce.mmocore.gui.social.party.EditablePartyCreation; import net.Indyuce.mmocore.gui.social.party.EditablePartyView; @@ -33,10 +35,12 @@ public class InventoryManager { public static final EditableFriendRemoval FRIEND_REMOVAL = new EditableFriendRemoval(); public static final EditablePartyView PARTY_VIEW = new EditablePartyView(); public static final EditablePartyCreation PARTY_CREATION = new EditablePartyCreation(); + public static final EditableGuildView GUILD_VIEW = new EditableGuildView(); + public static final EditableGuildCreation GUILD_CREATION = new EditableGuildCreation(); public static final QuestViewer QUEST_LIST = new QuestViewer(); public static final AttributeView ATTRIBUTE_VIEW = new AttributeView(); - public static final List list = Arrays.asList(PLAYER_STATS, ATTRIBUTE_VIEW, SKILL_LIST, CLASS_SELECT, SUBCLASS_SELECT, SUBCLASS_CONFIRM, QUEST_LIST, WAYPOINTS, CLASS_CONFIRM, FRIEND_LIST, FRIEND_REMOVAL, PARTY_VIEW, PARTY_CREATION); + public static final List list = Arrays.asList(PLAYER_STATS, ATTRIBUTE_VIEW, SKILL_LIST, CLASS_SELECT, SUBCLASS_SELECT, SUBCLASS_CONFIRM, QUEST_LIST, WAYPOINTS, CLASS_CONFIRM, FRIEND_LIST, FRIEND_REMOVAL, PARTY_VIEW, PARTY_CREATION, GUILD_VIEW, GUILD_CREATION); public InventoryManager() { list.forEach(inv -> { diff --git a/src/main/java/net/Indyuce/mmocore/manager/social/GuildManager.java b/src/main/java/net/Indyuce/mmocore/manager/social/GuildManager.java new file mode 100644 index 00000000..7e7a649f --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/manager/social/GuildManager.java @@ -0,0 +1,39 @@ +package net.Indyuce.mmocore.manager.social; + +import java.util.HashSet; +import java.util.Set; + +import net.Indyuce.mmocore.api.player.PlayerData; +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<>(); + + public void registerGuild(Guild guild) { + guilds.add(guild); + } + + public Guild newRegisteredGuild(PlayerData owner, String name) { + Guild guild = new Guild(owner, name); + registerGuild(guild); + return guild; + } + + public boolean isRegistered(Guild guild) { + return guilds.contains(guild); + } + + public void unregisterGuild(Guild guild) { + guild.getMembers().forEach(member -> guild.removeMember(member)); + guilds.remove(guild); + } + + @Override + public void reload() { + } + + @Override + public void clear() { + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 1aab803d..b1c88fdc 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -48,6 +48,12 @@ 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/commands.yml b/src/main/resources/default/commands.yml index 8f34b4a3..b6ddec29 100644 --- a/src/main/resources/default/commands.yml +++ b/src/main/resources/default/commands.yml @@ -22,6 +22,9 @@ friends: party: main: "party" aliases: [] +guild: + main: "guild" + aliases: [] withdraw: main: "withdraw" aliases: ["w"] diff --git a/src/main/resources/default/gui/guild-creation.yml b/src/main/resources/default/gui/guild-creation.yml new file mode 100644 index 00000000..79289cc1 --- /dev/null +++ b/src/main/resources/default/gui/guild-creation.yml @@ -0,0 +1,21 @@ + +# GUI display name +name: Guild Creation + +# Number of slots in your inventory. Must be +# between 9 and 54 and must be a multiple of 9. +slots: 27 + +items: + create: + slots: [12] + item: GREEN_TERRACOTTA + function: 'create' + name: '&aCreate a guild!' + lore: {} + back: + slots: [14] + item: RED_TERRACOTTA + function: back + name: '&aBack' + lore: {} diff --git a/src/main/resources/default/gui/guild-view.yml b/src/main/resources/default/gui/guild-view.yml new file mode 100644 index 00000000..7d88dd6f --- /dev/null +++ b/src/main/resources/default/gui/guild-view.yml @@ -0,0 +1,33 @@ + +# GUI display name +name: Guild ({players}/{max}) + +# Number of slots in your inventory. Must be +# between 9 and 54 and must be a multiple of 9. +slots: 54 + +items: + member: + slots: [10,12,14,16,28,30,32,34] + function: member + empty: + item: GRAY_STAINED_GLASS_PANE + name: '&aNo Player' + member: + item: PLAYER_HEAD + name: '&a{name}' + lore: + - '&7Level {level} {class}' + - '&7Online Since: {since}' + leave: + slots: [50] + function: leave + item: REDSTONE + name: '&cLeave Guild' + lore: {} + request: + slots: [48] + function: invite + item: WRITABLE_BOOK + name: '&aInvite a player..' + lore: {} \ No newline at end of file diff --git a/src/main/resources/default/messages.yml b/src/main/resources/default/messages.yml index e89d583b..36057ed7 100644 --- a/src/main/resources/default/messages.yml +++ b/src/main/resources/default/messages.yml @@ -36,9 +36,11 @@ player-input: anvil: friend-request: 'Friend name..' party-invite: 'Player name..' + guild-invite: 'Player 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.' cancel: '&eWrite &c''cancel'' &eto cancel.' # Spell Casting @@ -108,6 +110,22 @@ transfer-party-ownership: '&eYou were transfered the party ownership.' 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}' +sent-guild-invite: '&eYou sent a guild invite to &6{player}&e.' +already-in-guild: '&c{player} is already in your guild.' +guild-invite: +- '{"text":""}' +- '{"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-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}.' + # Quests already-on-quest: '&cYou are already on a quest.' cancel-quest: '&eYou successfully canceled your ongoing quest.'