From 6e99b42919cf02b8db3fb384e6635fe7dfeb99d4 Mon Sep 17 00:00:00 2001 From: lucky-fish Date: Tue, 18 Aug 2020 19:47:10 +0000 Subject: [PATCH] Add whitelist and compress data. --- pom.xml | 15 +++- .../antileakaccount/AntiLeakAccount.java | 24 ++++++ .../bungee/AntiLeakAccount.java | 10 +++ .../bungee/command/WhiteListCommand.java | 56 +++++++++++++ .../bungee/storage/PlayerStorage.java | 24 +----- .../command/CommandHelper.java | 27 +++++++ .../command/WhiteListAddCommand.java | 51 ++++++++++++ .../command/WhiteListListCommand.java | 42 ++++++++++ .../command/WhiteListRemoveCommand.java | 52 +++++++++++++ .../listener/PlayerListener.java | 8 ++ .../mojang/MojangApiHelper.java | 28 +++++++ .../antileakaccount/mojang/UserCache.java | 18 ++++- .../storage/BungeeStorage.java | 8 +- .../storage/PlayerStorage.java | 30 ++----- .../antileakaccount/util/UuidHelper.java | 41 ++++++++++ .../antileakaccount/verify/VerifyManager.java | 6 +- .../whitelist/WhiteListStorage.java | 78 +++++++++++++++++++ src/main/resources/plugin.yml | 21 +++++ 18 files changed, 489 insertions(+), 50 deletions(-) create mode 100644 src/main/java/cn/mcres/luckyfish/antileakaccount/bungee/command/WhiteListCommand.java create mode 100644 src/main/java/cn/mcres/luckyfish/antileakaccount/command/CommandHelper.java create mode 100644 src/main/java/cn/mcres/luckyfish/antileakaccount/command/WhiteListAddCommand.java create mode 100644 src/main/java/cn/mcres/luckyfish/antileakaccount/command/WhiteListListCommand.java create mode 100644 src/main/java/cn/mcres/luckyfish/antileakaccount/command/WhiteListRemoveCommand.java create mode 100644 src/main/java/cn/mcres/luckyfish/antileakaccount/util/UuidHelper.java create mode 100644 src/main/java/cn/mcres/luckyfish/antileakaccount/whitelist/WhiteListStorage.java diff --git a/pom.xml b/pom.xml index dfd8b63..aedcba5 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ cn.mcres.luckyfish AntiLeakAccount - 1.0.0-BETA + 1.1.0-BETA jar AntiLeakAccount @@ -66,6 +66,12 @@ bungeecord-repo https://oss.sonatype.org/content/repositories/snapshots + + luckyfish-repo + + https://raw.githubusercontent.com/Lucky-fish/mvn-repo/master/ + + @@ -76,7 +82,7 @@ provided - org.nanohttpd + org.nanohttpd nanohttpd 2.2.0 @@ -104,5 +110,10 @@ javadoc provided + + cn.mcres.luckyfish + PluginCommons + 1.2-SNAPSHOT + diff --git a/src/main/java/cn/mcres/luckyfish/antileakaccount/AntiLeakAccount.java b/src/main/java/cn/mcres/luckyfish/antileakaccount/AntiLeakAccount.java index 5ec1ff5..2f923dd 100644 --- a/src/main/java/cn/mcres/luckyfish/antileakaccount/AntiLeakAccount.java +++ b/src/main/java/cn/mcres/luckyfish/antileakaccount/AntiLeakAccount.java @@ -1,11 +1,16 @@ package cn.mcres.luckyfish.antileakaccount; import cn.mcres.luckyfish.antileakaccount.api.ApiServer; +import cn.mcres.luckyfish.antileakaccount.command.WhiteListAddCommand; +import cn.mcres.luckyfish.antileakaccount.command.WhiteListListCommand; +import cn.mcres.luckyfish.antileakaccount.command.WhiteListRemoveCommand; import cn.mcres.luckyfish.antileakaccount.http.HttpServer; import cn.mcres.luckyfish.antileakaccount.listener.PlayerListener; import cn.mcres.luckyfish.antileakaccount.mojang.MojangApiHelper; import cn.mcres.luckyfish.antileakaccount.task.SpamTask; import cn.mcres.luckyfish.antileakaccount.verify.VerifyManager; +import cn.mcres.luckyfish.antileakaccount.whitelist.WhiteListStorage; +import cn.mcres.luckyfish.plugincommons.commands.CommonCommand; import org.bukkit.plugin.java.JavaPlugin; import java.io.IOException; @@ -15,6 +20,7 @@ public final class AntiLeakAccount extends JavaPlugin { private ConfigHolder configHolder; private VerifyManager verifyManager; + private WhiteListStorage whiteListStorage = null; @Override public void onEnable() { // Plugin startup logic @@ -30,6 +36,10 @@ public void onEnable() { MojangApiHelper.setUserCache(getDataFolder()); verifyManager = new VerifyManager(); + if (!configHolder.bungeeMode) { + whiteListStorage = new WhiteListStorage(getDataFolder()); + } + if (configHolder.httpdEnabled) { HttpServer hs = new HttpServer(); try { @@ -41,6 +51,16 @@ public void onEnable() { if (configHolder.apiEnabled) { new ApiServer(); } + + if (!configHolder.bungeeMode) { + CommonCommand whiteListCommand = new CommonCommand(); + whiteListCommand.registerCommand(new WhiteListAddCommand()); + whiteListCommand.registerCommand(new WhiteListRemoveCommand()); + whiteListCommand.registerCommand(new WhiteListListCommand()); + getCommand("alawhitelist").setExecutor(whiteListCommand); + getCommand("alawhitelist").setTabCompleter(whiteListCommand); + } + getServer().getPluginManager().registerEvents(new PlayerListener(), this); getServer().getScheduler().runTaskTimer(this, new SpamTask(), configHolder.spamInterval, configHolder.spamInterval); } @@ -61,4 +81,8 @@ public ConfigHolder getConfigHolder() { public VerifyManager getVerifyManager() { return verifyManager; } + + public WhiteListStorage getWhiteListStorage() { + return whiteListStorage; + } } diff --git a/src/main/java/cn/mcres/luckyfish/antileakaccount/bungee/AntiLeakAccount.java b/src/main/java/cn/mcres/luckyfish/antileakaccount/bungee/AntiLeakAccount.java index 800da63..f4a8a16 100644 --- a/src/main/java/cn/mcres/luckyfish/antileakaccount/bungee/AntiLeakAccount.java +++ b/src/main/java/cn/mcres/luckyfish/antileakaccount/bungee/AntiLeakAccount.java @@ -1,14 +1,17 @@ package cn.mcres.luckyfish.antileakaccount.bungee; +import cn.mcres.luckyfish.antileakaccount.bungee.command.WhiteListCommand; import cn.mcres.luckyfish.antileakaccount.bungee.listener.PlayerListener; import cn.mcres.luckyfish.antileakaccount.bungee.listener.PluginListener; import cn.mcres.luckyfish.antileakaccount.bungee.storage.PlayerStorage; import cn.mcres.luckyfish.antileakaccount.mojang.MojangApiHelper; +import cn.mcres.luckyfish.antileakaccount.whitelist.WhiteListStorage; import net.md_5.bungee.api.plugin.Plugin; public class AntiLeakAccount extends Plugin { private static AntiLeakAccount instance; private PlayerStorage ps; + private WhiteListStorage whiteListStorage; @Override public void onEnable() { instance = this; @@ -18,11 +21,14 @@ public void onEnable() { } ps = new PlayerStorage(); + whiteListStorage = new WhiteListStorage(getDataFolder()); getProxy().registerChannel("ala:message"); MojangApiHelper.setUserCache(getDataFolder()); getProxy().getPluginManager().registerListener(this, new PlayerListener()); getProxy().getPluginManager().registerListener(this, new PluginListener()); + getProxy().getPluginManager().registerCommand(this, new WhiteListCommand()); + } public PlayerStorage getPlayerStorage() { @@ -32,4 +38,8 @@ public PlayerStorage getPlayerStorage() { public static AntiLeakAccount getInstance() { return instance; } + + public WhiteListStorage getWhiteListStorage() { + return whiteListStorage; + } } diff --git a/src/main/java/cn/mcres/luckyfish/antileakaccount/bungee/command/WhiteListCommand.java b/src/main/java/cn/mcres/luckyfish/antileakaccount/bungee/command/WhiteListCommand.java new file mode 100644 index 0000000..9e862bc --- /dev/null +++ b/src/main/java/cn/mcres/luckyfish/antileakaccount/bungee/command/WhiteListCommand.java @@ -0,0 +1,56 @@ +package cn.mcres.luckyfish.antileakaccount.bungee.command; + +import cn.mcres.luckyfish.antileakaccount.bungee.AntiLeakAccount; +import cn.mcres.luckyfish.antileakaccount.mojang.MojangApiHelper; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.api.plugin.Command; + +import java.util.List; +import java.util.UUID; + +public class WhiteListCommand extends Command { + public WhiteListCommand() { + super("alawhitelist", "antileakaccount.whitelist", "awhitelist", "aw"); + } + + @Override + public void execute(CommandSender sender, String[] args) { + switch (args[0]) { + case "add": { + if (args.length != 2) { + sender.sendMessage(new TextComponent("用法:/alawhitelist add <玩家名>")); + break; + } + + if (AntiLeakAccount.getInstance().getWhiteListStorage().addWhitelistPlayer(args[1])) { + sender.sendMessage(new TextComponent(ChatColor.GREEN + "已将" + args[1] + "加入白名单,该玩家不再需要接受黑卡验证")); + } else { + sender.sendMessage(new TextComponent(ChatColor.RED + "你说的" + args[1] + ",她长什么样?")); + } + + break; + } + case "remove": { + if (args.length != 2) { + sender.sendMessage(new TextComponent("用法:/alawhitelist remove <玩家名>")); + break; + } + + if (AntiLeakAccount.getInstance().getWhiteListStorage().removeWhitelistPlayer(args[1])) { + sender.sendMessage(new TextComponent(ChatColor.GREEN + "已将" + args[1] + "移除白名单,该玩家再次需要接受黑卡验证")); + } else { + sender.sendMessage(new TextComponent(ChatColor.RED + "你说的" + args[1] + ",她长什么样?")); + } + break; + } + case "list": { + List whiteList = AntiLeakAccount.getInstance().getWhiteListStorage().getWhiteList();; + for (UUID uid : whiteList) { + sender.sendMessage(new TextComponent(ChatColor.YELLOW + "玩家 " + ChatColor.GREEN + MojangApiHelper.getMinecraftNameByUuid(uid) + " - " + uid)); + } + } + } + } +} diff --git a/src/main/java/cn/mcres/luckyfish/antileakaccount/bungee/storage/PlayerStorage.java b/src/main/java/cn/mcres/luckyfish/antileakaccount/bungee/storage/PlayerStorage.java index 4aa6c32..ddecc39 100644 --- a/src/main/java/cn/mcres/luckyfish/antileakaccount/bungee/storage/PlayerStorage.java +++ b/src/main/java/cn/mcres/luckyfish/antileakaccount/bungee/storage/PlayerStorage.java @@ -2,6 +2,7 @@ import cn.mcres.luckyfish.antileakaccount.bungee.AntiLeakAccount; import cn.mcres.luckyfish.antileakaccount.mojang.MojangApiHelper; +import cn.mcres.luckyfish.antileakaccount.util.UuidHelper; import net.md_5.bungee.api.connection.ProxiedPlayer; import java.io.*; @@ -22,20 +23,11 @@ public PlayerStorage() { } } - try (DataInputStream dis = new DataInputStream(new FileInputStream(storageFile))) { - int amount = dis.readInt(); - for (int i = 0; i < amount; i ++) { - verifiedUuids.add(new UUID(dis.readLong(), dis.readLong())); - } - } catch (EOFException e) { - - } catch (Exception e) { - e.printStackTrace(); - } + UuidHelper.readUuidListFromFile(storageFile, verifiedUuids); } public boolean isPlayerVerified(ProxiedPlayer player) { - return verifiedUuids.contains(player.getUniqueId()) || !player.getName().equals(MojangApiHelper.getMinecraftNameByUuid(player.getUniqueId())); + return verifiedUuids.contains(player.getUniqueId()) || !player.getName().equals(MojangApiHelper.getMinecraftNameByUuid(player.getUniqueId())) || AntiLeakAccount.getInstance().getWhiteListStorage().isPlayerWhiteListed(player.getUniqueId()); } public boolean isUuidVerified(UUID uuid) { @@ -48,14 +40,6 @@ public void addVerifiedUuid(UUID uuid) { } private void save() { - try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(new File(AntiLeakAccount.getInstance().getDataFolder(), "verifiedPlayers.dat")))) { - dos.writeInt(verifiedUuids.size()); - for (UUID uid : verifiedUuids) { - dos.writeLong(uid.getMostSignificantBits()); - dos.writeLong(uid.getLeastSignificantBits()); - } - } catch (Exception e) { - e.printStackTrace(); - } + UuidHelper.writeUuidListToFile(new File(AntiLeakAccount.getInstance().getDataFolder(), "verifiedPlayers.dat"), verifiedUuids); } } diff --git a/src/main/java/cn/mcres/luckyfish/antileakaccount/command/CommandHelper.java b/src/main/java/cn/mcres/luckyfish/antileakaccount/command/CommandHelper.java new file mode 100644 index 0000000..a0d40d8 --- /dev/null +++ b/src/main/java/cn/mcres/luckyfish/antileakaccount/command/CommandHelper.java @@ -0,0 +1,27 @@ +package cn.mcres.luckyfish.antileakaccount.command; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; + +public class CommandHelper { + static List listPlayers(String[] args) { + if (args.length > 1) { + return new ArrayList<>(); + } + + List playerNames = new ArrayList<>(); + + for (Player p : Bukkit.getOnlinePlayers()) { + playerNames.add(p.getName()); + } + + if (args.length == 1) { + playerNames.removeIf((name) -> !name.startsWith(args[0])); + } + + return playerNames; + } +} diff --git a/src/main/java/cn/mcres/luckyfish/antileakaccount/command/WhiteListAddCommand.java b/src/main/java/cn/mcres/luckyfish/antileakaccount/command/WhiteListAddCommand.java new file mode 100644 index 0000000..40f8e60 --- /dev/null +++ b/src/main/java/cn/mcres/luckyfish/antileakaccount/command/WhiteListAddCommand.java @@ -0,0 +1,51 @@ +package cn.mcres.luckyfish.antileakaccount.command; + +import cn.mcres.luckyfish.antileakaccount.AntiLeakAccount; +import cn.mcres.luckyfish.plugincommons.commands.SubCommandBase; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; + +import java.util.List; + +public class WhiteListAddCommand extends SubCommandBase { + @Override + public String getName() { + return "add"; + } + + @Override + public String getDescription() { + return "添加白名单玩家"; + } + + @Override + public String getUsage() { + return "add <玩家名>"; + } + + @Override + public String getPermissionRequired() { + return "antileakaccount.whitelist.add"; + } + + @Override + public boolean execute(CommandSender sender, Command command, String[] args) { + if (args.length != 1) { + return false; + } + + if (AntiLeakAccount.getInstance().getWhiteListStorage().addWhitelistPlayer(args[0])) { + sender.sendMessage(ChatColor.GREEN + "已将" + args[0] + "加入白名单,该玩家不再需要接受黑卡验证"); + } else { + sender.sendMessage(ChatColor.RED + "你说的" + args[0] + ",她长什么样?"); + } + + return true; + } + + @Override + public List tabComplete(CommandSender sender, String[] args) { + return CommandHelper.listPlayers(args); + } +} diff --git a/src/main/java/cn/mcres/luckyfish/antileakaccount/command/WhiteListListCommand.java b/src/main/java/cn/mcres/luckyfish/antileakaccount/command/WhiteListListCommand.java new file mode 100644 index 0000000..77fb4b5 --- /dev/null +++ b/src/main/java/cn/mcres/luckyfish/antileakaccount/command/WhiteListListCommand.java @@ -0,0 +1,42 @@ +package cn.mcres.luckyfish.antileakaccount.command; + +import cn.mcres.luckyfish.antileakaccount.AntiLeakAccount; +import cn.mcres.luckyfish.antileakaccount.mojang.MojangApiHelper; +import cn.mcres.luckyfish.plugincommons.commands.SubCommandBase; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; + +import java.util.List; +import java.util.UUID; + +public class WhiteListListCommand extends SubCommandBase { + @Override + public String getName() { + return "list"; + } + + @Override + public String getDescription() { + return "列出所有白名单玩家"; + } + + @Override + public String getUsage() { + return "list"; + } + + @Override + public boolean execute(CommandSender sender, Command command, String[] args) { + if (args.length != 0) { + return false; + } + + List whiteList = AntiLeakAccount.getInstance().getWhiteListStorage().getWhiteList();; + for (UUID uid : whiteList) { + sender.sendMessage(ChatColor.YELLOW + "玩家 " + ChatColor.GREEN + MojangApiHelper.getMinecraftNameByUuid(uid) + " - " + uid); + } + + return true; + } +} diff --git a/src/main/java/cn/mcres/luckyfish/antileakaccount/command/WhiteListRemoveCommand.java b/src/main/java/cn/mcres/luckyfish/antileakaccount/command/WhiteListRemoveCommand.java new file mode 100644 index 0000000..a9f3303 --- /dev/null +++ b/src/main/java/cn/mcres/luckyfish/antileakaccount/command/WhiteListRemoveCommand.java @@ -0,0 +1,52 @@ +package cn.mcres.luckyfish.antileakaccount.command; + +import cn.mcres.luckyfish.antileakaccount.AntiLeakAccount; +import cn.mcres.luckyfish.plugincommons.commands.SubCommandBase; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; + +import java.util.List; + +public class WhiteListRemoveCommand extends SubCommandBase { + @Override + public String getName() { + return "remove"; + } + + @Override + public String getDescription() { + return "移除白名单玩家"; + } + + @Override + public String getUsage() { + return "remove <玩家名>"; + } + + @Override + public String getPermissionRequired() { + return "antileakaccount.whitelist.remove"; + } + + @Override + public boolean execute(CommandSender sender, Command command, String[] args) { + if (args.length != 1) { + return false; + } + + if (AntiLeakAccount.getInstance().getWhiteListStorage().removeWhitelistPlayer(args[0])) { + sender.sendMessage(ChatColor.GREEN + "已将" + args[0] + "移除白名单,该玩家再次需要接受黑卡验证"); + } else { + sender.sendMessage(ChatColor.RED + "你说的" + args[0] + ",她长什么样?"); + } + + return true; + } + + @Override + public List tabComplete(CommandSender sender, String[] args) { + return CommandHelper.listPlayers(args); + } + +} diff --git a/src/main/java/cn/mcres/luckyfish/antileakaccount/listener/PlayerListener.java b/src/main/java/cn/mcres/luckyfish/antileakaccount/listener/PlayerListener.java index 25763fe..3c65193 100644 --- a/src/main/java/cn/mcres/luckyfish/antileakaccount/listener/PlayerListener.java +++ b/src/main/java/cn/mcres/luckyfish/antileakaccount/listener/PlayerListener.java @@ -12,6 +12,7 @@ import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.EntityDamageByBlockEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.inventory.InventoryOpenEvent; import org.bukkit.event.player.*; import org.bukkit.event.server.TabCompleteEvent; @@ -191,4 +192,11 @@ public void onPlayerQuit(PlayerQuitEvent event) { event.setQuitMessage(""); } } + + @EventHandler(ignoreCancelled = true) + public void onInventoryOpen(InventoryOpenEvent event) { + if (!vm.isVerified(event.getPlayer())) { + event.setCancelled(true); + } + } } diff --git a/src/main/java/cn/mcres/luckyfish/antileakaccount/mojang/MojangApiHelper.java b/src/main/java/cn/mcres/luckyfish/antileakaccount/mojang/MojangApiHelper.java index 1443363..8e83b26 100644 --- a/src/main/java/cn/mcres/luckyfish/antileakaccount/mojang/MojangApiHelper.java +++ b/src/main/java/cn/mcres/luckyfish/antileakaccount/mojang/MojangApiHelper.java @@ -1,5 +1,6 @@ package cn.mcres.luckyfish.antileakaccount.mojang; +import cn.mcres.luckyfish.antileakaccount.util.UuidHelper; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import org.apache.commons.io.IOUtils; @@ -16,6 +17,7 @@ public class MojangApiHelper { private static final String profileUrl = "https://sessionserver.mojang.com/session/minecraft/profile/"; private static final String authUrl = "https://authserver.mojang.com/authenticate"; + private static final String uuidUrl = "https://api.mojang.com/users/profiles/minecraft/"; private static final Gson gson = new Gson(); private static UserCache userCache = null; @@ -58,6 +60,32 @@ public static String getMinecraftNameByUuid(UUID uuid) { } } + public static UUID getMinecraftUuidByName(String name) { + if (userCache != null) { + UUID cache = userCache.getCachedUuid(name); + if (cache != null) { + return cache; + } + } + + try { + URL url = new URL(uuidUrl + name); + HttpsURLConnection uc = (HttpsURLConnection) url.openConnection(); + uc.setRequestMethod("GET"); + uc.setConnectTimeout(5000); + uc.setReadTimeout(5000); + uc.setDoInput(true); + uc.connect(); + if (uc.getResponseCode() != 200) { + return null; + } + Map content = gson.fromJson(new InputStreamReader(uc.getInputStream()), Map.class); + return UuidHelper.fromTrimmedUuid(content.get("id").toString()); + } catch (Exception e) { + return null; + } + } + public static boolean validateWithEmailAndPassword(String email, String password, UUID uuid) { try { HttpsURLConnection uc = (HttpsURLConnection) new URL(authUrl).openConnection(); diff --git a/src/main/java/cn/mcres/luckyfish/antileakaccount/mojang/UserCache.java b/src/main/java/cn/mcres/luckyfish/antileakaccount/mojang/UserCache.java index a6497e0..ea46826 100644 --- a/src/main/java/cn/mcres/luckyfish/antileakaccount/mojang/UserCache.java +++ b/src/main/java/cn/mcres/luckyfish/antileakaccount/mojang/UserCache.java @@ -4,6 +4,9 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; public class UserCache { private final File cacheFile; @@ -20,7 +23,7 @@ public UserCache(File dataFolder) { } } - try (DataInputStream dis = new DataInputStream(new FileInputStream(cacheFile))) { + try (DataInputStream dis = new DataInputStream(new GZIPInputStream(new FileInputStream(cacheFile)))) { int amount = dis.readInt(); for (int i = 0; i < amount; i ++) { long most = dis.readLong(); @@ -52,6 +55,17 @@ public String getCachedUsername(UUID uuid) { return cu.getName(); } + public UUID getCachedUuid(String name) { + AtomicReference result = new AtomicReference<>(); + cachedUserMap.forEach((uid, u) -> { + if (u.getName().equals(name)) { + result.set(uid); + } + }); + + return result.get(); + } + public void writeUser(UUID uuid, String name) { CachedUser cu = new CachedUser(name); cachedUserMap.put(uuid, cu); @@ -60,7 +74,7 @@ public void writeUser(UUID uuid, String name) { } private void writeToFile() { - try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(cacheFile))) { + try (DataOutputStream dos = new DataOutputStream(new GZIPOutputStream(new FileOutputStream(cacheFile)))) { dos.writeInt(cachedUserMap.size()); cachedUserMap.forEach((uid, user) -> { try { diff --git a/src/main/java/cn/mcres/luckyfish/antileakaccount/storage/BungeeStorage.java b/src/main/java/cn/mcres/luckyfish/antileakaccount/storage/BungeeStorage.java index 2d03ad2..b413265 100644 --- a/src/main/java/cn/mcres/luckyfish/antileakaccount/storage/BungeeStorage.java +++ b/src/main/java/cn/mcres/luckyfish/antileakaccount/storage/BungeeStorage.java @@ -5,6 +5,7 @@ import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteStreams; import org.bukkit.Bukkit; +import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import org.bukkit.plugin.messaging.PluginMessageListener; @@ -35,13 +36,16 @@ public void addVerifiedPlayer(Player player) { } @Override - public boolean isPlayerVerified(Player player) { + public boolean isPlayerVerified(HumanEntity player) { + if (!(player instanceof Player)) { + return false; + } ByteArrayDataOutput bado = ByteStreams.newDataOutput(); bado.writeUTF("fetch"); bado.writeLong(player.getUniqueId().getMostSignificantBits()); bado.writeLong(player.getUniqueId().getLeastSignificantBits()); - player.sendPluginMessage(AntiLeakAccount.getInstance(), "ala:message", bado.toByteArray()); + ((Player) player).sendPluginMessage(AntiLeakAccount.getInstance(), "ala:message", bado.toByteArray()); return verifiedPlayers.contains(player.getUniqueId()); } diff --git a/src/main/java/cn/mcres/luckyfish/antileakaccount/storage/PlayerStorage.java b/src/main/java/cn/mcres/luckyfish/antileakaccount/storage/PlayerStorage.java index 974218d..8325e7b 100644 --- a/src/main/java/cn/mcres/luckyfish/antileakaccount/storage/PlayerStorage.java +++ b/src/main/java/cn/mcres/luckyfish/antileakaccount/storage/PlayerStorage.java @@ -1,15 +1,16 @@ package cn.mcres.luckyfish.antileakaccount.storage; import cn.mcres.luckyfish.antileakaccount.AntiLeakAccount; +import cn.mcres.luckyfish.antileakaccount.util.UuidHelper; import org.bukkit.Bukkit; +import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; -import java.io.*; +import java.io.File; +import java.io.IOException; import java.util.List; import java.util.UUID; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; public class PlayerStorage { private final List verifiedPlayerUuids = new CopyOnWriteArrayList<>(); @@ -29,16 +30,7 @@ protected void init() { } } - try (DataInputStream dis = new DataInputStream(new GZIPInputStream(new FileInputStream(storageFile)))) { - int length = dis.readInt(); - for (int i = 0; i < length; i ++) { - verifiedPlayerUuids.add(new UUID(dis.readLong(), dis.readLong())); - } - } catch (EOFException e) { - - } catch (Exception e) { - e.printStackTrace(); - } + UuidHelper.readUuidListFromFile(storageFile, verifiedPlayerUuids); } public void addVerifiedPlayer(Player player) { @@ -46,19 +38,11 @@ public void addVerifiedPlayer(Player player) { Bukkit.getScheduler().runTaskAsynchronously(AntiLeakAccount.getInstance(), this::save); } - public boolean isPlayerVerified(Player player) { + public boolean isPlayerVerified(HumanEntity player) { return verifiedPlayerUuids.contains(player.getUniqueId()); } public void save() { - try (DataOutputStream dos = new DataOutputStream(new GZIPOutputStream(new FileOutputStream(new File(AntiLeakAccount.getInstance().getDataFolder(), "verifiedPlayers.dat"))))) { - dos.writeInt(verifiedPlayerUuids.size()); - for (UUID uid : verifiedPlayerUuids) { - dos.writeLong(uid.getMostSignificantBits()); - dos.writeLong(uid.getLeastSignificantBits()); - } - } catch (Exception e) { - e.printStackTrace(); - } + UuidHelper.writeUuidListToFile(new File(AntiLeakAccount.getInstance().getDataFolder(), "verifiedPlayers.dat"), verifiedPlayerUuids); } } diff --git a/src/main/java/cn/mcres/luckyfish/antileakaccount/util/UuidHelper.java b/src/main/java/cn/mcres/luckyfish/antileakaccount/util/UuidHelper.java new file mode 100644 index 0000000..e351ea1 --- /dev/null +++ b/src/main/java/cn/mcres/luckyfish/antileakaccount/util/UuidHelper.java @@ -0,0 +1,41 @@ +package cn.mcres.luckyfish.antileakaccount.util; + +import java.io.*; +import java.util.List; +import java.util.UUID; +import java.util.regex.Pattern; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +public class UuidHelper { + private static final Pattern UUID_FIX = Pattern.compile("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})"); + + public static UUID fromTrimmedUuid(String trimmed) { + return UUID.fromString(UUID_FIX.matcher(trimmed.replace("-", "")).replaceAll("$1-$2-$3-$4-$5")); + } + + public static void readUuidListFromFile(File targetFile, List uuidList) { + try (DataInputStream dis = new DataInputStream(new GZIPInputStream(new FileInputStream(targetFile)))) { + int amount = dis.readInt(); + for (int i = 0; i < amount; i ++) { + uuidList.add(new UUID(dis.readLong(), dis.readLong())); + } + } catch (EOFException e) { + + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void writeUuidListToFile(File targetFile, List uuidList) { + try (DataOutputStream dos = new DataOutputStream(new GZIPOutputStream(new FileOutputStream(targetFile)))) { + dos.writeInt(uuidList.size()); + for (UUID uid : uuidList) { + dos.writeLong(uid.getMostSignificantBits()); + dos.writeLong(uid.getLeastSignificantBits()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/cn/mcres/luckyfish/antileakaccount/verify/VerifyManager.java b/src/main/java/cn/mcres/luckyfish/antileakaccount/verify/VerifyManager.java index 2441a0f..6ffe614 100644 --- a/src/main/java/cn/mcres/luckyfish/antileakaccount/verify/VerifyManager.java +++ b/src/main/java/cn/mcres/luckyfish/antileakaccount/verify/VerifyManager.java @@ -6,6 +6,7 @@ import cn.mcres.luckyfish.antileakaccount.storage.PlayerStorage; import cn.mcres.luckyfish.antileakaccount.util.PasswordHelper; import org.bukkit.Bukkit; +import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import java.util.*; @@ -85,8 +86,11 @@ public String fetchPassword(Player player) { return passwords.get(player.getUniqueId()); } - public boolean isVerified(Player player) { + public boolean isVerified(HumanEntity player) { if (!AntiLeakAccount.getInstance().getConfigHolder().bungeeMode) { + if (AntiLeakAccount.getInstance().getWhiteListStorage().isPlayerWhiteListed(player.getUniqueId())) { + return true; + } if (!player.getName().equals(MojangApiHelper.getMinecraftNameByUuid(player.getUniqueId()))) { return true; } diff --git a/src/main/java/cn/mcres/luckyfish/antileakaccount/whitelist/WhiteListStorage.java b/src/main/java/cn/mcres/luckyfish/antileakaccount/whitelist/WhiteListStorage.java new file mode 100644 index 0000000..d8a848e --- /dev/null +++ b/src/main/java/cn/mcres/luckyfish/antileakaccount/whitelist/WhiteListStorage.java @@ -0,0 +1,78 @@ +package cn.mcres.luckyfish.antileakaccount.whitelist; + +import cn.mcres.luckyfish.antileakaccount.mojang.MojangApiHelper; +import cn.mcres.luckyfish.antileakaccount.util.UuidHelper; + +import java.io.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +public class WhiteListStorage { + private final File whiteListFile; + private final List whiteList = new ArrayList<>(); + public WhiteListStorage(File dataFolder) { + whiteListFile = new File(dataFolder, "whitelist.dat"); + if (!whiteListFile.exists()) { + try { + whiteListFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + load(); + } + + public boolean addWhitelistPlayer(String playerName) { + return addWhitelistPlayer(MojangApiHelper.getMinecraftUuidByName(playerName)); + } + + public boolean addWhitelistPlayer(UUID uid) { + if (uid == null) { + return false; + } + + whiteList.add(uid); + + new Thread(this::save).start(); + return true; + } + + public boolean removeWhtielistPlayer(UUID uid) { + if (uid == null) { + return false; + } + + try { + return whiteList.remove(uid); + } finally { + new Thread(this::save).start(); + } + } + + public boolean removeWhitelistPlayer(String name) { + return removeWhtielistPlayer(MojangApiHelper.getMinecraftUuidByName(name)); + } + + public boolean isPlayerWhiteListed(UUID uuid) { + return whiteList.contains(uuid); + } + + public boolean isPlayerWhiteListed(String name) { + return isPlayerWhiteListed(MojangApiHelper.getMinecraftUuidByName(name)); + } + + private void load() { + UuidHelper.readUuidListFromFile(whiteListFile, whiteList); + } + + private void save() { + UuidHelper.writeUuidListToFile(whiteListFile, whiteList); + } + + public List getWhiteList() { + return Collections.unmodifiableList(whiteList); + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 69f6d64..ad24956 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -4,3 +4,24 @@ main: cn.mcres.luckyfish.antileakaccount.AntiLeakAccount api-version: 1.16 authors: [Lucky_fish20] description: Check if the premium account is legal + +commands: + alawhitelist: + aliases: + - awhitelist + - awl + permission: antileakaccount.whitelist + +permissions: + antileakaccount.whitelist: + default: op + children: + antileakaccount.whitelist.add: true + antileakaccount.whitelist.remove: true + antileakaccount.whitelist.list: true + antileakaccount.whitelist.add: + default: op + antileakaccount.whitelist.remove: + default: op + antileakaccount.whitelist.list: + default: op