mirror of
https://github.com/funkemunky/KauriV3.git
synced 2026-06-03 14:52:18 +00:00
Block Tracking, Fixing Reach falses
This commit is contained in:
@@ -25,7 +25,7 @@ public class Reach extends Check {
|
||||
private int hbuffer;
|
||||
|
||||
public Timer lastAimOnTarget = new TickTimer();
|
||||
private final Queue<Entity> attacks = new LinkedBlockingQueue<>();
|
||||
private final Queue<Tuple<Entity, KLocation>> attacks = new LinkedBlockingQueue<>();
|
||||
|
||||
private static final EnumSet<EntityType> allowedEntityTypes = EnumSet.of(EntityType.ZOMBIE, EntityType.SHEEP,
|
||||
EntityType.BLAZE, EntityType.SKELETON, EntityType.PLAYER, EntityType.VILLAGER, EntityType.IRON_GOLEM,
|
||||
@@ -39,7 +39,7 @@ public class Reach extends Check {
|
||||
public void onUse(WPacketPlayInUseEntity packet) {
|
||||
if(packet.getAction() == WPacketPlayInUseEntity.EnumEntityUseAction.ATTACK
|
||||
&& allowedEntityTypes.contains(packet.getEntity(getPlayer().getBukkitPlayer().getWorld()).getType())) {
|
||||
attacks.add(packet.getEntity(getPlayer().getBukkitPlayer().getWorld()));
|
||||
attacks.add(new Tuple<>(packet.getEntity(getPlayer().getBukkitPlayer().getWorld()), getPlayer().getMovement().getTo().getLoc().clone()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,11 +49,11 @@ public class Reach extends Check {
|
||||
attacks.clear();
|
||||
return;
|
||||
}
|
||||
Entity target;
|
||||
Tuple<Entity, KLocation> target;
|
||||
|
||||
while((target = attacks.poll()) != null) {
|
||||
//Updating new entity loc
|
||||
Optional<EntityLocation> optionalEloc = getPlayer().getEntityLocationHandler().getEntityLocation(target);
|
||||
Optional<EntityLocation> optionalEloc = getPlayer().getEntityLocationHandler().getEntityLocation(target.one);
|
||||
|
||||
if(!optionalEloc.isPresent()) {
|
||||
return;
|
||||
@@ -61,16 +61,10 @@ public class Reach extends Check {
|
||||
|
||||
final EntityLocation eloc = optionalEloc.get();
|
||||
|
||||
final KLocation to = getPlayer().getMovement().getTo().getLoc().clone(),
|
||||
from = getPlayer().getMovement().getFrom().getLoc().clone();
|
||||
final KLocation to = target.two;
|
||||
|
||||
//debug("current loc: %.4f, %.4f, %.4f", eloc.x, eloc.y, eloc.z);
|
||||
|
||||
to.y+= getPlayer().getInfo().isSneaking() ? (ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_14)
|
||||
? 1.27f : 1.54f) : 1.62f;
|
||||
from.y+= getPlayer().getInfo().isSneaking() ? (ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_14)
|
||||
? 1.27f : 1.54f) : 1.62f;
|
||||
|
||||
if(eloc.x == 0 && eloc.y == 0 & eloc.z == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -82,29 +76,29 @@ public class Reach extends Check {
|
||||
if(eloc.oldLocations.size() > 0) {
|
||||
for (KLocation oldLocation : eloc.oldLocations) {
|
||||
SimpleCollisionBox box = (SimpleCollisionBox)
|
||||
EntityData.getEntityBox(oldLocation.toVector(), target);
|
||||
EntityData.getEntityBox(oldLocation.toVector(), target.one);
|
||||
|
||||
if(getPlayer().getPlayerVersion().isBelow(ProtocolVersion.V1_9)) {
|
||||
box = box.expand(0.1);
|
||||
box = box.expand(0.1325);
|
||||
} else box = box.expand(0.0325);
|
||||
boxes.add(box);
|
||||
}
|
||||
for (KLocation oldLocation : eloc.interpolatedLocations) {
|
||||
SimpleCollisionBox box = (SimpleCollisionBox)
|
||||
EntityData.getEntityBox(oldLocation.toVector(), target);
|
||||
EntityData.getEntityBox(oldLocation.toVector(), target.one);
|
||||
|
||||
if(getPlayer().getPlayerVersion().isBelow(ProtocolVersion.V1_9)) {
|
||||
box = box.expand(0.1);
|
||||
box = box.expand(0.1325);
|
||||
} else box = box.expand(0.0325);
|
||||
boxes.add(box);
|
||||
}
|
||||
} else {
|
||||
for (KLocation oldLocation : eloc.interpolatedLocations) {
|
||||
SimpleCollisionBox box = (SimpleCollisionBox)
|
||||
EntityData.getEntityBox(oldLocation.toVector(), target);
|
||||
EntityData.getEntityBox(oldLocation.toVector(), target.one);
|
||||
|
||||
if(getPlayer().getPlayerVersion().isBelow(ProtocolVersion.V1_9)) {
|
||||
box = box.expand(0.1);
|
||||
box = box.expand(0.1325);
|
||||
} else box = box.expand(0.0325);
|
||||
boxes.add(box);
|
||||
}
|
||||
@@ -114,24 +108,41 @@ public class Reach extends Check {
|
||||
|
||||
int hits = 0;
|
||||
|
||||
for (SimpleCollisionBox targetBox : boxes) {
|
||||
final AxisAlignedBB vanillaBox = new AxisAlignedBB(targetBox);
|
||||
boolean didSneakOrElytra = getPlayer().getInfo().getLastElytra().isNotPassed(40)
|
||||
|| getPlayer().getInfo().getLastElytra().isNotPassed(40);
|
||||
|
||||
Vec3D intersectTo = vanillaBox.rayTrace(to.toVector(), MathUtils.getDirection(to), 10),
|
||||
intersectFrom = vanillaBox.rayTrace(from.toVector(),
|
||||
MathUtils.getDirection(from), 10);
|
||||
if(!didSneakOrElytra) {
|
||||
to.y+= 1.62f;
|
||||
for (SimpleCollisionBox targetBox : boxes) {
|
||||
final AxisAlignedBB vanillaBox = new AxisAlignedBB(targetBox);
|
||||
|
||||
if(intersectTo != null) {
|
||||
lastAimOnTarget.reset();
|
||||
hits++;
|
||||
distance = Math.min(distance, intersectTo.distanceSquared(new Vec3D(to.x, to.y, to.z)));
|
||||
collided = true;
|
||||
Vec3D intersectTo = vanillaBox.rayTrace(to.toVector(), MathUtils.getDirection(to), 10);
|
||||
|
||||
if(intersectTo != null) {
|
||||
lastAimOnTarget.reset();
|
||||
hits++;
|
||||
distance = Math.min(distance, intersectTo.distanceSquared(new Vec3D(to.x, to.y, to.z)));
|
||||
collided = true;
|
||||
}
|
||||
}
|
||||
if(intersectFrom != null) {
|
||||
lastAimOnTarget.reset();
|
||||
hits++;
|
||||
distance = Math.min(distance, intersectFrom.distanceSquared(new Vec3D(from.x, from.y, from.z)));
|
||||
collided = true;
|
||||
//Checking all possible eyeheights since client actions notoriously desync from the server side
|
||||
} else {
|
||||
for (double eyeHeight : getPlayer().getMovement().getEyeHeights()) {
|
||||
for (SimpleCollisionBox targetBox : boxes) {
|
||||
final AxisAlignedBB vanillaBox = new AxisAlignedBB(targetBox);
|
||||
|
||||
KLocation from = to.clone();
|
||||
|
||||
from.y+= eyeHeight;
|
||||
Vec3D intersectTo = vanillaBox.rayTrace(from.toVector(), MathUtils.getDirection(from), 10);
|
||||
|
||||
if(intersectTo != null) {
|
||||
lastAimOnTarget.reset();
|
||||
hits++;
|
||||
distance = Math.min(distance, intersectTo.distanceSquared(new Vec3D(from.x, from.y, from.z)));
|
||||
collided = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,14 @@ import dev.brighten.ac.packet.ProtocolVersion;
|
||||
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
|
||||
import dev.brighten.ac.utils.BlockUtils;
|
||||
import dev.brighten.ac.utils.MathHelper;
|
||||
import dev.brighten.ac.utils.math.IntVector;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.util.CraftMagicNumbers;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.util.Deque;
|
||||
|
||||
@CheckData(name = "Speed", type = CheckType.MOVEMENT)
|
||||
public class Speed extends Check {
|
||||
private boolean lastLastClientGround;
|
||||
@@ -38,16 +42,17 @@ public class Speed extends Check {
|
||||
if (underBlock == null || lastUnderBlock == null)
|
||||
return;
|
||||
|
||||
float friction = CraftMagicNumbers.getBlock(underBlock).frictionFactor,
|
||||
lfriction = CraftMagicNumbers.getBlock(lastUnderBlock).frictionFactor;
|
||||
Deque<Material> frictionList = getPlayer().getBlockUpdateHandler()
|
||||
.getPossibleMaterials(new IntVector(underBlock.getX(), underBlock.getY(), underBlock.getZ())),
|
||||
lfrictionList = getPlayer().getBlockUpdateHandler()
|
||||
.getPossibleMaterials(new IntVector(lastUnderBlock.getX(), lastUnderBlock.getY(), lastUnderBlock.getZ()));
|
||||
|
||||
check:
|
||||
{
|
||||
if (!packet.isMoved()
|
||||
/*|| getPlayer().playerInfo.generalCancel
|
||||
|| getPlayer().playerInfo.onLadder
|
||||
|| getPlayer().playerInfo.lastEntityCollision.isNotPassed(2)
|
||||
|| getPlayer().playerInfo.lastVelocity.isNotPassed(1)*/
|
||||
|| getPlayer().getInfo().isGeneralCancel()
|
||||
|| getPlayer().getBlockInformation().onClimbable
|
||||
|| getPlayer().getInfo().getVelocity().isNotPassed(1)
|
||||
|| getPlayer().getBlockInformation().inLiquid
|
||||
|| getPlayer().getBlockInformation().collidesHorizontally) {
|
||||
break check;
|
||||
@@ -59,129 +64,137 @@ public class Speed extends Check {
|
||||
loop:
|
||||
{
|
||||
for (int f = -1; f < 2; f++) {
|
||||
for (int s = -1; s < 2; s++) {
|
||||
for (boolean sprinting : TRUE_FALSE) {
|
||||
for (int fastMath = 0; fastMath <= 2; fastMath++) {
|
||||
for (boolean attack : TRUE_FALSE) {
|
||||
for (boolean using : TRUE_FALSE) {
|
||||
for (boolean sneaking : TRUE_FALSE) {
|
||||
for (boolean jumped : TRUE_FALSE) {
|
||||
for(Material underMaterial : frictionList) {
|
||||
for(Material lastUnderMaterial : lfrictionList) {
|
||||
for (int s = -1; s < 2; s++) {
|
||||
for (boolean sprinting : TRUE_FALSE) {
|
||||
for (int fastMath = 0; fastMath <= 2; fastMath++) {
|
||||
for (boolean attack : TRUE_FALSE) {
|
||||
for (boolean using : TRUE_FALSE) {
|
||||
for (boolean sneaking : TRUE_FALSE) {
|
||||
for (boolean jumped : TRUE_FALSE) {
|
||||
|
||||
float forward = f, strafe = s;
|
||||
float forward = f, strafe = s;
|
||||
|
||||
if (sneaking) {
|
||||
forward *= 0.3;
|
||||
strafe *= 0.3;
|
||||
}
|
||||
if (sneaking) {
|
||||
forward *= 0.3;
|
||||
strafe *= 0.3;
|
||||
}
|
||||
|
||||
if (using) {
|
||||
forward *= 0.2;
|
||||
strafe *= 0.2;
|
||||
}
|
||||
float friction = CraftMagicNumbers.getBlock(underMaterial).frictionFactor;
|
||||
float lfriction = CraftMagicNumbers.getBlock(lastUnderMaterial).frictionFactor;
|
||||
|
||||
//Multiplying by 0.98 like in client
|
||||
forward *= 0.9800000190734863F;
|
||||
strafe *= 0.9800000190734863F;
|
||||
if (using) {
|
||||
forward *= 0.2;
|
||||
strafe *= 0.2;
|
||||
}
|
||||
|
||||
double aiMoveSpeed = getPlayer().getBukkitPlayer().getWalkSpeed() / 2;
|
||||
//Multiplying by 0.98 like in client
|
||||
forward *= 0.9800000190734863F;
|
||||
strafe *= 0.9800000190734863F;
|
||||
|
||||
float drag = 0.91f;
|
||||
double lmotionX = getPlayer().getMovement().getLDeltaX(),
|
||||
lmotionZ = getPlayer().getMovement().getLDeltaZ();
|
||||
double aiMoveSpeed = getPlayer().getBukkitPlayer().getWalkSpeed() / 2;
|
||||
|
||||
//The "1" will effectively remove lastFriction from the equation
|
||||
lmotionX *= (lastLastClientGround ? lfriction : 1) * 0.9100000262260437D;
|
||||
lmotionZ *= (lastLastClientGround ? lfriction : 1) * 0.9100000262260437D;
|
||||
float drag = 0.91f;
|
||||
double lmotionX = getPlayer().getMovement().getLDeltaX(),
|
||||
lmotionZ = getPlayer().getMovement().getLDeltaZ();
|
||||
|
||||
//Running multiplication done after previous prediction
|
||||
if (getPlayer().getPlayerVersion().isOrAbove(ProtocolVersion.V1_9)) {
|
||||
if (Math.abs(lmotionX) < 0.003)
|
||||
lmotionX = 0;
|
||||
if (Math.abs(lmotionZ) < 0.003)
|
||||
lmotionZ = 0;
|
||||
} else {
|
||||
if (Math.abs(lmotionX) < 0.005)
|
||||
lmotionX = 0;
|
||||
if (Math.abs(lmotionZ) < 0.005)
|
||||
lmotionZ = 0;
|
||||
}
|
||||
//The "1" will effectively remove lastFriction from the equation
|
||||
lmotionX *= (lastLastClientGround ? lfriction : 1) * 0.9100000262260437D;
|
||||
lmotionZ *= (lastLastClientGround ? lfriction : 1) * 0.9100000262260437D;
|
||||
|
||||
// Attack slowdown
|
||||
if (attack) {
|
||||
lmotionX *= 0.6;
|
||||
lmotionZ *= 0.6;
|
||||
}
|
||||
//Running multiplication done after previous prediction
|
||||
if (getPlayer().getPlayerVersion().isOrAbove(ProtocolVersion.V1_9)) {
|
||||
if (Math.abs(lmotionX) < 0.003)
|
||||
lmotionX = 0;
|
||||
if (Math.abs(lmotionZ) < 0.003)
|
||||
lmotionZ = 0;
|
||||
} else {
|
||||
if (Math.abs(lmotionX) < 0.005)
|
||||
lmotionX = 0;
|
||||
if (Math.abs(lmotionZ) < 0.005)
|
||||
lmotionZ = 0;
|
||||
}
|
||||
|
||||
if (sprinting) aiMoveSpeed += aiMoveSpeed * 0.30000001192092896D;
|
||||
// Attack slowdown
|
||||
if (attack) {
|
||||
lmotionX *= 0.6;
|
||||
lmotionZ *= 0.6;
|
||||
}
|
||||
|
||||
if (getPlayer().getPotionHandler().hasPotionEffect(PotionEffectType.SPEED))
|
||||
aiMoveSpeed += (getPlayer().getPotionHandler().getEffectByType(PotionEffectType.SPEED)
|
||||
.get()
|
||||
.getAmplifier() + 1) * (double) 0.20000000298023224D * aiMoveSpeed;
|
||||
if (getPlayer().getPotionHandler().hasPotionEffect(PotionEffectType.SLOW))
|
||||
aiMoveSpeed += (getPlayer().getPotionHandler().getEffectByType(PotionEffectType.SLOW)
|
||||
.get()
|
||||
.getAmplifier() + 1) * (double) -0.15000000596046448D * aiMoveSpeed;
|
||||
if (sprinting)
|
||||
aiMoveSpeed += aiMoveSpeed * 0.30000001192092896D;
|
||||
|
||||
float f5;
|
||||
if (onGround) {
|
||||
drag *= friction;
|
||||
if (getPlayer().getPotionHandler().hasPotionEffect(PotionEffectType.SPEED))
|
||||
aiMoveSpeed += (getPlayer().getPotionHandler().getEffectByType(PotionEffectType.SPEED)
|
||||
.get()
|
||||
.getAmplifier() + 1) * (double) 0.20000000298023224D * aiMoveSpeed;
|
||||
if (getPlayer().getPotionHandler().hasPotionEffect(PotionEffectType.SLOW))
|
||||
aiMoveSpeed += (getPlayer().getPotionHandler().getEffectByType(PotionEffectType.SLOW)
|
||||
.get()
|
||||
.getAmplifier() + 1) * (double) -0.15000000596046448D * aiMoveSpeed;
|
||||
|
||||
f5 = (float) (aiMoveSpeed * (0.16277136F / (drag * drag * drag)));
|
||||
float f5;
|
||||
if (onGround) {
|
||||
drag *= friction;
|
||||
|
||||
if (sprinting && jumped) {
|
||||
float rot = getPlayer().getMovement().getTo().getLoc().yaw * 0.017453292F;
|
||||
lmotionX -= sin(fastMath, rot) * 0.2F;
|
||||
lmotionZ += cos(fastMath, rot) * 0.2F;
|
||||
}
|
||||
f5 = (float) (aiMoveSpeed * (0.16277136F / (drag * drag * drag)));
|
||||
|
||||
} else f5 = sprinting ? 0.025999999F : 0.02f;
|
||||
if (sprinting && jumped) {
|
||||
float rot = getPlayer().getMovement().getTo().getLoc().yaw * 0.017453292F;
|
||||
lmotionX -= sin(fastMath, rot) * 0.2F;
|
||||
lmotionZ += cos(fastMath, rot) * 0.2F;
|
||||
}
|
||||
|
||||
if (getPlayer().getPlayerVersion().isOrAbove(ProtocolVersion.V1_9)) {
|
||||
double keyedMotion = forward * forward + strafe * strafe;
|
||||
} else f5 = sprinting ? 0.025999999F : 0.02f;
|
||||
|
||||
if (keyedMotion >= 1.0E-4F) {
|
||||
keyedMotion = f5 / Math.max(1.0, Math.sqrt(keyedMotion));
|
||||
forward *= keyedMotion;
|
||||
strafe *= keyedMotion;
|
||||
if (getPlayer().getPlayerVersion().isOrAbove(ProtocolVersion.V1_9)) {
|
||||
double keyedMotion = forward * forward + strafe * strafe;
|
||||
|
||||
final float yawSin = sin(fastMath,
|
||||
getPlayer().getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F),
|
||||
yawCos = cos(fastMath,
|
||||
getPlayer().getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F);
|
||||
if (keyedMotion >= 1.0E-4F) {
|
||||
keyedMotion = f5 / Math.max(1.0, Math.sqrt(keyedMotion));
|
||||
forward *= keyedMotion;
|
||||
strafe *= keyedMotion;
|
||||
|
||||
lmotionX += (strafe * yawCos - forward * yawSin);
|
||||
lmotionZ += (forward * yawCos + strafe * yawSin);
|
||||
}
|
||||
} else {
|
||||
float keyedMotion = forward * forward + strafe * strafe;
|
||||
final float yawSin = sin(fastMath,
|
||||
getPlayer().getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F),
|
||||
yawCos = cos(fastMath,
|
||||
getPlayer().getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F);
|
||||
|
||||
if (keyedMotion >= 1.0E-4F) {
|
||||
keyedMotion = f5 / Math.max(1.0f, MathHelper.sqrt_float(keyedMotion));
|
||||
forward *= keyedMotion;
|
||||
strafe *= keyedMotion;
|
||||
lmotionX += (strafe * yawCos - forward * yawSin);
|
||||
lmotionZ += (forward * yawCos + strafe * yawSin);
|
||||
}
|
||||
} else {
|
||||
float keyedMotion = forward * forward + strafe * strafe;
|
||||
|
||||
final float yawSin = sin(fastMath,
|
||||
getPlayer().getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F),
|
||||
yawCos = cos(fastMath,
|
||||
getPlayer().getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F);
|
||||
if (keyedMotion >= 1.0E-4F) {
|
||||
keyedMotion = f5 / Math.max(1.0f, MathHelper.sqrt_float(keyedMotion));
|
||||
forward *= keyedMotion;
|
||||
strafe *= keyedMotion;
|
||||
|
||||
lmotionX += (strafe * yawCos - forward * yawSin);
|
||||
lmotionZ += (forward * yawCos + strafe * yawSin);
|
||||
}
|
||||
}
|
||||
final float yawSin = sin(fastMath,
|
||||
getPlayer().getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F),
|
||||
yawCos = cos(fastMath,
|
||||
getPlayer().getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F);
|
||||
|
||||
double diffX = getPlayer().getMovement().getDeltaX() - lmotionX,
|
||||
diffZ = getPlayer().getMovement().getDeltaZ() - lmotionZ;
|
||||
double delta = (diffX * diffX) + (diffZ * diffZ);
|
||||
lmotionX += (strafe * yawCos - forward * yawSin);
|
||||
lmotionZ += (forward * yawCos + strafe * yawSin);
|
||||
}
|
||||
}
|
||||
|
||||
if (delta < smallestDelta) {
|
||||
smallestDelta = delta;
|
||||
pmotionx = lmotionX;
|
||||
pmotionz = lmotionZ;
|
||||
double diffX = getPlayer().getMovement().getDeltaX() - lmotionX,
|
||||
diffZ = getPlayer().getMovement().getDeltaZ() - lmotionZ;
|
||||
double delta = (diffX * diffX) + (diffZ * diffZ);
|
||||
|
||||
if (delta < 1E-15) {
|
||||
break loop;
|
||||
if (delta < smallestDelta) {
|
||||
smallestDelta = delta;
|
||||
pmotionx = lmotionX;
|
||||
pmotionz = lmotionZ;
|
||||
|
||||
if (delta < 1E-15) {
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,14 @@ import dev.brighten.ac.check.Check;
|
||||
import dev.brighten.ac.check.CheckData;
|
||||
import dev.brighten.ac.data.APlayer;
|
||||
import dev.brighten.ac.messages.Messages;
|
||||
import dev.brighten.ac.packet.handler.HandlerAbstract;
|
||||
import dev.brighten.ac.utils.Color;
|
||||
import dev.brighten.ac.utils.Init;
|
||||
import dev.brighten.ac.utils.MiscUtils;
|
||||
import dev.brighten.ac.utils.Priority;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.server.v1_8_R3.PacketDataSerializer;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayOutCustomPayload;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -96,4 +100,23 @@ public class AnticheatCommand extends BaseCommand {
|
||||
sender.sendMessage(MiscUtils.line(Color.Dark_Gray));
|
||||
});
|
||||
}
|
||||
|
||||
@Subcommand("runtest")
|
||||
public void onCommand(Player player) {
|
||||
long start = System.currentTimeMillis();
|
||||
PacketDataSerializer serializer = new PacketDataSerializer(Unpooled.buffer());
|
||||
serializer.writeLong(start);
|
||||
PacketPlayOutCustomPayload payload = new PacketPlayOutCustomPayload("Time|Send", serializer);
|
||||
|
||||
HandlerAbstract.getHandler().sendPacket(player, payload);
|
||||
Anticheat.INSTANCE.getPlayerRegistry().getPlayer(player.getUniqueId()).ifPresent(aplayer -> {
|
||||
aplayer.runInstantAction(ka -> {
|
||||
if(!ka.isEnd()) {
|
||||
long transDelta = System.currentTimeMillis() - start;
|
||||
|
||||
player.sendMessage("Transaction delta: " + transDelta + "ms");
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import dev.brighten.ac.data.obj.InstantAction;
|
||||
import dev.brighten.ac.data.obj.NormalAction;
|
||||
import dev.brighten.ac.handler.EntityLocationHandler;
|
||||
import dev.brighten.ac.handler.PotionHandler;
|
||||
import dev.brighten.ac.handler.block.BlockUpdateHandler;
|
||||
import dev.brighten.ac.handler.keepalive.KeepAlive;
|
||||
import dev.brighten.ac.handler.protocolsupport.ProtocolAPI;
|
||||
import dev.brighten.ac.messages.Messages;
|
||||
@@ -45,6 +46,10 @@ public class APlayer {
|
||||
private PotionHandler potionHandler;
|
||||
@Getter
|
||||
private EntityLocationHandler entityLocationHandler;
|
||||
|
||||
@Getter
|
||||
private BlockUpdateHandler blockUpdateHandler;
|
||||
|
||||
@Getter
|
||||
private GeneralInformation info;
|
||||
@Getter
|
||||
@@ -87,6 +92,7 @@ public class APlayer {
|
||||
this.movement = new MovementHandler(this);
|
||||
this.potionHandler = new PotionHandler(this);
|
||||
this.entityLocationHandler = new EntityLocationHandler(this);
|
||||
this.blockUpdateHandler = new BlockUpdateHandler(this);
|
||||
this.info = new GeneralInformation();
|
||||
this.lagInfo = new LagInformation();
|
||||
this.blockInformation = new BlockInformation(this);
|
||||
|
||||
@@ -17,10 +17,12 @@ import java.util.Optional;
|
||||
@Setter
|
||||
public class GeneralInformation {
|
||||
private Optional<Block> blockOnTo, blockBelow;
|
||||
private Timer lastMove = new TickTimer(), vehicleSwitch = new TickTimer();
|
||||
private Timer lastMove = new TickTimer(), vehicleSwitch = new TickTimer(),
|
||||
lastSneak = new TickTimer(), velocity = new TickTimer(),
|
||||
lastElytra = new TickTimer();
|
||||
private LivingEntity target;
|
||||
private boolean serverGround, lastServerGround, nearGround, worldLoaded, generalCancel, inVehicle, creative,
|
||||
sneaking, sprinting;
|
||||
sneaking, sprinting, gliding, riptiding;
|
||||
private List<Entity> nearbyEntities = Collections.emptyList();
|
||||
private PastLocation targetPastLocation = new PastLocation();;
|
||||
private PastLocation targetPastLocation = new PastLocation();
|
||||
}
|
||||
|
||||
@@ -228,6 +228,13 @@ public class MovementHandler {
|
||||
boolean hasLevitation = ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_9)
|
||||
&& player.getPotionHandler().hasPotionEffect(XPotion.LEVITATION.getPotionEffectType());
|
||||
|
||||
player.getInfo().setRiptiding(CompatHandler.getInstance().isRiptiding(player.getBukkitPlayer()));
|
||||
player.getInfo().setGliding(CompatHandler.getInstance().isGliding(player.getBukkitPlayer()));
|
||||
|
||||
// Resetting glide/sneak timers
|
||||
if(player.getInfo().isGliding()) player.getInfo().getLastElytra().reset();
|
||||
if(player.getInfo().isSneaking()) player.getInfo().getLastSneak().reset();
|
||||
|
||||
player.getInfo().setGeneralCancel(player.getBukkitPlayer().getAllowFlight()
|
||||
|| moveTicks == 0
|
||||
|| excuseNextFlying
|
||||
@@ -237,8 +244,8 @@ public class MovementHandler {
|
||||
|| player.getInfo().isInVehicle()
|
||||
|| player.getInfo().getVehicleSwitch().isNotPassed(1)
|
||||
|| player.getBukkitPlayer().isSleeping()
|
||||
|| CompatHandler.getInstance().isRiptiding(player.getBukkitPlayer())
|
||||
|| CompatHandler.getInstance().isGliding(player.getBukkitPlayer())
|
||||
|| player.getInfo().isGliding()
|
||||
|| player.getInfo().isRiptiding()
|
||||
|| hasLevitation);
|
||||
|
||||
/*
|
||||
@@ -283,6 +290,14 @@ public class MovementHandler {
|
||||
return result;
|
||||
}
|
||||
|
||||
public double[] getEyeHeights() {
|
||||
if(player.getPlayerVersion().isOrAbove(ProtocolVersion.V1_14)) {
|
||||
return new double[] {0.4f, 1.27f, 1.62f};
|
||||
} else if(player.getPlayerVersion().isOrAbove(ProtocolVersion.V1_9)) {
|
||||
return new double[] {0.4f, 1.54f, 1.62f};
|
||||
} else return new double[] {1.54f, 1.62f};
|
||||
}
|
||||
|
||||
public static float getExpiermentalDeltaY(APlayer data) {
|
||||
float deltaPitch = data.getMovement().getDeltaPitch();
|
||||
float sens = data.getMovement().sensitivityY;
|
||||
|
||||
@@ -85,8 +85,6 @@ public class EntityLocationHandler {
|
||||
eloc.newPitch += packet.getPitch();
|
||||
|
||||
eloc.increment = 3;
|
||||
|
||||
eloc.interpolatedLocations.clear();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -120,7 +118,6 @@ public class EntityLocationHandler {
|
||||
eloc.newZ = eloc.z = packet.getZ();
|
||||
eloc.newYaw = eloc.yaw = packet.getYaw();
|
||||
eloc.newPitch = eloc.pitch = packet.getPitch();
|
||||
eloc.interpolatedLocations.clear();
|
||||
} else {
|
||||
eloc.newX = packet.getX();
|
||||
eloc.newY = packet.getY();
|
||||
@@ -129,7 +126,6 @@ public class EntityLocationHandler {
|
||||
eloc.newPitch = packet.getPitch();
|
||||
|
||||
eloc.increment = 3;
|
||||
eloc.interpolatedLocations.clear();
|
||||
}
|
||||
} else {
|
||||
//We don't need to do version checking here. Atlas handles this for us.
|
||||
@@ -159,6 +155,7 @@ public class EntityLocationHandler {
|
||||
if(data.getInfo().getTarget() != null && data.getInfo().getTarget().getEntityId() == entity.getEntityId()) {
|
||||
data.runInstantAction(ia -> {
|
||||
if(!ia.isEnd()) {
|
||||
|
||||
action.run();
|
||||
} else entityLocationMap.get(entity.getUniqueId()).oldLocations.clear();
|
||||
});
|
||||
|
||||
@@ -5,13 +5,13 @@ import dev.brighten.ac.data.APlayer;
|
||||
import dev.brighten.ac.data.obj.NormalAction;
|
||||
import dev.brighten.ac.packet.ProtocolVersion;
|
||||
import dev.brighten.ac.packet.wrapper.PacketType;
|
||||
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInEntityAction;
|
||||
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
|
||||
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInUseEntity;
|
||||
import dev.brighten.ac.packet.wrapper.in.*;
|
||||
import dev.brighten.ac.packet.wrapper.out.*;
|
||||
import dev.brighten.ac.utils.KLocation;
|
||||
import dev.brighten.ac.utils.MovementUtils;
|
||||
import lombok.val;
|
||||
import net.minecraft.server.v1_8_R3.PacketDataSerializer;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayInCustomPayload;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayInSteerVehicle;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayInTransaction;
|
||||
import org.bukkit.entity.Entity;
|
||||
@@ -108,12 +108,28 @@ public class PacketHandler {
|
||||
player.getMovement().process(packet, System.currentTimeMillis());
|
||||
break;
|
||||
}
|
||||
case BLOCK_CHANGE: {
|
||||
WPacketPlayOutBlockChange packet = (WPacketPlayOutBlockChange) packetObject;
|
||||
|
||||
player.getBlockUpdateHandler().runUpdate(packet);
|
||||
break;
|
||||
}
|
||||
case MULTI_BLOCK_CHANGE: {
|
||||
WPacketPlayOutMultiBlockChange packet = (WPacketPlayOutMultiBlockChange) packetObject;
|
||||
|
||||
player.getBlockUpdateHandler().runUpdate(packet);
|
||||
break;
|
||||
}
|
||||
case ENTITY_EFFECT: {
|
||||
WPacketPlayOutEntityEffect packet = (WPacketPlayOutEntityEffect) packetObject;
|
||||
|
||||
player.getPotionHandler().onPotionEffect(packet);
|
||||
break;
|
||||
}
|
||||
case VELOCITY: {
|
||||
player.runKeepaliveAction(ka -> player.getInfo().getVelocity().reset());
|
||||
break;
|
||||
}
|
||||
case SERVER_POSITION: {
|
||||
player.getMovement().addPosition((WPacketPlayOutPosition) packetObject);
|
||||
break;
|
||||
@@ -141,6 +157,24 @@ public class PacketHandler {
|
||||
|
||||
break;
|
||||
}
|
||||
case CLIENT_PAYLOAD: {
|
||||
PacketPlayInCustomPayload packet = (PacketPlayInCustomPayload) packetObject;
|
||||
|
||||
if(packet.a().equals("Time|Receive")) {
|
||||
PacketDataSerializer serial = packet.b();
|
||||
|
||||
long serverTime = serial.readLong();
|
||||
long clientReceivedTime = serial.readLong();
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
long serverPing = clientReceivedTime - serverTime;
|
||||
long clientToServer = currentTime - clientReceivedTime;
|
||||
long totalFeedback = currentTime - serverTime;
|
||||
|
||||
player.getBukkitPlayer().sendMessage(String.format("total: %sms client-server: %sms server-client: %sms", totalFeedback, clientToServer, serverPing));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ENTITY_ACTION: {
|
||||
WPacketPlayInEntityAction packet = (WPacketPlayInEntityAction) packetObject;
|
||||
|
||||
@@ -189,6 +223,18 @@ public class PacketHandler {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BLOCK_DIG: {
|
||||
WPacketPlayInBlockPlace packet = (WPacketPlayInBlockPlace) packetObject;
|
||||
|
||||
player.getBlockUpdateHandler().onPlace(packet);
|
||||
break;
|
||||
}
|
||||
case BLOCK_PLACE: {
|
||||
WPacketPlayInBlockDig packet = (WPacketPlayInBlockDig) packetObject;
|
||||
|
||||
player.getBlockUpdateHandler().onDig(packet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
player.callPacket(packetObject);
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
package dev.brighten.ac.handler.block;
|
||||
|
||||
import dev.brighten.ac.data.APlayer;
|
||||
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInBlockDig;
|
||||
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInBlockPlace;
|
||||
import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutBlockChange;
|
||||
import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutMultiBlockChange;
|
||||
import dev.brighten.ac.utils.BlockUtils;
|
||||
import dev.brighten.ac.utils.Tuple;
|
||||
import dev.brighten.ac.utils.math.IntVector;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.val;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class BlockUpdateHandler {
|
||||
private final Map<IntVector, Deque<Material>> blockInformation = new ConcurrentHashMap<>();
|
||||
|
||||
private final APlayer player;
|
||||
|
||||
public void onWorldChange() {
|
||||
blockInformation.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep track of block placements since the Bukkit API will be a bit behind
|
||||
* @param place
|
||||
*/
|
||||
public void onPlace(WPacketPlayInBlockPlace place) {
|
||||
if(!place.getItemStack().getType().isBlock()) return;
|
||||
|
||||
Deque<Material> possible = getPossibleMaterials(place.getBlockPos());
|
||||
possible.add(place.getItemStack().getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep track of block breaking since the Bukkit API will be a bit behind.
|
||||
* @param dig
|
||||
*/
|
||||
public void onDig(WPacketPlayInBlockDig dig) {
|
||||
Deque<Material> possible = getPossibleMaterials(dig.getBlockPos());
|
||||
possible.clear();
|
||||
possible.add(Material.AIR);
|
||||
}
|
||||
|
||||
public void runUpdate(WPacketPlayOutBlockChange packet) {
|
||||
Deque<Material> blockInfo = blockInformation.compute(packet.getBlockLocation(), (blockLoc, blockI) -> {
|
||||
if(blockI == null) {
|
||||
blockI = new LinkedList<>();
|
||||
|
||||
val optional = BlockUtils
|
||||
.getBlockAsync(packet.getBlockLocation().toBukkitVector()
|
||||
.toLocation(player.getBukkitPlayer().getWorld()));
|
||||
|
||||
if(optional.isPresent()) {
|
||||
Block block = optional.get();
|
||||
|
||||
blockI.add(block.getType());
|
||||
}
|
||||
}
|
||||
|
||||
return blockI;
|
||||
});
|
||||
|
||||
// Updating block information
|
||||
player.runInstantAction(k -> {
|
||||
if(!k.isEnd()) {
|
||||
blockInfo.add(packet.getMaterial());
|
||||
} else if(blockInfo.size() > 1) {
|
||||
blockInfo.removeFirst();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void runUpdate(WPacketPlayOutMultiBlockChange packet) {
|
||||
List<Tuple<Deque<Material>, Material>> changes = new ArrayList<>();
|
||||
for (WPacketPlayOutMultiBlockChange.BlockChange change : packet.getChanges()) {
|
||||
Deque<Material> blockInfo = blockInformation.compute(change.getLocation(), (blockLoc, blockI) -> {
|
||||
if(blockI == null) {
|
||||
blockI = new LinkedList<>();
|
||||
|
||||
val optional = BlockUtils
|
||||
.getBlockAsync(change.getLocation().toBukkitVector()
|
||||
.toLocation(player.getBukkitPlayer().getWorld()));
|
||||
|
||||
if(optional.isPresent()) {
|
||||
Block block = optional.get();
|
||||
|
||||
blockI.add(block.getType());
|
||||
}
|
||||
}
|
||||
|
||||
return blockI;
|
||||
});
|
||||
|
||||
changes.add(new Tuple<>(blockInfo, change.getMaterial()));
|
||||
}
|
||||
|
||||
player.runInstantAction(k -> {
|
||||
if(!k.isEnd()) {
|
||||
for (Tuple<Deque<Material>, Material> tuple : changes) {
|
||||
tuple.one.add(tuple.two);
|
||||
}
|
||||
} else {
|
||||
for (Tuple<Deque<Material>, Material> tuple : changes) {
|
||||
if(tuple.one.size() > 1) {
|
||||
tuple.one.removeFirst();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Deque<Material> getPossibleMaterials(IntVector loc) {
|
||||
return blockInformation.compute(loc, (blockLoc, blockI) -> {
|
||||
if(blockI == null) {
|
||||
blockI = new LinkedList<>();
|
||||
|
||||
val optional = BlockUtils
|
||||
.getBlockAsync(loc.toBukkitVector()
|
||||
.toLocation(player.getBukkitPlayer().getWorld()));
|
||||
|
||||
if(optional.isPresent()) {
|
||||
Block block = optional.get();
|
||||
|
||||
blockI.add(block.getType());
|
||||
}
|
||||
}
|
||||
|
||||
return blockI;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerKickEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -82,6 +83,14 @@ public class JoinListener implements Listener {
|
||||
player.callEvent(event);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onTeleport(PlayerTeleportEvent event) {
|
||||
if(event.getFrom().getWorld().equals(event.getTo().getWorld())) return;
|
||||
|
||||
Anticheat.INSTANCE.getPlayerRegistry().getPlayer(event.getPlayer().getUniqueId())
|
||||
.ifPresent(player -> player.getBlockUpdateHandler().onWorldChange());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(PlayerQuitEvent event) {
|
||||
Anticheat.INSTANCE.getPlayerRegistry().unregister(event.getPlayer().getUniqueId());
|
||||
|
||||
@@ -30,4 +30,8 @@ public interface PacketConverter {
|
||||
WPacketPlayOutEntityTeleport processEntityTeleport(Object object);
|
||||
|
||||
WPacketHandshakingInSetProtocol processHandshakingProtocol(Object object);
|
||||
|
||||
WPacketPlayOutBlockChange processBlockChange(Object object);
|
||||
|
||||
WPacketPlayOutMultiBlockChange processMultiBlockChange(Object object);
|
||||
}
|
||||
|
||||
@@ -85,13 +85,6 @@ public enum PacketType {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public static class Login {
|
||||
public static final String HANDSHAKE = "PacketHandshakingInSetProtocol";
|
||||
public static final String PING = "PacketStatusInPing";
|
||||
public static final String STATUS_START = "PacketStatusInStart";
|
||||
public static final String LOGIN_START = "PacketLoginInStart";
|
||||
}
|
||||
|
||||
public static Object processType(PacketType type, Object object) {
|
||||
PacketConverter convert = Anticheat.INSTANCE.getPacketProcessor().getPacketConverter();
|
||||
|
||||
@@ -127,6 +120,10 @@ public enum PacketType {
|
||||
return convert.processEntityTeleport(object);
|
||||
case LOGIN_HANDSHAKE:
|
||||
return convert.processHandshakingProtocol(object);
|
||||
case BLOCK_CHANGE:
|
||||
return convert.processBlockChange(object);
|
||||
case MULTI_BLOCK_CHANGE:
|
||||
return convert.processMultiBlockChange(object);
|
||||
default:
|
||||
return object;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@ import dev.brighten.ac.utils.reflections.types.WrappedClass;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedField;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.server.v1_8_R3.*;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.util.CraftMagicNumbers;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -238,4 +240,55 @@ public class Processor_18 implements PacketConverter {
|
||||
.protocol(WPacketHandshakingInSetProtocol.EnumProtocol.valueOf(EnumProtocol.a(serial.e()).name()))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WPacketPlayOutBlockChange processBlockChange(Object object) {
|
||||
PacketPlayOutBlockChange packet = (PacketPlayOutBlockChange) object;
|
||||
PacketDataSerializer serial = new PacketDataSerializer(Unpooled.buffer());
|
||||
|
||||
try {
|
||||
packet.b(serial);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
BlockPosition blockPos = serial.c();
|
||||
IntVector vecPos = new IntVector(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||
Material material = CraftMagicNumbers.getMaterial(packet.block.getBlock());
|
||||
|
||||
return WPacketPlayOutBlockChange.builder()
|
||||
.blockLocation(vecPos)
|
||||
.material(material)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WPacketPlayOutMultiBlockChange processMultiBlockChange(Object object) {
|
||||
PacketPlayOutMultiBlockChange packet = (PacketPlayOutMultiBlockChange) object;
|
||||
PacketDataSerializer serial = new PacketDataSerializer(Unpooled.buffer());
|
||||
|
||||
try {
|
||||
packet.b(serial);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
final int[] chunkLoc = new int[] {serial.readInt(), serial.readInt()};
|
||||
final WPacketPlayOutMultiBlockChange.BlockChange[]
|
||||
blockChanges = new WPacketPlayOutMultiBlockChange.BlockChange[serial.e()];
|
||||
|
||||
for (int i = 0; i < blockChanges.length; i++) {
|
||||
short encodedloc = serial.readShort();
|
||||
|
||||
IntVector loc = new IntVector(encodedloc >> 12 & 15, encodedloc & 255, encodedloc >> 8 & 15);
|
||||
Material blockType = CraftMagicNumbers.getMaterial(Block.d.a(serial.e()).getBlock());
|
||||
|
||||
blockChanges[i] = new WPacketPlayOutMultiBlockChange.BlockChange(loc, blockType);
|
||||
}
|
||||
|
||||
return WPacketPlayOutMultiBlockChange.builder()
|
||||
.chunk(chunkLoc)
|
||||
.changes(blockChanges)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ package dev.brighten.ac.utils;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Vec3D {
|
||||
public static final Vec3D a = new Vec3D(0.0D, 0.0D, 0.0D);
|
||||
@@ -138,33 +139,6 @@ public class Vec3D {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(Object var1) {
|
||||
if (this == var1) {
|
||||
return true;
|
||||
} else if (!(var1 instanceof Vec3D)) {
|
||||
return false;
|
||||
} else {
|
||||
Vec3D var2 = (Vec3D)var1;
|
||||
if (Double.compare(var2.x, this.x) != 0) {
|
||||
return false;
|
||||
} else if (Double.compare(var2.y, this.y) != 0) {
|
||||
return false;
|
||||
} else {
|
||||
return Double.compare(var2.z, this.z) == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
long var2 = Double.doubleToLongBits(this.x);
|
||||
int var1 = (int)(var2 ^ var2 >>> 32);
|
||||
var2 = Double.doubleToLongBits(this.y);
|
||||
var1 = 31 * var1 + (int)(var2 ^ var2 >>> 32);
|
||||
var2 = Double.doubleToLongBits(this.z);
|
||||
var1 = 31 * var1 + (int)(var2 ^ var2 >>> 32);
|
||||
return var1;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "(" + this.x + ", " + this.y + ", " + this.z + ")";
|
||||
}
|
||||
@@ -186,4 +160,17 @@ public class Vec3D {
|
||||
double var8 = this.z * (double)var2 - this.x * (double)var3;
|
||||
return new Vec3D(var4, var6, var8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Vec3D vec3D = (Vec3D) o;
|
||||
return Double.compare(vec3D.x, x) == 0 && Double.compare(vec3D.y, y) == 0 && Double.compare(vec3D.z, z) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class IntVector {
|
||||
@@ -25,4 +27,17 @@ public class IntVector {
|
||||
public String toString() {
|
||||
return String.format("IntVector[%s, %s, %s]", x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
IntVector intVector = (IntVector) o;
|
||||
return x == intVector.x && y == intVector.y && z == intVector.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user