package me.neznamy.tab.platforms.bukkit.features; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import me.neznamy.tab.platforms.bukkit.Main; import me.neznamy.tab.shared.Configs; import me.neznamy.tab.shared.ITabPlayer; import me.neznamy.tab.shared.Shared; import me.neznamy.tab.shared.cpu.CPUFeature; import me.neznamy.tab.shared.features.interfaces.PlayerInfoPacketListener; import me.neznamy.tab.shared.features.interfaces.JoinEventListener; import me.neznamy.tab.shared.features.interfaces.Loadable; import me.neznamy.tab.shared.features.interfaces.WorldChangeListener; import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo; import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo.EnumPlayerInfoAction; import me.neznamy.tab.shared.packets.PacketPlayOutPlayerInfo.PlayerInfoData; @SuppressWarnings({"deprecation", "unchecked"}) public class PerWorldPlayerlist implements Loadable, JoinEventListener, WorldChangeListener, PlayerInfoPacketListener{ private boolean allowBypass; private List<String> ignoredWorlds; private Map<String, List<String>> sharedWorlds; @Override public void load(){ allowBypass = Configs.advancedconfig.getBoolean("per-world-playerlist.allow-bypass-permission", false); ignoredWorlds = Configs.advancedconfig.getStringList("per-world-playerlist.ignore-effect-in-worlds", Arrays.asList("ignoredworld", "build")); sharedWorlds = Configs.advancedconfig.getConfigurationSection("per-world-playerlist.shared-playerlist-world-groups"); for (Player p : Main.instance.getOnlinePlayers()){ hidePlayer(p); showInSameWorldGroup(p); } } @Override public void unload(){ for (Player p : Main.instance.getOnlinePlayers()) for (Player pl : Main.instance.getOnlinePlayers()) p.showPlayer(pl); } @Override public void onJoin(ITabPlayer connectedPlayer) { hidePlayer(connectedPlayer.getBukkitEntity()); showInSameWorldGroup(connectedPlayer.getBukkitEntity()); } @Override public void onWorldChange(ITabPlayer p, String from, String to) { hidePlayer(p.getBukkitEntity()); showInSameWorldGroup(p.getBukkitEntity()); } private void showInSameWorldGroup(Player shown){ Bukkit.getScheduler().runTask(Main.instance, new Runnable() { @Override public void run() { for (Player everyone : Main.instance.getOnlinePlayers()){ if (everyone == shown) continue; if (shouldSee(shown, everyone)) shown.showPlayer(everyone); if (shouldSee(everyone, shown)) everyone.showPlayer(shown); } } }); } private boolean shouldSee(Player viewer, Player displayed) { if (displayed == viewer) return true; String player1WorldGroup = null; for (String group : sharedWorlds.keySet()) { if (sharedWorlds.get(group).contains(viewer.getWorld().getName())) player1WorldGroup = group; } String player2WorldGroup = null; for (String group : sharedWorlds.keySet()) { if (sharedWorlds.get(group).contains(displayed.getWorld().getName())) player2WorldGroup = group; } if (viewer.getWorld() == displayed.getWorld() || (player1WorldGroup != null && player2WorldGroup != null && player1WorldGroup.equals(player2WorldGroup))) { return true; } if ((allowBypass && viewer.hasPermission("tab.bypass")) || ignoredWorlds.contains(viewer.getWorld().getName())) { return true; } return false; } public void hidePlayer(Player hidden){ Bukkit.getScheduler().runTask(Main.instance, new Runnable() { @Override public void run() { for (Player everyone : Main.instance.getOnlinePlayers()){ if (everyone == hidden) continue; hidden.hidePlayer(everyone); everyone.hidePlayer(hidden); } } }); } //fixing bukkit api bug making players not hide when hidePlayer is called too early @Override public PacketPlayOutPlayerInfo onPacketSend(ITabPlayer receiver, PacketPlayOutPlayerInfo info) { if (info.action != EnumPlayerInfoAction.ADD_PLAYER) return info; List<PlayerInfoData> toRemove = new ArrayList<PlayerInfoData>(); for (PlayerInfoData data : info.entries) { ITabPlayer added = Shared.getPlayerByTablistUUID(data.uniqueId); if (added != null && !shouldSee(receiver.getBukkitEntity(), added.getBukkitEntity())) { toRemove.add(data); } } List<PlayerInfoData> newList = new ArrayList<PlayerInfoData>(); Arrays.asList(info.entries).forEach(d -> newList.add(d)); newList.removeAll(toRemove); info.entries = newList.toArray(new PlayerInfoData[0]); if (info.entries.length == 0) return null; return info; } @Override public CPUFeature getCPUName() { return CPUFeature.PER_WORLD_PLAYERLIST; } }