mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-11-09 20:20:11 +01:00
RAW CODING: completely asynchronous chat (executeActions is synched
into main thread).
This commit is contained in:
parent
7f9d2d2c11
commit
889930fd9b
@ -12,6 +12,7 @@ import org.bukkit.event.player.PlayerJoinEvent;
|
|||||||
import org.bukkit.plugin.PluginDescriptionFile;
|
import org.bukkit.plugin.PluginDescriptionFile;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import fr.neatmonster.nocheatplus.checks.ExecuteActionsEvent;
|
||||||
import fr.neatmonster.nocheatplus.checks.Workarounds;
|
import fr.neatmonster.nocheatplus.checks.Workarounds;
|
||||||
import fr.neatmonster.nocheatplus.checks.blockbreak.BlockBreakListener;
|
import fr.neatmonster.nocheatplus.checks.blockbreak.BlockBreakListener;
|
||||||
import fr.neatmonster.nocheatplus.checks.blockinteract.BlockInteractListener;
|
import fr.neatmonster.nocheatplus.checks.blockinteract.BlockInteractListener;
|
||||||
@ -188,4 +189,9 @@ public class NoCheatPlus extends JavaPlugin implements Listener {
|
|||||||
|
|
||||||
player.sendMessage(message);
|
player.sendMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority=EventPriority.LOWEST)
|
||||||
|
final void onExecuteActions(final ExecuteActionsEvent event){
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
package fr.neatmonster.nocheatplus.checks;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This event is to be fired to execute actions in the main thread.
|
||||||
|
* @author mc_dev
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ExecuteActionsEvent extends Event {
|
||||||
|
|
||||||
|
private static final HandlerList handlers = new HandlerList();
|
||||||
|
|
||||||
|
private final Check check;
|
||||||
|
final Player player;
|
||||||
|
/**
|
||||||
|
* If the actions have been executed already.
|
||||||
|
*/
|
||||||
|
private boolean actionsExecuted = false;
|
||||||
|
private boolean cancel = false;
|
||||||
|
|
||||||
|
public ExecuteActionsEvent(final Check check, final Player player){
|
||||||
|
this.check = check;
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Must have :_) ...
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void executeActions(){
|
||||||
|
if (actionsExecuted) return;
|
||||||
|
cancel = check.executeActions(player);
|
||||||
|
actionsExecuted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getCancel(){
|
||||||
|
return cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -34,8 +34,10 @@ public class ChatConfig {
|
|||||||
* Clear all the configurations.
|
* Clear all the configurations.
|
||||||
*/
|
*/
|
||||||
public static void clear() {
|
public static void clear() {
|
||||||
|
synchronized (worldsMap) {
|
||||||
worldsMap.clear();
|
worldsMap.clear();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the configuration for a specified player.
|
* Gets the configuration for a specified player.
|
||||||
@ -45,11 +47,13 @@ public class ChatConfig {
|
|||||||
* @return the configuration
|
* @return the configuration
|
||||||
*/
|
*/
|
||||||
public static ChatConfig getConfig(final Player player) {
|
public static ChatConfig getConfig(final Player player) {
|
||||||
|
synchronized (worldsMap) {
|
||||||
if (!worldsMap.containsKey(player.getWorld().getName()))
|
if (!worldsMap.containsKey(player.getWorld().getName()))
|
||||||
worldsMap.put(player.getWorld().getName(),
|
worldsMap.put(player.getWorld().getName(),
|
||||||
new ChatConfig(ConfigManager.getConfigFile(player.getWorld().getName())));
|
new ChatConfig(ConfigManager.getConfigFile(player.getWorld().getName())));
|
||||||
return worldsMap.get(player.getWorld().getName());
|
return worldsMap.get(player.getWorld().getName());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public final boolean arrivalsCheck;
|
public final boolean arrivalsCheck;
|
||||||
public final int arrivalsJoinsLimit;
|
public final int arrivalsJoinsLimit;
|
||||||
|
@ -30,7 +30,7 @@ public class ChatData {
|
|||||||
* the player
|
* the player
|
||||||
* @return the data
|
* @return the data
|
||||||
*/
|
*/
|
||||||
public static ChatData getData(final Player player) {
|
public synchronized static ChatData getData(final Player player) {
|
||||||
if (!playersMap.containsKey(player.getName()))
|
if (!playersMap.containsKey(player.getName()))
|
||||||
playersMap.put(player.getName(), new ChatData());
|
playersMap.put(player.getName(), new ChatData());
|
||||||
return playersMap.get(player.getName());
|
return playersMap.get(player.getName());
|
||||||
@ -59,7 +59,7 @@ public class ChatData {
|
|||||||
/**
|
/**
|
||||||
* Clear the data of the no pwnage check.
|
* Clear the data of the no pwnage check.
|
||||||
*/
|
*/
|
||||||
public void clearNoPwnageData() {
|
public synchronized void clearNoPwnageData() {
|
||||||
noPwnageCaptchTries = noPwnageReloginWarnings = 0;
|
noPwnageCaptchTries = noPwnageReloginWarnings = 0;
|
||||||
noPwnageJoinTime = noPwnageLastMessageTime = noPwnageLastMovedTime = noPwnageLastWarningTime = noPwnageLeaveTime = noPwnageReloginWarningTime = 0L;
|
noPwnageJoinTime = noPwnageLastMessageTime = noPwnageLastMovedTime = noPwnageLastWarningTime = noPwnageLeaveTime = noPwnageReloginWarningTime = 0L;
|
||||||
noPwnageGeneratedCaptcha = noPwnageLastMessage = "";
|
noPwnageGeneratedCaptcha = noPwnageLastMessage = "";
|
||||||
|
@ -59,7 +59,7 @@ public class ChatListener implements Listener {
|
|||||||
event.setMessage(color.check(player, event.getMessage()));
|
event.setMessage(color.check(player, event.getMessage()));
|
||||||
|
|
||||||
// Then the no pwnage check.
|
// Then the no pwnage check.
|
||||||
if (noPwnage.isEnabled(player) && noPwnage.check(player))
|
if (noPwnage.check(player, event, false))
|
||||||
player.kickPlayer(Check.removeColors(ChatConfig.getConfig(player).noPwnageKickMessage));
|
player.kickPlayer(Check.removeColors(ChatConfig.getConfig(player).noPwnageKickMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ public class ChatListener implements Listener {
|
|||||||
event.setMessage(color.check(player, event.getMessage()));
|
event.setMessage(color.check(player, event.getMessage()));
|
||||||
|
|
||||||
// Then the no pwnage check.
|
// Then the no pwnage check.
|
||||||
if (noPwnage.isEnabled(player) && noPwnage.check(player))
|
if (noPwnage.check(player, event, true))
|
||||||
player.kickPlayer(Check.removeColors(ChatConfig.getConfig(player).noPwnageKickMessage));
|
player.kickPlayer(Check.removeColors(ChatConfig.getConfig(player).noPwnageKickMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ public class ChatListener implements Listener {
|
|||||||
* |___/
|
* |___/
|
||||||
*/
|
*/
|
||||||
final Player player = event.getPlayer();
|
final Player player = event.getPlayer();
|
||||||
final ChatConfig cc = ChatConfig.getConfig(player);
|
final ChatConfig cc = ChatConfig.getConfig(player); // Non critical use (concurrency).
|
||||||
|
|
||||||
// First the arrivals check, if enabled of course.
|
// First the arrivals check, if enabled of course.
|
||||||
if (arrivals.isEnabled(player) && arrivals.check(player))
|
if (arrivals.isEnabled(player) && arrivals.check(player))
|
||||||
@ -135,7 +135,7 @@ public class ChatListener implements Listener {
|
|||||||
event.disallow(Result.KICK_OTHER, cc.arrivalsMessage);
|
event.disallow(Result.KICK_OTHER, cc.arrivalsMessage);
|
||||||
|
|
||||||
// Then the no pwnage check, if the login isn't already disallowed.
|
// Then the no pwnage check, if the login isn't already disallowed.
|
||||||
if (event.getResult() != Result.KICK_OTHER && noPwnage.isEnabled(player) && noPwnage.check(player))
|
if (event.getResult() != Result.KICK_OTHER && noPwnage.check(player))
|
||||||
event.disallow(Result.KICK_OTHER, cc.noPwnageReloginKickMessage);
|
event.disallow(Result.KICK_OTHER, cc.noPwnageReloginKickMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import org.bukkit.event.player.PlayerEvent;
|
|||||||
import fr.neatmonster.nocheatplus.actions.ParameterName;
|
import fr.neatmonster.nocheatplus.actions.ParameterName;
|
||||||
import fr.neatmonster.nocheatplus.checks.Check;
|
import fr.neatmonster.nocheatplus.checks.Check;
|
||||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||||
|
import fr.neatmonster.nocheatplus.checks.ExecuteActionsEvent;
|
||||||
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
|
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -49,21 +50,43 @@ public class NoPwnage extends Check {
|
|||||||
public NoPwnage() {
|
public NoPwnage() {
|
||||||
super(CheckType.CHAT_NOPWNAGE);
|
super(CheckType.CHAT_NOPWNAGE);
|
||||||
|
|
||||||
for (final Player player : Bukkit.getOnlinePlayers())
|
for (final Player player : Bukkit.getOnlinePlayers()){
|
||||||
ChatData.getData(player).noPwnageLastLocation = player.getLocation();
|
final ChatData data = ChatData.getData(player);
|
||||||
|
synchronized(data){
|
||||||
|
data.noPwnageLastLocation = player.getLocation();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks a player (join).
|
* Checks a player (join).
|
||||||
*
|
*
|
||||||
|
* Only called from the main thread.
|
||||||
|
*
|
||||||
* @param player
|
* @param player
|
||||||
* the player
|
* the player
|
||||||
* @return true, if successful
|
* @return true, if successful
|
||||||
*/
|
*/
|
||||||
public boolean check(final Player player) {
|
public boolean check(final Player player) {
|
||||||
|
|
||||||
|
if (!isEnabled(player)) return false;
|
||||||
|
|
||||||
final ChatConfig cc = ChatConfig.getConfig(player);
|
final ChatConfig cc = ChatConfig.getConfig(player);
|
||||||
final ChatData data = ChatData.getData(player);
|
final ChatData data = ChatData.getData(player);
|
||||||
|
|
||||||
|
synchronized(data){
|
||||||
|
return unsafeCheck(player, cc, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check (Join), only call from synchronized code.
|
||||||
|
* @param player
|
||||||
|
* @param cc
|
||||||
|
* @param data
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean unsafeCheck(final Player player, final ChatConfig cc, final ChatData data) {
|
||||||
boolean cancel = false;
|
boolean cancel = false;
|
||||||
|
|
||||||
final long now = System.currentTimeMillis();
|
final long now = System.currentTimeMillis();
|
||||||
@ -80,7 +103,7 @@ public class NoPwnage extends Check {
|
|||||||
data.noPwnageReloginWarnings++;
|
data.noPwnageReloginWarnings++;
|
||||||
} else if (now - data.noPwnageReloginWarningTime < cc.noPwnageReloginWarningTimeout)
|
} else if (now - data.noPwnageReloginWarningTime < cc.noPwnageReloginWarningTimeout)
|
||||||
// Find out if we need to ban the player or not.
|
// Find out if we need to ban the player or not.
|
||||||
cancel = executeActions_(player);
|
cancel = executeActionsThreadSafe(player, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store his location and some other data.
|
// Store his location and some other data.
|
||||||
@ -99,9 +122,28 @@ public class NoPwnage extends Check {
|
|||||||
* the event
|
* the event
|
||||||
* @return true, if successful
|
* @return true, if successful
|
||||||
*/
|
*/
|
||||||
public boolean check(final Player player, final PlayerEvent event) {
|
public boolean check(final Player player, final PlayerEvent event, final boolean isMainThread) {
|
||||||
|
|
||||||
|
if (isMainThread && !isEnabled(player)) return false;
|
||||||
|
|
||||||
final ChatConfig cc = ChatConfig.getConfig(player);
|
final ChatConfig cc = ChatConfig.getConfig(player);
|
||||||
final ChatData data = ChatData.getData(player);
|
final ChatData data = ChatData.getData(player);
|
||||||
|
|
||||||
|
synchronized(data){
|
||||||
|
return unsafeCheck(player, event, isMainThread, cc, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only to be called form synchronized code.
|
||||||
|
* @param player
|
||||||
|
* @param event
|
||||||
|
* @param isMainThread
|
||||||
|
* @param cc
|
||||||
|
* @param data
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean unsafeCheck(final Player player, final PlayerEvent event, final boolean isMainThread, final ChatConfig cc, final ChatData data) {
|
||||||
data.noPwnageVL = 0D;
|
data.noPwnageVL = 0D;
|
||||||
|
|
||||||
boolean cancel = false;
|
boolean cancel = false;
|
||||||
@ -126,7 +168,7 @@ public class NoPwnage extends Check {
|
|||||||
// Does he failed too much times?
|
// Does he failed too much times?
|
||||||
if (data.noPwnageCaptchTries > cc.noPwnageCaptchaTries)
|
if (data.noPwnageCaptchTries > cc.noPwnageCaptchaTries)
|
||||||
// Find out if we need to ban the player or not.
|
// Find out if we need to ban the player or not.
|
||||||
cancel = executeActions_(player);
|
cancel = executeActionsThreadSafe(player, isMainThread);
|
||||||
|
|
||||||
// Increment his tries number counter.
|
// Increment his tries number counter.
|
||||||
data.noPwnageCaptchTries++;
|
data.noPwnageCaptchTries++;
|
||||||
@ -223,7 +265,7 @@ public class NoPwnage extends Check {
|
|||||||
((PlayerCommandPreprocessEvent) event).setCancelled(true);
|
((PlayerCommandPreprocessEvent) event).setCancelled(true);
|
||||||
|
|
||||||
// Find out if we need to ban the player or not.
|
// Find out if we need to ban the player or not.
|
||||||
cancel = executeActions_(player);
|
cancel = executeActionsThreadSafe(player, isMainThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the message and some other data.
|
// Store the message and some other data.
|
||||||
@ -236,20 +278,40 @@ public class NoPwnage extends Check {
|
|||||||
return cancel;
|
return cancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final boolean executeActions(final Player player){
|
||||||
|
// To be called from synchronized code (ChatData).
|
||||||
|
// Late check of bypass permissions:
|
||||||
|
// (One might use a bypass flag, set if its already been checked and then reset.)
|
||||||
|
if (!isEnabled(player)) return false;
|
||||||
|
return super.executeActions(player);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute actions.
|
* Execute actions from another thread (not the main thread).<br>
|
||||||
*
|
* This does not use extra synchronization.
|
||||||
* @param player
|
* @param player
|
||||||
* the player
|
* @return
|
||||||
* @return true, if successful
|
|
||||||
*/
|
*/
|
||||||
private boolean executeActions_(final Player player) {
|
public final boolean executeActionsThreadSafe(final Player player, boolean isMainThread){
|
||||||
if (super.executeActions(player)) {
|
if (isMainThread){
|
||||||
|
// Just execute.
|
||||||
|
if (executeActions(player)){
|
||||||
ChatData.getData(player).clearNoPwnageData();
|
ChatData.getData(player).clearNoPwnageData();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// Sync it into the main thread by using an event.
|
||||||
|
final ExecuteActionsEvent event = new ExecuteActionsEvent(this, player);
|
||||||
|
Bukkit.getPluginManager().callEvent(event);
|
||||||
|
final boolean cancel = event.getCancel();
|
||||||
|
if (cancel) ChatData.getData(player).clearNoPwnageData();
|
||||||
|
return cancel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player)
|
* @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player)
|
||||||
@ -261,4 +323,5 @@ public class NoPwnage extends Check {
|
|||||||
else
|
else
|
||||||
return super.getParameter(wildcard, player);
|
return super.getParameter(wildcard, player);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user