Compare commits
122
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
513e42c58e | ||
|
|
e1281c24fa | ||
|
|
82bb743120 | ||
|
|
85ed18e108 | ||
|
|
61a9bae878 | ||
|
|
d0ff246b03 | ||
|
|
f84321b7e7 | ||
|
|
72b1ec2665 | ||
|
|
2337386b37 | ||
|
|
d1288bf4af | ||
|
|
0072bfdee5 | ||
|
|
6b2153f03e | ||
|
|
ab86e65a65 | ||
|
|
1f2b6977b9 | ||
|
|
d5847f73d3 | ||
|
|
4e5e20280f | ||
|
|
baba4d6f6e | ||
|
|
97abaaf8ad | ||
|
|
1f3ac2a174 | ||
|
|
ff0629d0b7 | ||
|
|
9936984534 | ||
|
|
ca56975136 | ||
|
|
348daf6a52 | ||
|
|
d67b470ff6 | ||
|
|
130f9e1023 | ||
|
|
eaac8ad908 | ||
|
|
89f8696d88 | ||
|
|
940a1f819f | ||
|
|
3f01edba9d | ||
|
|
24409a5771 | ||
|
|
88e0f98241 | ||
|
|
fde99a7cbf | ||
|
|
1c3929834a | ||
|
|
3a839d7240 | ||
|
|
7737337a86 | ||
|
|
88dc6a42a9 | ||
|
|
bcc93aab4a | ||
|
|
b88561284c | ||
|
|
5fd8230884 | ||
|
|
ca0fa88a77 | ||
|
|
cbb3c1cc0f | ||
|
|
519968b85a | ||
|
|
6314b78e47 | ||
|
|
b791897dbc | ||
|
|
61af1d1e72 | ||
|
|
bf3fc94d92 | ||
|
|
1bb0bf7e76 | ||
|
|
c6cabe7ed6 | ||
|
|
4f2fe70300 | ||
|
|
52a611bf94 | ||
|
|
354564485a | ||
|
|
4887415912 | ||
|
|
7f0838832d | ||
|
|
336efafbd3 | ||
|
|
782f8f8a09 | ||
|
|
c1858e49d8 | ||
|
|
7dce3a7a12 | ||
|
|
7786da7296 | ||
|
|
bc365176b1 | ||
|
|
7fe224c206 | ||
|
|
48e5f54341 | ||
|
|
5edf92f124 | ||
|
|
1c3e938f0f | ||
|
|
ec71581eae | ||
|
|
0904b61df0 | ||
|
|
c9e082257c | ||
|
|
8875bbf991 | ||
|
|
e933186d2e | ||
|
|
89bec80b34 | ||
|
|
cc78eca02f | ||
|
|
77a91ec627 | ||
|
|
1036563b24 | ||
|
|
dd5ea74ae4 | ||
|
|
aa7a4dc155 | ||
|
|
3387365732 | ||
|
|
411aa4f2b2 | ||
|
|
63a8e394a9 | ||
|
|
9804b8b62f | ||
|
|
f82cce32f6 | ||
|
|
474ae7dd27 | ||
|
|
d85c1d267b | ||
|
|
6ce2bcb9e9 | ||
|
|
48eff610c3 | ||
|
|
677dd044ff | ||
|
|
87f30eea37 | ||
|
|
370da407ce | ||
|
|
1ef4b4eec9 | ||
|
|
954eb8b51c | ||
|
|
84ceaa29dc | ||
|
|
6974d61b9d | ||
|
|
d9a3a890c8 | ||
|
|
c4495d995a | ||
|
|
9bd5c2db0b | ||
|
|
2518b23f8b | ||
|
|
bd2ceeeed4 | ||
|
|
a6d082b355 | ||
|
|
8af0dbc46d | ||
|
|
3fedd558d6 | ||
|
|
547a2965dd | ||
|
|
c19914e83f | ||
|
|
6c14faa51d | ||
|
|
6b4060e0c4 | ||
|
|
483706151b | ||
|
|
9dc128cc1d | ||
|
|
50b7e84f58 | ||
|
|
a77067ffe5 | ||
|
|
2a49635497 | ||
|
|
a158019d66 | ||
|
|
5f7d296b4d | ||
|
|
c4cd8136bf | ||
|
|
dbc0c11795 | ||
|
|
d30b024bd3 | ||
|
|
a3e979abc8 | ||
|
|
93f14a5b40 | ||
|
|
2de0f49af9 | ||
|
|
39a53db067 | ||
|
|
9bfc7d7d9b | ||
|
|
7c93eda985 | ||
|
|
1e7a858aa0 | ||
|
|
11fba1b6bd | ||
|
|
ce9d66c199 | ||
|
|
330a9782bc |
No files matched your search
+173
-4
@@ -30,12 +30,15 @@ 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(17))
|
||||
toolchain.languageVersion.set(JavaLanguageVersion.of(18))
|
||||
}
|
||||
|
||||
// Set to false for debug builds
|
||||
// You cannot live reload classes if the jar relocates dependencies
|
||||
var relocate = true;
|
||||
// Checks Project properties -> environment variable -> defaults true
|
||||
val relocate: Boolean = project.findProperty("relocate")?.toString()?.toBoolean()
|
||||
?: System.getenv("RELOCATE_JAR")?.toBoolean()
|
||||
?: true
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
@@ -56,11 +59,18 @@ repositories {
|
||||
// FastUtil, Discord-Webhooks
|
||||
}
|
||||
|
||||
// Add JMH configuration
|
||||
configurations {
|
||||
create("jmh")
|
||||
create("jmhAnnotationProcessor")
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
implementation("com.github.retrooper:packetevents-spigot:2.5.1-SNAPSHOT")
|
||||
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.13")
|
||||
implementation("it.unimi.dsi:fastutil:8.5.15")
|
||||
implementation("github.scarsz:configuralize:1.4.0")
|
||||
|
||||
//implementation("com.github.grimanticheat:grimapi:1193c4fa41")
|
||||
@@ -73,6 +83,12 @@ 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 {
|
||||
@@ -140,6 +156,16 @@ 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,6 +182,71 @@ 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")
|
||||
@@ -179,3 +270,81 @@ 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")
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
//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();
|
||||
// }
|
||||
//}
|
||||
@@ -0,0 +1,114 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
//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();
|
||||
// }
|
||||
//}
|
||||
@@ -0,0 +1,114 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
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,6 +8,8 @@ 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;
|
||||
@@ -150,6 +152,39 @@ 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,6 +6,7 @@ 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")
|
||||
@@ -23,10 +24,12 @@ 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) {
|
||||
} else if (event.getPacketType() == PacketType.Play.Client.STEER_VEHICLE
|
||||
|| (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21_2) && player.compensatedEntities.getSelf().inVehicle())) {
|
||||
noReminderTicks = 0; // Exempt vehicles
|
||||
}
|
||||
|
||||
|
||||
if (noReminderTicks > 20) {
|
||||
flagAndAlert("ticks=" + noReminderTicks); // ban? I don't know how this would false
|
||||
}
|
||||
|
||||
@@ -10,8 +10,7 @@ import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEn
|
||||
|
||||
@CheckData(name = "BadPacketsG")
|
||||
public class BadPacketsG extends Check implements PacketCheck {
|
||||
boolean wasTeleport;
|
||||
boolean lastSneaking;
|
||||
private boolean lastSneaking, respawn;
|
||||
|
||||
public BadPacketsG(GrimPlayer player) {
|
||||
super(player);
|
||||
@@ -19,13 +18,12 @@ 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) {
|
||||
if (lastSneaking && !wasTeleport) {
|
||||
// The player may send two START_SNEAKING packets if they respawned
|
||||
if (lastSneaking && !respawn) {
|
||||
if (flagAndAlert("state=true") && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -33,8 +31,9 @@ public class BadPacketsG extends Check implements PacketCheck {
|
||||
} else {
|
||||
lastSneaking = true;
|
||||
}
|
||||
respawn = false;
|
||||
} else if (packet.getAction() == WrapperPlayClientEntityAction.Action.STOP_SNEAKING) {
|
||||
if (!lastSneaking && !wasTeleport) {
|
||||
if (!lastSneaking && !respawn) {
|
||||
if (flagAndAlert("state=false") && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -42,7 +41,13 @@ 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()) {
|
||||
if (!sentAnimation && flagAndAlert() && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
|
||||
@@ -41,7 +41,8 @@ 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 && player.compensatedEntities.getSelf().inVehicle()) {
|
||||
} else if ((event.getPacketType() == PacketType.Play.Client.STEER_VEHICLE || event.getPacketType() == PacketType.Play.Client.VEHICLE_MOVE)
|
||||
&& player.inVehicle()) {
|
||||
positions++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,53 @@
|
||||
package ac.grim.grimac.checks.impl.badpackets;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
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 ac.grim.grimac.utils.anticheat.update.BlockBreak;
|
||||
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.type.StateType;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
|
||||
@CheckData(name = "BadPacketsX", experimental = true)
|
||||
@CheckData(name = "BadPacketsX")
|
||||
public class BadPacketsX extends Check implements PacketCheck {
|
||||
public BadPacketsX(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
private int lastTick;
|
||||
private boolean didLastFlag;
|
||||
private Vector3i lastBreakLoc;
|
||||
private StateType lastBlockType;
|
||||
|
||||
public final boolean noFireHitbox = player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_15_2);
|
||||
|
||||
public final void handle(PacketReceiveEvent event, WrapperPlayClientPlayerDigging dig, StateType block) {
|
||||
if (dig.getAction() != DiggingAction.START_DIGGING && dig.getAction() != DiggingAction.FINISHED_DIGGING)
|
||||
public final void handle(BlockBreak blockBreak) {
|
||||
if (blockBreak.action != DiggingAction.START_DIGGING && blockBreak.action != 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)
|
||||
&& !didLastFlag
|
||||
&& lastBlockType.getHardness() == 0.0F
|
||||
&& lastBlockType.getBlastResistance() == 0.0F
|
||||
&& block == StateTypes.WATER
|
||||
) return;
|
||||
lastTick = newTick;
|
||||
lastBreakLoc = blockBreak.position;
|
||||
lastBlockType = block;
|
||||
|
||||
// the block does not have a hitbox
|
||||
boolean invalid = (block == StateTypes.LIGHT && !(player.getInventory().getHeldItem().is(ItemTypes.LIGHT) || player.getInventory().getOffHand().is(ItemTypes.LIGHT)))
|
||||
|| block.isAir()
|
||||
@@ -31,13 +55,15 @@ 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 && dig.getAction() == DiggingAction.FINISHED_DIGGING;
|
||||
|| block.getHardness() == -1.0f && blockBreak.action == DiggingAction.FINISHED_DIGGING;
|
||||
|
||||
if (invalid && flagAndAlert("block=" + block.getName() + ", type=" + dig.getAction()) && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
if (invalid && flagAndAlert("block=" + block.getName() + ", type=" + blockBreak.action) && shouldModifyPackets()) {
|
||||
didLastFlag = true;
|
||||
blockBreak.cancel();
|
||||
} else {
|
||||
didLastFlag = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,18 +5,17 @@ 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;
|
||||
|
||||
@CheckData(name = "BadPacketsZ", experimental = true)
|
||||
@CheckData(name = "BadPacketsZ")
|
||||
public class BadPacketsZ extends Check implements PacketCheck {
|
||||
public BadPacketsZ(final GrimPlayer player) {
|
||||
super(player);
|
||||
@@ -40,9 +39,9 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
return player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) || getBlockDamage(player, pos) < 1;
|
||||
}
|
||||
|
||||
public void handle(PacketReceiveEvent event, WrapperPlayClientPlayerDigging dig) {
|
||||
if (dig.getAction() == DiggingAction.START_DIGGING) {
|
||||
final Vector3i pos = dig.getBlockPosition();
|
||||
public void handle(BlockBreak blockBreak) {
|
||||
if (blockBreak.action == DiggingAction.START_DIGGING) {
|
||||
final Vector3i pos = blockBreak.position;
|
||||
|
||||
lastBlockWasInstantBreak = getBlockDamage(player, pos) >= 1;
|
||||
lastCancelledBlock = null;
|
||||
@@ -50,8 +49,8 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
lastBlock = pos;
|
||||
}
|
||||
|
||||
if (dig.getAction() == DiggingAction.CANCELLED_DIGGING) {
|
||||
final Vector3i pos = dig.getBlockPosition();
|
||||
if (blockBreak.action == DiggingAction.CANCELLED_DIGGING) {
|
||||
final Vector3i pos = blockBreak.position;
|
||||
|
||||
if (shouldExempt(pos)) {
|
||||
lastCancelledBlock = pos;
|
||||
@@ -65,8 +64,7 @@ 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()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
blockBreak.cancel();
|
||||
resyncPosition(player, pos);
|
||||
}
|
||||
}
|
||||
@@ -79,15 +77,14 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dig.getAction() == DiggingAction.FINISHED_DIGGING) {
|
||||
final Vector3i pos = dig.getBlockPosition();
|
||||
if (blockBreak.action == DiggingAction.FINISHED_DIGGING) {
|
||||
final Vector3i pos = blockBreak.position;
|
||||
|
||||
// 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()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
blockBreak.cancel();
|
||||
resyncPosition(player, pos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ public class MultiInteractA extends Check implements PostPredictionCheck {
|
||||
// we don't need to check pre-1.9 players here (no tick skipping)
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) return;
|
||||
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
if (player.isTickingReliablyFor(3) && !player.uncertaintyHandler.lastVehicleSwitch.hasOccurredSince(0)) {
|
||||
for (String verbose : flags) {
|
||||
flagAndAlert(verbose);
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public class MultiInteractB extends Check implements PostPredictionCheck {
|
||||
// we don't need to check pre-1.9 players here (no tick skipping)
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) return;
|
||||
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
if (player.isTickingReliablyFor(3) && !player.uncertaintyHandler.lastVehicleSwitch.hasOccurredSince(0)) {
|
||||
for (String verbose : flags) {
|
||||
flagAndAlert(verbose);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ 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;
|
||||
@@ -33,13 +34,14 @@ 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
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 {
|
||||
@@ -108,9 +110,7 @@ public class Reach extends Check implements PacketCheck {
|
||||
}
|
||||
|
||||
// If the player set their look, or we know they have a new tick
|
||||
if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType()) ||
|
||||
event.getPacketType() == PacketType.Play.Client.PONG ||
|
||||
event.getPacketType() == PacketType.Play.Client.WINDOW_CONFIRMATION) {
|
||||
if (isUpdate(event.getPacketType())) {
|
||||
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<Vector> possibleLookDirs = new ArrayList<>(Collections.singletonList(ReachUtils.getLook(player, player.xRot, player.yRot)));
|
||||
List<Vector3D> 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 (Vector lookVec : possibleLookDirs) {
|
||||
for (Vector3D lookVec : possibleLookDirs) {
|
||||
for (double eye : possibleEyeHeights) {
|
||||
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));
|
||||
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 intercept = ReachUtils.calculateIntercept(targetBox, eyePos, endReachPos).first();
|
||||
Vector3D intercept = ReachUtils.calculateIntercept(targetBox, eyePos, endReachPos).first();
|
||||
|
||||
if (ReachUtils.isVecInside(targetBox, eyePos)) {
|
||||
minDistance = 0;
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
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,7 +8,6 @@ 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 {
|
||||
@@ -18,10 +17,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?
|
||||
// How long should the player be able to fall back behind their ping? (nanos)
|
||||
// Default: 120 milliseconds
|
||||
long clockDrift;
|
||||
|
||||
// At what ping should we start to limit the balance advantage? (nanos)
|
||||
long limitAbuseOverPing;
|
||||
|
||||
boolean hasGottenMovementAfterTransaction = false;
|
||||
@@ -73,35 +72,31 @@ public class TimerCheck extends Check implements PacketCheck {
|
||||
doCheck(event);
|
||||
}
|
||||
|
||||
|
||||
public void doCheck(final PacketReceiveEvent event) {
|
||||
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 (timerBalanceRealTime > System.nanoTime()) {
|
||||
if (flag()) {
|
||||
// Cancel the packet
|
||||
// Only cancel if not an adjustment setback
|
||||
if (wouldFailNormal && shouldModifyPackets()) {
|
||||
if (shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
|
||||
if (isAboveSetbackVl()) player.getSetbackTeleportUtil().executeNonSimulatingSetback();
|
||||
|
||||
if (wouldFailNormal) {
|
||||
// Only alert if we would fail without adjusted limit
|
||||
alert("");
|
||||
}
|
||||
alert("");
|
||||
}
|
||||
|
||||
// Reset the violation by 1 movement
|
||||
timerBalanceRealTime -= 50e6;
|
||||
}
|
||||
|
||||
timerBalanceRealTime = Math.max(timerBalanceRealTime, lastMovementPlayerClock - clockDrift);
|
||||
// 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);
|
||||
}
|
||||
|
||||
public boolean checkForTransaction(PacketTypeCommon packetType) {
|
||||
@@ -111,13 +106,12 @@ 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 WrapperPlayClientPlayerFlying.isFlying(packetType) &&
|
||||
!player.packetStateData.lastPacketWasTeleport && !player.packetStateData.lastPacketWasOnePointSeventeenDuplicate;
|
||||
return isTickPacket(packetType);
|
||||
}
|
||||
|
||||
@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));
|
||||
limitAbuseOverPing = (long) (config.getDoubleElse(getConfigName() + ".ping-abuse-limit-threshold", 1000) * 1e6);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
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,7 +15,6 @@ 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;
|
||||
@@ -43,7 +42,7 @@ public class PostCheck extends Check implements PacketCheck, PostPredictionCheck
|
||||
// Okay, the user might be cheating, let's double check
|
||||
// 1.8 clients have the idle packet, and this shouldn't false on 1.8 clients
|
||||
// 1.9+ clients have predictions, which will determine if hidden tick skipping occurred
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
if (player.isTickingReliablyFor(3) && !player.uncertaintyHandler.lastVehicleSwitch.hasOccurredSince(0)) {
|
||||
for (String flag : flags) {
|
||||
flagAndAlert(flag);
|
||||
}
|
||||
@@ -68,12 +67,7 @@ public class PostCheck extends Check implements PacketCheck, PostPredictionCheck
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(final PacketReceiveEvent event) {
|
||||
if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) {
|
||||
// Don't count teleports or duplicates as movements
|
||||
if (player.packetStateData.lastPacketWasTeleport || player.packetStateData.lastPacketWasOnePointSeventeenDuplicate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isTickPacket(event.getPacketType())) { // Don't count teleports or duplicates as movements
|
||||
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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -45,8 +45,8 @@ public class DebugHandler extends Check implements PostPredictionCheck {
|
||||
|
||||
ChatColor color = pickColor(offset, offset);
|
||||
|
||||
Vector predicted = player.predictedVelocity.vector;
|
||||
Vector actually = player.actualMovement;
|
||||
Vector3D predicted = player.predictedVelocity.vector;
|
||||
Vector3D actually = player.actualMovement;
|
||||
|
||||
ChatColor xColor = pickColor(Math.abs(predicted.getX() - actually.getX()), offset);
|
||||
ChatColor yColor = pickColor(Math.abs(predicted.getY() - actually.getY()), offset);
|
||||
|
||||
@@ -9,7 +9,9 @@ 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
@CheckData(name = "FarPlace")
|
||||
public class FarPlace extends BlockPlaceCheck {
|
||||
@@ -27,8 +29,8 @@ public class FarPlace extends BlockPlaceCheck {
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
for (double d : possibleEyeHeights) {
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(blockPos);
|
||||
Vector eyes = new Vector(player.x, player.y + d, player.z);
|
||||
Vector best = VectorUtils.cutBoxToVector(eyes, box);
|
||||
Vector3D eyes = newVector3D(player.x, player.y + d, player.z);
|
||||
Vector3D best = VectorUtils.cutBoxToVector(eyes, box);
|
||||
min = Math.min(min, eyes.distanceSquared(best));
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ 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;
|
||||
@@ -56,14 +55,14 @@ public class MultiPlace extends BlockPlaceCheck {
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType()) && !player.packetStateData.lastPacketWasTeleport && !player.packetStateData.lastPacketWasOnePointSeventeenDuplicate) {
|
||||
if (isTickPacket(event.getPacketType())) {
|
||||
hasPlaced = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (player.getClientVersion().isNewerThan(ClientVersion.V_1_8) && player.isTickingReliablyFor(3)) {
|
||||
if (player.getClientVersion().isNewerThan(ClientVersion.V_1_8) && player.isTickingReliablyFor(3) && !player.uncertaintyHandler.lastVehicleSwitch.hasOccurredSince(0)) {
|
||||
for (String verbose : flags) {
|
||||
flagAndAlert(verbose);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ 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;
|
||||
@@ -15,7 +16,6 @@ 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<Vector, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
Pair<Vector3D, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
|
||||
if (intercept.first() != null) return true;
|
||||
}
|
||||
|
||||
@@ -19,12 +19,13 @@ 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<>();
|
||||
@@ -121,7 +122,7 @@ public class ExplosionHandler extends Check implements PostPredictionCheck {
|
||||
}
|
||||
|
||||
public void addPlayerExplosion(int breadOne, Vector3f explosion) {
|
||||
firstBreadMap.add(new VelocityData(-1, breadOne, player.getSetbackTeleportUtil().isSendingSetback, new Vector(explosion.getX(), explosion.getY(), explosion.getZ())));
|
||||
firstBreadMap.add(new VelocityData(-1, breadOne, player.getSetbackTeleportUtil().isSendingSetback, newVector3D(explosion.getX(), explosion.getY(), explosion.getZ())));
|
||||
}
|
||||
|
||||
public void setPointThree(boolean isPointThree) {
|
||||
|
||||
@@ -15,12 +15,14 @@ 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
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 {
|
||||
@@ -66,16 +68,17 @@ 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(), new Vector(playerVelocity.getX(), playerVelocity.getY(), playerVelocity.getZ()));
|
||||
addPlayerKnockback(entityId, player.lastTransactionSent.get(), newVector3D(playerVelocity.getX(), playerVelocity.getY(), playerVelocity.getZ()));
|
||||
event.getTasksAfterSend().add(player::sendTransaction);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull public Pair<VelocityData, Vector> getFutureKnockback() {
|
||||
@NotNull public Pair<VelocityData, Vector3D> getFutureKnockback() {
|
||||
// Chronologically in the future
|
||||
if (firstBreadMap.size() > 0) {
|
||||
VelocityData data = firstBreadMap.peek();
|
||||
@@ -97,7 +100,7 @@ public class KnockbackHandler extends Check implements PostPredictionCheck {
|
||||
return new Pair<>(null, null);
|
||||
}
|
||||
|
||||
private void addPlayerKnockback(int entityID, int breadOne, Vector knockback) {
|
||||
private void addPlayerKnockback(int entityID, int breadOne, Vector3D knockback) {
|
||||
firstBreadMap.add(new VelocityData(entityID, breadOne, player.getSetbackTeleportUtil().isSendingSetback, knockback));
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.update.BlockPlace;
|
||||
import ac.grim.grimac.utils.collisions.HitboxData;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.CollisionBox;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.ComplexCollisionBox;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.defaulttags.BlockTags;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
@@ -18,6 +19,7 @@ import java.util.List;
|
||||
public class BlockPlaceCheck extends Check implements RotationCheck, PostPredictionCheck {
|
||||
private static final List<StateType> weirdBoxes = new ArrayList<>();
|
||||
private static final List<StateType> buggyBoxes = new ArrayList<>();
|
||||
private final SimpleCollisionBox[] boxes = new SimpleCollisionBox[ComplexCollisionBox.DEFAULT_MAX_COLLISION_BOX_SIZE];
|
||||
|
||||
protected int cancelVL;
|
||||
|
||||
@@ -69,11 +71,11 @@ public class BlockPlaceCheck extends Check implements RotationCheck, PostPredict
|
||||
Vector3i clicked = place.getPlacedAgainstBlockLocation();
|
||||
CollisionBox placedOn = HitboxData.getBlockHitbox(player, place.getMaterial(), player.getClientVersion(), player.compensatedWorld.getWrappedBlockStateAt(clicked), clicked.getX(), clicked.getY(), clicked.getZ());
|
||||
|
||||
List<SimpleCollisionBox> boxes = new ArrayList<>();
|
||||
placedOn.downCast(boxes);
|
||||
int size = placedOn.downCast(boxes);
|
||||
|
||||
SimpleCollisionBox combined = new SimpleCollisionBox(clicked.getX(), clicked.getY(), clicked.getZ());
|
||||
for (SimpleCollisionBox box : boxes) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
SimpleCollisionBox box = boxes[i];
|
||||
double minX = Math.max(box.minX, combined.minX);
|
||||
double minY = Math.max(box.minY, combined.minY);
|
||||
double minZ = Math.max(box.minZ, combined.minZ);
|
||||
|
||||
@@ -1,19 +1,10 @@
|
||||
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 onPositionUpdate(final PositionUpdate positionUpdate) {
|
||||
}
|
||||
default void onPacketReceive(final PacketReceiveEvent event) {}
|
||||
default void onPacketSend(final PacketSendEvent event) {}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ package ac.grim.grimac.commands;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
import co.aikar.commands.BaseCommand;
|
||||
import co.aikar.commands.BukkitCommandCompletionContext;
|
||||
import co.aikar.commands.CommandCompletions.CommandCompletionHandler;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
@@ -10,16 +12,21 @@ import co.aikar.commands.annotation.Subcommand;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@CommandAlias("grim|grimac")
|
||||
public class GrimStopSpectating extends BaseCommand {
|
||||
public static final CommandCompletionHandler<BukkitCommandCompletionContext> completionHandler = context -> context.getSender().hasPermission("grim.spectate.stophere") ? List.of("here") : List.of();
|
||||
|
||||
@Subcommand("stopspectating")
|
||||
@CommandPermission("grim.spectate")
|
||||
@CommandCompletion("here")
|
||||
@CommandCompletion("@stopspectating")
|
||||
public void onStopSpectate(CommandSender sender, String[] args) {
|
||||
String string = args.length > 0 ? args[0] : null;
|
||||
if (!(sender instanceof Player player)) return;
|
||||
if (!(sender instanceof Player)) return;
|
||||
Player player = (Player) sender;
|
||||
if (GrimAPI.INSTANCE.getSpectateManager().isSpectating(player.getUniqueId())) {
|
||||
boolean teleportBack = string == null || !string.equalsIgnoreCase("here");
|
||||
boolean teleportBack = string == null || !string.equalsIgnoreCase("here") || !sender.hasPermission("grim.spectate.stophere");
|
||||
GrimAPI.INSTANCE.getSpectateManager().disable(player, teleportBack);
|
||||
} else {
|
||||
String message = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("cannot-spectate-return", "%prefix% &cYou can only do this after spectating a player.");
|
||||
|
||||
@@ -17,6 +17,8 @@ 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;
|
||||
@@ -47,7 +49,6 @@ 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;
|
||||
@@ -371,9 +372,7 @@ 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 -> {
|
||||
return !type.isAir() && type.getHardness() != -1.0f && type != StateTypes.WATER && type != StateTypes.LAVA;
|
||||
};
|
||||
private static final Function<StateType, Boolean> BREAKABLE = type -> !type.isAir() && type.getHardness() != -1.0f && type != StateTypes.WATER && type != StateTypes.LAVA;
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
@@ -455,43 +454,43 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Client.PLAYER_DIGGING) {
|
||||
WrapperPlayClientPlayerDigging dig = new WrapperPlayClientPlayerDigging(event);
|
||||
final Vector3i digPosition = dig.getBlockPosition();
|
||||
WrappedBlockState block = player.compensatedWorld.getWrappedBlockStateAt(digPosition);
|
||||
final StateType type = block.getType();
|
||||
final WrapperPlayClientPlayerDigging packet = new WrapperPlayClientPlayerDigging(event);
|
||||
final BlockBreak blockBreak = new BlockBreak(packet, player);
|
||||
|
||||
player.checkManager.getPacketCheck(BadPacketsX.class).handle(event, dig, type);
|
||||
player.checkManager.getPacketCheck(BadPacketsZ.class).handle(event, dig);
|
||||
player.checkManager.getPacketCheck(BadPacketsX.class).handle(blockBreak);
|
||||
player.checkManager.getPacketCheck(BadPacketsZ.class).handle(blockBreak);
|
||||
|
||||
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 (blockBreak.isCancelled()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
|
||||
if (!event.isCancelled()) {
|
||||
if (dig.getAction() == DiggingAction.START_DIGGING || dig.getAction() == DiggingAction.FINISHED_DIGGING || dig.getAction() == DiggingAction.CANCELLED_DIGGING) {
|
||||
player.compensatedWorld.handleBlockBreakPrediction(dig);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -578,6 +577,15 @@ 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;
|
||||
@@ -747,6 +755,10 @@ 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) {
|
||||
@@ -782,10 +794,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);
|
||||
Vector startingVec = new Vector(startingPos.getX(), startingPos.getY(), startingPos.getZ());
|
||||
Vector3D startingVec = VectorFactory.newVector3D(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);
|
||||
Vector endVec = trace.getPointAtDistance(distance);
|
||||
Vector3D endVec = trace.getPointAtDistance(distance);
|
||||
Vector3d endPos = new Vector3d(endVec.getX(), endVec.getY(), endVec.getZ());
|
||||
|
||||
return traverseBlocks(player, startingPos, endPos, (block, vector3i) -> {
|
||||
@@ -794,14 +806,14 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
data.downCast(boxes);
|
||||
|
||||
double bestHitResult = Double.MAX_VALUE;
|
||||
Vector bestHitLoc = null;
|
||||
Vector3D bestHitLoc = null;
|
||||
BlockFace bestFace = null;
|
||||
|
||||
for (SimpleCollisionBox box : boxes) {
|
||||
Pair<Vector, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
Pair<Vector3D, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
if (intercept.first() == null) continue; // No intercept
|
||||
|
||||
Vector hitLoc = intercept.first();
|
||||
Vector3D hitLoc = intercept.first();
|
||||
|
||||
if (hitLoc.distanceSquared(startingVec) < bestHitResult) {
|
||||
bestHitResult = hitLoc.distanceSquared(startingVec);
|
||||
@@ -819,7 +831,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<Vector, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
Pair<Vector3D, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
|
||||
if (intercept.first() != null) {
|
||||
return new HitData(vector3i, intercept.first(), intercept.second(), block);
|
||||
|
||||
@@ -13,6 +13,7 @@ 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;
|
||||
@@ -21,7 +22,6 @@ 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,22 +60,19 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) {
|
||||
// Teleports don't interpolate, duplicate 1.17 packets don't interpolate
|
||||
if (player.packetStateData.lastPacketWasTeleport || player.packetStateData.lastPacketWasOnePointSeventeenDuplicate)
|
||||
return;
|
||||
// Teleports don't interpolate, duplicate 1.17 packets don't interpolate
|
||||
if (!isTickPacket(event.getPacketType())) 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,44 +83,55 @@ 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();
|
||||
}
|
||||
if (event.getPacketType() == PacketType.Play.Server.SPAWN_LIVING_ENTITY) {
|
||||
else 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);
|
||||
}
|
||||
if (event.getPacketType() == PacketType.Play.Server.SPAWN_ENTITY) {
|
||||
else 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());
|
||||
}
|
||||
if (event.getPacketType() == PacketType.Play.Server.SPAWN_PLAYER) {
|
||||
else 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);
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Server.ENTITY_RELATIVE_MOVE) {
|
||||
else 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());
|
||||
}
|
||||
else 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);
|
||||
}
|
||||
if (event.getPacketType() == PacketType.Play.Server.ENTITY_RELATIVE_MOVE_AND_ROTATION) {
|
||||
else 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);
|
||||
}
|
||||
if (event.getPacketType() == PacketType.Play.Server.ENTITY_TELEPORT) {
|
||||
else 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);
|
||||
}
|
||||
if (event.getPacketType() == PacketType.Play.Server.ENTITY_ROTATION) { // Affects interpolation
|
||||
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
|
||||
WrapperPlayServerEntityRotation move = new WrapperPlayServerEntityRotation(event);
|
||||
handleMoveEntity(event, move.getEntityId(), 0, 0, 0, move.getYaw() * 0.7111111F, move.getPitch() * 0.7111111F, true, false);
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Server.ENTITY_METADATA) {
|
||||
else 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+
|
||||
if (event.getPacketType() == PacketType.Play.Server.PLAYER_INFO_UPDATE) {
|
||||
else 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()) {
|
||||
@@ -150,7 +158,7 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
});
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Server.ENTITY_EFFECT) {
|
||||
else if (event.getPacketType() == PacketType.Play.Server.ENTITY_EFFECT) {
|
||||
WrapperPlayServerEntityEffect effect = new WrapperPlayServerEntityEffect(event);
|
||||
|
||||
PotionType type = effect.getPotionType();
|
||||
@@ -182,7 +190,7 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
});
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Server.REMOVE_ENTITY_EFFECT) {
|
||||
else if (event.getPacketType() == PacketType.Play.Server.REMOVE_ENTITY_EFFECT) {
|
||||
WrapperPlayServerRemoveEntityEffect effect = new WrapperPlayServerRemoveEntityEffect(event);
|
||||
|
||||
if (isDirectlyAffectingPlayer(player, effect.getEntityId())) player.sendTransaction();
|
||||
@@ -195,7 +203,7 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
});
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Server.UPDATE_ATTRIBUTES) {
|
||||
else if (event.getPacketType() == PacketType.Play.Server.UPDATE_ATTRIBUTES) {
|
||||
WrapperPlayServerUpdateAttributes attributes = new WrapperPlayServerUpdateAttributes(event);
|
||||
|
||||
int entityID = attributes.getEntityId();
|
||||
@@ -207,7 +215,7 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
() -> player.compensatedEntities.updateAttributes(entityID, attributes.getProperties()));
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Server.ENTITY_STATUS) {
|
||||
else 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.
|
||||
@@ -241,7 +249,7 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Server.SET_SLOT) {
|
||||
else if (event.getPacketType() == PacketType.Play.Server.SET_SLOT) {
|
||||
WrapperPlayServerSetSlot slot = new WrapperPlayServerSetSlot(event);
|
||||
|
||||
if (slot.getWindowId() == 0) {
|
||||
@@ -259,7 +267,7 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Server.WINDOW_ITEMS) {
|
||||
else if (event.getPacketType() == PacketType.Play.Server.WINDOW_ITEMS) {
|
||||
WrapperPlayServerWindowItems items = new WrapperPlayServerWindowItems(event);
|
||||
|
||||
if (items.getWindowId() == 0) { // Player inventory
|
||||
@@ -269,16 +277,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
|
||||
if (event.getPacketType() == PacketType.Play.Server.OPEN_WINDOW) {
|
||||
else 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));
|
||||
}
|
||||
if (event.getPacketType() == PacketType.Play.Server.OPEN_HORSE_WINDOW) {
|
||||
else 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));
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Server.SET_PASSENGERS) {
|
||||
else if (event.getPacketType() == PacketType.Play.Server.SET_PASSENGERS) {
|
||||
WrapperPlayServerSetPassengers mount = new WrapperPlayServerSetPassengers(event);
|
||||
|
||||
int vehicleID = mount.getEntityId();
|
||||
@@ -287,7 +295,7 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
handleMountVehicle(event, vehicleID, passengers);
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Server.ATTACH_ENTITY) {
|
||||
else 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
|
||||
@@ -318,7 +326,7 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Server.DESTROY_ENTITIES) {
|
||||
else if (event.getPacketType() == PacketType.Play.Server.DESTROY_ENTITIES) {
|
||||
WrapperPlayServerDestroyEntities destroy = new WrapperPlayServerDestroyEntities(event);
|
||||
|
||||
int[] destroyEntityIds = destroy.getEntityIds();
|
||||
@@ -413,9 +421,13 @@ 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) &&
|
||||
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)
|
||||
// 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);
|
||||
|
||||
// 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,6 +36,9 @@ 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,6 +3,7 @@ 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;
|
||||
@@ -19,11 +20,12 @@ 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).
|
||||
@@ -131,7 +133,11 @@ public class PacketPlayerRespawn extends PacketListenerAbstract {
|
||||
}
|
||||
|
||||
player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get() + 1, () -> {
|
||||
player.isSneaking = false;
|
||||
// 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.lastOnGround = false;
|
||||
player.onGround = false;
|
||||
player.isInBed = false;
|
||||
@@ -157,6 +163,7 @@ 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)) {
|
||||
@@ -185,7 +192,7 @@ public class PacketPlayerRespawn extends PacketListenerAbstract {
|
||||
player.compensatedEntities.hasSprintingAttributeEnabled = false;
|
||||
}
|
||||
player.pose = Pose.STANDING;
|
||||
player.clientVelocity = new Vector();
|
||||
player.clientVelocity = newVector3D();
|
||||
player.gamemode = respawn.getGameMode();
|
||||
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_17)) {
|
||||
player.compensatedWorld.setDimension(respawn.getDimensionType(), event.getUser());
|
||||
|
||||
@@ -3,6 +3,7 @@ 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;
|
||||
@@ -12,6 +13,7 @@ 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 {
|
||||
@@ -22,13 +24,12 @@ public class PacketPlayerSteer extends PacketListenerAbstract {
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
|
||||
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();
|
||||
|
||||
@@ -99,6 +100,33 @@ 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerMultiBlockChange;
|
||||
import io.github.retrooper.packetevents.util.folia.FoliaScheduler;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
@@ -35,19 +36,20 @@ public class ResyncWorldUtil {
|
||||
|| !player.compensatedWorld.isChunkLoaded(maxBlockX >> 4, minBlockZ >> 4) || !player.compensatedWorld.isChunkLoaded(maxBlockX >> 4, maxBlockZ >> 4))
|
||||
return;
|
||||
|
||||
if (player.bukkitPlayer == null) return;
|
||||
World world = player.bukkitPlayer.getWorld();
|
||||
|
||||
// Takes 0.15ms or so to complete. Not bad IMO. Unsure how I could improve this other than sending packets async.
|
||||
// But that's on PacketEvents.
|
||||
FoliaScheduler.getRegionScheduler().execute(GrimAPI.INSTANCE.getPlugin(), player.bukkitPlayer.getWorld(),
|
||||
FoliaScheduler.getRegionScheduler().execute(GrimAPI.INSTANCE.getPlugin(), world,
|
||||
minBlockX >> 4, minBlockZ >> 4, () -> {
|
||||
boolean flat = PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_13);
|
||||
|
||||
if (player.bukkitPlayer == null) return;
|
||||
// Player hasn't spawned, don't spam packets
|
||||
if (!player.getSetbackTeleportUtil().hasAcceptedSpawnTeleport) return;
|
||||
|
||||
// Check the 4 corners of the BB for loaded chunks, don't freeze main thread to load chunks.
|
||||
if (!player.bukkitPlayer.getWorld().isChunkLoaded(minBlockX >> 4, minBlockZ >> 4) || !player.bukkitPlayer.getWorld().isChunkLoaded(minBlockX >> 4, maxBlockZ >> 4)
|
||||
|| !player.bukkitPlayer.getWorld().isChunkLoaded(maxBlockX >> 4, minBlockZ >> 4) || !player.bukkitPlayer.getWorld().isChunkLoaded(maxBlockX >> 4, maxBlockZ >> 4))
|
||||
if (!world.isChunkLoaded(minBlockX >> 4, minBlockZ >> 4) || !world.isChunkLoaded(minBlockX >> 4, maxBlockZ >> 4)
|
||||
|| !world.isChunkLoaded(maxBlockX >> 4, minBlockZ >> 4) || !world.isChunkLoaded(maxBlockX >> 4, maxBlockZ >> 4))
|
||||
return;
|
||||
|
||||
// This is based on Tuinity's code, thanks leaf. Now merged into paper.
|
||||
@@ -76,7 +78,7 @@ public class ResyncWorldUtil {
|
||||
int minX = currChunkX == minChunkX ? minBlockX & 15 : 0; // coordinate in chunk
|
||||
int maxX = currChunkX == maxChunkX ? maxBlockX & 15 : 15; // coordinate in chunk
|
||||
|
||||
Chunk chunk = player.bukkitPlayer.getWorld().getChunkAt(currChunkX, currChunkZ);
|
||||
Chunk chunk = world.getChunkAt(currChunkX, currChunkZ);
|
||||
|
||||
for (int currChunkY = minChunkY; currChunkY <= maxChunkY; ++currChunkY) {
|
||||
int minY = currChunkY == minChunkY ? minBlockY & 15 : 0; // coordinate in chunk
|
||||
|
||||
@@ -6,7 +6,6 @@ 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
|
||||
@@ -27,7 +26,7 @@ public class ActionManager extends Check implements PacketCheck {
|
||||
attacking = true;
|
||||
lastAttack = System.currentTimeMillis();
|
||||
}
|
||||
} else if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) {
|
||||
} else if (isTickPacketIncludingNonMovement(event.getPacketType())) {
|
||||
player.totalFlyingPacketsSent++;
|
||||
attacking = false;
|
||||
}
|
||||
|
||||
@@ -11,12 +11,14 @@ 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;
|
||||
@@ -98,11 +100,15 @@ 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))
|
||||
@@ -151,6 +157,7 @@ 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))
|
||||
@@ -161,6 +168,7 @@ 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))
|
||||
@@ -171,6 +179,7 @@ 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, String violations) {
|
||||
public void sendAlert(GrimPlayer player, String verbose, String checkName, int violations) {
|
||||
if (client != null) {
|
||||
|
||||
String content = staticContent;
|
||||
content = content.replace("%check%", checkName);
|
||||
content = content.replace("%violations%", violations);
|
||||
content = content.replace("%violations%", Integer.toString(violations));
|
||||
content = GrimAPI.INSTANCE.getExternalAPI().replaceVariables(player, content, false);
|
||||
content = content.replace("_", "\\_");
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ 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;
|
||||
@@ -99,16 +98,14 @@ public class PunishmentManager implements ConfigReloadable {
|
||||
}
|
||||
}
|
||||
|
||||
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() + "";
|
||||
private String replaceAlertPlaceholders(String original, int vl, PunishGroup group, Check check, String alertString, String verbose) {
|
||||
|
||||
original = MessageUtil.format(original
|
||||
.replace("[alert]", alertString)
|
||||
.replace("[proxy]", alertString)
|
||||
.replace("%check_name%", check.getDisplayName())
|
||||
.replace("%experimental%", check.isExperimental() ? experimentalSymbol : "")
|
||||
.replace("%vl%", vl)
|
||||
.replace("%vl%", Integer.toString(vl))
|
||||
.replace("%verbose%", verbose)
|
||||
.replace("%description%", check.getDescription())
|
||||
);
|
||||
@@ -124,12 +121,13 @@ public class PunishmentManager implements ConfigReloadable {
|
||||
// Check commands
|
||||
for (PunishGroup group : groups) {
|
||||
if (group.getChecks().contains(check)) {
|
||||
int violationCount = group.getViolations().size();
|
||||
final int vl = getViolations(group, check);
|
||||
final int violationCount = group.getViolations().size();
|
||||
for (ParsedCommand command : group.getCommands()) {
|
||||
String cmd = replaceAlertPlaceholders(command.getCommand(), group, check, alertString, verbose);
|
||||
String cmd = replaceAlertPlaceholders(command.getCommand(), vl, group, check, alertString, verbose);
|
||||
|
||||
// Verbose that prints all flags
|
||||
if (GrimAPI.INSTANCE.getAlertManager().getEnabledVerbose().size() > 0 && command.command.equals("[alert]")) {
|
||||
if (!GrimAPI.INSTANCE.getAlertManager().getEnabledVerbose().isEmpty() && command.command.equals("[alert]")) {
|
||||
sentDebug = true;
|
||||
for (Player bukkitPlayer : GrimAPI.INSTANCE.getAlertManager().getEnabledVerbose()) {
|
||||
bukkitPlayer.sendMessage(cmd);
|
||||
@@ -149,10 +147,9 @@ 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(), group, check, proxyAlertString, verbose));
|
||||
ProxyAlertMessenger.sendPluginMessage(replaceAlertPlaceholders(command.getCommand(), vl, group, check, proxyAlertString, verbose));
|
||||
} else {
|
||||
if (command.command.equals("[alert]")) {
|
||||
sentDebug = true;
|
||||
@@ -184,10 +181,19 @@ public class PunishmentManager implements ConfigReloadable {
|
||||
|
||||
group.violations.put(currentTime, check);
|
||||
// Remove violations older than the defined time in the config
|
||||
group.violations.long2ObjectEntrySet().removeIf(time -> currentTime - time.getLongKey() > group.removeViolationsAfter);
|
||||
group.violations.entrySet().removeIf(time -> currentTime - time.getKey() > 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 {
|
||||
@@ -196,7 +202,7 @@ class PunishGroup {
|
||||
@Getter
|
||||
List<ParsedCommand> commands;
|
||||
@Getter
|
||||
Long2ObjectOpenHashMap<Check> violations = new Long2ObjectOpenHashMap<>();
|
||||
public Map<Long, Check> violations = new HashMap<>();
|
||||
@Getter
|
||||
int removeViolationsAfter;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ 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;
|
||||
@@ -31,13 +32,15 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
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<>();
|
||||
@@ -65,7 +68,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
|
||||
Vector afterTickFriction = player.clientVelocity.clone();
|
||||
Vector3D 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
|
||||
@@ -115,7 +118,7 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void simulateFriction(Vector vector) {
|
||||
private void simulateFriction(Vector3D 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) {
|
||||
@@ -123,12 +126,13 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
} else if (player.wasTouchingLava) {
|
||||
vector.multiply(0.5D);
|
||||
if (player.hasGravity)
|
||||
vector.add(new Vector(0.0D, -player.gravity / 4.0D, 0.0D));
|
||||
vector.add(newVector3D(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(new Vector(0.99F, 0.98F, 0.99F));
|
||||
PredictionEngineElytra.getElytraMovement(player, vector, ReachUtils.getLook(player, player.xRot, player.yRot)).multiply(player.stuckSpeedMultiplier).multiply(newVector3D(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?
|
||||
@@ -147,9 +151,9 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
lastWorldResync = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
Vector clientVel = lastKnownGoodPosition.vector.clone();
|
||||
Vector3D clientVel = lastKnownGoodPosition.vector.clone();
|
||||
|
||||
Pair<VelocityData, Vector> futureKb = player.checkManager.getKnockbackHandler().getFutureKnockback();
|
||||
Pair<VelocityData, Vector3D> futureKb = player.checkManager.getKnockbackHandler().getFutureKnockback();
|
||||
VelocityData futureExplosion = player.checkManager.getExplosionHandler().getFutureExplosion();
|
||||
|
||||
// Velocity sets
|
||||
@@ -169,7 +173,7 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
|
||||
// Mini prediction engine - simulate collisions
|
||||
if (simulateNextTickPosition) {
|
||||
Vector collide = Collisions.collide(player, clientVel.getX(), clientVel.getY(), clientVel.getZ());
|
||||
Vector3D 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
|
||||
@@ -397,22 +401,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.isSet(RelativeFlag.X.getMask())) {
|
||||
if (flags.has(RelativeFlag.X)) {
|
||||
safePosition = safePosition.withX(safePosition.getX() + lastKnownGoodPosition.pos.getX());
|
||||
}
|
||||
|
||||
if (flags.isSet(RelativeFlag.Y.getMask())) {
|
||||
if (flags.has(RelativeFlag.Y)) {
|
||||
safePosition = safePosition.withY(safePosition.getY() + lastKnownGoodPosition.pos.getY());
|
||||
}
|
||||
|
||||
if (flags.isSet(RelativeFlag.Z.getMask())) {
|
||||
if (flags.has(RelativeFlag.Z)) {
|
||||
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, new Vector());
|
||||
this.lastKnownGoodPosition = new SetbackPosWithVector(safePosition, newVector3D());
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@@ -420,6 +424,6 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
@Setter
|
||||
public static class SetbackPosWithVector {
|
||||
private Vector3d pos;
|
||||
private Vector vector;
|
||||
private Vector3D vector;
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,14 @@ package ac.grim.grimac.manager.init.start;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.manager.init.Initable;
|
||||
import io.github.retrooper.packetevents.bstats.bukkit.Metrics;
|
||||
|
||||
public class BStats implements Initable {
|
||||
@Override
|
||||
public void start() {
|
||||
int pluginId = 12820; // <-- Replace with the id of your plugin!
|
||||
try {
|
||||
new io.github.retrooper.packetevents.bstats.Metrics(GrimAPI.INSTANCE.getPlugin(), pluginId);
|
||||
new Metrics(GrimAPI.INSTANCE.getPlugin(), pluginId);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,5 +23,7 @@ public class CommandRegister implements Initable {
|
||||
commandManager.registerCommand(new GrimStopSpectating());
|
||||
commandManager.registerCommand(new GrimLog());
|
||||
commandManager.registerCommand(new GrimVerbose());
|
||||
|
||||
commandManager.getCommandCompletions().registerCompletion("stopspectating", GrimStopSpectating.completionHandler);
|
||||
}
|
||||
}
|
||||
@@ -10,26 +10,28 @@ 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<Vector> actually = new EvictingQueue<>(60);
|
||||
List<Vector3D> actually = new EvictingQueue<>(60);
|
||||
List<Location> locations = new EvictingQueue<>(60);
|
||||
List<Vector> startTickClientVel = new EvictingQueue<>(60);
|
||||
List<Vector> baseTickAddition = new EvictingQueue<>(60);
|
||||
List<Vector> baseTickWater = new EvictingQueue<>(60);
|
||||
List<Vector3D> startTickClientVel = new EvictingQueue<>(60);
|
||||
List<Vector3D> baseTickAddition = new EvictingQueue<>(60);
|
||||
List<Vector3D> baseTickWater = new EvictingQueue<>(60);
|
||||
|
||||
public SuperDebug(GrimPlayer player) {
|
||||
super(player);
|
||||
@@ -80,11 +82,11 @@ public final class SuperDebug extends Check implements PostPredictionCheck {
|
||||
|
||||
for (int i = 0; i < predicted.size(); i++) {
|
||||
VectorData predict = predicted.get(i);
|
||||
Vector actual = actually.get(i);
|
||||
Vector3D actual = actually.get(i);
|
||||
Location loc = locations.get(i);
|
||||
Vector startTickVel = startTickClientVel.get(i);
|
||||
Vector addition = baseTickAddition.get(i);
|
||||
Vector water = baseTickWater.get(i);
|
||||
Vector3D startTickVel = startTickClientVel.get(i);
|
||||
Vector3D addition = baseTickAddition.get(i);
|
||||
Vector3D water = baseTickWater.get(i);
|
||||
appendDebug(sb, predict, actual, loc, startTickVel, addition, water);
|
||||
}
|
||||
|
||||
@@ -189,7 +191,7 @@ public final class SuperDebug extends Check implements PostPredictionCheck {
|
||||
continuedDebug.put(sb, 40);
|
||||
}
|
||||
|
||||
private void appendDebug(StringBuilder sb, VectorData predict, Vector actual, Location location, Vector startTick, Vector addition, Vector water) {
|
||||
private void appendDebug(StringBuilder sb, VectorData predict, Vector3D actual, Location location, Vector3D startTick, Vector3D addition, Vector3D water) {
|
||||
if (predict.isZeroPointZeroThree()) {
|
||||
sb.append("Movement threshold/tick skipping\n");
|
||||
}
|
||||
@@ -225,11 +227,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);
|
||||
Vector trueStartVel = ((VectorData) set.toArray()[0]).vector;
|
||||
Vector3D trueStartVel = ((VectorData) set.toArray()[0]).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);
|
||||
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);
|
||||
trueStartVel.add(addition);
|
||||
trueStartVel.add(water);
|
||||
|
||||
@@ -268,14 +270,14 @@ public final class SuperDebug extends Check implements PostPredictionCheck {
|
||||
sb.append("\n\n");
|
||||
}
|
||||
|
||||
private Vector getPlayerMathMovement(GrimPlayer player, Vector wantedMovement, float f2) {
|
||||
private Vector3D getPlayerMathMovement(GrimPlayer player, Vector3D 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 new Vector(bestTheoreticalX, 0, bestTheoreticalZ);
|
||||
return newVector3D(bestTheoreticalX, 0, bestTheoreticalZ);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
|
||||
@@ -3,7 +3,10 @@ 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;
|
||||
@@ -30,6 +33,10 @@ 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
@@ -64,6 +64,9 @@ 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
|
||||
@@ -90,7 +93,7 @@ public class GrimPlayer implements GrimUser {
|
||||
public MovementCheckRunner movementCheckRunner;
|
||||
public SyncedTags tagManager;
|
||||
// End manager like classes
|
||||
public Vector clientVelocity = new Vector();
|
||||
public ac.grim.grimac.utils.vector.Vector3D clientVelocity = newVector3D();
|
||||
PacketTracker packetTracker;
|
||||
private long transactionPing = 0;
|
||||
public long lastTransSent = 0;
|
||||
@@ -103,9 +106,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(new Vector(), VectorData.VectorType.Normal);
|
||||
public Vector actualMovement = new Vector();
|
||||
public Vector stuckSpeedMultiplier = new Vector(1, 1, 1);
|
||||
public VectorData predictedVelocity = new VectorData(newVector3D(), Normal);
|
||||
public Vector3D actualMovement = newVector3D();
|
||||
public Vector3D stuckSpeedMultiplier = newVector3D(1, 1, 1);
|
||||
public UncertaintyHandler uncertaintyHandler;
|
||||
public double gravity;
|
||||
public float friction;
|
||||
@@ -184,9 +187,9 @@ public class GrimPlayer implements GrimUser {
|
||||
public TrigHandler trigHandler;
|
||||
public PacketStateData packetStateData;
|
||||
// Keep track of basetick stuff
|
||||
public Vector baseTickAddition = new Vector();
|
||||
public Vector baseTickWaterPushing = new Vector();
|
||||
public Vector startTickClientVel = new Vector();
|
||||
public Vector3D baseTickAddition = newVector3D();
|
||||
public Vector3D baseTickWaterPushing = newVector3D();
|
||||
public Vector3D startTickClientVel = newVector3D();
|
||||
// For syncing the player's full swing in 1.9+
|
||||
public int movementPackets = 0;
|
||||
public VelocityData firstBreadKB = null;
|
||||
@@ -242,6 +245,7 @@ public class GrimPlayer implements GrimUser {
|
||||
|
||||
packetStateData = new PacketStateData();
|
||||
|
||||
uncertaintyHandler.riptideEntities.add(0);
|
||||
uncertaintyHandler.collidingEntities.add(0);
|
||||
|
||||
if (getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14)) {
|
||||
@@ -292,7 +296,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.collidingEntities) > 0) {
|
||||
if (riptideSpinAttackTicks >= 0 && Collections.max(uncertaintyHandler.riptideEntities) > 0) {
|
||||
possibleMovements.add(new VectorData(clientVelocity.clone().multiply(-0.2), VectorData.VectorType.Trident));
|
||||
}
|
||||
|
||||
@@ -360,15 +364,15 @@ public class GrimPlayer implements GrimUser {
|
||||
return data != null && data.first() == id;
|
||||
}
|
||||
|
||||
public void baseTickAddWaterPushing(Vector vector) {
|
||||
public void baseTickAddWaterPushing(ac.grim.grimac.utils.vector.Vector3D vector) {
|
||||
baseTickWaterPushing.add(vector);
|
||||
}
|
||||
|
||||
public void baseTickAddVector(Vector vector) {
|
||||
public void baseTickAddVector(Vector3D vector) {
|
||||
clientVelocity.add(vector);
|
||||
}
|
||||
|
||||
public void trackBaseTickAddition(Vector vector) {
|
||||
public void trackBaseTickAddition(Vector3D vector) {
|
||||
baseTickAddition.add(vector);
|
||||
}
|
||||
|
||||
@@ -565,11 +569,18 @@ 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) {
|
||||
return (getClientVersion().isOlderThan(ClientVersion.V_1_9)
|
||||
|| !uncertaintyHandler.lastPointThree.hasOccurredSince(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)
|
||||
|| compensatedEntities.getSelf().inVehicle();
|
||||
}
|
||||
|
||||
public boolean inVehicle() {
|
||||
return compensatedEntities.getSelf().inVehicle();
|
||||
}
|
||||
|
||||
public boolean canThePlayerBeCloseToZeroMovement(int ticks) {
|
||||
return (!uncertaintyHandler.lastPointThree.hasOccurredSince(ticks));
|
||||
}
|
||||
@@ -697,6 +708,11 @@ 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);
|
||||
@@ -751,6 +767,7 @@ 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) {
|
||||
@@ -759,6 +776,7 @@ 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,7 +38,10 @@ 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 org.bukkit.util.Vector;
|
||||
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;
|
||||
|
||||
public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
// Averaged over 500 predictions (Defaults set slightly above my 3600x results)
|
||||
@@ -138,10 +141,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);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
boolean isEast = NE.getX() != posX || SE.getX() != posX;
|
||||
boolean isWest = NW.getX() != negX || SW.getX() != negX;
|
||||
@@ -184,7 +187,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
player.vehicleData.wasVehicleSwitch = false;
|
||||
|
||||
if (riding != null) {
|
||||
Vector pos = new Vector(player.x, player.y, player.z);
|
||||
Vector3D pos = newVector3D(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
|
||||
@@ -194,7 +197,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
interTruePositions.expand(-width, 0, -width);
|
||||
interTruePositions.expandMax(0, -height, 0);
|
||||
|
||||
Vector cutTo = VectorUtils.cutBoxToVector(pos, interTruePositions);
|
||||
Vector3D 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
|
||||
@@ -212,14 +215,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 (new Vector(player.lastX, player.lastY, player.lastZ).distance(new Vector(player.x, player.y, player.z)) > 3) {
|
||||
if (newVector3D(player.lastX, player.lastY, player.lastZ).distance(newVector3D(player.x, player.y, player.z)) > 3) {
|
||||
player.getSetbackTeleportUtil().executeForceResync(); // Too far! (I think this value is sane)
|
||||
}
|
||||
|
||||
handleTeleport(update);
|
||||
|
||||
if (player.isClimbing) {
|
||||
Vector ladder = player.clientVelocity.clone().setY(0.2);
|
||||
Vector3D ladder = player.clientVelocity.clone().setY(0.2);
|
||||
PredictionEngineNormal.staticVectorEndOfTick(player, ladder);
|
||||
player.lastWasClimbing = ladder.getY();
|
||||
}
|
||||
@@ -299,7 +302,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 = new Vector(player.x - player.lastX, player.y - player.lastY, player.z - player.lastZ);
|
||||
player.actualMovement = newVector3D(player.x - player.lastX, player.y - player.lastY, player.z - player.lastZ);
|
||||
|
||||
if (player.isSprinting != player.lastSprinting) {
|
||||
player.compensatedEntities.hasSprintingAttributeEnabled = player.isSprinting;
|
||||
@@ -347,7 +350,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
player.packetStateData.lastRiptide = currentTime;
|
||||
}
|
||||
|
||||
SimpleCollisionBox steppingOnBB = GetBoundingBox.getCollisionBoxForPlayer(player, player.x, player.y, player.z).expand(0.03).offset(0, -1, 0);
|
||||
SimpleCollisionBox steppingOnBB = GetBoundingBox.getCollisionBoxForPlayer(player, player.x, player.y, player.z).expand(player.getMovementThreshold()).offset(0, -1, 0);
|
||||
Collisions.hasMaterial(player, steppingOnBB, (pair) -> {
|
||||
WrappedBlockState data = pair.first();
|
||||
if (data.getType() == StateTypes.SLIME_BLOCK && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8)) {
|
||||
@@ -411,8 +414,8 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
player.uncertaintyHandler.lastUnderwaterFlyingHack.reset();
|
||||
}
|
||||
|
||||
boolean couldBeStuckSpeed = Collisions.checkStuckSpeed(player, 0.03);
|
||||
boolean couldLeaveStuckSpeed = player.isPointThree() && Collisions.checkStuckSpeed(player, -0.03);
|
||||
boolean couldBeStuckSpeed = Collisions.checkStuckSpeed(player, player.getMovementThreshold());
|
||||
boolean couldLeaveStuckSpeed = player.isPointThree() && Collisions.checkStuckSpeed(player, -player.getMovementThreshold());
|
||||
player.uncertaintyHandler.claimingLeftStuckSpeed = !player.compensatedEntities.getSelf().inVehicle() && player.stuckSpeedMultiplier.getX() < 1 && !couldLeaveStuckSpeed;
|
||||
|
||||
if (couldBeStuckSpeed) {
|
||||
@@ -426,9 +429,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(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) {
|
||||
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)) {
|
||||
// We could technically check spectator but what's the point...
|
||||
// Added complexity to analyze a gamemode used mainly by moderators
|
||||
//
|
||||
@@ -450,7 +453,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()) {
|
||||
Vector pushingMovement = Collisions.collide(player, 0, 1.1999999F, 0);
|
||||
Vector3D pushingMovement = Collisions.collide(player, 0, 1.1999999F, 0);
|
||||
player.verticalCollision = pushingMovement.getY() != 1.1999999F;
|
||||
double currentY = player.clientVelocity.getY();
|
||||
|
||||
@@ -462,7 +465,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 = new Vector(player.x - player.lastX, player.y - player.lastY, player.z - player.lastZ);
|
||||
player.actualMovement = newVector3D(player.x - player.lastX, player.y - player.lastY, player.z - player.lastZ);
|
||||
|
||||
player.couldSkipTick = true;
|
||||
|
||||
@@ -514,7 +517,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) {
|
||||
Vector setbackVel = player.getSetbackTeleportUtil().getRequiredSetBack().getVelocity();
|
||||
Vector3D 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
|
||||
@@ -543,7 +546,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(new Vector(0.6 * 0.91, 1, 0.6 * 0.91)));
|
||||
lastKnownGoodPosition.setVector(lastKnownGoodPosition.getVector().multiply(newVector3D(0.6 * 0.91, 1, 0.6 * 0.91)));
|
||||
player.getSetbackTeleportUtil().executeNonSimulatingSetback();
|
||||
}
|
||||
|
||||
@@ -620,7 +623,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(Vector pushingMovement) {
|
||||
private boolean likelyGroundRiptide(Vector3D pushingMovement) {
|
||||
// Y velocity gets reset if the player collides vertically
|
||||
double riptideYResult = Riptide.getRiptideVelocity(player).getY();
|
||||
|
||||
@@ -638,5 +641,4 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
public void onReload(ConfigManager config) {
|
||||
allowSprintJumpingWithElytra = config.getBooleanElse("exploit.allow-sprint-jumping-when-using-elytra", true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,16 +9,19 @@ 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
public class PlayerBaseTick {
|
||||
GrimPlayer player;
|
||||
|
||||
@@ -40,11 +43,11 @@ public class PlayerBaseTick {
|
||||
|
||||
public void doBaseTick() {
|
||||
// Keep track of basetick stuff
|
||||
player.baseTickAddition = new Vector();
|
||||
player.baseTickWaterPushing = new Vector();
|
||||
player.baseTickAddition = newVector3D();
|
||||
player.baseTickWaterPushing = newVector3D();
|
||||
|
||||
if (player.isFlying && player.isSneaking && !player.compensatedEntities.getSelf().inVehicle()) {
|
||||
Vector flyingShift = new Vector(0, player.flySpeed * -3, 0);
|
||||
Vector3D flyingShift = newVector3D(0, player.flySpeed * -3, 0);
|
||||
player.baseTickAddVector(flyingShift);
|
||||
player.trackBaseTickAddition(flyingShift);
|
||||
}
|
||||
@@ -60,7 +63,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()) {
|
||||
Vector waterPushVector = new Vector(0, -0.04f, 0);
|
||||
Vector3D waterPushVector = newVector3D(0, -0.04f, 0);
|
||||
player.baseTickAddVector(waterPushVector);
|
||||
player.trackBaseTickAddition(waterPushVector);
|
||||
}
|
||||
@@ -268,13 +271,14 @@ public class PlayerBaseTick {
|
||||
|
||||
|
||||
private void moveTowardsClosestSpace(double xPosition, double zPosition) {
|
||||
player.boundingBox = player.boundingBox.expand(0.03, 0, 0.03); // 0.03... thanks mojang!
|
||||
double movementThreshold = player.getMovementThreshold();
|
||||
player.boundingBox = player.boundingBox.expand(movementThreshold, 0, movementThreshold); // 0.03... thanks mojang!
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14)) {
|
||||
moveTowardsClosestSpaceModern(xPosition, zPosition);
|
||||
} else {
|
||||
moveTowardsClosestSpaceLegacy(xPosition, zPosition);
|
||||
}
|
||||
player.boundingBox = player.boundingBox.expand(-0.03, 0, -0.03);
|
||||
player.boundingBox = player.boundingBox.expand(-movementThreshold, 0, -movementThreshold);
|
||||
}
|
||||
|
||||
// Mojang is incompetent and this will push the player out a lot when using elytras
|
||||
@@ -413,7 +417,7 @@ public class PlayerBaseTick {
|
||||
}
|
||||
|
||||
boolean hasPushed = false;
|
||||
Vector vec3 = new Vector();
|
||||
Vector3D vec3 = newVector3D();
|
||||
|
||||
for (int x = floorX; x < ceilX; ++x) {
|
||||
for (int y = floorY; y < ceilY; ++y) {
|
||||
@@ -463,7 +467,7 @@ public class PlayerBaseTick {
|
||||
}
|
||||
double d2 = 0.0;
|
||||
boolean hasTouched = false;
|
||||
Vector vec3 = new Vector();
|
||||
Vector3D vec3 = newVector3D();
|
||||
int n7 = 0;
|
||||
|
||||
for (int x = floorX; x < ceilX; ++x) {
|
||||
@@ -488,7 +492,7 @@ public class PlayerBaseTick {
|
||||
d2 = Math.max(fluidHeightToWorld - aABB.minY, d2);
|
||||
|
||||
if (!player.isFlying) {
|
||||
Vector vec32 = FluidTypeFlowing.getFlow(player, x, y, z);
|
||||
Vector3D vec32 = FluidTypeFlowing.getFlow(player, x, y, z);
|
||||
if (d2 < 0.4) {
|
||||
vec32 = vec32.multiply(d2);
|
||||
}
|
||||
|
||||
@@ -18,11 +18,13 @@ 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
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>
|
||||
@@ -127,12 +129,13 @@ public class PointThreeEstimator {
|
||||
|
||||
// Calculate head hitters. Take a shortcut by checking if the player doesn't intersect with this block, but does
|
||||
// when the player vertically moves upwards by 0.03! This is equivalent to the move method, but MUCH faster.
|
||||
SimpleCollisionBox slightlyExpanded = normalBox.copy().expand(0.03, 0, 0.03);
|
||||
if (!slightlyExpanded.isIntersected(data) && slightlyExpanded.offset(0, 0.03, 0).isIntersected(data)) {
|
||||
double movementThreshold = player.getMovementThreshold();
|
||||
SimpleCollisionBox slightlyExpanded = normalBox.copy().expand(movementThreshold, 0, movementThreshold);
|
||||
if (!slightlyExpanded.isIntersected(data) && slightlyExpanded.offset(0, movementThreshold, 0).isIntersected(data)) {
|
||||
headHitter = true;
|
||||
}
|
||||
|
||||
SimpleCollisionBox pointThreeBox = GetBoundingBox.getBoundingBoxFromPosAndSize(player, player.x, player.y - 0.03, player.z, 0.66f, 1.86f);
|
||||
SimpleCollisionBox pointThreeBox = GetBoundingBox.getBoundingBoxFromPosAndSize(player, player.x, player.y - movementThreshold, player.z, 0.66f, 1.86f);
|
||||
if ((Materials.isWater(player.getClientVersion(), state) || stateType == StateTypes.LAVA) &&
|
||||
pointThreeBox.isIntersected(new SimpleCollisionBox(x, y, z))) {
|
||||
|
||||
@@ -140,7 +143,7 @@ public class PointThreeEstimator {
|
||||
isNearBubbleColumn = true;
|
||||
}
|
||||
|
||||
Vector fluidVector = FluidTypeFlowing.getFlow(player, x, y, z);
|
||||
Vector3D fluidVector = FluidTypeFlowing.getFlow(player, x, y, z);
|
||||
if (fluidVector.getX() != 0 || fluidVector.getZ() != 0) {
|
||||
isNearHorizontalFlowingLiquid = true;
|
||||
}
|
||||
@@ -212,7 +215,8 @@ public class PointThreeEstimator {
|
||||
}
|
||||
|
||||
public void endOfTickTick() {
|
||||
SimpleCollisionBox pointThreeBox = GetBoundingBox.getBoundingBoxFromPosAndSize(player, player.x, player.y - 0.03, player.z, 0.66f, 1.86f);
|
||||
double movementThreshold = player.getMovementThreshold();
|
||||
SimpleCollisionBox pointThreeBox = GetBoundingBox.getBoundingBoxFromPosAndSize(player, player.x, player.y - movementThreshold, player.z, 0.66f, 1.86f);
|
||||
|
||||
// Determine the head hitter using the current Y position
|
||||
SimpleCollisionBox oldBB = player.boundingBox;
|
||||
@@ -222,7 +226,7 @@ public class PointThreeEstimator {
|
||||
for (float sizes : (player.skippedTickInActualMovement ? new float[]{0.6f, 1.5f, 1.8f} : new float[]{player.pose.height})) {
|
||||
// Try to limit collisions to be as small as possible, for maximum performance
|
||||
player.boundingBox = GetBoundingBox.getBoundingBoxFromPosAndSize(player, player.x, player.y + (sizes - 0.01f), player.z, 0.6f, 0.01f);
|
||||
headHitter = headHitter || Collisions.collide(player, 0, 0.03, 0).getY() != 0.03;
|
||||
headHitter = headHitter || Collisions.collide(player, 0, movementThreshold, 0).getY() != movementThreshold;
|
||||
}
|
||||
|
||||
player.boundingBox = oldBB;
|
||||
@@ -303,7 +307,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);
|
||||
Vector collisionResult = Collisions.collide(player, 0, searchDistance, 0);
|
||||
Vector3D collisionResult = Collisions.collide(player, 0, searchDistance, 0);
|
||||
player.boundingBox = playerBox;
|
||||
return collisionResult.getY() != searchDistance;
|
||||
}
|
||||
@@ -312,7 +316,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.getClientVersion().isOlderThan(ClientVersion.V_1_9) && player.packetStateData.didLastMovementIncludePosition && !player.uncertaintyHandler.isSteppingOnSlime) {
|
||||
if ((player.supportsEndTick() || player.getClientVersion().isOlderThan(ClientVersion.V_1_9)) && player.packetStateData.didLastMovementIncludePosition && !player.uncertaintyHandler.isSteppingOnSlime) {
|
||||
return false; // Last packet included a position so not 0.03
|
||||
}
|
||||
|
||||
@@ -337,9 +341,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...
|
||||
Vector toZeroVec = new PredictionEngine().handleStartingVelocityUncertainty(player, data, new Vector());
|
||||
Vector3D toZeroVec = new PredictionEngine().handleStartingVelocityUncertainty(player, data, newVector3D());
|
||||
// Collide to handle mostly gravity, but other scenarios similar to this.
|
||||
Vector collisionResult = Collisions.collide(player, toZeroVec.getX(), toZeroVec.getY(), toZeroVec.getZ(), Integer.MIN_VALUE, null);
|
||||
Vector3D 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,11 +13,12 @@ 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 it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
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
|
||||
@@ -65,8 +66,10 @@ 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?
|
||||
// How many entities are within 0.5 blocks of the player's bounding box that are pushable?
|
||||
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;
|
||||
@@ -148,15 +151,15 @@ public class UncertaintyHandler {
|
||||
entityBox.maxY -= height;
|
||||
entityBox.expand(-width / 2, 0, -width / 2);
|
||||
|
||||
Vector maxLocation = new Vector(entityBox.maxX, entityBox.maxY, entityBox.maxZ);
|
||||
Vector minLocation = new Vector(entityBox.minX, entityBox.minY, entityBox.minZ);
|
||||
Vector3D maxLocation = newVector3D(entityBox.maxX, entityBox.maxY, entityBox.maxZ);
|
||||
Vector3D minLocation = newVector3D(entityBox.minX, entityBox.minY, entityBox.minZ);
|
||||
|
||||
Vector diff = minLocation.subtract(new Vector(player.lastX, player.lastY + 0.8 * 1.8, player.lastZ)).multiply(0.1);
|
||||
Vector3D diff = minLocation.subtract(newVector3D(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(new Vector(player.lastX, player.lastY + 0.8 * 1.8, player.lastZ)).multiply(0.1);
|
||||
diff = maxLocation.subtract(newVector3D(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());
|
||||
@@ -171,8 +174,8 @@ public class UncertaintyHandler {
|
||||
|
||||
fireworksBox = new SimpleCollisionBox();
|
||||
|
||||
Vector currentLook = ReachUtils.getLook(player, player.xRot, player.yRot);
|
||||
Vector lastLook = ReachUtils.getLook(player, player.lastXRot, player.lastYRot);
|
||||
Vector3D currentLook = ReachUtils.getLook(player, player.xRot, player.yRot);
|
||||
ac.grim.grimac.utils.vector.Vector3D lastLook = ReachUtils.getLook(player, player.lastXRot, player.lastYRot);
|
||||
|
||||
double antiTickSkipping = player.isPointThree() ? 0 : 0.05; // With 0.03, let that handle tick skipping
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@ 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
public class MovementTicker {
|
||||
public final GrimPlayer player;
|
||||
@@ -41,6 +43,7 @@ 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()) {
|
||||
@@ -52,16 +55,23 @@ public class MovementTicker {
|
||||
final TeamHandler teamHandler = player.checkManager.getPacketCheck(TeamHandler.class);
|
||||
|
||||
for (PacketEntity entity : player.compensatedEntities.entityMap.values()) {
|
||||
if (!entity.isPushable())
|
||||
continue;
|
||||
// TODO actually handle entity collisions instead of this awfulness
|
||||
SimpleCollisionBox entityBox = entity.getPossibleCollisionBoxes();
|
||||
|
||||
// 1.9+ player on 1.8- server with ViaVersion prevent-collision disabled.
|
||||
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;
|
||||
|
||||
SimpleCollisionBox entityBox = entity.getPossibleCollisionBoxes();
|
||||
if (!entity.isPushable())
|
||||
continue;
|
||||
|
||||
if (playerBox.isCollided(entityBox)) {
|
||||
if (isCollided) {
|
||||
possibleCollidingEntities++;
|
||||
}
|
||||
}
|
||||
@@ -74,12 +84,13 @@ public class MovementTicker {
|
||||
player.uncertaintyHandler.yPositiveUncertainty += 0.05;
|
||||
}
|
||||
|
||||
player.uncertaintyHandler.riptideEntities.add(possibleRiptideEntities);
|
||||
player.uncertaintyHandler.collidingEntities.add(possibleCollidingEntities);
|
||||
}
|
||||
|
||||
public void move(Vector inputVel, Vector collide) {
|
||||
public void move(Vector3D inputVel, Vector3D collide) {
|
||||
if (player.stuckSpeedMultiplier.getX() < 0.99) {
|
||||
player.clientVelocity = new Vector();
|
||||
player.clientVelocity = newVector3D();
|
||||
}
|
||||
|
||||
if (inputVel.getX() != collide.getX()) {
|
||||
@@ -172,21 +183,21 @@ public class MovementTicker {
|
||||
|
||||
// The game disregards movements smaller than 1e-7 (such as in boats)
|
||||
if (collide.lengthSquared() < 1e-7) {
|
||||
collide = new Vector();
|
||||
collide = newVector3D();
|
||||
}
|
||||
|
||||
// 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(new Vector(f, 1, f));
|
||||
player.clientVelocity.multiply(newVector3D(f, 1, f));
|
||||
|
||||
// Reset stuck speed so it can update
|
||||
if (player.stuckSpeedMultiplier.getX() < 0.99) {
|
||||
player.uncertaintyHandler.lastStuckSpeedMultiplier.reset();
|
||||
}
|
||||
|
||||
player.stuckSpeedMultiplier = new Vector(1, 1, 1);
|
||||
player.stuckSpeedMultiplier = newVector3D(1, 1, 1);
|
||||
|
||||
// 1.15 and older clients use the handleInsideBlocks method for lava
|
||||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_16))
|
||||
@@ -201,7 +212,7 @@ public class MovementTicker {
|
||||
|
||||
// Flying players are not affected by cobwebs/sweet berry bushes
|
||||
if (player.isFlying) {
|
||||
player.stuckSpeedMultiplier = new Vector(1, 1, 1);
|
||||
player.stuckSpeedMultiplier = newVector3D(1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,14 +399,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(new Vector(0.5D, 0.800000011920929D, 0.5D));
|
||||
player.clientVelocity = player.clientVelocity.multiply(newVector3D(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(new Vector(0.0D, -playerGravity / 4.0D, 0.0D));
|
||||
player.clientVelocity.add(newVector3D(0.0D, -playerGravity / 4.0D, 0.0D));
|
||||
|
||||
} else if (player.isGliding) {
|
||||
player.friction = 0.99F; // Not vanilla, just useful for other grim stuff
|
||||
|
||||
@@ -5,7 +5,8 @@ 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 org.bukkit.util.Vector;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
public class MovementTickerHorse extends MovementTickerLivingVehicle {
|
||||
|
||||
@@ -26,7 +27,7 @@ public class MovementTickerHorse extends MovementTickerLivingVehicle {
|
||||
forwardsInput *= 0.25F;
|
||||
}
|
||||
|
||||
this.movementInput = new Vector(horizInput, 0, forwardsInput);
|
||||
this.movementInput = newVector3D(horizInput, 0, forwardsInput);
|
||||
if (movementInput.lengthSquared() > 1) movementInput.normalize();
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -7,10 +7,13 @@ 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
public class MovementTickerLivingVehicle extends MovementTicker {
|
||||
Vector movementInput = new Vector();
|
||||
Vector3D movementInput = newVector3D();
|
||||
|
||||
public MovementTickerLivingVehicle(GrimPlayer player) {
|
||||
super(player);
|
||||
|
||||
@@ -3,12 +3,13 @@ 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 org.bukkit.util.Vector;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
public class MovementTickerPig extends MovementTickerRideable {
|
||||
public MovementTickerPig(GrimPlayer player) {
|
||||
super(player);
|
||||
movementInput = new Vector(0, 0, 1);
|
||||
movementInput = newVector3D(0, 0, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-3
@@ -11,15 +11,16 @@ 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 = new Vector(0, 0, 1);
|
||||
movementInput = newVector3D(0, 0, 1);
|
||||
}
|
||||
|
||||
public static void floatStrider(GrimPlayer player) {
|
||||
@@ -27,7 +28,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(new Vector(0, 0.05, 0));
|
||||
player.clientVelocity.multiply(0.5).add(newVector3D(0, 0.05, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ 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;
|
||||
@@ -11,20 +12,29 @@ 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 com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
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 Vector clampMovementToHardBorder(GrimPlayer player, Vector outputVel) {
|
||||
public static Vector3D clampMovementToHardBorder(GrimPlayer player, Vector3D outputVel) {
|
||||
// TODO: Reimplement
|
||||
return outputVel;
|
||||
}
|
||||
|
||||
public static Vector transformInputsToVector(GrimPlayer player, Vector theoreticalInput) {
|
||||
public static Vector3D transformInputsToVector(GrimPlayer player, Vector3D theoreticalInput) {
|
||||
float bestPossibleX;
|
||||
float bestPossibleZ;
|
||||
|
||||
@@ -42,15 +52,15 @@ public class PredictionEngine {
|
||||
bestPossibleZ *= 0.2F;
|
||||
}
|
||||
|
||||
Vector inputVector = new Vector(bestPossibleX, 0, bestPossibleZ);
|
||||
Vector3D inputVector = newVector3D(bestPossibleX, 0, bestPossibleZ);
|
||||
inputVector.multiply(0.98F);
|
||||
|
||||
// Simulate float rounding imprecision
|
||||
inputVector = new Vector((float) inputVector.getX(), (float) inputVector.getY(), (float) inputVector.getZ());
|
||||
inputVector = newVector3D((float) inputVector.getX(), (float) inputVector.getY(), (float) inputVector.getZ());
|
||||
|
||||
if (inputVector.lengthSquared() > 1) {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
return inputVector;
|
||||
@@ -62,7 +72,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...
|
||||
Vector toZeroVec = new PredictionEngine().handleStartingVelocityUncertainty(player, data, new Vector(0, -1000000000, 0)); // Downwards without overflow risk
|
||||
Vector3D toZeroVec = new PredictionEngine().handleStartingVelocityUncertainty(player, data, newVector3D(0, -1000000000, 0)); // Downwards without overflow risk
|
||||
|
||||
player.uncertaintyHandler.nextTickSlimeBlockUncertainty = Math.max(Math.abs(toZeroVec.getY()), player.uncertaintyHandler.nextTickSlimeBlockUncertainty);
|
||||
}
|
||||
@@ -105,20 +115,22 @@ public class PredictionEngine {
|
||||
double bestInput = Double.MAX_VALUE;
|
||||
|
||||
VectorData bestCollisionVel = null;
|
||||
Vector beforeCollisionMovement = null;
|
||||
Vector originalClientVel = player.clientVelocity.clone();
|
||||
Vector3D beforeCollisionMovement = null;
|
||||
Vector3D 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) {
|
||||
Vector primaryPushMovement = handleStartingVelocityUncertainty(player, clientVelAfterInput, player.actualMovement);
|
||||
Vector3D primaryPushMovement = handleStartingVelocityUncertainty(player, clientVelAfterInput, player.actualMovement);
|
||||
|
||||
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());
|
||||
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());
|
||||
// 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()) {
|
||||
@@ -132,9 +144,9 @@ public class PredictionEngine {
|
||||
}
|
||||
|
||||
// Returns pair of primary push movement, and then outputvel
|
||||
Pair<Vector, Vector> output = doSeekingWallCollisions(player, primaryPushMovement, originalClientVel, clientVelAfterInput);
|
||||
Pair<Vector3D, Vector3D> output = doSeekingWallCollisions(player, primaryPushMovement, originalClientVel, clientVelAfterInput);
|
||||
primaryPushMovement = output.first();
|
||||
Vector outputVel = clampMovementToHardBorder(player, output.second());
|
||||
Vector3D outputVel = clampMovementToHardBorder(player, output.second());
|
||||
|
||||
double resultAccuracy = outputVel.distanceSquared(player.actualMovement);
|
||||
|
||||
@@ -208,7 +220,7 @@ public class PredictionEngine {
|
||||
}
|
||||
}
|
||||
|
||||
private Pair<Vector, Vector> doSeekingWallCollisions(GrimPlayer player, Vector primaryPushMovement, Vector originalClientVel, VectorData clientVelAfterInput) {
|
||||
private Pair<Vector3D, Vector3D> doSeekingWallCollisions(GrimPlayer player, Vector3D primaryPushMovement, Vector3D 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;
|
||||
@@ -221,9 +233,9 @@ public class PredictionEngine {
|
||||
double testX = primaryPushMovement.getX() + xAdditional;
|
||||
double testY = primaryPushMovement.getY() + yAdditional;
|
||||
double testZ = primaryPushMovement.getZ() + zAdditional;
|
||||
primaryPushMovement = new Vector(testX, testY, testZ);
|
||||
primaryPushMovement = newVector3D(testX, testY, testZ);
|
||||
|
||||
Vector outputVel = Collisions.collide(player, primaryPushMovement.getX(), primaryPushMovement.getY(), primaryPushMovement.getZ(), originalClientVel.getY(), clientVelAfterInput);
|
||||
Vector3D 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);
|
||||
@@ -249,20 +261,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
|
||||
Vector pointThreeVector = new Vector();
|
||||
Vector3D pointThreeVector = newVector3D();
|
||||
|
||||
// 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(new Vector(0, player.clientVelocity.getY(), 0), VectorData.VectorType.ZeroPointZeroThree));
|
||||
pointThreePossibilities.add(new VectorData(newVector3D(0, player.clientVelocity.getY(), 0), 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(new Vector(0, 0.3, 0), VectorData.VectorType.ZeroPointZeroThree));
|
||||
pointThreePossibilities.add(new VectorData(newVector3D(0, 0.3, 0), ZeroPointZeroThree));
|
||||
}
|
||||
|
||||
// Swimming vertically can add more Y velocity than normal
|
||||
@@ -279,7 +291,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
|
||||
Vector hackyClimbVector = new Vector(0, 0.2, 0);
|
||||
Vector3D hackyClimbVector = newVector3D(0, 0.2, 0);
|
||||
PredictionEngineNormal.staticVectorEndOfTick(player, hackyClimbVector);
|
||||
|
||||
pointThreePossibilities.add(new VectorData(hackyClimbVector, VectorData.VectorType.ZeroPointZeroThree));
|
||||
@@ -290,8 +302,8 @@ public class PredictionEngine {
|
||||
addExplosionToPossibilities(player, pointThreePossibilities);
|
||||
|
||||
if (player.packetStateData.tryingToRiptide) {
|
||||
Vector riptideAddition = Riptide.getRiptideVelocity(player);
|
||||
pointThreePossibilities.add(new VectorData(player.clientVelocity.clone().add(riptideAddition), new VectorData(new Vector(), VectorData.VectorType.ZeroPointZeroThree), VectorData.VectorType.Trident));
|
||||
Vector3D riptideAddition = Riptide.getRiptideVelocity(player);
|
||||
pointThreePossibilities.add(new VectorData(player.clientVelocity.clone().add(riptideAddition), new VectorData(newVector3D(), ZeroPointZeroThree), VectorData.VectorType.Trident));
|
||||
}
|
||||
|
||||
possibleVelocities.addAll(applyInputsToVelocityPossibilities(player, pointThreePossibilities, speed));
|
||||
@@ -312,7 +324,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)) {
|
||||
Vector vec3 = player.baseTickWaterPushing.clone();
|
||||
Vector3D 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);
|
||||
}
|
||||
@@ -332,7 +344,7 @@ public class PredictionEngine {
|
||||
addExplosionToPossibilities(player, velocities);
|
||||
|
||||
if (player.packetStateData.tryingToRiptide) {
|
||||
Vector riptideAddition = Riptide.getRiptideVelocity(player);
|
||||
Vector3D riptideAddition = Riptide.getRiptideVelocity(player);
|
||||
velocities.add(new VectorData(player.clientVelocity.clone().add(riptideAddition), VectorData.VectorType.Trident));
|
||||
}
|
||||
|
||||
@@ -361,7 +373,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(new Vector(0.6, 1, 0.6)), VectorData.VectorType.AttackSlow));
|
||||
velocities.add(data.returnNewModified(data.vector.clone().multiply(newVector3D(0.6, 1, 0.6)), VectorData.VectorType.AttackSlow));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -464,15 +476,15 @@ public class PredictionEngine {
|
||||
return Double.compare(a.vector.distanceSquared(player.actualMovement), b.vector.distanceSquared(player.actualMovement));
|
||||
}
|
||||
|
||||
public Vector handleStartingVelocityUncertainty(GrimPlayer player, VectorData vector, Vector targetVec) {
|
||||
double avgColliding = Collections.max(player.uncertaintyHandler.collidingEntities);
|
||||
public Vector3D handleStartingVelocityUncertainty(GrimPlayer player, VectorData vector, Vector3D targetVec) {
|
||||
double avgColliding = max(player.uncertaintyHandler.collidingEntities);
|
||||
|
||||
double additionHorizontal = player.uncertaintyHandler.getOffsetHorizontal(vector);
|
||||
double additionVertical = player.uncertaintyHandler.getVerticalOffset(vector);
|
||||
|
||||
double pistonX = Collections.max(player.uncertaintyHandler.pistonX);
|
||||
double pistonY = Collections.max(player.uncertaintyHandler.pistonY);
|
||||
double pistonZ = Collections.max(player.uncertaintyHandler.pistonZ);
|
||||
double pistonX = max(player.uncertaintyHandler.pistonX);
|
||||
double pistonY = max(player.uncertaintyHandler.pistonY);
|
||||
double pistonZ = max(player.uncertaintyHandler.pistonZ);
|
||||
|
||||
additionHorizontal += player.uncertaintyHandler.lastHorizontalOffset;
|
||||
additionVertical += player.uncertaintyHandler.lastVerticalOffset;
|
||||
@@ -515,13 +527,13 @@ public class PredictionEngine {
|
||||
// 0.075 seems safe?
|
||||
//
|
||||
// Be somewhat careful as there is an antikb (for horizontal) that relies on this lenience
|
||||
Vector uncertainty = new Vector(avgColliding * 0.08, additionVertical, avgColliding * 0.08);
|
||||
Vector3D uncertainty = newVector3D(avgColliding * 0.08, additionVertical, avgColliding * 0.08);
|
||||
|
||||
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 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 minVector = vector.vector.clone().add(min.subtract(uncertainty));
|
||||
Vector maxVector = vector.vector.clone().add(max.add(uncertainty));
|
||||
Vector3D minVector = vector.vector.clone().add(min.subtract(uncertainty));
|
||||
Vector3D 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) {
|
||||
@@ -548,7 +560,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(Attributes.GENERIC_GRAVITY));
|
||||
minVector.setY(minVector.getY() - player.compensatedEntities.getSelf().getAttributeValue(GENERIC_GRAVITY));
|
||||
}
|
||||
|
||||
// Hidden slime block bounces by missing idle tick and 0.03
|
||||
@@ -588,9 +600,9 @@ public class PredictionEngine {
|
||||
box.maxZ += sneaking.getSneakingPotentialHiddenVelocity().maxZ;
|
||||
|
||||
if (player.uncertaintyHandler.fireworksBox != null) {
|
||||
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 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 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());
|
||||
@@ -646,7 +658,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(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)))) {
|
||||
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)))) {
|
||||
box.expandToAbsoluteCoordinates(0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -658,9 +670,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 = 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 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 maxX = Math.max(box.maxX, box.maxX + (player.speed * trueFriction));
|
||||
double maxZ = Math.max(box.maxZ, box.maxZ + (player.speed * trueFriction));
|
||||
|
||||
@@ -676,15 +688,15 @@ public class PredictionEngine {
|
||||
maxVector = box.max();
|
||||
|
||||
if (pistonX != 0) {
|
||||
minVector.setX(Math.min(minVector.getX() - pistonX, pistonX));
|
||||
minVector.setX(min(minVector.getX() - pistonX, pistonX));
|
||||
maxVector.setX(Math.max(maxVector.getX() + pistonX, pistonX));
|
||||
}
|
||||
if (pistonY != 0) {
|
||||
minVector.setY(Math.min(minVector.getY() - pistonY, pistonY));
|
||||
minVector.setY(min(minVector.getY() - pistonY, pistonY));
|
||||
maxVector.setY(Math.max(maxVector.getY() + pistonY, pistonY));
|
||||
}
|
||||
if (pistonZ != 0) {
|
||||
minVector.setZ(Math.min(minVector.getZ() - pistonZ, pistonZ));
|
||||
minVector.setZ(min(minVector.getZ() - pistonZ, pistonZ));
|
||||
maxVector.setZ(Math.max(maxVector.getZ() + pistonZ, pistonZ));
|
||||
}
|
||||
return VectorUtils.cutBoxToVector(targetVec, minVector, maxVector);
|
||||
@@ -700,7 +712,36 @@ 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 zMin = player.isSprinting && !player.isSwimming ? 1 : -1;
|
||||
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--;
|
||||
}
|
||||
}
|
||||
|
||||
for (int loopSlowed = 0; loopSlowed <= 1; loopSlowed++) {
|
||||
// Loop twice for the using item status if the player is using a trident
|
||||
@@ -712,9 +753,11 @@ public class PredictionEngine {
|
||||
for (VectorData possibleLastTickOutput : possibleVectors) {
|
||||
// Only do this when there is tick skipping
|
||||
if (loopSlowed == 1 && !possibleLastTickOutput.isZeroPointZeroThree()) continue;
|
||||
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);
|
||||
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);
|
||||
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
|
||||
@@ -781,21 +824,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 Vector getMovementResultFromInput(GrimPlayer player, Vector inputVector, float f, float f2) {
|
||||
public Vector3D getMovementResultFromInput(GrimPlayer player, Vector3D 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 new Vector(xResult * f, 0, zResult * f);
|
||||
return newVector3D(xResult * f, 0, zResult * f);
|
||||
}
|
||||
|
||||
public Vector handleOnClimbable(Vector vector, GrimPlayer player) {
|
||||
public Vector3D handleOnClimbable(Vector3D vector, GrimPlayer player) {
|
||||
return vector;
|
||||
}
|
||||
|
||||
public void doJump(GrimPlayer player, Vector vector) {
|
||||
public void doJump(GrimPlayer player, Vector3D vector) {
|
||||
if (!player.lastOnGround || player.onGround)
|
||||
return;
|
||||
|
||||
|
||||
+21
-16
@@ -3,28 +3,33 @@ 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 com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
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<>();
|
||||
Vector currentLook = ReachUtils.getLook(player, player.xRot, player.yRot);
|
||||
Vector3D currentLook = ReachUtils.getLook(player, player.xRot, player.yRot);
|
||||
|
||||
for (VectorData data : possibleVectors) {
|
||||
Vector elytraResult = getElytraMovement(player, data.vector.clone(), currentLook).multiply(player.stuckSpeedMultiplier).multiply(new Vector(0.99F, 0.98F, 0.99F));
|
||||
Vector3D elytraResult = getElytraMovement(player, data.vector.clone(), currentLook).multiply(player.stuckSpeedMultiplier).multiply(newVector3D(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(new Vector(0.99F, 0.98F, 0.99F));
|
||||
elytraResult = getElytraMovement(player, data.vector.clone(), ReachUtils.getLook(player, player.xRot, player.yRot)).multiply(player.stuckSpeedMultiplier).multiply(newVector3D(0.99F, 0.98F, 0.99F));
|
||||
player.trigHandler.toggleShitMath();
|
||||
results.add(data.returnNewModified(elytraResult, VectorData.VectorType.InputResult));
|
||||
}
|
||||
@@ -32,42 +37,42 @@ public class PredictionEngineElytra extends PredictionEngine {
|
||||
return results;
|
||||
}
|
||||
|
||||
public static Vector getElytraMovement(GrimPlayer player, Vector vector, Vector lookVector) {
|
||||
public static Vector3D getElytraMovement(GrimPlayer player, Vector3D vector, Vector3D lookVector) {
|
||||
float yRotRadians = player.yRot * 0.017453292F;
|
||||
double horizontalSqrt = Math.sqrt(lookVector.getX() * lookVector.getX() + lookVector.getZ() * lookVector.getZ());
|
||||
double horizontalSqrt = 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(ClientVersion.V_1_18_2) ? Math.cos(yRotRadians) : player.trigHandler.cos(yRotRadians);
|
||||
vertCosRotation = (float) (vertCosRotation * vertCosRotation * Math.min(1.0D, length / 0.4D));
|
||||
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));
|
||||
|
||||
// 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(Attributes.GENERIC_GRAVITY);
|
||||
double recalculatedGravity = player.compensatedEntities.getSelf().getAttributeValue(GENERIC_GRAVITY);
|
||||
if (player.clientVelocity.getY() <= 0 && player.compensatedEntities.getSlowFallingAmplifier().isPresent()) {
|
||||
recalculatedGravity = player.getClientVersion().isOlderThan(ClientVersion.V_1_20_5) ? 0.01 : Math.min(recalculatedGravity, 0.01);
|
||||
recalculatedGravity = player.getClientVersion().isOlderThan(V_1_20_5) ? 0.01 : min(recalculatedGravity, 0.01);
|
||||
}
|
||||
|
||||
vector.add(new Vector(0.0D, recalculatedGravity * (-1.0D + vertCosRotation * 0.75D), 0.0D));
|
||||
vector.add(newVector3D(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(new Vector(lookVector.getX() * d5 / horizontalSqrt, d5, lookVector.getZ() * d5 / horizontalSqrt));
|
||||
vector.add(newVector3D(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(new Vector(-lookVector.getX() * d5 / horizontalSqrt, d5 * 3.2D, -lookVector.getZ() * d5 / horizontalSqrt));
|
||||
vector.add(newVector3D(-lookVector.getX() * d5 / horizontalSqrt, d5 * 3.2D, -lookVector.getZ() * d5 / horizontalSqrt));
|
||||
}
|
||||
|
||||
// Handle accelerating the player sideways
|
||||
if (horizontalSqrt > 0) {
|
||||
vector.add(new Vector((lookVector.getX() / horizontalSqrt * horizontalLength - vector.getX()) * 0.1D, 0.0D, (lookVector.getZ() / horizontalSqrt * horizontalLength - vector.getZ()) * 0.1D));
|
||||
vector.add(newVector3D((lookVector.getX() / horizontalSqrt * horizontalLength - vector.getX()) * 0.1D, 0.0D, (lookVector.getZ() / horizontalSqrt * horizontalLength - vector.getZ()) * 0.1D));
|
||||
}
|
||||
|
||||
return vector;
|
||||
|
||||
@@ -3,11 +3,13 @@ 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
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) {
|
||||
@@ -16,11 +18,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(new Vector(0, 0.04f, 0)), vector, VectorData.VectorType.Jump));
|
||||
existingVelocities.add(new VectorData(vector.vector.clone().add(newVector3D(0, 0.04f, 0)), vector, VectorData.VectorType.Jump));
|
||||
}
|
||||
|
||||
if (player.slightlyTouchingLava && player.lastOnGround && !player.onGround) {
|
||||
Vector withJump = vector.vector.clone();
|
||||
Vector3D withJump = vector.vector.clone();
|
||||
super.doJump(player, withJump);
|
||||
existingVelocities.add(new VectorData(withJump, vector, VectorData.VectorType.Jump));
|
||||
}
|
||||
|
||||
+21
-12
@@ -3,23 +3,28 @@ 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
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, Vector vector) {
|
||||
public static void staticVectorEndOfTick(GrimPlayer player, Vector3D vector) {
|
||||
double adjustedY = vector.getY();
|
||||
final OptionalInt levitation = player.compensatedEntities.getPotionLevelForPlayer(PotionTypes.LEVITATION);
|
||||
if (levitation.isPresent()) {
|
||||
@@ -37,8 +42,12 @@ 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)) {
|
||||
Vector jump = vector.vector.clone();
|
||||
Vector3D jump = vector.vector.clone();
|
||||
|
||||
if (!player.isFlying) {
|
||||
// Negative jump boost does not allow the player to leave the ground
|
||||
@@ -52,9 +61,9 @@ public class PredictionEngineNormal extends PredictionEngine {
|
||||
|
||||
JumpPower.jumpFromGround(player, jump);
|
||||
} else {
|
||||
jump.add(new Vector(0, player.flySpeed * 3, 0));
|
||||
jump.add(newVector3D(0, player.flySpeed * 3, 0));
|
||||
if (!player.wasFlying) {
|
||||
Vector edgeCaseJump = jump.clone();
|
||||
Vector3D edgeCaseJump = jump.clone();
|
||||
JumpPower.jumpFromGround(player, edgeCaseJump);
|
||||
existingVelocities.add(vector.returnNewModified(edgeCaseJump, VectorData.VectorType.Jump));
|
||||
}
|
||||
@@ -82,7 +91,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) {
|
||||
Vector ladderVelocity = player.clientVelocity.clone().setY(0.2);
|
||||
Vector3D ladderVelocity = player.clientVelocity.clone().setY(0.2);
|
||||
staticVectorEndOfTick(player, ladderVelocity);
|
||||
player.lastWasClimbing = ladderVelocity.getY();
|
||||
}
|
||||
@@ -93,17 +102,17 @@ public class PredictionEngineNormal extends PredictionEngine {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector handleOnClimbable(Vector vector, GrimPlayer player) {
|
||||
public Vector3D handleOnClimbable(Vector3D vector, GrimPlayer player) {
|
||||
if (player.isClimbing) {
|
||||
// Reset fall distance when climbing
|
||||
player.fallDistance = 0;
|
||||
|
||||
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));
|
||||
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));
|
||||
|
||||
// Yes, this uses shifting not crouching
|
||||
if (vector.getY() < 0.0 && !(player.compensatedWorld.getStateTypeAt(player.lastX, player.lastY, player.lastZ) == StateTypes.SCAFFOLDING) && player.isSneaking && !player.isFlying) {
|
||||
if (vector.getY() < 0.0 && !(player.compensatedWorld.getStateTypeAt(player.lastX, player.lastY, player.lastZ) == SCAFFOLDING) && player.isSneaking && !player.isFlying) {
|
||||
vector.setY(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
+10
-7
@@ -9,11 +9,14 @@ 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
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;
|
||||
@@ -21,9 +24,9 @@ public class PredictionEngineWater extends PredictionEngine {
|
||||
float swimmingFriction;
|
||||
double lastY;
|
||||
|
||||
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);
|
||||
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);
|
||||
vector.setX(fluidVector.getX());
|
||||
vector.setY(fluidVector.getY());
|
||||
vector.setZ(fluidVector.getZ());
|
||||
@@ -47,7 +50,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(new Vector(vector.vector.getX(), vector.vector.getY() + ((lookYAmount - vector.vector.getY()) * scalar), vector.vector.getZ()), VectorData.VectorType.SwimmingSpace));
|
||||
swimmingVelocities.add(vector.returnNewModified(newVector3D(vector.vector.getX(), vector.vector.getY() + ((lookYAmount - vector.vector.getY()) * scalar), vector.vector.getZ()), 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
|
||||
@@ -80,11 +83,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(new Vector(0, 0.04f, 0)), vector, VectorData.VectorType.Jump));
|
||||
existingVelocities.add(new VectorData(vector.vector.clone().add(newVector3D(0, 0.04f, 0)), vector, VectorData.VectorType.Jump));
|
||||
}
|
||||
|
||||
if (player.slightlyTouchingWater && player.lastOnGround && !player.onGround) {
|
||||
Vector withJump = vector.vector.clone();
|
||||
Vector3D withJump = vector.vector.clone();
|
||||
super.doJump(player, withJump);
|
||||
existingVelocities.add(new VectorData(withJump, vector, VectorData.VectorType.Jump));
|
||||
}
|
||||
|
||||
+12
-9
@@ -2,11 +2,15 @@ package ac.grim.grimac.predictionengine.predictions;
|
||||
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.data.VectorData;
|
||||
import org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
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;
|
||||
@@ -23,11 +27,11 @@ public class PredictionEngineWaterLegacy extends PredictionEngine {
|
||||
|
||||
// This is just the vanilla equation for legacy water movement
|
||||
@Override
|
||||
public Vector getMovementResultFromInput(GrimPlayer player, Vector inputVector, float f, float f2) {
|
||||
public Vector3D getMovementResultFromInput(GrimPlayer player, Vector3D inputVector, float f, float f2) {
|
||||
float lengthSquared = (float) inputVector.lengthSquared();
|
||||
|
||||
if (lengthSquared >= 1.0E-4F) {
|
||||
lengthSquared = (float) Math.sqrt(lengthSquared);
|
||||
lengthSquared = (float) sqrt(lengthSquared);
|
||||
|
||||
if (lengthSquared < 1.0F) {
|
||||
lengthSquared = 1.0F;
|
||||
@@ -38,21 +42,20 @@ public class PredictionEngineWaterLegacy extends PredictionEngine {
|
||||
float sinResult = player.trigHandler.sin(player.xRot * 0.017453292F);
|
||||
float cosResult = player.trigHandler.cos(player.xRot * 0.017453292F);
|
||||
|
||||
return new Vector(inputVector.getX() * cosResult - inputVector.getZ() * sinResult,
|
||||
inputVector.getY(), inputVector.getZ() * cosResult + inputVector.getX() * sinResult);
|
||||
return newVector3D(inputVector.getX() * cosResult - inputVector.getZ() * sinResult, inputVector.getY(), inputVector.getZ() * cosResult + inputVector.getX() * sinResult);
|
||||
}
|
||||
|
||||
return new Vector();
|
||||
return newVector3D();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addJumpsToPossibilities(GrimPlayer player, Set<VectorData> existingVelocities) {
|
||||
for (VectorData vector : new HashSet<>(existingVelocities)) {
|
||||
existingVelocities.add(new VectorData(vector.vector.clone().add(new Vector(0, 0.04f, 0)), vector, VectorData.VectorType.Jump));
|
||||
existingVelocities.add(new VectorData(vector.vector.clone().add(newVector3D(0, 0.04f, 0)), vector, VectorData.VectorType.Jump));
|
||||
|
||||
if (player.skippedTickInActualMovement) {
|
||||
existingVelocities.add(new VectorData(vector.vector.clone().add(new Vector(0, 0.02f, 0)), vector, VectorData.VectorType.Jump));
|
||||
existingVelocities.add(new VectorData(vector.vector.clone().add(newVector3D(0, 0.02f, 0)), vector, VectorData.VectorType.Jump));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,7 +65,7 @@ public class PredictionEngineWaterLegacy extends PredictionEngine {
|
||||
super.endOfTick(player, playerGravity);
|
||||
|
||||
for (VectorData vector : player.getPossibleVelocitiesMinusKnockback()) {
|
||||
vector.vector.multiply(new Vector(swimmingFriction, 0.8F, swimmingFriction));
|
||||
vector.vector.multiply(newVector3D(swimmingFriction, 0.8F, swimmingFriction));
|
||||
|
||||
// Gravity
|
||||
vector.vector.setY(vector.vector.getY() - 0.02D);
|
||||
|
||||
+9
-6
@@ -13,12 +13,15 @@ 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
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
|
||||
@@ -147,7 +150,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) {
|
||||
Vector vector = data.vector.clone();
|
||||
Vector3D vector = data.vector.clone();
|
||||
controlBoat(player, vector, true);
|
||||
vector.multiply(player.stuckSpeedMultiplier);
|
||||
vectors.add(data.returnNewModified(vector, VectorData.VectorType.InputResult));
|
||||
@@ -184,7 +187,7 @@ public class BoatPredictionEngine extends PredictionEngine {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void floatBoat(GrimPlayer player, Vector vector) {
|
||||
private void floatBoat(GrimPlayer player, Vector3D vector) {
|
||||
double d1 = player.hasGravity ? -0.04f : 0;
|
||||
double d2 = 0.0D;
|
||||
float invFriction = 0.05F;
|
||||
@@ -194,7 +197,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 = new Vector(player.x - player.lastX, player.y - player.lastY, player.z - player.lastZ);
|
||||
player.actualMovement = newVector3D(player.x - player.lastX, player.y - player.lastY, player.z - player.lastZ);
|
||||
vector.setY(0);
|
||||
|
||||
player.vehicleData.lastYd = 0.0D;
|
||||
@@ -260,7 +263,7 @@ public class BoatPredictionEngine extends PredictionEngine {
|
||||
return (float) (l + 1);
|
||||
}
|
||||
|
||||
private void controlBoat(GrimPlayer player, Vector vector, boolean intermediate) {
|
||||
private void controlBoat(GrimPlayer player, Vector3D vector, boolean intermediate) {
|
||||
float f = 0.0F;
|
||||
if (player.vehicleData.vehicleHorizontal != 0 && (!intermediate && player.vehicleData.vehicleForward == 0)) {
|
||||
f += 0.005F;
|
||||
@@ -275,6 +278,6 @@ public class BoatPredictionEngine extends PredictionEngine {
|
||||
f -= 0.005F;
|
||||
}
|
||||
|
||||
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)));
|
||||
vector.add(newVector3D(player.trigHandler.sin(-player.xRot * ((float) PI / 180F)) * f, 0, (double) (player.trigHandler.cos(player.xRot * ((float) 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PredictionEngineRideableLava extends PredictionEngineLava {
|
||||
|
||||
Vector movementVector;
|
||||
Vector3D movementVector;
|
||||
|
||||
public PredictionEngineRideableLava(Vector movementVector) {
|
||||
public PredictionEngineRideableLava(Vector3D 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PredictionEngineRideableNormal extends PredictionEngineNormal {
|
||||
|
||||
Vector movementVector;
|
||||
Vector3D movementVector;
|
||||
|
||||
public PredictionEngineRideableNormal(Vector movementVector) {
|
||||
public PredictionEngineRideableNormal(Vector3D movementVector) {
|
||||
this.movementVector = movementVector;
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -8,13 +8,15 @@ 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
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;
|
||||
@@ -55,7 +57,7 @@ public class PredictionEngineRideableUtils {
|
||||
for (VectorData vectorData : possibleVectors) {
|
||||
vectorData.vector.setY(d1);
|
||||
if (f1 > 0.0F) {
|
||||
vectorData.vector.add(new Vector(-0.4F * f2 * player.vehicleData.horseJump, 0.0D, 0.4F * f3 * player.vehicleData.horseJump));
|
||||
vectorData.vector.add(newVector3D(-0.4F * f2 * player.vehicleData.horseJump, 0.0D, 0.4F * f3 * player.vehicleData.horseJump));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +73,7 @@ public class PredictionEngineRideableUtils {
|
||||
return possibleVectors;
|
||||
}
|
||||
|
||||
public static List<VectorData> applyInputsToVelocityPossibilities(Vector movementVector, GrimPlayer player, Set<VectorData> possibleVectors, float speed) {
|
||||
public static List<VectorData> applyInputsToVelocityPossibilities(Vector3D 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PredictionEngineRideableWater extends PredictionEngineWater {
|
||||
|
||||
Vector movementVector;
|
||||
Vector3D movementVector;
|
||||
|
||||
public PredictionEngineRideableWater(Vector movementVector) {
|
||||
public PredictionEngineRideableWater(Vector3D 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PredictionEngineRideableWaterLegacy extends PredictionEngineWaterLegacy {
|
||||
Vector movementVector;
|
||||
Vector3D movementVector;
|
||||
|
||||
public PredictionEngineRideableWaterLegacy(Vector movementVector) {
|
||||
public PredictionEngineRideableWaterLegacy(Vector3D movementVector) {
|
||||
this.movementVector = movementVector;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import ac.grim.grimac.utils.collisions.AxisUtil;
|
||||
import ac.grim.grimac.utils.collisions.CollisionData;
|
||||
import ac.grim.grimac.utils.collisions.blocks.DoorHandler;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.CollisionBox;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.ComplexCollisionBox;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.HitData;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntity;
|
||||
@@ -15,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.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.attribute.Attributes;
|
||||
@@ -34,19 +35,23 @@ import com.github.retrooper.packetevents.util.Vector3f;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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
|
||||
Vector3i blockPosition;
|
||||
public Vector3i blockPosition;
|
||||
@Getter
|
||||
InteractionHand hand;
|
||||
@Getter
|
||||
@@ -72,6 +77,9 @@ public class BlockPlace {
|
||||
|
||||
@Getter private final boolean block;
|
||||
|
||||
// Allocated once instead of in functions to reduce new[] calls that need to be made. Since per-instance BlockPlace is always dealt with on the same thread we can use 1 buffer array
|
||||
private final SimpleCollisionBox[] collisions = new SimpleCollisionBox[ComplexCollisionBox.DEFAULT_MAX_COLLISION_BOX_SIZE];
|
||||
|
||||
public BlockPlace(GrimPlayer player, InteractionHand hand, Vector3i blockPosition, int faceId, BlockFace face, ItemStack itemStack, HitData hitData) {
|
||||
this.player = player;
|
||||
this.hand = hand;
|
||||
@@ -200,12 +208,12 @@ public class BlockPlace {
|
||||
if (BlockTags.LEAVES.contains(data.getType())) return false;
|
||||
if (BlockTags.FENCE_GATES.contains(data.getType())) return false;
|
||||
|
||||
List<SimpleCollisionBox> collisions = new ArrayList<>();
|
||||
box.downCast(collisions);
|
||||
int size = box.downCast(collisions);
|
||||
|
||||
AxisSelect axis = AxisUtil.getAxis(facing.getOppositeFace());
|
||||
|
||||
for (SimpleCollisionBox simpleBox : collisions) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
SimpleCollisionBox simpleBox = collisions[i];
|
||||
simpleBox = axis.modify(simpleBox);
|
||||
if (simpleBox.minX <= 7 / 16d && simpleBox.maxX >= 7 / 16d
|
||||
&& simpleBox.minY <= 0 && simpleBox.maxY >= 10 / 16d
|
||||
@@ -225,12 +233,12 @@ public class BlockPlace {
|
||||
if (isFullFace(facing)) return true;
|
||||
if (BlockTags.LEAVES.contains(data.getType())) return false;
|
||||
|
||||
List<SimpleCollisionBox> collisions = new ArrayList<>();
|
||||
box.downCast(collisions);
|
||||
int size = box.downCast(collisions);
|
||||
|
||||
AxisSelect axis = AxisUtil.getAxis(facing.getOppositeFace());
|
||||
|
||||
for (SimpleCollisionBox simpleBox : collisions) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
SimpleCollisionBox simpleBox = collisions[i];
|
||||
simpleBox = axis.modify(simpleBox);
|
||||
if (simpleBox.minX <= 2 / 16d && simpleBox.maxX >= 14 / 16d
|
||||
&& simpleBox.minY <= 0 && simpleBox.maxY >= 1
|
||||
@@ -289,10 +297,10 @@ public class BlockPlace {
|
||||
}
|
||||
}
|
||||
|
||||
List<SimpleCollisionBox> collisions = new ArrayList<>();
|
||||
box.downCast(collisions);
|
||||
int size = box.downCast(collisions);
|
||||
|
||||
for (SimpleCollisionBox simpleBox : collisions) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
SimpleCollisionBox simpleBox = collisions[i];
|
||||
if (axis.modify(simpleBox).isFullBlockNoCache()) return true;
|
||||
}
|
||||
|
||||
@@ -318,12 +326,12 @@ public class BlockPlace {
|
||||
if (isFullFace(facing)) return true;
|
||||
if (BlockTags.LEAVES.contains(data.getType())) return false;
|
||||
|
||||
List<SimpleCollisionBox> collisions = new ArrayList<>();
|
||||
box.downCast(collisions);
|
||||
int size = box.downCast(collisions);
|
||||
|
||||
AxisSelect axis = AxisUtil.getAxis(facing.getOppositeFace());
|
||||
|
||||
for (SimpleCollisionBox simpleBox : collisions) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
SimpleCollisionBox simpleBox = collisions[i];
|
||||
simpleBox = axis.modify(simpleBox);
|
||||
// If all sides to the box have width, there is collision.
|
||||
switch (facing) {
|
||||
@@ -658,18 +666,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 Vector getClickedLocation() {
|
||||
public Vector3D getClickedLocation() {
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(getPlacedAgainstBlockLocation());
|
||||
Vector look = ReachUtils.getLook(player, player.xRot, player.yRot);
|
||||
Vector3D look = getLook(player, player.xRot, player.yRot);
|
||||
|
||||
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();
|
||||
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();
|
||||
|
||||
// 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 new Vector();
|
||||
if (intercept == null) return newVector3D();
|
||||
|
||||
intercept.setX(intercept.getX() - box.minX);
|
||||
intercept.setY(intercept.getY() - box.minY);
|
||||
|
||||
@@ -21,11 +21,13 @@ 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
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
|
||||
@@ -80,7 +82,7 @@ public enum BlockPlaceResult {
|
||||
}, ItemTypes.SNOW),
|
||||
|
||||
SLAB((player, place) -> {
|
||||
Vector clickedPos = place.getClickedLocation();
|
||||
Vector3D clickedPos = place.getClickedLocation();
|
||||
WrappedBlockState slabData = place.getMaterial().createBlockState(CompensatedWorld.blockVersion);
|
||||
WrappedBlockState existing = place.getExistingBlockData();
|
||||
|
||||
@@ -909,7 +911,7 @@ public enum BlockPlaceResult {
|
||||
WrappedBlockState ccwState = place.getDirectionalState(ccw);
|
||||
CollisionBox ccwBox = CollisionData.getData(ccwState.getType()).getMovementCollisionBox(player, player.getClientVersion(), ccwState);
|
||||
|
||||
Vector aboveCCWPos = place.getClickedLocation().add(new Vector(ccw.getModX(), ccw.getModY(), ccw.getModZ())).add(new Vector(0, 1, 0));
|
||||
Vector3D aboveCCWPos = place.getClickedLocation().add(newVector3D(ccw.getModX(), ccw.getModY(), ccw.getModZ())).add(newVector3D(0, 1, 0));
|
||||
WrappedBlockState aboveCCWState = player.compensatedWorld.getWrappedBlockStateAt(aboveCCWPos);
|
||||
CollisionBox aboveCCWBox = CollisionData.getData(aboveCCWState.getType()).getMovementCollisionBox(player, player.getClientVersion(), aboveCCWState);
|
||||
|
||||
@@ -917,7 +919,7 @@ public enum BlockPlaceResult {
|
||||
WrappedBlockState cwState = place.getDirectionalState(cw);
|
||||
CollisionBox cwBox = CollisionData.getData(cwState.getType()).getMovementCollisionBox(player, player.getClientVersion(), cwState);
|
||||
|
||||
Vector aboveCWPos = place.getClickedLocation().add(new Vector(cw.getModX(), cw.getModY(), cw.getModZ())).add(new Vector(0, 1, 0));
|
||||
Vector3D aboveCWPos = place.getClickedLocation().add(newVector3D(cw.getModX(), cw.getModY(), cw.getModZ())).add(newVector3D(0, 1, 0));
|
||||
WrappedBlockState aboveCWState = player.compensatedWorld.getWrappedBlockStateAt(aboveCWPos);
|
||||
CollisionBox aboveCWBox = CollisionData.getData(aboveCWState.getType()).getMovementCollisionBox(player, player.getClientVersion(), aboveCWState);
|
||||
|
||||
@@ -934,7 +936,7 @@ public enum BlockPlaceResult {
|
||||
if ((!isCWLower || isCCWLower) && i >= 0) {
|
||||
int j = playerFacing.getModX();
|
||||
int k = playerFacing.getModZ();
|
||||
Vector vec3 = place.getClickedLocation();
|
||||
Vector3D 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,7 +1,8 @@
|
||||
package ac.grim.grimac.utils.blockstate.helper;
|
||||
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
public class BlockFaceHelper {
|
||||
public static boolean isFaceVertical(BlockFace face) {
|
||||
@@ -56,7 +57,7 @@ public class BlockFaceHelper {
|
||||
};
|
||||
}
|
||||
|
||||
public Vector offset(Vector toOffset, BlockFace face) {
|
||||
public Vector3D offset(Vector3D toOffset, BlockFace face) {
|
||||
toOffset.setX(toOffset.getX() + face.getModX());
|
||||
toOffset.setY(toOffset.getY() + face.getModY());
|
||||
toOffset.setZ(toOffset.getZ() + face.getModZ());
|
||||
|
||||
@@ -36,7 +36,7 @@ import java.util.stream.Stream;
|
||||
// This is actually mean to be put into PacketEvents, but I don't like proprietary plugins stealing my code...
|
||||
public enum CollisionData {
|
||||
VINE((player, version, block, x, y, z) -> {
|
||||
ComplexCollisionBox boxes = new ComplexCollisionBox();
|
||||
ComplexCollisionBox boxes = new ComplexCollisionBox(5);
|
||||
|
||||
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_13) && block.isUp())
|
||||
boxes.add(new HexCollisionBox(0.0D, 15.0D, 0.0D, 16.0D, 16.0D, 16.0D));
|
||||
@@ -73,11 +73,19 @@ public enum CollisionData {
|
||||
|
||||
BREWING_STAND((player, version, block, x, y, z) -> {
|
||||
int base = 0;
|
||||
// maxIndex is 3 instead of 2 for legacy clients because for 1.8 players there is a very rare bug
|
||||
// That we handle later in the code requiring us to add a box https://bugs.mojang.com/browse/MC-85109 For 1.8 PLAYERS
|
||||
// 1.8 Brewing Stand hitbox is a fullblock until it is hit sometimes, can be caused be restarting client and joining server
|
||||
int maxIndex = 3;
|
||||
|
||||
if (version.isNewerThanOrEquals(ClientVersion.V_1_13))
|
||||
// Yes I know we only need maxIndex = 3 for 1.8 specifically
|
||||
// No I'm not adding a special clause for which would require another if check, I'll take compute > memory any day
|
||||
if (version.isNewerThanOrEquals(ClientVersion.V_1_13)) {
|
||||
maxIndex = 2;
|
||||
base = 1;
|
||||
}
|
||||
|
||||
return new ComplexCollisionBox(
|
||||
return new ComplexCollisionBox(maxIndex,
|
||||
new HexCollisionBox(base, 0, base, 16 - base, 2, 16 - base),
|
||||
new SimpleCollisionBox(0.4375, 0.0, 0.4375, 0.5625, 0.875, 0.5625, false));
|
||||
|
||||
@@ -100,7 +108,7 @@ public enum CollisionData {
|
||||
if (version.isOlderThanOrEquals(ClientVersion.V_1_12_2))
|
||||
height = 0.3125;
|
||||
|
||||
return new ComplexCollisionBox(
|
||||
return new ComplexCollisionBox(5,
|
||||
new SimpleCollisionBox(0, 0, 0, 1, height, 1, false),
|
||||
new SimpleCollisionBox(0, height, 0, 0.125, 1, 1, false),
|
||||
new SimpleCollisionBox(1 - 0.125, height, 0, 1, 1, 1, false),
|
||||
@@ -119,7 +127,7 @@ public enum CollisionData {
|
||||
// The base is 0.75×0.75, and its floor is 0.25b high.
|
||||
// The top is 1×0.625, and its ceiling is 0.375b low.
|
||||
if (version.isNewerThanOrEquals(ClientVersion.V_1_13)) {
|
||||
ComplexCollisionBox complexAnvil = new ComplexCollisionBox();
|
||||
ComplexCollisionBox complexAnvil = new ComplexCollisionBox(4);
|
||||
// Base of the anvil
|
||||
complexAnvil.add(new HexCollisionBox(2, 0, 2, 14, 4, 14));
|
||||
if (face == BlockFace.NORTH || face == BlockFace.SOUTH) {
|
||||
@@ -188,7 +196,7 @@ public enum CollisionData {
|
||||
|
||||
HOPPER((player, version, data, x, y, z) -> {
|
||||
if (version.isNewerThanOrEquals(ClientVersion.V_1_13)) {
|
||||
ComplexCollisionBox hopperBox = new ComplexCollisionBox();
|
||||
ComplexCollisionBox hopperBox = new ComplexCollisionBox(7);
|
||||
|
||||
switch (data.getFacing()) {
|
||||
case DOWN:
|
||||
@@ -219,7 +227,7 @@ public enum CollisionData {
|
||||
} else {
|
||||
double height = 0.125 * 5;
|
||||
|
||||
return new ComplexCollisionBox(
|
||||
return new ComplexCollisionBox(5,
|
||||
new SimpleCollisionBox(0, 0, 0, 1, height, 1, false),
|
||||
new SimpleCollisionBox(0, height, 0, 0.125, 1, 1, false),
|
||||
new SimpleCollisionBox(1 - 0.125, height, 0, 1, 1, 1, false),
|
||||
@@ -290,7 +298,7 @@ public enum CollisionData {
|
||||
|
||||
}
|
||||
|
||||
ComplexCollisionBox complex = new ComplexCollisionBox(
|
||||
ComplexCollisionBox complex = new ComplexCollisionBox(3,
|
||||
new HexCollisionBox(5.0D, 6.0D, 5.0D, 11.0D, 13.0D, 11.0D),
|
||||
new HexCollisionBox(4.0D, 4.0D, 4.0D, 12.0D, 6.0D, 12.0D));
|
||||
|
||||
@@ -324,7 +332,8 @@ public enum CollisionData {
|
||||
return new SimpleCollisionBox(0, 0, 0, 1, 1, 1, true);
|
||||
|
||||
if (player.lastY > y + 1 - 1e-5 && !player.isSneaking) {
|
||||
return new ComplexCollisionBox(new HexCollisionBox(0.0D, 14.0D, 0.0D, 16.0D, 16.0D, 16.0D),
|
||||
return new ComplexCollisionBox(5,
|
||||
new HexCollisionBox(0.0D, 14.0D, 0.0D, 16.0D, 16.0D, 16.0D),
|
||||
new HexCollisionBox(0.0D, 0.0D, 0.0D, 2.0D, 16.0D, 2.0D),
|
||||
new HexCollisionBox(14.0D, 0.0D, 0.0D, 16.0D, 16.0D, 2.0D),
|
||||
new HexCollisionBox(0.0D, 0.0D, 14.0D, 2.0D, 16.0D, 16.0),
|
||||
@@ -368,11 +377,13 @@ public enum CollisionData {
|
||||
return new SimpleCollisionBox(0, 0, 0, 1, 1, 1, true);
|
||||
|
||||
if (data.isHanging()) {
|
||||
return new ComplexCollisionBox(new HexCollisionBox(5.0D, 1.0D, 5.0D, 11.0D, 8.0D, 11.0D),
|
||||
return new ComplexCollisionBox(2,
|
||||
new HexCollisionBox(5.0D, 1.0D, 5.0D, 11.0D, 8.0D, 11.0D),
|
||||
new HexCollisionBox(6.0D, 8.0D, 6.0D, 10.0D, 10.0D, 10.0D));
|
||||
}
|
||||
|
||||
return new ComplexCollisionBox(new HexCollisionBox(5.0D, 0.0D, 5.0D, 11.0D, 7.0D, 11.0D),
|
||||
return new ComplexCollisionBox(2,
|
||||
new HexCollisionBox(5.0D, 0.0D, 5.0D, 11.0D, 7.0D, 11.0D),
|
||||
new HexCollisionBox(6.0D, 7.0D, 6.0D, 10.0D, 9.0D, 10.0D));
|
||||
|
||||
}, StateTypes.LANTERN, StateTypes.SOUL_LANTERN),
|
||||
@@ -382,7 +393,7 @@ public enum CollisionData {
|
||||
if (version.isOlderThanOrEquals(ClientVersion.V_1_13_2))
|
||||
return new SimpleCollisionBox(0, 0, 0, 1, 1, 1, true);
|
||||
|
||||
return new ComplexCollisionBox(
|
||||
return new ComplexCollisionBox(2,
|
||||
new HexCollisionBox(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D), // base
|
||||
new HexCollisionBox(4.0D, 2.0D, 4.0D, 12.0D, 14.0D, 12.0D)); // post
|
||||
}, StateTypes.LECTERN),
|
||||
@@ -411,7 +422,7 @@ public enum CollisionData {
|
||||
}
|
||||
|
||||
if (version.isOlderThanOrEquals(ClientVersion.V_1_13_2)) {
|
||||
ComplexCollisionBox complexAnvil = new ComplexCollisionBox();
|
||||
ComplexCollisionBox complexAnvil = new ComplexCollisionBox(4);
|
||||
// Base of the anvil
|
||||
complexAnvil.add(new HexCollisionBox(2, 0, 2, 14, 4, 14));
|
||||
|
||||
@@ -431,13 +442,15 @@ public enum CollisionData {
|
||||
Face attachment = data.getFace();
|
||||
if (attachment == Face.FLOOR) {
|
||||
if (facing == BlockFace.NORTH || facing == BlockFace.SOUTH) {
|
||||
return new ComplexCollisionBox(new HexCollisionBox(2.0D, 0.0D, 6.0D, 4.0D, 7.0D, 10.0D),
|
||||
return new ComplexCollisionBox(5,
|
||||
new HexCollisionBox(2.0D, 0.0D, 6.0D, 4.0D, 7.0D, 10.0D),
|
||||
new HexCollisionBox(12.0D, 0.0D, 6.0D, 14.0D, 7.0D, 10.0D),
|
||||
new HexCollisionBox(2.0D, 7.0D, 5.0D, 4.0D, 13.0D, 11.0D),
|
||||
new HexCollisionBox(12.0D, 7.0D, 5.0D, 14.0D, 13.0D, 11.0D),
|
||||
new HexCollisionBox(4.0D, 4.0D, 2.0D, 12.0D, 16.0D, 14.0D));
|
||||
} else {
|
||||
return new ComplexCollisionBox(new HexCollisionBox(6.0D, 0.0D, 2.0D, 10.0D, 7.0D, 4.0D),
|
||||
return new ComplexCollisionBox(5,
|
||||
new HexCollisionBox(6.0D, 0.0D, 2.0D, 10.0D, 7.0D, 4.0D),
|
||||
new HexCollisionBox(6.0D, 0.0D, 12.0D, 10.0D, 7.0D, 14.0D),
|
||||
new HexCollisionBox(5.0D, 7.0D, 2.0D, 11.0D, 13.0D, 4.0D),
|
||||
new HexCollisionBox(5.0D, 7.0D, 12.0D, 11.0D, 13.0D, 14.0D),
|
||||
@@ -446,25 +459,29 @@ public enum CollisionData {
|
||||
} else if (attachment == Face.WALL) {
|
||||
switch (facing) {
|
||||
case NORTH:
|
||||
return new ComplexCollisionBox(new HexCollisionBox(2.0D, 6.0D, 7.0D, 4.0D, 10.0D, 16.0D),
|
||||
return new ComplexCollisionBox(5,
|
||||
new HexCollisionBox(2.0D, 6.0D, 7.0D, 4.0D, 10.0D, 16.0D),
|
||||
new HexCollisionBox(12.0D, 6.0D, 7.0D, 14.0D, 10.0D, 16.0D),
|
||||
new HexCollisionBox(2.0D, 5.0D, 3.0D, 4.0D, 11.0D, 9.0D),
|
||||
new HexCollisionBox(12.0D, 5.0D, 3.0D, 14.0D, 11.0D, 9.0D),
|
||||
new HexCollisionBox(4.0D, 2.0D, 0.0D, 12.0D, 14.0D, 12.0D));
|
||||
case WEST:
|
||||
return new ComplexCollisionBox(new HexCollisionBox(7.0D, 6.0D, 2.0D, 16.0D, 10.0D, 4.0D),
|
||||
return new ComplexCollisionBox(5,
|
||||
new HexCollisionBox(7.0D, 6.0D, 2.0D, 16.0D, 10.0D, 4.0D),
|
||||
new HexCollisionBox(7.0D, 6.0D, 12.0D, 16.0D, 10.0D, 14.0D),
|
||||
new HexCollisionBox(3.0D, 5.0D, 2.0D, 9.0D, 11.0D, 4.0D),
|
||||
new HexCollisionBox(3.0D, 5.0D, 12.0D, 9.0D, 11.0D, 14.0D),
|
||||
new HexCollisionBox(0.0D, 2.0D, 4.0D, 12.0D, 14.0D, 12.0D));
|
||||
case SOUTH:
|
||||
return new ComplexCollisionBox(new HexCollisionBox(2.0D, 6.0D, 0.0D, 4.0D, 10.0D, 7.0D),
|
||||
return new ComplexCollisionBox(5,
|
||||
new HexCollisionBox(2.0D, 6.0D, 0.0D, 4.0D, 10.0D, 7.0D),
|
||||
new HexCollisionBox(12.0D, 6.0D, 0.0D, 14.0D, 10.0D, 7.0D),
|
||||
new HexCollisionBox(2.0D, 5.0D, 7.0D, 4.0D, 11.0D, 13.0D),
|
||||
new HexCollisionBox(12.0D, 5.0D, 7.0D, 14.0D, 11.0D, 13.0D),
|
||||
new HexCollisionBox(4.0D, 2.0D, 4.0D, 12.0D, 14.0D, 16.0D));
|
||||
case EAST:
|
||||
return new ComplexCollisionBox(new HexCollisionBox(0.0D, 6.0D, 2.0D, 9.0D, 10.0D, 4.0D),
|
||||
return new ComplexCollisionBox(5,
|
||||
new HexCollisionBox(0.0D, 6.0D, 2.0D, 9.0D, 10.0D, 4.0D),
|
||||
new HexCollisionBox(0.0D, 6.0D, 12.0D, 9.0D, 10.0D, 14.0D),
|
||||
new HexCollisionBox(7.0D, 5.0D, 2.0D, 13.0D, 11.0D, 4.0D),
|
||||
new HexCollisionBox(7.0D, 5.0D, 12.0D, 13.0D, 11.0D, 14.0D),
|
||||
@@ -472,13 +489,15 @@ public enum CollisionData {
|
||||
}
|
||||
} else {
|
||||
if (facing == BlockFace.NORTH || facing == BlockFace.SOUTH) {
|
||||
return new ComplexCollisionBox(new HexCollisionBox(2.0D, 9.0D, 6.0D, 4.0D, 16.0D, 10.0D),
|
||||
return new ComplexCollisionBox(5,
|
||||
new HexCollisionBox(2.0D, 9.0D, 6.0D, 4.0D, 16.0D, 10.0D),
|
||||
new HexCollisionBox(12.0D, 9.0D, 6.0D, 14.0D, 16.0D, 10.0D),
|
||||
new HexCollisionBox(2.0D, 3.0D, 5.0D, 4.0D, 9.0D, 11.0D),
|
||||
new HexCollisionBox(12.0D, 3.0D, 5.0D, 14.0D, 9.0D, 11.0D),
|
||||
new HexCollisionBox(4.0D, 0.0D, 2.0D, 12.0D, 12.0D, 14.0D));
|
||||
} else {
|
||||
return new ComplexCollisionBox(new HexCollisionBox(6.0D, 9.0D, 2.0D, 10.0D, 16.0D, 4.0D),
|
||||
return new ComplexCollisionBox(5,
|
||||
new HexCollisionBox(6.0D, 9.0D, 2.0D, 10.0D, 16.0D, 4.0D),
|
||||
new HexCollisionBox(6.0D, 9.0D, 12.0D, 10.0D, 16.0D, 14.0D),
|
||||
new HexCollisionBox(5.0D, 3.0D, 2.0D, 11.0D, 9.0D, 4.0D),
|
||||
new HexCollisionBox(5.0D, 3.0D, 12.0D, 11.0D, 9.0D, 14.0D),
|
||||
@@ -551,7 +570,7 @@ public enum CollisionData {
|
||||
StateTypes.ENCHANTING_TABLE),
|
||||
|
||||
FRAME((player, version, data, x, y, z) -> {
|
||||
ComplexCollisionBox complexCollisionBox = new ComplexCollisionBox(new HexCollisionBox(0.0D, 0.0D, 0.0D, 16.0D, 13.0D, 16.0D));
|
||||
ComplexCollisionBox complexCollisionBox = new ComplexCollisionBox(2, new HexCollisionBox(0.0D, 0.0D, 0.0D, 16.0D, 13.0D, 16.0D));
|
||||
|
||||
if (data.isEye()) {
|
||||
if (version.isNewerThanOrEquals(ClientVersion.V_1_13)) { // 1.13 players have a 0.5x0.5 eye
|
||||
@@ -622,7 +641,7 @@ public enum CollisionData {
|
||||
if (version.isOlderThan(ClientVersion.V_1_14))
|
||||
return new SimpleCollisionBox(0.0F, 0.0F, 0.0F, 1.0F, 0.5625, 1.0F, false);
|
||||
|
||||
ComplexCollisionBox baseBox = new ComplexCollisionBox(new HexCollisionBox(0.0D, 3.0D, 0.0D, 16.0D, 9.0D, 16.0D));
|
||||
ComplexCollisionBox baseBox = new ComplexCollisionBox(3, new HexCollisionBox(0.0D, 3.0D, 0.0D, 16.0D, 9.0D, 16.0D));
|
||||
|
||||
switch (data.getFacing()) {
|
||||
case NORTH:
|
||||
@@ -661,8 +680,8 @@ public enum CollisionData {
|
||||
}, StateTypes.END_ROD, StateTypes.LIGHTNING_ROD),
|
||||
|
||||
CAULDRON((player, version, data, x, y, z) -> {
|
||||
if (version.isNewerThan(ClientVersion.getById(467))) { // changed in 19w13a, 1.14 Snapshot
|
||||
return new ComplexCollisionBox(
|
||||
if (version.isNewerThan(ClientVersion.V_1_13_2)) { // 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),
|
||||
new SimpleCollisionBox(0.125, 0.0, 0.0, 0.25, 1.0, 0.125, false),
|
||||
@@ -684,7 +703,7 @@ public enum CollisionData {
|
||||
if (version.isOlderThan(ClientVersion.V_1_13))
|
||||
height = 0.3125;
|
||||
|
||||
return new ComplexCollisionBox(
|
||||
return new ComplexCollisionBox(5,
|
||||
new SimpleCollisionBox(0, 0, 0, 1, height, 1, false),
|
||||
new SimpleCollisionBox(0, height, 0, 0.125, 1, 1, false),
|
||||
new SimpleCollisionBox(1 - 0.125, height, 0, 1, 1, 1, false),
|
||||
@@ -834,10 +853,14 @@ public enum CollisionData {
|
||||
}, BlockTags.CANDLES.getStates().toArray(new StateType[0])),
|
||||
|
||||
CANDLE_CAKE((player, version, data, x, y, z) -> {
|
||||
ComplexCollisionBox cake = new ComplexCollisionBox(new HexCollisionBox(1.0, 0.0, 1.0, 15.0, 8.0, 15.0));
|
||||
if (version.isNewerThanOrEquals(ClientVersion.V_1_17))
|
||||
cake.add(new HexCollisionBox(7.0, 8.0, 7.0, 9.0, 14.0, 9.0));
|
||||
return cake;
|
||||
SimpleCollisionBox cake = new HexCollisionBox(1.0, 0.0, 1.0, 15.0, 8.0, 15.0);
|
||||
if (version.isOlderThan(ClientVersion.V_1_17)) {
|
||||
return cake;
|
||||
} else {
|
||||
return new ComplexCollisionBox(2,
|
||||
cake,
|
||||
new HexCollisionBox(7.0, 8.0, 7.0, 9.0, 14.0, 9.0));
|
||||
}
|
||||
}, BlockTags.CANDLE_CAKES.getStates().toArray(new StateType[0])),
|
||||
|
||||
SCULK_SENSOR(new HexCollisionBox(0.0, 0.0, 0.0, 16.0, 8.0, 16.0), StateTypes.SCULK_SENSOR, StateTypes.CALIBRATED_SCULK_SENSOR),
|
||||
@@ -914,7 +937,8 @@ public enum CollisionData {
|
||||
}, StateTypes.NETHER_PORTAL),
|
||||
|
||||
AZALEA((player, version, data, x, y, z) -> {
|
||||
return new ComplexCollisionBox(new HexCollisionBox(0.0, 8.0, 0.0, 16.0, 16.0, 16.0),
|
||||
return new ComplexCollisionBox(2,
|
||||
new HexCollisionBox(0.0, 8.0, 0.0, 16.0, 16.0, 16.0),
|
||||
new HexCollisionBox(6.0, 0.0, 6.0, 10.0, 8.0, 10.0));
|
||||
}, StateTypes.AZALEA, StateTypes.FLOWERING_AZALEA),
|
||||
|
||||
|
||||
@@ -216,9 +216,11 @@ public enum HitboxData {
|
||||
|
||||
WALL_HANGING_SIGN((player, item, version, data, x, y, z) -> {
|
||||
return switch (data.getFacing()) {
|
||||
case NORTH, SOUTH -> new ComplexCollisionBox(new HexCollisionBox(0.0D, 14.0D, 6.0D, 16.0D, 16.0D, 10.0D),
|
||||
case NORTH, SOUTH -> new ComplexCollisionBox(2,
|
||||
new HexCollisionBox(0.0D, 14.0D, 6.0D, 16.0D, 16.0D, 10.0D),
|
||||
new HexCollisionBox(1.0D, 0.0D, 7.0D, 15.0D, 10.0D, 9.0D));
|
||||
default -> new ComplexCollisionBox(new HexCollisionBox(6.0D, 14.0D, 0.0D, 10.0D, 16.0D, 16.0D),
|
||||
default -> new ComplexCollisionBox(2,
|
||||
new HexCollisionBox(6.0D, 14.0D, 0.0D, 10.0D, 16.0D, 16.0D),
|
||||
new HexCollisionBox(7.0D, 0.0D, 1.0D, 9.0D, 10.0D, 15.0D));
|
||||
};
|
||||
}, BlockTags.WALL_HANGING_SIGNS.getStates().toArray(new StateType[0])),
|
||||
@@ -263,7 +265,7 @@ public enum HitboxData {
|
||||
if (version.isOlderThan(ClientVersion.V_1_13)) {
|
||||
return new SimpleCollisionBox(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F);
|
||||
} else {
|
||||
return new ComplexCollisionBox(
|
||||
return new ComplexCollisionBox(2,
|
||||
new HexCollisionBox(1.0, 0.0, 1.0, 15.0, 2.0, 15.0),
|
||||
new SimpleCollisionBox(0.4375, 0.0, 0.4375, 0.5625, 0.875, 0.5625, false));
|
||||
}
|
||||
@@ -303,7 +305,8 @@ public enum HitboxData {
|
||||
}, StateTypes.SNOW),
|
||||
|
||||
LECTERN_BLOCK((player, item, version, data, x, y, z) -> {
|
||||
ComplexCollisionBox common = new ComplexCollisionBox(new HexCollisionBox(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D),
|
||||
ComplexCollisionBox common = new ComplexCollisionBox(5,
|
||||
new HexCollisionBox(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D),
|
||||
new HexCollisionBox(4.0D, 2.0D, 4.0D, 12.0D, 14.0D, 12.0D));
|
||||
|
||||
if (data.getFacing() == BlockFace.WEST) {
|
||||
@@ -329,7 +332,7 @@ public enum HitboxData {
|
||||
|
||||
GLOW_LICHEN_SCULK_VEIN((player, item, version, data, x, y, z) -> {
|
||||
if (version.isNewerThan(ClientVersion.V_1_16_4)) {
|
||||
ComplexCollisionBox box = new ComplexCollisionBox();
|
||||
ComplexCollisionBox box = new ComplexCollisionBox(6);
|
||||
|
||||
if (data.isUp()) {
|
||||
box.add(new HexCollisionBox(0.0D, 15.0D, 0.0D, 16.0D, 16.0D, 16.0D));
|
||||
@@ -491,7 +494,7 @@ public enum HitboxData {
|
||||
}
|
||||
|
||||
// STABLE_SHAPE for the scaffolding
|
||||
ComplexCollisionBox box = new ComplexCollisionBox(
|
||||
ComplexCollisionBox box = new ComplexCollisionBox(9,
|
||||
new HexCollisionBox(0.0D, 14.0D, 0.0D, 16.0D, 16.0D, 16.0D),
|
||||
new HexCollisionBox(0.0D, 0.0D, 0.0D, 2.0D, 16.0D, 2.0D),
|
||||
new HexCollisionBox(14.0D, 0.0D, 0.0D, 16.0D, 16.0D, 2.0D),
|
||||
@@ -512,7 +515,7 @@ public enum HitboxData {
|
||||
if (version.isOlderThanOrEquals(ClientVersion.V_1_16_4))
|
||||
return new SimpleCollisionBox(0, 0, 0, 1, 1, 1, true);
|
||||
|
||||
ComplexCollisionBox box = new ComplexCollisionBox();
|
||||
ComplexCollisionBox box = new ComplexCollisionBox(2);
|
||||
|
||||
if (data.getFacing() == BlockFace.NORTH) { // Stem
|
||||
box.add(new HexCollisionBox(5.0D, 0.0D, 9.0D, 11.0D, 15.0D, 15.0D));
|
||||
@@ -653,7 +656,7 @@ public enum HitboxData {
|
||||
}
|
||||
} else {
|
||||
// Via replacement - 4 sided vine
|
||||
return new ComplexCollisionBox(
|
||||
return new ComplexCollisionBox(4,
|
||||
new HexCollisionBox(0.0D, 0.0D, 0.0D, 1.0D, 16.0D, 16.0D),
|
||||
new HexCollisionBox(15.0D, 0.0D, 0.0D, 16.0D, 16.0D, 16.0D),
|
||||
new HexCollisionBox(0.0D, 0.0D, 0.0D, 16.0D, 16.0D, 1.0D),
|
||||
|
||||
@@ -31,7 +31,7 @@ public class DynamicChorusPlant implements CollisionFactory {
|
||||
float f = 0.5F - (float) 0.3125;
|
||||
float f1 = 0.5F + (float) 0.3125;
|
||||
SimpleCollisionBox baseShape = new SimpleCollisionBox(f, f, f, f1, f1, f1, false);
|
||||
CollisionBox[] avoxelshape = new CollisionBox[directions.length];
|
||||
SimpleCollisionBox[] avoxelshape = new SimpleCollisionBox[directions.length];
|
||||
|
||||
for (int i = 0; i < directions.length; ++i) {
|
||||
BlockFace direction = directions[i];
|
||||
@@ -41,7 +41,7 @@ public class DynamicChorusPlant implements CollisionFactory {
|
||||
CollisionBox[] avoxelshape1 = new CollisionBox[64];
|
||||
|
||||
for (int k = 0; k < 64; ++k) {
|
||||
ComplexCollisionBox directionalShape = new ComplexCollisionBox(baseShape);
|
||||
ComplexCollisionBox directionalShape = new ComplexCollisionBox(7, baseShape); // how big is this one??
|
||||
|
||||
for (int j = 0; j < directions.length; ++j) {
|
||||
if ((k & 1 << j) != 0) {
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package ac.grim.grimac.utils.collisions.blocks;
|
||||
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.CollisionBox;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.CollisionFactory;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.ComplexCollisionBox;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.HexCollisionBox;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.*;
|
||||
import ac.grim.grimac.utils.nmsutil.Materials;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
@@ -18,16 +15,16 @@ import com.github.retrooper.packetevents.protocol.world.states.enums.Shape;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class DynamicStair implements CollisionFactory {
|
||||
protected static final CollisionBox TOP_AABB = new HexCollisionBox(0, 8, 0, 16, 16, 16);
|
||||
protected static final CollisionBox BOTTOM_AABB = new HexCollisionBox(0, 0, 0, 16, 8, 16);
|
||||
protected static final CollisionBox OCTET_NNN = new HexCollisionBox(0.0D, 0.0D, 0.0D, 8.0D, 8.0D, 8.0D);
|
||||
protected static final CollisionBox OCTET_NNP = new HexCollisionBox(0.0D, 0.0D, 8.0D, 8.0D, 8.0D, 16.0D);
|
||||
protected static final CollisionBox OCTET_NPN = new HexCollisionBox(0.0D, 8.0D, 0.0D, 8.0D, 16.0D, 8.0D);
|
||||
protected static final CollisionBox OCTET_NPP = new HexCollisionBox(0.0D, 8.0D, 8.0D, 8.0D, 16.0D, 16.0D);
|
||||
protected static final CollisionBox OCTET_PNN = new HexCollisionBox(8.0D, 0.0D, 0.0D, 16.0D, 8.0D, 8.0D);
|
||||
protected static final CollisionBox OCTET_PNP = new HexCollisionBox(8.0D, 0.0D, 8.0D, 16.0D, 8.0D, 16.0D);
|
||||
protected static final CollisionBox OCTET_PPN = new HexCollisionBox(8.0D, 8.0D, 0.0D, 16.0D, 16.0D, 8.0D);
|
||||
protected static final CollisionBox OCTET_PPP = new HexCollisionBox(8.0D, 8.0D, 8.0D, 16.0D, 16.0D, 16.0D);
|
||||
protected static final SimpleCollisionBox TOP_AABB = new HexCollisionBox(0, 8, 0, 16, 16, 16);
|
||||
protected static final SimpleCollisionBox BOTTOM_AABB = new HexCollisionBox(0, 0, 0, 16, 8, 16);
|
||||
protected static final SimpleCollisionBox OCTET_NNN = new HexCollisionBox(0.0D, 0.0D, 0.0D, 8.0D, 8.0D, 8.0D);
|
||||
protected static final SimpleCollisionBox OCTET_NNP = new HexCollisionBox(0.0D, 0.0D, 8.0D, 8.0D, 8.0D, 16.0D);
|
||||
protected static final SimpleCollisionBox OCTET_NPN = new HexCollisionBox(0.0D, 8.0D, 0.0D, 8.0D, 16.0D, 8.0D);
|
||||
protected static final SimpleCollisionBox OCTET_NPP = new HexCollisionBox(0.0D, 8.0D, 8.0D, 8.0D, 16.0D, 16.0D);
|
||||
protected static final SimpleCollisionBox OCTET_PNN = new HexCollisionBox(8.0D, 0.0D, 0.0D, 16.0D, 8.0D, 8.0D);
|
||||
protected static final SimpleCollisionBox OCTET_PNP = new HexCollisionBox(8.0D, 0.0D, 8.0D, 16.0D, 8.0D, 16.0D);
|
||||
protected static final SimpleCollisionBox OCTET_PPN = new HexCollisionBox(8.0D, 8.0D, 0.0D, 16.0D, 16.0D, 8.0D);
|
||||
protected static final SimpleCollisionBox OCTET_PPP = new HexCollisionBox(8.0D, 8.0D, 8.0D, 16.0D, 16.0D, 16.0D);
|
||||
protected static final CollisionBox[] TOP_SHAPES = makeShapes(TOP_AABB, OCTET_NNN, OCTET_PNN, OCTET_NNP, OCTET_PNP);
|
||||
protected static final CollisionBox[] BOTTOM_SHAPES = makeShapes(BOTTOM_AABB, OCTET_NPN, OCTET_PPN, OCTET_NPP, OCTET_PPP);
|
||||
private static final int[] SHAPE_BY_STATE = new int[]{12, 5, 3, 10, 14, 13, 7, 11, 13, 7, 11, 14, 8, 4, 1, 2, 4, 1, 2, 8};
|
||||
@@ -85,12 +82,12 @@ public class DynamicStair implements CollisionFactory {
|
||||
};
|
||||
}
|
||||
|
||||
private static CollisionBox[] makeShapes(CollisionBox p_199779_0_, CollisionBox p_199779_1_, CollisionBox p_199779_2_, CollisionBox p_199779_3_, CollisionBox p_199779_4_) {
|
||||
private static CollisionBox[] makeShapes(SimpleCollisionBox p_199779_0_, SimpleCollisionBox p_199779_1_, SimpleCollisionBox p_199779_2_, SimpleCollisionBox p_199779_3_, SimpleCollisionBox p_199779_4_) {
|
||||
return IntStream.range(0, 16).mapToObj((p_199780_5_) -> makeStairShape(p_199780_5_, p_199779_0_, p_199779_1_, p_199779_2_, p_199779_3_, p_199779_4_)).toArray(CollisionBox[]::new);
|
||||
}
|
||||
|
||||
private static CollisionBox makeStairShape(int p_199781_0_, CollisionBox p_199781_1_, CollisionBox p_199781_2_, CollisionBox p_199781_3_, CollisionBox p_199781_4_, CollisionBox p_199781_5_) {
|
||||
ComplexCollisionBox voxelshape = new ComplexCollisionBox(p_199781_1_);
|
||||
private static CollisionBox makeStairShape(int p_199781_0_, SimpleCollisionBox p_199781_1_, SimpleCollisionBox p_199781_2_, SimpleCollisionBox p_199781_3_, SimpleCollisionBox p_199781_4_, SimpleCollisionBox p_199781_5_) {
|
||||
ComplexCollisionBox voxelshape = new ComplexCollisionBox(5, p_199781_1_); // can we do better than 5?
|
||||
if ((p_199781_0_ & 1) != 0) {
|
||||
voxelshape.add(p_199781_2_);
|
||||
}
|
||||
|
||||
@@ -39,33 +39,41 @@ public class PistonHeadCollision implements CollisionFactory {
|
||||
|
||||
|
||||
return switch (block.getFacing()) {
|
||||
case UP -> new ComplexCollisionBox(new HexCollisionBox(0, 12, 0, 16, 16, 16),
|
||||
case UP -> new ComplexCollisionBox(2,
|
||||
new HexCollisionBox(0, 12, 0, 16, 16, 16),
|
||||
new HexCollisionBox(6, 0 - longAmount, 6, 10, 12, 10));
|
||||
case NORTH -> new ComplexCollisionBox(new HexCollisionBox(0, 0, 0, 16, 16, 4),
|
||||
case NORTH -> new ComplexCollisionBox(2,
|
||||
new HexCollisionBox(0, 0, 0, 16, 16, 4),
|
||||
new HexCollisionBox(6, 6, 4, 10, 10, 16 + longAmount));
|
||||
case SOUTH -> {
|
||||
// SOUTH piston is glitched in 1.7 and 1.8, fixed in 1.9
|
||||
// Don't bother with short piston boxes as 1.7/1.8 clients don't have them
|
||||
if (version.isOlderThanOrEquals(ClientVersion.V_1_8))
|
||||
yield new ComplexCollisionBox(new HexCollisionBox(0, 0, 12, 16, 16, 16),
|
||||
yield new ComplexCollisionBox(2,
|
||||
new HexCollisionBox(0, 0, 12, 16, 16, 16),
|
||||
new HexCollisionBox(4, 6, 0, 12, 10, 12));
|
||||
|
||||
yield new ComplexCollisionBox(new HexCollisionBox(0, 0, 12, 16, 16, 16),
|
||||
yield new ComplexCollisionBox(2,
|
||||
new HexCollisionBox(0, 0, 12, 16, 16, 16),
|
||||
new HexCollisionBox(6, 6, 0 - longAmount, 10, 10, 12));
|
||||
}
|
||||
case WEST -> {
|
||||
// WEST piston is glitched in 1.7 and 1.8, fixed in 1.9
|
||||
// Don't bother with short piston boxes as 1.7/1.8 clients don't have them
|
||||
if (version.isOlderThanOrEquals(ClientVersion.V_1_8))
|
||||
yield new ComplexCollisionBox(new HexCollisionBox(0, 0, 0, 4, 16, 16),
|
||||
yield new ComplexCollisionBox(2,
|
||||
new HexCollisionBox(0, 0, 0, 4, 16, 16),
|
||||
new HexCollisionBox(6, 4, 4, 10, 12, 16));
|
||||
|
||||
yield new ComplexCollisionBox(new HexCollisionBox(0, 0, 0, 4, 16, 16),
|
||||
yield new ComplexCollisionBox(2,
|
||||
new HexCollisionBox(0, 0, 0, 4, 16, 16),
|
||||
new HexCollisionBox(4, 6, 6, 16 + longAmount, 10, 10));
|
||||
}
|
||||
case EAST -> new ComplexCollisionBox(new HexCollisionBox(12, 0, 0, 16, 16, 16),
|
||||
case EAST -> new ComplexCollisionBox(2,
|
||||
new HexCollisionBox(12, 0, 0, 16, 16, 16),
|
||||
new HexCollisionBox(0 - longAmount, 6, 4, 12, 10, 12));
|
||||
default -> new ComplexCollisionBox(new HexCollisionBox(0, 0, 0, 16, 4, 16),
|
||||
default -> new ComplexCollisionBox(2,
|
||||
new HexCollisionBox(0, 0, 0, 16, 4, 16),
|
||||
new HexCollisionBox(6, 4, 6, 10, 16 + longAmount, 10));
|
||||
};
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
|
||||
public class DynamicCollisionFence extends DynamicConnecting implements CollisionFactory {
|
||||
private static final CollisionBox[] COLLISION_BOXES = makeShapes(2.0F, 2.0F, 24.0F, 0.0F, 24.0F, true);
|
||||
private static final CollisionBox[] COLLISION_BOXES = makeShapes(2.0F, 2.0F, 24.0F, 0.0F, 24.0F, true, 1);
|
||||
|
||||
@Override
|
||||
public CollisionBox fetch(GrimPlayer player, ClientVersion version, WrappedBlockState block, int x, int y, int z) {
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
|
||||
public class DynamicCollisionPane extends DynamicConnecting implements CollisionFactory {
|
||||
|
||||
private static final CollisionBox[] COLLISION_BOXES = makeShapes(1.0F, 1.0F, 16.0F, 0.0F, 16.0F, true);
|
||||
private static final CollisionBox[] COLLISION_BOXES = makeShapes(1.0F, 1.0F, 16.0F, 0.0F, 16.0F, true, 1);
|
||||
|
||||
@Override
|
||||
public CollisionBox fetch(GrimPlayer player, ClientVersion version, WrappedBlockState block, int x, int y, int z) {
|
||||
@@ -52,7 +52,7 @@ public class DynamicCollisionPane extends DynamicConnecting implements Collision
|
||||
if (version.isNewerThanOrEquals(ClientVersion.V_1_9)) {
|
||||
return COLLISION_BOXES[getAABBIndex(north, east, south, west)].copy();
|
||||
} else { // 1.8 and below clients have pane bounding boxes one pixel less
|
||||
ComplexCollisionBox boxes = new ComplexCollisionBox();
|
||||
ComplexCollisionBox boxes = new ComplexCollisionBox(2);
|
||||
if ((!west || !east) && (west || east || north || south)) {
|
||||
if (west) {
|
||||
boxes.add(new SimpleCollisionBox(0.0F, 0.0F, 0.4375F, 0.5F, 1.0F, 0.5625F));
|
||||
|
||||
+4
-7
@@ -16,10 +16,9 @@ import com.github.retrooper.packetevents.protocol.world.states.enums.West;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
|
||||
public class DynamicCollisionWall extends DynamicConnecting implements CollisionFactory {
|
||||
public static final CollisionBox[] BOXES = makeShapes(4.0F, 3.0F, 16.0F, 0.0F, 16.0F, false);
|
||||
// https://bugs.mojang.com/browse/MC-9565
|
||||
// https://bugs.mojang.com/browse/MC-94016
|
||||
private static final CollisionBox[] COLLISION_BOXES = makeShapes(4.0F, 3.0F, 24.0F, 0.0F, 24.0F, false);
|
||||
private static final CollisionBox[] COLLISION_BOXES = makeShapes(4.0F, 3.0F, 24.0F, 0.0F, 24.0F, false, 1);
|
||||
|
||||
/**
|
||||
* @deprecated use DynamicHitboxWall
|
||||
@@ -53,12 +52,11 @@ public class DynamicCollisionWall extends DynamicConnecting implements Collision
|
||||
|
||||
// On 1.13+ clients the bounding box is much more complicated
|
||||
if (version.isNewerThanOrEquals(ClientVersion.V_1_13)) {
|
||||
ComplexCollisionBox box = new ComplexCollisionBox();
|
||||
ComplexCollisionBox box = new ComplexCollisionBox(5);
|
||||
|
||||
// Proper and faster way would be to compute all this beforehand
|
||||
if (up == 1) {
|
||||
box.add(new HexCollisionBox(4, 0, 4, 12, 16, 12));
|
||||
return box;
|
||||
}
|
||||
|
||||
if (north == 1) {
|
||||
@@ -81,6 +79,7 @@ public class DynamicCollisionWall extends DynamicConnecting implements Collision
|
||||
} else if (east == 2) {
|
||||
box.add(new HexCollisionBox(5, 0, 5, 16, 16, 11));
|
||||
}
|
||||
return box;
|
||||
}
|
||||
|
||||
// Magic 1.8 code for walls that I copied over, 1.12 below uses this mess
|
||||
@@ -143,9 +142,7 @@ public class DynamicCollisionWall extends DynamicConnecting implements Collision
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_13)) {
|
||||
// Proper and faster way would be to compute all this beforehand
|
||||
if (up) {
|
||||
ComplexCollisionBox box = new ComplexCollisionBox(COLLISION_BOXES[getAABBIndex(north, east, south, west)].copy());
|
||||
box.add(new HexCollisionBox(4, 0, 4, 12, 24, 12));
|
||||
return box;
|
||||
return COLLISION_BOXES[getAABBIndex(north, east, south, west)].copy().union(new HexCollisionBox(4, 0, 4, 12, 24, 12));
|
||||
}
|
||||
|
||||
return COLLISION_BOXES[getAABBIndex(north, east, south, west)].copy();
|
||||
|
||||
+12
-5
@@ -18,7 +18,7 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
|
||||
public class DynamicConnecting {
|
||||
|
||||
public static CollisionBox[] makeShapes(float p_196408_1_, float p_196408_2_, float p_196408_3_, float p_196408_4_, float p_196408_5_, boolean includeCenter) {
|
||||
public static CollisionBox[] makeShapes(float p_196408_1_, float p_196408_2_, float p_196408_3_, float p_196408_4_, float p_196408_5_, boolean includeCenter, int additionalMaxIndex) {
|
||||
float middleMin = 8.0F - p_196408_1_;
|
||||
float middleMax = 8.0F + p_196408_1_;
|
||||
float f2 = 8.0F - p_196408_2_;
|
||||
@@ -29,14 +29,21 @@ public class DynamicConnecting {
|
||||
SimpleCollisionBox voxelshape3 = new HexCollisionBox(0.0D, p_196408_4_, f2, f3, p_196408_5_, f3);
|
||||
SimpleCollisionBox voxelshape4 = new HexCollisionBox(f2, p_196408_4_, f2, 16.0D, p_196408_5_, f3);
|
||||
|
||||
ComplexCollisionBox voxelshape5 = new ComplexCollisionBox(voxelshape1, voxelshape4);
|
||||
ComplexCollisionBox voxelshape6 = new ComplexCollisionBox(voxelshape2, voxelshape3);
|
||||
ComplexCollisionBox voxelshape5 = new ComplexCollisionBox(2 + additionalMaxIndex, voxelshape1, voxelshape4);
|
||||
ComplexCollisionBox voxelshape6 = new ComplexCollisionBox(2 + additionalMaxIndex, voxelshape2, voxelshape3);
|
||||
|
||||
CollisionBox[] avoxelshape = new CollisionBox[]{NoCollisionBox.INSTANCE, voxelshape2, voxelshape3, voxelshape6, voxelshape1, new ComplexCollisionBox(voxelshape2, voxelshape1), new ComplexCollisionBox(voxelshape3, voxelshape1), new ComplexCollisionBox(voxelshape6, voxelshape1), voxelshape4, new ComplexCollisionBox(voxelshape2, voxelshape4), new ComplexCollisionBox(voxelshape3, voxelshape4), new ComplexCollisionBox(voxelshape6, voxelshape4), voxelshape5, new ComplexCollisionBox(voxelshape2, voxelshape5), new ComplexCollisionBox(voxelshape3, voxelshape5), new ComplexCollisionBox(voxelshape6, voxelshape5)};
|
||||
CollisionBox[] avoxelshape = new CollisionBox[]{
|
||||
NoCollisionBox.INSTANCE, voxelshape2, voxelshape3, voxelshape6, voxelshape1,
|
||||
new ComplexCollisionBox(2 + additionalMaxIndex, voxelshape2, voxelshape1), new ComplexCollisionBox(2 + additionalMaxIndex, voxelshape3, voxelshape1),
|
||||
new ComplexCollisionBox(3 + additionalMaxIndex, voxelshape2, voxelshape3, voxelshape1), voxelshape4,
|
||||
new ComplexCollisionBox(2 + additionalMaxIndex, voxelshape2, voxelshape4), new ComplexCollisionBox(2 + additionalMaxIndex, voxelshape3, voxelshape4),
|
||||
new ComplexCollisionBox(3 + additionalMaxIndex, voxelshape2, voxelshape3, voxelshape4), voxelshape5,
|
||||
new ComplexCollisionBox(3 + additionalMaxIndex, voxelshape2, voxelshape1, voxelshape4), new ComplexCollisionBox(3 + additionalMaxIndex, voxelshape3, voxelshape1, voxelshape4),
|
||||
new ComplexCollisionBox(4 + additionalMaxIndex, voxelshape1, voxelshape2, voxelshape3, voxelshape4)};
|
||||
|
||||
if (includeCenter) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
avoxelshape[i] = new ComplexCollisionBox(up, avoxelshape[i]);
|
||||
avoxelshape[i] = avoxelshape[i].union(up);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-13
@@ -16,27 +16,29 @@ import com.github.retrooper.packetevents.protocol.world.states.enums.*;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DynamicHitboxFence extends DynamicConnecting implements HitBoxFactory {
|
||||
private static final CollisionBox[] MODERN_HITBOXES = makeShapes(2.0F, 2.0F, 24.0F, 0.0F, 24.0F, true);
|
||||
private static final CollisionBox[] MODERN_HITBOXES = makeShapes(2.0F, 2.0F, 24.0F, 0.0F, 24.0F, true, 1);
|
||||
|
||||
public static SimpleCollisionBox[] LEGACY_HITBOXES = new SimpleCollisionBox[] {new SimpleCollisionBox(0.375D, 0.0D, 0.375D, 0.625D, 1.0D, 0.625D), new SimpleCollisionBox(0.375D, 0.0D, 0.375D, 0.625D, 1.0D, 1.0D), new SimpleCollisionBox(0.0D, 0.0D, 0.375D, 0.625D, 1.0D, 0.625D), new SimpleCollisionBox(0.0D, 0.0D, 0.375D, 0.625D, 1.0D, 1.0D), new SimpleCollisionBox(0.375D, 0.0D, 0.0D, 0.625D, 1.0D, 0.625D), new SimpleCollisionBox(0.375D, 0.0D, 0.0D, 0.625D, 1.0D, 1.0D), new SimpleCollisionBox(0.0D, 0.0D, 0.0D, 0.625D, 1.0D, 0.625D), new SimpleCollisionBox(0.0D, 0.0D, 0.0D, 0.625D, 1.0D, 1.0D), new SimpleCollisionBox(0.375D, 0.0D, 0.375D, 1.0D, 1.0D, 0.625D), new SimpleCollisionBox(0.375D, 0.0D, 0.375D, 1.0D, 1.0D, 1.0D), new SimpleCollisionBox(0.0D, 0.0D, 0.375D, 1.0D, 1.0D, 0.625D), new SimpleCollisionBox(0.0D, 0.0D, 0.375D, 1.0D, 1.0D, 1.0D), new SimpleCollisionBox(0.375D, 0.0D, 0.0D, 1.0D, 1.0D, 0.625D), new SimpleCollisionBox(0.375D, 0.0D, 0.0D, 1.0D, 1.0D, 1.0D), new SimpleCollisionBox(0.0D, 0.0D, 0.0D, 1.0D, 1.0D, 0.625D), new SimpleCollisionBox(0.0D, 0.0D, 0.0D, 1.0D, 1.0D, 1.0D)};
|
||||
|
||||
static {
|
||||
for (int i = 0; i < MODERN_HITBOXES.length; i++) {
|
||||
CollisionBox collisionBox = MODERN_HITBOXES[i];
|
||||
List<SimpleCollisionBox> boxes = new ArrayList<>();
|
||||
collisionBox.downCast(boxes);
|
||||
// no ComplexCollisionBox produced by makeShapes is every larger than 5 SimpleCollisionBoxes
|
||||
private static final int MAX_MODERN_HITBOX_COMPLEX_COLLISION_BOX_SIZE = 5;
|
||||
|
||||
for (SimpleCollisionBox box : boxes) {
|
||||
if (box.maxY > 1) {
|
||||
box.maxY = 1;
|
||||
static {
|
||||
SimpleCollisionBox[] boxes = new SimpleCollisionBox[MAX_MODERN_HITBOX_COMPLEX_COLLISION_BOX_SIZE];
|
||||
|
||||
// we start from one because MODERN_HITBOXES[0] is a NoCollisionBox
|
||||
for (int i = 1; i < MODERN_HITBOXES.length; i++) {
|
||||
CollisionBox collisionBox = MODERN_HITBOXES[i];
|
||||
int size = collisionBox.downCast(boxes);
|
||||
|
||||
for (int j = 0; j < size; j++) {
|
||||
if (boxes[j].maxY > 1) {
|
||||
boxes[j].maxY = 1;
|
||||
}
|
||||
}
|
||||
|
||||
MODERN_HITBOXES[i] = new ComplexCollisionBox(boxes.toArray(new SimpleCollisionBox[0]));
|
||||
MODERN_HITBOXES[i] = size == 1 ? boxes[0] : new ComplexCollisionBox(size, boxes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
|
||||
public class DynamicHitboxPane extends DynamicConnecting implements HitBoxFactory {
|
||||
|
||||
private static final CollisionBox[] COLLISION_BOXES = makeShapes(1.0F, 1.0F, 16.0F, 0.0F, 16.0F, true);
|
||||
private static final CollisionBox[] COLLISION_BOXES = makeShapes(1.0F, 1.0F, 16.0F, 0.0F, 16.0F, true, 1);
|
||||
|
||||
@Override
|
||||
public CollisionBox fetch(GrimPlayer player, StateType item, ClientVersion version, WrappedBlockState block, int x, int y, int z) {
|
||||
|
||||
+1
-3
@@ -13,8 +13,6 @@ import com.github.retrooper.packetevents.protocol.world.states.enums.*;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
|
||||
public class DynamicHitboxWall extends DynamicConnecting implements HitBoxFactory {
|
||||
private static final CollisionBox[] HIT_BOXES = makeShapes(4.0F, 3.0F, 16.0F, 0.0F, 16.0F, false);
|
||||
|
||||
@Override
|
||||
public CollisionBox fetch(GrimPlayer player, StateType heldItem, ClientVersion version, WrappedBlockState state, int x, int y, int z) {
|
||||
int[] connections = getConnections(player, version, state, x, y, z);
|
||||
@@ -60,7 +58,7 @@ public class DynamicHitboxWall extends DynamicConnecting implements HitBoxFactor
|
||||
}
|
||||
|
||||
private CollisionBox getModernHitBox(int north, int south, int west, int east, int up) {
|
||||
ComplexCollisionBox box = new ComplexCollisionBox();
|
||||
ComplexCollisionBox box = new ComplexCollisionBox(5);
|
||||
if (up == 1) {
|
||||
box.add(new HexCollisionBox(4, 0, 4, 12, 16, 12));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package ac.grim.grimac.utils.collisions.datatypes;
|
||||
|
||||
import org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import static ac.grim.grimac.utils.vector.VectorFactory.newVector3D;
|
||||
|
||||
public class BoundingBox {
|
||||
|
||||
@@ -15,7 +18,7 @@ public class BoundingBox {
|
||||
this.maxZ = maxZ;
|
||||
}
|
||||
|
||||
public BoundingBox(Vector min, Vector max) {
|
||||
public BoundingBox(Vector3D min, Vector3D 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());
|
||||
@@ -44,7 +47,7 @@ public class BoundingBox {
|
||||
return new BoundingBox(newMinX, newMinY, newMinZ, newMaxX, newMaxY, newMaxZ);
|
||||
}
|
||||
|
||||
public BoundingBox add(Vector vector) {
|
||||
public BoundingBox add(Vector3D vector) {
|
||||
float x = (float) vector.getX(), y = (float) vector.getY(), z = (float) vector.getZ();
|
||||
|
||||
float newMinX = minX + x;
|
||||
@@ -87,27 +90,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(Vector vector) {
|
||||
public boolean intersectsWithBox(Vector3D 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 Vector getMinimum() {
|
||||
return new Vector(minX, minY, minZ);
|
||||
public Vector3D getMinimum() {
|
||||
return newVector3D(minX, minY, minZ);
|
||||
}
|
||||
|
||||
public Vector getMaximum() {
|
||||
return new Vector(maxX, maxY, maxZ);
|
||||
public Vector3D getMaximum() {
|
||||
return newVector3D(maxX, maxY, maxZ);
|
||||
}
|
||||
|
||||
public boolean collides(Vector vector) {
|
||||
public boolean collides(Vector3D 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(Vector vector) {
|
||||
public boolean collidesHorizontally(Vector3D 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(Vector vector) {
|
||||
public boolean collidesVertically(Vector3D 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));
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,13 @@ public interface CollisionBox {
|
||||
|
||||
void downCast(List<SimpleCollisionBox> list);
|
||||
|
||||
/**
|
||||
* @param list - A list that will contain all of the SimpleCollisionBoxes representing the CollisionBox.
|
||||
* @return - int representing the size of elements in the array that belong to this downcast.
|
||||
* The contents of elements starting from list[size] and above are undefined and should not be iterated over.
|
||||
*/
|
||||
int downCast(SimpleCollisionBox[] list);
|
||||
|
||||
boolean isNull();
|
||||
|
||||
boolean isFullBlock();
|
||||
|
||||
@@ -1,19 +1,33 @@
|
||||
package ac.grim.grimac.utils.collisions.datatypes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class ComplexCollisionBox implements CollisionBox {
|
||||
|
||||
private final List<CollisionBox> boxes = new ArrayList<>();
|
||||
// Most complex shape is the Modern MC Cauldron which is made up of 15 boxes
|
||||
public static int DEFAULT_MAX_COLLISION_BOX_SIZE = 15; // increase if we somehow have a shape made of more than 15 parts.
|
||||
private final SimpleCollisionBox[] boxes;
|
||||
private int currentLength;
|
||||
|
||||
public ComplexCollisionBox(CollisionBox... boxes) {
|
||||
Collections.addAll(this.boxes, boxes);
|
||||
public ComplexCollisionBox(SimpleCollisionBox... boxes) {
|
||||
this(DEFAULT_MAX_COLLISION_BOX_SIZE, boxes);
|
||||
}
|
||||
|
||||
public boolean add(CollisionBox collisionBox) {
|
||||
return boxes.add(collisionBox);
|
||||
public ComplexCollisionBox(int maxIndex) {
|
||||
this.boxes = new SimpleCollisionBox[maxIndex];
|
||||
}
|
||||
|
||||
public ComplexCollisionBox(int maxIndex, SimpleCollisionBox... boxes) {
|
||||
this.boxes = new SimpleCollisionBox[maxIndex];
|
||||
currentLength = Math.min(maxIndex, boxes.length);
|
||||
System.arraycopy(boxes, 0, this.boxes, 0, this.currentLength);
|
||||
}
|
||||
|
||||
public boolean add(SimpleCollisionBox collisionBox) {
|
||||
boxes[currentLength] = collisionBox;
|
||||
currentLength++;
|
||||
return currentLength <= boxes.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -24,47 +38,54 @@ public class ComplexCollisionBox implements CollisionBox {
|
||||
|
||||
@Override
|
||||
public boolean isCollided(SimpleCollisionBox other) {
|
||||
for (CollisionBox box : boxes) {
|
||||
if (box.isCollided(other)) return true;
|
||||
for (int i = 0; i < currentLength; i++) {
|
||||
if (boxes[i].isCollided(other)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIntersected(SimpleCollisionBox other) {
|
||||
for (CollisionBox box : boxes) {
|
||||
if (box.isIntersected(other))
|
||||
return true;
|
||||
for (int i = 0; i < currentLength; i++) {
|
||||
if (boxes[i].isIntersected(other)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollisionBox copy() {
|
||||
ComplexCollisionBox cc = new ComplexCollisionBox();
|
||||
for (CollisionBox b : boxes)
|
||||
cc.boxes.add(b.copy());
|
||||
return cc;
|
||||
ComplexCollisionBox copy = new ComplexCollisionBox(boxes.length);
|
||||
for (int i = 0; i < currentLength; i++) {
|
||||
copy.boxes[i] = boxes[i].copy();
|
||||
}
|
||||
copy.currentLength = this.currentLength;
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollisionBox offset(double x, double y, double z) {
|
||||
for (CollisionBox b : boxes)
|
||||
b.offset(x, y, z);
|
||||
for (int i = 0; i < currentLength; i++) {
|
||||
boxes[i].offset(x, y ,z);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downCast(List<SimpleCollisionBox> list) {
|
||||
for (CollisionBox box : boxes)
|
||||
box.downCast(list);
|
||||
list.addAll(Arrays.asList(boxes).subList(0, currentLength));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int downCast(SimpleCollisionBox[] list) {
|
||||
System.arraycopy(boxes, 0, list, 0, currentLength);
|
||||
return currentLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNull() {
|
||||
for (CollisionBox box : boxes)
|
||||
if (!box.isNull())
|
||||
return false;
|
||||
for (int i = 0; i < currentLength; i++) {
|
||||
if (!boxes[i].isNull()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,11 @@ public class DynamicCollisionBox implements CollisionBox {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int downCast(SimpleCollisionBox[] list) {
|
||||
return box.fetch(player, version, block, x, y, z).offset(x, y, z).downCast(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downCast(List<SimpleCollisionBox> list) {
|
||||
box.fetch(player, version, block, x, y, z).offset(x, y, z).downCast(list);
|
||||
|
||||
@@ -32,6 +32,9 @@ public class NoCollisionBox implements CollisionBox {
|
||||
@Override
|
||||
public void downCast(List<SimpleCollisionBox> list) { /**/ }
|
||||
|
||||
@Override
|
||||
public int downCast(SimpleCollisionBox[] list) { return 0; }
|
||||
|
||||
@Override
|
||||
public boolean isNull() {
|
||||
return true;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
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;
|
||||
@@ -8,11 +9,12 @@ 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 org.bukkit.util.Vector;
|
||||
import ac.grim.grimac.utils.vector.Vector3D;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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;
|
||||
@@ -20,6 +22,8 @@ public class SimpleCollisionBox implements CollisionBox {
|
||||
public double minX, minY, minZ, maxX, maxY, maxZ;
|
||||
private boolean isFullBlock = false;
|
||||
|
||||
SimpleCollisionBox[] boxes = new SimpleCollisionBox[ComplexCollisionBox.DEFAULT_MAX_COLLISION_BOX_SIZE];
|
||||
|
||||
public SimpleCollisionBox() {
|
||||
this(0, 0, 0, 0, 0, 0, false);
|
||||
}
|
||||
@@ -45,7 +49,7 @@ public class SimpleCollisionBox implements CollisionBox {
|
||||
isFullBlock = fullBlock;
|
||||
}
|
||||
|
||||
public SimpleCollisionBox(Vector min, Vector max) {
|
||||
public SimpleCollisionBox(Vector3D min, Vector3D max) {
|
||||
this(min.getX(), min.getY(), min.getZ(), max.getX(), max.getY(), max.getZ());
|
||||
}
|
||||
|
||||
@@ -84,10 +88,10 @@ public class SimpleCollisionBox implements CollisionBox {
|
||||
}
|
||||
|
||||
public SimpleCollisionBox(Location loc, double width, double height) {
|
||||
this(loc.toVector(), width, height);
|
||||
this(newVector3D(loc.getX(), loc.getY(), loc.getZ()), width, height);
|
||||
}
|
||||
|
||||
public SimpleCollisionBox(Vector vec, double width, double height) {
|
||||
public SimpleCollisionBox(Vector3D vec, double width, double height) {
|
||||
this(vec.getX(), vec.getY(), vec.getZ(), vec.getX(), vec.getY(), vec.getZ());
|
||||
|
||||
expand(width / 2, 0, width / 2);
|
||||
@@ -150,16 +154,16 @@ public class SimpleCollisionBox implements CollisionBox {
|
||||
return this;
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
return vectors;
|
||||
}
|
||||
|
||||
@@ -233,11 +237,10 @@ public class SimpleCollisionBox implements CollisionBox {
|
||||
return isIntersected((SimpleCollisionBox) other);
|
||||
}
|
||||
|
||||
List<SimpleCollisionBox> boxes = new ArrayList<>();
|
||||
other.downCast(boxes);
|
||||
int size = other.downCast(boxes);
|
||||
|
||||
for (SimpleCollisionBox box : boxes) {
|
||||
if (isIntersected(box)) return true;
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (isIntersected(boxes[i])) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -268,6 +271,12 @@ public class SimpleCollisionBox implements CollisionBox {
|
||||
list.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int downCast(SimpleCollisionBox[] list) {
|
||||
list[0] = this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNull() {
|
||||
return false;
|
||||
@@ -402,14 +411,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 Vector intersectsRay(Ray ray, float minDist, float maxDist) {
|
||||
Vector invDir = new Vector(1f / ray.calculateDirection().getX(), 1f / ray.calculateDirection().getY(), 1f / ray.calculateDirection().getZ());
|
||||
public Vector3D intersectsRay(Ray ray, float minDist, float maxDist) {
|
||||
Vector3D invDir = newVector3D(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;
|
||||
|
||||
Vector bbox = signDirX ? max() : min();
|
||||
Vector3D 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();
|
||||
@@ -448,12 +457,12 @@ public class SimpleCollisionBox implements CollisionBox {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Vector max() {
|
||||
return new Vector(maxX, maxY, maxZ);
|
||||
public Vector3D max() {
|
||||
return newVector3D(maxX, maxY, maxZ);
|
||||
}
|
||||
|
||||
public Vector min() {
|
||||
return new Vector(minX, minY, minZ);
|
||||
public Vector3D min() {
|
||||
return newVector3D(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;
|
||||
Vector blockHitLocation;
|
||||
Vector3D blockHitLocation;
|
||||
WrappedBlockState state;
|
||||
BlockFace closestDirection;
|
||||
|
||||
public HitData(Vector3i position, Vector blockHitLocation, BlockFace closestDirection, WrappedBlockState state) {
|
||||
public HitData(Vector3i position, Vector3D blockHitLocation, BlockFace closestDirection, WrappedBlockState state) {
|
||||
this.position = position;
|
||||
this.blockHitLocation = blockHitLocation;
|
||||
this.closestDirection = closestDirection;
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
package ac.grim.grimac.utils.data;
|
||||
|
||||
public record KnownInput(boolean forward, boolean backward, boolean left, boolean right, boolean jump, boolean shift, boolean sprint) {
|
||||
}
|
||||
@@ -24,6 +24,9 @@ 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;
|
||||
|
||||
Loaded 100 of 141 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user