mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2025-01-08 00:38:27 +01:00
Improved PlayerLocation objects management. Cleaned up the exemption
API.
This commit is contained in:
parent
5625b61b41
commit
2d5850a547
@ -190,12 +190,12 @@ public abstract class Check {
|
|||||||
* @return true, if the check is enabled
|
* @return true, if the check is enabled
|
||||||
*/
|
*/
|
||||||
public boolean isEnabled(final Player player) {
|
public boolean isEnabled(final Player player) {
|
||||||
if (NCPExemptionManager.isExempted(player, type)) return false;
|
|
||||||
try {
|
try {
|
||||||
return type.isEnabled(player) && !player.hasPermission(type.getPermission());
|
if (!type.isEnabled(player) || player.hasPermission(type.getPermission()))
|
||||||
|
return false;
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return false;
|
return !NCPExemptionManager.isExempted(player, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ public class Color extends Check {
|
|||||||
return message;
|
return message;
|
||||||
|
|
||||||
final ChatConfig cc = ChatConfig.getConfig(player);
|
final ChatConfig cc = ChatConfig.getConfig(player);
|
||||||
if (!isMainThread && (NCPExemptionManager.isExempted(player, type) || !cc.isEnabled(type)))
|
if (!isMainThread && (!cc.isEnabled(type) || NCPExemptionManager.isExempted(player, type)))
|
||||||
// Leave out the permission check.
|
// Leave out the permission check.
|
||||||
return message;
|
return message;
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ public class NoPwnage extends Check {
|
|||||||
final ChatConfig cc = ChatConfig.getConfig(player);
|
final ChatConfig cc = ChatConfig.getConfig(player);
|
||||||
final ChatData data = ChatData.getData(player);
|
final ChatData data = ChatData.getData(player);
|
||||||
|
|
||||||
if (!isMainThread && (NCPExemptionManager.isExempted(player, type) || !cc.isEnabled(type)))
|
if (!isMainThread && (!cc.isEnabled(type) || NCPExemptionManager.isExempted(player, type)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Keep related to ChatData/NoPwnage/Color used lock.
|
// Keep related to ChatData/NoPwnage/Color used lock.
|
||||||
|
@ -43,7 +43,8 @@ public class Critical extends Check {
|
|||||||
boolean cancel = false;
|
boolean cancel = false;
|
||||||
|
|
||||||
// We'll need the PlayerLocation to know some important stuff.
|
// We'll need the PlayerLocation to know some important stuff.
|
||||||
final PlayerLocation location = new PlayerLocation(player.getLocation(), player);
|
PlayerLocation location = new PlayerLocation();
|
||||||
|
location.set(player.getLocation(), player);
|
||||||
|
|
||||||
// Check if the hit was a critical hit (positive fall distance, entity in the air, not on ladder, not in liquid
|
// Check if the hit was a critical hit (positive fall distance, entity in the air, not on ladder, not in liquid
|
||||||
// and without blindness effect).
|
// and without blindness effect).
|
||||||
@ -70,6 +71,8 @@ public class Critical extends Check {
|
|||||||
cancel = executeActions(player, data.criticalVL, delta, cc.criticalActions);
|
cancel = executeActions(player, data.criticalVL, delta, cc.criticalActions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location = null;
|
||||||
|
|
||||||
return cancel;
|
return cancel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,8 @@ public class CreativeFly extends Check {
|
|||||||
else if (wildcard == ParameterName.LOCATION_TO)
|
else if (wildcard == ParameterName.LOCATION_TO)
|
||||||
return String.format(Locale.US, "%.2f, %.2f, %.2f", data.to.getX(), data.to.getY(), data.to.getZ());
|
return String.format(Locale.US, "%.2f, %.2f, %.2f", data.to.getX(), data.to.getY(), data.to.getZ());
|
||||||
else if (wildcard == ParameterName.DISTANCE)
|
else if (wildcard == ParameterName.DISTANCE)
|
||||||
return String.format(Locale.US, "%.2f", data.to.subtract(data.from).lengthSquared());
|
return String.format(Locale.US, "%.2f", data.to.getLocation().subtract(data.from.getLocation())
|
||||||
|
.lengthSquared());
|
||||||
else
|
else
|
||||||
return super.getParameter(wildcard, violationData);
|
return super.getParameter(wildcard, violationData);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import org.bukkit.entity.Player;
|
|||||||
|
|
||||||
import fr.neatmonster.nocheatplus.checks.CheckData;
|
import fr.neatmonster.nocheatplus.checks.CheckData;
|
||||||
import fr.neatmonster.nocheatplus.checks.CheckDataFactory;
|
import fr.neatmonster.nocheatplus.checks.CheckDataFactory;
|
||||||
|
import fr.neatmonster.nocheatplus.utilities.PlayerLocation;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* M"""""`'"""`YM oo M""""""'YMM dP
|
* M"""""`'"""`YM oo M""""""'YMM dP
|
||||||
@ -49,54 +50,54 @@ public class MovingData implements CheckData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Violation levels.
|
// Violation levels.
|
||||||
public double creativeFlyVL = 0D;
|
public double creativeFlyVL = 0D;
|
||||||
public double morePacketsVL = 0D;
|
public double morePacketsVL = 0D;
|
||||||
public double morePacketsVehicleVL = 0D;
|
public double morePacketsVehicleVL = 0D;
|
||||||
public double noFallVL = 0D;
|
public double noFallVL = 0D;
|
||||||
public double survivalFlyVL = 0D;
|
public double survivalFlyVL = 0D;
|
||||||
|
|
||||||
// Data shared between the fly checks.
|
// Data shared between the fly checks.
|
||||||
public int bunnyhopDelay;
|
public int bunnyhopDelay;
|
||||||
public double horizontalBuffer;
|
public double horizontalBuffer;
|
||||||
public double horizontalFreedom;
|
public double horizontalFreedom;
|
||||||
public double horizontalVelocityCounter;
|
public double horizontalVelocityCounter;
|
||||||
public double jumpAmplifier;
|
public double jumpAmplifier;
|
||||||
public double verticalFreedom;
|
public double verticalFreedom;
|
||||||
public double verticalVelocity;
|
public double verticalVelocity;
|
||||||
public int verticalVelocityCounter;
|
public int verticalVelocityCounter;
|
||||||
|
|
||||||
// Data of the creative check.
|
// Data of the creative check.
|
||||||
public boolean creativeFlyPreviousRefused;
|
public boolean creativeFlyPreviousRefused;
|
||||||
|
|
||||||
// Data of the more packets check.
|
// Data of the more packets check.
|
||||||
public int morePacketsBuffer = 50;
|
public int morePacketsBuffer = 50;
|
||||||
public long morePacketsLastTime;
|
public long morePacketsLastTime;
|
||||||
public int morePacketsPackets;
|
public int morePacketsPackets;
|
||||||
public Location morePacketsSetback;
|
public Location morePacketsSetback;
|
||||||
|
|
||||||
// Data of the more packets vehicle check.
|
// Data of the more packets vehicle check.
|
||||||
public int morePacketsVehicleBuffer = 50;
|
public int morePacketsVehicleBuffer = 50;
|
||||||
public long morePacketsVehicleLastTime;
|
public long morePacketsVehicleLastTime;
|
||||||
public int morePacketsVehiclePackets;
|
public int morePacketsVehiclePackets;
|
||||||
public Location morePacketsVehicleSetback;
|
public Location morePacketsVehicleSetback;
|
||||||
|
|
||||||
// Data of the no fall check.
|
// Data of the no fall check.
|
||||||
public double noFallFallDistance;
|
public double noFallFallDistance;
|
||||||
public boolean noFallOnGround;
|
public boolean noFallOnGround;
|
||||||
public boolean noFallWasOnGround;
|
public boolean noFallWasOnGround;
|
||||||
|
|
||||||
// Data of the survival fly check.
|
// Data of the survival fly check.
|
||||||
public int survivalFlyJumpPhase;
|
public int survivalFlyJumpPhase;
|
||||||
public double survivalFlyLastFromY;
|
public double survivalFlyLastFromY;
|
||||||
public int survivalFlyOnIce;
|
public int survivalFlyOnIce;
|
||||||
public boolean survivalFlyWasInBed;
|
public boolean survivalFlyWasInBed;
|
||||||
|
|
||||||
// Locations shared between all checks.
|
// Locations shared between all checks.
|
||||||
public Location from;
|
public PlayerLocation from = new PlayerLocation();
|
||||||
public Location ground;
|
public Location ground;
|
||||||
public Location setBack;
|
public Location setBack;
|
||||||
public Location teleported;
|
public Location teleported;
|
||||||
public Location to;
|
public PlayerLocation to = new PlayerLocation();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the data of the fly checks.
|
* Clear the data of the fly checks.
|
||||||
|
@ -29,7 +29,6 @@ import org.bukkit.util.Vector;
|
|||||||
|
|
||||||
import fr.neatmonster.nocheatplus.NoCheatPlus;
|
import fr.neatmonster.nocheatplus.NoCheatPlus;
|
||||||
import fr.neatmonster.nocheatplus.players.Permissions;
|
import fr.neatmonster.nocheatplus.players.Permissions;
|
||||||
import fr.neatmonster.nocheatplus.utilities.PlayerLocation;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* M"""""`'"""`YM oo
|
* M"""""`'"""`YM oo
|
||||||
@ -330,31 +329,29 @@ public class MovingListener implements Listener {
|
|||||||
// Counter has run out, now reduce the vertical freedom over time.
|
// Counter has run out, now reduce the vertical freedom over time.
|
||||||
data.verticalFreedom *= 0.93D;
|
data.verticalFreedom *= 0.93D;
|
||||||
|
|
||||||
final PlayerLocation from = new PlayerLocation(event.getFrom(), player);
|
data.from.set(event.getFrom(), player);
|
||||||
data.from = from.getLocation();
|
if (data.from.isOnGround())
|
||||||
if (from.isOnGround())
|
data.ground = data.from.getLocation();
|
||||||
data.ground = from.getLocation();
|
data.to.set(event.getTo(), player);
|
||||||
final PlayerLocation to = new PlayerLocation(event.getTo(), player);
|
|
||||||
data.to = to.getLocation();
|
|
||||||
|
|
||||||
Location newTo = null;
|
Location newTo = null;
|
||||||
|
|
||||||
if ((player.getGameMode() == GameMode.CREATIVE || player.getAllowFlight()) && creativeFly.isEnabled(player))
|
if ((player.getGameMode() == GameMode.CREATIVE || player.getAllowFlight()) && creativeFly.isEnabled(player))
|
||||||
// If the player is handled by the creative fly check, execute it.
|
// If the player is handled by the creative fly check, execute it.
|
||||||
newTo = creativeFly.check(player, from, to);
|
newTo = creativeFly.check(player, data.from, data.to);
|
||||||
else if (survivalFly.isEnabled(player)) {
|
else if (survivalFly.isEnabled(player)) {
|
||||||
// If he is handled by the survival fly check, execute it.
|
// If he is handled by the survival fly check, execute it.
|
||||||
newTo = survivalFly.check(player, from, to);
|
newTo = survivalFly.check(player, data.from, data.to);
|
||||||
// If don't have a new location and if he is handled by the no fall check, execute it.
|
// If don't have a new location and if he is handled by the no fall check, execute it.
|
||||||
if (newTo == null && noFall.isEnabled(player))
|
if (newTo == null && noFall.isEnabled(player))
|
||||||
noFall.check(player, from, to);
|
noFall.check(player, data.from, data.to);
|
||||||
} else
|
} else
|
||||||
// He isn't handled by any fly check, clear his data.
|
// He isn't handled by any fly check, clear his data.
|
||||||
data.clearFlyData();
|
data.clearFlyData();
|
||||||
|
|
||||||
if (newTo == null && morePackets.isEnabled(player))
|
if (newTo == null && morePackets.isEnabled(player))
|
||||||
// If he hasn't been stopped by any other check and is handled by the more packets check, execute it.
|
// If he hasn't been stopped by any other check and is handled by the more packets check, execute it.
|
||||||
newTo = morePackets.check(player, from, to);
|
newTo = morePackets.check(player, data.from, data.to);
|
||||||
else
|
else
|
||||||
// Otherwise we need to clear his data.
|
// Otherwise we need to clear his data.
|
||||||
data.clearMorePacketsData();
|
data.clearMorePacketsData();
|
||||||
|
@ -262,7 +262,8 @@ public class SurvivalFly extends Check {
|
|||||||
else if (wildcard == ParameterName.LOCATION_TO)
|
else if (wildcard == ParameterName.LOCATION_TO)
|
||||||
return String.format(Locale.US, "%.2f, %.2f, %.2f", data.to.getX(), data.to.getY(), data.to.getZ());
|
return String.format(Locale.US, "%.2f, %.2f, %.2f", data.to.getX(), data.to.getY(), data.to.getZ());
|
||||||
else if (wildcard == ParameterName.DISTANCE)
|
else if (wildcard == ParameterName.DISTANCE)
|
||||||
return String.format(Locale.US, "%.2f", data.to.subtract(data.from).lengthSquared());
|
return String.format(Locale.US, "%.2f", data.to.getLocation().subtract(data.from.getLocation())
|
||||||
|
.lengthSquared());
|
||||||
else
|
else
|
||||||
return super.getParameter(wildcard, violationData);
|
return super.getParameter(wildcard, violationData);
|
||||||
}
|
}
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
package fr.neatmonster.nocheatplus.hooks;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
|
||||||
|
|
||||||
public class APIUtil {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Only the children.
|
|
||||||
*/
|
|
||||||
private static final Map<CheckType, CheckType[]> childrenMap = new HashMap<CheckType, CheckType[]>();
|
|
||||||
|
|
||||||
static{
|
|
||||||
Map<CheckType, Set<CheckType>> temp = new HashMap<CheckType, Set<CheckType>>();
|
|
||||||
// uh uh
|
|
||||||
for (CheckType checkType : CheckType.values()){
|
|
||||||
Set<CheckType> set = new HashSet<CheckType>();
|
|
||||||
temp.put(checkType, set);
|
|
||||||
}
|
|
||||||
for (CheckType checkType : CheckType.values()){
|
|
||||||
for (CheckType other : CheckType.values()){
|
|
||||||
if (isParent(other, checkType)){
|
|
||||||
temp.get(other).add(checkType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (CheckType parent : temp.keySet()){
|
|
||||||
Set<CheckType> set = temp.get(parent);
|
|
||||||
CheckType[] a = new CheckType[set.size()];
|
|
||||||
set.toArray(a);
|
|
||||||
childrenMap.put(parent, a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if propablyParent is ancestor of checkType. Does not check versus checkType directly.
|
|
||||||
* @param probablyParent
|
|
||||||
* @param checkType
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static final boolean isParent(final CheckType probablyParent, final CheckType checkType){
|
|
||||||
CheckType parent = checkType.getParent();
|
|
||||||
while (parent != null){
|
|
||||||
if (parent == probablyParent) return true;
|
|
||||||
else parent = parent.getParent();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an unmodifiable collection of children for the given check type. Always returns a collection, does not contain checkType itself.
|
|
||||||
* @param checkType
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static final Collection<CheckType> getChildren(final CheckType checkType){
|
|
||||||
return Arrays.asList(childrenMap.get(checkType));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final boolean needsSynchronization(final CheckType checkType){
|
|
||||||
return checkType == CheckType.CHAT || isParent(CheckType.CHAT, checkType);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
86
src/fr/neatmonster/nocheatplus/hooks/APIUtils.java
Normal file
86
src/fr/neatmonster/nocheatplus/hooks/APIUtils.java
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package fr.neatmonster.nocheatplus.hooks;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MMP"""""""MM MM"""""""`YM M""M M""MMMMM""M dP oo dP
|
||||||
|
* M' .mmmm MM MM mmmmm M M M M MMMMM M 88 88
|
||||||
|
* M `M M' .M M M M MMMMM M d8888P dP 88 .d8888b.
|
||||||
|
* M MMMMM MM MM MMMMMMMM M M M MMMMM M 88 88 88 Y8ooooo.
|
||||||
|
* M MMMMM MM MM MMMMMMMM M M M `MMM' M 88 88 88 88
|
||||||
|
* M MMMMM MM MM MMMMMMMM M M Mb dM dP dP dP `88888P'
|
||||||
|
* MMMMMMMMMMMM MMMMMMMMMMMM MMMM MMMMMMMMMMM
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* A class providing utilities to the NoCheatPlus API.
|
||||||
|
*
|
||||||
|
* @author asofold
|
||||||
|
*/
|
||||||
|
public class APIUtils {
|
||||||
|
|
||||||
|
/** Only the children. */
|
||||||
|
private static final Map<CheckType, CheckType[]> childrenMap = new HashMap<CheckType, CheckType[]>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
final Map<CheckType, Set<CheckType>> map = new HashMap<CheckType, Set<CheckType>>();
|
||||||
|
for (final CheckType type : CheckType.values())
|
||||||
|
map.put(type, new HashSet<CheckType>());
|
||||||
|
for (final CheckType type : CheckType.values())
|
||||||
|
for (final CheckType other : CheckType.values())
|
||||||
|
if (isParent(other, type))
|
||||||
|
map.get(other).add(type);
|
||||||
|
for (final CheckType parent : map.keySet())
|
||||||
|
childrenMap.put(parent, map.get(parent).toArray(new CheckType[] {}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an unmodifiable collection of children for the given check type. Always returns a collection, does not
|
||||||
|
* contain check type itself.
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* the check type
|
||||||
|
* @return the children
|
||||||
|
*/
|
||||||
|
public static final Collection<CheckType> getChildren(final CheckType type) {
|
||||||
|
return Arrays.asList(childrenMap.get(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the supposed parent is ancestor of the supposed child. Does not check versus the supposed child
|
||||||
|
* directly.
|
||||||
|
*
|
||||||
|
* @param supposedParent
|
||||||
|
* the supposed parent
|
||||||
|
* @param supposedChild
|
||||||
|
* the supposed child
|
||||||
|
* @return true, if is parent
|
||||||
|
*/
|
||||||
|
public static final boolean isParent(final CheckType supposedParent, final CheckType supposedChild) {
|
||||||
|
CheckType parent = supposedChild.getParent();
|
||||||
|
while (parent != null)
|
||||||
|
if (parent == supposedParent)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
parent = parent.getParent();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return if the check type requires synchronization.
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* the check type
|
||||||
|
* @return true, if successful
|
||||||
|
*/
|
||||||
|
public static final boolean needsSynchronization(final CheckType type) {
|
||||||
|
return type == CheckType.CHAT || isParent(CheckType.CHAT, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -15,212 +15,244 @@ import org.bukkit.event.player.PlayerQuitEvent;
|
|||||||
|
|
||||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M"""""""`YM MM'""""'YMM MM"""""""`YM MM""""""""`M dP oo
|
||||||
|
* M mmmm. M M' .mmm. `M MM mmmmm M MM mmmmmmmM 88
|
||||||
|
* M MMMMM M M MMMMMooM M' .M M` MMMM dP. .dP .d8888b. 88d8b.d8b. 88d888b. d8888P dP .d8888b. 88d888b.
|
||||||
|
* M MMMMM M M MMMMMMMM MM MMMMMMMM MM MMMMMMMM `8bd8' 88ooood8 88'`88'`88 88' `88 88 88 88' `88 88' `88
|
||||||
|
* M MMMMM M M. `MMM' .M MM MMMMMMMM MM MMMMMMMM .d88b. 88. ... 88 88 88 88. .88 88 88 88. .88 88 88
|
||||||
|
* M MMMMM M MM. .dM MM MMMMMMMM MM .M dP' `dP `88888P' dP dP dP 88Y888P' dP dP `88888P' dP dP
|
||||||
|
* MMMMMMMMMMM MMMMMMMMMMM MMMMMMMMMMMM MMMMMMMMMMMM 88
|
||||||
|
* dP
|
||||||
|
* M"""""`'"""`YM
|
||||||
|
* M mm. mm. M
|
||||||
|
* M MMM MMM M .d8888b. 88d888b. .d8888b. .d8888b. .d8888b. 88d888b.
|
||||||
|
* M MMM MMM M 88' `88 88' `88 88' `88 88' `88 88ooood8 88' `88
|
||||||
|
* M MMM MMM M 88. .88 88 88 88. .88 88. .88 88. ... 88
|
||||||
|
* M MMM MMM M `88888P8 dP dP `88888P8 `8888P88 `88888P' dP
|
||||||
|
* MMMMMMMMMMMMMM .88
|
||||||
|
* d8888P
|
||||||
|
*/
|
||||||
/**
|
/**
|
||||||
* API for exempting players of checks, checked before calculations are done.
|
* API for exempting players of checks, checked before calculations are done.
|
||||||
*
|
*
|
||||||
* @author mc_dev
|
* @author asofold
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class NCPExemptionManager {
|
public class NCPExemptionManager {
|
||||||
|
|
||||||
/**
|
/** A map associating a check type with the entity ids of its exempted players. */
|
||||||
* CheckType -> Entity id -> Exemption info.
|
private static final Map<CheckType, Set<Integer>> exempted = new HashMap<CheckType, Set<Integer>>();
|
||||||
*
|
|
||||||
* TODO: opt: move these to checks individually for even faster access.
|
|
||||||
*/
|
|
||||||
private static final Map<CheckType, Set<Integer>> exempted = new HashMap<CheckType, Set<Integer>>();
|
|
||||||
|
|
||||||
/**
|
/** A map associating the registred player with their entity id. */
|
||||||
* Registered players (exact name) -> entity id (last time registered).
|
private static final Map<String, Integer> registeredPlayers = new HashMap<String, Integer>();
|
||||||
*/
|
|
||||||
private static final Map<String, Integer> registeredPlayers = new HashMap<String, Integer>();
|
|
||||||
|
|
||||||
static{
|
static {
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a player is exempted from a check right now.
|
* Remove all exemptions.
|
||||||
*
|
*/
|
||||||
* @param player
|
public static final void clear() {
|
||||||
* The player to exempt from checks.
|
registeredPlayers.clear();
|
||||||
* @param checkType
|
// Use put with a new map to keep entries to stay thread safe.
|
||||||
* The type of check to exempt the player from. This can be individual check types, as well as a check group like MOVING or ALL.
|
for (final CheckType type : CheckType.values())
|
||||||
* @return
|
if (APIUtils.needsSynchronization(type))
|
||||||
* If the player is exempted from the check right now.
|
exempted.put(type, Collections.synchronizedSet(new HashSet<Integer>()));
|
||||||
*/
|
else
|
||||||
public static final boolean isExempted(final Player player, final CheckType checkType){
|
exempted.put(type, new HashSet<Integer>());
|
||||||
return isExempted(player.getEntityId(), checkType);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if an entity is exempted from a check by entity id right now.
|
* Exempt an entity from all checks permanently.
|
||||||
* <hr>
|
*
|
||||||
* This might help exempting NPCs from checks for all time, making performance a lot better. A future purpose might be to exempt vehicles and similar (including passengers) from checks.
|
* @param entityId
|
||||||
* @param id
|
* the entity id
|
||||||
* Entity id to exempt from checks.
|
*/
|
||||||
* @param checkType
|
public static final void exemptPermanently(final int entityId) {
|
||||||
* The type of check to exempt the player from. This can be individual check types, as well as a check group like MOVING or ALL.
|
exemptPermanently(entityId, CheckType.ALL);
|
||||||
* @return
|
}
|
||||||
* If the entity is exempted from checks right now.
|
|
||||||
*/
|
|
||||||
public static final boolean isExempted(final int id, final CheckType checkType){
|
|
||||||
return exempted.get(checkType).contains(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all exemptions.
|
* Exempt an entity from the given check or check group permanently (only until restart).
|
||||||
*/
|
*
|
||||||
public static final void clear(){
|
* @param entityId
|
||||||
registeredPlayers.clear();
|
* the entity id
|
||||||
// Use put with a new map to keep entries to stay thread safe.
|
* @param checkType
|
||||||
for (final CheckType checkType : CheckType.values()){
|
* the check type
|
||||||
if (APIUtil.needsSynchronization(checkType))
|
*/
|
||||||
exempted.put(checkType, Collections.synchronizedSet(new HashSet<Integer>(10)));
|
public static final void exemptPermanently(final int entityId, final CheckType checkType) {
|
||||||
else
|
final Integer id = entityId;
|
||||||
exempted.put(checkType, new HashSet<Integer>(10));
|
exempted.get(checkType).add(id);
|
||||||
}
|
for (final CheckType child : APIUtils.getChildren(checkType))
|
||||||
|
exempted.get(child).add(id);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* Exempt a player form all checks permanently.
|
||||||
|
*
|
||||||
|
* @param player
|
||||||
|
* the player
|
||||||
|
*/
|
||||||
|
public static final void exemptPermanently(final Player player) {
|
||||||
|
exemptPermanently(player, CheckType.ALL);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This should be registered before all other listeners of NCP (!).
|
* Exempt a player from a check or check group permanently.
|
||||||
*
|
*
|
||||||
* NOTE: For internal use only, DO NOT CALL FROM OUTSIDE.
|
* @param player
|
||||||
* @return
|
* the player
|
||||||
*/
|
* @param type
|
||||||
public static Listener getListener(){
|
* the check type
|
||||||
return new Listener() {
|
*/
|
||||||
@SuppressWarnings("unused")
|
public static final void exemptPermanently(final Player player, final CheckType type) {
|
||||||
@EventHandler(priority=EventPriority.LOWEST)
|
exemptPermanently(player.getEntityId(), type);
|
||||||
final void onJoin(final PlayerJoinEvent event){
|
}
|
||||||
NCPExemptionManager.registerPlayer(event.getPlayer());
|
|
||||||
}
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
@EventHandler(priority=EventPriority.MONITOR)
|
|
||||||
final void onJoin(final PlayerQuitEvent event){
|
|
||||||
NCPExemptionManager.checkRemovePlayer(event.getPlayer());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the registeredPlayers mapping can be removed for a player, i.e. no exemptions are present.
|
* This should be registered before all other listeners of NoCheatPlus.
|
||||||
* @param player
|
*
|
||||||
*/
|
* NOTE: For internal use only, DO NOT CALL FROM OUTSIDE.
|
||||||
protected static final void checkRemovePlayer(final Player player) {
|
*
|
||||||
if (!registeredPlayers.containsKey(player.getName())) return;
|
* @return the listener
|
||||||
final Integer id = player.getEntityId();
|
*/
|
||||||
for (final CheckType checkType : CheckType.values()){
|
public static Listener getListener() {
|
||||||
// Check if player is exempted from something.
|
return new Listener() {
|
||||||
if (isExempted(id, checkType)) return;
|
@SuppressWarnings("unused")
|
||||||
}
|
@EventHandler(
|
||||||
// No return = remove player.
|
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||||
registeredPlayers.remove(player.getName());
|
public void onPlayerJoin(final PlayerJoinEvent event) {
|
||||||
}
|
NCPExemptionManager.registerPlayer(event.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
@SuppressWarnings("unused")
|
||||||
* Register current entity id for the player.
|
@EventHandler(
|
||||||
* @param player
|
ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||||
*/
|
public void onPlayerQuit(final PlayerQuitEvent event) {
|
||||||
public static final void registerPlayer(final Player player) {
|
NCPExemptionManager.tryToRemove(event.getPlayer());
|
||||||
final int newId = player.getEntityId();
|
}
|
||||||
final String name = player.getName();
|
};
|
||||||
|
}
|
||||||
|
|
||||||
final Integer registeredId = registeredPlayers.get(name);
|
/**
|
||||||
if (registeredId == null){
|
* Check if an entity is exempted from a check right now.
|
||||||
// Was not registered.
|
* <hr>
|
||||||
registeredPlayers.put(name, newId);
|
* This might help exempting NPCs from checks for all time, making performance a lot better. A future purpose might
|
||||||
}
|
* be to exempt vehicles and similar (including passengers) from checks.
|
||||||
else if (newId == registeredId.intValue()){
|
*
|
||||||
// No change.
|
* @param entityId
|
||||||
}
|
* the entity id to exempt from checks
|
||||||
else {
|
* @param type
|
||||||
// Player was registered under another id (needs exchange).
|
* the type of check to exempt the player from. This can be individual check types, as well as a check
|
||||||
for (final Set<Integer> set : exempted.values()){
|
* group like MOVING or ALL
|
||||||
if (set.remove(registeredId)){
|
* @return if the entity is exempted from checks right now
|
||||||
// replace.
|
*/
|
||||||
set.add(newId);
|
public static final boolean isExempted(final int entityId, final CheckType type) {
|
||||||
}
|
return exempted.get(type).contains(entityId);
|
||||||
}
|
}
|
||||||
registeredPlayers.put(name, newId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all exempting a player.
|
* Check if a player is exempted from a check right now.
|
||||||
* @param player
|
*
|
||||||
*/
|
* @param player
|
||||||
public static final void unExempt(final Player player){
|
* the player to exempt from checks
|
||||||
unExempt(player, CheckType.ALL);
|
* @param type
|
||||||
}
|
* the type of check to exempt the player from. This can be individual check types, as well as a check
|
||||||
|
* group like MOVING or ALL
|
||||||
|
* @return if the player is exempted from the check right now
|
||||||
|
*/
|
||||||
|
public static final boolean isExempted(final Player player, final CheckType type) {
|
||||||
|
return isExempted(player.getEntityId(), type);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Undo exempting a player form a certain check, or check group, as given.
|
* Register current entity id for the player.
|
||||||
* @param player
|
*
|
||||||
* @param checkType
|
* @param player
|
||||||
*/
|
* the player
|
||||||
public static final void unExempt(final Player player, final CheckType checkType){
|
*/
|
||||||
unExempt(player.getEntityId(), checkType);
|
public static final void registerPlayer(final Player player) {
|
||||||
}
|
final int entityId = player.getEntityId();
|
||||||
|
final String name = player.getName();
|
||||||
|
|
||||||
/**
|
final Integer registeredId = registeredPlayers.get(name);
|
||||||
* Undo exempting an entity by entity id from all checks.
|
if (registeredId == null)
|
||||||
* @param entityId
|
// Player wasn't registered.
|
||||||
*/
|
registeredPlayers.put(name, entityId);
|
||||||
public static final void unExempt(final int entityId){
|
else if (entityId != registeredId.intValue()) {
|
||||||
unExempt(entityId, CheckType.ALL);
|
// Player was registered under another id (needs exchange).
|
||||||
}
|
for (final Set<Integer> set : exempted.values())
|
||||||
|
if (set.remove(registeredId))
|
||||||
|
// Replace.
|
||||||
|
set.add(entityId);
|
||||||
|
registeredPlayers.put(name, entityId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Undo exempting an entity by entity id from a certain check type, also check groups, etc.
|
* Check if the registeredPlayers mapping can be removed for a player, i.e. no exemptions are present.
|
||||||
* @param entityId
|
*
|
||||||
* @param checkType
|
* @param player
|
||||||
*/
|
* the player
|
||||||
public static final void unExempt(final int entityId, final CheckType checkType){
|
*/
|
||||||
final Integer id = entityId;
|
protected static final void tryToRemove(final Player player) {
|
||||||
exempted.get(checkType).remove(id);
|
if (!registeredPlayers.containsKey(player.getName()))
|
||||||
for (final CheckType child : APIUtil.getChildren(checkType)){
|
return;
|
||||||
exempted.get(child).remove(id);
|
final Integer entityId = player.getEntityId();
|
||||||
}
|
for (final CheckType type : CheckType.values())
|
||||||
}
|
// Check if player is exempted from something.
|
||||||
|
if (isExempted(entityId, type))
|
||||||
|
// If he is, we can't remove him so we return.
|
||||||
|
return;
|
||||||
|
registeredPlayers.remove(player.getName());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exempt a player form all checks.
|
* Undo exempting an entity from all checks.
|
||||||
* @param player
|
*
|
||||||
*/
|
* @param entityId
|
||||||
public static final void exemptPermanently(final Player player){
|
* the entity id
|
||||||
exemptPermanently(player, CheckType.ALL);
|
*/
|
||||||
}
|
public static final void unexempt(final int entityId) {
|
||||||
|
unexempt(entityId, CheckType.ALL);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exempt a player from a check or check group permanently.
|
* Undo exempting an entity from a certain check, or check group, as given.
|
||||||
* @param player
|
*
|
||||||
* @param checkType
|
* @param entityId
|
||||||
*/
|
* the entity id
|
||||||
public static final void exemptPermanently(final Player player, final CheckType checkType){
|
* @param type
|
||||||
exemptPermanently(player.getEntityId(), checkType);
|
* the check type
|
||||||
}
|
*/
|
||||||
|
public static final void unexempt(final int entityId, final CheckType type) {
|
||||||
|
final Integer id = entityId;
|
||||||
|
exempted.get(type).remove(id);
|
||||||
|
for (final CheckType child : APIUtils.getChildren(type))
|
||||||
|
exempted.get(child).remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* exempt an entity from all checks, by entity id.
|
* Undo exempting a player from all checks.
|
||||||
* @param entityId
|
*
|
||||||
*/
|
* @param player
|
||||||
public static final void exemptPermanently(final int entityId){
|
* the player
|
||||||
exemptPermanently(entityId, CheckType.ALL);
|
*/
|
||||||
}
|
public static final void unexempt(final Player player) {
|
||||||
|
unexempt(player, CheckType.ALL);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exempt an entity by entity id from the given check or check group permanently (only until restart).
|
* Undo exempting a player form a certain check, or check group, as given.
|
||||||
* @param entityId
|
*
|
||||||
* @param checkType
|
* @param player
|
||||||
*/
|
* the player
|
||||||
public static final void exemptPermanently(final int entityId, final CheckType checkType){
|
* @param checkType
|
||||||
final Integer id = entityId;
|
* the check type
|
||||||
exempted.get(checkType).add(id);
|
*/
|
||||||
for (final CheckType child : APIUtil.getChildren(checkType)){
|
public static final void unexempt(final Player player, final CheckType checkType) {
|
||||||
exempted.get(child).add(id);
|
unexempt(player.getEntityId(), checkType);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,112 +36,45 @@ import org.bukkit.entity.Player;
|
|||||||
*/
|
*/
|
||||||
public class PlayerLocation {
|
public class PlayerLocation {
|
||||||
|
|
||||||
/**
|
private static final Material[] STAIRS = new Material[] {Material.WOOD_STAIRS, Material.COBBLESTONE_STAIRS,
|
||||||
* Another utility class used to manipulate differently booleans.
|
|
||||||
*/
|
|
||||||
private class CustomBoolean {
|
|
||||||
|
|
||||||
/** Is the boolean set? */
|
|
||||||
private boolean isSet = false;
|
|
||||||
|
|
||||||
/** What is its value? */
|
|
||||||
private boolean value = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the boolean.
|
|
||||||
*
|
|
||||||
* @return the value
|
|
||||||
*/
|
|
||||||
public boolean get() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the boolean is set.
|
|
||||||
*
|
|
||||||
* @return true, if the boolean is set
|
|
||||||
*/
|
|
||||||
public boolean isSet() {
|
|
||||||
return isSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the boolean.
|
|
||||||
*
|
|
||||||
* @param value
|
|
||||||
* the value
|
|
||||||
*/
|
|
||||||
public void set(final boolean value) {
|
|
||||||
this.value = value;
|
|
||||||
isSet = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Material[] STAIRS = new Material[] {Material.WOOD_STAIRS, Material.COBBLESTONE_STAIRS,
|
|
||||||
Material.BRICK_STAIRS, Material.SMOOTH_STAIRS, Material.NETHER_BRICK_STAIRS, Material.SANDSTONE_STAIRS,
|
Material.BRICK_STAIRS, Material.SMOOTH_STAIRS, Material.NETHER_BRICK_STAIRS, Material.SANDSTONE_STAIRS,
|
||||||
Material.SPRUCE_WOOD_STAIRS, Material.BIRCH_WOOD_STAIRS, Material.JUNGLE_WOOD_STAIRS};
|
Material.SPRUCE_WOOD_STAIRS, Material.BIRCH_WOOD_STAIRS, Material.JUNGLE_WOOD_STAIRS};
|
||||||
|
|
||||||
/** The original location. */
|
/** The original location. */
|
||||||
private final Location location;
|
private Location location;
|
||||||
|
|
||||||
/** Is the player above stairs? */
|
/** Is the player above stairs? */
|
||||||
private final CustomBoolean aboveStairs = new CustomBoolean();
|
private Boolean aboveStairs;
|
||||||
|
|
||||||
/** Is the player in lava? */
|
/** Is the player in lava? */
|
||||||
private final CustomBoolean inLava = new CustomBoolean();
|
private Boolean inLava;
|
||||||
|
|
||||||
/** Is the player in water? */
|
/** Is the player in water? */
|
||||||
private final CustomBoolean inWater = new CustomBoolean();
|
private Boolean inWater;
|
||||||
|
|
||||||
/** Is the player is web? */
|
/** Is the player is web? */
|
||||||
private final CustomBoolean inWeb = new CustomBoolean();
|
private Boolean inWeb;
|
||||||
|
|
||||||
/** Is the player on the ground? */
|
/** Is the player on the ground? */
|
||||||
private final CustomBoolean onGround = new CustomBoolean();
|
private Boolean onGround;
|
||||||
|
|
||||||
/** Is the player on ice? */
|
/** Is the player on ice? */
|
||||||
private final CustomBoolean onIce = new CustomBoolean();
|
private Boolean onIce;
|
||||||
|
|
||||||
/** Is the player on ladder? */
|
/** Is the player on ladder? */
|
||||||
private final CustomBoolean onLadder = new CustomBoolean();
|
private Boolean onLadder;
|
||||||
|
|
||||||
/** Is the player on ladder (ignoring unclimbable vines)? **/
|
|
||||||
private final CustomBoolean onLadderBis = new CustomBoolean();
|
|
||||||
|
|
||||||
/** Is the player on soul sand? */
|
|
||||||
private final CustomBoolean onSoulSand = new CustomBoolean();
|
|
||||||
|
|
||||||
/** The bounding box of the player. */
|
/** The bounding box of the player. */
|
||||||
private final AxisAlignedBB boundingBox;
|
private AxisAlignedBB boundingBox;
|
||||||
|
|
||||||
/** The entity player. */
|
/** The entity player. */
|
||||||
private final EntityPlayer entity;
|
private EntityPlayer entity;
|
||||||
|
|
||||||
/** The x, y and z coordinates. */
|
/** The x, y and z coordinates. */
|
||||||
private final int x, y, z;
|
private int x, y, z;
|
||||||
|
|
||||||
/** The world. */
|
/** The world. */
|
||||||
private final WorldServer world;
|
private WorldServer world;
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiates a new player location.
|
|
||||||
*
|
|
||||||
* @param location
|
|
||||||
* the location
|
|
||||||
* @param player
|
|
||||||
* the player
|
|
||||||
*/
|
|
||||||
public PlayerLocation(final Location location, final Player player) {
|
|
||||||
this.location = location;
|
|
||||||
|
|
||||||
entity = ((CraftPlayer) player).getHandle();
|
|
||||||
boundingBox = entity.boundingBox.clone().d(location.getX() - entity.locX, location.getY() - entity.locY,
|
|
||||||
location.getZ() - entity.locZ);
|
|
||||||
x = (int) Math.floor(location.getX());
|
|
||||||
y = (int) Math.floor(boundingBox.b);
|
|
||||||
z = (int) Math.floor(location.getZ());
|
|
||||||
world = ((CraftWorld) location.getWorld()).getHandle();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the location.
|
* Gets the location.
|
||||||
@ -203,9 +136,9 @@ public class PlayerLocation {
|
|||||||
* @return true, if the player above on stairs
|
* @return true, if the player above on stairs
|
||||||
*/
|
*/
|
||||||
public boolean isAboveStairs() {
|
public boolean isAboveStairs() {
|
||||||
if (!aboveStairs.isSet())
|
if (aboveStairs == null)
|
||||||
aboveStairs.set(Arrays.asList(STAIRS).contains(Material.getMaterial(world.getTypeId(x, y - 1, z))));
|
aboveStairs = Arrays.asList(STAIRS).contains(Material.getMaterial(world.getTypeId(x, y - 1, z)));
|
||||||
return aboveStairs.get();
|
return aboveStairs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -214,12 +147,12 @@ public class PlayerLocation {
|
|||||||
* @return true, if the player is in lava
|
* @return true, if the player is in lava
|
||||||
*/
|
*/
|
||||||
public boolean isInLava() {
|
public boolean isInLava() {
|
||||||
if (!inLava.isSet()) {
|
if (inLava == null) {
|
||||||
AxisAlignedBB boundingBoxLava = boundingBox.clone();
|
AxisAlignedBB boundingBoxLava = boundingBox.clone();
|
||||||
boundingBoxLava = boundingBoxLava.grow(-0.10000000149011612D, -0.40000000596046448D, -0.10000000149011612D);
|
boundingBoxLava = boundingBoxLava.grow(-0.10000000149011612D, -0.40000000596046448D, -0.10000000149011612D);
|
||||||
inLava.set(world.a(boundingBoxLava, net.minecraft.server.Material.LAVA));
|
inLava = world.a(boundingBoxLava, net.minecraft.server.Material.LAVA);
|
||||||
}
|
}
|
||||||
return inLava.get();
|
return inLava;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -237,13 +170,13 @@ public class PlayerLocation {
|
|||||||
* @return true, if the player is in water
|
* @return true, if the player is in water
|
||||||
*/
|
*/
|
||||||
public boolean isInWater() {
|
public boolean isInWater() {
|
||||||
if (!inWater.isSet()) {
|
if (inWater == null) {
|
||||||
AxisAlignedBB boundingBoxWater = boundingBox.clone();
|
AxisAlignedBB boundingBoxWater = boundingBox.clone();
|
||||||
boundingBoxWater = boundingBoxWater.grow(0.0D, -0.40000000596046448D, 0.0D);
|
boundingBoxWater = boundingBoxWater.grow(0.0D, -0.40000000596046448D, 0.0D);
|
||||||
boundingBoxWater = boundingBoxWater.shrink(0.001D, 0.001D, 0.001D);
|
boundingBoxWater = boundingBoxWater.shrink(0.001D, 0.001D, 0.001D);
|
||||||
inWater.set(world.a(boundingBoxWater, net.minecraft.server.Material.WATER, entity));
|
inWater = world.a(boundingBoxWater, net.minecraft.server.Material.WATER, entity);
|
||||||
}
|
}
|
||||||
return inWater.get();
|
return inWater;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -252,19 +185,19 @@ public class PlayerLocation {
|
|||||||
* @return true, if the player is in web
|
* @return true, if the player is in web
|
||||||
*/
|
*/
|
||||||
public boolean isInWeb() {
|
public boolean isInWeb() {
|
||||||
if (!inWeb.isSet()) {
|
if (inWeb == null) {
|
||||||
for (int blockX = (int) Math.floor(boundingBox.a + 0.001D); blockX <= (int) Math
|
for (int blockX = (int) Math.floor(boundingBox.a + 0.001D); blockX <= (int) Math
|
||||||
.floor(boundingBox.d - 0.001D); blockX++)
|
.floor(boundingBox.d - 0.001D); blockX++)
|
||||||
for (int blockY = (int) Math.floor(boundingBox.b + 0.001D); blockY <= (int) Math
|
for (int blockY = (int) Math.floor(boundingBox.b + 0.001D); blockY <= (int) Math
|
||||||
.floor(boundingBox.e - 0.001D); blockY++)
|
.floor(boundingBox.e - 0.001D); blockY++)
|
||||||
for (int blockZ = (int) Math.floor(boundingBox.c + 0.001D); blockZ <= (int) Math
|
for (int blockZ = (int) Math.floor(boundingBox.c + 0.001D); blockZ <= (int) Math
|
||||||
.floor(boundingBox.f - 0.001D); blockZ++)
|
.floor(boundingBox.f - 0.001D); blockZ++)
|
||||||
if (!inWeb.get() && world.getTypeId(blockX, blockY, blockZ) == Block.WEB.id)
|
if (world.getTypeId(blockX, blockY, blockZ) == Block.WEB.id)
|
||||||
inWeb.set(true);
|
inWeb = true;
|
||||||
if (!inWeb.isSet())
|
if (inWeb == null)
|
||||||
inWeb.set(false);
|
inWeb = false;
|
||||||
}
|
}
|
||||||
return inWeb.get();
|
return inWeb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -273,12 +206,12 @@ public class PlayerLocation {
|
|||||||
* @return true, if the player is on ground
|
* @return true, if the player is on ground
|
||||||
*/
|
*/
|
||||||
public boolean isOnGround() {
|
public boolean isOnGround() {
|
||||||
if (!onGround.isSet()) {
|
if (onGround == null) {
|
||||||
AxisAlignedBB boundingBoxGround = boundingBox.clone();
|
AxisAlignedBB boundingBoxGround = boundingBox.clone();
|
||||||
boundingBoxGround = boundingBoxGround.d(0D, -0.001D, 0D);
|
boundingBoxGround = boundingBoxGround.d(0D, -0.001D, 0D);
|
||||||
onGround.set(world.getCubes(entity, boundingBoxGround).size() > 0);
|
onGround = world.getCubes(entity, boundingBoxGround).size() > 0;
|
||||||
}
|
}
|
||||||
return onGround.get();
|
return onGround;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -287,12 +220,12 @@ public class PlayerLocation {
|
|||||||
* @return true, if the player is on ice
|
* @return true, if the player is on ice
|
||||||
*/
|
*/
|
||||||
public boolean isOnIce() {
|
public boolean isOnIce() {
|
||||||
if (!onIce.isSet())
|
if (onIce == null)
|
||||||
if (entity.getBukkitEntity().isSneaking() || entity.getBukkitEntity().isBlocking())
|
if (entity.getBukkitEntity().isSneaking() || entity.getBukkitEntity().isBlocking())
|
||||||
onIce.set(world.getTypeId(x, (int) Math.floor(boundingBox.b - 0.1D), z) == Block.ICE.id);
|
onIce = world.getTypeId(x, (int) Math.floor(boundingBox.b - 0.1D), z) == Block.ICE.id;
|
||||||
else
|
else
|
||||||
onIce.set(world.getTypeId(x, y - 1, z) == Block.ICE.id);
|
onIce = world.getTypeId(x, y - 1, z) == Block.ICE.id;
|
||||||
return onIce.get();
|
return onIce;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -301,71 +234,30 @@ public class PlayerLocation {
|
|||||||
* @return true, if the player is on a ladder
|
* @return true, if the player is on a ladder
|
||||||
*/
|
*/
|
||||||
public boolean isOnLadder() {
|
public boolean isOnLadder() {
|
||||||
return isOnLadder(false);
|
if (onLadder == null)
|
||||||
|
onLadder = world.getTypeId(x, y, z) == Block.LADDER.id || world.getTypeId(x, y, z) == Block.VINE.id;
|
||||||
|
return onLadder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the player is on a ladder.
|
* Sets the player location object.
|
||||||
*
|
*
|
||||||
* @param ignoreUnclimbableVines
|
* @param location
|
||||||
* ignore unclimbable vines or not?
|
* the location
|
||||||
* @return true, if the player is on a ladder
|
* @param player
|
||||||
|
* the player
|
||||||
*/
|
*/
|
||||||
public boolean isOnLadder(final boolean ignoreUnclimbableVines) {
|
public void set(final Location location, final Player player) {
|
||||||
if (ignoreUnclimbableVines) {
|
this.location = location;
|
||||||
if (!onLadderBis.isSet())
|
|
||||||
if (world.getTypeId(x, y, z) == Block.LADDER.id)
|
|
||||||
onLadderBis.set(true);
|
|
||||||
else if (world.getTypeId(x, y, z) == Block.VINE.id) {
|
|
||||||
final int data = world.getData(x, y, z);
|
|
||||||
if ((data & 1) != 0) {
|
|
||||||
final int id = world.getTypeId(x, y, z + 1);
|
|
||||||
if (id != 0 && Block.byId[id].c() && Block.byId[id].material.isSolid())
|
|
||||||
onLadderBis.set(true);
|
|
||||||
}
|
|
||||||
if (!onLadder.isSet() && (data & 2) != 0) {
|
|
||||||
final int id = world.getTypeId(x - 1, y, z);
|
|
||||||
if (id != 0 && Block.byId[id].c() && Block.byId[id].material.isSolid())
|
|
||||||
onLadderBis.set(true);
|
|
||||||
}
|
|
||||||
if (!onLadder.isSet() && (data & 4) != 0) {
|
|
||||||
final int id = world.getTypeId(x, y, z - 1);
|
|
||||||
if (id != 0 && Block.byId[id].c() && Block.byId[id].material.isSolid())
|
|
||||||
onLadderBis.set(true);
|
|
||||||
}
|
|
||||||
if (!onLadder.isSet() && (data & 8) != 0) {
|
|
||||||
final int id = world.getTypeId(x + 1, y, z);
|
|
||||||
if (id != 0 && Block.byId[id].c() && Block.byId[id].material.isSolid())
|
|
||||||
onLadderBis.set(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return onLadderBis.get();
|
|
||||||
}
|
|
||||||
if (!onLadder.isSet())
|
|
||||||
onLadder.set(world.getTypeId(x, y, z) == Block.LADDER.id || world.getTypeId(x, y, z) == Block.VINE.id);
|
|
||||||
return onLadder.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
entity = ((CraftPlayer) player).getHandle();
|
||||||
* Checks if the player is on soul sand.
|
boundingBox = entity.boundingBox.clone().d(location.getX() - entity.locX, location.getY() - entity.locY,
|
||||||
*
|
location.getZ() - entity.locZ);
|
||||||
* @return true, if the player is on soul sand
|
x = (int) Math.floor(location.getX());
|
||||||
*/
|
y = (int) Math.floor(boundingBox.b);
|
||||||
public boolean isOnSoulSand() {
|
z = (int) Math.floor(location.getZ());
|
||||||
if (!onSoulSand.isSet()) {
|
world = ((CraftWorld) location.getWorld()).getHandle();
|
||||||
AxisAlignedBB boundingBoxGround = boundingBox.clone();
|
|
||||||
boundingBoxGround = boundingBoxGround.d(0D, -0.001D, 0D);
|
aboveStairs = inLava = inWater = inWeb = onGround = onIce = onLadder = null;
|
||||||
for (final Object object : world.getCubes(entity, boundingBoxGround)) {
|
|
||||||
final AxisAlignedBB aabbCube = (AxisAlignedBB) object;
|
|
||||||
final int blockX = (int) Math.floor(aabbCube.a);
|
|
||||||
final int blockY = (int) Math.floor(aabbCube.b);
|
|
||||||
final int blockZ = (int) Math.floor(aabbCube.c);
|
|
||||||
if (!onSoulSand.get() && world.getTypeId(blockX, blockY, blockZ) == Block.SOUL_SAND.id)
|
|
||||||
onSoulSand.set(true);
|
|
||||||
}
|
|
||||||
if (!onSoulSand.isSet())
|
|
||||||
onSoulSand.set(false);
|
|
||||||
}
|
|
||||||
return onSoulSand.get();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user