+ Added a new check called WaterWalk

+ Added Zombe and CJB mods disabling
+ Added survival's fly mode support
= Code cleanup (mostly events related)
- Removed the active checks printer
This commit is contained in:
NeatMonster 2012-04-05 18:24:39 +02:00
parent 9d5f1f1266
commit e057737fb0
101 changed files with 3526 additions and 3425 deletions

View File

@ -1,11 +1,10 @@
################################################################################
# #
# Important files, config.yml or "clean up your stuff" #
# #
################################################################################
1) The config file for NoCheat is called "config.yml" now.
1) The config file for NoCheatPlus is called "config.yml" now.
2) You can have different config files for different worlds. To achieve this,
copy the "config.yml" and rename the copy to "worldname_config.yml". Set-
@ -14,7 +13,7 @@
won't use. They'll be implicitly taken from the master "config.yml" file.
3) If you have files named "config.txt", "default_actions.txt" or "actions.txt"
please delete them. They are no longer used by NoCheat and serve no purpose
please delete them. They are no longer used by NoCheatPlus and serve no purpose
anymore.
4) Never change the amount of white-spaces in front of options in the config
@ -27,7 +26,7 @@
# #
################################################################################
NoCheat allows to define in detail what should happen when a player fails a
NoCheatPlus allows to define in detail what should happen when a player fails a
check in form of "actions". There are 4 possible things that may be done.
(read on to learn in detail on how to define/modify actions):
@ -63,8 +62,8 @@
2) The "log" action is a string of the form "log:string:delay:repeat:target".
log: is simply used to let NoCheat know it is a log action. Don't remove
it from the action, or NoCheat will not know what it is and how to
log: is simply used to let NoCheatPlus know it is a log action. Don't remove
it from the action, or NoCheatPlus will not know what it is and how to
handle it.
string: is the message that will be logged. Because there is so little
@ -91,8 +90,8 @@
3) The "cmd" action is a string of the form "cmd:string:delay:repeat".
cmd: is simply used to let NoCheat know it is a command action. Don't
remove it from the action, or NoCheat will not know what it is and
cmd: is simply used to let NoCheatPlus know it is a command action. Don't
remove it from the action, or NoCheatPlus will not know what it is and
how to handle it.
string: is the command that will be issued. Because there is so little space
@ -124,9 +123,9 @@
################################################################################
NoCheat only supports "SuperPerms", CraftBukkits official permission framework.
NoCheatPlus only supports "SuperPerms", CraftBukkits official permission framework.
You'll need to use a permissions plugin that supports "SuperPerms" to use it
with NoCheat. Here are some I know of:
with NoCheatPlus. Here are some I know of:
- bPermissions
- PermissionsEx
@ -146,39 +145,39 @@
having one of these nodes means he will NOT be checked. Players without the
permission node will be checked.
Example: A player has permission "nocheat.checks.moving.morepackets". That
means he is allowed to use that hack/cheat because NoCheat won't check/stop it.
Example: A player has permission "NoCheatPlus.checks.moving.morepackets". That
means he is allowed to use that hack/cheat because NoCheatPlus won't check/stop it.
------------------------ MOVING Permissions for CHECKS -------------------------
- nocheat.checks.moving.runfly
- nocheatplus.checks.moving.runfly
Allows the player to move freely. It also treats the player as if he has
the ".flying", ".swimming", ".sneaking" and ".nofall" permission too.
- nocheat.checks.moving.flying
- nocheatplus.checks.moving.flying
Allows the player to fly, independent of if he is in "creative mode" or not.
He will be limited in speed by the config settings "flyingspeedvertical"
and "flyingspeedhorizontal". It also treats the player as if he has the
".nofall" permission too.
- nocheat.checks.moving.swimming
- nocheatplus.checks.moving.swimming
Allows the player to swim as fast as he is allowed to walk. Normally a
player swims slower than he walks and NoCheat prevents faster movement in
player swims slower than he walks and NoCheatPlus prevents faster movement in
water.
- nocheat.checks.moving.sneaking
- nocheatplus.checks.moving.sneaking
Allows the player to sneak faster than he is allowed to walk. Normally a
player sneaks a lot slower than he walks and NoCheat prevents faster
player sneaks a lot slower than he walks and NoCheatPlus prevents faster
movement while sneaking.
- nocheat.checks.moving.nofall
Allows the player to avoid fall damage by using hacks. Normally NoCheat
- nocheatplus.checks.moving.nofall
Allows the player to avoid fall damage by using hacks. Normally NoCheatPlus
will keep track of a players movement and try to rectify the fall-damage
calculations of Minecraft in case they seem to be wrong because of players
tricking the server.
- nocheat.checks.moving.morepackets
- nocheatplus.checks.moving.morepackets
Allows players to make a lot more movements than normally possible. Doing
more movements will result in faster overall movement speed and causes the
server to spend a lot of additional time for processing these movements.
@ -186,87 +185,106 @@
-------------------- BLOCKBREAK Permissions for CHECKS -------------------------
- nocheat.checks.blockbreak.reach
- nocheatplus.checks.blockbreak.reach
Allows the player to break blocks that are further away than usual.
- nocheat.checks.blockbreak.direction
- nocheatplus.checks.blockbreak.direction
Don't force players to look at the blocks that they try to destroy.
- nocheat.checks.blockbreak.noswing
- nocheatplus.checks.blockbreak.noswing
Don't force players to swing their arm when breaking blocks.
-------------------- BLOCKPLACE Permissions for CHECKS -------------------------
- nocheat.checks.blockplace.reach
- nocheatplus.checks.blockplace.reach
Allows the player to place blocks that are further away than usual.
- nocheat.checks.blockplace.direction
- nocheatplus.checks.blockplace.direction
Don't force players to look at the blocks that they try to place.
--------------------- INVENTORY Permissions for CHECKS -------------------------
- nocheat.checks.inventory.drop
- nocheatplus.checks.inventory.drop
Don't limit the number of items that a player may drop within a short time
- nocheat.checks.inventory.instantbow
- nocheatplus.checks.inventory.instantbow
Don't prevent players from shooting their bows instantly without taking the
usual time to pull the string back
- nocheat.checks.inventory.instanteat
- nocheatplus.checks.inventory.instanteat
Don't prevent players from eating their food instantly without taking the
usual time to munch on it
----------------------- CHAT Permissions for CHECKS ----------------------------
- nocheat.checks.chat.spam
- nocheatplus.checks.chat.spam
Don't limit the number of messages and commands that a player may send in a
short timeframe
- nocheat.checks.chat.color
- nocheatplus.checks.chat.color
Don't filter color codes from messages that get sent by players, allowing
them to use colors in their messages.
---------------------- FIGHT Permissions for CHECKS ----------------------------
- nocheat.checks.fight.direction
- nocheatplus.checks.fight.direction
Don't force players to look at their targets while fighting
- nocheat.checks.fight.noswing
- nocheatplus.checks.fight.noswing
Don't force players to move their arms while fighting
- nocheat.checks.fight.reach
- nocheatplus.checks.fight.reach
Don't limit the distance for fights
- nocheat.checks.fight.speed
- nocheatplus.checks.fight.speed
Don't limit the number of attacks that the player can do per second
- nocheat.checks.fight.godmode
- nocheatplus.checks.fight.godmode
Don't prevent the player from keeping the temporary invulnerability that he
gets when taking damage
- nocheat.checks.fight.instantheal
- nocheatplus.checks.fight.instantheal
Don't prevent the player from accellerating their health generation by
food saturation
--------------------------------------------------------------------------------
--------------------------- Permissions for CHECKS -----------------------------
--------------------------------------------------------------------------------
- nocheatplus.zombe.fly
Don't prevent the player from using Zombe's fly mod
- nocheatplus.zombe.cheats
Don't prevent the player from using all other Zombe's cheats
- nocheatplus.cjb.fly
Don't prevent the player from using CJB's fly mod
- nocheatplus.cjb.xray
Don't prevent the player from using CJB's Xray
- nocheatplus.cjb.minimap
Don't prevent the player from using CJB's minimap
--------------------------------------------------------------------------------
----------------------- Permissions for ADMINISTRATION -------------------------
--------------------------------------------------------------------------------
- nocheat.admin.chatlog
- nocheatplus.admin.chatlog
The player will receive log messages that are directed at the "ingame chat"
as a normal chat message ingame.
- nocheat.admin.commands
The player gets access to some of the "/nocheat" commands
- nocheatplus.admin.commands
The player gets access to some of the "/NoCheatPlus" commands
- nocheat.admin.reload
In combination with "nocheat.admin.commands", the player gets access to the
"/nocheat reload" command, which will cause NoCheat to reread its config
- nocheatplus.admin.reload
In combination with "NoCheatPlus.admin.commands", the player gets access to the
"/NoCheatPlus reload" command, which will cause NoCheatPlus to reread its config
files.
@ -274,33 +292,33 @@
---------------------- Things to know about Permissions ------------------------
--------------------------------------------------------------------------------
NoCheat defines "parent" nodes for all permissions already for you. That means
NoCheatPlus defines "parent" nodes for all permissions already for you. That means
you can use one of the following:
- nocheat
- nocheat.admin
- nocheat.checks
- nocheat.checks.moving
- nocheat.checks.blockbreak
- nocheat.checks.blockplace
- nocheat.checks.inventory
- nocheat.checks.chat
- nocheat.checks.fight
- NoCheatPlus
- NoCheatPlus.admin
- NoCheatPlus.checks
- NoCheatPlus.checks.moving
- NoCheatPlus.checks.blockbreak
- NoCheatPlus.checks.blockplace
- NoCheatPlus.checks.inventory
- NoCheatPlus.checks.chat
- NoCheatPlus.checks.fight
To give a player all the permissions that start with that permission node.
Especially you don't have to and should not use ".*" anywhere when defining
NoCheat permissions.
NoCheatPlus permissions.
You can exclude a specific player from getting logged by appending ".silent"
to the relevant permission node of the specific check. E.g.
- nocheat.checks.moving.nofall.silent
- NoCheatPlus.checks.moving.nofall.silent
will prevent NoCheat from recording log messages for that player for the
will prevent NoCheatPlus from recording log messages for that player for the
"nofall" check, while still executing all other actions as usual. These silent
permissions won't show up elsewhere, e.g. when using the "nocheat permlist"
permissions won't show up elsewhere, e.g. when using the "NoCheatPlus permlist"
command.
@ -318,13 +336,13 @@
-------------------------------- LOGGING Section -------------------------------
--------------------------------------------------------------------------------
Everything that in general has to do with controlling NoCheats logging can be
Everything that in general has to do with controlling NoCheatPluss logging can be
found at this part of the config.yml
active:
Should messages get logged at all. If you are not interested in messages,
set this to false and you'll hear and see (almost) nothing of NoCheat.
set this to false and you'll hear and see (almost) nothing of NoCheatPlus.
prefix:
@ -334,8 +352,8 @@
filename:
The name of the logfile that NoCheat will use to log its messages. The
default name is "nocheat.log", but you can use a different one if you want
The name of the logfile that NoCheatPlus will use to log its messages. The
default name is "NoCheatPlus.log", but you can use a different one if you want
to.
file:
@ -346,26 +364,26 @@
console:
Should the server console be used to display messages. Set to false if you
don't want NoCheat to show messages related to checks in the console. Error
don't want NoCheatPlus to show messages related to checks in the console. Error
messages may still get displayed there though.
ingamechat:
Should NoCheat display messages in the ingame chat? Set to false if you
don't want NoCheat to show messages ingame. The messages will only be seen
by players with the permission node "nocheat.admin.chatlog" or if you don't
Should NoCheatPlus display messages in the ingame chat? Set to false if you
don't want NoCheatPlus to show messages ingame. The messages will only be seen
by players with the permission node "NoCheatPlus.admin.chatlog" or if you don't
use a permissions plugin, by players who are OP.
showactivechecks:
Should NoCheat display lists of checks that are enabled for each world. Set
Should NoCheatPlus display lists of checks that are enabled for each world. Set
to true if you are unsure that your (multiworld) setup of the config files
is done correctly.
debugmessages:
Should some additional messages be displayed in the server console, e.g.
about NoCheat encountering lag. The displayed messages may change from
about NoCheatPlus encountering lag. The displayed messages may change from
version to version. This is deactivated by default.
@ -373,7 +391,7 @@
-------------------------------- CHECKS Section --------------------------------
--------------------------------------------------------------------------------
Everything that in has to do with the various checks that NoCheat runs on the
Everything that in has to do with the various checks that NoCheatPlus runs on the
players. Use these to specify what will be done, how it will be done and what
happens if somebody fails checks.
@ -424,9 +442,9 @@
What should happen if the player fails this check. Default is to stop
the attack ("cancel" it) and log messages. The Violation Level (VL) for
this check the time difference between how long it took the player to
fire an arrow and how long NoCheat thinks he should have taken, in
fire an arrow and how long NoCheatPlus thinks he should have taken, in
1/10 seconds. Therefore a VL of 10 would mean that the player shot an
arrow 1 second faster than NoCheat expected. The VL gets increased with
arrow 1 second faster than NoCheatPlus expected. The VL gets increased with
every failed check and slowly decreased for every passed check.
3) INSTANTEAT:
@ -442,9 +460,9 @@
What should happen if the player fails this check. Default is to stop
the eating ("cancel" it) and log messages. The Violation Level (VL) for
this check the time difference between how long it took the player to
eat his food and how long NoCheat thinks he should have taken, in
eat his food and how long NoCheatPlus thinks he should have taken, in
1/10 seconds. Therefore a VL of 10 would mean that the player ate his
food 1 second faster than NoCheat expected. The VL gets increased with
food 1 second faster than NoCheatPlus expected. The VL gets increased with
every failed check and slowly decreased for every passed check.
@ -468,7 +486,7 @@
How fast should the player be allowed to walk. Default is "100",
meaning 100% of normal walking speed. You will not see this option in
your config.yml file, because normally you shouldn't have to change the
walking speed of players at all (NoCheat knows when players sprint, use
walking speed of players at all (NoCheatPlus knows when players sprint, use
Swiftness potions etc and will already adapt the speed based on that
data).
@ -476,7 +494,7 @@
How fast should the player be allowed to sprint. Default is "100",
meaning 100% of normal sprinting speed. You will not see this option in
your config.yml file, because normally you shouldn't have to change the
sprinting speed of players at all (NoCheat knows when players sprint,
sprinting speed of players at all (NoCheatPlus knows when players sprint,
use Swiftness potions etc and will already adapt the speed based on
that data).
@ -484,7 +502,7 @@
How fast should the player be allowed to sneak. Default is "100",
meaning 100% of normal sneaking speed. You will not see this option in
your config.yml file, because normally you shouldn't have to change the
sneaking speed of players at all (NoCheat knows when players sprint,
sneaking speed of players at all (NoCheatPlus knows when players sprint,
use Swiftness potions etc and will already adapt the speed based on
that data).
@ -492,7 +510,7 @@
How fast should the player be allowed to swim. Default is "100",
meaning 100% of normal swimming speed. You will not see this option in
your config.yml file, because normally you shouldn't have to change the
swimming speed of players at all (NoCheat knows when players sprint,
swimming speed of players at all (NoCheatPlus knows when players sprint,
use Swiftness potions etc and will already adapt the speed based on
that data).
@ -505,7 +523,7 @@
What should happen when a player sneaks/swims/walks/runs faster than
normally allowed or is flying. Default is to log messages (depending on
how severe the cheating is) and teleport the player to the last known
legitimate location on ground that NoCheat can remember for that player
legitimate location on ground that NoCheatPlus can remember for that player
("cancel" the movement)
checknofall:
@ -562,7 +580,7 @@
What should happen if a player flies faster/higher than defined here?
Default is to log messages and to prevent the player from moving
("cancel" his last movement). The Violation Level (VL) of this check
is the distance that the player went beyond what NoCheat allowed him.
is the distance that the player went beyond what NoCheatPlus allowed him.
The VL increases with every failed check and slowly decreases for
every passed check.
@ -605,7 +623,7 @@
What should happen if the player is considered to cheat this way. The
default is to prevent him from breaking the block ("cancel" breaking)
and on repeated offenses to log messages about it. The Violation Level
(VL) is the distance in Blocks between the reach distance that NoCheat
(VL) is the distance in Blocks between the reach distance that NoCheatPlus
allowed and what the player actually tried to use. The VL increases
with every failed attempt to break a block out of reach, and decreases
with every successful attempt.
@ -620,7 +638,7 @@
Should players get checked for this type of hack
precision:
How strict should NoCheat be when comparing the players line of view
How strict should NoCheatPlus be when comparing the players line of view
with the broken block location. The value represents (roughly) the
amount of 1/100 blocks that the player is allowed to look past the to
be broken block. 50 (0.5 blocks) seems a good default value.
@ -673,7 +691,7 @@
What should happen if the player is considered to cheat this way. The
default is to prevent him from placing the block ("cancel" placing)
and on repeated offenses to log messages about it. The Violation Level
(VL) is the distance in Blocks between the reach distance that NoCheat
(VL) is the distance in Blocks between the reach distance that NoCheatPlus
allowed and what the player actually tried to use. The VL increases
with every failed attempt to place a block out of reach, and decreases
with every successful attempt.
@ -687,7 +705,7 @@
Should players get checked for this type of hack
precision:
How strict should NoCheat be when comparing the players line of view
How strict should NoCheatPlus be when comparing the players line of view
with the placed block location. The value represents (roughly) the
amount of 1/100 blocks that the player is allowed to look past the to
be placed block. 75 (0.75 blocks) seems a good default value.
@ -782,7 +800,7 @@
Should players get checked for this type of hack
precision:
How strict should NoCheat be when comparing the players line of view
How strict should NoCheatPlus be when comparing the players line of view
with the his target's location. The value represents (roughly) the
amount of 1/100 blocks that the player is allowed to look past the to
be attacked entity. 75 (0.75 blocks) seems a good default value.
@ -844,7 +862,7 @@
What should happen if the player is considered to cheat this way. The
default is to prevent him from attacking the target ("cancel" attack)
and on repeated offenses to log messages about it. The Violation Level
(VL) is the distance in Blocks between the reach distance that NoCheat
(VL) is the distance in Blocks between the reach distance that NoCheatPlus
allowed and what the player actually tried to use. The VL increases
with every failed attempt to attack enemies out of reach, and decreases
with every successful attempt.
@ -927,12 +945,12 @@
################################################################################
- NoCheat isn't perfect and won't prevent all forms of cheating. It's a best
- NoCheatPlus isn't perfect and won't prevent all forms of cheating. It's a best
effort approach.
- NoCheat may make mistakes. Don't see everything NoCheat says or does as
- NoCheatPlus may make mistakes. Don't see everything NoCheatPlus says or does as
indisputable fact that somebody cheated. It's not possible to be 100% sure
if somebody is cheating or not, NoCheat will try to be right most of the
if somebody is cheating or not, NoCheatPlus will try to be right most of the
time.
Thank you for reading this file. It took hours to write it, so it's nice that

View File

@ -1,21 +0,0 @@
The MIT License
Copyright (c) 2012 Wilfried Pasquazzo (Evenprime) <wilfried.pasquazzo@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -1,9 +0,0 @@
Copyright (c) 2012 Wilfried Pasquazzo (Evenprime)
<wilfried.pasquazzo@gmail.com>
# Dual-Licensed - you may freely choose between (or use both):
#
# 1) GPL v3 (see LICENSE_GPL3.txt)
# 2) MIT (see LICENSE_MIT.txt)
#
#

View File

@ -1,97 +1,112 @@
name: NoCheat
name: NoCheatPlus
version: ${project.version}
description: ${project.description}
author: Evenprime
author: NeatMonster
website: ${project.url}
main: cc.co.evenprime.bukkit.nocheat.NoCheat
main: me.neatmonster.nocheatplus.NoCheatPlus
commands:
nocheat:
description: NoCheat command(s)
permission: nocheat.admin.commands
nocheatplus:
description: NoCheatPlus command(s)
permission: nocheatplus.admin.commands
usage: |
/<command> permlist player [permission]: list NoCheat permissions of player, optionally only if beginning with [permission]
/<command> playerinfo player: show the collected data NoCheat collected about a player
/<command> reload: fast reload of NoCheats configuration file(s) - needs additional permissions
/<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> reload: fast reload of NoCheatPlus' configuration file(s) - needs additional permissions
permissions:
nocheat:
nocheatplus:
description: Allow a player to bypass all checks and give him all admin permissions
children:
nocheat.admin:
nocheatplus.admin:
description: Give a player all admin rights
children:
nocheat.admin.chatlog:
description: Player can see NoCheats log messages in the ingame chat
nocheat.admin.commands:
description: allow use of the "nocheat" commands (may be given to players to allow them to check statistics)
nocheat.admin.reload:
description: allow access to the special "nocheat reload" command (only intended for the actual server administrator)
nocheat.checks:
nocheatplus.admin.chatlog:
description: Player can see NoCheatPlus' log messages in the ingame chat
nocheatplus.admin.commands:
description: allow use of the "nocheatplus" commands (may be given to players to allow them to check statistics)
nocheatplus.admin.reload:
description: allow access to the special "nocheatplus reload" command (only intended for the actual server administrator)
nocheatplus.checks:
description: Allow the player to bypass all checks
children:
nocheat.checks.moving:
nocheatplus.checks.moving:
description: Allow the player to bypass all moving related checks
children:
nocheat.checks.moving.runfly:
nocheatplus.checks.moving.runfly:
description: Allow a player to move as free and as fast as he wants (ignores flying, swimming and sneaking settings)
nocheat.checks.moving.flying:
nocheatplus.checks.moving.flying:
description: Allow a player to fly, but only within given speed limits (ignores swimming and sneaking settings)
nocheat.checks.moving.swimming:
nocheatplus.checks.moving.swimming:
description: Allow a player to move through water without slowdown
nocheat.checks.moving.sneaking:
nocheatplus.checks.moving.sneaking:
description: Allow a player to sneak without slowdown
nocheat.checks.moving.nofall:
nocheatplus.checks.moving.nofall:
description: Allow a player to cheat and not take fall damage at all
nocheat.checks.moving.morepackets:
nocheatplus.checks.moving.morepackets:
description: Allow a player to send more move-event-packets than normal, causing him to move faster than normal
nocheat.checks.blockbreak:
nocheatplus.checks.blockbreak:
description: Allow the player to bypass all blockbreak checks
children:
nocheat.checks.blockbreak.reach:
nocheatplus.checks.blockbreak.reach:
description: Allow a player to break blocks at maximum range (about 6-7 blocks, in creative mode unlimited)
nocheat.checks.blockbreak.direction:
nocheatplus.checks.blockbreak.direction:
description: Allow a player to break blocks that are not in front of them
nocheat.checks.blockbreak.noswing:
nocheatplus.checks.blockbreak.noswing:
description: Allow a player to break blocks without swinging their arm
nocheat.checks.blockplace:
nocheatplus.checks.blockplace:
description: Allow the player to bypass all blockplace checks
children:
nocheat.checks.blockplace.reach:
nocheatplus.checks.blockplace.reach:
description: Allow a player to place blocks at maximum range (about 6-7 blocks)
nocheat.checks.blockplace.direction:
nocheatplus.checks.blockplace.direction:
description: Allow a player to place blocks outside their line of view
nocheat.checks.chat:
nocheatplus.checks.chat:
description: Allow the player to bypass all chat checks
children:
nocheat.checks.chat.spam:
nocheatplus.checks.chat.spam:
description: Allow a player to send an infinite amount of chat messages
nocheat.checks.chat.color:
nocheatplus.checks.chat.color:
description: Allow a player to send colored chat messages
nocheat.checks.fight:
nocheatplus.checks.fight:
description: Allow the player to bypass all fight checks
children:
nocheat.checks.fight.direction:
nocheatplus.checks.fight.direction:
description: Allow a player to attack players and monster even if they are not in his field of view
nocheat.checks.fight.noswing:
nocheatplus.checks.fight.noswing:
description: Allow a player to fight without swinging their arm
nocheat.checks.fight.reach:
nocheatplus.checks.fight.reach:
description: Allow a player to fight over bigger distances than usual
nocheat.checks.fight.speed:
nocheatplus.checks.fight.speed:
description: Allow a player to attack faster than usual
nocheat.checks.fight.godmode:
nocheatplus.checks.fight.godmode:
description: Allow a player to not take damage by exploiting a design flaw in Minecraft
nocheat.checks.fight.instantheal:
nocheatplus.checks.fight.instantheal:
description: Allow a player to artificially speed up his health regeneration
nocheat.checks.inventory:
nocheatplus.checks.inventory:
description: Allow the player to bypass all inventory checks
children:
nocheat.checks.inventory.drop:
nocheatplus.checks.inventory.drop:
description: Allow a player to drop more items in a short timeframe than the defined limit
nocheat.checks.inventory.instanteat:
nocheatplus.checks.inventory.instanteat:
description: Allow a player to eat food faster than normally possible
nocheat.checks.inventory.instantbow:
nocheatplus.checks.inventory.instantbow:
description: Allow a player to charge his bow faster than usual
nocheatplus.zombe:
description: Allow the player to use Zombe's cheats (including fly, Xray, etc.)
children:
nocheatplus.zombe.fly:
description: Allow the player to use Zombe's fly
nocheatplus.zombe.cheats:
description: Allow the player to use Zombe's cheats (including Xray, etc.)
nocheatplus.cjb:
description: Allow the player to use CJB's cheats (including fly, Xray, minimap, etc.)
children:
nocheatplus.cjb.fly:
description: Allow the player to use CJB's fly
nocheatplus.cjb.xray:
description: Allow the player to use CJB's Xray
nocheatplus.cjb.minimap:
description: Allow the player to use CJB's minimap

120
pom.xml
View File

@ -1,96 +1,102 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cc.co.evenprime.bukkit</groupId>
<artifactId>NoCheat</artifactId>
<version>3.5.0</version>
<!-- Informations -->
<name>NoCheatPlus</name>
<version>3.5.1</version>
<description>Detect and fight the exploitation of various flaws/bugs in Minecraft.</description>
<url>http://dev.bukkit.org/server-mods/nocheatplus</url>
<groupId>me.neatmonster.nocheatplus</groupId>
<artifactId>nocheatplus</artifactId>
<packaging>jar</packaging>
<name>NoCheat</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- License -->
<licenses>
<license>
<name>GNU General Public License v3</name>
<url>http://www.gnu.org/licenses/gpl-3.0.html</url>
<distribution>repo</distribution>
</license>
</licenses>
<!-- Source code -->
<scm>
<developerConnection>scm:git:git@github.com:NeatMonster/${project.name}.git</developerConnection>
<connection>scm:git:git://github.com/NeatMonster/${project.name}.git</connection>
<url>https://github.com/NeatMonster/${project.name}</url>
</scm>
<!-- Repositories -->
<repositories>
<repository>
<id>bukkit</id>
<name>Bukkit</name>
<url>http://repo.bukkit.org/content/groups/public/</url>
</repository>
</repositories>
<!-- Dependencies -->
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.1-R6</version>
<version>1.2.5-R1.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
</dependencies>
<distributionManagement>
<repository>
<id>repobo-rel</id>
<name>repo.bukkit.org Releases</name>
<url>http://repo.bukkit.org/content/repositories/releases/</url>
</repository>
<snapshotRepository>
<id>repobo-snap</id>
<name>repo.bukkit.org Snapshots</name>
<url>http://repo.bukkit.org/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
<repositories>
<repository>
<id>repobo-snap</id>
<url>http://repo.bukkit.org/content/groups/public</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>bukkit-plugins</id>
<url>http://repo.bukkit.org/content/groups/public</url>
</pluginRepository>
</pluginRepositories>
<description>Detect and Fight the exploitation of various Flaws/Bugs in Minecraft.</description>
<url>http://dev.bukkit.org/server-mods/nocheat</url>
<scm>
<connection>scm:git:https://github.com/Evenprime/NoCheat.git</connection>
<developerConnection>scm:git:https://github.com/Evenprime/NoCheat.git</developerConnection>
<url>https://github.com/Evenprime/NoCheat</url>
</scm>
<!-- Building -->
<build>
<defaultGoal>clean install</defaultGoal>
<sourceDirectory>${basedir}/src</sourceDirectory>
<resources>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>.</directory>
<directory>${basedir}</directory>
<includes>
<include>plugin.yml</include>
<include>README.txt</include>
<include>LICENSE_GPL3.txt</include>
<include>LICENSE_MIT.txt</include>
<include>LICENSE.txt</include>
<include>Instructions.txt</include>
</includes>
</resource>
</resources>
<defaultGoal>clean install</defaultGoal>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.1</version>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
<finalName>NoCheat</finalName>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<finalName>NoCheatPlus</finalName>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
<pomPropertiesFile>false</pomPropertiesFile>
<manifest>
<addDefaultSpecificationEntries>false</addDefaultSpecificationEntries>
<addDefaultImplementationEntries>false</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<!-- Properties -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@ -1,5 +0,0 @@
package cc.co.evenprime.bukkit.nocheat;
public interface ConfigItem {
}

View File

@ -1,206 +0,0 @@
package cc.co.evenprime.bukkit.nocheat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import cc.co.evenprime.bukkit.nocheat.checks.WorkaroundsListener;
import cc.co.evenprime.bukkit.nocheat.checks.blockbreak.BlockBreakCheckListener;
import cc.co.evenprime.bukkit.nocheat.checks.blockplace.BlockPlaceCheckListener;
import cc.co.evenprime.bukkit.nocheat.checks.chat.ChatCheckListener;
import cc.co.evenprime.bukkit.nocheat.checks.fight.FightCheckListener;
import cc.co.evenprime.bukkit.nocheat.checks.inventory.InventoryCheckListener;
import cc.co.evenprime.bukkit.nocheat.checks.moving.MovingCheckListener;
import cc.co.evenprime.bukkit.nocheat.command.CommandHandler;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationManager;
import cc.co.evenprime.bukkit.nocheat.config.NoCheatConfiguration;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.data.PlayerManager;
import cc.co.evenprime.bukkit.nocheat.debug.ActiveCheckPrinter;
import cc.co.evenprime.bukkit.nocheat.debug.LagMeasureTask;
/**
*
* NoCheat
*
* Check various player events for their plausibility and log/deny them/react to
* them based on configuration
*/
public class NoCheat extends JavaPlugin implements Listener {
private ConfigurationManager conf;
private CommandHandler commandHandler;
private PlayerManager players;
private List<EventManager> eventManagers;
private LagMeasureTask lagMeasureTask;
private Logger fileLogger;
public NoCheat() {
}
public void onDisable() {
PluginDescriptionFile pdfFile = this.getDescription();
if(lagMeasureTask != null) {
lagMeasureTask.cancel();
lagMeasureTask = null;
}
if(conf != null) {
conf.cleanup();
conf = null;
}
// Just to be sure nothing gets left out
getServer().getScheduler().cancelTasks(this);
commandHandler = null;
System.out.println("[NoCheat] version [" + pdfFile.getVersion() + "] is disabled.");
}
public void onEnable() {
// Then set up in memory per player data storage
this.players = new PlayerManager(this);
this.commandHandler = new CommandHandler(this);
// Then read the configuration files
this.conf = new ConfigurationManager(this, this.getDataFolder());
eventManagers = new ArrayList<EventManager>(8); // Big enough
// Then set up the event listeners
eventManagers.add(new MovingCheckListener(this));
eventManagers.add(new WorkaroundsListener());
eventManagers.add(new ChatCheckListener(this));
eventManagers.add(new BlockBreakCheckListener(this));
eventManagers.add(new BlockPlaceCheckListener(this));
eventManagers.add(new FightCheckListener(this));
eventManagers.add(new InventoryCheckListener(this));
// Then set up a task to monitor server lag
if(lagMeasureTask == null) {
lagMeasureTask = new LagMeasureTask(this);
lagMeasureTask.start();
}
// Then print a list of active checks per world
ActiveCheckPrinter.printActiveChecks(this, eventManagers);
// register all listeners
for(EventManager eventManager : eventManagers) {
Bukkit.getPluginManager().registerEvents(eventManager, this);
}
Bukkit.getPluginManager().registerEvents(this, this);
NoCheatConfiguration.writeInstructions(this.getDataFolder());
// Tell the server admin that we finished loading NoCheat now
System.out.println("[NoCheat] version [" + this.getDescription().getVersion() + "] is enabled.");
}
public ConfigurationCacheStore getConfig(Player player) {
if(player != null)
return getConfig(player.getWorld());
else
return conf.getConfigurationCacheForWorld(null);
}
public ConfigurationCacheStore getConfig(World world) {
if(world != null)
return conf.getConfigurationCacheForWorld(world.getName());
else
return conf.getConfigurationCacheForWorld(null);
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
boolean result = commandHandler.handleCommand(this, sender, command, label, args);
return result;
}
public boolean skipCheck() {
if(lagMeasureTask != null)
return lagMeasureTask.skipCheck();
return false;
}
public void reloadConfiguration() {
conf.cleanup();
this.conf = new ConfigurationManager(this, this.getDataFolder());
players.cleanDataMap();
}
/**
* Call this periodically to walk over the stored data map and remove
* old/unused entries
*
*/
public void cleanDataMap() {
players.cleanDataMap();
}
/**
* An interface method usable by other plugins to collect information about
* a player. It will include the plugin version, two timestamps (beginning
* and end of data collection for that player), and various data from
* checks)
*
* @param playerName
* a player name
* @return A newly created map of identifiers and corresponding values
*/
public Map<String, Object> getPlayerData(String playerName) {
Map<String, Object> map = players.getPlayerData(playerName);
map.put("nocheat.version", this.getDescription().getVersion());
return map;
}
public NoCheatPlayer getPlayer(Player player) {
return players.getPlayer(player);
}
@EventHandler(priority = EventPriority.MONITOR)
public void logEvent(NoCheatLogEvent event) {
if(event.toConsole()) {
// Console logs are not colored
System.out.println(Colors.removeColors(event.getPrefix() + event.getMessage()));
}
if(event.toChat()) {
for(Player player : Bukkit.getServer().getOnlinePlayers()) {
if(player.hasPermission(Permissions.ADMIN_CHATLOG)) {
// Chat logs are potentially colored
player.sendMessage(Colors.replaceColors(event.getPrefix() + event.getMessage()));
}
}
}
if(event.toFile()) {
// File logs are not colored
fileLogger.info(Colors.removeColors(event.getMessage()));
}
}
public void setFileLogger(Logger logger) {
this.fileLogger = logger;
}
}

View File

@ -1,30 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.actions;
/**
* Some wildcards that are used in commands and log messages
*/
public enum ParameterName {
PLAYER("player"), LOCATION("location"), WORLD("world"),
VIOLATIONS("violations"), MOVEDISTANCE("movedistance"),
REACHDISTANCE("reachdistance"), FALLDISTANCE("falldistance"),
LOCATION_TO("locationto"), CHECK("check"), PACKETS("packets"),
TEXT("text"), PLACE_LOCATION("placelocation"),
PLACE_AGAINST("placeagainst"), BLOCK_TYPE("blocktype"), LIMIT("limit"),
FOOD("food"), SERVERS("servers");
private final String s;
private ParameterName(String s) {
this.s = s;
}
public static final ParameterName get(String s) {
for(ParameterName c : ParameterName.values()) {
if(c.s.equals(s)) {
return c;
}
}
return null;
}
}

View File

@ -1,80 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.actions.types;
import java.util.ArrayList;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.Action;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.checks.Check;
/**
* Action with parameters is used to
*
*/
public abstract class ActionWithParameters extends Action {
private final ArrayList<Object> messageParts;
public ActionWithParameters(String name, int delay, int repeat, String message) {
super(name, delay, repeat);
messageParts = new ArrayList<Object>();
parseMessage(message);
}
private void parseMessage(String message) {
String parts[] = message.split("\\[", 2);
// No opening braces left
if(parts.length != 2) {
messageParts.add(message);
}
// Found an opening brace
else {
String parts2[] = parts[1].split("\\]", 2);
// Found no matching closing brace
if(parts2.length != 2) {
messageParts.add(message);
}
// Found a matching closing brace
else {
ParameterName w = ParameterName.get(parts2[0]);
if(w != null) {
// Found an existing wildcard inbetween the braces
messageParts.add(parts[0]);
messageParts.add(w);
// Go further down recursive
parseMessage(parts2[1]);
} else {
messageParts.add(message);
}
}
}
}
/**
* Get a string with all the wildcards replaced with data from LogData
*
* @param data
* @return
*/
protected String getMessage(NoCheatPlayer player, Check check) {
StringBuilder log = new StringBuilder(100); // Should be big enough most
// of the time
for(Object part : messageParts) {
if(part instanceof String) {
log.append((String) part);
} else {
log.append(check.getParameter((ParameterName) part, player));
}
}
return log.toString();
}
}

View File

@ -1,131 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.checks;
import java.util.Locale;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.command.CommandException;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatLogEvent;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.Action;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.actions.types.ActionList;
import cc.co.evenprime.bukkit.nocheat.actions.types.ConsolecommandAction;
import cc.co.evenprime.bukkit.nocheat.actions.types.DummyAction;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.actions.types.SpecialAction;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
/**
* The abstract Check class, providing some basic functionality
*
*/
public abstract class Check {
private final String name;
// used to bundle information of multiple checks
private final String groupId;
protected final NoCheat plugin;
public Check(NoCheat plugin, String groupId, String name) {
this.plugin = plugin;
this.groupId = groupId;
this.name = name;
}
/**
* Execute some actions for the specified player
*
* @param player
* @param actions
* @return
*/
protected final boolean executeActions(NoCheatPlayer player, ActionList actionList, double violationLevel) {
boolean special = false;
// Get the to be executed actions
Action[] actions = actionList.getActions(violationLevel);
final long time = System.currentTimeMillis() / 1000L;
// The configuration will be needed too
final ConfigurationCacheStore cc = player.getConfigurationStore();
for(Action ac : actions) {
if(player.getExecutionHistory().executeAction(groupId, ac, time)) {
// The executionHistory said it really is time to execute the
// action, find out what it is and do what is needed
if(ac instanceof LogAction && !player.hasPermission(actionList.permissionSilent)) {
executeLogAction((LogAction) ac, this, player, cc);
} else if(ac instanceof SpecialAction) {
special = true;
} else if(ac instanceof ConsolecommandAction) {
executeConsoleCommand((ConsolecommandAction) ac, this, player, cc);
} else if(ac instanceof DummyAction) {
// nothing - it's a "DummyAction" after all
}
}
}
return special;
}
/**
* Collect information about the players violations
*
* @param player
* @param id
* @param vl
*/
protected void incrementStatistics(NoCheatPlayer player, Id id, double vl) {
player.getDataStore().getStatistics().increment(id, vl);
}
private final void executeLogAction(LogAction l, Check check, NoCheatPlayer player, ConfigurationCacheStore cc) {
if(!cc.logging.active)
return;
// Fire one of our custom "Log" Events
Bukkit.getServer().getPluginManager().callEvent(new NoCheatLogEvent(cc.logging.prefix, l.getLogMessage(player, check), cc.logging.toConsole && l.toConsole(), cc.logging.toChat && l.toChat(), cc.logging.toFile && l.toFile()));
}
private final void executeConsoleCommand(ConsolecommandAction action, Check check, NoCheatPlayer player, ConfigurationCacheStore cc) {
final String command = action.getCommand(player, check);
try {
plugin.getServer().dispatchCommand(Bukkit.getConsoleSender(), command);
} catch(CommandException e) {
System.out.println("[NoCheat] failed to execute the command '" + command + "': " + e.getMessage() + ", please check if everything is setup correct.");
} catch(Exception e) {
// I don't care in this case, your problem if your command fails
}
}
/**
* Replace a parameter for commands or log actions with an actual
* value. Individual checks should override this to get their own
* parameters handled too.
*
* @param wildcard
* @param player
* @return
*/
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.PLAYER)
return player.getName();
else if(wildcard == ParameterName.CHECK)
return name;
else if(wildcard == ParameterName.LOCATION) {
Location l = player.getPlayer().getLocation();
return String.format(Locale.US, "%.2f,%.2f,%.2f", l.getX(), l.getY(), l.getZ());
} else if(wildcard == ParameterName.WORLD)
return player.getPlayer().getWorld().getName();
else
return "the Author was lazy and forgot to define " + wildcard + ".";
}
}

View File

@ -1,40 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.checks.chat;
import java.util.Locale;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
public class ColorCheck extends ChatCheck {
public ColorCheck(NoCheat plugin) {
super(plugin, "chat.color");
}
public boolean check(NoCheatPlayer player, ChatData data, ChatConfig cc) {
if(data.message.contains("\247")) {
data.colorVL += 1;
incrementStatistics(player, Id.CHAT_COLOR, 1);
boolean filter = executeActions(player, cc.colorActions, data.colorVL);
if(filter) {
// Remove color codes
data.message = data.message.replaceAll("\302\247.", "").replaceAll("\247.", "");
}
}
return false;
}
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).colorVL);
else
return super.getParameter(wildcard, player);
}
}

View File

@ -1,153 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.config;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import cc.co.evenprime.bukkit.nocheat.actions.Action;
import cc.co.evenprime.bukkit.nocheat.actions.types.ActionList;
import cc.co.evenprime.bukkit.nocheat.actions.types.ConsolecommandAction;
import cc.co.evenprime.bukkit.nocheat.actions.types.DummyAction;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.actions.types.SpecialAction;
/**
* Helps with creating Actions out of text string definitions
*
*/
public class ActionFactory {
private static final Map<String, Object> lib = new HashMap<String, Object>();
public ActionFactory(Map<String, Object> library) {
lib.putAll(library);
}
public Action createAction(String actionDefinition) {
actionDefinition = actionDefinition.toLowerCase();
if(actionDefinition.equals("cancel")) {
return new SpecialAction();
}
if(actionDefinition.startsWith("log:")) {
return parseLogAction(actionDefinition.split(":", 2)[1]);
}
if(actionDefinition.startsWith("cmd:")) {
return parseCmdAction(actionDefinition.split(":", 2)[1]);
}
throw new IllegalArgumentException("NoCheat doesn't understand action '" + actionDefinition + "' at all");
}
private Action parseCmdAction(String definition) {
String[] parts = definition.split(":");
String name = parts[0];
Object command = lib.get(parts[0]);
int delay = 0;
int repeat = 1;
if(command == null) {
throw new IllegalArgumentException("NoCheat doesn't know command '" + name + "'. Have you forgotten to define it?");
}
if(parts.length > 1) {
try {
delay = Integer.parseInt(parts[1]);
repeat = Integer.parseInt(parts[2]);
} catch(Exception e) {
System.out.println("NoCheat couldn't parse details of command '" + definition + "', will use default values instead.");
delay = 0;
repeat = 1;
}
}
return new ConsolecommandAction(name, delay, repeat, command.toString());
}
private Action parseLogAction(String definition) {
String[] parts = definition.split(":");
String name = parts[0];
Object message = lib.get(parts[0]);
int delay = 0;
int repeat = 1;
boolean toConsole = true;
boolean toFile = true;
boolean toChat = true;
if(message == null) {
throw new IllegalArgumentException("NoCheat doesn't know log message '" + name + "'. Have you forgotten to define it?");
}
try {
delay = Integer.parseInt(parts[1]);
repeat = Integer.parseInt(parts[2]);
toConsole = parts[3].contains("c");
toChat = parts[3].contains("i");
toFile = parts[3].contains("f");
} catch(Exception e) {
System.out.println("NoCheat couldn't parse details of log action '" + definition + "', will use default values instead.");
e.printStackTrace();
delay = 0;
repeat = 1;
toConsole = true;
toFile = true;
toChat = true;
}
return new LogAction(name, delay, repeat, toChat, toConsole, toFile, message.toString());
}
public Action[] createActions(String... definitions) {
List<Action> actions = new ArrayList<Action>();
for(String def : definitions) {
if(def.length() == 0)
continue;
try {
actions.add(createAction(def));
} catch(IllegalArgumentException e) {
System.out.println(e.getMessage());
actions.add(new DummyAction(def));
}
}
return actions.toArray(new Action[actions.size()]);
}
public ActionList createActionList(String definition, String permission) {
ActionList list = new ActionList(permission);
boolean first = true;
for(String s : definition.split("vl>")) {
s = s.trim();
if(s.length() == 0) {
first = false;
continue;
}
try {
Integer vl;
String def;
if(first) {
first = false;
vl = 0;
def = s;
} else {
String[] listEntry = s.split("\\s+", 2);
vl = Integer.parseInt(listEntry[0]);
def = listEntry[1];
}
list.setActions(vl, createActions(def.split("\\s+")));
} catch(Exception e) {
System.out.println("NoCheat couldn't parse action definition 'vl:" + s + "'");
}
}
return list;
}
}

View File

@ -1,44 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.config;
import java.util.HashMap;
import java.util.Map;
import cc.co.evenprime.bukkit.nocheat.ConfigItem;
/**
* A class to keep all configurables of the plugin associated with
* a world
*
*/
public class ConfigurationCacheStore {
public final LoggingConfig logging;
private final Map<String, ConfigItem> configMap = new HashMap<String, ConfigItem>();
private final NoCheatConfiguration data;
/**
* Instantiate a config cache and populate it with the data of a
* Config tree (and its parent tree)
*/
public ConfigurationCacheStore(NoCheatConfiguration data) {
logging = new LoggingConfig(data);
this.data = data;
}
@SuppressWarnings("unchecked")
public <T extends ConfigItem>T get(String id) {
return (T) configMap.get(id);
}
public void set(String id, ConfigItem config) {
configMap.put(id, config);
}
public NoCheatConfiguration getConfiguration() {
return this.data;
}
}

View File

@ -1,104 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.config;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.lang.reflect.Field;
import org.bukkit.configuration.MemorySection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.yaml.snakeyaml.DumperOptions;
import cc.co.evenprime.bukkit.nocheat.actions.Action;
import cc.co.evenprime.bukkit.nocheat.actions.types.ActionList;
public class NoCheatConfiguration extends YamlConfiguration {
private ActionFactory factory;
@Override
public String saveToString() {
// Some reflection wizardry to avoid having a lot of
// linebreaks in the yml file, and get a "footer" into the file
try {
Field op;
op = YamlConfiguration.class.getDeclaredField("yamlOptions");
op.setAccessible(true);
DumperOptions options = (DumperOptions) op.get(this);
options.setWidth(200);
} catch(Exception e) {}
String result = super.saveToString();
return result;
}
public static void writeInstructions(File rootConfigFolder) {
InputStream fis = NoCheatConfiguration.class.getClassLoader().getResourceAsStream("Instructions.txt");
StringBuffer result = new StringBuffer();
try {
byte[] buf = new byte[1024];
int i = 0;
while((i = fis.read(buf)) != -1) {
result.append(new String(buf).substring(0, i));
}
File iFile = new File(rootConfigFolder, "Instructions.txt");
if(iFile.exists()) {
iFile.delete();
}
FileWriter output = new FileWriter(iFile);
String nl = System.getProperty("line.separator");
String instructions = result.toString();
instructions = instructions.replaceAll("\r\n", "\n");
String lines[] = instructions.split("\n");
for(String line : lines) {
output.append(line);
output.append(nl);
}
output.flush();
output.close();
} catch(Exception e) {
e.printStackTrace();
}
}
/**
* Do this after reading new data
*/
public void regenerateActionLists() {
factory = new ActionFactory(((MemorySection) this.get(ConfPaths.STRINGS)).getValues(false));
}
/**
* A convenience method to get action lists from the config
* @param path
* @return
*/
public ActionList getActionList(String path, String permission) {
String value = this.getString(path);
return factory.createActionList(value, permission);
}
/**
* Savely store ActionLists back into the yml file
* @param path
* @param list
*/
public void set(String path, ActionList list) {
StringBuffer string = new StringBuffer();
for(int treshold : list.getTresholds()) {
if(treshold > 0) {
string.append(" vl>").append(treshold);
}
for(Action action : list.getActions(treshold)) {
string.append(" ").append(action);
}
}
set(path, string.toString().trim());
}
}

View File

@ -1,52 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.config;
/**
* The various permission nodes used by NoCheat
*
*/
public class Permissions {
private final static String NOCHEAT = "nocheat";
private final static String ADMIN = NOCHEAT + ".admin";
private final static String CHECKS = NOCHEAT + ".checks";
public final static String MOVING = CHECKS + ".moving";
public final static String MOVING_RUNFLY = MOVING + ".runfly";
public static final String MOVING_SWIMMING = MOVING + ".swimming";
public final static String MOVING_SNEAKING = MOVING + ".sneaking";
public final static String MOVING_FLYING = MOVING + ".flying";
public final static String MOVING_NOFALL = MOVING + ".nofall";
public final static String MOVING_MOREPACKETS = MOVING + ".morepackets";
public final static String BLOCKBREAK = CHECKS + ".blockbreak";
public final static String BLOCKBREAK_REACH = BLOCKBREAK + ".reach";
public final static String BLOCKBREAK_DIRECTION = BLOCKBREAK + ".direction";
public static final String BLOCKBREAK_NOSWING = BLOCKBREAK + ".noswing";
public final static String BLOCKPLACE = CHECKS + ".blockplace";
public final static String BLOCKPLACE_REACH = BLOCKPLACE + ".reach";
public static final String BLOCKPLACE_DIRECTION = BLOCKPLACE + ".direction";
public final static String CHAT = CHECKS + ".chat";
public final static String CHAT_SPAM = CHAT + ".spam";
public static final String CHAT_COLOR = CHAT + ".color";
public static final String FIGHT = CHECKS + ".fight";
public static final String FIGHT_DIRECTION = FIGHT + ".direction";
public static final String FIGHT_NOSWING = FIGHT + ".noswing";
public static final String FIGHT_REACH = FIGHT + ".reach";
public static final String FIGHT_SPEED = FIGHT + ".speed";
public static final String FIGHT_GODMODE = FIGHT + ".godmode";
public static final String FIGHT_INSTANTHEAL = FIGHT + ".instantheal";
public final static String ADMIN_CHATLOG = ADMIN + ".chatlog";
public static final String ADMIN_COMMANDS = ADMIN + ".commands";
public static final String ADMIN_RELOAD = ADMIN + ".reload";
public 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 Permissions() {}
}

View File

@ -1,73 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.data;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.player.NoCheatPlayerImpl;
/**
* Provide secure access to player-specific data objects for various checks or
* check groups.
*/
public class PlayerManager {
// Store data between Events
private final Map<String, NoCheatPlayerImpl> players;
private final NoCheat plugin;
public PlayerManager(NoCheat plugin) {
this.players = new HashMap<String, NoCheatPlayerImpl>();
this.plugin = plugin;
}
/**
* Get a data object of the specified class. If none is stored yet, create
* one.
*/
public NoCheatPlayer getPlayer(Player player) {
NoCheatPlayerImpl p = this.players.get(player.getName().toLowerCase());
if(p == null) {
p = new NoCheatPlayerImpl(player, plugin);
this.players.put(player.getName().toLowerCase(), p);
}
p.setLastUsedTime(System.currentTimeMillis());
p.refresh(player);
return p;
}
public void cleanDataMap() {
long time = System.currentTimeMillis();
List<String> removals = new ArrayList<String>(5);
for(Entry<String, NoCheatPlayerImpl> e : this.players.entrySet()) {
if(e.getValue().shouldBeRemoved(time)) {
removals.add(e.getKey());
}
}
for(String key : removals) {
this.players.remove(key);
}
}
public Map<String, Object> getPlayerData(String playerName) {
NoCheatPlayer player = this.players.get(playerName.toLowerCase());
if(player != null) {
return player.getDataStore().collectData();
}
return new HashMap<String, Object>();
}
}

View File

@ -1,72 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.data;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
public class Statistics {
public enum Id {
BB_DIRECTION("blockbreak.direction"), BB_NOSWING("blockbreak.noswing"),
BB_REACH("blockbreak.reach"), BP_DIRECTION("blockplace.direction"),
BP_REACH("blockplace.reach"), CHAT_COLOR("chat.color"),
CHAT_SPAM("chat.spam"), FI_DIRECTION("fight.direction"),
FI_NOSWING("fight.noswing"), FI_REACH("fight.reach"),
FI_SPEED("fight.speed"), INV_DROP("inventory.drop"),
INV_BOW("inventory.instantbow"), INV_EAT("inventory.instanteat"),
MOV_RUNNING("moving.running"), MOV_FLYING("moving.flying"),
MOV_MOREPACKETS("moving.morepackets"), MOV_NOFALL("moving.nofall"),
MOV_SNEAKING("moving.sneaking"), MOV_SWIMMING("moving.swimming"),
FI_GODMODE("fight.godmode"), FI_INSTANTHEAL("fight.instantheal");
private final String name;
private Id(String name) {
this.name = name;
}
public String toString() {
return this.name;
}
}
private final Map<Id, Double> statisticVLs = new HashMap<Id, Double>(Id.values().length);
private final Map<Id, Integer> statisticFails = new HashMap<Id, Integer>(Id.values().length);
public Statistics() {
// Initialize statistic values
for(Id id : Id.values()) {
statisticVLs.put(id, 0D);
statisticFails.put(id, 0);
}
}
public void increment(Id id, double vl) {
Double stored = statisticVLs.get(id);
if(stored == null)
stored = 0D;
statisticVLs.put(id, stored + vl);
Integer failed = statisticFails.get(id);
if(failed == null)
failed = 0;
statisticFails.put(id, failed + 1);
}
public Map<String, Object> get() {
Map<String, Object> map = new TreeMap<String, Object>();
for(Entry<Id, Double> entry : statisticVLs.entrySet()) {
map.put(entry.getKey().toString() + ".vl", entry.getValue().intValue());
}
for(Entry<Id, Integer> entry : statisticFails.entrySet()) {
map.put(entry.getKey().toString() + ".failed", entry.getValue());
}
return map;
}
}

View File

@ -1,56 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.debug;
import java.util.List;
import org.bukkit.World;
import cc.co.evenprime.bukkit.nocheat.EventManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
/**
* Prints the list of active checks per world on startup, if requested
*
*/
public class ActiveCheckPrinter {
public static void printActiveChecks(NoCheat plugin, List<EventManager> eventManagers) {
boolean introPrinted = false;
String intro = "[NoCheat] Active Checks: ";
// Print active checks for NoCheat, if needed.
for(World world : plugin.getServer().getWorlds()) {
StringBuilder line = new StringBuilder(" ").append(world.getName()).append(": ");
int length = line.length();
ConfigurationCacheStore cc = plugin.getConfig(world);
if(!cc.logging.showactivechecks)
continue;
for(EventManager em : eventManagers) {
if(em.getActiveChecks(cc).size() == 0)
continue;
for(String active : em.getActiveChecks(cc)) {
line.append(active).append(' ');
}
if(!introPrinted) {
System.out.println(intro);
introPrinted = true;
}
System.out.println(line.toString());
line = new StringBuilder(length);
for(int i = 0; i < length; i++) {
line.append(' ');
}
}
}
}
}

View File

@ -1,80 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.debug;
import org.bukkit.World;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
/**
* A task running in the background that measures tick time vs. real time
*
*/
public class LagMeasureTask implements Runnable {
private int ingameseconds = 1;
private long lastIngamesecondTime = System.currentTimeMillis();
private long lastIngamesecondDuration = 2000L;
private boolean skipCheck = false;
private int lagMeasureTaskId = -1;
private final NoCheat plugin;
public LagMeasureTask(NoCheat plugin) {
this.plugin = plugin;
}
public void start() {
// start measuring with a delay of 10 seconds
lagMeasureTaskId = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, this, 20, 20);
}
public void run() {
try {
boolean oldStatus = skipCheck;
// If the previous second took to long, skip checks during
// this second
skipCheck = lastIngamesecondDuration > 2000;
if(plugin.getConfig((World) null).logging.debugmessages) {
if(oldStatus != skipCheck && skipCheck) {
System.out.println("[NoCheat] detected server lag, some checks will not work.");
} else if(oldStatus != skipCheck && !skipCheck) {
System.out.println("[NoCheat] server lag seems to have stopped, reenabling checks.");
}
}
long time = System.currentTimeMillis();
lastIngamesecondDuration = time - lastIngamesecondTime;
if(lastIngamesecondDuration < 1000)
lastIngamesecondDuration = 1000;
else if(lastIngamesecondDuration > 3600000) {
lastIngamesecondDuration = 3600000; // top limit of 1
// hour per "second"
}
lastIngamesecondTime = time;
ingameseconds++;
// Check if some data is outdated now and let it be removed
if(ingameseconds % 62 == 0) {
plugin.cleanDataMap();
}
} catch(Exception e) {
// Just prevent this thread from dying for whatever reason
}
}
public void cancel() {
if(lagMeasureTaskId != -1) {
try {
plugin.getServer().getScheduler().cancelTask(lagMeasureTaskId);
} catch(Exception e) {
System.out.println("NoCheat: Couldn't cancel LagMeasureTask: " + e.getMessage());
}
lagMeasureTaskId = -1;
}
}
public boolean skipCheck() {
return skipCheck;
}
}

View File

@ -1,127 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.player;
import net.minecraft.server.EntityPlayer;
import net.minecraft.server.MobEffectList;
import org.bukkit.GameMode;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.data.DataStore;
import cc.co.evenprime.bukkit.nocheat.data.ExecutionHistory;
public class NoCheatPlayerImpl implements NoCheatPlayer {
private Player player;
private final NoCheat plugin;
private final DataStore data;
private ConfigurationCacheStore config;
private long lastUsedTime;
private final ExecutionHistory history;
public NoCheatPlayerImpl(Player player, NoCheat plugin) {
this.player = player;
this.plugin = plugin;
this.data = new DataStore();
this.history = new ExecutionHistory();
this.lastUsedTime = System.currentTimeMillis();
}
public void refresh(Player player) {
this.player = player;
this.config = plugin.getConfig(player);
}
public boolean isDead() {
return this.player.getHealth() <= 0 || this.player.isDead();
}
public boolean hasPermission(String permission) {
if(permission == null) {
// System.out.println("NoCheat: Warning, asked for null permission");
return false;
}
return player.hasPermission(permission);
}
public DataStore getDataStore() {
return data;
}
public ConfigurationCacheStore getConfigurationStore() {
return config;
}
public Player getPlayer() {
return player;
}
public String getName() {
return player.getName();
}
public int getTicksLived() {
return player.getTicksLived();
}
public float getSpeedAmplifier() {
EntityPlayer ep = ((CraftPlayer) player).getHandle();
if(ep.hasEffect(MobEffectList.FASTER_MOVEMENT)) {
// Taken directly from Minecraft code, should work
return 1.0F + 0.2F * (float) (ep.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier() + 1);
} else {
return 1.0F;
}
}
@Override
public float getJumpAmplifier() {
EntityPlayer ep = ((CraftPlayer) player).getHandle();
if(ep.hasEffect(MobEffectList.JUMP)) {
int amp = ep.getEffect(MobEffectList.JUMP).getAmplifier();
// Very rough estimates only
if(amp > 20) {
return 1.5F * (float) (ep.getEffect(MobEffectList.JUMP).getAmplifier() + 1);
} else {
return 1.2F * (float) (ep.getEffect(MobEffectList.JUMP).getAmplifier() + 1);
}
} else {
return 1.0F;
}
}
public boolean isSprinting() {
return player.isSprinting();
}
public void setLastUsedTime(long currentTimeInMilliseconds) {
this.lastUsedTime = currentTimeInMilliseconds;
}
public boolean shouldBeRemoved(long currentTimeInMilliseconds) {
if(lastUsedTime > currentTimeInMilliseconds) {
// Should never happen, but if it does, fix it somewhat
lastUsedTime = currentTimeInMilliseconds;
}
return lastUsedTime + 60000L < currentTimeInMilliseconds;
}
public boolean isCreative() {
return player.getGameMode() == GameMode.CREATIVE;
}
@Override
public ExecutionHistory getExecutionHistory() {
return history;
}
@Override
public void dealFallDamage() {
EntityPlayer p = ((CraftPlayer) player).getHandle();
p.b(0D, true);
}
}

View File

@ -1,31 +1,14 @@
package cc.co.evenprime.bukkit.nocheat;
package me.neatmonster.nocheatplus;
import org.bukkit.ChatColor;
/**
* Somehow manage color codes in NoCheat
* Somehow manage color codes in NoCheatPlus
*
*/
public class Colors {
/**
* Replace instances of &X with a color
*
* @param text
* @return
*/
public static String replaceColors(String text) {
for(ChatColor c : ChatColor.values()) {
text = text.replace("&" + c.getChar(), c.toString());
}
return text;
}
/**
/**
* Remove instances of &X
*
* @param text
@ -33,9 +16,22 @@ public class Colors {
*/
public static String removeColors(String text) {
for(ChatColor c : ChatColor.values()) {
for (final ChatColor c : ChatColor.values())
text = text.replace("&" + c.getChar(), "");
}
return text;
}
/**
* Replace instances of &X with a color
*
* @param text
* @return
*/
public static String replaceColors(String text) {
for (final ChatColor c : ChatColor.values())
text = text.replace("&" + c.getChar(), c.toString());
return text;
}

View File

@ -0,0 +1,5 @@
package me.neatmonster.nocheatplus;
public interface ConfigItem {
}

View File

@ -1,4 +1,4 @@
package cc.co.evenprime.bukkit.nocheat;
package me.neatmonster.nocheatplus;
/**
*

View File

@ -1,15 +1,19 @@
package cc.co.evenprime.bukkit.nocheat;
package me.neatmonster.nocheatplus;
import java.util.List;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import org.bukkit.event.Listener;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
public interface EventManager extends Listener {
/**
* Used for debug output, if checks are activated for the world-specific
* config that is given as a parameter
* @param cc The config
*
* @param cc
* The config
* @return A list of active/enabled checks
*/
public List<String> getActiveChecks(ConfigurationCacheStore cc);

View File

@ -0,0 +1,76 @@
package me.neatmonster.nocheatplus;
import org.bukkit.World;
/**
* A task running in the background that measures tick time vs. real time
*
*/
public class LagMeasureTask implements Runnable {
private int ingameseconds = 1;
private long lastIngamesecondTime = System.currentTimeMillis();
private long lastIngamesecondDuration = 2000L;
private boolean skipCheck = false;
private int lagMeasureTaskId = -1;
private final NoCheatPlus plugin;
public LagMeasureTask(final NoCheatPlus plugin) {
this.plugin = plugin;
}
public void cancel() {
if (lagMeasureTaskId != -1) {
try {
plugin.getServer().getScheduler().cancelTask(lagMeasureTaskId);
} catch (final Exception e) {
System.out.println("NoCheatPlus: Couldn't cancel LagMeasureTask: " + e.getMessage());
}
lagMeasureTaskId = -1;
}
}
@Override
public void run() {
try {
final boolean oldStatus = skipCheck;
// If the previous second took to long, skip checks during
// this second
skipCheck = lastIngamesecondDuration > 2000;
if (plugin.getConfig((World) null).logging.debugmessages)
if (oldStatus != skipCheck && skipCheck)
System.out.println("[NoCheatPlus] detected server lag, some checks will not work.");
else if (oldStatus != skipCheck && !skipCheck)
System.out.println("[NoCheatPlus] server lag seems to have stopped, reenabling checks.");
final long time = System.currentTimeMillis();
lastIngamesecondDuration = time - lastIngamesecondTime;
if (lastIngamesecondDuration < 1000)
lastIngamesecondDuration = 1000;
else if (lastIngamesecondDuration > 3600000)
lastIngamesecondDuration = 3600000; // top limit of 1
// hour per "second"
lastIngamesecondTime = time;
ingameseconds++;
// Check if some data is outdated now and let it be removed
if (ingameseconds % 62 == 0)
plugin.cleanDataMap();
} catch (final Exception e) {
// Just prevent this thread from dying for whatever reason
}
}
public boolean skipCheck() {
return skipCheck;
}
public void start() {
// start measuring with a delay of 10 seconds
lagMeasureTaskId = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, this, 20, 20);
}
}

View File

@ -0,0 +1,224 @@
package me.neatmonster.nocheatplus;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import me.neatmonster.nocheatplus.checks.WorkaroundsListener;
import me.neatmonster.nocheatplus.checks.blockbreak.BlockBreakCheckListener;
import me.neatmonster.nocheatplus.checks.blockplace.BlockPlaceCheckListener;
import me.neatmonster.nocheatplus.checks.chat.ChatCheckListener;
import me.neatmonster.nocheatplus.checks.fight.FightCheckListener;
import me.neatmonster.nocheatplus.checks.inventory.InventoryCheckListener;
import me.neatmonster.nocheatplus.checks.moving.MovingCheckListener;
import me.neatmonster.nocheatplus.command.CommandHandler;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import me.neatmonster.nocheatplus.config.ConfigurationManager;
import me.neatmonster.nocheatplus.config.NoCheatPlusConfiguration;
import me.neatmonster.nocheatplus.config.Permissions;
import me.neatmonster.nocheatplus.data.PlayerManager;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
/**
*
* NoCheatPlus
*
* Check various player events for their plausibility and log/deny them/react to
* them based on configuration
*/
public class NoCheatPlus extends JavaPlugin implements Listener {
private ConfigurationManager conf;
private CommandHandler commandHandler;
private PlayerManager players;
private List<EventManager> eventManagers;
private LagMeasureTask lagMeasureTask;
private Logger fileLogger;
public NoCheatPlus() {
}
/**
* Call this periodically to walk over the stored data map and remove
* old/unused entries
*
*/
public void cleanDataMap() {
players.cleanDataMap();
}
public ConfigurationCacheStore getConfig(final Player player) {
if (player != null)
return getConfig(player.getWorld());
else
return conf.getConfigurationCacheForWorld(null);
}
public ConfigurationCacheStore getConfig(final World world) {
if (world != null)
return conf.getConfigurationCacheForWorld(world.getName());
else
return conf.getConfigurationCacheForWorld(null);
}
public NoCheatPlusPlayer getPlayer(final Player player) {
return players.getPlayer(player);
}
/**
* An interface method usable by other plugins to collect information about
* a player. It will include the plugin version, two timestamps (beginning
* and end of data collection for that player), and various data from
* checks)
*
* @param playerName
* a player name
* @return A newly created map of identifiers and corresponding values
*/
public Map<String, Object> getPlayerData(final String playerName) {
final Map<String, Object> map = players.getPlayerData(playerName);
map.put("nocheatplus.version", getDescription().getVersion());
return map;
}
@EventHandler(
priority = EventPriority.MONITOR)
public void logEvent(final NoCheatPlusLogEvent event) {
if (event.toConsole())
// Console logs are not colored
System.out.println(Colors.removeColors(event.getPrefix() + event.getMessage()));
if (event.toChat())
for (final Player player : Bukkit.getServer().getOnlinePlayers())
if (player.hasPermission(Permissions.ADMIN_CHATLOG))
// Chat logs are potentially colored
player.sendMessage(Colors.replaceColors(event.getPrefix() + event.getMessage()));
if (event.toFile())
// File logs are not colored
fileLogger.info(Colors.removeColors(event.getMessage()));
}
@Override
public boolean onCommand(final CommandSender sender, final Command command, final String label, final String[] args) {
final boolean result = commandHandler.handleCommand(this, sender, command, label, args);
return result;
}
@Override
public void onDisable() {
final PluginDescriptionFile pdfFile = getDescription();
if (lagMeasureTask != null) {
lagMeasureTask.cancel();
lagMeasureTask = null;
}
if (conf != null) {
conf.cleanup();
conf = null;
}
// Just to be sure nothing gets left out
getServer().getScheduler().cancelTasks(this);
commandHandler = null;
System.out.println("[NoCheatPlus] version [" + pdfFile.getVersion() + "] is disabled.");
}
@Override
public void onEnable() {
// Then set up in memory per player data storage
players = new PlayerManager(this);
commandHandler = new CommandHandler(this);
// Then read the configuration files
conf = new ConfigurationManager(this, getDataFolder());
eventManagers = new ArrayList<EventManager>(8); // Big enough
// Then set up the event listeners
eventManagers.add(new MovingCheckListener(this));
eventManagers.add(new WorkaroundsListener());
eventManagers.add(new ChatCheckListener(this));
eventManagers.add(new BlockBreakCheckListener(this));
eventManagers.add(new BlockPlaceCheckListener(this));
eventManagers.add(new FightCheckListener(this));
eventManagers.add(new InventoryCheckListener(this));
// Then set up a task to monitor server lag
if (lagMeasureTask == null) {
lagMeasureTask = new LagMeasureTask(this);
lagMeasureTask.start();
}
// register all listeners
for (final EventManager eventManager : eventManagers)
Bukkit.getPluginManager().registerEvents(eventManager, this);
Bukkit.getPluginManager().registerEvents(this, this);
NoCheatPlusConfiguration.writeInstructions(this);
// Tell the server admin that we finished loading NoCheatPlus now
System.out.println("[NoCheatPlus] version [" + getDescription().getVersion() + "] is enabled.");
}
@EventHandler(
ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onPlayerJoin(final PlayerJoinEvent event) {
final Player player = event.getPlayer();
String message = "";
// Disable Zombe's fly mod
if (!player.hasPermission(Permissions.ZOMBE_FLY))
message = message + "§f §f §1 §0 §2 §4";
// Disable Zombe's cheats
if (!player.hasPermission(Permissions.ZOMBE_CHEATS))
message = message + "§f §f §2 §0 §4 §8";
// Disable CJB's fly mod
if (!player.hasPermission(Permissions.CJB_FLY))
message = message + "§3 §9 §2 §0 §0 §1";
// Disable CJB's XRay
if (!player.hasPermission(Permissions.CJB_XRAY))
message = message + "§3 §9 §2 §0 §0 §2";
// Disable CJB's minimap
if (!player.hasPermission(Permissions.CJB_MINIMAP))
message = message + "§3 §9 §2 §0 §0 §3";
player.sendMessage(message);
}
public void reloadConfiguration() {
conf.cleanup();
conf = new ConfigurationManager(this, getDataFolder());
players.cleanDataMap();
}
public void setFileLogger(final Logger logger) {
fileLogger = logger;
}
public boolean skipCheck() {
if (lagMeasureTask != null)
return lagMeasureTask.skipCheck();
return false;
}
}

View File

@ -1,18 +1,23 @@
package cc.co.evenprime.bukkit.nocheat;
package me.neatmonster.nocheatplus;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public class NoCheatLogEvent extends Event {
public class NoCheatPlusLogEvent extends Event {
private static final long serialVersionUID = 1L;
private static final HandlerList handlers = new HandlerList();
private static final HandlerList handlers = new HandlerList();
private String message;
private String prefix;
private boolean toConsole, toChat, toFile;
public static HandlerList getHandlerList() {
return handlers;
}
public NoCheatLogEvent(String prefix, String message, boolean toConsole, boolean toChat, boolean toFile) {
private String message;
private String prefix;
private boolean toConsole, toChat, toFile;
public NoCheatPlusLogEvent(final String prefix, final String message, final boolean toConsole,
final boolean toChat, final boolean toFile) {
this.prefix = prefix;
this.message = message;
this.toConsole = toConsole;
@ -20,27 +25,36 @@ public class NoCheatLogEvent extends Event {
this.toFile = toFile;
}
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
@Override
public HandlerList getHandlers() {
return handlers;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
public String getPrefix() {
return prefix;
}
public void setMessage(final String message) {
this.message = message;
}
public boolean toFile() {
return toFile;
public void setPrefix(final String prefix) {
this.prefix = prefix;
}
public void setToFile(boolean toFile) {
public void setToChat(final boolean toChat) {
this.toChat = toChat;
}
public void setToConsole(final boolean toConsole) {
this.toConsole = toConsole;
}
public void setToFile(final boolean toFile) {
this.toFile = toFile;
}
@ -48,23 +62,11 @@ public class NoCheatLogEvent extends Event {
return toChat;
}
public void setToChat(boolean toChat) {
this.toChat = toChat;
}
public boolean toConsole() {
return toConsole;
}
public void setToConsole(boolean toConsole) {
this.toConsole = toConsole;
}
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
public boolean toFile() {
return toFile;
}
}

View File

@ -1,36 +1,37 @@
package cc.co.evenprime.bukkit.nocheat;
package me.neatmonster.nocheatplus;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import me.neatmonster.nocheatplus.data.DataStore;
import me.neatmonster.nocheatplus.data.ExecutionHistory;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.data.DataStore;
import cc.co.evenprime.bukkit.nocheat.data.ExecutionHistory;
public interface NoCheatPlayer {
public interface NoCheatPlusPlayer {
public boolean hasPermission(String permission);
public void dealFallDamage();
public ConfigurationCacheStore getConfigurationStore();
public DataStore getDataStore();
public ExecutionHistory getExecutionHistory();
public float getJumpAmplifier();
public String getName();
public Player getPlayer();
public DataStore getDataStore();
public float getSpeedAmplifier();
public int getTicksLived();
public boolean hasPermission(String permission);
public boolean isCreative();
public boolean isDead();
public boolean isSprinting();
public int getTicksLived();
public ConfigurationCacheStore getConfigurationStore();
public float getSpeedAmplifier();
public float getJumpAmplifier();
public boolean isCreative();
public ExecutionHistory getExecutionHistory();
public void dealFallDamage();
}

View File

@ -0,0 +1,131 @@
package me.neatmonster.nocheatplus;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import me.neatmonster.nocheatplus.data.DataStore;
import me.neatmonster.nocheatplus.data.ExecutionHistory;
import net.minecraft.server.EntityPlayer;
import net.minecraft.server.MobEffectList;
import org.bukkit.GameMode;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
public class NoCheatPlusPlayerImpl implements NoCheatPlusPlayer {
private Player player;
private final NoCheatPlus plugin;
private final DataStore data;
private ConfigurationCacheStore config;
private long lastUsedTime;
private final ExecutionHistory history;
public NoCheatPlusPlayerImpl(final Player player, final NoCheatPlus plugin) {
this.player = player;
this.plugin = plugin;
data = new DataStore();
history = new ExecutionHistory();
lastUsedTime = System.currentTimeMillis();
}
@Override
public void dealFallDamage() {
final EntityPlayer p = ((CraftPlayer) player).getHandle();
p.b(0D, true);
}
@Override
public ConfigurationCacheStore getConfigurationStore() {
return config;
}
@Override
public DataStore getDataStore() {
return data;
}
@Override
public ExecutionHistory getExecutionHistory() {
return history;
}
@Override
public float getJumpAmplifier() {
final EntityPlayer ep = ((CraftPlayer) player).getHandle();
if (ep.hasEffect(MobEffectList.JUMP)) {
final int amp = ep.getEffect(MobEffectList.JUMP).getAmplifier();
// Very rough estimates only
if (amp > 20)
return 1.5F * (ep.getEffect(MobEffectList.JUMP).getAmplifier() + 1);
else
return 1.2F * (ep.getEffect(MobEffectList.JUMP).getAmplifier() + 1);
} else
return 1.0F;
}
@Override
public String getName() {
return player.getName();
}
@Override
public Player getPlayer() {
return player;
}
@Override
public float getSpeedAmplifier() {
final EntityPlayer ep = ((CraftPlayer) player).getHandle();
if (ep.hasEffect(MobEffectList.FASTER_MOVEMENT))
// Taken directly from Minecraft code, should work
return 1.0F + 0.2F * (ep.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier() + 1);
else
return 1.0F;
}
@Override
public int getTicksLived() {
return player.getTicksLived();
}
@Override
public boolean hasPermission(final String permission) {
if (permission == null)
// System.out.println("NoCheatPlus: Warning, asked for null permission");
return false;
return player.hasPermission(permission);
}
@Override
public boolean isCreative() {
return player.getGameMode() == GameMode.CREATIVE || player.getAllowFlight();
}
@Override
public boolean isDead() {
return player.getHealth() <= 0 || player.isDead();
}
@Override
public boolean isSprinting() {
return player.isSprinting();
}
public void refresh(final Player player) {
this.player = player;
config = plugin.getConfig(player);
}
public void setLastUsedTime(final long currentTimeInMilliseconds) {
lastUsedTime = currentTimeInMilliseconds;
}
public boolean shouldBeRemoved(final long currentTimeInMilliseconds) {
if (lastUsedTime > currentTimeInMilliseconds)
// Should never happen, but if it does, fix it somewhat
lastUsedTime = currentTimeInMilliseconds;
return lastUsedTime + 60000L < currentTimeInMilliseconds;
}
}

View File

@ -1,4 +1,4 @@
package cc.co.evenprime.bukkit.nocheat.actions;
package me.neatmonster.nocheatplus.actions;
/**
* An action gets executed as the result of a failed check. If it 'really' gets
@ -16,9 +16,9 @@ public abstract class Action {
public final int delay;
/**
* Repeat only every "repeat" seconds. An "ExecutionHistory" will use this
* Repeat only every "repeat" seconds. An "ExecutionHistory" will use this
* info to make sure that there were at least "repeat" seconds between the
* last execution of this action and this execution.
* last execution of this action and this execution.
*/
public final int repeat;
@ -27,7 +27,7 @@ public abstract class Action {
*/
public final String name;
public Action(String name, int delay, int repeat) {
public Action(final String name, final int delay, final int repeat) {
this.name = name;
this.delay = delay;
this.repeat = repeat;

View File

@ -0,0 +1,38 @@
package me.neatmonster.nocheatplus.actions;
/**
* Some wildcards that are used in commands and log messages
*/
public enum ParameterName {
PLAYER("player"),
LOCATION("location"),
WORLD("world"),
VIOLATIONS("violations"),
MOVEDISTANCE("movedistance"),
REACHDISTANCE("reachdistance"),
FALLDISTANCE("falldistance"),
LOCATION_TO("locationto"),
CHECK("check"),
PACKETS("packets"),
TEXT("text"),
PLACE_LOCATION("placelocation"),
PLACE_AGAINST("placeagainst"),
BLOCK_TYPE("blocktype"),
LIMIT("limit"),
FOOD("food"),
SERVERS("servers");
public static final ParameterName get(final String s) {
for (final ParameterName c : ParameterName.values())
if (c.s.equals(s))
return c;
return null;
}
private final String s;
private ParameterName(final String s) {
this.s = s;
}
}

View File

@ -1,11 +1,12 @@
package cc.co.evenprime.bukkit.nocheat.actions.types;
package me.neatmonster.nocheatplus.actions.types;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import cc.co.evenprime.bukkit.nocheat.actions.Action;
import me.neatmonster.nocheatplus.actions.Action;
/**
* A list of actions, that associates actions to tresholds. It allows to
@ -16,11 +17,7 @@ public class ActionList {
// This is a very bad design decision, but it's also really
// convenient to define this here
public final String permissionSilent;
public ActionList(String permission) {
this.permissionSilent = permission + ".silent";
}
public final String permissionSilent;
// If there are no actions registered, we still return an Array. It's
// just empty/size=0
@ -32,44 +29,28 @@ public class ActionList {
// The tresholds of this list
private final List<Integer> tresholds = new ArrayList<Integer>();
/**
* Add an entry to this actionList. The list will be sorted by tresholds
* automatically after the insertion.
*
* @param treshold The minimum violation level a player needs to have
* to be suspected to the given actions
* @param actions The actions that will be used if the player reached the
* accompanying treshold/violation level
*/
public void setActions(Integer treshold, Action[] actions) {
if(!this.tresholds.contains(treshold)) {
this.tresholds.add(treshold);
Collections.sort(this.tresholds);
}
this.actions.put(treshold, actions);
public ActionList(final String permission) {
permissionSilent = permission + ".silent";
}
/**
* Get a list of actions that match the violation level.
* The only method that has to be called by a check
*
* @param violationLevel The violation level that should be matched.
* @return The array of actions whose treshold was closest to the
* violationLevel but not bigger
* @param violationLevel
* The violation level that should be matched.
* @return The array of actions whose treshold was closest to the
* violationLevel but not bigger
*/
public Action[] getActions(double violationLevel) {
public Action[] getActions(final double violationLevel) {
Integer result = null;
for(Integer treshold : tresholds) {
if(treshold <= violationLevel) {
for (final Integer treshold : tresholds)
if (treshold <= violationLevel)
result = treshold;
}
}
if(result != null)
if (result != null)
return actions.get(result);
else
return emptyArray;
@ -78,9 +59,31 @@ public class ActionList {
/**
* Get a sorted list of the tresholds/violation levels that were used
* in this list
*
* @return The sorted list of tresholds
*/
public List<Integer> getTresholds() {
return tresholds;
}
/**
* Add an entry to this actionList. The list will be sorted by tresholds
* automatically after the insertion.
*
* @param treshold
* The minimum violation level a player needs to have
* to be suspected to the given actions
* @param actions
* The actions that will be used if the player reached the
* accompanying treshold/violation level
*/
public void setActions(final Integer treshold, final Action[] actions) {
if (!tresholds.contains(treshold)) {
tresholds.add(treshold);
Collections.sort(tresholds);
}
this.actions.put(treshold, actions);
}
}

View File

@ -0,0 +1,74 @@
package me.neatmonster.nocheatplus.actions.types;
import java.util.ArrayList;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.Action;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.checks.Check;
/**
* Action with parameters is used to
*
*/
public abstract class ActionWithParameters extends Action {
private final ArrayList<Object> messageParts;
public ActionWithParameters(final String name, final int delay, final int repeat, final String message) {
super(name, delay, repeat);
messageParts = new ArrayList<Object>();
parseMessage(message);
}
/**
* Get a string with all the wildcards replaced with data from LogData
*
* @param data
* @return
*/
protected String getMessage(final NoCheatPlusPlayer player, final Check check) {
final StringBuilder log = new StringBuilder(100); // Should be big enough most
// of the time
for (final Object part : messageParts)
if (part instanceof String)
log.append((String) part);
else
log.append(check.getParameter((ParameterName) part, player));
return log.toString();
}
private void parseMessage(final String message) {
final String parts[] = message.split("\\[", 2);
// No opening braces left
if (parts.length != 2)
messageParts.add(message);
else {
final String parts2[] = parts[1].split("\\]", 2);
// Found no matching closing brace
if (parts2.length != 2)
messageParts.add(message);
else {
final ParameterName w = ParameterName.get(parts2[0]);
if (w != null) {
// Found an existing wildcard inbetween the braces
messageParts.add(parts[0]);
messageParts.add(w);
// Go further down recursive
parseMessage(parts2[1]);
} else
messageParts.add(message);
}
}
}
}

View File

@ -1,7 +1,7 @@
package cc.co.evenprime.bukkit.nocheat.actions.types;
package me.neatmonster.nocheatplus.actions.types;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.checks.Check;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.checks.Check;
/**
* Execute a command by imitating an admin typing the command directly into the
@ -10,7 +10,7 @@ import cc.co.evenprime.bukkit.nocheat.checks.Check;
*/
public class ConsolecommandAction extends ActionWithParameters {
public ConsolecommandAction(String name, int delay, int repeat, String command) {
public ConsolecommandAction(final String name, final int delay, final int repeat, final String command) {
// Log messages may have color codes now
super(name, delay, repeat, command);
}
@ -20,11 +20,13 @@ public class ConsolecommandAction extends ActionWithParameters {
* information, make a nice String out of it that can be directly used
* as a command in the console.
*
* @param player The player that is used to fill in missing data
* @param check The check that is used to fill in missing data
* @param player
* The player that is used to fill in missing data
* @param check
* The check that is used to fill in missing data
* @return The complete, ready to use, command
*/
public String getCommand(NoCheatPlayer player, Check check) {
public String getCommand(final NoCheatPlusPlayer player, final Check check) {
return super.getMessage(player, check);
}
@ -32,6 +34,7 @@ public class ConsolecommandAction extends ActionWithParameters {
* Convert the commands data into a string that can be used in the config
* files
*/
@Override
public String toString() {
return "cmd:" + name + ":" + delay + ":" + repeat;
}

View File

@ -1,22 +1,23 @@
package cc.co.evenprime.bukkit.nocheat.actions.types;
package me.neatmonster.nocheatplus.actions.types;
import cc.co.evenprime.bukkit.nocheat.actions.Action;
import me.neatmonster.nocheatplus.actions.Action;
/**
* If an action can't be parsed correctly, at least keep it
* stored in this form to not lose it when loading/storing the config file
*
*
*/
public class DummyAction extends Action {
// The original string used for this action definition
private final String def;
public DummyAction(String def) {
public DummyAction(final String def) {
super("dummyAction", 10000, 10000);
this.def = def;
}
@Override
public String toString() {
return def;
}

View File

@ -1,7 +1,7 @@
package cc.co.evenprime.bukkit.nocheat.actions.types;
package me.neatmonster.nocheatplus.actions.types;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.checks.Check;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.checks.Check;
/**
* Print a log message to various locations
@ -15,7 +15,8 @@ public class LogAction extends ActionWithParameters {
private final boolean toConsole;
private final boolean toFile;
public LogAction(String name, int delay, int repeat, boolean toChat, boolean toConsole, boolean toFile, String message) {
public LogAction(final String name, final int delay, final int repeat, final boolean toChat,
final boolean toConsole, final boolean toFile, final String message) {
super(name, delay, repeat, message);
this.toChat = toChat;
this.toConsole = toConsole;
@ -25,16 +26,20 @@ public class LogAction extends ActionWithParameters {
/**
* Parse the final log message out of various data from the player and
* check that triggered the action.
* @param player The player that is used as a source for the log message
* @param check The check that is used as a source for the log message
*
* @param player
* The player that is used as a source for the log message
* @param check
* The check that is used as a source for the log message
* @return
*/
public String getLogMessage(NoCheatPlayer player, Check check) {
public String getLogMessage(final NoCheatPlusPlayer player, final Check check) {
return super.getMessage(player, check);
}
/**
* Should the message be shown in chat?
*
* @return true, if yes
*/
public boolean toChat() {
@ -43,6 +48,7 @@ public class LogAction extends ActionWithParameters {
/**
* Should the message be shown in the console?
*
* @return true, if yes
*/
public boolean toConsole() {
@ -51,6 +57,7 @@ public class LogAction extends ActionWithParameters {
/**
* Should the message be written to the logfile?
*
* @return true, if yes
*/
public boolean toFile() {
@ -60,7 +67,9 @@ public class LogAction extends ActionWithParameters {
/**
* Create the string that's used to define the action in the logfile
*/
@Override
public String toString() {
return "log:" + name + ":" + delay + ":" + repeat + ":" + (toConsole ? "c" : "") + (toChat ? "i" : "") + (toFile ? "f" : "");
return "log:" + name + ":" + delay + ":" + repeat + ":" + (toConsole ? "c" : "") + (toChat ? "i" : "")
+ (toFile ? "f" : "");
}
}

View File

@ -1,6 +1,6 @@
package cc.co.evenprime.bukkit.nocheat.actions.types;
package me.neatmonster.nocheatplus.actions.types;
import cc.co.evenprime.bukkit.nocheat.actions.Action;
import me.neatmonster.nocheatplus.actions.Action;
/**
* Do something check-specific. Usually that is to cancel the event, undo
@ -13,6 +13,7 @@ public class SpecialAction extends Action {
super("cancel", 0, 0);
}
@Override
public String toString() {
return "cancel";
}

View File

@ -0,0 +1,139 @@
package me.neatmonster.nocheatplus.checks;
import java.util.Locale;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusLogEvent;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.Action;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.actions.types.ActionList;
import me.neatmonster.nocheatplus.actions.types.ConsolecommandAction;
import me.neatmonster.nocheatplus.actions.types.DummyAction;
import me.neatmonster.nocheatplus.actions.types.LogAction;
import me.neatmonster.nocheatplus.actions.types.SpecialAction;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import me.neatmonster.nocheatplus.data.Statistics.Id;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.command.CommandException;
/**
* The abstract Check class, providing some basic functionality
*
*/
public abstract class Check {
private final String name;
// used to bundle information of multiple checks
private final String groupId;
protected final NoCheatPlus plugin;
public Check(final NoCheatPlus plugin, final String groupId, final String name) {
this.plugin = plugin;
this.groupId = groupId;
this.name = name;
}
/**
* Execute some actions for the specified player
*
* @param player
* @param actions
* @return
*/
protected boolean executeActions(final NoCheatPlusPlayer player, final ActionList actionList,
final double violationLevel) {
boolean special = false;
// Get the to be executed actions
final Action[] actions = actionList.getActions(violationLevel);
final long time = System.currentTimeMillis() / 1000L;
// The configuration will be needed too
final ConfigurationCacheStore cc = player.getConfigurationStore();
for (final Action ac : actions)
if (player.getExecutionHistory().executeAction(groupId, ac, time))
// The executionHistory said it really is time to execute the
// action, find out what it is and do what is needed
if (ac instanceof LogAction && !player.hasPermission(actionList.permissionSilent))
executeLogAction((LogAction) ac, this, player, cc);
else if (ac instanceof SpecialAction)
special = true;
else if (ac instanceof ConsolecommandAction)
executeConsoleCommand((ConsolecommandAction) ac, this, player, cc);
else if (ac instanceof DummyAction) {
// nothing - it's a "DummyAction" after all
}
return special;
}
private void executeConsoleCommand(final ConsolecommandAction action, final Check check,
final NoCheatPlusPlayer player, final ConfigurationCacheStore cc) {
final String command = action.getCommand(player, check);
try {
plugin.getServer().dispatchCommand(Bukkit.getConsoleSender(), command);
} catch (final CommandException e) {
System.out.println("[NoCheatPlus] failed to execute the command '" + command + "': " + e.getMessage()
+ ", please check if everything is setup correct.");
} catch (final Exception e) {
// I don't care in this case, your problem if your command fails
}
}
private void executeLogAction(final LogAction l, final Check check, final NoCheatPlusPlayer player,
final ConfigurationCacheStore cc) {
if (!cc.logging.active)
return;
// Fire one of our custom "Log" Events
Bukkit.getServer()
.getPluginManager()
.callEvent(
new NoCheatPlusLogEvent(cc.logging.prefix, l.getLogMessage(player, check), cc.logging.toConsole
&& l.toConsole(), cc.logging.toChat && l.toChat(), cc.logging.toFile && l.toFile()));
}
/**
* Replace a parameter for commands or log actions with an actual
* value. Individual checks should override this to get their own
* parameters handled too.
*
* @param wildcard
* @param player
* @return
*/
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if (wildcard == ParameterName.PLAYER)
return player.getName();
else if (wildcard == ParameterName.CHECK)
return name;
else if (wildcard == ParameterName.LOCATION) {
final Location l = player.getPlayer().getLocation();
return String.format(Locale.US, "%.2f,%.2f,%.2f", l.getX(), l.getY(), l.getZ());
} else if (wildcard == ParameterName.WORLD)
return player.getPlayer().getWorld().getName();
else
return "the Author was lazy and forgot to define " + wildcard + ".";
}
/**
* Collect information about the players violations
*
* @param player
* @param id
* @param vl
*/
protected void incrementStatistics(final NoCheatPlusPlayer player, final Id id, final double vl) {
player.getDataStore().getStatistics().increment(id, vl);
}
}

View File

@ -1,15 +1,14 @@
package cc.co.evenprime.bukkit.nocheat.checks;
package me.neatmonster.nocheatplus.checks;
import java.util.HashSet;
import java.util.Set;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.data.PreciseLocation;
import net.minecraft.server.Block;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.data.PreciseLocation;
/**
* Some stuff that's used by different checks or just too complex to keep
@ -18,106 +17,49 @@ import cc.co.evenprime.bukkit.nocheat.data.PreciseLocation;
*/
public class CheckUtil {
/**
* Check if a player looks at a target of a specific size, with a specific
* precision value (roughly)
*/
public static final double directionCheck(final NoCheatPlayer player, final double targetX, final double targetY, final double targetZ, final double targetWidth, final double targetHeight, final double precision) {
private final static double magic = 0.45D;
// Eye location of the player
final Location eyes = player.getPlayer().getEyeLocation();
private final static double magic2 = 0.55D;
final double factor = Math.sqrt(Math.pow(eyes.getX() - targetX, 2) + Math.pow(eyes.getY() - targetY, 2) + Math.pow(eyes.getZ() - targetZ, 2));
// View direction of the player
final Vector direction = eyes.getDirection();
final double x = ((double) targetX) - eyes.getX();
final double y = ((double) targetY) - eyes.getY();
final double z = ((double) targetZ) - eyes.getZ();
final double xPrediction = factor * direction.getX();
final double yPrediction = factor * direction.getY();
final double zPrediction = factor * direction.getZ();
double off = 0.0D;
off += Math.max(Math.abs(x - xPrediction) - (targetWidth / 2 + precision), 0.0D);
off += Math.max(Math.abs(z - zPrediction) - (targetWidth / 2 + precision), 0.0D);
off += Math.max(Math.abs(y - yPrediction) - (targetHeight / 2 + precision), 0.0D);
if(off > 1) {
off = Math.sqrt(off);
}
return off;
}
/**
* Check if a player is close enough to a target, based on his eye location
*
* @param player
* @param targetX
* @param targetY
* @param targetZ
* @param limit
* @return
*/
public static final double reachCheck(final NoCheatPlayer player, final double targetX, final double targetY, final double targetZ, final double limit) {
final Location eyes = player.getPlayer().getEyeLocation();
final double distance = Math.sqrt(Math.pow(eyes.getX() - targetX, 2) + Math.pow(eyes.getY() - targetY, 2) + Math.pow(eyes.getZ() - targetZ, 2));
return Math.max(distance - limit, 0.0D);
}
private final static double magic = 0.45D;
private final static double magic2 = 0.55D;
private static final int NONSOLID = 1; // 0x00000001
private static final int SOLID = 2; // 0x00000010
private static final int NONSOLID = 1; // 0x00000001
private static final int SOLID = 2; // 0x00000010
// All liquids are "nonsolid" too
private static final int LIQUID = 4 | NONSOLID; // 0x00000101
private static final int LIQUID = 4 | NONSOLID; // 0x00000101
// All ladders are "nonsolid" and "solid" too
private static final int LADDER = 8 | NONSOLID | SOLID; // 0x00001011
private static final int LADDER = 8 | NONSOLID | SOLID; // 0x00001011
// All fences are solid - fences are treated specially due
// to being 1.5 blocks high
private static final int FENCE = 16 | SOLID | NONSOLID; // 0x00010011
private static final int FENCE = 16 | SOLID | NONSOLID; // 0x00010011
private static final int INGROUND = 128;
private static final int ONGROUND = 256;
private static final int INGROUND = 128;
private static final int ONGROUND = 256;
// Until I can think of a better way to determine if a block is solid or
// not, this is what I'll do
private static final int types[];
private static final Set<Material> foods = new HashSet<Material>();
private static final int types[];
static {
types = new int[256];
// Find and define properties of all other blocks
for(int i = 0; i < types.length; i++) {
for (int i = 0; i < types.length; i++) {
// Everything unknown is considered nonsolid and solid
types[i] = NONSOLID | SOLID;
if(Block.byId[i] != null) {
if(Block.byId[i].material.isSolid()) {
if (Block.byId[i] != null)
if (Block.byId[i].material.isSolid())
// STONE, CAKE, LEAFS, ...
types[i] = SOLID;
} else if(Block.byId[i].material.isLiquid()) {
else if (Block.byId[i].material.isLiquid())
// WATER, LAVA, ...
types[i] = LIQUID;
} else {
else
// AIR, SAPLINGS, ...
types[i] = NONSOLID;
}
}
}
// Some exceptions where the above method fails
@ -170,28 +112,46 @@ public class CheckUtil {
* }
* }
*/
// We need to know what is considered food for the instanteat check
foods.add(Material.APPLE);
foods.add(Material.BREAD);
foods.add(Material.COOKED_BEEF);
foods.add(Material.COOKED_CHICKEN);
foods.add(Material.COOKED_FISH);
foods.add(Material.COOKIE);
foods.add(Material.GOLDEN_APPLE);
foods.add(Material.GRILLED_PORK);
foods.add(Material.MELON);
foods.add(Material.MUSHROOM_SOUP);
foods.add(Material.PORK);
foods.add(Material.RAW_BEEF);
foods.add(Material.RAW_CHICKEN);
foods.add(Material.RAW_FISH);
foods.add(Material.ROTTEN_FLESH);
foods.add(Material.SPIDER_EYE);
}
/**
* Ask NoCheat what it thinks about a certain location.
* Check if a player looks at a target of a specific size, with a specific
* precision value (roughly)
*/
public static double directionCheck(final NoCheatPlusPlayer player, final double targetX, final double targetY,
final double targetZ, final double targetWidth, final double targetHeight, final double precision) {
// Eye location of the player
final Location eyes = player.getPlayer().getEyeLocation();
final double factor = Math.sqrt(Math.pow(eyes.getX() - targetX, 2) + Math.pow(eyes.getY() - targetY, 2)
+ Math.pow(eyes.getZ() - targetZ, 2));
// View direction of the player
final Vector direction = eyes.getDirection();
final double x = targetX - eyes.getX();
final double y = targetY - eyes.getY();
final double z = targetZ - eyes.getZ();
final double xPrediction = factor * direction.getX();
final double yPrediction = factor * direction.getY();
final double zPrediction = factor * direction.getZ();
double off = 0.0D;
off += Math.max(Math.abs(x - xPrediction) - (targetWidth / 2 + precision), 0.0D);
off += Math.max(Math.abs(z - zPrediction) - (targetWidth / 2 + precision), 0.0D);
off += Math.max(Math.abs(y - yPrediction) - (targetHeight / 2 + precision), 0.0D);
if (off > 1)
off = Math.sqrt(off);
return off;
}
/**
* Ask NoCheatPlus what it thinks about a certain location.
* Is it a place where a player can safely stand, should
* it be considered as being inside a liquid etc.
*
@ -202,7 +162,7 @@ public class CheckUtil {
*
* @return
*/
public static final int evaluateLocation(final World world, final PreciseLocation location) {
public static int evaluateLocation(final World world, final PreciseLocation location) {
final int lowerX = lowerBorder(location.x);
final int upperX = upperBorder(location.x);
@ -219,12 +179,11 @@ public class CheckUtil {
result |= evaluateSimpleLocation(world, upperX, Y, upperZ);
result |= evaluateSimpleLocation(world, lowerX, Y, upperZ);
if(!isInGround(result)) {
if (!isInGround(result))
// Original location: X, Z (allow standing in walls this time)
if(isSolid(types[world.getBlockTypeIdAt(Location.locToBlock(location.x), Location.locToBlock(location.y), Location.locToBlock(location.z))])) {
if (isSolid(types[world.getBlockTypeIdAt(Location.locToBlock(location.x), Location.locToBlock(location.y),
Location.locToBlock(location.z))]))
result |= INGROUND;
}
}
return result;
}
@ -240,7 +199,7 @@ public class CheckUtil {
* @param z
* @return Returns INGROUND, ONGROUND, LIQUID, combination of the three or 0
*/
private static final int evaluateSimpleLocation(final World world, final int x, final int y, final int z) {
private static int evaluateSimpleLocation(final World world, final int x, final int y, final int z) {
// First we need to know about the block itself, the block
// below it and the block above it
@ -251,111 +210,114 @@ public class CheckUtil {
int type = 0;
// Special case: Standing on a fence
// Behave as if there is a block on top of the fence
if((below == FENCE) && base != FENCE && isNonSolid(top)) {
if (below == FENCE && base != FENCE && isNonSolid(top))
type = INGROUND;
}
// Special case: Fence
// Being a bit above a fence
else if(below != FENCE && isNonSolid(base) && types[world.getBlockTypeIdAt(x, y - 2, z)] == FENCE) {
else if (below != FENCE && isNonSolid(base) && types[world.getBlockTypeIdAt(x, y - 2, z)] == FENCE)
type = ONGROUND;
}
else if(isNonSolid(top)) {
else if (isNonSolid(top))
// Simplest (and most likely) case:
// Below the player is a solid block
if(isSolid(below) && isNonSolid(base)) {
if (isSolid(below) && isNonSolid(base))
type = ONGROUND;
}
// Next (likely) case:
// There is a ladder
else if(isLadder(base) || isLadder(top)) {
else if (isLadder(base) || isLadder(top))
type = ONGROUND;
}
// Next (likely) case:
// At least the block the player stands
// in is solid
else if(isSolid(base)) {
else if (isSolid(base))
type = INGROUND;
}
}
// (In every case, check for water)
if(isLiquid(base) || isLiquid(top)) {
if (isLiquid(base) || isLiquid(top))
type |= LIQUID | INGROUND;
}
return type;
}
public static final boolean isSolid(final int value) {
return (value & SOLID) == SOLID;
}
public static final boolean isLiquid(final int value) {
return (value & LIQUID) == LIQUID;
}
private static final boolean isNonSolid(final int value) {
return((value & NONSOLID) == NONSOLID);
}
private static final boolean isLadder(final int value) {
return((value & LADDER) == LADDER);
}
public static final boolean isOnGround(final int fromType) {
return (fromType & ONGROUND) == ONGROUND;
}
public static final boolean isInGround(final int fromType) {
return (fromType & INGROUND) == INGROUND;
}
/**
* Personal Rounding function to determine if a player is still touching a
* block or not
*
* @param d1
* @return
*/
private static final int lowerBorder(final double d1) {
final double floor = Math.floor(d1);
if(floor + magic <= d1)
return (int) (floor);
else
return (int) (floor - 1);
}
/**
* Personal Rounding function to determine if a player is still touching a
* block or not
*
* @param d1
* @return
*/
private static final int upperBorder(final double d1) {
final double floor = Math.floor(d1);
if(floor + magic2 < d1)
return (int) (floor + 1);
else
return (int) floor;
}
public static int getType(final int typeId) {
return types[typeId];
}
public static boolean isFood(ItemStack item) {
if(item == null)
public static boolean isFood(final ItemStack item) {
if (item == null)
return false;
return foods.contains(item.getType());
return item.getType().isEdible();
}
public static boolean isInGround(final int fromType) {
return (fromType & INGROUND) == INGROUND;
}
private static boolean isLadder(final int value) {
return (value & LADDER) == LADDER;
}
public static boolean isLiquid(final int value) {
return (value & LIQUID) == LIQUID;
}
private static boolean isNonSolid(final int value) {
return (value & NONSOLID) == NONSOLID;
}
public static boolean isOnGround(final int fromType) {
return (fromType & ONGROUND) == ONGROUND;
}
public static boolean isSolid(final int value) {
return (value & SOLID) == SOLID;
}
/**
* Personal Rounding function to determine if a player is still touching a
* block or not
*
* @param d1
* @return
*/
private static int lowerBorder(final double d1) {
final double floor = Math.floor(d1);
if (floor + magic <= d1)
return (int) floor;
else
return (int) (floor - 1);
}
/**
* Check if a player is close enough to a target, based on his eye location
*
* @param player
* @param targetX
* @param targetY
* @param targetZ
* @param limit
* @return
*/
public static double reachCheck(final NoCheatPlusPlayer player, final double targetX, final double targetY,
final double targetZ, final double limit) {
final Location eyes = player.getPlayer().getEyeLocation();
final double distance = Math.sqrt(Math.pow(eyes.getX() - targetX, 2) + Math.pow(eyes.getY() - targetY, 2)
+ Math.pow(eyes.getZ() - targetZ, 2));
return Math.max(distance - limit, 0.0D);
}
/**
* Personal Rounding function to determine if a player is still touching a
* block or not
*
* @param d1
* @return
*/
private static int upperBorder(final double d1) {
final double floor = Math.floor(d1);
if (floor + magic2 < d1)
return (int) (floor + 1);
else
return (int) floor;
}
}

View File

@ -1,14 +1,16 @@
package cc.co.evenprime.bukkit.nocheat.checks;
package me.neatmonster.nocheatplus.checks;
import java.util.Collections;
import java.util.List;
import me.neatmonster.nocheatplus.EventManager;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerToggleSprintEvent;
import cc.co.evenprime.bukkit.nocheat.EventManager;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
/**
* Only place that listens to Player-teleport related events and dispatches them
@ -19,10 +21,16 @@ public class WorkaroundsListener implements Listener, EventManager {
public WorkaroundsListener() {}
@EventHandler(priority = EventPriority.HIGHEST)
@Override
public List<String> getActiveChecks(final ConfigurationCacheStore cc) {
return Collections.emptyList();
}
@EventHandler(
priority = EventPriority.HIGHEST)
public void playerMove(final PlayerMoveEvent event) {
// No typo here. I really only handle cancelled events and ignore others
if(!event.isCancelled())
if (!event.isCancelled())
return;
// Fix a common mistake that other developers make (cancelling move
@ -31,17 +39,13 @@ public class WorkaroundsListener implements Listener, EventManager {
event.setTo(event.getFrom().clone());
}
@EventHandler(priority = EventPriority.HIGHEST)
@EventHandler(
priority = EventPriority.HIGHEST)
public void toggleSprint(final PlayerToggleSprintEvent event) {
// Some plugins cancel "sprinting", which makes no sense at all because
// it doesn't stop people from sprinting and rewards them by reducing
// their hunger bar as if they were walking instead of sprinting
if(event.isCancelled() && event.isSprinting()) {
if (event.isCancelled() && event.isSprinting())
event.setCancelled(false);
}
}
public List<String> getActiveChecks(ConfigurationCacheStore cc) {
return Collections.emptyList();
}
}

View File

@ -1,39 +1,27 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockbreak;
package me.neatmonster.nocheatplus.checks.blockbreak;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.checks.Check;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.data.DataStore;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.checks.Check;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import me.neatmonster.nocheatplus.data.DataStore;
/**
* Abstract base class for BlockBreakChecks. Provides some static convenience
* methods for retrieving data and config objects for players
*
*
*/
public abstract class BlockBreakCheck extends Check {
private static final String id = "blockbreak";
public BlockBreakCheck(NoCheat plugin, String name) {
super(plugin, id, name);
}
/**
* Get the "BlockBreakData" object that belongs to the player. Will ensure
* that such a object exists and if not, create one
*
* @param player
* @return
*/
public static BlockBreakData getData(NoCheatPlayer player) {
DataStore base = player.getDataStore();
BlockBreakData data = base.get(id);
if(data == null) {
data = new BlockBreakData();
base.set(id, data);
public static BlockBreakConfig getConfig(final ConfigurationCacheStore cache) {
BlockBreakConfig config = cache.get(id);
if (config == null) {
config = new BlockBreakConfig(cache.getConfiguration());
cache.set(id, config);
}
return data;
return config;
}
/**
@ -43,16 +31,28 @@ public abstract class BlockBreakCheck extends Check {
* @param player
* @return
*/
public static BlockBreakConfig getConfig(NoCheatPlayer player) {
public static BlockBreakConfig getConfig(final NoCheatPlusPlayer player) {
return getConfig(player.getConfigurationStore());
}
public static BlockBreakConfig getConfig(ConfigurationCacheStore cache) {
BlockBreakConfig config = cache.get(id);
if(config == null) {
config = new BlockBreakConfig(cache.getConfiguration());
cache.set(id, config);
/**
* Get the "BlockBreakData" object that belongs to the player. Will ensure
* that such a object exists and if not, create one
*
* @param player
* @return
*/
public static BlockBreakData getData(final NoCheatPlusPlayer player) {
final DataStore base = player.getDataStore();
BlockBreakData data = base.get(id);
if (data == null) {
data = new BlockBreakData();
base.set(id, data);
}
return config;
return data;
}
public BlockBreakCheck(final NoCheatPlus plugin, final String name) {
super(plugin, id, name);
}
}

View File

@ -1,7 +1,14 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockbreak;
package me.neatmonster.nocheatplus.checks.blockbreak;
import java.util.LinkedList;
import java.util.List;
import me.neatmonster.nocheatplus.EventManager;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import me.neatmonster.nocheatplus.config.Permissions;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
@ -9,14 +16,9 @@ import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockDamageEvent;
import org.bukkit.event.player.PlayerAnimationEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import cc.co.evenprime.bukkit.nocheat.EventManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
/**
* Central location to listen to events that are
* Central location to listen to events that are
* relevant for the blockbreak checks
*
*/
@ -25,9 +27,9 @@ public class BlockBreakCheckListener implements Listener, EventManager {
private final NoswingCheck noswingCheck;
private final ReachCheck reachCheck;
private final DirectionCheck directionCheck;
private final NoCheat plugin;
private final NoCheatPlus plugin;
public BlockBreakCheckListener(NoCheat plugin) {
public BlockBreakCheckListener(final NoCheatPlus plugin) {
noswingCheck = new NoswingCheck(plugin);
reachCheck = new ReachCheck(plugin);
@ -37,18 +39,33 @@ public class BlockBreakCheckListener implements Listener, EventManager {
}
/**
* We listen to blockBreak events for obvious reasons
* @param event The blockbreak event
* We listen to PlayerAnimationEvent because it is (currently) equivalent
* to "player swings arm" and we want to check if he did that between
* blockbreaks.
*
* @param event
* The PlayerAnimation Event
*/
@EventHandler(priority = EventPriority.LOWEST)
public void blockBreak(final BlockBreakEvent event) {
@EventHandler(
priority = EventPriority.MONITOR)
public void armSwing(final PlayerAnimationEvent event) {
// Just set a flag to true when the arm was swung
BlockBreakCheck.getData(plugin.getPlayer(event.getPlayer())).armswung = true;
}
if(event.isCancelled())
return;
/**
* We listen to blockBreak events for obvious reasons
*
* @param event
* The blockbreak event
*/
@EventHandler(
ignoreCancelled = true, priority = EventPriority.LOWEST)
public void blockBreak(final BlockBreakEvent event) {
boolean cancelled = false;
final NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
final NoCheatPlusPlayer player = plugin.getPlayer(event.getPlayer());
final BlockBreakConfig cc = BlockBreakCheck.getConfig(player);
final BlockBreakData data = BlockBreakCheck.getData(player);
@ -56,7 +73,7 @@ public class BlockBreakCheckListener implements Listener, EventManager {
data.brokenBlockLocation.set(event.getBlock());
// Only if the block got damaged directly before, do the check(s)
if(!data.brokenBlockLocation.equals(data.lastDamagedBlock)) {
if (!data.brokenBlockLocation.equals(data.lastDamagedBlock)) {
// Something caused a blockbreak event that's not from the player
// Don't check it at all
data.lastDamagedBlock.reset();
@ -69,22 +86,19 @@ public class BlockBreakCheckListener implements Listener, EventManager {
// First NoSwing: Did the arm of the player move before breaking this
// block?
if(cc.noswingCheck && !player.hasPermission(Permissions.BLOCKBREAK_NOSWING)) {
if (cc.noswingCheck && !player.hasPermission(Permissions.BLOCKBREAK_NOSWING))
cancelled = noswingCheck.check(player, data, cc);
}
// Second Reach: Is the block really in reach distance
if(!cancelled && cc.reachCheck && !player.hasPermission(Permissions.BLOCKBREAK_REACH)) {
if (!cancelled && cc.reachCheck && !player.hasPermission(Permissions.BLOCKBREAK_REACH))
cancelled = reachCheck.check(player, data, cc);
}
// Third Direction: Did the player look at the block at all
if(!cancelled && cc.directionCheck && !player.hasPermission(Permissions.BLOCKBREAK_DIRECTION)) {
if (!cancelled && cc.directionCheck && !player.hasPermission(Permissions.BLOCKBREAK_DIRECTION))
cancelled = directionCheck.check(player, data, cc);
}
// At least one check failed and demanded to cancel the event
if(cancelled)
if (cancelled)
event.setCancelled(cancelled);
}
@ -92,23 +106,21 @@ public class BlockBreakCheckListener implements Listener, EventManager {
* We listen to BlockDamage events to grab the information if it has been
* an "insta-break". That info may come in handy later.
*
* @param event The BlockDamage event
* @param event
* The BlockDamage event
*/
@EventHandler(priority = EventPriority.MONITOR)
@EventHandler(
ignoreCancelled = true, priority = EventPriority.MONITOR)
public void blockHit(final BlockDamageEvent event) {
if(event.isCancelled())
return;
NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
BlockBreakData data = BlockBreakCheck.getData(player);
final NoCheatPlusPlayer player = plugin.getPlayer(event.getPlayer());
final BlockBreakData data = BlockBreakCheck.getData(player);
// Only interested in insta-break events here
if(event.getInstaBreak()) {
if (event.getInstaBreak())
// Remember this location. We handle insta-breaks slightly
// different in some of the blockbreak checks.
data.instaBrokenBlockLocation.set(event.getBlock());
}
}
@ -119,42 +131,28 @@ public class BlockBreakCheckListener implements Listener, EventManager {
*
* @param event
*/
@EventHandler(priority = EventPriority.MONITOR)
@EventHandler(
ignoreCancelled = true, priority = EventPriority.MONITOR)
public void blockInteract(final PlayerInteractEvent event) {
if(event.getClickedBlock() == null)
return;
NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
BlockBreakData data = BlockBreakCheck.getData(player);
// Remember this location. Only blockbreakevents for this specific
final NoCheatPlusPlayer player = plugin.getPlayer(event.getPlayer());
final BlockBreakData data = BlockBreakCheck.getData(player);
// Remember this location. Only blockbreakevents for this specific
// block will be handled at all
data.lastDamagedBlock.set(event.getClickedBlock());
}
/**
* We listen to PlayerAnimationEvent because it is (currently) equivalent
* to "player swings arm" and we want to check if he did that between
* blockbreaks.
*
* @param event The PlayerAnimation Event
*/
@EventHandler(priority = EventPriority.MONITOR)
public void armSwing(final PlayerAnimationEvent event) {
// Just set a flag to true when the arm was swung
BlockBreakCheck.getData(plugin.getPlayer(event.getPlayer())).armswung = true;
}
@Override
public List<String> getActiveChecks(final ConfigurationCacheStore cc) {
final LinkedList<String> s = new LinkedList<String>();
public List<String> getActiveChecks(ConfigurationCacheStore cc) {
LinkedList<String> s = new LinkedList<String>();
final BlockBreakConfig bb = BlockBreakCheck.getConfig(cc);
BlockBreakConfig bb = BlockBreakCheck.getConfig(cc);
if(bb.directionCheck)
if (bb.directionCheck)
s.add("blockbreak.direction");
if(bb.reachCheck)
if (bb.reachCheck)
s.add("blockbreak.reach");
if(bb.noswingCheck)
if (bb.noswingCheck)
s.add("blockbreak.noswing");
return s;

View File

@ -1,10 +1,10 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockbreak;
package me.neatmonster.nocheatplus.checks.blockbreak;
import cc.co.evenprime.bukkit.nocheat.ConfigItem;
import cc.co.evenprime.bukkit.nocheat.actions.types.ActionList;
import cc.co.evenprime.bukkit.nocheat.config.ConfPaths;
import cc.co.evenprime.bukkit.nocheat.config.NoCheatConfiguration;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import me.neatmonster.nocheatplus.ConfigItem;
import me.neatmonster.nocheatplus.actions.types.ActionList;
import me.neatmonster.nocheatplus.config.ConfPaths;
import me.neatmonster.nocheatplus.config.NoCheatPlusConfiguration;
import me.neatmonster.nocheatplus.config.Permissions;
/**
* Configurations specific for the "BlockBreak" checks
@ -26,13 +26,13 @@ public class BlockBreakConfig implements ConfigItem {
public final boolean noswingCheck;
public final ActionList noswingActions;
public BlockBreakConfig(NoCheatConfiguration data) {
public BlockBreakConfig(final NoCheatPlusConfiguration data) {
reachCheck = data.getBoolean(ConfPaths.BLOCKBREAK_REACH_CHECK);
reachDistance = 535D / 100D;
reachActions = data.getActionList(ConfPaths.BLOCKBREAK_REACH_ACTIONS, Permissions.BLOCKBREAK_REACH);
directionCheck = data.getBoolean(ConfPaths.BLOCKBREAK_DIRECTION_CHECK);
directionPrecision = ((double) data.getInt(ConfPaths.BLOCKBREAK_DIRECTION_PRECISION)) / 100D;
directionPrecision = data.getInt(ConfPaths.BLOCKBREAK_DIRECTION_PRECISION) / 100D;
directionPenaltyTime = data.getInt(ConfPaths.BLOCKBREAK_DIRECTION_PENALTYTIME);
directionActions = data.getActionList(ConfPaths.BLOCKBREAK_DIRECTION_ACTIONS, Permissions.BLOCKBREAK_DIRECTION);
noswingCheck = data.getBoolean(ConfPaths.BLOCKBREAK_NOSWING_CHECK);

View File

@ -1,7 +1,7 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockbreak;
package me.neatmonster.nocheatplus.checks.blockbreak;
import cc.co.evenprime.bukkit.nocheat.DataItem;
import cc.co.evenprime.bukkit.nocheat.data.SimpleLocation;
import me.neatmonster.nocheatplus.DataItem;
import me.neatmonster.nocheatplus.data.SimpleLocation;
/**
* Player specific data for the blockbreak checks
@ -26,7 +26,7 @@ public class BlockBreakData implements DataItem {
// indicate if the player swung his arm since he got checked last time
public boolean armswung = true;
// For logging, remember the reachDistance that was calculated in the
// For logging, remember the reachDistance that was calculated in the
// reach check
public double reachDistance;

View File

@ -1,12 +1,13 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockbreak;
package me.neatmonster.nocheatplus.checks.blockbreak;
import java.util.Locale;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.checks.CheckUtil;
import cc.co.evenprime.bukkit.nocheat.data.SimpleLocation;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.checks.CheckUtil;
import me.neatmonster.nocheatplus.data.SimpleLocation;
import me.neatmonster.nocheatplus.data.Statistics.Id;
/**
* The DirectionCheck will find out if a player tried to interact with something
@ -15,11 +16,11 @@ import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
*/
public class DirectionCheck extends BlockBreakCheck {
public DirectionCheck(NoCheat plugin) {
public DirectionCheck(final NoCheatPlus plugin) {
super(plugin, "blockbreak.direction");
}
public boolean check(final NoCheatPlayer player, final BlockBreakData data, final BlockBreakConfig ccblockbreak) {
public boolean check(final NoCheatPlusPlayer player, final BlockBreakData data, final BlockBreakConfig ccblockbreak) {
final SimpleLocation brokenBlock = data.brokenBlockLocation;
boolean cancel = false;
@ -28,22 +29,22 @@ public class DirectionCheck extends BlockBreakCheck {
// 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
double off = CheckUtil.directionCheck(player, brokenBlock.x + 0.5D, brokenBlock.y + 0.5D, brokenBlock.z + 0.5D, 1D, 1D, ccblockbreak.directionPrecision);
double off = CheckUtil.directionCheck(player, brokenBlock.x + 0.5D, brokenBlock.y + 0.5D, brokenBlock.z + 0.5D,
1D, 1D, ccblockbreak.directionPrecision);
final long time = System.currentTimeMillis();
if(off < 0.1D) {
if (off < 0.1D)
// Player did likely nothing wrong
// reduce violation counter to reward him
data.directionVL *= 0.9D;
} else {
else {
// Player failed the check
// Increment violation counter
if(data.instaBrokenBlockLocation.equals(brokenBlock)) {
if (data.instaBrokenBlockLocation.equals(brokenBlock))
// Instabreak block failures are very common, so don't be as
// hard on people failing them
off /= 5;
}
// Add to the overall violation level of the check and add to
// statistics
@ -54,19 +55,17 @@ public class DirectionCheck extends BlockBreakCheck {
// violation level and find out if we should cancel the event
cancel = executeActions(player, ccblockbreak.directionActions, data.directionVL);
if(cancel) {
if (cancel)
// if we should cancel, remember the current time too
data.directionLastViolationTime = time;
}
}
// If the player is still in penalty time, cancel the event anyway
if(data.directionLastViolationTime + ccblockbreak.directionPenaltyTime > time) {
if (data.directionLastViolationTime + ccblockbreak.directionPenaltyTime > time) {
// A saveguard to avoid people getting stuck in penalty time
// indefinitely in case the system time of the server gets changed
if(data.directionLastViolationTime > time) {
if (data.directionLastViolationTime > time)
data.directionLastViolationTime = 0;
}
// He is in penalty time, therefore request cancelling of the event
return true;
@ -76,9 +75,9 @@ public class DirectionCheck extends BlockBreakCheck {
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).directionVL);
else
return super.getParameter(wildcard, player);

View File

@ -1,28 +1,29 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockbreak;
package me.neatmonster.nocheatplus.checks.blockbreak;
import java.util.Locale;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.data.Statistics.Id;
/**
* We require that the player moves his arm between blockbreaks, this is
* what gets checked here.
*
*
*/
public class NoswingCheck extends BlockBreakCheck {
public NoswingCheck(NoCheat plugin) {
public NoswingCheck(final NoCheatPlus plugin) {
super(plugin, "blockbreak.noswing");
}
public boolean check(NoCheatPlayer player, BlockBreakData data, BlockBreakConfig cc) {
public boolean check(final NoCheatPlusPlayer player, final BlockBreakData data, final BlockBreakConfig cc) {
boolean cancel = false;
// did he swing his arm before
if(data.armswung) {
if (data.armswung) {
// "consume" the flag
data.armswung = false;
// reward with lowering of the violation level
@ -41,9 +42,9 @@ public class NoswingCheck extends BlockBreakCheck {
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).noswingVL);
else
return super.getParameter(wildcard, player);

View File

@ -1,12 +1,13 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockbreak;
package me.neatmonster.nocheatplus.checks.blockbreak;
import java.util.Locale;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.checks.CheckUtil;
import cc.co.evenprime.bukkit.nocheat.data.SimpleLocation;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.checks.CheckUtil;
import me.neatmonster.nocheatplus.data.SimpleLocation;
import me.neatmonster.nocheatplus.data.Statistics.Id;
/**
* The reach check will find out if a player interacts with something that's
@ -15,11 +16,11 @@ import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
*/
public class ReachCheck extends BlockBreakCheck {
public ReachCheck(NoCheat plugin) {
public ReachCheck(final NoCheatPlus plugin) {
super(plugin, "blockbreak.reach");
}
public boolean check(NoCheatPlayer player, BlockBreakData data, BlockBreakConfig cc) {
public boolean check(final NoCheatPlusPlayer player, final BlockBreakData data, final BlockBreakConfig cc) {
boolean cancel = false;
@ -28,12 +29,13 @@ public class ReachCheck extends BlockBreakCheck {
// 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 = CheckUtil.reachCheck(player, brokenBlock.x + 0.5D, brokenBlock.y + 0.5D, brokenBlock.z + 0.5D, player.isCreative() ? cc.reachDistance + 2 : cc.reachDistance);
final double distance = CheckUtil.reachCheck(player, brokenBlock.x + 0.5D, brokenBlock.y + 0.5D,
brokenBlock.z + 0.5D, player.isCreative() ? cc.reachDistance + 2 : cc.reachDistance);
if(distance <= 0D) {
if (distance <= 0D)
// Player passed the check, reward him
data.reachVL *= 0.9D;
} else {
else {
// He failed, increment violation level and statistics
data.reachVL += distance;
incrementStatistics(player, Id.BB_REACH, distance);
@ -51,11 +53,11 @@ public class ReachCheck extends BlockBreakCheck {
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).reachVL);
else if(wildcard == ParameterName.REACHDISTANCE)
else if (wildcard == ParameterName.REACHDISTANCE)
return String.format(Locale.US, "%.2f", getData(player).reachDistance);
else
return super.getParameter(wildcard, player);

View File

@ -1,13 +1,14 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockplace;
package me.neatmonster.nocheatplus.checks.blockplace;
import java.util.Locale;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.checks.Check;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.data.DataStore;
import cc.co.evenprime.bukkit.nocheat.data.SimpleLocation;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.checks.Check;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import me.neatmonster.nocheatplus.data.DataStore;
import me.neatmonster.nocheatplus.data.SimpleLocation;
/**
* Abstract base class for BlockPlace checks, provides some convenience
@ -17,49 +18,13 @@ public abstract class BlockPlaceCheck extends Check {
private static final String id = "blockplace";
public BlockPlaceCheck(NoCheat plugin, String name) {
super(plugin, id, name);
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.PLACE_LOCATION) {
SimpleLocation l = getData(player).blockPlaced;
if(l.isSet()) {
return String.format(Locale.US, "%d %d %d", l.x, l.y, l.z);
} else {
return "null";
}
public static BlockPlaceConfig getConfig(final ConfigurationCacheStore cache) {
BlockPlaceConfig config = cache.get(id);
if (config == null) {
config = new BlockPlaceConfig(cache.getConfiguration());
cache.set(id, config);
}
else if(wildcard == ParameterName.PLACE_AGAINST) {
SimpleLocation l = getData(player).blockPlacedAgainst;
if(l.isSet()) {
return String.format(Locale.US, "%d %d %d", l.x, l.y, l.z);
} else {
return "null";
}
}
else
return super.getParameter(wildcard, player);
}
/**
* Get the "BlockPlaceData" object that belongs to the player. Will ensure
* that such a object exists and if not, create one
*
* @param player
* @return
*/
public static BlockPlaceData getData(NoCheatPlayer player) {
DataStore base = player.getDataStore();
BlockPlaceData data = base.get(id);
if(data == null) {
data = new BlockPlaceData();
base.set(id, data);
}
return data;
return config;
}
/**
@ -69,16 +34,50 @@ public abstract class BlockPlaceCheck extends Check {
* @param player
* @return
*/
public static BlockPlaceConfig getConfig(NoCheatPlayer player) {
public static BlockPlaceConfig getConfig(final NoCheatPlusPlayer player) {
return getConfig(player.getConfigurationStore());
}
public static BlockPlaceConfig getConfig(ConfigurationCacheStore cache) {
BlockPlaceConfig config = cache.get(id);
if(config == null) {
config = new BlockPlaceConfig(cache.getConfiguration());
cache.set(id, config);
/**
* Get the "BlockPlaceData" object that belongs to the player. Will ensure
* that such a object exists and if not, create one
*
* @param player
* @return
*/
public static BlockPlaceData getData(final NoCheatPlusPlayer player) {
final DataStore base = player.getDataStore();
BlockPlaceData data = base.get(id);
if (data == null) {
data = new BlockPlaceData();
base.set(id, data);
}
return config;
return data;
}
public BlockPlaceCheck(final NoCheatPlus plugin, final String name) {
super(plugin, id, name);
}
@Override
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if (wildcard == ParameterName.PLACE_LOCATION) {
final SimpleLocation l = getData(player).blockPlaced;
if (l.isSet())
return String.format(Locale.US, "%d %d %d", l.x, l.y, l.z);
else
return "null";
}
else if (wildcard == ParameterName.PLACE_AGAINST) {
final SimpleLocation l = getData(player).blockPlacedAgainst;
if (l.isSet())
return String.format(Locale.US, "%d %d %d", l.x, l.y, l.z);
else
return "null";
}
else
return super.getParameter(wildcard, player);
}
}

View File

@ -1,16 +1,18 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockplace;
package me.neatmonster.nocheatplus.checks.blockplace;
import java.util.LinkedList;
import java.util.List;
import me.neatmonster.nocheatplus.EventManager;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import me.neatmonster.nocheatplus.config.Permissions;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import cc.co.evenprime.bukkit.nocheat.EventManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
/**
* Central location to listen to Block-related events and dispatching them to
@ -21,9 +23,9 @@ public class BlockPlaceCheckListener implements Listener, EventManager {
private final ReachCheck reachCheck;
private final DirectionCheck directionCheck;
private final NoCheat plugin;
private final NoCheatPlus plugin;
public BlockPlaceCheckListener(NoCheat plugin) {
public BlockPlaceCheckListener(final NoCheatPlus plugin) {
this.plugin = plugin;
@ -31,19 +33,36 @@ public class BlockPlaceCheckListener implements Listener, EventManager {
directionCheck = new DirectionCheck(plugin);
}
@Override
public List<String> getActiveChecks(final ConfigurationCacheStore cc) {
final LinkedList<String> s = new LinkedList<String>();
final BlockPlaceConfig bp = BlockPlaceCheck.getConfig(cc);
if (bp.reachCheck)
s.add("blockplace.reach");
if (bp.directionCheck)
s.add("blockplace.direction");
return s;
}
/**
* We listen to BlockPlace events for obvious reasons
* @param event the BlockPlace event
*
* @param event
* the BlockPlace event
*/
@EventHandler(priority = EventPriority.LOWEST)
protected void handleBlockPlaceEvent(BlockPlaceEvent event) {
@EventHandler(
ignoreCancelled = true, priority = EventPriority.LOWEST)
protected void handleBlockPlaceEvent(final BlockPlaceEvent event) {
if(event.isCancelled() || event.getBlock() == null || event.getBlockAgainst() == null)
if (event.getBlock() == null || event.getBlockAgainst() == null)
return;
boolean cancelled = false;
final NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
final NoCheatPlusPlayer player = plugin.getPlayer(event.getPlayer());
final BlockPlaceConfig cc = BlockPlaceCheck.getConfig(player);
final BlockPlaceData data = BlockPlaceCheck.getData(player);
@ -54,30 +73,15 @@ public class BlockPlaceCheckListener implements Listener, EventManager {
// Now do the actual checks
// First the reach check
if(cc.reachCheck && !player.hasPermission(Permissions.BLOCKPLACE_REACH)) {
if (cc.reachCheck && !player.hasPermission(Permissions.BLOCKPLACE_REACH))
cancelled = reachCheck.check(player, data, cc);
}
// Second the direction check
if(!cancelled && cc.directionCheck && !player.hasPermission(Permissions.BLOCKPLACE_DIRECTION)) {
if (!cancelled && cc.directionCheck && !player.hasPermission(Permissions.BLOCKPLACE_DIRECTION))
cancelled = directionCheck.check(player, data, cc);
}
// If one of the checks requested to cancel the event, do so
if(cancelled)
if (cancelled)
event.setCancelled(cancelled);
}
public List<String> getActiveChecks(ConfigurationCacheStore cc) {
LinkedList<String> s = new LinkedList<String>();
BlockPlaceConfig bp = BlockPlaceCheck.getConfig(cc);
if(bp.reachCheck)
s.add("blockplace.reach");
if(bp.directionCheck)
s.add("blockplace.direction");
return s;
}
}

View File

@ -1,10 +1,10 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockplace;
package me.neatmonster.nocheatplus.checks.blockplace;
import cc.co.evenprime.bukkit.nocheat.ConfigItem;
import cc.co.evenprime.bukkit.nocheat.actions.types.ActionList;
import cc.co.evenprime.bukkit.nocheat.config.ConfPaths;
import cc.co.evenprime.bukkit.nocheat.config.NoCheatConfiguration;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import me.neatmonster.nocheatplus.ConfigItem;
import me.neatmonster.nocheatplus.actions.types.ActionList;
import me.neatmonster.nocheatplus.config.ConfPaths;
import me.neatmonster.nocheatplus.config.NoCheatPlusConfiguration;
import me.neatmonster.nocheatplus.config.Permissions;
/**
* Configurations specific for the "BlockPlace" checks
@ -23,7 +23,7 @@ public class BlockPlaceConfig implements ConfigItem {
public final long directionPenaltyTime;
public final double directionPrecision;
public BlockPlaceConfig(NoCheatConfiguration data) {
public BlockPlaceConfig(final NoCheatPlusConfiguration data) {
reachCheck = data.getBoolean(ConfPaths.BLOCKPLACE_REACH_CHECK);
reachDistance = 535D / 100D;
@ -31,7 +31,7 @@ public class BlockPlaceConfig implements ConfigItem {
directionCheck = data.getBoolean(ConfPaths.BLOCKPLACE_DIRECTION_CHECK);
directionPenaltyTime = data.getInt(ConfPaths.BLOCKPLACE_DIRECTION_PENALTYTIME);
directionPrecision = ((double) data.getInt(ConfPaths.BLOCKPLACE_DIRECTION_PRECISION)) / 100D;
directionPrecision = data.getInt(ConfPaths.BLOCKPLACE_DIRECTION_PRECISION) / 100D;
directionActions = data.getActionList(ConfPaths.BLOCKPLACE_DIRECTION_ACTIONS, Permissions.BLOCKPLACE_DIRECTION);
}
}

View File

@ -1,7 +1,7 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockplace;
package me.neatmonster.nocheatplus.checks.blockplace;
import cc.co.evenprime.bukkit.nocheat.DataItem;
import cc.co.evenprime.bukkit.nocheat.data.SimpleLocation;
import me.neatmonster.nocheatplus.DataItem;
import me.neatmonster.nocheatplus.data.SimpleLocation;
/**
* Player specific data for the blockbreak checks
@ -21,7 +21,7 @@ public class BlockPlaceData implements DataItem {
public final SimpleLocation blockPlacedAgainst = new SimpleLocation();
public final SimpleLocation blockPlaced = new SimpleLocation();
// For logging, remember the reachDistance that was calculated in the
// For logging, remember the reachDistance that was calculated in the
// reach check
public double reachdistance;
}

View File

@ -1,13 +1,15 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockplace;
package me.neatmonster.nocheatplus.checks.blockplace;
import java.util.Locale;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.checks.CheckUtil;
import me.neatmonster.nocheatplus.data.SimpleLocation;
import me.neatmonster.nocheatplus.data.Statistics.Id;
import org.bukkit.Location;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.checks.CheckUtil;
import cc.co.evenprime.bukkit.nocheat.data.SimpleLocation;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
/**
* The DirectionCheck will find out if a player tried to interact with something
@ -16,11 +18,11 @@ import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
*/
public class DirectionCheck extends BlockPlaceCheck {
public DirectionCheck(NoCheat plugin) {
public DirectionCheck(final NoCheatPlus plugin) {
super(plugin, "blockplace.direction");
}
public boolean check(NoCheatPlayer player, BlockPlaceData data, BlockPlaceConfig cc) {
public boolean check(final NoCheatPlusPlayer player, final BlockPlaceData data, final BlockPlaceConfig cc) {
boolean cancel = false;
@ -31,40 +33,39 @@ public class DirectionCheck extends BlockPlaceCheck {
// 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
double off = CheckUtil.directionCheck(player, blockPlacedAgainst.x + 0.5D, blockPlacedAgainst.y + 0.5D, blockPlacedAgainst.z + 0.5D, 1D, 1D, cc.directionPrecision);
double off = CheckUtil.directionCheck(player, blockPlacedAgainst.x + 0.5D, blockPlacedAgainst.y + 0.5D,
blockPlacedAgainst.z + 0.5D, 1D, 1D, cc.directionPrecision);
// now check if the player is looking at the block from the correct side
double off2 = 0.0D;
// Find out against which face the player tried to build, and if he
// stood on the correct side of it
Location eyes = player.getPlayer().getEyeLocation();
if(blockPlaced.x > blockPlacedAgainst.x) {
final Location eyes = player.getPlayer().getEyeLocation();
if (blockPlaced.x > blockPlacedAgainst.x)
off2 = blockPlacedAgainst.x + 0.5D - eyes.getX();
} else if(blockPlaced.x < blockPlacedAgainst.x) {
else if (blockPlaced.x < blockPlacedAgainst.x)
off2 = -(blockPlacedAgainst.x + 0.5D - eyes.getX());
} else if(blockPlaced.y > blockPlacedAgainst.y) {
else if (blockPlaced.y > blockPlacedAgainst.y)
off2 = blockPlacedAgainst.y + 0.5D - eyes.getY();
} else if(blockPlaced.y < blockPlacedAgainst.y) {
else if (blockPlaced.y < blockPlacedAgainst.y)
off2 = -(blockPlacedAgainst.y + 0.5D - eyes.getY());
} else if(blockPlaced.z > blockPlacedAgainst.z) {
else if (blockPlaced.z > blockPlacedAgainst.z)
off2 = blockPlacedAgainst.z + 0.5D - eyes.getZ();
} else if(blockPlaced.z < blockPlacedAgainst.z) {
else if (blockPlaced.z < blockPlacedAgainst.z)
off2 = -(blockPlacedAgainst.z + 0.5D - eyes.getZ());
}
// If he wasn't on the correct side, add that to the "off" value
if(off2 > 0.0D) {
if (off2 > 0.0D)
off += off2;
}
final long time = System.currentTimeMillis();
if(off < 0.1D) {
if (off < 0.1D)
// Player did nothing wrong
// reduce violation counter to reward him
data.directionVL *= 0.9D;
} else {
else {
// Player failed the check
// Increment violation counter and statistics
data.directionVL += off;
@ -74,19 +75,17 @@ public class DirectionCheck extends BlockPlaceCheck {
// violation level and find out if we should cancel the event
cancel = executeActions(player, cc.directionActions, data.directionVL);
if(cancel) {
if (cancel)
// if we should cancel, remember the current time too
data.directionLastViolationTime = time;
}
}
// If the player is still in penalty time, cancel the event anyway
if(data.directionLastViolationTime + cc.directionPenaltyTime > time) {
if (data.directionLastViolationTime + cc.directionPenaltyTime > time) {
// A safeguard to avoid people getting stuck in penalty time
// indefinitely in case the system time of the server gets changed
if(data.directionLastViolationTime > time) {
if (data.directionLastViolationTime > time)
data.directionLastViolationTime = 0;
}
// He is in penalty time, therefore request cancelling of the event
return true;
@ -96,9 +95,9 @@ public class DirectionCheck extends BlockPlaceCheck {
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).directionVL);
else
return super.getParameter(wildcard, player);

View File

@ -1,12 +1,13 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockplace;
package me.neatmonster.nocheatplus.checks.blockplace;
import java.util.Locale;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.checks.CheckUtil;
import cc.co.evenprime.bukkit.nocheat.data.SimpleLocation;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.checks.CheckUtil;
import me.neatmonster.nocheatplus.data.SimpleLocation;
import me.neatmonster.nocheatplus.data.Statistics.Id;
/**
* The reach check will find out if a player interacts with something that's
@ -15,11 +16,11 @@ import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
*/
public class ReachCheck extends BlockPlaceCheck {
public ReachCheck(NoCheat plugin) {
public ReachCheck(final NoCheatPlus plugin) {
super(plugin, "blockplace.reach");
}
public boolean check(NoCheatPlayer player, BlockPlaceData data, BlockPlaceConfig cc) {
public boolean check(final NoCheatPlusPlayer player, final BlockPlaceData data, final BlockPlaceConfig cc) {
boolean cancel = false;
@ -28,12 +29,13 @@ public class ReachCheck extends BlockPlaceCheck {
// 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 = CheckUtil.reachCheck(player, placedAgainstBlock.x + 0.5D, placedAgainstBlock.y + 0.5D, placedAgainstBlock.z + 0.5D, player.isCreative() ? cc.reachDistance + 2 : cc.reachDistance);
final double distance = CheckUtil.reachCheck(player, placedAgainstBlock.x + 0.5D, placedAgainstBlock.y + 0.5D,
placedAgainstBlock.z + 0.5D, player.isCreative() ? cc.reachDistance + 2 : cc.reachDistance);
if(distance <= 0D) {
if (distance <= 0D)
// Player passed the check, reward him
data.reachVL *= 0.9D;
} else {
else {
// He failed, increment violation level and statistics
data.reachVL += distance;
incrementStatistics(player, Id.BP_REACH, distance);
@ -51,11 +53,11 @@ public class ReachCheck extends BlockPlaceCheck {
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).reachVL);
else if(wildcard == ParameterName.REACHDISTANCE)
else if (wildcard == ParameterName.REACHDISTANCE)
return String.format(Locale.US, "%.2f", getData(player).reachdistance);
else
return super.getParameter(wildcard, player);

View File

@ -1,11 +1,11 @@
package cc.co.evenprime.bukkit.nocheat.checks.chat;
package me.neatmonster.nocheatplus.checks.chat;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.checks.Check;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.data.DataStore;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.checks.Check;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import me.neatmonster.nocheatplus.data.DataStore;
/**
* Abstract base class for Chat checks, provides some convenience
@ -15,35 +15,13 @@ public abstract class ChatCheck extends Check {
private static final String id = "chat";
public ChatCheck(NoCheat plugin, String name) {
super(plugin, id, name);
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.TEXT)
// Filter colors from the players message when logging
return getData(player).message.replaceAll("\302\247.", "").replaceAll("\247.", "");
else
return super.getParameter(wildcard, player);
}
/**
* Get the "ChatData" object that belongs to the player. Will ensure
* that such a object exists and if not, create one
*
* @param player
* @return
*/
public static ChatData getData(NoCheatPlayer player) {
DataStore base = player.getDataStore();
ChatData data = base.get(id);
if(data == null) {
data = new ChatData();
base.set(id, data);
public static ChatConfig getConfig(final ConfigurationCacheStore cache) {
ChatConfig config = cache.get(id);
if (config == null) {
config = new ChatConfig(cache.getConfiguration());
cache.set(id, config);
}
return data;
return config;
}
/**
@ -53,16 +31,38 @@ public abstract class ChatCheck extends Check {
* @param player
* @return
*/
public static ChatConfig getConfig(NoCheatPlayer player) {
public static ChatConfig getConfig(final NoCheatPlusPlayer player) {
return getConfig(player.getConfigurationStore());
}
public static ChatConfig getConfig(ConfigurationCacheStore cache) {
ChatConfig config = cache.get(id);
if(config == null) {
config = new ChatConfig(cache.getConfiguration());
cache.set(id, config);
/**
* Get the "ChatData" object that belongs to the player. Will ensure
* that such a object exists and if not, create one
*
* @param player
* @return
*/
public static ChatData getData(final NoCheatPlusPlayer player) {
final DataStore base = player.getDataStore();
ChatData data = base.get(id);
if (data == null) {
data = new ChatData();
base.set(id, data);
}
return config;
return data;
}
public ChatCheck(final NoCheatPlus plugin, final String name) {
super(plugin, id, name);
}
@Override
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if (wildcard == ParameterName.TEXT)
// Filter colors from the players message when logging
return getData(player).message.replaceAll("\302\247.", "").replaceAll("\247.", "");
else
return super.getParameter(wildcard, player);
}
}

View File

@ -1,31 +1,33 @@
package cc.co.evenprime.bukkit.nocheat.checks.chat;
package me.neatmonster.nocheatplus.checks.chat;
import java.util.LinkedList;
import java.util.List;
import me.neatmonster.nocheatplus.EventManager;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import me.neatmonster.nocheatplus.config.Permissions;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import cc.co.evenprime.bukkit.nocheat.EventManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
/**
* Central location to listen to events that are
* Central location to listen to events that are
* relevant for the chat checks
*
*/
public class ChatCheckListener implements Listener, EventManager {
private final SpamCheck spamCheck;
private final ColorCheck colorCheck;
private final SpamCheck spamCheck;
private final ColorCheck colorCheck;
private final NoCheat plugin;
private final NoCheatPlus plugin;
public ChatCheckListener(NoCheat plugin) {
public ChatCheckListener(final NoCheatPlus plugin) {
this.plugin = plugin;
@ -33,32 +35,19 @@ public class ChatCheckListener implements Listener, EventManager {
colorCheck = new ColorCheck(plugin);
}
/**
* We listen to PlayerCommandPreprocess events because commands can be
* used for spamming too.
*
* @param event The PlayerCommandPreprocess Event
*/
@EventHandler(priority = EventPriority.LOWEST)
public void commandPreprocess(final PlayerCommandPreprocessEvent event) {
// This type of event is derived from PlayerChatEvent, therefore
// just treat it like that
chat((PlayerChatEvent) event);
}
/**
* We listen to PlayerChat events for obvious reasons
* @param event The PlayerChat event
*
* @param event
* The PlayerChat event
*/
@EventHandler(priority = EventPriority.LOWEST)
@EventHandler(
ignoreCancelled = true, priority = EventPriority.LOWEST)
public void chat(final PlayerChatEvent event) {
if(event.isCancelled())
return;
boolean cancelled = false;
final NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
final NoCheatPlusPlayer player = plugin.getPlayer(event.getPlayer());
final ChatConfig cc = ChatCheck.getConfig(player);
final ChatData data = ChatCheck.getData(player);
@ -68,32 +57,45 @@ public class ChatCheckListener implements Listener, EventManager {
// Now do the actual checks
// First the spam check
if(cc.spamCheck && !player.hasPermission(Permissions.CHAT_SPAM)) {
if (cc.spamCheck && !player.hasPermission(Permissions.CHAT_SPAM))
cancelled = spamCheck.check(player, data, cc);
}
// Second the color check
if(!cancelled && cc.colorCheck && !player.hasPermission(Permissions.CHAT_COLOR)) {
if (!cancelled && cc.colorCheck && !player.hasPermission(Permissions.CHAT_COLOR))
cancelled = colorCheck.check(player, data, cc);
}
// If one of the checks requested the event to be cancelled, do it
if(cancelled) {
if (cancelled)
event.setCancelled(cancelled);
} else {
else
// In case one of the events modified the message, make sure that
// the new message gets used
event.setMessage(data.message);
}
}
public List<String> getActiveChecks(ConfigurationCacheStore cc) {
LinkedList<String> s = new LinkedList<String>();
/**
* We listen to PlayerCommandPreprocess events because commands can be
* used for spamming too.
*
* @param event
* The PlayerCommandPreprocess Event
*/
@EventHandler(
priority = EventPriority.LOWEST)
public void commandPreprocess(final PlayerCommandPreprocessEvent event) {
// This type of event is derived from PlayerChatEvent, therefore
// just treat it like that
chat(event);
}
ChatConfig c = ChatCheck.getConfig(cc);
if(c.spamCheck)
@Override
public List<String> getActiveChecks(final ConfigurationCacheStore cc) {
final LinkedList<String> s = new LinkedList<String>();
final ChatConfig c = ChatCheck.getConfig(cc);
if (c.spamCheck)
s.add("chat.spam");
if(c.colorCheck)
if (c.colorCheck)
s.add("chat.color");
return s;
}

View File

@ -1,12 +1,13 @@
package cc.co.evenprime.bukkit.nocheat.checks.chat;
package me.neatmonster.nocheatplus.checks.chat;
import java.util.LinkedList;
import java.util.List;
import cc.co.evenprime.bukkit.nocheat.ConfigItem;
import cc.co.evenprime.bukkit.nocheat.actions.types.ActionList;
import cc.co.evenprime.bukkit.nocheat.config.ConfPaths;
import cc.co.evenprime.bukkit.nocheat.config.NoCheatConfiguration;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import me.neatmonster.nocheatplus.ConfigItem;
import me.neatmonster.nocheatplus.actions.types.ActionList;
import me.neatmonster.nocheatplus.config.ConfPaths;
import me.neatmonster.nocheatplus.config.NoCheatPlusConfiguration;
import me.neatmonster.nocheatplus.config.Permissions;
/**
* Configurations specific for the "Chat" checks
@ -26,7 +27,7 @@ public class ChatConfig implements ConfigItem {
public final boolean colorCheck;
public final ActionList colorActions;
public ChatConfig(NoCheatConfiguration data) {
public ChatConfig(final NoCheatPlusConfiguration data) {
spamCheck = data.getBoolean(ConfPaths.CHAT_SPAM_CHECK);
spamWhitelist = splitWhitelist(data.getString(ConfPaths.CHAT_SPAM_WHITELIST));
@ -41,19 +42,19 @@ public class ChatConfig implements ConfigItem {
/**
* Convenience method to split a string into an array on every occurance of
* the "," character, removing all whitespaces before and after it too.
* @param string The string containing text seperated by ","
*
* @param string
* The string containing text seperated by ","
* @return An array of the seperate texts
*/
private String[] splitWhitelist(String string) {
List<String> strings = new LinkedList<String>();
final List<String> strings = new LinkedList<String>();
string = string.trim();
for(String s : string.split(",")) {
if(s != null && s.trim().length() > 0) {
for (final String s : string.split(","))
if (s != null && s.trim().length() > 0)
strings.add(s.trim());
}
}
return strings.toArray(new String[strings.size()]);
}

View File

@ -1,6 +1,6 @@
package cc.co.evenprime.bukkit.nocheat.checks.chat;
package me.neatmonster.nocheatplus.checks.chat;
import cc.co.evenprime.bukkit.nocheat.DataItem;
import me.neatmonster.nocheatplus.DataItem;
/**
* Player specific data for the chat checks

View File

@ -0,0 +1,41 @@
package me.neatmonster.nocheatplus.checks.chat;
import java.util.Locale;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.data.Statistics.Id;
public class ColorCheck extends ChatCheck {
public ColorCheck(final NoCheatPlus plugin) {
super(plugin, "chat.color");
}
public boolean check(final NoCheatPlusPlayer player, final ChatData data, final ChatConfig cc) {
if (data.message.contains("\247")) {
data.colorVL += 1;
incrementStatistics(player, Id.CHAT_COLOR, 1);
final boolean filter = executeActions(player, cc.colorActions, data.colorVL);
if (filter)
// Remove color codes
data.message = data.message.replaceAll("\302\247.", "").replaceAll("\247.", "");
}
return false;
}
@Override
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", getData(player).colorVL);
else
return super.getParameter(wildcard, player);
}
}

View File

@ -1,10 +1,11 @@
package cc.co.evenprime.bukkit.nocheat.checks.chat;
package me.neatmonster.nocheatplus.checks.chat;
import java.util.Locale;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.data.Statistics.Id;
/**
* The SpamCheck will count messages and commands over a short timeframe to
@ -13,47 +14,44 @@ import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
*/
public class SpamCheck extends ChatCheck {
public SpamCheck(NoCheat plugin) {
public SpamCheck(final NoCheatPlus plugin) {
super(plugin, "chat.spam");
}
public boolean check(NoCheatPlayer player, ChatData data, ChatConfig cc) {
public boolean check(final NoCheatPlusPlayer player, final ChatData data, final ChatConfig cc) {
boolean cancel = false;
// Maybe it's a command and on the whitelist
for(String s : cc.spamWhitelist) {
if(data.message.startsWith(s)) {
for (final String s : cc.spamWhitelist)
if (data.message.startsWith(s))
// It is
return false;
}
}
int commandLimit = cc.spamCommandLimit;
int messageLimit = cc.spamMessageLimit;
long timeframe = cc.spamTimeframe;
final int commandLimit = cc.spamCommandLimit;
final int messageLimit = cc.spamMessageLimit;
final long timeframe = cc.spamTimeframe;
final long time = System.currentTimeMillis();
// Has enough time passed? Then reset the counters
if(data.spamLastTime + timeframe <= time) {
if (data.spamLastTime + timeframe <= time) {
data.spamLastTime = time;
data.messageCount = 0;
data.commandCount = 0;
}
// Security check, if the system time changes
else if(data.spamLastTime > time) {
else if (data.spamLastTime > time)
data.spamLastTime = Integer.MIN_VALUE;
}
// Increment appropriate counter
if(data.message.startsWith("/"))
if (data.message.startsWith("/"))
data.commandCount++;
else
data.messageCount++;
// Did the player go over the limit on at least one of the counters?
if(data.messageCount > messageLimit || data.commandCount > commandLimit) {
if (data.messageCount > messageLimit || data.commandCount > commandLimit) {
// Set the vl as the number of messages above the limit and
// increment statistics
@ -70,10 +68,10 @@ public class SpamCheck extends ChatCheck {
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).spamVL);
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", getData(player).spamVL);
else
return super.getParameter(wildcard, player);
}

View File

@ -1,15 +1,16 @@
package cc.co.evenprime.bukkit.nocheat.checks.fight;
package me.neatmonster.nocheatplus.checks.fight;
import java.util.Locale;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.checks.CheckUtil;
import me.neatmonster.nocheatplus.config.Permissions;
import me.neatmonster.nocheatplus.data.Statistics.Id;
import net.minecraft.server.Entity;
import net.minecraft.server.EntityComplex;
import net.minecraft.server.EntityComplexPart;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.checks.CheckUtil;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
/**
* The DirectionCheck will find out if a player tried to interact with something
@ -18,28 +19,28 @@ import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
*/
public class DirectionCheck extends FightCheck {
public DirectionCheck(NoCheat plugin) {
public DirectionCheck(final NoCheatPlus plugin) {
super(plugin, "fight.direction", Permissions.FIGHT_DIRECTION);
}
public boolean check(NoCheatPlayer player, FightData data, FightConfig cc) {
@Override
public boolean check(final NoCheatPlusPlayer player, final FightData data, final FightConfig cc) {
boolean cancel = false;
final long time = System.currentTimeMillis();
// Get the damagee (entity that got hit)
Entity entity = data.damagee;
final Entity entity = data.damagee;
// Safeguard, if entity is complex, this check will fail
// due to giant and hard to define hitboxes
if(entity instanceof EntityComplex || entity instanceof EntityComplexPart) {
if (entity instanceof EntityComplex || entity instanceof EntityComplexPart)
return false;
}
// Find out how wide the entity is
final float width = entity.length > entity.width ? entity.length : entity.width;
// entity.height is broken and will always be 0, therefore
// entity.height is broken and will always be 0, therefore
// calculate height instead based on boundingBox
final double height = entity.boundingBox.e - entity.boundingBox.b;
@ -47,18 +48,19 @@ public class DirectionCheck extends FightCheck {
// players eye location and view direction to the center of the target
// entity. If the line of sight is more too far off, "off" will be
// bigger than 0
final double off = CheckUtil.directionCheck(player, entity.locX, entity.locY + (height / 2D), entity.locZ, width, height, cc.directionPrecision);
final double off = CheckUtil.directionCheck(player, entity.locX, entity.locY + height / 2D, entity.locZ, width,
height, cc.directionPrecision);
if(off < 0.1D) {
if (off < 0.1D)
// Player did probably nothing wrong
// reduce violation counter to reward him
data.directionVL *= 0.80D;
} else {
else {
// Player failed the check
// Increment violation counter and statistics, but only if there
// wasn't serious lag
if(!plugin.skipCheck()) {
double sqrt = Math.sqrt(off);
if (!plugin.skipCheck()) {
final double sqrt = Math.sqrt(off);
data.directionVL += sqrt;
incrementStatistics(player, Id.FI_DIRECTION, sqrt);
}
@ -67,19 +69,17 @@ public class DirectionCheck extends FightCheck {
// violation level and find out if we should cancel the event
cancel = executeActions(player, cc.directionActions, data.directionVL);
if(cancel) {
if (cancel)
// if we should cancel, remember the current time too
data.directionLastViolationTime = time;
}
}
// If the player is still in penalty time, cancel the event anyway
if(data.directionLastViolationTime + cc.directionPenaltyTime > time) {
if (data.directionLastViolationTime + cc.directionPenaltyTime > time) {
// A safeguard to avoid people getting stuck in penalty time
// indefinitely in case the system time of the server gets changed
if(data.directionLastViolationTime > time) {
if (data.directionLastViolationTime > time)
data.directionLastViolationTime = 0;
}
// He is in penalty time, therefore request cancelling of the event
return true;
@ -89,16 +89,16 @@ public class DirectionCheck extends FightCheck {
}
@Override
public boolean isEnabled(FightConfig cc) {
return cc.directionCheck;
}
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).directionVL);
else
return super.getParameter(wildcard, player);
}
@Override
public boolean isEnabled(final FightConfig cc) {
return cc.directionCheck;
}
}

View File

@ -1,10 +1,10 @@
package cc.co.evenprime.bukkit.nocheat.checks.fight;
package me.neatmonster.nocheatplus.checks.fight;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.checks.Check;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.data.DataStore;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.checks.Check;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import me.neatmonster.nocheatplus.data.DataStore;
/**
* Abstract base class for Fight checks, provides some convenience
@ -13,32 +13,14 @@ import cc.co.evenprime.bukkit.nocheat.data.DataStore;
public abstract class FightCheck extends Check {
private static final String id = "fight";
public final String permission;
public FightCheck(NoCheat plugin, String name, String permission) {
super(plugin, id, name);
this.permission = permission;
}
public abstract boolean check(NoCheatPlayer player, FightData data, FightConfig cc);
public abstract boolean isEnabled(FightConfig cc);
/**
* Get the "FightData" object that belongs to the player. Will ensure
* that such a object exists and if not, create one
*
* @param player
* @return
*/
public static FightData getData(NoCheatPlayer player) {
DataStore base = player.getDataStore();
FightData data = base.get(id);
if(data == null) {
data = new FightData();
base.set(id, data);
public static FightConfig getConfig(final ConfigurationCacheStore cache) {
FightConfig config = cache.get(id);
if (config == null) {
config = new FightConfig(cache.getConfiguration());
cache.set(id, config);
}
return data;
return config;
}
/**
@ -48,16 +30,35 @@ public abstract class FightCheck extends Check {
* @param player
* @return
*/
public static FightConfig getConfig(NoCheatPlayer player) {
public static FightConfig getConfig(final NoCheatPlusPlayer player) {
return getConfig(player.getConfigurationStore());
}
public static FightConfig getConfig(ConfigurationCacheStore cache) {
FightConfig config = cache.get(id);
if(config == null) {
config = new FightConfig(cache.getConfiguration());
cache.set(id, config);
/**
* Get the "FightData" object that belongs to the player. Will ensure
* that such a object exists and if not, create one
*
* @param player
* @return
*/
public static FightData getData(final NoCheatPlusPlayer player) {
final DataStore base = player.getDataStore();
FightData data = base.get(id);
if (data == null) {
data = new FightData();
base.set(id, data);
}
return config;
return data;
}
public final String permission;
public FightCheck(final NoCheatPlus plugin, final String name, final String permission) {
super(plugin, id, name);
this.permission = permission;
}
public abstract boolean check(NoCheatPlusPlayer player, FightData data, FightConfig cc);
public abstract boolean isEnabled(FightConfig cc);
}

View File

@ -1,8 +1,14 @@
package cc.co.evenprime.bukkit.nocheat.checks.fight;
package me.neatmonster.nocheatplus.checks.fight;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import me.neatmonster.nocheatplus.EventManager;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Entity;
@ -17,146 +23,180 @@ import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason;
import org.bukkit.event.player.PlayerAnimationEvent;
import cc.co.evenprime.bukkit.nocheat.EventManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
/**
* Central location to listen to events that are
* Central location to listen to events that are
* relevant for the fight checks
*
*/
public class FightCheckListener implements Listener, EventManager {
private final List<FightCheck> checks;
private final List<FightCheck> checks = new ArrayList<FightCheck>(4);
private final GodmodeCheck godmodeCheck;
private final InstanthealCheck instanthealCheck;
private final NoCheat plugin;
private final NoCheatPlus plugin;
public FightCheckListener(NoCheat plugin) {
this.checks = new ArrayList<FightCheck>(4);
public FightCheckListener(final NoCheatPlus plugin) {
// Keep these in a list, because they can be executed in a bundle
this.checks.add(new SpeedCheck(plugin));
this.checks.add(new NoswingCheck(plugin));
this.checks.add(new DirectionCheck(plugin));
this.checks.add(new ReachCheck(plugin));
checks.add(new SpeedCheck(plugin));
checks.add(new NoswingCheck(plugin));
checks.add(new DirectionCheck(plugin));
checks.add(new ReachCheck(plugin));
this.godmodeCheck = new GodmodeCheck(plugin);
this.instanthealCheck = new InstanthealCheck(plugin);
godmodeCheck = new GodmodeCheck(plugin);
instanthealCheck = new InstanthealCheck(plugin);
this.plugin = plugin;
}
/**
* We listen to EntityDamage events for obvious reasons
* @param event The EntityDamage Event
* We listen to PlayerAnimationEvent because it is used for arm swinging
*
* @param event
* The PlayerAnimationEvent
*/
@EventHandler(priority = EventPriority.LOWEST)
@EventHandler(
priority = EventPriority.MONITOR)
protected void armSwing(final PlayerAnimationEvent event) {
// Set a flag telling us that the arm has been swung
FightCheck.getData(plugin.getPlayer(event.getPlayer())).armswung = true;
}
/**
* There is an unofficial agreement that if a plugin wants an attack to
* not get checked by NoCheatPlus, it either has to use a Damage type different
* from ENTITY_ATTACK or fire an event with damage type CUSTOM and damage
* 0 directly before the to-be-ignored event.
*
* @param event
* The EntityDamageByEntityEvent
*/
private void customDamage(final EntityDamageByEntityEvent event) {
final Player damager = (Player) event.getDamager();
final NoCheatPlusPlayer player = plugin.getPlayer(damager);
final FightData data = FightCheck.getData(player);
// Skip the next damage event, because it is with high probability
// something from the Heroes plugin
data.skipNext = true;
}
/**
* We listen to death events to prevent a very specific method of doing
* godmode.
*
* @param event
* The EntityDeathEvent
*/
@EventHandler(
priority = EventPriority.MONITOR)
protected void death(final EntityDeathEvent event) {
// Only interested in dying players
if (!(event.getEntity() instanceof CraftPlayer))
return;
godmodeCheck.death((CraftPlayer) event.getEntity());
}
/**
* We listen to EntityDamage events for obvious reasons
*
* @param event
* The EntityDamage Event
*/
@EventHandler(
ignoreCancelled = true, priority = EventPriority.LOWEST)
public void entityDamage(final EntityDamageEvent event) {
// Filter some unwanted events right now
if(event.isCancelled() || !(event instanceof EntityDamageByEntityEvent))
if (!(event instanceof EntityDamageByEntityEvent))
return;
final EntityDamageByEntityEvent e = (EntityDamageByEntityEvent) event;
if(!(e.getDamager() instanceof Player)) {
if (!(e.getDamager() instanceof Player))
return;
}
if(e.getCause() == DamageCause.ENTITY_ATTACK) {
if (e.getCause() == DamageCause.ENTITY_ATTACK)
normalDamage(e);
} else if(e.getCause() == DamageCause.CUSTOM) {
else if (e.getCause() == DamageCause.CUSTOM)
customDamage(e);
}
}
/**
* We listen to EntityDamage events (again) for obvious reasons
* @param event The EntityDamage Event
*
* @param event
* The EntityDamage Event
*/
@EventHandler(priority = EventPriority.LOW)
@EventHandler(
ignoreCancelled = true, priority = EventPriority.LOW)
public void entityDamageForGodmodeCheck(final EntityDamageEvent event) {
if(event.isCancelled())
return;
// Filter unwanted events right here
final Entity entity = event.getEntity();
if(!(entity instanceof Player) || entity.isDead()) {
if (!(entity instanceof Player) || entity.isDead())
return;
}
NoCheatPlayer player = plugin.getPlayer((Player) entity);
FightConfig cc = FightCheck.getConfig(player);
final NoCheatPlusPlayer player = plugin.getPlayer((Player) entity);
final FightConfig cc = FightCheck.getConfig(player);
if(!godmodeCheck.isEnabled(cc) || player.hasPermission(godmodeCheck.permission)) {
if (!godmodeCheck.isEnabled(cc) || player.hasPermission(godmodeCheck.permission))
return;
}
FightData data = FightCheck.getData(player);
final FightData data = FightCheck.getData(player);
// Run the godmode check on the attacked player
boolean cancelled = godmodeCheck.check(plugin.getPlayer((Player) entity), data, cc);
final boolean cancelled = godmodeCheck.check(plugin.getPlayer((Player) entity), data, cc);
// It requested to "cancel" the players invulnerability, so set his
// noDamageTicks to 0
if(cancelled) {
if (cancelled)
// Remove the invulnerability from the player
player.getPlayer().setNoDamageTicks(0);
}
}
/**
* We listen to EntityRegainHealth events of type "Satiated"
* for instantheal check
*
* @param event The EntityRegainHealth Event
*/
@EventHandler(priority = EventPriority.LOWEST)
public void satiatedRegen(final EntityRegainHealthEvent event) {
@Override
public List<String> getActiveChecks(final ConfigurationCacheStore cc) {
final LinkedList<String> s = new LinkedList<String>();
if(!(event.getEntity() instanceof Player) || event.isCancelled() || event.getRegainReason() != RegainReason.SATIATED) {
return;
}
final FightConfig f = FightCheck.getConfig(cc);
boolean cancelled = false;
NoCheatPlayer player = plugin.getPlayer((Player) event.getEntity());
FightConfig config = FightCheck.getConfig(player);
if(!instanthealCheck.isEnabled(config) || player.hasPermission(instanthealCheck.permission)) {
return;
}
FightData data = FightCheck.getData(player);
cancelled = instanthealCheck.check(player, data, config);
if(cancelled) {
event.setCancelled(true);
}
if (f.directionCheck)
s.add("fight.direction");
if (f.noswingCheck)
s.add("fight.noswing");
if (f.reachCheck)
s.add("fight.reach");
if (f.speedCheck)
s.add("fight.speed");
if (f.godmodeCheck)
s.add("fight.godmode");
if (f.instanthealCheck)
s.add("fight.instantHeal");
return s;
}
/**
* A player attacked something with DamageCause ENTITY_ATTACK. That's most
* likely what we want to really check.
*
* @param event The EntityDamageByEntityEvent
* @param event
* The EntityDamageByEntityEvent
*/
private void normalDamage(final EntityDamageByEntityEvent event) {
final Player damager = (Player) event.getDamager();
final NoCheatPlayer player = plugin.getPlayer(damager);
final NoCheatPlusPlayer player = plugin.getPlayer(damager);
final FightConfig cc = FightCheck.getConfig(player);
final FightData data = FightCheck.getData(player);
// For some reason we decided to skip this event anyway
if(data.skipNext) {
if (data.skipNext) {
data.skipNext = false;
return;
}
@ -167,85 +207,46 @@ public class FightCheckListener implements Listener, EventManager {
data.damagee = ((CraftEntity) event.getEntity()).getHandle();
// Run through the four main checks
for(FightCheck check : checks) {
for (final FightCheck check : checks)
// If it should be executed, do it
if(!cancelled && check.isEnabled(cc) && !player.hasPermission(check.permission)) {
if (!cancelled && check.isEnabled(cc) && !player.hasPermission(check.permission))
cancelled = check.check(player, data, cc);
}
}
// Forget the attacked entity (to allow garbage collecting etc.
data.damagee = null;
// One of the checks requested the event to be cancelled, so do it
if(cancelled)
if (cancelled)
event.setCancelled(cancelled);
}
/**
* There is an unofficial agreement that if a plugin wants an attack to
* not get checked by NoCheat, it either has to use a Damage type different
* from ENTITY_ATTACK or fire an event with damage type CUSTOM and damage
* 0 directly before the to-be-ignored event.
* @param event The EntityDamageByEntityEvent
* We listen to EntityRegainHealth events of type "Satiated"
* for instantheal check
*
* @param event
* The EntityRegainHealth Event
*/
private void customDamage(final EntityDamageByEntityEvent event) {
@EventHandler(
ignoreCancelled = true, priority = EventPriority.LOWEST)
public void satiatedRegen(final EntityRegainHealthEvent event) {
final Player damager = (Player) event.getDamager();
final NoCheatPlayer player = plugin.getPlayer(damager);
if (!(event.getEntity() instanceof Player) || event.getRegainReason() != RegainReason.SATIATED)
return;
boolean cancelled = false;
final NoCheatPlusPlayer player = plugin.getPlayer((Player) event.getEntity());
final FightConfig config = FightCheck.getConfig(player);
if (!instanthealCheck.isEnabled(config) || player.hasPermission(instanthealCheck.permission))
return;
final FightData data = FightCheck.getData(player);
// Skip the next damage event, because it is with high probability
// something from the Heroes plugin
data.skipNext = true;
cancelled = instanthealCheck.check(player, data, config);
return;
}
/**
* We listen to death events to prevent a very specific method of doing
* godmode.
*
* @param event The EntityDeathEvent
*/
@EventHandler(priority = EventPriority.MONITOR)
protected void death(final EntityDeathEvent event) {
// Only interested in dying players
if(!(event.getEntity() instanceof CraftPlayer)) {
return;
}
godmodeCheck.death((CraftPlayer) event.getEntity());
}
/**
* We listen to PlayerAnimationEvent because it is used for arm swinging
* @param event The PlayerAnimationEvent
*/
@EventHandler(priority = EventPriority.MONITOR)
protected void armSwing(final PlayerAnimationEvent event) {
// Set a flag telling us that the arm has been swung
FightCheck.getData(plugin.getPlayer(event.getPlayer())).armswung = true;
}
public List<String> getActiveChecks(ConfigurationCacheStore cc) {
LinkedList<String> s = new LinkedList<String>();
FightConfig f = FightCheck.getConfig(cc);
if(f.directionCheck)
s.add("fight.direction");
if(f.noswingCheck)
s.add("fight.noswing");
if(f.reachCheck)
s.add("fight.reach");
if(f.speedCheck)
s.add("fight.speed");
if(f.godmodeCheck)
s.add("fight.godmode");
if(f.instanthealCheck)
s.add("fight.instantHeal");
return s;
if (cancelled)
event.setCancelled(true);
}
}

View File

@ -1,10 +1,10 @@
package cc.co.evenprime.bukkit.nocheat.checks.fight;
package me.neatmonster.nocheatplus.checks.fight;
import cc.co.evenprime.bukkit.nocheat.ConfigItem;
import cc.co.evenprime.bukkit.nocheat.actions.types.ActionList;
import cc.co.evenprime.bukkit.nocheat.config.ConfPaths;
import cc.co.evenprime.bukkit.nocheat.config.NoCheatConfiguration;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import me.neatmonster.nocheatplus.ConfigItem;
import me.neatmonster.nocheatplus.actions.types.ActionList;
import me.neatmonster.nocheatplus.config.ConfPaths;
import me.neatmonster.nocheatplus.config.NoCheatPlusConfiguration;
import me.neatmonster.nocheatplus.config.Permissions;
/**
* Configurations specific for the "Fight" checks
@ -37,16 +37,16 @@ public class FightConfig implements ConfigItem {
public final boolean instanthealCheck;
public final ActionList instanthealActions;
public FightConfig(NoCheatConfiguration data) {
public FightConfig(final NoCheatPlusConfiguration data) {
directionCheck = data.getBoolean(ConfPaths.FIGHT_DIRECTION_CHECK);
directionPrecision = ((double) (data.getInt(ConfPaths.FIGHT_DIRECTION_PRECISION))) / 100D;
directionPrecision = data.getInt(ConfPaths.FIGHT_DIRECTION_PRECISION) / 100D;
directionPenaltyTime = data.getInt(ConfPaths.FIGHT_DIRECTION_PENALTYTIME);
directionActions = data.getActionList(ConfPaths.FIGHT_DIRECTION_ACTIONS, Permissions.FIGHT_DIRECTION);
noswingCheck = data.getBoolean(ConfPaths.FIGHT_NOSWING_CHECK);
noswingActions = data.getActionList(ConfPaths.FIGHT_NOSWING_ACTIONS, Permissions.FIGHT_NOSWING);
reachCheck = data.getBoolean(ConfPaths.FIGHT_REACH_CHECK);
reachLimit = ((double) (data.getInt(ConfPaths.FIGHT_REACH_LIMIT))) / 100D;
reachLimit = data.getInt(ConfPaths.FIGHT_REACH_LIMIT) / 100D;
reachPenaltyTime = data.getInt(ConfPaths.FIGHT_REACH_PENALTYTIME);
reachActions = data.getActionList(ConfPaths.FIGHT_REACH_ACTIONS, Permissions.FIGHT_REACH);
speedCheck = data.getBoolean(ConfPaths.FIGHT_SPEED_CHECK);

View File

@ -1,7 +1,7 @@
package cc.co.evenprime.bukkit.nocheat.checks.fight;
package me.neatmonster.nocheatplus.checks.fight;
import me.neatmonster.nocheatplus.DataItem;
import net.minecraft.server.Entity;
import cc.co.evenprime.bukkit.nocheat.DataItem;
/**
* Player specific data for the fight checks

View File

@ -1,14 +1,16 @@
package cc.co.evenprime.bukkit.nocheat.checks.fight;
package me.neatmonster.nocheatplus.checks.fight;
import java.util.Locale;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.config.Permissions;
import me.neatmonster.nocheatplus.data.Statistics;
import net.minecraft.server.EntityPlayer;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.data.Statistics;
/**
* The Godmode Check will find out if a player tried to stay invulnerable after
@ -17,35 +19,35 @@ import cc.co.evenprime.bukkit.nocheat.data.Statistics;
*/
public class GodmodeCheck extends FightCheck {
public GodmodeCheck(NoCheat plugin) {
public GodmodeCheck(final NoCheatPlus plugin) {
super(plugin, "fight.godmode", Permissions.FIGHT_GODMODE);
}
@Override
public boolean check(NoCheatPlayer player, FightData data, FightConfig cc) {
public boolean check(final NoCheatPlusPlayer player, final FightData data, final FightConfig cc) {
boolean cancelled = false;
long time = System.currentTimeMillis();
final long time = System.currentTimeMillis();
// Check at most once a second
if(data.godmodeLastDamageTime + 1000L < time) {
if (data.godmodeLastDamageTime + 1000L < time) {
data.godmodeLastDamageTime = time;
// How old is the player now?
int age = player.getTicksLived();
final int age = player.getTicksLived();
// How much older did he get?
int ageDiff = Math.max(0, age - data.godmodeLastAge);
final int ageDiff = Math.max(0, age - data.godmodeLastAge);
// Is he invulnerable?
int nodamageTicks = player.getPlayer().getNoDamageTicks();
final int nodamageTicks = player.getPlayer().getNoDamageTicks();
if(nodamageTicks > 0 && ageDiff < 15) {
if (nodamageTicks > 0 && ageDiff < 15) {
// He is invulnerable and didn't age fast enough, that costs
// some points
data.godmodeBuffer -= (15 - ageDiff);
data.godmodeBuffer -= 15 - ageDiff;
// Still points left?
if(data.godmodeBuffer <= 0) {
if (data.godmodeBuffer <= 0) {
// No, that means VL and statistics increased
data.godmodeVL -= data.godmodeBuffer;
incrementStatistics(player, Statistics.Id.FI_GODMODE, -data.godmodeBuffer);
@ -60,13 +62,12 @@ public class GodmodeCheck extends FightCheck {
data.godmodeVL *= 0.95;
}
if(data.godmodeBuffer < 0) {
if (data.godmodeBuffer < 0)
// Can't have less than 0
data.godmodeBuffer = 0;
} else if(data.godmodeBuffer > 30) {
else if (data.godmodeBuffer > 30)
// And 30 is enough for simple lag situations
data.godmodeBuffer = 30;
}
// Start age counting from a new time
data.godmodeLastAge = age;
@ -75,49 +76,50 @@ public class GodmodeCheck extends FightCheck {
return cancelled;
}
@Override
public boolean isEnabled(FightConfig cc) {
return cc.godmodeCheck;
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).godmodeVL);
else
return super.getParameter(wildcard, player);
}
/**
* If a player apparently died, make sure he really dies after some time
* if he didn't already, by setting up a Bukkit task
*
* @param player The player
*
* @param player
* The player
*/
public void death(CraftPlayer player) {
public void death(final CraftPlayer player) {
// First check if the player is really dead (e.g. another plugin could
// have just fired an artificial event)
if(player.getHealth() <= 0 && player.isDead()) {
if (player.getHealth() <= 0 && player.isDead())
try {
final EntityPlayer entity = player.getHandle();
// Schedule a task to be executed in roughly 1.5 seconds
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
@Override
public void run() {
try {
// Check again if the player should be dead, and
// if the game didn't mark him as dead
if(entity.getHealth() <= 0 && !entity.dead) {
if (entity.getHealth() <= 0 && !entity.dead) {
// Artifically "kill" him
entity.deathTicks = 19;
entity.a(true);
}
} catch(Exception e) {}
} catch (final Exception e) {}
}
}, 30);
} catch(Exception e) {}
}
} catch (final Exception e) {}
}
@Override
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).godmodeVL);
else
return super.getParameter(wildcard, player);
}
@Override
public boolean isEnabled(final FightConfig cc) {
return cc.godmodeCheck;
}
}

View File

@ -1,11 +1,12 @@
package cc.co.evenprime.bukkit.nocheat.checks.fight;
package me.neatmonster.nocheatplus.checks.fight;
import java.util.Locale;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.data.Statistics;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.config.Permissions;
import me.neatmonster.nocheatplus.data.Statistics;
/**
* The instantheal Check should find out if a player tried to artificially
@ -14,31 +15,31 @@ import cc.co.evenprime.bukkit.nocheat.data.Statistics;
*/
public class InstanthealCheck extends FightCheck {
public InstanthealCheck(NoCheat plugin) {
public InstanthealCheck(final NoCheatPlus plugin) {
super(plugin, "fight.instantheal", Permissions.FIGHT_INSTANTHEAL);
}
@Override
public boolean check(NoCheatPlayer player, FightData data, FightConfig cc) {
public boolean check(final NoCheatPlusPlayer player, final FightData data, final FightConfig cc) {
boolean cancelled = false;
long time = System.currentTimeMillis();
final long time = System.currentTimeMillis();
// security check if system time ran backwards
if(data.instanthealLastRegenTime > time) {
if (data.instanthealLastRegenTime > time) {
data.instanthealLastRegenTime = 0;
return false;
}
long difference = time - (data.instanthealLastRegenTime + 3500L);
final long difference = time - (data.instanthealLastRegenTime + 3500L);
data.instanthealBuffer += difference;
if(data.instanthealBuffer < 0) {
if (data.instanthealBuffer < 0) {
// Buffer has been fully consumed
// Increase vl and statistics
double vl = data.instanthealVL -= data.instanthealBuffer / 1000;
final double vl = data.instanthealVL -= data.instanthealBuffer / 1000;
incrementStatistics(player, Statistics.Id.FI_INSTANTHEAL, vl);
data.instanthealBuffer = 0;
@ -46,35 +47,32 @@ public class InstanthealCheck extends FightCheck {
// Execute whatever actions are associated with this check and the
// violation level and find out if we should cancel the event
cancelled = executeActions(player, cc.instanthealActions, data.instanthealVL);
} else {
} else
// vl gets decreased
data.instanthealVL *= 0.9;
}
// max 2 seconds buffer
if(data.instanthealBuffer > 2000L) {
if (data.instanthealBuffer > 2000L)
data.instanthealBuffer = 2000L;
}
if(!cancelled) {
if (!cancelled)
// New reference time
data.instanthealLastRegenTime = time;
}
return cancelled;
}
@Override
public boolean isEnabled(FightConfig cc) {
return cc.instanthealCheck;
}
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).instanthealVL);
else
return super.getParameter(wildcard, player);
}
@Override
public boolean isEnabled(final FightConfig cc) {
return cc.instanthealCheck;
}
}

View File

@ -1,29 +1,31 @@
package cc.co.evenprime.bukkit.nocheat.checks.fight;
package me.neatmonster.nocheatplus.checks.fight;
import java.util.Locale;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.config.Permissions;
import me.neatmonster.nocheatplus.data.Statistics.Id;
/**
* We require that the player moves his arm between attacks, this is
* what gets checked here.
*
*
*/
public class NoswingCheck extends FightCheck {
public NoswingCheck(NoCheat plugin) {
public NoswingCheck(final NoCheatPlus plugin) {
super(plugin, "fight.noswing", Permissions.FIGHT_NOSWING);
}
public boolean check(NoCheatPlayer player, FightData data, FightConfig cc) {
@Override
public boolean check(final NoCheatPlusPlayer player, final FightData data, final FightConfig cc) {
boolean cancel = false;
// did he swing his arm before?
if(data.armswung) {
if (data.armswung) {
// Yes, reward him with reduction of his vl
data.armswung = false;
data.noswingVL *= 0.90D;
@ -41,16 +43,16 @@ public class NoswingCheck extends FightCheck {
}
@Override
public boolean isEnabled(FightConfig cc) {
return cc.noswingCheck;
}
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).noswingVL);
else
return super.getParameter(wildcard, player);
}
@Override
public boolean isEnabled(final FightConfig cc) {
return cc.noswingCheck;
}
}

View File

@ -1,15 +1,16 @@
package cc.co.evenprime.bukkit.nocheat.checks.fight;
package me.neatmonster.nocheatplus.checks.fight;
import java.util.Locale;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.checks.CheckUtil;
import me.neatmonster.nocheatplus.config.Permissions;
import me.neatmonster.nocheatplus.data.Statistics.Id;
import net.minecraft.server.Entity;
import net.minecraft.server.EntityComplex;
import net.minecraft.server.EntityComplexPart;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.checks.CheckUtil;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
/**
* The reach check will find out if a player interacts with something that's
@ -18,40 +19,40 @@ import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
*/
public class ReachCheck extends FightCheck {
public ReachCheck(NoCheat plugin) {
public ReachCheck(final NoCheatPlus plugin) {
super(plugin, "fight.reach", Permissions.FIGHT_REACH);
}
public boolean check(NoCheatPlayer player, FightData data, FightConfig cc) {
@Override
public boolean check(final NoCheatPlusPlayer player, final FightData data, final FightConfig cc) {
boolean cancel = false;
final long time = System.currentTimeMillis();
// Get the width of the damagee
Entity entity = data.damagee;
final Entity entity = data.damagee;
// Safeguard, if entity is Giant or Ender Dragon, this check will fail
// due to giant and hard to define hitboxes
if(entity instanceof EntityComplex || entity instanceof EntityComplexPart) {
if (entity instanceof EntityComplex || entity instanceof EntityComplexPart)
return false;
}
// Distance is calculated from eye location to center of targeted
// If the player is further away from his target than allowed, the
// difference will be assigned to "distance"
final double off = CheckUtil.reachCheck(player, entity.locX, entity.locY + 1.0D, entity.locZ, cc.reachLimit);
if(off < 0.1D) {
if (off < 0.1D)
// Player did probably nothing wrong
// reduce violation counter to reward him
data.reachVL *= 0.80D;
} else {
else {
// Player failed the check
// Increment violation counter and statistics
// This is influenced by lag, so don't do it if there was lag
if(!plugin.skipCheck()) {
double sqrt = Math.sqrt(off);
if (!plugin.skipCheck()) {
final double sqrt = Math.sqrt(off);
data.reachVL += sqrt;
incrementStatistics(player, Id.FI_REACH, sqrt);
}
@ -60,19 +61,17 @@ public class ReachCheck extends FightCheck {
// violation level and find out if we should cancel the event
cancel = executeActions(player, cc.reachActions, data.reachVL);
if(cancel) {
if (cancel)
// if we should cancel, remember the current time too
data.reachLastViolationTime = time;
}
}
// If the player is still in penalty time, cancel the event anyway
if(data.reachLastViolationTime + cc.reachPenaltyTime > time) {
if (data.reachLastViolationTime + cc.reachPenaltyTime > time) {
// A safeguard to avoid people getting stuck in penalty time
// indefinitely in case the system time of the server gets changed
if(data.reachLastViolationTime > time) {
if (data.reachLastViolationTime > time)
data.reachLastViolationTime = 0;
}
// He is in penalty time, therefore request cancelling of the event
return true;
@ -82,16 +81,16 @@ public class ReachCheck extends FightCheck {
}
@Override
public boolean isEnabled(FightConfig cc) {
return cc.reachCheck;
}
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).reachVL);
else
return super.getParameter(wildcard, player);
}
@Override
public boolean isEnabled(final FightConfig cc) {
return cc.reachCheck;
}
}

View File

@ -1,11 +1,12 @@
package cc.co.evenprime.bukkit.nocheat.checks.fight;
package me.neatmonster.nocheatplus.checks.fight;
import java.util.Locale;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.config.Permissions;
import me.neatmonster.nocheatplus.data.Statistics.Id;
/**
* The speed check will find out if a player interacts with something that's
@ -14,18 +15,19 @@ import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
*/
public class SpeedCheck extends FightCheck {
public SpeedCheck(NoCheat plugin) {
public SpeedCheck(final NoCheatPlus plugin) {
super(plugin, "fight.speed", Permissions.FIGHT_SPEED);
}
public boolean check(NoCheatPlayer player, FightData data, FightConfig cc) {
@Override
public boolean check(final NoCheatPlusPlayer player, final FightData data, final FightConfig cc) {
boolean cancel = false;
final long time = System.currentTimeMillis();
// Check if one second has passed and reset counters and vl in that case
if(data.speedTime + 1000L <= time) {
if (data.speedTime + 1000L <= time) {
data.speedTime = time;
data.speedAttackCount = 0;
data.speedVL = 0;
@ -35,9 +37,9 @@ public class SpeedCheck extends FightCheck {
data.speedAttackCount++;
// too many attacks
if(data.speedAttackCount > cc.speedAttackLimit) {
if (data.speedAttackCount > cc.speedAttackLimit) {
// if there was lag, don't count it towards statistics and vl
if(!plugin.skipCheck()) {
if (!plugin.skipCheck()) {
data.speedVL += 1;
incrementStatistics(player, Id.FI_SPEED, 1);
}
@ -51,18 +53,18 @@ public class SpeedCheck extends FightCheck {
}
@Override
public boolean isEnabled(FightConfig cc) {
return cc.speedCheck;
}
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).speedVL);
else if(wildcard == ParameterName.LIMIT)
return String.format(Locale.US, "%d", (int) getConfig(player.getConfigurationStore()).speedAttackLimit);
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", getData(player).speedVL);
else if (wildcard == ParameterName.LIMIT)
return String.format(Locale.US, "%d", getConfig(player.getConfigurationStore()).speedAttackLimit);
else
return super.getParameter(wildcard, player);
}
@Override
public boolean isEnabled(final FightConfig cc) {
return cc.speedCheck;
}
}

View File

@ -1,10 +1,11 @@
package cc.co.evenprime.bukkit.nocheat.checks.inventory;
package me.neatmonster.nocheatplus.checks.inventory;
import java.util.Locale;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.data.Statistics.Id;
/**
* The DropCheck will find out if a player drops too many items within a short
@ -13,31 +14,30 @@ import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
*/
public class DropCheck extends InventoryCheck {
public DropCheck(NoCheat plugin) {
public DropCheck(final NoCheatPlus plugin) {
super(plugin, "inventory.drop");
}
public boolean check(NoCheatPlayer player, InventoryData data, InventoryConfig cc) {
public boolean check(final NoCheatPlusPlayer player, final InventoryData data, final InventoryConfig cc) {
boolean cancel = false;
final long time = System.currentTimeMillis();
// Has the configured time passed? If so, reset the counter
if(data.dropLastTime + cc.dropTimeFrame <= time) {
if (data.dropLastTime + cc.dropTimeFrame <= time) {
data.dropLastTime = time;
data.dropCount = 0;
data.dropVL = 0;
}
// Security check, if the system time changes
else if(data.dropLastTime > time) {
else if (data.dropLastTime > time)
data.dropLastTime = Integer.MIN_VALUE;
}
data.dropCount++;
// The player dropped more than he should
if(data.dropCount > cc.dropLimit) {
if (data.dropCount > cc.dropLimit) {
// Set vl and increment statistics
data.dropVL = data.dropCount - cc.dropLimit;
incrementStatistics(player, Id.INV_DROP, 1);
@ -51,9 +51,9 @@ public class DropCheck extends InventoryCheck {
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", getData(player).dropVL);
else
return super.getParameter(wildcard, player);

View File

@ -1,11 +1,13 @@
package cc.co.evenprime.bukkit.nocheat.checks.inventory;
package me.neatmonster.nocheatplus.checks.inventory;
import java.util.Locale;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.data.Statistics.Id;
import org.bukkit.event.entity.EntityShootBowEvent;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
/**
* The InstantBowCheck will find out if a player pulled the string of his bow
@ -13,31 +15,32 @@ import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
*/
public class InstantBowCheck extends InventoryCheck {
public InstantBowCheck(NoCheat plugin) {
public InstantBowCheck(final NoCheatPlus plugin) {
super(plugin, "inventory.instantbow");
}
public boolean check(NoCheatPlayer player, EntityShootBowEvent event, InventoryData data, InventoryConfig cc) {
public boolean check(final NoCheatPlusPlayer player, final EntityShootBowEvent event, final InventoryData data,
final InventoryConfig cc) {
boolean cancelled = false;
long time = System.currentTimeMillis();
final long time = System.currentTimeMillis();
// How fast will the arrow be?
float bowForce = event.getForce();
final float bowForce = event.getForce();
// Rough estimation of how long pulling the string should've taken
long expectedTimeWhenStringDrawn = data.lastBowInteractTime + (int) (bowForce * bowForce * 700F);
final long expectedTimeWhenStringDrawn = data.lastBowInteractTime + (int) (bowForce * bowForce * 700F);
if(expectedTimeWhenStringDrawn < time) {
if (expectedTimeWhenStringDrawn < time)
// The player was slow enough, reward him by lowering the vl
data.instantBowVL *= 0.90D;
} else if(data.lastBowInteractTime > time) {
else if (data.lastBowInteractTime > time)
// Security check if time ran backwards, reset
data.lastBowInteractTime = 0;
} else {
else {
// Player was too fast, increase violation level and statistics
int vl = ((int) (expectedTimeWhenStringDrawn - time)) / 100;
final int vl = (int) (expectedTimeWhenStringDrawn - time) / 100;
data.instantBowVL += vl;
incrementStatistics(player, Id.INV_BOW, vl);
@ -50,10 +53,10 @@ public class InstantBowCheck extends InventoryCheck {
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).instantBowVL);
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", getData(player).instantBowVL);
else
return super.getParameter(wildcard, player);
}

View File

@ -1,42 +1,45 @@
package cc.co.evenprime.bukkit.nocheat.checks.inventory;
package me.neatmonster.nocheatplus.checks.inventory;
import java.util.Locale;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.data.Statistics.Id;
import org.bukkit.event.entity.FoodLevelChangeEvent;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
/**
* The InstantEatCheck will find out if a player eats his food too fast
*/
public class InstantEatCheck extends InventoryCheck {
public InstantEatCheck(NoCheat plugin) {
public InstantEatCheck(final NoCheatPlus plugin) {
super(plugin, "inventory.instanteat");
}
public boolean check(NoCheatPlayer player, FoodLevelChangeEvent event, InventoryData data, InventoryConfig cc) {
public boolean check(final NoCheatPlusPlayer player, final FoodLevelChangeEvent event, final InventoryData data,
final InventoryConfig cc) {
// Hunger level change seems to not be the result of eating
if(data.foodMaterial == null || event.getFoodLevel() <= player.getPlayer().getFoodLevel())
if (data.foodMaterial == null || event.getFoodLevel() <= player.getPlayer().getFoodLevel())
return false;
boolean cancelled = false;
long time = System.currentTimeMillis();
final long time = System.currentTimeMillis();
// rough estimation about how long it should take to eat
long expectedTimeWhenEatingFinished = data.lastEatInteractTime + 700;
final long expectedTimeWhenEatingFinished = data.lastEatInteractTime + 700;
if(expectedTimeWhenEatingFinished < time) {
if (expectedTimeWhenEatingFinished < time)
// Acceptable, reduce VL to reward the player
data.instantEatVL *= 0.60D;
} else if(data.lastEatInteractTime > time) {
else if (data.lastEatInteractTime > time)
// Security test, if time ran backwards, reset
data.lastEatInteractTime = 0;
} else {
else {
// Player was too fast, increase violation level and statistics
int vl = ((int) (expectedTimeWhenEatingFinished - time)) / 100;
final int vl = (int) (expectedTimeWhenEatingFinished - time) / 100;
data.instantEatVL += vl;
incrementStatistics(player, Id.INV_EAT, vl);
@ -49,11 +52,11 @@ public class InstantEatCheck extends InventoryCheck {
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).instantEatVL);
else if(wildcard == ParameterName.FOOD)
else if (wildcard == ParameterName.FOOD)
return getData(player).foodMaterial.toString();
else
return super.getParameter(wildcard, player);

View File

@ -1,10 +1,10 @@
package cc.co.evenprime.bukkit.nocheat.checks.inventory;
package me.neatmonster.nocheatplus.checks.inventory;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.checks.Check;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.data.DataStore;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.checks.Check;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import me.neatmonster.nocheatplus.data.DataStore;
/**
* Abstract base class for Inventory checks, provides some convenience
@ -14,25 +14,13 @@ public abstract class InventoryCheck extends Check {
private static final String id = "inventory";
public InventoryCheck(NoCheat plugin, String name) {
super(plugin, id, name);
}
/**
* Get the "InventoryData" object that belongs to the player. Will ensure
* that such a object exists and if not, create one
*
* @param player
* @return
*/
public static InventoryData getData(NoCheatPlayer player) {
DataStore base = player.getDataStore();
InventoryData data = base.get(id);
if(data == null) {
data = new InventoryData();
base.set(id, data);
public static InventoryConfig getConfig(final ConfigurationCacheStore cache) {
InventoryConfig config = cache.get(id);
if (config == null) {
config = new InventoryConfig(cache.getConfiguration());
cache.set(id, config);
}
return data;
return config;
}
/**
@ -42,16 +30,28 @@ public abstract class InventoryCheck extends Check {
* @param player
* @return
*/
public static InventoryConfig getConfig(NoCheatPlayer player) {
public static InventoryConfig getConfig(final NoCheatPlusPlayer player) {
return getConfig(player.getConfigurationStore());
}
public static InventoryConfig getConfig(ConfigurationCacheStore cache) {
InventoryConfig config = cache.get(id);
if(config == null) {
config = new InventoryConfig(cache.getConfiguration());
cache.set(id, config);
/**
* Get the "InventoryData" object that belongs to the player. Will ensure
* that such a object exists and if not, create one
*
* @param player
* @return
*/
public static InventoryData getData(final NoCheatPlusPlayer player) {
final DataStore base = player.getDataStore();
InventoryData data = base.get(id);
if (data == null) {
data = new InventoryData();
base.set(id, data);
}
return config;
return data;
}
public InventoryCheck(final NoCheatPlus plugin, final String name) {
super(plugin, id, name);
}
}

View File

@ -1,7 +1,15 @@
package cc.co.evenprime.bukkit.nocheat.checks.inventory;
package me.neatmonster.nocheatplus.checks.inventory;
import java.util.LinkedList;
import java.util.List;
import me.neatmonster.nocheatplus.EventManager;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.checks.CheckUtil;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import me.neatmonster.nocheatplus.config.Permissions;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -12,15 +20,9 @@ import org.bukkit.event.entity.EntityShootBowEvent;
import org.bukkit.event.entity.FoodLevelChangeEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import cc.co.evenprime.bukkit.nocheat.EventManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.checks.CheckUtil;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
/**
* Central location to listen to events that are
* Central location to listen to events that are
* relevant for the inventory checks
*
*/
@ -30,76 +32,39 @@ public class InventoryCheckListener implements Listener, EventManager {
private final InstantBowCheck instantBowCheck;
private final InstantEatCheck instantEatCheck;
private final NoCheat plugin;
private final NoCheatPlus plugin;
public InventoryCheckListener(NoCheat plugin) {
public InventoryCheckListener(final NoCheatPlus plugin) {
this.dropCheck = new DropCheck(plugin);
this.instantBowCheck = new InstantBowCheck(plugin);
this.instantEatCheck = new InstantEatCheck(plugin);
dropCheck = new DropCheck(plugin);
instantBowCheck = new InstantBowCheck(plugin);
instantEatCheck = new InstantEatCheck(plugin);
this.plugin = plugin;
}
/**
* We listen to DropItem Event for the dropCheck
* @param event The PlayerDropItem Event
* We listen to EntityShootBowEvent for the instantbow check
*
* @param event
* The EntityShootBowEvent
*/
@EventHandler(priority = EventPriority.LOWEST)
protected void handlePlayerDropItemEvent(final PlayerDropItemEvent event) {
@EventHandler(
ignoreCancelled = true, priority = EventPriority.LOWEST)
public void bowfired(final EntityShootBowEvent event) {
// Only if a player shot the arrow
if (event.getEntity() instanceof Player) {
final NoCheatPlusPlayer player = plugin.getPlayer((Player) event.getEntity());
final InventoryConfig cc = InventoryCheck.getConfig(player);
if(event.isCancelled() || event.getPlayer().isDead())
return;
// Only if he should get checked
if (cc.bowCheck && !player.hasPermission(Permissions.INVENTORY_INSTANTBOW)) {
final InventoryData data = InventoryCheck.getData(player);
final boolean cancelled = instantBowCheck.check(player, event, data, cc);
boolean cancelled = false;
final NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
final InventoryConfig cc = InventoryCheck.getConfig(player);
final InventoryData data = InventoryCheck.getData(player);
// If it should be executed, do it
if(cc.dropCheck && !player.hasPermission(Permissions.INVENTORY_DROP)) {
cancelled = dropCheck.check(player, data, cc);
}
if(cancelled) {
// Cancelling drop events is not save (in certain circumstances
// items will disappear completely). So don't do it and kick
// players instead by default
// event.setCancelled(true);
}
}
/**
* We listen to PlayerInteractEvent for the instantEat and instantBow
* checks
* @param event The PlayerInteractEvent
*/
@EventHandler(priority = EventPriority.LOWEST)
public void interact(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))
return;
NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
final InventoryData data = InventoryCheck.getData(player);
if(event.getItem().getType() == Material.BOW) {
// It was a bow, the player starts to pull the string
// Remember this time
data.lastBowInteractTime = System.currentTimeMillis();
} else if(CheckUtil.isFood(event.getItem())) {
// It was food, the player starts to eat some food
// Remember this time and the type of food
data.foodMaterial = event.getItem().getType();
data.lastEatInteractTime = System.currentTimeMillis();
} else {
// Nothing that we are interested in, reset data
data.lastBowInteractTime = 0;
data.lastEatInteractTime = 0;
data.foodMaterial = null;
// The check requested the bowshooting to get cancelled
event.setCancelled(cancelled);
}
}
}
@ -107,20 +72,22 @@ public class InventoryCheckListener implements Listener, EventManager {
* We listen to FoodLevelChange Event because Bukkit doesn't provide a
* PlayerFoodEating Event (or whatever it would be called).
*
* @param event The FoodLevelChangeEvent
* @param event
* The FoodLevelChangeEvent
*/
@EventHandler(priority = EventPriority.LOWEST)
@EventHandler(
ignoreCancelled = true, priority = EventPriority.LOWEST)
public void foodchanged(final FoodLevelChangeEvent event) {
// Only if a player ate food
if(!event.isCancelled() && event.getEntity() instanceof Player) {
final NoCheatPlayer player = plugin.getPlayer((Player) event.getEntity());
if (event.getEntity() instanceof Player) {
final NoCheatPlusPlayer player = plugin.getPlayer((Player) event.getEntity());
final InventoryConfig cc = InventoryCheck.getConfig(player);
final InventoryData data = InventoryCheck.getData(player);
// Only if he should get checked
if(cc.eatCheck && !player.hasPermission(Permissions.INVENTORY_INSTANTEAT)) {
if (cc.eatCheck && !player.hasPermission(Permissions.INVENTORY_INSTANTEAT)) {
boolean cancelled = instantEatCheck.check(player, event, data, cc);
final boolean cancelled = instantEatCheck.check(player, event, data, cc);
// The check requested the foodlevelchange to get cancelled
event.setCancelled(cancelled);
@ -132,39 +99,85 @@ public class InventoryCheckListener implements Listener, EventManager {
}
/**
* We listen to EntityShootBowEvent for the instantbow check
*
* @param event The EntityShootBowEvent
*/
@EventHandler(priority = EventPriority.LOWEST)
public void bowfired(final EntityShootBowEvent event) {
// Only if a player shot the arrow
if(!event.isCancelled() && event.getEntity() instanceof Player) {
final NoCheatPlayer player = plugin.getPlayer((Player) event.getEntity());
final InventoryConfig cc = InventoryCheck.getConfig(player);
@Override
public List<String> getActiveChecks(final ConfigurationCacheStore cc) {
final LinkedList<String> s = new LinkedList<String>();
// Only if he should get checked
if(cc.bowCheck && !player.hasPermission(Permissions.INVENTORY_INSTANTBOW)) {
final InventoryData data = InventoryCheck.getData(player);
boolean cancelled = instantBowCheck.check(player, event, data, cc);
// The check requested the bowshooting to get cancelled
event.setCancelled(cancelled);
}
}
}
public List<String> getActiveChecks(ConfigurationCacheStore cc) {
LinkedList<String> s = new LinkedList<String>();
InventoryConfig i = InventoryCheck.getConfig(cc);
if(i.dropCheck)
final InventoryConfig i = InventoryCheck.getConfig(cc);
if (i.dropCheck)
s.add("inventory.dropCheck");
if(i.bowCheck)
if (i.bowCheck)
s.add("inventory.instantbow");
if(i.eatCheck)
if (i.eatCheck)
s.add("inventory.instanteat");
return s;
}
/**
* We listen to DropItem Event for the dropCheck
*
* @param event
* The PlayerDropItem Event
*/
@EventHandler(
ignoreCancelled = true, priority = EventPriority.LOWEST)
protected void handlePlayerDropItemEvent(final PlayerDropItemEvent event) {
if (event.getPlayer().isDead())
return;
boolean cancelled = false;
final NoCheatPlusPlayer player = plugin.getPlayer(event.getPlayer());
final InventoryConfig cc = InventoryCheck.getConfig(player);
final InventoryData data = InventoryCheck.getData(player);
// If it should be executed, do it
if (cc.dropCheck && !player.hasPermission(Permissions.INVENTORY_DROP))
cancelled = dropCheck.check(player, data, cc);
if (cancelled) {
// Cancelling drop events is not save (in certain circumstances
// items will disappear completely). So don't do it and kick
// players instead by default
// event.setCancelled(true);
}
}
/**
* We listen to PlayerInteractEvent for the instantEat and instantBow
* checks
*
* @param event
* The PlayerInteractEvent
*/
@EventHandler(
priority = EventPriority.LOWEST)
public void interact(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))
return;
final NoCheatPlusPlayer player = plugin.getPlayer(event.getPlayer());
final InventoryData data = InventoryCheck.getData(player);
if (event.getItem().getType() == Material.BOW)
// It was a bow, the player starts to pull the string
// Remember this time
data.lastBowInteractTime = System.currentTimeMillis();
else if (CheckUtil.isFood(event.getItem())) {
// It was food, the player starts to eat some food
// Remember this time and the type of food
data.foodMaterial = event.getItem().getType();
data.lastEatInteractTime = System.currentTimeMillis();
} else {
// Nothing that we are interested in, reset data
data.lastBowInteractTime = 0;
data.lastEatInteractTime = 0;
data.foodMaterial = null;
}
}
}

View File

@ -1,10 +1,10 @@
package cc.co.evenprime.bukkit.nocheat.checks.inventory;
package me.neatmonster.nocheatplus.checks.inventory;
import cc.co.evenprime.bukkit.nocheat.ConfigItem;
import cc.co.evenprime.bukkit.nocheat.actions.types.ActionList;
import cc.co.evenprime.bukkit.nocheat.config.ConfPaths;
import cc.co.evenprime.bukkit.nocheat.config.NoCheatConfiguration;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import me.neatmonster.nocheatplus.ConfigItem;
import me.neatmonster.nocheatplus.actions.types.ActionList;
import me.neatmonster.nocheatplus.config.ConfPaths;
import me.neatmonster.nocheatplus.config.NoCheatPlusConfiguration;
import me.neatmonster.nocheatplus.config.Permissions;
/**
* Configurations specific for the "Inventory" checks
@ -25,7 +25,7 @@ public class InventoryConfig implements ConfigItem {
public final boolean eatCheck;
public final ActionList eatActions;
public InventoryConfig(NoCheatConfiguration data) {
public InventoryConfig(final NoCheatPlusConfiguration data) {
dropCheck = data.getBoolean(ConfPaths.INVENTORY_DROP_CHECK);
dropTimeFrame = data.getInt(ConfPaths.INVENTORY_DROP_TIMEFRAME) * 1000;

View File

@ -1,7 +1,8 @@
package cc.co.evenprime.bukkit.nocheat.checks.inventory;
package me.neatmonster.nocheatplus.checks.inventory;
import me.neatmonster.nocheatplus.DataItem;
import org.bukkit.Material;
import cc.co.evenprime.bukkit.nocheat.DataItem;
/**
* Player specific data for the inventory checks

View File

@ -1,11 +1,12 @@
package cc.co.evenprime.bukkit.nocheat.checks.moving;
package me.neatmonster.nocheatplus.checks.moving;
import java.util.Locale;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.data.PreciseLocation;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.data.PreciseLocation;
import me.neatmonster.nocheatplus.data.Statistics.Id;
/**
* A check designed for people that are allowed to fly. The complement to
@ -15,15 +16,15 @@ import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
*/
public class FlyingCheck extends MovingCheck {
public FlyingCheck(NoCheat plugin) {
super(plugin, "moving.flying");
}
// Determined by trial and error, the flying movement speed of the creative
// mode
private static final double creativeSpeed = 0.60D;
public PreciseLocation check(NoCheatPlayer player, MovingData data, MovingConfig ccmoving) {
public FlyingCheck(final NoCheatPlus plugin) {
super(plugin, "moving.flying");
}
public PreciseLocation check(final NoCheatPlusPlayer player, final MovingData data, final MovingConfig ccmoving) {
// The setBack is the location that players may get teleported to when
// they fail the check
@ -33,18 +34,17 @@ public class FlyingCheck extends MovingCheck {
final PreciseLocation to = data.to;
// If we have no setback, define one now
if(!setBack.isSet()) {
if (!setBack.isSet())
setBack.set(from);
}
// Used to store the location where the player gets teleported to
PreciseLocation newToLocation = null;
// Before doing anything, do a basic height check to determine if
// players are flying too high
int maxheight = ccmoving.flyingHeightLimit + player.getPlayer().getWorld().getMaxHeight();
final int maxheight = ccmoving.flyingHeightLimit + player.getPlayer().getWorld().getMaxHeight();
if(to.y - data.vertFreedom > maxheight) {
if (to.y - data.vertFreedom > maxheight) {
newToLocation = new PreciseLocation();
newToLocation.set(setBack);
newToLocation.y = maxheight - 10;
@ -57,14 +57,15 @@ public class FlyingCheck extends MovingCheck {
final double zDistance = to.z - from.z;
// How far did the player move horizontally
final double horizontalDistance = Math.sqrt((xDistance * xDistance + zDistance * zDistance));
final double horizontalDistance = Math.sqrt(xDistance * xDistance + zDistance * zDistance);
double resultHoriz = 0;
double resultVert = 0;
double result = 0;
// In case of creative game mode give at least 0.60 speed limit horizontal
double speedLimitHorizontal = player.isCreative() ? Math.max(creativeSpeed, ccmoving.flyingSpeedLimitHorizontal) : ccmoving.flyingSpeedLimitHorizontal;
double speedLimitHorizontal = player.isCreative() ? Math
.max(creativeSpeed, ccmoving.flyingSpeedLimitHorizontal) : ccmoving.flyingSpeedLimitHorizontal;
// If the player is affected by potion of swiftness
speedLimitHorizontal *= player.getSpeedAmplifier();
@ -72,36 +73,32 @@ public class FlyingCheck extends MovingCheck {
// Finally, determine how far the player went beyond the set limits
resultHoriz = Math.max(0.0D, horizontalDistance - data.horizFreedom - speedLimitHorizontal);
boolean sprinting = player.isSprinting();
final boolean sprinting = player.isSprinting();
data.bunnyhopdelay--;
if(resultHoriz > 0 && sprinting) {
if (resultHoriz > 0 && sprinting)
// Try to treat it as a the "bunnyhop" problem
// The bunnyhop problem is that landing and immediatly jumping
// again leads to a player moving almost twice as far in that step
if(data.bunnyhopdelay <= 0 && resultHoriz < 0.4D) {
if (data.bunnyhopdelay <= 0 && resultHoriz < 0.4D) {
data.bunnyhopdelay = 9;
resultHoriz = 0;
}
}
resultHoriz *= 100;
// Is the player affected by the "jumping" potion
// This is really just a very, very crude estimation and far from
// reality
double jumpAmplifier = player.getJumpAmplifier();
if(jumpAmplifier > data.lastJumpAmplifier) {
final double jumpAmplifier = player.getJumpAmplifier();
if (jumpAmplifier > data.lastJumpAmplifier)
data.lastJumpAmplifier = jumpAmplifier;
}
double speedLimitVertical = ccmoving.flyingSpeedLimitVertical * data.lastJumpAmplifier;
final double speedLimitVertical = ccmoving.flyingSpeedLimitVertical * data.lastJumpAmplifier;
if(data.from.y >= data.to.y && data.lastJumpAmplifier > 0) {
if (data.from.y >= data.to.y && data.lastJumpAmplifier > 0)
data.lastJumpAmplifier--;
}
// super simple, just check distance compared to max distance vertical
resultVert = Math.max(0.0D, yDistance - data.vertFreedom - speedLimitVertical) * 100;
@ -109,43 +106,39 @@ public class FlyingCheck extends MovingCheck {
result = resultHoriz + resultVert;
// The player went to far, either horizontal or vertical
if(result > 0) {
if (result > 0) {
// Increment violation counter and statistics
data.runflyVL += result;
if(resultHoriz > 0) {
if (resultHoriz > 0)
incrementStatistics(player, Id.MOV_RUNNING, resultHoriz);
}
if(resultVert > 0) {
if (resultVert > 0)
incrementStatistics(player, Id.MOV_FLYING, resultVert);
}
// Execute whatever actions are associated with this check and the
// violation level and find out if we should cancel the event
boolean cancel = executeActions(player, ccmoving.flyingActions, data.runflyVL);
final boolean cancel = executeActions(player, ccmoving.flyingActions, data.runflyVL);
// Was one of the actions a cancel? Then really do it
if(cancel) {
if (cancel)
newToLocation = setBack;
}
}
// Slowly reduce the violation level with each event
data.runflyVL *= 0.97;
// If the player did not get cancelled, define a new setback point
if(newToLocation == null) {
if (newToLocation == null)
setBack.set(to);
}
return newToLocation;
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).runflyVL);
else
return super.getParameter(wildcard, player);

View File

@ -1,11 +1,12 @@
package cc.co.evenprime.bukkit.nocheat.checks.moving;
package me.neatmonster.nocheatplus.checks.moving;
import java.util.Locale;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.data.PreciseLocation;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.data.PreciseLocation;
import me.neatmonster.nocheatplus.data.Statistics.Id;
/**
* The morePacketsCheck (previously called SpeedhackCheck) will try to identify
@ -22,7 +23,7 @@ public class MorePacketsCheck extends MovingCheck {
// 20 would be for perfect internet connections, 22 is good enough
private final static int packetsPerTimeframe = 22;
public MorePacketsCheck(NoCheat plugin) {
public MorePacketsCheck(final NoCheatPlus plugin) {
super(plugin, "moving.morepackets");
}
@ -30,26 +31,25 @@ public class MorePacketsCheck extends MovingCheck {
* 1. Players get assigned a certain amount of "free" packets as a limit initially
* 2. Every move packet reduces that limit by 1
* 3. If more than 1 second of time passed, the limit gets increased
* by 22 * time in seconds, up to 50 and he gets a new "setback" location
* by 22 * time in seconds, up to 50 and he gets a new "setback" location
* 4. If the player reaches limit = 0 -> teleport him back to "setback"
* 5. If there was a long pause (maybe lag), limit may be up to 100
*
*/
public PreciseLocation check(NoCheatPlayer player, MovingData data, MovingConfig cc) {
public PreciseLocation check(final NoCheatPlusPlayer player, final MovingData data, final MovingConfig cc) {
PreciseLocation newToLocation = null;
if(!data.morePacketsSetbackPoint.isSet()) {
if (!data.morePacketsSetbackPoint.isSet())
data.morePacketsSetbackPoint.set(data.from);
}
long time = System.currentTimeMillis();
final long time = System.currentTimeMillis();
// Take a packet from the buffer
data.morePacketsBuffer--;
// Player used up buffer, he fails the check
if(data.morePacketsBuffer < 0) {
if (data.morePacketsBuffer < 0) {
data.morePacketsVL = -data.morePacketsBuffer;
incrementStatistics(player, Id.MOV_MOREPACKETS, 1);
@ -60,52 +60,45 @@ public class MorePacketsCheck extends MovingCheck {
// violation level and find out if we should cancel the event
final boolean cancel = executeActions(player, cc.morePacketsActions, data.morePacketsVL);
if(cancel)
if (cancel)
newToLocation = data.morePacketsSetbackPoint;
}
if(data.morePacketsLastTime + 1000 < time) {
if (data.morePacketsLastTime + 1000 < time) {
// More than 1 second elapsed, but how many?
double seconds = ((double) (time - data.morePacketsLastTime)) / 1000D;
final double seconds = (time - data.morePacketsLastTime) / 1000D;
// For each second, fill the buffer
data.morePacketsBuffer += packetsPerTimeframe * seconds;
// If there was a long pause (maybe server lag?)
// Allow buffer to grow up to 100
if(seconds > 2) {
if(data.morePacketsBuffer > 100) {
if (seconds > 2) {
if (data.morePacketsBuffer > 100)
data.morePacketsBuffer = 100;
}
// Else only allow growth up to 50
} else {
if(data.morePacketsBuffer > 50) {
data.morePacketsBuffer = 50;
}
}
} else if (data.morePacketsBuffer > 50)
data.morePacketsBuffer = 50;
// Set the new "last" time
data.morePacketsLastTime = time;
// Set the new "setback" location
if(newToLocation == null) {
if (newToLocation == null)
data.morePacketsSetbackPoint.set(data.from);
}
} else if(data.morePacketsLastTime > time) {
} else if (data.morePacketsLastTime > time)
// Security check, maybe system time changed
data.morePacketsLastTime = time;
}
return newToLocation;
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).morePacketsVL);
else if(wildcard == ParameterName.PACKETS)
return String.format(Locale.US, "%d", (int) getData(player).packets);
else if (wildcard == ParameterName.PACKETS)
return String.format(Locale.US, "%d", getData(player).packets);
else
return super.getParameter(wildcard, player);
}

View File

@ -1,13 +1,14 @@
package cc.co.evenprime.bukkit.nocheat.checks.moving;
package me.neatmonster.nocheatplus.checks.moving;
import java.util.Locale;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.checks.Check;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.data.DataStore;
import cc.co.evenprime.bukkit.nocheat.data.PreciseLocation;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.checks.Check;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import me.neatmonster.nocheatplus.data.DataStore;
import me.neatmonster.nocheatplus.data.PreciseLocation;
/**
* Abstract base class for Moving checks, provides some convenience
@ -17,43 +18,13 @@ public abstract class MovingCheck extends Check {
private static final String id = "moving";
public MovingCheck(NoCheat plugin, String name) {
super(plugin, id, name);
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.LOCATION) {
PreciseLocation from = getData(player).from;
return String.format(Locale.US, "%.2f,%.2f,%.2f", from.x, from.y, from.z);
} else if(wildcard == ParameterName.MOVEDISTANCE) {
PreciseLocation from = getData(player).from;
PreciseLocation to = getData(player).to;
return String.format(Locale.US, "%.2f,%.2f,%.2f", to.x - from.x, to.y - from.y, to.z - from.z);
} else if(wildcard == ParameterName.LOCATION_TO) {
PreciseLocation to = getData(player).to;
return String.format(Locale.US, "%.2f,%.2f,%.2f", to.x, to.y, to.z);
} else
return super.getParameter(wildcard, player);
}
/**
* Get the "MovingData" object that belongs to the player. Will ensure
* that such a object exists and if not, create one
*
* @param player
* @return
*/
public static MovingData getData(NoCheatPlayer player) {
DataStore base = player.getDataStore();
MovingData data = base.get(id);
if(data == null) {
data = new MovingData();
base.set(id, data);
public static MovingConfig getConfig(final ConfigurationCacheStore cache) {
MovingConfig config = cache.get(id);
if (config == null) {
config = new MovingConfig(cache.getConfiguration());
cache.set(id, config);
}
return data;
return config;
}
/**
@ -63,16 +34,46 @@ public abstract class MovingCheck extends Check {
* @param player
* @return
*/
public static MovingConfig getConfig(NoCheatPlayer player) {
public static MovingConfig getConfig(final NoCheatPlusPlayer player) {
return getConfig(player.getConfigurationStore());
}
public static MovingConfig getConfig(ConfigurationCacheStore cache) {
MovingConfig config = cache.get(id);
if(config == null) {
config = new MovingConfig(cache.getConfiguration());
cache.set(id, config);
/**
* Get the "MovingData" object that belongs to the player. Will ensure
* that such a object exists and if not, create one
*
* @param player
* @return
*/
public static MovingData getData(final NoCheatPlusPlayer player) {
final DataStore base = player.getDataStore();
MovingData data = base.get(id);
if (data == null) {
data = new MovingData();
base.set(id, data);
}
return config;
return data;
}
public MovingCheck(final NoCheatPlus plugin, final String name) {
super(plugin, id, name);
}
@Override
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if (wildcard == ParameterName.LOCATION) {
final PreciseLocation from = getData(player).from;
return String.format(Locale.US, "%.2f,%.2f,%.2f", from.x, from.y, from.z);
} else if (wildcard == ParameterName.MOVEDISTANCE) {
final PreciseLocation from = getData(player).from;
final PreciseLocation to = getData(player).to;
return String.format(Locale.US, "%.2f,%.2f,%.2f", to.x - from.x, to.y - from.y, to.z - from.z);
} else if (wildcard == ParameterName.LOCATION_TO) {
final PreciseLocation to = getData(player).to;
return String.format(Locale.US, "%.2f,%.2f,%.2f", to.x, to.y, to.z);
} else
return super.getParameter(wildcard, player);
}
}

View File

@ -1,7 +1,16 @@
package cc.co.evenprime.bukkit.nocheat.checks.moving;
package me.neatmonster.nocheatplus.checks.moving;
import java.util.LinkedList;
import java.util.List;
import me.neatmonster.nocheatplus.EventManager;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.checks.CheckUtil;
import me.neatmonster.nocheatplus.config.ConfigurationCacheStore;
import me.neatmonster.nocheatplus.config.Permissions;
import me.neatmonster.nocheatplus.data.PreciseLocation;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.event.EventHandler;
@ -15,16 +24,9 @@ import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.PlayerVelocityEvent;
import org.bukkit.util.Vector;
import cc.co.evenprime.bukkit.nocheat.EventManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.checks.CheckUtil;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.data.PreciseLocation;
/**
* Central location to listen to events that are
* Central location to listen to events that are
* relevant for the moving checks
*
*/
@ -33,54 +35,53 @@ public class MovingCheckListener implements Listener, EventManager {
private final MorePacketsCheck morePacketsCheck;
private final FlyingCheck flyingCheck;
private final RunningCheck runningCheck;
private final WaterWalkCheck waterWalkCheck;
private final NoCheat plugin;
private final NoCheatPlus plugin;
public MovingCheckListener(NoCheat plugin) {
public MovingCheckListener(final NoCheatPlus plugin) {
flyingCheck = new FlyingCheck(plugin);
runningCheck = new RunningCheck(plugin);
morePacketsCheck = new MorePacketsCheck(plugin);
waterWalkCheck = new WaterWalkCheck(plugin);
this.plugin = plugin;
}
/**
* A workaround for players placing blocks below them getting pushed
* off the block by NoCheat.
* off the block by NoCheatPlus.
*
* It essentially moves the "setbackpoint" to the top of the newly
* placed block, therefore tricking NoCheat into thinking the player
* It essentially moves the "setbackpoint" to the top of the newly
* placed block, therefore tricking NoCheatPlus into thinking the player
* was already on top of that block and should be allowed to stay
* there
*
* @param event The BlockPlaceEvent
* @param event
* The BlockPlaceEvent
*/
@EventHandler(priority = EventPriority.MONITOR)
@EventHandler(
ignoreCancelled = true, priority = EventPriority.MONITOR)
public void blockPlace(final BlockPlaceEvent event) {
// Block wasn't placed, so we don't care
if(event.isCancelled())
return;
final NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
final NoCheatPlusPlayer player = plugin.getPlayer(event.getPlayer());
final MovingConfig config = MovingCheck.getConfig(player);
// If the player is allowed to fly anyway, the workaround is not needed
// It's kind of expensive (looking up block types) therefore it makes
// sense to avoid it
if(config.allowFlying || !config.runflyCheck || player.hasPermission(Permissions.MOVING_FLYING) || player.hasPermission(Permissions.MOVING_RUNFLY)) {
if (config.allowFlying || !config.runflyCheck || player.hasPermission(Permissions.MOVING_FLYING)
|| player.hasPermission(Permissions.MOVING_RUNFLY))
return;
}
// Get the player-specific stored data that applies here
final MovingData data = MovingCheck.getData(player);
final Block block = event.getBlockPlaced();
if(block == null || !data.runflySetBackPoint.isSet()) {
if (block == null || !data.runflySetBackPoint.isSet())
return;
}
// Keep some results of "expensive calls
final Location l = player.getPlayer().getLocation();
@ -90,116 +91,62 @@ public class MovingCheckListener implements Listener, EventManager {
final int blockY = block.getY();
// Was the block below the player?
if(Math.abs(playerX - block.getX()) <= 1 && Math.abs(playerZ - block.getZ()) <= 1 && playerY - blockY >= 0 && playerY - blockY <= 2) {
if (Math.abs(playerX - block.getX()) <= 1 && Math.abs(playerZ - block.getZ()) <= 1 && playerY - blockY >= 0
&& playerY - blockY <= 2) {
// yes
final int type = CheckUtil.getType(block.getTypeId());
if(CheckUtil.isSolid(type) || CheckUtil.isLiquid(type)) {
if(blockY + 1 >= data.runflySetBackPoint.y) {
data.runflySetBackPoint.y = (blockY + 1);
if (CheckUtil.isSolid(type) || CheckUtil.isLiquid(type))
if (blockY + 1 >= data.runflySetBackPoint.y) {
data.runflySetBackPoint.y = blockY + 1;
data.jumpPhase = 0;
}
}
}
}
/**
* If a player gets teleported, it may have two reasons. Either
* it was NoCheat or another plugin. If it was NoCheat, the target
* location should match the "data.teleportTo" value.
*
* On teleports, reset some movement related data that gets invalid
*
* @param event The PlayerTeleportEvent
*/
@EventHandler(priority = EventPriority.HIGHEST)
public void teleport(final PlayerTeleportEvent event) {
@Override
public List<String> getActiveChecks(final ConfigurationCacheStore cc) {
final LinkedList<String> s = new LinkedList<String>();
NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
final MovingData data = MovingCheck.getData(player);
final MovingConfig m = MovingCheck.getConfig(cc);
// If it was a teleport initialized by NoCheat, do it anyway
// even if another plugin said "no"
if(data.teleportTo.isSet() && data.teleportTo.equals(event.getTo())) {
event.setCancelled(false);
} else {
// Only if it wasn't NoCheat, drop data from morepackets check.
// If it was NoCheat, we don't want players to exploit the
// runfly check teleporting to get rid of the "morepackets"
// data.
data.clearMorePacketsData();
}
if (m.runflyCheck)
if (!m.allowFlying) {
s.add("moving.runfly");
if (m.sneakingCheck)
s.add("moving.sneaking");
if (m.nofallCheck)
s.add("moving.nofall");
} else
s.add("moving.flying");
if (m.morePacketsCheck)
s.add("moving.morepackets");
// Always drop data from runfly check, as it always loses its validity
// after teleports. Always!
data.teleportTo.reset();
data.clearRunFlyData();
return;
}
/**
* Just for security, if a player switches between worlds, reset the
* runfly and morepackets checks data, because it is definitely invalid
* now
*
* @param event The PlayerChangedWorldEvent
*/
@EventHandler(priority = EventPriority.MONITOR)
public void worldChange(final PlayerChangedWorldEvent event) {
// Maybe this helps with people teleporting through multiverse portals having problems?
final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()));
data.teleportTo.reset();
data.clearRunFlyData();
data.clearMorePacketsData();
}
/**
* When a player uses a portal, all information related to the
* moving checks becomes invalid.
*
* @param event
*/
@EventHandler(priority = EventPriority.MONITOR)
public void portal(final PlayerPortalEvent event) {
final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()));
data.clearMorePacketsData();
data.clearRunFlyData();
}
/**
* When a player respawns, all information related to the
* moving checks becomes invalid.
*
* @param event
*/
@EventHandler(priority = EventPriority.MONITOR)
public void respawn(final PlayerRespawnEvent event) {
final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()));
data.clearMorePacketsData();
data.clearRunFlyData();
return s;
}
/**
* When a player moves, he will be checked for various
* suspicious behaviour.
*
* @param event The PlayerMoveEvent
* @param event
* The PlayerMoveEvent
*/
@EventHandler(priority = EventPriority.LOWEST)
@EventHandler(
ignoreCancelled = true, priority = EventPriority.LOWEST)
public void move(final PlayerMoveEvent event) {
// Don't care for vehicles
if(event.isCancelled() || event.getPlayer().isInsideVehicle())
if (event.getPlayer().isInsideVehicle())
return;
// Don't care for movements that are very high distance or to another
// world (such that it is very likely the event data was modified by
// Don't care for movements that are very high distance or to another
// world (such that it is very likely the event data was modified by
// another plugin before we got it)
if(!event.getFrom().getWorld().equals(event.getTo().getWorld()) || event.getFrom().distanceSquared(event.getTo()) > 400) {
if (!event.getFrom().getWorld().equals(event.getTo().getWorld())
|| event.getFrom().distanceSquared(event.getTo()) > 400)
return;
}
final NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
final NoCheatPlusPlayer player = plugin.getPlayer(event.getPlayer());
final MovingConfig cc = MovingCheck.getConfig(player);
final MovingData data = MovingCheck.getData(player);
@ -218,37 +165,104 @@ public class MovingCheckListener implements Listener, EventManager {
/** RUNFLY CHECK SECTION **/
// If the player isn't handled by runfly checks
if(!cc.runflyCheck || player.hasPermission(Permissions.MOVING_RUNFLY)) {
if (!cc.runflyCheck || player.hasPermission(Permissions.MOVING_RUNFLY))
// Just because he is allowed now, doesn't mean he will always
// be. So forget data about the player related to moving
data.clearRunFlyData();
} else if(cc.allowFlying || (player.isCreative() && cc.identifyCreativeMode) || player.hasPermission(Permissions.MOVING_FLYING)) {
else if (cc.allowFlying || player.isCreative() && cc.identifyCreativeMode
|| player.hasPermission(Permissions.MOVING_FLYING))
// Only do the limited flying check
newTo = flyingCheck.check(player, data, cc);
} else {
else
// Go for the full treatment
newTo = runningCheck.check(player, data, cc);
}
/** WATERWALK CHECK SECTION **/
if (newTo == null && cc.waterWalkCheck && (!player.isCreative() || !cc.identifyCreativeMode)
&& !player.hasPermission(Permissions.MOVING_WATERWALK))
newTo = waterWalkCheck.check(player, data, cc);
/** MOREPACKETS CHECK SECTION **/
if(!cc.morePacketsCheck || player.hasPermission(Permissions.MOVING_MOREPACKETS)) {
if (!cc.morePacketsCheck || player.hasPermission(Permissions.MOVING_MOREPACKETS))
data.clearMorePacketsData();
} else if(newTo == null) {
else if (newTo == null)
newTo = morePacketsCheck.check(player, data, cc);
}
// Did one of the check(s) decide we need a new "to"-location?
if(newTo != null) {
if (newTo != null) {
// Compose a new location based on coordinates of "newTo" and
// viewing direction of "event.getTo()" to allow the player to
// look somewhere else despite getting pulled back by NoCheat
event.setTo(new Location(player.getPlayer().getWorld(), newTo.x, newTo.y, newTo.z, to.getYaw(), to.getPitch()));
// look somewhere else despite getting pulled back by NoCheatPlus
event.setTo(new Location(player.getPlayer().getWorld(), newTo.x, newTo.y, newTo.z, to.getYaw(), to
.getPitch()));
// remember where we send the player to
data.teleportTo.set(newTo);
}
}
/**
* When a player uses a portal, all information related to the
* moving checks becomes invalid.
*
* @param event
*/
@EventHandler(
priority = EventPriority.MONITOR)
public void portal(final PlayerPortalEvent event) {
final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()));
data.clearMorePacketsData();
data.clearRunFlyData();
}
/**
* When a player respawns, all information related to the
* moving checks becomes invalid.
*
* @param event
*/
@EventHandler(
priority = EventPriority.MONITOR)
public void respawn(final PlayerRespawnEvent event) {
final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()));
data.clearMorePacketsData();
data.clearRunFlyData();
}
/**
* If a player gets teleported, it may have two reasons. Either
* it was NoCheatPlus or another plugin. If it was NoCheatPlus, the target
* location should match the "data.teleportTo" value.
*
* On teleports, reset some movement related data that gets invalid
*
* @param event
* The PlayerTeleportEvent
*/
@EventHandler(
priority = EventPriority.HIGHEST)
public void teleport(final PlayerTeleportEvent event) {
final NoCheatPlusPlayer player = plugin.getPlayer(event.getPlayer());
final MovingData data = MovingCheck.getData(player);
// If it was a teleport initialized by NoCheatPlus, do it anyway
// even if another plugin said "no"
if (data.teleportTo.isSet() && data.teleportTo.equals(event.getTo()))
event.setCancelled(false);
else
// Only if it wasn't NoCheatPlus, drop data from morepackets check.
// If it was NoCheatPlus, we don't want players to exploit the
// runfly check teleporting to get rid of the "morepackets"
// data.
data.clearMorePacketsData();
// Always drop data from runfly check, as it always loses its validity
// after teleports. Always!
data.teleportTo.reset();
data.clearRunFlyData();
}
/**
* Just try to estimate velocities over time
* Not very precise, but works good enough most
@ -256,25 +270,22 @@ public class MovingCheckListener implements Listener, EventManager {
*
* @param data
*/
private void tickVelocities(MovingData data) {
private void tickVelocities(final MovingData data) {
/******** DO GENERAL DATA MODIFICATIONS ONCE FOR EACH EVENT *****/
if(data.horizVelocityCounter > 0) {
if (data.horizVelocityCounter > 0)
data.horizVelocityCounter--;
} else if(data.horizFreedom > 0.001) {
else if (data.horizFreedom > 0.001)
data.horizFreedom *= 0.90;
}
if(data.vertVelocity <= 0.1) {
if (data.vertVelocity <= 0.1)
data.vertVelocityCounter--;
}
if(data.vertVelocityCounter > 0) {
if (data.vertVelocityCounter > 0) {
data.vertFreedom += data.vertVelocity;
data.vertVelocity *= 0.90;
} else if(data.vertFreedom > 0.001) {
} else if (data.vertFreedom > 0.001)
// Counter has run out, now reduce the vert freedom over time
data.vertFreedom *= 0.93;
}
}
/**
@ -282,19 +293,19 @@ public class MovingCheckListener implements Listener, EventManager {
* of actual velocity values (by design), so we have to try
* and do that ourselves. Very rough estimates.
*
* @param event The PlayerVelocityEvent
* @param event
* The PlayerVelocityEvent
*/
@EventHandler(priority = EventPriority.MONITOR)
@EventHandler(
ignoreCancelled = true, priority = EventPriority.MONITOR)
public void velocity(final PlayerVelocityEvent event) {
if(event.isCancelled())
return;
final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()));
final Vector v = event.getVelocity();
double newVal = v.getY();
if(newVal >= 0.0D) {
if (newVal >= 0.0D) {
data.vertVelocity += newVal;
data.vertFreedom += data.vertVelocity;
}
@ -302,32 +313,27 @@ public class MovingCheckListener implements Listener, EventManager {
data.vertVelocityCounter = 50;
newVal = Math.sqrt(Math.pow(v.getX(), 2) + Math.pow(v.getZ(), 2));
if(newVal > 0.0D) {
if (newVal > 0.0D) {
data.horizFreedom += newVal;
data.horizVelocityCounter = 30;
}
}
public List<String> getActiveChecks(ConfigurationCacheStore cc) {
LinkedList<String> s = new LinkedList<String>();
MovingConfig m = MovingCheck.getConfig(cc);
if(m.runflyCheck) {
if(!m.allowFlying) {
s.add("moving.runfly");
if(m.sneakingCheck)
s.add("moving.sneaking");
if(m.nofallCheck)
s.add("moving.nofall");
} else
s.add("moving.flying");
}
if(m.morePacketsCheck)
s.add("moving.morepackets");
return s;
/**
* Just for security, if a player switches between worlds, reset the
* runfly and morepackets checks data, because it is definitely invalid
* now
*
* @param event
* The PlayerChangedWorldEvent
*/
@EventHandler(
priority = EventPriority.MONITOR)
public void worldChange(final PlayerChangedWorldEvent event) {
// Maybe this helps with people teleporting through multiverse portals having problems?
final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()));
data.teleportTo.reset();
data.clearRunFlyData();
data.clearMorePacketsData();
}
}

View File

@ -1,10 +1,10 @@
package cc.co.evenprime.bukkit.nocheat.checks.moving;
package me.neatmonster.nocheatplus.checks.moving;
import cc.co.evenprime.bukkit.nocheat.ConfigItem;
import cc.co.evenprime.bukkit.nocheat.actions.types.ActionList;
import cc.co.evenprime.bukkit.nocheat.config.ConfPaths;
import cc.co.evenprime.bukkit.nocheat.config.NoCheatConfiguration;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import me.neatmonster.nocheatplus.ConfigItem;
import me.neatmonster.nocheatplus.actions.types.ActionList;
import me.neatmonster.nocheatplus.config.ConfPaths;
import me.neatmonster.nocheatplus.config.NoCheatPlusConfiguration;
import me.neatmonster.nocheatplus.config.Permissions;
/**
* Configurations specific for the Move Checks. Every world gets one of these
@ -35,39 +35,45 @@ public class MovingConfig implements ConfigItem {
public final boolean morePacketsCheck;
public final ActionList morePacketsActions;
public final boolean waterWalkCheck;
public final ActionList waterWalkActions;
public final int flyingHeightLimit;
public MovingConfig(NoCheatConfiguration data) {
public MovingConfig(final NoCheatPlusConfiguration data) {
identifyCreativeMode = data.getBoolean(ConfPaths.MOVING_RUNFLY_FLYING_ALLOWINCREATIVE);
runflyCheck = data.getBoolean(ConfPaths.MOVING_RUNFLY_CHECK);
int walkspeed = data.getInt(ConfPaths.MOVING_RUNFLY_WALKSPEED, 100);
int sprintspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SPRINTSPEED, 100);
int swimspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SWIMSPEED, 100);
int sneakspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SNEAKSPEED, 100);
walkingSpeedLimit = ((double) 0.22 * walkspeed) / 100D;
sprintingSpeedLimit = ((double) 0.35 * sprintspeed) / 100D;
swimmingSpeedLimit = ((double) 0.18 * swimspeed) / 100D;
sneakingSpeedLimit = ((double) 0.14 * sneakspeed) / 100D;
jumpheight = ((double) 135) / 100D;
final int walkspeed = data.getInt(ConfPaths.MOVING_RUNFLY_WALKSPEED, 100);
final int sprintspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SPRINTSPEED, 100);
final int swimspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SWIMSPEED, 100);
final int sneakspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SNEAKSPEED, 100);
walkingSpeedLimit = 0.22 * walkspeed / 100D;
sprintingSpeedLimit = 0.35 * sprintspeed / 100D;
swimmingSpeedLimit = 0.18 * swimspeed / 100D;
sneakingSpeedLimit = 0.14 * sneakspeed / 100D;
jumpheight = 135 / 100D;
sneakingCheck = !data.getBoolean(ConfPaths.MOVING_RUNFLY_ALLOWFASTSNEAKING);
actions = data.getActionList(ConfPaths.MOVING_RUNFLY_ACTIONS, Permissions.MOVING_RUNFLY);
allowFlying = data.getBoolean(ConfPaths.MOVING_RUNFLY_FLYING_ALLOWALWAYS);
flyingSpeedLimitVertical = ((double) data.getInt(ConfPaths.MOVING_RUNFLY_FLYING_SPEEDLIMITVERTICAL)) / 100D;
flyingSpeedLimitHorizontal = ((double) data.getInt(ConfPaths.MOVING_RUNFLY_FLYING_SPEEDLIMITHORIZONTAL)) / 100D;
flyingSpeedLimitVertical = data.getInt(ConfPaths.MOVING_RUNFLY_FLYING_SPEEDLIMITVERTICAL) / 100D;
flyingSpeedLimitHorizontal = data.getInt(ConfPaths.MOVING_RUNFLY_FLYING_SPEEDLIMITHORIZONTAL) / 100D;
flyingHeightLimit = data.getInt(ConfPaths.MOVING_RUNFLY_FLYING_HEIGHTLIMIT);
flyingActions = data.getActionList(ConfPaths.MOVING_RUNFLY_FLYING_ACTIONS, Permissions.MOVING_FLYING);
nofallCheck = data.getBoolean(ConfPaths.MOVING_RUNFLY_CHECKNOFALL);
nofallMultiplier = ((float) 200) / 100F;
nofallMultiplier = 200 / 100F;
nofallaggressive = data.getBoolean(ConfPaths.MOVING_RUNFLY_NOFALLAGGRESSIVE);
nofallActions = data.getActionList(ConfPaths.MOVING_RUNFLY_NOFALLACTIONS, Permissions.MOVING_NOFALL);
morePacketsCheck = data.getBoolean(ConfPaths.MOVING_MOREPACKETS_CHECK);
morePacketsActions = data.getActionList(ConfPaths.MOVING_MOREPACKETS_ACTIONS, Permissions.MOVING_MOREPACKETS);
waterWalkCheck = data.getBoolean(ConfPaths.MOVING_WATERWALK_CHECK);
waterWalkActions = data.getActionList(ConfPaths.MOVING_WATERWALK_ACTIONS, Permissions.MOVING_WATERWALK);
}
}

View File

@ -1,8 +1,8 @@
package cc.co.evenprime.bukkit.nocheat.checks.moving;
package me.neatmonster.nocheatplus.checks.moving;
import cc.co.evenprime.bukkit.nocheat.DataItem;
import cc.co.evenprime.bukkit.nocheat.data.PreciseLocation;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
import me.neatmonster.nocheatplus.DataItem;
import me.neatmonster.nocheatplus.data.PreciseLocation;
import me.neatmonster.nocheatplus.data.Statistics.Id;
/**
* Player specific data for the moving check group
@ -13,6 +13,7 @@ public class MovingData implements DataItem {
public double runflyVL;
public double nofallVL;
public double morePacketsVL;
public double waterWalkVL;
// Count how long a player is in the air
public int jumpPhase;
@ -49,7 +50,7 @@ public class MovingData implements DataItem {
// Where to teleport the player that fails the "morepackets" check
public final PreciseLocation morePacketsSetbackPoint = new PreciseLocation();
// When NoCheat 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
public final PreciseLocation teleportTo = new PreciseLocation();
@ -58,12 +59,16 @@ public class MovingData implements DataItem {
public final PreciseLocation to = new PreciseLocation();
// For convenience, remember if the locations are considered "on ground"
// by NoCheat
// by NoCheatPlus
public boolean fromOnOrInGround;
public boolean toOnOrInGround;
public Id statisticCategory = Id.MOV_RUNNING;
public void clearMorePacketsData() {
morePacketsSetbackPoint.reset();
}
public void clearRunFlyData() {
runflySetBackPoint.reset();
jumpPhase = 0;
@ -71,8 +76,4 @@ public class MovingData implements DataItem {
lastAddedFallDistance = 0;
bunnyhopdelay = 0;
}
public void clearMorePacketsData() {
morePacketsSetbackPoint.reset();
}
}

View File

@ -1,10 +1,11 @@
package cc.co.evenprime.bukkit.nocheat.checks.moving;
package me.neatmonster.nocheatplus.checks.moving;
import java.util.Locale;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.data.Statistics.Id;
/**
* A check to see if people cheat by tricking the server to not deal them
@ -13,7 +14,7 @@ import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
*/
public class NoFallCheck extends MovingCheck {
public NoFallCheck(NoCheat plugin) {
public NoFallCheck(final NoCheatPlus plugin) {
super(plugin, "moving.nofall");
}
@ -21,23 +22,23 @@ public class NoFallCheck extends MovingCheck {
* Calculate if and how much the player "failed" this check.
*
*/
public void check(NoCheatPlayer player, MovingData data, MovingConfig cc) {
public void check(final NoCheatPlusPlayer player, final MovingData data, final MovingConfig cc) {
// If the player is serverside in creative mode, we have to stop here to
// avoid hurting him when he switches back to "normal" mode
if(player.isCreative()) {
if (player.isCreative()) {
data.fallDistance = 0F;
data.lastAddedFallDistance = 0F;
return;
}
// This check is pretty much always a step behind for technical reasons.
if(data.fromOnOrInGround) {
if (data.fromOnOrInGround)
// Start with zero fall distance
data.fallDistance = 0F;
}
if(cc.nofallaggressive && data.fromOnOrInGround && data.toOnOrInGround && data.from.y <= data.to.y && player.getPlayer().getFallDistance() > 3.0F) {
if (cc.nofallaggressive && data.fromOnOrInGround && data.toOnOrInGround && data.from.y <= data.to.y
&& player.getPlayer().getFallDistance() > 3.0F) {
data.fallDistance = player.getPlayer().getFallDistance();
data.nofallVL += data.fallDistance;
incrementStatistics(player, Id.MOV_NOFALL, data.fallDistance);
@ -45,17 +46,15 @@ public class NoFallCheck extends MovingCheck {
// Execute whatever actions are associated with this check and the
// violation level and find out if we should cancel the event
final boolean cancel = executeActions(player, cc.nofallActions, data.nofallVL);
if(cancel) {
if (cancel)
player.dealFallDamage();
}
data.fallDistance = 0F;
}
// If we increased fall height before for no good reason, reduce now by
// the same amount
if(player.getPlayer().getFallDistance() > data.lastAddedFallDistance) {
if (player.getPlayer().getFallDistance() > data.lastAddedFallDistance)
player.getPlayer().setFallDistance(player.getPlayer().getFallDistance() - data.lastAddedFallDistance);
}
data.lastAddedFallDistance = 0;
@ -63,7 +62,7 @@ public class NoFallCheck extends MovingCheck {
// than the fall distance recorded by the plugin
final float difference = data.fallDistance - player.getPlayer().getFallDistance();
if(difference > 1.0F && data.toOnOrInGround && data.fallDistance > 2.0F) {
if (difference > 1.0F && data.toOnOrInGround && data.fallDistance > 2.0F) {
data.nofallVL += difference;
incrementStatistics(player, Id.MOV_NOFALL, difference);
@ -73,7 +72,7 @@ public class NoFallCheck extends MovingCheck {
// If "cancelled", the fall damage gets dealt in a way that's
// visible to other plugins
if(cancel) {
if (cancel) {
// Increase the fall distance a bit :)
final float totalDistance = data.fallDistance + difference * (cc.nofallMultiplier - 1.0F);
@ -96,19 +95,17 @@ public class NoFallCheck extends MovingCheck {
final double oldY = data.from.y;
final double newY = data.to.y;
if(oldY > newY) {
if (oldY > newY) {
final float dist = (float) (oldY - newY);
data.fallDistance += dist;
if(dist > 1.0F) {
if (dist > 1.0F) {
data.lastAddedFallDistance = dist;
player.getPlayer().setFallDistance(player.getPlayer().getFallDistance() + dist);
} else {
} else
data.lastAddedFallDistance = 0.0F;
}
} else {
} else
data.lastAddedFallDistance = 0.0F;
}
// Reduce falldamage violation level
data.nofallVL *= 0.95D;
@ -117,11 +114,11 @@ public class NoFallCheck extends MovingCheck {
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).nofallVL);
else if(wildcard == ParameterName.FALLDISTANCE)
else if (wildcard == ParameterName.FALLDISTANCE)
return String.format(Locale.US, "%.2f", getData(player).fallDistance);
else
return super.getParameter(wildcard, player);

View File

@ -1,15 +1,17 @@
package cc.co.evenprime.bukkit.nocheat.checks.moving;
package me.neatmonster.nocheatplus.checks.moving;
import java.util.Locale;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.checks.CheckUtil;
import me.neatmonster.nocheatplus.config.Permissions;
import me.neatmonster.nocheatplus.data.PreciseLocation;
import me.neatmonster.nocheatplus.data.Statistics.Id;
import org.bukkit.Material;
import org.bukkit.block.Block;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.checks.CheckUtil;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.data.PreciseLocation;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
/**
* The counterpart to the FlyingCheck. People that are not allowed to fly
@ -28,14 +30,14 @@ public class RunningCheck extends MovingCheck {
private final NoFallCheck noFallCheck;
public RunningCheck(NoCheat plugin) {
public RunningCheck(final NoCheatPlus plugin) {
super(plugin, "moving.running");
this.noFallCheck = new NoFallCheck(plugin);
noFallCheck = new NoFallCheck(plugin);
}
public PreciseLocation check(NoCheatPlayer player, MovingData data, MovingConfig cc) {
public PreciseLocation check(final NoCheatPlusPlayer player, final MovingData data, final MovingConfig cc) {
// Some shortcuts:
final PreciseLocation setBack = data.runflySetBackPoint;
@ -45,11 +47,10 @@ public class RunningCheck extends MovingCheck {
// Calculate some distances
final double xDistance = data.to.x - from.x;
final double zDistance = to.z - from.z;
final double horizontalDistance = Math.sqrt((xDistance * xDistance + zDistance * zDistance));
final double horizontalDistance = Math.sqrt(xDistance * xDistance + zDistance * zDistance);
if(!setBack.isSet()) {
if (!setBack.isSet())
setBack.set(from);
}
// To know if a player "is on ground" is useful
final int fromType = CheckUtil.evaluateLocation(player.getPlayer().getWorld(), from);
@ -62,7 +63,10 @@ public class RunningCheck extends MovingCheck {
PreciseLocation newToLocation = null;
final double resultHoriz = Math.max(0.0D, checkHorizontal(player, data, CheckUtil.isLiquid(fromType) && CheckUtil.isLiquid(toType), horizontalDistance, cc));
final double resultHoriz = Math.max(
0.0D,
checkHorizontal(player, data, CheckUtil.isLiquid(fromType) && CheckUtil.isLiquid(toType),
horizontalDistance, cc));
final double resultVert = Math.max(0.0D, checkVertical(player, data, fromOnGround, toOnGround, cc));
final double result = (resultHoriz + resultVert) * 100;
@ -73,51 +77,44 @@ public class RunningCheck extends MovingCheck {
data.runflyVL *= 0.95;
// Did the player move in unexpected ways?
if(result > 0) {
if (result > 0) {
// Increment violation counter
data.runflyVL += result;
incrementStatistics(player, data.statisticCategory, result);
boolean cancel = executeActions(player, cc.actions, data.runflyVL);
final boolean cancel = executeActions(player, cc.actions, data.runflyVL);
// Was one of the actions a cancel? Then do it
if(cancel) {
if (cancel)
newToLocation = setBack;
} else if(toOnGround || toInGround) {
// In case it only gets logged, not stopped by NoCheat
else if (toOnGround || toInGround) {
// In case it only gets logged, not stopped by NoCheatPlus
// Update the setback location at least a bit
setBack.set(to);
data.jumpPhase = 0;
}
} else {
// Decide if we should create a new setBack point
// These are the result of a lot of bug reports, experience and
// trial and error
if((toInGround && from.y >= to.y) || CheckUtil.isLiquid(toType)) {
// Yes, if the player moved down "into" the ground or into liquid
setBack.set(to);
setBack.y = Math.ceil(setBack.y);
data.jumpPhase = 0;
} else if(toOnGround && (from.y >= to.y || setBack.y <= Math.floor(to.y))) {
// Yes, if the player moved down "onto" the ground and the new
// setback point is higher up than the old or at least at the
// same height
setBack.set(to);
setBack.y = Math.floor(setBack.y);
data.jumpPhase = 0;
} else if(fromOnGround || fromInGround || toOnGround || toInGround) {
// The player at least touched the ground somehow
data.jumpPhase = 0;
}
}
} else if (toInGround && from.y >= to.y || CheckUtil.isLiquid(toType)) {
// Yes, if the player moved down "into" the ground or into liquid
setBack.set(to);
setBack.y = Math.ceil(setBack.y);
data.jumpPhase = 0;
} else if (toOnGround && (from.y >= to.y || setBack.y <= Math.floor(to.y))) {
// Yes, if the player moved down "onto" the ground and the new
// setback point is higher up than the old or at least at the
// same height
setBack.set(to);
setBack.y = Math.floor(setBack.y);
data.jumpPhase = 0;
} else if (fromOnGround || fromInGround || toOnGround || toInGround)
// The player at least touched the ground somehow
data.jumpPhase = 0;
/********* EXECUTE THE NOFALL CHECK ********************/
final boolean checkNoFall = cc.nofallCheck && !player.hasPermission(Permissions.MOVING_NOFALL);
if(checkNoFall && newToLocation == null) {
if (checkNoFall && newToLocation == null) {
data.fromOnOrInGround = fromOnGround || fromInGround;
data.toOnOrInGround = toOnGround || toInGround;
noFallCheck.check(player, data, cc);
@ -130,34 +127,34 @@ public class RunningCheck extends MovingCheck {
* Calculate how much the player failed this check
*
*/
private double checkHorizontal(final NoCheatPlayer player, final MovingData data, final boolean isSwimming, final double totalDistance, final MovingConfig cc) {
private double checkHorizontal(final NoCheatPlusPlayer player, final MovingData data, final boolean isSwimming,
final double totalDistance, final MovingConfig cc) {
// How much further did the player move than expected??
double distanceAboveLimit = 0.0D;
// A player is considered sprinting if the flag is set and if he has
// enough food level (configurable)
final boolean sprinting = player.isSprinting() && (player.getPlayer().getFoodLevel() > 5);
final boolean sprinting = player.isSprinting() && player.getPlayer().getFoodLevel() > 5;
double limit = 0.0D;
Id statisticsCategory = null;
// Player on ice? Give him higher max speed
Block b = player.getPlayer().getLocation().getBlock();
if(b.getType() == Material.ICE || b.getRelative(0, -1, 0).getType() == Material.ICE) {
final Block b = player.getPlayer().getLocation().getBlock();
if (b.getType() == Material.ICE || b.getRelative(0, -1, 0).getType() == Material.ICE)
data.onIce = 20;
} else if(data.onIce > 0) {
else if (data.onIce > 0)
data.onIce--;
}
if(cc.sneakingCheck && player.getPlayer().isSneaking() && !player.hasPermission(Permissions.MOVING_SNEAKING)) {
if (cc.sneakingCheck && player.getPlayer().isSneaking() && !player.hasPermission(Permissions.MOVING_SNEAKING)) {
limit = cc.sneakingSpeedLimit;
statisticsCategory = Id.MOV_SNEAKING;
} else if(isSwimming && !player.hasPermission(Permissions.MOVING_SWIMMING)) {
} else if (isSwimming && !player.hasPermission(Permissions.MOVING_SWIMMING)) {
limit = cc.swimmingSpeedLimit;
statisticsCategory = Id.MOV_SWIMMING;
} else if(!sprinting) {
} else if (!sprinting) {
limit = cc.walkingSpeedLimit;
statisticsCategory = Id.MOV_RUNNING;
} else {
@ -165,9 +162,8 @@ public class RunningCheck extends MovingCheck {
statisticsCategory = Id.MOV_RUNNING;
}
if(data.onIce > 0) {
if (data.onIce > 0)
limit *= 2.5;
}
// Taken directly from Minecraft code, should work
limit *= player.getSpeedAmplifier();
@ -177,33 +173,26 @@ public class RunningCheck extends MovingCheck {
data.bunnyhopdelay--;
// Did he go too far?
if(distanceAboveLimit > 0 && sprinting) {
if (distanceAboveLimit > 0 && sprinting)
// Try to treat it as a the "bunnyhop" problem
if(data.bunnyhopdelay <= 0 && distanceAboveLimit > 0.05D && distanceAboveLimit < 0.4D) {
if (data.bunnyhopdelay <= 0 && distanceAboveLimit > 0.05D && distanceAboveLimit < 0.4D) {
data.bunnyhopdelay = 9;
distanceAboveLimit = 0;
}
}
if(distanceAboveLimit > 0) {
if (distanceAboveLimit > 0) {
// Try to consume the "buffer"
distanceAboveLimit -= data.horizontalBuffer;
data.horizontalBuffer = 0;
// Put back the "overconsumed" buffer
if(distanceAboveLimit < 0) {
if (distanceAboveLimit < 0)
data.horizontalBuffer = -distanceAboveLimit;
}
}
// He was within limits, give the difference as buffer
else {
} else
data.horizontalBuffer = Math.min(maxBonus, data.horizontalBuffer - distanceAboveLimit);
}
if(distanceAboveLimit > 0) {
if (distanceAboveLimit > 0)
data.statisticCategory = statisticsCategory;
}
return distanceAboveLimit;
}
@ -212,45 +201,42 @@ public class RunningCheck extends MovingCheck {
* Calculate if and how much the player "failed" this check.
*
*/
private double checkVertical(final NoCheatPlayer player, final MovingData data, final boolean fromOnGround, final boolean toOnGround, final MovingConfig cc) {
private double checkVertical(final NoCheatPlusPlayer player, final MovingData data, final boolean fromOnGround,
final boolean toOnGround, final MovingConfig cc) {
// How much higher did the player move than expected??
double distanceAboveLimit = 0.0D;
// Potion effect "Jump"
double jumpAmplifier = player.getJumpAmplifier();
if(jumpAmplifier > data.lastJumpAmplifier) {
final double jumpAmplifier = player.getJumpAmplifier();
if (jumpAmplifier > data.lastJumpAmplifier)
data.lastJumpAmplifier = jumpAmplifier;
}
double limit = data.vertFreedom + cc.jumpheight;
limit *= data.lastJumpAmplifier;
if(data.jumpPhase > jumpingLimit + data.lastJumpAmplifier) {
if (data.jumpPhase > jumpingLimit + data.lastJumpAmplifier)
limit -= (data.jumpPhase - jumpingLimit) * 0.15D;
}
distanceAboveLimit = data.to.y - data.runflySetBackPoint.y - limit;
if(distanceAboveLimit > 0) {
if (distanceAboveLimit > 0)
data.statisticCategory = Id.MOV_FLYING;
}
if(toOnGround || fromOnGround) {
if (toOnGround || fromOnGround)
data.lastJumpAmplifier = 0;
}
return distanceAboveLimit;
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if(wildcard == ParameterName.CHECK)
if (wildcard == ParameterName.CHECK)
// Workaround for something until I find a better way to do it
return getData(player).statisticCategory.toString();
else if(wildcard == ParameterName.VIOLATIONS)
else if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).runflyVL);
else
return super.getParameter(wildcard, player);

View File

@ -0,0 +1,98 @@
package me.neatmonster.nocheatplus.checks.moving;
import java.util.Locale;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.actions.ParameterName;
import me.neatmonster.nocheatplus.checks.CheckUtil;
import me.neatmonster.nocheatplus.data.PreciseLocation;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
public class WaterWalkCheck extends MovingCheck {
public WaterWalkCheck(final NoCheatPlus plugin) {
super(plugin, "moving.waterwalk");
}
public PreciseLocation check(final NoCheatPlusPlayer player, final MovingData data, final MovingConfig cc) {
// Some shortcuts:
final PreciseLocation to = data.to;
final PreciseLocation from = data.from;
final PreciseLocation up = new PreciseLocation();
up.x = to.x;
up.y = to.y + 1;
up.z = to.z;
// To know if a player "is in water" is useful
final int fromType = CheckUtil.evaluateLocation(player.getPlayer().getWorld(), from);
final int toType = CheckUtil.evaluateLocation(player.getPlayer().getWorld(), to);
final int upType = CheckUtil.evaluateLocation(player.getPlayer().getWorld(), up);
final boolean fromLiquid = CheckUtil.isLiquid(fromType);
final boolean toLiquid = CheckUtil.isLiquid(toType);
final boolean upLiquid = CheckUtil.isLiquid(upType);
// Make sure the block where the player comes is a stationary liquid block
boolean fromBukkitLiquid = false;
final Block fromBlock = new Location(player.getPlayer().getWorld(), from.x, from.y, from.z).getBlock();
if (fromBlock.getType() == Material.STATIONARY_WATER || fromBlock.getType() == Material.STATIONARY_LAVA
|| (fromBlock.getType() == Material.WATER || fromBlock.getType() == Material.LAVA)
&& fromBlock.getData() == 0x0)
fromBukkitLiquid = true;
// Calculate some distances
final double deltaX = Math.abs(Math.round(to.x) - to.x);
final double deltaY = Math.abs(from.y - to.y);
final double deltaZ = Math.abs(Math.round(to.z) - to.z);
final double deltaWithSurface = Math.abs(to.y - Math.ceil(to.y)) + (to.y - Math.ceil(to.y) == 0 ? 1 : 0);
final double resultXZ = (Math.abs(deltaX - 0.30D) + Math.abs(deltaZ - 0.30D)) * 100;
final double resultY = deltaWithSurface * 100;
PreciseLocation newToLocation = null;
// Slowly reduce the level with each event
data.waterWalkVL *= 0.95;
if (fromLiquid && toLiquid && !upLiquid && deltaY == 0D && deltaWithSurface < 0.8D) {
// If the player is trying to move while being in water
// Increment violation counter
data.waterWalkVL += resultY;
incrementStatistics(player, data.statisticCategory, resultY);
final boolean cancel = executeActions(player, cc.actions, data.waterWalkVL);
// Was one of the actions a cancel? Then do it
if (cancel)
newToLocation = from;
} else if (fromLiquid && fromBukkitLiquid && !toLiquid && (deltaX < 0.27D || deltaX > 0.29D)
&& (deltaZ < 0.27D || deltaZ > 0.29D)) {
// If the player is trying to jump while being in water
// Increment violation counter
data.waterWalkVL += resultXZ;
incrementStatistics(player, data.statisticCategory, resultXZ);
final boolean cancel = executeActions(player, cc.actions, data.waterWalkVL);
// Was one of the actions a cancel? Then do it
if (cancel)
newToLocation = from;
}
return newToLocation;
}
@Override
public String getParameter(final ParameterName wildcard, final NoCheatPlusPlayer player) {
if (wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player).waterWalkVL);
else
return super.getParameter(wildcard, player);
}
}

View File

@ -1,4 +1,4 @@
package cc.co.evenprime.bukkit.nocheat.command;
package me.neatmonster.nocheatplus.command;
import java.util.Collections;
import java.util.Comparator;
@ -6,21 +6,23 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.config.Permissions;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permission;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
/**
* Handle all NoCheat related commands in a common place
* Handle all NoCheatPlus related commands in a common place
*/
public class CommandHandler {
private final List<Permission> perms;
public CommandHandler(NoCheat plugin) {
public CommandHandler(final NoCheatPlus plugin) {
// Make a copy to allow sorting
perms = new LinkedList<Permission>(plugin.getDescription().getPermissions());
@ -28,21 +30,20 @@ public class CommandHandler {
// a custom sorting method
Collections.sort(perms, new Comparator<Permission>() {
public int compare(Permission o1, Permission o2) {
@Override
public int compare(final Permission o1, final Permission o2) {
String name1 = o1.getName();
String name2 = o2.getName();
final String name1 = o1.getName();
final String name2 = o2.getName();
if(name1.equals(name2))
if (name1.equals(name2))
return 0;
if(name1.startsWith(name2)) {
if (name1.startsWith(name2))
return 1;
}
if(name2.startsWith(name1)) {
if (name2.startsWith(name1))
return -1;
}
return name1.compareTo(name2);
}
@ -50,7 +51,8 @@ public class CommandHandler {
}
/**
* Handle a command that is directed at NoCheat
* Handle a command that is directed at NoCheatPlus
*
* @param plugin
* @param sender
* @param command
@ -58,82 +60,72 @@ public class CommandHandler {
* @param args
* @return
*/
public boolean handleCommand(NoCheat plugin, CommandSender sender, Command command, String label, String[] args) {
public boolean handleCommand(final NoCheatPlus plugin, final CommandSender sender, final Command command,
final String label, final String[] args) {
boolean result = false;
// Not our command, how did it get here?
if(!command.getName().equalsIgnoreCase("nocheat") || args.length == 0) {
if (!command.getName().equalsIgnoreCase("nocheatplus") || args.length == 0)
result = false;
} else if(args[0].equalsIgnoreCase("permlist") && args.length >= 2) {
else if (args[0].equalsIgnoreCase("permlist") && args.length >= 2)
// permlist command was used
result = handlePermlistCommand(plugin, sender, args);
} else if(args[0].equalsIgnoreCase("reload")) {
else if (args[0].equalsIgnoreCase("reload"))
// reload command was used
result = handleReloadCommand(plugin, sender);
}
else if(args[0].equalsIgnoreCase("playerinfo") && args.length >= 2) {
else if (args[0].equalsIgnoreCase("playerinfo") && args.length >= 2)
// playerinfo command was used
result = handlePlayerInfoCommand(plugin, sender, args);
}
return result;
}
private boolean handlePlayerInfoCommand(NoCheat plugin, CommandSender sender, String[] args) {
Map<String, Object> map = plugin.getPlayerData(args[1]);
String filter = "";
if(args.length > 2) {
filter = args[2];
}
sender.sendMessage("PlayerInfo for " + args[1]);
for(Entry<String, Object> entry : map.entrySet()) {
if(entry.getKey().contains(filter)) {
sender.sendMessage(entry.getKey() + ": " + entry.getValue());
}
}
return true;
}
private boolean handlePermlistCommand(NoCheat plugin, CommandSender sender, String[] args) {
private boolean handlePermlistCommand(final NoCheatPlus plugin, final CommandSender sender, final String[] args) {
// Get the player by name
Player player = plugin.getServer().getPlayerExact(args[1]);
if(player == null) {
final Player player = plugin.getServer().getPlayerExact(args[1]);
if (player == null) {
sender.sendMessage("Unknown player: " + args[1]);
return true;
}
// Should permissions be filtered by prefix?
String prefix = "";
if(args.length == 3) {
if (args.length == 3)
prefix = args[2];
}
sender.sendMessage("Player " + player.getName() + " has the permission(s):");
for(Permission permission : perms) {
if(permission.getName().startsWith(prefix)) {
for (final Permission permission : perms)
if (permission.getName().startsWith(prefix))
sender.sendMessage(permission.getName() + ": " + player.hasPermission(permission));
}
}
return true;
}
private boolean handleReloadCommand(NoCheat plugin, CommandSender sender) {
private boolean handlePlayerInfoCommand(final NoCheatPlus plugin, final CommandSender sender, final String[] args) {
final Map<String, Object> map = plugin.getPlayerData(args[1]);
String filter = "";
if (args.length > 2)
filter = args[2];
sender.sendMessage("PlayerInfo for " + args[1]);
for (final Entry<String, Object> entry : map.entrySet())
if (entry.getKey().contains(filter))
sender.sendMessage(entry.getKey() + ": " + entry.getValue());
return true;
}
private boolean handleReloadCommand(final NoCheatPlus plugin, final CommandSender sender) {
// Players need a special permission for this
if(!(sender instanceof Player) || sender.hasPermission(Permissions.ADMIN_RELOAD)) {
sender.sendMessage("[NoCheat] Reloading configuration");
if (!(sender instanceof Player) || sender.hasPermission(Permissions.ADMIN_RELOAD)) {
sender.sendMessage("[NoCheatPlus] Reloading configuration");
plugin.reloadConfiguration();
sender.sendMessage("[NoCheat] Configuration reloaded");
} else {
sender.sendMessage("[NoCheatPlus] Configuration reloaded");
} else
sender.sendMessage("You lack the " + Permissions.ADMIN_RELOAD + " permission to use 'reload'");
}
return true;
}

View File

@ -0,0 +1,152 @@
package me.neatmonster.nocheatplus.config;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import me.neatmonster.nocheatplus.actions.Action;
import me.neatmonster.nocheatplus.actions.types.ActionList;
import me.neatmonster.nocheatplus.actions.types.ConsolecommandAction;
import me.neatmonster.nocheatplus.actions.types.DummyAction;
import me.neatmonster.nocheatplus.actions.types.LogAction;
import me.neatmonster.nocheatplus.actions.types.SpecialAction;
/**
* Helps with creating Actions out of text string definitions
*
*/
public class ActionFactory {
private static final Map<String, Object> lib = new HashMap<String, Object>();
public ActionFactory(final Map<String, Object> library) {
lib.putAll(library);
}
public Action createAction(String actionDefinition) {
actionDefinition = actionDefinition.toLowerCase();
if (actionDefinition.equals("cancel"))
return new SpecialAction();
if (actionDefinition.startsWith("log:"))
return parseLogAction(actionDefinition.split(":", 2)[1]);
if (actionDefinition.startsWith("cmd:"))
return parseCmdAction(actionDefinition.split(":", 2)[1]);
throw new IllegalArgumentException("NoCheatPlus doesn't understand action '" + actionDefinition + "' at all");
}
public ActionList createActionList(final String definition, final String permission) {
final ActionList list = new ActionList(permission);
boolean first = true;
for (String s : definition.split("vl>")) {
s = s.trim();
if (s.length() == 0) {
first = false;
continue;
}
try {
Integer vl;
String def;
if (first) {
first = false;
vl = 0;
def = s;
} else {
final String[] listEntry = s.split("\\s+", 2);
vl = Integer.parseInt(listEntry[0]);
def = listEntry[1];
}
list.setActions(vl, createActions(def.split("\\s+")));
} catch (final Exception e) {
System.out.println("NoCheatPlus couldn't parse action definition 'vl:" + s + "'");
}
}
return list;
}
public Action[] createActions(final String... definitions) {
final List<Action> actions = new ArrayList<Action>();
for (final String def : definitions) {
if (def.length() == 0)
continue;
try {
actions.add(createAction(def));
} catch (final IllegalArgumentException e) {
System.out.println(e.getMessage());
actions.add(new DummyAction(def));
}
}
return actions.toArray(new Action[actions.size()]);
}
private Action parseCmdAction(final String definition) {
final String[] parts = definition.split(":");
final String name = parts[0];
final Object command = lib.get(parts[0]);
int delay = 0;
int repeat = 1;
if (command == null)
throw new IllegalArgumentException("NoCheatPlus doesn't know command '" + name
+ "'. Have you forgotten to define it?");
if (parts.length > 1)
try {
delay = Integer.parseInt(parts[1]);
repeat = Integer.parseInt(parts[2]);
} catch (final Exception e) {
System.out.println("NoCheatPlus couldn't parse details of command '" + definition
+ "', will use default values instead.");
delay = 0;
repeat = 1;
}
return new ConsolecommandAction(name, delay, repeat, command.toString());
}
private Action parseLogAction(final String definition) {
final String[] parts = definition.split(":");
final String name = parts[0];
final Object message = lib.get(parts[0]);
int delay = 0;
int repeat = 1;
boolean toConsole = true;
boolean toFile = true;
boolean toChat = true;
if (message == null)
throw new IllegalArgumentException("NoCheatPlus doesn't know log message '" + name
+ "'. Have you forgotten to define it?");
try {
delay = Integer.parseInt(parts[1]);
repeat = Integer.parseInt(parts[2]);
toConsole = parts[3].contains("c");
toChat = parts[3].contains("i");
toFile = parts[3].contains("f");
} catch (final Exception e) {
System.out.println("NoCheatPlus couldn't parse details of log action '" + definition
+ "', will use default values instead.");
e.printStackTrace();
delay = 0;
repeat = 1;
toConsole = true;
toFile = true;
toChat = true;
}
return new LogAction(name, delay, repeat, toChat, toConsole, toFile, message.toString());
}
}

View File

@ -1,4 +1,4 @@
package cc.co.evenprime.bukkit.nocheat.config;
package me.neatmonster.nocheatplus.config;
/**
* Paths for the configuration options
@ -56,9 +56,12 @@ public abstract class ConfPaths {
private final static String MOVING_RUNFLY_FLYING = MOVING_RUNFLY + "flying.";
public final static String MOVING_RUNFLY_FLYING_ALLOWALWAYS = MOVING_RUNFLY_FLYING + "allowflyingalways";
public final static String MOVING_RUNFLY_FLYING_ALLOWINCREATIVE = MOVING_RUNFLY_FLYING + "allowflyingincreative";
public final static String MOVING_RUNFLY_FLYING_SPEEDLIMITVERTICAL = MOVING_RUNFLY_FLYING + "flyingspeedlimitvertical";
public final static String MOVING_RUNFLY_FLYING_SPEEDLIMITHORIZONTAL = MOVING_RUNFLY_FLYING + "flyingspeedlimithorizontal";
public final static String MOVING_RUNFLY_FLYING_ALLOWINCREATIVE = MOVING_RUNFLY_FLYING
+ "allowflyingincreative";
public final static String MOVING_RUNFLY_FLYING_SPEEDLIMITVERTICAL = MOVING_RUNFLY_FLYING
+ "flyingspeedlimitvertical";
public final static String MOVING_RUNFLY_FLYING_SPEEDLIMITHORIZONTAL = MOVING_RUNFLY_FLYING
+ "flyingspeedlimithorizontal";
public final static String MOVING_RUNFLY_FLYING_HEIGHTLIMIT = MOVING_RUNFLY_FLYING + "flyingheightlimit";
public final static String MOVING_RUNFLY_FLYING_ACTIONS = MOVING_RUNFLY_FLYING + "actions";
@ -66,6 +69,10 @@ public abstract class ConfPaths {
public final static String MOVING_MOREPACKETS_CHECK = MOVING_MOREPACKETS + "active";
public final static String MOVING_MOREPACKETS_ACTIONS = MOVING_MOREPACKETS + "actions";
private final static String MOVING_WATERWALK = MOVING + "waterwalk.";
public final static String MOVING_WATERWALK_CHECK = MOVING_WATERWALK + "active";
public final static String MOVING_WATERWALK_ACTIONS = MOVING_WATERWALK + "actions";
private final static String BLOCKBREAK = CHECKS + "blockbreak.";
private final static String BLOCKBREAK_REACH = BLOCKBREAK + "reach.";

View File

@ -0,0 +1,45 @@
package me.neatmonster.nocheatplus.config;
import java.util.HashMap;
import java.util.Map;
import me.neatmonster.nocheatplus.ConfigItem;
/**
* A class to keep all configurables of the plugin associated with
* a world
*
*/
public class ConfigurationCacheStore {
public final LoggingConfig logging;
private final Map<String, ConfigItem> configMap = new HashMap<String, ConfigItem>();
private final NoCheatPlusConfiguration data;
/**
* Instantiate a config cache and populate it with the data of a
* Config tree (and its parent tree)
*/
public ConfigurationCacheStore(final NoCheatPlusConfiguration data) {
logging = new LoggingConfig(data);
this.data = data;
}
@SuppressWarnings("unchecked")
public <T extends ConfigItem> T get(final String id) {
return (T) configMap.get(id);
}
public NoCheatPlusConfiguration getConfiguration() {
return data;
}
public void set(final String id, final ConfigItem config) {
configMap.put(id, config);
}
}

View File

@ -1,4 +1,4 @@
package cc.co.evenprime.bukkit.nocheat.config;
package me.neatmonster.nocheatplus.config;
import java.io.File;
import java.io.PrintWriter;
@ -13,7 +13,8 @@ import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import me.neatmonster.nocheatplus.NoCheatPlus;
/**
* Central location for everything that's described in the configuration file(s)
@ -21,13 +22,6 @@ import cc.co.evenprime.bukkit.nocheat.NoCheat;
*/
public class ConfigurationManager {
private final static String configFileName = "config.yml";
private final Map<String, ConfigurationCacheStore> worldnameToConfigCacheMap = new HashMap<String, ConfigurationCacheStore>();
private FileHandler fileHandler;
private final NoCheat plugin;
private static class LogFileFormatter extends Formatter {
private final SimpleDateFormat date;
@ -37,9 +31,9 @@ public class ConfigurationManager {
}
@Override
public String format(LogRecord record) {
StringBuilder builder = new StringBuilder();
Throwable ex = record.getThrown();
public String format(final LogRecord record) {
final StringBuilder builder = new StringBuilder();
final Throwable ex = record.getThrown();
builder.append(date.format(record.getMillis()));
builder.append(" [");
@ -48,8 +42,8 @@ public class ConfigurationManager {
builder.append(record.getMessage());
builder.append('\n');
if(ex != null) {
StringWriter writer = new StringWriter();
if (ex != null) {
final StringWriter writer = new StringWriter();
ex.printStackTrace(new PrintWriter(writer));
builder.append(writer);
}
@ -58,7 +52,40 @@ public class ConfigurationManager {
}
}
public ConfigurationManager(NoCheat plugin, File rootConfigFolder) {
private final static String configFileName = "config.yml";
private static File getGlobalConfigFile(final File rootFolder) {
final File globalConfig = new File(rootFolder, configFileName);
return globalConfig;
}
private static Map<String, File> getWorldSpecificConfigFiles(final File rootFolder) {
final HashMap<String, File> files = new HashMap<String, File>();
if (rootFolder.isDirectory())
for (final File f : rootFolder.listFiles())
if (f.isFile()) {
final String filename = f.getName();
if (filename.matches(".+_" + configFileName + "$")) {
// Get the first part = world name
final String worldname = filename.substring(0, filename.length()
- (configFileName.length() + 1));
files.put(worldname, f);
}
}
return files;
}
private final Map<String, ConfigurationCacheStore> worldnameToConfigCacheMap = new HashMap<String, ConfigurationCacheStore>();
private FileHandler fileHandler;
private final NoCheatPlus plugin;
public ConfigurationManager(final NoCheatPlus plugin, final File rootConfigFolder) {
this.plugin = plugin;
@ -67,33 +94,67 @@ public class ConfigurationManager {
}
/**
* Reset the loggers and flush and close the fileHandlers
* to be able to use them next time without problems
*/
public void cleanup() {
fileHandler.flush();
fileHandler.close();
final Logger l = Logger.getLogger("NoCheatPlus");
l.removeHandler(fileHandler);
fileHandler = null;
}
/**
* Get the cache of the specified world, or the default cache,
* if no cache exists for that world.
*
* @param worldname
* @return
*/
public ConfigurationCacheStore getConfigurationCacheForWorld(final String worldname) {
ConfigurationCacheStore cache = worldnameToConfigCacheMap.get(worldname);
if (cache != null)
return cache;
else {
// Enter a reference to the cache under the new name
// to be faster in looking it up later
cache = worldnameToConfigCacheMap.get(null);
worldnameToConfigCacheMap.put(worldname, cache);
return cache;
}
}
/**
* Read the configuration file and assign either standard values or whatever
* is declared in the file
*
* @param configurationFile
*/
private void initializeConfig(File rootConfigFolder) {
private void initializeConfig(final File rootConfigFolder) {
// First try to obtain and parse the global config file
NoCheatConfiguration root = new NoCheatConfiguration();
final NoCheatPlusConfiguration root = new NoCheatPlusConfiguration();
root.setDefaults(new DefaultConfiguration());
root.options().copyDefaults(true);
root.options().copyHeader(true);
File globalConfigFile = getGlobalConfigFile(rootConfigFolder);
final File globalConfigFile = getGlobalConfigFile(rootConfigFolder);
if(globalConfigFile.exists()) {
if (globalConfigFile.exists())
try {
root.load(globalConfigFile);
} catch(Exception e) {
} catch (final Exception e) {
e.printStackTrace();
}
}
try {
root.save(globalConfigFile);
} catch(Exception e) {
} catch (final Exception e) {
e.printStackTrace();
}
@ -106,13 +167,13 @@ public class ConfigurationManager {
plugin.setFileLogger(setupFileLogger(new File(rootConfigFolder, root.getString(ConfPaths.LOGGING_FILENAME))));
// Try to find world-specific config files
Map<String, File> worldFiles = getWorldSpecificConfigFiles(rootConfigFolder);
final Map<String, File> worldFiles = getWorldSpecificConfigFiles(rootConfigFolder);
for(Entry<String, File> worldEntry : worldFiles.entrySet()) {
for (final Entry<String, File> worldEntry : worldFiles.entrySet()) {
File worldConfigFile = worldEntry.getValue();
final File worldConfigFile = worldEntry.getValue();
NoCheatConfiguration world = new NoCheatConfiguration();
final NoCheatPlusConfiguration world = new NoCheatPlusConfiguration();
world.setDefaults(root);
try {
@ -123,8 +184,8 @@ public class ConfigurationManager {
// write the config file back to disk immediately
world.save(worldConfigFile);
} catch(Exception e) {
System.out.println("NoCheat: Couldn't load world-specific config for " + worldEntry.getKey());
} catch (final Exception e) {
System.out.println("NoCheatPlus: Couldn't load world-specific config for " + worldEntry.getKey());
e.printStackTrace();
}
@ -132,43 +193,16 @@ public class ConfigurationManager {
}
}
private static File getGlobalConfigFile(File rootFolder) {
private Logger setupFileLogger(final File logfile) {
File globalConfig = new File(rootFolder, configFileName);
return globalConfig;
}
private static Map<String, File> getWorldSpecificConfigFiles(File rootFolder) {
HashMap<String, File> files = new HashMap<String, File>();
if(rootFolder.isDirectory()) {
for(File f : rootFolder.listFiles()) {
if(f.isFile()) {
String filename = f.getName();
if(filename.matches(".+_" + configFileName + "$")) {
// Get the first part = world name
String worldname = filename.substring(0, filename.length() - (configFileName.length() + 1));
files.put(worldname, f);
}
}
}
}
return files;
}
private Logger setupFileLogger(File logfile) {
Logger l = Logger.getAnonymousLogger();
final Logger l = Logger.getAnonymousLogger();
l.setLevel(Level.INFO);
// Ignore parent's settings
l.setUseParentHandlers(false);
for(Handler h : l.getHandlers()) {
for (final Handler h : l.getHandlers())
l.removeHandler(h);
}
if(fileHandler != null) {
if (fileHandler != null) {
fileHandler.close();
l.removeHandler(fileHandler);
fileHandler = null;
@ -177,7 +211,7 @@ public class ConfigurationManager {
try {
try {
logfile.getParentFile().mkdirs();
} catch(Exception e) {
} catch (final Exception e) {
e.printStackTrace();
}
fileHandler = new FileHandler(logfile.getCanonicalPath(), true);
@ -185,45 +219,10 @@ public class ConfigurationManager {
fileHandler.setFormatter(new LogFileFormatter());
l.addHandler(fileHandler);
} catch(Exception e) {
} catch (final Exception e) {
e.printStackTrace();
}
return l;
}
/**
* Reset the loggers and flush and close the fileHandlers
* to be able to use them next time without problems
*/
public void cleanup() {
fileHandler.flush();
fileHandler.close();
Logger l = Logger.getLogger("NoCheat");
l.removeHandler(fileHandler);
fileHandler = null;
}
/**
* Get the cache of the specified world, or the default cache,
* if no cache exists for that world.
*
* @param worldname
* @return
*/
public ConfigurationCacheStore getConfigurationCacheForWorld(String worldname) {
ConfigurationCacheStore cache = worldnameToConfigCacheMap.get(worldname);
if(cache != null) {
return cache;
} else {
// Enter a reference to the cache under the new name
// to be faster in looking it up later
cache = worldnameToConfigCacheMap.get(null);
worldnameToConfigCacheMap.put(worldname, cache);
return cache;
}
}
}

View File

@ -1,26 +1,26 @@
package cc.co.evenprime.bukkit.nocheat.config;
package me.neatmonster.nocheatplus.config;
/**
* These are the default settings for NoCheat. They will be used
* These are the default settings for NoCheatPlus. They will be used
* in addition to/in replacement of configurations given in the
* config.yml file
*
*/
public class DefaultConfiguration extends NoCheatConfiguration {
public class DefaultConfiguration extends NoCheatPlusConfiguration {
public DefaultConfiguration() {
super();
this.options().header("Main configuration file for NoCheat. Read \"Instructions.txt\"");
options().header("Main configuration file for NoCheatPlus. Read \"Instructions.txt\"");
/** LOGGING **/
set(ConfPaths.LOGGING_ACTIVE, true);
set(ConfPaths.LOGGING_SHOWACTIVECHECKS, false);
set(ConfPaths.LOGGING_DEBUGMESSAGES, false);
set(ConfPaths.LOGGING_PREFIX, "&4NC&f: ");
set(ConfPaths.LOGGING_FILENAME, "nocheat.log");
set(ConfPaths.LOGGING_PREFIX, "&4NCP&f: ");
set(ConfPaths.LOGGING_FILENAME, "nocheatplus.log");
set(ConfPaths.LOGGING_LOGTOFILE, true);
set(ConfPaths.LOGGING_LOGTOCONSOLE, true);
set(ConfPaths.LOGGING_LOGTOINGAMECHAT, true);
@ -42,7 +42,8 @@ public class DefaultConfiguration extends NoCheatConfiguration {
set(ConfPaths.MOVING_RUNFLY_CHECK, true);
set(ConfPaths.MOVING_RUNFLY_ALLOWFASTSNEAKING, false);
set(ConfPaths.MOVING_RUNFLY_ACTIONS, "log:moveshort:3:5:f cancel vl>100 log:moveshort:0:5:if cancel vl>400 log:movelong:0:5:cif cancel");
set(ConfPaths.MOVING_RUNFLY_ACTIONS,
"log:moveshort:3:5:f cancel vl>100 log:moveshort:0:5:if cancel vl>400 log:movelong:0:5:cif cancel");
set(ConfPaths.MOVING_RUNFLY_CHECKNOFALL, true);
set(ConfPaths.MOVING_RUNFLY_NOFALLAGGRESSIVE, true);
@ -53,11 +54,16 @@ public class DefaultConfiguration extends NoCheatConfiguration {
set(ConfPaths.MOVING_RUNFLY_FLYING_SPEEDLIMITHORIZONTAL, 60);
set(ConfPaths.MOVING_RUNFLY_FLYING_SPEEDLIMITVERTICAL, 100);
set(ConfPaths.MOVING_RUNFLY_FLYING_HEIGHTLIMIT, 128);
set(ConfPaths.MOVING_RUNFLY_FLYING_ACTIONS, "log:moveshort:3:5:f cancel vl>100 log:moveshort:0:5:if cancel vl>400 log:movelong:0:5:cif cancel");
set(ConfPaths.MOVING_RUNFLY_FLYING_ACTIONS,
"log:moveshort:3:5:f cancel vl>100 log:moveshort:0:5:if cancel vl>400 log:movelong:0:5:cif cancel");
set(ConfPaths.MOVING_MOREPACKETS_CHECK, true);
set(ConfPaths.MOVING_MOREPACKETS_ACTIONS, "log:morepackets:3:2:if cancel vl>20 log:morepackets:0:2:if cancel");
set(ConfPaths.MOVING_WATERWALK_CHECK, true);
set(ConfPaths.MOVING_WATERWALK_ACTIONS,
"log:waterwalk:3:5:f cancel vl>100 log:waterwalk:0:5:if cancel vl>400 log:waterwalk:0:5:cif cancel");
/*** BLOCKBREAK ***/
set(ConfPaths.BLOCKBREAK_REACH_CHECK, true);
@ -98,7 +104,8 @@ public class DefaultConfiguration extends NoCheatConfiguration {
set(ConfPaths.FIGHT_DIRECTION_CHECK, true);
set(ConfPaths.FIGHT_DIRECTION_PRECISION, 75);
set(ConfPaths.FIGHT_DIRECTION_PENALTYTIME, 500);
set(ConfPaths.FIGHT_DIRECTION_ACTIONS, "cancel vl>5 log:fdirection:3:5:f cancel vl>20 log:fdirection:0:5:if cancel vl>50 log:fdirection:0:5:cif cancel");
set(ConfPaths.FIGHT_DIRECTION_ACTIONS,
"cancel vl>5 log:fdirection:3:5:f cancel vl>20 log:fdirection:0:5:if cancel vl>50 log:fdirection:0:5:cif cancel");
set(ConfPaths.FIGHT_NOSWING_CHECK, true);
set(ConfPaths.FIGHT_NOSWING_ACTIONS, "log:fnoswing:0:5:cif cancel");
@ -118,24 +125,39 @@ public class DefaultConfiguration extends NoCheatConfiguration {
set(ConfPaths.FIGHT_INSTANTHEAL_CHECK, true);
set(ConfPaths.FIGHT_INSTANTHEAL_ACTIONS, "log:fheal:1:1:if cancel");
set(ConfPaths.STRINGS + ".drop", "[player] failed [check]: Tried to drop more items than allowed. VL [violations]");
set(ConfPaths.STRINGS + ".drop",
"[player] failed [check]: Tried to drop more items than allowed. VL [violations]");
set(ConfPaths.STRINGS + ".moveshort", "[player] failed [check]. VL [violations]");
set(ConfPaths.STRINGS + ".movelong", "[player] in [world] at [location] moving to [locationto] over distance [movedistance] failed check [check]. Total violation level so far [violations]");
set(ConfPaths.STRINGS + ".nofall", "[player] failed [check]: tried to avoid fall damage for ~[falldistance] blocks. VL [violations]");
set(ConfPaths.STRINGS + ".morepackets", "[player] failed [check]: Sent [packets] more packets than expected. Total violation level [violations]");
set(ConfPaths.STRINGS + ".bbreach", "[player] failed [check]: tried to interact with a block over distance [reachdistance]. VL [violations]");
set(ConfPaths.STRINGS + ".bbdirection", "[player] failed [check]: tried to interact with a block out of line of sight. VL [violations]");
set(ConfPaths.STRINGS + ".movelong",
"[player] in [world] at [location] moving to [locationto] over distance [movedistance] failed check [check]. Total violation level so far [violations]");
set(ConfPaths.STRINGS + ".nofall",
"[player] failed [check]: tried to avoid fall damage for ~[falldistance] blocks. VL [violations]");
set(ConfPaths.STRINGS + ".morepackets",
"[player] failed [check]: Sent [packets] more packets than expected. Total violation level [violations]");
set(ConfPaths.STRINGS + ".waterwalk",
"[player] failed [check]: tried to walk on water. Total violation level [violations]");
set(ConfPaths.STRINGS + ".bbreach",
"[player] failed [check]: tried to interact with a block over distance [reachdistance]. VL [violations]");
set(ConfPaths.STRINGS + ".bbdirection",
"[player] failed [check]: tried to interact with a block out of line of sight. VL [violations]");
set(ConfPaths.STRINGS + ".bbnoswing", "[player] failed [check]: Didn't swing arm. VL [violations]");
set(ConfPaths.STRINGS + ".bpreach", "[player] failed [check]: tried to interact with a block over distance [reachdistance]. VL [violations]");
set(ConfPaths.STRINGS + ".bpdirection", "[player] failed [check]: tried to interact with a block out of line of sight. VL [violations]");
set(ConfPaths.STRINGS + ".color", "[player] failed [check]: Sent colored chat message '[text]'. VL [violations]");
set(ConfPaths.STRINGS + ".bpreach",
"[player] failed [check]: tried to interact with a block over distance [reachdistance]. VL [violations]");
set(ConfPaths.STRINGS + ".bpdirection",
"[player] failed [check]: tried to interact with a block out of line of sight. VL [violations]");
set(ConfPaths.STRINGS + ".color",
"[player] failed [check]: Sent colored chat message '[text]'. VL [violations]");
set(ConfPaths.STRINGS + ".spam", "[player] failed [check]: Last sent message '[text]'. VL [violations]");
set(ConfPaths.STRINGS + ".fdirection", "[player] failed [check]: tried to interact with a block out of line of sight. VL [violations]");
set(ConfPaths.STRINGS + ".freach", "[player] failed [check]: tried to attack entity out of reach. VL [violations]");
set(ConfPaths.STRINGS + ".fspeed", "[player] failed [check]: tried to attack more than [limit] times per second. VL [violations]");
set(ConfPaths.STRINGS + ".fdirection",
"[player] failed [check]: tried to interact with a block out of line of sight. VL [violations]");
set(ConfPaths.STRINGS + ".freach",
"[player] failed [check]: tried to attack entity out of reach. VL [violations]");
set(ConfPaths.STRINGS + ".fspeed",
"[player] failed [check]: tried to attack more than [limit] times per second. VL [violations]");
set(ConfPaths.STRINGS + ".fnoswing", "[player] failed [check]: Didn't swing arm. VL [violations]");
set(ConfPaths.STRINGS + ".fgod", "[player] failed [check]: Avoided taking damage or lagging. VL [violations]");
set(ConfPaths.STRINGS + ".fheal", "[player] failed [check]: Tried to regenerate health faster than normal. VL [violations]");
set(ConfPaths.STRINGS + ".fheal",
"[player] failed [check]: Tried to regenerate health faster than normal. VL [violations]");
set(ConfPaths.STRINGS + ".ibow", "[player] failed [check]: Fires bow to fast. VL [violations]");
set(ConfPaths.STRINGS + ".ieat", "[player] failed [check]: Eats food [food] too fast. VL [violations]");
set(ConfPaths.STRINGS + ".kick", "kick [player]");

View File

@ -1,4 +1,4 @@
package cc.co.evenprime.bukkit.nocheat.config;
package me.neatmonster.nocheatplus.config;
/**
* Configurations specific for logging. Every world gets one of these.
@ -14,7 +14,7 @@ public class LoggingConfig {
public final String prefix;
public final boolean debugmessages;
public LoggingConfig(NoCheatConfiguration data) {
public LoggingConfig(final NoCheatPlusConfiguration data) {
active = data.getBoolean(ConfPaths.LOGGING_ACTIVE);
showactivechecks = data.getBoolean(ConfPaths.LOGGING_SHOWACTIVECHECKS);

View File

@ -0,0 +1,90 @@
package me.neatmonster.nocheatplus.config;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.actions.Action;
import me.neatmonster.nocheatplus.actions.types.ActionList;
import org.bukkit.configuration.MemorySection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.yaml.snakeyaml.DumperOptions;
public class NoCheatPlusConfiguration extends YamlConfiguration {
public static void writeInstructions(final NoCheatPlus plugin) {
try {
final InputStream is = plugin.getResource("Instructions.txt");
final FileOutputStream fos = new FileOutputStream(new File(plugin.getDataFolder(), "Intructions.txt"));
final byte[] buffer = new byte[64 * 1024];
int length = 0;
while ((length = is.read(buffer)) != -1)
fos.write(buffer, 0, length);
fos.flush();
fos.close();
is.close();
} catch (final Exception e) {
e.printStackTrace();
}
}
private ActionFactory factory;
/**
* A convenience method to get action lists from the config
*
* @param path
* @return
*/
public ActionList getActionList(final String path, final String permission) {
final String value = this.getString(path);
return factory.createActionList(value, permission);
}
/**
* Do this after reading new data
*/
public void regenerateActionLists() {
factory = new ActionFactory(((MemorySection) this.get(ConfPaths.STRINGS)).getValues(false));
}
@Override
public String saveToString() {
// Some reflection wizardry to avoid having a lot of
// linebreaks in the yml file, and get a "footer" into the file
try {
Field op;
op = YamlConfiguration.class.getDeclaredField("yamlOptions");
op.setAccessible(true);
final DumperOptions options = (DumperOptions) op.get(this);
options.setWidth(200);
} catch (final Exception e) {}
final String result = super.saveToString();
return result;
}
/**
* Savely store ActionLists back into the yml file
*
* @param path
* @param list
*/
public void set(final String path, final ActionList list) {
final StringBuffer string = new StringBuffer();
for (final int treshold : list.getTresholds()) {
if (treshold > 0)
string.append(" vl>").append(treshold);
for (final Action action : list.getActions(treshold))
string.append(" ").append(action);
}
set(path, string.toString().trim());
}
}

View File

@ -0,0 +1,62 @@
package me.neatmonster.nocheatplus.config;
/**
* The various permission nodes used by NoCheatPlus
*
*/
public class Permissions {
private static final String NOCHEATPLUS = "nocheatplus";
private static final String ADMIN = NOCHEATPLUS + ".admin";
private static final String CHECKS = NOCHEATPLUS + ".checks";
private static final String ZOMBE = NOCHEATPLUS + ".zombe";
private static final String CJB = NOCHEATPLUS + ".cjb";
public static final String MOVING = CHECKS + ".moving";
public static final String MOVING_RUNFLY = MOVING + ".runfly";
public static final String MOVING_SWIMMING = MOVING + ".swimming";
public static final String MOVING_SNEAKING = MOVING + ".sneaking";
public static final String MOVING_FLYING = MOVING + ".flying";
public static final String MOVING_NOFALL = MOVING + ".nofall";
public static final String MOVING_MOREPACKETS = MOVING + ".morepackets";
public static final String MOVING_WATERWALK = MOVING + ".waterwalk";
public static final String BLOCKBREAK = CHECKS + ".blockbreak";
public static final String BLOCKBREAK_REACH = BLOCKBREAK + ".reach";
public static final String BLOCKBREAK_DIRECTION = BLOCKBREAK + ".direction";
public static final String BLOCKBREAK_NOSWING = BLOCKBREAK + ".noswing";
public static final String BLOCKPLACE = CHECKS + ".blockplace";
public static final String BLOCKPLACE_REACH = BLOCKPLACE + ".reach";
public static final String BLOCKPLACE_DIRECTION = BLOCKPLACE + ".direction";
public static final String CHAT = CHECKS + ".chat";
public static final String CHAT_SPAM = CHAT + ".spam";
public static final String CHAT_COLOR = CHAT + ".color";
public static final String FIGHT = CHECKS + ".fight";
public static final String FIGHT_DIRECTION = FIGHT + ".direction";
public static final String FIGHT_NOSWING = FIGHT + ".noswing";
public static final String FIGHT_REACH = FIGHT + ".reach";
public static final String FIGHT_SPEED = FIGHT + ".speed";
public static final String FIGHT_GODMODE = FIGHT + ".godmode";
public static final String FIGHT_INSTANTHEAL = FIGHT + ".instantheal";
public static final String ADMIN_CHATLOG = ADMIN + ".chatlog";
public static final String ADMIN_COMMANDS = ADMIN + ".commands";
public static final String ADMIN_RELOAD = ADMIN + ".reload";
public 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";
public static final String ZOMBE_FLY = ZOMBE + ".fly";
public static final String ZOMBE_CHEATS = ZOMBE + ".cheats";
public static final String CJB_FLY = CJB + ".fly";
public static final String CJB_XRAY = CJB + ".xray";
public static final String CJB_MINIMAP = CJB + ".minimap";
private Permissions() {}
}

View File

@ -1,8 +1,9 @@
package cc.co.evenprime.bukkit.nocheat.data;
package me.neatmonster.nocheatplus.data;
import java.util.HashMap;
import java.util.Map;
import cc.co.evenprime.bukkit.nocheat.DataItem;
import me.neatmonster.nocheatplus.DataItem;
public class DataStore {
@ -11,24 +12,24 @@ public class DataStore {
private final long timestamp = System.currentTimeMillis();
@SuppressWarnings("unchecked")
public <T extends DataItem>T get(String id) {
return (T) dataMap.get(id);
}
public void set(String id, DataItem data) {
dataMap.put(id, data);
}
public Map<String, Object> collectData() {
Map<String, Object> map = statistics.get();
map.put("nocheat.starttime", timestamp);
map.put("nocheat.endtime", System.currentTimeMillis());
final Map<String, Object> map = statistics.get();
map.put("nocheatplus.starttime", timestamp);
map.put("nocheatplus.endtime", System.currentTimeMillis());
return map;
}
@SuppressWarnings("unchecked")
public <T extends DataItem> T get(final String id) {
return (T) dataMap.get(id);
}
public Statistics getStatistics() {
return statistics;
}
public void set(final String id, final DataItem data) {
dataMap.put(id, data);
}
}

View File

@ -1,8 +1,9 @@
package cc.co.evenprime.bukkit.nocheat.data;
package me.neatmonster.nocheatplus.data;
import java.util.HashMap;
import java.util.Map;
import cc.co.evenprime.bukkit.nocheat.actions.Action;
import me.neatmonster.nocheatplus.actions.Action;
/**
* Store amount of action executions for last 60 seconds
@ -18,16 +19,16 @@ public class ExecutionHistory {
private int totalEntries = 0;
private long lastClearedTime = 0;
private ExecutionHistoryEntry(int monitoredTimeFrame) {
this.executionTimes = new int[monitoredTimeFrame];
private ExecutionHistoryEntry(final int monitoredTimeFrame) {
executionTimes = new int[monitoredTimeFrame];
}
/**
* Remember an execution at the specific time
*/
private void addCounter(long time) {
private void addCounter(final long time) {
// clear out now outdated values from the array
if(time - lastClearedTime > 0) {
if (time - lastClearedTime > 0) {
// Clear the next few fields of the array
clearTimes(lastClearedTime + 1, time - lastClearedTime);
lastClearedTime = time + 1;
@ -43,21 +44,18 @@ public class ExecutionHistory {
* @param start
* @param length
*/
private void clearTimes(long start, long length) {
private void clearTimes(final long start, long length) {
if(length <= 0) {
if (length <= 0)
return; // nothing to do (yet)
}
if(length > executionTimes.length) {
if (length > executionTimes.length)
length = executionTimes.length;
}
int j = (int) start % executionTimes.length;
for(int i = 0; i < length; i++) {
if(j == executionTimes.length) {
for (int i = 0; i < length; i++) {
if (j == executionTimes.length)
j = 0;
}
totalEntries -= executionTimes[j];
executionTimes[j] = 0;
@ -74,8 +72,8 @@ public class ExecutionHistory {
return lastExecution;
}
public void setLastExecution(long time) {
this.lastExecution = time;
public void setLastExecution(final long time) {
lastExecution = time;
}
}
@ -99,18 +97,18 @@ public class ExecutionHistory {
* a time IN SECONDS
* @return
*/
public boolean executeAction(String check, Action action, long time) {
public boolean executeAction(final String check, final Action action, final long time) {
Map<Action, ExecutionHistoryEntry> executionHistory = executionHistories.get(check);
if(executionHistory == null) {
if (executionHistory == null) {
executionHistory = new HashMap<Action, ExecutionHistoryEntry>();
executionHistories.put(check, executionHistory);
}
ExecutionHistoryEntry entry = executionHistory.get(action);
if(entry == null) {
if (entry == null) {
entry = new ExecutionHistoryEntry(60);
executionHistory.put(action, entry);
}
@ -118,14 +116,13 @@ public class ExecutionHistory {
// update entry
entry.addCounter(time);
if(entry.getCounter() > action.delay) {
if (entry.getCounter() > action.delay)
// Execute action?
if(entry.getLastExecution() <= time - action.repeat) {
if (entry.getLastExecution() <= time - action.repeat) {
// Execute action!
entry.setLastExecution(time);
return true;
}
}
return false;
}

View File

@ -0,0 +1,71 @@
package me.neatmonster.nocheatplus.data;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import me.neatmonster.nocheatplus.NoCheatPlus;
import me.neatmonster.nocheatplus.NoCheatPlusPlayer;
import me.neatmonster.nocheatplus.NoCheatPlusPlayerImpl;
import org.bukkit.entity.Player;
/**
* Provide secure access to player-specific data objects for various checks or
* check groups.
*/
public class PlayerManager {
// Store data between Events
private final Map<String, NoCheatPlusPlayerImpl> players;
private final NoCheatPlus plugin;
public PlayerManager(final NoCheatPlus plugin) {
players = new HashMap<String, NoCheatPlusPlayerImpl>();
this.plugin = plugin;
}
public void cleanDataMap() {
final long time = System.currentTimeMillis();
final List<String> removals = new ArrayList<String>(5);
for (final Entry<String, NoCheatPlusPlayerImpl> e : players.entrySet())
if (e.getValue().shouldBeRemoved(time))
removals.add(e.getKey());
for (final String key : removals)
players.remove(key);
}
/**
* Get a data object of the specified class. If none is stored yet, create
* one.
*/
public NoCheatPlusPlayer getPlayer(final Player player) {
NoCheatPlusPlayerImpl p = players.get(player.getName().toLowerCase());
if (p == null) {
p = new NoCheatPlusPlayerImpl(player, plugin);
players.put(player.getName().toLowerCase(), p);
}
p.setLastUsedTime(System.currentTimeMillis());
p.refresh(player);
return p;
}
public Map<String, Object> getPlayerData(final String playerName) {
final NoCheatPlusPlayer player = players.get(playerName.toLowerCase());
if (player != null)
return player.getDataStore().collectData();
return new HashMap<String, Object>();
}
}

View File

@ -1,4 +1,4 @@
package cc.co.evenprime.bukkit.nocheat.data;
package me.neatmonster.nocheatplus.data;
import org.bukkit.Location;
@ -17,16 +17,8 @@ public final class PreciseLocation {
reset();
}
public final void set(Location location) {
x = location.getX();
y = location.getY();
z = location.getZ();
}
public final void set(PreciseLocation location) {
x = location.x;
y = location.y;
z = location.z;
public final boolean equals(final Location location) {
return location.getX() == x && location.getY() == y && location.getZ() == z;
}
public final boolean isSet() {
@ -39,7 +31,15 @@ public final class PreciseLocation {
z = Double.MAX_VALUE;
}
public final boolean equals(Location location) {
return location.getX() == x && location.getY() == y && location.getZ() == z;
public final void set(final Location location) {
x = location.getX();
y = location.getY();
z = location.getZ();
}
public final void set(final PreciseLocation location) {
x = location.x;
y = location.y;
z = location.z;
}
}

View File

@ -1,4 +1,4 @@
package cc.co.evenprime.bukkit.nocheat.data;
package me.neatmonster.nocheatplus.data;
import org.bukkit.Location;
import org.bukkit.block.Block;
@ -20,15 +20,15 @@ public final class SimpleLocation {
}
@Override
public final boolean equals(Object object) {
if(!(object instanceof SimpleLocation))
public final boolean equals(final Object object) {
if (!(object instanceof SimpleLocation))
return false;
SimpleLocation simpleLocation = (SimpleLocation) object;
final SimpleLocation simpleLocation = (SimpleLocation) object;
if(!isSet() && !simpleLocation.isSet())
if (!isSet() && !simpleLocation.isSet())
return true;
else if(!isSet() || !simpleLocation.isSet())
else if (!isSet() || !simpleLocation.isSet())
return false;
return simpleLocation.x == x && simpleLocation.y == y && simpleLocation.z == z;
@ -39,18 +39,6 @@ public final class SimpleLocation {
return x * 1000000 + y * 1000 + z;
}
public final void set(Block block) {
x = block.getX();
y = block.getY();
z = block.getZ();
}
public final void setLocation(Location location) {
x = location.getBlockX();
y = location.getBlockY();
z = location.getBlockZ();
}
public final boolean isSet() {
return x != Integer.MAX_VALUE;
}
@ -61,4 +49,16 @@ public final class SimpleLocation {
z = Integer.MAX_VALUE;
}
public final void set(final Block block) {
x = block.getX();
y = block.getY();
z = block.getZ();
}
public final void setLocation(final Location location) {
x = location.getBlockX();
y = location.getBlockY();
z = location.getBlockZ();
}
}

Some files were not shown because too many files have changed in this diff Show More