Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72b8616ffe | ||
|
|
0f3bf60549 | ||
|
|
deb2628f77 |
No files matched your search
+2
-168
@@ -30,7 +30,7 @@ version = "2.3.68"
|
||||
description = "Libre simulation anticheat designed for 1.21 with 1.8-1.21 support, powered by PacketEvents 2.0."
|
||||
|
||||
java {
|
||||
toolchain.languageVersion.set(JavaLanguageVersion.of(18))
|
||||
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
|
||||
}
|
||||
|
||||
// Set to false for debug builds
|
||||
@@ -59,18 +59,11 @@ repositories {
|
||||
// FastUtil, Discord-Webhooks
|
||||
}
|
||||
|
||||
// Add JMH configuration
|
||||
configurations {
|
||||
create("jmh")
|
||||
create("jmhAnnotationProcessor")
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
implementation("com.github.retrooper:packetevents-spigot:2.6.1-SNAPSHOT")
|
||||
implementation("co.aikar:acf-paper:0.5.1-SNAPSHOT")
|
||||
implementation("club.minnced:discord-webhooks:0.8.0") // Newer versions include kotlin-stdlib, which leads to incompatibility with plugins that use Kotlin
|
||||
implementation("it.unimi.dsi:fastutil:8.5.15")
|
||||
implementation("it.unimi.dsi:fastutil:8.5.13")
|
||||
implementation("github.scarsz:configuralize:1.4.0")
|
||||
|
||||
//implementation("com.github.grimanticheat:grimapi:1193c4fa41")
|
||||
@@ -83,12 +76,6 @@ dependencies {
|
||||
compileOnly("com.viaversion:viaversion-api:5.0.4-SNAPSHOT")
|
||||
//
|
||||
compileOnly("io.netty:netty-all:4.1.85.Final")
|
||||
|
||||
// Replace jmhImplementation with the new configuration
|
||||
"jmh"("org.openjdk.jmh:jmh-core:1.37")
|
||||
"jmhAnnotationProcessor"("org.openjdk.jmh:jmh-generator-annprocess:1.37")
|
||||
|
||||
implementation(files("./nalim.jar"))
|
||||
}
|
||||
|
||||
bukkit {
|
||||
@@ -156,16 +143,6 @@ bukkit {
|
||||
description = "Exempt from all checks"
|
||||
default = Permission.Default.FALSE
|
||||
}
|
||||
|
||||
register("grim.verbose") {
|
||||
description = "Receive verbose alerts for violations. Requires grim.alerts"
|
||||
default = Permission.Default.OP
|
||||
}
|
||||
|
||||
register("grim.verbose.enable-on-join") {
|
||||
description = "Enable verbose alerts on join. Requires grim.alerts and grim.alerts.enable-on-join"
|
||||
default = Permission.Default.FALSE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,71 +159,6 @@ publishing.publications.create<MavenPublication>("maven") {
|
||||
artifact(tasks["shadowJar"])
|
||||
}
|
||||
|
||||
java {
|
||||
sourceSets {
|
||||
create("java18") {
|
||||
java {
|
||||
srcDirs("src/main/java18")
|
||||
}
|
||||
compileClasspath += main.get().output
|
||||
runtimeClasspath += main.get().output
|
||||
dependencies {
|
||||
implementation(files("./nalim.jar")) // Add nalim.jar to java18 source set
|
||||
}
|
||||
}
|
||||
create("jmh") {
|
||||
java {
|
||||
srcDir("src/jmh/java")
|
||||
}
|
||||
compileClasspath += sourceSets.main.get().output +
|
||||
sourceSets.getByName("java18").output +
|
||||
configurations["jmh"]
|
||||
runtimeClasspath += sourceSets.main.get().output +
|
||||
sourceSets.getByName("java18").output +
|
||||
configurations["jmh"]
|
||||
}
|
||||
}
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(18))
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile> {
|
||||
if (name == "compileJava") {
|
||||
options.compilerArgs.addAll(listOf("--add-exports","java.base/jdk.internal=ALL-UNNAMED",
|
||||
"--add-exports", "java.base/jdk.internal.vm.annotation=ALL-UNNAMED"))
|
||||
}
|
||||
if (name == "compileJava18Java") {
|
||||
options.compilerArgs.addAll(listOf("--add-modules", "jdk.incubator.vector", "-Xlint:unchecked"))
|
||||
sourceCompatibility = "18"
|
||||
targetCompatibility = "18"
|
||||
}
|
||||
if (name == "compileJava21Java") {
|
||||
options.compilerArgs.addAll(listOf("--enable-preview", "--add-modules", "jdk.incubator.vector", "-Xlint:unchecked"))
|
||||
sourceCompatibility = "21"
|
||||
targetCompatibility = "21"
|
||||
}
|
||||
if (name == "compileJmhJava") {
|
||||
options.compilerArgs.addAll(listOf("--add-modules", "jdk.incubator.vector"))
|
||||
sourceCompatibility = "18"
|
||||
targetCompatibility = "18"
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<Jar> {
|
||||
manifest {
|
||||
attributes("Multi-Release" to "true")
|
||||
}
|
||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE // Important for multi-release JARs
|
||||
from(sourceSets.main.get().output)
|
||||
from(sourceSets.getByName("java18").output) {
|
||||
into("META-INF/versions/18")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.shadowJar {
|
||||
minimize()
|
||||
archiveFileName.set("${project.name}-${project.version}.jar")
|
||||
@@ -270,81 +182,3 @@ tasks.shadowJar {
|
||||
relocate("org.jetbrains", "ac.grim.grimac.shaded.jetbrains")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register<Jar>("jmhJar") {
|
||||
dependsOn("compileGeneratedJmh")
|
||||
|
||||
from(sourceSets["main"].output)
|
||||
from(sourceSets["java18"].output)
|
||||
from(sourceSets["jmh"].output)
|
||||
from("${buildDir}/classes/java/jmh")
|
||||
from(configurations["jmh"].map { if (it.isDirectory) it else zipTree(it) })
|
||||
|
||||
manifest {
|
||||
attributes(
|
||||
"Main-Class" to "org.openjdk.jmh.Main",
|
||||
"Add-Opens" to "java.base/java.lang java.base/java.io java.base/java.util java.base/java.util.concurrent java.base/java.net",
|
||||
"Add-Modules" to "jdk.incubator.vector"
|
||||
)
|
||||
}
|
||||
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
archiveClassifier.set("benchmarks")
|
||||
}
|
||||
|
||||
|
||||
tasks.register<JavaCompile>("compileGeneratedJmh") {
|
||||
dependsOn("compileJmhJava")
|
||||
|
||||
source = fileTree("${buildDir}/generated-sources/jmh")
|
||||
|
||||
classpath = sourceSets["jmh"].compileClasspath +
|
||||
sourceSets["java18"].output +
|
||||
sourceSets["java18"].compileClasspath +
|
||||
sourceSets.main.get().output +
|
||||
sourceSets.main.get().compileClasspath +
|
||||
files("${buildDir}/classes/java/jmh")
|
||||
|
||||
destinationDirectory.set(file("${buildDir}/classes/java/jmh"))
|
||||
|
||||
sourceCompatibility = "18"
|
||||
targetCompatibility = "18"
|
||||
options.compilerArgs.addAll(listOf("--add-modules", "jdk.incubator.vector"))
|
||||
}
|
||||
|
||||
tasks.register("jmh") {
|
||||
dependsOn("jmhJar")
|
||||
doLast {
|
||||
val includes = System.getProperty("includes", "")
|
||||
|
||||
javaexec {
|
||||
classpath = files(tasks.named("jmhJar").get().outputs.files)
|
||||
mainClass.set("org.openjdk.jmh.Main")
|
||||
jvmArgs = listOf("--enable-preview", "--add-modules", "jdk.incubator.vector", "-XX:+UnlockExperimentalVMOptions", "-XX:+EnableJVMCI", "-javaagent:nalim.jar")
|
||||
|
||||
// Initialize the args list with default settings
|
||||
args = mutableListOf<String>().apply {
|
||||
// Add any default arguments here if needed
|
||||
if (includes.isNotEmpty()) {
|
||||
addAll(listOf(includes))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named<JavaCompile>("compileJmhJava") {
|
||||
source = fileTree("src/jmh/java")
|
||||
classpath = sourceSets["jmh"].compileClasspath +
|
||||
sourceSets.main.get().output +
|
||||
sourceSets["java18"].output
|
||||
destinationDirectory.set(file("${buildDir}/classes/java/jmh"))
|
||||
|
||||
sourceCompatibility = "18"
|
||||
targetCompatibility = "18"
|
||||
options.compilerArgs.addAll(listOf("--add-modules", "jdk.incubator.vector"))
|
||||
}
|
||||
|
||||
tasks.named("jmhJar") {
|
||||
dependsOn("compileJmhJava")
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
package ac.grim.grimac.utils.vector;
|
||||
|
||||
import jdk.incubator.vector.*;
|
||||
|
||||
public final class SIMDVector3D implements Vector3D {
|
||||
|
||||
private static final VectorSpecies<Double> SPECIES = DoubleVector.SPECIES_256;
|
||||
private static final VectorMask<Double> LENGTH_3_ARRAY_MASK = SPECIES.indexInRange(0, 3);
|
||||
private static final VectorShuffle<Double> CROSS_PRODUCT_SHUFFLE1 = VectorShuffle.fromArray(SPECIES, new int[]{1, 2, 0, 3}, 0);
|
||||
private static final VectorShuffle<Double> CROSS_PRODUCT_SHUFFLE2 = VectorShuffle.fromArray(SPECIES, new int[]{2, 0, 1, 3}, 0);
|
||||
private static final DoubleVector FOURTH_COMPONENT_ZERO = DoubleVector.zero(SPECIES).withLane(3, 1.0);
|
||||
|
||||
private DoubleVector vector;
|
||||
|
||||
public SIMDVector3D(double x, double y, double z) {
|
||||
this.vector = DoubleVector.fromArray(SPECIES, new double[]{x, y, z, 0}, 0, LENGTH_3_ARRAY_MASK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getX() {
|
||||
return this.vector.lane(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getY() {
|
||||
return this.vector.lane(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getZ() {
|
||||
return this.vector.lane(2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3D setX(double x) {
|
||||
this.vector = this.vector.withLane(0, x);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3D setY(double y) {
|
||||
this.vector = this.vector.withLane(1, y);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3D setZ(double z) {
|
||||
this.vector = this.vector.withLane(2, z);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double length() {
|
||||
return Math.sqrt(lengthSquared());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double lengthSquared() {
|
||||
return this.vector.mul(this.vector).reduceLanes(VectorOperators.ADD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3D multiply(double m) {
|
||||
this.vector = this.vector.mul(m);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3D normalize() {
|
||||
// DoubleVector squared = this.vector.mul(this.vector);
|
||||
// double sum = squared.reduceLanes(VectorOperators.ADD);
|
||||
// double length = Math.sqrt(sum);
|
||||
// this.vector = this.vector.div(length);
|
||||
// return this;
|
||||
this.vector = this.vector.div(length());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3D crossProduct(Vector3D other) {
|
||||
SIMDVector3D o = (SIMDVector3D) other;
|
||||
|
||||
DoubleVector tmp0 = this.vector.rearrange(CROSS_PRODUCT_SHUFFLE1);
|
||||
DoubleVector tmp1 = o.vector.rearrange(CROSS_PRODUCT_SHUFFLE2);
|
||||
|
||||
DoubleVector tmp2 = tmp0.mul(o.vector);
|
||||
DoubleVector tmp3 = tmp0.mul(tmp1);
|
||||
|
||||
DoubleVector tmp4 = tmp2.rearrange(CROSS_PRODUCT_SHUFFLE1);
|
||||
|
||||
this.vector = tmp3.sub(tmp4).blend(FOURTH_COMPONENT_ZERO, LENGTH_3_ARRAY_MASK.not());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3D add(Vector3D o) {
|
||||
this.vector = this.vector.add(((SIMDVector3D) o).vector);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3D subtract(Vector3D o) {
|
||||
this.vector = this.vector.sub(((SIMDVector3D) o).vector);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3D multiply(Vector3D o) {
|
||||
this.vector = this.vector.mul(((SIMDVector3D) o).vector);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double distance(Vector3D o) {
|
||||
return Math.sqrt(distanceSquared(o));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double distanceSquared(Vector3D o) {
|
||||
DoubleVector diff = this.vector.sub(((SIMDVector3D) o).vector);
|
||||
return diff.mul(diff).reduceLanes(VectorOperators.ADD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double dot(Vector3D o) {
|
||||
return this.vector.mul(((SIMDVector3D) o).vector).reduceLanes(VectorOperators.ADD);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Vector3D clone() {
|
||||
// I think this makes a shallow clone if I do it like this?
|
||||
// try {
|
||||
// return (Vector3D) super.clone();
|
||||
// } catch (CloneNotSupportedException e) {
|
||||
// throw new Error(e);
|
||||
// }
|
||||
try {
|
||||
SIMDVector3D cloned = (SIMDVector3D) super.clone();
|
||||
// Create a new DoubleVector with the same values
|
||||
cloned.vector = DoubleVector.fromArray(SPECIES,
|
||||
new double[]{this.getX(), this.getY(), this.getZ(), 0}, 0);
|
||||
return cloned;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package ac.grim.grimac.utils.vector;
|
||||
|
||||
|
||||
public class VectorOperationsJava18 implements VectorOperations {
|
||||
|
||||
@Override
|
||||
public Vector3D newVector(double x, double y, double z) {
|
||||
return new SIMDVector3D(x, y, z);
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
//package ac.grim.grimac.benchmark.vector;
|
||||
//
|
||||
//import ac.grim.grimac.utils.vector.Java21SIMDVector3D;
|
||||
//import org.openjdk.jmh.annotations.*;
|
||||
//
|
||||
//import java.util.concurrent.TimeUnit;
|
||||
//
|
||||
//@BenchmarkMode(Mode.AverageTime)
|
||||
//@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
//@State(Scope.Thread)
|
||||
//@Warmup(iterations = 2, time = 1)
|
||||
//@Measurement(iterations = 3, time = 1)
|
||||
//@Fork(1)
|
||||
//public class Java21SIMDVector3DBenchmark {
|
||||
//
|
||||
// private Java21SIMDVector3D vector1;
|
||||
// private Java21SIMDVector3D vector2;
|
||||
//
|
||||
// @Setup
|
||||
// public void setup() {
|
||||
// vector1 = new Java21SIMDVector3D(1.0, 2.0, 3.0);
|
||||
// vector2 = new Java21SIMDVector3D(4.0, 5.0, 6.0);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public double benchmarkGetX() {
|
||||
// return vector1.getX();
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public double benchmarkGetY() {
|
||||
// return vector1.getY();
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public double benchmarkGetZ() {
|
||||
// return vector1.getZ();
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public Java21SIMDVector3D benchmarkSetX() {
|
||||
// return (Java21SIMDVector3D) vector1.setX(10.0);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public Java21SIMDVector3D benchmarkSetY() {
|
||||
// return (Java21SIMDVector3D) vector1.setY(20.0);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public Java21SIMDVector3D benchmarkSetZ() {
|
||||
// return (Java21SIMDVector3D) vector1.setZ(30.0);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public double benchmarkLength() {
|
||||
// return vector1.length();
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public double benchmarkLengthSquared() {
|
||||
// return vector1.lengthSquared();
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public Java21SIMDVector3D benchmarkMultiplyScalar() {
|
||||
// return (Java21SIMDVector3D) vector1.multiply(2.0);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public Java21SIMDVector3D benchmarkNormalize() {
|
||||
// return (Java21SIMDVector3D) vector1.normalize();
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public Java21SIMDVector3D benchmarkCrossProduct() {
|
||||
// return (Java21SIMDVector3D) vector1.crossProduct(vector2);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public Java21SIMDVector3D benchmarkAdd() {
|
||||
// return (Java21SIMDVector3D) vector1.add(vector2);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public Java21SIMDVector3D benchmarkSubtract() {
|
||||
// return (Java21SIMDVector3D) vector1.subtract(vector2);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public Java21SIMDVector3D benchmarkMultiplyVector() {
|
||||
// return (Java21SIMDVector3D) vector1.multiply(vector2);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public double benchmarkDistance() {
|
||||
// return vector1.distance(vector2);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public double benchmarkDistanceSquared() {
|
||||
// return vector1.distanceSquared(vector2);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public double benchmarkDotProduct() {
|
||||
// return vector1.dot(vector2);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public Java21SIMDVector3D benchmarkClone() {
|
||||
// return (Java21SIMDVector3D) vector1.clone();
|
||||
// }
|
||||
//}
|
||||
@@ -1,114 +0,0 @@
|
||||
package ac.grim.grimac.benchmark.vector;
|
||||
|
||||
import ac.grim.grimac.utils.vector.NalimVector3D;
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
@State(Scope.Thread)
|
||||
@Warmup(iterations = 2, time = 1)
|
||||
@Measurement(iterations = 3, time = 1)
|
||||
@Fork(1)
|
||||
public class NalimVector3DBenchmark {
|
||||
|
||||
private NalimVector3D vector1;
|
||||
private NalimVector3D vector2;
|
||||
|
||||
@Setup
|
||||
public void setup() {
|
||||
vector1 = new NalimVector3D(1.0, 2.0, 3.0);
|
||||
vector2 = new NalimVector3D(4.0, 5.0, 6.0);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkGetX() {
|
||||
return vector1.getX();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkGetY() {
|
||||
return vector1.getY();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkGetZ() {
|
||||
return vector1.getZ();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public NalimVector3D benchmarkSetX() {
|
||||
return (NalimVector3D) vector1.setX(10.0);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public NalimVector3D benchmarkSetY() {
|
||||
return (NalimVector3D) vector1.setY(20.0);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public NalimVector3D benchmarkSetZ() {
|
||||
return (NalimVector3D) vector1.setZ(30.0);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkLength() {
|
||||
return vector1.length();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkLengthSquared() {
|
||||
return vector1.lengthSquared();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public NalimVector3D benchmarkMultiplyScalar() {
|
||||
return (NalimVector3D) vector1.multiply(2.0);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public NalimVector3D benchmarkNormalize() {
|
||||
return (NalimVector3D) vector1.normalize();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public NalimVector3D benchmarkCrossProduct() {
|
||||
return (NalimVector3D) vector1.crossProduct(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public NalimVector3D benchmarkAdd() {
|
||||
return (NalimVector3D) vector1.add(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public NalimVector3D benchmarkSubtract() {
|
||||
return (NalimVector3D) vector1.subtract(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public NalimVector3D benchmarkMultiplyVector() {
|
||||
return (NalimVector3D) vector1.multiply(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkDistance() {
|
||||
return vector1.distance(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkDistanceSquared() {
|
||||
return vector1.distanceSquared(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkDotProduct() {
|
||||
return vector1.dot(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public NalimVector3D benchmarkClone() {
|
||||
return (NalimVector3D) vector1.clone();
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
//package ac.grim.grimac.benchmark.vector;
|
||||
//
|
||||
//import ac.grim.grimac.utils.vector.NativeVector3D;
|
||||
//import org.openjdk.jmh.annotations.*;
|
||||
//
|
||||
//import java.util.concurrent.TimeUnit;
|
||||
//
|
||||
//@BenchmarkMode(Mode.AverageTime)
|
||||
//@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
//@State(Scope.Thread)
|
||||
//@Warmup(iterations = 2, time = 1)
|
||||
//@Measurement(iterations = 3, time = 1)
|
||||
//@Fork(1)
|
||||
//public class NativeVector3DBenchmark {
|
||||
//
|
||||
// private NativeVector3D vector1;
|
||||
// private NativeVector3D vector2;
|
||||
//
|
||||
// @Setup
|
||||
// public void setup() {
|
||||
// vector1 = new NativeVector3D(1.0, 2.0, 3.0);
|
||||
// vector2 = new NativeVector3D(4.0, 5.0, 6.0);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public double benchmarkGetX() {
|
||||
// return vector1.getX();
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public double benchmarkGetY() {
|
||||
// return vector1.getY();
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public double benchmarkGetZ() {
|
||||
// return vector1.getZ();
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public NativeVector3D benchmarkSetX() {
|
||||
// return (NativeVector3D) vector1.setX(10.0);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public NativeVector3D benchmarkSetY() {
|
||||
// return (NativeVector3D) vector1.setY(20.0);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public NativeVector3D benchmarkSetZ() {
|
||||
// return (NativeVector3D) vector1.setZ(30.0);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public double benchmarkLength() {
|
||||
// return vector1.length();
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public double benchmarkLengthSquared() {
|
||||
// return vector1.lengthSquared();
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public NativeVector3D benchmarkMultiplyScalar() {
|
||||
// return (NativeVector3D) vector1.multiply(2.0);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public NativeVector3D benchmarkNormalize() {
|
||||
// return (NativeVector3D) vector1.normalize();
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public NativeVector3D benchmarkCrossProduct() {
|
||||
// return (NativeVector3D) vector1.crossProduct(vector2);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public NativeVector3D benchmarkAdd() {
|
||||
// return (NativeVector3D) vector1.add(vector2);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public NativeVector3D benchmarkSubtract() {
|
||||
// return (NativeVector3D) vector1.subtract(vector2);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public NativeVector3D benchmarkMultiplyVector() {
|
||||
// return (NativeVector3D) vector1.multiply(vector2);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public double benchmarkDistance() {
|
||||
// return vector1.distance(vector2);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public double benchmarkDistanceSquared() {
|
||||
// return vector1.distanceSquared(vector2);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public double benchmarkDotProduct() {
|
||||
// return vector1.dot(vector2);
|
||||
// }
|
||||
//
|
||||
// @Benchmark
|
||||
// public NativeVector3D benchmarkClone() {
|
||||
// return (NativeVector3D) vector1.clone();
|
||||
// }
|
||||
//}
|
||||
@@ -1,114 +0,0 @@
|
||||
package ac.grim.grimac.benchmark.vector;
|
||||
|
||||
import ac.grim.grimac.utils.vector.SIMDVector3D;
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
@State(Scope.Thread)
|
||||
@Warmup(iterations = 2, time = 1)
|
||||
@Measurement(iterations = 3, time = 1)
|
||||
@Fork(1)
|
||||
public class SIMDVector3DBenchmark {
|
||||
|
||||
private SIMDVector3D vector1;
|
||||
private SIMDVector3D vector2;
|
||||
|
||||
@Setup
|
||||
public void setup() {
|
||||
vector1 = new SIMDVector3D(1.0, 2.0, 3.0);
|
||||
vector2 = new SIMDVector3D(4.0, 5.0, 6.0);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkGetX() {
|
||||
return vector1.getX();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkGetY() {
|
||||
return vector1.getY();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkGetZ() {
|
||||
return vector1.getZ();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public SIMDVector3D benchmarkSetX() {
|
||||
return (SIMDVector3D) vector1.setX(10.0);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public SIMDVector3D benchmarkSetY() {
|
||||
return (SIMDVector3D) vector1.setY(20.0);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public SIMDVector3D benchmarkSetZ() {
|
||||
return (SIMDVector3D) vector1.setZ(30.0);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkLength() {
|
||||
return vector1.length();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkLengthSquared() {
|
||||
return vector1.lengthSquared();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public SIMDVector3D benchmarkMultiplyScalar() {
|
||||
return (SIMDVector3D) vector1.multiply(2.0);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public SIMDVector3D benchmarkNormalize() {
|
||||
return (SIMDVector3D) vector1.normalize();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public SIMDVector3D benchmarkCrossProduct() {
|
||||
return (SIMDVector3D) vector1.crossProduct(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public SIMDVector3D benchmarkAdd() {
|
||||
return (SIMDVector3D) vector1.add(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public SIMDVector3D benchmarkSubtract() {
|
||||
return (SIMDVector3D) vector1.subtract(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public SIMDVector3D benchmarkMultiplyVector() {
|
||||
return (SIMDVector3D) vector1.multiply(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkDistance() {
|
||||
return vector1.distance(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkDistanceSquared() {
|
||||
return vector1.distanceSquared(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkDotProduct() {
|
||||
return vector1.dot(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public SIMDVector3D benchmarkClone() {
|
||||
return (SIMDVector3D) vector1.clone();
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
package ac.grim.grimac.benchmark.vector;
|
||||
|
||||
import ac.grim.grimac.utils.vector.ScalarVector3D;
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
@State(Scope.Thread)
|
||||
@Warmup(iterations = 2, time = 1)
|
||||
@Measurement(iterations = 3, time = 1)
|
||||
@Fork(1)
|
||||
public class ScalarVector3DBenchmark {
|
||||
|
||||
private ScalarVector3D vector1;
|
||||
private ScalarVector3D vector2;
|
||||
|
||||
@Setup
|
||||
public void setup() {
|
||||
vector1 = new ScalarVector3D(1.0, 2.0, 3.0);
|
||||
vector2 = new ScalarVector3D(4.0, 5.0, 6.0);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkGetX() {
|
||||
return vector1.getX();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkGetY() {
|
||||
return vector1.getY();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkGetZ() {
|
||||
return vector1.getZ();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public ScalarVector3D benchmarkSetX() {
|
||||
return (ScalarVector3D) vector1.setX(10.0);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public ScalarVector3D benchmarkSetY() {
|
||||
return (ScalarVector3D) vector1.setY(20.0);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public ScalarVector3D benchmarkSetZ() {
|
||||
return (ScalarVector3D) vector1.setZ(30.0);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkLength() {
|
||||
return vector1.length();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkLengthSquared() {
|
||||
return vector1.lengthSquared();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public ScalarVector3D benchmarkMultiplyScalar() {
|
||||
return (ScalarVector3D) vector1.multiply(2.0);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public ScalarVector3D benchmarkNormalize() {
|
||||
return (ScalarVector3D) vector1.normalize();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public ScalarVector3D benchmarkCrossProduct() {
|
||||
return (ScalarVector3D) vector1.crossProduct(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public ScalarVector3D benchmarkAdd() {
|
||||
return (ScalarVector3D) vector1.add(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public ScalarVector3D benchmarkSubtract() {
|
||||
return (ScalarVector3D) vector1.subtract(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public ScalarVector3D benchmarkMultiplyVector() {
|
||||
return (ScalarVector3D) vector1.multiply(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkDistance() {
|
||||
return vector1.distance(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkDistanceSquared() {
|
||||
return vector1.distanceSquared(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public double benchmarkDotProduct() {
|
||||
return vector1.dot(vector2);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public ScalarVector3D benchmarkClone() {
|
||||
return (ScalarVector3D) vector1.clone();
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,6 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.common.ConfigReloadObserver;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
|
||||
import io.github.retrooper.packetevents.util.folia.FoliaScheduler;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -152,39 +150,6 @@ public class Check implements AbstractCheck, ConfigReloadObserver {
|
||||
packetType == PacketType.Play.Client.WINDOW_CONFIRMATION;
|
||||
}
|
||||
|
||||
public boolean isFlying(PacketTypeCommon packetType) {
|
||||
return WrapperPlayClientPlayerFlying.isFlying(packetType);
|
||||
}
|
||||
|
||||
public boolean isUpdate(PacketTypeCommon packetType) {
|
||||
return isFlying(packetType)
|
||||
|| packetType == PacketType.Play.Client.CLIENT_TICK_END
|
||||
|| isTransaction(packetType);
|
||||
}
|
||||
|
||||
public boolean isTickPacket(PacketTypeCommon packetType) {
|
||||
if (isTickPacketIncludingNonMovement(packetType)) {
|
||||
if (isFlying(packetType)) {
|
||||
return !player.packetStateData.lastPacketWasTeleport && !player.packetStateData.lastPacketWasOnePointSeventeenDuplicate;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isTickPacketIncludingNonMovement(PacketTypeCommon packetType) {
|
||||
// On 1.21.2+ fall back to the TICK_END packet IF the player did not send a movement packet for their tick
|
||||
// TickTimer checks to see if player did not send a tick end packet before new flying packet is sent
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21_2)
|
||||
&& !player.packetStateData.didSendMovementBeforeTickEnd) {
|
||||
if (packetType == PacketType.Play.Client.CLIENT_TICK_END) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return isFlying(packetType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
reload(GrimAPI.INSTANCE.getConfigManager().getConfig());
|
||||
|
||||
@@ -6,7 +6,6 @@ import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
|
||||
|
||||
@CheckData(name = "BadPacketsE")
|
||||
@@ -24,12 +23,11 @@ public class BadPacketsE extends Check implements PacketCheck {
|
||||
noReminderTicks = 0;
|
||||
} else if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) {
|
||||
noReminderTicks++;
|
||||
} else if (event.getPacketType() == PacketType.Play.Client.STEER_VEHICLE
|
||||
|| (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21_2) && player.compensatedEntities.getSelf().inVehicle())) {
|
||||
} else if (event.getPacketType() == PacketType.Play.Client.STEER_VEHICLE ||
|
||||
event.getPacketType() == PacketType.Play.Client.VEHICLE_MOVE) {
|
||||
noReminderTicks = 0; // Exempt vehicles
|
||||
}
|
||||
|
||||
|
||||
if (noReminderTicks > 20) {
|
||||
flagAndAlert("ticks=" + noReminderTicks); // ban? I don't know how this would false
|
||||
}
|
||||
|
||||
@@ -10,7 +10,8 @@ import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEn
|
||||
|
||||
@CheckData(name = "BadPacketsG")
|
||||
public class BadPacketsG extends Check implements PacketCheck {
|
||||
private boolean lastSneaking, respawn;
|
||||
boolean wasTeleport;
|
||||
boolean lastSneaking;
|
||||
|
||||
public BadPacketsG(GrimPlayer player) {
|
||||
super(player);
|
||||
@@ -18,12 +19,13 @@ public class BadPacketsG extends Check implements PacketCheck {
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
wasTeleport = player.packetStateData.lastPacketWasTeleport || wasTeleport;
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Client.ENTITY_ACTION) {
|
||||
WrapperPlayClientEntityAction packet = new WrapperPlayClientEntityAction(event);
|
||||
|
||||
if (packet.getAction() == WrapperPlayClientEntityAction.Action.START_SNEAKING) {
|
||||
// The player may send two START_SNEAKING packets if they respawned
|
||||
if (lastSneaking && !respawn) {
|
||||
if (lastSneaking && !wasTeleport) {
|
||||
if (flagAndAlert("state=true") && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -31,9 +33,8 @@ public class BadPacketsG extends Check implements PacketCheck {
|
||||
} else {
|
||||
lastSneaking = true;
|
||||
}
|
||||
respawn = false;
|
||||
} else if (packet.getAction() == WrapperPlayClientEntityAction.Action.STOP_SNEAKING) {
|
||||
if (!lastSneaking && !respawn) {
|
||||
if (!lastSneaking && !wasTeleport) {
|
||||
if (flagAndAlert("state=false") && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -41,13 +42,7 @@ public class BadPacketsG extends Check implements PacketCheck {
|
||||
} else {
|
||||
lastSneaking = false;
|
||||
}
|
||||
respawn = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleRespawn() {
|
||||
// Clients could potentially not send a STOP_SNEAKING packet when they die, so we need to track it
|
||||
respawn = true;
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ public class BadPacketsH extends Check implements PacketCheck {
|
||||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_9)
|
||||
&& PacketEvents.getAPI().getServerManager().getVersion().isNewerThan(ServerVersion.V_1_8)) return;
|
||||
|
||||
if (!sentAnimation && flagAndAlert() && shouldModifyPackets()) {
|
||||
if (!sentAnimation && flagAndAlert()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
|
||||
@@ -41,8 +41,9 @@ public class BadPacketsR extends Check implements PacketCheck {
|
||||
if ((event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION ||
|
||||
event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION) && !player.compensatedEntities.getSelf().inVehicle()) {
|
||||
positions++;
|
||||
} else if ((event.getPacketType() == PacketType.Play.Client.STEER_VEHICLE || event.getPacketType() == PacketType.Play.Client.VEHICLE_MOVE)
|
||||
&& player.inVehicle()) {
|
||||
} else if ((event.getPacketType() == PacketType.Play.Client.STEER_VEHICLE ||
|
||||
event.getPacketType() == PacketType.Play.Client.VEHICLE_MOVE)
|
||||
&& player.compensatedEntities.getSelf().inVehicle()) {
|
||||
positions++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package ac.grim.grimac.checks.impl.badpackets;
|
||||
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
|
||||
|
||||
@CheckData(name = "BadPacketsV", experimental = true)
|
||||
public class BadPacketsV extends Check implements PacketCheck {
|
||||
public BadPacketsV(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY) {
|
||||
WrapperPlayClientInteractEntity interactEntity = new WrapperPlayClientInteractEntity(event);
|
||||
if (interactEntity.getAction() != WrapperPlayClientInteractEntity.InteractAction.ATTACK) return;
|
||||
if (!player.packetStateData.isSlowedByUsingItem()) return;
|
||||
ItemStack itemInUse = player.getInventory().getItemInHand(player.packetStateData.eatingHand);
|
||||
if (flagAndAlert("UseItem=" + itemInUse.getType().getName().getKey()) && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,13 +5,16 @@ import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.update.BlockBreak;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.DiggingAction;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging;
|
||||
|
||||
@CheckData(name = "BadPacketsX")
|
||||
public class BadPacketsX extends Check implements PacketCheck {
|
||||
@@ -26,26 +29,26 @@ public class BadPacketsX extends Check implements PacketCheck {
|
||||
|
||||
public final boolean noFireHitbox = player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_15_2);
|
||||
|
||||
public final void handle(BlockBreak blockBreak) {
|
||||
if (blockBreak.action != DiggingAction.START_DIGGING && blockBreak.action != DiggingAction.FINISHED_DIGGING)
|
||||
public final void handle(PacketReceiveEvent event, WrapperPlayClientPlayerDigging dig, StateType block) {
|
||||
if (dig.getAction() != DiggingAction.START_DIGGING && dig.getAction() != DiggingAction.FINISHED_DIGGING)
|
||||
return;
|
||||
|
||||
final StateType block = blockBreak.block.getType();
|
||||
|
||||
// Fixes false from breaking kelp underwater
|
||||
// The client sends two start digging packets to the server both in the same tick. BadPacketsX gets called twice, doesn't false the first time, but falses the second
|
||||
// One ends up breaking the kelp, the other ends up doing nothing besides falsing this check because we think they're trying to mine water
|
||||
// I am explicitly making this patch as narrow and specific as possible to potentially discover other blocks that exhibit similar behaviour
|
||||
int newTick = GrimAPI.INSTANCE.getTickManager().currentTick;
|
||||
if (lastTick == newTick
|
||||
&& lastBreakLoc.equals(blockBreak.position)
|
||||
&& lastBreakLoc.equals(dig.getBlockPosition())
|
||||
&& !didLastFlag
|
||||
&& lastBlockType.getHardness() == 0.0F
|
||||
&& lastBlockType.getBlastResistance() == 0.0F
|
||||
&& block == StateTypes.WATER
|
||||
) return;
|
||||
) {
|
||||
return;
|
||||
}
|
||||
lastTick = newTick;
|
||||
lastBreakLoc = blockBreak.position;
|
||||
lastBreakLoc = dig.getBlockPosition();
|
||||
lastBlockType = block;
|
||||
|
||||
// the block does not have a hitbox
|
||||
@@ -55,13 +58,14 @@ public class BadPacketsX extends Check implements PacketCheck {
|
||||
|| block == StateTypes.LAVA
|
||||
|| block == StateTypes.BUBBLE_COLUMN
|
||||
|| block == StateTypes.MOVING_PISTON
|
||||
|| block == StateTypes.FIRE && noFireHitbox
|
||||
|| (block == StateTypes.FIRE && noFireHitbox)
|
||||
// or the client claims to have broken an unbreakable block
|
||||
|| block.getHardness() == -1.0f && blockBreak.action == DiggingAction.FINISHED_DIGGING;
|
||||
|| block.getHardness() == -1.0f && dig.getAction() == DiggingAction.FINISHED_DIGGING;
|
||||
|
||||
if (invalid && flagAndAlert("block=" + block.getName() + ", type=" + blockBreak.action) && shouldModifyPackets()) {
|
||||
if (invalid && flagAndAlert("block=" + block.getName() + ", type=" + dig.getAction()) && shouldModifyPackets()) {
|
||||
didLastFlag = true;
|
||||
blockBreak.cancel();
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
} else {
|
||||
didLastFlag = false;
|
||||
}
|
||||
|
||||
@@ -5,12 +5,13 @@ import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
import ac.grim.grimac.utils.anticheat.update.BlockBreak;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.DiggingAction;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging;
|
||||
|
||||
import static ac.grim.grimac.events.packets.patch.ResyncWorldUtil.resyncPosition;
|
||||
import static ac.grim.grimac.utils.nmsutil.BlockBreakSpeed.getBlockDamage;
|
||||
@@ -39,9 +40,9 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
return player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) || getBlockDamage(player, pos) < 1;
|
||||
}
|
||||
|
||||
public void handle(BlockBreak blockBreak) {
|
||||
if (blockBreak.action == DiggingAction.START_DIGGING) {
|
||||
final Vector3i pos = blockBreak.position;
|
||||
public void handle(PacketReceiveEvent event, WrapperPlayClientPlayerDigging dig) {
|
||||
if (dig.getAction() == DiggingAction.START_DIGGING) {
|
||||
final Vector3i pos = dig.getBlockPosition();
|
||||
|
||||
lastBlockWasInstantBreak = getBlockDamage(player, pos) >= 1;
|
||||
lastCancelledBlock = null;
|
||||
@@ -49,8 +50,8 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
lastBlock = pos;
|
||||
}
|
||||
|
||||
if (blockBreak.action == DiggingAction.CANCELLED_DIGGING) {
|
||||
final Vector3i pos = blockBreak.position;
|
||||
if (dig.getAction() == DiggingAction.CANCELLED_DIGGING) {
|
||||
final Vector3i pos = dig.getBlockPosition();
|
||||
|
||||
if (shouldExempt(pos)) {
|
||||
lastCancelledBlock = pos;
|
||||
@@ -64,7 +65,8 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) || (!lastBlockWasInstantBreak && pos.equals(lastCancelledBlock))) {
|
||||
if (flagAndAlert("action=CANCELLED_DIGGING" + ", last=" + MessageUtil.toUnlabledString(lastBlock) + ", pos=" + MessageUtil.toUnlabledString(pos))) {
|
||||
if (shouldModifyPackets()) {
|
||||
blockBreak.cancel();
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
resyncPosition(player, pos);
|
||||
}
|
||||
}
|
||||
@@ -77,14 +79,15 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
return;
|
||||
}
|
||||
|
||||
if (blockBreak.action == DiggingAction.FINISHED_DIGGING) {
|
||||
final Vector3i pos = blockBreak.position;
|
||||
if (dig.getAction() == DiggingAction.FINISHED_DIGGING) {
|
||||
final Vector3i pos = dig.getBlockPosition();
|
||||
|
||||
// when a player looks away from the mined block, they send a cancel, and if they look at it again, they don't send another start. (thanks mojang!)
|
||||
if (!pos.equals(lastCancelledBlock) && (!lastBlockWasInstantBreak || player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4)) && !pos.equals(lastBlock)) {
|
||||
if (flagAndAlert("action=FINISHED_DIGGING" + ", last=" + MessageUtil.toUnlabledString(lastBlock) + ", pos=" + MessageUtil.toUnlabledString(pos))) {
|
||||
if (shouldModifyPackets()) {
|
||||
blockBreak.cancel();
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
resyncPosition(player, pos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntity;
|
||||
import ac.grim.grimac.utils.data.packetentity.dragon.PacketEntityEnderDragonPart;
|
||||
import ac.grim.grimac.utils.nmsutil.ReachUtils;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
|
||||
@@ -34,14 +33,13 @@ import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
// You may not copy the check unless you are licensed under GPL
|
||||
@CheckData(name = "Reach", configName = "Reach", setback = 10)
|
||||
public class Reach extends Check implements PacketCheck {
|
||||
@@ -110,7 +108,9 @@ public class Reach extends Check implements PacketCheck {
|
||||
}
|
||||
|
||||
// If the player set their look, or we know they have a new tick
|
||||
if (isUpdate(event.getPacketType())) {
|
||||
if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType()) ||
|
||||
event.getPacketType() == PacketType.Play.Client.PONG ||
|
||||
event.getPacketType() == PacketType.Play.Client.WINDOW_CONFIRMATION) {
|
||||
tickBetterReachCheckWithAngle();
|
||||
}
|
||||
}
|
||||
@@ -185,7 +185,7 @@ public class Reach extends Check implements PacketCheck {
|
||||
double minDistance = Double.MAX_VALUE;
|
||||
|
||||
// https://bugs.mojang.com/browse/MC-67665
|
||||
List<Vector3D> possibleLookDirs = new ArrayList<>(Collections.singletonList(ReachUtils.getLook(player, player.xRot, player.yRot)));
|
||||
List<Vector> possibleLookDirs = new ArrayList<>(Collections.singletonList(ReachUtils.getLook(player, player.xRot, player.yRot)));
|
||||
|
||||
// If we are a tick behind, we don't know their next look so don't bother doing this
|
||||
if (!isPrediction) {
|
||||
@@ -205,12 +205,12 @@ public class Reach extends Check implements PacketCheck {
|
||||
// +3 would be 3 + 3 = 6, which is the pre-1.20.5 behaviour, preventing "Missed Hitbox"
|
||||
final double distance = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_ENTITY_INTERACTION_RANGE) + 3;
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
for (Vector3D lookVec : possibleLookDirs) {
|
||||
for (Vector lookVec : possibleLookDirs) {
|
||||
for (double eye : possibleEyeHeights) {
|
||||
ac.grim.grimac.utils.vector.Vector3D eyePos = newVector3D(from.getX(), from.getY() + eye, from.getZ());
|
||||
ac.grim.grimac.utils.vector.Vector3D endReachPos = eyePos.clone().add(newVector3D(lookVec.getX() * distance, lookVec.getY() * distance, lookVec.getZ() * distance));
|
||||
Vector eyePos = new Vector(from.getX(), from.getY() + eye, from.getZ());
|
||||
Vector endReachPos = eyePos.clone().add(new Vector(lookVec.getX() * distance, lookVec.getY() * distance, lookVec.getZ() * distance));
|
||||
|
||||
Vector3D intercept = ReachUtils.calculateIntercept(targetBox, eyePos, endReachPos).first();
|
||||
Vector intercept = ReachUtils.calculateIntercept(targetBox, eyePos, endReachPos).first();
|
||||
|
||||
if (ReachUtils.isVecInside(targetBox, eyePos)) {
|
||||
minDistance = 0;
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
package ac.grim.grimac.checks.impl.exploit;
|
||||
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEditBook;
|
||||
|
||||
@CheckData(name = "ExploitC")
|
||||
public class ExploitC extends Check implements PacketCheck {
|
||||
public ExploitC(GrimPlayer playerData) {
|
||||
super(playerData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.EDIT_BOOK) {
|
||||
final String title = new WrapperPlayClientEditBook(event).getTitle();
|
||||
|
||||
if (title == null) return; // book was not signed
|
||||
|
||||
if (title.length() > 15) {
|
||||
if (flagAndAlert("title=" + title) && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package ac.grim.grimac.checks.impl.movement;
|
||||
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PostPredictionCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
|
||||
|
||||
@CheckData(name = "TickTimer", setback = 1)
|
||||
public class TickTimer extends Check implements PostPredictionCheck {
|
||||
|
||||
private boolean receivedTickEnd = true;
|
||||
private int flyingPackets = 0;
|
||||
|
||||
public TickTimer(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (!player.supportsEndTick()) return;
|
||||
if (isFlying(event.getPacketType()) && !player.packetStateData.lastPacketWasTeleport) {
|
||||
if (!receivedTickEnd) flagAndAlert("type=flying, packets=" + flyingPackets);
|
||||
receivedTickEnd = false;
|
||||
flyingPackets++;
|
||||
} else if (event.getPacketType() == PacketType.Play.Client.CLIENT_TICK_END) {
|
||||
receivedTickEnd = true;
|
||||
if (flyingPackets > 1) flagAndAlert("type=end, packets=" + flyingPackets);
|
||||
flyingPackets = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
|
||||
|
||||
@CheckData(name = "Timer", configName = "TimerA", setback = 10)
|
||||
public class TimerCheck extends Check implements PacketCheck {
|
||||
@@ -17,10 +18,10 @@ public class TimerCheck extends Check implements PacketCheck {
|
||||
long knownPlayerClockTime = (long) (System.nanoTime() - 6e10);
|
||||
long lastMovementPlayerClock = (long) (System.nanoTime() - 6e10);
|
||||
|
||||
// How long should the player be able to fall back behind their ping? (nanos)
|
||||
// How long should the player be able to fall back behind their ping?
|
||||
// Default: 120 milliseconds
|
||||
long clockDrift;
|
||||
// At what ping should we start to limit the balance advantage? (nanos)
|
||||
|
||||
long limitAbuseOverPing;
|
||||
|
||||
boolean hasGottenMovementAfterTransaction = false;
|
||||
@@ -72,31 +73,35 @@ public class TimerCheck extends Check implements PacketCheck {
|
||||
doCheck(event);
|
||||
}
|
||||
|
||||
|
||||
public void doCheck(final PacketReceiveEvent event) {
|
||||
if (timerBalanceRealTime > System.nanoTime()) {
|
||||
final double transactionPing = player.getTransactionPing();
|
||||
// Limit using transaction ping if over 1000ms (default)
|
||||
final boolean needsAdjustment = limitAbuseOverPing != -1 && transactionPing >= limitAbuseOverPing;
|
||||
final boolean wouldFailNormal = timerBalanceRealTime > System.nanoTime();
|
||||
final boolean failsAdjusted = needsAdjustment && (timerBalanceRealTime + ((transactionPing * 1e6) - clockDrift - 50e6)) > System.nanoTime();
|
||||
if (wouldFailNormal || failsAdjusted) {
|
||||
if (flag()) {
|
||||
// Cancel the packet
|
||||
// Only cancel if not an adjustment setback
|
||||
if (shouldModifyPackets()) {
|
||||
if (wouldFailNormal && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
|
||||
if (isAboveSetbackVl()) player.getSetbackTeleportUtil().executeNonSimulatingSetback();
|
||||
|
||||
alert("");
|
||||
if (wouldFailNormal) {
|
||||
// Only alert if we would fail without adjusted limit
|
||||
alert("");
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the violation by 1 movement
|
||||
timerBalanceRealTime -= 50e6;
|
||||
}
|
||||
|
||||
// Limit using transaction ping if over 1000ms (default)
|
||||
long playerClock = lastMovementPlayerClock;
|
||||
if (System.nanoTime() - playerClock > limitAbuseOverPing) {
|
||||
playerClock = System.nanoTime() - limitAbuseOverPing;
|
||||
}
|
||||
timerBalanceRealTime = Math.max(timerBalanceRealTime, playerClock - clockDrift);
|
||||
timerBalanceRealTime = Math.max(timerBalanceRealTime, lastMovementPlayerClock - clockDrift);
|
||||
}
|
||||
|
||||
public boolean checkForTransaction(PacketTypeCommon packetType) {
|
||||
@@ -106,12 +111,13 @@ public class TimerCheck extends Check implements PacketCheck {
|
||||
|
||||
public boolean shouldCountPacketForTimer(PacketTypeCommon packetType) {
|
||||
// If not flying, or this was a teleport, or this was a duplicate 1.17 mojang stupidity packet
|
||||
return isTickPacket(packetType);
|
||||
return WrapperPlayClientPlayerFlying.isFlying(packetType) &&
|
||||
!player.packetStateData.lastPacketWasTeleport && !player.packetStateData.lastPacketWasOnePointSeventeenDuplicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
clockDrift = (long) (config.getDoubleElse(getConfigName() + ".drift", 120.0) * 1e6);
|
||||
limitAbuseOverPing = (long) (config.getDoubleElse(getConfigName() + ".ping-abuse-limit-threshold", 1000) * 1e6);
|
||||
limitAbuseOverPing = (long) (config.getDoubleElse(getConfigName() + ".ping-abuse-limit-threshold", 1000));
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package ac.grim.grimac.checks.impl.multiactions;
|
||||
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.player.InteractionHand;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
|
||||
|
||||
@CheckData(name = "MultiActionsA", experimental = true)
|
||||
public class MultiActionsA extends Check implements PacketCheck {
|
||||
public MultiActionsA(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (player.packetStateData.isSlowedByUsingItem() && (player.packetStateData.lastSlotSelected == player.packetStateData.getSlowedByUsingItemSlot() || player.packetStateData.eatingHand == InteractionHand.OFF_HAND) && event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY) {
|
||||
if (new WrapperPlayClientInteractEntity(event).getAction() == WrapperPlayClientInteractEntity.InteractAction.ATTACK) {
|
||||
if (flagAndAlert() && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package ac.grim.grimac.checks.impl.multiactions;
|
||||
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.DiggingAction;
|
||||
import com.github.retrooper.packetevents.protocol.player.InteractionHand;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging;
|
||||
|
||||
import static ac.grim.grimac.events.packets.patch.ResyncWorldUtil.resyncPosition;
|
||||
|
||||
@CheckData(name = "MultiActionsB", experimental = true)
|
||||
public class MultiActionsB extends Check implements PacketCheck {
|
||||
public MultiActionsB(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (player.packetStateData.isSlowedByUsingItem() && (player.packetStateData.lastSlotSelected == player.packetStateData.getSlowedByUsingItemSlot() || player.packetStateData.eatingHand == InteractionHand.OFF_HAND) && event.getPacketType() == PacketType.Play.Client.PLAYER_DIGGING) {
|
||||
// this is vanilla on 1.7
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_7_10)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final WrapperPlayClientPlayerDigging packet = new WrapperPlayClientPlayerDigging(event);
|
||||
|
||||
if (packet.getAction() == DiggingAction.START_DIGGING || packet.getAction() == DiggingAction.CANCELLED_DIGGING || packet.getAction() == DiggingAction.FINISHED_DIGGING) {
|
||||
if (flagAndAlert() && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
resyncPosition(player, packet.getBlockPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package ac.grim.grimac.checks.impl.multiactions;
|
||||
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
|
||||
@CheckData(name = "MultiActionsC", experimental = true)
|
||||
public class MultiActionsC extends Check implements PacketCheck {
|
||||
public MultiActionsC(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.CLICK_WINDOW) {
|
||||
String verbose = player.isSprinting && !player.isSwimming ? "sprinting" : "";
|
||||
|
||||
if (player.packetStateData.isSlowedByUsingItem()) {
|
||||
verbose += (verbose.isEmpty() ? "" : ", ") + "using";
|
||||
}
|
||||
|
||||
if (!verbose.isEmpty() && flagAndAlert(verbose) && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package ac.grim.grimac.checks.impl.multiactions;
|
||||
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
|
||||
@CheckData(name = "MultiActionsD", experimental = true)
|
||||
public class MultiActionsD extends Check implements PacketCheck {
|
||||
public MultiActionsD(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.CLOSE_WINDOW) {
|
||||
String verbose = player.isSprinting && !player.isSwimming ? "sprinting" : "";
|
||||
|
||||
if (player.packetStateData.isSlowedByUsingItem()) {
|
||||
verbose += (verbose.isEmpty() ? "" : ", ") + "using";
|
||||
}
|
||||
|
||||
if (!verbose.isEmpty() && flagAndAlert(verbose) && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package ac.grim.grimac.checks.impl.multiactions;
|
||||
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.InteractionHand;
|
||||
|
||||
@CheckData(name = "MultiActionsE", experimental = true)
|
||||
public class MultiActionsE extends Check implements PacketCheck {
|
||||
public MultiActionsE(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (player.packetStateData.isSlowedByUsingItem() && (player.packetStateData.lastSlotSelected == player.packetStateData.getSlowedByUsingItemSlot() || player.packetStateData.eatingHand == InteractionHand.OFF_HAND) && event.getPacketType() == PacketType.Play.Client.ANIMATION) {
|
||||
// this is possible to false on 1.7
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_7_10)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (flagAndAlert() && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
package ac.grim.grimac.checks.impl.multiactions;
|
||||
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.BlockPlaceCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.update.BlockPlace;
|
||||
import ac.grim.grimac.utils.anticheat.update.PredictionComplete;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.DiggingAction;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static ac.grim.grimac.events.packets.patch.ResyncWorldUtil.resyncPosition;
|
||||
|
||||
@CheckData(name = "MultiActionsF", experimental = true)
|
||||
public class MultiActionsF extends BlockPlaceCheck {
|
||||
public MultiActionsF(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
private final List<String> flags = new ArrayList<>();
|
||||
boolean entity, block;
|
||||
|
||||
@Override
|
||||
public void onBlockPlace(BlockPlace place) {
|
||||
block = true;
|
||||
if (entity) {
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) {
|
||||
if (flagAndAlert("place") && shouldModifyPackets() && shouldCancel()) {
|
||||
place.resync();
|
||||
}
|
||||
} else {
|
||||
flags.add("place");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY) {
|
||||
entity = true;
|
||||
if (block) {
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) {
|
||||
if (flagAndAlert("entity") && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
} else {
|
||||
flags.add("entity");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Client.PLAYER_DIGGING) {
|
||||
WrapperPlayClientPlayerDigging packet = new WrapperPlayClientPlayerDigging(event);
|
||||
if (packet.getAction() == DiggingAction.START_DIGGING || packet.getAction() == DiggingAction.FINISHED_DIGGING) {
|
||||
block = true;
|
||||
if (entity) {
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) {
|
||||
if (flagAndAlert("dig") && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
resyncPosition(player, packet.getBlockPosition());
|
||||
}
|
||||
} else {
|
||||
flags.add("dig");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType()) && !player.packetStateData.lastPacketWasTeleport && !player.packetStateData.lastPacketWasOnePointSeventeenDuplicate) {
|
||||
block = entity = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (player.getClientVersion().isNewerThan(ClientVersion.V_1_8) && player.isTickingReliablyFor(3) && !player.uncertaintyHandler.lastVehicleSwitch.hasOccurredSince(0)) {
|
||||
for (String verbose : flags) {
|
||||
flagAndAlert(verbose);
|
||||
}
|
||||
}
|
||||
|
||||
flags.clear();
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEntityAction;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityAnimation;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
@@ -67,7 +68,12 @@ public class PostCheck extends Check implements PacketCheck, PostPredictionCheck
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(final PacketReceiveEvent event) {
|
||||
if (isTickPacket(event.getPacketType())) { // Don't count teleports or duplicates as movements
|
||||
if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) {
|
||||
// Don't count teleports or duplicates as movements
|
||||
if (player.packetStateData.lastPacketWasTeleport || player.packetStateData.lastPacketWasOnePointSeventeenDuplicate) {
|
||||
return;
|
||||
}
|
||||
|
||||
post.clear();
|
||||
sentFlying = true;
|
||||
} else {
|
||||
|
||||
@@ -9,7 +9,7 @@ import ac.grim.grimac.utils.anticheat.update.PredictionComplete;
|
||||
import ac.grim.grimac.utils.lists.EvictingQueue;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -45,8 +45,8 @@ public class DebugHandler extends Check implements PostPredictionCheck {
|
||||
|
||||
ChatColor color = pickColor(offset, offset);
|
||||
|
||||
Vector3D predicted = player.predictedVelocity.vector;
|
||||
Vector3D actually = player.actualMovement;
|
||||
Vector predicted = player.predictedVelocity.vector;
|
||||
Vector actually = player.actualMovement;
|
||||
|
||||
ChatColor xColor = pickColor(Math.abs(predicted.getX() - actually.getX()), offset);
|
||||
ChatColor yColor = pickColor(Math.abs(predicted.getY() - actually.getY()), offset);
|
||||
|
||||
@@ -9,9 +9,7 @@ import ac.grim.grimac.utils.math.VectorUtils;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
@CheckData(name = "FarPlace")
|
||||
public class FarPlace extends BlockPlaceCheck {
|
||||
@@ -29,8 +27,8 @@ public class FarPlace extends BlockPlaceCheck {
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
for (double d : possibleEyeHeights) {
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(blockPos);
|
||||
Vector3D eyes = newVector3D(player.x, player.y + d, player.z);
|
||||
Vector3D best = VectorUtils.cutBoxToVector(eyes, box);
|
||||
Vector eyes = new Vector(player.x, player.y + d, player.z);
|
||||
Vector best = VectorUtils.cutBoxToVector(eyes, box);
|
||||
min = Math.min(min, eyes.distanceSquared(best));
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.util.Vector3f;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -55,7 +56,7 @@ public class MultiPlace extends BlockPlaceCheck {
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (isTickPacket(event.getPacketType())) {
|
||||
if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType()) && !player.packetStateData.lastPacketWasTeleport && !player.packetStateData.lastPacketWasOnePointSeventeenDuplicate) {
|
||||
hasPlaced = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.Pair;
|
||||
import ac.grim.grimac.utils.nmsutil.Ray;
|
||||
import ac.grim.grimac.utils.nmsutil.ReachUtils;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
@@ -16,6 +15,7 @@ import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.util.Vector3f;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -111,7 +111,7 @@ public class RotationPlace extends BlockPlaceCheck {
|
||||
Vector3d starting = new Vector3d(player.x, player.y + d, player.z);
|
||||
// xRot and yRot are a tick behind
|
||||
Ray trace = new Ray(player, starting.getX(), starting.getY(), starting.getZ(), lookDir.getX(), lookDir.getY());
|
||||
Pair<Vector3D, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
Pair<Vector, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
|
||||
if (intercept.first() != null) return true;
|
||||
}
|
||||
|
||||
@@ -19,13 +19,12 @@ import com.github.retrooper.packetevents.util.Vector3f;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerExplosion;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
@CheckData(name = "AntiExplosion", configName = "Explosion", setback = 10)
|
||||
public class ExplosionHandler extends Check implements PostPredictionCheck {
|
||||
Deque<VelocityData> firstBreadMap = new LinkedList<>();
|
||||
@@ -122,7 +121,7 @@ public class ExplosionHandler extends Check implements PostPredictionCheck {
|
||||
}
|
||||
|
||||
public void addPlayerExplosion(int breadOne, Vector3f explosion) {
|
||||
firstBreadMap.add(new VelocityData(-1, breadOne, player.getSetbackTeleportUtil().isSendingSetback, newVector3D(explosion.getX(), explosion.getY(), explosion.getZ())));
|
||||
firstBreadMap.add(new VelocityData(-1, breadOne, player.getSetbackTeleportUtil().isSendingSetback, new Vector(explosion.getX(), explosion.getY(), explosion.getZ())));
|
||||
}
|
||||
|
||||
public void setPointThree(boolean isPointThree) {
|
||||
|
||||
@@ -15,14 +15,12 @@ import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityVelocity;
|
||||
import lombok.Getter;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
// We are making a velocity sandwich between two pieces of transaction packets (bread)
|
||||
@CheckData(name = "AntiKB", alternativeName = "AntiKnockback", configName = "Knockback", setback = 10, decay = 0.025)
|
||||
public class KnockbackHandler extends Check implements PostPredictionCheck {
|
||||
@@ -68,17 +66,16 @@ public class KnockbackHandler extends Check implements PostPredictionCheck {
|
||||
if (playerVelocity.getY() == -0.04) {
|
||||
velocity.setVelocity(playerVelocity.add(new Vector3d(0, 1 / 8000D, 0)));
|
||||
playerVelocity = velocity.getVelocity();
|
||||
event.markForReEncode(true);
|
||||
}
|
||||
|
||||
// Wrap velocity between two transactions
|
||||
player.sendTransaction();
|
||||
addPlayerKnockback(entityId, player.lastTransactionSent.get(), newVector3D(playerVelocity.getX(), playerVelocity.getY(), playerVelocity.getZ()));
|
||||
addPlayerKnockback(entityId, player.lastTransactionSent.get(), new Vector(playerVelocity.getX(), playerVelocity.getY(), playerVelocity.getZ()));
|
||||
event.getTasksAfterSend().add(player::sendTransaction);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull public Pair<VelocityData, Vector3D> getFutureKnockback() {
|
||||
@NotNull public Pair<VelocityData, Vector> getFutureKnockback() {
|
||||
// Chronologically in the future
|
||||
if (firstBreadMap.size() > 0) {
|
||||
VelocityData data = firstBreadMap.peek();
|
||||
@@ -100,7 +97,7 @@ public class KnockbackHandler extends Check implements PostPredictionCheck {
|
||||
return new Pair<>(null, null);
|
||||
}
|
||||
|
||||
private void addPlayerKnockback(int entityID, int breadOne, Vector3D knockback) {
|
||||
private void addPlayerKnockback(int entityID, int breadOne, Vector knockback) {
|
||||
firstBreadMap.add(new VelocityData(entityID, breadOne, player.getSetbackTeleportUtil().isSendingSetback, knockback));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
package ac.grim.grimac.checks.type;
|
||||
|
||||
|
||||
import ac.grim.grimac.api.AbstractCheck;
|
||||
import ac.grim.grimac.utils.anticheat.update.PositionUpdate;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.event.PacketSendEvent;
|
||||
|
||||
public interface PacketCheck extends AbstractCheck {
|
||||
default void onPacketReceive(final PacketReceiveEvent event) {}
|
||||
default void onPacketSend(final PacketSendEvent event) {}
|
||||
|
||||
default void onPacketReceive(final PacketReceiveEvent event) {
|
||||
}
|
||||
|
||||
default void onPacketSend(final PacketSendEvent event) {
|
||||
}
|
||||
|
||||
default void onPositionUpdate(final PositionUpdate positionUpdate) {
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,6 @@ import ac.grim.grimac.utils.latency.CompensatedWorld;
|
||||
import ac.grim.grimac.utils.math.GrimMath;
|
||||
import ac.grim.grimac.utils.math.VectorUtils;
|
||||
import ac.grim.grimac.utils.nmsutil.*;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import ac.grim.grimac.utils.vector.VectorFactory;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import com.github.retrooper.packetevents.event.PacketListenerPriority;
|
||||
@@ -49,6 +47,7 @@ import com.github.retrooper.packetevents.wrapper.play.client.*;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerAcknowledgeBlockChanges;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetSlot;
|
||||
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -372,7 +371,9 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
}
|
||||
|
||||
// Manual filter on FINISH_DIGGING to prevent clients setting non-breakable blocks to air
|
||||
private static final Function<StateType, Boolean> BREAKABLE = type -> !type.isAir() && type.getHardness() != -1.0f && type != StateTypes.WATER && type != StateTypes.LAVA;
|
||||
private static final Function<StateType, Boolean> BREAKABLE = type -> {
|
||||
return !type.isAir() && type.getHardness() != -1.0f && type != StateTypes.WATER && type != StateTypes.LAVA;
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
@@ -454,43 +455,43 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Client.PLAYER_DIGGING) {
|
||||
final WrapperPlayClientPlayerDigging packet = new WrapperPlayClientPlayerDigging(event);
|
||||
final BlockBreak blockBreak = new BlockBreak(packet, player);
|
||||
WrapperPlayClientPlayerDigging dig = new WrapperPlayClientPlayerDigging(event);
|
||||
final Vector3i digPosition = dig.getBlockPosition();
|
||||
WrappedBlockState block = player.compensatedWorld.getWrappedBlockStateAt(digPosition);
|
||||
final StateType type = block.getType();
|
||||
|
||||
player.checkManager.getPacketCheck(BadPacketsX.class).handle(blockBreak);
|
||||
player.checkManager.getPacketCheck(BadPacketsZ.class).handle(blockBreak);
|
||||
player.checkManager.getPacketCheck(BadPacketsX.class).handle(event, dig, type);
|
||||
player.checkManager.getPacketCheck(BadPacketsZ.class).handle(event, dig);
|
||||
|
||||
if (blockBreak.isCancelled()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
if (dig.getAction() == DiggingAction.FINISHED_DIGGING) {
|
||||
// Not unbreakable
|
||||
if (BREAKABLE.apply(type) && !event.isCancelled()) {
|
||||
player.compensatedWorld.startPredicting();
|
||||
player.compensatedWorld.updateBlock(digPosition.getX(), digPosition.getY(), digPosition.getZ(), 0);
|
||||
player.compensatedWorld.stopPredicting(dig);
|
||||
}
|
||||
}
|
||||
|
||||
if (dig.getAction() == DiggingAction.START_DIGGING && !event.isCancelled()) {
|
||||
double damage = BlockBreakSpeed.getBlockDamage(player, digPosition);
|
||||
|
||||
//Instant breaking, no damage means it is unbreakable by creative players (with swords)
|
||||
if (damage >= 1) {
|
||||
player.compensatedWorld.startPredicting();
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_13) && Materials.isWaterSource(player.getClientVersion(), block)) {
|
||||
// Vanilla uses a method to grab water flowing, but as you can't break flowing water
|
||||
// We can simply treat all waterlogged blocks or source blocks as source blocks
|
||||
player.compensatedWorld.updateBlock(digPosition, StateTypes.WATER.createBlockState(CompensatedWorld.blockVersion));
|
||||
} else {
|
||||
player.compensatedWorld.updateBlock(digPosition.getX(), digPosition.getY(), digPosition.getZ(), 0);
|
||||
}
|
||||
player.compensatedWorld.stopPredicting(dig);
|
||||
}
|
||||
}
|
||||
|
||||
if (!event.isCancelled()) {
|
||||
if (blockBreak.action == DiggingAction.FINISHED_DIGGING && BREAKABLE.apply(blockBreak.block.getType())) {
|
||||
player.compensatedWorld.startPredicting();
|
||||
player.compensatedWorld.updateBlock(blockBreak.position.x, blockBreak.position.y, blockBreak.position.z, 0);
|
||||
player.compensatedWorld.stopPredicting(packet);
|
||||
}
|
||||
|
||||
if (blockBreak.action == DiggingAction.START_DIGGING) {
|
||||
double damage = BlockBreakSpeed.getBlockDamage(player, blockBreak.position);
|
||||
|
||||
// Instant breaking, no damage means it is unbreakable by creative players (with swords)
|
||||
if (damage >= 1) {
|
||||
player.compensatedWorld.startPredicting();
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_13) && Materials.isWaterSource(player.getClientVersion(), blockBreak.block)) {
|
||||
// Vanilla uses a method to grab water flowing, but as you can't break flowing water
|
||||
// We can simply treat all waterlogged blocks or source blocks as source blocks
|
||||
player.compensatedWorld.updateBlock(blockBreak.position, StateTypes.WATER.createBlockState(CompensatedWorld.blockVersion));
|
||||
} else {
|
||||
player.compensatedWorld.updateBlock(blockBreak.position.x, blockBreak.position.y, blockBreak.position.z, 0);
|
||||
}
|
||||
player.compensatedWorld.stopPredicting(packet);
|
||||
}
|
||||
}
|
||||
|
||||
if (blockBreak.action == DiggingAction.START_DIGGING || blockBreak.action == DiggingAction.FINISHED_DIGGING || blockBreak.action == DiggingAction.CANCELLED_DIGGING) {
|
||||
player.compensatedWorld.handleBlockBreakPrediction(packet);
|
||||
if (dig.getAction() == DiggingAction.START_DIGGING || dig.getAction() == DiggingAction.FINISHED_DIGGING || dig.getAction() == DiggingAction.CANCELLED_DIGGING) {
|
||||
player.compensatedWorld.handleBlockBreakPrediction(dig);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -577,15 +578,6 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
player.packetStateData.cancelDuplicatePacket = false;
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Client.CLIENT_TICK_END) {
|
||||
if (!player.packetStateData.didSendMovementBeforeTickEnd) {
|
||||
// The player didn't send a movement packet, so we can predict this like we had idle tick on 1.8
|
||||
player.packetStateData.didLastLastMovementIncludePosition = player.packetStateData.didLastMovementIncludePosition;
|
||||
player.packetStateData.didLastMovementIncludePosition = false;
|
||||
}
|
||||
player.packetStateData.didSendMovementBeforeTickEnd = false;
|
||||
}
|
||||
|
||||
// Finally, remove the packet state variables on this packet
|
||||
player.packetStateData.lastPacketWasOnePointSeventeenDuplicate = false;
|
||||
player.packetStateData.lastPacketWasTeleport = false;
|
||||
@@ -755,10 +747,6 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
|
||||
player.packetStateData.didLastLastMovementIncludePosition = player.packetStateData.didLastMovementIncludePosition;
|
||||
player.packetStateData.didLastMovementIncludePosition = hasPosition;
|
||||
|
||||
if (!player.packetStateData.lastPacketWasTeleport) {
|
||||
player.packetStateData.didSendMovementBeforeTickEnd = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static void placeLilypad(GrimPlayer player, InteractionHand hand) {
|
||||
@@ -794,10 +782,10 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
|
||||
private static HitData getNearestHitResult(GrimPlayer player, StateType heldItem, boolean sourcesHaveHitbox) {
|
||||
Vector3d startingPos = new Vector3d(player.x, player.y + player.getEyeHeight(), player.z);
|
||||
Vector3D startingVec = VectorFactory.newVector3D(startingPos.getX(), startingPos.getY(), startingPos.getZ());
|
||||
Vector startingVec = new Vector(startingPos.getX(), startingPos.getY(), startingPos.getZ());
|
||||
Ray trace = new Ray(player, startingPos.getX(), startingPos.getY(), startingPos.getZ(), player.xRot, player.yRot);
|
||||
final double distance = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE);
|
||||
Vector3D endVec = trace.getPointAtDistance(distance);
|
||||
Vector endVec = trace.getPointAtDistance(distance);
|
||||
Vector3d endPos = new Vector3d(endVec.getX(), endVec.getY(), endVec.getZ());
|
||||
|
||||
return traverseBlocks(player, startingPos, endPos, (block, vector3i) -> {
|
||||
@@ -806,14 +794,14 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
data.downCast(boxes);
|
||||
|
||||
double bestHitResult = Double.MAX_VALUE;
|
||||
Vector3D bestHitLoc = null;
|
||||
Vector bestHitLoc = null;
|
||||
BlockFace bestFace = null;
|
||||
|
||||
for (SimpleCollisionBox box : boxes) {
|
||||
Pair<Vector3D, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
Pair<Vector, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
if (intercept.first() == null) continue; // No intercept
|
||||
|
||||
Vector3D hitLoc = intercept.first();
|
||||
Vector hitLoc = intercept.first();
|
||||
|
||||
if (hitLoc.distanceSquared(startingVec) < bestHitResult) {
|
||||
bestHitResult = hitLoc.distanceSquared(startingVec);
|
||||
@@ -831,7 +819,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
double waterHeight = player.compensatedWorld.getFluidLevelAt(vector3i.getX(), vector3i.getY(), vector3i.getZ());
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(vector3i.getX(), vector3i.getY(), vector3i.getZ(), vector3i.getX() + 1, vector3i.getY() + waterHeight, vector3i.getZ() + 1);
|
||||
|
||||
Pair<Vector3D, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
Pair<Vector, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
|
||||
if (intercept.first() != null) {
|
||||
return new HitData(vector3i, intercept.first(), intercept.second(), block);
|
||||
|
||||
@@ -13,7 +13,6 @@ import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.event.PacketSendEvent;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.entity.EntityPositionData;
|
||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
@@ -22,6 +21,7 @@ import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.UserProfile;
|
||||
import com.github.retrooper.packetevents.protocol.potion.PotionType;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.*;
|
||||
import io.github.retrooper.packetevents.util.viaversion.ViaVersionUtil;
|
||||
|
||||
@@ -60,19 +60,22 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
// Teleports don't interpolate, duplicate 1.17 packets don't interpolate
|
||||
if (!isTickPacket(event.getPacketType())) return;
|
||||
if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) {
|
||||
// Teleports don't interpolate, duplicate 1.17 packets don't interpolate
|
||||
if (player.packetStateData.lastPacketWasTeleport || player.packetStateData.lastPacketWasOnePointSeventeenDuplicate)
|
||||
return;
|
||||
|
||||
boolean isTickingReliably = player.isTickingReliablyFor(3);
|
||||
boolean isTickingReliably = player.isTickingReliablyFor(3);
|
||||
|
||||
PacketEntity playerVehicle = player.compensatedEntities.getSelf().getRiding();
|
||||
for (PacketEntity entity : player.compensatedEntities.entityMap.values()) {
|
||||
if (entity == playerVehicle && !player.vehicleData.lastDummy) {
|
||||
// The player has this as their vehicle, so they aren't interpolating it.
|
||||
// And it isn't a dummy position
|
||||
entity.setPositionRaw(entity.getPossibleCollisionBoxes());
|
||||
} else {
|
||||
entity.onMovement(isTickingReliably);
|
||||
PacketEntity playerVehicle = player.compensatedEntities.getSelf().getRiding();
|
||||
for (PacketEntity entity : player.compensatedEntities.entityMap.values()) {
|
||||
if (entity == playerVehicle && !player.vehicleData.lastDummy) {
|
||||
// The player has this as their vehicle, so they aren't interpolating it.
|
||||
// And it isn't a dummy position
|
||||
entity.setPositionRaw(entity.getPossibleCollisionBoxes());
|
||||
} else {
|
||||
entity.onMovement(isTickingReliably);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,55 +86,48 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
if ((event.getPacketType() == PacketType.Play.Server.PING || event.getPacketType() == PacketType.Play.Server.WINDOW_CONFIRMATION) && player.packetStateData.lastServerTransWasValid) {
|
||||
despawnedEntitiesThisTransaction.clear();
|
||||
}
|
||||
else if (event.getPacketType() == PacketType.Play.Server.SPAWN_LIVING_ENTITY) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.SPAWN_LIVING_ENTITY) {
|
||||
WrapperPlayServerSpawnLivingEntity packetOutEntity = new WrapperPlayServerSpawnLivingEntity(event);
|
||||
addEntity(packetOutEntity.getEntityId(), packetOutEntity.getEntityUUID(), packetOutEntity.getEntityType(), packetOutEntity.getPosition(), packetOutEntity.getYaw(), packetOutEntity.getPitch(), packetOutEntity.getEntityMetadata(), 0);
|
||||
}
|
||||
else if (event.getPacketType() == PacketType.Play.Server.SPAWN_ENTITY) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.SPAWN_ENTITY) {
|
||||
WrapperPlayServerSpawnEntity packetOutEntity = new WrapperPlayServerSpawnEntity(event);
|
||||
addEntity(packetOutEntity.getEntityId(), packetOutEntity.getUUID().orElse(null), packetOutEntity.getEntityType(), packetOutEntity.getPosition(), packetOutEntity.getYaw(), packetOutEntity.getPitch(), null, packetOutEntity.getData());
|
||||
}
|
||||
else if (event.getPacketType() == PacketType.Play.Server.SPAWN_PLAYER) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.SPAWN_PLAYER) {
|
||||
WrapperPlayServerSpawnPlayer packetOutEntity = new WrapperPlayServerSpawnPlayer(event);
|
||||
addEntity(packetOutEntity.getEntityId(), packetOutEntity.getUUID(), EntityTypes.PLAYER, packetOutEntity.getPosition(), packetOutEntity.getYaw(), packetOutEntity.getPitch(), packetOutEntity.getEntityMetadata(), 0);
|
||||
}
|
||||
else if (event.getPacketType() == PacketType.Play.Server.SPAWN_PAINTING) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.SPAWN_PAINTING) {
|
||||
WrapperPlayServerSpawnPainting packetOutEntity = new WrapperPlayServerSpawnPainting(event);
|
||||
addEntity(packetOutEntity.getEntityId(), packetOutEntity.getUUID(), EntityTypes.PAINTING, packetOutEntity.getPosition().toVector3d(), 0, 0f, null, packetOutEntity.getDirection().getHorizontalIndex());
|
||||
addEntity(packetOutEntity.getEntityId(), packetOutEntity.getUUID(), EntityTypes.PAINTING, packetOutEntity.getPosition().toVector3d(), packetOutEntity.getDirection().getHorizontalIndex(), 0f, null, packetOutEntity.getType().isPresent() ? packetOutEntity.getType().get().getId() : -1);
|
||||
}
|
||||
else if (event.getPacketType() == PacketType.Play.Server.ENTITY_RELATIVE_MOVE) {
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Server.ENTITY_RELATIVE_MOVE) {
|
||||
WrapperPlayServerEntityRelativeMove move = new WrapperPlayServerEntityRelativeMove(event);
|
||||
handleMoveEntity(event, move.getEntityId(), move.getDeltaX(), move.getDeltaY(), move.getDeltaZ(), null, null, true, true);
|
||||
}
|
||||
else if (event.getPacketType() == PacketType.Play.Server.ENTITY_RELATIVE_MOVE_AND_ROTATION) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.ENTITY_RELATIVE_MOVE_AND_ROTATION) {
|
||||
WrapperPlayServerEntityRelativeMoveAndRotation move = new WrapperPlayServerEntityRelativeMoveAndRotation(event);
|
||||
handleMoveEntity(event, move.getEntityId(), move.getDeltaX(), move.getDeltaY(), move.getDeltaZ(), move.getYaw() * 0.7111111F, move.getPitch() * 0.7111111F, true, true);
|
||||
}
|
||||
else if (event.getPacketType() == PacketType.Play.Server.ENTITY_TELEPORT) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.ENTITY_TELEPORT) {
|
||||
WrapperPlayServerEntityTeleport move = new WrapperPlayServerEntityTeleport(event);
|
||||
Vector3d pos = move.getPosition();
|
||||
handleMoveEntity(event, move.getEntityId(), pos.getX(), pos.getY(), pos.getZ(), move.getYaw(), move.getPitch(), false, true);
|
||||
}
|
||||
else if (event.getPacketType() == PacketType.Play.Server.ENTITY_POSITION_SYNC) {
|
||||
// ENTITY_TELEPORT but without relative flags
|
||||
WrapperPlayServerEntityPositionSync move = new WrapperPlayServerEntityPositionSync(event);
|
||||
final EntityPositionData values = move.getValues();
|
||||
final Vector3d pos = values.getPosition();
|
||||
// TODO this isn't technically correct
|
||||
// If the position sync is to a pos > 4096 from the entity pos, client does some special stuff without interpolation
|
||||
handleMoveEntity(event, move.getId(), pos.getX(), pos.getY(), pos.getZ(), values.getYaw(), values.getPitch(), false, true);
|
||||
}
|
||||
else if (event.getPacketType() == PacketType.Play.Server.ENTITY_ROTATION) { // Affects interpolation
|
||||
if (event.getPacketType() == PacketType.Play.Server.ENTITY_ROTATION) { // Affects interpolation
|
||||
WrapperPlayServerEntityRotation move = new WrapperPlayServerEntityRotation(event);
|
||||
handleMoveEntity(event, move.getEntityId(), 0, 0, 0, move.getYaw() * 0.7111111F, move.getPitch() * 0.7111111F, true, false);
|
||||
}
|
||||
else if (event.getPacketType() == PacketType.Play.Server.ENTITY_METADATA) {
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Server.ENTITY_METADATA) {
|
||||
WrapperPlayServerEntityMetadata entityMetadata = new WrapperPlayServerEntityMetadata(event);
|
||||
player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(), () -> player.compensatedEntities.updateEntityMetadata(entityMetadata.getEntityId(), entityMetadata.getEntityMetadata()));
|
||||
}
|
||||
|
||||
// 1.19.3+
|
||||
else if (event.getPacketType() == PacketType.Play.Server.PLAYER_INFO_UPDATE) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.PLAYER_INFO_UPDATE) {
|
||||
WrapperPlayServerPlayerInfoUpdate info = new WrapperPlayServerPlayerInfoUpdate(event);
|
||||
player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(), () -> {
|
||||
for (WrapperPlayServerPlayerInfoUpdate.PlayerInfo entry : info.getEntries()) {
|
||||
@@ -158,7 +154,7 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
});
|
||||
}
|
||||
|
||||
else if (event.getPacketType() == PacketType.Play.Server.ENTITY_EFFECT) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.ENTITY_EFFECT) {
|
||||
WrapperPlayServerEntityEffect effect = new WrapperPlayServerEntityEffect(event);
|
||||
|
||||
PotionType type = effect.getPotionType();
|
||||
@@ -190,7 +186,7 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
});
|
||||
}
|
||||
|
||||
else if (event.getPacketType() == PacketType.Play.Server.REMOVE_ENTITY_EFFECT) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.REMOVE_ENTITY_EFFECT) {
|
||||
WrapperPlayServerRemoveEntityEffect effect = new WrapperPlayServerRemoveEntityEffect(event);
|
||||
|
||||
if (isDirectlyAffectingPlayer(player, effect.getEntityId())) player.sendTransaction();
|
||||
@@ -203,7 +199,7 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
});
|
||||
}
|
||||
|
||||
else if (event.getPacketType() == PacketType.Play.Server.UPDATE_ATTRIBUTES) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.UPDATE_ATTRIBUTES) {
|
||||
WrapperPlayServerUpdateAttributes attributes = new WrapperPlayServerUpdateAttributes(event);
|
||||
|
||||
int entityID = attributes.getEntityId();
|
||||
@@ -215,7 +211,7 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
() -> player.compensatedEntities.updateAttributes(entityID, attributes.getProperties()));
|
||||
}
|
||||
|
||||
else if (event.getPacketType() == PacketType.Play.Server.ENTITY_STATUS) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.ENTITY_STATUS) {
|
||||
WrapperPlayServerEntityStatus status = new WrapperPlayServerEntityStatus(event);
|
||||
// This hasn't changed from 1.7.2 to 1.17
|
||||
// Needed to exempt players on dead vehicles, as dead entities have strange physics.
|
||||
@@ -249,7 +245,7 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
}
|
||||
}
|
||||
|
||||
else if (event.getPacketType() == PacketType.Play.Server.SET_SLOT) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.SET_SLOT) {
|
||||
WrapperPlayServerSetSlot slot = new WrapperPlayServerSetSlot(event);
|
||||
|
||||
if (slot.getWindowId() == 0) {
|
||||
@@ -267,7 +263,7 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
}
|
||||
}
|
||||
|
||||
else if (event.getPacketType() == PacketType.Play.Server.WINDOW_ITEMS) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.WINDOW_ITEMS) {
|
||||
WrapperPlayServerWindowItems items = new WrapperPlayServerWindowItems(event);
|
||||
|
||||
if (items.getWindowId() == 0) { // Player inventory
|
||||
@@ -277,16 +273,16 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
}
|
||||
|
||||
// 1.8 clients fail to send the RELEASE_USE_ITEM packet when a window is opened client sided while using an item
|
||||
else if (event.getPacketType() == PacketType.Play.Server.OPEN_WINDOW) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.OPEN_WINDOW) {
|
||||
player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(), () -> player.packetStateData.setSlowedByUsingItem(false));
|
||||
player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get() + 1, () -> player.packetStateData.setSlowedByUsingItem(false));
|
||||
}
|
||||
else if (event.getPacketType() == PacketType.Play.Server.OPEN_HORSE_WINDOW) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.OPEN_HORSE_WINDOW) {
|
||||
player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(), () -> player.packetStateData.setSlowedByUsingItem(false));
|
||||
player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get() + 1, () -> player.packetStateData.setSlowedByUsingItem(false));
|
||||
}
|
||||
|
||||
else if (event.getPacketType() == PacketType.Play.Server.SET_PASSENGERS) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.SET_PASSENGERS) {
|
||||
WrapperPlayServerSetPassengers mount = new WrapperPlayServerSetPassengers(event);
|
||||
|
||||
int vehicleID = mount.getEntityId();
|
||||
@@ -295,7 +291,7 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
handleMountVehicle(event, vehicleID, passengers);
|
||||
}
|
||||
|
||||
else if (event.getPacketType() == PacketType.Play.Server.ATTACH_ENTITY) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.ATTACH_ENTITY) {
|
||||
WrapperPlayServerAttachEntity attach = new WrapperPlayServerAttachEntity(event);
|
||||
|
||||
// This packet was replaced by the mount packet on 1.9+ servers - to support multiple passengers on one vehicle
|
||||
@@ -326,7 +322,7 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
}
|
||||
}
|
||||
|
||||
else if (event.getPacketType() == PacketType.Play.Server.DESTROY_ENTITIES) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.DESTROY_ENTITIES) {
|
||||
WrapperPlayServerDestroyEntities destroy = new WrapperPlayServerDestroyEntities(event);
|
||||
|
||||
int[] destroyEntityIds = destroy.getEntityIds();
|
||||
@@ -421,13 +417,9 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
// As we don't want vehicles to fly, we need to replace it with a teleport if it is player vehicle
|
||||
//
|
||||
// Don't bother with client controlled vehicles though
|
||||
boolean vanillaVehicleFlight = player.compensatedEntities.serverPlayerVehicle != null
|
||||
&& player.compensatedEntities.serverPlayerVehicle == entityId
|
||||
&& player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)
|
||||
// TODO: https://discord.com/channels/721686193061888071/721686193515003966/1310659538831020123
|
||||
// Why does the server now send an entity rel move packet matching the player's vehicle movement every time?
|
||||
&& PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_21_2)
|
||||
&& PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9);
|
||||
boolean vanillaVehicleFlight = player.compensatedEntities.serverPlayerVehicle != null && player.compensatedEntities.serverPlayerVehicle == entityId
|
||||
&& player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) &&
|
||||
PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9);
|
||||
|
||||
// ViaVersion sends two relative packets when moving more than 4 blocks
|
||||
// This is broken and causes the client to interpolate like (0, 4) and (1, 3) instead of (1, 7)
|
||||
|
||||
@@ -36,9 +36,6 @@ public class PacketPlayerJoinQuit extends PacketListenerAbstract {
|
||||
}
|
||||
if (player.hasPermission("grim.alerts") && player.hasPermission("grim.alerts.enable-on-join")) {
|
||||
GrimAPI.INSTANCE.getAlertManager().toggleAlerts(player);
|
||||
if (player.hasPermission("grim.verbose") && player.hasPermission("grim.verbose.enable-on-join")) {
|
||||
GrimAPI.INSTANCE.getAlertManager().toggleVerbose(player);
|
||||
}
|
||||
}
|
||||
if (player.hasPermission("grim.spectate") && GrimAPI.INSTANCE.getConfigManager().getConfig().getBooleanElse("spectators.hide-regardless", false)) {
|
||||
GrimAPI.INSTANCE.getSpectateManager().onLogin(player);
|
||||
|
||||
@@ -3,7 +3,6 @@ package ac.grim.grimac.events.packets;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.checks.impl.badpackets.BadPacketsE;
|
||||
import ac.grim.grimac.checks.impl.badpackets.BadPacketsF;
|
||||
import ac.grim.grimac.checks.impl.badpackets.BadPacketsG;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.data.TrackerData;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntitySelf;
|
||||
@@ -20,12 +19,11 @@ import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerJoinGame;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerRespawn;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateHealth;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
/**
|
||||
* PlayerRespawnS2CPacket info (1.20.2+):
|
||||
* If the world is different (check via registry key), world is recreated (all entities etc destroyed).
|
||||
@@ -133,11 +131,7 @@ public class PacketPlayerRespawn extends PacketListenerAbstract {
|
||||
}
|
||||
|
||||
player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get() + 1, () -> {
|
||||
// From 1.16 to 1.19, this doesn't get set to false for whatever reason
|
||||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_16) || player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_20)) {
|
||||
player.isSneaking = false;
|
||||
}
|
||||
|
||||
player.isSneaking = false;
|
||||
player.lastOnGround = false;
|
||||
player.onGround = false;
|
||||
player.isInBed = false;
|
||||
@@ -163,7 +157,6 @@ public class PacketPlayerRespawn extends PacketListenerAbstract {
|
||||
}
|
||||
|
||||
player.checkManager.getPacketCheck(BadPacketsE.class).handleRespawn(); // Reminder ticks reset
|
||||
player.checkManager.getPacketCheck(BadPacketsG.class).handleRespawn();
|
||||
|
||||
// compensate for immediate respawn gamerule
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_15)) {
|
||||
@@ -192,7 +185,7 @@ public class PacketPlayerRespawn extends PacketListenerAbstract {
|
||||
player.compensatedEntities.hasSprintingAttributeEnabled = false;
|
||||
}
|
||||
player.pose = Pose.STANDING;
|
||||
player.clientVelocity = newVector3D();
|
||||
player.clientVelocity = new Vector();
|
||||
player.gamemode = respawn.getGameMode();
|
||||
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_17)) {
|
||||
player.compensatedWorld.setDimension(respawn.getDimensionType(), event.getUser());
|
||||
|
||||
@@ -3,7 +3,6 @@ package ac.grim.grimac.events.packets;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.KnownInput;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntity;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntityHorse;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
@@ -13,7 +12,6 @@ import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerInput;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientSteerVehicle;
|
||||
|
||||
public class PacketPlayerSteer extends PacketListenerAbstract {
|
||||
@@ -24,12 +22,13 @@ public class PacketPlayerSteer extends PacketListenerAbstract {
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
//TODO: add support for 1.21.2 with new vehicle move packet
|
||||
if (event.getPacketType() == PacketType.Play.Client.STEER_VEHICLE) {
|
||||
WrapperPlayClientSteerVehicle steer = new WrapperPlayClientSteerVehicle(event);
|
||||
|
||||
GrimPlayer player = GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(event.getUser());
|
||||
if (player == null) return;
|
||||
|
||||
WrapperPlayClientSteerVehicle steer = new WrapperPlayClientSteerVehicle(event);
|
||||
|
||||
float forwards = steer.getForward();
|
||||
float sideways = steer.getSideways();
|
||||
|
||||
@@ -100,33 +99,6 @@ public class PacketPlayerSteer extends PacketListenerAbstract {
|
||||
}
|
||||
|
||||
player.packetStateData.receivedSteerVehicle = true;
|
||||
} else if (event.getPacketType() == PacketType.Play.Client.PLAYER_INPUT) {
|
||||
GrimPlayer player = GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(event.getUser());
|
||||
if (player == null) return;
|
||||
|
||||
WrapperPlayClientPlayerInput input = new WrapperPlayClientPlayerInput(event);
|
||||
byte forward = 0;
|
||||
byte sideways = 0;
|
||||
if (input.isForward()) {
|
||||
forward++;
|
||||
}
|
||||
|
||||
if (input.isBackward()) {
|
||||
forward--;
|
||||
}
|
||||
|
||||
if (input.isLeft()) {
|
||||
sideways++;
|
||||
}
|
||||
|
||||
if (input.isRight()) {
|
||||
sideways--;
|
||||
}
|
||||
|
||||
player.vehicleData.nextVehicleForward = forward * 0.98f;
|
||||
player.vehicleData.nextVehicleHorizontal = sideways * 0.98f;
|
||||
|
||||
player.packetStateData.knownInput = new KnownInput(input.isForward(), input.isBackward(), input.isLeft(), input.isRight(), input.isJump(), input.isShift(), input.isSprint());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@@ -26,7 +27,7 @@ public class ActionManager extends Check implements PacketCheck {
|
||||
attacking = true;
|
||||
lastAttack = System.currentTimeMillis();
|
||||
}
|
||||
} else if (isTickPacketIncludingNonMovement(event.getPacketType())) {
|
||||
} else if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) {
|
||||
player.totalFlyingPacketsSent++;
|
||||
attacking = false;
|
||||
}
|
||||
|
||||
@@ -11,14 +11,12 @@ import ac.grim.grimac.checks.impl.combat.Reach;
|
||||
import ac.grim.grimac.checks.impl.crash.*;
|
||||
import ac.grim.grimac.checks.impl.exploit.ExploitA;
|
||||
import ac.grim.grimac.checks.impl.exploit.ExploitB;
|
||||
import ac.grim.grimac.checks.impl.exploit.ExploitC;
|
||||
import ac.grim.grimac.checks.impl.groundspoof.NoFallA;
|
||||
import ac.grim.grimac.checks.impl.misc.ClientBrand;
|
||||
import ac.grim.grimac.checks.impl.misc.FastBreak;
|
||||
import ac.grim.grimac.checks.impl.misc.GhostBlockMitigation;
|
||||
import ac.grim.grimac.checks.impl.misc.TransactionOrder;
|
||||
import ac.grim.grimac.checks.impl.movement.*;
|
||||
import ac.grim.grimac.checks.impl.multiactions.*;
|
||||
import ac.grim.grimac.checks.impl.post.PostCheck;
|
||||
import ac.grim.grimac.checks.impl.prediction.DebugHandler;
|
||||
import ac.grim.grimac.checks.impl.prediction.NoFallB;
|
||||
@@ -100,15 +98,11 @@ public class CheckManager {
|
||||
.put(BadPacketsS.class, new BadPacketsS(player))
|
||||
.put(BadPacketsT.class, new BadPacketsT(player))
|
||||
.put(BadPacketsU.class, new BadPacketsU(player))
|
||||
.put(BadPacketsV.class, new BadPacketsV(player))
|
||||
.put(BadPacketsW.class, new BadPacketsW(player))
|
||||
.put(BadPacketsX.class, new BadPacketsX(player))
|
||||
.put(BadPacketsY.class, new BadPacketsY(player))
|
||||
.put(BadPacketsZ.class, new BadPacketsZ(player))
|
||||
.put(MultiActionsA.class, new MultiActionsA(player))
|
||||
.put(MultiActionsB.class, new MultiActionsB(player))
|
||||
.put(MultiActionsC.class, new MultiActionsC(player))
|
||||
.put(MultiActionsD.class, new MultiActionsD(player))
|
||||
.put(MultiActionsE.class, new MultiActionsE(player))
|
||||
.put(FastBreak.class, new FastBreak(player))
|
||||
.put(TransactionOrder.class, new TransactionOrder(player))
|
||||
.put(NoSlowB.class, new NoSlowB(player))
|
||||
@@ -157,7 +151,6 @@ public class CheckManager {
|
||||
.put(InvalidPlaceB.class, new InvalidPlaceB(player))
|
||||
.put(AirLiquidPlace.class, new AirLiquidPlace(player))
|
||||
.put(MultiPlace.class, new MultiPlace(player))
|
||||
.put(MultiActionsF.class, new MultiActionsF(player))
|
||||
.put(FarPlace.class, new FarPlace(player))
|
||||
.put(FabricatedPlace.class, new FabricatedPlace(player))
|
||||
.put(PositionPlace.class, new PositionPlace(player))
|
||||
@@ -168,7 +161,6 @@ public class CheckManager {
|
||||
|
||||
prePredictionChecks = new ImmutableClassToInstanceMap.Builder<PacketCheck>()
|
||||
.put(TimerCheck.class, new TimerCheck(player))
|
||||
.put(TickTimer.class, new TickTimer(player))
|
||||
.put(CrashA.class, new CrashA(player))
|
||||
.put(CrashB.class, new CrashB(player))
|
||||
.put(CrashC.class, new CrashC(player))
|
||||
@@ -179,7 +171,6 @@ public class CheckManager {
|
||||
.put(CrashH.class, new CrashH(player))
|
||||
.put(ExploitA.class, new ExploitA(player))
|
||||
.put(ExploitB.class, new ExploitB(player))
|
||||
.put(ExploitC.class, new ExploitC(player))
|
||||
.put(VehicleTimer.class, new VehicleTimer(player))
|
||||
.build();
|
||||
|
||||
|
||||
@@ -70,12 +70,12 @@ public class DiscordManager implements Initable {
|
||||
return list;
|
||||
}
|
||||
|
||||
public void sendAlert(GrimPlayer player, String verbose, String checkName, int violations) {
|
||||
public void sendAlert(GrimPlayer player, String verbose, String checkName, String violations) {
|
||||
if (client != null) {
|
||||
|
||||
String content = staticContent;
|
||||
content = content.replace("%check%", checkName);
|
||||
content = content.replace("%violations%", Integer.toString(violations));
|
||||
content = content.replace("%violations%", violations);
|
||||
content = GrimAPI.INSTANCE.getExternalAPI().replaceVariables(player, content, false);
|
||||
content = content.replace("_", "\\_");
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
import io.github.retrooper.packetevents.util.folia.FoliaScheduler;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -98,14 +99,16 @@ public class PunishmentManager implements ConfigReloadable {
|
||||
}
|
||||
}
|
||||
|
||||
private String replaceAlertPlaceholders(String original, int vl, PunishGroup group, Check check, String alertString, String verbose) {
|
||||
private String replaceAlertPlaceholders(String original, PunishGroup group, Check check, String alertString, String verbose) {
|
||||
// Streams are slow but this isn't a hot path... it's fine.
|
||||
String vl = group.violations.values().stream().filter((e) -> e == check).count() + "";
|
||||
|
||||
original = MessageUtil.format(original
|
||||
.replace("[alert]", alertString)
|
||||
.replace("[proxy]", alertString)
|
||||
.replace("%check_name%", check.getDisplayName())
|
||||
.replace("%experimental%", check.isExperimental() ? experimentalSymbol : "")
|
||||
.replace("%vl%", Integer.toString(vl))
|
||||
.replace("%vl%", vl)
|
||||
.replace("%verbose%", verbose)
|
||||
.replace("%description%", check.getDescription())
|
||||
);
|
||||
@@ -121,13 +124,12 @@ public class PunishmentManager implements ConfigReloadable {
|
||||
// Check commands
|
||||
for (PunishGroup group : groups) {
|
||||
if (group.getChecks().contains(check)) {
|
||||
final int vl = getViolations(group, check);
|
||||
final int violationCount = group.getViolations().size();
|
||||
int violationCount = group.getViolations().size();
|
||||
for (ParsedCommand command : group.getCommands()) {
|
||||
String cmd = replaceAlertPlaceholders(command.getCommand(), vl, group, check, alertString, verbose);
|
||||
String cmd = replaceAlertPlaceholders(command.getCommand(), group, check, alertString, verbose);
|
||||
|
||||
// Verbose that prints all flags
|
||||
if (!GrimAPI.INSTANCE.getAlertManager().getEnabledVerbose().isEmpty() && command.command.equals("[alert]")) {
|
||||
if (GrimAPI.INSTANCE.getAlertManager().getEnabledVerbose().size() > 0 && command.command.equals("[alert]")) {
|
||||
sentDebug = true;
|
||||
for (Player bukkitPlayer : GrimAPI.INSTANCE.getAlertManager().getEnabledVerbose()) {
|
||||
bukkitPlayer.sendMessage(cmd);
|
||||
@@ -147,9 +149,10 @@ public class PunishmentManager implements ConfigReloadable {
|
||||
if (executeEvent.isCancelled()) continue;
|
||||
|
||||
if (command.command.equals("[webhook]")) {
|
||||
String vl = group.violations.values().stream().filter((e) -> e == check).count() + "";
|
||||
GrimAPI.INSTANCE.getDiscordManager().sendAlert(player, verbose, check.getDisplayName(), vl);
|
||||
} else if (command.command.equals("[proxy]")) {
|
||||
ProxyAlertMessenger.sendPluginMessage(replaceAlertPlaceholders(command.getCommand(), vl, group, check, proxyAlertString, verbose));
|
||||
ProxyAlertMessenger.sendPluginMessage(replaceAlertPlaceholders(command.getCommand(), group, check, proxyAlertString, verbose));
|
||||
} else {
|
||||
if (command.command.equals("[alert]")) {
|
||||
sentDebug = true;
|
||||
@@ -181,19 +184,10 @@ public class PunishmentManager implements ConfigReloadable {
|
||||
|
||||
group.violations.put(currentTime, check);
|
||||
// Remove violations older than the defined time in the config
|
||||
group.violations.entrySet().removeIf(time -> currentTime - time.getKey() > group.removeViolationsAfter);
|
||||
group.violations.long2ObjectEntrySet().removeIf(time -> currentTime - time.getLongKey() > group.removeViolationsAfter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getViolations(PunishGroup group, Check check) {
|
||||
int vl = 0;
|
||||
for (Check value : group.violations.values()) {
|
||||
if (value == check) vl++;
|
||||
}
|
||||
return vl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PunishGroup {
|
||||
@@ -202,7 +196,7 @@ class PunishGroup {
|
||||
@Getter
|
||||
List<ParsedCommand> commands;
|
||||
@Getter
|
||||
public Map<Long, Check> violations = new HashMap<>();
|
||||
Long2ObjectOpenHashMap<Check> violations = new Long2ObjectOpenHashMap<>();
|
||||
@Getter
|
||||
int removeViolationsAfter;
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ import ac.grim.grimac.utils.math.VectorUtils;
|
||||
import ac.grim.grimac.utils.nmsutil.Collisions;
|
||||
import ac.grim.grimac.utils.nmsutil.GetBoundingBox;
|
||||
import ac.grim.grimac.utils.nmsutil.ReachUtils;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
@@ -32,15 +31,13 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
// Sync to netty
|
||||
public final ConcurrentLinkedQueue<TeleportData> pendingTeleports = new ConcurrentLinkedQueue<>();
|
||||
@@ -68,7 +65,7 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
@Override
|
||||
public void onPredictionComplete(final PredictionComplete predictionComplete) {
|
||||
// Grab friction now when we know player on ground and other variables
|
||||
Vector3D afterTickFriction = player.clientVelocity.clone();
|
||||
Vector afterTickFriction = player.clientVelocity.clone();
|
||||
|
||||
// We must first check if the player has accepted their setback
|
||||
// If the setback isn't complete, then this position is illegitimate
|
||||
@@ -118,7 +115,7 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void simulateFriction(Vector3D vector) {
|
||||
private void simulateFriction(Vector vector) {
|
||||
// We must always do this before simulating positions, as this is the last actual (safe) movement
|
||||
// We must not do this for knockback or explosions, as they are at the start of the tick
|
||||
if (player.wasTouchingWater) {
|
||||
@@ -126,13 +123,12 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
} else if (player.wasTouchingLava) {
|
||||
vector.multiply(0.5D);
|
||||
if (player.hasGravity)
|
||||
vector.add(newVector3D(0.0D, -player.gravity / 4.0D, 0.0D));
|
||||
vector.add(new Vector(0.0D, -player.gravity / 4.0D, 0.0D));
|
||||
} else if (player.isGliding) {
|
||||
PredictionEngineElytra.getElytraMovement(player, vector, ReachUtils.getLook(player, player.xRot, player.yRot)).multiply(player.stuckSpeedMultiplier).multiply(newVector3D(0.99F, 0.98F, 0.99F));
|
||||
PredictionEngineElytra.getElytraMovement(player, vector, ReachUtils.getLook(player, player.xRot, player.yRot)).multiply(player.stuckSpeedMultiplier).multiply(new Vector(0.99F, 0.98F, 0.99F));
|
||||
vector.setY(vector.getY() - 0.05); // Make the player fall a bit
|
||||
} else { // Gliding doesn't have friction, we handle it differently
|
||||
PredictionEngineNormal.staticVectorEndOfTick(player, vector); // Lava and normal movement
|
||||
vector.multiply(player.stuckSpeedMultiplier); // Prevent abusing setbacks to move out of blocks like webs
|
||||
}
|
||||
|
||||
// stop 1.8 players from stepping onto 1.25 high blocks, because why not?
|
||||
@@ -151,9 +147,9 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
lastWorldResync = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
Vector3D clientVel = lastKnownGoodPosition.vector.clone();
|
||||
Vector clientVel = lastKnownGoodPosition.vector.clone();
|
||||
|
||||
Pair<VelocityData, Vector3D> futureKb = player.checkManager.getKnockbackHandler().getFutureKnockback();
|
||||
Pair<VelocityData, Vector> futureKb = player.checkManager.getKnockbackHandler().getFutureKnockback();
|
||||
VelocityData futureExplosion = player.checkManager.getExplosionHandler().getFutureExplosion();
|
||||
|
||||
// Velocity sets
|
||||
@@ -173,7 +169,7 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
|
||||
// Mini prediction engine - simulate collisions
|
||||
if (simulateNextTickPosition) {
|
||||
Vector3D collide = Collisions.collide(player, clientVel.getX(), clientVel.getY(), clientVel.getZ());
|
||||
Vector collide = Collisions.collide(player, clientVel.getX(), clientVel.getY(), clientVel.getZ());
|
||||
|
||||
position = position.withX(position.getX() + collide.getX());
|
||||
// 1.8 players need the collision epsilon to not phase into blocks when being setback
|
||||
@@ -401,22 +397,22 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
Vector3d safePosition = new Vector3d(position.getX(), position.getY(), position.getZ());
|
||||
|
||||
// We must convert relative teleports to avoid them becoming client controlled in the case of setback
|
||||
if (flags.has(RelativeFlag.X)) {
|
||||
if (flags.isSet(RelativeFlag.X.getMask())) {
|
||||
safePosition = safePosition.withX(safePosition.getX() + lastKnownGoodPosition.pos.getX());
|
||||
}
|
||||
|
||||
if (flags.has(RelativeFlag.Y)) {
|
||||
if (flags.isSet(RelativeFlag.Y.getMask())) {
|
||||
safePosition = safePosition.withY(safePosition.getY() + lastKnownGoodPosition.pos.getY());
|
||||
}
|
||||
|
||||
if (flags.has(RelativeFlag.Z)) {
|
||||
if (flags.isSet(RelativeFlag.Z.getMask())) {
|
||||
safePosition = safePosition.withZ(safePosition.getZ() + lastKnownGoodPosition.pos.getZ());
|
||||
}
|
||||
|
||||
data = new TeleportData(safePosition, flags, transaction, teleportId);
|
||||
requiredSetBack = new SetBackData(data, player.xRot, player.yRot, null, false, plugin);
|
||||
|
||||
this.lastKnownGoodPosition = new SetbackPosWithVector(safePosition, newVector3D());
|
||||
this.lastKnownGoodPosition = new SetbackPosWithVector(safePosition, new Vector());
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@@ -424,6 +420,6 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
@Setter
|
||||
public static class SetbackPosWithVector {
|
||||
private Vector3d pos;
|
||||
private Vector3D vector;
|
||||
private Vector vector;
|
||||
}
|
||||
}
|
||||
@@ -10,28 +10,26 @@ import ac.grim.grimac.utils.anticheat.update.PredictionComplete;
|
||||
import ac.grim.grimac.utils.data.VectorData;
|
||||
import ac.grim.grimac.utils.lists.EvictingQueue;
|
||||
import ac.grim.grimac.utils.math.GrimMath;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
public final class SuperDebug extends Check implements PostPredictionCheck {
|
||||
private static final StringBuilder[] flags = new StringBuilder[256]; // 17 MB of logs in memory
|
||||
|
||||
Object2IntMap<StringBuilder> continuedDebug = new Object2IntOpenHashMap<>();
|
||||
|
||||
List<VectorData> predicted = new EvictingQueue<>(60);
|
||||
List<Vector3D> actually = new EvictingQueue<>(60);
|
||||
List<Vector> actually = new EvictingQueue<>(60);
|
||||
List<Location> locations = new EvictingQueue<>(60);
|
||||
List<Vector3D> startTickClientVel = new EvictingQueue<>(60);
|
||||
List<Vector3D> baseTickAddition = new EvictingQueue<>(60);
|
||||
List<Vector3D> baseTickWater = new EvictingQueue<>(60);
|
||||
List<Vector> startTickClientVel = new EvictingQueue<>(60);
|
||||
List<Vector> baseTickAddition = new EvictingQueue<>(60);
|
||||
List<Vector> baseTickWater = new EvictingQueue<>(60);
|
||||
|
||||
public SuperDebug(GrimPlayer player) {
|
||||
super(player);
|
||||
@@ -82,11 +80,11 @@ public final class SuperDebug extends Check implements PostPredictionCheck {
|
||||
|
||||
for (int i = 0; i < predicted.size(); i++) {
|
||||
VectorData predict = predicted.get(i);
|
||||
Vector3D actual = actually.get(i);
|
||||
Vector actual = actually.get(i);
|
||||
Location loc = locations.get(i);
|
||||
Vector3D startTickVel = startTickClientVel.get(i);
|
||||
Vector3D addition = baseTickAddition.get(i);
|
||||
Vector3D water = baseTickWater.get(i);
|
||||
Vector startTickVel = startTickClientVel.get(i);
|
||||
Vector addition = baseTickAddition.get(i);
|
||||
Vector water = baseTickWater.get(i);
|
||||
appendDebug(sb, predict, actual, loc, startTickVel, addition, water);
|
||||
}
|
||||
|
||||
@@ -191,7 +189,7 @@ public final class SuperDebug extends Check implements PostPredictionCheck {
|
||||
continuedDebug.put(sb, 40);
|
||||
}
|
||||
|
||||
private void appendDebug(StringBuilder sb, VectorData predict, Vector3D actual, Location location, Vector3D startTick, Vector3D addition, Vector3D water) {
|
||||
private void appendDebug(StringBuilder sb, VectorData predict, Vector actual, Location location, Vector startTick, Vector addition, Vector water) {
|
||||
if (predict.isZeroPointZeroThree()) {
|
||||
sb.append("Movement threshold/tick skipping\n");
|
||||
}
|
||||
@@ -227,11 +225,11 @@ public final class SuperDebug extends Check implements PostPredictionCheck {
|
||||
// Apply 0.003/0.005 to make numbers more accurate
|
||||
Set<VectorData> set = new HashSet<>(Collections.singletonList(new VectorData(startTick.clone(), VectorData.VectorType.BestVelPicked)));
|
||||
new PredictionEngine().applyMovementThreshold(player, set);
|
||||
Vector3D trueStartVel = ((VectorData) set.toArray()[0]).vector;
|
||||
Vector trueStartVel = ((VectorData) set.toArray()[0]).vector;
|
||||
|
||||
Vector3D clientMovement = getPlayerMathMovement(player, actual.clone().subtract(trueStartVel), location.xRot);
|
||||
Vector3D simulatedMovement = getPlayerMathMovement(player, predict.vector.clone().subtract(trueStartVel), location.xRot);
|
||||
Vector3D offset = actual.clone().subtract(predict.vector);
|
||||
Vector clientMovement = getPlayerMathMovement(player, actual.clone().subtract(trueStartVel), location.xRot);
|
||||
Vector simulatedMovement = getPlayerMathMovement(player, predict.vector.clone().subtract(trueStartVel), location.xRot);
|
||||
Vector offset = actual.clone().subtract(predict.vector);
|
||||
trueStartVel.add(addition);
|
||||
trueStartVel.add(water);
|
||||
|
||||
@@ -270,14 +268,14 @@ public final class SuperDebug extends Check implements PostPredictionCheck {
|
||||
sb.append("\n\n");
|
||||
}
|
||||
|
||||
private Vector3D getPlayerMathMovement(GrimPlayer player, Vector3D wantedMovement, float f2) {
|
||||
private Vector getPlayerMathMovement(GrimPlayer player, Vector wantedMovement, float f2) {
|
||||
float f3 = player.trigHandler.sin(f2 * 0.017453292f);
|
||||
float f4 = player.trigHandler.cos(f2 * 0.017453292f);
|
||||
|
||||
float bestTheoreticalX = (float) (f3 * wantedMovement.getZ() + f4 * wantedMovement.getX()) / (f3 * f3 + f4 * f4);
|
||||
float bestTheoreticalZ = (float) (-f3 * wantedMovement.getX() + f4 * wantedMovement.getZ()) / (f3 * f3 + f4 * f4);
|
||||
|
||||
return newVector3D(bestTheoreticalX, 0, bestTheoreticalZ);
|
||||
return new Vector(bestTheoreticalX, 0, bestTheoreticalZ);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
|
||||
@@ -3,10 +3,7 @@ package ac.grim.grimac.manager.init.start;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.manager.init.Initable;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import ac.grim.grimac.utils.lists.HookedListWrapper;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.util.reflection.Reflection;
|
||||
import io.github.retrooper.packetevents.util.SpigotReflectionUtil;
|
||||
import sun.misc.Unsafe;
|
||||
@@ -33,10 +30,6 @@ public class TickEndEvent implements Initable {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThan(ServerVersion.V_1_11_2) && !Boolean.getBoolean("paper.explicit-flush")) {
|
||||
LogUtil.warn("Reach.enable-post-packet=true but paper.explicit-flush=false, add \"-Dpaper.explicit-flush=true\" to your server's startup flags for fully functional extra reach accuracy.");
|
||||
}
|
||||
|
||||
// Inject so we can add the final transaction pre-flush event
|
||||
try {
|
||||
Object connection = SpigotReflectionUtil.getMinecraftServerConnectionInstance();
|
||||
|
||||
@@ -54,7 +54,7 @@ import net.kyori.adventure.text.TranslatableComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
@@ -64,9 +64,6 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static ac.grim.grimac.utils.data.VectorData.VectorType.Normal;
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
// Everything in this class should be sync'd to the anticheat thread.
|
||||
// Put variables sync'd to the netty thread in PacketStateData
|
||||
// Variables that need lag compensation should have their own class
|
||||
@@ -93,7 +90,7 @@ public class GrimPlayer implements GrimUser {
|
||||
public MovementCheckRunner movementCheckRunner;
|
||||
public SyncedTags tagManager;
|
||||
// End manager like classes
|
||||
public ac.grim.grimac.utils.vector.Vector3D clientVelocity = newVector3D();
|
||||
public Vector clientVelocity = new Vector();
|
||||
PacketTracker packetTracker;
|
||||
private long transactionPing = 0;
|
||||
public long lastTransSent = 0;
|
||||
@@ -106,9 +103,9 @@ public class GrimPlayer implements GrimUser {
|
||||
public boolean hasGravity = true;
|
||||
public final long joinTime = System.currentTimeMillis();
|
||||
public boolean playerEntityHasGravity = true;
|
||||
public VectorData predictedVelocity = new VectorData(newVector3D(), Normal);
|
||||
public Vector3D actualMovement = newVector3D();
|
||||
public Vector3D stuckSpeedMultiplier = newVector3D(1, 1, 1);
|
||||
public VectorData predictedVelocity = new VectorData(new Vector(), VectorData.VectorType.Normal);
|
||||
public Vector actualMovement = new Vector();
|
||||
public Vector stuckSpeedMultiplier = new Vector(1, 1, 1);
|
||||
public UncertaintyHandler uncertaintyHandler;
|
||||
public double gravity;
|
||||
public float friction;
|
||||
@@ -187,9 +184,9 @@ public class GrimPlayer implements GrimUser {
|
||||
public TrigHandler trigHandler;
|
||||
public PacketStateData packetStateData;
|
||||
// Keep track of basetick stuff
|
||||
public Vector3D baseTickAddition = newVector3D();
|
||||
public Vector3D baseTickWaterPushing = newVector3D();
|
||||
public Vector3D startTickClientVel = newVector3D();
|
||||
public Vector baseTickAddition = new Vector();
|
||||
public Vector baseTickWaterPushing = new Vector();
|
||||
public Vector startTickClientVel = new Vector();
|
||||
// For syncing the player's full swing in 1.9+
|
||||
public int movementPackets = 0;
|
||||
public VelocityData firstBreadKB = null;
|
||||
@@ -245,7 +242,6 @@ public class GrimPlayer implements GrimUser {
|
||||
|
||||
packetStateData = new PacketStateData();
|
||||
|
||||
uncertaintyHandler.riptideEntities.add(0);
|
||||
uncertaintyHandler.collidingEntities.add(0);
|
||||
|
||||
if (getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14)) {
|
||||
@@ -296,7 +292,7 @@ public class GrimPlayer implements GrimUser {
|
||||
// If the player has that client sided riptide thing and has colliding with an entity
|
||||
// This was determined in the previous tick but whatever just include the 2 ticks around it
|
||||
// for a bit of safety as I doubt people will try to bypass this, it would be a very useless cheat
|
||||
if (riptideSpinAttackTicks >= 0 && Collections.max(uncertaintyHandler.riptideEntities) > 0) {
|
||||
if (riptideSpinAttackTicks >= 0 && Collections.max(uncertaintyHandler.collidingEntities) > 0) {
|
||||
possibleMovements.add(new VectorData(clientVelocity.clone().multiply(-0.2), VectorData.VectorType.Trident));
|
||||
}
|
||||
|
||||
@@ -364,15 +360,15 @@ public class GrimPlayer implements GrimUser {
|
||||
return data != null && data.first() == id;
|
||||
}
|
||||
|
||||
public void baseTickAddWaterPushing(ac.grim.grimac.utils.vector.Vector3D vector) {
|
||||
public void baseTickAddWaterPushing(Vector vector) {
|
||||
baseTickWaterPushing.add(vector);
|
||||
}
|
||||
|
||||
public void baseTickAddVector(Vector3D vector) {
|
||||
public void baseTickAddVector(Vector vector) {
|
||||
clientVelocity.add(vector);
|
||||
}
|
||||
|
||||
public void trackBaseTickAddition(Vector3D vector) {
|
||||
public void trackBaseTickAddition(Vector vector) {
|
||||
baseTickAddition.add(vector);
|
||||
}
|
||||
|
||||
@@ -569,18 +565,11 @@ public class GrimPlayer implements GrimUser {
|
||||
// - 3 ticks is a magic value, but it should buffer out incorrect predictions somewhat.
|
||||
// 2. The player is in a vehicle
|
||||
public boolean isTickingReliablyFor(int ticks) {
|
||||
// 1.21.2+: Tick end packet, on servers 1.21.2+
|
||||
// 1.8-: Flying packet
|
||||
return supportsEndTick()
|
||||
|| getClientVersion().isOlderThan(ClientVersion.V_1_9)
|
||||
|| !uncertaintyHandler.lastPointThree.hasOccurredSince(ticks)
|
||||
return (getClientVersion().isOlderThan(ClientVersion.V_1_9)
|
||||
|| !uncertaintyHandler.lastPointThree.hasOccurredSince(ticks))
|
||||
|| compensatedEntities.getSelf().inVehicle();
|
||||
}
|
||||
|
||||
public boolean inVehicle() {
|
||||
return compensatedEntities.getSelf().inVehicle();
|
||||
}
|
||||
|
||||
public boolean canThePlayerBeCloseToZeroMovement(int ticks) {
|
||||
return (!uncertaintyHandler.lastPointThree.hasOccurredSince(ticks));
|
||||
}
|
||||
@@ -708,11 +697,6 @@ public class GrimPlayer implements GrimUser {
|
||||
return getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_10) || (gamemode == GameMode.CREATIVE && compensatedEntities.getSelf().getOpLevel() >= 2);
|
||||
}
|
||||
|
||||
public boolean supportsEndTick() {
|
||||
// TODO: Bypass viaversion
|
||||
return getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21_2) && PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runSafely(Runnable runnable) {
|
||||
ChannelHelper.runInEventLoop(this.user.getChannel(), runnable);
|
||||
@@ -767,7 +751,6 @@ public class GrimPlayer implements GrimUser {
|
||||
@Getter private boolean ignoreDuplicatePacketRotation = false;
|
||||
@Getter private boolean experimentalChecks = false;
|
||||
@Getter private boolean cancelDuplicatePacket = true;
|
||||
@Getter private boolean exemptElytra = false;
|
||||
|
||||
@Override
|
||||
public void reload(ConfigManager config) {
|
||||
@@ -776,7 +759,6 @@ public class GrimPlayer implements GrimUser {
|
||||
experimentalChecks = config.getBooleanElse("experimental-checks", false);
|
||||
ignoreDuplicatePacketRotation = config.getBooleanElse("ignore-duplicate-packet-rotation", false);
|
||||
cancelDuplicatePacket = config.getBooleanElse("cancel-duplicate-packet", true);
|
||||
exemptElytra = config.getBooleanElse("exempt-elytra", false);
|
||||
// reload all checks
|
||||
for (AbstractCheck value : checkManager.allChecks.values()) value.reload(config);
|
||||
// reload punishment manager
|
||||
|
||||
@@ -38,10 +38,7 @@ import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.defaulttags.BlockTags;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import static ac.grim.grimac.utils.data.VectorData.VectorType.Dead;
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
// Averaged over 500 predictions (Defaults set slightly above my 3600x results)
|
||||
@@ -141,10 +138,10 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
double negX = Math.min(-0.05, GrimMath.clamp(player.actualMovement.getX(), -16, 16) - 0.05);
|
||||
double negZ = Math.min(-0.05, GrimMath.clamp(player.actualMovement.getZ(), -16, 16) - 0.05);
|
||||
|
||||
Vector3D NE = Collisions.maybeBackOffFromEdge(newVector3D(posX, 0, negZ), player, true);
|
||||
Vector3D NW = Collisions.maybeBackOffFromEdge(newVector3D(negX, 0, negZ), player, true);
|
||||
Vector3D SE = Collisions.maybeBackOffFromEdge(newVector3D(posX, 0, posZ), player, true);
|
||||
Vector3D SW = Collisions.maybeBackOffFromEdge(newVector3D(negX, 0, posZ), player, true);
|
||||
Vector NE = Collisions.maybeBackOffFromEdge(new Vector(posX, 0, negZ), player, true);
|
||||
Vector NW = Collisions.maybeBackOffFromEdge(new Vector(negX, 0, negZ), player, true);
|
||||
Vector SE = Collisions.maybeBackOffFromEdge(new Vector(posX, 0, posZ), player, true);
|
||||
Vector SW = Collisions.maybeBackOffFromEdge(new Vector(negX, 0, posZ), player, true);
|
||||
|
||||
boolean isEast = NE.getX() != posX || SE.getX() != posX;
|
||||
boolean isWest = NW.getX() != negX || SW.getX() != negX;
|
||||
@@ -187,7 +184,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
player.vehicleData.wasVehicleSwitch = false;
|
||||
|
||||
if (riding != null) {
|
||||
Vector3D pos = newVector3D(player.x, player.y, player.z);
|
||||
Vector pos = new Vector(player.x, player.y, player.z);
|
||||
SimpleCollisionBox interTruePositions = riding.getPossibleCollisionBoxes();
|
||||
|
||||
// We shrink the expanded bounding box to what the packet positions can be, for a smaller box
|
||||
@@ -197,7 +194,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
interTruePositions.expand(-width, 0, -width);
|
||||
interTruePositions.expandMax(0, -height, 0);
|
||||
|
||||
Vector3D cutTo = VectorUtils.cutBoxToVector(pos, interTruePositions);
|
||||
Vector cutTo = VectorUtils.cutBoxToVector(pos, interTruePositions);
|
||||
|
||||
// Now we need to simulate a tick starting at the most optimal position
|
||||
// The start position is never sent, so we assume the most optimal start position
|
||||
@@ -215,14 +212,14 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
} else {
|
||||
// Server always teleports the player when they eject anyways,
|
||||
// so just let the player control where they eject within reason, they get set back anyways
|
||||
if (newVector3D(player.lastX, player.lastY, player.lastZ).distance(newVector3D(player.x, player.y, player.z)) > 3) {
|
||||
if (new Vector(player.lastX, player.lastY, player.lastZ).distance(new Vector(player.x, player.y, player.z)) > 3) {
|
||||
player.getSetbackTeleportUtil().executeForceResync(); // Too far! (I think this value is sane)
|
||||
}
|
||||
|
||||
handleTeleport(update);
|
||||
|
||||
if (player.isClimbing) {
|
||||
Vector3D ladder = player.clientVelocity.clone().setY(0.2);
|
||||
Vector ladder = player.clientVelocity.clone().setY(0.2);
|
||||
PredictionEngineNormal.staticVectorEndOfTick(player, ladder);
|
||||
player.lastWasClimbing = ladder.getY();
|
||||
}
|
||||
@@ -302,7 +299,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
player.clientControlledVerticalCollision = Math.abs(player.y % (1 / 64D)) < 0.00001;
|
||||
|
||||
// This isn't the final velocity of the player in the tick, only the one applied to the player
|
||||
player.actualMovement = newVector3D(player.x - player.lastX, player.y - player.lastY, player.z - player.lastZ);
|
||||
player.actualMovement = new Vector(player.x - player.lastX, player.y - player.lastY, player.z - player.lastZ);
|
||||
|
||||
if (player.isSprinting != player.lastSprinting) {
|
||||
player.compensatedEntities.hasSprintingAttributeEnabled = player.isSprinting;
|
||||
@@ -429,9 +426,9 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
// Exempt if the player is dead or is riding a dead entity
|
||||
if (player.compensatedEntities.getSelf().isDead || (riding != null && riding.isDead)) {
|
||||
// Dead players can't cheat, if you find a way how they could, open an issue
|
||||
player.predictedVelocity = new VectorData(newVector3D(), Dead);
|
||||
player.clientVelocity = newVector3D();
|
||||
} else if (player.disableGrim || (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_8) && player.gamemode == GameMode.SPECTATOR) || player.isFlying || (player.isExemptElytra() && player.isGliding)) {
|
||||
player.predictedVelocity = new VectorData(new Vector(), VectorData.VectorType.Dead);
|
||||
player.clientVelocity = new Vector();
|
||||
} else if (player.disableGrim || (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_8) && player.gamemode == GameMode.SPECTATOR) || player.isFlying) {
|
||||
// We could technically check spectator but what's the point...
|
||||
// Added complexity to analyze a gamemode used mainly by moderators
|
||||
//
|
||||
@@ -453,7 +450,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
// Riptiding while on the ground moves the hitbox upwards before any movement code runs
|
||||
// It's a pain to support and this is my best attempt
|
||||
if (player.lastOnGround && player.packetStateData.tryingToRiptide && !player.compensatedEntities.getSelf().inVehicle()) {
|
||||
Vector3D pushingMovement = Collisions.collide(player, 0, 1.1999999F, 0);
|
||||
Vector pushingMovement = Collisions.collide(player, 0, 1.1999999F, 0);
|
||||
player.verticalCollision = pushingMovement.getY() != 1.1999999F;
|
||||
double currentY = player.clientVelocity.getY();
|
||||
|
||||
@@ -465,7 +462,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
player.lastY += pushingMovement.getY();
|
||||
new PlayerBaseTick(player).updatePlayerPose();
|
||||
player.boundingBox = GetBoundingBox.getPlayerBoundingBox(player, player.lastX, player.lastY, player.lastZ);
|
||||
player.actualMovement = newVector3D(player.x - player.lastX, player.y - player.lastY, player.z - player.lastZ);
|
||||
player.actualMovement = new Vector(player.x - player.lastX, player.y - player.lastY, player.z - player.lastZ);
|
||||
|
||||
player.couldSkipTick = true;
|
||||
|
||||
@@ -517,7 +514,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
//
|
||||
// Checking for oldClientVel being too high fixes BleachHack vertical scaffold
|
||||
if (player.getSetbackTeleportUtil().getRequiredSetBack() != null && player.getSetbackTeleportUtil().getRequiredSetBack().getTicksComplete() == 1) {
|
||||
Vector3D setbackVel = player.getSetbackTeleportUtil().getRequiredSetBack().getVelocity();
|
||||
Vector setbackVel = player.getSetbackTeleportUtil().getRequiredSetBack().getVelocity();
|
||||
// A player must have velocity going INTO the ground to be able to jump
|
||||
// Otherwise they could ignore upwards velocity that isn't useful into more useful upwards velocity (towering)
|
||||
// So if they are supposed to be going upwards, or are supposed to be off the ground, resync
|
||||
@@ -546,7 +543,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
// Patch sprint jumping with elytra exploit
|
||||
if (player.bukkitPlayer != null && player.isGliding && player.predictedVelocity.isJump() && player.isSprinting && !allowSprintJumpingWithElytra) {
|
||||
SetbackTeleportUtil.SetbackPosWithVector lastKnownGoodPosition = player.getSetbackTeleportUtil().lastKnownGoodPosition;
|
||||
lastKnownGoodPosition.setVector(lastKnownGoodPosition.getVector().multiply(newVector3D(0.6 * 0.91, 1, 0.6 * 0.91)));
|
||||
lastKnownGoodPosition.setVector(lastKnownGoodPosition.getVector().multiply(new Vector(0.6 * 0.91, 1, 0.6 * 0.91)));
|
||||
player.getSetbackTeleportUtil().executeNonSimulatingSetback();
|
||||
}
|
||||
|
||||
@@ -623,7 +620,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
* @param pushingMovement The collision result when trying to move the player upwards by 1.2f
|
||||
* @return Whether it is more likely that this player was on the ground the tick they riptided
|
||||
*/
|
||||
private boolean likelyGroundRiptide(Vector3D pushingMovement) {
|
||||
private boolean likelyGroundRiptide(Vector pushingMovement) {
|
||||
// Y velocity gets reset if the player collides vertically
|
||||
double riptideYResult = Riptide.getRiptideVelocity(player).getY();
|
||||
|
||||
@@ -641,4 +638,5 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
public void onReload(ConfigManager config) {
|
||||
allowSprintJumpingWithElytra = config.getBooleanElse("exploit.allow-sprint-jumping-when-using-elytra", true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,19 +9,16 @@ import ac.grim.grimac.utils.enums.Pose;
|
||||
import ac.grim.grimac.utils.latency.CompensatedEntities;
|
||||
import ac.grim.grimac.utils.math.GrimMath;
|
||||
import ac.grim.grimac.utils.nmsutil.*;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
public class PlayerBaseTick {
|
||||
GrimPlayer player;
|
||||
|
||||
@@ -43,11 +40,11 @@ public class PlayerBaseTick {
|
||||
|
||||
public void doBaseTick() {
|
||||
// Keep track of basetick stuff
|
||||
player.baseTickAddition = newVector3D();
|
||||
player.baseTickWaterPushing = newVector3D();
|
||||
player.baseTickAddition = new Vector();
|
||||
player.baseTickWaterPushing = new Vector();
|
||||
|
||||
if (player.isFlying && player.isSneaking && !player.compensatedEntities.getSelf().inVehicle()) {
|
||||
Vector3D flyingShift = newVector3D(0, player.flySpeed * -3, 0);
|
||||
Vector flyingShift = new Vector(0, player.flySpeed * -3, 0);
|
||||
player.baseTickAddVector(flyingShift);
|
||||
player.trackBaseTickAddition(flyingShift);
|
||||
}
|
||||
@@ -63,7 +60,7 @@ public class PlayerBaseTick {
|
||||
// You cannot crouch while flying, only shift - could be specific to 1.14?
|
||||
// pre-1.13 clients don't have this code
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_13) && player.wasTouchingWater && player.isSneaking && !player.isFlying && !player.compensatedEntities.getSelf().inVehicle()) {
|
||||
Vector3D waterPushVector = newVector3D(0, -0.04f, 0);
|
||||
Vector waterPushVector = new Vector(0, -0.04f, 0);
|
||||
player.baseTickAddVector(waterPushVector);
|
||||
player.trackBaseTickAddition(waterPushVector);
|
||||
}
|
||||
@@ -417,7 +414,7 @@ public class PlayerBaseTick {
|
||||
}
|
||||
|
||||
boolean hasPushed = false;
|
||||
Vector3D vec3 = newVector3D();
|
||||
Vector vec3 = new Vector();
|
||||
|
||||
for (int x = floorX; x < ceilX; ++x) {
|
||||
for (int y = floorY; y < ceilY; ++y) {
|
||||
@@ -467,7 +464,7 @@ public class PlayerBaseTick {
|
||||
}
|
||||
double d2 = 0.0;
|
||||
boolean hasTouched = false;
|
||||
Vector3D vec3 = newVector3D();
|
||||
Vector vec3 = new Vector();
|
||||
int n7 = 0;
|
||||
|
||||
for (int x = floorX; x < ceilX; ++x) {
|
||||
@@ -492,7 +489,7 @@ public class PlayerBaseTick {
|
||||
d2 = Math.max(fluidHeightToWorld - aABB.minY, d2);
|
||||
|
||||
if (!player.isFlying) {
|
||||
Vector3D vec32 = FluidTypeFlowing.getFlow(player, x, y, z);
|
||||
Vector vec32 = FluidTypeFlowing.getFlow(player, x, y, z);
|
||||
if (d2 < 0.4) {
|
||||
vec32 = vec32.multiply(d2);
|
||||
}
|
||||
|
||||
@@ -18,13 +18,11 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
import java.util.Set;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
/**
|
||||
* A lot of care was put into handling all the stupid stuff occurring between events
|
||||
* <p>
|
||||
@@ -143,7 +141,7 @@ public class PointThreeEstimator {
|
||||
isNearBubbleColumn = true;
|
||||
}
|
||||
|
||||
Vector3D fluidVector = FluidTypeFlowing.getFlow(player, x, y, z);
|
||||
Vector fluidVector = FluidTypeFlowing.getFlow(player, x, y, z);
|
||||
if (fluidVector.getX() != 0 || fluidVector.getZ() != 0) {
|
||||
isNearHorizontalFlowingLiquid = true;
|
||||
}
|
||||
@@ -307,7 +305,7 @@ public class PointThreeEstimator {
|
||||
player.boundingBox = player.boundingBox.copy().expand(0.03, 0, 0.03).offset(0, 0.03, 0);
|
||||
// 0.16 magic value -> 0.03 plus gravity, plus some additional lenience
|
||||
double searchDistance = -0.2 + Math.min(0, y);
|
||||
Vector3D collisionResult = Collisions.collide(player, 0, searchDistance, 0);
|
||||
Vector collisionResult = Collisions.collide(player, 0, searchDistance, 0);
|
||||
player.boundingBox = playerBox;
|
||||
return collisionResult.getY() != searchDistance;
|
||||
}
|
||||
@@ -316,7 +314,7 @@ public class PointThreeEstimator {
|
||||
public boolean determineCanSkipTick(float speed, Set<VectorData> init) {
|
||||
// If possible, check for idle packet
|
||||
// TODO: Find a better way to fix slime without forcing 0.03 where there is none
|
||||
if ((player.supportsEndTick() || player.getClientVersion().isOlderThan(ClientVersion.V_1_9)) && player.packetStateData.didLastMovementIncludePosition && !player.uncertaintyHandler.isSteppingOnSlime) {
|
||||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_9) && player.packetStateData.didLastMovementIncludePosition && !player.uncertaintyHandler.isSteppingOnSlime) {
|
||||
return false; // Last packet included a position so not 0.03
|
||||
}
|
||||
|
||||
@@ -341,9 +339,9 @@ public class PointThreeEstimator {
|
||||
// Takes 0.01 millis, on average, to compute... this should be improved eventually
|
||||
for (VectorData data : init) {
|
||||
// Try to get the vector as close to zero as possible to give the best chance at 0.03...
|
||||
Vector3D toZeroVec = new PredictionEngine().handleStartingVelocityUncertainty(player, data, newVector3D());
|
||||
Vector toZeroVec = new PredictionEngine().handleStartingVelocityUncertainty(player, data, new Vector());
|
||||
// Collide to handle mostly gravity, but other scenarios similar to this.
|
||||
Vector3D collisionResult = Collisions.collide(player, toZeroVec.getX(), toZeroVec.getY(), toZeroVec.getZ(), Integer.MIN_VALUE, null);
|
||||
Vector collisionResult = Collisions.collide(player, toZeroVec.getX(), toZeroVec.getY(), toZeroVec.getZ(), Integer.MIN_VALUE, null);
|
||||
|
||||
// If this tick is the tick after y velocity was by 0, a stepping movement is POSSIBLE to have been hidden
|
||||
// A bit hacky... is there a better way? I'm unsure...
|
||||
|
||||
@@ -13,12 +13,10 @@ import ac.grim.grimac.utils.nmsutil.ReachUtils;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
public class UncertaintyHandler {
|
||||
private final GrimPlayer player;
|
||||
// Handles uncertainty when a piston could have pushed a player in a direction
|
||||
@@ -66,10 +64,8 @@ public class UncertaintyHandler {
|
||||
public boolean lastMovementWasUnknown003VectorReset = false;
|
||||
// Handles 0.03 vertical false where actual velocity is greater than predicted because of previous lenience
|
||||
public boolean wasZeroPointThreeVertically = false;
|
||||
// How many entities are within 0.5 blocks of the player's bounding box that are pushable?
|
||||
// How many entities are within 0.5 blocks of the player's bounding box?
|
||||
public EvictingQueue<Integer> collidingEntities = new EvictingQueue<>(3);
|
||||
// How many entities are within 0.5 blocks of the player's bounding box? Should only exclude entities in spectator
|
||||
public EvictingQueue<Integer> riptideEntities = new EvictingQueue<>(3);
|
||||
// Fishing rod pulling is another method of adding to a player's velocity
|
||||
public List<Integer> fishingRodPulls = new ArrayList<>();
|
||||
public SimpleCollisionBox fireworksBox = null;
|
||||
@@ -151,15 +147,15 @@ public class UncertaintyHandler {
|
||||
entityBox.maxY -= height;
|
||||
entityBox.expand(-width / 2, 0, -width / 2);
|
||||
|
||||
Vector3D maxLocation = newVector3D(entityBox.maxX, entityBox.maxY, entityBox.maxZ);
|
||||
Vector3D minLocation = newVector3D(entityBox.minX, entityBox.minY, entityBox.minZ);
|
||||
Vector maxLocation = new Vector(entityBox.maxX, entityBox.maxY, entityBox.maxZ);
|
||||
Vector minLocation = new Vector(entityBox.minX, entityBox.minY, entityBox.minZ);
|
||||
|
||||
Vector3D diff = minLocation.subtract(newVector3D(player.lastX, player.lastY + 0.8 * 1.8, player.lastZ)).multiply(0.1);
|
||||
Vector diff = minLocation.subtract(new Vector(player.lastX, player.lastY + 0.8 * 1.8, player.lastZ)).multiply(0.1);
|
||||
fishingRodPullBox.minX = Math.min(0, diff.getX());
|
||||
fishingRodPullBox.minY = Math.min(0, diff.getY());
|
||||
fishingRodPullBox.minZ = Math.min(0, diff.getZ());
|
||||
|
||||
diff = maxLocation.subtract(newVector3D(player.lastX, player.lastY + 0.8 * 1.8, player.lastZ)).multiply(0.1);
|
||||
diff = maxLocation.subtract(new Vector(player.lastX, player.lastY + 0.8 * 1.8, player.lastZ)).multiply(0.1);
|
||||
fishingRodPullBox.maxX = Math.max(0, diff.getX());
|
||||
fishingRodPullBox.maxY = Math.max(0, diff.getY());
|
||||
fishingRodPullBox.maxZ = Math.max(0, diff.getZ());
|
||||
@@ -174,8 +170,8 @@ public class UncertaintyHandler {
|
||||
|
||||
fireworksBox = new SimpleCollisionBox();
|
||||
|
||||
Vector3D currentLook = ReachUtils.getLook(player, player.xRot, player.yRot);
|
||||
ac.grim.grimac.utils.vector.Vector3D lastLook = ReachUtils.getLook(player, player.lastXRot, player.lastYRot);
|
||||
Vector currentLook = ReachUtils.getLook(player, player.xRot, player.yRot);
|
||||
Vector lastLook = ReachUtils.getLook(player, player.lastXRot, player.lastYRot);
|
||||
|
||||
double antiTickSkipping = player.isPointThree() ? 0 : 0.05; // With 0.03, let that handle tick skipping
|
||||
|
||||
|
||||
@@ -24,9 +24,7 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import io.github.retrooper.packetevents.util.viaversion.ViaVersionUtil;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class MovementTicker {
|
||||
public final GrimPlayer player;
|
||||
@@ -43,7 +41,6 @@ public class MovementTicker {
|
||||
&& (!ViaVersionUtil.isAvailable() || Via.getConfig().isPreventCollision()))) return;
|
||||
|
||||
int possibleCollidingEntities = 0;
|
||||
int possibleRiptideEntities = 0;
|
||||
|
||||
// Players in vehicles do not have collisions
|
||||
if (!player.compensatedEntities.getSelf().inVehicle()) {
|
||||
@@ -55,23 +52,16 @@ public class MovementTicker {
|
||||
final TeamHandler teamHandler = player.checkManager.getPacketCheck(TeamHandler.class);
|
||||
|
||||
for (PacketEntity entity : player.compensatedEntities.entityMap.values()) {
|
||||
// TODO actually handle entity collisions instead of this awfulness
|
||||
SimpleCollisionBox entityBox = entity.getPossibleCollisionBoxes();
|
||||
|
||||
boolean isCollided = playerBox.isCollided(entityBox);
|
||||
if (isCollided) {
|
||||
possibleRiptideEntities++;
|
||||
}
|
||||
|
||||
// Filters out entities that can't be pushed/collided because of team collision rules
|
||||
// Also handles 1.9+ player on 1.8- server with ViaVersion prevent-collision disabled.
|
||||
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9)
|
||||
&& !EntityPredicates.canBePushedBy(player, entity, teamHandler).test(player)) continue;
|
||||
|
||||
if (!entity.isPushable())
|
||||
continue;
|
||||
|
||||
if (isCollided) {
|
||||
// 1.9+ player on 1.8- server with ViaVersion prevent-collision disabled.
|
||||
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9)
|
||||
&& !EntityPredicates.canBePushedBy(player, entity, teamHandler).test(player)) continue;
|
||||
|
||||
SimpleCollisionBox entityBox = entity.getPossibleCollisionBoxes();
|
||||
|
||||
if (playerBox.isCollided(entityBox)) {
|
||||
possibleCollidingEntities++;
|
||||
}
|
||||
}
|
||||
@@ -84,13 +74,12 @@ public class MovementTicker {
|
||||
player.uncertaintyHandler.yPositiveUncertainty += 0.05;
|
||||
}
|
||||
|
||||
player.uncertaintyHandler.riptideEntities.add(possibleRiptideEntities);
|
||||
player.uncertaintyHandler.collidingEntities.add(possibleCollidingEntities);
|
||||
}
|
||||
|
||||
public void move(Vector3D inputVel, Vector3D collide) {
|
||||
public void move(Vector inputVel, Vector collide) {
|
||||
if (player.stuckSpeedMultiplier.getX() < 0.99) {
|
||||
player.clientVelocity = newVector3D();
|
||||
player.clientVelocity = new Vector();
|
||||
}
|
||||
|
||||
if (inputVel.getX() != collide.getX()) {
|
||||
@@ -183,21 +172,21 @@ public class MovementTicker {
|
||||
|
||||
// The game disregards movements smaller than 1e-7 (such as in boats)
|
||||
if (collide.lengthSquared() < 1e-7) {
|
||||
collide = newVector3D();
|
||||
collide = new Vector();
|
||||
}
|
||||
|
||||
// This is where vanilla moves the bounding box and sets it
|
||||
player.predictedVelocity = new VectorData(collide.clone(), player.predictedVelocity.lastVector, player.predictedVelocity.vectorType);
|
||||
|
||||
float f = BlockProperties.getBlockSpeedFactor(player, player.mainSupportingBlockData, new Vector3d(player.x, player.y, player.z));
|
||||
player.clientVelocity.multiply(newVector3D(f, 1, f));
|
||||
player.clientVelocity.multiply(new Vector(f, 1, f));
|
||||
|
||||
// Reset stuck speed so it can update
|
||||
if (player.stuckSpeedMultiplier.getX() < 0.99) {
|
||||
player.uncertaintyHandler.lastStuckSpeedMultiplier.reset();
|
||||
}
|
||||
|
||||
player.stuckSpeedMultiplier = newVector3D(1, 1, 1);
|
||||
player.stuckSpeedMultiplier = new Vector(1, 1, 1);
|
||||
|
||||
// 1.15 and older clients use the handleInsideBlocks method for lava
|
||||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_16))
|
||||
@@ -212,7 +201,7 @@ public class MovementTicker {
|
||||
|
||||
// Flying players are not affected by cobwebs/sweet berry bushes
|
||||
if (player.isFlying) {
|
||||
player.stuckSpeedMultiplier = newVector3D(1, 1, 1);
|
||||
player.stuckSpeedMultiplier = new Vector(1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -399,14 +388,14 @@ public class MovementTicker {
|
||||
|
||||
// Lava movement changed in 1.16
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_16) && player.slightlyTouchingLava) {
|
||||
player.clientVelocity = player.clientVelocity.multiply(newVector3D(0.5D, 0.800000011920929D, 0.5D));
|
||||
player.clientVelocity = player.clientVelocity.multiply(new Vector(0.5D, 0.800000011920929D, 0.5D));
|
||||
player.clientVelocity = FluidFallingAdjustedMovement.getFluidFallingAdjustedMovement(player, playerGravity, isFalling, player.clientVelocity);
|
||||
} else {
|
||||
player.clientVelocity.multiply(0.5D);
|
||||
}
|
||||
|
||||
if (player.hasGravity)
|
||||
player.clientVelocity.add(newVector3D(0.0D, -playerGravity / 4.0D, 0.0D));
|
||||
player.clientVelocity.add(new Vector(0.0D, -playerGravity / 4.0D, 0.0D));
|
||||
|
||||
} else if (player.isGliding) {
|
||||
player.friction = 0.99F; // Not vanilla, just useful for other grim stuff
|
||||
|
||||
@@ -5,8 +5,7 @@ import ac.grim.grimac.utils.data.packetentity.PacketEntityHorse;
|
||||
import ac.grim.grimac.utils.nmsutil.Collisions;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class MovementTickerHorse extends MovementTickerLivingVehicle {
|
||||
|
||||
@@ -27,7 +26,7 @@ public class MovementTickerHorse extends MovementTickerLivingVehicle {
|
||||
forwardsInput *= 0.25F;
|
||||
}
|
||||
|
||||
this.movementInput = newVector3D(horizInput, 0, forwardsInput);
|
||||
this.movementInput = new Vector(horizInput, 0, forwardsInput);
|
||||
if (movementInput.lengthSquared() > 1) movementInput.normalize();
|
||||
}
|
||||
|
||||
|
||||
+2
-5
@@ -7,13 +7,10 @@ import ac.grim.grimac.predictionengine.predictions.rideable.PredictionEngineRide
|
||||
import ac.grim.grimac.predictionengine.predictions.rideable.PredictionEngineRideableWaterLegacy;
|
||||
import ac.grim.grimac.utils.nmsutil.BlockProperties;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class MovementTickerLivingVehicle extends MovementTicker {
|
||||
Vector3D movementInput = newVector3D();
|
||||
Vector movementInput = new Vector();
|
||||
|
||||
public MovementTickerLivingVehicle(GrimPlayer player) {
|
||||
super(player);
|
||||
|
||||
@@ -3,13 +3,12 @@ package ac.grim.grimac.predictionengine.movementtick;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntityRideable;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class MovementTickerPig extends MovementTickerRideable {
|
||||
public MovementTickerPig(GrimPlayer player) {
|
||||
super(player);
|
||||
movementInput = newVector3D(0, 0, 1);
|
||||
movementInput = new Vector(0, 0, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-4
@@ -11,16 +11,15 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
public class MovementTickerStrider extends MovementTickerRideable {
|
||||
|
||||
public MovementTickerStrider(GrimPlayer player) {
|
||||
super(player);
|
||||
movementInput = newVector3D(0, 0, 1);
|
||||
movementInput = new Vector(0, 0, 1);
|
||||
}
|
||||
|
||||
public static void floatStrider(GrimPlayer player) {
|
||||
@@ -28,7 +27,7 @@ public class MovementTickerStrider extends MovementTickerRideable {
|
||||
if (isAbove(player) && player.compensatedWorld.getLavaFluidLevelAt((int) Math.floor(player.x), (int) Math.floor(player.y + 1), (int) Math.floor(player.z)) == 0) {
|
||||
player.onGround = true;
|
||||
} else {
|
||||
player.clientVelocity.multiply(0.5).add(newVector3D(0, 0.05, 0));
|
||||
player.clientVelocity.multiply(0.5).add(new Vector(0, 0.05, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.predictionengine.SneakingEstimator;
|
||||
import ac.grim.grimac.predictionengine.movementtick.MovementTickerPlayer;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.KnownInput;
|
||||
import ac.grim.grimac.utils.data.Pair;
|
||||
import ac.grim.grimac.utils.data.VectorData;
|
||||
import ac.grim.grimac.utils.math.VectorUtils;
|
||||
@@ -12,29 +11,20 @@ import ac.grim.grimac.utils.nmsutil.Collisions;
|
||||
import ac.grim.grimac.utils.nmsutil.GetBoundingBox;
|
||||
import ac.grim.grimac.utils.nmsutil.JumpPower;
|
||||
import ac.grim.grimac.utils.nmsutil.Riptide;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static ac.grim.grimac.utils.data.VectorData.VectorType.ZeroPointZeroThree;
|
||||
import static ac.grim.grimac.utils.nmsutil.Collisions.isEmpty;
|
||||
import static ac.grim.grimac.utils.nmsutil.GetBoundingBox.getBoundingBoxFromPosAndSize;
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import static com.github.retrooper.packetevents.protocol.attribute.Attributes.GENERIC_GRAVITY;
|
||||
import static com.github.retrooper.packetevents.protocol.player.ClientVersion.V_1_13;
|
||||
import static java.lang.Math.*;
|
||||
import static java.util.Collections.max;
|
||||
|
||||
public class PredictionEngine {
|
||||
|
||||
public static Vector3D clampMovementToHardBorder(GrimPlayer player, Vector3D outputVel) {
|
||||
public static Vector clampMovementToHardBorder(GrimPlayer player, Vector outputVel) {
|
||||
// TODO: Reimplement
|
||||
return outputVel;
|
||||
}
|
||||
|
||||
public static Vector3D transformInputsToVector(GrimPlayer player, Vector3D theoreticalInput) {
|
||||
public static Vector transformInputsToVector(GrimPlayer player, Vector theoreticalInput) {
|
||||
float bestPossibleX;
|
||||
float bestPossibleZ;
|
||||
|
||||
@@ -52,15 +42,15 @@ public class PredictionEngine {
|
||||
bestPossibleZ *= 0.2F;
|
||||
}
|
||||
|
||||
Vector3D inputVector = newVector3D(bestPossibleX, 0, bestPossibleZ);
|
||||
Vector inputVector = new Vector(bestPossibleX, 0, bestPossibleZ);
|
||||
inputVector.multiply(0.98F);
|
||||
|
||||
// Simulate float rounding imprecision
|
||||
inputVector = newVector3D((float) inputVector.getX(), (float) inputVector.getY(), (float) inputVector.getZ());
|
||||
inputVector = new Vector((float) inputVector.getX(), (float) inputVector.getY(), (float) inputVector.getZ());
|
||||
|
||||
if (inputVector.lengthSquared() > 1) {
|
||||
double d0 = sqrt(inputVector.getX() * inputVector.getX() + inputVector.getY() * inputVector.getY() + inputVector.getZ() * inputVector.getZ());
|
||||
inputVector = newVector3D(inputVector.getX() / d0, inputVector.getY() / d0, inputVector.getZ() / d0);
|
||||
double d0 = Math.sqrt(inputVector.getX() * inputVector.getX() + inputVector.getY() * inputVector.getY() + inputVector.getZ() * inputVector.getZ());
|
||||
inputVector = new Vector(inputVector.getX() / d0, inputVector.getY() / d0, inputVector.getZ() / d0);
|
||||
}
|
||||
|
||||
return inputVector;
|
||||
@@ -72,7 +62,7 @@ public class PredictionEngine {
|
||||
if (player.uncertaintyHandler.influencedByBouncyBlock()) {
|
||||
for (VectorData data : init) {
|
||||
// Try to get the vector as close to zero as possible to give the best chance at 0.03...
|
||||
Vector3D toZeroVec = new PredictionEngine().handleStartingVelocityUncertainty(player, data, newVector3D(0, -1000000000, 0)); // Downwards without overflow risk
|
||||
Vector toZeroVec = new PredictionEngine().handleStartingVelocityUncertainty(player, data, new Vector(0, -1000000000, 0)); // Downwards without overflow risk
|
||||
|
||||
player.uncertaintyHandler.nextTickSlimeBlockUncertainty = Math.max(Math.abs(toZeroVec.getY()), player.uncertaintyHandler.nextTickSlimeBlockUncertainty);
|
||||
}
|
||||
@@ -115,22 +105,20 @@ public class PredictionEngine {
|
||||
double bestInput = Double.MAX_VALUE;
|
||||
|
||||
VectorData bestCollisionVel = null;
|
||||
Vector3D beforeCollisionMovement = null;
|
||||
Vector3D originalClientVel = player.clientVelocity.clone();
|
||||
Vector beforeCollisionMovement = null;
|
||||
Vector originalClientVel = player.clientVelocity.clone();
|
||||
|
||||
SimpleCollisionBox originalBB = player.boundingBox;
|
||||
// 0.03 doesn't exist with vehicles, thank god
|
||||
// 1.13+ clients have stupid poses that desync because mojang brilliantly removed the idle packet in 1.9
|
||||
SimpleCollisionBox pointThreeThanksMojang = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_13)
|
||||
? GetBoundingBox.getBoundingBoxFromPosAndSize(player, player.lastX, player.lastY, player.lastZ, 0.6f, 0.6f)
|
||||
: originalBB;
|
||||
SimpleCollisionBox pointThreeThanksMojang = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_13) ? GetBoundingBox.getBoundingBoxFromPosAndSize(player, player.lastX, player.lastY, player.lastZ, 0.6f, 0.6f) : originalBB;
|
||||
|
||||
player.skippedTickInActualMovement = false;
|
||||
|
||||
for (VectorData clientVelAfterInput : possibleVelocities) {
|
||||
Vector3D primaryPushMovement = handleStartingVelocityUncertainty(player, clientVelAfterInput, player.actualMovement);
|
||||
Vector primaryPushMovement = handleStartingVelocityUncertainty(player, clientVelAfterInput, player.actualMovement);
|
||||
|
||||
Vector3D bestTheoreticalCollisionResult = VectorUtils.cutBoxToVector(player.actualMovement, new SimpleCollisionBox(0, Math.min(0, primaryPushMovement.getY()), 0, primaryPushMovement.getX(), Math.max(0.6, primaryPushMovement.getY()), primaryPushMovement.getZ()).sort());
|
||||
Vector bestTheoreticalCollisionResult = VectorUtils.cutBoxToVector(player.actualMovement, new SimpleCollisionBox(0, Math.min(0, primaryPushMovement.getY()), 0, primaryPushMovement.getX(), Math.max(0.6, primaryPushMovement.getY()), primaryPushMovement.getZ()).sort());
|
||||
// Check if this vector could ever possible beat the last vector in terms of accuracy
|
||||
// This is quite a good optimization :)
|
||||
if (bestTheoreticalCollisionResult.distanceSquared(player.actualMovement) > bestInput && !clientVelAfterInput.isKnockback() && !clientVelAfterInput.isExplosion()) {
|
||||
@@ -144,9 +132,9 @@ public class PredictionEngine {
|
||||
}
|
||||
|
||||
// Returns pair of primary push movement, and then outputvel
|
||||
Pair<Vector3D, Vector3D> output = doSeekingWallCollisions(player, primaryPushMovement, originalClientVel, clientVelAfterInput);
|
||||
Pair<Vector, Vector> output = doSeekingWallCollisions(player, primaryPushMovement, originalClientVel, clientVelAfterInput);
|
||||
primaryPushMovement = output.first();
|
||||
Vector3D outputVel = clampMovementToHardBorder(player, output.second());
|
||||
Vector outputVel = clampMovementToHardBorder(player, output.second());
|
||||
|
||||
double resultAccuracy = outputVel.distanceSquared(player.actualMovement);
|
||||
|
||||
@@ -220,7 +208,7 @@ public class PredictionEngine {
|
||||
}
|
||||
}
|
||||
|
||||
private Pair<Vector3D, Vector3D> doSeekingWallCollisions(GrimPlayer player, Vector3D primaryPushMovement, Vector3D originalClientVel, VectorData clientVelAfterInput) {
|
||||
private Pair<Vector, Vector> doSeekingWallCollisions(GrimPlayer player, Vector primaryPushMovement, Vector originalClientVel, VectorData clientVelAfterInput) {
|
||||
boolean vehicleKB = player.compensatedEntities.getSelf().inVehicle() && clientVelAfterInput.isKnockback() && clientVelAfterInput.vector.getY() == 0;
|
||||
// Extra collision epsilon required for vehicles to be accurate
|
||||
double xAdditional = Math.signum(primaryPushMovement.getX()) * SimpleCollisionBox.COLLISION_EPSILON;
|
||||
@@ -233,9 +221,9 @@ public class PredictionEngine {
|
||||
double testX = primaryPushMovement.getX() + xAdditional;
|
||||
double testY = primaryPushMovement.getY() + yAdditional;
|
||||
double testZ = primaryPushMovement.getZ() + zAdditional;
|
||||
primaryPushMovement = newVector3D(testX, testY, testZ);
|
||||
primaryPushMovement = new Vector(testX, testY, testZ);
|
||||
|
||||
Vector3D outputVel = Collisions.collide(player, primaryPushMovement.getX(), primaryPushMovement.getY(), primaryPushMovement.getZ(), originalClientVel.getY(), clientVelAfterInput);
|
||||
Vector outputVel = Collisions.collide(player, primaryPushMovement.getX(), primaryPushMovement.getY(), primaryPushMovement.getZ(), originalClientVel.getY(), clientVelAfterInput);
|
||||
|
||||
if (testX == outputVel.getX()) { // the player didn't have X collision, don't ruin offset by collision epsilon
|
||||
primaryPushMovement.setX(primaryPushMovement.getX() - xAdditional);
|
||||
@@ -261,20 +249,20 @@ public class PredictionEngine {
|
||||
|
||||
// For now just let the player control their Y velocity within 0.03. Gravity should stop exploits.
|
||||
// 0.03 - 0.784 < -0.03 = can't skip next tick
|
||||
Vector3D pointThreeVector = newVector3D();
|
||||
Vector pointThreeVector = new Vector();
|
||||
|
||||
// Stop a bypass (and fix falses) by carrying over the player's current velocity IF they couldn't have modified it
|
||||
if (!player.pointThreeEstimator.controlsVerticalMovement()) {
|
||||
pointThreeVector.setY(player.clientVelocity.getY());
|
||||
} else { // Carry over the current Y velocity to try and help with gravity issues
|
||||
pointThreePossibilities.add(new VectorData(newVector3D(0, player.clientVelocity.getY(), 0), ZeroPointZeroThree));
|
||||
pointThreePossibilities.add(new VectorData(new Vector(0, player.clientVelocity.getY(), 0), VectorData.VectorType.ZeroPointZeroThree));
|
||||
}
|
||||
|
||||
pointThreePossibilities.add(new VectorData(pointThreeVector, VectorData.VectorType.ZeroPointZeroThree));
|
||||
|
||||
// Swim hop
|
||||
if (player.pointThreeEstimator.isNearFluid && !Collisions.isEmpty(player, player.boundingBox.copy().expand(0.4, 0, 0.4)) && !player.onGround) { // onGround can still be used here, else generic 0.03
|
||||
pointThreePossibilities.add(new VectorData(newVector3D(0, 0.3, 0), ZeroPointZeroThree));
|
||||
pointThreePossibilities.add(new VectorData(new Vector(0, 0.3, 0), VectorData.VectorType.ZeroPointZeroThree));
|
||||
}
|
||||
|
||||
// Swimming vertically can add more Y velocity than normal
|
||||
@@ -291,7 +279,7 @@ public class PredictionEngine {
|
||||
player.clientVelocity.getX(), 0, player.clientVelocity.getZ()).expand(0.5, -SimpleCollisionBox.COLLISION_EPSILON, 0.5)))) {
|
||||
|
||||
// Calculate the Y velocity after friction
|
||||
Vector3D hackyClimbVector = newVector3D(0, 0.2, 0);
|
||||
Vector hackyClimbVector = new Vector(0, 0.2, 0);
|
||||
PredictionEngineNormal.staticVectorEndOfTick(player, hackyClimbVector);
|
||||
|
||||
pointThreePossibilities.add(new VectorData(hackyClimbVector, VectorData.VectorType.ZeroPointZeroThree));
|
||||
@@ -302,8 +290,8 @@ public class PredictionEngine {
|
||||
addExplosionToPossibilities(player, pointThreePossibilities);
|
||||
|
||||
if (player.packetStateData.tryingToRiptide) {
|
||||
Vector3D riptideAddition = Riptide.getRiptideVelocity(player);
|
||||
pointThreePossibilities.add(new VectorData(player.clientVelocity.clone().add(riptideAddition), new VectorData(newVector3D(), ZeroPointZeroThree), VectorData.VectorType.Trident));
|
||||
Vector riptideAddition = Riptide.getRiptideVelocity(player);
|
||||
pointThreePossibilities.add(new VectorData(player.clientVelocity.clone().add(riptideAddition), new VectorData(new Vector(), VectorData.VectorType.ZeroPointZeroThree), VectorData.VectorType.Trident));
|
||||
}
|
||||
|
||||
possibleVelocities.addAll(applyInputsToVelocityPossibilities(player, pointThreePossibilities, speed));
|
||||
@@ -324,7 +312,7 @@ public class PredictionEngine {
|
||||
// Water pushing movement is affected by initial velocity due to 0.003 eating pushing in the past
|
||||
if (vectorData.isKnockback() && player.baseTickWaterPushing.lengthSquared() != 0) {
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_13)) {
|
||||
Vector3D vec3 = player.baseTickWaterPushing.clone();
|
||||
Vector vec3 = player.baseTickWaterPushing.clone();
|
||||
if (Math.abs(vectorData.vector.getX()) < 0.003 && Math.abs(vectorData.vector.getZ()) < 0.003 && player.baseTickWaterPushing.length() < 0.0045000000000000005D) {
|
||||
vec3 = vec3.normalize().multiply(0.0045000000000000005);
|
||||
}
|
||||
@@ -344,7 +332,7 @@ public class PredictionEngine {
|
||||
addExplosionToPossibilities(player, velocities);
|
||||
|
||||
if (player.packetStateData.tryingToRiptide) {
|
||||
Vector3D riptideAddition = Riptide.getRiptideVelocity(player);
|
||||
Vector riptideAddition = Riptide.getRiptideVelocity(player);
|
||||
velocities.add(new VectorData(player.clientVelocity.clone().add(riptideAddition), VectorData.VectorType.Trident));
|
||||
}
|
||||
|
||||
@@ -373,7 +361,7 @@ public class PredictionEngine {
|
||||
private void addAttackSlowToPossibilities(GrimPlayer player, Set<VectorData> velocities) {
|
||||
for (int x = 1; x <= Math.min(player.maxPlayerAttackSlow, 5); x++) {
|
||||
for (VectorData data : new HashSet<>(velocities)) {
|
||||
velocities.add(data.returnNewModified(data.vector.clone().multiply(newVector3D(0.6, 1, 0.6)), VectorData.VectorType.AttackSlow));
|
||||
velocities.add(data.returnNewModified(data.vector.clone().multiply(new Vector(0.6, 1, 0.6)), VectorData.VectorType.AttackSlow));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -476,15 +464,15 @@ public class PredictionEngine {
|
||||
return Double.compare(a.vector.distanceSquared(player.actualMovement), b.vector.distanceSquared(player.actualMovement));
|
||||
}
|
||||
|
||||
public Vector3D handleStartingVelocityUncertainty(GrimPlayer player, VectorData vector, Vector3D targetVec) {
|
||||
double avgColliding = max(player.uncertaintyHandler.collidingEntities);
|
||||
public Vector handleStartingVelocityUncertainty(GrimPlayer player, VectorData vector, Vector targetVec) {
|
||||
double avgColliding = Collections.max(player.uncertaintyHandler.collidingEntities);
|
||||
|
||||
double additionHorizontal = player.uncertaintyHandler.getOffsetHorizontal(vector);
|
||||
double additionVertical = player.uncertaintyHandler.getVerticalOffset(vector);
|
||||
|
||||
double pistonX = max(player.uncertaintyHandler.pistonX);
|
||||
double pistonY = max(player.uncertaintyHandler.pistonY);
|
||||
double pistonZ = max(player.uncertaintyHandler.pistonZ);
|
||||
double pistonX = Collections.max(player.uncertaintyHandler.pistonX);
|
||||
double pistonY = Collections.max(player.uncertaintyHandler.pistonY);
|
||||
double pistonZ = Collections.max(player.uncertaintyHandler.pistonZ);
|
||||
|
||||
additionHorizontal += player.uncertaintyHandler.lastHorizontalOffset;
|
||||
additionVertical += player.uncertaintyHandler.lastVerticalOffset;
|
||||
@@ -527,13 +515,13 @@ public class PredictionEngine {
|
||||
// 0.075 seems safe?
|
||||
//
|
||||
// Be somewhat careful as there is an antikb (for horizontal) that relies on this lenience
|
||||
Vector3D uncertainty = newVector3D(avgColliding * 0.08, additionVertical, avgColliding * 0.08);
|
||||
Vector uncertainty = new Vector(avgColliding * 0.08, additionVertical, avgColliding * 0.08);
|
||||
|
||||
Vector3D min = newVector3D(player.uncertaintyHandler.xNegativeUncertainty - additionHorizontal, -bonusY + player.uncertaintyHandler.yNegativeUncertainty, player.uncertaintyHandler.zNegativeUncertainty - additionHorizontal);
|
||||
Vector3D max = newVector3D(player.uncertaintyHandler.xPositiveUncertainty + additionHorizontal, bonusY + player.uncertaintyHandler.yPositiveUncertainty, player.uncertaintyHandler.zPositiveUncertainty + additionHorizontal);
|
||||
Vector min = new Vector(player.uncertaintyHandler.xNegativeUncertainty - additionHorizontal, -bonusY + player.uncertaintyHandler.yNegativeUncertainty, player.uncertaintyHandler.zNegativeUncertainty - additionHorizontal);
|
||||
Vector max = new Vector(player.uncertaintyHandler.xPositiveUncertainty + additionHorizontal, bonusY + player.uncertaintyHandler.yPositiveUncertainty, player.uncertaintyHandler.zPositiveUncertainty + additionHorizontal);
|
||||
|
||||
Vector3D minVector = vector.vector.clone().add(min.subtract(uncertainty));
|
||||
Vector3D maxVector = vector.vector.clone().add(max.add(uncertainty));
|
||||
Vector minVector = vector.vector.clone().add(min.subtract(uncertainty));
|
||||
Vector maxVector = vector.vector.clone().add(max.add(uncertainty));
|
||||
|
||||
// Handle the player landing within 0.03 movement, which resets Y velocity
|
||||
if (player.uncertaintyHandler.onGroundUncertain && vector.vector.getY() < 0) {
|
||||
@@ -560,7 +548,7 @@ public class PredictionEngine {
|
||||
// We can't simulate the player's Y velocity, unknown number of ticks with a gravity change
|
||||
// Feel free to simulate all 104857600000000000000000000 possibilities!
|
||||
if (!player.pointThreeEstimator.canPredictNextVerticalMovement()) {
|
||||
minVector.setY(minVector.getY() - player.compensatedEntities.getSelf().getAttributeValue(GENERIC_GRAVITY));
|
||||
minVector.setY(minVector.getY() - player.compensatedEntities.getSelf().getAttributeValue(Attributes.GENERIC_GRAVITY));
|
||||
}
|
||||
|
||||
// Hidden slime block bounces by missing idle tick and 0.03
|
||||
@@ -600,9 +588,9 @@ public class PredictionEngine {
|
||||
box.maxZ += sneaking.getSneakingPotentialHiddenVelocity().maxZ;
|
||||
|
||||
if (player.uncertaintyHandler.fireworksBox != null) {
|
||||
double minXdiff = min(0, player.uncertaintyHandler.fireworksBox.minX - originalVec.vector.getX());
|
||||
double minYdiff = min(0, player.uncertaintyHandler.fireworksBox.minY - originalVec.vector.getY());
|
||||
double minZdiff = min(0, player.uncertaintyHandler.fireworksBox.minZ - originalVec.vector.getZ());
|
||||
double minXdiff = Math.min(0, player.uncertaintyHandler.fireworksBox.minX - originalVec.vector.getX());
|
||||
double minYdiff = Math.min(0, player.uncertaintyHandler.fireworksBox.minY - originalVec.vector.getY());
|
||||
double minZdiff = Math.min(0, player.uncertaintyHandler.fireworksBox.minZ - originalVec.vector.getZ());
|
||||
double maxXdiff = Math.max(0, player.uncertaintyHandler.fireworksBox.maxX - originalVec.vector.getX());
|
||||
double maxYdiff = Math.max(0, player.uncertaintyHandler.fireworksBox.maxY - originalVec.vector.getY());
|
||||
double maxZdiff = Math.max(0, player.uncertaintyHandler.fireworksBox.maxZ - originalVec.vector.getZ());
|
||||
@@ -658,7 +646,7 @@ public class PredictionEngine {
|
||||
//
|
||||
// Or the player is switching in and out of controlling a vehicle, in which friction messes it up
|
||||
//
|
||||
if (player.uncertaintyHandler.lastVehicleSwitch.hasOccurredSince(0) || player.uncertaintyHandler.lastHardCollidingLerpingEntity.hasOccurredSince(3) || (player.getClientVersion().isNewerThanOrEquals(V_1_13) && vector.vector.getY() > 0 && vector.isZeroPointZeroThree() && !isEmpty(player, getBoundingBoxFromPosAndSize(player, player.lastX, vector.vector.getY() + player.lastY + 0.6, player.lastZ, 0.6f, 1.26f)))) {
|
||||
if (player.uncertaintyHandler.lastVehicleSwitch.hasOccurredSince(0) || player.uncertaintyHandler.lastHardCollidingLerpingEntity.hasOccurredSince(3) || (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_13) && vector.vector.getY() > 0 && vector.isZeroPointZeroThree() && !Collisions.isEmpty(player, GetBoundingBox.getBoundingBoxFromPosAndSize(player, player.lastX, vector.vector.getY() + player.lastY + 0.6, player.lastZ, 0.6f, 1.26f)))) {
|
||||
box.expandToAbsoluteCoordinates(0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -670,9 +658,9 @@ public class PredictionEngine {
|
||||
if (player.wasTouchingWater) trueFriction = 0.96;
|
||||
|
||||
double maxY = Math.max(box.maxY, box.maxY + ((box.maxY - player.gravity) * 0.91));
|
||||
double minY = min(box.minY, box.minY + ((box.minY - player.gravity) * 0.91));
|
||||
double minX = min(box.minX, box.minX + (-player.speed * trueFriction));
|
||||
double minZ = min(box.minZ, box.minZ + (-player.speed * trueFriction));
|
||||
double minY = Math.min(box.minY, box.minY + ((box.minY - player.gravity) * 0.91));
|
||||
double minX = Math.min(box.minX, box.minX + (-player.speed * trueFriction));
|
||||
double minZ = Math.min(box.minZ, box.minZ + (-player.speed * trueFriction));
|
||||
double maxX = Math.max(box.maxX, box.maxX + (player.speed * trueFriction));
|
||||
double maxZ = Math.max(box.maxZ, box.maxZ + (player.speed * trueFriction));
|
||||
|
||||
@@ -688,15 +676,15 @@ public class PredictionEngine {
|
||||
maxVector = box.max();
|
||||
|
||||
if (pistonX != 0) {
|
||||
minVector.setX(min(minVector.getX() - pistonX, pistonX));
|
||||
minVector.setX(Math.min(minVector.getX() - pistonX, pistonX));
|
||||
maxVector.setX(Math.max(maxVector.getX() + pistonX, pistonX));
|
||||
}
|
||||
if (pistonY != 0) {
|
||||
minVector.setY(min(minVector.getY() - pistonY, pistonY));
|
||||
minVector.setY(Math.min(minVector.getY() - pistonY, pistonY));
|
||||
maxVector.setY(Math.max(maxVector.getY() + pistonY, pistonY));
|
||||
}
|
||||
if (pistonZ != 0) {
|
||||
minVector.setZ(min(minVector.getZ() - pistonZ, pistonZ));
|
||||
minVector.setZ(Math.min(minVector.getZ() - pistonZ, pistonZ));
|
||||
maxVector.setZ(Math.max(maxVector.getZ() + pistonZ, pistonZ));
|
||||
}
|
||||
return VectorUtils.cutBoxToVector(targetVec, minVector, maxVector);
|
||||
@@ -712,36 +700,7 @@ public class PredictionEngine {
|
||||
// Optimization - Also cuts down scenarios by 2/3
|
||||
// For some reason the player sprints while swimming no matter what
|
||||
// Probably as a way to tell the server it is swimming
|
||||
int forwardMin = player.isSprinting && !player.isSwimming ? 1 : -1;
|
||||
int forwardMax = 1;
|
||||
int strafeMin = -1;
|
||||
int strafeMax = 1;
|
||||
|
||||
// Calculate inputs by the players known inputs on 1.21.2+
|
||||
if (player.supportsEndTick()) {
|
||||
forwardMin = forwardMax = strafeMin = strafeMax = 0;
|
||||
|
||||
final KnownInput knownInput = player.packetStateData.knownInput;
|
||||
if (knownInput.forward()) {
|
||||
forwardMax++;
|
||||
forwardMin++;
|
||||
}
|
||||
|
||||
if (knownInput.backward() && (!player.isSprinting || player.isSwimming)) {
|
||||
forwardMax--;
|
||||
forwardMin--;
|
||||
}
|
||||
|
||||
if (knownInput.left()) {
|
||||
strafeMax++;
|
||||
strafeMin++;
|
||||
}
|
||||
|
||||
if (knownInput.right()) {
|
||||
strafeMax--;
|
||||
strafeMin--;
|
||||
}
|
||||
}
|
||||
int zMin = player.isSprinting && !player.isSwimming ? 1 : -1;
|
||||
|
||||
for (int loopSlowed = 0; loopSlowed <= 1; loopSlowed++) {
|
||||
// Loop twice for the using item status if the player is using a trident
|
||||
@@ -753,11 +712,9 @@ public class PredictionEngine {
|
||||
for (VectorData possibleLastTickOutput : possibleVectors) {
|
||||
// Only do this when there is tick skipping
|
||||
if (loopSlowed == 1 && !possibleLastTickOutput.isZeroPointZeroThree()) continue;
|
||||
for (int strafe = strafeMin; strafe <= strafeMax; strafe++) {
|
||||
for (int forward = forwardMin; forward <= forwardMax; forward++) {
|
||||
VectorData result = new VectorData(possibleLastTickOutput.vector.clone()
|
||||
.add(getMovementResultFromInput(player, transformInputsToVector(player, newVector3D(strafe, 0, forward)), speed, player.xRot)),
|
||||
possibleLastTickOutput, VectorData.VectorType.InputResult);
|
||||
for (int x = -1; x <= 1; x++) {
|
||||
for (int z = zMin; z <= 1; z++) {
|
||||
VectorData result = new VectorData(possibleLastTickOutput.vector.clone().add(getMovementResultFromInput(player, transformInputsToVector(player, new Vector(x, 0, z)), speed, player.xRot)), possibleLastTickOutput, VectorData.VectorType.InputResult);
|
||||
result = result.returnNewModified(result.vector.clone().multiply(player.stuckSpeedMultiplier), VectorData.VectorType.StuckMultiplier);
|
||||
result = result.returnNewModified(handleOnClimbable(result.vector.clone(), player), VectorData.VectorType.Climbable);
|
||||
// Signal that we need to flip sneaking bounding box
|
||||
@@ -824,21 +781,21 @@ public class PredictionEngine {
|
||||
|
||||
// This is just the vanilla equation, which accepts invalid inputs greater than 1
|
||||
// We need it because of collision support when a player is using speed
|
||||
public Vector3D getMovementResultFromInput(GrimPlayer player, Vector3D inputVector, float f, float f2) {
|
||||
public Vector getMovementResultFromInput(GrimPlayer player, Vector inputVector, float f, float f2) {
|
||||
float f3 = player.trigHandler.sin(f2 * 0.017453292f);
|
||||
float f4 = player.trigHandler.cos(f2 * 0.017453292f);
|
||||
|
||||
double xResult = inputVector.getX() * f4 - inputVector.getZ() * f3;
|
||||
double zResult = inputVector.getZ() * f4 + inputVector.getX() * f3;
|
||||
|
||||
return newVector3D(xResult * f, 0, zResult * f);
|
||||
return new Vector(xResult * f, 0, zResult * f);
|
||||
}
|
||||
|
||||
public Vector3D handleOnClimbable(Vector3D vector, GrimPlayer player) {
|
||||
public Vector handleOnClimbable(Vector vector, GrimPlayer player) {
|
||||
return vector;
|
||||
}
|
||||
|
||||
public void doJump(GrimPlayer player, Vector3D vector) {
|
||||
public void doJump(GrimPlayer player, Vector vector) {
|
||||
if (!player.lastOnGround || player.onGround)
|
||||
return;
|
||||
|
||||
|
||||
+16
-21
@@ -3,33 +3,28 @@ package ac.grim.grimac.predictionengine.predictions;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.data.VectorData;
|
||||
import ac.grim.grimac.utils.nmsutil.ReachUtils;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import static com.github.retrooper.packetevents.protocol.attribute.Attributes.GENERIC_GRAVITY;
|
||||
import static com.github.retrooper.packetevents.protocol.player.ClientVersion.V_1_18_2;
|
||||
import static com.github.retrooper.packetevents.protocol.player.ClientVersion.V_1_20_5;
|
||||
import static java.lang.Math.*;
|
||||
|
||||
public class PredictionEngineElytra extends PredictionEngine {
|
||||
// Inputs have no effect on movement
|
||||
@Override
|
||||
public List<VectorData> applyInputsToVelocityPossibilities(GrimPlayer player, Set<VectorData> possibleVectors, float speed) {
|
||||
List<VectorData> results = new ArrayList<>();
|
||||
Vector3D currentLook = ReachUtils.getLook(player, player.xRot, player.yRot);
|
||||
Vector currentLook = ReachUtils.getLook(player, player.xRot, player.yRot);
|
||||
|
||||
for (VectorData data : possibleVectors) {
|
||||
Vector3D elytraResult = getElytraMovement(player, data.vector.clone(), currentLook).multiply(player.stuckSpeedMultiplier).multiply(newVector3D(0.99F, 0.98F, 0.99F));
|
||||
Vector elytraResult = getElytraMovement(player, data.vector.clone(), currentLook).multiply(player.stuckSpeedMultiplier).multiply(new Vector(0.99F, 0.98F, 0.99F));
|
||||
results.add(data.returnNewModified(elytraResult, VectorData.VectorType.InputResult));
|
||||
|
||||
// We must bruteforce Optifine ShitMath
|
||||
player.trigHandler.toggleShitMath();
|
||||
elytraResult = getElytraMovement(player, data.vector.clone(), ReachUtils.getLook(player, player.xRot, player.yRot)).multiply(player.stuckSpeedMultiplier).multiply(newVector3D(0.99F, 0.98F, 0.99F));
|
||||
elytraResult = getElytraMovement(player, data.vector.clone(), ReachUtils.getLook(player, player.xRot, player.yRot)).multiply(player.stuckSpeedMultiplier).multiply(new Vector(0.99F, 0.98F, 0.99F));
|
||||
player.trigHandler.toggleShitMath();
|
||||
results.add(data.returnNewModified(elytraResult, VectorData.VectorType.InputResult));
|
||||
}
|
||||
@@ -37,42 +32,42 @@ public class PredictionEngineElytra extends PredictionEngine {
|
||||
return results;
|
||||
}
|
||||
|
||||
public static Vector3D getElytraMovement(GrimPlayer player, Vector3D vector, Vector3D lookVector) {
|
||||
public static Vector getElytraMovement(GrimPlayer player, Vector vector, Vector lookVector) {
|
||||
float yRotRadians = player.yRot * 0.017453292F;
|
||||
double horizontalSqrt = sqrt(lookVector.getX() * lookVector.getX() + lookVector.getZ() * lookVector.getZ());
|
||||
double horizontalSqrt = Math.sqrt(lookVector.getX() * lookVector.getX() + lookVector.getZ() * lookVector.getZ());
|
||||
double horizontalLength = vector.clone().setY(0).length();
|
||||
double length = lookVector.length();
|
||||
|
||||
// Mojang changed from using their math to using regular java math in 1.18.2 elytra movement
|
||||
double vertCosRotation = player.getClientVersion().isNewerThanOrEquals(V_1_18_2) ? cos(yRotRadians) : player.trigHandler.cos(yRotRadians);
|
||||
vertCosRotation = (float) (vertCosRotation * vertCosRotation * min(1.0D, length / 0.4D));
|
||||
double vertCosRotation = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_18_2) ? Math.cos(yRotRadians) : player.trigHandler.cos(yRotRadians);
|
||||
vertCosRotation = (float) (vertCosRotation * vertCosRotation * Math.min(1.0D, length / 0.4D));
|
||||
|
||||
// So we actually use the player's actual movement to get the gravity/slow falling status
|
||||
// However, this is wrong with elytra movement because players can control vertical movement after gravity is calculated
|
||||
// Yeah, slow falling needs a refactor in grim.
|
||||
double recalculatedGravity = player.compensatedEntities.getSelf().getAttributeValue(GENERIC_GRAVITY);
|
||||
double recalculatedGravity = player.compensatedEntities.getSelf().getAttributeValue(Attributes.GENERIC_GRAVITY);
|
||||
if (player.clientVelocity.getY() <= 0 && player.compensatedEntities.getSlowFallingAmplifier().isPresent()) {
|
||||
recalculatedGravity = player.getClientVersion().isOlderThan(V_1_20_5) ? 0.01 : min(recalculatedGravity, 0.01);
|
||||
recalculatedGravity = player.getClientVersion().isOlderThan(ClientVersion.V_1_20_5) ? 0.01 : Math.min(recalculatedGravity, 0.01);
|
||||
}
|
||||
|
||||
vector.add(newVector3D(0.0D, recalculatedGravity * (-1.0D + vertCosRotation * 0.75D), 0.0D));
|
||||
vector.add(new Vector(0.0D, recalculatedGravity * (-1.0D + vertCosRotation * 0.75D), 0.0D));
|
||||
double d5;
|
||||
|
||||
// Handle slowing the player down when falling
|
||||
if (vector.getY() < 0.0D && horizontalSqrt > 0.0D) {
|
||||
d5 = vector.getY() * -0.1D * vertCosRotation;
|
||||
vector.add(newVector3D(lookVector.getX() * d5 / horizontalSqrt, d5, lookVector.getZ() * d5 / horizontalSqrt));
|
||||
vector.add(new Vector(lookVector.getX() * d5 / horizontalSqrt, d5, lookVector.getZ() * d5 / horizontalSqrt));
|
||||
}
|
||||
|
||||
// Handle accelerating the player when they are looking down
|
||||
if (yRotRadians < 0.0F && horizontalSqrt > 0.0D) {
|
||||
d5 = horizontalLength * (double) (-player.trigHandler.sin(yRotRadians)) * 0.04D;
|
||||
vector.add(newVector3D(-lookVector.getX() * d5 / horizontalSqrt, d5 * 3.2D, -lookVector.getZ() * d5 / horizontalSqrt));
|
||||
vector.add(new Vector(-lookVector.getX() * d5 / horizontalSqrt, d5 * 3.2D, -lookVector.getZ() * d5 / horizontalSqrt));
|
||||
}
|
||||
|
||||
// Handle accelerating the player sideways
|
||||
if (horizontalSqrt > 0) {
|
||||
vector.add(newVector3D((lookVector.getX() / horizontalSqrt * horizontalLength - vector.getX()) * 0.1D, 0.0D, (lookVector.getZ() / horizontalSqrt * horizontalLength - vector.getZ()) * 0.1D));
|
||||
vector.add(new Vector((lookVector.getX() / horizontalSqrt * horizontalLength - vector.getX()) * 0.1D, 0.0D, (lookVector.getZ() / horizontalSqrt * horizontalLength - vector.getZ()) * 0.1D));
|
||||
}
|
||||
|
||||
return vector;
|
||||
|
||||
@@ -3,13 +3,11 @@ package ac.grim.grimac.predictionengine.predictions;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.data.VectorData;
|
||||
import ac.grim.grimac.utils.math.GrimMath;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
public class PredictionEngineLava extends PredictionEngine {
|
||||
@Override
|
||||
public void addJumpsToPossibilities(GrimPlayer player, Set<VectorData> existingVelocities) {
|
||||
@@ -18,11 +16,11 @@ public class PredictionEngineLava extends PredictionEngine {
|
||||
double extraVelFromVertTickSkipUpwards = GrimMath.clamp(player.actualMovement.getY(), vector.vector.clone().getY(), vector.vector.clone().getY() + 0.05f);
|
||||
existingVelocities.add(new VectorData(vector.vector.clone().setY(extraVelFromVertTickSkipUpwards), vector, VectorData.VectorType.Jump));
|
||||
} else {
|
||||
existingVelocities.add(new VectorData(vector.vector.clone().add(newVector3D(0, 0.04f, 0)), vector, VectorData.VectorType.Jump));
|
||||
existingVelocities.add(new VectorData(vector.vector.clone().add(new Vector(0, 0.04f, 0)), vector, VectorData.VectorType.Jump));
|
||||
}
|
||||
|
||||
if (player.slightlyTouchingLava && player.lastOnGround && !player.onGround) {
|
||||
Vector3D withJump = vector.vector.clone();
|
||||
Vector withJump = vector.vector.clone();
|
||||
super.doJump(player, withJump);
|
||||
existingVelocities.add(new VectorData(withJump, vector, VectorData.VectorType.Jump));
|
||||
}
|
||||
|
||||
+12
-21
@@ -3,28 +3,23 @@ package ac.grim.grimac.predictionengine.predictions;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.VectorData;
|
||||
import ac.grim.grimac.utils.math.GrimMath;
|
||||
import ac.grim.grimac.utils.nmsutil.Collisions;
|
||||
import ac.grim.grimac.utils.nmsutil.JumpPower;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.potion.PotionTypes;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.Set;
|
||||
|
||||
import static ac.grim.grimac.utils.math.GrimMath.clamp;
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import static com.github.retrooper.packetevents.protocol.world.states.type.StateTypes.SCAFFOLDING;
|
||||
import static java.lang.Math.max;
|
||||
|
||||
public class PredictionEngineNormal extends PredictionEngine {
|
||||
|
||||
public static void staticVectorEndOfTick(GrimPlayer player, Vector3D vector) {
|
||||
public static void staticVectorEndOfTick(GrimPlayer player, Vector vector) {
|
||||
double adjustedY = vector.getY();
|
||||
final OptionalInt levitation = player.compensatedEntities.getPotionLevelForPlayer(PotionTypes.LEVITATION);
|
||||
if (levitation.isPresent()) {
|
||||
@@ -42,12 +37,8 @@ public class PredictionEngineNormal extends PredictionEngine {
|
||||
|
||||
@Override
|
||||
public void addJumpsToPossibilities(GrimPlayer player, Set<VectorData> existingVelocities) {
|
||||
if (player.supportsEndTick() && !player.packetStateData.knownInput.jump()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (VectorData vector : new HashSet<>(existingVelocities)) {
|
||||
Vector3D jump = vector.vector.clone();
|
||||
Vector jump = vector.vector.clone();
|
||||
|
||||
if (!player.isFlying) {
|
||||
// Negative jump boost does not allow the player to leave the ground
|
||||
@@ -61,9 +52,9 @@ public class PredictionEngineNormal extends PredictionEngine {
|
||||
|
||||
JumpPower.jumpFromGround(player, jump);
|
||||
} else {
|
||||
jump.add(newVector3D(0, player.flySpeed * 3, 0));
|
||||
jump.add(new Vector(0, player.flySpeed * 3, 0));
|
||||
if (!player.wasFlying) {
|
||||
Vector3D edgeCaseJump = jump.clone();
|
||||
Vector edgeCaseJump = jump.clone();
|
||||
JumpPower.jumpFromGround(player, edgeCaseJump);
|
||||
existingVelocities.add(vector.returnNewModified(edgeCaseJump, VectorData.VectorType.Jump));
|
||||
}
|
||||
@@ -91,7 +82,7 @@ public class PredictionEngineNormal extends PredictionEngine {
|
||||
if (player.lastWasClimbing == 0 && (player.pointThreeEstimator.isNearClimbable() || player.isClimbing) && (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14)
|
||||
|| !Collisions.isEmpty(player, player.boundingBox.copy().expand(
|
||||
player.clientVelocity.getX(), 0, player.clientVelocity.getZ()).expand(0.5, -SimpleCollisionBox.COLLISION_EPSILON, 0.5))) || walkingOnPowderSnow) {
|
||||
Vector3D ladderVelocity = player.clientVelocity.clone().setY(0.2);
|
||||
Vector ladderVelocity = player.clientVelocity.clone().setY(0.2);
|
||||
staticVectorEndOfTick(player, ladderVelocity);
|
||||
player.lastWasClimbing = ladderVelocity.getY();
|
||||
}
|
||||
@@ -102,17 +93,17 @@ public class PredictionEngineNormal extends PredictionEngine {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3D handleOnClimbable(Vector3D vector, GrimPlayer player) {
|
||||
public Vector handleOnClimbable(Vector vector, GrimPlayer player) {
|
||||
if (player.isClimbing) {
|
||||
// Reset fall distance when climbing
|
||||
player.fallDistance = 0;
|
||||
|
||||
vector.setX(clamp(vector.getX(), -0.15F, 0.15F));
|
||||
vector.setZ(clamp(vector.getZ(), -0.15F, 0.15F));
|
||||
vector.setY(max(vector.getY(), -0.15F));
|
||||
vector.setX(GrimMath.clamp(vector.getX(), -0.15F, 0.15F));
|
||||
vector.setZ(GrimMath.clamp(vector.getZ(), -0.15F, 0.15F));
|
||||
vector.setY(Math.max(vector.getY(), -0.15F));
|
||||
|
||||
// Yes, this uses shifting not crouching
|
||||
if (vector.getY() < 0.0 && !(player.compensatedWorld.getStateTypeAt(player.lastX, player.lastY, player.lastZ) == SCAFFOLDING) && player.isSneaking && !player.isFlying) {
|
||||
if (vector.getY() < 0.0 && !(player.compensatedWorld.getStateTypeAt(player.lastX, player.lastY, player.lastZ) == StateTypes.SCAFFOLDING) && player.isSneaking && !player.isFlying) {
|
||||
vector.setY(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-10
@@ -9,14 +9,11 @@ import ac.grim.grimac.utils.nmsutil.Collisions;
|
||||
import ac.grim.grimac.utils.nmsutil.FluidFallingAdjustedMovement;
|
||||
import ac.grim.grimac.utils.nmsutil.ReachUtils;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static ac.grim.grimac.utils.data.VectorData.VectorType.SwimmingSpace;
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
public class PredictionEngineWater extends PredictionEngine {
|
||||
boolean isFalling;
|
||||
double playerGravity;
|
||||
@@ -24,9 +21,9 @@ public class PredictionEngineWater extends PredictionEngine {
|
||||
float swimmingFriction;
|
||||
double lastY;
|
||||
|
||||
public static void staticVectorEndOfTick(GrimPlayer player, Vector3D vector, float swimmingFriction, double playerGravity, boolean isFalling) {
|
||||
vector.multiply(newVector3D(swimmingFriction, 0.8F, swimmingFriction));
|
||||
Vector3D fluidVector = FluidFallingAdjustedMovement.getFluidFallingAdjustedMovement(player, playerGravity, isFalling, vector);
|
||||
public static void staticVectorEndOfTick(GrimPlayer player, Vector vector, float swimmingFriction, double playerGravity, boolean isFalling) {
|
||||
vector.multiply(new Vector(swimmingFriction, 0.8F, swimmingFriction));
|
||||
Vector fluidVector = FluidFallingAdjustedMovement.getFluidFallingAdjustedMovement(player, playerGravity, isFalling, vector);
|
||||
vector.setX(fluidVector.getX());
|
||||
vector.setY(fluidVector.getY());
|
||||
vector.setZ(fluidVector.getZ());
|
||||
@@ -50,7 +47,7 @@ public class PredictionEngineWater extends PredictionEngine {
|
||||
double scalar = lookYAmount < -0.2 ? 0.085 : 0.06;
|
||||
|
||||
// The player can always press jump and activate this
|
||||
swimmingVelocities.add(vector.returnNewModified(newVector3D(vector.vector.getX(), vector.vector.getY() + ((lookYAmount - vector.vector.getY()) * scalar), vector.vector.getZ()), SwimmingSpace));
|
||||
swimmingVelocities.add(vector.returnNewModified(new Vector(vector.vector.getX(), vector.vector.getY() + ((lookYAmount - vector.vector.getY()) * scalar), vector.vector.getZ()), VectorData.VectorType.SwimmingSpace));
|
||||
|
||||
// This scenario will occur if the player does not press jump and the other conditions are met
|
||||
// Theoretically we should check this BEFORE allowing no look, but there isn't a cheat that takes advantage of this yet
|
||||
@@ -83,11 +80,11 @@ public class PredictionEngineWater extends PredictionEngine {
|
||||
double extraVelFromVertTickSkipUpwards = GrimMath.clamp(player.actualMovement.getY(), vector.vector.clone().getY(), vector.vector.clone().getY() + 0.05f);
|
||||
existingVelocities.add(new VectorData(vector.vector.clone().setY(extraVelFromVertTickSkipUpwards), vector, VectorData.VectorType.Jump));
|
||||
} else {
|
||||
existingVelocities.add(new VectorData(vector.vector.clone().add(newVector3D(0, 0.04f, 0)), vector, VectorData.VectorType.Jump));
|
||||
existingVelocities.add(new VectorData(vector.vector.clone().add(new Vector(0, 0.04f, 0)), vector, VectorData.VectorType.Jump));
|
||||
}
|
||||
|
||||
if (player.slightlyTouchingWater && player.lastOnGround && !player.onGround) {
|
||||
Vector3D withJump = vector.vector.clone();
|
||||
Vector withJump = vector.vector.clone();
|
||||
super.doJump(player, withJump);
|
||||
existingVelocities.add(new VectorData(withJump, vector, VectorData.VectorType.Jump));
|
||||
}
|
||||
|
||||
+9
-12
@@ -2,15 +2,11 @@ package ac.grim.grimac.predictionengine.predictions;
|
||||
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.data.VectorData;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import static java.lang.Math.sqrt;
|
||||
|
||||
public class PredictionEngineWaterLegacy extends PredictionEngine {
|
||||
double playerGravity;
|
||||
float swimmingSpeed;
|
||||
@@ -27,11 +23,11 @@ public class PredictionEngineWaterLegacy extends PredictionEngine {
|
||||
|
||||
// This is just the vanilla equation for legacy water movement
|
||||
@Override
|
||||
public Vector3D getMovementResultFromInput(GrimPlayer player, Vector3D inputVector, float f, float f2) {
|
||||
public Vector getMovementResultFromInput(GrimPlayer player, Vector inputVector, float f, float f2) {
|
||||
float lengthSquared = (float) inputVector.lengthSquared();
|
||||
|
||||
if (lengthSquared >= 1.0E-4F) {
|
||||
lengthSquared = (float) sqrt(lengthSquared);
|
||||
lengthSquared = (float) Math.sqrt(lengthSquared);
|
||||
|
||||
if (lengthSquared < 1.0F) {
|
||||
lengthSquared = 1.0F;
|
||||
@@ -42,20 +38,21 @@ public class PredictionEngineWaterLegacy extends PredictionEngine {
|
||||
float sinResult = player.trigHandler.sin(player.xRot * 0.017453292F);
|
||||
float cosResult = player.trigHandler.cos(player.xRot * 0.017453292F);
|
||||
|
||||
return newVector3D(inputVector.getX() * cosResult - inputVector.getZ() * sinResult, inputVector.getY(), inputVector.getZ() * cosResult + inputVector.getX() * sinResult);
|
||||
return new Vector(inputVector.getX() * cosResult - inputVector.getZ() * sinResult,
|
||||
inputVector.getY(), inputVector.getZ() * cosResult + inputVector.getX() * sinResult);
|
||||
}
|
||||
|
||||
return newVector3D();
|
||||
return new Vector();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addJumpsToPossibilities(GrimPlayer player, Set<VectorData> existingVelocities) {
|
||||
for (VectorData vector : new HashSet<>(existingVelocities)) {
|
||||
existingVelocities.add(new VectorData(vector.vector.clone().add(newVector3D(0, 0.04f, 0)), vector, VectorData.VectorType.Jump));
|
||||
existingVelocities.add(new VectorData(vector.vector.clone().add(new Vector(0, 0.04f, 0)), vector, VectorData.VectorType.Jump));
|
||||
|
||||
if (player.skippedTickInActualMovement) {
|
||||
existingVelocities.add(new VectorData(vector.vector.clone().add(newVector3D(0, 0.02f, 0)), vector, VectorData.VectorType.Jump));
|
||||
existingVelocities.add(new VectorData(vector.vector.clone().add(new Vector(0, 0.02f, 0)), vector, VectorData.VectorType.Jump));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,7 +62,7 @@ public class PredictionEngineWaterLegacy extends PredictionEngine {
|
||||
super.endOfTick(player, playerGravity);
|
||||
|
||||
for (VectorData vector : player.getPossibleVelocitiesMinusKnockback()) {
|
||||
vector.vector.multiply(newVector3D(swimmingFriction, 0.8F, swimmingFriction));
|
||||
vector.vector.multiply(new Vector(swimmingFriction, 0.8F, swimmingFriction));
|
||||
|
||||
// Gravity
|
||||
vector.vector.setY(vector.vector.getY() - 0.02D);
|
||||
|
||||
+6
-9
@@ -13,15 +13,12 @@ import ac.grim.grimac.utils.nmsutil.GetBoundingBox;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import static java.lang.Math.PI;
|
||||
|
||||
public class BoatPredictionEngine extends PredictionEngine {
|
||||
public BoatPredictionEngine(GrimPlayer player) {
|
||||
player.uncertaintyHandler.collidingEntities.add(0); // We don't do collisions like living entities
|
||||
@@ -150,7 +147,7 @@ public class BoatPredictionEngine extends PredictionEngine {
|
||||
// so if a player tries to move in both directions, a packet will
|
||||
// show that the player is staying, but the boat will move anyway
|
||||
if (player.vehicleData.vehicleForward == 0) {
|
||||
Vector3D vector = data.vector.clone();
|
||||
Vector vector = data.vector.clone();
|
||||
controlBoat(player, vector, true);
|
||||
vector.multiply(player.stuckSpeedMultiplier);
|
||||
vectors.add(data.returnNewModified(vector, VectorData.VectorType.InputResult));
|
||||
@@ -187,7 +184,7 @@ public class BoatPredictionEngine extends PredictionEngine {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void floatBoat(GrimPlayer player, Vector3D vector) {
|
||||
private void floatBoat(GrimPlayer player, Vector vector) {
|
||||
double d1 = player.hasGravity ? -0.04f : 0;
|
||||
double d2 = 0.0D;
|
||||
float invFriction = 0.05F;
|
||||
@@ -197,7 +194,7 @@ public class BoatPredictionEngine extends PredictionEngine {
|
||||
|
||||
player.lastY = getWaterLevelAbove(player) - 0.5625F + 0.101D;
|
||||
player.boundingBox = GetBoundingBox.getCollisionBoxForPlayer(player, player.lastX, player.lastY, player.lastZ);
|
||||
player.actualMovement = newVector3D(player.x - player.lastX, player.y - player.lastY, player.z - player.lastZ);
|
||||
player.actualMovement = new Vector(player.x - player.lastX, player.y - player.lastY, player.z - player.lastZ);
|
||||
vector.setY(0);
|
||||
|
||||
player.vehicleData.lastYd = 0.0D;
|
||||
@@ -263,7 +260,7 @@ public class BoatPredictionEngine extends PredictionEngine {
|
||||
return (float) (l + 1);
|
||||
}
|
||||
|
||||
private void controlBoat(GrimPlayer player, Vector3D vector, boolean intermediate) {
|
||||
private void controlBoat(GrimPlayer player, Vector vector, boolean intermediate) {
|
||||
float f = 0.0F;
|
||||
if (player.vehicleData.vehicleHorizontal != 0 && (!intermediate && player.vehicleData.vehicleForward == 0)) {
|
||||
f += 0.005F;
|
||||
@@ -278,6 +275,6 @@ public class BoatPredictionEngine extends PredictionEngine {
|
||||
f -= 0.005F;
|
||||
}
|
||||
|
||||
vector.add(newVector3D(player.trigHandler.sin(-player.xRot * ((float) PI / 180F)) * f, 0, (double) (player.trigHandler.cos(player.xRot * ((float) PI / 180F)) * f)));
|
||||
vector.add(new Vector(player.trigHandler.sin(-player.xRot * ((float) Math.PI / 180F)) * f, 0, (double) (player.trigHandler.cos(player.xRot * ((float) Math.PI / 180F)) * f)));
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -3,16 +3,16 @@ package ac.grim.grimac.predictionengine.predictions.rideable;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.predictionengine.predictions.PredictionEngineLava;
|
||||
import ac.grim.grimac.utils.data.VectorData;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PredictionEngineRideableLava extends PredictionEngineLava {
|
||||
|
||||
Vector3D movementVector;
|
||||
Vector movementVector;
|
||||
|
||||
public PredictionEngineRideableLava(Vector3D movementVector) {
|
||||
public PredictionEngineRideableLava(Vector movementVector) {
|
||||
this.movementVector = movementVector;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -3,16 +3,16 @@ package ac.grim.grimac.predictionengine.predictions.rideable;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.predictionengine.predictions.PredictionEngineNormal;
|
||||
import ac.grim.grimac.utils.data.VectorData;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PredictionEngineRideableNormal extends PredictionEngineNormal {
|
||||
|
||||
Vector3D movementVector;
|
||||
Vector movementVector;
|
||||
|
||||
public PredictionEngineRideableNormal(Vector3D movementVector) {
|
||||
public PredictionEngineRideableNormal(Vector movementVector) {
|
||||
this.movementVector = movementVector;
|
||||
}
|
||||
|
||||
|
||||
+3
-5
@@ -8,15 +8,13 @@ import ac.grim.grimac.utils.data.packetentity.PacketEntityHorse;
|
||||
import ac.grim.grimac.utils.nmsutil.JumpPower;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.potion.PotionTypes;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.Set;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
public class PredictionEngineRideableUtils {
|
||||
public static Set<VectorData> handleJumps(GrimPlayer player, Set<VectorData> possibleVectors) {
|
||||
if (!(player.compensatedEntities.getSelf().getRiding() instanceof PacketEntityHorse horse)) return possibleVectors;
|
||||
@@ -57,7 +55,7 @@ public class PredictionEngineRideableUtils {
|
||||
for (VectorData vectorData : possibleVectors) {
|
||||
vectorData.vector.setY(d1);
|
||||
if (f1 > 0.0F) {
|
||||
vectorData.vector.add(newVector3D(-0.4F * f2 * player.vehicleData.horseJump, 0.0D, 0.4F * f3 * player.vehicleData.horseJump));
|
||||
vectorData.vector.add(new Vector(-0.4F * f2 * player.vehicleData.horseJump, 0.0D, 0.4F * f3 * player.vehicleData.horseJump));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +71,7 @@ public class PredictionEngineRideableUtils {
|
||||
return possibleVectors;
|
||||
}
|
||||
|
||||
public static List<VectorData> applyInputsToVelocityPossibilities(Vector3D movementVector, GrimPlayer player, Set<VectorData> possibleVectors, float speed) {
|
||||
public static List<VectorData> applyInputsToVelocityPossibilities(Vector movementVector, GrimPlayer player, Set<VectorData> possibleVectors, float speed) {
|
||||
List<VectorData> returnVectors = new ArrayList<>();
|
||||
|
||||
for (VectorData possibleLastTickOutput : possibleVectors) {
|
||||
|
||||
+3
-3
@@ -3,16 +3,16 @@ package ac.grim.grimac.predictionengine.predictions.rideable;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.predictionengine.predictions.PredictionEngineWater;
|
||||
import ac.grim.grimac.utils.data.VectorData;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PredictionEngineRideableWater extends PredictionEngineWater {
|
||||
|
||||
Vector3D movementVector;
|
||||
Vector movementVector;
|
||||
|
||||
public PredictionEngineRideableWater(Vector3D movementVector) {
|
||||
public PredictionEngineRideableWater(Vector movementVector) {
|
||||
this.movementVector = movementVector;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -3,15 +3,15 @@ package ac.grim.grimac.predictionengine.predictions.rideable;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.predictionengine.predictions.PredictionEngineWaterLegacy;
|
||||
import ac.grim.grimac.utils.data.VectorData;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PredictionEngineRideableWaterLegacy extends PredictionEngineWaterLegacy {
|
||||
Vector3D movementVector;
|
||||
Vector movementVector;
|
||||
|
||||
public PredictionEngineRideableWaterLegacy(Vector3D movementVector) {
|
||||
public PredictionEngineRideableWaterLegacy(Vector movementVector) {
|
||||
this.movementVector = movementVector;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
package ac.grim.grimac.utils.anticheat.update;
|
||||
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.protocol.player.DiggingAction;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging;
|
||||
import lombok.Getter;
|
||||
|
||||
public class BlockBreak {
|
||||
public final Vector3i position;
|
||||
public final BlockFace face;
|
||||
public final DiggingAction action;
|
||||
@Getter
|
||||
private boolean cancelled;
|
||||
|
||||
public final WrappedBlockState block;
|
||||
|
||||
public BlockBreak(WrapperPlayClientPlayerDigging packet, GrimPlayer player) {
|
||||
this(packet.getBlockPosition(), packet.getBlockFace(), packet.getAction(), player.compensatedWorld.getWrappedBlockStateAt(packet.getBlockPosition()));
|
||||
}
|
||||
|
||||
public BlockBreak(Vector3i position, BlockFace face, DiggingAction action, WrappedBlockState block) {
|
||||
this.position = position;
|
||||
this.face = face;
|
||||
this.action = action;
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.cancelled = true;
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ import ac.grim.grimac.utils.math.GrimMath;
|
||||
import ac.grim.grimac.utils.nmsutil.BoundingBoxSize;
|
||||
import ac.grim.grimac.utils.nmsutil.GetBoundingBox;
|
||||
import ac.grim.grimac.utils.nmsutil.Materials;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import ac.grim.grimac.utils.nmsutil.ReachUtils;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
@@ -35,23 +35,18 @@ import com.github.retrooper.packetevents.util.Vector3f;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static ac.grim.grimac.utils.nmsutil.ReachUtils.calculateIntercept;
|
||||
import static ac.grim.grimac.utils.nmsutil.ReachUtils.getLook;
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import static com.github.retrooper.packetevents.protocol.attribute.Attributes.PLAYER_BLOCK_INTERACTION_RANGE;
|
||||
|
||||
public class BlockPlace {
|
||||
protected static final BlockFace[] UPDATE_SHAPE_ORDER = new BlockFace[]{BlockFace.WEST, BlockFace.EAST, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.DOWN, BlockFace.UP};
|
||||
private static final BlockFace[] BY_2D = new BlockFace[]{BlockFace.SOUTH, BlockFace.WEST, BlockFace.NORTH, BlockFace.EAST};
|
||||
static final BlockFace[] BY_3D = new BlockFace[]{BlockFace.DOWN, BlockFace.UP, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.WEST, BlockFace.EAST};
|
||||
@Setter
|
||||
public Vector3i blockPosition;
|
||||
Vector3i blockPosition;
|
||||
@Getter
|
||||
InteractionHand hand;
|
||||
@Getter
|
||||
@@ -666,18 +661,18 @@ public class BlockPlace {
|
||||
// You also have the desync caused by eye height as apparently tracking the player's ticks wasn't important to you
|
||||
// No mojang, you really do need to track client ticks to get their accurate eye height.
|
||||
// another damn desync added... maybe next decade it will get fixed and double the amount of issues.
|
||||
public Vector3D getClickedLocation() {
|
||||
public Vector getClickedLocation() {
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(getPlacedAgainstBlockLocation());
|
||||
Vector3D look = getLook(player, player.xRot, player.yRot);
|
||||
Vector look = ReachUtils.getLook(player, player.xRot, player.yRot);
|
||||
|
||||
final double distance = player.compensatedEntities.getSelf().getAttributeValue(PLAYER_BLOCK_INTERACTION_RANGE) + 3;
|
||||
Vector3D eyePos = newVector3D(player.x, player.y + player.getEyeHeight(), player.z);
|
||||
Vector3D endReachPos = eyePos.clone().add(newVector3D(look.getX() * distance, look.getY() * distance, look.getZ() * distance));
|
||||
Vector3D intercept = calculateIntercept(box, eyePos, endReachPos).first();
|
||||
final double distance = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE) + 3;
|
||||
Vector eyePos = new Vector(player.x, player.y + player.getEyeHeight(), player.z);
|
||||
Vector endReachPos = eyePos.clone().add(new Vector(look.getX() * distance, look.getY() * distance, look.getZ() * distance));
|
||||
Vector intercept = ReachUtils.calculateIntercept(box, eyePos, endReachPos).first();
|
||||
|
||||
// Bring this back to relative to the block
|
||||
// The player didn't even click the block... (we should force resync BEFORE we get here!)
|
||||
if (intercept == null) return newVector3D();
|
||||
if (intercept == null) return new Vector();
|
||||
|
||||
intercept.setX(intercept.getX() - box.minX);
|
||||
intercept.setY(intercept.getY() - box.minY);
|
||||
|
||||
@@ -21,13 +21,11 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateValue;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
public enum BlockPlaceResult {
|
||||
|
||||
// If the block only has directional data
|
||||
@@ -82,7 +80,7 @@ public enum BlockPlaceResult {
|
||||
}, ItemTypes.SNOW),
|
||||
|
||||
SLAB((player, place) -> {
|
||||
Vector3D clickedPos = place.getClickedLocation();
|
||||
Vector clickedPos = place.getClickedLocation();
|
||||
WrappedBlockState slabData = place.getMaterial().createBlockState(CompensatedWorld.blockVersion);
|
||||
WrappedBlockState existing = place.getExistingBlockData();
|
||||
|
||||
@@ -911,7 +909,7 @@ public enum BlockPlaceResult {
|
||||
WrappedBlockState ccwState = place.getDirectionalState(ccw);
|
||||
CollisionBox ccwBox = CollisionData.getData(ccwState.getType()).getMovementCollisionBox(player, player.getClientVersion(), ccwState);
|
||||
|
||||
Vector3D aboveCCWPos = place.getClickedLocation().add(newVector3D(ccw.getModX(), ccw.getModY(), ccw.getModZ())).add(newVector3D(0, 1, 0));
|
||||
Vector aboveCCWPos = place.getClickedLocation().add(new Vector(ccw.getModX(), ccw.getModY(), ccw.getModZ())).add(new Vector(0, 1, 0));
|
||||
WrappedBlockState aboveCCWState = player.compensatedWorld.getWrappedBlockStateAt(aboveCCWPos);
|
||||
CollisionBox aboveCCWBox = CollisionData.getData(aboveCCWState.getType()).getMovementCollisionBox(player, player.getClientVersion(), aboveCCWState);
|
||||
|
||||
@@ -919,7 +917,7 @@ public enum BlockPlaceResult {
|
||||
WrappedBlockState cwState = place.getDirectionalState(cw);
|
||||
CollisionBox cwBox = CollisionData.getData(cwState.getType()).getMovementCollisionBox(player, player.getClientVersion(), cwState);
|
||||
|
||||
Vector3D aboveCWPos = place.getClickedLocation().add(newVector3D(cw.getModX(), cw.getModY(), cw.getModZ())).add(newVector3D(0, 1, 0));
|
||||
Vector aboveCWPos = place.getClickedLocation().add(new Vector(cw.getModX(), cw.getModY(), cw.getModZ())).add(new Vector(0, 1, 0));
|
||||
WrappedBlockState aboveCWState = player.compensatedWorld.getWrappedBlockStateAt(aboveCWPos);
|
||||
CollisionBox aboveCWBox = CollisionData.getData(aboveCWState.getType()).getMovementCollisionBox(player, player.getClientVersion(), aboveCWState);
|
||||
|
||||
@@ -936,7 +934,7 @@ public enum BlockPlaceResult {
|
||||
if ((!isCWLower || isCCWLower) && i >= 0) {
|
||||
int j = playerFacing.getModX();
|
||||
int k = playerFacing.getModZ();
|
||||
Vector3D vec3 = place.getClickedLocation();
|
||||
Vector vec3 = place.getClickedLocation();
|
||||
double d0 = vec3.getX();
|
||||
double d1 = vec3.getY();
|
||||
hinge = (j >= 0 || d1 >= 0.5D) && (j <= 0 || d1 <= 0.5D) && (k >= 0 || d0 <= 0.5D) && (k <= 0 || d0 >= 0.5D) ? Hinge.LEFT : Hinge.RIGHT;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package ac.grim.grimac.utils.blockstate.helper;
|
||||
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class BlockFaceHelper {
|
||||
public static boolean isFaceVertical(BlockFace face) {
|
||||
@@ -57,7 +56,7 @@ public class BlockFaceHelper {
|
||||
};
|
||||
}
|
||||
|
||||
public Vector3D offset(Vector3D toOffset, BlockFace face) {
|
||||
public Vector offset(Vector toOffset, BlockFace face) {
|
||||
toOffset.setX(toOffset.getX() + face.getModX());
|
||||
toOffset.setY(toOffset.getY() + face.getModY());
|
||||
toOffset.setZ(toOffset.getZ() + face.getModZ());
|
||||
|
||||
@@ -680,7 +680,7 @@ public enum CollisionData {
|
||||
}, StateTypes.END_ROD, StateTypes.LIGHTNING_ROD),
|
||||
|
||||
CAULDRON((player, version, data, x, y, z) -> {
|
||||
if (version.isNewerThan(ClientVersion.V_1_13_2)) { // changed in 19w13a, 1.14 Snapshot
|
||||
if (version.isNewerThan(ClientVersion.getById(467))) { // changed in 19w13a, 1.14 Snapshot
|
||||
return new ComplexCollisionBox(15,
|
||||
new SimpleCollisionBox(0.0, 0.0, 0.0, 0.125, 1.0, 0.25, false),
|
||||
new SimpleCollisionBox(0.0, 0.0, 0.75, 0.125, 1.0, 1.0, false),
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package ac.grim.grimac.utils.collisions.datatypes;
|
||||
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class BoundingBox {
|
||||
|
||||
@@ -18,7 +15,7 @@ public class BoundingBox {
|
||||
this.maxZ = maxZ;
|
||||
}
|
||||
|
||||
public BoundingBox(Vector3D min, Vector3D max) {
|
||||
public BoundingBox(Vector min, Vector max) {
|
||||
this.minX = (float) Math.min(min.getX(), max.getX());
|
||||
this.minY = (float) Math.min(min.getY(), max.getY());
|
||||
this.minZ = (float) Math.min(min.getZ(), max.getZ());
|
||||
@@ -47,7 +44,7 @@ public class BoundingBox {
|
||||
return new BoundingBox(newMinX, newMinY, newMinZ, newMaxX, newMaxY, newMaxZ);
|
||||
}
|
||||
|
||||
public BoundingBox add(Vector3D vector) {
|
||||
public BoundingBox add(Vector vector) {
|
||||
float x = (float) vector.getX(), y = (float) vector.getY(), z = (float) vector.getZ();
|
||||
|
||||
float newMinX = minX + x;
|
||||
@@ -90,27 +87,27 @@ public class BoundingBox {
|
||||
return new BoundingBox(this.minX - minX, this.minY - minY, this.minZ - minZ, this.maxX - maxX, this.maxY - maxY, this.maxZ - maxZ);
|
||||
}
|
||||
|
||||
public boolean intersectsWithBox(Vector3D vector) {
|
||||
public boolean intersectsWithBox(Vector vector) {
|
||||
return (vector.getX() > this.minX && vector.getX() < this.maxX) && ((vector.getY() > this.minY && vector.getY() < this.maxY) && (vector.getZ() > this.minZ && vector.getZ() < this.maxZ));
|
||||
}
|
||||
|
||||
public Vector3D getMinimum() {
|
||||
return newVector3D(minX, minY, minZ);
|
||||
public Vector getMinimum() {
|
||||
return new Vector(minX, minY, minZ);
|
||||
}
|
||||
|
||||
public Vector3D getMaximum() {
|
||||
return newVector3D(maxX, maxY, maxZ);
|
||||
public Vector getMaximum() {
|
||||
return new Vector(maxX, maxY, maxZ);
|
||||
}
|
||||
|
||||
public boolean collides(Vector3D vector) {
|
||||
public boolean collides(Vector vector) {
|
||||
return (vector.getX() >= this.minX && vector.getX() <= this.maxX) && ((vector.getY() >= this.minY && vector.getY() <= this.maxY) && (vector.getZ() >= this.minZ && vector.getZ() <= this.maxZ));
|
||||
}
|
||||
|
||||
public boolean collidesHorizontally(Vector3D vector) {
|
||||
public boolean collidesHorizontally(Vector vector) {
|
||||
return (vector.getX() >= this.minX && vector.getX() <= this.maxX) && ((vector.getY() > this.minY && vector.getY() < this.maxY) && (vector.getZ() >= this.minZ && vector.getZ() <= this.maxZ));
|
||||
}
|
||||
|
||||
public boolean collidesVertically(Vector3D vector) {
|
||||
public boolean collidesVertically(Vector vector) {
|
||||
return (vector.getX() > this.minX && vector.getX() < this.maxX) && ((vector.getY() >= this.minY && vector.getY() <= this.maxY) && (vector.getZ() > this.minZ && vector.getZ() < this.maxZ));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package ac.grim.grimac.utils.collisions.datatypes;
|
||||
|
||||
import ac.grim.grimac.utils.nmsutil.Ray;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
@@ -9,12 +8,10 @@ import it.unimi.dsi.fastutil.doubles.AbstractDoubleList;
|
||||
import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
|
||||
import it.unimi.dsi.fastutil.doubles.DoubleList;
|
||||
import org.bukkit.Location;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
public class SimpleCollisionBox implements CollisionBox {
|
||||
|
||||
public static final double COLLISION_EPSILON = 1.0E-7;
|
||||
@@ -49,7 +46,7 @@ public class SimpleCollisionBox implements CollisionBox {
|
||||
isFullBlock = fullBlock;
|
||||
}
|
||||
|
||||
public SimpleCollisionBox(Vector3D min, Vector3D max) {
|
||||
public SimpleCollisionBox(Vector min, Vector max) {
|
||||
this(min.getX(), min.getY(), min.getZ(), max.getX(), max.getY(), max.getZ());
|
||||
}
|
||||
|
||||
@@ -88,10 +85,10 @@ public class SimpleCollisionBox implements CollisionBox {
|
||||
}
|
||||
|
||||
public SimpleCollisionBox(Location loc, double width, double height) {
|
||||
this(newVector3D(loc.getX(), loc.getY(), loc.getZ()), width, height);
|
||||
this(loc.toVector(), width, height);
|
||||
}
|
||||
|
||||
public SimpleCollisionBox(Vector3D vec, double width, double height) {
|
||||
public SimpleCollisionBox(Vector vec, double width, double height) {
|
||||
this(vec.getX(), vec.getY(), vec.getZ(), vec.getX(), vec.getY(), vec.getZ());
|
||||
|
||||
expand(width / 2, 0, width / 2);
|
||||
@@ -154,16 +151,16 @@ public class SimpleCollisionBox implements CollisionBox {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vector3D[] corners() {
|
||||
Vector3D[] vectors = new Vector3D[8];
|
||||
vectors[0] = newVector3D(minX, minY, minZ);
|
||||
vectors[1] = newVector3D(minX, minY, maxZ);
|
||||
vectors[2] = newVector3D(maxX, minY, minZ);
|
||||
vectors[3] = newVector3D(maxX, minY, maxZ);
|
||||
vectors[4] = newVector3D(minX, maxY, minZ);
|
||||
vectors[5] = newVector3D(minX, maxY, maxZ);
|
||||
vectors[6] = newVector3D(maxX, maxY, minZ);
|
||||
vectors[7] = newVector3D(maxX, maxY, maxZ);
|
||||
public Vector[] corners() {
|
||||
Vector[] vectors = new Vector[8];
|
||||
vectors[0] = new Vector(minX, minY, minZ);
|
||||
vectors[1] = new Vector(minX, minY, maxZ);
|
||||
vectors[2] = new Vector(maxX, minY, minZ);
|
||||
vectors[3] = new Vector(maxX, minY, maxZ);
|
||||
vectors[4] = new Vector(minX, maxY, minZ);
|
||||
vectors[5] = new Vector(minX, maxY, maxZ);
|
||||
vectors[6] = new Vector(maxX, maxY, minZ);
|
||||
vectors[7] = new Vector(maxX, maxY, maxZ);
|
||||
return vectors;
|
||||
}
|
||||
|
||||
@@ -411,14 +408,14 @@ public class SimpleCollisionBox implements CollisionBox {
|
||||
*/
|
||||
// Copied from hawk lol
|
||||
// I would like to point out that this is magic to me and I have not attempted to understand this code
|
||||
public Vector3D intersectsRay(Ray ray, float minDist, float maxDist) {
|
||||
Vector3D invDir = newVector3D(1f / ray.calculateDirection().getX(), 1f / ray.calculateDirection().getY(), 1f / ray.calculateDirection().getZ());
|
||||
public Vector intersectsRay(Ray ray, float minDist, float maxDist) {
|
||||
Vector invDir = new Vector(1f / ray.calculateDirection().getX(), 1f / ray.calculateDirection().getY(), 1f / ray.calculateDirection().getZ());
|
||||
|
||||
boolean signDirX = invDir.getX() < 0;
|
||||
boolean signDirY = invDir.getY() < 0;
|
||||
boolean signDirZ = invDir.getZ() < 0;
|
||||
|
||||
Vector3D bbox = signDirX ? max() : min();
|
||||
Vector bbox = signDirX ? max() : min();
|
||||
double tmin = (bbox.getX() - ray.getOrigin().getX()) * invDir.getX();
|
||||
bbox = signDirX ? min() : max();
|
||||
double tmax = (bbox.getX() - ray.getOrigin().getX()) * invDir.getX();
|
||||
@@ -457,12 +454,12 @@ public class SimpleCollisionBox implements CollisionBox {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Vector3D max() {
|
||||
return newVector3D(maxX, maxY, maxZ);
|
||||
public Vector max() {
|
||||
return new Vector(maxX, maxY, maxZ);
|
||||
}
|
||||
|
||||
public Vector3D min() {
|
||||
return newVector3D(minX, minY, minZ);
|
||||
public Vector min() {
|
||||
return new Vector(minX, minY, minZ);
|
||||
}
|
||||
|
||||
public DoubleList getYPointPositions() {
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
package ac.grim.grimac.utils.data;
|
||||
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
public class HitData {
|
||||
Vector3i position;
|
||||
Vector3D blockHitLocation;
|
||||
Vector blockHitLocation;
|
||||
WrappedBlockState state;
|
||||
BlockFace closestDirection;
|
||||
|
||||
public HitData(Vector3i position, Vector3D blockHitLocation, BlockFace closestDirection, WrappedBlockState state) {
|
||||
public HitData(Vector3i position, Vector blockHitLocation, BlockFace closestDirection, WrappedBlockState state) {
|
||||
this.position = position;
|
||||
this.blockHitLocation = blockHitLocation;
|
||||
this.closestDirection = closestDirection;
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
package ac.grim.grimac.utils.data;
|
||||
|
||||
public record KnownInput(boolean forward, boolean backward, boolean left, boolean right, boolean jump, boolean shift, boolean sprint) {
|
||||
}
|
||||
@@ -24,9 +24,6 @@ public class PacketStateData {
|
||||
// This works on 1.8 only
|
||||
public boolean didLastLastMovementIncludePosition = false;
|
||||
public boolean didLastMovementIncludePosition = false;
|
||||
// This works on 1.21.2+ only
|
||||
public boolean didSendMovementBeforeTickEnd = false;
|
||||
public KnownInput knownInput = new KnownInput(false, false, false, false, false, false, false);
|
||||
public Vector3d lastClaimedPosition = new Vector3d(0, 0, 0);
|
||||
|
||||
public float lastHealth, lastSaturation;
|
||||
|
||||
@@ -18,4 +18,20 @@
|
||||
|
||||
package ac.grim.grimac.utils.data;
|
||||
|
||||
public record Pair<A, B>(A first, B second) {}
|
||||
import java.util.Objects;
|
||||
|
||||
public record Pair<A, B>(A first, B second) {
|
||||
|
||||
public static <T, K> Pair<T, K> of(T a, K b) {
|
||||
return new Pair<>(a, b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Pair)) {
|
||||
return false;
|
||||
}
|
||||
Pair b = (Pair) o;
|
||||
return Objects.equals(this.first, b.first) && Objects.equals(this.second, b.second);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package ac.grim.grimac.utils.data;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@@ -11,14 +11,14 @@ import ac.grim.grimac.utils.vector.Vector3D;
|
||||
public class SetBackData {
|
||||
TeleportData teleportData;
|
||||
float xRot, yRot;
|
||||
Vector3D velocity;
|
||||
Vector velocity;
|
||||
boolean vehicle;
|
||||
boolean isComplete = false;
|
||||
// TODO: Rethink when we block movements for teleports, perhaps after 10 ticks or 5 blocks?
|
||||
boolean isPlugin = false;
|
||||
int ticksComplete = 0;
|
||||
|
||||
public SetBackData(TeleportData teleportData, float xRot, float yRot, Vector3D velocity, boolean vehicle, boolean isPlugin) {
|
||||
public SetBackData(TeleportData teleportData, float xRot, float yRot, Vector velocity, boolean vehicle, boolean isPlugin) {
|
||||
this.teleportData = teleportData;
|
||||
this.xRot = xRot;
|
||||
this.yRot = yRot;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package ac.grim.grimac.utils.data;
|
||||
|
||||
import lombok.Getter;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -9,13 +9,13 @@ public class VectorData {
|
||||
public VectorType vectorType;
|
||||
public VectorData lastVector;
|
||||
public VectorData preUncertainty;
|
||||
public Vector3D vector;
|
||||
public Vector vector;
|
||||
|
||||
@Getter
|
||||
private boolean isKnockback, firstBreadKb, isExplosion, firstBreadExplosion, isTrident, isZeroPointZeroThree, isSwimHop, isFlipSneaking, isFlipItem, isJump, isAttackSlow = false;
|
||||
|
||||
// For handling replacing the type of vector it is while keeping data
|
||||
public VectorData(Vector3D vector, VectorData lastVector, VectorType vectorType) {
|
||||
public VectorData(Vector vector, VectorData lastVector, VectorType vectorType) {
|
||||
this.vector = vector;
|
||||
this.lastVector = lastVector;
|
||||
this.vectorType = vectorType;
|
||||
@@ -38,7 +38,7 @@ public class VectorData {
|
||||
addVectorType(vectorType);
|
||||
}
|
||||
|
||||
public VectorData(Vector3D vector, VectorType vectorType) {
|
||||
public VectorData(Vector vector, VectorType vectorType) {
|
||||
this.vector = vector;
|
||||
this.vectorType = vectorType;
|
||||
addVectorType(vectorType);
|
||||
@@ -48,7 +48,7 @@ public class VectorData {
|
||||
return new VectorData(vector, this, type);
|
||||
}
|
||||
|
||||
public VectorData returnNewModified(Vector3D newVec, VectorType type) {
|
||||
public VectorData returnNewModified(Vector newVec, VectorType type) {
|
||||
return new VectorData(newVec, this, type);
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class VectorData {
|
||||
return Objects.hash(vectorType, lastVector, preUncertainty, vector, isKnockback, firstBreadKb, isExplosion, firstBreadExplosion, isTrident, isZeroPointZeroThree, isSwimHop, isFlipSneaking, isFlipItem, isJump, isAttackSlow);
|
||||
}
|
||||
|
||||
protected void addVectorType(VectorType type) {
|
||||
private void addVectorType(VectorType type) {
|
||||
switch (type) {
|
||||
case Knockback:
|
||||
isKnockback = true;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package ac.grim.grimac.utils.data;
|
||||
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class VelocityData {
|
||||
public final Vector3D vector;
|
||||
public final Vector vector;
|
||||
public final int entityID;
|
||||
public final int transaction;
|
||||
public double offset = Integer.MAX_VALUE;
|
||||
public boolean isSetback;
|
||||
|
||||
public VelocityData(int entityID, int transaction, boolean isSetback, Vector3D vector) {
|
||||
public VelocityData(int entityID, int transaction, boolean isSetback, Vector vector) {
|
||||
this.entityID = entityID;
|
||||
this.vector = vector;
|
||||
this.transaction = transaction;
|
||||
@@ -17,7 +17,7 @@ public class VelocityData {
|
||||
}
|
||||
|
||||
// First bread last tick -> Required this tick = don't require kb twice
|
||||
public VelocityData(int entityID, int transaction, Vector3D vector, boolean isSetback, double offset) {
|
||||
public VelocityData(int entityID, int transaction, Vector vector, boolean isSetback, double offset) {
|
||||
this.entityID = entityID;
|
||||
this.vector = vector;
|
||||
this.transaction = transaction;
|
||||
|
||||
@@ -3,17 +3,21 @@ package ac.grim.grimac.utils.data.packetentity;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.github.retrooper.packetevents.protocol.world.Direction;
|
||||
import com.github.retrooper.packetevents.protocol.world.PaintingType;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
public class PacketEntityPainting extends PacketEntity {
|
||||
|
||||
private final @Nullable PaintingType paintingType;
|
||||
private final Direction direction;
|
||||
|
||||
public PacketEntityPainting(GrimPlayer player, UUID uuid, double x, double y, double z, Direction direction) {
|
||||
public PacketEntityPainting(GrimPlayer player, UUID uuid, double x, double y, double z, @Nullable PaintingType paintingType, Direction direction) {
|
||||
super(player, uuid, EntityTypes.PAINTING, x, y, z);
|
||||
this.paintingType = paintingType;
|
||||
this.direction = direction;
|
||||
}
|
||||
}
|
||||
@@ -39,48 +39,24 @@ public enum MenuType {
|
||||
|
||||
private final int id;
|
||||
|
||||
private static final MenuType[] MENU_BY_ID_ARRAY;
|
||||
static {
|
||||
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
|
||||
MenuType[] menuTypes = MenuType.values();
|
||||
|
||||
int menuIdLimit;
|
||||
|
||||
if (version.isOlderThan(ServerVersion.V_1_20_3)) {
|
||||
// versions under 1.20.3
|
||||
menuIdLimit = 23;
|
||||
} else {
|
||||
// 1.20.3 & greater
|
||||
menuIdLimit = menuTypes.length - 1; // Don't iterate the UNKNOWN menu type
|
||||
}
|
||||
|
||||
MENU_BY_ID_ARRAY = new MenuType[menuIdLimit];
|
||||
|
||||
for (int itr = 0; itr < menuIdLimit; itr++) {
|
||||
MENU_BY_ID_ARRAY[itr] = menuTypes[itr];
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: could be optimized
|
||||
public static MenuType getMenuType(int id) {
|
||||
if (id < 0) {
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
if (id < 0) return UNKNOWN;
|
||||
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
|
||||
// versions under 1.20.3
|
||||
if (version.isOlderThan(ServerVersion.V_1_20_3)) { // TODO: Can this be moved to the static block?
|
||||
if (id >= 7) {
|
||||
id++;
|
||||
}
|
||||
if (version.isOlderThan(ServerVersion.V_1_20_3)) {
|
||||
if (id > 23) return UNKNOWN;
|
||||
MenuType[] values = MenuType.values();
|
||||
if (id >= 7) id++;
|
||||
return values[id];
|
||||
}
|
||||
|
||||
if (id >= MENU_BY_ID_ARRAY.length) {
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
return MENU_BY_ID_ARRAY[id];
|
||||
// 1.20.3 & greater
|
||||
MenuType[] values = MenuType.values();
|
||||
if (id >= values.length) return UNKNOWN;
|
||||
return MenuType.values()[id];
|
||||
}
|
||||
|
||||
|
||||
public static AbstractContainerMenu getMenuFromID(GrimPlayer player, Inventory playerInventory, MenuType type) {
|
||||
return switch (type) {
|
||||
case GENERIC_9x1, GENERIC_9x2, GENERIC_9x3, GENERIC_9x4, GENERIC_9x5, GENERIC_9x6 ->
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.github.retrooper.packetevents.protocol.potion.PotionType;
|
||||
import com.github.retrooper.packetevents.protocol.potion.PotionTypes;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.protocol.world.Direction;
|
||||
import com.github.retrooper.packetevents.protocol.world.PaintingType;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes;
|
||||
@@ -181,8 +182,8 @@ public class CompensatedEntities {
|
||||
packetEntity = new PacketEntityHook(player, uuid, entityType, position.getX(), position.getY(), position.getZ(), data);
|
||||
} else if (EntityTypes.ENDER_DRAGON.equals(entityType)) {
|
||||
packetEntity = new PacketEntityEnderDragon(player, uuid, entityID, position.getX(), position.getY(), position.getZ());
|
||||
} else if (EntityTypes.PAINTING.equals(entityType)) {
|
||||
packetEntity = new PacketEntityPainting(player, uuid, position.x, position.y, position.z, Direction.getByHorizontalIndex(data));
|
||||
} else if (entityType == EntityTypes.PAINTING) {
|
||||
packetEntity = new PacketEntityPainting(player, uuid, position.x, position.y, position.z, data == -1 ? null : PaintingType.getById(data), Direction.getByHorizontalIndex((int) xRot));
|
||||
} else {
|
||||
packetEntity = new PacketEntity(player, uuid, entityType, position.getX(), position.getY(), position.getZ());
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
|
||||
import org.bukkit.Bukkit;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -686,7 +686,7 @@ public class CompensatedWorld {
|
||||
return maxHeight;
|
||||
}
|
||||
|
||||
public WrappedBlockState getWrappedBlockStateAt(Vector3D aboveCCWPos) {
|
||||
public WrappedBlockState getWrappedBlockStateAt(Vector aboveCCWPos) {
|
||||
return getWrappedBlockStateAt(aboveCCWPos.getX(), aboveCCWPos.getY(), aboveCCWPos.getZ());
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import ac.grim.grimac.utils.inventory.InventoryStorage;
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
|
||||
import io.github.retrooper.packetevents.util.folia.FoliaScheduler;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
|
||||
import java.util.*;
|
||||
@@ -43,7 +44,7 @@ public class CorrectingPlayerInventoryStorage extends InventoryStorage {
|
||||
// The key for this map is the inventory slot ID
|
||||
// The value for this map is the transaction that we care about
|
||||
// Returns -1 if the entry is null
|
||||
Map<Integer, Integer> serverIsCurrentlyProcessingThesePredictions = new ConcurrentHashMap<>();
|
||||
Int2IntOpenHashMap serverIsCurrentlyProcessingThesePredictions = new Int2IntOpenHashMap();
|
||||
// A list of predictions the client has made for inventory changes
|
||||
// Remove if the server rejects these changes
|
||||
Map<Integer, Integer> pendingFinalizedSlot = new ConcurrentHashMap<>();
|
||||
@@ -55,6 +56,7 @@ public class CorrectingPlayerInventoryStorage extends InventoryStorage {
|
||||
public CorrectingPlayerInventoryStorage(GrimPlayer player, int size) {
|
||||
super(size);
|
||||
this.player = player;
|
||||
this.serverIsCurrentlyProcessingThesePredictions.defaultReturnValue(-1);
|
||||
}
|
||||
|
||||
// 1.17+ clients send what slots they have changed. This makes our jobs much easier.
|
||||
@@ -76,7 +78,7 @@ public class CorrectingPlayerInventoryStorage extends InventoryStorage {
|
||||
@Override
|
||||
public void setItem(int item, ItemStack stack) {
|
||||
// If there is a more recent change to this one, don't override it
|
||||
int finalTransaction = serverIsCurrentlyProcessingThesePredictions.getOrDefault(item, -1);
|
||||
int finalTransaction = serverIsCurrentlyProcessingThesePredictions.get(item);
|
||||
|
||||
// If the server is currently sending a packet to the player AND it is the final change to the slot
|
||||
// OR, the client was in control of setting this slot
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
package ac.grim.grimac.utils.math;
|
||||
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import lombok.Getter;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import static com.github.retrooper.packetevents.protocol.player.ClientVersion.V_1_8;
|
||||
import static java.lang.Math.abs;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class TrigHandler {
|
||||
GrimPlayer player;
|
||||
@@ -24,24 +19,24 @@ public class TrigHandler {
|
||||
isVanillaMath = !isVanillaMath;
|
||||
}
|
||||
|
||||
public Vector3D getVanillaMathMovement(Vector3D wantedMovement, float f, float f2) {
|
||||
public Vector getVanillaMathMovement(Vector wantedMovement, float f, float f2) {
|
||||
float f3 = VanillaMath.sin(f2 * 0.017453292f);
|
||||
float f4 = VanillaMath.cos(f2 * 0.017453292f);
|
||||
|
||||
float bestTheoreticalX = (float) (f3 * wantedMovement.getZ() + f4 * wantedMovement.getX()) / (f3 * f3 + f4 * f4) / f;
|
||||
float bestTheoreticalZ = (float) (-f3 * wantedMovement.getX() + f4 * wantedMovement.getZ()) / (f3 * f3 + f4 * f4) / f;
|
||||
|
||||
return newVector3D(bestTheoreticalX, 0, bestTheoreticalZ);
|
||||
return new Vector(bestTheoreticalX, 0, bestTheoreticalZ);
|
||||
}
|
||||
|
||||
public Vector3D getShitMathMovement(Vector3D wantedMovement, float f, float f2) {
|
||||
float f3 = player.getClientVersion().isNewerThanOrEquals(V_1_8) ? OptifineFastMath.sin(f2 * 0.017453292f) : LegacyFastMath.sin(f2 * 0.017453292f);
|
||||
float f4 = player.getClientVersion().isNewerThanOrEquals(V_1_8) ? OptifineFastMath.cos(f2 * 0.017453292f) : LegacyFastMath.cos(f2 * 0.017453292f);
|
||||
public Vector getShitMathMovement(Vector wantedMovement, float f, float f2) {
|
||||
float f3 = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8) ? OptifineFastMath.sin(f2 * 0.017453292f) : LegacyFastMath.sin(f2 * 0.017453292f);
|
||||
float f4 = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8) ? OptifineFastMath.cos(f2 * 0.017453292f) : LegacyFastMath.cos(f2 * 0.017453292f);
|
||||
|
||||
float bestTheoreticalX = (float) (f3 * wantedMovement.getZ() + f4 * wantedMovement.getX()) / (f3 * f3 + f4 * f4) / f;
|
||||
float bestTheoreticalZ = (float) (-f3 * wantedMovement.getX() + f4 * wantedMovement.getZ()) / (f3 * f3 + f4 * f4) / f;
|
||||
|
||||
return newVector3D(bestTheoreticalX, 0, bestTheoreticalZ);
|
||||
return new Vector(bestTheoreticalX, 0, bestTheoreticalZ);
|
||||
}
|
||||
|
||||
public void setOffset(double offset) {
|
||||
@@ -54,12 +49,12 @@ public class TrigHandler {
|
||||
}
|
||||
|
||||
if (offset > 1e-5) {
|
||||
Vector3D trueMovement = player.actualMovement.clone().subtract(player.startTickClientVel);
|
||||
Vector3D correctMath = getVanillaMathMovement(trueMovement, 0.1f, player.xRot);
|
||||
Vector3D fastMath = getShitMathMovement(trueMovement, 0.1f, player.xRot);
|
||||
Vector trueMovement = player.actualMovement.clone().subtract(player.startTickClientVel);
|
||||
Vector correctMath = getVanillaMathMovement(trueMovement, 0.1f, player.xRot);
|
||||
Vector fastMath = getShitMathMovement(trueMovement, 0.1f, player.xRot);
|
||||
|
||||
correctMath = newVector3D(abs(correctMath.getX()), 0, abs(correctMath.getZ()));
|
||||
fastMath = newVector3D(abs(fastMath.getX()), 0, abs(fastMath.getZ()));
|
||||
correctMath = new Vector(Math.abs(correctMath.getX()), 0, Math.abs(correctMath.getZ()));
|
||||
fastMath = new Vector(Math.abs(fastMath.getX()), 0, Math.abs(fastMath.getZ()));
|
||||
|
||||
double minCorrectHorizontal = Math.min(correctMath.getX(), correctMath.getZ());
|
||||
// Support diagonal inputs
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
package ac.grim.grimac.utils.math;
|
||||
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import static ac.grim.grimac.utils.math.GrimMath.clamp;
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class VectorUtils {
|
||||
public static Vector3D cutBoxToVector(Vector3D vectorToCutTo, Vector3D min, Vector3D max) {
|
||||
public static Vector cutBoxToVector(Vector vectorToCutTo, Vector min, Vector max) {
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(min, max).sort();
|
||||
return cutBoxToVector(vectorToCutTo, box);
|
||||
}
|
||||
|
||||
public static Vector3D cutBoxToVector(Vector3D vectorCutTo, SimpleCollisionBox box) {
|
||||
return newVector3D(clamp(vectorCutTo.getX(), box.minX, box.maxX), clamp(vectorCutTo.getY(), box.minY, box.maxY), clamp(vectorCutTo.getZ(), box.minZ, box.maxZ));
|
||||
public static Vector cutBoxToVector(Vector vectorCutTo, SimpleCollisionBox box) {
|
||||
return new Vector(GrimMath.clamp(vectorCutTo.getX(), box.minX, box.maxX),
|
||||
GrimMath.clamp(vectorCutTo.getY(), box.minY, box.maxY),
|
||||
GrimMath.clamp(vectorCutTo.getZ(), box.minZ, box.maxZ));
|
||||
}
|
||||
|
||||
public static Vector3D fromVec3d(Vector3d vector3d) {
|
||||
return newVector3D(vector3d.getX(), vector3d.getY(), vector3d.getZ());
|
||||
public static Vector fromVec3d(Vector3d vector3d) {
|
||||
return new Vector(vector3d.getX(), vector3d.getY(), vector3d.getZ());
|
||||
}
|
||||
|
||||
// Clamping stops the player from causing an integer overflow and crashing the netty thread
|
||||
|
||||
@@ -45,8 +45,8 @@ public class BlockProperties {
|
||||
}
|
||||
|
||||
// In 1.19.4, air sprinting is based on current sprinting, not last sprinting
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_19_4)) {
|
||||
return player.isSprinting ? 0.025999999F : 0.02f;
|
||||
if (player.getClientVersion().getProtocolVersion() > ClientVersion.V_1_19_3.getProtocolVersion()) {
|
||||
return player.isSprinting ? (float) ((double) 0.02f + 0.005999999865889549D) : 0.02f;
|
||||
}
|
||||
|
||||
return player.lastSprintingForSpeed ? (float) ((double) 0.02f + 0.005999999865889549D) : 0.02f;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -12,7 +12,6 @@ import ac.grim.grimac.utils.data.tags.SyncedTags;
|
||||
import ac.grim.grimac.utils.latency.CompensatedWorld;
|
||||
import ac.grim.grimac.utils.math.GrimMath;
|
||||
import ac.grim.grimac.utils.math.VectorUtils;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
@@ -27,7 +26,7 @@ import it.unimi.dsi.fastutil.floats.FloatArraySet;
|
||||
import it.unimi.dsi.fastutil.floats.FloatArrays;
|
||||
import it.unimi.dsi.fastutil.floats.FloatSet;
|
||||
import org.bukkit.Location;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -35,13 +34,6 @@ import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static ac.grim.grimac.utils.nmsutil.Collisions.Axis.*;
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import static com.github.retrooper.packetevents.protocol.player.ClientVersion.*;
|
||||
import static java.lang.Double.MAX_VALUE;
|
||||
import static java.lang.Math.max;
|
||||
import static java.lang.Math.min;
|
||||
|
||||
public class Collisions {
|
||||
private static final double COLLISION_EPSILON = 1.0E-7;
|
||||
|
||||
@@ -80,12 +72,12 @@ public class Collisions {
|
||||
}
|
||||
|
||||
// Call this when there isn't uncertainty on the Y axis
|
||||
public static Vector3D collide(GrimPlayer player, double desiredX, double desiredY, double desiredZ) {
|
||||
public static Vector collide(GrimPlayer player, double desiredX, double desiredY, double desiredZ) {
|
||||
return collide(player, desiredX, desiredY, desiredZ, desiredY, null);
|
||||
}
|
||||
|
||||
public static Vector3D collide(GrimPlayer player, double desiredX, double desiredY, double desiredZ, double clientVelY, VectorData data) {
|
||||
if (desiredX == 0 && desiredY == 0 && desiredZ == 0) return newVector3D();
|
||||
public static Vector collide(GrimPlayer player, double desiredX, double desiredY, double desiredZ, double clientVelY, VectorData data) {
|
||||
if (desiredX == 0 && desiredY == 0 && desiredZ == 0) return new Vector();
|
||||
|
||||
final SimpleCollisionBox grabBoxesBB = player.boundingBox.copy();
|
||||
final double stepUpHeight = player.getMaxUpStep();
|
||||
@@ -103,7 +95,7 @@ public class Collisions {
|
||||
grabBoxesBB.expandToCoordinate(desiredX, desiredY, desiredZ);
|
||||
grabBoxesBB.maxY += stepUpHeight;
|
||||
} else {
|
||||
grabBoxesBB.expandToCoordinate(desiredX, max(stepUpHeight, desiredY), desiredZ);
|
||||
grabBoxesBB.expandToCoordinate(desiredX, Math.max(stepUpHeight, desiredY), desiredZ);
|
||||
}
|
||||
} else {
|
||||
grabBoxesBB.expandToCoordinate(desiredX, desiredY, desiredZ);
|
||||
@@ -113,14 +105,14 @@ public class Collisions {
|
||||
List<SimpleCollisionBox> desiredMovementCollisionBoxes = new ArrayList<>();
|
||||
getCollisionBoxes(player, grabBoxesBB, desiredMovementCollisionBoxes, false);
|
||||
|
||||
double bestInput = MAX_VALUE;
|
||||
Vector3D bestOrderResult = null;
|
||||
double bestInput = Double.MAX_VALUE;
|
||||
Vector bestOrderResult = null;
|
||||
|
||||
Vector3D bestTheoreticalCollisionResult = VectorUtils.cutBoxToVector(player.actualMovement, new SimpleCollisionBox(0, min(0, desiredY), 0, desiredX, max(stepUpHeight, desiredY), desiredZ).sort());
|
||||
Vector bestTheoreticalCollisionResult = VectorUtils.cutBoxToVector(player.actualMovement, new SimpleCollisionBox(0, Math.min(0, desiredY), 0, desiredX, Math.max(stepUpHeight, desiredY), desiredZ).sort());
|
||||
int zeroCount = (desiredX == 0 ? 1 : 0) + (desiredY == 0 ? 1 : 0) + (desiredZ == 0 ? 1 : 0);
|
||||
|
||||
for (List<Axis> order : (data != null && data.isZeroPointZeroThree() ? allAxisCombinations : nonStupidityCombinations)) {
|
||||
Vector3D collisionResult = collideBoundingBoxLegacy(newVector3D(desiredX, desiredY, desiredZ), player.boundingBox, desiredMovementCollisionBoxes, order);
|
||||
Vector collisionResult = collideBoundingBoxLegacy(new Vector(desiredX, desiredY, desiredZ), player.boundingBox, desiredMovementCollisionBoxes, order);
|
||||
|
||||
// While running up stairs and holding space, the player activates the "lastOnGround" part without otherwise being able to step
|
||||
// 0.03 movement must compensate for stepping elsewhere. Too much of a hack to include in this met5hod.
|
||||
@@ -132,7 +124,7 @@ public class Collisions {
|
||||
if (stepUpHeight > 0.0F && movingIntoGround && (collisionResult.getX() != desiredX || collisionResult.getZ() != desiredZ)) {
|
||||
player.uncertaintyHandler.isStepMovement = true;
|
||||
// 1.21 significantly refactored this
|
||||
if (player.getClientVersion().isNewerThanOrEquals(V_1_21)) {
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21)) {
|
||||
SimpleCollisionBox box2 = movingIntoGroundReal ? player.boundingBox.copy().offset(0.0, collisionResult.getY(), 0.0) : player.boundingBox.copy();
|
||||
SimpleCollisionBox box3 = box2.copy().expandToCoordinate(desiredX, stepUpHeight, desiredZ);
|
||||
if (!movingIntoGroundReal) {
|
||||
@@ -144,21 +136,21 @@ public class Collisions {
|
||||
final float[] stepHeights = collectStepHeights(box2, list2, (float) stepUpHeight, (float) collisionResult.getY());
|
||||
|
||||
for (float stepHeight : stepHeights) {
|
||||
Vector3D vec3d2 = collideBoundingBoxLegacy(newVector3D(desiredX, stepHeight, desiredZ), box2, list2, order);
|
||||
Vector vec3d2 = collideBoundingBoxLegacy(new Vector(desiredX, stepHeight, desiredZ), box2, list2, order);
|
||||
if (getHorizontalDistanceSqr(vec3d2) > getHorizontalDistanceSqr(collisionResult)) {
|
||||
final double d = player.boundingBox.minY - box2.minY;
|
||||
collisionResult = vec3d2.add(newVector3D(0.0, -d, 0.0));
|
||||
collisionResult = vec3d2.add(new Vector(0.0, -d, 0.0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Vector3D regularStepUp = collideBoundingBoxLegacy(newVector3D(desiredX, stepUpHeight, desiredZ), player.boundingBox, desiredMovementCollisionBoxes, order);
|
||||
Vector regularStepUp = collideBoundingBoxLegacy(new Vector(desiredX, stepUpHeight, desiredZ), player.boundingBox, desiredMovementCollisionBoxes, order);
|
||||
|
||||
// 1.7 clients do not have this stepping bug fix
|
||||
if (player.getClientVersion().isNewerThanOrEquals(V_1_8)) {
|
||||
Vector3D stepUpBugFix = collideBoundingBoxLegacy(newVector3D(0, stepUpHeight, 0), player.boundingBox.copy().expandToCoordinate(desiredX, 0, desiredZ), desiredMovementCollisionBoxes, order);
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8)) {
|
||||
Vector stepUpBugFix = collideBoundingBoxLegacy(new Vector(0, stepUpHeight, 0), player.boundingBox.copy().expandToCoordinate(desiredX, 0, desiredZ), desiredMovementCollisionBoxes, order);
|
||||
if (stepUpBugFix.getY() < stepUpHeight) {
|
||||
Vector3D stepUpBugFixResult = collideBoundingBoxLegacy(newVector3D(desiredX, 0, desiredZ), player.boundingBox.copy().offset(0, stepUpBugFix.getY(), 0), desiredMovementCollisionBoxes, order).add(stepUpBugFix);
|
||||
Vector stepUpBugFixResult = collideBoundingBoxLegacy(new Vector(desiredX, 0, desiredZ), player.boundingBox.copy().offset(0, stepUpBugFix.getY(), 0), desiredMovementCollisionBoxes, order).add(stepUpBugFix);
|
||||
if (getHorizontalDistanceSqr(stepUpBugFixResult) > getHorizontalDistanceSqr(regularStepUp)) {
|
||||
regularStepUp = stepUpBugFixResult;
|
||||
}
|
||||
@@ -166,7 +158,7 @@ public class Collisions {
|
||||
}
|
||||
|
||||
if (getHorizontalDistanceSqr(regularStepUp) > getHorizontalDistanceSqr(collisionResult)) {
|
||||
collisionResult = regularStepUp.add(collideBoundingBoxLegacy(newVector3D(0, -regularStepUp.getY() + (player.getClientVersion().isNewerThanOrEquals(V_1_14) ? desiredY : 0), 0), player.boundingBox.copy().offset(regularStepUp.getX(), regularStepUp.getY(), regularStepUp.getZ()), desiredMovementCollisionBoxes, order));
|
||||
collisionResult = regularStepUp.add(collideBoundingBoxLegacy(new Vector(0, -regularStepUp.getY() + (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14) ? desiredY : 0), 0), player.boundingBox.copy().offset(regularStepUp.getX(), regularStepUp.getY(), regularStepUp.getZ()), desiredMovementCollisionBoxes, order));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -351,7 +343,7 @@ public class Collisions {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Vector3D collideBoundingBoxLegacy(Vector3D toCollide, SimpleCollisionBox
|
||||
public static Vector collideBoundingBoxLegacy(Vector toCollide, SimpleCollisionBox
|
||||
box, List<SimpleCollisionBox> desiredMovementCollisionBoxes, List<Axis> order) {
|
||||
double x = toCollide.getX();
|
||||
double y = toCollide.getY();
|
||||
@@ -360,17 +352,17 @@ public class Collisions {
|
||||
SimpleCollisionBox setBB = box.copy();
|
||||
|
||||
for (Axis axis : order) {
|
||||
if (axis == X) {
|
||||
if (axis == Axis.X) {
|
||||
for (SimpleCollisionBox bb : desiredMovementCollisionBoxes) {
|
||||
x = bb.collideX(setBB, x);
|
||||
}
|
||||
setBB.offset(x, 0.0D, 0.0D);
|
||||
} else if (axis == Y) {
|
||||
} else if (axis == Axis.Y) {
|
||||
for (SimpleCollisionBox bb : desiredMovementCollisionBoxes) {
|
||||
y = bb.collideY(setBB, y);
|
||||
}
|
||||
setBB.offset(0.0D, y, 0.0D);
|
||||
} else if (axis == Z) {
|
||||
} else if (axis == Axis.Z) {
|
||||
for (SimpleCollisionBox bb : desiredMovementCollisionBoxes) {
|
||||
z = bb.collideZ(setBB, z);
|
||||
}
|
||||
@@ -378,23 +370,23 @@ public class Collisions {
|
||||
}
|
||||
}
|
||||
|
||||
return newVector3D(x, y, z);
|
||||
return new Vector(x, y, z);
|
||||
}
|
||||
|
||||
public static boolean isEmpty(GrimPlayer player, SimpleCollisionBox playerBB) {
|
||||
return !getCollisionBoxes(player, playerBB, null, true);
|
||||
}
|
||||
|
||||
private static double getHorizontalDistanceSqr(Vector3D vector) {
|
||||
private static double getHorizontalDistanceSqr(Vector vector) {
|
||||
return vector.getX() * vector.getX() + vector.getZ() * vector.getZ();
|
||||
}
|
||||
|
||||
public static Vector3D maybeBackOffFromEdge(Vector3D vec3, GrimPlayer player, boolean overrideVersion) {
|
||||
public static Vector maybeBackOffFromEdge(Vector vec3, GrimPlayer player, boolean overrideVersion) {
|
||||
if (!player.isFlying && player.isSneaking && isAboveGround(player)) {
|
||||
double x = vec3.getX();
|
||||
double z = vec3.getZ();
|
||||
|
||||
double maxStepDown = overrideVersion || player.getClientVersion().isNewerThanOrEquals(V_1_11) ? -player.getMaxUpStep() : -1 + COLLISION_EPSILON;
|
||||
double maxStepDown = overrideVersion || player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_11) ? -player.getMaxUpStep() : -1 + COLLISION_EPSILON;
|
||||
|
||||
while (x != 0.0 && isEmpty(player, player.boundingBox.copy().offset(x, maxStepDown, 0.0))) {
|
||||
if (x < 0.05D && x >= -0.05D) {
|
||||
@@ -431,7 +423,7 @@ public class Collisions {
|
||||
z += 0.05D;
|
||||
}
|
||||
}
|
||||
vec3 = newVector3D(x, vec3.getY(), z);
|
||||
vec3 = new Vector(x, vec3.getY(), z);
|
||||
}
|
||||
|
||||
return vec3;
|
||||
@@ -462,20 +454,20 @@ public class Collisions {
|
||||
|
||||
if (blockType == StateTypes.COBWEB) {
|
||||
if (player.compensatedEntities.hasPotionEffect(PotionTypes.WEAVING)) {
|
||||
player.stuckSpeedMultiplier = newVector3D(0.5, 0.25, 0.5);
|
||||
player.stuckSpeedMultiplier = new Vector(0.5, 0.25, 0.5);
|
||||
} else {
|
||||
player.stuckSpeedMultiplier = newVector3D(0.25, 0.05000000074505806, 0.25);
|
||||
player.stuckSpeedMultiplier = new Vector(0.25, 0.05000000074505806, 0.25);
|
||||
}
|
||||
}
|
||||
|
||||
if (blockType == StateTypes.SWEET_BERRY_BUSH
|
||||
&& player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14)) {
|
||||
player.stuckSpeedMultiplier = newVector3D(0.800000011920929, 0.75, 0.800000011920929);
|
||||
player.stuckSpeedMultiplier = new Vector(0.800000011920929, 0.75, 0.800000011920929);
|
||||
}
|
||||
|
||||
if (blockType == StateTypes.POWDER_SNOW && i == Math.floor(player.x) && j == Math.floor(player.y) && k == Math.floor(player.z)
|
||||
&& player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_17)) {
|
||||
player.stuckSpeedMultiplier = newVector3D(0.8999999761581421, 1.5, 0.8999999761581421);
|
||||
player.stuckSpeedMultiplier = new Vector(0.8999999761581421, 1.5, 0.8999999761581421);
|
||||
}
|
||||
|
||||
if (blockType == StateTypes.SOUL_SAND && player.getClientVersion().isOlderThan(ClientVersion.V_1_15)) {
|
||||
@@ -542,7 +534,7 @@ public class Collisions {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isSlidingDown(Vector3D vector, GrimPlayer player, int locationX, int locationY,
|
||||
private static boolean isSlidingDown(Vector vector, GrimPlayer player, int locationX, int locationY,
|
||||
int locationZ) {
|
||||
if (player.onGround) {
|
||||
return false;
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
package ac.grim.grimac.utils.nmsutil;
|
||||
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import static com.github.retrooper.packetevents.protocol.player.ClientVersion.V_1_14;
|
||||
import static java.lang.Math.abs;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class FluidFallingAdjustedMovement {
|
||||
public static Vector3D getFluidFallingAdjustedMovement(GrimPlayer player, double d, boolean bl, Vector3D vec3) {
|
||||
public static Vector getFluidFallingAdjustedMovement(GrimPlayer player, double d, boolean bl, Vector vec3) {
|
||||
if (player.hasGravity && !player.isSprinting) {
|
||||
boolean falling = player.getClientVersion().isNewerThanOrEquals(V_1_14) ? bl : vec3.getY() < 0;
|
||||
double d2 = falling && abs(vec3.getY() - 0.005) >= 0.003 && abs(vec3.getY() - d / 16.0) < 0.003 ? -0.003 : vec3.getY() - d / 16.0;
|
||||
return newVector3D(vec3.getX(), d2, vec3.getZ());
|
||||
boolean falling = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14) ? bl : vec3.getY() < 0;
|
||||
double d2 = falling && Math.abs(vec3.getY() - 0.005) >= 0.003 && Math.abs(vec3.getY() - d / 16.0) < 0.003 ? -0.003 : vec3.getY() - d / 16.0;
|
||||
return new Vector(vec3.getX(), d2, vec3.getZ());
|
||||
}
|
||||
return vec3;
|
||||
}
|
||||
|
||||
@@ -3,37 +3,29 @@ package ac.grim.grimac.utils.nmsutil;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.collisions.CollisionData;
|
||||
import ac.grim.grimac.utils.collisions.blocks.DoorHandler;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.defaulttags.BlockTags;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import static ac.grim.grimac.utils.nmsutil.Materials.isSolidBlockingBlacklist;
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import static com.github.retrooper.packetevents.protocol.world.BlockFace.*;
|
||||
import static com.github.retrooper.packetevents.protocol.world.states.type.StateTypes.LAVA;
|
||||
import static com.github.retrooper.packetevents.protocol.world.states.type.StateTypes.WATER;
|
||||
import static java.lang.Math.min;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class FluidTypeFlowing {
|
||||
public static Vector3D getFlow(GrimPlayer player, int originalX, int originalY, int originalZ) {
|
||||
float fluidLevel = (float) min(player.compensatedWorld.getFluidLevelAt(originalX, originalY, originalZ), 8 / 9D);
|
||||
public static Vector getFlow(GrimPlayer player, int originalX, int originalY, int originalZ) {
|
||||
float fluidLevel = (float) Math.min(player.compensatedWorld.getFluidLevelAt(originalX, originalY, originalZ), 8 / 9D);
|
||||
ClientVersion version = player.getClientVersion();
|
||||
|
||||
if (fluidLevel == 0) return newVector3D();
|
||||
if (fluidLevel == 0) return new Vector();
|
||||
|
||||
double d0 = 0.0D;
|
||||
double d1 = 0.0D;
|
||||
for (BlockFace enumdirection : new BlockFace[]{NORTH, EAST, SOUTH, WEST}) {
|
||||
for (BlockFace enumdirection : new BlockFace[]{BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST}) {
|
||||
int modifiedX = originalX + enumdirection.getModX();
|
||||
int modifiedZ = originalZ + enumdirection.getModZ();
|
||||
|
||||
if (affectsFlow(player, originalX, originalY, originalZ, modifiedX, originalY, modifiedZ)) {
|
||||
float f = (float) min(player.compensatedWorld.getFluidLevelAt(modifiedX, originalY, modifiedZ), 8 / 9D);
|
||||
float f = (float) Math.min(player.compensatedWorld.getFluidLevelAt(modifiedX, originalY, modifiedZ), 8 / 9D);
|
||||
float f1 = 0.0F;
|
||||
if (f == 0.0F) {
|
||||
StateType mat = player.compensatedWorld.getStateTypeAt(modifiedX, originalY, modifiedZ);
|
||||
@@ -41,9 +33,9 @@ public class FluidTypeFlowing {
|
||||
// Grim's definition of solid is whether the block has a hitbox
|
||||
// Minecraft is... it's whatever Mojang was feeling like, but it's very consistent
|
||||
// Use method call to support 1.13-1.15 clients and banner oddity
|
||||
if (isSolidBlockingBlacklist(mat, version)) {
|
||||
if (Materials.isSolidBlockingBlacklist(mat, version)) {
|
||||
if (affectsFlow(player, originalX, originalY, originalZ, modifiedX, originalY - 1, modifiedZ)) {
|
||||
f = (float) min(player.compensatedWorld.getFluidLevelAt(modifiedX, originalY - 1, modifiedZ), 8 / 9D);
|
||||
f = (float) Math.min(player.compensatedWorld.getFluidLevelAt(modifiedX, originalY - 1, modifiedZ), 8 / 9D);
|
||||
if (f > 0.0F) {
|
||||
f1 = fluidLevel - (f - 0.8888889F);
|
||||
}
|
||||
@@ -61,15 +53,15 @@ public class FluidTypeFlowing {
|
||||
}
|
||||
}
|
||||
|
||||
Vector3D vec3d = newVector3D(d0, 0.0D, d1);
|
||||
Vector vec3d = new Vector(d0, 0.0D, d1);
|
||||
|
||||
// Fluid level 1-7 is for regular fluid heights
|
||||
// Fluid level 8-15 is for falling fluids
|
||||
WrappedBlockState state = player.compensatedWorld.getWrappedBlockStateAt(originalX, originalY, originalZ);
|
||||
if ((state.getType() == WATER || state.getType() == LAVA) && state.getLevel() >= 8) {
|
||||
for (BlockFace enumdirection : new BlockFace[]{NORTH, EAST, SOUTH, WEST}) {
|
||||
if ((state.getType() == StateTypes.WATER || state.getType() == StateTypes.LAVA) && state.getLevel() >= 8) {
|
||||
for (BlockFace enumdirection : new BlockFace[]{BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST}) {
|
||||
if (isSolidFace(player, originalX, originalY, originalZ, enumdirection) || isSolidFace(player, originalX, originalY + 1, originalZ, enumdirection)) {
|
||||
vec3d = normalizeVectorWithoutNaN(vec3d).add(newVector3D(0.0D, -6.0D, 0.0D));
|
||||
vec3d = normalizeVectorWithoutNaN(vec3d).add(new Vector(0.0D, -6.0D, 0.0D));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -158,9 +150,9 @@ public class FluidTypeFlowing {
|
||||
}
|
||||
}
|
||||
|
||||
private static Vector3D normalizeVectorWithoutNaN(Vector3D vector) {
|
||||
private static Vector normalizeVectorWithoutNaN(Vector vector) {
|
||||
double var0 = vector.length();
|
||||
return var0 < 1.0E-4 ? newVector3D() : vector.multiply(1 / var0);
|
||||
return var0 < 1.0E-4 ? new Vector() : vector.multiply(1 / var0);
|
||||
}
|
||||
|
||||
public static boolean isEmpty(GrimPlayer player, int x, int y, int z) {
|
||||
|
||||
@@ -5,14 +5,12 @@ import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.potion.PotionTypes;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
public class JumpPower {
|
||||
public static void jumpFromGround(GrimPlayer player, Vector3D vector) {
|
||||
public static void jumpFromGround(GrimPlayer player, Vector vector) {
|
||||
float jumpPower = getJumpPower(player);
|
||||
|
||||
final OptionalInt jumpBoost = player.compensatedEntities.getPotionLevelForPlayer(PotionTypes.JUMP_BOOST);
|
||||
@@ -22,11 +20,11 @@ public class JumpPower {
|
||||
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_20_5) && jumpPower <= 1.0E-5F) return;
|
||||
|
||||
vector.setY(player.getClientVersion().isOlderThan(ClientVersion.V_1_21_2) ? jumpPower : Math.max(jumpPower, vector.getY()));
|
||||
vector.setY(jumpPower);
|
||||
|
||||
if (player.isSprinting) {
|
||||
float radRotation = player.xRot * ((float) Math.PI / 180);
|
||||
vector.add(newVector3D(-player.trigHandler.sin(radRotation) * 0.2, 0.0, player.trigHandler.cos(radRotation) * 0.2));
|
||||
float radRotation = player.xRot * ((float) Math.PI / 180F);
|
||||
vector.add(new Vector(-player.trigHandler.sin(radRotation) * 0.2f, 0.0, player.trigHandler.cos(radRotation) * 0.2f));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,34 +2,30 @@ package ac.grim.grimac.utils.nmsutil;
|
||||
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.data.Pair;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import static java.lang.Math.toRadians;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
// Copied directly from Hawk
|
||||
public class Ray implements Cloneable {
|
||||
|
||||
private Vector3D origin;
|
||||
private Vector3D direction;
|
||||
private Vector origin;
|
||||
private Vector direction;
|
||||
|
||||
public Ray(Vector3D origin, Vector3D direction) {
|
||||
public Ray(Vector origin, Vector direction) {
|
||||
this.origin = origin;
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public Ray(GrimPlayer player, double x, double y, double z, float xRot, float yRot) {
|
||||
this.origin = newVector3D(x, y, z);
|
||||
this.origin = new Vector(x, y, z);
|
||||
this.direction = calculateDirection(player, xRot, yRot);
|
||||
}
|
||||
|
||||
// Account for FastMath by using player's trig handler
|
||||
// Copied from hawk which probably copied it from NMS
|
||||
public static Vector3D calculateDirection(GrimPlayer player, float xRot, float yRot) {
|
||||
Vector3D vector = newVector3D();
|
||||
float rotX = (float) toRadians(xRot);
|
||||
float rotY = (float) toRadians(yRot);
|
||||
public static Vector calculateDirection(GrimPlayer player, float xRot, float yRot) {
|
||||
Vector vector = new Vector();
|
||||
float rotX = (float) Math.toRadians(xRot);
|
||||
float rotY = (float) Math.toRadians(yRot);
|
||||
vector.setY(-player.trigHandler.sin(rotY));
|
||||
double xz = player.trigHandler.cos(rotY);
|
||||
vector.setX(-xz * player.trigHandler.sin(rotX));
|
||||
@@ -54,28 +50,28 @@ public class Ray implements Cloneable {
|
||||
return "origin: " + origin + " direction: " + direction;
|
||||
}
|
||||
|
||||
public Vector3D getPointAtDistance(double distance) {
|
||||
Vector3D dir = newVector3D(direction.getX(), direction.getY(), direction.getZ());
|
||||
Vector3D orig = newVector3D(origin.getX(), origin.getY(), origin.getZ());
|
||||
public Vector getPointAtDistance(double distance) {
|
||||
Vector dir = new Vector(direction.getX(), direction.getY(), direction.getZ());
|
||||
Vector orig = new Vector(origin.getX(), origin.getY(), origin.getZ());
|
||||
return orig.add(dir.multiply(distance));
|
||||
}
|
||||
|
||||
//https://en.wikipedia.org/wiki/Skew_lines#Nearest_Points
|
||||
public Pair<Vector3D, Vector3D> closestPointsBetweenLines(Ray other) {
|
||||
Vector3D n1 = direction.clone().crossProduct(other.direction.clone().crossProduct(direction));
|
||||
Vector3D n2 = other.direction.clone().crossProduct(direction.clone().crossProduct(other.direction));
|
||||
public Pair<Vector, Vector> closestPointsBetweenLines(Ray other) {
|
||||
Vector n1 = direction.clone().crossProduct(other.direction.clone().crossProduct(direction));
|
||||
Vector n2 = other.direction.clone().crossProduct(direction.clone().crossProduct(other.direction));
|
||||
|
||||
Vector3D c1 = origin.clone().add(direction.clone().multiply(other.origin.clone().subtract(origin).dot(n2) / direction.dot(n2)));
|
||||
Vector3D c2 = other.origin.clone().add(other.direction.clone().multiply(origin.clone().subtract(other.origin).dot(n1) / other.direction.dot(n1)));
|
||||
Vector c1 = origin.clone().add(direction.clone().multiply(other.origin.clone().subtract(origin).dot(n2) / direction.dot(n2)));
|
||||
Vector c2 = other.origin.clone().add(other.direction.clone().multiply(origin.clone().subtract(other.origin).dot(n1) / other.direction.dot(n1)));
|
||||
|
||||
return new Pair<>(c1, c2);
|
||||
}
|
||||
|
||||
public Vector3D getOrigin() {
|
||||
public Vector getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public Vector3D calculateDirection() {
|
||||
public Vector calculateDirection() {
|
||||
return direction;
|
||||
}
|
||||
}
|
||||
@@ -5,24 +5,19 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.Pair;
|
||||
import ac.grim.grimac.utils.math.VectorUtils;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import static com.github.retrooper.packetevents.protocol.player.ClientVersion.V_1_12_2;
|
||||
import static java.lang.Math.PI;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class ReachUtils {
|
||||
// Copied from 1.8... I couldn't figure out 1.14+. "Enterprise" java code is unreadable!
|
||||
public static Pair<Vector3D, BlockFace> calculateIntercept(SimpleCollisionBox self, Vector3D origin, Vector3D end) {
|
||||
Vector3D minX = getIntermediateWithXValue(origin, end, self.minX);
|
||||
Vector3D maxX = getIntermediateWithXValue(origin, end, self.maxX);
|
||||
Vector3D minY = getIntermediateWithYValue(origin, end, self.minY);
|
||||
Vector3D maxY = getIntermediateWithYValue(origin, end, self.maxY);
|
||||
Vector3D minZ = getIntermediateWithZValue(origin, end, self.minZ);
|
||||
Vector3D maxZ = getIntermediateWithZValue(origin, end, self.maxZ);
|
||||
public static Pair<Vector, BlockFace> calculateIntercept(SimpleCollisionBox self, Vector origin, Vector end) {
|
||||
Vector minX = getIntermediateWithXValue(origin, end, self.minX);
|
||||
Vector maxX = getIntermediateWithXValue(origin, end, self.maxX);
|
||||
Vector minY = getIntermediateWithYValue(origin, end, self.minY);
|
||||
Vector maxY = getIntermediateWithYValue(origin, end, self.maxY);
|
||||
Vector minZ = getIntermediateWithZValue(origin, end, self.minZ);
|
||||
Vector maxZ = getIntermediateWithZValue(origin, end, self.maxZ);
|
||||
|
||||
BlockFace bestFace = null;
|
||||
|
||||
@@ -50,7 +45,7 @@ public class ReachUtils {
|
||||
maxZ = null;
|
||||
}
|
||||
|
||||
Vector3D best = null;
|
||||
Vector best = null;
|
||||
|
||||
if (minX != null) {
|
||||
best = minX;
|
||||
@@ -89,7 +84,7 @@ public class ReachUtils {
|
||||
* Returns a new vector with x value equal to the second parameter, along the line between this vector and the
|
||||
* passed in vector, or null if not possible.
|
||||
*/
|
||||
public static Vector3D getIntermediateWithXValue(Vector3D self, Vector3D other, double x) {
|
||||
public static Vector getIntermediateWithXValue(Vector self, Vector other, double x) {
|
||||
double d0 = other.getX() - self.getX();
|
||||
double d1 = other.getY() - self.getY();
|
||||
double d2 = other.getZ() - self.getZ();
|
||||
@@ -98,7 +93,7 @@ public class ReachUtils {
|
||||
return null;
|
||||
} else {
|
||||
double d3 = (x - self.getX()) / d0;
|
||||
return d3 >= 0.0D && d3 <= 1.0D ? newVector3D(self.getX() + d0 * d3, self.getY() + d1 * d3, self.getZ() + d2 * d3) : null;
|
||||
return d3 >= 0.0D && d3 <= 1.0D ? new Vector(self.getX() + d0 * d3, self.getY() + d1 * d3, self.getZ() + d2 * d3) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +101,7 @@ public class ReachUtils {
|
||||
* Returns a new vector with y value equal to the second parameter, along the line between this vector and the
|
||||
* passed in vector, or null if not possible.
|
||||
*/
|
||||
public static Vector3D getIntermediateWithYValue(Vector3D self, Vector3D other, double y) {
|
||||
public static Vector getIntermediateWithYValue(Vector self, Vector other, double y) {
|
||||
double d0 = other.getX() - self.getX();
|
||||
double d1 = other.getY() - self.getY();
|
||||
double d2 = other.getZ() - self.getZ();
|
||||
@@ -115,7 +110,7 @@ public class ReachUtils {
|
||||
return null;
|
||||
} else {
|
||||
double d3 = (y - self.getY()) / d1;
|
||||
return d3 >= 0.0D && d3 <= 1.0D ? newVector3D(self.getX() + d0 * d3, self.getY() + d1 * d3, self.getZ() + d2 * d3) : null;
|
||||
return d3 >= 0.0D && d3 <= 1.0D ? new Vector(self.getX() + d0 * d3, self.getY() + d1 * d3, self.getZ() + d2 * d3) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +118,7 @@ public class ReachUtils {
|
||||
* Returns a new vector with z value equal to the second parameter, along the line between this vector and the
|
||||
* passed in vector, or null if not possible.
|
||||
*/
|
||||
public static Vector3D getIntermediateWithZValue(Vector3D self, Vector3D other, double z) {
|
||||
public static Vector getIntermediateWithZValue(Vector self, Vector other, double z) {
|
||||
double d0 = other.getX() - self.getX();
|
||||
double d1 = other.getY() - self.getY();
|
||||
double d2 = other.getZ() - self.getZ();
|
||||
@@ -132,51 +127,51 @@ public class ReachUtils {
|
||||
return null;
|
||||
} else {
|
||||
double d3 = (z - self.getZ()) / d2;
|
||||
return d3 >= 0.0D && d3 <= 1.0D ? newVector3D(self.getX() + d0 * d3, self.getY() + d1 * d3, self.getZ() + d2 * d3) : null;
|
||||
return d3 >= 0.0D && d3 <= 1.0D ? new Vector(self.getX() + d0 * d3, self.getY() + d1 * d3, self.getZ() + d2 * d3) : null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified vector is within the YZ dimensions of the bounding box. Args: Vec3D
|
||||
*/
|
||||
private static boolean isVecInYZ(SimpleCollisionBox self, Vector3D vec) {
|
||||
private static boolean isVecInYZ(SimpleCollisionBox self, Vector vec) {
|
||||
return vec != null && vec.getY() >= self.minY && vec.getY() <= self.maxY && vec.getZ() >= self.minZ && vec.getZ() <= self.maxZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified vector is within the XZ dimensions of the bounding box. Args: Vec3D
|
||||
*/
|
||||
private static boolean isVecInXZ(SimpleCollisionBox self, Vector3D vec) {
|
||||
private static boolean isVecInXZ(SimpleCollisionBox self, Vector vec) {
|
||||
return vec != null && vec.getX() >= self.minX && vec.getX() <= self.maxX && vec.getZ() >= self.minZ && vec.getZ() <= self.maxZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified vector is within the XY dimensions of the bounding box. Args: Vec3D
|
||||
*/
|
||||
private static boolean isVecInXY(SimpleCollisionBox self, Vector3D vec) {
|
||||
private static boolean isVecInXY(SimpleCollisionBox self, Vector vec) {
|
||||
return vec != null && vec.getX() >= self.minX && vec.getX() <= self.maxX && vec.getY() >= self.minY && vec.getY() <= self.maxY;
|
||||
}
|
||||
|
||||
// Look vector accounting for optifine FastMath, and client version differences
|
||||
public static Vector3D getLook(GrimPlayer player, float yaw, float pitch) {
|
||||
if (player.getClientVersion().isOlderThanOrEquals(V_1_12_2)) {
|
||||
float f = player.trigHandler.cos(-yaw * 0.017453292F - (float) PI);
|
||||
float f1 = player.trigHandler.sin(-yaw * 0.017453292F - (float) PI);
|
||||
public static Vector getLook(GrimPlayer player, float yaw, float pitch) {
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_12_2)) {
|
||||
float f = player.trigHandler.cos(-yaw * 0.017453292F - (float)Math.PI);
|
||||
float f1 = player.trigHandler.sin(-yaw * 0.017453292F - (float)Math.PI);
|
||||
float f2 = -player.trigHandler.cos(-pitch * 0.017453292F);
|
||||
float f3 = player.trigHandler.sin(-pitch * 0.017453292F);
|
||||
return newVector3D(f1 * f2, f3, f * f2);
|
||||
return new Vector(f1 * f2, f3, f * f2);
|
||||
} else {
|
||||
float f = pitch * ((float) PI / 180F);
|
||||
float f1 = -yaw * ((float) PI / 180F);
|
||||
float f = pitch * ((float) Math.PI / 180F);
|
||||
float f1 = -yaw * ((float) Math.PI / 180F);
|
||||
float f2 = player.trigHandler.cos(f1);
|
||||
float f3 = player.trigHandler.sin(f1);
|
||||
float f4 = player.trigHandler.cos(f);
|
||||
float f5 = player.trigHandler.sin(f);
|
||||
return newVector3D(f3 * f4, -f5, (double) (f2 * f4));
|
||||
return new Vector(f3 * f4, -f5, (double) (f2 * f4));
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isVecInside(SimpleCollisionBox self, Vector3D vec) {
|
||||
public static boolean isVecInside(SimpleCollisionBox self, Vector vec) {
|
||||
return vec.getX() > self.minX && vec.getX() < self.maxX && (vec.getY() > self.minY && vec.getY() < self.maxY && vec.getZ() > self.minZ && vec.getZ() < self.maxZ);
|
||||
}
|
||||
|
||||
@@ -189,8 +184,8 @@ public class ReachUtils {
|
||||
if (giveMovementThresholdLenience) targetBox.expand(player.getMovementThreshold());
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
for (double eyes : possibleEyeHeights) {
|
||||
Vector3D from = newVector3D(player.x, player.y + eyes, player.z);
|
||||
Vector3D closestPoint = VectorUtils.cutBoxToVector(from, targetBox);
|
||||
Vector from = new Vector(player.x, player.y + eyes, player.z);
|
||||
Vector closestPoint = VectorUtils.cutBoxToVector(from, targetBox);
|
||||
lowest = Math.min(lowest, closestPoint.distance(from));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,37 +1,32 @@
|
||||
package ac.grim.grimac.utils.nmsutil;
|
||||
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
import static com.github.retrooper.packetevents.PacketEvents.getAPI;
|
||||
import static com.github.retrooper.packetevents.protocol.item.enchantment.type.EnchantmentTypes.RIPTIDE;
|
||||
import static com.github.retrooper.packetevents.protocol.item.type.ItemTypes.TRIDENT;
|
||||
import static java.lang.Math.PI;
|
||||
import static java.lang.Math.sqrt;
|
||||
import com.github.retrooper.packetevents.protocol.item.enchantment.type.EnchantmentTypes;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class Riptide {
|
||||
public static Vector3D getRiptideVelocity(GrimPlayer player) {
|
||||
public static Vector getRiptideVelocity(GrimPlayer player) {
|
||||
ItemStack main = player.getInventory().getHeldItem();
|
||||
ItemStack off = player.getInventory().getOffHand();
|
||||
|
||||
int j;
|
||||
if (main.getType() == TRIDENT) {
|
||||
j = main.getEnchantmentLevel(RIPTIDE, getAPI().getServerManager().getVersion().toClientVersion());
|
||||
} else if (off.getType() == TRIDENT) {
|
||||
j = off.getEnchantmentLevel(RIPTIDE, getAPI().getServerManager().getVersion().toClientVersion());
|
||||
if (main.getType() == ItemTypes.TRIDENT) {
|
||||
j = main.getEnchantmentLevel(EnchantmentTypes.RIPTIDE, PacketEvents.getAPI().getServerManager().getVersion().toClientVersion());
|
||||
} else if (off.getType() == ItemTypes.TRIDENT) {
|
||||
j = off.getEnchantmentLevel(EnchantmentTypes.RIPTIDE, PacketEvents.getAPI().getServerManager().getVersion().toClientVersion());
|
||||
} else {
|
||||
return newVector3D(); // Can't riptide
|
||||
return new Vector(); // Can't riptide
|
||||
}
|
||||
|
||||
float f7 = player.xRot;
|
||||
float f = player.yRot;
|
||||
float f1 = -player.trigHandler.sin(f7 * ((float) PI / 180F)) * player.trigHandler.cos(f * ((float) PI / 180F));
|
||||
float f2 = -player.trigHandler.sin(f * ((float) PI / 180F));
|
||||
float f3 = player.trigHandler.cos(f7 * ((float) PI / 180F)) * player.trigHandler.cos(f * ((float) PI / 180F));
|
||||
float f4 = (float) sqrt(f1 * f1 + f2 * f2 + f3 * f3);
|
||||
float f1 = -player.trigHandler.sin(f7 * ((float) Math.PI / 180F)) * player.trigHandler.cos(f * ((float) Math.PI / 180F));
|
||||
float f2 = -player.trigHandler.sin(f * ((float) Math.PI / 180F));
|
||||
float f3 = player.trigHandler.cos(f7 * ((float) Math.PI / 180F)) * player.trigHandler.cos(f * ((float) Math.PI / 180F));
|
||||
float f4 = (float) Math.sqrt(f1 * f1 + f2 * f2 + f3 * f3);
|
||||
float f5 = 3.0F * ((1.0F + j) / 4.0F);
|
||||
f1 = f1 * (f5 / f4);
|
||||
f2 = f2 * (f5 / f4);
|
||||
@@ -39,8 +34,8 @@ public class Riptide {
|
||||
|
||||
// If the player collided vertically with the 1.199999F pushing movement, then the Y additional movement was added
|
||||
// (We switched the order around as our prediction engine isn't designed for the proper implementation)
|
||||
if (player.verticalCollision) return newVector3D(f1, 0, f3);
|
||||
if (player.verticalCollision) return new Vector(f1, 0, f3);
|
||||
|
||||
return newVector3D(f1, f2, f3);
|
||||
return new Vector(f1, f2, f3);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package ac.grim.grimac.utils.vector;
|
||||
|
||||
public class BasicVectorOps implements VectorOperations {
|
||||
|
||||
@Override
|
||||
public Vector3D newVector(double x, double y, double z) {
|
||||
return new ScalarVector3D(x, y, z);
|
||||
}
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
package ac.grim.grimac.utils.vector;
|
||||
|
||||
import one.nalim.Library;
|
||||
import one.nalim.Link;
|
||||
import one.nalim.Linker;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Arrays;
|
||||
|
||||
@Library("vector_ops")
|
||||
public class NalimVector3D implements Vector3D {
|
||||
|
||||
static {
|
||||
Linker.linkClass(NalimVector3D.class);
|
||||
}
|
||||
|
||||
double[] loc;
|
||||
|
||||
// public final long nativePtr; // Holds pointer to SimdVector
|
||||
// @Link(name = "create_vector")
|
||||
// private static native long create_vector(double x, double y, double z);
|
||||
|
||||
public NalimVector3D(double x, double y, double z) {
|
||||
loc = new double[]{x, y, z};
|
||||
// nativePtr = create_vector(0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getX() {
|
||||
return loc[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getY() {
|
||||
return loc[1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getZ() {
|
||||
return loc[2];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3D setX(double x) {
|
||||
loc[0] = x;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Vector3D setY(double y) {
|
||||
loc[1] =y;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3D setZ(double z) {
|
||||
loc[2] = z;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double length() {
|
||||
return Math.sqrt(loc[0] * loc[0] + loc[1] * loc[1] + loc[2] * loc[2]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double lengthSquared() {
|
||||
return loc[0] * loc[0] + loc[1] * loc[1] + loc[2] * loc[2];
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Vector3D multiply(double m) {
|
||||
loc[0] *= m;
|
||||
loc[1] *= m;
|
||||
loc[2] *= m;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Vector3D normalize() {
|
||||
double length = this.length();
|
||||
loc[0] /= length;
|
||||
loc[1] /= length;
|
||||
loc[2] /= length;
|
||||
return this;
|
||||
}
|
||||
|
||||
// @Link(name = "delete_vector2")
|
||||
// private static native void delete_vector(long[] x);
|
||||
|
||||
@IntrinsicCandidate @ForceInline @Link(name = "cross_product2")
|
||||
private static native void crossProduct(double[] a, double[] b);
|
||||
|
||||
@IntrinsicCandidate @ForceInline @Link(name = "cross_product")
|
||||
private static native void cross_product(long a, long b);
|
||||
|
||||
@Override
|
||||
public @NotNull Vector3D crossProduct(@NotNull Vector3D o) {
|
||||
// cross_product(nativePtr, ((NalimVector3D) o).nativePtr);
|
||||
crossProduct(this.loc, ((NalimVector3D) o).loc);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Vector3D add(@NotNull Vector3D vec) {
|
||||
loc[0] += vec.getX();
|
||||
loc[1] += vec.getY();
|
||||
loc[2] += vec.getZ();
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Vector3D subtract(@NotNull Vector3D vec) {
|
||||
loc[0] -= vec.getX();
|
||||
loc[1] -= vec.getY();
|
||||
loc[2] -= vec.getZ();
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Vector3D multiply(@NotNull Vector3D vec) {
|
||||
loc[0] *= vec.getX();
|
||||
loc[1] *= vec.getY();
|
||||
loc[2] *= vec.getZ();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double distance(@NotNull Vector3D o) {
|
||||
return Math.sqrt(distanceSquared(o));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double distanceSquared(@NotNull Vector3D o) {
|
||||
return (loc[0] - o.getX()) * (loc[0] - o.getX())
|
||||
+ (loc[1] - o.getY()) * (loc[1] - o.getY())
|
||||
+ (loc[2] - o.getZ()) * (loc[2] - o.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double dot(@NotNull Vector3D other) {
|
||||
return loc[0] * other.getX() + loc[1] * other.getY() + loc[2] * other.getZ();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Vector3D clone() {
|
||||
try {
|
||||
return (Vector3D) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loaded 100 of 113 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user