Guilds!!!

They're finally here. Even if it's just the foundation.
- Also added an auto-saver (more info in config.yml)

It's recommended to regenerate these files:
config.yml, messages.yml, commands.yml
This commit is contained in:
Aria 2019-11-30 01:11:05 +01:00
parent b6b3ce8c76
commit 6b05f32d4c
16 changed files with 697 additions and 102 deletions

View File

@ -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();
}

View File

@ -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!");
}
}

View File

@ -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("_", "-");

View File

@ -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<UUID, PlayerDataOfflineValues> 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();

View File

@ -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<UUID, Long> 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<String> memberList = new ArrayList<>();
for(UUID uuid : members.members)
memberList.add(uuid.toString());
config.set("members", memberList);
}
public class GuildMembers {
private final List<PlayerData> members = new ArrayList<>();
private final List<UUID> 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<? super PlayerData> action) {
public void forEach(Consumer<? super UUID> 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;
}
}
}

View File

@ -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());
}

View File

@ -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);
}
}
}
}

View File

@ -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;
}
}

View File

@ -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; }
}
}

View File

@ -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);
});
});
}
}

View File

@ -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);

View File

@ -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<Guild> guilds = new HashSet<>();
private final Map<String, Guild> 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;
}
}

View File

@ -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.

View File

@ -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: {}
lore: []

View File

@ -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

View File

@ -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.'