mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-11-02 08:40:01 +01:00
[Development] Last commit for today. Added NoSwing for BlockPlace, added
Direction, FastInteract, NoSwing, Reach for BlockInteract. Too tired to test them, good luck! zZZ
This commit is contained in:
parent
28ae0a2bef
commit
b879002527
@ -7,6 +7,7 @@ import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.neatmonster.nocheatplus.checks.blockbreak.BlockBreakConfig;
|
||||
import fr.neatmonster.nocheatplus.checks.blockinteract.BlockInteractConfig;
|
||||
import fr.neatmonster.nocheatplus.checks.blockplace.BlockPlaceConfig;
|
||||
import fr.neatmonster.nocheatplus.checks.chat.ChatConfig;
|
||||
import fr.neatmonster.nocheatplus.checks.fight.FightConfig;
|
||||
@ -65,6 +66,7 @@ public class CommandHandler implements CommandExecutor {
|
||||
ConfigManager.cleanup();
|
||||
ConfigManager.init(plugin);
|
||||
BlockBreakConfig.clear();
|
||||
BlockInteractConfig.clear();
|
||||
BlockPlaceConfig.clear();
|
||||
ChatConfig.clear();
|
||||
FightConfig.clear();
|
||||
|
@ -14,6 +14,7 @@ import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import fr.neatmonster.nocheatplus.checks.Workarounds;
|
||||
import fr.neatmonster.nocheatplus.checks.blockbreak.BlockBreakListener;
|
||||
import fr.neatmonster.nocheatplus.checks.blockinteract.BlockInteractListener;
|
||||
import fr.neatmonster.nocheatplus.checks.blockplace.BlockPlaceListener;
|
||||
import fr.neatmonster.nocheatplus.checks.chat.ChatListener;
|
||||
import fr.neatmonster.nocheatplus.checks.fight.FightListener;
|
||||
@ -72,6 +73,7 @@ public class NoCheatPlus extends JavaPlugin implements Listener {
|
||||
// List the events listeners.
|
||||
listeners = new ArrayList<Listener>();
|
||||
listeners.add(new BlockBreakListener());
|
||||
listeners.add(new BlockInteractListener());
|
||||
listeners.add(new BlockPlaceListener());
|
||||
listeners.add(new ChatListener());
|
||||
listeners.add(new FightListener());
|
||||
|
@ -0,0 +1,97 @@
|
||||
package fr.neatmonster.nocheatplus.checks.blockinteract;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.neatmonster.nocheatplus.actions.types.ActionList;
|
||||
import fr.neatmonster.nocheatplus.config.ConfPaths;
|
||||
import fr.neatmonster.nocheatplus.config.ConfigFile;
|
||||
import fr.neatmonster.nocheatplus.config.ConfigManager;
|
||||
import fr.neatmonster.nocheatplus.players.Permissions;
|
||||
|
||||
/*
|
||||
* M#"""""""'M dP dP M""M dP dP
|
||||
* ## mmmm. `M 88 88 M M 88 88
|
||||
* #' .M 88 .d8888b. .d8888b. 88 .dP M M 88d888b. d8888P .d8888b. 88d888b. .d8888b. .d8888b. d8888P
|
||||
* M# MMMb.'YM 88 88' `88 88' `"" 88888" M M 88' `88 88 88ooood8 88' `88 88' `88 88' `"" 88
|
||||
* M# MMMM' M 88 88. .88 88. ... 88 `8b. M M 88 88 88 88. ... 88 88. .88 88. ... 88
|
||||
* M# .;M dP `88888P' `88888P' dP `YP M M dP dP dP `88888P' dP `88888P8 `88888P' dP
|
||||
* M#########M MMMM
|
||||
*
|
||||
* MM'""""'YMM .8888b oo
|
||||
* M' .mmm. `M 88 "
|
||||
* M MMMMMooM .d8888b. 88d888b. 88aaa dP .d8888b.
|
||||
* M MMMMMMMM 88' `88 88' `88 88 88 88' `88
|
||||
* M. `MMM' .M 88. .88 88 88 88 88 88. .88
|
||||
* MM. .dM `88888P' dP dP dP dP `8888P88
|
||||
* MMMMMMMMMMM .88
|
||||
* d8888P
|
||||
*/
|
||||
/**
|
||||
* Configurations specific for the block interact checks. Every world gets one of these assigned to it, or if a world
|
||||
* doesn't get it's own, it will use the "global" version.
|
||||
*/
|
||||
public class BlockInteractConfig {
|
||||
|
||||
/** The map containing the configurations per world. */
|
||||
private static Map<String, BlockInteractConfig> worldsMap = new HashMap<String, BlockInteractConfig>();
|
||||
|
||||
/**
|
||||
* Clear all the configurations.
|
||||
*/
|
||||
public static void clear() {
|
||||
worldsMap.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configuration for a specified player.
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
* @return the configuration
|
||||
*/
|
||||
public static BlockInteractConfig getConfig(final Player player) {
|
||||
if (!worldsMap.containsKey(player.getWorld().getName()))
|
||||
worldsMap.put(player.getWorld().getName(),
|
||||
new BlockInteractConfig(ConfigManager.getConfigFile(player.getWorld().getName())));
|
||||
return worldsMap.get(player.getWorld().getName());
|
||||
}
|
||||
|
||||
public final boolean directionCheck;
|
||||
public final ActionList directionActions;
|
||||
|
||||
public final boolean fastInteractCheck;
|
||||
public final long fastInteractInterval;
|
||||
public final ActionList fastInteractActions;
|
||||
|
||||
public final boolean noSwingCheck;
|
||||
public final ActionList noSwingActions;
|
||||
|
||||
public final boolean reachCheck;
|
||||
public final ActionList reachActions;
|
||||
|
||||
/**
|
||||
* Instantiates a new block interact configuration.
|
||||
*
|
||||
* @param data
|
||||
* the data
|
||||
*/
|
||||
public BlockInteractConfig(final ConfigFile data) {
|
||||
directionCheck = data.getBoolean(ConfPaths.BLOCKINTERACT_DIRECTION_CHECK);
|
||||
directionActions = data.getActionList(ConfPaths.BLOCKINTERACT_DIRECTION_ACTIONS,
|
||||
Permissions.BLOCKINTERACT_DIRECTION);
|
||||
|
||||
fastInteractCheck = data.getBoolean(ConfPaths.BLOCKINTERACT_FASTINTERACT_CHECK);
|
||||
fastInteractInterval = data.getLong(ConfPaths.BLOCKINTERACT_FASTINTERACT_INTERVAL);
|
||||
fastInteractActions = data.getActionList(ConfPaths.BLOCKINTERACT_FASTINTERACT_ACTIONS,
|
||||
Permissions.BLOCKINTERACT_FASTINTERACT);
|
||||
|
||||
noSwingCheck = data.getBoolean(ConfPaths.BLOCKINTERACT_NOSWING_CHECK);
|
||||
noSwingActions = data.getActionList(ConfPaths.BLOCKINTERACT_NOSWING_ACTIONS, Permissions.BLOCKINTERACT_NOSWING);
|
||||
|
||||
reachCheck = data.getBoolean(ConfPaths.BLOCKINTERACT_REACH_CHECK);
|
||||
reachActions = data.getActionList(ConfPaths.BLOCKINTERACT_REACH_ACTIONS, Permissions.BLOCKINTERACT_REACH);
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package fr.neatmonster.nocheatplus.checks.blockinteract;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/*
|
||||
* M#"""""""'M dP dP M""M dP dP
|
||||
* ## mmmm. `M 88 88 M M 88 88
|
||||
* #' .M 88 .d8888b. .d8888b. 88 .dP M M 88d888b. d8888P .d8888b. 88d888b. .d8888b. .d8888b. d8888P
|
||||
* M# MMMb.'YM 88 88' `88 88' `"" 88888" M M 88' `88 88 88ooood8 88' `88 88' `88 88' `"" 88
|
||||
* M# MMMM' M 88 88. .88 88. ... 88 `8b. M M 88 88 88 88. ... 88 88. .88 88. ... 88
|
||||
* M# .;M dP `88888P' `88888P' dP `YP M M dP dP dP `88888P' dP `88888P8 `88888P' dP
|
||||
* M#########M MMMM
|
||||
*
|
||||
* M""""""'YMM dP
|
||||
* M mmmm. `M 88
|
||||
* M MMMMM M .d8888b. d8888P .d8888b.
|
||||
* M MMMMM M 88' `88 88 88' `88
|
||||
* M MMMM' .M 88. .88 88 88. .88
|
||||
* M .MM `88888P8 dP `88888P8
|
||||
* MMMMMMMMMMM
|
||||
*/
|
||||
/**
|
||||
* Player specific data for the block interact checks.
|
||||
*/
|
||||
public class BlockInteractData {
|
||||
|
||||
/** The map containing the data per players. */
|
||||
private static Map<String, BlockInteractData> playersMap = new HashMap<String, BlockInteractData>();
|
||||
|
||||
/**
|
||||
* Gets the data of a specified player.
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
* @return the data
|
||||
*/
|
||||
public static BlockInteractData getData(final Player player) {
|
||||
if (!playersMap.containsKey(player.getName()))
|
||||
playersMap.put(player.getName(), new BlockInteractData());
|
||||
return playersMap.get(player.getName());
|
||||
}
|
||||
|
||||
// Violation levels.
|
||||
public double directionVL;
|
||||
public double fastInteractVL;
|
||||
public double noSwingVL;
|
||||
public double reachVL;
|
||||
|
||||
// Data of the fast interact check.
|
||||
public boolean fastInteractLastRefused;
|
||||
public double fastInteractLastTime;
|
||||
|
||||
// Data of the no swing check.
|
||||
public boolean noSwingArmSwung;
|
||||
|
||||
// Data of the reach check.
|
||||
public double reachDistance;
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
package fr.neatmonster.nocheatplus.checks.blockinteract;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.player.PlayerAnimationEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
|
||||
/*
|
||||
* M#"""""""'M dP dP M""M dP dP
|
||||
* ## mmmm. `M 88 88 M M 88 88
|
||||
* #' .M 88 .d8888b. .d8888b. 88 .dP M M 88d888b. d8888P .d8888b. 88d888b. .d8888b. .d8888b. d8888P
|
||||
* M# MMMb.'YM 88 88' `88 88' `"" 88888" M M 88' `88 88 88ooood8 88' `88 88' `88 88' `"" 88
|
||||
* M# MMMM' M 88 88. .88 88. ... 88 `8b. M M 88 88 88 88. ... 88 88. .88 88. ... 88
|
||||
* M# .;M dP `88888P' `88888P' dP `YP M M dP dP dP `88888P' dP `88888P8 `88888P' dP
|
||||
* M#########M MMMM
|
||||
*
|
||||
* M""MMMMMMMM oo dP
|
||||
* M MMMMMMMM 88
|
||||
* M MMMMMMMM dP .d8888b. d8888P .d8888b. 88d888b. .d8888b. 88d888b.
|
||||
* M MMMMMMMM 88 Y8ooooo. 88 88ooood8 88' `88 88ooood8 88' `88
|
||||
* M MMMMMMMM 88 88 88 88. ... 88 88 88. ... 88
|
||||
* M M dP `88888P' dP `88888P' dP dP `88888P' dP
|
||||
* MMMMMMMMMMM
|
||||
*/
|
||||
/**
|
||||
* Central location to listen to events that are relevant for the block interact checks.
|
||||
*
|
||||
* @see BlockInteractEvent
|
||||
*/
|
||||
public class BlockInteractListener implements Listener {
|
||||
private final Direction direction = new Direction();
|
||||
private final FastInteract fastInteract = new FastInteract();
|
||||
private final NoSwing noSwing = new NoSwing();
|
||||
private final Reach reach = new Reach();
|
||||
|
||||
/**
|
||||
* We listen to PlayerAnimation events because it is (currently) equivalent to "player swings arm" and we want to
|
||||
* check if he did that between interactions with blocks.
|
||||
*
|
||||
* @param event
|
||||
* the event
|
||||
*/
|
||||
@EventHandler(
|
||||
priority = EventPriority.MONITOR)
|
||||
public void onPlayerAnimation(final PlayerAnimationEvent event) {
|
||||
/*
|
||||
* ____ _ _ _ _ _
|
||||
* | _ \| | __ _ _ _ ___ _ __ / \ _ __ (_)_ __ ___ __ _| |_(_) ___ _ __
|
||||
* | |_) | |/ _` | | | |/ _ \ '__| / _ \ | '_ \| | '_ ` _ \ / _` | __| |/ _ \| '_ \
|
||||
* | __/| | (_| | |_| | __/ | / ___ \| | | | | | | | | | (_| | |_| | (_) | | | |
|
||||
* |_| |_|\__,_|\__, |\___|_| /_/ \_\_| |_|_|_| |_| |_|\__,_|\__|_|\___/|_| |_|
|
||||
* |___/
|
||||
*/
|
||||
// Just set a flag to true when the arm was swung.
|
||||
BlockInteractData.getData(event.getPlayer()).noSwingArmSwung = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* We listen to PlayerInteractEvent events for obvious reasons
|
||||
*
|
||||
* @param event
|
||||
* the event
|
||||
*/
|
||||
@EventHandler(
|
||||
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
protected void onPlayerInteract(final PlayerInteractEvent event) {
|
||||
/*
|
||||
* ____ _ ___ _ _
|
||||
* | _ \| | __ _ _ _ ___ _ __ |_ _|_ __ | |_ ___ _ __ __ _ ___| |_
|
||||
* | |_) | |/ _` | | | |/ _ \ '__| | || '_ \| __/ _ \ '__/ _` |/ __| __|
|
||||
* | __/| | (_| | |_| | __/ | | || | | | || __/ | | (_| | (__| |_
|
||||
* |_| |_|\__,_|\__, |\___|_| |___|_| |_|\__\___|_| \__,_|\___|\__|
|
||||
* |___/
|
||||
*/
|
||||
final Player player = event.getPlayer();
|
||||
|
||||
if (event.getClickedBlock() == null || event.getAction() != Action.LEFT_CLICK_BLOCK
|
||||
&& event.getAction() != Action.RIGHT_CLICK_BLOCK)
|
||||
return;
|
||||
|
||||
final Block block = event.getClickedBlock();
|
||||
|
||||
boolean cancelled = false;
|
||||
|
||||
// Do the actual checks, first the fast interact check.
|
||||
if (fastInteract.isEnabled(player) && fastInteract.check(player))
|
||||
cancelled = true;
|
||||
|
||||
// Second the no swing check.
|
||||
if (!cancelled && noSwing.isEnabled(player) && noSwing.check(player))
|
||||
cancelled = true;
|
||||
|
||||
// Third the reach check
|
||||
if (!cancelled && reach.isEnabled(player) && reach.check(player, block.getLocation()))
|
||||
cancelled = true;
|
||||
|
||||
// Fourth the direction check
|
||||
if (!cancelled && direction.isEnabled(player) && direction.check(player, block.getLocation()))
|
||||
cancelled = true;
|
||||
|
||||
// If one of the checks requested to cancel the event, do so.
|
||||
if (cancelled)
|
||||
event.setCancelled(cancelled);
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
package fr.neatmonster.nocheatplus.checks.blockinteract;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import fr.neatmonster.nocheatplus.actions.ParameterName;
|
||||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckEvent;
|
||||
import fr.neatmonster.nocheatplus.players.Permissions;
|
||||
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
|
||||
|
||||
/*
|
||||
* M""""""'YMM oo dP oo
|
||||
* M mmmm. `M 88
|
||||
* M MMMMM M dP 88d888b. .d8888b. .d8888b. d8888P dP .d8888b. 88d888b.
|
||||
* M MMMMM M 88 88' `88 88ooood8 88' `"" 88 88 88' `88 88' `88
|
||||
* M MMMM' .M 88 88 88. ... 88. ... 88 88 88. .88 88 88
|
||||
* M .MM dP dP `88888P' `88888P' dP dP `88888P' dP dP
|
||||
* MMMMMMMMMMM
|
||||
*/
|
||||
/**
|
||||
* The Direction check will find out if a player tried to interact with something that's not in his field of view.
|
||||
*/
|
||||
public class Direction extends Check {
|
||||
|
||||
/**
|
||||
* The event triggered by this check.
|
||||
*/
|
||||
public class DirectionEvent extends CheckEvent {
|
||||
|
||||
/**
|
||||
* Instantiates a new direction event.
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
*/
|
||||
public DirectionEvent(final Player player) {
|
||||
super(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a player.
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
* @param location
|
||||
* the location
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean check(final Player player, final Location location) {
|
||||
final BlockInteractConfig cc = BlockInteractConfig.getConfig(player);
|
||||
final BlockInteractData data = BlockInteractData.getData(player);
|
||||
|
||||
boolean cancel = false;
|
||||
|
||||
// How far "off" is the player with his aim. We calculate from the players eye location and view direction to
|
||||
// the center of the target block. If the line of sight is more too far off, "off" will be bigger than 0.
|
||||
final double off = CheckUtils.directionCheck(player, location.getX() + 0.5D, location.getY() + 0.5D,
|
||||
location.getZ() + 0.5D, 1D, 1D, 50);
|
||||
|
||||
if (off > 0.1D) {
|
||||
// Player failed the check. Let's try to guess how far he was from looking directly to the block...
|
||||
final Vector direction = player.getEyeLocation().getDirection();
|
||||
final Vector blockEyes = location.add(0.5D, 0.5D, 0.5D).subtract(player.getEyeLocation()).toVector();
|
||||
final double distance = blockEyes.crossProduct(direction).length() / direction.length();
|
||||
|
||||
// Add the overall violation level of the check.
|
||||
data.directionVL += distance;
|
||||
|
||||
// Dispatch a direction event (API).
|
||||
final DirectionEvent e = new DirectionEvent(player);
|
||||
Bukkit.getPluginManager().callEvent(e);
|
||||
|
||||
// Execute whatever actions are associated with this check and the violation level and find out if we should
|
||||
// cancel the event.
|
||||
cancel = !e.isCancelled() && executeActions(player, cc.directionActions, data.directionVL);
|
||||
} else
|
||||
// Player did likely nothing wrong, reduce violation counter to reward him.
|
||||
data.directionVL *= 0.9D;
|
||||
|
||||
return cancel;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player)
|
||||
*/
|
||||
@Override
|
||||
public String getParameter(final ParameterName wildcard, final Player player) {
|
||||
if (wildcard == ParameterName.VIOLATIONS)
|
||||
return String.valueOf(Math.round(BlockInteractData.getData(player).directionVL));
|
||||
else
|
||||
return super.getParameter(wildcard, player);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player)
|
||||
*/
|
||||
@Override
|
||||
protected boolean isEnabled(final Player player) {
|
||||
return !player.hasPermission(Permissions.BLOCKINTERACT_DIRECTION)
|
||||
&& BlockInteractConfig.getConfig(player).directionCheck;
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
package fr.neatmonster.nocheatplus.checks.blockinteract;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.neatmonster.nocheatplus.actions.ParameterName;
|
||||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckEvent;
|
||||
import fr.neatmonster.nocheatplus.players.Permissions;
|
||||
import fr.neatmonster.nocheatplus.utilities.LagMeasureTask;
|
||||
|
||||
/*
|
||||
* MM""""""""`M dP M""M dP dP
|
||||
MM mmmmmmmM 88 M M 88 88
|
||||
M' MMMM .d8888b. .d8888b. d8888P M M 88d888b. d8888P .d8888b. 88d888b. .d8888b. .d8888b. d8888P
|
||||
MM MMMMMMMM 88' `88 Y8ooooo. 88 M M 88' `88 88 88ooood8 88' `88 88' `88 88' `"" 88
|
||||
MM MMMMMMMM 88. .88 88 88 M M 88 88 88 88. ... 88 88. .88 88. ... 88
|
||||
MM MMMMMMMM `88888P8 `88888P' dP M M dP dP dP `88888P' dP `88888P8 `88888P' dP
|
||||
MMMMMMMMMMMM MMMM
|
||||
*/
|
||||
/**
|
||||
* A check used to verify if the player isn't interacting with blocks too quickly.
|
||||
*/
|
||||
public class FastInteract extends Check {
|
||||
|
||||
/**
|
||||
* The event triggered by this check.
|
||||
*/
|
||||
public class FastInteractEvent extends CheckEvent {
|
||||
|
||||
/**
|
||||
* Instantiates a new fast interact event.
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
*/
|
||||
public FastInteractEvent(final Player player) {
|
||||
super(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a player.
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean check(final Player player) {
|
||||
final BlockInteractConfig cc = BlockInteractConfig.getConfig(player);
|
||||
final BlockInteractData data = BlockInteractData.getData(player);
|
||||
|
||||
boolean cancel = false;
|
||||
|
||||
// Has the player interacted with blocks too quickly?
|
||||
if (data.fastInteractLastTime != 0
|
||||
&& System.currentTimeMillis() - data.fastInteractLastTime < cc.fastInteractInterval) {
|
||||
if (!LagMeasureTask.skipCheck()) {
|
||||
if (data.fastInteractLastRefused) {
|
||||
// He failed, increase his violation level.
|
||||
data.fastInteractVL += cc.fastInteractInterval - System.currentTimeMillis()
|
||||
+ data.fastInteractLastTime;
|
||||
|
||||
// Distance a fast interact event (API).
|
||||
final FastInteractEvent e = new FastInteractEvent(player);
|
||||
Bukkit.getPluginManager().callEvent(e);
|
||||
|
||||
// Execute whatever actions are associated with this check and the violation level and find out if
|
||||
// we should cancel the event.
|
||||
cancel = !e.isCancelled() && executeActions(player, cc.fastInteractActions, data.fastInteractVL);
|
||||
}
|
||||
|
||||
data.fastInteractLastRefused = true;
|
||||
}
|
||||
} else {
|
||||
// Reward him by lowering his violation level.
|
||||
data.fastInteractVL *= 0.9D;
|
||||
data.fastInteractLastRefused = false;
|
||||
}
|
||||
|
||||
data.fastInteractLastTime = System.currentTimeMillis();
|
||||
|
||||
return cancel;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player)
|
||||
*/
|
||||
@Override
|
||||
public String getParameter(final ParameterName wildcard, final Player player) {
|
||||
if (wildcard == ParameterName.VIOLATIONS)
|
||||
return String.valueOf(Math.round(BlockInteractData.getData(player).fastInteractVL));
|
||||
else
|
||||
return super.getParameter(wildcard, player);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player)
|
||||
*/
|
||||
@Override
|
||||
protected boolean isEnabled(final Player player) {
|
||||
return !player.hasPermission(Permissions.BLOCKINTERACT_FASTINTERACT)
|
||||
&& BlockInteractConfig.getConfig(player).fastInteractCheck;
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
package fr.neatmonster.nocheatplus.checks.blockinteract;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.neatmonster.nocheatplus.actions.ParameterName;
|
||||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckEvent;
|
||||
import fr.neatmonster.nocheatplus.players.Permissions;
|
||||
|
||||
/*
|
||||
* M"""""""`YM MP""""""`MM oo
|
||||
* M mmmm. M M mmmmm..M
|
||||
* M MMMMM M .d8888b. M. `YM dP dP dP dP 88d888b. .d8888b.
|
||||
* M MMMMM M 88' `88 MMMMMMM. M 88 88 88 88 88' `88 88' `88
|
||||
* M MMMMM M 88. .88 M. .MMM' M 88.88b.88' 88 88 88 88. .88
|
||||
* M MMMMM M `88888P' Mb. .dM 8888P Y8P dP dP dP `8888P88
|
||||
* MMMMMMMMMMM MMMMMMMMMMM .88
|
||||
* d8888P
|
||||
*/
|
||||
/**
|
||||
* We require that the player moves his arm between block breaks, this is what gets checked here.
|
||||
*/
|
||||
public class NoSwing extends Check {
|
||||
|
||||
/**
|
||||
* The event triggered by this check.
|
||||
*/
|
||||
public class NoSwingEvent extends CheckEvent {
|
||||
|
||||
/**
|
||||
* Instantiates a new no swing event.
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
*/
|
||||
public NoSwingEvent(final Player player) {
|
||||
super(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a player.
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean check(final Player player) {
|
||||
final BlockInteractConfig cc = BlockInteractConfig.getConfig(player);
|
||||
final BlockInteractData data = BlockInteractData.getData(player);
|
||||
|
||||
boolean cancel = false;
|
||||
|
||||
// Did he swing his arm before?
|
||||
if (data.noSwingArmSwung) {
|
||||
// "Consume" the flag.
|
||||
data.noSwingArmSwung = false;
|
||||
// Reward with lowering of the violation level.
|
||||
data.noSwingVL *= 0.9D;
|
||||
} else {
|
||||
// He failed, increase violation level.
|
||||
data.noSwingVL += 1D;
|
||||
|
||||
// Dispatch a no swing event (API).
|
||||
final NoSwingEvent e = new NoSwingEvent(player);
|
||||
Bukkit.getPluginManager().callEvent(e);
|
||||
|
||||
// Execute whatever actions are associated with this check and the violation level and find out if we should
|
||||
// cancel the event.
|
||||
cancel = !e.isCancelled() && executeActions(player, cc.noSwingActions, data.noSwingVL);
|
||||
}
|
||||
|
||||
return cancel;
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player)
|
||||
*/
|
||||
@Override
|
||||
public String getParameter(final ParameterName wildcard, final Player player) {
|
||||
if (wildcard == ParameterName.VIOLATIONS)
|
||||
return String.valueOf(Math.round(BlockInteractData.getData(player).noSwingVL));
|
||||
else
|
||||
return super.getParameter(wildcard, player);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player)
|
||||
*/
|
||||
@Override
|
||||
protected boolean isEnabled(final Player player) {
|
||||
return !player.hasPermission(Permissions.BLOCKINTERACT_NOSWING)
|
||||
&& BlockInteractConfig.getConfig(player).noSwingCheck;
|
||||
}
|
||||
}
|
107
src/fr/neatmonster/nocheatplus/checks/blockinteract/Reach.java
Normal file
107
src/fr/neatmonster/nocheatplus/checks/blockinteract/Reach.java
Normal file
@ -0,0 +1,107 @@
|
||||
package fr.neatmonster.nocheatplus.checks.blockinteract;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.neatmonster.nocheatplus.actions.ParameterName;
|
||||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckEvent;
|
||||
import fr.neatmonster.nocheatplus.players.Permissions;
|
||||
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
|
||||
|
||||
/*
|
||||
* MM"""""""`MM dP
|
||||
* MM mmmm, M 88
|
||||
* M' .M .d8888b. .d8888b. .d8888b. 88d888b.
|
||||
* MM MMMb. "M 88ooood8 88' `88 88' `"" 88' `88
|
||||
* MM MMMMM M 88. ... 88. .88 88. ... 88 88
|
||||
* MM MMMMM M `88888P' `88888P8 `88888P' dP dP
|
||||
* MMMMMMMMMMMM
|
||||
*/
|
||||
/**
|
||||
* The Reach check will find out if a player interacts with something that's too far away.
|
||||
*/
|
||||
public class Reach extends Check {
|
||||
|
||||
/**
|
||||
* The event triggered by this check.
|
||||
*/
|
||||
public class ReachEvent extends CheckEvent {
|
||||
|
||||
/**
|
||||
* Instantiates a new reach event.
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
*/
|
||||
public ReachEvent(final Player player) {
|
||||
super(player);
|
||||
}
|
||||
}
|
||||
|
||||
/** The maximum distance allowed to interact with a block. */
|
||||
public final double DISTANCE = 5D; // TODO: Test with creative mode.
|
||||
|
||||
/**
|
||||
* Checks a player.
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
* @param location
|
||||
* the location
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean check(final Player player, final Location location) {
|
||||
final BlockInteractConfig cc = BlockInteractConfig.getConfig(player);
|
||||
final BlockInteractData data = BlockInteractData.getData(player);
|
||||
|
||||
boolean cancel = false;
|
||||
|
||||
// Distance is calculated from eye location to center of targeted block. If the player is further away from his
|
||||
// target than allowed, the difference will be assigned to "distance".
|
||||
final double distance = Math.max(CheckUtils.distance(player, location) - DISTANCE, 0D);
|
||||
|
||||
if (distance > 0) {
|
||||
// He failed, increment violation level.
|
||||
data.reachVL += distance;
|
||||
|
||||
// Dispatch a reach event (API).
|
||||
final ReachEvent e = new ReachEvent(player);
|
||||
Bukkit.getPluginManager().callEvent(e);
|
||||
|
||||
// Remember how much further than allowed he tried to reach for logging, if necessary.
|
||||
data.reachDistance = distance + DISTANCE;
|
||||
|
||||
// Execute whatever actions are associated with this check and the violation level and find out if we should
|
||||
// cancel the event.
|
||||
cancel = !e.isCancelled() && executeActions(player, cc.reachActions, data.reachVL);
|
||||
} else
|
||||
// Player passed the check, reward him.
|
||||
data.reachVL *= 0.9D;
|
||||
|
||||
return cancel;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player)
|
||||
*/
|
||||
@Override
|
||||
public String getParameter(final ParameterName wildcard, final Player player) {
|
||||
if (wildcard == ParameterName.VIOLATIONS)
|
||||
return String.valueOf(Math.round(BlockInteractData.getData(player).reachVL));
|
||||
else if (wildcard == ParameterName.REACH_DISTANCE)
|
||||
return String.valueOf(Math.round(BlockInteractData.getData(player).reachDistance));
|
||||
else
|
||||
return super.getParameter(wildcard, player);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player)
|
||||
*/
|
||||
@Override
|
||||
protected boolean isEnabled(final Player player) {
|
||||
return !player.hasPermission(Permissions.BLOCKINTERACT_REACH)
|
||||
&& BlockInteractConfig.getConfig(player).reachCheck;
|
||||
}
|
||||
}
|
@ -70,12 +70,12 @@ public class FastPlace extends Check {
|
||||
// we should cancel the event.
|
||||
cancel = !e.isCancelled() && executeActions(player, cc.fastPlaceActions, data.fastPlaceVL);
|
||||
}
|
||||
|
||||
data.fastPlaceLastRefused = true;
|
||||
}
|
||||
} else {
|
||||
// Reward him by lowering his violation level.
|
||||
data.fastPlaceVL *= 0.9D;
|
||||
|
||||
data.fastPlaceLastRefused = false;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,95 @@
|
||||
package fr.neatmonster.nocheatplus.checks.blockplace;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.neatmonster.nocheatplus.actions.ParameterName;
|
||||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckEvent;
|
||||
import fr.neatmonster.nocheatplus.players.Permissions;
|
||||
|
||||
/*
|
||||
* M"""""""`YM MP""""""`MM oo
|
||||
* M mmmm. M M mmmmm..M
|
||||
* M MMMMM M .d8888b. M. `YM dP dP dP dP 88d888b. .d8888b.
|
||||
* M MMMMM M 88' `88 MMMMMMM. M 88 88 88 88 88' `88 88' `88
|
||||
* M MMMMM M 88. .88 M. .MMM' M 88.88b.88' 88 88 88 88. .88
|
||||
* M MMMMM M `88888P' Mb. .dM 8888P Y8P dP dP dP `8888P88
|
||||
* MMMMMMMMMMM MMMMMMMMMMM .88
|
||||
* d8888P
|
||||
*/
|
||||
/**
|
||||
* We require that the player moves his arm between block places, this is what gets checked here.
|
||||
*/
|
||||
public class NoSwing extends Check {
|
||||
|
||||
/**
|
||||
* The event triggered by this check.
|
||||
*/
|
||||
public class NoSwingEvent extends CheckEvent {
|
||||
|
||||
/**
|
||||
* Instantiates a new no swing event.
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
*/
|
||||
public NoSwingEvent(final Player player) {
|
||||
super(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a player.
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean check(final Player player) {
|
||||
final BlockPlaceConfig cc = BlockPlaceConfig.getConfig(player);
|
||||
final BlockPlaceData data = BlockPlaceData.getData(player);
|
||||
|
||||
boolean cancel = false;
|
||||
|
||||
// Did he swing his arm before?
|
||||
if (data.noSwingArmSwung) {
|
||||
// "Consume" the flag.
|
||||
data.noSwingArmSwung = false;
|
||||
// Reward with lowering of the violation level.
|
||||
data.noSwingVL *= 0.9D;
|
||||
} else {
|
||||
// He failed, increase violation level.
|
||||
data.noSwingVL += 1D;
|
||||
|
||||
// Dispatch a no swing event (API).
|
||||
final NoSwingEvent e = new NoSwingEvent(player);
|
||||
Bukkit.getPluginManager().callEvent(e);
|
||||
|
||||
// Execute whatever actions are associated with this check and the violation level and find out if we should
|
||||
// cancel the event.
|
||||
cancel = !e.isCancelled() && executeActions(player, cc.noSwingActions, data.noSwingVL);
|
||||
}
|
||||
|
||||
return cancel;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player)
|
||||
*/
|
||||
@Override
|
||||
public String getParameter(final ParameterName wildcard, final Player player) {
|
||||
if (wildcard == ParameterName.VIOLATIONS)
|
||||
return String.valueOf(Math.round(BlockPlaceData.getData(player).noSwingVL));
|
||||
else
|
||||
return super.getParameter(wildcard, player);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player)
|
||||
*/
|
||||
@Override
|
||||
protected boolean isEnabled(final Player player) {
|
||||
return !player.hasPermission(Permissions.BLOCKPLACE_NOSWING) && BlockPlaceConfig.getConfig(player).noSwingCheck;
|
||||
}
|
||||
}
|
@ -115,6 +115,14 @@ public class FightListener implements Listener {
|
||||
@EventHandler(
|
||||
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onEntityDamage(final EntityDamageEvent event) {
|
||||
/*
|
||||
* _____ _ _ _ ____
|
||||
* | ____|_ __ | |_(_) |_ _ _ | _ \ __ _ _ __ ___ __ _ __ _ ___
|
||||
* | _| | '_ \| __| | __| | | | | | | |/ _` | '_ ` _ \ / _` |/ _` |/ _ \
|
||||
* | |___| | | | |_| | |_| |_| | | |_| | (_| | | | | | | (_| | (_| | __/
|
||||
* |_____|_| |_|\__|_|\__|\__, | |____/ \__,_|_| |_| |_|\__,_|\__, |\___|
|
||||
* |___/ |___/
|
||||
*/
|
||||
// Filter some unwanted events right now.
|
||||
if (event instanceof EntityDamageByEntityEvent) {
|
||||
final EntityDamageByEntityEvent e = (EntityDamageByEntityEvent) event;
|
||||
@ -135,6 +143,14 @@ public class FightListener implements Listener {
|
||||
@EventHandler(
|
||||
ignoreCancelled = true, priority = EventPriority.LOW)
|
||||
public void onEntityDamage_(final EntityDamageEvent event) {
|
||||
/*
|
||||
* _____ _ _ _ ____
|
||||
* | ____|_ __ | |_(_) |_ _ _ | _ \ __ _ _ __ ___ __ _ __ _ ___
|
||||
* | _| | '_ \| __| | __| | | | | | | |/ _` | '_ ` _ \ / _` |/ _` |/ _ \
|
||||
* | |___| | | | |_| | |_| |_| | | |_| | (_| | | | | | | (_| | (_| | __/
|
||||
* |_____|_| |_|\__|_|\__|\__, | |____/ \__,_|_| |_| |_|\__,_|\__, |\___|
|
||||
* |___/ |___/
|
||||
*/
|
||||
// Filter unwanted events right here.
|
||||
if (event.getEntity() instanceof Player && !event.getEntity().isDead()) {
|
||||
final Player player = (Player) event.getEntity();
|
||||
@ -153,6 +169,14 @@ public class FightListener implements Listener {
|
||||
@EventHandler(
|
||||
priority = EventPriority.MONITOR)
|
||||
protected void onEntityDeathEvent(final EntityDeathEvent event) {
|
||||
/*
|
||||
* _____ _ _ _ ____ _ _
|
||||
* | ____|_ __ | |_(_) |_ _ _ | _ \ ___ __ _| |_| |__
|
||||
* | _| | '_ \| __| | __| | | | | | | |/ _ \/ _` | __| '_ \
|
||||
* | |___| | | | |_| | |_| |_| | | |_| | __/ (_| | |_| | | |
|
||||
* |_____|_| |_|\__|_|\__|\__, | |____/ \___|\__,_|\__|_| |_|
|
||||
* |___/
|
||||
*/
|
||||
// Only interested in dying players.
|
||||
if (event.getEntity() instanceof Player)
|
||||
godMode.death((Player) event.getEntity());
|
||||
@ -167,6 +191,14 @@ public class FightListener implements Listener {
|
||||
@EventHandler(
|
||||
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onEntityRegainHealth(final EntityRegainHealthEvent event) {
|
||||
/*
|
||||
* _____ _ _ _ ____ _ _ _ _ _ _
|
||||
* | ____|_ __ | |_(_) |_ _ _ | _ \ ___ __ _ __ _(_)_ __ | | | | ___ __ _| | |_| |__
|
||||
* | _| | '_ \| __| | __| | | | | |_) / _ \/ _` |/ _` | | '_ \ | |_| |/ _ \/ _` | | __| '_ \
|
||||
* | |___| | | | |_| | |_| |_| | | _ < __/ (_| | (_| | | | | | | _ | __/ (_| | | |_| | | |
|
||||
* |_____|_| |_|\__|_|\__|\__, | |_| \_\___|\__, |\__,_|_|_| |_| |_| |_|\___|\__,_|_|\__|_| |_|
|
||||
* |___/ |___/
|
||||
*/
|
||||
if (event.getEntity() instanceof Player && event.getRegainReason() == RegainReason.SATIATED) {
|
||||
final Player player = (Player) event.getEntity();
|
||||
if (instantHeal.isEnabled(player) && instantHeal.check(player))
|
||||
@ -183,6 +215,14 @@ public class FightListener implements Listener {
|
||||
@EventHandler(
|
||||
priority = EventPriority.MONITOR)
|
||||
protected void onPlayerAnimation(final PlayerAnimationEvent event) {
|
||||
/*
|
||||
* ____ _ _ _ _ _
|
||||
* | _ \| | __ _ _ _ ___ _ __ / \ _ __ (_)_ __ ___ __ _| |_(_) ___ _ __
|
||||
* | |_) | |/ _` | | | |/ _ \ '__| / _ \ | '_ \| | '_ ` _ \ / _` | __| |/ _ \| '_ \
|
||||
* | __/| | (_| | |_| | __/ | / ___ \| | | | | | | | | | (_| | |_| | (_) | | | |
|
||||
* |_| |_|\__,_|\__, |\___|_| /_/ \_\_| |_|_|_| |_| |_|\__,_|\__|_|\___/|_| |_|
|
||||
* |___/
|
||||
*/
|
||||
// Set a flag telling us that the arm has been swung.
|
||||
FightData.getData(event.getPlayer()).noSwingArmSwung = true;
|
||||
}
|
||||
@ -196,6 +236,14 @@ public class FightListener implements Listener {
|
||||
@EventHandler(
|
||||
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerToggleSprint(final PlayerToggleSprintEvent event) {
|
||||
/*
|
||||
* ____ _ _____ _ ____ _ _
|
||||
* | _ \| | __ _ _ _ ___ _ __ |_ _|__ __ _ __ _| | ___ / ___| _ __ _ __(_)_ __ | |_
|
||||
* | |_) | |/ _` | | | |/ _ \ '__| | |/ _ \ / _` |/ _` | |/ _ \ \___ \| '_ \| '__| | '_ \| __|
|
||||
* | __/| | (_| | |_| | __/ | | | (_) | (_| | (_| | | __/ ___) | |_) | | | | | | | |_
|
||||
* |_| |_|\__,_|\__, |\___|_| |_|\___/ \__, |\__, |_|\___| |____/| .__/|_| |_|_| |_|\__|
|
||||
* |___/ |___/ |___/ |_|
|
||||
*/
|
||||
FightData.getData(event.getPlayer()).knockbackSprintTime = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +46,14 @@ public class InventoryListener implements Listener {
|
||||
@EventHandler(
|
||||
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onEntityShootBow(final EntityShootBowEvent event) {
|
||||
/*
|
||||
* _____ _ _ _ ____ _ _ ____
|
||||
* | ____|_ __ | |_(_) |_ _ _ / ___|| |__ ___ ___ | |_ | __ ) _____ __
|
||||
* | _| | '_ \| __| | __| | | | \___ \| '_ \ / _ \ / _ \| __| | _ \ / _ \ \ /\ / /
|
||||
* | |___| | | | |_| | |_| |_| | ___) | | | | (_) | (_) | |_ | |_) | (_) \ V V /
|
||||
* |_____|_| |_|\__|_|\__|\__, | |____/|_| |_|\___/ \___/ \__| |____/ \___/ \_/\_/
|
||||
* |___/
|
||||
*/
|
||||
// Only if a player shot the arrow.
|
||||
if (event.getEntity() instanceof Player) {
|
||||
final Player player = (Player) event.getEntity();
|
||||
@ -65,6 +73,14 @@ public class InventoryListener implements Listener {
|
||||
@EventHandler(
|
||||
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onFoodLevelChange(final FoodLevelChangeEvent event) {
|
||||
/*
|
||||
* _____ _ _ _ ____ _
|
||||
* | ___|__ ___ __| | | | _____ _____| | / ___| |__ __ _ _ __ __ _ ___
|
||||
* | |_ / _ \ / _ \ / _` | | | / _ \ \ / / _ \ | | | | '_ \ / _` | '_ \ / _` |/ _ \
|
||||
* | _| (_) | (_) | (_| | | |__| __/\ V / __/ | | |___| | | | (_| | | | | (_| | __/
|
||||
* |_| \___/ \___/ \__,_| |_____\___| \_/ \___|_| \____|_| |_|\__,_|_| |_|\__, |\___|
|
||||
* |___/
|
||||
*/
|
||||
// Only if a player ate food.
|
||||
if (event.getEntity() instanceof Player) {
|
||||
final Player player = (Player) event.getEntity();
|
||||
@ -84,6 +100,14 @@ public class InventoryListener implements Listener {
|
||||
@EventHandler(
|
||||
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
protected void onPlayerDropItem(final PlayerDropItemEvent event) {
|
||||
/*
|
||||
* ____ _ ____
|
||||
* | _ \| | __ _ _ _ ___ _ __ | _ \ _ __ ___ _ __
|
||||
* | |_) | |/ _` | | | |/ _ \ '__| | | | | '__/ _ \| '_ \
|
||||
* | __/| | (_| | |_| | __/ | | |_| | | | (_) | |_) |
|
||||
* |_| |_|\__,_|\__, |\___|_| |____/|_| \___/| .__/
|
||||
* |___/ |_|
|
||||
*/
|
||||
// If the player died, all his items are dropped so ignore him.
|
||||
if (event.getPlayer().isDead())
|
||||
return;
|
||||
@ -103,6 +127,14 @@ public class InventoryListener implements Listener {
|
||||
@EventHandler(
|
||||
priority = EventPriority.LOWEST)
|
||||
public void onPlayerInteractEvent(final PlayerInteractEvent event) {
|
||||
/*
|
||||
* ____ _ ___ _ _
|
||||
* | _ \| | __ _ _ _ ___ _ __ |_ _|_ __ | |_ ___ _ __ __ _ ___| |_
|
||||
* | |_) | |/ _` | | | |/ _ \ '__| | || '_ \| __/ _ \ '__/ _` |/ __| __|
|
||||
* | __/| | (_| | |_| | __/ | | || | | | || __/ | | (_| | (__| |_
|
||||
* |_| |_|\__,_|\__, |\___|_| |___|_| |_|\__\___|_| \__,_|\___|\__|
|
||||
* |___/
|
||||
*/
|
||||
// Only interested in right-clicks while holding an item.
|
||||
if (!event.hasItem()
|
||||
|| !(event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK))
|
||||
|
@ -70,6 +70,32 @@ public abstract class ConfPaths {
|
||||
public static final String BLOCKBREAK_REACH_CHECK = BLOCKBREAK_REACH + "active";
|
||||
public static final String BLOCKBREAK_REACH_ACTIONS = BLOCKBREAK_REACH + "actions";
|
||||
|
||||
/*
|
||||
* 888 88b, 888 888 888 d8 d8
|
||||
* 888 88P' 888 e88 88e e88'888 888 ee 888 888 8e d88 ,e e, 888,8, ,"Y88b e88'888 d88
|
||||
* 888 8K 888 d888 888b d888 '8 888 P 888 888 88b d88888 d88 88b 888 " "8" 888 d888 '8 d88888
|
||||
* 888 88b, 888 Y888 888P Y888 , 888 b 888 888 888 888 888 , 888 ,ee 888 Y888 , 888
|
||||
* 888 88P' 888 "88 88" "88,e8' 888 8b 888 888 888 888 "YeeP" 888 "88 888 "88,e8' 888
|
||||
*/
|
||||
private static final String BLOCKINTERACT = CHECKS + "blockinteract.";
|
||||
|
||||
private static final String BLOCKINTERACT_DIRECTION = BLOCKINTERACT + "direction.";
|
||||
public static final String BLOCKINTERACT_DIRECTION_CHECK = BLOCKINTERACT_DIRECTION + "active";
|
||||
public static final String BLOCKINTERACT_DIRECTION_ACTIONS = BLOCKINTERACT_DIRECTION + "actions";
|
||||
|
||||
private static final String BLOCKINTERACT_FASTINTERACT = BLOCKINTERACT + "fastinteract.";
|
||||
public static final String BLOCKINTERACT_FASTINTERACT_CHECK = BLOCKINTERACT_FASTINTERACT + "active";
|
||||
public static final String BLOCKINTERACT_FASTINTERACT_INTERVAL = BLOCKINTERACT_FASTINTERACT + "interval";
|
||||
public static final String BLOCKINTERACT_FASTINTERACT_ACTIONS = BLOCKINTERACT_FASTINTERACT + "actions";
|
||||
|
||||
private static final String BLOCKINTERACT_NOSWING = BLOCKINTERACT + "noswing.";
|
||||
public static final String BLOCKINTERACT_NOSWING_CHECK = BLOCKINTERACT_NOSWING + "active";
|
||||
public static final String BLOCKINTERACT_NOSWING_ACTIONS = BLOCKINTERACT_NOSWING + "actions";
|
||||
|
||||
private static final String BLOCKINTERACT_REACH = BLOCKINTERACT + "reach.";
|
||||
public static final String BLOCKINTERACT_REACH_CHECK = BLOCKINTERACT_REACH + "active";
|
||||
public static final String BLOCKINTERACT_REACH_ACTIONS = BLOCKINTERACT_REACH + "actions";
|
||||
|
||||
/*
|
||||
* 888 88b, 888 888 888 88e 888
|
||||
* 888 88P' 888 e88 88e e88'888 888 ee 888 888D 888 ,"Y88b e88'888 ,e e,
|
||||
|
@ -62,7 +62,7 @@ public class DefaultConfig extends ConfigFile {
|
||||
set(ConfPaths.BLOCKBREAK_FASTBREAK_CHECK, true);
|
||||
set(ConfPaths.BLOCKBREAK_FASTBREAK_EXPERIMENTAL, true);
|
||||
set(ConfPaths.BLOCKBREAK_FASTBREAK_INTERVAL, 100);
|
||||
set(ConfPaths.BLOCKBREAK_FASTBREAK_ACTIONS, "cancel vl>100 log:fastbreak:3:5:cif cancel");
|
||||
set(ConfPaths.BLOCKBREAK_FASTBREAK_ACTIONS, "cancel vl>100 log:fastinteract:3:5:cif cancel");
|
||||
|
||||
set(ConfPaths.BLOCKBREAK_NOSWING_CHECK, true);
|
||||
set(ConfPaths.BLOCKBREAK_NOSWING_ACTIONS, "log:noswing:3:2:if cancel");
|
||||
@ -70,6 +70,26 @@ public class DefaultConfig extends ConfigFile {
|
||||
set(ConfPaths.BLOCKBREAK_REACH_CHECK, true);
|
||||
set(ConfPaths.BLOCKBREAK_REACH_ACTIONS, "cancel vl>5 log:breach:0:2:if cancel");
|
||||
|
||||
/*
|
||||
* 888 88b, 888 888 888 d8 d8
|
||||
* 888 88P' 888 e88 88e e88'888 888 ee 888 888 8e d88 ,e e, 888,8, ,"Y88b e88'888 d88
|
||||
* 888 8K 888 d888 888b d888 '8 888 P 888 888 88b d88888 d88 88b 888 " "8" 888 d888 '8 d88888
|
||||
* 888 88b, 888 Y888 888P Y888 , 888 b 888 888 888 888 888 , 888 ,ee 888 Y888 , 888
|
||||
* 888 88P' 888 "88 88" "88,e8' 888 8b 888 888 888 888 "YeeP" 888 "88 888 "88,e8' 888
|
||||
*/
|
||||
set(ConfPaths.BLOCKINTERACT_DIRECTION_CHECK, true);
|
||||
set(ConfPaths.BLOCKINTERACT_DIRECTION_ACTIONS, "cancel vl>10 log:bdirection:0:3:if cancel");
|
||||
|
||||
set(ConfPaths.BLOCKINTERACT_FASTINTERACT_CHECK, true);
|
||||
set(ConfPaths.BLOCKINTERACT_FASTINTERACT_INTERVAL, 95L);
|
||||
set(ConfPaths.BLOCKINTERACT_FASTINTERACT_ACTIONS, "cancel vl>100 log:fastplace:3:5:cif cancel");
|
||||
|
||||
set(ConfPaths.BLOCKINTERACT_NOSWING_CHECK, true);
|
||||
set(ConfPaths.BLOCKINTERACT_NOSWING_ACTIONS, "log:noswing:3:2:if cancel");
|
||||
|
||||
set(ConfPaths.BLOCKINTERACT_REACH_CHECK, true);
|
||||
set(ConfPaths.BLOCKINTERACT_REACH_ACTIONS, "cancel vl>5 log:breach:0:2:if cancel");
|
||||
|
||||
/*
|
||||
* 888 88b, 888 888 888 88e 888
|
||||
* 888 88P' 888 e88 88e e88'888 888 ee 888 888D 888 ,"Y88b e88'888 ,e e,
|
||||
@ -299,6 +319,7 @@ public class DefaultConfig extends ConfigFile {
|
||||
set(ConfPaths.STRINGS + ".critical", start + "tried to do a critical hit but wasn't technically jumping" + end);
|
||||
set(ConfPaths.STRINGS + ".drop", start + "tried to drop more items than allowed" + end);
|
||||
set(ConfPaths.STRINGS + ".fastbreak", start + "tried to break too much blocks" + end);
|
||||
set(ConfPaths.STRINGS + ".fastinteract", start + "tried to interact with too much blocks" + end);
|
||||
set(ConfPaths.STRINGS + ".fastplace", start + "tried to place too much blocks" + end);
|
||||
set(ConfPaths.STRINGS + ".fdirection", start + "tried to hit an entity out of line of sight" + end);
|
||||
set(ConfPaths.STRINGS + ".flyshort", start + "tried to move unexpectedly" + end);
|
||||
|
@ -13,7 +13,7 @@ package fr.neatmonster.nocheatplus.players;
|
||||
* The various permission nodes used by NoCheatPlus.
|
||||
*/
|
||||
public class Permissions {
|
||||
private static final String NOCHEATPLUS = "nocheatplus";
|
||||
private static final String NOCHEATPLUS = "nocheatplus";
|
||||
|
||||
/*
|
||||
* e Y8b 888 ,e, ,e, d8 d8 ,e,
|
||||
@ -22,10 +22,10 @@ public class Permissions {
|
||||
* d888888888b Y888 888 888 888 888 888 888 888 888 Y88D 888 888 ,ee 888 888 888 Y888 888P 888 888
|
||||
* d8888888b Y8b "88 888 888 888 888 888 888 888 888 d,dP 888 888 "88 888 888 888 "88 88" 888 888
|
||||
*/
|
||||
private static final String ADMINISTRATION = NOCHEATPLUS + ".admin";
|
||||
public static final String ADMINISTRATION_NOTIFY = ADMINISTRATION + ".notify";
|
||||
public static final String ADMINISTRATION_PLUGINS = ADMINISTRATION + ".plugins";
|
||||
public static final String ADMINISTRATION_RELOAD = ADMINISTRATION + ".reload";
|
||||
private static final String ADMINISTRATION = NOCHEATPLUS + ".admin";
|
||||
public static final String ADMINISTRATION_NOTIFY = ADMINISTRATION + ".notify";
|
||||
public static final String ADMINISTRATION_PLUGINS = ADMINISTRATION + ".plugins";
|
||||
public static final String ADMINISTRATION_RELOAD = ADMINISTRATION + ".reload";
|
||||
|
||||
/*
|
||||
* e e 888 ,e, dP,e, ,e, d8 ,e,
|
||||
@ -34,36 +34,36 @@ public class Permissions {
|
||||
* d8b Y8b Y8b Y888 888P Y888 888 888 888 888 Y888 , ,ee 888 888 888 Y888 888P 888 888 Y88D
|
||||
* d888b Y8b Y8b "88 88" "88 888 888 888 888 "88,e8' "88 888 888 888 "88 88" 888 888 d,dP
|
||||
*/
|
||||
private static final String MODS = NOCHEATPLUS + ".mods";
|
||||
private static final String MODS = NOCHEATPLUS + ".mods";
|
||||
|
||||
private static final String CJB = MODS + ".cjb";
|
||||
public static final String CJB_FLY = CJB + ".fly";
|
||||
public static final String CJB_XRAY = CJB + ".xray";
|
||||
public static final String CJB_RADAR = CJB + ".radar";
|
||||
private static final String CJB = MODS + ".cjb";
|
||||
public static final String CJB_FLY = CJB + ".fly";
|
||||
public static final String CJB_XRAY = CJB + ".xray";
|
||||
public static final String CJB_RADAR = CJB + ".radar";
|
||||
|
||||
private static final String MINECRAFTAUTOMAP = MODS + ".minecraftautomap";
|
||||
public static final String MINECRAFTAUTOMAP_ORES = MINECRAFTAUTOMAP + ".ores";
|
||||
public static final String MINECRAFTAUTOMAP_CAVE = MINECRAFTAUTOMAP + ".cave";
|
||||
public static final String MINECRAFTAUTOMAP_RADAR = MINECRAFTAUTOMAP + ".radar";
|
||||
private static final String MINECRAFTAUTOMAP = MODS + ".minecraftautomap";
|
||||
public static final String MINECRAFTAUTOMAP_ORES = MINECRAFTAUTOMAP + ".ores";
|
||||
public static final String MINECRAFTAUTOMAP_CAVE = MINECRAFTAUTOMAP + ".cave";
|
||||
public static final String MINECRAFTAUTOMAP_RADAR = MINECRAFTAUTOMAP + ".radar";
|
||||
|
||||
private static final String REI = MODS + ".rei";
|
||||
public static final String REI_CAVE = REI + ".cave";
|
||||
public static final String REI_RADAR = REI + ".radar";
|
||||
private static final String REI = MODS + ".rei";
|
||||
public static final String REI_CAVE = REI + ".cave";
|
||||
public static final String REI_RADAR = REI + ".radar";
|
||||
|
||||
private static final String SMARTMOVING = MODS + ".smartmoving";
|
||||
public static final String SMARTMOVING_CLIMBING = SMARTMOVING + ".climbing";
|
||||
public static final String SMARTMOVING_SWIMMING = SMARTMOVING + ".swimming";
|
||||
public static final String SMARTMOVING_CRAWLING = SMARTMOVING + ".crawling";
|
||||
public static final String SMARTMOVING_SLIDING = SMARTMOVING + ".sliding";
|
||||
public static final String SMARTMOVING_JUMPING = SMARTMOVING + ".jumping";
|
||||
public static final String SMARTMOVING_FLYING = SMARTMOVING + ".flying";
|
||||
private static final String SMARTMOVING = MODS + ".smartmoving";
|
||||
public static final String SMARTMOVING_CLIMBING = SMARTMOVING + ".climbing";
|
||||
public static final String SMARTMOVING_SWIMMING = SMARTMOVING + ".swimming";
|
||||
public static final String SMARTMOVING_CRAWLING = SMARTMOVING + ".crawling";
|
||||
public static final String SMARTMOVING_SLIDING = SMARTMOVING + ".sliding";
|
||||
public static final String SMARTMOVING_JUMPING = SMARTMOVING + ".jumping";
|
||||
public static final String SMARTMOVING_FLYING = SMARTMOVING + ".flying";
|
||||
|
||||
private static final String ZOMBE = MODS + ".zombe";
|
||||
public static final String ZOMBE_FLY = ZOMBE + ".fly";
|
||||
public static final String ZOMBE_NOCLIP = ZOMBE + ".noclip";
|
||||
public static final String ZOMBE_CHEAT = ZOMBE + ".cheat";
|
||||
private static final String ZOMBE = MODS + ".zombe";
|
||||
public static final String ZOMBE_FLY = ZOMBE + ".fly";
|
||||
public static final String ZOMBE_NOCLIP = ZOMBE + ".noclip";
|
||||
public static final String ZOMBE_CHEAT = ZOMBE + ".cheat";
|
||||
|
||||
private static final String CHECKS = NOCHEATPLUS + ".checks";
|
||||
private static final String CHECKS = NOCHEATPLUS + ".checks";
|
||||
|
||||
/*
|
||||
* 888 88b, 888 888 888 88b, 888
|
||||
@ -72,11 +72,24 @@ public class Permissions {
|
||||
* 888 88b, 888 Y888 888P Y888 , 888 b 888 88b, 888 888 , ,ee 888 888 b
|
||||
* 888 88P' 888 "88 88" "88,e8' 888 8b 888 88P' 888 "YeeP" "88 888 888 8b
|
||||
*/
|
||||
private static final String BLOCKBREAK = CHECKS + ".blockbreak";
|
||||
public static final String BLOCKBREAK_DIRECTION = BLOCKBREAK + ".direction";
|
||||
public static final String BLOCKBREAK_FASTBREAK = BLOCKBREAK + ".fastbreak";
|
||||
public static final String BLOCKBREAK_NOSWING = BLOCKBREAK + ".noswing";
|
||||
public static final String BLOCKBREAK_REACH = BLOCKBREAK + ".reach";
|
||||
private static final String BLOCKBREAK = CHECKS + ".blockbreak";
|
||||
public static final String BLOCKBREAK_DIRECTION = BLOCKBREAK + ".direction";
|
||||
public static final String BLOCKBREAK_FASTBREAK = BLOCKBREAK + ".fastbreak";
|
||||
public static final String BLOCKBREAK_NOSWING = BLOCKBREAK + ".noswing";
|
||||
public static final String BLOCKBREAK_REACH = BLOCKBREAK + ".reach";
|
||||
|
||||
/*
|
||||
* 888 88b, 888 888 888 d8 d8
|
||||
* 888 88P' 888 e88 88e e88'888 888 ee 888 888 8e d88 ,e e, 888,8, ,"Y88b e88'888 d88
|
||||
* 888 8K 888 d888 888b d888 '8 888 P 888 888 88b d88888 d88 88b 888 " "8" 888 d888 '8 d88888
|
||||
* 888 88b, 888 Y888 888P Y888 , 888 b 888 888 888 888 888 , 888 ,ee 888 Y888 , 888
|
||||
* 888 88P' 888 "88 88" "88,e8' 888 8b 888 888 888 888 "YeeP" 888 "88 888 "88,e8' 888
|
||||
*/
|
||||
private static final String BLOCKINTERACT = CHECKS + ".blockinteract";
|
||||
public static final String BLOCKINTERACT_DIRECTION = BLOCKINTERACT + ".direction";
|
||||
public static final String BLOCKINTERACT_FASTINTERACT = BLOCKINTERACT + ".fastinteract";
|
||||
public static final String BLOCKINTERACT_NOSWING = BLOCKINTERACT + ".noswing";
|
||||
public static final String BLOCKINTERACT_REACH = BLOCKINTERACT + ".reach";
|
||||
|
||||
/*
|
||||
* 888 88b, 888 888 888 88e 888
|
||||
@ -85,12 +98,12 @@ public class Permissions {
|
||||
* 888 88b, 888 Y888 888P Y888 , 888 b 888 888 ,ee 888 Y888 , 888 ,
|
||||
* 888 88P' 888 "88 88" "88,e8' 888 8b 888 888 "88 888 "88,e8' "YeeP"
|
||||
*/
|
||||
private static final String BLOCKPLACE = CHECKS + ".blockplace";
|
||||
public static final String BLOCKPLACE_DIRECTION = BLOCKPLACE + ".direction";
|
||||
public static final String BLOCKPLACE_FASTPLACE = BLOCKPLACE + ".fastplace";
|
||||
public static final String BLOCKPLACE_NOSWING = BLOCKPLACE + ".noswing";
|
||||
public static final String BLOCKPLACE_REACH = BLOCKPLACE + ".reach";
|
||||
public static final String BLOCKPLACE_SPEED = BLOCKPLACE + ".speed";
|
||||
private static final String BLOCKPLACE = CHECKS + ".blockplace";
|
||||
public static final String BLOCKPLACE_DIRECTION = BLOCKPLACE + ".direction";
|
||||
public static final String BLOCKPLACE_FASTPLACE = BLOCKPLACE + ".fastplace";
|
||||
public static final String BLOCKPLACE_NOSWING = BLOCKPLACE + ".noswing";
|
||||
public static final String BLOCKPLACE_REACH = BLOCKPLACE + ".reach";
|
||||
public static final String BLOCKPLACE_SPEED = BLOCKPLACE + ".speed";
|
||||
|
||||
/*
|
||||
* e88'Y88 888 d8
|
||||
@ -99,10 +112,10 @@ public class Permissions {
|
||||
* Y888 ,d 888 888 ,ee 888 888
|
||||
* "88,d88 888 888 "88 888 888
|
||||
*/
|
||||
private static final String CHAT = CHECKS + ".chat";
|
||||
public static final String CHAT_ARRIVALS = CHAT + ".arrivals";
|
||||
public static final String CHAT_COLOR = CHAT + ".color";
|
||||
public static final String CHAT_NOPWNAGE = CHAT + ".nopwnage";
|
||||
private static final String CHAT = CHECKS + ".chat";
|
||||
public static final String CHAT_ARRIVALS = CHAT + ".arrivals";
|
||||
public static final String CHAT_COLOR = CHAT + ".color";
|
||||
public static final String CHAT_NOPWNAGE = CHAT + ".nopwnage";
|
||||
|
||||
/*
|
||||
* 888'Y88 ,e, 888 d8
|
||||
@ -113,16 +126,16 @@ public class Permissions {
|
||||
* , 88P
|
||||
* "8",P"
|
||||
*/
|
||||
private static final String FIGHT = CHECKS + ".fight";
|
||||
public static final String FIGHT_ANGLE = FIGHT + ".angle";
|
||||
public static final String FIGHT_CRITICAL = FIGHT + ".critical";
|
||||
public static final String FIGHT_DIRECTION = FIGHT + ".direction";
|
||||
public static final String FIGHT_GODMODE = FIGHT + ".godmode";
|
||||
public static final String FIGHT_INSTANTHEAL = FIGHT + ".instantheal";
|
||||
public static final String FIGHT_KNOCKBACK = FIGHT + ".knockback";
|
||||
public static final String FIGHT_NOSWING = FIGHT + ".noswing";
|
||||
public static final String FIGHT_REACH = FIGHT + ".reach";
|
||||
public static final String FIGHT_SPEED = FIGHT + ".speed";
|
||||
private static final String FIGHT = CHECKS + ".fight";
|
||||
public static final String FIGHT_ANGLE = FIGHT + ".angle";
|
||||
public static final String FIGHT_CRITICAL = FIGHT + ".critical";
|
||||
public static final String FIGHT_DIRECTION = FIGHT + ".direction";
|
||||
public static final String FIGHT_GODMODE = FIGHT + ".godmode";
|
||||
public static final String FIGHT_INSTANTHEAL = FIGHT + ".instantheal";
|
||||
public static final String FIGHT_KNOCKBACK = FIGHT + ".knockback";
|
||||
public static final String FIGHT_NOSWING = FIGHT + ".noswing";
|
||||
public static final String FIGHT_REACH = FIGHT + ".reach";
|
||||
public static final String FIGHT_SPEED = FIGHT + ".speed";
|
||||
|
||||
/*
|
||||
* 888 d8
|
||||
@ -133,10 +146,10 @@ public class Permissions {
|
||||
* 888
|
||||
* 888
|
||||
*/
|
||||
private static final String INVENTORY = CHECKS + ".inventory";
|
||||
public static final String INVENTORY_DROP = INVENTORY + ".drop";
|
||||
public static final String INVENTORY_INSTANTBOW = INVENTORY + ".instantbow";
|
||||
public static final String INVENTORY_INSTANTEAT = INVENTORY + ".instanteat";
|
||||
private static final String INVENTORY = CHECKS + ".inventory";
|
||||
public static final String INVENTORY_DROP = INVENTORY + ".drop";
|
||||
public static final String INVENTORY_INSTANTBOW = INVENTORY + ".instantbow";
|
||||
public static final String INVENTORY_INSTANTEAT = INVENTORY + ".instanteat";
|
||||
|
||||
/*
|
||||
* e e ,e,
|
||||
@ -147,11 +160,11 @@ public class Permissions {
|
||||
* , 88P
|
||||
* "8",P"
|
||||
*/
|
||||
private static final String MOVING = CHECKS + ".moving";
|
||||
public static final String MOVING_BOATSANYWHERE = MOVING + ".boatsanywhere";
|
||||
public static final String MOVING_CREATIVEFLY = MOVING + ".creativefly";
|
||||
public static final String MOVING_MOREPACKETS = MOVING + ".morepackets";
|
||||
public static final String MOVING_MOREPACKETSVEHICLE = MOVING + ".morepacketsvehicle";
|
||||
public static final String MOVING_NOFALL = MOVING + ".nofall";
|
||||
public static final String MOVING_SURVIVALFLY = MOVING + ".survivalfly";
|
||||
private static final String MOVING = CHECKS + ".moving";
|
||||
public static final String MOVING_BOATSANYWHERE = MOVING + ".boatsanywhere";
|
||||
public static final String MOVING_CREATIVEFLY = MOVING + ".creativefly";
|
||||
public static final String MOVING_MOREPACKETS = MOVING + ".morepackets";
|
||||
public static final String MOVING_MOREPACKETSVEHICLE = MOVING + ".morepacketsvehicle";
|
||||
public static final String MOVING_NOFALL = MOVING + ".nofall";
|
||||
public static final String MOVING_SURVIVALFLY = MOVING + ".survivalfly";
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user