Add requirements for mods and see mods in use if so
This commit is contained in:
		| @@ -16,6 +16,7 @@ import me.libraryaddict.disguise.utilities.reflection.NmsVersion; | |||||||
| import me.libraryaddict.disguise.utilities.translations.LibsMsg; | import me.libraryaddict.disguise.utilities.translations.LibsMsg; | ||||||
| import me.libraryaddict.disguise.utilities.translations.TranslateType; | import me.libraryaddict.disguise.utilities.translations.TranslateType; | ||||||
| import org.bukkit.Bukkit; | import org.bukkit.Bukkit; | ||||||
|  | import org.bukkit.ChatColor; | ||||||
| import org.bukkit.NamespacedKey; | import org.bukkit.NamespacedKey; | ||||||
| import org.bukkit.boss.BarColor; | import org.bukkit.boss.BarColor; | ||||||
| import org.bukkit.boss.BarStyle; | import org.bukkit.boss.BarStyle; | ||||||
| @@ -590,6 +591,8 @@ public class DisguiseConfig { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         ArrayList<String> channels = new ArrayList<>(); | ||||||
|  |  | ||||||
|         for (String name : config.getConfigurationSection("Custom-Entities").getKeys(false)) { |         for (String name : config.getConfigurationSection("Custom-Entities").getKeys(false)) { | ||||||
|             try { |             try { | ||||||
|                 if (!name.matches("[a-zA-Z0-9_]+")) { |                 if (!name.matches("[a-zA-Z0-9_]+")) { | ||||||
| @@ -620,6 +623,20 @@ public class DisguiseConfig { | |||||||
|                 String[] version = |                 String[] version = | ||||||
|                         mod == null || !section.contains("Version") ? null : section.getString("Version").split(","); |                         mod == null || !section.contains("Version") ? null : section.getString("Version").split(","); | ||||||
|                 String requireMessage = mod == null ? null : section.getString("Required"); |                 String requireMessage = mod == null ? null : section.getString("Required"); | ||||||
|  |                 if (section.contains("Channels")) { | ||||||
|  |                     for (String s : section.getString("Channels").split(",")) { | ||||||
|  |                         if (!s.contains("|")) { | ||||||
|  |                             s += "|"; | ||||||
|  |                             DisguiseUtilities.getLogger().severe("No channel version declared for " + s); | ||||||
|  |                         } | ||||||
|  |  | ||||||
|  |                         channels.add(s); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (requireMessage != null) { | ||||||
|  |                     requireMessage = ChatColor.translateAlternateColorCodes('&', requireMessage); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|                 CustomEntity entity = new CustomEntity(null, name, living, mod, version, requireMessage, 0); |                 CustomEntity entity = new CustomEntity(null, name, living, mod, version, requireMessage, 0); | ||||||
|  |  | ||||||
| @@ -635,6 +652,8 @@ public class DisguiseConfig { | |||||||
|                 ex.printStackTrace(); |                 ex.printStackTrace(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         new ModdedManager(channels); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static ArrayList<String> doOutput(ConfigurationSection config, boolean informChangedUnknown, |     public static ArrayList<String> doOutput(ConfigurationSection config, boolean informChangedUnknown, | ||||||
|   | |||||||
| @@ -12,6 +12,8 @@ import me.libraryaddict.disguise.utilities.DisguiseUtilities; | |||||||
| import me.libraryaddict.disguise.utilities.LibsEntityInteract; | import me.libraryaddict.disguise.utilities.LibsEntityInteract; | ||||||
| import me.libraryaddict.disguise.utilities.LibsPremium; | import me.libraryaddict.disguise.utilities.LibsPremium; | ||||||
| import me.libraryaddict.disguise.utilities.UpdateChecker; | import me.libraryaddict.disguise.utilities.UpdateChecker; | ||||||
|  | import me.libraryaddict.disguise.utilities.modded.CustomEntity; | ||||||
|  | import me.libraryaddict.disguise.utilities.modded.ModdedManager; | ||||||
| import me.libraryaddict.disguise.utilities.translations.LibsMsg; | import me.libraryaddict.disguise.utilities.translations.LibsMsg; | ||||||
| import org.apache.commons.lang.math.RandomUtils; | import org.apache.commons.lang.math.RandomUtils; | ||||||
| import org.bukkit.Bukkit; | import org.bukkit.Bukkit; | ||||||
| @@ -41,6 +43,7 @@ import org.bukkit.scheduler.BukkitTask; | |||||||
|  |  | ||||||
| import java.lang.reflect.InvocationTargetException; | import java.lang.reflect.InvocationTargetException; | ||||||
| import java.util.HashMap; | import java.util.HashMap; | ||||||
|  | import java.util.Optional; | ||||||
| import java.util.Random; | import java.util.Random; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
| import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||||
| @@ -372,6 +375,18 @@ public class DisguiseListener implements Listener { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @EventHandler | ||||||
|  |     public void onLogin(PlayerRegisterChannelEvent event) { | ||||||
|  |         // If it's not a forge handshake, or we didn't register it | ||||||
|  |         if (!event.getChannel().equals("fml:handshake") || | ||||||
|  |                 !Bukkit.getMessenger().isOutgoingChannelRegistered(LibsDisguises.getInstance(), "fml:handshake")) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         event.getPlayer() | ||||||
|  |                 .sendPluginMessage(LibsDisguises.getInstance(), "fml:handshake", ModdedManager.getFmlHandshake()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @EventHandler |     @EventHandler | ||||||
|     public void onJoin(PlayerJoinEvent event) { |     public void onJoin(PlayerJoinEvent event) { | ||||||
|         Player p = event.getPlayer(); |         Player p = event.getPlayer(); | ||||||
| @@ -428,17 +443,41 @@ public class DisguiseListener implements Listener { | |||||||
|         new BukkitRunnable() { |         new BukkitRunnable() { | ||||||
|             @Override |             @Override | ||||||
|             public void run() { |             public void run() { | ||||||
|                 if (!event.getPlayer().isOnline()) { |                 if (!p.isOnline()) { | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 DisguiseUtilities.registerNoName(event.getPlayer().getScoreboard()); |                 DisguiseUtilities.registerNoName(p.getScoreboard()); | ||||||
|  |  | ||||||
|                 if (event.getPlayer().getScoreboard() != Bukkit.getScoreboardManager().getMainScoreboard()) { |                 if (p.getScoreboard() != Bukkit.getScoreboardManager().getMainScoreboard()) { | ||||||
|                     DisguiseUtilities.registerAllExtendedNames(event.getPlayer().getScoreboard()); |                     DisguiseUtilities.registerAllExtendedNames(p.getScoreboard()); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (!p.hasMetadata("forge_mods")) { | ||||||
|  |                     Optional<CustomEntity> required = ModdedManager.getEntities().values().stream() | ||||||
|  |                             .filter(c -> c.getMod() != null && c.getRequired() != null).findAny(); | ||||||
|  |  | ||||||
|  |                     required.ifPresent(customEntity -> p.kickPlayer(customEntity.getRequired())); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         }.runTaskLater(LibsDisguises.getInstance(), 20); |         }.runTaskLater(LibsDisguises.getInstance(), 20); | ||||||
|  |  | ||||||
|  |         new BukkitRunnable() { | ||||||
|  |             @Override | ||||||
|  |             public void run() { | ||||||
|  |                 if (!p.isOnline()) { | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (!p.hasMetadata("forge_mods")) { | ||||||
|  |                     Optional<CustomEntity> required = ModdedManager.getEntities().values().stream() | ||||||
|  |                             .filter(c -> c.getMod() != null && c.getRequired() != null).findAny(); | ||||||
|  |  | ||||||
|  |                     required.ifPresent(customEntity -> p.kickPlayer(customEntity.getRequired())); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }.runTaskLater(LibsDisguises.getInstance(), 60); | ||||||
|  |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|   | |||||||
| @@ -106,6 +106,40 @@ public class LibsDisguisesCommand implements CommandExecutor, TabCompleter { | |||||||
|                 DisguiseConfig.loadConfig(); |                 DisguiseConfig.loadConfig(); | ||||||
|                 sender.sendMessage(LibsMsg.RELOADED_CONFIG.get()); |                 sender.sendMessage(LibsMsg.RELOADED_CONFIG.get()); | ||||||
|                 return true; |                 return true; | ||||||
|  |             } else if (args[0].equalsIgnoreCase("mods")) { | ||||||
|  |                 if (!sender.hasPermission("libsdisguises.mods")) { | ||||||
|  |                     sender.sendMessage(LibsMsg.NO_PERM.get()); | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (!Bukkit.getMessenger().isOutgoingChannelRegistered(LibsDisguises.getInstance(), "fml:handshake")) { | ||||||
|  |                     sender.sendMessage(LibsMsg.NO_MODS_LISTENING.get()); | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 Player player; | ||||||
|  |  | ||||||
|  |                 if (args.length > 1) { | ||||||
|  |                     player = Bukkit.getPlayer(args[1]); | ||||||
|  |  | ||||||
|  |                     if (player == null) { | ||||||
|  |                         sender.sendMessage(LibsMsg.CANNOT_FIND_PLAYER.get(args[1])); | ||||||
|  |                         return true; | ||||||
|  |                     } | ||||||
|  |                 } else if (sender instanceof Player) { | ||||||
|  |                     player = (Player) sender; | ||||||
|  |                 } else { | ||||||
|  |                     sender.sendMessage(LibsMsg.NO_CONSOLE.get()); | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (!player.hasMetadata("forge_mods")) { | ||||||
|  |                     sender.sendMessage(LibsMsg.NO_MODS.get(player.getName())); | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 sender.sendMessage(LibsMsg.MODS_LIST.get(player.getName(), | ||||||
|  |                         StringUtils.join((List<String>) player.getMetadata("forge_mods").get(0).value(), ", "))); | ||||||
|             } else if (args[0].equalsIgnoreCase("scoreboard") || args[0].equalsIgnoreCase("board") || |             } else if (args[0].equalsIgnoreCase("scoreboard") || args[0].equalsIgnoreCase("board") || | ||||||
|                     args[0].equalsIgnoreCase("teams")) { |                     args[0].equalsIgnoreCase("teams")) { | ||||||
|                 if (!sender.hasPermission("libsdisguises.scoreboardtest")) { |                 if (!sender.hasPermission("libsdisguises.scoreboardtest")) { | ||||||
| @@ -368,7 +402,7 @@ public class LibsDisguisesCommand implements CommandExecutor, TabCompleter { | |||||||
|         String[] args = getArgs(origArgs); |         String[] args = getArgs(origArgs); | ||||||
|  |  | ||||||
|         if (args.length == 0) |         if (args.length == 0) | ||||||
|             tabs.addAll(Arrays.asList("reload", "scoreboard", "permtest", "json", "metainfo", "config")); |             tabs.addAll(Arrays.asList("reload", "scoreboard", "permtest", "json", "metainfo", "config", "mods")); | ||||||
|  |  | ||||||
|         return filterTabs(tabs, origArgs); |         return filterTabs(tabs, origArgs); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -1,10 +1,18 @@ | |||||||
| package me.libraryaddict.disguise.utilities.modded; | package me.libraryaddict.disguise.utilities.modded; | ||||||
|  |  | ||||||
|  | import com.comphenix.protocol.utility.StreamSerializer; | ||||||
|  | import lombok.Getter; | ||||||
|  | import me.libraryaddict.disguise.LibsDisguises; | ||||||
| import me.libraryaddict.disguise.disguisetypes.DisguiseType; | import me.libraryaddict.disguise.disguisetypes.DisguiseType; | ||||||
| import me.libraryaddict.disguise.utilities.parser.DisguisePerm; | import me.libraryaddict.disguise.utilities.parser.DisguisePerm; | ||||||
| import me.libraryaddict.disguise.utilities.reflection.ReflectionManager; | import me.libraryaddict.disguise.utilities.reflection.ReflectionManager; | ||||||
|  | import org.bukkit.Bukkit; | ||||||
| import org.bukkit.NamespacedKey; | import org.bukkit.NamespacedKey; | ||||||
|  | import org.bukkit.entity.Player; | ||||||
|  | import org.bukkit.metadata.FixedMetadataValue; | ||||||
|  | import org.bukkit.plugin.messaging.PluginMessageListener; | ||||||
|  |  | ||||||
|  | import java.io.*; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.HashMap; | import java.util.HashMap; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| @@ -12,8 +20,52 @@ import java.util.Map; | |||||||
| /** | /** | ||||||
|  * Created by libraryaddict on 14/04/2020. |  * Created by libraryaddict on 14/04/2020. | ||||||
|  */ |  */ | ||||||
| public class ModdedManager { | public class ModdedManager implements PluginMessageListener { | ||||||
|  |     @Getter | ||||||
|     private static final HashMap<NamespacedKey, CustomEntity> entities = new HashMap<>(); |     private static final HashMap<NamespacedKey, CustomEntity> entities = new HashMap<>(); | ||||||
|  |     @Getter | ||||||
|  |     private static byte[] fmlHandshake; | ||||||
|  |  | ||||||
|  |     public ModdedManager(ArrayList<String> channels) { | ||||||
|  |         if (getEntities().isEmpty()) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (getEntities().values().stream().noneMatch(e -> e.getMod() != null)) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         Bukkit.getMessenger().registerOutgoingPluginChannel(LibsDisguises.getInstance(), "fml:handshake"); | ||||||
|  |         Bukkit.getMessenger().registerIncomingPluginChannel(LibsDisguises.getInstance(), "fml:handshake", this); | ||||||
|  |  | ||||||
|  |         ByteArrayOutputStream stream = new ByteArrayOutputStream(); | ||||||
|  |         DataOutputStream output = new DataOutputStream(stream); | ||||||
|  |  | ||||||
|  |         StreamSerializer s = StreamSerializer.getDefault(); | ||||||
|  |  | ||||||
|  |         try { | ||||||
|  |             // Packet id 1 | ||||||
|  |             s.serializeVarInt(output, 1); | ||||||
|  |             // We have no mods to declare | ||||||
|  |             s.serializeVarInt(output, 0); | ||||||
|  |  | ||||||
|  |             // We want to declare some channels | ||||||
|  |             s.serializeVarInt(output, channels.size()); | ||||||
|  |  | ||||||
|  |             for (String channel : channels) { | ||||||
|  |                 s.serializeString(output, channel.substring(0, channel.indexOf("|"))); | ||||||
|  |                 s.serializeString(output, channel.substring(channel.indexOf("|") + 1)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // We have no resources to declare | ||||||
|  |             s.serializeVarInt(output, 0); | ||||||
|  |         } | ||||||
|  |         catch (IOException e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         fmlHandshake = stream.toByteArray(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     public static void registerCustomEntity(NamespacedKey name, CustomEntity entity, boolean register) { |     public static void registerCustomEntity(NamespacedKey name, CustomEntity entity, boolean register) { | ||||||
|         if (entities.keySet().stream().anyMatch(n -> n.toString().equalsIgnoreCase(name.toString()))) { |         if (entities.keySet().stream().anyMatch(n -> n.toString().equalsIgnoreCase(name.toString()))) { | ||||||
| @@ -68,4 +120,54 @@ public class ModdedManager { | |||||||
|  |  | ||||||
|         return perms; |         return perms; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void onPluginMessageReceived(String channel, Player player, byte[] bytes) { | ||||||
|  |         if (player.hasMetadata("forge_mods")) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         DataInputStream stream = new DataInputStream(new ByteArrayInputStream(bytes)); | ||||||
|  |  | ||||||
|  |         try { | ||||||
|  |             StreamSerializer s = StreamSerializer.getDefault(); | ||||||
|  |             int packetId = s.deserializeVarInt(stream); | ||||||
|  |  | ||||||
|  |             if (packetId != 2) { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             int count = s.deserializeVarInt(stream); | ||||||
|  |  | ||||||
|  |             ArrayList<String> mods = new ArrayList<>(); | ||||||
|  |  | ||||||
|  |             for (int i = 0; i < count; i++) { | ||||||
|  |                 mods.add(s.deserializeString(stream, 256)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             player.setMetadata("forge_mods", new FixedMetadataValue(LibsDisguises.getInstance(), mods)); | ||||||
|  |  | ||||||
|  |             for (CustomEntity e : getEntities().values()) { | ||||||
|  |                 if (e.getMod() == null) { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (mods.contains(e.getMod().toLowerCase())) { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 // TODO Idk, something because they don't have a mod? | ||||||
|  |  | ||||||
|  |                 if (e.getRequired() == null) { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 player.kickPlayer(e.getRequired()); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         catch (IOException e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -306,7 +306,7 @@ public class PacketHandlerSpawn implements IPacketHandler { | |||||||
|  |  | ||||||
|             PacketContainer spawnEntity; |             PacketContainer spawnEntity; | ||||||
|  |  | ||||||
|             if (NmsVersion.v1_14.isSupported()) { |             if (NmsVersion.v1_14.isSupported()) {System.out.println("..."); | ||||||
|                 Object entityType; |                 Object entityType; | ||||||
|  |  | ||||||
|                 if (disguise.isCustomDisguise()) { |                 if (disguise.isCustomDisguise()) { | ||||||
|   | |||||||
| @@ -134,8 +134,11 @@ public enum LibsMsg { | |||||||
|     MADE_REF(ChatColor.RED + "Constructed a %s disguise! Your reference is %s"), |     MADE_REF(ChatColor.RED + "Constructed a %s disguise! Your reference is %s"), | ||||||
|     MADE_REF_EXAMPLE(ChatColor.RED + "Example usage: /disguise %s"), |     MADE_REF_EXAMPLE(ChatColor.RED + "Example usage: /disguise %s"), | ||||||
|     NO_CONSOLE(ChatColor.RED + "You may not use this command from the console!"), |     NO_CONSOLE(ChatColor.RED + "You may not use this command from the console!"), | ||||||
|  |     NO_MODS(ChatColor.RED + "%s is not using any mods!"), | ||||||
|  |     MODS_LIST(ChatColor.DARK_GREEN + "%s has the mods:" + ChatColor.AQUA + " %s"), | ||||||
|     NO_PERM(ChatColor.RED + "You are forbidden to use this command."), |     NO_PERM(ChatColor.RED + "You are forbidden to use this command."), | ||||||
|     NO_PERM_DISGUISE(ChatColor.RED + "You do not have permission for that disguise!"), |     NO_PERM_DISGUISE(ChatColor.RED + "You do not have permission for that disguise!"), | ||||||
|  |     NO_MODS_LISTENING(ChatColor.RED + "This server is not listening for mods!"), | ||||||
|     NO_PERMS_USE_OPTIONS(ChatColor.RED + |     NO_PERMS_USE_OPTIONS(ChatColor.RED + | ||||||
|             "Ignored %s methods you do not have permission to use. Add 'show' to view unusable methods."), |             "Ignored %s methods you do not have permission to use. Add 'show' to view unusable methods."), | ||||||
|     OWNED_BY(ChatColor.GOLD + "Plugin registered to '%%__USER__%%'!"), |     OWNED_BY(ChatColor.GOLD + "Plugin registered to '%%__USER__%%'!"), | ||||||
|   | |||||||
| @@ -53,6 +53,6 @@ Custom-Entities: | |||||||
| #    Register: true # This means Lib's Disguises should register the EntityType in nms, not another plugin | #    Register: true # This means Lib's Disguises should register the EntityType in nms, not another plugin | ||||||
| #    Type: LIVING # MISC, LIVING - What type of disguise type, doesn't support custom packets | #    Type: LIVING # MISC, LIVING - What type of disguise type, doesn't support custom packets | ||||||
| #    Mod: LibAttacks # The mod they need installed | #    Mod: LibAttacks # The mod they need installed | ||||||
| #    Version: '1.0,1.01,@2\.[0]+' # The version they need seperated by commas, the prefix @ means its regex | # If exists, will prevent anyone without the mod from joining with this error | ||||||
| # If exists, will prevent anyone without the mod/version from joining with this error | #    Required: 'Install LibAttacks! Download it from our site!' | ||||||
| #    Required: 'Install LibAttacks! Download it from our site!' | #    Channels: librarian:channel|1 # Sometimes a mod needs a channel enabled.. Seperate each channel with a comma | ||||||
| @@ -88,6 +88,8 @@ commands: | |||||||
| permissions: | permissions: | ||||||
|     libsdisguises.reload: |     libsdisguises.reload: | ||||||
|       description: Allows the user to reload LibsDisguises. |       description: Allows the user to reload LibsDisguises. | ||||||
|  |     libsdisguises.mods: | ||||||
|  |       description: Allows the user to see mods in use. | ||||||
|     libsdisguises.seethrough: |     libsdisguises.seethrough: | ||||||
|       description: Allows player to see through disguises. |       description: Allows player to see through disguises. | ||||||
|       default: false |       default: false | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user