[Development] Some more issues fixed.

This commit is contained in:
NeatMonster 2012-08-08 18:21:06 +02:00
parent 58f4f838f9
commit 284eec9fc2
14 changed files with 180 additions and 194 deletions

View File

@ -1,10 +1,13 @@
package fr.neatmonster.nocheatplus; package fr.neatmonster.nocheatplus;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import fr.neatmonster.nocheatplus.checks.blockbreak.BlockBreakConfig; import fr.neatmonster.nocheatplus.checks.blockbreak.BlockBreakConfig;
import fr.neatmonster.nocheatplus.checks.blockinteract.BlockInteractConfig; import fr.neatmonster.nocheatplus.checks.blockinteract.BlockInteractConfig;
@ -38,6 +41,34 @@ import fr.neatmonster.nocheatplus.players.Permissions;
* This the class handling all the commands. * This the class handling all the commands.
*/ */
public class CommandHandler implements CommandExecutor { public class CommandHandler implements CommandExecutor {
/**
* The event triggered when NoCheatPlus configuration is reloaded.
*/
public static class NCPReloadEvent extends Event {
/** The handlers list. */
private static final HandlerList handlers = new HandlerList();
/**
* Gets the handler list.
*
* @return the handler list
*/
public static HandlerList getHandlerList() {
return handlers;
}
/* (non-Javadoc)
* @see org.bukkit.event.Event#getHandlers()
*/
@Override
public HandlerList getHandlers() {
return handlers;
}
}
/** The plugin. */
private final NoCheatPlus plugin; private final NoCheatPlus plugin;
/** /**
@ -73,6 +104,9 @@ public class CommandHandler implements CommandExecutor {
InventoryConfig.clear(); InventoryConfig.clear();
MovingConfig.clear(); MovingConfig.clear();
// Say to the other plugins that we've reloaded the configuration.
Bukkit.getPluginManager().callEvent(new NCPReloadEvent());
sender.sendMessage(ChatColor.RED + "NCP: " + ChatColor.WHITE + "Configuration reloaded!"); sender.sendMessage(ChatColor.RED + "NCP: " + ChatColor.WHITE + "Configuration reloaded!");
} else } else
sender.sendMessage(ChatColor.RED + "You lack the " + Permissions.ADMINISTRATION_RELOAD sender.sendMessage(ChatColor.RED + "You lack the " + Permissions.ADMINISTRATION_RELOAD

View File

@ -50,7 +50,6 @@ public enum CheckType {
BLOCKPLACE_SPEED(BLOCKPLACE, "speed", Permissions.BLOCKPLACE_SPEED), BLOCKPLACE_SPEED(BLOCKPLACE, "speed", Permissions.BLOCKPLACE_SPEED),
CHAT(ChatConfig.class, ChatData.class), CHAT(ChatConfig.class, ChatData.class),
CHAT_ARRIVALS(CHAT, "arrivals", Permissions.CHAT_ARRIVALS),
CHAT_COLOR(CHAT, "color", Permissions.CHAT_COLOR), CHAT_COLOR(CHAT, "color", Permissions.CHAT_COLOR),
CHAT_NOPWNAGE(CHAT, "noPwnage", Permissions.CHAT_NOPWNAGE), CHAT_NOPWNAGE(CHAT, "noPwnage", Permissions.CHAT_NOPWNAGE),

View File

@ -1,73 +0,0 @@
package fr.neatmonster.nocheatplus.checks.chat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.NoCheatPlus;
import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType;
/*
* MMP"""""""MM oo dP
* M' .mmmm MM 88
* M `M 88d888b. 88d888b. dP dP .dP .d8888b. 88 .d8888b.
* M MMMMM MM 88' `88 88' `88 88 88 d8' 88' `88 88 Y8ooooo.
* M MMMMM MM 88 88 88 88 .88' 88. .88 88 88
* M MMMMM MM dP dP dP 8888P' `88888P8 dP `88888P'
* MMMMMMMMMMMM
*/
/**
* The Arrivals check is used to limit the number of new players allowed to join in a specified time frame.
*/
public class Arrivals extends Check {
/** The map containing the time and the name of the player, every time that one of them joins. */
private final Map<Long, String> joins = new HashMap<Long, String>();
/**
* Instantiates a new arrivals check.
*/
public Arrivals() {
super(CheckType.CHAT_ARRIVALS);
}
/**
* Checks a player.
*
* @param player
* the player
* @return true, if successful
*/
public boolean check(final Player player) {
final ChatConfig cc = ChatConfig.getConfig(player);
// If the server has just restarted or if the player is a regular one, do not check it.
if (System.currentTimeMillis() - NoCheatPlus.time < 120000L
|| System.currentTimeMillis() - player.getFirstPlayed() > cc.arrivalsJoinsLimit)
return false;
boolean cancel = false;
// Remove the old data from the map holding the joins.
final List<Long> toRemove = new ArrayList<Long>();
for (final long time : joins.keySet())
// If the data is too old or belong to the checked player.
if (System.currentTimeMillis() - time > cc.arrivalsTimeLimit && joins.get(time).equals(player.getName()))
toRemove.add(time);
for (final long time : toRemove)
joins.remove(time);
// Add the new data.
joins.put(System.currentTimeMillis(), player.getName());
if (joins.size() > cc.arrivalsJoinsLimit)
// Find out if we should cancel the event or not.
cancel = executeActions(player);
return cancel;
}
}

View File

@ -51,12 +51,6 @@ public class ChatConfig {
return worldsMap.get(player.getWorld().getName()); return worldsMap.get(player.getWorld().getName());
} }
public final boolean arrivalsCheck;
public final int arrivalsJoinsLimit;
public final String arrivalsMessage;
public final long arrivalsTimeLimit;
public final ActionList arrivalsActions;
public final boolean colorCheck; public final boolean colorCheck;
public final ActionList colorActions; public final ActionList colorActions;
@ -112,6 +106,8 @@ public class ChatConfig {
public final ActionList noPwnageActions; public final ActionList noPwnageActions;
public final boolean opInConsoleOnly;
public final boolean protectPlugins; public final boolean protectPlugins;
/** /**
@ -121,12 +117,6 @@ public class ChatConfig {
* the data * the data
*/ */
public ChatConfig(final ConfigFile data) { public ChatConfig(final ConfigFile data) {
arrivalsCheck = data.getBoolean(ConfPaths.CHAT_ARRIVALS_CHECK);
arrivalsJoinsLimit = data.getInt(ConfPaths.CHAT_ARRIVALS_JOINSLIMIT);
arrivalsMessage = data.getString(ConfPaths.CHAT_ARRIVALS_MESSAGE);
arrivalsTimeLimit = data.getLong(ConfPaths.CHAT_ARRIVALS_TIMELIMIT);
arrivalsActions = data.getActionList(ConfPaths.CHAT_ARRIVALS_ACTIONS, Permissions.CHAT_ARRIVALS);
colorCheck = data.getBoolean(ConfPaths.CHAT_COLOR_CHECK); colorCheck = data.getBoolean(ConfPaths.CHAT_COLOR_CHECK);
colorActions = data.getActionList(ConfPaths.CHAT_COLOR_ACTIONS, Permissions.CHAT_COLOR); colorActions = data.getActionList(ConfPaths.CHAT_COLOR_ACTIONS, Permissions.CHAT_COLOR);
@ -182,6 +172,8 @@ public class ChatConfig {
noPwnageActions = data.getActionList(ConfPaths.CHAT_NOPWNAGE_ACTIONS, Permissions.CHAT_NOPWNAGE); noPwnageActions = data.getActionList(ConfPaths.CHAT_NOPWNAGE_ACTIONS, Permissions.CHAT_NOPWNAGE);
opInConsoleOnly = data.getBoolean(ConfPaths.MISCELLANEOUS_OPINCONSOLEONLY);
protectPlugins = data.getBoolean(ConfPaths.MISCELLANEOUS_PROTECTPLUGINS); protectPlugins = data.getBoolean(ConfPaths.MISCELLANEOUS_PROTECTPLUGINS);
} }
} }

View File

@ -37,7 +37,6 @@ public class ChatData {
} }
// Violation levels. // Violation levels.
public double arrivalsVL;
public double colorVL; public double colorVL;
public double noPwnageVL; public double noPwnageVL;

View File

@ -26,7 +26,6 @@ import fr.neatmonster.nocheatplus.players.Permissions;
* Central location to listen to events that are relevant for the chat checks. * Central location to listen to events that are relevant for the chat checks.
*/ */
public class ChatListener implements Listener { public class ChatListener implements Listener {
private final Arrivals arrivals = new Arrivals();
private final Color color = new Color(); private final Color color = new Color();
private final NoPwnage noPwnage = new NoPwnage(); private final NoPwnage noPwnage = new NoPwnage();
@ -95,6 +94,14 @@ public class ChatListener implements Listener {
return; return;
} }
// Prevent /op and /deop commands from being used in chat.
if (ChatConfig.getConfig(player).opInConsoleOnly && (command.equals("op") || command.equals("deop"))) {
event.getPlayer().sendMessage(
ChatColor.RED + "I'm sorry, but this command can't be executed in chat. Use the console instead!");
event.setCancelled(true);
return;
}
// First the color check. // First the color check.
if (color.isEnabled(player)) if (color.isEnabled(player))
event.setMessage(color.check(player, event.getMessage())); event.setMessage(color.check(player, event.getMessage()));
@ -124,13 +131,8 @@ public class ChatListener implements Listener {
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final ChatConfig cc = ChatConfig.getConfig(player); final ChatConfig cc = ChatConfig.getConfig(player);
// First the arrivals check, if enabled of course. // Execute the no pwnage check.
if (arrivals.isEnabled(player) && arrivals.check(player)) if (noPwnage.isEnabled(player) && noPwnage.check(player))
// The player failed the check, disallow the login.
event.disallow(Result.KICK_OTHER, cc.arrivalsMessage);
// Then the no pwnage check, if the login isn't already disallowed.
if (event.getResult() != Result.KICK_OTHER && noPwnage.isEnabled(player) && noPwnage.check(player))
event.disallow(Result.KICK_OTHER, cc.noPwnageReloginKickMessage); event.disallow(Result.KICK_OTHER, cc.noPwnageReloginKickMessage);
} }
} }

View File

@ -44,7 +44,7 @@ public class InstantHeal extends Check {
return false; return false;
} }
final long delta = System.currentTimeMillis() - (data.instantHealLastTime + 3500L); final long delta = System.currentTimeMillis() - (data.instantHealLastTime + 3000L);
data.instantHealBuffer += delta; data.instantHealBuffer += delta;
if (data.instantHealBuffer < 0) { if (data.instantHealBuffer < 0) {

View File

@ -67,6 +67,9 @@ public class MovingListener implements Listener {
/** The more packets vehicle check. */ /** The more packets vehicle check. */
private final MorePacketsVehicle morePacketsVehicle = new MorePacketsVehicle(); private final MorePacketsVehicle morePacketsVehicle = new MorePacketsVehicle();
/** The no fall check. */
private final NoFall noFall = new NoFall();
/** The survival fly check. */ /** The survival fly check. */
private final SurvivalFly survivalFly = new SurvivalFly(); private final SurvivalFly survivalFly = new SurvivalFly();
@ -313,10 +316,13 @@ public class MovingListener implements Listener {
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, from, 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, from, to);
else if (newTo == null && noFall.isEnabled(player))
// If he is handled by the no fall check, execute it.
noFall.check(player, from, to);
} 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();

View File

@ -54,6 +54,16 @@ public class NoFall extends Check {
return; return;
} }
// if (player.getName().equals("NeatMonster")) {
// player.sendMessage("---");
// player.sendMessage("bukkit = " + player.getFallDistance());
// player.sendMessage("ncp = " + data.noFallDistance);
// player.sendMessage("fromIsOnGround = " + from.isOnGround());
// player.sendMessage("fromIsOnStairs = " + from.isOnStairs());
// player.sendMessage("toIsOnGround = " + to.isOnGround());
// player.sendMessage("toIsOnStairs = " + to.isOnStairs());
// }
// This check is pretty much always a step behind for technical reasons. // This check is pretty much always a step behind for technical reasons.
if (from.isInLiquid() || from.isOnGround() || from.isOnLadder()) if (from.isInLiquid() || from.isOnGround() || from.isOnLadder())
// Start with zero fall distance. // Start with zero fall distance.
@ -104,7 +114,7 @@ public class NoFall extends Check {
// feeling. // feeling.
if (from.getY() > to.getY()) { if (from.getY() > to.getY()) {
final float deltaY = (float) (from.getY() - to.getY()); final float deltaY = (float) (from.getY() - to.getY());
data.noFallDistance += deltaY * 0.75F; // Magic number. :) data.noFallDistance += deltaY * 0.75D; // Magic number. :)
if (deltaY > 1F) { if (deltaY > 1F) {
data.noFallLastAddedDistance = deltaY; data.noFallLastAddedDistance = deltaY;
@ -114,7 +124,7 @@ public class NoFall extends Check {
} else } else
data.noFallLastAddedDistance = 0F; data.noFallLastAddedDistance = 0F;
if (to.isOnGround()) if (to.isOnGround() || from.isOnStairs())
data.noFallDistance = 0F; data.noFallDistance = 0F;
// Reduce violation level. // Reduce violation level.

View File

@ -84,7 +84,7 @@ public class SurvivalFly extends Check {
private static final double SOULSAND_SPRINTING_MOVE = 0.18D; private static final double SOULSAND_SPRINTING_MOVE = 0.18D;
/** The horizontal speed limit when sprinting. */ /** The horizontal speed limit when sprinting. */
private static final double SPRINTING_MOVE = 0.37D; private static final double SPRINTING_MOVE = 0.35D;
/** The vertical speed limit when ascending into water. */ /** The vertical speed limit when ascending into water. */
private static final double WATER_ASCEND = 0.13D + MARGIN; private static final double WATER_ASCEND = 0.13D + MARGIN;
@ -95,9 +95,6 @@ public class SurvivalFly extends Check {
/** The horizontal speed limit when moving into water. */ /** The horizontal speed limit when moving into water. */
private static final double WATER_MOVE = 0.18D; private static final double WATER_MOVE = 0.18D;
/** The no fall check. */
private final NoFall noFall = new NoFall();
/** /**
* Instantiates a new survival fly check. * Instantiates a new survival fly check.
*/ */
@ -177,7 +174,7 @@ public class SurvivalFly extends Check {
hAllowedDistance = cc.survivalFlyBlockingSpeed / 100D * BLOCKING_MOVE; hAllowedDistance = cc.survivalFlyBlockingSpeed / 100D * BLOCKING_MOVE;
else if (from.isInWater() && to.isInWater()) else if (from.isInWater() && to.isInWater())
hAllowedDistance = cc.survivalFlyWaterSpeed / 100D * WATER_MOVE; hAllowedDistance = cc.survivalFlyWaterSpeed / 100D * WATER_MOVE;
else if (player.isSprinting() && player.getFoodLevel() > 5) else if (sprinting)
hAllowedDistance = cc.survivalFlySprintingSpeed / 100D * SPRINTING_MOVE; hAllowedDistance = cc.survivalFlySprintingSpeed / 100D * SPRINTING_MOVE;
if (data.survivalFlyOnIce > 0) if (data.survivalFlyOnIce > 0)
@ -221,6 +218,16 @@ public class SurvivalFly extends Check {
hDistanceAboveLimit = Math.max(0D, hDistanceAboveLimit); hDistanceAboveLimit = Math.max(0D, hDistanceAboveLimit);
if (hDistanceAboveLimit == 0D && sprinting && !player.hasPermission(Permissions.MOVING_SURVIVALFLY_SPRINTING)) {
final double dX = to.getX() - from.getX();
final double dZ = to.getZ() - from.getZ();
final float yaw = from.getYaw();
// Prevent players from sprinting if they're moving backwards.
if (dX < 0D && dZ > 0D && yaw > 180F && yaw < 270F || dX < 0D && dZ < 0D && yaw > 270F && yaw < 360F
|| dX > 0D && dZ < 0D && yaw > 0F && yaw < 90F || dX > 0D && dZ > 0D && yaw > 90F && yaw < 180F)
hDistanceAboveLimit = hDistance;
}
// Potion effect "Jump". // Potion effect "Jump".
double jumpAmplifier = 1D; double jumpAmplifier = 1D;
if (entity.hasEffect(MobEffectList.JUMP)) { if (entity.hasEffect(MobEffectList.JUMP)) {
@ -288,7 +295,8 @@ public class SurvivalFly extends Check {
data.survivalFlyLastDistances[1] = data.survivalFlyLastDistances[0]; data.survivalFlyLastDistances[1] = data.survivalFlyLastDistances[0];
data.survivalFlyLastDistances[0] = vDistance; data.survivalFlyLastDistances[0] = vDistance;
double vAllowedDistance = (data.verticalFreedom + 1.35D) * data.jumpAmplifier; double vAllowedDistance = (data.verticalFreedom + (!from.isOnGround() && to.isOnGround() ? 1.5D : 1.35D))
* data.jumpAmplifier;
if (data.survivalFlyJumpPhase > JUMP_PHASE + data.jumpAmplifier) if (data.survivalFlyJumpPhase > JUMP_PHASE + data.jumpAmplifier)
vAllowedDistance -= (data.survivalFlyJumpPhase - JUMP_PHASE) * JUMP_STEP; vAllowedDistance -= (data.survivalFlyJumpPhase - JUMP_PHASE) * JUMP_STEP;
@ -352,10 +360,6 @@ public class SurvivalFly extends Check {
data.survivalFlyJumpPhase = 0; data.survivalFlyJumpPhase = 0;
} }
if (noFall.isEnabled(player))
// Execute the NoFall check.
noFall.check(player, from, to);
return null; return null;
} }

View File

@ -39,6 +39,7 @@ public abstract class ConfPaths {
*/ */
private static final String MISCELLANEOUS = "miscellaneous."; private static final String MISCELLANEOUS = "miscellaneous.";
public static final String MISCELLANEOUS_ALLOWCLIENTMODS = MISCELLANEOUS + "allowclientmods"; public static final String MISCELLANEOUS_ALLOWCLIENTMODS = MISCELLANEOUS + "allowclientmods";
public static final String MISCELLANEOUS_OPINCONSOLEONLY = MISCELLANEOUS + "opinconsoleonly";
public static final String MISCELLANEOUS_PROTECTPLUGINS = MISCELLANEOUS + "protectplugins"; public static final String MISCELLANEOUS_PROTECTPLUGINS = MISCELLANEOUS + "protectplugins";
private static final String CHECKS = "checks."; private static final String CHECKS = "checks.";
@ -129,13 +130,6 @@ public abstract class ConfPaths {
*/ */
private static final String CHAT = CHECKS + "chat."; private static final String CHAT = CHECKS + "chat.";
private static final String CHAT_ARRIVALS = CHAT + "arrivals.";
public static final String CHAT_ARRIVALS_CHECK = CHAT_ARRIVALS + "active";
public static final String CHAT_ARRIVALS_JOINSLIMIT = CHAT_ARRIVALS + "joinslimit";
public static final String CHAT_ARRIVALS_MESSAGE = CHAT_ARRIVALS + "message";
public static final String CHAT_ARRIVALS_TIMELIMIT = CHAT_ARRIVALS + "timelimit";
public static final String CHAT_ARRIVALS_ACTIONS = CHAT_ARRIVALS + "actions";
private static final String CHAT_COLOR = CHAT + "color."; private static final String CHAT_COLOR = CHAT + "color.";
public static final String CHAT_COLOR_CHECK = CHAT_COLOR + "active"; public static final String CHAT_COLOR_CHECK = CHAT_COLOR + "active";
public static final String CHAT_COLOR_ACTIONS = CHAT_COLOR + "actions"; public static final String CHAT_COLOR_ACTIONS = CHAT_COLOR + "actions";

View File

@ -47,6 +47,7 @@ public class DefaultConfig extends ConfigFile {
* d888b Y8b Y8b 888 d,dP "88,e8' "YeeP" 888 888 "88 888 888 888 "YeeP" "88 88" "88 88" d,dP * d888b Y8b Y8b 888 d,dP "88,e8' "YeeP" 888 888 "88 888 888 888 "YeeP" "88 88" "88 88" d,dP
*/ */
set(ConfPaths.MISCELLANEOUS_ALLOWCLIENTMODS, false); set(ConfPaths.MISCELLANEOUS_ALLOWCLIENTMODS, false);
set(ConfPaths.MISCELLANEOUS_OPINCONSOLEONLY, false);
set(ConfPaths.MISCELLANEOUS_PROTECTPLUGINS, true); set(ConfPaths.MISCELLANEOUS_PROTECTPLUGINS, true);
/* /*
@ -117,12 +118,6 @@ public class DefaultConfig extends ConfigFile {
* Y888 ,d 888 888 ,ee 888 888 * Y888 ,d 888 888 ,ee 888 888
* "88,d88 888 888 "88 888 888 * "88,d88 888 888 "88 888 888
*/ */
set(ConfPaths.CHAT_ARRIVALS_CHECK, false);
set(ConfPaths.CHAT_ARRIVALS_JOINSLIMIT, 3);
set(ConfPaths.CHAT_ARRIVALS_MESSAGE, "Please try again later!");
set(ConfPaths.CHAT_ARRIVALS_TIMELIMIT, 5000L);
set(ConfPaths.CHAT_ARRIVALS_ACTIONS, "cancel");
set(ConfPaths.CHAT_COLOR_CHECK, true); set(ConfPaths.CHAT_COLOR_CHECK, true);
set(ConfPaths.CHAT_COLOR_ACTIONS, "log:color:0:1:if cancel"); set(ConfPaths.CHAT_COLOR_ACTIONS, "log:color:0:1:if cancel");
@ -162,7 +157,7 @@ public class DefaultConfig extends ConfigFile {
set(ConfPaths.CHAT_NOPWNAGE_RELOGIN_WARNING_MESSAGE, set(ConfPaths.CHAT_NOPWNAGE_RELOGIN_WARNING_MESSAGE,
"&cYou relogged really fast! If you keep doing that, you're going to be banned."); "&cYou relogged really fast! If you keep doing that, you're going to be banned.");
set(ConfPaths.CHAT_NOPWNAGE_RELOGIN_WARNING_NUMBER, 1); set(ConfPaths.CHAT_NOPWNAGE_RELOGIN_WARNING_NUMBER, 1);
set(ConfPaths.CHAT_NOPWNAGE_RELOGIN_KICKMESSAGE, "Please try again later!"); set(ConfPaths.CHAT_NOPWNAGE_RELOGIN_KICKMESSAGE, "You've relogged too fast, joining cancelled!");
set(ConfPaths.CHAT_NOPWNAGE_RELOGIN_WARNING_TIMEOUT, 60000L); set(ConfPaths.CHAT_NOPWNAGE_RELOGIN_WARNING_TIMEOUT, 60000L);
set(ConfPaths.CHAT_NOPWNAGE_REPEAT_CHECK, true); set(ConfPaths.CHAT_NOPWNAGE_REPEAT_CHECK, true);

View File

@ -111,7 +111,6 @@ public class Permissions {
* "88,d88 888 888 "88 888 888 * "88,d88 888 888 "88 888 888
*/ */
private static final String CHAT = CHECKS + ".chat"; private static final String CHAT = CHECKS + ".chat";
public static final String CHAT_ARRIVALS = CHAT + ".arrivals";
public static final String CHAT_COLOR = CHAT + ".color"; public static final String CHAT_COLOR = CHAT + ".color";
public static final String CHAT_NOPWNAGE = CHAT + ".nopwnage"; public static final String CHAT_NOPWNAGE = CHAT + ".nopwnage";
@ -167,4 +166,5 @@ public class Permissions {
public static final String MOVING_SURVIVALFLY = MOVING + ".survivalfly"; public static final String MOVING_SURVIVALFLY = MOVING + ".survivalfly";
public static final String MOVING_SURVIVALFLY_BLOCKING = MOVING_SURVIVALFLY + ".blocking"; public static final String MOVING_SURVIVALFLY_BLOCKING = MOVING_SURVIVALFLY + ".blocking";
public static final String MOVING_SURVIVALFLY_SNEAKING = MOVING_SURVIVALFLY + ".sneaking"; public static final String MOVING_SURVIVALFLY_SNEAKING = MOVING_SURVIVALFLY + ".sneaking";
public static final String MOVING_SURVIVALFLY_SPRINTING = MOVING_SURVIVALFLY + ".sprinting";
} }

View File

@ -102,6 +102,9 @@ public class PlayerLocation {
/** Is the player on soul sand? */ /** Is the player on soul sand? */
private final CustomBoolean onSoulSand = new CustomBoolean(); private final CustomBoolean onSoulSand = new CustomBoolean();
/** Is the player on stairs? */
private final CustomBoolean onStairs = new CustomBoolean();
/** The bounding box of the player. */ /** The bounding box of the player. */
private final AxisAlignedBB boundingBox; private final AxisAlignedBB boundingBox;
@ -348,4 +351,25 @@ public class PlayerLocation {
} }
return onSoulSand.get(); return onSoulSand.get();
} }
public boolean isOnStairs() {
if (!onStairs.isSet()) {
AxisAlignedBB boundingBoxGround = boundingBox.clone();
boundingBoxGround = boundingBoxGround.d(0D, -0.5D, 0D);
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);
final int id = world.getTypeId(blockX, blockY, blockZ);
if (!onStairs.get()
&& (id == 53 || id == 67 || id == 108 || id == 109 || id == 114 || id == 128 || id == 134
|| id == 135 || id == 136))
onStairs.set(true);
}
if (!onStairs.isSet())
onStairs.set(false);
}
return onStairs.get();
}
} }