[Bleeding]Add fight.visible
Similar to blockinteract.visible, not a precise ray-cast but likely to provide more compatibility with bedrock later on. Look independent! * Known bypass: - Behind the door(at the door block) - Bottom/behind slab and trapdoor * Known false positive: - ...Waiting for report! * Might-Missing: - BlockChangeTracker? Will fix in next build or so, for now just rest a bit for fully update to 1.20.4.
This commit is contained in:
1 parent
349c96b9ef
commit
9dc3e81f46
13 files changed
+374
-215
No files matched your search
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package fr.neatmonster.nocheatplus.utilities.ds.map;
|
||||
|
||||
public class BlockCoord {
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
|
||||
public BlockCoord(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return CoordHash.hashCode3DPrimes(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null || getClass() != obj.getClass()) return false;
|
||||
BlockCoord bc = (BlockCoord)obj;
|
||||
return bc.getX() == x && bc.getY() == y && bc.getZ() == z;
|
||||
}
|
||||
}
|
||||
@@ -79,6 +79,7 @@ public enum CheckType {
|
||||
FIGHT_REACH(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_REACH),
|
||||
FIGHT_SELFHIT(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_SELFHIT),
|
||||
FIGHT_SPEED(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_SPEED),
|
||||
FIGHT_VISIBLE(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_VISIBLE),
|
||||
|
||||
INVENTORY(CheckTypeType.GROUP, CheckType.ALL, Permissions.INVENTORY),
|
||||
INVENTORY_FASTCLICK(CheckTypeType.CHECK, INVENTORY, Permissions.INVENTORY_FASTCLICK),
|
||||
|
||||
+15
-159
@@ -20,7 +20,6 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -34,12 +33,10 @@ import fr.neatmonster.nocheatplus.checks.net.FlyingQueueHandle;
|
||||
import fr.neatmonster.nocheatplus.checks.net.FlyingQueueLookBlockChecker;
|
||||
import fr.neatmonster.nocheatplus.players.IPlayerData;
|
||||
import fr.neatmonster.nocheatplus.utilities.StringUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.Axis;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.CollisionUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.InteractAxisTracing;
|
||||
import fr.neatmonster.nocheatplus.utilities.ds.map.CoordHash;
|
||||
import fr.neatmonster.nocheatplus.utilities.ds.map.BlockCoord;
|
||||
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.map.BlockFlags;
|
||||
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
|
||||
import fr.neatmonster.nocheatplus.utilities.map.WrapBlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.location.TrigUtil;
|
||||
|
||||
@@ -109,7 +106,7 @@ public class Visible extends Check {
|
||||
public Visible() {
|
||||
super(CheckType.BLOCKINTERACT_VISIBLE);
|
||||
wrapBlockCache = new WrapBlockCache();
|
||||
rayTracing.setMaxSteps(60); // TODO: Configurable ?
|
||||
rayTracing.setMaxSteps(30); // TODO: Configurable ?
|
||||
}
|
||||
|
||||
public boolean check(final Player player, final Location loc, final double eyeHeight, final Block block,
|
||||
@@ -143,16 +140,26 @@ public class Visible extends Check {
|
||||
// blockX, blockY, blockZ, flyingHandle, face, tags, debug, player);
|
||||
rayTracing.set(blockX, blockY, blockZ, eyeX, eyeY, eyeZ);
|
||||
rayTracing.loop();
|
||||
//System.out.println("origin: " + blockX + " " + blockY+ " " + blockZ + " " + Location.locToBlock(eyeX) + " " + Location.locToBlock(eyeY) + " " + Location.locToBlock(eyeZ));
|
||||
if (rayTracing.collides()) {
|
||||
collides = true;
|
||||
BlockCoord bc = new BlockCoord(blockX, blockY, blockZ);
|
||||
Vector direction = new Vector(eyeX - blockX, eyeY - blockY, eyeZ - blockZ).normalize();
|
||||
//System.out.println("dir:" + direction);
|
||||
boolean canContinue;
|
||||
Set<BlockCoord> visited = new HashSet<BlockCoord>();
|
||||
do {
|
||||
//System.out.println("dirl:" + direction);
|
||||
canContinue = false;
|
||||
for (BlockCoord neighbor : getNeighborsInDirection(bc, direction, eyeX, eyeY, eyeZ)) {
|
||||
if (canPassThrough(blockCache, bc, neighbor.getX(), neighbor.getY(), neighbor.getZ(), direction, eyeX, eyeY, eyeZ, eyeHeight) && correctDir(neighbor.getY(), blockY, Location.locToBlock(eyeY)) && !visited.contains(neighbor)) {
|
||||
for (BlockCoord neighbor : CollisionUtil.getNeighborsInDirection(bc, direction, eyeX, eyeY, eyeZ)) {
|
||||
//System.out.println(CollisionUtil.canPassThrough(rayTracing, blockCache, bc, neighbor.getX(), neighbor.getY(), neighbor.getZ(), direction, eyeX, eyeY, eyeZ, eyeHeight, null , null) + " " + CollisionUtil.correctDir(neighbor.getY(), blockY, Location.locToBlock(eyeY)) + " " + !visited.contains(neighbor)
|
||||
//+ " " + blockCache.getType(neighbor.getX(), neighbor.getY(), neighbor.getZ()) + " " + neighbor.getX() + " " + neighbor.getY() + " " + neighbor.getZ()
|
||||
//+ " " + blockCache.getType(bc.getX(), bc.getY(), bc.getZ()) + " " + bc.getX() + " " + bc.getY() + " " + bc.getZ());
|
||||
if (CollisionUtil.canPassThrough(rayTracing, blockCache, bc, neighbor.getX(), neighbor.getY(), neighbor.getZ(), direction, eyeX, eyeY, eyeZ, eyeHeight, null , null) && CollisionUtil.correctDir(neighbor.getY(), blockY, Location.locToBlock(eyeY)) && !visited.contains(neighbor)) {
|
||||
if (TrigUtil.isSameBlock(neighbor.getX(), neighbor.getY(), neighbor.getZ(), eyeX, eyeY, eyeZ)) {
|
||||
collides = false;
|
||||
break;
|
||||
}
|
||||
visited.add(neighbor);
|
||||
rayTracing.set(neighbor.getX(), neighbor.getY(), neighbor.getZ(), eyeX, eyeY, eyeZ);
|
||||
rayTracing.loop();
|
||||
@@ -181,7 +188,6 @@ public class Visible extends Check {
|
||||
useLoc.setWorld(null);
|
||||
//Cleanup.
|
||||
rayTracing.cleanup();
|
||||
//rayTracing.setIgnoreInitiallyColliding(false);
|
||||
blockCache.cleanup();
|
||||
}
|
||||
|
||||
@@ -207,121 +213,6 @@ public class Visible extends Check {
|
||||
}
|
||||
return cancel;
|
||||
}
|
||||
|
||||
private boolean correctDir(int neighbor, int block, int eyeBlock) {
|
||||
int d = eyeBlock - block;
|
||||
if (d > 0) {
|
||||
if (neighbor > eyeBlock) return false;
|
||||
} else if (d < 0) {
|
||||
if (neighbor < eyeBlock) return false;
|
||||
} else {
|
||||
if (neighbor < eyeBlock || neighbor > eyeBlock) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean canPassThrough(BlockCache blockCache, BlockCoord lastBlock, int x, int y, int z, Vector direction, double eyeX, double eyeY, double eyeZ, double eyeHeight) {
|
||||
double[] nextBounds = blockCache.getBounds(x, y, z);
|
||||
final Material mat = blockCache.getType(x, y, z);
|
||||
final long flags = BlockFlags.getBlockFlags(mat);
|
||||
//double[] lastBounds = blockCache.getBounds(lastBlock.getX(), lastBlock.getY(), lastBlock.getZ());
|
||||
if (nextBounds == null || canPassThroughWorkAround(blockCache, x, y, z, direction, eyeX, eyeY, eyeZ, eyeHeight)) return true;
|
||||
//if (lastBounds == null) return true;
|
||||
int dy = y - lastBlock.getY();
|
||||
int dx = x - lastBlock.getX();
|
||||
int dz = z - lastBlock.getZ();
|
||||
double stepX = dx * 0.99;
|
||||
double stepY = dy * 0.99;
|
||||
double stepZ = dz * 0.99;
|
||||
//rayTracing.setAxisOrder(Axis.AXIS_ORDER_XZY);
|
||||
rayTracing.set(lastBlock.getX(), lastBlock.getY(), lastBlock.getZ(), x + stepX, y + stepY, z + stepZ);
|
||||
rayTracing.setIgnoreInitiallyColliding(true);
|
||||
rayTracing.loop();
|
||||
rayTracing.setIgnoreInitiallyColliding(false);
|
||||
if (!rayTracing.collides()) return true;
|
||||
// Too headache to think out a perfect algorithm
|
||||
boolean wallConnector = (flags & (BlockFlags.F_THICK_FENCE | BlockFlags.F_THIN_FENCE)) != 0;
|
||||
boolean door = BlockProperties.isDoor(mat);
|
||||
if ((flags & BlockFlags.F_STAIRS) != 0) {
|
||||
if (dy == 0) {
|
||||
int eyeBlockY = Location.locToBlock(eyeY);
|
||||
if (eyeBlockY > y && nextBounds[4] == 1.0) return false;
|
||||
if (eyeBlockY < y && nextBounds[1] == 0.0) return false;
|
||||
}
|
||||
if (dx != 0) {
|
||||
// first bound is always a slab
|
||||
for (int i = 2; i <= (int)nextBounds.length / 6; i++) {
|
||||
if (nextBounds[i*6-4] == 0.0 && nextBounds[i*6-1] == 1.0 && (dx < 0 ? nextBounds[i*6-3] == 1.0 : nextBounds[i*6-6] == 0.0)) return false;
|
||||
}
|
||||
}
|
||||
if (dz != 0) {
|
||||
// first bound is always a slab
|
||||
for (int i = 2; i <= (int)nextBounds.length / 6; i++) {
|
||||
if (nextBounds[i*6-6] == 0.0 && nextBounds[i*6-3] == 1.0 && (dz < 0 ? nextBounds[i*6-1] == 1.0 : nextBounds[i*6-4] == 0.0)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dy != 0) {
|
||||
if (nextBounds[0] == 0.0 && nextBounds[3] == 1.0 && nextBounds[2] == 0.0 && nextBounds[5] == 1.0) return wallConnector || door ? rayTracing.getCollidingAxis() != Axis.Y_AXIS : dy > 0 ? nextBounds[1] != 0.0 : nextBounds[4] != 1.0;
|
||||
return true;
|
||||
}
|
||||
if (dx != 0) {
|
||||
if (nextBounds[1] == 0.0 && nextBounds[4] == 1.0 && nextBounds[2] == 0.0 && nextBounds[5] == 1.0) return wallConnector || door ? rayTracing.getCollidingAxis() != Axis.X_AXIS : dx > 0 ? nextBounds[0] != 0.0 : nextBounds[3] != 1.0;
|
||||
return true;
|
||||
}
|
||||
if (dz != 0) {
|
||||
if (nextBounds[0] == 0.0 && nextBounds[3] == 1.0 && nextBounds[1] == 0.0 && nextBounds[4] == 1.0) return wallConnector || door ? rayTracing.getCollidingAxis() != Axis.Z_AXIS : dz > 0 ? nextBounds[2] != 0.0 : nextBounds[5] != 1.0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean canPassThroughWorkAround(BlockCache blockCache, int blockX, int blockY, int blockZ, Vector direction, double eyeX, double eyeY, double eyeZ, double eyeHeight) {
|
||||
final Material mat = blockCache.getType(blockX, blockY, blockZ);
|
||||
final long flags = BlockFlags.getBlockFlags(mat);
|
||||
if ((flags & BlockFlags.F_SOLID) == 0) {
|
||||
// Ignore non solid blocks anyway.
|
||||
return true;
|
||||
}
|
||||
if ((flags & (BlockFlags.F_LIQUID | BlockFlags.F_IGN_PASSABLE)) != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((flags & (BlockFlags.F_THICK_FENCE | BlockFlags.F_THIN_FENCE)) != 0) {
|
||||
int entityBlockY = Location.locToBlock(eyeY - eyeHeight);
|
||||
return direction.getY() > 0.76 && entityBlockY > blockY || direction.getY() < -0.76 && entityBlockY < blockY;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<BlockCoord> getNeighborsInDirection(BlockCoord currentBlock, Vector direction, double eyeX, double eyeY, double eyeZ) {
|
||||
List<BlockCoord> neighbors = new ArrayList<>();
|
||||
int stepY = direction.getY() > 0 ? 1 : (direction.getY() < 0 ? -1 : 0);
|
||||
int stepX = direction.getX() > 0 ? 1 : (direction.getX() < 0 ? -1 : 0);
|
||||
int stepZ = direction.getZ() > 0 ? 1 : (direction.getZ() < 0 ? -1 : 0);
|
||||
|
||||
final double dYM = TrigUtil.manhattan(currentBlock.getX(), currentBlock.getY() + stepY, currentBlock.getZ(), eyeX, eyeY, eyeZ);
|
||||
final double dZM = TrigUtil.manhattan(currentBlock.getX(), currentBlock.getY(), currentBlock.getZ() + stepZ, eyeX, eyeY, eyeZ);
|
||||
final double dXM = TrigUtil.manhattan(currentBlock.getX() + stepX, currentBlock.getY(), currentBlock.getZ(), eyeX, eyeY, eyeZ);
|
||||
|
||||
if (dYM <= dXM && dYM <= dZM) {
|
||||
neighbors.add(new BlockCoord(currentBlock.getX(), currentBlock.getY() + stepY, currentBlock.getZ()));
|
||||
neighbors.add(new BlockCoord(currentBlock.getX() + stepX, currentBlock.getY(), currentBlock.getZ()));
|
||||
neighbors.add(new BlockCoord(currentBlock.getX(), currentBlock.getY(), currentBlock.getZ() + stepZ));
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
if (dXM < dZM) {
|
||||
neighbors.add(new BlockCoord(currentBlock.getX() + stepX, currentBlock.getY(), currentBlock.getZ()));
|
||||
neighbors.add(new BlockCoord(currentBlock.getX(), currentBlock.getY(), currentBlock.getZ() + stepZ));
|
||||
neighbors.add(new BlockCoord(currentBlock.getX(), currentBlock.getY() + stepY, currentBlock.getZ()));
|
||||
} else {
|
||||
neighbors.add(new BlockCoord(currentBlock.getX(), currentBlock.getY(), currentBlock.getZ() + stepZ));
|
||||
neighbors.add(new BlockCoord(currentBlock.getX() + stepX, currentBlock.getY(), currentBlock.getZ()));
|
||||
neighbors.add(new BlockCoord(currentBlock.getX(), currentBlock.getY() + stepY, currentBlock.getZ()));
|
||||
}
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
private boolean checkRayTracing(final double eyeX, final double eyeY, final double eyeZ, final double dirX, final double dirY, final double dirZ, final int blockX, final int blockY,
|
||||
final int blockZ, final BlockFace face, final List<String> tags, final boolean debug) {
|
||||
@@ -499,39 +390,4 @@ public class Visible extends Check {
|
||||
return Math.round(coord);
|
||||
}
|
||||
}
|
||||
|
||||
private class BlockCoord {
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
|
||||
public BlockCoord(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return CoordHash.hashCode3DPrimes(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null || getClass() != obj.getClass()) return false;
|
||||
BlockCoord bc = (BlockCoord)obj;
|
||||
return bc.getX() == x && bc.getY() == y && bc.getZ() == z;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,6 +89,8 @@ public class FightConfig extends ACheckConfig {
|
||||
public final float speedImprobableWeight;
|
||||
public final ActionList speedActions;
|
||||
|
||||
public final ActionList visibleActions;
|
||||
|
||||
// Special flags:
|
||||
public final boolean cancelDead;
|
||||
public final boolean knockBackVelocityPvP;
|
||||
@@ -175,6 +177,8 @@ public class FightConfig extends ACheckConfig {
|
||||
speedImprobableWeight = (float) config.getDouble(ConfPaths.FIGHT_SPEED_IMPROBABLE_WEIGHT);
|
||||
speedActions = config.getOptimizedActionList(ConfPaths.FIGHT_SPEED_ACTIONS, Permissions.FIGHT_SPEED);
|
||||
|
||||
visibleActions = config.getOptimizedActionList(ConfPaths.FIGHT_VISIBLE_ACTIONS, Permissions.FIGHT_VISIBLE);
|
||||
|
||||
cancelDead = config.getBoolean(ConfPaths.FIGHT_CANCELDEAD);
|
||||
loopMaxLatencyTicks = config.getInt(ConfPaths.FIGHT_MAXLOOPLETENCYTICKS, 1, 15, 8);
|
||||
AlmostBoolean ref = config.getAlmostBoolean(ConfPaths.FIGHT_PVP_KNOCKBACKVELOCITY, AlmostBoolean.MAYBE);
|
||||
|
||||
@@ -43,6 +43,7 @@ public class FightData extends ACheckData implements IDataOnRemoveSubCheckData,
|
||||
public double reachVL;
|
||||
public double speedVL;
|
||||
public double impossibleHitVL;
|
||||
public double visibleVL;
|
||||
|
||||
// Shared
|
||||
public String lastWorld = "";
|
||||
@@ -172,6 +173,9 @@ public class FightData extends ACheckData implements IDataOnRemoveSubCheckData,
|
||||
noSwingVL = 0;
|
||||
// Not reset time, for leniency rather.
|
||||
break;
|
||||
case FIGHT_VISIBLE:
|
||||
visibleVL = 0;
|
||||
break;
|
||||
case FIGHT_SELFHIT:
|
||||
selfHitVL.clear(System.currentTimeMillis());
|
||||
break;
|
||||
|
||||
@@ -116,6 +116,9 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
/** The speed check. */
|
||||
private final Speed speed = addCheck(new Speed());
|
||||
|
||||
/** The visible check. */
|
||||
private final Visible visible = addCheck(new Visible());
|
||||
|
||||
/** For temporary use: LocUtil.clone before passing deeply, call setWorld(null) after use. */
|
||||
private final Location useLoc1 = new Location(null, 0, 0, 0);
|
||||
|
||||
@@ -358,6 +361,10 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
}
|
||||
}
|
||||
|
||||
if (!cancelled && visible.isEnabled(player, pData)) {
|
||||
if (visible.check(player, loc, damaged, damagedIsFake, damagedLoc, data, cc)) cancelled = true;
|
||||
}
|
||||
|
||||
// Checks that use the LocationTrace instance of the attacked entity/player.
|
||||
// TODO: To be replaced by Fight.HitBox
|
||||
if (!cancelled) {
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package fr.neatmonster.nocheatplus.checks.fight;
|
||||
|
||||
import fr.neatmonster.nocheatplus.actions.ParameterName;
|
||||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.ViolationData;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.util.MovingUtil;
|
||||
import fr.neatmonster.nocheatplus.compat.MCAccess;
|
||||
import fr.neatmonster.nocheatplus.utilities.StringUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.CollisionUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.InteractAxisTracing;
|
||||
import fr.neatmonster.nocheatplus.utilities.ds.map.BlockCoord;
|
||||
import fr.neatmonster.nocheatplus.utilities.location.TrigUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.map.WrapBlockCache;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xaw3ep
|
||||
*/
|
||||
public class Visible extends Check{
|
||||
private final InteractAxisTracing rayTracing = new InteractAxisTracing();
|
||||
private final WrapBlockCache wrapBlockCache;
|
||||
|
||||
public Visible() {
|
||||
super(CheckType.FIGHT_VISIBLE);
|
||||
wrapBlockCache = new WrapBlockCache();
|
||||
rayTracing.setMaxSteps(30);
|
||||
}
|
||||
|
||||
public boolean check(final Player player, final Location loc,
|
||||
final Entity damaged, final boolean damagedIsFake, final Location dLoc,
|
||||
final FightData data, final FightConfig cc) {
|
||||
boolean cancel = false;
|
||||
|
||||
final MCAccess mcAccess = this.mcAccess.getHandle();
|
||||
|
||||
if (!damagedIsFake && mcAccess.isComplexPart(damaged)) {
|
||||
return cancel;
|
||||
}
|
||||
|
||||
// Find out how wide the entity is.
|
||||
final double width = damagedIsFake ? 0.6 : mcAccess.getWidth(damaged);
|
||||
|
||||
// Find out how high the entity is.
|
||||
final double height = damagedIsFake ? (damaged instanceof LivingEntity ? ((LivingEntity) damaged).getEyeHeight() : 1.75) : mcAccess.getHeight(damaged);
|
||||
final double dxz = Math.round(width * 500.0) / 1000.0; // this.width / 2; // 0.3;
|
||||
final double dminX = dLoc.getX() - dxz;
|
||||
final double dminY = dLoc.getY();
|
||||
final double dminZ = dLoc.getZ() - dxz;
|
||||
final double dmaxX = dLoc.getX() + dxz;
|
||||
final double dmaxY = dLoc.getY() + height;
|
||||
final double dmaxZ = dLoc.getZ() + dxz;
|
||||
final int dBX = Location.locToBlock(dLoc.getX());
|
||||
final int dBY = Location.locToBlock(dLoc.getY());
|
||||
final int dBZ = Location.locToBlock(dLoc.getZ());
|
||||
|
||||
final double eyeX = loc.getX();
|
||||
final double eyeY = loc.getY() + MovingUtil.getEyeHeight(player);
|
||||
final double eyeZ = loc.getZ();
|
||||
|
||||
final BlockCoord sCollidingBox = new BlockCoord(Location.locToBlock(dminX), Location.locToBlock(dminY), Location.locToBlock(dminZ));
|
||||
final BlockCoord eCollidingBox = new BlockCoord(Location.locToBlock(dmaxX), Location.locToBlock(dmaxY), Location.locToBlock(dmaxZ));
|
||||
if (CollisionUtil.isInsideAABBIncludeEdges(eyeX, eyeY, eyeZ, dminX, dminY, dminZ, dmaxX, dmaxY, dmaxZ)) return cancel;
|
||||
|
||||
final BlockCache blockCache = this.wrapBlockCache.getBlockCache();
|
||||
blockCache.setAccess(loc.getWorld());
|
||||
rayTracing.setBlockCache(blockCache);
|
||||
rayTracing.set(dLoc.getX(), dLoc.getY(), dLoc.getZ(), eyeX, eyeY, eyeZ);
|
||||
rayTracing.loop();
|
||||
//System.out.println("origin: " + eyeX + " " + eyeY+ " " + eyeZ + " | " + dLoc.getX() + " " + dLoc.getY() + " " + dLoc.getZ());
|
||||
if (rayTracing.collides()) {
|
||||
cancel = true;
|
||||
BlockCoord bc = new BlockCoord(dBX, dBY, dBZ);
|
||||
Vector direction = new Vector(eyeX - dBX, eyeY - dBY, eyeZ - dBZ).normalize();
|
||||
boolean canContinue;
|
||||
//System.out.println("dir:" + direction);
|
||||
Set<BlockCoord> visited = new HashSet<>();
|
||||
do {
|
||||
//System.out.println("dirl:" + direction);
|
||||
canContinue = false;
|
||||
for (BlockCoord neighbor : CollisionUtil.getNeighborsInDirection(bc, direction, eyeX, eyeY, eyeZ)) {
|
||||
//System.out.println(CollisionUtil.canPassThrough(rayTracing, blockCache, bc, neighbor.getX(), neighbor.getY(), neighbor.getZ(), direction, eyeX, eyeY, eyeZ, MovingUtil.getEyeHeight(player), sCollidingBox, eCollidingBox) + " " + CollisionUtil.correctDir(neighbor.getY(), dBY, Location.locToBlock(eyeY), sCollidingBox.getY(), eCollidingBox.getY()) + " " + !visited.contains(neighbor)
|
||||
// + " " + blockCache.getType(neighbor.getX(), neighbor.getY(), neighbor.getZ()) + " " + neighbor.getX() + " " + neighbor.getY() + " " + neighbor.getZ()
|
||||
// + " " + blockCache.getType(bc.getX(), bc.getY(), bc.getZ()) + " " + bc.getX() + " " + bc.getY() + " " + bc.getZ());
|
||||
if (CollisionUtil.canPassThrough(rayTracing, blockCache, bc, neighbor.getX(), neighbor.getY(), neighbor.getZ(), direction, eyeX, eyeY, eyeZ, MovingUtil.getEyeHeight(player), sCollidingBox, eCollidingBox) && CollisionUtil.correctDir(neighbor.getY(), dBY, Location.locToBlock(eyeY), sCollidingBox.getY(), eCollidingBox.getY()) && !visited.contains(neighbor)) {
|
||||
if (TrigUtil.isSameBlock(neighbor.getX(), neighbor.getY(), neighbor.getZ(), eyeX, eyeY, eyeZ)) {
|
||||
cancel = false;
|
||||
break;
|
||||
}
|
||||
visited.add(neighbor);
|
||||
rayTracing.set(neighbor.getX(), neighbor.getY(), neighbor.getZ(), eyeX, eyeY, eyeZ);
|
||||
rayTracing.loop();
|
||||
canContinue = true;
|
||||
cancel = rayTracing.collides();
|
||||
//if (!collides) break;
|
||||
//bc = new BlockCoord(rayTracing.getBlockX(), rayTracing.getBlockY(), rayTracing.getBlockZ());
|
||||
//direction = new Vector(eyeX - rayTracing.getBlockX(), eyeY - rayTracing.getBlockY(), eyeZ - rayTracing.getBlockZ()).normalize();
|
||||
bc = new BlockCoord(neighbor.getX(), neighbor.getY(), neighbor.getZ());
|
||||
direction = new Vector(eyeX - neighbor.getX(), eyeY - neighbor.getY(), eyeZ - neighbor.getZ()).normalize();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (cancel && canContinue);
|
||||
}
|
||||
if (rayTracing.getStepsDone() > rayTracing.getMaxSteps()) {
|
||||
cancel = true;
|
||||
}
|
||||
if (cancel) {
|
||||
data.visibleVL += 1.0;
|
||||
final ViolationData vd = new ViolationData(this, player, data.visibleVL, 1.0, cc.visibleActions);
|
||||
//if (vd.needsParameters()) vd.setParameter(ParameterName.TAGS, StringUtil.join(tags, "+"));
|
||||
cancel = executeActions(vd).willCancel();
|
||||
}
|
||||
rayTracing.cleanup();
|
||||
blockCache.cleanup();
|
||||
return cancel;
|
||||
}
|
||||
}
|
||||
@@ -557,6 +557,10 @@ public abstract class ConfPaths {
|
||||
private static final String FIGHT_YAWRATE = FIGHT + "yawrate.";
|
||||
public static final String FIGHT_YAWRATE_CHECK = FIGHT_YAWRATE + SUB_ACTIVE;
|
||||
|
||||
private static final String FIGHT_VISIBLE = FIGHT + "visible.";
|
||||
public static final String FIGHT_VISIBLE_CHECK = FIGHT_VISIBLE + SUB_ACTIVE;
|
||||
public static final String FIGHT_VISIBLE_ACTIONS = FIGHT_VISIBLE + "actions";
|
||||
|
||||
public static final String INVENTORY = CHECKS + "inventory.";
|
||||
public static final String INVENTORY_ACTIVE = INVENTORY + SUB_ACTIVE;
|
||||
|
||||
|
||||
@@ -389,6 +389,9 @@ public class DefaultConfig extends ConfigFile {
|
||||
set(ConfPaths.FIGHT_SPEED_SHORTTERM_LIMIT, 5, 1154);
|
||||
set(ConfPaths.FIGHT_SPEED_IMPROBABLE_FEEDONLY, false, 1154);
|
||||
set(ConfPaths.FIGHT_SPEED_IMPROBABLE_WEIGHT, 1.0, 1154);
|
||||
// Visible
|
||||
set(ConfPaths.FIGHT_VISIBLE_CHECK, "default", 1154);
|
||||
set(ConfPaths.FIGHT_VISIBLE_ACTIONS, "cancel vl>30 log:fvisible:8:5:if cancel", 1154);
|
||||
|
||||
|
||||
/* Inventory */
|
||||
@@ -679,6 +682,7 @@ public class DefaultConfig extends ConfigFile {
|
||||
set(ConfPaths.STRINGS + ".freach", start + "tried to hit an entity from a suspicious distance (Reach: &6[reachdistance]&7)" + end, 1154);
|
||||
set(ConfPaths.STRINGS + ".fselfhit", start + "tried to hit themselves" + end, 1154);
|
||||
set(ConfPaths.STRINGS + ".fspeed", start + "tried to click [violations] times over the established [limit] CPS limit" + end, 1154);
|
||||
set(ConfPaths.STRINGS + ".fvisible", start + "tried to attack target through a solid obstacle" + end, 1154);
|
||||
set(ConfPaths.STRINGS + ".godmode", start + "tried to ignore inflicted damage (Health: &7[health]&7)" + end, 1154);
|
||||
set(ConfPaths.STRINGS + ".gutenberg", start + "created a book with too many pages" + end, 785);
|
||||
set(ConfPaths.STRINGS + ".impossiblehit", start + "tried to hit an entity while performing another action (Tags: &6[tags]&7)" + end, 1154);
|
||||
|
||||
@@ -125,7 +125,6 @@ public class Permissions {
|
||||
|
||||
public static final RegisteredPermission CHAT = add(CHECKS + ".chat");
|
||||
public static final RegisteredPermission CHAT_CAPTCHA = add(CHAT + ".captcha");
|
||||
public static final RegisteredPermission CHAT_COLOR = add(CHAT + ".color");
|
||||
public static final RegisteredPermission CHAT_COMMANDS = add(CHAT + ".commands");
|
||||
public static final RegisteredPermission CHAT_LOGINS = add(CHAT + ".logins");
|
||||
public static final RegisteredPermission CHAT_RELOG = add(CHAT + ".relog");
|
||||
@@ -147,6 +146,7 @@ public class Permissions {
|
||||
public static final RegisteredPermission FIGHT_REACH = add(FIGHT + ".reach");
|
||||
public static final RegisteredPermission FIGHT_SELFHIT = add(FIGHT + ".selfhit");
|
||||
public static final RegisteredPermission FIGHT_SPEED = add(FIGHT + ".speed");
|
||||
public static final RegisteredPermission FIGHT_VISIBLE = add(FIGHT + ".visible");
|
||||
|
||||
public static final RegisteredPermission INVENTORY = add(CHECKS + ".inventory");
|
||||
public static final RegisteredPermission INVENTORY_DROP = add(INVENTORY + ".drop");
|
||||
|
||||
+143
-7
@@ -14,9 +14,11 @@
|
||||
*/
|
||||
package fr.neatmonster.nocheatplus.utilities.collision;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
@@ -24,7 +26,11 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import fr.neatmonster.nocheatplus.checks.moving.util.MovingUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.ds.map.BlockCoord;
|
||||
import fr.neatmonster.nocheatplus.utilities.location.TrigUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.map.BlockFlags;
|
||||
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
|
||||
|
||||
/**
|
||||
* Collision related static utility.
|
||||
@@ -111,7 +117,7 @@ public class CollisionUtil {
|
||||
*/
|
||||
public static double directionCheck(final Location sourceFoot, final double eyeHeight, final Vector dir, final double targetX, final double targetY, final double targetZ, final double targetWidth, final double targetHeight, final double precision)
|
||||
{
|
||||
return directionCheck(sourceFoot.getX(), sourceFoot.getY() + eyeHeight, sourceFoot.getZ(), dir.getX(), dir.getY(), dir.getZ(), targetX, targetY, targetZ, targetWidth, targetHeight, precision);
|
||||
return directionCheck(sourceFoot.getX(), sourceFoot.getY() + eyeHeight, sourceFoot.getZ(), dir.getX(), dir.getY(), dir.getZ(), targetX, targetY, targetZ, targetWidth, targetHeight, precision);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,8 +152,8 @@ public class CollisionUtil {
|
||||
public static double directionCheck(final double sourceX, final double sourceY, final double sourceZ, final double dirX, final double dirY, final double dirZ, final double targetX, final double targetY, final double targetZ, final double targetWidth, final double targetHeight, final double precision)
|
||||
{
|
||||
|
||||
// // TODO: Here we have 0.x vs. 2.x, sometimes !
|
||||
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "COMBINED: " + combinedDirectionCheck(sourceX, sourceY, sourceZ, dirX, dirY, dirZ, targetX, targetY, targetZ, targetWidth, targetHeight, precision, 60));
|
||||
// // TODO: Here we have 0.x vs. 2.x, sometimes !
|
||||
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "COMBINED: " + combinedDirectionCheck(sourceX, sourceY, sourceZ, dirX, dirY, dirZ, targetX, targetY, targetZ, targetWidth, targetHeight, precision, 60));
|
||||
|
||||
// TODO: rework / standardize.
|
||||
|
||||
@@ -202,7 +208,7 @@ public class CollisionUtil {
|
||||
*/
|
||||
public static double combinedDirectionCheck(final Location sourceFoot, final double eyeHeight, final Vector dir, final double targetX, final double targetY, final double targetZ, final double targetWidth, final double targetHeight, final double precision, final double anglePrecision, boolean isPlayer)
|
||||
{
|
||||
return combinedDirectionCheck(sourceFoot.getX(), sourceFoot.getY() + eyeHeight, sourceFoot.getZ(), dir.getX(), dir.getY(), dir.getZ(), targetX, targetY, targetZ, targetWidth, targetHeight, precision, anglePrecision, isPlayer);
|
||||
return combinedDirectionCheck(sourceFoot.getX(), sourceFoot.getY() + eyeHeight, sourceFoot.getZ(), dir.getX(), dir.getY(), dir.getZ(), targetX, targetY, targetZ, targetWidth, targetHeight, precision, anglePrecision, isPlayer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,7 +278,7 @@ public class CollisionUtil {
|
||||
final double minDist = isPlayer ? Math.max(targetHeight, targetWidth) / 2.0 : Math.max(targetHeight, targetWidth);
|
||||
|
||||
if (targetDist > minDist && TrigUtil.angle(sourceX, sourceY, sourceZ, dirX, dirY, dirZ, targetX, targetY, targetZ) * TrigUtil.fRadToGrad > anglePrecision){
|
||||
return targetDist - minDist;
|
||||
return targetDist - minDist;
|
||||
}
|
||||
|
||||
final double xPrediction = targetDist * dirX / dirLength;
|
||||
@@ -479,8 +485,8 @@ public class CollisionUtil {
|
||||
public static double axisDistance(final double pos, final double minPos, final double maxPos) {
|
||||
return pos < minPos ? Math.abs(pos - minPos) : (pos > maxPos ? Math.abs(pos - maxPos) : 0.0);
|
||||
}
|
||||
|
||||
public static boolean isCollidingWithEntities(final Player p, final boolean onlylivingenitites) {
|
||||
|
||||
public static boolean isCollidingWithEntities(final Player p, final boolean onlylivingenitites) {
|
||||
if (onlylivingenitites) {
|
||||
List<Entity> entities = p.getNearbyEntities(0.15, 0.2, 0.15);
|
||||
entities.removeIf(e -> !(e instanceof LivingEntity));
|
||||
@@ -489,4 +495,134 @@ public class CollisionUtil {
|
||||
return !p.getNearbyEntities(0.15, 0.15, 0.15).isEmpty();
|
||||
}
|
||||
|
||||
public static boolean correctDir(int neighbor, int block, int eyeBlock) {
|
||||
int d = eyeBlock - block;
|
||||
if (d > 0) {
|
||||
if (neighbor > eyeBlock) return false;
|
||||
} else if (d < 0) {
|
||||
if (neighbor < eyeBlock) return false;
|
||||
} else {
|
||||
if (neighbor < eyeBlock || neighbor > eyeBlock) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean correctDir(int neighbor, int block, int eyeBlock, int min, int max) {
|
||||
if (neighbor >= min && neighbor <= max) return true;
|
||||
int d = eyeBlock - block;
|
||||
if (d > 0) {
|
||||
if (neighbor > eyeBlock) return false;
|
||||
} else if (d < 0) {
|
||||
if (neighbor < eyeBlock) return false;
|
||||
} else {
|
||||
if (neighbor < eyeBlock || neighbor > eyeBlock) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean canPassThrough(InteractAxisTracing rayTracing, BlockCache blockCache, BlockCoord lastBlock, int x, int y, int z, Vector direction, double eyeX, double eyeY, double eyeZ, double eyeHeight, BlockCoord sCollidingBox, BlockCoord eCollidingBox) {
|
||||
double[] nextBounds = blockCache.getBounds(x, y, z);
|
||||
final Material mat = blockCache.getType(x, y, z);
|
||||
final long flags = BlockFlags.getBlockFlags(mat);
|
||||
//double[] lastBounds = blockCache.getBounds(lastBlock.getX(), lastBlock.getY(), lastBlock.getZ());
|
||||
if (sCollidingBox != null && eCollidingBox != null
|
||||
&& isInsideAABBIncludeEdges(x,y,z, sCollidingBox.getX(), sCollidingBox.getY(), sCollidingBox.getZ(), eCollidingBox.getX(), eCollidingBox.getY(), eCollidingBox.getZ())) return true;
|
||||
if (nextBounds == null || canPassThroughWorkAround(blockCache, x, y, z, direction, eyeX, eyeY, eyeZ, eyeHeight)) return true;
|
||||
//if (lastBounds == null) return true;
|
||||
int dy = y - lastBlock.getY();
|
||||
int dx = x - lastBlock.getX();
|
||||
int dz = z - lastBlock.getZ();
|
||||
double stepX = dx * 0.99;
|
||||
double stepY = dy * 0.99;
|
||||
double stepZ = dz * 0.99;
|
||||
//rayTracing.setAxisOrder(Axis.AXIS_ORDER_XZY);
|
||||
rayTracing.set(lastBlock.getX(), lastBlock.getY(), lastBlock.getZ(), x + stepX, y + stepY, z + stepZ);
|
||||
rayTracing.setIgnoreInitiallyColliding(true);
|
||||
rayTracing.loop();
|
||||
rayTracing.setIgnoreInitiallyColliding(false);
|
||||
if (!rayTracing.collides()) return true;
|
||||
// Too headache to think out a perfect algorithm
|
||||
boolean wallConnector = (flags & (BlockFlags.F_THICK_FENCE | BlockFlags.F_THIN_FENCE)) != 0;
|
||||
boolean door = BlockProperties.isDoor(mat);
|
||||
if ((flags & BlockFlags.F_STAIRS) != 0) {
|
||||
if (dy == 0) {
|
||||
int eyeBlockY = Location.locToBlock(eyeY);
|
||||
if (eyeBlockY > y && nextBounds[4] == 1.0) return false;
|
||||
if (eyeBlockY < y && nextBounds[1] == 0.0) return false;
|
||||
}
|
||||
if (dx != 0) {
|
||||
// first bound is always a slab
|
||||
for (int i = 2; i <= (int)nextBounds.length / 6; i++) {
|
||||
if (nextBounds[i*6-4] == 0.0 && nextBounds[i*6-1] == 1.0 && (dx < 0 ? nextBounds[i*6-3] == 1.0 : nextBounds[i*6-6] == 0.0)) return false;
|
||||
}
|
||||
}
|
||||
if (dz != 0) {
|
||||
// first bound is always a slab
|
||||
for (int i = 2; i <= (int)nextBounds.length / 6; i++) {
|
||||
if (nextBounds[i*6-6] == 0.0 && nextBounds[i*6-3] == 1.0 && (dz < 0 ? nextBounds[i*6-1] == 1.0 : nextBounds[i*6-4] == 0.0)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dy != 0) {
|
||||
if (nextBounds[0] == 0.0 && nextBounds[3] == 1.0 && nextBounds[2] == 0.0 && nextBounds[5] == 1.0) return wallConnector || door ? rayTracing.getCollidingAxis() != Axis.Y_AXIS : dy > 0 ? nextBounds[1] != 0.0 : nextBounds[4] != 1.0;
|
||||
return true;
|
||||
}
|
||||
if (dx != 0) {
|
||||
if (nextBounds[1] == 0.0 && nextBounds[4] == 1.0 && nextBounds[2] == 0.0 && nextBounds[5] == 1.0) return wallConnector || door ? rayTracing.getCollidingAxis() != Axis.X_AXIS : dx > 0 ? nextBounds[0] != 0.0 : nextBounds[3] != 1.0;
|
||||
return true;
|
||||
}
|
||||
if (dz != 0) {
|
||||
if (nextBounds[0] == 0.0 && nextBounds[3] == 1.0 && nextBounds[1] == 0.0 && nextBounds[4] == 1.0) return wallConnector || door ? rayTracing.getCollidingAxis() != Axis.Z_AXIS : dz > 0 ? nextBounds[2] != 0.0 : nextBounds[5] != 1.0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean canPassThroughWorkAround(BlockCache blockCache, int blockX, int blockY, int blockZ, Vector direction, double eyeX, double eyeY, double eyeZ, double eyeHeight) {
|
||||
final Material mat = blockCache.getType(blockX, blockY, blockZ);
|
||||
final long flags = BlockFlags.getBlockFlags(mat);
|
||||
if ((flags & BlockFlags.F_SOLID) == 0) {
|
||||
// Ignore non solid blocks anyway.
|
||||
return true;
|
||||
}
|
||||
if ((flags & (BlockFlags.F_LIQUID | BlockFlags.F_IGN_PASSABLE)) != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((flags & (BlockFlags.F_THICK_FENCE | BlockFlags.F_THIN_FENCE)) != 0) {
|
||||
int entityBlockY = Location.locToBlock(eyeY - eyeHeight);
|
||||
return direction.getY() > 0.76 && entityBlockY > blockY || direction.getY() < -0.76 && entityBlockY < blockY;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<BlockCoord> getNeighborsInDirection(BlockCoord currentBlock, Vector direction, double eyeX, double eyeY, double eyeZ) {
|
||||
List<BlockCoord> neighbors = new ArrayList<>();
|
||||
int stepY = direction.getY() > 0 ? 1 : (direction.getY() < 0 ? -1 : 0);
|
||||
int stepX = direction.getX() > 0 ? 1 : (direction.getX() < 0 ? -1 : 0);
|
||||
int stepZ = direction.getZ() > 0 ? 1 : (direction.getZ() < 0 ? -1 : 0);
|
||||
|
||||
final double dYM = TrigUtil.manhattan(currentBlock.getX(), currentBlock.getY() + stepY, currentBlock.getZ(), eyeX, eyeY, eyeZ);
|
||||
final double dZM = TrigUtil.manhattan(currentBlock.getX(), currentBlock.getY(), currentBlock.getZ() + stepZ, eyeX, eyeY, eyeZ);
|
||||
final double dXM = TrigUtil.manhattan(currentBlock.getX() + stepX, currentBlock.getY(), currentBlock.getZ(), eyeX, eyeY, eyeZ);
|
||||
|
||||
// Is this one correct?
|
||||
if (dYM <= dXM && dYM <= dZM && Math.abs(direction.getY()) >= 0.5) {
|
||||
neighbors.add(new BlockCoord(currentBlock.getX(), currentBlock.getY() + stepY, currentBlock.getZ()));
|
||||
neighbors.add(new BlockCoord(currentBlock.getX() + stepX, currentBlock.getY(), currentBlock.getZ()));
|
||||
neighbors.add(new BlockCoord(currentBlock.getX(), currentBlock.getY(), currentBlock.getZ() + stepZ));
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
if (dXM < dZM) {
|
||||
neighbors.add(new BlockCoord(currentBlock.getX() + stepX, currentBlock.getY(), currentBlock.getZ()));
|
||||
neighbors.add(new BlockCoord(currentBlock.getX(), currentBlock.getY(), currentBlock.getZ() + stepZ));
|
||||
neighbors.add(new BlockCoord(currentBlock.getX(), currentBlock.getY() + stepY, currentBlock.getZ()));
|
||||
} else {
|
||||
neighbors.add(new BlockCoord(currentBlock.getX(), currentBlock.getY(), currentBlock.getZ() + stepZ));
|
||||
neighbors.add(new BlockCoord(currentBlock.getX() + stepX, currentBlock.getY(), currentBlock.getZ()));
|
||||
neighbors.add(new BlockCoord(currentBlock.getX(), currentBlock.getY() + stepY, currentBlock.getZ()));
|
||||
}
|
||||
return neighbors;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -68,7 +68,7 @@ public class InteractAxisTracing extends AxisTracing {
|
||||
final double minX, final double minY, final double minZ,
|
||||
final double maxX, final double maxY, final double maxZ,
|
||||
final Axis axis, final int increment) {
|
||||
if (BlockProperties.isPassableInteractBox(blockCache, blockX, blockY, blockZ, minX, minY, minZ, maxX, maxY, maxZ)) {
|
||||
if (BlockProperties.isPassableBox(blockCache, blockX, blockY, blockZ, minX, minY, minZ, maxX, maxY, maxZ)) {
|
||||
return true;
|
||||
}
|
||||
// No condition for passing through found.
|
||||
|
||||
@@ -4658,53 +4658,6 @@ public class BlockProperties {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check passability with an arbitrary bounding box vs. a block.
|
||||
*
|
||||
* @param access
|
||||
* the access
|
||||
* @param blockX
|
||||
* the block x
|
||||
* @param blockY
|
||||
* the block y
|
||||
* @param blockZ
|
||||
* the block z
|
||||
* @param minX
|
||||
* the min x
|
||||
* @param minY
|
||||
* the min y
|
||||
* @param minZ
|
||||
* the min z
|
||||
* @param maxX
|
||||
* the max x
|
||||
* @param maxY
|
||||
* the max y
|
||||
* @param maxZ
|
||||
* the max z
|
||||
* @return true, if is passable box
|
||||
*/
|
||||
public static final boolean isPassableInteractBox(final BlockCache access,
|
||||
final int blockX, final int blockY, final int blockZ,
|
||||
final double minX, final double minY, final double minZ,
|
||||
final double maxX, final double maxY, final double maxZ) {
|
||||
// TODO: This mostly is copy and paste from isPassableBox but without workaround.
|
||||
final IBlockCacheNode node = access.getOrCreateBlockCacheNode(blockX, blockY, blockZ, false);
|
||||
final Material id = node.getType();
|
||||
if (BlockProperties.isPassable(id)) {
|
||||
return true;
|
||||
}
|
||||
double[] bounds = access.getBounds(blockX, blockY, blockZ);
|
||||
if (bounds == null) {
|
||||
return true;
|
||||
}
|
||||
// (Coordinates are already passed in an ordered form.)
|
||||
if (!collidesBlock(access, minX, minY, minZ, maxX, maxY, maxZ, blockX, blockY, blockZ, node, null, BlockFlags.getBlockFlags(id) | BlockFlags.F_COLLIDE_EDGES)) {
|
||||
return true;
|
||||
}
|
||||
// Does collide (most likely).
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the bounding box collides with a block (passable + accounting
|
||||
* for workarounds).
|
||||
|
||||
Reference in new issue
Block a user