ProjectAres/Commons/bukkit/src/main/java/tc/oc/commons/bukkit/nick/PlayerOrderCache.java

90 lines
3.6 KiB
Java

package tc.oc.commons.bukkit.nick;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ComparisonChain;
import com.google.common.eventbus.Subscribe;
import java.lang.ref.WeakReference;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerQuitEvent;
import tc.oc.api.bukkit.users.BukkitUserStore;
import tc.oc.api.minecraft.MinecraftService;
import tc.oc.api.minecraft.servers.LocalServerReconfigureEvent;
import tc.oc.commons.core.plugin.PluginFacet;
import tc.oc.commons.core.util.CacheUtils;
@Singleton
public class PlayerOrderCache implements PlayerOrder.Factory, PluginFacet {
private final LoadingCache<Player, Integer> prioritiesByPlayer;
private final LoadingCache<CommandSender, PlayerOrder> comparatorsByViewer;
@Inject PlayerOrderCache(IdentityProvider identityProvider, BukkitUserStore userStore, MinecraftService minecraftService) {
prioritiesByPlayer = CacheUtils.newWeakKeyCache(player -> userStore
.getUser(player)
.minecraft_flair()
.stream()
.filter(flair -> minecraftService.getLocalServer().realms().contains(flair.realm))
.map(flair -> flair.priority)
.min(Integer::compare)
.orElse(Integer.MAX_VALUE)
);
comparatorsByViewer = CacheUtils.newWeakKeyCache(strongViewer -> {
final WeakReference<CommandSender> weakViewer = new WeakReference<>(strongViewer);
return (a, b) -> {
// Do not reference strongViewer in here
final CommandSender viewer = weakViewer.get();
if(viewer == null) return 0;
final Identity aIdentity = identityProvider.currentIdentity(a);
final Identity bIdentity = identityProvider.currentIdentity(b);
return ComparisonChain.start()
.compareTrueFirst(a == viewer, b == viewer)
.compareTrueFirst(aIdentity.isFriend(viewer), bIdentity.isFriend(viewer))
.compare(priority(a, aIdentity, viewer), priority(b, bIdentity, viewer))
.compare(aIdentity.getName(viewer), bIdentity.getName(viewer), String::compareToIgnoreCase)
.result();
};
});
}
private int priority(Player player, Identity identity, CommandSender viewer) {
if(identity.isDisguised(viewer)) return Integer.MAX_VALUE;
final Integer priority = prioritiesByPlayer.getUnchecked(player);
if(!player.willBeOnline()) {
prioritiesByPlayer.invalidate(player);
}
return priority;
}
@Override
public PlayerOrder apply(CommandSender viewer) {
final PlayerOrder order = comparatorsByViewer.getUnchecked(viewer);
if(viewer instanceof Player && !((Player) viewer).willBeOnline()) {
comparatorsByViewer.invalidate(viewer);
}
return order;
}
@Subscribe
public void onReconfigure(LocalServerReconfigureEvent event) {
// Invalidate everything if local realms change
if(event.getOldConfig() != null && !event.getOldConfig().realms().equals(event.getNewConfig().realms())) {
prioritiesByPlayer.invalidateAll();
}
}
@EventHandler(priority = EventPriority.MONITOR)
private void onQuit(PlayerQuitEvent event) {
prioritiesByPlayer.invalidate(event.getPlayer());
comparatorsByViewer.invalidate(event.getPlayer());
}
}