mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2025-01-31 20:01:25 +01:00
+ Patched the disconnect nofall exploit
+ Commands are now hidden (from players) = Fixed the SpamJoin check (2 issues) = Fixed the issue with plugins lists = Fixed the Tracker check's issue with AuthMe = Fixed an issue with boats and moving water
This commit is contained in:
parent
9aa5536fe4
commit
27c79ac30c
@ -3,6 +3,7 @@ version: ${project.version}
|
|||||||
description: ${project.description}
|
description: ${project.description}
|
||||||
|
|
||||||
author: NeatMonster
|
author: NeatMonster
|
||||||
|
authors: [Eventprime, Juliui]
|
||||||
website: ${project.url}
|
website: ${project.url}
|
||||||
|
|
||||||
main: me.neatmonster.nocheatplus.NoCheatPlus
|
main: me.neatmonster.nocheatplus.NoCheatPlus
|
||||||
@ -10,7 +11,7 @@ main: me.neatmonster.nocheatplus.NoCheatPlus
|
|||||||
commands:
|
commands:
|
||||||
nocheatplus:
|
nocheatplus:
|
||||||
description: NoCheatPlus command(s)
|
description: NoCheatPlus command(s)
|
||||||
permission: nocheatplus.admin.commands
|
# permission: nocheatplus.admin.commands
|
||||||
usage: |
|
usage: |
|
||||||
/<command> permlist player [permission]: list NoCheatPlus' permissions of player, optionally only if beginning with [permission]
|
/<command> permlist player [permission]: list NoCheatPlus' permissions of player, optionally only if beginning with [permission]
|
||||||
/<command> playerinfo player: show the collected data NoCheatPlus collected about a player
|
/<command> playerinfo player: show the collected data NoCheatPlus collected about a player
|
||||||
|
2
pom.xml
2
pom.xml
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<!-- Informations -->
|
<!-- Informations -->
|
||||||
<name>NoCheatPlus</name>
|
<name>NoCheatPlus</name>
|
||||||
<version>3.5.5_3</version>
|
<version>3.5.5_4</version>
|
||||||
<description>Detect and fight the exploitation of various flaws/bugs in Minecraft.</description>
|
<description>Detect and fight the exploitation of various flaws/bugs in Minecraft.</description>
|
||||||
<url>http://dev.bukkit.org/server-mods/nocheatplus</url>
|
<url>http://dev.bukkit.org/server-mods/nocheatplus</url>
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ public class ChatCheckListener implements Listener, EventManager {
|
|||||||
if ((event.getMessage().equalsIgnoreCase("/plugins")
|
if ((event.getMessage().equalsIgnoreCase("/plugins")
|
||||||
|| event.getMessage().toLowerCase().startsWith("/plugins ")
|
|| event.getMessage().toLowerCase().startsWith("/plugins ")
|
||||||
|| event.getMessage().equalsIgnoreCase("/pl") || event.getMessage().toLowerCase().startsWith("/pl "))
|
|| event.getMessage().equalsIgnoreCase("/pl") || event.getMessage().toLowerCase().startsWith("/pl "))
|
||||||
&& cc.hideNoCheatPlus) {
|
&& Bukkit.getPluginManager().getPlugin("PluginList") == null && cc.hideNoCheatPlus) {
|
||||||
// If the player isn't allowed to use this command
|
// If the player isn't allowed to use this command
|
||||||
if (!event.getPlayer().hasPermission("bukkit.command.plugins"))
|
if (!event.getPlayer().hasPermission("bukkit.command.plugins"))
|
||||||
// Fake the permissions error message
|
// Fake the permissions error message
|
||||||
@ -153,8 +153,8 @@ public class ChatCheckListener implements Listener, EventManager {
|
|||||||
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||||
public void login(final PlayerLoginEvent event) {
|
public void login(final PlayerLoginEvent event) {
|
||||||
|
|
||||||
// Only check players who haven't played before
|
// Only check new players (who has joined less than 10 minutes ago)
|
||||||
if (event.getPlayer().hasPlayedBefore())
|
if (System.currentTimeMillis() - event.getPlayer().getFirstPlayed() > 600000D)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
final NoCheatPlusPlayer player = plugin.getPlayer(event.getPlayer());
|
final NoCheatPlusPlayer player = plugin.getPlayer(event.getPlayer());
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
package me.neatmonster.nocheatplus.checks.chat;
|
package me.neatmonster.nocheatplus.checks.chat;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import me.neatmonster.nocheatplus.NoCheatPlus;
|
import me.neatmonster.nocheatplus.NoCheatPlus;
|
||||||
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
|
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
|
||||||
|
|
||||||
public class SpamJoinsCheck extends ChatCheck {
|
public class SpamJoinsCheck extends ChatCheck {
|
||||||
|
|
||||||
// Used to know if the cooldown is enabled and since when
|
// Used to know if the cooldown is enabled and since when
|
||||||
private boolean cooldown = false;
|
private boolean cooldown = false;
|
||||||
private long cooldownStartTime = 0L;
|
private long cooldownStartTime = 0L;
|
||||||
|
|
||||||
// Used to remember the latest joins;
|
// Used to remember the latest joins;
|
||||||
private long[] joins = null;
|
private long[] joinsTimes = null;
|
||||||
|
private String[] joinsPlayers = null;
|
||||||
|
|
||||||
public SpamJoinsCheck(final NoCheatPlus plugin) {
|
public SpamJoinsCheck(final NoCheatPlus plugin) {
|
||||||
super(plugin, "chat.spamjoins");
|
super(plugin, "chat.spamjoins");
|
||||||
@ -19,8 +22,10 @@ public class SpamJoinsCheck extends ChatCheck {
|
|||||||
public boolean check(final NoCheatPlusPlayer player, final ChatData data, final ChatConfig cc) {
|
public boolean check(final NoCheatPlusPlayer player, final ChatData data, final ChatConfig cc) {
|
||||||
|
|
||||||
// Initialize the joins array
|
// Initialize the joins array
|
||||||
if (joins == null)
|
if (joinsTimes == null)
|
||||||
joins = new long[cc.spamJoinsPlayersLimit];
|
joinsTimes = new long[cc.spamJoinsPlayersLimit];
|
||||||
|
if (joinsPlayers == null)
|
||||||
|
joinsPlayers = new String[cc.spamJoinsPlayersLimit];
|
||||||
|
|
||||||
boolean kick = false;
|
boolean kick = false;
|
||||||
|
|
||||||
@ -37,7 +42,7 @@ public class SpamJoinsCheck extends ChatCheck {
|
|||||||
kick = true;
|
kick = true;
|
||||||
|
|
||||||
// If more than limit new players have joined in less than limit time
|
// If more than limit new players have joined in less than limit time
|
||||||
else if (System.currentTimeMillis() - joins[0] < cc.spamJoinsTimeLimit) {
|
else if (System.currentTimeMillis() - joinsTimes[0] < cc.spamJoinsTimeLimit) {
|
||||||
// Enable the new players cooldown
|
// Enable the new players cooldown
|
||||||
cooldown = true;
|
cooldown = true;
|
||||||
cooldownStartTime = System.currentTimeMillis();
|
cooldownStartTime = System.currentTimeMillis();
|
||||||
@ -46,9 +51,14 @@ public class SpamJoinsCheck extends ChatCheck {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fill the joining times array
|
// Fill the joining times array
|
||||||
for (int i = 0; i < cc.spamJoinsPlayersLimit - 1; i++)
|
if (!Arrays.asList(joinsPlayers).contains(player.getName())) {
|
||||||
joins[i] = joins[i + 1];
|
for (int i = 0; i < cc.spamJoinsPlayersLimit - 1; i++) {
|
||||||
joins[cc.spamJoinsPlayersLimit - 1] = System.currentTimeMillis();
|
joinsTimes[i] = joinsTimes[i + 1];
|
||||||
|
joinsPlayers[i] = joinsPlayers[i + 1];
|
||||||
|
}
|
||||||
|
joinsTimes[cc.spamJoinsPlayersLimit - 1] = System.currentTimeMillis();
|
||||||
|
joinsPlayers[cc.spamJoinsPlayersLimit - 1] = player.getName();
|
||||||
|
}
|
||||||
|
|
||||||
return kick;
|
return kick;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import org.bukkit.event.block.Action;
|
|||||||
import org.bukkit.event.block.BlockPlaceEvent;
|
import org.bukkit.event.block.BlockPlaceEvent;
|
||||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
import org.bukkit.event.player.PlayerMoveEvent;
|
import org.bukkit.event.player.PlayerMoveEvent;
|
||||||
import org.bukkit.event.player.PlayerPortalEvent;
|
import org.bukkit.event.player.PlayerPortalEvent;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
@ -135,6 +136,26 @@ public class MovingCheckListener implements Listener, EventManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a player tries to place a boat on the ground, the event
|
||||||
|
* will be cancelled.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* The PlayerInteractEvent
|
||||||
|
*/
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||||
|
public void boat(final PlayerInteractEvent event) {
|
||||||
|
if (!event.getPlayer().hasPermission(Permissions.MOVING_BOATONGROUND)
|
||||||
|
&& event.getAction() == Action.RIGHT_CLICK_BLOCK
|
||||||
|
&& event.getPlayer().getItemInHand().getType() == Material.BOAT
|
||||||
|
&& event.getClickedBlock().getType() != Material.WATER
|
||||||
|
&& event.getClickedBlock().getType() != Material.STATIONARY_WATER
|
||||||
|
&& event.getClickedBlock().getRelative(event.getBlockFace()).getType() != Material.WATER
|
||||||
|
&& event.getClickedBlock().getRelative(event.getBlockFace()).getType() != Material.STATIONARY_WATER)
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getActiveChecks(final ConfigurationCacheStore cc) {
|
public List<String> getActiveChecks(final ConfigurationCacheStore cc) {
|
||||||
final LinkedList<String> s = new LinkedList<String>();
|
final LinkedList<String> s = new LinkedList<String>();
|
||||||
@ -160,6 +181,27 @@ public class MovingCheckListener implements Listener, EventManager {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This event handler is used to prevent the player from quickly
|
||||||
|
* disconnecting/reconnecting in order to cancel his fall damages.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* The PlayerJoinEvent
|
||||||
|
*/
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||||
|
public void join(final PlayerJoinEvent event) {
|
||||||
|
|
||||||
|
final NoCheatPlusPlayer player = plugin.getPlayer(event.getPlayer());
|
||||||
|
final MovingData data = MovingCheck.getData(player);
|
||||||
|
|
||||||
|
// If the player has joined in the air and a safe location is defined...
|
||||||
|
if (player.getPlayer().getLocation().add(0, -1, 0).getBlock().getType() == Material.AIR
|
||||||
|
&& data.lastSafeLocations[0] != null)
|
||||||
|
// ...then teleport him to this location
|
||||||
|
event.getPlayer().teleport(data.lastSafeLocations[0]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When a player moves, he will be checked for various
|
* When a player moves, he will be checked for various
|
||||||
* suspicious behaviour.
|
* suspicious behaviour.
|
||||||
@ -197,6 +239,12 @@ public class MovingCheckListener implements Listener, EventManager {
|
|||||||
final Location to = event.getTo();
|
final Location to = event.getTo();
|
||||||
data.to.set(to);
|
data.to.set(to);
|
||||||
|
|
||||||
|
// Remember safe locations
|
||||||
|
if (Math.abs(event.getPlayer().getVelocity().getY()) < 0.0785D) {
|
||||||
|
data.lastSafeLocations[0] = data.lastSafeLocations[1];
|
||||||
|
data.lastSafeLocations[1] = event.getFrom();
|
||||||
|
}
|
||||||
|
|
||||||
PreciseLocation newTo = null;
|
PreciseLocation newTo = null;
|
||||||
|
|
||||||
/** RUNFLY CHECK SECTION **/
|
/** RUNFLY CHECK SECTION **/
|
||||||
@ -238,24 +286,6 @@ public class MovingCheckListener implements Listener, EventManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* If a player tries to place a boat on the ground, the event
|
|
||||||
* will be cancelled.
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
* The PlayerInteractEvent
|
|
||||||
*/
|
|
||||||
@EventHandler(
|
|
||||||
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
|
||||||
public void onPlayerInteract(final PlayerInteractEvent event) {
|
|
||||||
if (!event.getPlayer().hasPermission(Permissions.MOVING_BOATONGROUND)
|
|
||||||
&& event.getAction() == Action.RIGHT_CLICK_BLOCK
|
|
||||||
&& event.getPlayer().getItemInHand().getType() == Material.BOAT
|
|
||||||
&& event.getClickedBlock().getType() != Material.WATER
|
|
||||||
&& event.getClickedBlock().getType() != Material.STATIONARY_WATER)
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When a player uses a portal, all information related to the
|
* When a player uses a portal, all information related to the
|
||||||
* moving checks becomes invalid.
|
* moving checks becomes invalid.
|
||||||
@ -278,6 +308,13 @@ public class MovingCheckListener implements Listener, EventManager {
|
|||||||
*/
|
*/
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void quit(final PlayerQuitEvent event) {
|
public void quit(final PlayerQuitEvent event) {
|
||||||
|
|
||||||
|
final NoCheatPlusPlayer player = plugin.getPlayer(event.getPlayer());
|
||||||
|
final MovingData data = MovingCheck.getData(player);
|
||||||
|
|
||||||
|
// Reset the variable
|
||||||
|
data.fallingSince = 0L;
|
||||||
|
|
||||||
if (!event.getPlayer().hasPermission(Permissions.MOVING_RESPAWNTRICK)
|
if (!event.getPlayer().hasPermission(Permissions.MOVING_RESPAWNTRICK)
|
||||||
&& (event.getPlayer().getLocation().getBlock().getType() == Material.GRAVEL || event.getPlayer()
|
&& (event.getPlayer().getLocation().getBlock().getType() == Material.GRAVEL || event.getPlayer()
|
||||||
.getLocation().getBlock().getType() == Material.SAND)) {
|
.getLocation().getBlock().getType() == Material.SAND)) {
|
||||||
@ -420,6 +457,9 @@ public class MovingCheckListener implements Listener, EventManager {
|
|||||||
|
|
||||||
final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()));
|
final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()));
|
||||||
|
|
||||||
|
// Reset the tracker's data
|
||||||
|
data.fallingSince = 0L;
|
||||||
|
|
||||||
final Vector v = event.getVelocity();
|
final Vector v = event.getVelocity();
|
||||||
|
|
||||||
double newVal = v.getY();
|
double newVal = v.getY();
|
||||||
|
@ -4,6 +4,8 @@ import me.neatmonster.nocheatplus.DataItem;
|
|||||||
import me.neatmonster.nocheatplus.data.PreciseLocation;
|
import me.neatmonster.nocheatplus.data.PreciseLocation;
|
||||||
import me.neatmonster.nocheatplus.data.Statistics.Id;
|
import me.neatmonster.nocheatplus.data.Statistics.Id;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Player specific data for the moving check group
|
* Player specific data for the moving check group
|
||||||
*/
|
*/
|
||||||
@ -28,7 +30,7 @@ public class MovingData implements DataItem {
|
|||||||
public int onIce;
|
public int onIce;
|
||||||
|
|
||||||
// Where should a player be teleported back to when failing the check
|
// Where should a player be teleported back to when failing the check
|
||||||
public final PreciseLocation runflySetBackPoint = new PreciseLocation();
|
public final PreciseLocation runflySetBackPoint = new PreciseLocation();
|
||||||
|
|
||||||
// Some values for estimating movement freedom
|
// Some values for estimating movement freedom
|
||||||
public double vertFreedom;
|
public double vertFreedom;
|
||||||
@ -44,39 +46,45 @@ public class MovingData implements DataItem {
|
|||||||
public float lastAddedFallDistance;
|
public float lastAddedFallDistance;
|
||||||
|
|
||||||
// Keep in mind since when the player in falling/jumping
|
// Keep in mind since when the player in falling/jumping
|
||||||
public long fallingSince = 0L;
|
public long fallingSince = 0L;
|
||||||
|
|
||||||
|
// Remember if the player has already been on the ground
|
||||||
|
public boolean hasAlreadyBeenOnTheGround = false;
|
||||||
|
|
||||||
|
// Keep in mind the player's last safe position
|
||||||
|
public Location[] lastSafeLocations = new Location[] {null, null};
|
||||||
|
|
||||||
// Keep track of when "morePackets" last time checked and how much packets
|
// Keep track of when "morePackets" last time checked and how much packets
|
||||||
// a player sent and may send before failing the check
|
// a player sent and may send before failing the check
|
||||||
public long morePacketsLastTime;
|
public long morePacketsLastTime;
|
||||||
public int packets;
|
public int packets;
|
||||||
public int morePacketsBuffer = 50;
|
public int morePacketsBuffer = 50;
|
||||||
|
|
||||||
// Where to teleport the player that fails the "morepackets" check
|
// Where to teleport the player that fails the "morepackets" check
|
||||||
public final PreciseLocation morePacketsSetbackPoint = new PreciseLocation();
|
public final PreciseLocation morePacketsSetbackPoint = new PreciseLocation();
|
||||||
|
|
||||||
// Keep track of when "morePacketsVehicle" last time checked an how much
|
// Keep track of when "morePacketsVehicle" last time checked an how much
|
||||||
// packets a vehicle sent and may send before failing the check
|
// packets a vehicle sent and may send before failing the check
|
||||||
public long morePacketsVehicleLastTime;
|
public long morePacketsVehicleLastTime;
|
||||||
public int packetsVehicle;
|
public int packetsVehicle;
|
||||||
public int morePacketsVehicleBuffer = 50;
|
public int morePacketsVehicleBuffer = 50;
|
||||||
|
|
||||||
// When NoCheatPlus does teleport the player, remember the target location to
|
// When NoCheatPlus does teleport the player, remember the target location to
|
||||||
// be able to distinguish "our" teleports from teleports of others
|
// be able to distinguish "our" teleports from teleports of others
|
||||||
public final PreciseLocation teleportTo = new PreciseLocation();
|
public final PreciseLocation teleportTo = new PreciseLocation();
|
||||||
|
|
||||||
// For logging and convenience, make copies of the events locations
|
// For logging and convenience, make copies of the events locations
|
||||||
public final PreciseLocation from = new PreciseLocation();
|
public final PreciseLocation from = new PreciseLocation();
|
||||||
public final PreciseLocation fromVehicle = new PreciseLocation();
|
public final PreciseLocation fromVehicle = new PreciseLocation();
|
||||||
public final PreciseLocation to = new PreciseLocation();
|
public final PreciseLocation to = new PreciseLocation();
|
||||||
public final PreciseLocation toVehicle = new PreciseLocation();
|
public final PreciseLocation toVehicle = new PreciseLocation();
|
||||||
|
|
||||||
// For convenience, remember if the locations are considered "on ground"
|
// For convenience, remember if the locations are considered "on ground"
|
||||||
// by NoCheatPlus
|
// by NoCheatPlus
|
||||||
public boolean fromOnOrInGround;
|
public boolean fromOnOrInGround;
|
||||||
public boolean toOnOrInGround;
|
public boolean toOnOrInGround;
|
||||||
|
|
||||||
public Id statisticCategory = Id.MOV_RUNNING;
|
public Id statisticCategory = Id.MOV_RUNNING;
|
||||||
|
|
||||||
public void clearMorePacketsData() {
|
public void clearMorePacketsData() {
|
||||||
morePacketsSetbackPoint.reset();
|
morePacketsSetbackPoint.reset();
|
||||||
|
@ -28,24 +28,32 @@ public class TrackerCheck extends MovingCheck {
|
|||||||
final int type = CheckUtil.evaluateLocation(player.getPlayer().getWorld(), location);
|
final int type = CheckUtil.evaluateLocation(player.getPlayer().getWorld(), location);
|
||||||
final boolean isLiquid = CheckUtil.isLiquid(type);
|
final boolean isLiquid = CheckUtil.isLiquid(type);
|
||||||
|
|
||||||
|
// Check if the player is on the ground
|
||||||
|
if (player.getPlayer().getLocation().add(0, -1, 0).getBlock().getType() != Material.AIR)
|
||||||
|
data.hasAlreadyBeenOnTheGround = true;
|
||||||
|
|
||||||
// Do not do the check if it's disabled, if flying is allowed, if the player is
|
// Do not do the check if it's disabled, if flying is allowed, if the player is
|
||||||
// allowed to fly because of its game mode, if he has the required permission,
|
// allowed to fly because of its game mode, if he has the required permission,
|
||||||
// if he is in water or in vines.
|
// if he is in water, on a ladder or in vines.
|
||||||
if (!cc.tracker || cc.allowFlying || player.getPlayer().getGameMode() == GameMode.CREATIVE
|
if (!cc.tracker || cc.allowFlying || player.getPlayer().getGameMode() == GameMode.CREATIVE
|
||||||
|| player.getPlayer().getAllowFlight() || player.getPlayer().hasPermission(Permissions.MOVING_RUNFLY)
|
|| player.getPlayer().getAllowFlight() || player.getPlayer().hasPermission(Permissions.MOVING_RUNFLY)
|
||||||
|| player.getPlayer().hasPermission(Permissions.MOVING_FLYING) || isLiquid
|
|| player.getPlayer().hasPermission(Permissions.MOVING_FLYING) || isLiquid
|
||||||
|| player.getPlayer().getLocation().getBlock().getType() == Material.LADDER
|
|| player.getPlayer().getLocation().getBlock().getType() == Material.LADDER
|
||||||
|| player.getPlayer().getLocation().getBlock().getType() == Material.VINE
|
|| player.getPlayer().getLocation().getBlock().getType() == Material.VINE
|
||||||
|| player.getPlayer().getLocation().getX() < 0D) {
|
|| player.getPlayer().getLocation().getY() < 0D) {
|
||||||
data.fallingSince = 0;
|
data.fallingSince = 0L;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the player isn't falling or jumping
|
// If the player isn't static or jumping
|
||||||
if (Math.abs(player.getPlayer().getVelocity().getY()) > 0.1D) {
|
if (Math.abs(player.getPlayer().getVelocity().getY()) > 0.1D) {
|
||||||
|
|
||||||
// The player is falling/jumping, check if he was previously on the ground
|
// Only do something if the player has already been on the ground
|
||||||
if (data.fallingSince == 0)
|
if (!data.hasAlreadyBeenOnTheGround)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// The player is static/jumping, check if he was previously on the ground
|
||||||
|
if (data.fallingSince == 0L)
|
||||||
data.fallingSince = System.currentTimeMillis();
|
data.fallingSince = System.currentTimeMillis();
|
||||||
|
|
||||||
// Check if he has stayed too much time in the air (more than 6 seconds)
|
// Check if he has stayed too much time in the air (more than 6 seconds)
|
||||||
@ -56,11 +64,11 @@ public class TrackerCheck extends MovingCheck {
|
|||||||
|
|
||||||
// Execute whatever actions are associated with this check and the
|
// Execute whatever actions are associated with this check and the
|
||||||
// violation level and find out if we should cancel the event
|
// violation level and find out if we should cancel the event
|
||||||
executeActions(player, cc.nofallActions, data.nofallVL);
|
executeActions(player, cc.trackerActions, data.trackerVL);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Reset the timer
|
// Reset the timer
|
||||||
data.fallingSince = 0;
|
data.fallingSince = 0L;
|
||||||
|
|
||||||
// Reduce the violation level
|
// Reduce the violation level
|
||||||
data.trackerVL *= 0.95;
|
data.trackerVL *= 0.95;
|
||||||
|
@ -63,6 +63,12 @@ public class CommandHandler {
|
|||||||
public boolean handleCommand(final NoCheatPlus plugin, final CommandSender sender, final Command command,
|
public boolean handleCommand(final NoCheatPlus plugin, final CommandSender sender, final Command command,
|
||||||
final String label, final String[] args) {
|
final String label, final String[] args) {
|
||||||
|
|
||||||
|
// Hide NoCheatPlus's commands if the player doesn't have the required permission
|
||||||
|
if (sender instanceof Player && !sender.hasPermission("nocheatplus.admin.commands")) {
|
||||||
|
sender.sendMessage("Unknown command. Type \"help\" for help.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
// Not our command, how did it get here?
|
// Not our command, how did it get here?
|
||||||
if (!command.getName().equalsIgnoreCase("nocheatplus") || args.length == 0)
|
if (!command.getName().equalsIgnoreCase("nocheatplus") || args.length == 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user