mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-09-27 14:13:11 +02:00
Fix / "refine" elytra handling. Set all maxheight to 128.
* Lift-off side conditions. * Force stop gliding for some side conditions, to avoid freezing. * Set maxheight to 128 for elytra and levitation too (mods/plugins/etc) - better refine checks to catch stuff. * Fix special flags not getting set with initializing ModelFlying from config. * Debug log exceeding the maxheight setting. * Mostly harmless: Add interfaces and access methods, including convenience methods. * Don't store methods in Bridge1_9. Issues left, not limited to: * Boost not recognized on occasion. * Gliding state kept when submerged in water and moving normally like when not gliding, e.g. ascending (head in water / fully submerged). * Elytra lift off not accepted: Gliding state set near the water surface, but survivalfly check runs. Might be fixed already, though.
This commit is contained in:
parent
9505c0747d
commit
344b032d49
@ -301,16 +301,28 @@ public class BlockInteractListener extends CheckListener {
|
||||
final BlockInteractData data = BlockInteractData.getData(player);
|
||||
data.setPlayerInteractEventResolution(event);
|
||||
/*
|
||||
* TODO: BlockDamageEvent fires before MONITOR level, BlockBreak after
|
||||
* (!). Thus resolution is set on LOWEST already, probably should be
|
||||
* HIGHEST to account for other plugins.
|
||||
* TODO: BlockDamageEvent fires before BlockInteract/MONITOR level,
|
||||
* BlockBreak after (!). Thus resolution is set on LOWEST already,
|
||||
* probably should be HIGHEST to account for other plugins.
|
||||
*/
|
||||
// Elytra boost.
|
||||
final Block block = event.getClickedBlock();
|
||||
if ((event.getAction() == Action.RIGHT_CLICK_AIR
|
||||
|| event.getAction() == Action.RIGHT_CLICK_BLOCK
|
||||
&& block != null && BlockProperties.isLiquid(block.getType())
|
||||
)
|
||||
/*
|
||||
* TODO: Cross check with the next incoming move: has an item been used,
|
||||
* is gliding, reset if necessary.
|
||||
*/
|
||||
//final Block block = event.getClickedBlock();
|
||||
// if (data.debug) {
|
||||
// debug(player, "BlockInteractResolution: cancelled=" + event.isCancelled()
|
||||
// + " action=" + event.getAction() + " block=" + block + " item=" + Bridge1_9.getUsedItem(player, event));
|
||||
// }
|
||||
if (
|
||||
(
|
||||
event.getAction() == Action.RIGHT_CLICK_AIR
|
||||
// Water doesn't happen, block typically is null.
|
||||
// || event.getAction() == Action.RIGHT_CLICK_BLOCK
|
||||
// && block != null && BlockProperties.isLiquid(block.getType())
|
||||
// TODO: web ?
|
||||
)
|
||||
&& event.isCancelled() && event.useItemInHand() != Result.DENY) {
|
||||
final ItemStack stack = Bridge1_9.getUsedItem(player, event);
|
||||
if (stack != null && BridgeMisc.maybeElytraBoost(player, stack.getType())) {
|
||||
|
@ -250,8 +250,6 @@ public class MovingData extends ACheckData implements IRemoveSubCheckData {
|
||||
public int combinedMediumHCount = 0;
|
||||
/** Sum of actual speed / base speed for horizontal moving within air + certain medium. */
|
||||
public double combinedMediumHValue = 0.0;
|
||||
/** Count combined medium successive moves, permanent. */
|
||||
public int combinedMediumPermanentCount = 0; // TODO: Not 100% convinced of usefulness.
|
||||
|
||||
// Locations shared between all checks.
|
||||
private Location setBack = null;
|
||||
|
@ -30,8 +30,10 @@ import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
||||
import org.bukkit.event.entity.EntityToggleGlideEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.event.player.PlayerBedEnterEvent;
|
||||
import org.bukkit.event.player.PlayerBedLeaveEvent;
|
||||
@ -64,6 +66,7 @@ import fr.neatmonster.nocheatplus.checks.combined.Combined;
|
||||
import fr.neatmonster.nocheatplus.checks.combined.CombinedConfig;
|
||||
import fr.neatmonster.nocheatplus.checks.combined.CombinedData;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.magic.Magic;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.model.ModelFlying;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveInfo;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.player.CreativeFly;
|
||||
@ -208,6 +211,43 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
// Register vehicleChecks.
|
||||
NCPAPIProvider.getNoCheatPlusAPI().addComponent(vehicleChecks);
|
||||
blockChangeTracker = NCPAPIProvider.getNoCheatPlusAPI().getBlockChangeTracker();
|
||||
if (Bridge1_9.hasEntityToggleGlideEvent()) {
|
||||
queuedComponents.add(new Listener() {
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onEntityToggleGlide(final EntityToggleGlideEvent event) {
|
||||
if (handleEntityToggleGlideEvent(event.getEntity(), event.isGliding())) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param entity
|
||||
* @param isGliding
|
||||
* @return True, if the event is to be cancelled.
|
||||
*/
|
||||
private boolean handleEntityToggleGlideEvent(final Entity entity, final boolean isGliding) {
|
||||
// Ignore non players.
|
||||
if (!(entity instanceof Player)) {
|
||||
return false;
|
||||
}
|
||||
final Player player = (Player) entity;
|
||||
if (isGliding && !Bridge1_9.isGlidingWithElytra(player)) { // Includes check for elytra item.
|
||||
final PlayerMoveInfo info = aux.usePlayerMoveInfo();
|
||||
info.set(player, player.getLocation(info.useLoc), null, 0.001); // Only restrict very near ground.
|
||||
final MovingData data = MovingData.getData(player);
|
||||
final boolean res = !MovingUtil.canLiftOffWithElytra(player, info.from, data);
|
||||
info.cleanup();
|
||||
aux.returnPlayerMoveInfo(info);
|
||||
if (res && data.debug) {
|
||||
debug(player, "Prevent toggle glide on.");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -625,15 +665,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
&& !player.hasPermission(Permissions.MOVING_CREATIVEFLY)) {
|
||||
checkCf = true;
|
||||
checkSf = false;
|
||||
data.adjustFlySpeed(player.getFlySpeed(), tick, cc.speedGrace);
|
||||
data.adjustWalkSpeed(player.getWalkSpeed(), tick, cc.speedGrace);
|
||||
thisMove.flyCheck = CheckType.MOVING_CREATIVEFLY;
|
||||
// TODO: Adjust height of PlayerLocation more efficiently / fetch model early.
|
||||
thisMove.modelFlying = cc.getModelFlying(player, pFrom, data, cc);
|
||||
if (MovingConfig.ID_JETPACK_ELYTRA.equals(thisMove.modelFlying.getId())) {
|
||||
pFrom.setByGivenHeight(from, player, 0.6, cc.yOnGround);
|
||||
pTo.setByGivenHeight(to, player, 0.6, cc.yOnGround);
|
||||
}
|
||||
prepareCreativeFlyCheck(player, from, to, moveInfo, thisMove, multiMoveCount, tick, data, cc);
|
||||
}
|
||||
else {
|
||||
checkCf = checkSf = false;
|
||||
@ -896,10 +928,41 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
}
|
||||
// Set back handling.
|
||||
prepareSetBack(player, event, newTo, data, cc);
|
||||
// Prevent freezing (e.g. ascending with gliding set in water, but moving normally).
|
||||
if ((thisMove.flyCheck == CheckType.MOVING_SURVIVALFLY
|
||||
|| thisMove.flyCheck == CheckType.MOVING_CREATIVEFLY
|
||||
&& pFrom.isInLiquid()
|
||||
) && Bridge1_9.isGlidingWithElytra(player)) {
|
||||
stopGliding(player);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static void stopGliding(final Player player) {
|
||||
player.setGliding(false);
|
||||
}
|
||||
|
||||
private void prepareCreativeFlyCheck(final Player player, final Location from, final Location to,
|
||||
final PlayerMoveInfo moveInfo, final PlayerMoveData thisMove, final int multiMoveCount,
|
||||
final int tick, final MovingData data, final MovingConfig cc) {
|
||||
data.adjustFlySpeed(player.getFlySpeed(), tick, cc.speedGrace);
|
||||
data.adjustWalkSpeed(player.getWalkSpeed(), tick, cc.speedGrace);
|
||||
// TODO: Adjust height of PlayerLocation more efficiently / fetch model early.
|
||||
final ModelFlying model = cc.getModelFlying(player, moveInfo.from, data, cc);
|
||||
if (MovingConfig.ID_JETPACK_ELYTRA.equals(model.getId())) {
|
||||
final MCAccess mcAccess = this.mcAccess.getHandle();
|
||||
MovingUtil.setElytraProperties(player, moveInfo.from, from, cc.yOnGround, mcAccess);
|
||||
MovingUtil.setElytraProperties(player, moveInfo.to, to, cc.yOnGround, mcAccess);
|
||||
thisMove.set(moveInfo.from, moveInfo.to);
|
||||
if (multiMoveCount > 0) {
|
||||
thisMove.multiMoveCount = multiMoveCount;
|
||||
}
|
||||
}
|
||||
thisMove.flyCheck = CheckType.MOVING_CREATIVEFLY;
|
||||
thisMove.modelFlying = model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only for yDistance < 0 + some bounce envelope checked.
|
||||
* @param player
|
||||
|
@ -98,12 +98,12 @@ public class ModelFlying {
|
||||
horizontalModSpeed(config.getDouble(prefix + ConfPaths.SUB_HORIZONTAL_SPEED, defaults.getHorizontalModSpeed()));
|
||||
horizontalModSprint(config.getDouble(prefix + ConfPaths.SUB_HORIZONTAL_MODSPRINT, defaults.getHorizontalModSprint()));
|
||||
verticalAscendModSpeed(config.getDouble(prefix + ConfPaths.SUB_VERTICAL_ASCEND_SPEED, defaults.getVerticalAscendModSpeed()));
|
||||
// TODO: verticalAscendGliding.
|
||||
verticalAscendGliding(defaults.getVerticalAscendGliding()); // Config ?
|
||||
maxHeight(config.getDouble(prefix + ConfPaths.SUB_VERTICAL_MAXHEIGHT, defaults.getMaxHeight()));
|
||||
applyModifiers(config.getBoolean(prefix + ConfPaths.SUB_MODIFIERS, defaults.getApplyModifiers()));
|
||||
gravity(config.getBoolean(prefix + ConfPaths.SUB_VERTICAL_GRAVITY, defaults.getGravity()));
|
||||
ground(config.getBoolean(prefix + ConfPaths.SUB_GROUND, defaults.getGround()));
|
||||
// TODO: scaleLevitationEffect.
|
||||
scaleLevitationEffect(defaults.getScaleLevitationEffect()); // Config?
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -228,6 +228,9 @@ public class CreativeFly extends Check {
|
||||
// Maximum height check (silent set back).
|
||||
if (to.getY() > maximumHeight) {
|
||||
setBack = data.getSetBack(to);
|
||||
if (data.debug) {
|
||||
debug(player, "Maximum height exceeded, silent set-back.");
|
||||
}
|
||||
}
|
||||
if (setBack == null) {
|
||||
// Slowly reduce the violation level with each event.
|
||||
@ -375,9 +378,9 @@ public class CreativeFly extends Check {
|
||||
}
|
||||
|
||||
// Related to elytra.
|
||||
if (limitV == 0.0 && model.getVerticalAscendGliding()) {
|
||||
if (model.getVerticalAscendGliding()) {
|
||||
// TODO: Better detection of an elytra model (extra flags?).
|
||||
limitV = hackLytra(yDistance, limitV, thisMove, lastMove, data);
|
||||
limitV = Math.max(limitV, limitV = hackLytra(yDistance, limitV, thisMove, lastMove, data));
|
||||
}
|
||||
|
||||
if (model.getGravity()) {
|
||||
|
@ -571,12 +571,10 @@ public class SurvivalFly extends Check {
|
||||
// TODO: Is above stairs ?
|
||||
}
|
||||
// Count how long one is moving inside of a medium.
|
||||
data.combinedMediumPermanentCount ++;
|
||||
if (oldLiftOffEnvelope != data.liftOffEnvelope) {
|
||||
data.insideMediumCount = 0;
|
||||
data.combinedMediumHCount = 0;
|
||||
data.combinedMediumHValue = 0.0;
|
||||
data.combinedMediumPermanentCount = 0;
|
||||
}
|
||||
else if (!resetFrom || !resetTo) {
|
||||
data.insideMediumCount = 0;
|
||||
|
@ -30,7 +30,6 @@ import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.MovingData;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.magic.Magic;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.model.LiftOffEnvelope;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.model.MoveData;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.player.PlayerSetBackMethod;
|
||||
@ -89,10 +88,14 @@ public class MovingUtil {
|
||||
&& (cc.ignoreCreative || gameMode != GameMode.CREATIVE) && !player.isFlying()
|
||||
&& (cc.ignoreAllowFlight || !player.getAllowFlight())
|
||||
&& !NCPExemptionManager.isExempted(player, CheckType.MOVING_SURVIVALFLY, true)
|
||||
&& (!Bridge1_9.isGlidingWithElytra(player)
|
||||
|| !isGlidingWithElytraValid(player, fromLocation, data, cc))
|
||||
&& (Double.isInfinite(Bridge1_9.getLevitationAmplifier(player))
|
||||
|| fromLocation.isInLiquid())
|
||||
&& (
|
||||
!Bridge1_9.isGlidingWithElytra(player)
|
||||
|| !isGlidingWithElytraValid(player, fromLocation, data, cc)
|
||||
)
|
||||
&& (
|
||||
Double.isInfinite(Bridge1_9.getLevitationAmplifier(player))
|
||||
|| fromLocation.isInLiquid()
|
||||
)
|
||||
&& !player.hasPermission(Permissions.MOVING_SURVIVALFLY);
|
||||
}
|
||||
|
||||
@ -109,37 +112,110 @@ public class MovingUtil {
|
||||
public static boolean isGlidingWithElytraValid(final Player player, final PlayerLocation fromLocation,
|
||||
final MovingData data, final MovingConfig cc) {
|
||||
|
||||
// Prevent forms of noclip - could be too coarse / false positives.
|
||||
if (!fromLocation.isPassable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Confine/relax more, if needed (in-medium count, past moves).
|
||||
|
||||
// TODO: Configuration for which/if to check on either lift-off / unknown / gliding.
|
||||
// TODO: Item durability?
|
||||
// TODO: TEST LAVA (ordinary and boost, lift off and other).
|
||||
/*
|
||||
* TODO: Allow if last move not touched ground (+-) after all the
|
||||
* onGround check isn't much needed, if we can test for the relevant stuff (web?).
|
||||
*/
|
||||
|
||||
// Check start glide conditions.
|
||||
final PlayerMoveData firstPastMove = data.playerMoves.getFirstPastMove();
|
||||
if (!firstPastMove.toIsValid || firstPastMove.modelFlying == null
|
||||
if (
|
||||
// Skip lift-off conditions if the EntityToggleGlideEvent is present (checked there).
|
||||
!Bridge1_9.hasEntityToggleGlideEvent()
|
||||
// Otherwise only treat as lift-off, if not already gliding.
|
||||
&& !firstPastMove.toIsValid || firstPastMove.modelFlying == null
|
||||
|| !MovingConfig.ID_JETPACK_ELYTRA.equals(firstPastMove.modelFlying.getId())) {
|
||||
// Treat as a lift off.
|
||||
return canLiftOffWithElytra(fromLocation, data);
|
||||
// TODO: Past map states might allow lift off (...).
|
||||
return canLiftOffWithElytra(player, fromLocation, data);
|
||||
}
|
||||
// TODO: Past map states might allow lift off (...).
|
||||
// TODO: Other abort conditions.
|
||||
|
||||
/*
|
||||
* TODO: Test / verify it gets turned off if depleted during gliding,
|
||||
* provided the client doesn't help knowing. (Only shortly tested with
|
||||
* grep -r "ItemElytra.d" <- looks good.)
|
||||
*/
|
||||
// // Test late, as lift-off check also tests for this.
|
||||
// if (InventoryUtil.isItemBroken(player.getInventory().getChestplate())) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
/*
|
||||
* TODO: Rather focus on abort conditions (in-medium stay time for
|
||||
* special blocks, sleeping / dead / ...)?
|
||||
*/
|
||||
|
||||
// Only the web can stop a player who isn't propelled by a rocket.
|
||||
// TODO: If this is not lift-off, check with a lowered bounding box!
|
||||
return data.fireworksBoostDuration > 0 || !fromLocation.isInWeb();
|
||||
return data.fireworksBoostDuration > 0 || !BlockProperties.collidesId(fromLocation.getBlockCache(),
|
||||
fromLocation.getMinX(), fromLocation.getMinY(), fromLocation.getMinZ(),
|
||||
fromLocation.getMaxX(), fromLocation.getMinY() + 0.6, fromLocation.getMaxZ(), Material.WEB);
|
||||
}
|
||||
|
||||
private static boolean canLiftOffWithElytra(final PlayerLocation fromLocation, final MovingData data) {
|
||||
return !fromLocation.isInLiquid() && !fromLocation.isInWeb()
|
||||
&& (data.liftOffEnvelope == LiftOffEnvelope.LIMIT_NEAR_GROUND
|
||||
|| data.liftOffEnvelope == LiftOffEnvelope.NORMAL);
|
||||
// && !fromLocation.isOnGround() // TODO: Nice to have: been in air slightly before.
|
||||
//|| data.combinedMediumPermanentCount > data.insideMediumCount
|
||||
//&& data.combinedMediumPermanentCount > 15;
|
||||
/**
|
||||
* Check lift-off (CB: on ground is done wrongly, inWater probably is
|
||||
* correct, web is not checked).
|
||||
*
|
||||
* @param fromLocation
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
public static boolean canLiftOffWithElytra(final Player player, final PlayerLocation loc,
|
||||
final MovingData data) {
|
||||
// TODO: Item durability here too?
|
||||
// TODO: this/firstPast- Move not touching or not explicitly on ground would be enough?
|
||||
return
|
||||
loc.isPassableBox() // Full box as if standing for lift-off.
|
||||
&& !loc.isInWeb()
|
||||
// Durability is checked within PlayerConnection (toggling on).
|
||||
// && !InventoryUtil.isItemBroken(player.getInventory().getChestplate())
|
||||
/*
|
||||
* TODO: Could be a problem with too high yOnGround. Actual
|
||||
* cheating rather would have to be prevented by monitoring
|
||||
* jumping more tightly (low jump = set back, needs
|
||||
* false-positive-free checking (...)).
|
||||
*/
|
||||
&& !loc.isOnGround(0.001)
|
||||
// Assume water is checked correctly.
|
||||
// && (
|
||||
// !fromLocation.isInLiquid() // (Needs to check for actual block bounds).
|
||||
// /*
|
||||
// * Observed with head free, but feet clearly in water:
|
||||
// * lift off from water (not 100% easy to do).
|
||||
// */
|
||||
// || !BlockProperties.isLiquid(fromLocation.getTypeId())
|
||||
// || !BlockProperties.isLiquid(fromLocation.getTypeIdAbove())
|
||||
// )
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Workaround for getEyeHeight not accounting for special conditions like
|
||||
* gliding with elytra. (Sleeping is not checked.)
|
||||
*
|
||||
* @param player
|
||||
* @return
|
||||
*/
|
||||
public static double getEyeHeight(final Player player) {
|
||||
// TODO: Need a variant/method to test legitimate state transitions?
|
||||
// TODO: EntityToggleGlideEvent
|
||||
return Bridge1_9.isGlidingWithElytra(player) ? 0.4 : player.getEyeHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize pLoc with edge data specific to gliding with elytra.
|
||||
*
|
||||
* @param player
|
||||
* @param pLoc
|
||||
* @param loc
|
||||
* @param yOnGround
|
||||
* @param mcAccess
|
||||
*/
|
||||
public static void setElytraProperties(final Player player, final PlayerLocation pLoc, final Location loc,
|
||||
final double yOnGround, final MCAccess mcAccess) {
|
||||
pLoc.set(loc, player, mcAccess.getWidth(player), 0.4, 0.6, 0.6, yOnGround);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -14,8 +14,6 @@
|
||||
*/
|
||||
package fr.neatmonster.nocheatplus.compat;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
@ -35,10 +33,11 @@ public class Bridge1_9 {
|
||||
public static final Material ELYTRA = Material.getMaterial("ELYTRA");
|
||||
public static final Material END_CRYSTAL_ITEM = Material.getMaterial("END_CRYSTAL");
|
||||
|
||||
private static Method getItemInOffHand = ReflectionUtil.getMethodNoArgs(PlayerInventory.class, "getItemInOffHand", ItemStack.class);
|
||||
private static Method getItemInMainHand = ReflectionUtil.getMethodNoArgs(PlayerInventory.class, "getItemInMainHand", ItemStack.class);
|
||||
private static final boolean hasGetItemInOffHand = ReflectionUtil.getMethodNoArgs(PlayerInventory.class, "getItemInOffHand", ItemStack.class) != null;
|
||||
private static final boolean hasGetItemInMainHand = ReflectionUtil.getMethodNoArgs(PlayerInventory.class, "getItemInMainHand", ItemStack.class) != null;
|
||||
|
||||
private static Method isGliding = ReflectionUtil.getMethodNoArgs(Player.class, "isGliding", boolean.class);
|
||||
private static final boolean hasIsGliding = ReflectionUtil.getMethodNoArgs(Player.class, "isGliding", boolean.class) != null;
|
||||
private static final boolean hasEntityToggleGlideEvent = ReflectionUtil.getClass("org.bukkit.event.entity.EntityToggleGlideEvent") != null;
|
||||
|
||||
public static boolean hasLevitation() {
|
||||
return LEVITATION != null;
|
||||
@ -57,15 +56,19 @@ public class Bridge1_9 {
|
||||
}
|
||||
|
||||
public static boolean hasGetItemInOffHand() {
|
||||
return getItemInOffHand != null;
|
||||
return hasGetItemInOffHand;
|
||||
}
|
||||
|
||||
public static boolean hasGetItemInMainHand() {
|
||||
return getItemInMainHand != null;
|
||||
return hasGetItemInMainHand;
|
||||
}
|
||||
|
||||
public static boolean hasIsGliding() {
|
||||
return isGliding != null;
|
||||
return hasIsGliding;
|
||||
}
|
||||
|
||||
public static boolean hasEntityToggleGlideEvent() {
|
||||
return hasEntityToggleGlideEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,12 +131,8 @@ public class Bridge1_9 {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static ItemStack getItemInMainHand(final Player player) {
|
||||
if (getItemInMainHand == null) {
|
||||
return player.getItemInHand(); // As long as feasible (see: CraftInventoryPlayer).
|
||||
}
|
||||
else {
|
||||
return player.getInventory().getItemInMainHand();
|
||||
}
|
||||
return hasGetItemInMainHand ? player.getInventory().getItemInMainHand()
|
||||
: player.getItemInHand(); // As long as feasible (see: CraftInventoryPlayer).
|
||||
}
|
||||
|
||||
/**
|
||||
@ -143,21 +142,11 @@ public class Bridge1_9 {
|
||||
* @return In case the method is not present, null will be returned.
|
||||
*/
|
||||
public static ItemStack getItemInOffHand(final Player player) {
|
||||
if (getItemInOffHand == null) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return player.getInventory().getItemInOffHand();
|
||||
}
|
||||
return hasGetItemInOffHand ? player.getInventory().getItemInOffHand() : null;
|
||||
}
|
||||
|
||||
public static boolean isGliding(final Player player) {
|
||||
if (isGliding == null) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return player.isGliding();
|
||||
}
|
||||
return hasIsGliding ? player.isGliding() : false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -183,7 +172,7 @@ public class Bridge1_9 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the item that was used with this event, assume right click (not feet etc.).
|
||||
* @param player
|
||||
|
@ -0,0 +1,14 @@
|
||||
package fr.neatmonster.nocheatplus.components.location;
|
||||
|
||||
/**
|
||||
* 3D bounding box (doubles).
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public interface IGetBox2D {
|
||||
public double getMinX();
|
||||
public double getMinZ();
|
||||
public double getMaxX();
|
||||
public double getMaxZ();
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package fr.neatmonster.nocheatplus.components.location;
|
||||
|
||||
/**
|
||||
* 3D bounding box (doubles).
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public interface IGetBox3D extends IGetBox2D {
|
||||
public double getMinY();
|
||||
public double getMaxY();
|
||||
}
|
@ -385,7 +385,7 @@ public class DefaultConfig extends ConfigFile {
|
||||
if (Bridge1_9.hasLevitation()) {
|
||||
set(ConfPaths.MOVING_CREATIVEFLY_MODEL + "levitation." + ConfPaths.SUB_HORIZONTAL_SPEED, 50, 785);
|
||||
set(ConfPaths.MOVING_CREATIVEFLY_MODEL + "levitation." + ConfPaths.SUB_VERTICAL_ASCEND_SPEED, 10, 785);
|
||||
set(ConfPaths.MOVING_CREATIVEFLY_MODEL + "levitation." + ConfPaths.SUB_VERTICAL_MAXHEIGHT, 32, 785);
|
||||
set(ConfPaths.MOVING_CREATIVEFLY_MODEL + "levitation." + ConfPaths.SUB_VERTICAL_MAXHEIGHT, 128, 1104);
|
||||
set(ConfPaths.MOVING_CREATIVEFLY_MODEL + "levitation." + ConfPaths.SUB_VERTICAL_GRAVITY, false, 785);
|
||||
set(ConfPaths.MOVING_CREATIVEFLY_MODEL + "levitation." + ConfPaths.SUB_MODIFIERS, false, 785);
|
||||
set(ConfPaths.MOVING_CREATIVEFLY_MODEL + "levitation." + ConfPaths.SUB_GRAVITY, false, 785);
|
||||
@ -395,7 +395,7 @@ public class DefaultConfig extends ConfigFile {
|
||||
set(ConfPaths.MOVING_CREATIVEFLY_MODEL + "elytra." + ConfPaths.SUB_HORIZONTAL_SPEED, 520, 785);
|
||||
set(ConfPaths.MOVING_CREATIVEFLY_MODEL + "elytra." + ConfPaths.SUB_HORIZONTAL_MODSPRINT, 1.0, 785);
|
||||
set(ConfPaths.MOVING_CREATIVEFLY_MODEL + "elytra." + ConfPaths.SUB_VERTICAL_ASCEND_SPEED, 0, 785);
|
||||
set(ConfPaths.MOVING_CREATIVEFLY_MODEL + "elytra." + ConfPaths.SUB_VERTICAL_MAXHEIGHT, 8, 785);
|
||||
set(ConfPaths.MOVING_CREATIVEFLY_MODEL + "elytra." + ConfPaths.SUB_VERTICAL_MAXHEIGHT, 128, 1104);
|
||||
set(ConfPaths.MOVING_CREATIVEFLY_MODEL + "elytra." + ConfPaths.SUB_MODIFIERS, false, 785);
|
||||
}
|
||||
set(ConfPaths.MOVING_CREATIVEFLY_ACTIONS,
|
||||
|
@ -187,4 +187,23 @@ public class InventoryUtil {
|
||||
(type.isEdible() || type == Material.POTION || type == Material.MILK_BUCKET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for max durability, only makes sense with items that can be in
|
||||
* inventory once broken, such as elytra. This method does not (yet) provide
|
||||
* legacy support. This tests for ItemStack.getDurability() >=
|
||||
* Material.getMaxDurability, so it only is suited for a context where this
|
||||
* is what you want to check for.
|
||||
*
|
||||
* @param stack
|
||||
* May be null, would yield true.
|
||||
* @return
|
||||
*/
|
||||
public static boolean isItemBroken(final ItemStack stack) {
|
||||
if (stack == null) {
|
||||
return true;
|
||||
}
|
||||
final Material mat = stack.getType();
|
||||
return stack.getDurability() >= mat.getMaxDurability();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,6 +14,8 @@
|
||||
*/
|
||||
package fr.neatmonster.nocheatplus.utilities.collision;
|
||||
|
||||
import fr.neatmonster.nocheatplus.components.location.IGetBox3D;
|
||||
|
||||
public class CollideRayVsAABB implements ICollideRayVsAABB {
|
||||
|
||||
private boolean findNearestPointIfNotCollide = false;
|
||||
@ -42,6 +44,12 @@ public class CollideRayVsAABB implements ICollideRayVsAABB {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICollideRayVsAABB setAABB(final IGetBox3D box) {
|
||||
setAABB(box.getMinX(), box.getMinY(), box.getMinZ(), box.getMaxX(), box.getMaxY(), box.getMaxZ());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICollideRayVsAABB setAABB(double targetX, double targetY, double targetZ,
|
||||
double boxMarginHorizontal, double boxMarginVertical) {
|
||||
|
@ -14,6 +14,7 @@
|
||||
*/
|
||||
package fr.neatmonster.nocheatplus.utilities.collision;
|
||||
|
||||
import fr.neatmonster.nocheatplus.components.location.IGetBox3D;
|
||||
import fr.neatmonster.nocheatplus.components.location.IGetPosition;
|
||||
|
||||
/**
|
||||
@ -73,6 +74,15 @@ public interface ICollideRayVsAABB extends IGetPosition {
|
||||
public ICollideRayVsAABB setAABB(double targetX, double targetY, double targetZ,
|
||||
double boxMarginHorizontal, double boxMarginVertical);
|
||||
|
||||
/**
|
||||
* Set the properties of the AABB, using a given boxIGetBox3D instance.
|
||||
*
|
||||
* @param box
|
||||
* The 3D bounding box to set.
|
||||
* @return The same instance for chaining.
|
||||
*/
|
||||
public ICollideRayVsAABB setAABB(IGetBox3D box);
|
||||
|
||||
/**
|
||||
* Set the properties of the AABB, using block coordinates and a margin.
|
||||
* This can be called independently of setRay and loop, in order to
|
||||
|
@ -116,18 +116,18 @@ public class PlayerLocation extends RichEntityLocation {
|
||||
}
|
||||
|
||||
/**
|
||||
* Like set, but for the height properties only the given height is used, no
|
||||
* special cases.
|
||||
*
|
||||
* Set with specific height/length/eyeHeight properties.
|
||||
* @param location
|
||||
* @param player
|
||||
* @param width
|
||||
* @param eyeHeight
|
||||
* @param height
|
||||
* @param fullHeight
|
||||
* @param yOnGround
|
||||
*/
|
||||
public void setByGivenHeight(final Location location, final Player player, final double height,
|
||||
final double yOnGround) {
|
||||
super.doSetExactHeight(location, player, true, getMCAccess().getWidth(player),
|
||||
height, height, height, yOnGround);
|
||||
public void set(final Location location, final Player player, final double width,
|
||||
final double eyeHeight, final double height, final double fullHeight, final double yOnGround) {
|
||||
super.doSetExactHeight(location, player, true, width, eyeHeight, height, fullHeight, yOnGround);
|
||||
// Entity reference.
|
||||
this.player = player;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeReferen
|
||||
import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker;
|
||||
import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker.BlockChangeEntry;
|
||||
import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker.Direction;
|
||||
import fr.neatmonster.nocheatplus.components.location.IGetBox3D;
|
||||
import fr.neatmonster.nocheatplus.components.location.IGetBlockPosition;
|
||||
import fr.neatmonster.nocheatplus.components.location.IGetBukkitLocation;
|
||||
import fr.neatmonster.nocheatplus.components.location.IGetPosition;
|
||||
@ -43,7 +44,7 @@ import fr.neatmonster.nocheatplus.utilities.map.MapUtil;
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public class RichBoundsLocation implements IGetBukkitLocation, IGetBlockPosition {
|
||||
public class RichBoundsLocation implements IGetBukkitLocation, IGetBlockPosition, IGetBox3D {
|
||||
|
||||
// TODO: Store IBlockCacheNode (s) ?
|
||||
// TODO: Consider switching back from default to private visibility (use getters for other places).
|
||||
@ -250,6 +251,36 @@ public class RichBoundsLocation implements IGetBukkitLocation, IGetBlockPosition
|
||||
return new double[] {minX, minY, minZ, maxX, maxY, maxZ};
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMinX() {
|
||||
return minX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMinZ() {
|
||||
return minZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMaxX() {
|
||||
return maxX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMaxZ() {
|
||||
return maxZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMinY() {
|
||||
return minY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMaxY() {
|
||||
return maxY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bounding box margin from the center (x ,z) to the edge of the
|
||||
* box. This value may be adapted from entity width or other input, and it
|
||||
|
@ -34,7 +34,8 @@ public class RichEntityLocation extends RichBoundsLocation {
|
||||
|
||||
/*
|
||||
* TODO: HumanEntity default with + height (1.11.2): elytra 0.6/0.6,
|
||||
* sleeping 0.2/0.2, sneaking 0.6/1.65, normal 0.6/1.8
|
||||
* sleeping 0.2/0.2, sneaking 0.6/1.65, normal 0.6/1.8 - head height is 0.4
|
||||
* with elytra, 0.2 with sleeping, height - 0.08 otherwise.
|
||||
*/
|
||||
|
||||
/** The mc access. */
|
||||
@ -397,6 +398,7 @@ public class RichEntityLocation extends RichBoundsLocation {
|
||||
this.isLiving = isLiving;
|
||||
final MCAccess mcAccess = this.mcAccess.getHandle();
|
||||
this.width = mcAccess.getWidth(entity);
|
||||
this.eyeHeight = eyeHeight;
|
||||
this.height = mcAccess.getHeight(entity);
|
||||
standsOnEntity = false;
|
||||
super.set(location, fullWidth, fullHeight, yOnGround);
|
||||
|
Loading…
Reference in New Issue
Block a user