diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/admin/Admin.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/admin/Admin.java index 0b5fdc95..ce491f8b 100644 --- a/commons/src/main/java/me/totalfreedom/totalfreedommod/admin/Admin.java +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/admin/Admin.java @@ -38,7 +38,7 @@ public class Admin { this.uuid = UUID.fromString(resultSet.getString("uuid")); this.active = resultSet.getBoolean("active"); - this.rank = GroupProvider.fromArgument(resultSet.getString("rank")).getGroup(); + this.rank = GroupProvider.fromString(resultSet.getString("rank")).getGroup(); this.ips.clear(); this.ips.addAll(FUtil.stringToList(resultSet.getString("ips"))); this.lastLogin = new Date(resultSet.getLong("last_login")); @@ -70,15 +70,15 @@ public class Admin public Map toSQLStorable() { HashMap map = new HashMap<>(); - map.put("uuid", uuid.toString()); - map.put("active", active); - map.put("rank", rank.toString()); - map.put("ips", FUtil.listToString(ips)); - map.put("last_login", lastLogin.getTime()); - map.put("command_spy", commandSpy); - map.put("potion_spy", potionSpy); - map.put("ac_format", acFormat); - return map; + map.put("uuid", uuid.toString()); + map.put("active", active); + map.put("rank", rank.toString()); + map.put("ips", FUtil.listToString(ips)); + map.put("last_login", lastLogin.getTime()); + map.put("command_spy", commandSpy); + map.put("potion_spy", potionSpy); + map.put("ac_format", acFormat); + return map; } diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/admin/AdminList.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/admin/AdminList.java index 10bf705e..6ba49090 100644 --- a/commons/src/main/java/me/totalfreedom/totalfreedommod/admin/AdminList.java +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/admin/AdminList.java @@ -5,6 +5,7 @@ import com.google.common.collect.Sets; import me.totalfreedom.totalfreedommod.FreedomService; import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.rank.GroupProvider; +import me.totalfreedom.totalfreedommod.rank.Hierarchy; import me.totalfreedom.totalfreedommod.util.FLog; import me.totalfreedom.totalfreedommod.util.FUtil; import net.kyori.adventure.text.Component; @@ -106,9 +107,10 @@ public class AdminList extends FreedomService return admin != null && admin.isActive(); } - // Cast to OfflinePlayer public boolean isAdmin(Player player) { + if (Hierarchy.getHierarchy().isUserOnAdminTrack(player)) return true; + return isAdmin((OfflinePlayer) player); } @@ -124,19 +126,6 @@ public class AdminList extends FreedomService return admin != null && admin.isActive(); } - public boolean isSeniorAdmin(CommandSender sender) - { - Admin admin = getAdmin(sender); - if (admin == null) - { - return false; - } - - return admin.getRank().getLuckPermsGroup().getWeight().orElse(0) - >= GroupProvider.SENIOR_ADMIN.getGroup().getLuckPermsGroup().getWeight().orElse(1); - // We don't want this to return true if there's no group weight available. - } - public Admin getAdmin(CommandSender sender) { if (sender instanceof Player player) diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_deop.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_deop.java index 947aeb9b..c901c137 100644 --- a/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_deop.java +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_deop.java @@ -1,10 +1,9 @@ package me.totalfreedom.totalfreedommod.command; -import me.totalfreedom.totalfreedommod.rank.GroupProvider; -import me.totalfreedom.totalfreedommod.rank.HierarchyProvider; +import me.totalfreedom.totalfreedommod.rank.Hierarchy; import me.totalfreedom.totalfreedommod.util.FLog; import me.totalfreedom.totalfreedommod.util.FUtil; -import net.luckperms.api.model.user.User; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -39,12 +38,18 @@ public class Command_deop extends FreedomCommand } AtomicBoolean atomicBoolean = new AtomicBoolean(silent); - User user = GroupProvider.getUser(player); - HierarchyProvider.OP.getHierarchy().demoteUser(user).whenComplete((result, throwable) -> + Hierarchy.getHierarchy().demoteUser(Hierarchy.getHierarchy().op(), player).whenComplete((result, throwable) -> { if (throwable != null) { - FLog.severe("Error while demoting " + player.getName() + " to OP: " + throwable.getMessage()); + msgNew("Could not demote to non-OP. Check the logs for more details.", player(player)); + FLog.severe("Error while demoting " + player.getName() + " to non-OP:"); + FLog.severe(throwable); + return; + } + + if (!result.wasSuccessful()) { + msgNew(" is already non-op.", Placeholder.unparsed("player", player.getName())); return; } diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_deopall.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_deopall.java index b452b6ab..7c70cf8c 100644 --- a/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_deopall.java +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_deopall.java @@ -1,10 +1,9 @@ package me.totalfreedom.totalfreedommod.command; -import me.totalfreedom.totalfreedommod.rank.GroupProvider; -import me.totalfreedom.totalfreedommod.rank.HierarchyProvider; +import me.totalfreedom.totalfreedommod.rank.Hierarchy; import me.totalfreedom.totalfreedommod.util.FLog; import me.totalfreedom.totalfreedommod.util.FUtil; -import net.luckperms.api.model.user.User; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -20,17 +19,24 @@ public class Command_deopall extends FreedomCommand FUtil.adminAction(sender.getName(), "De-opping all players on the server", true); server.getOnlinePlayers().forEach(player -> - { - User user = GroupProvider.getUser(player); - HierarchyProvider.OP.getHierarchy().demoteUser(user).whenComplete((result, ex) -> { - if (ex != null) { - FLog.severe("Failed to demote " + player.getName() + " to default rank"); - } + Hierarchy.getHierarchy().demoteUser(Hierarchy.getHierarchy().op(), player).whenComplete((result, ex) -> + { + if (ex != null) + { + msgNew("Could not demote to non-OP. Check the logs for more details.", player(player)); + FLog.severe("Failed to demote " + player.getName() + " to non-OP:"); + FLog.severe(ex); + return; + } - msg(player, YOU_ARE_NOT_OP); - plugin.rm.updateDisplay(player); - }); - }); + if (!result.wasSuccessful()) { + msgNew(" is already non-OP.", Placeholder.unparsed("player", player.getName())); + return; + } + + msg(player, YOU_ARE_NOT_OP); + plugin.rm.updateDisplay(player); + })); return true; } diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_mbconfig.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_mbconfig.java index 455c339f..f7125ee3 100644 --- a/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_mbconfig.java +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_mbconfig.java @@ -1,9 +1,13 @@ package me.totalfreedom.totalfreedommod.command; +import com.earth2me.essentials.commands.PlayerNotFoundException; import me.totalfreedom.totalfreedommod.player.PlayerData; +import me.totalfreedom.totalfreedommod.rank.GroupProvider; +import me.totalfreedom.totalfreedommod.rank.Hierarchy; import me.totalfreedom.totalfreedommod.util.FUtil; import org.apache.commons.lang.StringUtils; import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -120,6 +124,7 @@ public class Command_mbconfig extends FreedomCommand { FUtil.adminAction(sender.getName(), "Adding " + data.getName() + " to the Master Builder list", true); data.setMasterBuilder(true); + Hierarchy.getHierarchy().addUserToGroup(GroupProvider.MASTER_BUILDER.getGroup(), player); plugin.pl.save(data); if (player != null) { @@ -143,23 +148,34 @@ public class Command_mbconfig extends FreedomCommand return noPerms(); } - Player player = getPlayer(args[1]); - PlayerData data = player != null ? plugin.pl.getData(player) : plugin.pl.getData(args[1]); - - if (data == null || !data.isMasterBuilder()) + try { - msg("Master Builder not found: " + args[1]); + OfflinePlayer player = getOfflinePlayer(args[1]); + PlayerData data = plugin.pl.getData(args[1]); + + if (data == null || !data.isMasterBuilder()) + { + msgNew("Master Builder not found: ", arg(args[1])); + return true; + } + + FUtil.adminAction(sender.getName(), "Removing " + data.getName() + " from the Master Builder list", true); + Hierarchy.getHierarchy().dropUserFromAll(Hierarchy.getHierarchy().builder(), player); + data.setMasterBuilder(false); + plugin.pl.save(data); + + if (player.isOnline()) + { + // This is not null because the player is online, so we can safely call this method. + plugin.rm.updateDisplay(player.getPlayer()); + } + + return true; + } catch (PlayerNotFoundException e) + { + msgNew("Player not found: ", arg(args[1])); return true; } - - FUtil.adminAction(sender.getName(), "Removing " + data.getName() + " from the Master Builder list", true); - data.setMasterBuilder(false); - plugin.pl.save(data); - if (player != null) - { - plugin.rm.updateDisplay(player); - } - return true; } default: { diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_op.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_op.java index 46737cf3..750a6e18 100644 --- a/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_op.java +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_op.java @@ -1,10 +1,8 @@ package me.totalfreedom.totalfreedommod.command; -import me.totalfreedom.totalfreedommod.rank.GroupProvider; -import me.totalfreedom.totalfreedommod.rank.HierarchyProvider; +import me.totalfreedom.totalfreedommod.rank.Hierarchy; import me.totalfreedom.totalfreedommod.util.FLog; import me.totalfreedom.totalfreedommod.util.FUtil; -import net.luckperms.api.model.user.User; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -40,15 +38,21 @@ public class Command_op extends FreedomCommand } AtomicBoolean atomicBoolean = new AtomicBoolean(silent); - User user = GroupProvider.getUser(player); - HierarchyProvider.OP.getHierarchy().promoteUser(user).whenComplete((ignored, throwable) -> + Hierarchy.getHierarchy().promoteUser(Hierarchy.getHierarchy().op(), player).whenComplete((result, throwable) -> { if (throwable != null) { - FLog.severe("Failed to promote user " + player.getName()); + msgNew("Failed to promote to OP. Check logs for more details.", player(player)); + FLog.severe("Failed to promote " + player.getName() + " to OP:"); + FLog.severe(throwable); return; } + if (!result.wasSuccessful()) + { + msgNew(" is already OP!", player(player)); + } + msg(player, YOU_ARE_OP); plugin.rm.updateDisplay(player); if (!atomicBoolean.get()) diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_opall.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_opall.java index 1b1e8744..6ecd3beb 100644 --- a/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_opall.java +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_opall.java @@ -1,10 +1,8 @@ package me.totalfreedom.totalfreedommod.command; -import me.totalfreedom.totalfreedommod.rank.GroupProvider; -import me.totalfreedom.totalfreedommod.rank.HierarchyProvider; +import me.totalfreedom.totalfreedommod.rank.Hierarchy; import me.totalfreedom.totalfreedommod.util.FLog; import me.totalfreedom.totalfreedommod.util.FUtil; -import net.luckperms.api.model.user.User; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -19,20 +17,19 @@ public class Command_opall extends FreedomCommand FUtil.adminAction(sender.getName(), "Opping all players on the server", true); server.getOnlinePlayers().forEach(player -> - { - User user = GroupProvider.getUser(player); - HierarchyProvider.OP.getHierarchy().promoteUser(user).whenComplete((ignored, throwable) -> - { - if (throwable != null) + Hierarchy.getHierarchy().promoteUser(Hierarchy.getHierarchy().op(), player).whenComplete((ignored, throwable) -> { - FLog.severe("Failed to promote " + player.getName()); - return; - } + if (throwable != null) + { + msgNew("Failed to promote to OP. Check the logs for more details.", player(player)); + FLog.severe("Failed to promote " + player.getName()); + FLog.severe(throwable); + return; + } - msg(player, YOU_ARE_OP); - plugin.rm.updateDisplay(player); - }); - }); + msg(player, YOU_ARE_OP); + plugin.rm.updateDisplay(player); + })); return true; } diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_opme.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_opme.java index b56f324e..14b17427 100644 --- a/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_opme.java +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_opme.java @@ -1,10 +1,8 @@ package me.totalfreedom.totalfreedommod.command; -import me.totalfreedom.totalfreedommod.rank.GroupProvider; -import me.totalfreedom.totalfreedommod.rank.HierarchyProvider; +import me.totalfreedom.totalfreedommod.rank.Hierarchy; import me.totalfreedom.totalfreedommod.util.FLog; import me.totalfreedom.totalfreedommod.util.FUtil; -import net.luckperms.api.model.user.User; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -18,9 +16,10 @@ public class Command_opme extends FreedomCommand public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole) { FUtil.adminAction(sender.getName(), "Opping " + sender.getName(), false); - User user = GroupProvider.getUser(playerSender); - HierarchyProvider.OP.getHierarchy().promoteUser(user).whenComplete((result, error) -> { - if (error != null) { + Hierarchy.getHierarchy().promoteUser(Hierarchy.getHierarchy().op(), playerSender).whenComplete((result, error) -> + { + if (error != null) + { FLog.severe("Error while promoting " + playerSender.getName() + " to OP: " + error.getMessage()); return; } diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_saconfig.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_saconfig.java index 23b630b9..58f7e3cd 100644 --- a/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_saconfig.java +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/command/Command_saconfig.java @@ -5,14 +5,13 @@ import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.player.FPlayer; import me.totalfreedom.totalfreedommod.rank.DisplayableGroup; import me.totalfreedom.totalfreedommod.rank.GroupProvider; -import me.totalfreedom.totalfreedommod.rank.HierarchyProvider; +import me.totalfreedom.totalfreedommod.rank.Hierarchy; import me.totalfreedom.totalfreedommod.util.FLog; import me.totalfreedom.totalfreedommod.util.FUtil; import me.totalfreedom.totalfreedommod.util.PermissibleCompletion; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; -import net.luckperms.api.model.user.User; +import net.luckperms.api.model.group.Group; import org.apache.commons.lang.StringUtils; -import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -73,72 +72,77 @@ public class Command_saconfig extends FreedomCommand Player player = getPlayer(args[1]); - FUtil.adminAction(sender.getName(), "Promoting " + player.getName() + " to the next rank", true); - HierarchyProvider.ADMIN.getHierarchy() - .promoteUser(GroupProvider.getUser(player)) - .whenComplete((result, ex) -> { - if (ex != null) { - FLog.severe("Failed to promote " - + player.getName() - + " to the next rank"); - return; - } - - result.getGroupTo() - .ifPresent(group -> - msgNew("Admin has been promoted to ", - Placeholder.unparsed("player", player.getName()), - Placeholder.unparsed("rank", group))); - }); - } - case "setrank" -> - { - checkConsole(); - checkPermission("tfm.saconfig.setrank"); - - if (args.length < 3) + if (player == null) { - return false; - } - - DisplayableGroup rank = GroupProvider.fromArgument(args[2]).getGroup(); - if (rank == null) - { - msgNew("Unknown rank: ", Placeholder.unparsed("rank", args[2])); + msgNew("Player not found."); return true; } + Hierarchy.getHierarchy() + .promoteUser(Hierarchy.getHierarchy().admin(), player) + .whenComplete((result, ex) -> + { + if (ex != null) + { + FLog.severe("Failed to promote " + + player.getName() + + " to the next rank"); + return; + } - if (!rank.isAtLeast(GroupProvider.ADMIN.getGroup())) - { - msgNew("Rank must be Admin or higher."); - return true; - } + if (!result.wasSuccessful() || result.getGroupTo().isEmpty()) + { + msgNew("Failed to promote to the next rank.", player(player)); + return; + } - Admin admin = plugin.al.getEntryByName(args[1]); - if (admin == null) - { - msgNew("Unknown admin: ", Placeholder.unparsed("player", args[1])); - return true; - } + result.getGroupTo().ifPresentOrElse(group -> + { + Admin admin = plugin.al.getAdmin(player); - FUtil.adminAction(sender.getName(), "Setting " + admin.getName() + "'s rank to " + rank.getName(), true); + if (admin == null) + { + admin = new Admin(player); + plugin.al.addAdmin(admin); + } - admin.setRank(rank); - plugin.al.save(admin); + Group actual = Hierarchy.getHierarchy().getGroup(group); + DisplayableGroup rank = GroupProvider.fromLuckPermsGroup(actual).getGroup(); - Player player = getPlayer(admin.getName()); - if (player != null) - { - plugin.rm.updateDisplay(player); - } + if (rank == null) + { + msgNew("Unknown rank: ", Placeholder.unparsed("rank", args[2])); + return; + } - if (plugin.dc != null && plugin.dc.isEnabled() && ConfigEntry.DISCORD_ROLE_SYNC.getBoolean()) - { - plugin.dc.syncRoles(admin, plugin.pl.getData(admin.getName()).getDiscordID()); - } + admin.setRank(rank); + admin.addIp(FUtil.getIp(player)); + admin.setActive(true); + admin.setLastLogin(new Date()); - msgNew("Set 's rank to .", Placeholder.unparsed("admin", admin.getName()), Placeholder.component("rank", rank.getName())); + plugin.al.save(admin); + plugin.al.updateTables(); + plugin.rm.updateDisplay(player); + + if (plugin.dc != null && plugin.dc.isEnabled() && ConfigEntry.DISCORD_ROLE_SYNC.getBoolean()) + { + plugin.dc.syncRoles(admin, plugin.pl.getData(player).getDiscordID()); + } + + msgNew("Set 's rank to .", Placeholder.unparsed("admin", admin.getName()), Placeholder.component("rank", rank.getName())); + + final FPlayer fPlayer = plugin.pl.getPlayer(player); + if (fPlayer.getFreezeData().isFrozen()) + { + fPlayer.getFreezeData().setFrozen(false); + msgNew(player, "You have been unfrozen."); + } + + msgNew("Admin has been promoted to ", + player(player), + Placeholder.unparsed("rank", group)); + }, () -> msgNew("Failed to promote to the next rank.", player(player))); + }); return true; } @@ -173,78 +177,87 @@ public class Command_saconfig extends FreedomCommand return true; } - case "add" -> + case "demote" -> { + checkConsole(); + checkPermission("tfm.saconfig.demote"); + if (args.length < 2) { return false; } - checkConsole(); - checkPermission("tfm.saconfig.add"); - - // Player already admin? - final Player player = getPlayer(args[1]); + Player player = getPlayer(args[1]); if (player == null) { - msg(PLAYER_NOT_FOUND); + msgNew("Player not found."); return true; } - if (plugin.al.isAdmin(player)) - { - msgNew("That player is already an admin."); - return true; - } + Hierarchy.getHierarchy() + .demoteUser(Hierarchy.getHierarchy().admin(), player) + .whenComplete((result, ex) -> + { + if (ex != null) + { + FLog.severe("Failed to demote " + + player.getName() + + " to the next rank"); + return; + } - // Find the old admin entry - Admin admin = null; - for (Admin loopAdmin : plugin.al.getAllAdmins()) - { - if (loopAdmin.getUuid().equals(player.getUniqueId())) - { - admin = loopAdmin; - break; - } - } + if (!result.wasSuccessful() || result.getGroupTo().isEmpty()) + { + msgNew("Failed to demote to the next rank.", player(player)); + return; + } - if (admin == null) // New admin - { - FUtil.adminAction(sender.getName(), "Adding " + player.getName() + " to the admin list", true); - admin = new Admin(player); - User user = GroupProvider.getUser(player); - HierarchyProvider.ADMIN.getHierarchy().promoteUser(user); + result.getGroupTo().ifPresentOrElse(group -> + { + Admin admin = plugin.al.getAdmin(player); - plugin.al.addAdmin(admin); - plugin.rm.updateDisplay(player); - } else // Existing admin - { - User user = GroupProvider.getUser(player); - HierarchyProvider.ADMIN.getHierarchy().promoteUser(user); - FUtil.adminAction(sender.getName(), "Re-adding " + player.getName() + " to the admin list", true); - admin.addIp(FUtil.getIp(player)); - admin.setActive(true); - admin.setLastLogin(new Date()); + if (admin == null) + { + admin = new Admin(player); + plugin.al.addAdmin(admin); + } - plugin.al.save(admin); - plugin.al.updateTables(); - plugin.rm.updateDisplay(player); + Group actual = Hierarchy.getHierarchy().getGroup(group); + DisplayableGroup rank = GroupProvider.fromLuckPermsGroup(actual).getGroup(); - if (plugin.dc != null && plugin.dc.isEnabled() && ConfigEntry.DISCORD_ROLE_SYNC.getBoolean()) - { - plugin.dc.syncRoles(admin, plugin.pl.getData(player).getDiscordID()); - } - } + if (rank == null) + { + msgNew("Unknown rank: ", Placeholder.unparsed("rank", args[2])); + return; + } - final FPlayer fPlayer = plugin.pl.getPlayer(player); - if (fPlayer.getFreezeData().isFrozen()) - { - fPlayer.getFreezeData().setFrozen(false); - msgNew(player, "You have been unfrozen."); - } + admin.setRank(rank); + admin.setLastLogin(new Date()); - return true; + plugin.al.save(admin); + plugin.al.updateTables(); + plugin.rm.updateDisplay(player); + + if (plugin.dc != null && plugin.dc.isEnabled() && ConfigEntry.DISCORD_ROLE_SYNC.getBoolean()) + { + plugin.dc.syncRoles(admin, plugin.pl.getData(player).getDiscordID()); + } + + msgNew("Set 's rank to .", Placeholder.unparsed("admin", admin.getName()), Placeholder.component("rank", rank.getName())); + + final FPlayer fPlayer = plugin.pl.getPlayer(player); + if (fPlayer.getFreezeData().isFrozen()) + { + fPlayer.getFreezeData().setFrozen(false); + msgNew(player, "You have been unfrozen."); + } + + msgNew("Admin has been demoted to ", + Placeholder.unparsed("player", player.getName()), + Placeholder.unparsed("rank", group)); + }, () -> msgNew("Failed to demote to the next rank.", Placeholder.unparsed("player", player.getName()))); + }); } case "remove" -> { @@ -260,8 +273,7 @@ public class Command_saconfig extends FreedomCommand Admin admin = plugin.al.getAdmin(player); plugin.al.removeAdmin(admin); - User user = GroupProvider.getUser(player); - HierarchyProvider.ADMIN.getHierarchy().dropUserFromAll(user); + Hierarchy.getHierarchy().dropUserFromAll(Hierarchy.getHierarchy().admin(), player); FUtil.adminAction(sender.getName(), "Removing " + admin.getName() + " from the admin list", true); admin.setActive(false); @@ -297,11 +309,11 @@ public class Command_saconfig extends FreedomCommand { return argumentCompletions(args[0], PermissibleCompletion.of("tfm.saconfig.info", "info"), - PermissibleCompletion.of("tfm.saconfig.add", "add"), + PermissibleCompletion.of("tfm.saconfig.demote", "demote"), PermissibleCompletion.of("tfm.saconfig.remove", "remove"), PermissibleCompletion.of("tfm.saconfig.reload", "reload"), PermissibleCompletion.of("tfm.saconfig.clean", "clean"), - PermissibleCompletion.of("tfm.saconfig.setrank", "setrank")); + PermissibleCompletion.of("tfm.saconfig.promote", "promote")); } if (args.length == 2 && (args[0].equals("add") || args[0].equals("remove") || args[0].equals("setrank") || args[0].equals("info"))) { diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/command/FreedomCommand.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/command/FreedomCommand.java index ba21ec2e..f59d82e7 100644 --- a/commons/src/main/java/me/totalfreedom/totalfreedommod/command/FreedomCommand.java +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/command/FreedomCommand.java @@ -10,6 +10,7 @@ import me.totalfreedom.totalfreedommod.util.FUtil; import me.totalfreedom.totalfreedommod.util.PermissibleCompletion; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import org.apache.commons.lang.StringUtils; import org.bukkit.Bukkit; @@ -22,7 +23,6 @@ import org.bukkit.plugin.Plugin; import org.bukkit.util.StringUtil; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.lang.annotation.AnnotationFormatError; import java.util.*; @@ -160,7 +160,8 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter .toList(); } - protected List playerCompletions(String arg) { + protected List playerCompletions(String arg) + { return Bukkit.getOnlinePlayers() .stream() .map(Player::getName) @@ -178,6 +179,24 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter return plugin.al.isAdmin(sender); } + @NotNull + public TagResolver.Single player(Player player) + { + return Placeholder.unparsed("player", player.getName()); + } + + @NotNull + public TagResolver.Single sender(CommandSender sender) + { + return Placeholder.unparsed("sender", sender.getName()); + } + + @NotNull + public TagResolver.Single usage() + { + return Placeholder.unparsed("usage", this.getUsage().replace("", this.getName().toLowerCase())); + } + protected void checkConsole() { if (!isConsole()) @@ -232,6 +251,11 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter public abstract boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole); + protected TagResolver.Single arg(String arg) + { + return Placeholder.unparsed("arg", arg); + } + protected List getTabCompleteOptions(CommandSender sender, Command command, String alias, String[] args) { return FUtil.getPlayerList(); @@ -347,6 +371,7 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter { if (cmd == null) { + msgNew(sender, "", usage()); return false; } // Reduce complexity! Exit immediately if the command is null. diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/perms/GroupWrapper.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/perms/GroupWrapper.java new file mode 100644 index 00000000..08079a4b --- /dev/null +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/perms/GroupWrapper.java @@ -0,0 +1,48 @@ +package me.totalfreedom.totalfreedommod.perms; + +import net.luckperms.api.model.group.Group; +import net.luckperms.api.model.group.GroupManager; + +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +public class GroupWrapper +{ + private final GroupManager manager; + private final Set groupSet; + + public GroupWrapper(GroupManager manager) + { + this.manager = manager; + this.groupSet = manager.getLoadedGroups(); + } + + public CompletableFuture getGroup(String name) + { + if (!manager.isLoaded(name) || !groupSet.contains(manager.getGroup(name))) + { + return manager.createAndLoadGroup(name); + } + + return CompletableFuture.supplyAsync(() -> manager.getGroup(name)); + } + + public CompletableFuture removeGroup(String name) + { + return getGroup(name).thenAccept(a -> + { + manager.deleteGroup(a); + groupSet.remove(a); + }); + } + + public CompletableFuture addGroup(String name) + { + return getGroup(name).thenAccept(groupSet::add); + } + + public CompletableFuture saveGroup(String name) + { + return getGroup(name).thenAccept(manager::saveGroup); + } +} diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/perms/TrackWrapper.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/perms/TrackWrapper.java new file mode 100644 index 00000000..8d2f244c --- /dev/null +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/perms/TrackWrapper.java @@ -0,0 +1,37 @@ +package me.totalfreedom.totalfreedommod.perms; + +import net.luckperms.api.track.Track; +import net.luckperms.api.track.TrackManager; + +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +public class TrackWrapper +{ + private final TrackManager manager; + private final Set trackSet; + + public TrackWrapper(TrackManager manager) + { + this.manager = manager; + this.trackSet = manager.getLoadedTracks(); + } + + public CompletableFuture getTrack(String name) + { + if (!manager.isLoaded(name) || !trackSet.contains(manager.getTrack(name))) + { + return manager.createAndLoadTrack(name).thenApplyAsync(a -> { + trackSet.add(a); + return a; + }); + } + + return CompletableFuture.supplyAsync(() -> manager.getTrack(name)); + } + + public CompletableFuture saveTrack(String name) + { + return getTrack(name).thenAccept(manager::saveTrack); + } +} diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/perms/UserData.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/perms/UserData.java new file mode 100644 index 00000000..3ba2e5b5 --- /dev/null +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/perms/UserData.java @@ -0,0 +1,80 @@ +package me.totalfreedom.totalfreedommod.perms; + +import net.luckperms.api.cacheddata.CachedMetaData; +import net.luckperms.api.cacheddata.CachedPermissionData; +import net.luckperms.api.context.ImmutableContextSet; +import net.luckperms.api.model.user.User; +import net.luckperms.api.query.QueryOptions; + +public class UserData +{ + private User user; + private CachedMetaData metaData; + private CachedPermissionData permissionData; + private ImmutableContextSet contextSet; + private QueryOptions queryOptions; + + public UserData(User user, CachedMetaData metaData, CachedPermissionData permissionData, ImmutableContextSet contextSet, QueryOptions queryOptions) + { + this.user = user; + this.metaData = metaData; + this.permissionData = permissionData; + this.contextSet = contextSet; + this.queryOptions = queryOptions; + } + + public User getUser() + { + return user; + } + + public void setUser(User user) + { + this.user = user; + } + + public CachedMetaData getMetaData() + { + return metaData; + } + + public void setMetaData(CachedMetaData metaData) + { + this.metaData = metaData; + } + + public CachedPermissionData getPermissionData() + { + return permissionData; + } + + public void setPermissionData(CachedPermissionData permissionData) + { + this.permissionData = permissionData; + } + + public ImmutableContextSet getContextSet() + { + return contextSet; + } + + public void setContextSet(ImmutableContextSet contextSet) + { + this.contextSet = contextSet; + } + + public QueryOptions getQueryOptions() + { + return queryOptions; + } + + public void setQueryOptions(QueryOptions queryOptions) + { + this.queryOptions = queryOptions; + } + + public UserData clone() + { + return new UserData(user, metaData, permissionData, contextSet, queryOptions); + } +} diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/perms/UserWrapper.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/perms/UserWrapper.java new file mode 100644 index 00000000..b4cf794d --- /dev/null +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/perms/UserWrapper.java @@ -0,0 +1,107 @@ +package me.totalfreedom.totalfreedommod.perms; + +import net.luckperms.api.cacheddata.CachedMetaData; +import net.luckperms.api.cacheddata.CachedPermissionData; +import net.luckperms.api.context.ImmutableContextSet; +import net.luckperms.api.model.user.User; +import net.luckperms.api.model.user.UserManager; +import net.luckperms.api.platform.PlayerAdapter; +import net.luckperms.api.query.QueryOptions; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +public class UserWrapper +{ + private final UserManager manager; + private final PlayerAdapter playerAdapter; + private final Set userSet; + private final Set userDataSet; + + public UserWrapper(UserManager manager, PlayerAdapter adapter) + { + this.manager = manager; + this.userSet = manager.getLoadedUsers(); + this.playerAdapter = adapter; + this.userDataSet = new HashSet<>(); + } + + public CompletableFuture addUserData(OfflinePlayer player) + { + User user = playerAdapter.getUser(player); + CachedPermissionData permissionData = playerAdapter.getPermissionData(player); + ImmutableContextSet contextSet = playerAdapter.getContext(player); + QueryOptions queryOptions = playerAdapter.getQueryOptions(player); + CachedMetaData metaData = playerAdapter.getMetaData(player); + + UserData userData = new UserData(user, metaData, permissionData, contextSet, queryOptions); + return CompletableFuture.runAsync(() -> userDataSet.add(userData)); + } + + public CompletableFuture getUser(OfflinePlayer player) + { + if (!manager.isLoaded(player.getUniqueId()) || !userSet.contains(manager.getUser(player.getUniqueId()))) + { + return manager.loadUser(player.getUniqueId()); + } + + return CompletableFuture.supplyAsync(() -> manager.getUser(player.getUniqueId())); + } + + public CompletableFuture removeUser(OfflinePlayer player) + { + return getUser(player).thenAccept(a -> + { + manager.cleanupUser(a); + userSet.remove(a); + }); + } + + public CompletableFuture getUserData(OfflinePlayer player) + { + return getUser(player).thenApply(user -> + { + for (UserData userData : userDataSet) + { + if (userData.getUser().getUniqueId().equals(user.getUniqueId())) + { + return userData; + } + } + return null; + }); + } + + public CompletableFuture removeUserData(OfflinePlayer player) + { + return getUserData(player).thenAccept(userDataSet::remove); + } + + public CompletableFuture updateUserData(OfflinePlayer player) + { + return getUserData(player).thenApply(userData -> + { + UserData newData = userData.clone(); + CachedPermissionData permissionData = playerAdapter.getPermissionData(player); + ImmutableContextSet contextSet = playerAdapter.getContext(player); + QueryOptions queryOptions = playerAdapter.getQueryOptions(player); + CachedMetaData metaData = playerAdapter.getMetaData(player); + + newData.setPermissionData(permissionData); + newData.setContextSet(contextSet); + newData.setQueryOptions(queryOptions); + newData.setMetaData(metaData); + + userDataSet.remove(userData); + return newData; + }).thenAccept(userDataSet::add); + } + + public CompletableFuture saveUser(User user) + { + return CompletableFuture.runAsync(() -> manager.saveUser(user)); + } +} diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/player/PlayerList.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/player/PlayerList.java index d0487111..6c11ed0b 100644 --- a/commons/src/main/java/me/totalfreedom/totalfreedommod/player/PlayerList.java +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/player/PlayerList.java @@ -104,7 +104,7 @@ public class PlayerList extends FreedomService } // May not return null - public FPlayer getPlayer(Player player) + public FPlayer getPlayer(OfflinePlayer player) { FPlayer tPlayer = playerMap.get(player.getUniqueId()); if (tPlayer != null) diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/DisplayableGroup.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/DisplayableGroup.java index 621b6669..a2f6bfeb 100644 --- a/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/DisplayableGroup.java +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/DisplayableGroup.java @@ -39,7 +39,6 @@ public class DisplayableGroup implements Displayable private final boolean hasDefaultLoginMessage; public DisplayableGroup(String group, - String inheritance, Component plural, Component tag, int weight, @@ -65,11 +64,6 @@ public class DisplayableGroup implements Displayable .prefix(FUtil.miniMessage(GroupProvider.OPEN.append(tag.color(color)).append(GroupProvider.CLOSE))) .priority(1) .build(); - if (inheritance != null) - { - InheritanceNode inheritanceNode = InheritanceNode.builder(inheritance).build(); - g.getData(DataType.NORMAL).add(inheritanceNode); - } g.getData(DataType.NORMAL).add(prefixNode); g.getData(DataType.NORMAL).add(weightNode); }).join(); // Block until the group is created and loaded. diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/GroupProvider.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/GroupProvider.java index 172dc14b..40f39a70 100644 --- a/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/GroupProvider.java +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/GroupProvider.java @@ -3,8 +3,8 @@ package me.totalfreedom.totalfreedommod.rank; import me.totalfreedom.totalfreedommod.TotalFreedomMod; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; +import net.luckperms.api.model.group.Group; import net.luckperms.api.model.user.User; -import net.luckperms.api.track.TrackManager; import org.bukkit.ChatColor; import org.bukkit.entity.Player; @@ -16,11 +16,11 @@ public interface GroupProvider Component OPEN = Component.text("[", NamedTextColor.DARK_GRAY); Component CLOSE = Component.text("]", NamedTextColor.DARK_GRAY); - GroupProvider NON_OP = () -> new DisplayableGroup("default", null, Component.text("Non-Ops"), Component.empty(), 0, NamedTextColor.WHITE, null, false, false); - GroupProvider OP = () -> new DisplayableGroup("op", "default", Component.text("Operators"), Component.text("Op"), 1, NamedTextColor.GREEN, null, false, false); - GroupProvider MASTER_BUILDER = () -> new DisplayableGroup("builder", "op", Component.text("Master Builders"), Component.text("MB"), 2, NamedTextColor.DARK_AQUA, ChatColor.DARK_AQUA, true, true); - GroupProvider ADMIN = () -> new DisplayableGroup("admin", "builder", Component.text("Administrators"), Component.text("Admin"), 3, NamedTextColor.DARK_GREEN, ChatColor.DARK_GREEN, true, true); - GroupProvider SENIOR_ADMIN = () -> new DisplayableGroup("senior", "admin", Component.text("Senior Administrators"), Component.text("SrA"), 4, NamedTextColor.GOLD, ChatColor.GOLD, true, true); + GroupProvider NON_OP = () -> new DisplayableGroup("default", Component.text("Non-Ops"), Component.empty(), 0, NamedTextColor.WHITE, null, false, false); + GroupProvider OP = () -> new DisplayableGroup("op", Component.text("Operators"), Component.text("Op"), 1, NamedTextColor.GREEN, null, false, false); + GroupProvider MASTER_BUILDER = () -> new DisplayableGroup("builder", Component.text("Master Builders"), Component.text("MB"), 2, NamedTextColor.DARK_AQUA, ChatColor.DARK_AQUA, true, true); + GroupProvider ADMIN = () -> new DisplayableGroup("admin", Component.text("Administrators"), Component.text("Admin"), 3, NamedTextColor.DARK_GREEN, ChatColor.DARK_GREEN, true, true); + GroupProvider SENIOR_ADMIN = () -> new DisplayableGroup("senior", Component.text("Senior Administrators"), Component.text("SrA"), 4, NamedTextColor.GOLD, ChatColor.GOLD, true, true); static User getUser(Player player) { @@ -30,16 +30,26 @@ public interface GroupProvider .getUser(player); } - static GroupProvider fromArgument(String arg) + static GroupProvider fromString(String arg) { return switch (arg.toLowerCase()) - { - case "op" -> OP; - case "builder" -> MASTER_BUILDER; - case "admin" -> ADMIN; - case "senior" -> SENIOR_ADMIN; - default -> NON_OP; - }; + { + case "op" -> OP; + case "builder" -> MASTER_BUILDER; + case "admin" -> ADMIN; + case "senior" -> SENIOR_ADMIN; + default -> NON_OP; + }; + } + + static GroupProvider fromLuckPermsGroup(Group group) { + return switch (group.getName().toLowerCase()) { + case "op" -> OP; + case "builder" -> MASTER_BUILDER; + case "admin" -> ADMIN; + case "senior" -> SENIOR_ADMIN; + default -> NON_OP; + }; } static Set> providerSet() diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/Hierarchy.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/Hierarchy.java index d3455bb7..9ddc0c37 100644 --- a/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/Hierarchy.java +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/Hierarchy.java @@ -1,193 +1,179 @@ package me.totalfreedom.totalfreedommod.rank; import me.totalfreedom.totalfreedommod.TotalFreedomMod; +import me.totalfreedom.totalfreedommod.perms.GroupWrapper; +import me.totalfreedom.totalfreedommod.perms.TrackWrapper; +import me.totalfreedom.totalfreedommod.perms.UserWrapper; import me.totalfreedom.totalfreedommod.util.FLog; -import net.luckperms.api.LuckPerms; import net.luckperms.api.model.group.Group; -import net.luckperms.api.model.user.User; -import net.luckperms.api.query.QueryOptions; +import net.luckperms.api.node.NodeEqualityPredicate; +import net.luckperms.api.node.NodeType; +import net.luckperms.api.node.types.InheritanceNode; +import net.luckperms.api.track.DemotionResult; import net.luckperms.api.track.PromotionResult; import net.luckperms.api.track.Track; +import org.bukkit.OfflinePlayer; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.atomic.AtomicBoolean; public class Hierarchy { - private final LuckPerms lp; - private final Track track; + private static final Hierarchy hierarchy = new Hierarchy(); // static singleton for global state. + private final GroupWrapper groupWrapper; + private final TrackWrapper trackWrapper; + private final UserWrapper userWrapper; - public Hierarchy(String name) + private Hierarchy() { - this.lp = TotalFreedomMod.getPlugin().lpb.getAPI(); + this.groupWrapper = new GroupWrapper(TotalFreedomMod.getPlugin().lpb.getAPI().getGroupManager()); + this.trackWrapper = new TrackWrapper(TotalFreedomMod.getPlugin().lpb.getAPI().getTrackManager()); + this.userWrapper = new UserWrapper(TotalFreedomMod.getPlugin().lpb.getAPI().getUserManager(), + TotalFreedomMod.getPlugin().lpb.getAPI().getPlayerAdapter(OfflinePlayer.class)); + } - if (lp == null) - { - throw new IllegalStateException("LuckPerms not found!"); - } + public static Hierarchy getHierarchy() + { + return hierarchy; + } - if (!lp.getTrackManager().isLoaded(name)) + public boolean isUserOnAdminTrack(OfflinePlayer player) + { + AtomicBoolean isOnAdminTrack = new AtomicBoolean(false); + userWrapper.getUser(player).thenAccept(user -> + user.data().toCollection().stream() + .filter(NodeType.INHERITANCE::matches) + .map(NodeType.INHERITANCE::cast) + .filter(NodeEqualityPredicate.ONLY_KEY + .equalTo(InheritanceNode + .builder(GroupProvider.ADMIN.getGroup().getLuckPermsGroup().getName()) + .build())) + .forEach(node -> + { + if (node.getGroupName().startsWith("admin")) + { + isOnAdminTrack.set(true); + } + })).whenComplete((a, b) -> { - this.track = lp.getTrackManager().createAndLoadTrack(name).whenComplete((ignored, throwable) -> + if (b != null) { - if (throwable != null) + FLog.severe(b); + } + }); + + return isOnAdminTrack.get(); + } + + public Track op() + { + return trackWrapper.getTrack("OP").join(); + } + + public Track builder() + { + return trackWrapper.getTrack("BUILDER").join(); + } + + public Track admin() + { + return trackWrapper.getTrack("ADMIN").join(); + } + + public void addInheritance(DisplayableGroup previous, DisplayableGroup current) + { + CompletableFuture.runAsync(() -> + { + current.getLuckPermsGroup().data().add(InheritanceNode.builder(previous.getLuckPermsGroup()).build()); + groupWrapper.saveGroup(current.getLuckPermsGroup().getName()); + }).whenComplete((a, b) -> + { + if (b != null) + { + FLog.severe(b); + } + }); + } + + public Group getGroup(String name) { + return groupWrapper.getGroup(name).join(); + } + + public void addGroupToTrack(Track track, DisplayableGroup group) + { + trackWrapper.getTrack(track.getName()).thenAccept(t -> + { + t.appendGroup(group.getLuckPermsGroup()); + trackWrapper.saveTrack(t.getName()); + }).whenComplete((a, b) -> + { + if (b != null) + { + FLog.severe(b); + } + }); + } + + public CompletableFuture promoteUser(Track track, OfflinePlayer player) + { + return userWrapper.getUserData(player).thenApply(data -> + track.promote(data.getUser(), data.getContextSet())); + } + + public CompletableFuture demoteUser(Track track, OfflinePlayer player) + { + return userWrapper.getUserData(player).thenApply(data -> + track.demote(data.getUser(), data.getContextSet())); + } + + public void addUserToGroup(DisplayableGroup group, OfflinePlayer player) + { + userWrapper.getUserData(player).thenAccept(user -> + { + for (InheritanceNode node : group.getLuckPermsGroup().getNodes(NodeType.INHERITANCE)) + { + user.getUser().data().add(node); + } + + user.getUser().getInheritedGroups(user.getQueryOptions()).add(group.getLuckPermsGroup()); + + userWrapper.saveUser(user.getUser()); + }).whenComplete((a, b) -> + { + if (b != null) + { + FLog.severe(b); + } + }); + } + + public void dropUserFromAll(Track track, OfflinePlayer player) + { + userWrapper.getUserData(player).thenAccept(data -> + { + for (String group : track.getGroups()) + { + groupWrapper.getGroup(group).whenComplete((g, b) -> { - throw new IllegalStateException("Failed to create track " + name, throwable); - } - }).join(); // Block and wait for the track to load. - } else - { - this.track = lp.getTrackManager().getTrack(name); - } - } + if (b != null) + { + FLog.severe(b); + return; + } - public void addGroup(DisplayableGroup group) - { - updateAppend(group.getLuckPermsGroup()).join(); // wait for the group to be updated. - } - - public void addGroup(Group group, int index) - { - updateInsert(group, index).join(); // wait for the group to be updated. - } - - public void dropGroup(Group group) // This is non-blocking by default. - { - updateDrop(group).whenComplete((ignored, throwable) -> - { - if (throwable != null) - { - FLog.severe("Failed to update track " + track.getName()); + for (InheritanceNode node : g.getNodes(NodeType.INHERITANCE)) + { + data.getUser().data().remove(node); + } + }); } - }); - } - - public void addGroupNonBlocking(Group group, int index) - { - updateInsert(group, index).whenComplete((ignored, throwable) -> + userWrapper.saveUser(data.getUser()); + }).whenComplete((a, b) -> { - if (throwable != null) + if (b != null) { - FLog.severe("Failed to update track " + track.getName()); + FLog.severe(b); } }); } - - public CompletableFuture trackUser(User user) - { - Group group = fromName(track.getGroups().get(0)); // First group. - - return CompletableFuture.supplyAsync(() -> - lp.getContextManager() - .getContext(user) - .map(context -> user - .getInheritedGroups(QueryOptions.defaultContextualOptions()) - .add(group)) - .orElse(false)); - } - - public CompletableFuture promoteUser(User user) - { - boolean empty = user.getInheritedGroups(QueryOptions.defaultContextualOptions()) - .stream() - .filter(group -> track.getGroups().contains(group.getName())) - .findFirst() - .isEmpty(); - - if (empty) trackUser(user).whenComplete((ignored, throwable) -> - { - if (throwable != null) - { - FLog.severe("Failed to track user " + user.getFriendlyName()); - } - }); - - return CompletableFuture.supplyAsync(() -> - { - AtomicReference result = new AtomicReference<>(); - lp.getContextManager() - .getContext(user) - .ifPresent(context -> result.set(track.promote(user, context))); - return result.get(); - }); - } - - public void dropUserFromAll(User user) - { - for (String group : track.getGroups()) - { - dropUserFromGroup(user, fromName(group)) - .whenComplete((ignored, throwable) -> - { - if (throwable != null) - { - FLog.severe("Failed to drop user " - + user.getFriendlyName() - + " from group " - + group); - return; - } - FLog.info("Successfully removed " + user.getFriendlyName() + " from group " + group); - }); - } - } - - public CompletableFuture demoteUser(User user) - { - return CompletableFuture.supplyAsync(() -> { - lp.getContextManager() - .getContext(user) - .ifPresent(context -> track.demote(user, context)); - return null; - }); - } - - public CompletableFuture dropUserFromGroup(User user, Group group) - { - return CompletableFuture.supplyAsync(() -> user - .getInheritedGroups(QueryOptions.defaultContextualOptions()) - .remove(group)); - } - - public Group fromName(String name) - { - return lp.getGroupManager().getGroup(name); - } - - public CompletableFuture updateAppend(Group group) - { - return CompletableFuture.supplyAsync(() -> - { - if (!track.containsGroup(group.getName())) - { - track.appendGroup(group); - } - return null; - }); - } - - public CompletableFuture updateInsert(Group group, int index) - { - return CompletableFuture.supplyAsync(() -> - { - if (!track.containsGroup(group)) - { - track.insertGroup(group, index); - } - return null; - }); - } - - public CompletableFuture updateDrop(Group group) - { - return CompletableFuture.supplyAsync(() -> - { - if (track.containsGroup(group)) - { - track.removeGroup(group); - } - - return null; - }); - } } diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/HierarchyProvider.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/HierarchyProvider.java deleted file mode 100644 index 4ee9fa5f..00000000 --- a/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/HierarchyProvider.java +++ /dev/null @@ -1,11 +0,0 @@ -package me.totalfreedom.totalfreedommod.rank; - -@FunctionalInterface -public interface HierarchyProvider -{ - HierarchyProvider OP = () -> new Hierarchy("op-track"); - HierarchyProvider BUILDER = () -> new Hierarchy("builder-track"); - HierarchyProvider ADMIN = () -> new Hierarchy("admin-track"); - - T getHierarchy(); -} diff --git a/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/RankManager.java b/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/RankManager.java index 0fb2ff70..f2d9c3d4 100644 --- a/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/RankManager.java +++ b/commons/src/main/java/me/totalfreedom/totalfreedommod/rank/RankManager.java @@ -25,11 +25,17 @@ public class RankManager extends FreedomService @Override public void onStart() { - HierarchyProvider.OP.getHierarchy().addGroup(GroupProvider.NON_OP.getGroup()); - HierarchyProvider.OP.getHierarchy().addGroup(GroupProvider.OP.getGroup()); - HierarchyProvider.BUILDER.getHierarchy().addGroup(GroupProvider.MASTER_BUILDER.getGroup()); - HierarchyProvider.ADMIN.getHierarchy().addGroup(GroupProvider.ADMIN.getGroup()); - HierarchyProvider.ADMIN.getHierarchy().addGroup(GroupProvider.SENIOR_ADMIN.getGroup()); + + // Here, we are automatically creating new tracks if they don't exist, and then adding groups to them. + Hierarchy hierarchy = Hierarchy.getHierarchy(); + hierarchy.addGroupToTrack(hierarchy.op(), GroupProvider.NON_OP.getGroup()); + hierarchy.addGroupToTrack(hierarchy.op(), GroupProvider.OP.getGroup()); + hierarchy.addGroupToTrack(hierarchy.builder(), GroupProvider.MASTER_BUILDER.getGroup()); + hierarchy.addGroupToTrack(hierarchy.admin(), GroupProvider.ADMIN.getGroup()); + hierarchy.addGroupToTrack(hierarchy.admin(), GroupProvider.SENIOR_ADMIN.getGroup()); + + hierarchy.addInheritance(GroupProvider.NON_OP.getGroup(), GroupProvider.OP.getGroup()); + hierarchy.addInheritance(GroupProvider.ADMIN.getGroup(), GroupProvider.SENIOR_ADMIN.getGroup()); } @Override @@ -71,7 +77,7 @@ public class RankManager extends FreedomService // Master builders show up if they are not an admin if (plugin.pl.getData(player).isMasterBuilder() && !plugin.al.isAdmin(player)) { - return Title.MASTER_BUILDER; + return GroupProvider.MASTER_BUILDER.getGroup(); } return getRank(player); @@ -137,13 +143,11 @@ public class RankManager extends FreedomService return entry.getRank(); } - return plugin.lpb.getAPI() + String primary = plugin.lpb.getAPI() .getPlayerAdapter(Player.class) .getUser(player) - .getPrimaryGroup() - .equalsIgnoreCase("op") - ? GroupProvider.OP.getGroup() - : GroupProvider.NON_OP.getGroup(); + .getPrimaryGroup(); + return GroupProvider.fromString(primary).getGroup(); } public Component getTag(Player player, Component defaultTag) diff --git a/discord/pom.xml b/discord/pom.xml index 6560804d..f2f11df9 100644 --- a/discord/pom.xml +++ b/discord/pom.xml @@ -36,11 +36,5 @@ 3.5.4 provided - - me.totalfreedom - commons - 2023.03 - compile - \ No newline at end of file