mirror of
https://github.com/funkemunky/AntiVPN.git
synced 2026-06-24 04:20:51 +00:00
- Correct command concurrency issues on Bukkit servers
- Removed dynamic class loading of libraries to fix antivirus flags of the plugin.
This commit is contained in:
@@ -15,7 +15,6 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -56,12 +55,11 @@ public class BukkitListener extends VPNExecutor implements Listener {
|
||||
.ifPresent(player -> {
|
||||
AntiVPN.getInstance().getDatabase().alertsState(player.getUuid(), enabled -> {
|
||||
if(enabled) {
|
||||
AntiVPN.getInstance().getExecutor().log("Enabled");
|
||||
player.setAlertsEnabled(true);
|
||||
player.sendMessage(AntiVPN.getInstance().getMessageHandler()
|
||||
.getString("command-alerts-toggled")
|
||||
.getFormattedMessage(new VpnString.Var<>("state", true)));
|
||||
} else AntiVPN.getInstance().getExecutor().log("Not enabled");
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -76,7 +74,6 @@ public class BukkitListener extends VPNExecutor implements Listener {
|
||||
|| AntiVPN.getInstance().getVpnConfig().getPrefixWhitelists().stream()
|
||||
.anyMatch(prefix -> event.getPlayer().getName().startsWith(prefix))) return;
|
||||
|
||||
|
||||
if(responseCache.asMap().containsKey(event.getPlayer().getUniqueId())) {
|
||||
VPNResponse cached = responseCache.getIfPresent(event.getPlayer().getUniqueId());
|
||||
|
||||
@@ -93,113 +90,117 @@ public class BukkitListener extends VPNExecutor implements Listener {
|
||||
AntiVPN.getInstance().getVpnConfig().cachedResults(), result -> {
|
||||
if(result.isSuccess()) {
|
||||
//We need to run on main thread or kicking and running commands will cause errors
|
||||
new BukkitRunnable() {
|
||||
public void run() {
|
||||
//If the player is whitelisted, we don't want to kick them
|
||||
if(AntiVPN.getInstance().getExecutor().isWhitelisted(event.getPlayer().getUniqueId())) {
|
||||
log("UUID is whitelisted: %s",
|
||||
event.getPlayer().getUniqueId().toString());
|
||||
return;
|
||||
}
|
||||
{
|
||||
//If the IP is whitelisted, we don't want to kick them
|
||||
InetSocketAddress address = event.getPlayer().getAddress();
|
||||
if (address != null){
|
||||
InetAddress address1 = address.getAddress();
|
||||
if (address1 != null && AntiVPN.getInstance().getExecutor()
|
||||
.isWhitelisted(address1.getHostAddress())) {
|
||||
log("IP is whitelisted: %s",
|
||||
address1.getHostAddress());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
//If the player is whitelisted, we don't want to kick them
|
||||
if(AntiVPN.getInstance().getExecutor().isWhitelisted(event.getPlayer().getUniqueId())) {
|
||||
log("UUID is whitelisted: %s",
|
||||
event.getPlayer().getUniqueId().toString());
|
||||
return;
|
||||
}
|
||||
|
||||
// If the countryList() size is zero, no need to check.
|
||||
// Running country check first
|
||||
if(!AntiVPN.getInstance().getVpnConfig().countryList().isEmpty()
|
||||
// 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()) {
|
||||
final String kickReason = AntiVPN.getInstance().getVpnConfig()
|
||||
.countryVanillaKickReason();
|
||||
|
||||
// Start "online" fix
|
||||
// In case the response was so fast from API the player wouldn't be "online".
|
||||
event.setResult(PlayerLoginEvent.Result.KICK_BANNED);
|
||||
event.setKickMessage(ChatColor
|
||||
.translateAlternateColorCodes('&',
|
||||
kickReason
|
||||
.replace("%player%", event.getPlayer().getName())
|
||||
.replace("%country%", result.getCountryName())
|
||||
.replace("%code%", result.getCountryCode())));
|
||||
// End "online" fix
|
||||
|
||||
//Using our built in kicking system if no commands are configured
|
||||
if(AntiVPN.getInstance().getVpnConfig().countryKickCommands().isEmpty()) {
|
||||
// Kicking our player
|
||||
event.getPlayer().kickPlayer(ChatColor
|
||||
.translateAlternateColorCodes('&',
|
||||
kickReason
|
||||
.replace("%player%", event.getPlayer().getName())
|
||||
.replace("%country%", result.getCountryName())
|
||||
.replace("%code%", result.getCountryCode())));
|
||||
} else {
|
||||
for (String cmd : AntiVPN.getInstance().getVpnConfig().countryKickCommands()) {
|
||||
final String formattedCommand = ChatColor.translateAlternateColorCodes('&',
|
||||
cmd.replace("%player%", event.getPlayer().getName())
|
||||
.replace("%country%", result.getCountryName())
|
||||
.replace("%code%", result.getCountryCode()));
|
||||
|
||||
// Runs our command from console
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), formattedCommand);
|
||||
}
|
||||
}
|
||||
} else if(result.isProxy()) {
|
||||
|
||||
// Start "online" fix
|
||||
// In case the response was so fast from API the player wouldn't be "online".
|
||||
event.setResult(PlayerLoginEvent.Result.KICK_BANNED);
|
||||
event.setKickMessage(ChatColor
|
||||
.translateAlternateColorCodes('&',
|
||||
AntiVPN.getInstance().getVpnConfig().getKickString()
|
||||
.replace("%player%", event.getPlayer().getName())
|
||||
.replace("%country%", result.getCountryName())
|
||||
.replace("%code%", result.getCountryCode())));
|
||||
// End "online" fix
|
||||
|
||||
if(AntiVPN.getInstance().getVpnConfig().kickPlayersOnDetect())
|
||||
player.kickPlayer(org.bukkit.ChatColor.translateAlternateColorCodes('&',
|
||||
AntiVPN.getInstance().getVpnConfig().getKickString()));
|
||||
log(Level.INFO, event.getPlayer().getName()
|
||||
+ " 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().getName())
|
||||
.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()) {
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
|
||||
ChatColor.translateAlternateColorCodes('&',
|
||||
command.replace("%player%",
|
||||
event.getPlayer().getName())));
|
||||
}
|
||||
}
|
||||
AntiVPN.getInstance().detections++;
|
||||
}
|
||||
//If the IP is whitelisted, we don't want to kick them
|
||||
InetSocketAddress address = event.getPlayer().getAddress();
|
||||
if (address != null){
|
||||
InetAddress address1 = address.getAddress();
|
||||
if (address1 != null && AntiVPN.getInstance().getExecutor()
|
||||
.isWhitelisted(address1.getHostAddress())) {
|
||||
log("IP is whitelisted: %s",
|
||||
address1.getHostAddress());
|
||||
return;
|
||||
}
|
||||
}.runTask(BukkitPlugin.pluginInstance);
|
||||
}
|
||||
|
||||
// If the countryList() size is zero, no need to check.
|
||||
// Running country check first
|
||||
if(!AntiVPN.getInstance().getVpnConfig().countryList().isEmpty()
|
||||
// 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()) {
|
||||
final String kickReason = AntiVPN.getInstance().getVpnConfig()
|
||||
.countryVanillaKickReason();
|
||||
|
||||
// Start "online" fix
|
||||
// In case the response was so fast from API the player wouldn't be "online".
|
||||
event.setResult(PlayerLoginEvent.Result.KICK_BANNED);
|
||||
event.setKickMessage(ChatColor
|
||||
.translateAlternateColorCodes('&',
|
||||
kickReason
|
||||
.replace("%player%", event.getPlayer().getName())
|
||||
.replace("%country%", result.getCountryName())
|
||||
.replace("%code%", result.getCountryCode())));
|
||||
// End "online" fix
|
||||
|
||||
//Using our built in kicking system if no commands are configured
|
||||
if(AntiVPN.getInstance().getVpnConfig().countryKickCommands().isEmpty()) {
|
||||
// Kicking our player
|
||||
event.getPlayer().kickPlayer(ChatColor
|
||||
.translateAlternateColorCodes('&',
|
||||
kickReason
|
||||
.replace("%player%", event.getPlayer().getName())
|
||||
.replace("%country%", result.getCountryName())
|
||||
.replace("%code%", result.getCountryCode())));
|
||||
} else {
|
||||
final String playerName = event.getPlayer().getName();
|
||||
|
||||
BukkitPlugin.pluginInstance.getPlayerCommandRunner()
|
||||
.addAction(event.getPlayer().getUniqueId(), () -> {
|
||||
for (String cmd : AntiVPN.getInstance().getVpnConfig().countryKickCommands()) {
|
||||
final String formattedCommand = ChatColor.translateAlternateColorCodes('&',
|
||||
cmd.replace("%player%", playerName)
|
||||
.replace("%country%", result.getCountryName())
|
||||
.replace("%code%", result.getCountryCode()));
|
||||
|
||||
// Runs our command from console
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), formattedCommand);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if(result.isProxy()) {
|
||||
|
||||
// Start "online" fix
|
||||
// In case the response was so fast from API the player wouldn't be "online".
|
||||
event.setResult(PlayerLoginEvent.Result.KICK_BANNED);
|
||||
event.setKickMessage(ChatColor
|
||||
.translateAlternateColorCodes('&',
|
||||
AntiVPN.getInstance().getVpnConfig().getKickString()
|
||||
.replace("%player%", event.getPlayer().getName())
|
||||
.replace("%country%", result.getCountryName())
|
||||
.replace("%code%", result.getCountryCode())));
|
||||
// End "online" fix
|
||||
|
||||
if(AntiVPN.getInstance().getVpnConfig().kickPlayersOnDetect())
|
||||
player.kickPlayer(org.bukkit.ChatColor.translateAlternateColorCodes('&',
|
||||
AntiVPN.getInstance().getVpnConfig().getKickString()));
|
||||
log(Level.INFO, event.getPlayer().getName()
|
||||
+ " 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().getName())
|
||||
.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()) {
|
||||
String playerName = event.getPlayer().getName();
|
||||
BukkitPlugin.pluginInstance.getPlayerCommandRunner()
|
||||
.addAction(event.getPlayer().getUniqueId(), () -> {
|
||||
for (String command : AntiVPN.getInstance().getVpnConfig().commands()) {
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
|
||||
ChatColor.translateAlternateColorCodes('&',
|
||||
command.replace("%player%",
|
||||
playerName)));
|
||||
}
|
||||
});
|
||||
}
|
||||
AntiVPN.getInstance().detections++;
|
||||
}
|
||||
} else {
|
||||
log(Level.WARNING,
|
||||
"The API query was not a success! " +
|
||||
|
||||
@@ -3,6 +3,7 @@ package dev.brighten.antivpn.bukkit;
|
||||
import dev.brighten.antivpn.AntiVPN;
|
||||
import dev.brighten.antivpn.bukkit.command.BukkitCommand;
|
||||
import dev.brighten.antivpn.command.Command;
|
||||
import lombok.Getter;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.SingleLineChart;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -21,8 +22,12 @@ public class BukkitPlugin extends JavaPlugin {
|
||||
|
||||
public static BukkitPlugin pluginInstance;
|
||||
private SimpleCommandMap commandMap;
|
||||
private List<org.bukkit.command.Command> registeredCommands = new ArrayList<>();
|
||||
private final List<org.bukkit.command.Command> registeredCommands = new ArrayList<>();
|
||||
|
||||
@Getter
|
||||
private SingleLineChart vpnDetections, ipsChecked;
|
||||
@Getter
|
||||
private PlayerCommandRunner playerCommandRunner;
|
||||
|
||||
public void onEnable() {
|
||||
pluginInstance = this;
|
||||
@@ -30,6 +35,9 @@ public class BukkitPlugin extends JavaPlugin {
|
||||
Bukkit.getLogger().info("Starting AntiVPN services...");
|
||||
AntiVPN.start(new BukkitListener(), new BukkitPlayerExecutor(), getDataFolder());
|
||||
|
||||
playerCommandRunner = new PlayerCommandRunner();
|
||||
playerCommandRunner.start();
|
||||
|
||||
// Loading our bStats metrics to be pushed to https://bstats.org
|
||||
if(AntiVPN.getInstance().getVpnConfig().metrics()) {
|
||||
Bukkit.getLogger().info("Starting bStats metrics...");
|
||||
@@ -84,6 +92,7 @@ public class BukkitPlugin extends JavaPlugin {
|
||||
public void onDisable() {
|
||||
Bukkit.getLogger().info("Stopping plugin services...");
|
||||
AntiVPN.getInstance().stop();
|
||||
playerCommandRunner.stop();
|
||||
|
||||
Bukkit.getLogger().info("Unregistering commands...");
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package dev.brighten.antivpn.bukkit;
|
||||
|
||||
import dev.brighten.antivpn.utils.MiscUtils;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class PlayerCommandRunner {
|
||||
private final ScheduledExecutorService executorService;
|
||||
private final Queue<PlayerAction> playerActions = new ArrayBlockingQueue<>(10000);
|
||||
|
||||
public PlayerCommandRunner() {
|
||||
executorService = Executors.newSingleThreadScheduledExecutor(
|
||||
MiscUtils.createThreadFactory("AntiVPN:PlayerCommandRunner")
|
||||
);
|
||||
}
|
||||
|
||||
void start() {
|
||||
executorService.scheduleAtFixedRate(() -> {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
while(!playerActions.isEmpty()) {
|
||||
PlayerAction action = playerActions.peek();
|
||||
|
||||
if(action == null) continue;
|
||||
|
||||
if(currentTime - action.start > 2000L || Bukkit.getPlayer(action.getUuid()) != null) {
|
||||
new BukkitRunnable() {
|
||||
public void run() {
|
||||
action.getAction().run();
|
||||
}
|
||||
}.runTask(BukkitPlugin.pluginInstance);
|
||||
|
||||
playerActions.poll();
|
||||
}
|
||||
}
|
||||
}, 1000, 100, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
void stop() {
|
||||
executorService.shutdown();
|
||||
playerActions.clear();
|
||||
}
|
||||
|
||||
void addAction(UUID uuid, Runnable action) {
|
||||
playerActions.add(new PlayerAction(uuid, System.currentTimeMillis(), action));
|
||||
}
|
||||
|
||||
@Data
|
||||
static class PlayerAction {
|
||||
private final UUID uuid;
|
||||
private final long start;
|
||||
private final Runnable action;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user