From caa0aa69d913bad5e287fb737204632a5e7c2e50 Mon Sep 17 00:00:00 2001 From: libraryaddict Date: Thu, 16 Apr 2020 18:32:09 +1200 Subject: [PATCH] Add requirements for mods and see mods in use if so --- .../disguise/DisguiseConfig.java | 19 ++++ .../disguise/DisguiseListener.java | 47 +++++++- .../commands/LibsDisguisesCommand.java | 36 +++++- .../utilities/modded/ModdedManager.java | 104 +++++++++++++++++- .../packethandlers/PacketHandlerSpawn.java | 2 +- .../utilities/translations/LibsMsg.java | 3 + src/main/resources/disguises.yml | 6 +- src/main/resources/plugin.yml | 2 + 8 files changed, 209 insertions(+), 10 deletions(-) diff --git a/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java b/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java index 34f4008a..6c59b064 100644 --- a/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java +++ b/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java @@ -16,6 +16,7 @@ import me.libraryaddict.disguise.utilities.reflection.NmsVersion; import me.libraryaddict.disguise.utilities.translations.LibsMsg; import me.libraryaddict.disguise.utilities.translations.TranslateType; import org.bukkit.Bukkit; +import org.bukkit.ChatColor; import org.bukkit.NamespacedKey; import org.bukkit.boss.BarColor; import org.bukkit.boss.BarStyle; @@ -590,6 +591,8 @@ public class DisguiseConfig { return; } + ArrayList channels = new ArrayList<>(); + for (String name : config.getConfigurationSection("Custom-Entities").getKeys(false)) { try { if (!name.matches("[a-zA-Z0-9_]+")) { @@ -620,6 +623,20 @@ public class DisguiseConfig { String[] version = mod == null || !section.contains("Version") ? null : section.getString("Version").split(","); 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); @@ -635,6 +652,8 @@ public class DisguiseConfig { ex.printStackTrace(); } } + + new ModdedManager(channels); } public static ArrayList doOutput(ConfigurationSection config, boolean informChangedUnknown, diff --git a/src/main/java/me/libraryaddict/disguise/DisguiseListener.java b/src/main/java/me/libraryaddict/disguise/DisguiseListener.java index e35bad26..f72f19ad 100644 --- a/src/main/java/me/libraryaddict/disguise/DisguiseListener.java +++ b/src/main/java/me/libraryaddict/disguise/DisguiseListener.java @@ -12,6 +12,8 @@ import me.libraryaddict.disguise.utilities.DisguiseUtilities; import me.libraryaddict.disguise.utilities.LibsEntityInteract; import me.libraryaddict.disguise.utilities.LibsPremium; 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 org.apache.commons.lang.math.RandomUtils; import org.bukkit.Bukkit; @@ -41,6 +43,7 @@ import org.bukkit.scheduler.BukkitTask; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; +import java.util.Optional; import java.util.Random; import java.util.Set; 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 public void onJoin(PlayerJoinEvent event) { Player p = event.getPlayer(); @@ -428,17 +443,41 @@ public class DisguiseListener implements Listener { new BukkitRunnable() { @Override public void run() { - if (!event.getPlayer().isOnline()) { + if (!p.isOnline()) { return; } - DisguiseUtilities.registerNoName(event.getPlayer().getScoreboard()); + DisguiseUtilities.registerNoName(p.getScoreboard()); - if (event.getPlayer().getScoreboard() != Bukkit.getScoreboardManager().getMainScoreboard()) { - DisguiseUtilities.registerAllExtendedNames(event.getPlayer().getScoreboard()); + if (p.getScoreboard() != Bukkit.getScoreboardManager().getMainScoreboard()) { + DisguiseUtilities.registerAllExtendedNames(p.getScoreboard()); + } + + if (!p.hasMetadata("forge_mods")) { + Optional 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); + + new BukkitRunnable() { + @Override + public void run() { + if (!p.isOnline()) { + return; + } + + if (!p.hasMetadata("forge_mods")) { + Optional 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); + } /** diff --git a/src/main/java/me/libraryaddict/disguise/commands/LibsDisguisesCommand.java b/src/main/java/me/libraryaddict/disguise/commands/LibsDisguisesCommand.java index 66ec29a5..787ddd16 100644 --- a/src/main/java/me/libraryaddict/disguise/commands/LibsDisguisesCommand.java +++ b/src/main/java/me/libraryaddict/disguise/commands/LibsDisguisesCommand.java @@ -106,6 +106,40 @@ public class LibsDisguisesCommand implements CommandExecutor, TabCompleter { DisguiseConfig.loadConfig(); sender.sendMessage(LibsMsg.RELOADED_CONFIG.get()); 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) player.getMetadata("forge_mods").get(0).value(), ", "))); } else if (args[0].equalsIgnoreCase("scoreboard") || args[0].equalsIgnoreCase("board") || args[0].equalsIgnoreCase("teams")) { if (!sender.hasPermission("libsdisguises.scoreboardtest")) { @@ -368,7 +402,7 @@ public class LibsDisguisesCommand implements CommandExecutor, TabCompleter { String[] args = getArgs(origArgs); 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); } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/modded/ModdedManager.java b/src/main/java/me/libraryaddict/disguise/utilities/modded/ModdedManager.java index 68d53b6b..e594526e 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/modded/ModdedManager.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/modded/ModdedManager.java @@ -1,10 +1,18 @@ 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.utilities.parser.DisguisePerm; import me.libraryaddict.disguise.utilities.reflection.ReflectionManager; +import org.bukkit.Bukkit; 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.HashMap; import java.util.Map; @@ -12,8 +20,52 @@ import java.util.Map; /** * Created by libraryaddict on 14/04/2020. */ -public class ModdedManager { +public class ModdedManager implements PluginMessageListener { + @Getter private static final HashMap entities = new HashMap<>(); + @Getter + private static byte[] fmlHandshake; + + public ModdedManager(ArrayList 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) { if (entities.keySet().stream().anyMatch(n -> n.toString().equalsIgnoreCase(name.toString()))) { @@ -68,4 +120,54 @@ public class ModdedManager { 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 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(); + } + } } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/packets/packethandlers/PacketHandlerSpawn.java b/src/main/java/me/libraryaddict/disguise/utilities/packets/packethandlers/PacketHandlerSpawn.java index 39b5d198..54ea0631 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/packets/packethandlers/PacketHandlerSpawn.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/packets/packethandlers/PacketHandlerSpawn.java @@ -306,7 +306,7 @@ public class PacketHandlerSpawn implements IPacketHandler { PacketContainer spawnEntity; - if (NmsVersion.v1_14.isSupported()) { + if (NmsVersion.v1_14.isSupported()) {System.out.println("..."); Object entityType; if (disguise.isCustomDisguise()) { diff --git a/src/main/java/me/libraryaddict/disguise/utilities/translations/LibsMsg.java b/src/main/java/me/libraryaddict/disguise/utilities/translations/LibsMsg.java index 36ae0655..154221ee 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/translations/LibsMsg.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/translations/LibsMsg.java @@ -134,8 +134,11 @@ public enum LibsMsg { MADE_REF(ChatColor.RED + "Constructed a %s disguise! Your reference is %s"), MADE_REF_EXAMPLE(ChatColor.RED + "Example usage: /disguise %s"), 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_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 + "Ignored %s methods you do not have permission to use. Add 'show' to view unusable methods."), OWNED_BY(ChatColor.GOLD + "Plugin registered to '%%__USER__%%'!"), diff --git a/src/main/resources/disguises.yml b/src/main/resources/disguises.yml index e723b6c1..9f3ca5b6 100644 --- a/src/main/resources/disguises.yml +++ b/src/main/resources/disguises.yml @@ -53,6 +53,6 @@ Custom-Entities: # 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 # 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/version from joining with this error -# Required: 'Install LibAttacks! Download it from our site!' \ No newline at end of file +# If exists, will prevent anyone without the mod from joining with this error +# 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 \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 609bce57..1220e71d 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -88,6 +88,8 @@ commands: permissions: libsdisguises.reload: description: Allows the user to reload LibsDisguises. + libsdisguises.mods: + description: Allows the user to see mods in use. libsdisguises.seethrough: description: Allows player to see through disguises. default: false