[Instable] Bleeding: Encapsulate CB/MC access for compatibility.

Soem things are not optimized yet, also it is a raw commit no test, does
not even compile.
This commit is contained in:
asofold 2012-12-06 22:16:07 +01:00
parent d47c2cd533
commit ff94745999
28 changed files with 1004 additions and 1090 deletions

View File

@ -42,9 +42,15 @@
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.4.5-R0.2</version>
<version>1.4.5-R0.3-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.4.5-R0.2</version>
<scope>provided</scope>
</dependency>
</dependencies>
<!-- Building -->

View File

@ -38,6 +38,8 @@ import fr.neatmonster.nocheatplus.checks.inventory.InventoryListener;
import fr.neatmonster.nocheatplus.checks.moving.MovingListener;
import fr.neatmonster.nocheatplus.command.CommandHandler;
import fr.neatmonster.nocheatplus.command.INotifyReload;
import fr.neatmonster.nocheatplus.compat.MCAccess;
import fr.neatmonster.nocheatplus.compat.MCAccessFactory;
import fr.neatmonster.nocheatplus.components.ComponentWithName;
import fr.neatmonster.nocheatplus.components.INeedConfig;
import fr.neatmonster.nocheatplus.components.NCPListener;
@ -85,6 +87,26 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI {
/** Names of players with a certain permission. */
protected static final NameSetPermState nameSetPerms = new NameSetPermState(Permissions.ADMINISTRATION_NOTIFY);
/** MCAccess instance. */
protected static MCAccess mcAccess = null;
/**
* Get the wrapper for accessing Minecraft properties.
* @return
*/
public static MCAccess getMCAccess(){
if (mcAccess == null) initMCAccess();
return mcAccess;
}
private static void initMCAccess() {
synchronized (NoCheatPlus.class) {
if (mcAccess != null) return;
mcAccess = new MCAccessFactory().getMCAccess();
}
LogUtil.logInfo("[NoCheatPlus] McAccess set to: " + mcAccess.getMCVersion() + " / " + mcAccess.getServerVersionTag());
}
/**
* Remove expired entries.
*/

View File

@ -5,8 +5,10 @@ import java.util.Map;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.NoCheatPlus;
import fr.neatmonster.nocheatplus.actions.ActionList;
import fr.neatmonster.nocheatplus.actions.ParameterName;
import fr.neatmonster.nocheatplus.compat.MCAccess;
import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager;
import fr.neatmonster.nocheatplus.hooks.NCPHookManager;
import fr.neatmonster.nocheatplus.metrics.MetricsData;
@ -46,6 +48,8 @@ public abstract class Check {
/** The type. */
protected final CheckType type;
protected final MCAccess mcAccess;
/**
* Instantiates a new check.
@ -55,6 +59,7 @@ public abstract class Check {
*/
public Check(final CheckType type) {
this.type = type;
mcAccess = NoCheatPlus.getMCAccess();
ViolationHistory.checkTypeMap.put(getClass().getName(), type);
DataManager.registerExecutionHistory(type, histories);
}

View File

@ -1,5 +1,7 @@
package fr.neatmonster.nocheatplus.checks;
import fr.neatmonster.nocheatplus.NoCheatPlus;
import fr.neatmonster.nocheatplus.compat.MCAccess;
import fr.neatmonster.nocheatplus.components.NCPListener;
/**
@ -12,6 +14,7 @@ public class CheckListener extends NCPListener{
/** Check group / type which this listener is for. */
protected final CheckType checkType;
protected final MCAccess mcAccess;
public CheckListener(){
this(null);
@ -19,6 +22,7 @@ public class CheckListener extends NCPListener{
public CheckListener(CheckType checkType){
this.checkType = checkType;
this.mcAccess = NoCheatPlus.getMCAccess();
}
@Override

View File

@ -1,8 +1,5 @@
package fr.neatmonster.nocheatplus.checks.combined;
import net.minecraft.server.EntityPlayer;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -52,10 +49,9 @@ public class CombinedListener extends CheckListener {
if (cc.invulnerableCheck && (cc.invulnerableTriggerAlways || cc.invulnerableTriggerFallDistance && player.getFallDistance() > 0)){
// TODO: maybe make a heuristic for small fall distances with ground under feet (prevents future abuse with jumping) ?
final EntityPlayer mcPlayer= ((CraftPlayer) player).getHandle();
final int ticks = cc.invulnerableInitialTicksJoin >= 0 ? cc.invulnerableInitialTicksJoin : mcPlayer.invulnerableTicks;
final int ticks = cc.invulnerableInitialTicksJoin >= 0 ? cc.invulnerableInitialTicksJoin : mcAccess.getInvulnerableTicks(player);
data.invulnerableTick = TickTask.getTick() + ticks;
mcPlayer.invulnerableTicks = 0;
mcAccess.setInvulnerableTicks(player, 0);
}
}

View File

@ -1,5 +1,6 @@
package fr.neatmonster.nocheatplus.checks.fight;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffectType;
@ -44,8 +45,9 @@ public class Critical extends Check {
boolean cancel = false;
// We'll need the PlayerLocation to know some important stuff.
final PlayerLocation location = new PlayerLocation();
location.set(player.getLocation(), player);
final Location loc = player.getLocation();
final PlayerLocation location = new PlayerLocation(mcAccess.getBlockCache(loc.getWorld()));
location.set(loc, player);
if (location.isIllegal()) {
location.cleanup();
CheckUtils.onIllegalMove(player);

View File

@ -1,9 +1,7 @@
package fr.neatmonster.nocheatplus.checks.fight;
import net.minecraft.server.Entity;
import net.minecraft.server.EntityComplexPart;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
@ -49,25 +47,29 @@ public class Direction extends Check {
// Safeguard, if entity is complex, this check will fail due to giant and hard to define hitboxes.
// if (damaged instanceof EntityComplex || damaged instanceof EntityComplexPart)
if (damaged instanceof EntityComplexPart)
if (mcAccess.isComplexPart(damaged))
return false;
// Find out how wide the entity is.
final float width = damaged.length > damaged.width ? damaged.length : damaged.width;
final double width = mcAccess.getWidthOrLength(damaged);
// entity.height is broken and will always be 0, therefore. Calculate height instead based on boundingBox.
final double height = damaged.boundingBox.e - damaged.boundingBox.b;
final double height = mcAccess.getHeight(damaged);
final Location dLoc = damaged.getLocation();
// TODO: allow any hit on the y axis (might just adapt interface to use foot position + height)!
// How far "off" is the player with his aim. We calculate from the players eye location and view direction to
// the center of the target entity. If the line of sight is more too far off, "off" will be bigger than 0.
final double off = CheckUtils.directionCheck(player, damaged.locX, damaged.locY + height / 2D, damaged.locZ,
final double off = CheckUtils.directionCheck(player, dLoc.getX(), dLoc.getY() + height / 2D, dLoc.getZ(),
width, height, 75);
if (off > 0.1) {
// Player failed the check. Let's try to guess how far he was from looking directly to the entity...
final Vector direction = player.getEyeLocation().getDirection();
final Vector blockEyes = new Location(player.getWorld(), damaged.locX, damaged.locY + height / 2D,
damaged.locZ).subtract(player.getEyeLocation()).toVector();
final Vector blockEyes = new Location(player.getWorld(), dLoc.getX(), dLoc.getY() + height / 2D,
dLoc.getZ()).subtract(player.getEyeLocation()).toVector();
final double distance = blockEyes.crossProduct(direction).length() / direction.length();
// Add the overall violation level of the check.

View File

@ -1,6 +1,5 @@
package fr.neatmonster.nocheatplus.checks.fight;
import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -76,7 +75,7 @@ public class FightListener extends CheckListener {
* The EntityDamageByEntityEvent
* @return
*/
private boolean handleNormalDamage(final Player player, final Entity cbEntity) {
private boolean handleNormalDamage(final Player player, final Entity damaged) {
final FightConfig cc = FightConfig.getConfig(player);
final FightData data = FightData.getData(player);
@ -91,14 +90,14 @@ public class FightListener extends CheckListener {
final String worldName = player.getWorld().getName();
// Check for self hit exploits (mind that projectiles should be excluded)
if (cbEntity instanceof Player){
final Player damagedPlayer = (Player) cbEntity;
if (damaged instanceof Player){
final Player damagedPlayer = (Player) damaged;
if (selfHit.isEnabled(player) && selfHit.check(player, damagedPlayer, data, cc))
cancelled = true;
}
if (cc.cancelDead){
if (cbEntity.isDead()) cancelled = true;
if (damaged.isDead()) cancelled = true;
// Only allow damaging others if taken damage this tick.
if (player.isDead() && data.damageTakenTick != TickTask.getTick()){
cancelled = true;
@ -109,9 +108,6 @@ public class FightListener extends CheckListener {
final boolean worldChanged = !worldName.equals(data.lastWorld);
// Get the attacked entity.
final net.minecraft.server.Entity damaged = ((CraftEntity) cbEntity).getHandle();
// Run through the main checks.
if (!cancelled && speed.isEnabled(player)){
if (speed.check(player, now))
@ -144,7 +140,7 @@ public class FightListener extends CheckListener {
if (!cancelled && noSwing.isEnabled(player) && noSwing.check(player))
cancelled = true;
if (!cancelled && reach.isEnabled(player) && reach.check(player, cbEntity))
if (!cancelled && reach.isEnabled(player) && reach.check(player, damaged))
cancelled = true;
if (!cancelled && player.isBlocking() && !player.hasPermission(Permissions.MOVING_SURVIVALFLY_BLOCKING))

View File

@ -1,9 +1,6 @@
package fr.neatmonster.nocheatplus.checks.fight;
import net.minecraft.server.EntityPlayer;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.NoCheatPlus;
@ -105,12 +102,10 @@ public class GodMode extends Check {
@Override
public void run() {
try {
final EntityPlayer entity = ((CraftPlayer) player).getHandle();
// Check again if the player should be dead, and if the game didn't mark him as dead.
if (entity.getHealth() <= 0 && !entity.dead) {
if (mcAccess.shouldBeZombie(player)){
// Artificially "kill" him.
entity.deathTicks = 19;
entity.dead = true;
mcAccess.setDead(player, 19);
}
} catch (final Exception e) {}
}

View File

@ -80,7 +80,7 @@ public class Reach extends Check {
// Reference locations to check distance for.
final Location dRef = damaged.getLocation();
final double height = CheckUtils.getHeight(damaged);
final double height = mcAccess.getHeight(damaged);
final Location pRef = player.getEyeLocation();
// Refine y position.

View File

@ -2,11 +2,7 @@ package fr.neatmonster.nocheatplus.checks.moving;
import java.util.Locale;
import net.minecraft.server.EntityPlayer;
import net.minecraft.server.MobEffectList;
import org.bukkit.Location;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.actions.ParameterName;
@ -76,12 +72,14 @@ public class CreativeFly extends Check {
final double hDistance = Math.sqrt(xDistance * xDistance + zDistance * zDistance);
// If the player is affected by potion of swiftness.
final EntityPlayer entity = ((CraftPlayer) player).getHandle();
final double limitH = cc.creativeFlyHorizontalSpeed
/ 100D
* HORIZONTAL_SPEED
* (entity.hasEffect(MobEffectList.FASTER_MOVEMENT) ? 1D + 0.2D * (entity.getEffect(
MobEffectList.FASTER_MOVEMENT).getAmplifier() + 1D) : 1D);
final double speedModifier = mcAccess.getFasterMovementAmplifier(player);
final double fSpeed;
if (speedModifier == Double.MIN_VALUE) fSpeed = 1D;
else fSpeed = 1D + 0.2D * (speedModifier + 1D);
final double limitH = cc.creativeFlyHorizontalSpeed / 100D * HORIZONTAL_SPEED * fSpeed;
// Finally, determine how far the player went beyond the set limits.
double resultH = Math.max(0.0D, hDistance - data.horizontalFreedom - limitH);

View File

@ -3,9 +3,6 @@ package fr.neatmonster.nocheatplus.checks.moving;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.server.EntityPlayer;
import net.minecraft.server.MobEffectList;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
@ -30,8 +27,8 @@ import org.bukkit.event.player.PlayerPortalEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.PlayerVelocityEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.event.player.PlayerVelocityEvent;
import org.bukkit.event.vehicle.VehicleMoveEvent;
import org.bukkit.util.Vector;
@ -75,9 +72,9 @@ import fr.neatmonster.nocheatplus.utilities.PlayerLocation;
public class MovingListener extends CheckListener{
private static final class MoveInfo{
public final PlayerLocation from = new PlayerLocation();
public final PlayerLocation to = new PlayerLocation();
public final BlockCache cache = new BlockCache();
public final BlockCache cache = NoCheatPlus.getMCAccess().getBlockCache(null);
public final PlayerLocation from = new PlayerLocation(null);
public final PlayerLocation to = new PlayerLocation(null);
/**
* Demands at least setting from.
* @param player
@ -87,7 +84,7 @@ public class MovingListener extends CheckListener{
*/
public final void set(final Player player, final Location from, final Location to, final double yOnGround){
this.from.set(from, player, yOnGround);
this.cache.setAccess(this.from.getWorldServer());
this.cache.setAccess(from.getWorld());
this.from.setBlockCache(cache);
if (to != null){
this.to.set(to, player, yOnGround);
@ -178,7 +175,7 @@ public class MovingListener extends CheckListener{
if (Math.abs(loc.getX() - 0.5 - block.getX()) <= 1D
&& Math.abs(loc.getZ() - 0.5 - block.getZ()) <= 1D
&& loc.getY() - blockY > 0D && loc.getY() - blockY < 2D
&& (BlockProperties.i(mat.getId()) || BlockProperties.isLiquid(mat.getId()))) {
&& (mcAccess.Block_i(mat.getId()) || BlockProperties.isLiquid(mat.getId()))) {
// The creative fly and/or survival fly check is enabled, the
// block was placed below the player and is
// solid, so do what we have to do.
@ -367,10 +364,9 @@ public class MovingListener extends CheckListener{
}
pFrom.collectBlockFlags(cc.noFallyOnGround);
pTo.collectBlockFlags(cc.noFallyOnGround);
final EntityPlayer mcPlayer = pFrom.getEntityPlayer();
// Potion effect "Jump".
final double jumpAmplifier = MovingListener.getJumpAmplifier(mcPlayer);
final double jumpAmplifier = MovingListener.getJumpAmplifier(player);
if (jumpAmplifier > 0D && cc.debug) System.out.println(player.getName() + " Jump effect: " + jumpAmplifier);
if (jumpAmplifier > data.jumpAmplifier) data.jumpAmplifier = jumpAmplifier;
@ -406,7 +402,7 @@ public class MovingListener extends CheckListener{
if ((cc.ignoreCreative || player.getGameMode() != GameMode.CREATIVE) && (cc.ignoreAllowFlight || !player.getAllowFlight())
&& cc.survivalFlyCheck && !NCPExemptionManager.isExempted(player, CheckType.MOVING_SURVIVALFLY) && !player.hasPermission(Permissions.MOVING_SURVIVALFLY)){
// If he is handled by the survival fly check, execute it.
newTo = survivalFly.check(player, mcPlayer, pFrom, pTo, data, cc);
newTo = survivalFly.check(player, pFrom, pTo, data, cc);
// Check NoFall if no reset is done.
if (cc.noFallCheck && !NCPExemptionManager.isExempted(player, CheckType.MOVING_NOFALL) && !player.hasPermission(Permissions.MOVING_NOFALL)) {
if (passableTo != null){
@ -472,7 +468,7 @@ public class MovingListener extends CheckListener{
{
// This might get extended to a check-like thing.
boolean restored = false;
final PlayerLocation pLoc = new PlayerLocation();
final PlayerLocation pLoc = new PlayerLocation(null);
// (Mind that we don't set the block cache here).
if (!restored && data.setBack != null) {
pLoc.set(data.setBack, player);
@ -846,14 +842,15 @@ public class MovingListener extends CheckListener{
}
/**
* Determine "some jump amplifier": 1 is jump boost, 2 is jump boost II.
* Determine "some jump amplifier": 1 is jump boost, 2 is jump boost II. <br>
* NOTE: This is not the original amplifier value (use mcAccess for that).
* @param mcPlayer
* @return
*/
public static final double getJumpAmplifier(final EntityPlayer mcPlayer) {
if (mcPlayer.hasEffect(MobEffectList.JUMP)) {
return 1D + mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier();
} else return 0D;
public static final double getJumpAmplifier(final Player player) {
final double amplifier = NoCheatPlus.getMCAccess().getJumpAmplifier(player);
if (amplifier == Double.MIN_VALUE) return 0D;
else return 1D + amplifier;
}
/**

View File

@ -1,10 +1,6 @@
package fr.neatmonster.nocheatplus.checks.moving;
import net.minecraft.server.DamageSource;
import net.minecraft.server.EntityPlayer;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
@ -50,32 +46,32 @@ public class NoFall extends Check {
* @param data
* @param y
*/
private static final void handleOnGround(final EntityPlayer mcPlayer, final MovingData data, final double y, final MovingConfig cc, final boolean reallyOnGround) {
private final void handleOnGround(final Player player, final MovingData data, final double y, final MovingConfig cc, final boolean reallyOnGround) {
// final int pD = getDamage(mcPlayer.fallDistance);
// final int nfD = getDamage(data.noFallFallDistance);
// final int yD = getDamage((float) (data.noFallMaxY - y));
// final int maxD = Math.max(Math.max(pD, nfD), yD);
final int maxD = getDamage(Math.max((float) (data.noFallMaxY - y), Math.max(data.noFallFallDistance, mcPlayer.fallDistance)));
final int maxD = getDamage(Math.max((float) (data.noFallMaxY - y), Math.max(data.noFallFallDistance, player.getFallDistance())));
if (maxD > 0){
// Damage to be dealt.
// TODO: more effects like sounds, maybe use custom event with violation added.
if (cc.debug) System.out.println(mcPlayer.name + " NoFall deal damage" + (reallyOnGround ? "" : "violation") + ": " + maxD);
if (cc.debug) System.out.println(player.getName() + " NoFall deal damage" + (reallyOnGround ? "" : "violation") + ": " + maxD);
// TODO: might not be necessary: if (mcPlayer.invulnerableTicks <= 0) [no damage event for resetting]
data.noFallSkipAirCheck = true;
dealFallDamage(mcPlayer, maxD);
dealFallDamage(player, maxD);
}
else data.clearNoFallData();
}
private static void dealFallDamage(EntityPlayer mcPlayer, int damage) {
final EntityDamageEvent event = new EntityDamageEvent(mcPlayer.getBukkitEntity(), DamageCause.FALL, damage);
private void dealFallDamage(final Player player, final int damage) {
final EntityDamageEvent event = new EntityDamageEvent(player, DamageCause.FALL, damage);
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()){
mcPlayer.damageEntity(DamageSource.FALL, event.getDamage());
mcAccess.dealFallDamage(player, event.getDamage());
}
// TODO: let this be done by the damage event (!).
// data.clearNoFallData(); // -> currently done in the damage eventhandling method.
mcPlayer.fallDistance = 0;
player.setFallDistance(0);
}
/**
@ -113,9 +109,6 @@ public class NoFall extends Check {
final boolean toOnGround = to.isOnGround();
final boolean toReset = to.isResetCond();
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
// TODO: early returns (...)
final double pY = player.getLocation().getY();
@ -127,9 +120,9 @@ public class NoFall extends Check {
}
else if (fromOnGround || data.noFallAssumeGround){
// Check if to deal damage (fall back damage check).
if (cc.noFallDealDamage) handleOnGround(mcPlayer, data, minY, cc, true);
if (cc.noFallDealDamage) handleOnGround(player, data, minY, cc, true);
else{
mcPlayer.fallDistance = Math.max(mcPlayer.fallDistance, Math.max(data.noFallFallDistance, (float) (data.noFallMaxY - minY)));
player.setFallDistance(Math.max(player.getFallDistance(), Math.max(data.noFallFallDistance, (float) (data.noFallMaxY - minY))));
data.clearNoFallData();
}
}
@ -143,9 +136,9 @@ public class NoFall extends Check {
// In this case the player has traveled further: add the difference.
data.noFallFallDistance -= yDiff;
}
if (cc.noFallDealDamage) handleOnGround(mcPlayer, data, minY, cc, true);
if (cc.noFallDealDamage) handleOnGround(player, data, minY, cc, true);
else{
mcPlayer.fallDistance = Math.max(mcPlayer.fallDistance, Math.max(data.noFallFallDistance, (float) (data.noFallMaxY - minY)));
player.setFallDistance(Math.max(player.getFallDistance(), Math.max(data.noFallFallDistance, (float) (data.noFallMaxY - minY))));
data.clearNoFallData();
}
}
@ -159,14 +152,14 @@ public class NoFall extends Check {
// TODO: fall distance might be behind (!)
// TODO: should be the data.noFallMaxY be counted in ?
data.noFallFallDistance = Math.max(mcPlayer.fallDistance, data.noFallFallDistance);
data.noFallFallDistance = Math.max(player.getFallDistance(), data.noFallFallDistance);
// Add y distance.
if (!toReset && !toOnGround && yDiff < 0){
data.noFallFallDistance -= yDiff;
}
if (cc.debug) System.out.println(player.getName() + " NoFall: mc=" + CheckUtils.fdec3.format(mcPlayer.fallDistance) +" / nf=" + CheckUtils.fdec3.format(data.noFallFallDistance) + (oldNFDist < data.noFallFallDistance ? " (+" + CheckUtils.fdec3.format(data.noFallFallDistance - oldNFDist) + ")" : ""));
if (cc.debug) System.out.println(player.getName() + " NoFall: mc=" + CheckUtils.fdec3.format(player.getFallDistance()) +" / nf=" + CheckUtils.fdec3.format(data.noFallFallDistance) + (oldNFDist < data.noFallFallDistance ? " (+" + CheckUtils.fdec3.format(data.noFallFallDistance - oldNFDist) + ")" : ""));
}
@ -193,9 +186,8 @@ public class NoFall extends Check {
*/
public void checkDamage(final Player player, final MovingData data, final double y) {
final MovingConfig cc = MovingConfig.getConfig(player);
// Deal damage.
handleOnGround(((CraftPlayer) player).getHandle(), data, y, cc, false);
handleOnGround(player, data, y, cc, false);
}
}

View File

@ -44,7 +44,7 @@ public class Passable extends Check {
if (from.isPassable()){
// From should be the set-back.
loc = null;
} else if (BlockProperties.isPassable(from.getBlockAccess(), loc.getX(), loc.getY(), loc.getZ(), from.getTypeId(lbX, lbY, lbZ))){
} else if (BlockProperties.isPassable(from.getBlockCache(), loc.getX(), loc.getY(), loc.getZ(), from.getTypeId(lbX, lbY, lbZ))){
// (Mind that this can be the case on the same block theoretically.)
// Keep loc as set-back.
}
@ -61,7 +61,7 @@ public class Passable extends Check {
}
// Prefer the set-back location from the data.
if (data.setBack != null && BlockProperties.isPassable(from.getBlockAccess(), data.setBack)) loc = data.setBack;
if (data.setBack != null && BlockProperties.isPassable(from.getBlockCache(), data.setBack)) loc = data.setBack;
// TODO: set data.set-back ? or something: still some aji here.

View File

@ -3,9 +3,6 @@ package fr.neatmonster.nocheatplus.checks.moving;
import java.util.ArrayList;
import java.util.Locale;
import net.minecraft.server.EntityPlayer;
import net.minecraft.server.MobEffectList;
import org.bukkit.Location;
import org.bukkit.entity.Player;
@ -75,7 +72,7 @@ public class SurvivalFly extends Check {
* the to
* @return the location
*/
public Location check(final Player player, final EntityPlayer mcPlayer, final PlayerLocation from, final PlayerLocation to, final MovingData data, final MovingConfig cc) {
public Location check(final Player player, final PlayerLocation from, final PlayerLocation to, final MovingData data, final MovingConfig cc) {
final long now = System.currentTimeMillis();
tags.clear();
// A player is considered sprinting if the flag is set and if he has enough food level.
@ -101,14 +98,14 @@ public class SurvivalFly extends Check {
// "Lost ground" workaround.
if (fromOnGround || from.isResetCond()) resetFrom = true;
else if (lostGround(player, mcPlayer, from, to, yDistance, data, cc)){
else if (lostGround(player, from, to, yDistance, data, cc)){
resetFrom = true;
// TODO: Consider && !resetTo ?
// Note: if not setting resetFrom, other places have to check assumeGround...
}
else resetFrom = false;
double hAllowedDistance = getAllowedhDist(player, mcPlayer, from, to, sprinting, hDistance, data, cc, false);
double hAllowedDistance = getAllowedhDist(player, from, to, sprinting, hDistance, data, cc, false);
// Account for flowing liquids (only if needed).
// Assume: If in fluids this would be placed right here.
@ -122,7 +119,7 @@ public class SurvivalFly extends Check {
// Tag for simple speed violation (medium), might get overridden.
if (hDistanceAboveLimit > 0){
// After failure permission checks ( + speed modifier + sneaking + blocking + speeding) !
hAllowedDistance = getAllowedhDist(player, mcPlayer, from, to, sprinting, hDistance, data, cc, true);
hAllowedDistance = getAllowedhDist(player, from, to, sprinting, hDistance, data, cc, true);
hDistanceAboveLimit = hDistance - hAllowedDistance - data.horizontalFreedom;
if (hAllowedDistance > 0){
tags.add("hspeed");
@ -287,7 +284,7 @@ public class SurvivalFly extends Check {
if (data.noFallAssumeGround || fromOnGround || toOnGround) {
// Some reset condition.
data.jumpAmplifier = MovingListener.getJumpAmplifier(mcPlayer);
data.jumpAmplifier = MovingListener.getJumpAmplifier(player);
}
// TODO: on ground -> on ground improvements
@ -347,7 +344,7 @@ public class SurvivalFly extends Check {
return null;
}
private boolean lostGround(final Player player, final EntityPlayer mcPlayer, final PlayerLocation from, final PlayerLocation to, final double yDistance, final MovingData data, final MovingConfig cc) {
private boolean lostGround(final Player player, final PlayerLocation from, final PlayerLocation to, final double yDistance, final MovingData data, final MovingConfig cc) {
// Don't set "useWorkaround = x()", to avoid potential trouble with
// reordering to come, and similar.
boolean useWorkaround = false;
@ -373,7 +370,7 @@ public class SurvivalFly extends Check {
final double minY = Math.min(data.toY, Math.min(data.fromY, from.getY()));
final double iY = minY; // TODO ...
final double r = from.getWidth() / 2.0;
if (BlockProperties.isOnGround(from.getBlockAccess(), Math.min(data.fromX, from.getX()) - r, iY - cc.yOnGround, Math.min(data.fromZ, from.getZ()) - r, Math.max(data.fromX, from.getX()) + r, iY + 0.25, Math.max(data.fromZ, from.getZ()) + r)) {
if (BlockProperties.isOnGround(from.getBlockCache(), Math.min(data.fromX, from.getX()) - r, iY - cc.yOnGround, Math.min(data.fromZ, from.getZ()) - r, Math.max(data.fromX, from.getX()) + r, iY + 0.25, Math.max(data.fromZ, from.getZ()) + r)) {
useWorkaround = true;
setBackSafe = true;
}
@ -388,7 +385,7 @@ public class SurvivalFly extends Check {
// data.ground ?
// ? set jumpphase to height / 0.15 ?
data.sfJumpPhase = 0;
data.jumpAmplifier = MovingListener.getJumpAmplifier(mcPlayer);
data.jumpAmplifier = mcAccess.getJumpAmplifier(player);
data.clearAccounting();
// Tell NoFall that we assume the player to have been on ground somehow.
data.noFallAssumeGround = true;
@ -410,7 +407,7 @@ public class SurvivalFly extends Check {
* @param cc
* @return
*/
private double getAllowedhDist(final Player player, final EntityPlayer mcPlayer, final PlayerLocation from, final PlayerLocation to, final boolean sprinting, final double hDistance, final MovingData data, final MovingConfig cc, boolean checkPermissions)
private double getAllowedhDist(final Player player, final PlayerLocation from, final PlayerLocation to, final boolean sprinting, final double hDistance, final MovingData data, final MovingConfig cc, boolean checkPermissions)
{
if (checkPermissions) tags.add("permchecks");
// TODO: re-arrange for fastest checks first (check vs. allowed distance
@ -448,7 +445,8 @@ public class SurvivalFly extends Check {
if (hDistance <= hAllowedDistance) return hAllowedDistance;
// Speed amplifier.
if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) hAllowedDistance *= 1.0D + 0.2D * (mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier() + 1);
final double speedAmplifier = mcAccess.getFasterMovementAmplifier(player);
if (speedAmplifier != Double.MIN_VALUE) hAllowedDistance *= 1.0D + 0.2D * (speedAmplifier + 1);
return hAllowedDistance;
}

View File

@ -5,12 +5,11 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandMap;
import org.bukkit.command.SimpleCommandMap;
import org.bukkit.craftbukkit.CraftServer;
import fr.neatmonster.nocheatplus.NoCheatPlus;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.utilities.LogUtil;
@ -23,7 +22,7 @@ public class CommandUtil {
public static CommandMap getCommandMap(){
// TODO: compat / null
try{
return (((CraftServer) Bukkit.getServer()).getCommandMap());
return NoCheatPlus.getMCAccess().getCommandMap();
}
catch(Throwable t){
LogUtil.logSevere(t);

View File

@ -0,0 +1,21 @@
package fr.neatmonster.nocheatplus.compat;
public enum AlmostBoolean{
YES(true),
NO(false),
MAYBE(false);
public static final AlmostBoolean match(final boolean value) {
return value ? YES : NO;
}
private final boolean decision;
private AlmostBoolean(final boolean decision){
this.decision = decision;
}
public boolean decide(){
return decision;
}
}

View File

@ -0,0 +1,111 @@
package fr.neatmonster.nocheatplus.compat;
import org.bukkit.World;
import org.bukkit.command.CommandMap;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.utilities.BlockCache;
/**
* Compatibility interface to get properties for Bukkit instances that need access of CraftBukkit or Minecraft classes.<br>
* NOTE: Expect API changes in the near future!
* <hr>
* TODO: Make minimal (do we need WorldServer yet)?
* @author mc_dev
*
*/
public interface MCAccess {
/**
* Simple version identifier like 1.4.
* @return
*/
public String getMCVersion();
/**
* Server version tag, like CB 2511.
* @return
*/
public String getServerVersionTag();
public CommandMap getCommandMap();
/**
* Get a BlockCache implementation.
* @param world May be null to store an instance of BlockCache for future use.
* @return
*/
public BlockCache getBlockCache(World world);
/**
* Get height of an entity (attack relevant, the maximal "thing" found).
*/
public double getHeight(Entity entity);
/**
* Return maximum.
* @param entity
* @return
*/
public double getWidthOrLength(Entity entity);
public AlmostBoolean isBlockSolid(int id);
public AlmostBoolean isBlockLiquid(int id);
/**
* Hiding the API access here.<br>
* // TODO: Replace by independent method.
* TODO: Find description of this and use block properties from here, as well as a speaking method name.<br>
* Assumption: This is something like "can stand on this type of block".
* @param id
* @return
*/
public boolean Block_i(int id);
/**
* Does only check y bounds, returns false if dead. this is half a check as auxiliary means for PlayerLocation.isIllegal.
* @param player
* @return null If undecided, true / false if decided.
*/
public Boolean isIllegalBounds(Player player);
/**
*
* @param player
* @return Double.MIN_VALUE if not present.
*/
public double getJumpAmplifier(Player player);
/**
*
* @return Double.MIN_VALUE if not present.
*/
public double getFasterMovementAmplifier(Player player);
public int getInvulnerableTicks(Player player);
public void setInvulnerableTicks(Player player, int ticks);
public void dealFallDamage(Player player, int damage);
public boolean isComplexPart(Entity damaged);
/**
* Tests if player is not set to dead but has no health.
* @param player
* @return
*/
public boolean shouldBeZombie(Player player);
/**
* Set flag + death ticks.
* @param player
* @param i
*/
public void setDead(Player player, int deathTicks);
}

View File

@ -0,0 +1,30 @@
package fr.neatmonster.nocheatplus.compat;
import fr.neatmonster.nocheatplus.compat.cb2511.MCAccessCB2511;
import fr.neatmonster.nocheatplus.compat.cb2512.MCAccessCB2512;
/**
* Factory class to hide potentially dirty stuff.
* @author mc_dev
*
*/
public class MCAccessFactory {
/**
* @throws RuntimeException if no access can be set.
* @return
*/
public MCAccess getMCAccess(){
try{
return new MCAccessCB2511();
}
catch(Throwable t){};
try{
return new MCAccessCB2512();
}
catch(Throwable t){};
throw new RuntimeException("Could not set up access to Minecraft API.");
}
}

View File

@ -0,0 +1,123 @@
package fr.neatmonster.nocheatplus.compat.cb2511;
import java.util.Iterator;
import java.util.List;
import net.minecraft.server.AxisAlignedBB;
import net.minecraft.server.IBlockAccess;
import net.minecraft.server.Material;
import net.minecraft.server.TileEntity;
import net.minecraft.server.Vec3DPool;
import org.bukkit.World;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import fr.neatmonster.nocheatplus.utilities.BlockCache;
public class BlockCacheCB2511 extends BlockCache implements IBlockAccess{
/** Box for one time use, no nesting, no extra storing this(!). */
protected static final AxisAlignedBB useBox = AxisAlignedBB.a(0, 0, 0, 0, 0, 0);
protected net.minecraft.server.World world;
public BlockCacheCB2511(World world) {
setAccess(world);
}
@Override
public void setAccess(World world) {
this.world = ((CraftWorld) world).getHandle();
}
@Override
public int fetchTypeId(int x, int y, int z) {
return world.getTypeId(x, y, z);
}
@Override
public int fetchData(int x, int y, int z) {
return world.getData(x, y, z);
}
@Override
public double[] fetchBounds(int x, int y, int z){
// TODO: change api for this / use nodes (!)
final int id = getTypeId(x, y, z);
final net.minecraft.server.Block block = net.minecraft.server.Block.byId[id];
block.updateShape(world, x, y, z); // TODO: use THIS instead of world.
// minX, minY, minZ, maxX, maxY, maxZ
return new double[]{block.v(), block.x(), block.z(), block.w(), block.y(), block.A()};
}
@Override
public boolean standsOnEntity(Entity entity, final double minX, final double minY, final double minZ, final double maxX, final double maxY, final double maxZ){
try{
// TODO: Probably check other ids too before doing this ?
final net.minecraft.server.Entity mcEntity = ((CraftEntity) entity).getHandle();
final AxisAlignedBB box = useBox.b(minX, minY, minZ, maxX, maxY, maxZ);
@SuppressWarnings("rawtypes")
final List list = world.getEntities(mcEntity, box);
@SuppressWarnings("rawtypes")
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
final net.minecraft.server.Entity other = (net.minecraft.server.Entity) iterator.next();
final EntityType type = other.getBukkitEntity().getType();
if (type != EntityType.BOAT && type != EntityType.MINECART) continue;
final AxisAlignedBB otherBox = other.boundingBox;
if (box.a > otherBox.d || box.d < otherBox.a || box.b > otherBox.e || box.e < otherBox.b || box.c > otherBox.f || box.f < otherBox.c) continue;
else {
return true;
}
}
}
catch (Throwable t){
// Ignore exceptions (Context: DisguiseCraft).
}
return false;
}
@Override
public Material getMaterial(final int x, final int y, final int z) {
return world.getMaterial(x, y, z);
}
@Override
public TileEntity getTileEntity(final int x, final int y, final int z) {
return world.getTileEntity(x, y, z);
}
@Override
public Vec3DPool getVec3DPool() {
return world.getVec3DPool();
}
@Override
public boolean isBlockFacePowered(final int arg0, final int arg1, final int arg2, final int arg3) {
return world.isBlockFacePowered(arg0, arg1, arg2, arg3);
}
@Override
public boolean t(final int x, final int y, final int z) {
return world.t(x, y, z);
}
/**
* Compatibility with 1.4.2.
* @param x
* @param y
* @param z
* @return
*/
public boolean s(final int x, final int y, final int z) {
return world.t(x, y, z);
}
}

View File

@ -0,0 +1,156 @@
package fr.neatmonster.nocheatplus.compat.cb2511;
import net.minecraft.server.AxisAlignedBB;
import net.minecraft.server.Block;
import net.minecraft.server.DamageSource;
import net.minecraft.server.EntityComplexPart;
import net.minecraft.server.EntityPlayer;
import net.minecraft.server.MobEffectList;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.CommandMap;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.compat.MCAccess;
import fr.neatmonster.nocheatplus.utilities.BlockCache;
public class MCAccessCB2511 implements MCAccess {
/**
* Constructor to let it fail in time.
*/
public MCAccessCB2511(){
getCommandMap();
}
@Override
public String getMCVersion() {
return "1.4";
}
@Override
public String getServerVersionTag() {
return "CB2511";
}
@Override
public BlockCache getBlockCache(World world) {
return new BlockCacheCB2511(world);
}
@Override
public CommandMap getCommandMap() {
return ((CraftServer) Bukkit.getServer()).getCommandMap();
}
@Override
public double getHeight(final Entity entity) {
final net.minecraft.server.Entity mcEntity = ((CraftEntity) entity).getHandle();
final double entityHeight = Math.max(mcEntity.height, mcEntity.boundingBox.e - mcEntity.boundingBox.b);
if (entity instanceof LivingEntity) {
return Math.max(((LivingEntity) entity).getEyeHeight(), entityHeight);
} else return entityHeight;
}
@Override
public AlmostBoolean isBlockSolid(final int id) {
final Block block = Block.byId[id];
if (block == null || block.material == null) return AlmostBoolean.MAYBE;
else return AlmostBoolean.match(block.material.isSolid());
}
@Override
public AlmostBoolean isBlockLiquid(final int id) {
final Block block = Block.byId[id];
if (block == null || block.material == null) return AlmostBoolean.MAYBE;
else return AlmostBoolean.match(block.material.isLiquid());
}
@Override
public boolean Block_i(final int id) {
try{
return Block.i(id);
}
catch(Throwable t){
// Minecraft default value.
return true;
}
}
@Override
public double getWidthOrLength(final Entity entity) {
final net.minecraft.server.Entity mcEntity = ((CraftEntity) entity).getHandle();
return Math.max(mcEntity.width, mcEntity.length);
}
@Override
public Boolean isIllegalBounds(final Player player) {
final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
if (entityPlayer.dead) return false;
final AxisAlignedBB box = entityPlayer.boundingBox;
if (!entityPlayer.isSleeping()){
// This can not really test stance but height of bounding box.
final double dY = Math.abs(box.e - box.b);
if (dY > 1.8) return true; // dY > 1.65D ||
if (dY < 0.1D) return true;
}
return null;
}
@Override
public double getJumpAmplifier(final Player player) {
final net.minecraft.server.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
if (mcPlayer.hasEffect(MobEffectList.JUMP)) return mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier();
else return Double.MIN_VALUE;
}
@Override
public double getFasterMovementAmplifier(final Player player) {
final net.minecraft.server.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) return mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier();
else return Double.MIN_VALUE;
}
@Override
public int getInvulnerableTicks(final Player player) {
return ((CraftPlayer) player).getHandle().invulnerableTicks;
}
@Override
public void setInvulnerableTicks(final Player player, final int ticks) {
((CraftPlayer) player).getHandle().invulnerableTicks = ticks;
}
@Override
public void dealFallDamage(final Player player, final int damage) {
((CraftPlayer) player).getHandle().damageEntity(DamageSource.FALL, damage);
}
@Override
public boolean isComplexPart(final Entity entity) {
return ((CraftEntity) entity).getHandle() instanceof EntityComplexPart;
}
@Override
public boolean shouldBeZombie(final Player player) {
final net.minecraft.server.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
return !mcPlayer.dead && mcPlayer.getHealth() <= 0 ;
}
@Override
public void setDead(final Player player, final int deathTicks) {
final net.minecraft.server.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
mcPlayer.deathTicks = deathTicks;
mcPlayer.dead = true;
}
}

View File

@ -0,0 +1,112 @@
package fr.neatmonster.nocheatplus.compat.cb2512;
import java.util.Iterator;
import java.util.List;
import net.minecraft.server.v1_4_5.AxisAlignedBB;
import net.minecraft.server.v1_4_5.IBlockAccess;
import net.minecraft.server.v1_4_5.Material;
import net.minecraft.server.v1_4_5.TileEntity;
import net.minecraft.server.v1_4_5.Vec3DPool;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_4_5.CraftWorld;
import org.bukkit.craftbukkit.v1_4_5.entity.CraftEntity;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import fr.neatmonster.nocheatplus.utilities.BlockCache;
public class BlockCacheCB2512 extends BlockCache implements IBlockAccess{ // TODO: let it implement IBlockAccess !
/** Box for one time use, no nesting, no extra storing this(!). */
protected static final AxisAlignedBB useBox = AxisAlignedBB.a(0, 0, 0, 0, 0, 0);
protected net.minecraft.server.v1_4_5.World world;
public BlockCacheCB2512(World world) {
setAccess(world);
}
@Override
public void setAccess(World world) {
this.world = ((CraftWorld) world).getHandle();
}
@Override
public int fetchTypeId(final int x, final int y, final int z) {
return world.getTypeId(x, y, z);
}
@Override
public int fetchData(final int x, final int y, final int z) {
return world.getData(x, y, z);
}
@Override
public double[] fetchBounds(final int x, final int y, final int z){
// TODO: change api for this / use nodes (!)
final int id = getTypeId(x, y, z);
final net.minecraft.server.v1_4_5.Block block = net.minecraft.server.v1_4_5.Block.byId[id];
block.updateShape(world, x, y, z); // TODO: use THIS instead of world.
// minX, minY, minZ, maxX, maxY, maxZ
return new double[]{block.v(), block.x(), block.z(), block.w(), block.y(), block.A()};
}
@Override
public boolean standsOnEntity(final Entity entity, final double minX, final double minY, final double minZ, final double maxX, final double maxY, final double maxZ){
try{
// TODO: Probably check other ids too before doing this ?
final net.minecraft.server.v1_4_5.Entity mcEntity = ((CraftEntity) entity).getHandle();
final AxisAlignedBB box = useBox.b(minX, minY, minZ, maxX, maxY, maxZ);
@SuppressWarnings("rawtypes")
final List list = world.getEntities(mcEntity, box);
@SuppressWarnings("rawtypes")
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
final net.minecraft.server.v1_4_5.Entity other = (net.minecraft.server.v1_4_5.Entity) iterator.next();
final EntityType type = other.getBukkitEntity().getType();
if (type != EntityType.BOAT && type != EntityType.MINECART) continue;
final AxisAlignedBB otherBox = other.boundingBox;
if (box.a > otherBox.d || box.d < otherBox.a || box.b > otherBox.e || box.e < otherBox.b || box.c > otherBox.f || box.f < otherBox.c) continue;
else {
return true;
}
}
}
catch (Throwable t){
// Ignore exceptions (Context: DisguiseCraft).
}
return false;
}
@Override
public Material getMaterial(final int x, final int y, final int z) {
return world.getMaterial(x, y, z);
}
@Override
public TileEntity getTileEntity(final int x, final int y, final int z) {
return world.getTileEntity(x, y, z);
}
@Override
public Vec3DPool getVec3DPool() {
return world.getVec3DPool();
}
@Override
public boolean isBlockFacePowered(final int arg0, final int arg1, final int arg2, final int arg3) {
return world.isBlockFacePowered(arg0, arg1, arg2, arg3);
}
@Override
public boolean t(final int x, final int y, final int z) {
return world.t(x, y, z);
}
}

View File

@ -0,0 +1,155 @@
package fr.neatmonster.nocheatplus.compat.cb2512;
import net.minecraft.server.v1_4_5.AxisAlignedBB;
import net.minecraft.server.v1_4_5.Block;
import net.minecraft.server.v1_4_5.DamageSource;
import net.minecraft.server.v1_4_5.EntityComplexPart;
import net.minecraft.server.v1_4_5.EntityPlayer;
import net.minecraft.server.v1_4_5.MobEffectList;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.CommandMap;
import org.bukkit.craftbukkit.v1_4_5.CraftServer;
import org.bukkit.craftbukkit.v1_4_5.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_4_5.entity.CraftPlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.compat.MCAccess;
import fr.neatmonster.nocheatplus.utilities.BlockCache;
public class MCAccessCB2512 implements MCAccess{
/**
* Constructor to let it fail.
*/
public MCAccessCB2512(){
getCommandMap();
}
@Override
public String getMCVersion() {
return "1.4";
}
@Override
public String getServerVersionTag() {
return "CB2512";
}
@Override
public CommandMap getCommandMap() {
return ((CraftServer) Bukkit.getServer()).getCommandMap();
}
@Override
public BlockCache getBlockCache(final World world) {
return new BlockCacheCB2512(world);
}
@Override
public double getHeight(final Entity entity) {
final net.minecraft.server.v1_4_5.Entity mcEntity = ((CraftEntity) entity).getHandle();
final double entityHeight = Math.max(mcEntity.height, mcEntity.boundingBox.e - mcEntity.boundingBox.b);
if (entity instanceof LivingEntity) {
return Math.max(((LivingEntity) entity).getEyeHeight(), entityHeight);
} else return entityHeight;
}
@Override
public AlmostBoolean isBlockSolid(final int id) {
final Block block = Block.byId[id];
if (block == null || block.material == null) return AlmostBoolean.MAYBE;
else return AlmostBoolean.match(block.material.isSolid());
}
@Override
public AlmostBoolean isBlockLiquid(final int id) {
final Block block = Block.byId[id];
if (block == null || block.material == null) return AlmostBoolean.MAYBE;
else return AlmostBoolean.match(block.material.isLiquid());
}
@Override
public boolean Block_i(final int id) {
try{
return Block.i(id);
}
catch(Throwable t){
// Minecraft default value.
return true;
}
}
@Override
public double getWidthOrLength(final Entity entity) {
final net.minecraft.server.v1_4_5.Entity mcEntity = ((CraftEntity) entity).getHandle();
return Math.max(mcEntity.width, mcEntity.length);
}
@Override
public Boolean isIllegalBounds(final Player player) {
final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
if (entityPlayer.dead) return false;
final AxisAlignedBB box = entityPlayer.boundingBox;
if (!entityPlayer.isSleeping()){
// This can not really test stance but height of bounding box.
final double dY = Math.abs(box.e - box.b);
if (dY > 1.8) return true; // dY > 1.65D ||
if (dY < 0.1D) return true;
}
return null;
}
@Override
public double getJumpAmplifier(final Player player) {
final net.minecraft.server.v1_4_5.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
if (mcPlayer.hasEffect(MobEffectList.JUMP)) return mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier();
else return Double.MIN_VALUE;
}
@Override
public double getFasterMovementAmplifier(final Player player) {
final net.minecraft.server.v1_4_5.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) return mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier();
else return Double.MIN_VALUE;
}
@Override
public int getInvulnerableTicks(final Player player) {
return ((CraftPlayer) player).getHandle().invulnerableTicks;
}
@Override
public void setInvulnerableTicks(final Player player, final int ticks) {
((CraftPlayer) player).getHandle().invulnerableTicks = ticks;
}
@Override
public void dealFallDamage(final Player player, final int damage) {
((CraftPlayer) player).getHandle().damageEntity(DamageSource.FALL, damage);
}
@Override
public boolean isComplexPart(final Entity entity) {
return ((CraftEntity) entity).getHandle() instanceof EntityComplexPart;
}
@Override
public boolean shouldBeZombie(final Player player) {
final net.minecraft.server.v1_4_5.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
return !mcPlayer.dead && mcPlayer.getHealth() <= 0 ;
}
@Override
public void setDead(final Player player, final int deathTicks) {
final net.minecraft.server.v1_4_5.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
mcPlayer.deathTicks = deathTicks;
mcPlayer.dead = true;
}
}

View File

@ -1,735 +0,0 @@
package fr.neatmonster.nocheatplus.net;
import java.lang.reflect.Field;
import net.minecraft.server.AxisAlignedBB;
import net.minecraft.server.EntityPlayer;
import net.minecraft.server.INetworkManager;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.NetServerHandler;
import net.minecraft.server.Packet;
import net.minecraft.server.Packet0KeepAlive;
import net.minecraft.server.Packet101CloseWindow;
import net.minecraft.server.Packet102WindowClick;
import net.minecraft.server.Packet106Transaction;
import net.minecraft.server.Packet107SetCreativeSlot;
import net.minecraft.server.Packet108ButtonClick;
import net.minecraft.server.Packet10Flying;
import net.minecraft.server.Packet130UpdateSign;
import net.minecraft.server.Packet13PlayerLookMove;
import net.minecraft.server.Packet14BlockDig;
import net.minecraft.server.Packet15Place;
import net.minecraft.server.Packet16BlockItemSwitch;
import net.minecraft.server.Packet18ArmAnimation;
import net.minecraft.server.Packet19EntityAction;
import net.minecraft.server.Packet202Abilities;
import net.minecraft.server.Packet203TabComplete;
import net.minecraft.server.Packet204LocaleAndViewDistance;
import net.minecraft.server.Packet205ClientCommand;
import net.minecraft.server.Packet250CustomPayload;
import net.minecraft.server.Packet255KickDisconnect;
import net.minecraft.server.Packet3Chat;
import net.minecraft.server.Packet7UseEntity;
import net.minecraft.server.Packet9Respawn;
import net.minecraft.server.ServerConnection;
import net.minecraft.server.WorldServer;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
/*
* M"""""""`YM MM'""""'YMM MM"""""""`YM M"""""""`YM dP MP""""""`MM
* M mmmm. M M' .mmm. `M MM mmmmm M M mmmm. M 88 M mmmmm..M
* M MMMMM M M MMMMMooM M' .M M MMMMM M .d8888b. d8888P M. `YM .d8888b. 88d888b. dP .dP .d8888b. 88d888b.
* M MMMMM M M MMMMMMMM MM MMMMMMMM M MMMMM M 88ooood8 88 MMMMMMM. M 88ooood8 88' `88 88 d8' 88ooood8 88' `88
* M MMMMM M M. `MMM' .M MM MMMMMMMM M MMMMM M 88. ... 88 M. .MMM' M 88. ... 88 88 .88' 88. ... 88
* M MMMMM M MM. .dM MM MMMMMMMM M MMMMM M `88888P' dP Mb. .dM `88888P' dP 8888P' `88888P' dP
* MMMMMMMMMMM MMMMMMMMMMM MMMMMMMMMMMM MMMMMMMMMMM MMMMMMMMMMM
*
* M""MMMMM""MM dP dP
* M MMMMM MM 88 88
* M `M .d8888b. 88d888b. .d888b88 88 .d8888b. 88d888b.
* M MMMMM MM 88' `88 88' `88 88' `88 88 88ooood8 88' `88
* M MMMMM MM 88. .88 88 88 88. .88 88 88. ... 88
* M MMMMM MM `88888P8 dP dP `88888P8 dP `88888P' dP
* MMMMMMMMMMMM
*/
/**
* A custom NetServerHandler used as a workaround to prevent CraftBukkit from blocking fly mods.
* @deprecated Needs updating.
*/
public class NCPNetServerHandler extends NetServerHandler {
/** The default stance of a player. */
private static final double STANCE = 1.6200000047683716D;
/**
* Sets the NetServerHandler of the player.
*
* @param player
* the player
* @param useProxy
* the use proxy
*/
public static void changeNetServerHandler(final Player player, final boolean useProxy) {
final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
final NetServerHandler vanillaNSH = entityPlayer.netServerHandler;
final NCPNetServerHandler customNSH = new NCPNetServerHandler(MinecraftServer.getServer(),
vanillaNSH.networkManager, entityPlayer, useProxy ? vanillaNSH : null);
customNSH.a(entityPlayer.locX, entityPlayer.locY, entityPlayer.locZ, entityPlayer.yaw, entityPlayer.pitch);
// TODO: MC method changed.
// MinecraftServer.getServer().ac().a(customNSH);
try {
final Field connectionsField = ServerConnection.class.getDeclaredField("d");
connectionsField.setAccessible(true);
// TODO: MC method changed.
// ((List<?>) connectionsField.get(MinecraftServer.getServer().ac())).remove(vanillaNSH);
} catch (final Exception e) {
e.printStackTrace();
}
vanillaNSH.disconnected = !useProxy;
}
private Field hField = null;
private final NetServerHandler netServerHandler;
private double bukkitX = Double.MAX_VALUE;
private double bukkitY = Double.MAX_VALUE;
private double bukkitZ = Double.MAX_VALUE;
private float bukkitPitch = Float.MAX_VALUE;
private float bukkitYaw = Float.MAX_VALUE;
private boolean checkMovement;
private int flyingPackets;
private boolean justTeleported = false;
private double vanillaX;
private double vanillaY;
private double vanillaZ;
/**
* Instantiates a new nCP net server handler.
*
* @param minecraftServer
* the minecraft server
* @param networkManager
* the network manager
* @param entityPlayer
* the entity player
* @param netServerHandler
* the net server handler
*/
public NCPNetServerHandler(final MinecraftServer minecraftServer, final INetworkManager networkManager,
final EntityPlayer entityPlayer, final NetServerHandler netServerHandler) {
super(minecraftServer, networkManager, entityPlayer);
this.netServerHandler = netServerHandler;
try {
hField = NetServerHandler.class.getDeclaredField("h");
hField.setAccessible(true);
} catch (final Exception e) {
e.printStackTrace();
}
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a()
*/
@Override
public boolean a() {
if (netServerHandler != null)
return netServerHandler.a();
return super.a();
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(double, double, double, float, float)
*/
@Override
public void a(final double d0, final double d1, final double d2, final float f, final float f1) {
if (netServerHandler != null)
netServerHandler.a(d0, d1, d2, f, f1);
else
super.a(d0, d1, d2, f, f1);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet0KeepAlive)
*/
@Override
public void a(final Packet0KeepAlive packet0KeepAlive) {
if (netServerHandler != null)
netServerHandler.a(packet0KeepAlive);
else
super.a(packet0KeepAlive);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet102WindowClick)
*/
@Override
public void a(final Packet102WindowClick packet102WindowClick) {
if (netServerHandler != null)
netServerHandler.a(packet102WindowClick);
else
super.a(packet102WindowClick);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet106Transaction)
*/
@Override
public void a(final Packet106Transaction packet106Transaction) {
if (netServerHandler != null)
netServerHandler.a(packet106Transaction);
else
super.a(packet106Transaction);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet107SetCreativeSlot)
*/
@Override
public void a(final Packet107SetCreativeSlot packet107SetCreativeSlot) {
if (netServerHandler != null)
netServerHandler.a(packet107SetCreativeSlot);
else
super.a(packet107SetCreativeSlot);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet108ButtonClick)
*/
@Override
public void a(final Packet108ButtonClick packet108ButtonClick) {
if (netServerHandler != null)
netServerHandler.a(packet108ButtonClick);
else
super.a(packet108ButtonClick);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet10Flying)
*/
@Override
public void a(final Packet10Flying packet10Flying) {
final WorldServer worldserver = MinecraftServer.getServer().getWorldServer(player.dimension);
try {
hField.set(netServerHandler == null ? this : netServerHandler, true);
} catch (final Exception e) {
e.printStackTrace();
}
if (!player.viewingCredits) {
double d0;
if (!checkMovement) {
d0 = packet10Flying.y - vanillaY;
if (packet10Flying.x == vanillaX && d0 * d0 < 0.01D && packet10Flying.z == vanillaZ)
checkMovement = true;
}
final Player bPlayer = getPlayer();
final Location from = new Location(bPlayer.getWorld(), bukkitX, bukkitY, bukkitZ, bukkitYaw, bukkitPitch);
final Location to = bPlayer.getLocation().clone();
if (packet10Flying.hasPos && (packet10Flying.y != -999.0D || packet10Flying.stance != -999.0D)) {
to.setX(packet10Flying.x);
to.setY(packet10Flying.y);
to.setZ(packet10Flying.z);
}
if (packet10Flying.hasLook) {
to.setYaw(packet10Flying.yaw);
to.setPitch(packet10Flying.pitch);
}
final double delta = Math.pow(bukkitX - to.getX(), 2) + Math.pow(bukkitY - to.getY(), 2)
+ Math.pow(bukkitZ - to.getZ(), 2);
final float deltaAngle = Math.abs(bukkitYaw - to.getYaw()) + Math.abs(bukkitPitch - to.getPitch());
if ((delta > 1f / 256 || deltaAngle > 10f) && checkMovement && !player.dead) {
bukkitX = to.getX();
bukkitY = to.getY();
bukkitZ = to.getZ();
bukkitYaw = to.getYaw();
bukkitPitch = to.getPitch();
if (from.getX() != Double.MAX_VALUE) {
final PlayerMoveEvent event = new PlayerMoveEvent(bPlayer, from, to);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
sendPacket(new Packet13PlayerLookMove(from.getX(), from.getY() + STANCE, from.getY(),
from.getZ(), from.getYaw(), from.getPitch(), false));
return;
}
if (!to.equals(event.getTo()) && !event.isCancelled()) {
player.getBukkitEntity().teleport(event.getTo(), PlayerTeleportEvent.TeleportCause.UNKNOWN);
return;
}
if (!from.equals(getPlayer().getLocation()) && justTeleported) {
justTeleported = false;
return;
}
}
}
if (Double.isNaN(packet10Flying.x) || Double.isNaN(packet10Flying.y) || Double.isNaN(packet10Flying.z)
|| Double.isNaN(packet10Flying.stance)) {
bPlayer.teleport(bPlayer.getWorld().getSpawnLocation(), PlayerTeleportEvent.TeleportCause.UNKNOWN);
System.err.println(bPlayer.getName()
+ " was caught trying to crash the server with an invalid position.");
bPlayer.kickPlayer("Nope!");
return;
}
if (checkMovement && !player.dead) {
double d1;
double d2;
double d3;
double d4;
if (player.vehicle != null) {
float f = player.yaw;
float f1 = player.pitch;
player.vehicle.V();
d1 = player.locX;
d2 = player.locY;
d3 = player.locZ;
double d5 = 0.0D;
d4 = 0.0D;
if (packet10Flying.hasLook) {
f = packet10Flying.yaw;
f1 = packet10Flying.pitch;
}
if (packet10Flying.hasPos && packet10Flying.y == -999.0D && packet10Flying.stance == -999.0D) {
if (Math.abs(packet10Flying.x) > 1 || Math.abs(packet10Flying.z) > 1) {
System.err.println(bPlayer.getName()
+ " was caught trying to crash the server with an invalid position.");
bPlayer.kickPlayer("Nope!");
return;
}
d5 = packet10Flying.x;
d4 = packet10Flying.z;
}
player.onGround = packet10Flying.g;
player.g();
player.move(d5, 0.0D, d4);
player.setLocation(d1, d2, d3, f, f1);
player.motX = d5;
player.motZ = d4;
if (player.vehicle != null)
worldserver.vehicleEnteredWorld(player.vehicle, true);
if (player.vehicle != null)
player.vehicle.V();
MinecraftServer.getServer().getServerConfigurationManager().d(player);
vanillaX = player.locX;
vanillaY = player.locY;
vanillaZ = player.locZ;
worldserver.playerJoinedWorld(player);
return;
}
if (player.isSleeping()) {
player.g();
player.setLocation(vanillaX, vanillaY, vanillaZ, player.yaw, player.pitch);
worldserver.playerJoinedWorld(player);
return;
}
d0 = player.locY;
vanillaX = player.locX;
vanillaY = player.locY;
vanillaZ = player.locZ;
d1 = player.locX;
d2 = player.locY;
d3 = player.locZ;
float f2 = player.yaw;
float f3 = player.pitch;
if (packet10Flying.hasPos && packet10Flying.y == -999.0D && packet10Flying.stance == -999.0D)
packet10Flying.hasPos = false;
if (packet10Flying.hasPos) {
d1 = packet10Flying.x;
d2 = packet10Flying.y;
d3 = packet10Flying.z;
d4 = packet10Flying.stance - packet10Flying.y;
if (!player.isSleeping() && (d4 > 1.65D || d4 < 0.1D)) {
disconnect("Illegal stance");
logger.warning(player.name + " had an illegal stance: " + d4);
return;
}
if (Math.abs(packet10Flying.x) > 3.2E7D || Math.abs(packet10Flying.z) > 3.2E7D) {
disconnect("Illegal position");
return;
}
}
if (packet10Flying.hasLook) {
f2 = packet10Flying.yaw;
f3 = packet10Flying.pitch;
}
player.g();
player.V = 0.0F;
player.setLocation(vanillaX, vanillaY, vanillaZ, f2, f3);
if (!checkMovement)
return;
d4 = d1 - player.locX;
double d6 = d2 - player.locY;
double d7 = d3 - player.locZ;
final float f4 = 0.0625F;
final boolean flag = worldserver.getCubes(player, player.boundingBox.clone().shrink(f4, f4, f4))
.isEmpty();
if (player.onGround && !packet10Flying.g && d6 > 0.0D)
player.j(0.2F);
player.move(d4, d6, d7);
player.onGround = packet10Flying.g;
player.checkMovement(d4, d6, d7);
final double d12 = d6;
d4 = d1 - player.locX;
d6 = d2 - player.locY;
if (d6 > -0.5D || d6 < 0.5D)
d6 = 0.0D;
d7 = d3 - player.locZ;
player.setLocation(d1, d2, d3, f2, f3);
final boolean flag2 = worldserver.getCubes(player, player.boundingBox.clone().shrink(f4, f4, f4))
.isEmpty();
if (flag && !flag2 && !player.isSleeping()) {
this.a(vanillaX, vanillaY, vanillaZ, f2, f3);
return;
}
final AxisAlignedBB axisalignedbb = player.boundingBox.clone().grow(f4, f4, f4).a(0.0D, -0.55D, 0.0D);
if (!MinecraftServer.getServer().getAllowFlight() && !player.abilities.canFly
&& !worldserver.c(axisalignedbb)) {
if (d12 >= -0.03125D) {
flyingPackets++;
if (flyingPackets > 80) {
logger.warning(player.name + " was kicked for floating too long!");
disconnect("Flying is not enabled on this server");
return;
}
}
} else
flyingPackets = 0;
player.onGround = packet10Flying.g;
MinecraftServer.getServer().getServerConfigurationManager().d(player);
if (player.itemInWorldManager.isCreative())
return;
player.b(player.locY - d0, packet10Flying.g);
}
}
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet130UpdateSign)
*/
@Override
public void a(final Packet130UpdateSign packet130UpdateSign) {
if (netServerHandler != null)
netServerHandler.a(packet130UpdateSign);
else
super.a(packet130UpdateSign);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet14BlockDig)
*/
@Override
public void a(final Packet14BlockDig packet14BlockDig) {
if (netServerHandler != null)
netServerHandler.a(packet14BlockDig);
else
super.a(packet14BlockDig);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet15Place)
*/
@Override
public void a(final Packet15Place packet15Place) {
if (netServerHandler != null)
netServerHandler.a(packet15Place);
else
super.a(packet15Place);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet16BlockItemSwitch)
*/
@Override
public void a(final Packet16BlockItemSwitch packet16BlockItemSwitch) {
if (netServerHandler != null)
netServerHandler.a(packet16BlockItemSwitch);
else
super.a(packet16BlockItemSwitch);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet18ArmAnimation)
*/
@Override
public void a(final Packet18ArmAnimation packet18ArmAnimation) {
if (netServerHandler != null)
netServerHandler.a(packet18ArmAnimation);
else
super.a(packet18ArmAnimation);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet19EntityAction)
*/
@Override
public void a(final Packet19EntityAction packet19EntityAction) {
if (netServerHandler != null)
netServerHandler.a(packet19EntityAction);
else
super.a(packet19EntityAction);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet202Abilities)
*/
@Override
public void a(final Packet202Abilities packet202Abilities) {
if (netServerHandler != null)
netServerHandler.a(packet202Abilities);
else
super.a(packet202Abilities);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet203TabComplete)
*/
@Override
public void a(final Packet203TabComplete packet203TabComplete) {
if (netServerHandler != null)
netServerHandler.a(packet203TabComplete);
else
super.a(packet203TabComplete);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet204LocaleAndViewDistance)
*/
@Override
public void a(final Packet204LocaleAndViewDistance packet204LocaleAndViewDistance) {
if (netServerHandler != null)
netServerHandler.a(packet204LocaleAndViewDistance);
else
super.a(packet204LocaleAndViewDistance);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet205ClientCommand)
*/
@Override
public void a(final Packet205ClientCommand packet205ClientCommand) {
if (netServerHandler != null)
netServerHandler.a(packet205ClientCommand);
else
super.a(packet205ClientCommand);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet250CustomPayload)
*/
@Override
public void a(final Packet250CustomPayload packet250CustomPayload) {
if (netServerHandler != null)
netServerHandler.a(packet250CustomPayload);
else
super.a(packet250CustomPayload);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet255KickDisconnect)
*/
@Override
public void a(final Packet255KickDisconnect packet255KickDisconnect) {
if (netServerHandler != null)
netServerHandler.a(packet255KickDisconnect);
else
super.a(packet255KickDisconnect);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet3Chat)
*/
@Override
public void a(final Packet3Chat packet3Chat) {
if (netServerHandler != null)
netServerHandler.a(packet3Chat);
else
super.a(packet3Chat);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet7UseEntity)
*/
@Override
public void a(final Packet7UseEntity packet7UseEntity) {
if (netServerHandler != null)
netServerHandler.a(packet7UseEntity);
else
super.a(packet7UseEntity);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(net.minecraft.server.Packet9Respawn)
*/
@Override
public void a(final Packet9Respawn packet9Respawn) {
if (netServerHandler != null)
netServerHandler.a(packet9Respawn);
else
super.a(packet9Respawn);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#a(java.lang.String, java.lang.Object[])
*/
@Override
public void a(final String s, final Object[] aobject) {
if (netServerHandler != null)
netServerHandler.a(s, aobject);
else
super.a(s, aobject);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#b()
*/
@Override
public boolean b() {
if (netServerHandler != null)
return netServerHandler.b();
return super.b();
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#chat(java.lang.String, boolean)
*/
@Override
public void chat(final String s, final boolean async) {
if (netServerHandler != null)
netServerHandler.chat(s, async);
else
super.chat(s, async);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#d()
*/
@Override
public void d() {
if (netServerHandler != null)
netServerHandler.d();
else
super.d();
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#disconnect(java.lang.String)
*/
@Override
public void disconnect(final String s) {
if (netServerHandler != null)
netServerHandler.disconnect(s);
else
super.disconnect(s);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#getPlayer()
*/
@Override
public CraftPlayer getPlayer() {
if (netServerHandler != null)
return netServerHandler.getPlayer();
return super.getPlayer();
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#handleContainerClose(net.minecraft.server.Packet101CloseWindow)
*/
@Override
public void handleContainerClose(final Packet101CloseWindow packet101CloseWindow) {
if (netServerHandler != null)
netServerHandler.handleContainerClose(packet101CloseWindow);
else
super.handleContainerClose(packet101CloseWindow);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#lowPriorityCount()
*/
@Override
public int lowPriorityCount() {
if (netServerHandler != null)
return netServerHandler.lowPriorityCount();
return super.lowPriorityCount();
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#onUnhandledPacket(net.minecraft.server.Packet)
*/
@Override
public void onUnhandledPacket(final Packet packet) {
if (netServerHandler != null)
netServerHandler.onUnhandledPacket(packet);
else
super.onUnhandledPacket(packet);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#sendPacket(net.minecraft.server.Packet)
*/
@Override
public void sendPacket(final Packet packet) {
if (netServerHandler != null)
netServerHandler.sendPacket(packet);
else
super.sendPacket(packet);
}
/* (non-Javadoc)
* @see net.minecraft.server.NetServerHandler#teleport(org.bukkit.Location)
*/
@Override
public void teleport(final Location dest) {
final double x = bukkitX = vanillaX = dest.getX();
final double y = bukkitY = vanillaY = dest.getY();
final double z = bukkitZ = vanillaZ = dest.getZ();
final float yaw = bukkitYaw = Float.isNaN(dest.getYaw()) ? 0f : dest.getYaw();
final float pitch = bukkitPitch = Float.isNaN(dest.getPitch()) ? 0f : dest.getPitch();
checkMovement = !(justTeleported = true);
player.setLocation(x, y, z, yaw, pitch);
sendPacket(new Packet13PlayerLookMove(x, y + STANCE, y, z, yaw, pitch, false));
}
}

View File

@ -1,13 +1,7 @@
package fr.neatmonster.nocheatplus.utilities;
import net.minecraft.server.Block;
import net.minecraft.server.IBlockAccess;
import net.minecraft.server.Material;
import net.minecraft.server.TileEntity;
import net.minecraft.server.Vec3DPool;
import org.bukkit.World;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.entity.Entity;
import fr.neatmonster.nocheatplus.utilities.ds.CoordMap;
@ -16,12 +10,7 @@ import fr.neatmonster.nocheatplus.utilities.ds.CoordMap;
* @author mc_dev
*
*/
public class BlockCache implements IBlockAccess{
/**
* For getting ids.
*/
private IBlockAccess access = null;
public abstract class BlockCache {
/** Cached type-ids. */
private final CoordMap<Integer> idMap = new CoordMap<Integer>();
@ -29,6 +18,11 @@ public class BlockCache implements IBlockAccess{
/** Cached data values. */
private final CoordMap<Integer> dataMap = new CoordMap<Integer>();
/** Cached shape values. */
private final CoordMap<double[]> boundsMap = new CoordMap<double[]>();
// TODO: switch to nodes with all details on, store a working node ?
// TODO: maybe make very fast access arrays for the ray tracing checks.
// private int[] id = null;
// private int[] data = null;
@ -40,94 +34,99 @@ public class BlockCache implements IBlockAccess{
setAccess(world);
}
public BlockCache(final IBlockAccess access){
setAccess(access);
}
/**
* Does not do cleanup.
* @param world
*/
public void setAccess(final World world){
setAccess(((CraftWorld) world).getHandle());
}
public abstract void setAccess(final World world);
/**
* Does not do cleanup.
* @param access
* Fetch the type id from the underlying world.
* @param x
* @param y
* @param z
* @return
*/
public void setAccess(final IBlockAccess access){
this.access = access;
}
public abstract int fetchTypeId(int x, int y, int z);
/**
* Fetch the data from the underlying world.
* @param x
* @param y
* @param z
* @return
*/
public abstract int fetchData(int x, int y, int z);
public abstract double[] fetchBounds(int x, int y, int z);
/**
* This is a on-ground type check just for standing on minecarts / boats.
* @param entity
* @param minX
* @param minY
* @param minZ
* @param maxX
* @param maxY
* @param maxZ
* @return
*/
public abstract boolean standsOnEntity(Entity entity, final double minX, final double minY, final double minZ, final double maxX, final double maxY, final double maxZ);
/**
* Remove references.
* Remove references.<br>
* NOTE: You must delete world references with this one.
*/
public void cleanup(){
access = null;
idMap.clear();
dataMap.clear();
boundsMap.clear();
}
@Override
/**
* Get type id with cache access.
* @param x
* @param y
* @param z
* @return
*/
public int getTypeId(final int x, final int y, final int z) {
final Integer pId = idMap.get(x, y, z);
if (pId != null) return pId;
final Integer nId = access.getTypeId(x, y, z);
final Integer nId = fetchTypeId(x, y, z);
idMap.put(x, y, z, nId);
return nId;
}
@Override
/**
* Get data value with cache access.
* @param x
* @param y
* @param z
* @return
*/
public int getData(final int x, final int y, final int z) {
final Integer pData = dataMap.get(x, y, z);
if (pData != null) return pData;
final Integer nData = access.getData(x, y, z);
final Integer nData = fetchData(x, y, z);
dataMap.put(x, y, z, nData);
return nData;
}
/**
* Not Optimized.
*/
@Override
public Material getMaterial(int arg0, int arg1, int arg2) {
return access.getMaterial(arg0, arg1, arg2);
}
/**
* Not optimized.
*/
@Override
public TileEntity getTileEntity(int arg0, int arg1, int arg2) {
return access.getTileEntity(arg0, arg1, arg2);
}
@Override
public Vec3DPool getVec3DPool() {
return access.getVec3DPool();
}
@Override
public boolean isBlockFacePowered(int arg0, int arg1, int arg2, int arg3) {
return access.isBlockFacePowered(arg0, arg1, arg2, arg3);
}
@Override
public boolean t(int x, int y, int z) {
// Routes to Block.i(getTypeId(x,y,z)) <- ominous i !
return access.t(x, y, z);
}
/**
* Compatibility: CB 1.4.2
* @param arg0
* @param arg1
* @param arg2
* @return
* Get block bounds
* @param x
* @param y
* @param z
* @return Array of floats (minX, minY, minZ, maxX, maxY, maxZ), may be null theoretically.
*/
public boolean s(int x, int y, int z) {
return Block.i(getTypeId(x, y, z));
public double[] getBounds(final int x, final int y, final int z){
final double[] pBounds = boundsMap.get(x, y, z);
if (pBounds != null) return pBounds;
final double[] nBounds = fetchBounds(x, y, z);
boundsMap.put(x, y, z, nBounds);
return nBounds;
}
}

View File

@ -6,10 +6,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import net.minecraft.server.AxisAlignedBB;
import net.minecraft.server.Block;
import net.minecraft.server.IBlockAccess;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
@ -19,6 +15,8 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffectType;
import fr.neatmonster.nocheatplus.NoCheatPlus;
import fr.neatmonster.nocheatplus.compat.MCAccess;
import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigFile;
@ -245,8 +243,8 @@ public class BlockProperties {
Material.POTATO,
};
private static BlockCache blockCache = new BlockCache();
private static final PlayerLocation pLoc = new PlayerLocation();
private static BlockCache blockCache = NoCheatPlus.getMCAccess().getBlockCache(null);
private static final PlayerLocation pLoc = new PlayerLocation(null);
protected static final long[] blockFlags = new long[maxBlocks];
@ -322,23 +320,21 @@ public class BlockProperties {
///////////////////////////
// Initalize block flags
///////////////////////////
final MCAccess mcAccess = NoCheatPlus.getMCAccess();
for (int i = 0; i <maxBlocks; i++){
blockFlags[i] = 0;
final net.minecraft.server.Block block = net.minecraft.server.Block.byId[i];
if (block != null){
if (block.material != null){
final net.minecraft.server.Material material = block.material;
if (material.isLiquid()){
// TODO: do not set F_GROUND for fluids ?
blockFlags[i] |= F_LIQUID;
if (material.isSolid()) blockFlags[i] |= F_SOLID;
}
else if (material.isSolid()){
blockFlags[i] |= F_SOLID | F_GROUND;
}
}
if (mcAccess.isBlockLiquid(i).decide()){
// TODO: do not set F_GROUND for fluids ?
blockFlags[i] |= F_LIQUID;
if (mcAccess.isBlockSolid(i).decide()) blockFlags[i] |= F_SOLID;
}
else if (mcAccess.isBlockSolid(i).decide()){
blockFlags[i] |= F_SOLID | F_GROUND;
}
}
// Stairs.
for (final Material mat : new Material[] { Material.NETHER_BRICK_STAIRS, Material.COBBLESTONE_STAIRS,
Material.SMOOTH_STAIRS, Material.BRICK_STAIRS, Material.SANDSTONE_STAIRS, Material.WOOD_STAIRS,
@ -887,24 +883,6 @@ public class BlockProperties {
return onGround;
}
/**
* Hiding the API access here.<br>
* TODO: Find description of this and use block properties from here, as well as a speaking method name.<br>
* Assumption: This is something like "can stand on this type of block".
* @param id
* @return
*/
public static final boolean i(final int id) {
// TODO: Replace by independent method.
try{
return Block.i(id);
}
catch(Throwable t){
// Minecraft default value.
return true;
}
}
public static final long getBLockFlags(final int id){
return blockFlags[id];
}
@ -962,25 +940,26 @@ public class BlockProperties {
* @param id
* @return
*/
public static final boolean isPassable(final IBlockAccess blockAccess, final double x, final double y, final double z, final int id){
public static final boolean isPassable(final BlockCache access, final double x, final double y, final double z, final int id){
// Simple exclusion check first.
if (isPassable(id)) return true;
// Check if the position is inside of a bounding box.
final int bx = Location.locToBlock(x);
final int by = Location.locToBlock(y);
final int bz = Location.locToBlock(z);
final net.minecraft.server.Block block = net.minecraft.server.Block.byId[id];
if (block == null) return true;
block.updateShape(blockAccess, bx, by, bz);
final double[] bounds = access.getBounds(bx, by, bz);
if (bounds == null) return true;
final double fx = x - bx;
final double fy = y - by;
final double fz = z - bz;
// if (fx < block.minX || fx >= block.maxX || fy < block.minY || fy >= block.maxY || fz < block.minZ || fz >= block.maxZ) return true;
if (fx < block.v() || fx >= block.w() || fy < block.x() || fy >= block.y() || fz < block.z() || fz >= block.A()) return true;
if (fx < bounds[0] || fx >= bounds[3] || fy < bounds[1] || fy >= bounds[4] || fz < bounds[2] || fz >= bounds[5]) return true;
else{
// Workarounds (might get generalized some time).
if (isStairs(id)){
if ((blockAccess.getData(bx, by, bz) & 0x4) != 0){
if ((access.getData(bx, by, bz) & 0x4) != 0){
if (fy < 0.5) return true;
}
else if (fy >= 0.5) return true;
@ -989,7 +968,7 @@ public class BlockProperties {
else if (id == Material.IRON_FENCE.getId() || id == Material.THIN_GLASS.getId()){
if (Math.abs(0.5 - fx) > 0.05 && Math.abs(0.5 - fz) > 0.05) return true;
}
else if (id == Material.FENCE_GATE.getId() && (blockAccess.getData(bx, by, bz) & 0x4)!= 0) return true;
else if (id == Material.FENCE_GATE.getId() && (access.getData(bx, by, bz) & 0x4)!= 0) return true;
else if (id == Material.CAKE_BLOCK.getId() && fy >= 0.4375) return true; // 0.0625 = 0.125 / 2
else if (id == Material.CAULDRON.getId()){
if (Math.abs(0.5 - fx) < 0.1 && Math.abs(0.5 - fz) < 0.1 && fy > 0.1) return true;
@ -1006,7 +985,7 @@ public class BlockProperties {
* @return
*/
public static final boolean isPassable(final PlayerLocation loc) {
return isPassable(loc.getBlockAccess(), loc.getX(), loc.getY(), loc.getZ(), loc.getTypeId());
return isPassable(loc.getBlockCache(), loc.getX(), loc.getY(), loc.getZ(), loc.getTypeId());
}
/**
@ -1015,8 +994,10 @@ public class BlockProperties {
* @return
*/
public static final boolean isPassable(final Location loc) {
final IBlockAccess access = ((org.bukkit.craftbukkit.CraftWorld) loc.getWorld()).getHandle();
return isPassable(access, loc.getX(), loc.getY(), loc.getZ(), access.getTypeId(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
blockCache.setAccess(loc.getWorld());
boolean res = isPassable(blockCache, loc.getX(), loc.getY(), loc.getZ(), blockCache.getTypeId(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
blockCache.cleanup();
return res;
}
/**
@ -1025,7 +1006,7 @@ public class BlockProperties {
* @param loc
* @return
*/
public static final boolean isPassable(final IBlockAccess access, final Location loc)
public static final boolean isPassable(final BlockCache access, final Location loc)
{
return isPassable(access, loc.getX(), loc.getY(), loc.getZ(), access.getTypeId(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
}
@ -1043,15 +1024,15 @@ public class BlockProperties {
}
}
/**
* Test if the bounding box overlaps with a block of given flags (does not check the blocks bounding box).
* @param box
* @param flags Block flags (@see fr.neatmonster.nocheatplus.utilities.BlockProperties).
* @return If any block has the flags.
*/
public static final boolean hasAnyFlags(final IBlockAccess access, final AxisAlignedBB box, final long flags){
return hasAnyFlags(access, box.a, box.b, box.c, box.d, box.e, box.f, flags);
}
// /**
// * Test if the bounding box overlaps with a block of given flags (does not check the blocks bounding box).
// * @param box
// * @param flags Block flags (@see fr.neatmonster.nocheatplus.utilities.BlockProperties).
// * @return If any block has the flags.
// */
// public static final boolean hasAnyFlags(final BlockCache access, final AxisAlignedBB box, final long flags){
// return hasAnyFlags(access, box.a, box.b, box.c, box.d, box.e, box.f, flags);
// }
/**
* Test if the bounding box overlaps with a block of given flags (does not check the blocks bounding box).
@ -1064,7 +1045,7 @@ public class BlockProperties {
* @param flags Block flags (@see fr.neatmonster.nocheatplus.utilities.BlockProperties).
* @return If any block has the flags.
*/
public static final boolean hasAnyFlags(final IBlockAccess access, final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ, final long flags){
public static final boolean hasAnyFlags(final BlockCache access, final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ, final long flags){
return hasAnyFlags(access, Location.locToBlock(minX), Location.locToBlock(minY), Location.locToBlock(minZ), Location.locToBlock(maxX), Location.locToBlock(maxY), Location.locToBlock(maxZ), flags);
}
@ -1080,7 +1061,7 @@ public class BlockProperties {
* @param flags Block flags (@see fr.neatmonster.nocheatplus.utilities.BlockProperties).
* @return If any block has the flags.
*/
public static final boolean hasAnyFlags(final IBlockAccess access,final int minX, int minY, final int minZ, final int maxX, final int maxY, final int maxZ, final long flags){
public static final boolean hasAnyFlags(final BlockCache access,final int minX, int minY, final int minZ, final int maxX, final int maxY, final int maxZ, final long flags){
for (int x = minX; x <= maxX; x++){
for (int z = minZ; z <= maxZ; z++){
for (int y = minY; y <= maxY; y++){
@ -1091,15 +1072,15 @@ public class BlockProperties {
return false;
}
/**
* Test if the box collide with any block that matches the flags somehow.
* @param box
* @param flags
* @return
*/
public static final boolean collides(final IBlockAccess access, final AxisAlignedBB box, final long flags){
return collides(access, box.a, box.b, box.c, box.d, box.e, box.f, flags);
}
// /**
// * Test if the box collide with any block that matches the flags somehow.
// * @param box
// * @param flags
// * @return
// */
// public static final boolean collides(final BlockCache access, final AxisAlignedBB box, final long flags){
// return collides(access, box.a, box.b, box.c, box.d, box.e, box.f, flags);
// }
/**
* Test if the box collide with any block that matches the flags somehow.
@ -1112,7 +1093,7 @@ public class BlockProperties {
* @param flags
* @return
*/
public static final boolean collides(final IBlockAccess access, final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ, final long flags){
public static final boolean collides(final BlockCache access, final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ, final long flags){
final int iMinX = Location.locToBlock(minX);
final int iMaxX = Location.locToBlock(maxX);
// At least find fences etc. if searched for.
@ -1147,7 +1128,7 @@ public class BlockProperties {
* @param id
* @return
*/
public static final boolean collidesId(final IBlockAccess access, final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ, final int id){
public static final boolean collidesId(final BlockCache access, final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ, final int id){
final int iMinX = Location.locToBlock(minX);
final int iMaxX = Location.locToBlock(maxX);
final int iMinY = Location.locToBlock(minY - ((blockFlags[id] & F_HEIGHT150) != 0 ? 0.5625 : 0));
@ -1178,7 +1159,7 @@ public class BlockProperties {
* @param id
* @return
*/
public static final boolean collidesBlock(final IBlockAccess access, final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ, final int id){
public static final boolean collidesBlock(final BlockCache access, final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ, final int id){
final int iMinX = Location.locToBlock(minX);
final int iMaxX = Location.locToBlock(maxX);
final int iMinY = Location.locToBlock(minY - ((blockFlags[id] & F_HEIGHT150) != 0 ? 0.5625 : 0));
@ -1210,16 +1191,15 @@ public class BlockProperties {
* @param maxZ
* @param id
*/
public static final boolean collidesBlock(final IBlockAccess access, final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ, final int x, final int y, final int z, final int id){
public static final boolean collidesBlock(final BlockCache access, final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ, final int x, final int y, final int z, final int id){
// TODO: use internal block data unless delegation wanted?
final Block block = Block.byId[id];
if (block == null) return false; // TODO: policy ?
block.updateShape(access, x, y, z);
final double[] bounds = access.getBounds(x,y,z);
if (bounds == null) return false; // TODO: policy ?
final long flags = blockFlags[id];
final double bminX, bminZ, bminY;
final double bmaxX, bmaxY, bmaxZ;
bmaxX = block.w(); // maxX
bmaxZ = block.A(); // maxZ
bmaxX = bounds[3]; //block.w(); // maxX
bmaxZ = bounds[5]; //block.A(); // maxZ
if ((flags & F_STAIRS) != 0){
// Mainly for on ground style checks, would not go too well with passable.
// TODO: change this to something like F_FULLBOX probably.
@ -1227,9 +1207,9 @@ public class BlockProperties {
bmaxY = 1D;
}
else{
bminX = block.v(); // minX
bminY = block.x(); // minY
bminZ = block.z(); // minZ
bminX = bounds[0]; // block.v(); // minX
bminY = bounds[1]; // block.x(); // minY
bminZ = bounds[2]; // block.z(); // minZ
if (id == Material.SNOW.getId()){
// TODO: remove / solve differently ?
final int data = (access.getData(x, y, z) & 0xF) % 8;
@ -1237,7 +1217,7 @@ public class BlockProperties {
}
else if (( flags & F_HEIGHT150) != 0) bmaxY = 1.5;
else if ((flags & F_HEIGHT100) != 0) bmaxY = 1.0;
else bmaxY = block.y(); // maxY
else bmaxY = bounds[4]; // block.y(); // maxY
}
if (minX > bmaxX + x || maxX < bminX + x) return false;
else if (minY > bmaxY + y || maxY < bminY + y) return false;
@ -1258,7 +1238,7 @@ public class BlockProperties {
* @param maxZ
* @return
*/
public static final boolean isOnGround(final IBlockAccess access, final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ){
public static final boolean isOnGround(final BlockCache access, final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ){
final int iMinX = Location.locToBlock(minX);
final int iMaxX = Location.locToBlock(maxX);
final int iMinY = Location.locToBlock(minY - 0.5626);
@ -1302,7 +1282,7 @@ public class BlockProperties {
* @param dZ
* @return
*/
public static final boolean isDownStream(final IBlockAccess access, final int x, final int y, final int z, final int data,
public static final boolean isDownStream(final BlockCache access, final int x, final int y, final int z, final int data,
final double dX, final double dZ) {
// x > 0 -> south, z > 0 -> west
if ((data & 0x8) == 0){
@ -1357,7 +1337,7 @@ public class BlockProperties {
* @param maxZ
* @return
*/
public static final long collectFlagsSimple(final IBlockAccess access, final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ){
public static final long collectFlagsSimple(final BlockCache access, final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ){
final int iMinX = Location.locToBlock(minX);
final int iMaxX = Location.locToBlock(maxX);
final int iMinY = Location.locToBlock(minY);

View File

@ -9,12 +9,12 @@ import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import fr.neatmonster.nocheatplus.NoCheatPlus;
/**
* Random auxiliary gear, some might have general quality.
*/
@ -346,16 +346,12 @@ public class CheckUtils {
/**
* Get the height from getLocation().getY() to head / above head.<br>
* NOTE: Currently this is pretty much useless, it returns 1.0 most of the time.
*
* @deprecated This has been moved to MCAccess (compat).
* @param entity
* @return
*/
public static double getHeight(final Entity entity) {
final net.minecraft.server.Entity mcEntity = ((CraftEntity) entity).getHandle();
final double entityHeight = mcEntity.height;
if (entity instanceof LivingEntity) {
return Math.max(((LivingEntity) entity).getEyeHeight(), entityHeight);
} else return mcEntity.height;
return NoCheatPlus.getMCAccess().getHeight(entity);
}
public static void onIllegalMove(final Player player){

View File

@ -1,23 +1,13 @@
package fr.neatmonster.nocheatplus.utilities;
import java.util.Iterator;
import java.util.List;
import net.minecraft.server.AxisAlignedBB;
import net.minecraft.server.Entity;
import net.minecraft.server.EntityPlayer;
import net.minecraft.server.IBlockAccess;
import net.minecraft.server.WorldServer;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import fr.neatmonster.nocheatplus.NoCheatPlus;
/*
* MM"""""""`YM dP
* MM mmmmm M 88
@ -42,9 +32,6 @@ import org.bukkit.util.Vector;
*/
public class PlayerLocation {
/** Box for one time use, no nesting, no extra storing this(!). */
protected static final AxisAlignedBB useBox = AxisAlignedBB.a(0, 0, 0, 0, 0, 0);
/** Type id of the block at the position. */
private Integer typeId;
@ -88,25 +75,29 @@ public class PlayerLocation {
private float yaw, pitch;
// Members that need cleanup:
/** The entityPlayer player. */
private EntityPlayer entityPlayer;
private double width;
/** Bounding box of the player. */
private double minX, maxX, minY, maxY, minZ, maxZ;
// Members that need cleanup //
/** The player ! */
private Player player;
/** Bukkit world. */
private World world;
/** The worldServer. */
private WorldServer worldServer;
/** Optional block property cache. */
private BlockCache blockCache;
/** All block flags collected for maximum used bounds. */
private Long blockFlags;
public PlayerLocation(final BlockCache blockCache){
this.blockCache = blockCache;
}
/**
* Gets the location.
@ -167,7 +158,7 @@ public class PlayerLocation {
}
public double getWidth() {
return entityPlayer.width;
return width;
}
public int getBlockX() {
@ -245,7 +236,7 @@ public class PlayerLocation {
}
// TODO: Distinguish based on actual height off .0 ?
final double diff = 0.001;
aboveStairs = BlockProperties.collides(getBlockAccess(), minX - diff, minY - 1.0, minZ - diff, maxX + diff, minY + 0.25, maxZ + diff, BlockProperties.F_STAIRS);
aboveStairs = BlockProperties.collides(blockCache, minX - diff, minY - 1.0, minZ - diff, maxX + diff, minY + 0.25, maxZ + diff, BlockProperties.F_STAIRS);
}
return aboveStairs;
}
@ -264,7 +255,7 @@ public class PlayerLocation {
final double dX = -0.10000000149011612D;
final double dY = -0.40000000596046448D;
final double dZ = dX;
inLava = BlockProperties.collides(getBlockAccess(), minX - dX, minY - dY, minZ - dZ, maxX + dX, maxY + dY, maxZ + dZ, BlockProperties.F_LAVA);
inLava = BlockProperties.collides(blockCache, minX - dX, minY - dY, minZ - dZ, maxX + dX, maxY + dY, maxZ + dZ, BlockProperties.F_LAVA);
}
return inLava;
}
@ -283,7 +274,7 @@ public class PlayerLocation {
final double dX = -0.001D;
final double dY = -0.40000000596046448D - 0.001D;
final double dZ = -0.001D;
inWater = BlockProperties.collides(getBlockAccess(), minX - dX, minY - dY, minZ - dZ, maxX + dX, maxY + dY, maxZ + dZ, BlockProperties.F_WATER);
inWater = BlockProperties.collides(blockCache, minX - dX, minY - dY, minZ - dZ, maxX + dX, maxY + dY, maxZ + dZ, BlockProperties.F_WATER);
}
return inWater;
}
@ -306,9 +297,8 @@ public class PlayerLocation {
*/
public boolean isOnIce() {
if (onIce == null) {
final org.bukkit.entity.Player entity = this.entityPlayer.getBukkitEntity();
// TODO: Use a box here too ?
if (entity.isSneaking() || entity.isBlocking()) onIce = getTypeId(blockX, Location.locToBlock(minY - 0.1D), blockZ) == Material.ICE.getId();
if (player.isSneaking() || player.isBlocking()) onIce = getTypeId(blockX, Location.locToBlock(minY - 0.1D), blockZ) == Material.ICE.getId();
else onIce = getTypeIdBelow().intValue() == Material.ICE.getId();
}
return onIce;
@ -354,7 +344,7 @@ public class PlayerLocation {
public boolean isInWeb() {
if (inWeb == null) {
final double inset = 0.001d;
inWeb = BlockProperties.collidesId(getBlockAccess(), minX + inset, minY + inset, minZ + inset, maxX - inset, maxY - inset, maxZ - inset, Material.WEB.getId());
inWeb = BlockProperties.collidesId(blockCache, minX + inset, minY + inset, minZ + inset, maxX - inset, maxY - inset, maxZ - inset, Material.WEB.getId());
}
return inWeb;
}
@ -368,37 +358,15 @@ public class PlayerLocation {
if (onGround == null) {
final double d0 = 0; //0.001D;
if (blockFlags == null || (blockFlags.longValue() & BlockProperties.F_GROUND) != 0){
final IBlockAccess access = getBlockAccess();
if (BlockProperties.collidesBlock(access, x, minY - yOnGround, z, x, minY + 0.25, z, blockX, blockY, blockZ, getTypeId())){
if (BlockProperties.collidesBlock(blockCache, x, minY - yOnGround, z, x, minY + 0.25, z, blockX, blockY, blockZ, getTypeId())){
onGround = true;
}
else onGround = BlockProperties.isOnGround(access, minX - d0, minY - yOnGround, minZ - d0, maxX + d0, minY + 0.25, maxZ + d0);
else onGround = BlockProperties.isOnGround(blockCache, minX - d0, minY - yOnGround, minZ - d0, maxX + d0, minY + 0.25, maxZ + d0);
}
else onGround = false;
if (!onGround) {
try{
// TODO: Probably check other ids too before doing this ?
final double d1 = 0.25D;
final AxisAlignedBB box = useBox.b(minX - d1, minY - getyOnGround() - d1, minZ - d1, maxX + d1, minY + 0.25 + d1, maxZ + d1);
@SuppressWarnings("rawtypes")
final List list = worldServer.getEntities(entityPlayer, box);
@SuppressWarnings("rawtypes")
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
final Entity entity = (Entity) iterator.next();
final EntityType type = entity.getBukkitEntity().getType();
if (type != EntityType.BOAT && type != EntityType.MINECART) continue;
final AxisAlignedBB otherBox = entity.boundingBox;
if (box.a > otherBox.d || box.d < otherBox.a || box.b > otherBox.e || box.e < otherBox.b || box.c > otherBox.f || box.f < otherBox.c) continue;
else {
onGround = true;
break;
}
}
}
catch (Throwable t){
// Ignore exceptions (Context: DisguiseCraft).
}
final double d1 = 0.25D;
onGround = blockCache.standsOnEntity(player, minX - d1, minY - getyOnGround() - d1, minZ - d1, maxX + d1, minY + 0.25 + d1, maxZ + d1);
}
}
return onGround;
@ -428,7 +396,7 @@ public class PlayerLocation {
* @return
*/
public boolean isPassable() {
if (passable == null) passable = BlockProperties.isPassable(getBlockAccess(), x, y, z, getTypeId());
if (passable == null) passable = BlockProperties.isPassable(blockCache, x, y, z, getTypeId());
return passable;
}
@ -441,7 +409,7 @@ public class PlayerLocation {
*/
public boolean isDownStream(final double xDistance, final double zDistance)
{
return BlockProperties.isDownStream(getBlockAccess(), blockX, blockY, blockZ, getData(), xDistance, zDistance);
return BlockProperties.isDownStream(blockCache, blockX, blockY, blockZ, getData(), xDistance, zDistance);
}
public Integer getTypeId() {
@ -468,7 +436,7 @@ public class PlayerLocation {
* @return
*/
public final int getTypeId(final int x, final int y, final int z) {
return blockCache == null ? worldServer.getTypeId(x, y, z) : blockCache.getTypeId(x, y, z);
return blockCache.getTypeId(x, y, z);
}
/**
@ -480,11 +448,7 @@ public class PlayerLocation {
* @return
*/
public final int getData(final int x, final int y, final int z) {
return blockCache == null ? worldServer.getData(x, y, z) : blockCache.getData(x, y, z);
}
public WorldServer getWorldServer() {
return worldServer;
return blockCache.getData(x, y, z);
}
/**
@ -497,11 +461,11 @@ public class PlayerLocation {
}
/**
*
* Get the underlying BLockCache.
* @return
*/
public final IBlockAccess getBlockAccess() {
return blockCache == null ? worldServer : blockCache;
public final BlockCache getBlockCache() {
return blockCache;
}
/**
@ -528,7 +492,7 @@ public class PlayerLocation {
{
// Entity reference.
entityPlayer = ((CraftPlayer) player).getHandle();
this.player = player;
// Set coordinates.
blockX = location.getBlockX();
@ -551,7 +515,9 @@ public class PlayerLocation {
// maxY = y + entityPlayer.boundingBox.e + dY;
// maxZ = z + entityPlayer.boundingBox.f + dZ;
// // TODO: inset, outset ?
final double dxz = entityPlayer.width/2;
this.width = NoCheatPlus.getMCAccess().getWidthOrLength(player);
final double dxz = this.width / 2;
// final double dX = (entityPlayer.boundingBox.d - entityPlayer.boundingBox.a) / 2D;
// final double dY = entityPlayer.boundingBox.e - entityPlayer.boundingBox.b;
// final double dZ = (entityPlayer.boundingBox.f - entityPlayer.boundingBox.c) / 2D;
@ -565,7 +531,6 @@ public class PlayerLocation {
// Set world / block access.
world = location.getWorld();
worldServer = ((CraftWorld) world).getHandle();
// Reset cached values.
typeId = typeIdBelow = data = null;
@ -584,16 +549,15 @@ public class PlayerLocation {
* @param maxYonGround
*/
public void collectBlockFlags(double maxYonGround){
blockFlags = BlockProperties.collectFlagsSimple(getBlockAccess(), minX - 0.001, minY - Math.max(Math.max(1.0, yOnGround), maxYonGround), minZ - 0.001, maxX + 0.001, maxY + .25, maxZ + .001);
blockFlags = BlockProperties.collectFlagsSimple(blockCache, minX - 0.001, minY - Math.max(Math.max(1.0, yOnGround), maxYonGround), minZ - 0.001, maxX + 0.001, maxY + .25, maxZ + .001);
}
/**
* Set some references to null.
*/
public void cleanup() {
entityPlayer = null;
player = null;
world = null;
worldServer = null;
blockCache = null; // No reset here.
}
@ -603,21 +567,11 @@ public class PlayerLocation {
* @return
*/
public boolean isIllegal() {
if (entityPlayer.dead) return false;
AxisAlignedBB box = entityPlayer.boundingBox;
if (!entityPlayer.isSleeping()){
// This can not really test stance but height of bounding box.
final double dY = Math.abs(box.e - box.b);
if (dY > 1.8) return true; // dY > 1.65D ||
if (dY < 0.1D) return true;
}
if (Math.abs(minX) > 3.2E7D || Math.abs(maxX) > 3.2E7D || Math.abs(minY) > 3.2E7D || Math.abs(maxY) > 3.2E7D || Math.abs(minZ) > 3.2E7D || Math.abs(maxZ) > 3.2E7D) return true;
final Boolean spec = NoCheatPlus.getMCAccess().isIllegalBounds(player);
if (spec != null) return spec.booleanValue();
else if (Math.abs(minX) > 3.2E7D || Math.abs(maxX) > 3.2E7D || Math.abs(minY) > 3.2E7D || Math.abs(maxY) > 3.2E7D || Math.abs(minZ) > 3.2E7D || Math.abs(maxZ) > 3.2E7D) return true;
// if (Math.abs(box.a) > 3.2E7D || Math.abs(box.b) > 3.2E7D || Math.abs(box.c) > 3.2E7D || Math.abs(box.d) > 3.2E7D || Math.abs(box.e) > 3.2E7D || Math.abs(box.f) > 3.2E7D) return true;
return false;
}
public EntityPlayer getEntityPlayer() {
return entityPlayer;
else return false;
}
}