mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2025-03-10 13:39:23 +01:00
[BLEEDING] Add AutoSign check (first sketch).
This commit is contained in:
parent
f4b88b3309
commit
3b4352c044
@ -57,6 +57,7 @@ public enum CheckType {
|
||||
|
||||
BLOCKPLACE(BlockPlaceConfig.factory, BlockPlaceData.factory, Permissions.BLOCKPLACE),
|
||||
BLOCKPLACE_AGAINST(BLOCKPLACE, Permissions.BLOCKPLACE_AGAINST),
|
||||
BLOCKPLACE_AUTOSIGN(BLOCKPLACE, Permissions.BLOCKPLACE_AUTOSIGN),
|
||||
BLOCKPLACE_DIRECTION(BLOCKPLACE, Permissions.BLOCKPLACE_DIRECTION),
|
||||
BLOCKPLACE_FASTPLACE(BLOCKPLACE, Permissions.BLOCKPLACE_FASTPLACE),
|
||||
BLOCKPLACE_NOSWING(BLOCKPLACE, Permissions.BLOCKPLACE_NOSWING),
|
||||
|
@ -0,0 +1,110 @@
|
||||
package fr.neatmonster.nocheatplus.checks.blockplace;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.neatmonster.nocheatplus.actions.ParameterName;
|
||||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.ViolationData;
|
||||
import fr.neatmonster.nocheatplus.utilities.StringUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.TickTask;
|
||||
|
||||
public class AutoSign extends Check {
|
||||
|
||||
/** Reference time that is needed to edit the most complicated sign :). */
|
||||
private static long maxEditTime = 1500;
|
||||
/** Fastest time "possible" estimate for an empty sign. */
|
||||
private static long minEditTime = 150;
|
||||
/** Minimum time needed to add one extra line (not the first). */
|
||||
private static long minLineTime = 50;
|
||||
/** Minimum time needed to type a character. */
|
||||
private static long minCharTime = 50;
|
||||
|
||||
private final List<String> tags = new ArrayList<String>();
|
||||
|
||||
final Set<Character> chars = new HashSet<Character>(15 * 4);
|
||||
|
||||
public AutoSign() {
|
||||
super(CheckType.BLOCKPLACE_AUTOSIGN);
|
||||
}
|
||||
|
||||
public boolean check(final Player player, final Block block, final String[] lines) {
|
||||
// TODO: Might want to reset time + hash ?
|
||||
final long time = System.currentTimeMillis();
|
||||
tags.clear();
|
||||
final BlockPlaceData data = BlockPlaceData.getData(player);
|
||||
Material mat = block.getType();
|
||||
if (mat == Material.WALL_SIGN){
|
||||
// Use one thing for signs.
|
||||
mat = Material.SIGN_POST;
|
||||
}
|
||||
if (data.autoSignPlacedHash != BlockPlaceListener.getBlockPlaceHash(block, mat)){
|
||||
tags.add("block_mismatch");
|
||||
return handleViolation(player, maxEditTime, data);
|
||||
}
|
||||
if (time < data.autoSignPlacedTime){
|
||||
data.autoSignPlacedTime = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// check time, mind lag.
|
||||
|
||||
final long editTime = time - data.autoSignPlacedTime;
|
||||
long expected = getExpectedEditTime(lines);
|
||||
expected = (long) (expected / TickTask.getLag(expected));
|
||||
|
||||
if (expected > editTime){
|
||||
tags.add("edit_time");
|
||||
return handleViolation(player, expected - editTime, data);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private long getExpectedEditTime(final String[] lines) {
|
||||
long expected = minEditTime;
|
||||
int n = 0;
|
||||
for (String line : lines){
|
||||
if (line != null){
|
||||
line = line.trim().toLowerCase();
|
||||
if (!line.isEmpty()){
|
||||
chars.clear();
|
||||
n += 1;
|
||||
for (final char c : line.toCharArray()){
|
||||
chars.add(c);
|
||||
}
|
||||
expected += minCharTime * chars.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (n > 1){
|
||||
expected += minLineTime * n;
|
||||
}
|
||||
return expected;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param player
|
||||
* @param violationTime Amount of too fast editing.
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
private boolean handleViolation(final Player player, final long violationTime, final BlockPlaceData data) {
|
||||
final double addedVL = 10.0 * Math.min(maxEditTime, violationTime) / maxEditTime;
|
||||
data.autoSignVL += addedVL;
|
||||
final ViolationData vd = new ViolationData(this, player, data.autoSignVL, addedVL, BlockPlaceConfig.getConfig(player).autoSignActions);
|
||||
if (vd.needsParameters()){
|
||||
vd.setParameter(ParameterName.TAGS, StringUtil.join(tags, "+"));
|
||||
}
|
||||
return executeActions(vd);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -70,6 +70,9 @@ public class BlockPlaceConfig extends ACheckConfig {
|
||||
new BlockPlaceConfig(ConfigManager.getConfigFile(player.getWorld().getName())));
|
||||
return worldsMap.get(player.getWorld().getName());
|
||||
}
|
||||
|
||||
public final boolean autoSignCheck;
|
||||
public final ActionList autoSignActions;
|
||||
|
||||
public final boolean directionCheck;
|
||||
public final ActionList directionActions;
|
||||
@ -98,6 +101,11 @@ public class BlockPlaceConfig extends ACheckConfig {
|
||||
*/
|
||||
public BlockPlaceConfig(final ConfigFile data) {
|
||||
super(data, ConfPaths.BLOCKPLACE);
|
||||
|
||||
autoSignCheck = data.getBoolean(ConfPaths.BLOCKPLACE_AUTOSIGN_CHECK);
|
||||
autoSignActions = data.getOptimizedActionList(ConfPaths.BLOCKPLACE_AUTOSIGN_ACTIONS, Permissions.BLOCKPLACE_AUTOSIGN);
|
||||
|
||||
|
||||
directionCheck = data.getBoolean(ConfPaths.BLOCKPLACE_DIRECTION_CHECK);
|
||||
directionActions = data.getOptimizedActionList(ConfPaths.BLOCKPLACE_DIRECTION_ACTIONS, Permissions.BLOCKPLACE_DIRECTION);
|
||||
|
||||
@ -136,6 +144,8 @@ public class BlockPlaceConfig extends ACheckConfig {
|
||||
return speedCheck;
|
||||
case BLOCKPLACE_AGAINST:
|
||||
return true;
|
||||
case BLOCKPLACE_AUTOSIGN:
|
||||
return autoSignCheck;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
@ -75,12 +75,17 @@ public class BlockPlaceData extends ACheckData {
|
||||
}
|
||||
|
||||
// Violation levels.
|
||||
public double directionVL;
|
||||
public double fastPlaceVL;
|
||||
public double noSwingVL;
|
||||
public double reachVL;
|
||||
public double speedVL;
|
||||
|
||||
public double autoSignVL = 0;
|
||||
public double directionVL = 0;
|
||||
public double fastPlaceVL = 0;
|
||||
public double noSwingVL = 0;
|
||||
public double reachVL = 0;
|
||||
public double speedVL = 0;
|
||||
|
||||
// AutoSign.
|
||||
public long autoSignPlacedTime = 0;
|
||||
public long autoSignPlacedHash = 0;
|
||||
|
||||
// Data of the fast place check.
|
||||
public final ActionFrequency fastPlaceBuckets = new ActionFrequency(2, 1000);
|
||||
public int fastPlaceShortTermTick = 0;
|
||||
|
@ -9,6 +9,7 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.block.SignChangeEvent;
|
||||
import org.bukkit.event.entity.ProjectileLaunchEvent;
|
||||
import org.bukkit.event.player.PlayerAnimationEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
@ -45,6 +46,30 @@ import fr.neatmonster.nocheatplus.utilities.BlockProperties;
|
||||
* @see BlockPlaceEvent
|
||||
*/
|
||||
public class BlockPlaceListener extends CheckListener {
|
||||
|
||||
private static final int p1 = 73856093;
|
||||
private static final int p2 = 19349663;
|
||||
private static final int p3 = 83492791;
|
||||
|
||||
private static final int getHash(final int x, final int y, final int z) {
|
||||
return p1 * x ^ p2 * y ^ p3 * z;
|
||||
}
|
||||
|
||||
public static int getCoordHash(final Block block){
|
||||
return getHash(block.getX(), block.getY(), block.getZ());
|
||||
}
|
||||
|
||||
public static int getBlockPlaceHash(final Block block, final Material mat){
|
||||
int hash = getCoordHash(block);
|
||||
if (mat != null){
|
||||
hash |= mat.name().hashCode();
|
||||
}
|
||||
hash |= block.getWorld().getName().hashCode();
|
||||
return hash;
|
||||
}
|
||||
|
||||
/** AutoSign. */
|
||||
private final AutoSign autoSign = addCheck(new AutoSign());
|
||||
|
||||
/** The direction check. */
|
||||
private final Direction direction = addCheck(new Direction());
|
||||
@ -103,6 +128,14 @@ public class BlockPlaceListener extends CheckListener {
|
||||
else if (againstId == Material.AIR.getId()){
|
||||
if (!player.hasPermission(Permissions.BLOCKPLACE_AGAINST_AIR) && !NCPExemptionManager.isExempted(player, CheckType.BLOCKPLACE_AGAINST)) cancelled = true;
|
||||
}
|
||||
|
||||
final BlockPlaceData data = BlockPlaceData.getData(player);
|
||||
|
||||
if (mat == Material.SIGN_POST || mat == Material.WALL_SIGN){
|
||||
data.autoSignPlacedTime = System.currentTimeMillis();
|
||||
// Always hash as sign post for improved compatibility with Lockette etc.
|
||||
data.autoSignPlacedHash = getBlockPlaceHash(block, Material.SIGN_POST);
|
||||
}
|
||||
|
||||
// First, the fast place check.
|
||||
if (fastPlace.isEnabled(player)){
|
||||
@ -116,21 +149,40 @@ public class BlockPlaceListener extends CheckListener {
|
||||
|
||||
// Second, the no swing check (player doesn't swing his arm when placing a lily pad).
|
||||
if (!cancelled && mat != Material.WATER_LILY && noSwing.isEnabled(player)
|
||||
&& noSwing.check(player))
|
||||
&& noSwing.check(player, data))
|
||||
cancelled = true;
|
||||
|
||||
// Third, the reach check.
|
||||
if (!cancelled && reach.isEnabled(player) && reach.check(player, block))
|
||||
if (!cancelled && reach.isEnabled(player) && reach.check(player, block, data))
|
||||
cancelled = true;
|
||||
|
||||
// Fourth, the direction check.
|
||||
if (!cancelled && direction.isEnabled(player) && direction.check(player, block, blockAgainst))
|
||||
if (!cancelled && direction.isEnabled(player) && direction.check(player, block, blockAgainst, data))
|
||||
cancelled = true;
|
||||
|
||||
// If one of the checks requested to cancel the event, do so.
|
||||
if (cancelled)
|
||||
event.setCancelled(cancelled);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
public void onSignChange(final SignChangeEvent event){
|
||||
if (event.getClass() != SignChangeEvent.class){
|
||||
// Built in plugin compatibility.
|
||||
// TODO: Don't understand why two consecutive events editing the same block are a problem.
|
||||
return;
|
||||
}
|
||||
final Player player = event.getPlayer();
|
||||
final Block block = event.getBlock();
|
||||
final String[] lines = event.getLines();
|
||||
if (block == null || lines == null || player == null){
|
||||
// Somewhat defensive.
|
||||
return;
|
||||
}
|
||||
if (autoSign.isEnabled(player) && autoSign.check(player, block, lines)){
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We listen to PlayerAnimation events because it is (currently) equivalent to "player swings arm" and we want to
|
||||
|
@ -35,12 +35,12 @@ public class Direction extends Check {
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
* @param data
|
||||
* @param location
|
||||
* the location
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean check(final Player player, final Block placed, final Block against) {
|
||||
final BlockPlaceData data = BlockPlaceData.getData(player);
|
||||
public boolean check(final Player player, final Block placed, final Block against, final BlockPlaceData data) {
|
||||
|
||||
boolean cancel = false;
|
||||
|
||||
|
@ -32,10 +32,10 @@ public class NoSwing extends Check {
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
* @param data
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean check(final Player player) {
|
||||
final BlockPlaceData data = BlockPlaceData.getData(player);
|
||||
public boolean check(final Player player, final BlockPlaceData data) {
|
||||
|
||||
boolean cancel = false;
|
||||
|
||||
|
@ -44,12 +44,12 @@ public class Reach extends Check {
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
* @param data2
|
||||
* @param location
|
||||
* the location
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean check(final Player player, final Block block) {
|
||||
final BlockPlaceData data = BlockPlaceData.getData(player);
|
||||
public boolean check(final Player player, final Block block, final BlockPlaceData data) {
|
||||
|
||||
boolean cancel = false;
|
||||
|
||||
|
@ -177,6 +177,10 @@ public abstract class ConfPaths {
|
||||
* 888 88P' 888 "88 88" "88,e8' 888 8b 888 888 "88 888 "88,e8' "YeeP"
|
||||
*/
|
||||
public static final String BLOCKPLACE = CHECKS + "blockplace.";
|
||||
|
||||
private static final String BLOCKPLACE_AUTOSIGN = BLOCKPLACE + "autosign.";
|
||||
public static final String BLOCKPLACE_AUTOSIGN_CHECK = BLOCKPLACE_AUTOSIGN + "active";
|
||||
public static final String BLOCKPLACE_AUTOSIGN_ACTIONS = BLOCKPLACE_AUTOSIGN + "actions";
|
||||
|
||||
private static final String BLOCKPLACE_DIRECTION = BLOCKPLACE + "direction.";
|
||||
public static final String BLOCKPLACE_DIRECTION_CHECK = BLOCKPLACE_DIRECTION + "active";
|
||||
|
@ -148,6 +148,10 @@ public class DefaultConfig extends ConfigFile {
|
||||
* 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"
|
||||
*/
|
||||
|
||||
set(ConfPaths.BLOCKPLACE_AUTOSIGN_CHECK, true);
|
||||
set(ConfPaths.BLOCKPLACE_AUTOSIGN_ACTIONS, "cancel vl>10 log:bautosign:0:3:if cancel");
|
||||
|
||||
set(ConfPaths.BLOCKPLACE_DIRECTION_CHECK, true);
|
||||
set(ConfPaths.BLOCKPLACE_DIRECTION_ACTIONS, "cancel vl>10 log:bdirection:0:3:if cancel");
|
||||
|
||||
@ -458,6 +462,7 @@ public class DefaultConfig extends ConfigFile {
|
||||
set(ConfPaths.STRINGS + ".angle", start + "tried to hit multiple entities at the same time" + end);
|
||||
set(ConfPaths.STRINGS + ".ban", "ban [player]");
|
||||
set(ConfPaths.STRINGS + ".ban-ip", "ban-ip [ip]");
|
||||
set(ConfPaths.STRINGS + ".bautosign", start + "failed autosign with [tags]" + end);
|
||||
set(ConfPaths.STRINGS + ".bbfrequency", start + "tried to break too many blocks within time frame" + end);
|
||||
set(ConfPaths.STRINGS + ".bdirection", start + "tried to interact with a block out of his line of sight" + end);
|
||||
set(ConfPaths.STRINGS + ".bedleave", start + "sends bed leave packets (was not in bed)" + end);
|
||||
|
@ -95,6 +95,7 @@ public class Permissions {
|
||||
*/
|
||||
public static final String BLOCKPLACE = CHECKS + ".blockplace";
|
||||
public static final String BLOCKPLACE_AGAINST = BLOCKPLACE + ".against";
|
||||
public static final String BLOCKPLACE_AUTOSIGN = BLOCKPLACE + ".autosign";
|
||||
public static final String BLOCKPLACE_AGAINST_AIR = BLOCKPLACE_AGAINST + ".air";
|
||||
public static final String BLOCKPLACE_AGAINST_LIQUIDS = BLOCKPLACE_AGAINST + ".liquids";
|
||||
public static final String BLOCKPLACE_BOATSANYWHERE = BLOCKPLACE + ".boatsanywhere";
|
||||
|
Loading…
Reference in New Issue
Block a user