package me.totalfreedom.totalfreedommod.rank; import me.totalfreedom.totalfreedommod.TotalFreedomMod; 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.track.PromotionResult; import net.luckperms.api.track.Track; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; public class Hierarchy { private final LuckPerms lp; private final Track track; public Hierarchy(String name) { this.lp = TotalFreedomMod.getPlugin().lpb.getAPI(); if (lp == null) { throw new IllegalStateException("LuckPerms not found!"); } if (!lp.getTrackManager().isLoaded(name)) { this.track = lp.getTrackManager().createAndLoadTrack(name).whenComplete((ignored, throwable) -> { if (throwable != null) { 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); } } 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()); } }); } public void addGroupNonBlocking(Group group, int index) { updateInsert(group, index).whenComplete((ignored, throwable) -> { if (throwable != null) { FLog.severe("Failed to update track " + track.getName()); } }); } 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; }); } }