diff --git a/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitListener.java b/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitListener.java index 8c1c105..8736537 100644 --- a/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitListener.java +++ b/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitListener.java @@ -12,6 +12,7 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; @@ -35,7 +36,7 @@ public class BukkitListener extends VPNExecutor implements Listener { } @Override - public void shutdown() { + public void onShutdown() { } @@ -54,6 +55,12 @@ public class BukkitListener extends VPNExecutor implements Listener { Bukkit.getLogger().log(Level.SEVERE, message, ex); } + @Override + public void disablePlugin() { + HandlerList.unregisterAll(this); + BukkitPlugin.pluginInstance.getServer().getPluginManager().disablePlugin(BukkitPlugin.pluginInstance); + } + @EventHandler(priority = EventPriority.HIGH) public void onJoin(final PlayerJoinEvent event) { AntiVPN.getInstance().getPlayerExecutor().getPlayer(event.getPlayer().getUniqueId()) diff --git a/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeeListener.java b/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeeListener.java index 826d04e..30d6250 100644 --- a/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeeListener.java +++ b/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeeListener.java @@ -37,12 +37,11 @@ public class BungeeListener extends VPNExecutor implements Listener { } @Override - public void shutdown() { + public void onShutdown() { if(cacheResetTask != null) { cacheResetTask.cancel(); cacheResetTask = null; } - threadExecutor.shutdown(); BungeePlugin.pluginInstance.getProxy().getPluginManager().unregisterListener(this); } @@ -61,6 +60,17 @@ public class BungeeListener extends VPNExecutor implements Listener { BungeeCord.getInstance().getLogger().log(Level.SEVERE, message, ex); } + @Override + public void disablePlugin() { + BungeeCord.getInstance().getPluginManager().unregisterListeners(BungeePlugin.pluginInstance); + if(cacheResetTask != null) { + cacheResetTask.cancel(); + cacheResetTask = null; + } + BungeeCord.getInstance().getPluginManager().unregisterCommands(BungeePlugin.pluginInstance); + BungeePlugin.pluginInstance.onDisable(); + } + @EventHandler(priority = EventPriority.LOWEST) public void onListener(final PreLoginEvent event) { if(!responseCache.asMap().containsKey(event.getConnection().getUniqueId())) return; diff --git a/Common/src/main/java/dev/brighten/antivpn/AntiVPN.java b/Common/src/main/java/dev/brighten/antivpn/AntiVPN.java index 2bc20f4..9446bf8 100644 --- a/Common/src/main/java/dev/brighten/antivpn/AntiVPN.java +++ b/Common/src/main/java/dev/brighten/antivpn/AntiVPN.java @@ -54,13 +54,17 @@ public class AntiVPN { try { File configFile = new File(pluginFolder, "config.yml"); if(!configFile.exists()){ - configFile.getParentFile().mkdirs(); + if(configFile.getParentFile().mkdirs()) { + AntiVPN.getInstance().getExecutor().log("Created plugin folder!"); + } MiscUtils.copy(INSTANCE.getResource( "config.yml"), configFile); } INSTANCE.config = ConfigurationProvider.getProvider(YamlConfiguration.class) .load(configFile); } catch (IOException e) { - e.printStackTrace(); + AntiVPN.getInstance().getExecutor().logException("Could not load config.yml, plugin disabling...", e); + executor.disablePlugin(); + return; } INSTANCE.vpnConfig = new VPNConfig(); @@ -139,7 +143,8 @@ public class AntiVPN { } public void stop() { - executor.shutdown(); + executor.onShutdown(); + VPNExecutor.threadExecutor.shutdown(); if(database != null) database.shutdown(); } @@ -188,7 +193,7 @@ public class AntiVPN { ConfigurationProvider.getProvider(YamlConfiguration.class) .save(getConfig(), new File(pluginFolder.getPath() + File.separator + "config.yml")); } catch (IOException e) { - e.printStackTrace(); + AntiVPN.getInstance().getExecutor().logException(e); } } diff --git a/Common/src/main/java/dev/brighten/antivpn/api/VPNExecutor.java b/Common/src/main/java/dev/brighten/antivpn/api/VPNExecutor.java index 84d89f1..1ae8cd7 100644 --- a/Common/src/main/java/dev/brighten/antivpn/api/VPNExecutor.java +++ b/Common/src/main/java/dev/brighten/antivpn/api/VPNExecutor.java @@ -32,7 +32,7 @@ public abstract class VPNExecutor { public abstract void registerListeners(); - public abstract void shutdown(); + public abstract void onShutdown(); public abstract void log(Level level, String log, Object... objects); @@ -97,4 +97,6 @@ public abstract class VPNExecutor { } } } + + public abstract void disablePlugin(); } diff --git a/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityListener.java b/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityListener.java index ea8b57a..04ab467 100644 --- a/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityListener.java +++ b/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityListener.java @@ -2,6 +2,7 @@ package dev.brighten.antivpn.velocity; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; +import com.velocitypowered.api.event.EventHandler; import com.velocitypowered.api.event.ResultedEvent; import com.velocitypowered.api.event.connection.DisconnectEvent; import com.velocitypowered.api.event.connection.LoginEvent; @@ -26,6 +27,145 @@ public class VelocityListener extends VPNExecutor { .maximumSize(2000) .build(); + private final EventHandler loginEvent = event -> { + if (event.getResult().isAllowed()) { + if (event.getPlayer().hasPermission("antivpn.bypass") //Has bypass permission + //Is exempt + || AntiVPN.getInstance().getExecutor().isWhitelisted(event.getPlayer().getUniqueId()) + //Or has a name that starts with a certain prefix. This is for Bedrock exempting. + || AntiVPN.getInstance().getExecutor().isWhitelisted(event.getPlayer().getRemoteAddress() + .getAddress().getHostAddress()) + || AntiVPN.getInstance().getVpnConfig().getPrefixWhitelists().stream() + .anyMatch(prefix -> event.getPlayer().getUsername().startsWith(prefix))) return; + + if(responseCache.asMap().containsKey(event.getPlayer().getUniqueId())) { + VPNResponse cached = responseCache.getIfPresent(event.getPlayer().getUniqueId()); + + if (cached != null && cached.isProxy()) { + event.setResult(ResultedEvent.ComponentResult.denied(Component.text("No"))); + return; + } + } + + checkIp(event.getPlayer().getRemoteAddress().getAddress().getHostAddress(), + AntiVPN.getInstance().getVpnConfig().cachedResults(), result -> { + if (result.isSuccess()) { + // If the countryList() size is zero, no need to check. + // Running country check first + if (!AntiVPN.getInstance().getVpnConfig().countryList().isEmpty() + && !(AntiVPN.getInstance().getExecutor() + .isWhitelisted(event.getPlayer().getUniqueId()) //Is exempt + //Or has a name that starts with a certain prefix. This is for Bedrock exempting. + || AntiVPN.getInstance().getExecutor().isWhitelisted(event.getPlayer() + .getRemoteAddress().getAddress().getHostAddress())) + // This bit of code will decide whether or not to kick the player + // If it contains the code and it is set to whitelist, it will not kick + // as they are equal and vise versa. However, if the contains does not match + // the state, it will kick. + && AntiVPN.getInstance().getVpnConfig().countryList() + .contains(result.getCountryCode()) + != AntiVPN.getInstance().getVpnConfig().whitelistCountries()) { + //Using our built in kicking system if no commands are configured + if (AntiVPN.getInstance().getVpnConfig().countryKickCommands().isEmpty()) { + final String kickReason = AntiVPN.getInstance().getVpnConfig() + .countryVanillaKickReason(); + // Kicking our player + event.setResult(ResultedEvent.ComponentResult.denied(LegacyComponentSerializer.builder() + .character('&') + .build().deserialize(kickReason + .replace("%player%", event.getPlayer().getUsername()) + .replace("%country%", result.getCountryName()) + .replace("%code%", result.getCountryCode())))); + VelocityPlugin.INSTANCE.getServer().getScheduler() + .buildTask(VelocityPlugin.INSTANCE, () -> + event.getPlayer().disconnect(LegacyComponentSerializer.builder() + .character('&') + .build().deserialize(kickReason + .replace("%player%", event.getPlayer().getUsername()) + .replace("%country%", result.getCountryName()) + .replace("%code%", result.getCountryCode())))); + } else { + for (String cmd : AntiVPN.getInstance().getVpnConfig().countryKickCommands()) { + final String formattedCommand = StringUtils + .translateAlternateColorCodes('&', + cmd.replace("%player%", + event.getPlayer().getUsername()) + .replace("%country%", result.getCountryName()) + .replace("%code%", result.getCountryCode())); + // Running the command from console + VelocityPlugin.INSTANCE.getServer().getCommandManager() + .executeAsync(VelocityPlugin.INSTANCE.getServer() + .getConsoleCommandSource(), + StringUtils.translateAlternateColorCodes('&', + formattedCommand)); + } + } + } else if (result.isProxy()) { + if (AntiVPN.getInstance().getVpnConfig().kickPlayersOnDetect()) { + // Delay code execution + event.setResult(ResultedEvent.ComponentResult.denied(LegacyComponentSerializer.builder() + .character('&') + .build().deserialize(AntiVPN.getInstance().getVpnConfig() + .getKickString() + .replace("%player%", event.getPlayer().getUsername()) + .replace("%country%", result.getCountryName()) + .replace("%code%", result.getCountryCode())))); + + VelocityPlugin.INSTANCE.getServer().getScheduler() + .buildTask(VelocityPlugin.INSTANCE, () -> + event.getPlayer().disconnect(LegacyComponentSerializer.builder() + .character('&') + .build().deserialize(AntiVPN.getInstance().getVpnConfig() + .getKickString() + .replace("%player%", event.getPlayer().getUsername()) + .replace("%country%", result.getCountryName()) + .replace("%code%", result.getCountryCode())))) + .delay(1, TimeUnit.SECONDS).schedule(); + } + VelocityPlugin.INSTANCE.getLogger().info(event.getPlayer().getUsername() + + " joined on a VPN/Proxy (" + result.getMethod() + ")"); + //Ensuring the user wishes to alert to staff + if (AntiVPN.getInstance().getVpnConfig().alertToStaff()) + AntiVPN.getInstance().getPlayerExecutor().getOnlinePlayers().stream() + .filter(APIPlayer::isAlertsEnabled) + .forEach(pl -> + pl.sendMessage(AntiVPN.getInstance().getVpnConfig() + .alertMessage() + .replace("%player%", + event.getPlayer().getUsername()) + .replace("%reason%", + result.getMethod()) + .replace("%country%", + result.getCountryName()) + .replace("%city%", + result.getCity()))); + + //In case the user wants to run their own commands instead of using the + // built in kicking + if (AntiVPN.getInstance().getVpnConfig().runCommands()) { + for (String command : AntiVPN.getInstance().getVpnConfig().commands()) { + VelocityPlugin.INSTANCE.getServer().getCommandManager() + .executeAsync(VelocityPlugin.INSTANCE.getServer() + .getConsoleCommandSource(), + StringUtils.translateAlternateColorCodes('&', + command.replace("%player%", + event.getPlayer().getUsername()))); + } + } + AntiVPN.getInstance().detections++; + } + } else { + VelocityPlugin.INSTANCE.getLogger() + .log(Level.WARNING, + "The API query was not a success! " + + "You may need to upgrade your license on " + + "https://funkemunky.cc/shop"); + } + AntiVPN.getInstance().checked++; + }); + } + }; + @Override public void registerListeners() { @@ -33,156 +173,19 @@ public class VelocityListener extends VPNExecutor { .register(VelocityPlugin.INSTANCE, this); VelocityPlugin.INSTANCE.getServer().getEventManager().register(VelocityPlugin.INSTANCE, DisconnectEvent.class, - event -> AntiVPN.getInstance().getPlayerExecutor().unloadPlayer(event.getPlayer().getUniqueId())); + event -> AntiVPN.getInstance().getPlayerExecutor() + .unloadPlayer(event.getPlayer().getUniqueId())); VelocityPlugin.INSTANCE.getServer().getEventManager().register(VelocityPlugin.INSTANCE, LoginEvent.class, - event -> { - if (event.getResult().isAllowed()) { - if (event.getPlayer().hasPermission("antivpn.bypass") //Has bypass permission - //Is exempt - || AntiVPN.getInstance().getExecutor().isWhitelisted(event.getPlayer().getUniqueId()) - //Or has a name that starts with a certain prefix. This is for Bedrock exempting. - || AntiVPN.getInstance().getExecutor().isWhitelisted(event.getPlayer().getRemoteAddress() - .getAddress().getHostAddress()) - || AntiVPN.getInstance().getVpnConfig().getPrefixWhitelists().stream() - .anyMatch(prefix -> event.getPlayer().getUsername().startsWith(prefix))) return; - - if(responseCache.asMap().containsKey(event.getPlayer().getUniqueId())) { - VPNResponse cached = responseCache.getIfPresent(event.getPlayer().getUniqueId()); - - if (cached != null && cached.isProxy()) { - event.setResult(ResultedEvent.ComponentResult.denied(Component.text("No"))); - return; - } - } - - checkIp(event.getPlayer().getRemoteAddress().getAddress().getHostAddress(), - AntiVPN.getInstance().getVpnConfig().cachedResults(), result -> { - if (result.isSuccess()) { - // If the countryList() size is zero, no need to check. - // Running country check first - if (!AntiVPN.getInstance().getVpnConfig().countryList().isEmpty() - && !(AntiVPN.getInstance().getExecutor() - .isWhitelisted(event.getPlayer().getUniqueId()) //Is exempt - //Or has a name that starts with a certain prefix. This is for Bedrock exempting. - || AntiVPN.getInstance().getExecutor().isWhitelisted(event.getPlayer() - .getRemoteAddress().getAddress().getHostAddress())) - // This bit of code will decide whether or not to kick the player - // If it contains the code and it is set to whitelist, it will not kick - // as they are equal and vise versa. However, if the contains does not match - // the state, it will kick. - && AntiVPN.getInstance().getVpnConfig().countryList() - .contains(result.getCountryCode()) - != AntiVPN.getInstance().getVpnConfig().whitelistCountries()) { - //Using our built in kicking system if no commands are configured - if (AntiVPN.getInstance().getVpnConfig().countryKickCommands().isEmpty()) { - final String kickReason = AntiVPN.getInstance().getVpnConfig() - .countryVanillaKickReason(); - // Kicking our player - event.setResult(ResultedEvent.ComponentResult.denied(LegacyComponentSerializer.builder() - .character('&') - .build().deserialize(kickReason - .replace("%player%", event.getPlayer().getUsername()) - .replace("%country%", result.getCountryName()) - .replace("%code%", result.getCountryCode())))); - VelocityPlugin.INSTANCE.getServer().getScheduler() - .buildTask(VelocityPlugin.INSTANCE, () -> - event.getPlayer().disconnect(LegacyComponentSerializer.builder() - .character('&') - .build().deserialize(kickReason - .replace("%player%", event.getPlayer().getUsername()) - .replace("%country%", result.getCountryName()) - .replace("%code%", result.getCountryCode())))); - } else { - for (String cmd : AntiVPN.getInstance().getVpnConfig().countryKickCommands()) { - final String formattedCommand = StringUtils - .translateAlternateColorCodes('&', - cmd.replace("%player%", - event.getPlayer().getUsername()) - .replace("%country%", result.getCountryName()) - .replace("%code%", result.getCountryCode())); - // Running the command from console - VelocityPlugin.INSTANCE.getServer().getCommandManager() - .executeAsync(VelocityPlugin.INSTANCE.getServer() - .getConsoleCommandSource(), - StringUtils.translateAlternateColorCodes('&', - formattedCommand)); - } - } - } else if (result.isProxy()) { - if (AntiVPN.getInstance().getVpnConfig().kickPlayersOnDetect()) { - // Delay code execution - event.setResult(ResultedEvent.ComponentResult.denied(LegacyComponentSerializer.builder() - .character('&') - .build().deserialize(AntiVPN.getInstance().getVpnConfig() - .getKickString() - .replace("%player%", event.getPlayer().getUsername()) - .replace("%country%", result.getCountryName()) - .replace("%code%", result.getCountryCode())))); - - VelocityPlugin.INSTANCE.getServer().getScheduler() - .buildTask(VelocityPlugin.INSTANCE, () -> - event.getPlayer().disconnect(LegacyComponentSerializer.builder() - .character('&') - .build().deserialize(AntiVPN.getInstance().getVpnConfig() - .getKickString() - .replace("%player%", event.getPlayer().getUsername()) - .replace("%country%", result.getCountryName()) - .replace("%code%", result.getCountryCode())))) - .delay(1, TimeUnit.SECONDS).schedule(); - } - VelocityPlugin.INSTANCE.getLogger().info(event.getPlayer().getUsername() - + " joined on a VPN/Proxy (" + result.getMethod() + ")"); - //Ensuring the user wishes to alert to staff - if (AntiVPN.getInstance().getVpnConfig().alertToStaff()) - AntiVPN.getInstance().getPlayerExecutor().getOnlinePlayers().stream() - .filter(APIPlayer::isAlertsEnabled) - .forEach(pl -> - pl.sendMessage(AntiVPN.getInstance().getVpnConfig() - .alertMessage() - .replace("%player%", - event.getPlayer().getUsername()) - .replace("%reason%", - result.getMethod()) - .replace("%country%", - result.getCountryName()) - .replace("%city%", - result.getCity()))); - - //In case the user wants to run their own commands instead of using the - // built in kicking - if (AntiVPN.getInstance().getVpnConfig().runCommands()) { - for (String command : AntiVPN.getInstance().getVpnConfig().commands()) { - VelocityPlugin.INSTANCE.getServer().getCommandManager() - .executeAsync(VelocityPlugin.INSTANCE.getServer() - .getConsoleCommandSource(), - StringUtils.translateAlternateColorCodes('&', - command.replace("%player%", - event.getPlayer().getUsername()))); - } - } - AntiVPN.getInstance().detections++; - } - } else { - VelocityPlugin.INSTANCE.getLogger() - .log(Level.WARNING, - "The API query was not a success! " + - "You may need to upgrade your license on " + - "https://funkemunky.cc/shop"); - } - AntiVPN.getInstance().checked++; - }); - } - }); + loginEvent); } @Override - public void shutdown() { + public void onShutdown() { if (cacheResetTask != null) { cacheResetTask.cancel(); cacheResetTask = null; } - threadExecutor.shutdown(); VelocityPlugin.INSTANCE.getServer().getEventManager().unregisterListener(VelocityPlugin.INSTANCE, this); } @@ -200,4 +203,10 @@ public class VelocityListener extends VPNExecutor { public void logException(String message, Exception ex) { VelocityPlugin.INSTANCE.getLogger().log(Level.SEVERE, message, ex); } + + @Override + public void disablePlugin() { + VelocityPlugin.INSTANCE.getServer().getEventManager().unregisterListener(VelocityPlugin.INSTANCE, this); + VelocityPlugin.INSTANCE.getServer().getCommandManager().unregister("antivpn"); + } } diff --git a/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java b/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java index afecfa9..33e8e89 100644 --- a/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java +++ b/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java @@ -3,6 +3,7 @@ package dev.brighten.antivpn.velocity; import com.google.inject.Inject; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; +import com.velocitypowered.api.event.proxy.ProxyShutdownEvent; import com.velocitypowered.api.plugin.Plugin; import com.velocitypowered.api.plugin.annotation.DataDirectory; import com.velocitypowered.api.proxy.ProxyServer; @@ -12,6 +13,7 @@ import dev.brighten.antivpn.velocity.command.VelocityCommand; import lombok.Getter; import org.bstats.velocity.Metrics; +import javax.annotation.Nullable; import java.nio.file.Path; import java.util.logging.Logger; @@ -24,6 +26,9 @@ public class VelocityPlugin { private final Metrics.Factory metricsFactory; private final Path configDir; + @Nullable + private Metrics metrics; + public static VelocityPlugin INSTANCE; @Inject @@ -45,7 +50,7 @@ public class VelocityPlugin { if(AntiVPN.getInstance().getVpnConfig().metrics()) { logger.info("Starting metrics..."); - Metrics metrics = metricsFactory.make(this, 12791); + metrics = metricsFactory.make(this, 12791); } logger.info("Registering commands..."); @@ -54,4 +59,10 @@ public class VelocityPlugin { .aliases(command.aliases()).build(), new VelocityCommand(command)); } } + + @Subscribe + public void onShutdown(ProxyShutdownEvent event) { + AntiVPN.getInstance().stop(); + INSTANCE = null; + } }