+ 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:
parent
9d5f1f1266
commit
e057737fb0
192
Instructions.txt
192
Instructions.txt
|
@ -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
|
||||
|
|
|
@ -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.
|
|
@ -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)
|
||||
#
|
||||
#
|
109
plugin.yml
109
plugin.yml
|
@ -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
120
pom.xml
|
@ -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>
|
|
@ -1,5 +0,0 @@
|
|||
package cc.co.evenprime.bukkit.nocheat;
|
||||
|
||||
public interface ConfigItem {
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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 + ".";
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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() {}
|
||||
}
|
|
@ -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>();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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(' ');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package me.neatmonster.nocheatplus;
|
||||
|
||||
public interface ConfigItem {
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package cc.co.evenprime.bukkit.nocheat;
|
||||
package me.neatmonster.nocheatplus;
|
||||
|
||||
/**
|
||||
*
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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" : "");
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -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);
|
|
@ -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;
|
||||
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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()]);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -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
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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.";
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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]");
|
|
@ -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);
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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() {}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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>();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue