Compare commits
3
Commits
badpacketsz
..
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
187ef354e0 | ||
|
|
b6cc8ce57c | ||
|
|
e07f02a05f |
No files matched your search
@@ -1,71 +0,0 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ master ]
|
||||
schedule:
|
||||
- cron: '30 15 * * 2'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'java' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||
# Learn more:
|
||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
@@ -1,38 +0,0 @@
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
# This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created
|
||||
# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Publishing-using-gradle
|
||||
|
||||
name: Gradle Package
|
||||
|
||||
on:
|
||||
[push, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
|
||||
settings-path: ${{ github.workspace }} # location for the settings.xml file
|
||||
|
||||
- name: Build with Gradle
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
with:
|
||||
arguments: build
|
||||
- name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: /home/runner/work/Grim/Grim/build/libs/**.jar
|
||||
@@ -0,0 +1,95 @@
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
|
||||
|
||||
name: Java CI with Gradle
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "2.0" ]
|
||||
pull_request:
|
||||
branches: [ "2.0" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'temurin'
|
||||
|
||||
# Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
|
||||
# See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda
|
||||
|
||||
- name: Build with Gradle Wrapper
|
||||
run: ./gradlew build
|
||||
|
||||
- name: Get current datetime
|
||||
id: datetime
|
||||
run: echo "datetime=$(date +'%Y-%m-%d-%H%M%S')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Delete previous dev release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
previous_release_id=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
||||
"https://api.github.com/repos/${{ github.repository }}/releases/tags/dev" | jq -r .id)
|
||||
if [ "$previous_release_id" != "null" ]; then
|
||||
curl -X DELETE -H "Authorization: token $GITHUB_TOKEN" \
|
||||
"https://api.github.com/repos/${{ github.repository }}/releases/$previous_release_id"
|
||||
git push --delete origin dev || true
|
||||
fi
|
||||
- name: Create new dev release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: dev
|
||||
release_name: Dev Build ${{ steps.datetime.outputs.datetime }}
|
||||
body: |
|
||||
This is an automated dev build of the master branch.
|
||||
Build date: ${{ steps.datetime.outputs.datetime }}
|
||||
draft: false
|
||||
prerelease: true
|
||||
|
||||
- name: Find JAR file
|
||||
id: find_jar
|
||||
run: |
|
||||
JAR_PATH=$(find ./build/libs -name "*.jar" | head -n 1)
|
||||
echo "jar_path=$JAR_PATH" >> $GITHUB_OUTPUT
|
||||
echo "jar_name=$(basename $JAR_PATH)" >> $GITHUB_OUTPUT
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ${{ steps.find_jar.outputs.jar_path }}
|
||||
asset_name: GrimAC-${{ steps.datetime.outputs.datetime }}-dev.jar
|
||||
asset_content_type: application/java-archive
|
||||
|
||||
dependency-submission:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'temurin'
|
||||
@@ -7,7 +7,7 @@ GrimAC is an open source Minecraft anticheat designed for 1.21 and supports 1.8-
|
||||
### Compiling through terminal/command prompt
|
||||
1. git clone https://github.com/GrimAnticheat/Grim.git (or click the green code button, download ZIP, then unzip it.)
|
||||
2. cd Grim
|
||||
3. ./gradlew build
|
||||
3. gradlew build
|
||||
4. The final jar is located in build/libs
|
||||
|
||||
### API Information
|
||||
|
||||
+24
-55
@@ -6,39 +6,13 @@ plugins {
|
||||
id("com.github.johnrengelman.shadow") version "8.1.1"
|
||||
id("io.freefair.lombok") version "8.6"
|
||||
id("net.minecrell.plugin-yml.bukkit") version "0.6.0"
|
||||
id("com.diffplug.spotless") version "6.25.0"
|
||||
}
|
||||
|
||||
spotless {
|
||||
java {
|
||||
endWithNewline()
|
||||
indentWithSpaces(4)
|
||||
removeUnusedImports()
|
||||
trimTrailingWhitespace()
|
||||
targetExclude("build/generated/**/*")
|
||||
}
|
||||
|
||||
kotlinGradle {
|
||||
endWithNewline()
|
||||
indentWithSpaces(4)
|
||||
trimTrailingWhitespace()
|
||||
}
|
||||
}
|
||||
|
||||
group = "ac.grim.grimac"
|
||||
version = "2.3.68"
|
||||
version = "2.3.67"
|
||||
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))
|
||||
}
|
||||
|
||||
// Set to false for debug builds
|
||||
// You cannot live reload classes if the jar relocates dependencies
|
||||
// Checks Project properties -> environment variable -> defaults true
|
||||
val relocate: Boolean = project.findProperty("relocate")?.toString()?.toBoolean()
|
||||
?: System.getenv("RELOCATE_JAR")?.toBoolean()
|
||||
?: true
|
||||
java.sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
java.targetCompatibility = JavaVersion.VERSION_1_8
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
@@ -60,20 +34,19 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("com.github.retrooper:packetevents-spigot:2.5.1-SNAPSHOT")
|
||||
implementation("com.github.retrooper:packetevents-spigot:2.5.0-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("github.scarsz:configuralize:1.4.0")
|
||||
|
||||
//implementation("com.github.grimanticheat:grimapi:1193c4fa41")
|
||||
// Used for local testing: implementation("ac.grim.grimac:GRIMAPI:1.0")
|
||||
implementation("com.github.grimanticheat:grimapi:fc5634e444")
|
||||
implementation("com.github.grimanticheat:grimapi:1193c4fa41")
|
||||
// Used for local testing: implementation("ac.grim.grimac:grimapi:1.0")
|
||||
|
||||
implementation("org.jetbrains:annotations:24.1.0")
|
||||
compileOnly("org.geysermc.floodgate:api:2.0-SNAPSHOT")
|
||||
compileOnly("org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT")
|
||||
compileOnly("com.viaversion:viaversion-api:5.0.4-SNAPSHOT")
|
||||
compileOnly("com.viaversion:viaversion-api:4.9.4-SNAPSHOT")
|
||||
//
|
||||
compileOnly("io.netty:netty-all:4.1.85.Final")
|
||||
}
|
||||
@@ -82,7 +55,6 @@ bukkit {
|
||||
name = "GrimAC"
|
||||
author = "GrimAC"
|
||||
main = "ac.grim.grimac.GrimAC"
|
||||
website = "https://grim.ac/"
|
||||
apiVersion = "1.13"
|
||||
foliaSupported = true
|
||||
|
||||
@@ -148,7 +120,6 @@ bukkit {
|
||||
|
||||
tasks.build {
|
||||
dependsOn(tasks.shadowJar)
|
||||
dependsOn(tasks.spotlessApply)
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile> {
|
||||
@@ -162,23 +133,21 @@ publishing.publications.create<MavenPublication>("maven") {
|
||||
tasks.shadowJar {
|
||||
minimize()
|
||||
archiveFileName.set("${project.name}-${project.version}.jar")
|
||||
if (relocate) {
|
||||
relocate("io.github.retrooper.packetevents", "ac.grim.grimac.shaded.io.github.retrooper.packetevents")
|
||||
relocate("com.github.retrooper.packetevents", "ac.grim.grimac.shaded.com.github.retrooper.packetevents")
|
||||
relocate("co.aikar.commands", "ac.grim.grimac.shaded.acf")
|
||||
relocate("co.aikar.locale", "ac.grim.grimac.shaded.locale")
|
||||
relocate("club.minnced", "ac.grim.grimac.shaded.discord-webhooks")
|
||||
relocate("github.scarsz.configuralize", "ac.grim.grimac.shaded.configuralize")
|
||||
relocate("com.github.puregero", "ac.grim.grimac.shaded.com.github.puregero")
|
||||
relocate("com.google.code.gson", "ac.grim.grimac.shaded.gson")
|
||||
relocate("alexh", "ac.grim.grimac.shaded.maps")
|
||||
relocate("it.unimi.dsi.fastutil", "ac.grim.grimac.shaded.fastutil")
|
||||
relocate("net.kyori", "ac.grim.grimac.shaded.kyori")
|
||||
relocate("okhttp3", "ac.grim.grimac.shaded.okhttp3")
|
||||
relocate("okio", "ac.grim.grimac.shaded.okio")
|
||||
relocate("org.yaml.snakeyaml", "ac.grim.grimac.shaded.snakeyaml")
|
||||
relocate("org.json", "ac.grim.grimac.shaded.json")
|
||||
relocate("org.intellij", "ac.grim.grimac.shaded.intellij")
|
||||
relocate("org.jetbrains", "ac.grim.grimac.shaded.jetbrains")
|
||||
}
|
||||
relocate("io.github.retrooper.packetevents", "ac.grim.grimac.shaded.io.github.retrooper.packetevents")
|
||||
relocate("com.github.retrooper.packetevents", "ac.grim.grimac.shaded.com.github.retrooper.packetevents")
|
||||
relocate("co.aikar.commands", "ac.grim.grimac.shaded.acf")
|
||||
relocate("co.aikar.locale", "ac.grim.grimac.shaded.locale")
|
||||
relocate("club.minnced", "ac.grim.grimac.shaded.discord-webhooks")
|
||||
relocate("github.scarsz.configuralize", "ac.grim.grimac.shaded.configuralize")
|
||||
relocate("com.github.puregero", "ac.grim.grimac.shaded.com.github.puregero")
|
||||
relocate("com.google.code.gson", "ac.grim.grimac.shaded.gson")
|
||||
relocate("alexh", "ac.grim.grimac.shaded.maps")
|
||||
relocate("it.unimi.dsi.fastutil", "ac.grim.grimac.shaded.fastutil")
|
||||
relocate("net.kyori", "ac.grim.grimac.shaded.kyori")
|
||||
relocate("okhttp3", "ac.grim.grimac.shaded.okhttp3")
|
||||
relocate("okio", "ac.grim.grimac.shaded.okio")
|
||||
relocate("org.yaml.snakeyaml", "ac.grim.grimac.shaded.snakeyaml")
|
||||
relocate("org.json", "ac.grim.grimac.shaded.json")
|
||||
relocate("org.intellij", "ac.grim.grimac.shaded.intellij")
|
||||
relocate("org.jetbrains", "ac.grim.grimac.shaded.jetbrains")
|
||||
}
|
||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
package ac.grim.grimac;
|
||||
|
||||
import ac.grim.grimac.api.GrimAbstractAPI;
|
||||
import ac.grim.grimac.manager.*;
|
||||
import ac.grim.grimac.manager.config.BaseConfigManager;
|
||||
import ac.grim.grimac.utils.anticheat.PlayerDataManager;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
@Getter
|
||||
public enum GrimAPI {
|
||||
INSTANCE;
|
||||
|
||||
private final BaseConfigManager configManager = new BaseConfigManager();
|
||||
private final AlertManagerImpl alertManager = new AlertManagerImpl();
|
||||
private final SpectateManager spectateManager = new SpectateManager();
|
||||
private final DiscordManager discordManager = new DiscordManager();
|
||||
@@ -18,10 +19,12 @@ public enum GrimAPI {
|
||||
private final TickManager tickManager = new TickManager();
|
||||
private final GrimExternalAPI externalAPI = new GrimExternalAPI(this);
|
||||
private InitManager initManager;
|
||||
private ConfigManager configManager;
|
||||
private JavaPlugin plugin;
|
||||
|
||||
public void load(final JavaPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.configManager = new ConfigManager();
|
||||
initManager = new InitManager();
|
||||
initManager.load();
|
||||
}
|
||||
@@ -29,6 +32,7 @@ public enum GrimAPI {
|
||||
public void start(final JavaPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
initManager.start();
|
||||
Bukkit.getServicesManager().register(GrimAbstractAPI.class, externalAPI, plugin, ServicePriority.Normal);
|
||||
}
|
||||
|
||||
public void stop(final JavaPlugin plugin) {
|
||||
|
||||
@@ -1,34 +1,25 @@
|
||||
package ac.grim.grimac;
|
||||
|
||||
import ac.grim.grimac.api.AbstractCheck;
|
||||
import ac.grim.grimac.api.GrimAbstractAPI;
|
||||
import ac.grim.grimac.api.GrimUser;
|
||||
import ac.grim.grimac.api.alerts.AlertManager;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.api.events.GrimReloadEvent;
|
||||
import ac.grim.grimac.manager.config.ConfigManagerFileImpl;
|
||||
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.common.ConfigReloadObserver;
|
||||
import com.github.retrooper.packetevents.netty.channel.ChannelHelper;
|
||||
import io.github.retrooper.packetevents.util.SpigotReflectionUtil;
|
||||
import io.github.retrooper.packetevents.util.folia.FoliaScheduler;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
//This is used for grim's external API. It has its own class just for organization.
|
||||
|
||||
public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, Initable {
|
||||
public class GrimExternalAPI implements GrimAbstractAPI, Initable {
|
||||
|
||||
private final GrimAPI api;
|
||||
|
||||
@@ -50,8 +41,7 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, I
|
||||
@Getter
|
||||
private final Map<String, Function<GrimUser, String>> variableReplacements = new ConcurrentHashMap<>();
|
||||
|
||||
@Getter
|
||||
private final Map<String, String> staticReplacements = new ConcurrentHashMap<>();
|
||||
@Getter private final Map<String, String> staticReplacements = new ConcurrentHashMap<>();
|
||||
|
||||
public String replaceVariables(GrimUser user, String content, boolean colors) {
|
||||
if (colors) content = ChatColor.translateAlternateColorCodes('&', content);
|
||||
@@ -66,20 +56,12 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, I
|
||||
|
||||
@Override
|
||||
public void registerVariable(String string, Function<GrimUser, String> replacement) {
|
||||
if (replacement == null) {
|
||||
variableReplacements.remove(string);
|
||||
} else {
|
||||
variableReplacements.put(string, replacement);
|
||||
}
|
||||
variableReplacements.put(string, replacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerVariable(String variable, String replacement) {
|
||||
if (replacement == null) {
|
||||
staticReplacements.remove(variable);
|
||||
} else {
|
||||
staticReplacements.put(variable, replacement);
|
||||
}
|
||||
staticReplacements.put(variable, replacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -88,20 +70,34 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, I
|
||||
return description.getVersion();
|
||||
}
|
||||
|
||||
private final Map<String, Function<Object, Object>> functions = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void registerFunction(String key, Function<Object, Object> function) {
|
||||
if (function == null) {
|
||||
functions.remove(key);
|
||||
} else {
|
||||
functions.put(key, function);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<Object, Object> getFunction(String key) {
|
||||
return functions.get(key);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
GrimAPI.INSTANCE.getConfigManager().reload();
|
||||
//Reload checks for all players
|
||||
for (GrimPlayer grimPlayer : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
|
||||
ChannelHelper.runInEventLoop(grimPlayer.user.getChannel(), () -> {
|
||||
grimPlayer.onReload();
|
||||
grimPlayer.updatePermissions();
|
||||
grimPlayer.punishmentManager.reload();
|
||||
for (AbstractCheck value : grimPlayer.checkManager.allChecks.values()) {
|
||||
value.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
//Restart
|
||||
GrimAPI.INSTANCE.getDiscordManager().start();
|
||||
GrimAPI.INSTANCE.getSpectateManager().start();
|
||||
GrimAPI.INSTANCE.getExternalAPI().start();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,107 +105,17 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, I
|
||||
return GrimAPI.INSTANCE.getAlertManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigManager getConfigManager() {
|
||||
return configManager;
|
||||
}
|
||||
|
||||
private ConfigManager configManager = null;
|
||||
private final ConfigManagerFileImpl configManagerFile = new ConfigManagerFileImpl();
|
||||
private boolean started = false;
|
||||
|
||||
// on load, load the config & register the service
|
||||
public void load() {
|
||||
reload(configManagerFile);
|
||||
Bukkit.getServicesManager().register(GrimAbstractAPI.class, this, GrimAPI.INSTANCE.getPlugin(), ServicePriority.Normal);
|
||||
}
|
||||
|
||||
// handles any config loading that's needed to be done after load
|
||||
@Override
|
||||
public void start() {
|
||||
started = true;
|
||||
try {
|
||||
GrimAPI.INSTANCE.getConfigManager().start();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
variableReplacements.put("%player%", GrimUser::getName);
|
||||
variableReplacements.put("%uuid%", user -> user.getUniqueId().toString());
|
||||
variableReplacements.put("%ping%", user -> user.getTransactionPing() + "");
|
||||
variableReplacements.put("%brand%", GrimUser::getBrand);
|
||||
variableReplacements.put("%h_sensitivity%", user -> ((int) Math.round(user.getHorizontalSensitivity() * 200)) + "");
|
||||
variableReplacements.put("%v_sensitivity%", user -> ((int) Math.round(user.getVerticalSensitivity() * 200)) + "");
|
||||
variableReplacements.put("%fast_math%", user -> !user.isVanillaMath() + "");
|
||||
variableReplacements.put("%tps%", user -> String.format("%.2f", SpigotReflectionUtil.getTPS()));
|
||||
variableReplacements.put("%version%", GrimUser::getVersionName);
|
||||
variableReplacements.put("%prefix%", user -> ChatColor.translateAlternateColorCodes('&', GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("prefix", "&bGrim &8»")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload(ConfigManager config) {
|
||||
if (config.isLoadedAsync() && started) {
|
||||
FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(),
|
||||
o -> successfulReload(config));
|
||||
} else {
|
||||
successfulReload(config);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> reloadAsync(ConfigManager config) {
|
||||
if (config.isLoadedAsync() && started) {
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(),
|
||||
o -> future.complete(successfulReload(config)));
|
||||
return future;
|
||||
}
|
||||
return CompletableFuture.completedFuture(successfulReload(config));
|
||||
}
|
||||
|
||||
private boolean successfulReload(ConfigManager config) {
|
||||
try {
|
||||
config.reload();
|
||||
GrimAPI.INSTANCE.getConfigManager().load(config);
|
||||
if (started) GrimAPI.INSTANCE.getConfigManager().start();
|
||||
onReload(config);
|
||||
if (started) FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(),
|
||||
o -> Bukkit.getPluginManager().callEvent(new GrimReloadEvent(true)));
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (started) FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(),
|
||||
o -> Bukkit.getPluginManager().callEvent(new GrimReloadEvent(false)));
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager newConfig) {
|
||||
if (newConfig == null) {
|
||||
LogUtil.warn("ConfigManager not set. Using default config file manager.");
|
||||
configManager = configManagerFile;
|
||||
} else {
|
||||
configManager = newConfig;
|
||||
}
|
||||
// Update variables
|
||||
updateVariables();
|
||||
// Restart
|
||||
GrimAPI.INSTANCE.getDiscordManager().start();
|
||||
GrimAPI.INSTANCE.getSpectateManager().start();
|
||||
// Don't reload players if the plugin hasn't started yet
|
||||
if (!started) return;
|
||||
// Reload checks for all players
|
||||
for (GrimPlayer grimPlayer : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
|
||||
ChannelHelper.runInEventLoop(grimPlayer.user.getChannel(), () -> {
|
||||
grimPlayer.updatePermissions();
|
||||
grimPlayer.reload(configManager);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void updateVariables() {
|
||||
variableReplacements.putIfAbsent("%player%", GrimUser::getName);
|
||||
variableReplacements.putIfAbsent("%uuid%", user -> user.getUniqueId().toString());
|
||||
variableReplacements.putIfAbsent("%ping%", user -> user.getTransactionPing() + "");
|
||||
variableReplacements.putIfAbsent("%brand%", GrimUser::getBrand);
|
||||
variableReplacements.putIfAbsent("%h_sensitivity%", user -> ((int) Math.round(user.getHorizontalSensitivity() * 200)) + "");
|
||||
variableReplacements.putIfAbsent("%v_sensitivity%", user -> ((int) Math.round(user.getVerticalSensitivity() * 200)) + "");
|
||||
variableReplacements.putIfAbsent("%fast_math%", user -> !user.isVanillaMath() + "");
|
||||
variableReplacements.putIfAbsent("%tps%", user -> String.format("%.2f", SpigotReflectionUtil.getTPS()));
|
||||
variableReplacements.putIfAbsent("%version%", GrimUser::getVersionName);
|
||||
// static variables
|
||||
staticReplacements.putIfAbsent("%prefix%", ChatColor.translateAlternateColorCodes('&', GrimAPI.INSTANCE.getConfigManager().getPrefix()));
|
||||
staticReplacements.putIfAbsent("%grim_version%", getGrimVersion());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,20 +2,18 @@ package ac.grim.grimac.checks;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.AbstractCheck;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.api.events.FlagEvent;
|
||||
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 io.github.retrooper.packetevents.util.folia.FoliaScheduler;
|
||||
import github.scarsz.configuralize.DynamicConfig;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
// Class from https://github.com/Tecnio/AntiCheatBase/blob/master/src/main/java/me/tecnio/anticheat/check/Check.java
|
||||
@Getter
|
||||
public class Check implements AbstractCheck, ConfigReloadObserver {
|
||||
public class Check implements AbstractCheck {
|
||||
protected final GrimPlayer player;
|
||||
|
||||
public double violations;
|
||||
@@ -25,13 +23,11 @@ public class Check implements AbstractCheck, ConfigReloadObserver {
|
||||
private String checkName;
|
||||
private String configName;
|
||||
private String alternativeName;
|
||||
private String displayName;
|
||||
private String description;
|
||||
|
||||
private boolean experimental;
|
||||
@Setter
|
||||
private boolean isEnabled;
|
||||
private boolean exempted;
|
||||
|
||||
@Override
|
||||
public boolean isExperimental() {
|
||||
@@ -54,21 +50,13 @@ public class Check implements AbstractCheck, ConfigReloadObserver {
|
||||
this.alternativeName = checkData.alternativeName();
|
||||
this.experimental = checkData.experimental();
|
||||
this.description = checkData.description();
|
||||
this.displayName = this.checkName;
|
||||
}
|
||||
//
|
||||
|
||||
reload();
|
||||
}
|
||||
|
||||
public boolean shouldModifyPackets() {
|
||||
return isEnabled && !player.disableGrim && !player.noModifyPacketPermission && !exempted;
|
||||
}
|
||||
|
||||
public void updateExempted() {
|
||||
if (player.bukkitPlayer == null || checkName == null) return;
|
||||
FoliaScheduler.getEntityScheduler().run(player.bukkitPlayer, GrimAPI.INSTANCE.getPlugin(),
|
||||
t -> exempted = player.bukkitPlayer.hasPermission("grim.exempt." + checkName.toLowerCase()),
|
||||
() -> {});
|
||||
return isEnabled && !player.disableGrim && !player.noModifyPacketPermission;
|
||||
}
|
||||
|
||||
public final boolean flagAndAlert(String verbose) {
|
||||
@@ -84,7 +72,7 @@ public class Check implements AbstractCheck, ConfigReloadObserver {
|
||||
}
|
||||
|
||||
public final boolean flag() {
|
||||
if (player.disableGrim || (experimental && !player.isExperimentalChecks()) || exempted)
|
||||
if (player.disableGrim || (experimental && !GrimAPI.INSTANCE.getConfigManager().isExperimentalChecks()))
|
||||
return false; // Avoid calling event if disabled
|
||||
|
||||
FlagEvent event = new FlagEvent(player, this);
|
||||
@@ -110,26 +98,21 @@ public class Check implements AbstractCheck, ConfigReloadObserver {
|
||||
violations = Math.max(0, violations - decay);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload(ConfigManager configuration) {
|
||||
decay = configuration.getDoubleElse(configName + ".decay", decay);
|
||||
setbackVL = configuration.getDoubleElse(configName + ".setbackvl", setbackVL);
|
||||
displayName = configuration.getStringElse(configName + ".displayname", checkName);
|
||||
public void reload() {
|
||||
decay = getConfig().getDoubleElse(configName + ".decay", decay);
|
||||
setbackVL = getConfig().getDoubleElse(configName + ".setbackvl", setbackVL);
|
||||
|
||||
if (setbackVL == -1) setbackVL = Double.MAX_VALUE;
|
||||
updateExempted();
|
||||
onReload(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
|
||||
}
|
||||
|
||||
public boolean alert(String verbose) {
|
||||
return player.punishmentManager.handleAlert(player, verbose, this);
|
||||
}
|
||||
|
||||
public DynamicConfig getConfig() {
|
||||
return GrimAPI.INSTANCE.getConfigManager().getConfig();
|
||||
}
|
||||
|
||||
public boolean setbackIfAboveSetbackVL() {
|
||||
if (getViolations() > setbackVL) {
|
||||
return player.getSetbackTeleportUtil().executeViolationSetback();
|
||||
@@ -150,9 +133,5 @@ public class Check implements AbstractCheck, ConfigReloadObserver {
|
||||
packetType == PacketType.Play.Client.WINDOW_CONFIRMATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
reload(GrimAPI.INSTANCE.getConfigManager().getConfig());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,8 +11,7 @@ import ac.grim.grimac.utils.anticheat.update.RotationUpdate;
|
||||
// It works on clients who % 360 their rotation.
|
||||
@CheckData(name = "AimModulo360", decay = 0.005)
|
||||
public class AimModulo360 extends Check implements RotationCheck {
|
||||
|
||||
private float lastDeltaYaw;
|
||||
float lastDeltaYaw;
|
||||
|
||||
public AimModulo360(GrimPlayer playerData) {
|
||||
super(playerData);
|
||||
@@ -20,17 +19,12 @@ public class AimModulo360 extends Check implements RotationCheck {
|
||||
|
||||
@Override
|
||||
public void process(final RotationUpdate rotationUpdate) {
|
||||
if (player.packetStateData.lastPacketWasTeleport) {
|
||||
lastDeltaYaw = rotationUpdate.getDeltaXRot();
|
||||
return;
|
||||
}
|
||||
|
||||
lastDeltaYaw = rotationUpdate.getDeltaXRot();
|
||||
if (player.packetStateData.lastPacketWasTeleport) return;
|
||||
if (player.xRot < 360 && player.xRot > -360 && Math.abs(rotationUpdate.getDeltaXRot()) > 320 && Math.abs(lastDeltaYaw) < 30) {
|
||||
flagAndAlert();
|
||||
} else {
|
||||
reward();
|
||||
}
|
||||
|
||||
lastDeltaYaw = rotationUpdate.getDeltaXRot();
|
||||
}
|
||||
}
|
||||
@@ -59,15 +59,15 @@ public class AimProcessor extends Check implements RotationCheck {
|
||||
|
||||
if (this.xRotMode.size() > SIGNIFICANT_SAMPLES_THRESHOLD) {
|
||||
Pair<Double, Integer> modeX = this.xRotMode.getMode();
|
||||
if (modeX.second() > SIGNIFICANT_SAMPLES_THRESHOLD) {
|
||||
this.modeX = modeX.first();
|
||||
if (modeX.getSecond() > SIGNIFICANT_SAMPLES_THRESHOLD) {
|
||||
this.modeX = modeX.getFirst();
|
||||
this.sensitivityX = convertToSensitivity(this.modeX);
|
||||
}
|
||||
}
|
||||
if (this.yRotMode.size() > SIGNIFICANT_SAMPLES_THRESHOLD) {
|
||||
Pair<Double, Integer> modeY = this.yRotMode.getMode();
|
||||
if (modeY.second() > SIGNIFICANT_SAMPLES_THRESHOLD) {
|
||||
this.modeY = modeY.first();
|
||||
if (modeY.getSecond() > SIGNIFICANT_SAMPLES_THRESHOLD) {
|
||||
this.modeY = modeY.getFirst();
|
||||
this.sensitivityY = convertToSensitivity(this.modeY);
|
||||
}
|
||||
}
|
||||
@@ -81,4 +81,4 @@ public class AimProcessor extends Check implements RotationCheck {
|
||||
double var9 = Math.cbrt(var11);
|
||||
return (var9 - 0.2f) / 0.6f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ 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.WrapperPlayClientInteractEntity;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
|
||||
|
||||
@CheckData(name = "BadPacketsH")
|
||||
public class BadPacketsH extends Check implements PacketCheck {
|
||||
|
||||
@@ -39,7 +39,7 @@ public class BadPacketsO extends Check implements PacketCheck {
|
||||
boolean hasID = false;
|
||||
|
||||
for (Pair<Long, Long> iterator : keepaliveMap) {
|
||||
if (iterator.first() == id) {
|
||||
if (iterator.getFirst() == id) {
|
||||
hasID = true;
|
||||
break;
|
||||
}
|
||||
@@ -55,7 +55,7 @@ public class BadPacketsO extends Check implements PacketCheck {
|
||||
do {
|
||||
data = keepaliveMap.poll();
|
||||
if (data == null) break;
|
||||
} while (data.first() != id);
|
||||
} while (data.getFirst() != id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
|
||||
@@ -4,6 +4,7 @@ import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.nmsutil.BlockBreakSpeed;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
@@ -24,16 +25,17 @@ public class BadPacketsX extends Check implements PacketCheck {
|
||||
if (dig.getAction() != DiggingAction.START_DIGGING && dig.getAction() != DiggingAction.FINISHED_DIGGING)
|
||||
return;
|
||||
|
||||
// the block does not have a hitbox
|
||||
boolean invalid = (block == StateTypes.LIGHT && !(player.getInventory().getHeldItem().is(ItemTypes.LIGHT) || player.getInventory().getOffHand().is(ItemTypes.LIGHT)))
|
||||
final boolean invalid;
|
||||
|
||||
if (dig.getAction() == DiggingAction.FINISHED_DIGGING) {
|
||||
invalid = BlockBreakSpeed.getBlockDamage(player, dig.getBlockPosition()) >= 1 || block.getHardness() == -1.0f;
|
||||
} else invalid = (block == StateTypes.LIGHT && !(player.getInventory().getHeldItem().is(ItemTypes.LIGHT) || player.getInventory().getOffHand().is(ItemTypes.LIGHT)))
|
||||
|| block.isAir()
|
||||
|| block == StateTypes.WATER
|
||||
|| block == StateTypes.LAVA
|
||||
|| block == StateTypes.BUBBLE_COLUMN
|
||||
|| block == StateTypes.MOVING_PISTON
|
||||
|| (block == StateTypes.FIRE && noFireHitbox)
|
||||
// or the client claims to have broken an unbreakable block
|
||||
|| block.getHardness() == -1.0f && dig.getAction() == DiggingAction.FINISHED_DIGGING;
|
||||
|| (block == StateTypes.FIRE && noFireHitbox);
|
||||
|
||||
if (invalid && flagAndAlert("block=" + block.getName() + ", type=" + dig.getAction()) && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
|
||||
@@ -4,10 +4,7 @@ import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
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;
|
||||
@@ -16,7 +13,7 @@ import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPl
|
||||
import static ac.grim.grimac.events.packets.patch.ResyncWorldUtil.resyncPosition;
|
||||
import static ac.grim.grimac.utils.nmsutil.BlockBreakSpeed.getBlockDamage;
|
||||
|
||||
@CheckData(name = "BadPacketsZ")
|
||||
@CheckData(name = "BadPacketsZ", experimental = true)
|
||||
public class BadPacketsZ extends Check implements PacketCheck {
|
||||
public BadPacketsZ(final GrimPlayer player) {
|
||||
super(player);
|
||||
@@ -24,7 +21,7 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
|
||||
private boolean lastBlockWasInstantBreak = false;
|
||||
private Vector3i lastBlock, lastCancelledBlock, lastLastBlock = null;
|
||||
private final int exemptedY = player.getClientVersion().isOlderThan(ClientVersion.V_1_8) ? 255 : (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_14) ? -1 : 4095);
|
||||
private final int exemptedY = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8) ? 4095 : 255;
|
||||
|
||||
// The client sometimes sends a wierd cancel packet
|
||||
private boolean shouldExempt(final Vector3i pos) {
|
||||
@@ -36,10 +33,18 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) && pos.y != exemptedY)
|
||||
return false;
|
||||
|
||||
// the client only sends this packet if the last block was an instant break
|
||||
if (getBlockDamage(player, lastBlock) < 1)
|
||||
return false;
|
||||
|
||||
// and if this block is not an instant break
|
||||
return player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) || getBlockDamage(player, pos) < 1;
|
||||
}
|
||||
|
||||
private String formatted(Vector3i vec) {
|
||||
return vec == null ? "null" : vec.x + ", " + vec.y + ", " + vec.z;
|
||||
}
|
||||
|
||||
public void handle(PacketReceiveEvent event, WrapperPlayClientPlayerDigging dig) {
|
||||
if (dig.getAction() == DiggingAction.START_DIGGING) {
|
||||
final Vector3i pos = dig.getBlockPosition();
|
||||
@@ -54,7 +59,7 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
final Vector3i pos = dig.getBlockPosition();
|
||||
|
||||
if (shouldExempt(pos)) {
|
||||
lastCancelledBlock = pos;
|
||||
lastCancelledBlock = null;
|
||||
lastLastBlock = null;
|
||||
lastBlock = null;
|
||||
return;
|
||||
@@ -63,7 +68,7 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
if (!pos.equals(lastBlock)) {
|
||||
// https://github.com/GrimAnticheat/Grim/issues/1512
|
||||
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 (flagAndAlert("action=CANCELLED_DIGGING" + ", last=" + formatted(lastBlock) + ", pos=" + formatted(pos))) {
|
||||
if (shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -84,7 +89,7 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
|
||||
// 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 (flagAndAlert("action=FINISHED_DIGGING" + ", last=" + formatted(lastBlock) + ", pos=" + formatted(pos))) {
|
||||
if (shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
package ac.grim.grimac.checks.impl.combat;
|
||||
|
||||
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 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.wrapper.play.client.WrapperPlayClientInteractEntity;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@CheckData(name = "MultiInteractA", experimental = true)
|
||||
public class MultiInteractA extends Check implements PostPredictionCheck {
|
||||
public MultiInteractA(final GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
private final ArrayList<String> flags = new ArrayList<>();
|
||||
private int lastEntity;
|
||||
private boolean lastSneaking;
|
||||
private boolean hasInteracted = false;
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY) {
|
||||
WrapperPlayClientInteractEntity packet = new WrapperPlayClientInteractEntity(event);
|
||||
int entity = packet.getEntityId();
|
||||
boolean sneaking = packet.isSneaking().orElse(false);
|
||||
|
||||
if (hasInteracted && entity != lastEntity) {
|
||||
String verbose = "lastEntity=" + lastEntity + ", entity=" + entity
|
||||
+ ", lastSneaking=" + lastSneaking + ", sneaking=" + sneaking;
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) {
|
||||
if (flagAndAlert(verbose) && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
} else {
|
||||
flags.add(verbose);
|
||||
}
|
||||
}
|
||||
|
||||
lastEntity = entity;
|
||||
lastSneaking = sneaking;
|
||||
hasInteracted = true;
|
||||
}
|
||||
|
||||
if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType()) && player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8) && !player.packetStateData.lastPacketWasTeleport) {
|
||||
hasInteracted = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
// 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) && !player.uncertaintyHandler.lastVehicleSwitch.hasOccurredSince(0)) {
|
||||
for (String verbose : flags) {
|
||||
flagAndAlert(verbose);
|
||||
}
|
||||
}
|
||||
|
||||
flags.clear();
|
||||
hasInteracted = false;
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package ac.grim.grimac.checks.impl.combat;
|
||||
|
||||
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 ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
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.util.Vector3f;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@CheckData(name = "MultiInteractB", experimental = true)
|
||||
public class MultiInteractB extends Check implements PostPredictionCheck {
|
||||
public MultiInteractB(final GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
private final ArrayList<String> flags = new ArrayList<>();
|
||||
private Vector3f lastPos;
|
||||
private boolean hasInteracted = false;
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY) {
|
||||
Vector3f pos = new WrapperPlayClientInteractEntity(event).getTarget().orElse(null);
|
||||
|
||||
if (pos == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasInteracted && !pos.equals(lastPos)) {
|
||||
String verbose = "pos=" + MessageUtil.toUnlabledString(pos) + ", lastPos=" + MessageUtil.toUnlabledString(lastPos);
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) {
|
||||
if (flagAndAlert(verbose) && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
} else {
|
||||
flags.add(verbose);
|
||||
}
|
||||
}
|
||||
|
||||
lastPos = pos;
|
||||
hasInteracted = true;
|
||||
}
|
||||
|
||||
if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType()) && player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8) && !player.packetStateData.lastPacketWasTeleport) {
|
||||
hasInteracted = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
// 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) && !player.uncertaintyHandler.lastVehicleSwitch.hasOccurredSince(0)) {
|
||||
for (String verbose : flags) {
|
||||
flagAndAlert(verbose);
|
||||
}
|
||||
}
|
||||
|
||||
flags.clear();
|
||||
hasInteracted = false;
|
||||
}
|
||||
}
|
||||
@@ -15,13 +15,16 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
package ac.grim.grimac.checks.impl.combat;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
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 ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.HitData;
|
||||
import ac.grim.grimac.utils.data.Pair;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntity;
|
||||
import ac.grim.grimac.utils.nmsutil.BlockRayTrace;
|
||||
import ac.grim.grimac.utils.data.packetentity.dragon.PacketEntityEnderDragonPart;
|
||||
import ac.grim.grimac.utils.nmsutil.ReachUtils;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
@@ -31,21 +34,32 @@ import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
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 org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
// 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 {
|
||||
// Only one flag per reach attack, per entity, per tick.
|
||||
// We store position because lastX isn't reliable on teleports.
|
||||
private final Int2ObjectMap<Vector3d> playerAttackQueue = new Int2ObjectOpenHashMap<>();
|
||||
private final Map<Integer, Vector3d> playerAttackQueue = new HashMap<>();
|
||||
// Used to prevent falses in the wall hit check
|
||||
private final Set<Vector3i> blocksChangedThisTick = new HashSet<>();
|
||||
|
||||
private static final List<EntityType> blacklisted = Arrays.asList(
|
||||
EntityTypes.BOAT,
|
||||
EntityTypes.CHEST_BOAT,
|
||||
@@ -83,7 +97,7 @@ public class Reach extends Check implements PacketCheck {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Dead entities cause false flags (https://github.com/GrimAnticheat/Grim/issues/546)
|
||||
if (entity.isDead) return;
|
||||
|
||||
@@ -108,10 +122,11 @@ 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()) ||
|
||||
final boolean isFlying = WrapperPlayClientPlayerFlying.isFlying(event.getPacketType());
|
||||
if (isFlying ||
|
||||
event.getPacketType() == PacketType.Play.Client.PONG ||
|
||||
event.getPacketType() == PacketType.Play.Client.WINDOW_CONFIRMATION) {
|
||||
tickBetterReachCheckWithAngle();
|
||||
tickBetterReachCheckWithAngle(isFlying);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,9 +158,9 @@ public class Reach extends Check implements PacketCheck {
|
||||
}
|
||||
}
|
||||
|
||||
private void tickBetterReachCheckWithAngle() {
|
||||
for (Int2ObjectMap.Entry<Vector3d> attack : playerAttackQueue.int2ObjectEntrySet()) {
|
||||
PacketEntity reachEntity = player.compensatedEntities.entityMap.get(attack.getIntKey());
|
||||
private void tickBetterReachCheckWithAngle(boolean isFlying) {
|
||||
for (Map.Entry<Integer, Vector3d> attack : playerAttackQueue.entrySet()) {
|
||||
PacketEntity reachEntity = player.compensatedEntities.entityMap.get(attack.getKey().intValue());
|
||||
if (reachEntity != null) {
|
||||
String result = checkReach(reachEntity, attack.getValue(), false);
|
||||
if (result != null) {
|
||||
@@ -158,6 +173,9 @@ public class Reach extends Check implements PacketCheck {
|
||||
}
|
||||
}
|
||||
playerAttackQueue.clear();
|
||||
// We can't use transactions for this because of this problem:
|
||||
// transaction -> block changed applied -> 2nd transaction -> list cleared -> attack packet -> flying -> reach block hit checked, falses
|
||||
if (isFlying) blocksChangedThisTick.clear();
|
||||
}
|
||||
|
||||
private String checkReach(PacketEntity reachEntity, Vector3d from, boolean isPrediction) {
|
||||
@@ -204,13 +222,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 (double eye : possibleEyeHeights) {
|
||||
for (double eye : player.getPossibleEyeHeights()) {
|
||||
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));
|
||||
|
||||
Vector intercept = ReachUtils.calculateIntercept(targetBox, eyePos, endReachPos).first();
|
||||
Vector intercept = ReachUtils.calculateIntercept(targetBox, eyePos, endReachPos).getFirst();
|
||||
|
||||
if (ReachUtils.isVecInside(targetBox, eyePos)) {
|
||||
minDistance = 0;
|
||||
@@ -223,9 +240,26 @@ public class Reach extends Check implements PacketCheck {
|
||||
}
|
||||
}
|
||||
|
||||
final boolean experimentalChecks = true; //GrimAPI.INSTANCE.getConfigManager().isExperimentalChecks(); // TODO fix for undraft
|
||||
HitData foundHitData = null;
|
||||
// If the entity is within range of the player (we'll flag anyway if not, so no point checking blocks in this case)
|
||||
// Ignore when could be hitting through a moving shulker, piston blocks. They are just too glitchy/uncertain to check.
|
||||
if (experimentalChecks && minDistance <= 3 && !player.compensatedWorld.isNearHardEntity(player.boundingBox.copy().expand(4))) {
|
||||
final @Nullable Pair<Double, HitData> targetBlock = getTargetBlock(player, possibleLookDirs, from, minDistance);
|
||||
// And if the target block is closer to the player than the entity box, they should hit the block instead
|
||||
// So, this hit is invalid.
|
||||
if (targetBlock != null && targetBlock.getFirst() < (minDistance * minDistance)) { // targetBlock is squared
|
||||
minDistance = Double.MIN_VALUE;
|
||||
foundHitData = targetBlock.getSecond();
|
||||
}
|
||||
}
|
||||
|
||||
// if the entity is not exempt and the entity is alive
|
||||
if ((!blacklisted.contains(reachEntity.getType()) && reachEntity.isLivingEntity()) || reachEntity.getType() == EntityTypes.END_CRYSTAL) {
|
||||
if (minDistance == Double.MAX_VALUE) {
|
||||
if (minDistance == Double.MIN_VALUE && foundHitData != null) {
|
||||
cancelBuffer = 1;
|
||||
return "Hit block block=" + foundHitData.getState().getType().getName();
|
||||
} else if (minDistance == Double.MAX_VALUE) {
|
||||
cancelBuffer = 1;
|
||||
return "Missed hitbox";
|
||||
} else if (minDistance > player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_ENTITY_INTERACTION_RANGE)) {
|
||||
@@ -239,9 +273,49 @@ public class Reach extends Check implements PacketCheck {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void handleBlockChange(Vector3i vector3i, WrappedBlockState state) {
|
||||
if (blocksChangedThisTick.size() >= 40) return; // Don't let players freeze movement packets to grow this
|
||||
// Only do this for nearby blocks
|
||||
if (new Vector(vector3i.x, vector3i.y, vector3i.z).distanceSquared(new Vector(player.x, player.y, player.z)) > 6) return;
|
||||
// Only do this if the state really had any world impact
|
||||
if (state.equals(player.compensatedWorld.getWrappedBlockStateAt(vector3i))) return;
|
||||
blocksChangedThisTick.add(vector3i);
|
||||
}
|
||||
|
||||
// Returns a pair so we can check the block type in the flag
|
||||
@Nullable
|
||||
private Pair<Double, HitData> getTargetBlock(GrimPlayer player, List<Vector> possibleLookDirs, Vector3d from, double minDistance) {
|
||||
// Check every possible look direction and every possible eye height
|
||||
// IF *NONE* of them allow the player to hit the entity, this is an invalid hit
|
||||
HitData bestHitData = null;
|
||||
double min = Double.MAX_VALUE;
|
||||
for (Vector lookVec : possibleLookDirs) {
|
||||
for (double eye : player.getPossibleEyeHeights()) {
|
||||
Vector eyes = new Vector(from.getX(), from.getY() + eye, from.getZ());
|
||||
final double reach = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE);
|
||||
final HitData hitResult = BlockRayTrace.getNearestReachHitResult(player, eyes, lookVec, minDistance, reach);
|
||||
if (hitResult == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final double distance = eyes.distanceSquared(hitResult.getBlockHitLocation());
|
||||
// Block changes are uncertain, can't check this tick
|
||||
if (distance < (minDistance * minDistance) && blocksChangedThisTick.contains(hitResult.getPosition())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
bestHitData = hitResult;
|
||||
min = Math.min(min, distance);
|
||||
}
|
||||
}
|
||||
|
||||
return bestHitData == null ? null : Pair.of(min, bestHitData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
this.cancelImpossibleHits = config.getBooleanElse("Reach.block-impossible-hits", true);
|
||||
this.threshold = config.getDoubleElse("Reach.threshold", 0.0005);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
this.cancelImpossibleHits = getConfig().getBooleanElse("Reach.block-impossible-hits", true);
|
||||
this.threshold = getConfig().getDoubleElse("Reach.threshold", 0.0005);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ public class CrashB extends Check implements PacketCheck {
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.CREATIVE_INVENTORY_ACTION) {
|
||||
if (player.gamemode != GameMode.CREATIVE) {
|
||||
player.getSetbackTeleportUtil().executeViolationSetback();
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
flagAndAlert(); // Could be transaction split, no need to setback though
|
||||
|
||||
@@ -43,10 +43,7 @@ public class NoFallA extends Check implements PacketCheck {
|
||||
if (!isNearGround(wrapper.isOnGround())) { // If player isn't near ground
|
||||
// 1.8 boats have a mind on their own... only flag if they're not near a boat or are on 1.9+
|
||||
if (!GhostBlockDetector.isGhostBlock(player) && flagWithSetback()) alert("");
|
||||
if (shouldModifyPackets()) {
|
||||
wrapper.setOnGround(false);
|
||||
event.markForReEncode(true);
|
||||
}
|
||||
if (shouldModifyPackets()) wrapper.setOnGround(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,16 +59,10 @@ public class NoFallA extends Check implements PacketCheck {
|
||||
// Also flip teleports because I don't trust vanilla's handling of teleports and ground
|
||||
if (flipPlayerGroundStatus) {
|
||||
flipPlayerGroundStatus = false;
|
||||
if (shouldModifyPackets()) {
|
||||
wrapper.setOnGround(!wrapper.isOnGround());
|
||||
event.markForReEncode(true);
|
||||
}
|
||||
if (shouldModifyPackets()) wrapper.setOnGround(!wrapper.isOnGround());
|
||||
}
|
||||
if (player.packetStateData.lastPacketWasTeleport) {
|
||||
if (shouldModifyPackets()) {
|
||||
wrapper.setOnGround(false);
|
||||
event.markForReEncode(true);
|
||||
}
|
||||
if (shouldModifyPackets()) wrapper.setOnGround(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPluginMessage;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class ClientBrand extends Check implements PacketCheck {
|
||||
@@ -39,7 +38,6 @@ public class ClientBrand extends Check implements PacketCheck {
|
||||
System.arraycopy(data, 1, minusLength, 0, minusLength.length);
|
||||
|
||||
brand = new String(minusLength).replace(" (Velocity)", ""); //removes velocity's brand suffix
|
||||
brand = ChatColor.stripColor(brand); //strip color codes from client brand
|
||||
if (player.checkManager.getPrePredictionCheck(ExploitA.class).checkString(brand)) brand = "sent log4j";
|
||||
if (!GrimAPI.INSTANCE.getConfigManager().isIgnoredClient(brand)) {
|
||||
String message = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("client-brand-format", "%prefix% &f%player% joined using %brand%");
|
||||
|
||||
@@ -63,15 +63,15 @@ public class FastBreak extends Check implements PacketCheck {
|
||||
|
||||
if (digging.getAction() == DiggingAction.START_DIGGING) {
|
||||
WrappedBlockState block = player.compensatedWorld.getWrappedBlockStateAt(blockPosition);
|
||||
|
||||
|
||||
// Exempt all blocks that do not exist in the player version
|
||||
if (WrappedBlockState.getDefaultState(player.getClientVersion(), block.getType()).getType() == StateTypes.AIR) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
startBreak = System.currentTimeMillis() - (targetBlock == null ? 50 : 0); // ???
|
||||
targetBlock = blockPosition;
|
||||
|
||||
|
||||
maximumBlockDamage = BlockBreakSpeed.getBlockDamage(player, targetBlock);
|
||||
|
||||
double breakDelay = System.currentTimeMillis() - lastFinishBreak;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package ac.grim.grimac.checks.impl.misc;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.type.BlockPlaceCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.update.BlockPlace;
|
||||
@@ -64,9 +63,10 @@ public class GhostBlockMitigation extends BlockPlaceCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
allow = config.getBooleanElse("exploit.allow-building-on-ghostblocks", true);
|
||||
distance = config.getIntElse("exploit.distance-to-check-for-ghostblocks", 2);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
allow = getConfig().getBooleanElse("exploit.allow-building-on-ghostblocks", true);
|
||||
distance = getConfig().getIntElse("exploit.distance-to-check-for-ghostblocks", 2);
|
||||
|
||||
if (distance < 2 || distance > 4) distance = 2;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@CheckData(name = "TransactionOrder", experimental = false)
|
||||
public class TransactionOrder extends Check implements PacketCheck {
|
||||
@@ -13,4 +14,4 @@ public class TransactionOrder extends Check implements PacketCheck {
|
||||
super(player);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
package ac.grim.grimac.checks.impl.movement;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PostPredictionCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.update.PredictionComplete;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
|
||||
@CheckData(name = "NegativeTimer", configName = "NegativeTimer", setback = -1, experimental = true)
|
||||
@CheckData(name = "NegativeTimer", configName = "NegativeTimer", setback = 10, experimental = true)
|
||||
public class NegativeTimerCheck extends TimerCheck implements PostPredictionCheck {
|
||||
|
||||
public NegativeTimerCheck(GrimPlayer player) {
|
||||
@@ -24,7 +23,7 @@ public class NegativeTimerCheck extends TimerCheck implements PostPredictionChec
|
||||
|
||||
if (timerBalanceRealTime < lastMovementPlayerClock - clockDrift) {
|
||||
int lostMS = (int) ((System.nanoTime() - timerBalanceRealTime) / 1e6);
|
||||
if (flagAndAlert("-" + lostMS)) setbackIfAboveSetbackVL();
|
||||
flagAndAlert("-" + lostMS);
|
||||
timerBalanceRealTime += 50e6;
|
||||
}
|
||||
}
|
||||
@@ -36,7 +35,8 @@ public class NegativeTimerCheck extends TimerCheck implements PostPredictionChec
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
clockDrift = (long) (config.getDoubleElse(getConfigName() + ".drift", 1200.0) * 1e6);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
clockDrift = (long) (getConfig().getDoubleElse(getConfigName() + ".drift", 1200.0) * 1e6);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package ac.grim.grimac.checks.impl.movement;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PostPredictionCheck;
|
||||
@@ -34,7 +33,8 @@ public class NoSlowA extends Check implements PostPredictionCheck {
|
||||
}
|
||||
|
||||
if (bestOffset > offsetToFlag) {
|
||||
if (flaggedLastTick && flagWithSetback()) {
|
||||
if (flaggedLastTick) {
|
||||
flagWithSetback();
|
||||
alert("");
|
||||
}
|
||||
flaggedLastTick = true;
|
||||
@@ -51,7 +51,8 @@ public class NoSlowA extends Check implements PostPredictionCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
offsetToFlag = config.getDoubleElse("NoSlowA.threshold", 0.001);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
offsetToFlag = getConfig().getDoubleElse("NoSlowA.threshold", 0.001);
|
||||
}
|
||||
}
|
||||
@@ -35,4 +35,4 @@ public class NoSlowB extends Check implements PacketCheck {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,17 +2,32 @@ 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.PacketCheck;
|
||||
import ac.grim.grimac.checks.type.PostPredictionCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
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.wrapper.play.client.WrapperPlayClientEntityAction;
|
||||
|
||||
@CheckData(name = "NoSlowC", setback = 5, experimental = true)
|
||||
public class NoSlowC extends Check implements PostPredictionCheck {
|
||||
public class NoSlowC extends Check implements PostPredictionCheck, PacketCheck {
|
||||
public NoSlowC(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
public boolean startedSprintingBeforeSlowMovement = false;
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.ENTITY_ACTION) {
|
||||
if (new WrapperPlayClientEntityAction(event).getAction() == WrapperPlayClientEntityAction.Action.START_SPRINTING) {
|
||||
startedSprintingBeforeSlowMovement = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(final PredictionComplete predictionComplete) {
|
||||
if (!predictionComplete.isChecked()) return;
|
||||
@@ -21,7 +36,8 @@ public class NoSlowC extends Check implements PostPredictionCheck {
|
||||
ClientVersion client = player.getClientVersion();
|
||||
|
||||
// https://bugs.mojang.com/browse/MC-152728
|
||||
if (client.isNewerThanOrEquals(ClientVersion.V_1_14_2)) {
|
||||
if (startedSprintingBeforeSlowMovement && client.isNewerThanOrEquals(ClientVersion.V_1_14_2)) {
|
||||
reward();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,26 +2,42 @@ 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.PacketCheck;
|
||||
import ac.grim.grimac.checks.type.PostPredictionCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
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.wrapper.play.client.WrapperPlayClientEntityAction;
|
||||
|
||||
@CheckData(name = "NoSlowD", setback = 5, experimental = true)
|
||||
public class NoSlowD extends Check implements PostPredictionCheck {
|
||||
public class NoSlowD extends Check implements PostPredictionCheck, PacketCheck {
|
||||
public NoSlowD(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
public boolean startedSprintingBeforeUse = false;
|
||||
private boolean flaggedLastTick = false;
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.ENTITY_ACTION) {
|
||||
if (new WrapperPlayClientEntityAction(event).getAction() == WrapperPlayClientEntityAction.Action.START_SPRINTING) {
|
||||
startedSprintingBeforeUse = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(final PredictionComplete predictionComplete) {
|
||||
if (!predictionComplete.isChecked()) return;
|
||||
|
||||
if (player.packetStateData.isSlowedByUsingItem()) {
|
||||
// https://bugs.mojang.com/browse/MC-152728
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14_2)) {
|
||||
if (startedSprintingBeforeUse && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14_2)) {
|
||||
reward();
|
||||
flaggedLastTick = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ 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.PacketCheck;
|
||||
import ac.grim.grimac.checks.type.PostPredictionCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.update.PredictionComplete;
|
||||
@@ -12,7 +13,7 @@ import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEn
|
||||
import static com.github.retrooper.packetevents.protocol.potion.PotionTypes.BLINDNESS;
|
||||
|
||||
@CheckData(name = "NoSlowE", setback = 5, experimental = true)
|
||||
public class NoSlowE extends Check implements PostPredictionCheck {
|
||||
public class NoSlowE extends Check implements PostPredictionCheck, PacketCheck {
|
||||
public NoSlowE(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
|
||||
|
||||
public class SetbackBlocker extends Check implements PacketCheck {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package ac.grim.grimac.checks.impl.movement;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
@@ -20,9 +19,9 @@ public class TimerCheck extends Check implements PacketCheck {
|
||||
|
||||
// How long should the player be able to fall back behind their ping?
|
||||
// Default: 120 milliseconds
|
||||
long clockDrift;
|
||||
long clockDrift = (long) 120e6;
|
||||
|
||||
long limitAbuseOverPing;
|
||||
long limitAbuseOverPing = 1000;
|
||||
|
||||
boolean hasGottenMovementAfterTransaction = false;
|
||||
|
||||
@@ -116,8 +115,9 @@ public class TimerCheck extends Check implements PacketCheck {
|
||||
}
|
||||
|
||||
@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));
|
||||
public void reload() {
|
||||
super.reload();
|
||||
clockDrift = (long) (getConfig().getDoubleElse(getConfigName() + ".drift", 120.0) * 1e6);
|
||||
limitAbuseOverPing = (long) (getConfig().getDoubleElse(getConfigName() + ".ping-abuse-limit-threshold", 1000));
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPl
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityAnimation;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
@@ -43,7 +44,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) && !player.uncertaintyHandler.lastVehicleSwitch.hasOccurredSince(0)) {
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
for (String flag : flags) {
|
||||
flagAndAlert(flag);
|
||||
}
|
||||
@@ -86,7 +87,6 @@ public class PostCheck extends Check implements PacketCheck, PostPredictionCheck
|
||||
post.clear();
|
||||
sentFlying = false;
|
||||
} else if (PLAYER_ABILITIES.equals(packetType)
|
||||
|| (HELD_ITEM_CHANGE.equals(packetType) && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8))
|
||||
|| INTERACT_ENTITY.equals(packetType) || PLAYER_BLOCK_PLACEMENT.equals(packetType)
|
||||
|| USE_ITEM.equals(packetType) || PLAYER_DIGGING.equals(packetType)) {
|
||||
if (sentFlying) post.add(event.getPacketType());
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package ac.grim.grimac.checks.impl.prediction;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.api.events.CompletePredictionEvent;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
@@ -100,12 +99,14 @@ public class OffsetHandler extends Check implements PostPredictionCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
setbackDecayMultiplier = config.getDoubleElse("Simulation.setback-decay-multiplier", 0.999);
|
||||
threshold = config.getDoubleElse("Simulation.threshold", 0.001);
|
||||
immediateSetbackThreshold = config.getDoubleElse("Simulation.immediate-setback-threshold", 0.1);
|
||||
maxAdvantage = config.getDoubleElse("Simulation.max-advantage", 1);
|
||||
maxCeiling = config.getDoubleElse("Simulation.max-ceiling", 4);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
setbackDecayMultiplier = getConfig().getDoubleElse("Simulation.setback-decay-multiplier", 0.999);
|
||||
threshold = getConfig().getDoubleElse("Simulation.threshold", 0.001);
|
||||
immediateSetbackThreshold = getConfig().getDoubleElse("Simulation.immediate-setback-threshold", 0.1);
|
||||
maxAdvantage = getConfig().getDoubleElse("Simulation.max-advantage", 1);
|
||||
maxCeiling = getConfig().getDoubleElse("Simulation.max-ceiling", 4);
|
||||
|
||||
if (maxAdvantage == -1) maxAdvantage = Double.MAX_VALUE;
|
||||
if (immediateSetbackThreshold == -1) immediateSetbackThreshold = Double.MAX_VALUE;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package ac.grim.grimac.checks.impl.scaffolding;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.BlockPlaceCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
@@ -30,7 +29,8 @@ public class AirLiquidPlace extends BlockPlaceCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
this.cancelVL = config.getIntElse(getConfigName() + ".cancelVL", 0);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
this.cancelVL = getConfig().getIntElse(getConfigName() + ".cancelVL", 0);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@ import ac.grim.grimac.utils.anticheat.update.BlockPlace;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.math.VectorUtils;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import org.bukkit.util.Vector;
|
||||
@@ -24,8 +26,7 @@ public class FarPlace extends BlockPlaceCheck {
|
||||
if (place.getMaterial() == StateTypes.SCAFFOLDING) return;
|
||||
|
||||
double min = Double.MAX_VALUE;
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
for (double d : possibleEyeHeights) {
|
||||
for (double d : player.getPossibleEyeHeights()) {
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(blockPos);
|
||||
Vector eyes = new Vector(player.x, player.y + d, player.z);
|
||||
Vector best = VectorUtils.cutBoxToVector(eyes, box);
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
package ac.grim.grimac.checks.impl.scaffolding;
|
||||
|
||||
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.MessageUtil;
|
||||
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.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;
|
||||
|
||||
@CheckData(name = "MultiPlace", experimental = true)
|
||||
public class MultiPlace extends BlockPlaceCheck {
|
||||
public MultiPlace(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
private final List<String> flags = new ArrayList<>();
|
||||
|
||||
private boolean hasPlaced;
|
||||
private BlockFace lastFace;
|
||||
private Vector3f lastCursor;
|
||||
private Vector3i lastPos;
|
||||
|
||||
@Override
|
||||
public void onBlockPlace(final BlockPlace place) {
|
||||
final BlockFace face = place.getDirection();
|
||||
final Vector3f cursor = place.getCursor();
|
||||
final Vector3i pos = place.getPlacedAgainstBlockLocation();
|
||||
|
||||
if (hasPlaced && (face != lastFace || !cursor.equals(lastCursor) || !pos.equals(lastPos))) {
|
||||
final String verbose = "face=" + face + ", lastFace=" + lastFace
|
||||
+ ", cursor=" + MessageUtil.toUnlabledString(cursor) + ", lastCursor=" + MessageUtil.toUnlabledString(lastCursor)
|
||||
+ ", pos=" + MessageUtil.toUnlabledString(pos) + ", lastPos=" + MessageUtil.toUnlabledString(lastPos);
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) {
|
||||
if (flagAndAlert(verbose) && shouldModifyPackets() && shouldCancel()) {
|
||||
place.resync();
|
||||
}
|
||||
} else {
|
||||
flags.add(verbose);
|
||||
}
|
||||
}
|
||||
|
||||
lastFace = face;
|
||||
lastCursor = cursor;
|
||||
lastPos = pos;
|
||||
hasPlaced = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType()) && !player.packetStateData.lastPacketWasTeleport && !player.packetStateData.lastPacketWasOnePointSeventeenDuplicate) {
|
||||
hasPlaced = 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();
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@CheckData(name = "PositionPlace")
|
||||
public class PositionPlace extends BlockPlaceCheck {
|
||||
@@ -27,13 +28,8 @@ public class PositionPlace extends BlockPlaceCheck {
|
||||
// Each position represents the best case scenario to have clicked
|
||||
//
|
||||
// We will now calculate the most optimal position for the player's head to be in
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
double minEyeHeight = Double.MAX_VALUE;
|
||||
double maxEyeHeight = Double.MIN_VALUE;
|
||||
for (double height : possibleEyeHeights) {
|
||||
minEyeHeight = Math.min(minEyeHeight, height);
|
||||
maxEyeHeight = Math.max(maxEyeHeight, height);
|
||||
}
|
||||
double minEyeHeight = Collections.min(player.getPossibleEyeHeights());
|
||||
double maxEyeHeight = Collections.max(player.getPossibleEyeHeights());
|
||||
// I love the idle packet, why did you remove it mojang :(
|
||||
// Don't give 0.03 lenience if the player is a 1.8 player and we know they couldn't have 0.03'd because idle packet
|
||||
double movementThreshold = !player.packetStateData.didLastMovementIncludePosition || player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? player.getMovementThreshold() : 0;
|
||||
@@ -48,21 +44,27 @@ public class PositionPlace extends BlockPlaceCheck {
|
||||
|
||||
// So now we have the player's possible eye positions
|
||||
// So then look at the face that the player has clicked
|
||||
boolean flag = switch (place.getDirection()) {
|
||||
case NORTH -> // Z- face
|
||||
eyePositions.minZ > combined.minZ;
|
||||
case SOUTH -> // Z+ face
|
||||
eyePositions.maxZ < combined.maxZ;
|
||||
case EAST -> // X+ face
|
||||
eyePositions.maxX < combined.maxX;
|
||||
case WEST -> // X- face
|
||||
eyePositions.minX > combined.minX;
|
||||
case UP -> // Y+ face
|
||||
eyePositions.maxY < combined.maxY;
|
||||
case DOWN -> // Y- face
|
||||
eyePositions.minY > combined.minY;
|
||||
default -> false;
|
||||
};
|
||||
boolean flag = false;
|
||||
switch (place.getDirection()) {
|
||||
case NORTH: // Z- face
|
||||
flag = eyePositions.minZ > combined.minZ;
|
||||
break;
|
||||
case SOUTH: // Z+ face
|
||||
flag = eyePositions.maxZ < combined.maxZ;
|
||||
break;
|
||||
case EAST: // X+ face
|
||||
flag = eyePositions.maxX < combined.maxX;
|
||||
break;
|
||||
case WEST: // X- face
|
||||
flag = eyePositions.minX > combined.minX;
|
||||
break;
|
||||
case UP: // Y+ face
|
||||
flag = eyePositions.maxY < combined.maxY;
|
||||
break;
|
||||
case DOWN: // Y- face
|
||||
flag = eyePositions.minY > combined.minY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
if (flagAndAlert() && shouldModifyPackets() && shouldCancel()) {
|
||||
|
||||
@@ -71,19 +71,13 @@ public class RotationPlace extends BlockPlaceCheck {
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(place.getPlacedAgainstBlockLocation());
|
||||
|
||||
List<Vector3f> possibleLookDirs = new ArrayList<>(Arrays.asList(
|
||||
new Vector3f(player.xRot, player.yRot, 0),
|
||||
new Vector3f(player.lastXRot, player.yRot, 0)
|
||||
new Vector3f(player.lastXRot, player.yRot, 0),
|
||||
new Vector3f(player.xRot, player.yRot, 0)
|
||||
));
|
||||
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
|
||||
// Start checking if player is in the block
|
||||
double minEyeHeight = Double.MAX_VALUE;
|
||||
double maxEyeHeight = Double.MIN_VALUE;
|
||||
for (double height : possibleEyeHeights) {
|
||||
minEyeHeight = Math.min(minEyeHeight, height);
|
||||
maxEyeHeight = Math.max(maxEyeHeight, height);
|
||||
}
|
||||
double minEyeHeight = Collections.min(player.getPossibleEyeHeights());
|
||||
double maxEyeHeight = Collections.max(player.getPossibleEyeHeights());
|
||||
|
||||
SimpleCollisionBox eyePositions = new SimpleCollisionBox(player.x, player.y + minEyeHeight, player.z, player.x, player.y + maxEyeHeight, player.z);
|
||||
eyePositions.expand(player.getMovementThreshold());
|
||||
@@ -105,7 +99,7 @@ public class RotationPlace extends BlockPlaceCheck {
|
||||
}
|
||||
|
||||
final double distance = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE);
|
||||
for (double d : possibleEyeHeights) {
|
||||
for (double d : player.getPossibleEyeHeights()) {
|
||||
for (Vector3f lookDir : possibleLookDirs) {
|
||||
// x, y, z are correct for the block placement even after post tick because of code elsewhere
|
||||
Vector3d starting = new Vector3d(player.x, player.y + d, player.z);
|
||||
@@ -113,7 +107,7 @@ public class RotationPlace extends BlockPlaceCheck {
|
||||
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));
|
||||
|
||||
if (intercept.first() != null) return true;
|
||||
if (intercept.getFirst() != null) return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package ac.grim.grimac.checks.impl.velocity;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PostPredictionCheck;
|
||||
@@ -19,6 +18,7 @@ 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.Bukkit;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -256,10 +256,12 @@ public class ExplosionHandler extends Check implements PostPredictionCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
offsetToFlag = config.getDoubleElse("Explosion.threshold", 0.00001);
|
||||
setbackVL = config.getDoubleElse("Explosion.setbackvl", 10);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
|
||||
offsetToFlag = getConfig().getDoubleElse("Explosion.threshold", 0.00001);
|
||||
setbackVL = getConfig().getDoubleElse("Explosion.setbackvl", 10);
|
||||
|
||||
if (setbackVL == -1) setbackVL = Double.MAX_VALUE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package ac.grim.grimac.checks.impl.velocity;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PostPredictionCheck;
|
||||
@@ -241,14 +240,15 @@ public class KnockbackHandler extends Check implements PostPredictionCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
offsetToFlag = config.getDoubleElse("Knockback.threshold", 0.001);
|
||||
maxAdv = config.getDoubleElse("Knockback.max-advantage", 1);
|
||||
immediate = config.getDoubleElse("Knockback.immediate-setback-threshold", 0.1);
|
||||
multiplier = config.getDoubleElse("Knockback.setback-decay-multiplier", 0.999);
|
||||
ceiling = config.getDoubleElse("Knockback.max-ceiling", 4);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
offsetToFlag = getConfig().getDoubleElse("Knockback.threshold", 0.001);
|
||||
maxAdv = getConfig().getDoubleElse("Knockback.max-advantage", 1);
|
||||
immediate = getConfig().getDoubleElse("Knockback.immediate-setback-threshold", 0.1);
|
||||
multiplier = getConfig().getDoubleElse("Knockback.setback-decay-multiplier", 0.999);
|
||||
ceiling = getConfig().getDoubleElse("Knockback.max-ceiling", 4);
|
||||
|
||||
if (maxAdv < 0) maxAdv = Double.MAX_VALUE;
|
||||
if (immediate < 0) immediate = Double.MAX_VALUE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +1,10 @@
|
||||
package ac.grim.grimac.checks.type;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
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;
|
||||
@@ -16,10 +14,9 @@ import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BlockPlaceCheck extends Check implements RotationCheck, PostPredictionCheck {
|
||||
public class BlockPlaceCheck extends Check implements RotationCheck {
|
||||
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;
|
||||
|
||||
@@ -36,8 +33,9 @@ public class BlockPlaceCheck extends Check implements RotationCheck, PostPredict
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
this.cancelVL = config.getIntElse(getConfigName() + ".cancelVL", 5);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
this.cancelVL = getConfig().getIntElse(getConfigName() + ".cancelVL", 5);
|
||||
}
|
||||
|
||||
protected boolean shouldCancel() {
|
||||
@@ -71,11 +69,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());
|
||||
|
||||
int size = placedOn.downCast(boxes);
|
||||
List<SimpleCollisionBox> boxes = new ArrayList<>();
|
||||
placedOn.downCast(boxes);
|
||||
|
||||
SimpleCollisionBox combined = new SimpleCollisionBox(clicked.getX(), clicked.getY(), clicked.getZ());
|
||||
for (int i = 0; i < size; i++) {
|
||||
SimpleCollisionBox box = boxes[i];
|
||||
for (SimpleCollisionBox box : boxes) {
|
||||
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,6 +1,8 @@
|
||||
package ac.grim.grimac.checks.type;
|
||||
|
||||
import ac.grim.grimac.api.AbstractCheck;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.update.RotationUpdate;
|
||||
|
||||
public interface RotationCheck extends AbstractCheck {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package ac.grim.grimac.checks.type;
|
||||
|
||||
import ac.grim.grimac.api.AbstractCheck;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.update.VehiclePositionUpdate;
|
||||
|
||||
public interface VehicleCheck extends AbstractCheck {
|
||||
|
||||
@@ -70,4 +70,4 @@ public class GrimDebug extends BaseCommand {
|
||||
|
||||
sender.sendMessage("Console output for " + (grimPlayer.bukkitPlayer == null ? grimPlayer.user.getProfile().getName() : grimPlayer.bukkitPlayer.getName()) + " is now " + isOutput);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
package ac.grim.grimac.commands;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.checks.impl.aim.processor.AimProcessor;
|
||||
import ac.grim.grimac.checks.impl.misc.ClientBrand;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
import ac.grim.grimac.utils.anticheat.MultiLibUtil;
|
||||
import ac.grim.grimac.utils.math.GrimMath;
|
||||
import co.aikar.commands.BaseCommand;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package ac.grim.grimac.commands;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
import co.aikar.commands.BaseCommand;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import com.github.retrooper.packetevents.netty.channel.ChannelHelper;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
@CommandAlias("grim|grimac")
|
||||
@@ -14,15 +18,14 @@ public class GrimReload extends BaseCommand {
|
||||
@CommandPermission("grim.reload")
|
||||
public void onReload(CommandSender sender) {
|
||||
//reload config
|
||||
sender.sendMessage(MessageUtil.format("%prefix% &7Reloading config..."));
|
||||
GrimAPI.INSTANCE.getExternalAPI().reloadAsync().exceptionally(throwable -> false)
|
||||
.thenAccept(bool -> {
|
||||
if (bool) {
|
||||
sender.sendMessage(MessageUtil.format("%prefix% &fConfig has been reloaded."));
|
||||
} else {
|
||||
sender.sendMessage(MessageUtil.format("%prefix% &cFailed to reload config."));
|
||||
}
|
||||
});
|
||||
try {
|
||||
GrimAPI.INSTANCE.getExternalAPI().reload();
|
||||
} catch (RuntimeException e) {
|
||||
sender.sendMessage(ChatColor.RED + e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
sender.sendMessage(MessageUtil.format("%prefix% &fConfig has been reloaded."));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,7 +20,7 @@ public class GrimSendAlert extends BaseCommand {
|
||||
bukkitPlayer.sendMessage(string);
|
||||
}
|
||||
|
||||
if (GrimAPI.INSTANCE.getConfigManager().isPrintAlertsToConsole()) {
|
||||
if (GrimAPI.INSTANCE.getConfigManager().getConfig().getBooleanElse("alerts.print-to-console", true)) {
|
||||
LogUtil.console(string); // Print alert to console
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,8 @@ public class GrimSpectate extends BaseCommand {
|
||||
@CommandPermission("grim.spectate")
|
||||
@CommandCompletion("@players")
|
||||
public void onSpectate(CommandSender sender, @Optional OnlinePlayer target) {
|
||||
if (!(sender instanceof Player player)) return;
|
||||
if (!(sender instanceof Player)) return;
|
||||
Player player = (Player) sender;
|
||||
|
||||
if (target != null && target.getPlayer().getUniqueId().equals(player.getUniqueId())) {
|
||||
String message = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("cannot-run-on-self", "%prefix% &cYou cannot use this command on yourself!");
|
||||
|
||||
@@ -17,7 +17,8 @@ public class GrimStopSpectating extends BaseCommand {
|
||||
@CommandCompletion("here")
|
||||
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");
|
||||
GrimAPI.INSTANCE.getSpectateManager().disable(player, teleportBack);
|
||||
@@ -27,3 +28,4 @@ public class GrimStopSpectating extends BaseCommand {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.*;
|
||||
import ac.grim.grimac.utils.inventory.Inventory;
|
||||
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 com.github.retrooper.packetevents.PacketEvents;
|
||||
@@ -47,12 +46,9 @@ 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;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class CheckManagerListener extends PacketListenerAbstract {
|
||||
|
||||
@@ -60,79 +56,8 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
super(PacketListenerPriority.LOW);
|
||||
}
|
||||
|
||||
// Copied from MCP...
|
||||
// Returns null if there isn't anything.
|
||||
//
|
||||
// I do have to admit that I'm starting to like bifunctions/new java 8 things more than I originally did.
|
||||
// although I still don't understand Mojang's obsession with streams in some of the hottest methods... that kills performance
|
||||
public static HitData traverseBlocks(GrimPlayer player, Vector3d start, Vector3d end, BiFunction<WrappedBlockState, Vector3i, HitData> predicate) {
|
||||
// I guess go back by the collision epsilon?
|
||||
double endX = GrimMath.lerp(-1.0E-7D, end.x, start.x);
|
||||
double endY = GrimMath.lerp(-1.0E-7D, end.y, start.y);
|
||||
double endZ = GrimMath.lerp(-1.0E-7D, end.z, start.z);
|
||||
double startX = GrimMath.lerp(-1.0E-7D, start.x, end.x);
|
||||
double startY = GrimMath.lerp(-1.0E-7D, start.y, end.y);
|
||||
double startZ = GrimMath.lerp(-1.0E-7D, start.z, end.z);
|
||||
int floorStartX = GrimMath.floor(startX);
|
||||
int floorStartY = GrimMath.floor(startY);
|
||||
int floorStartZ = GrimMath.floor(startZ);
|
||||
|
||||
|
||||
if (start.equals(end)) return null;
|
||||
|
||||
WrappedBlockState state = player.compensatedWorld.getWrappedBlockStateAt(floorStartX, floorStartY, floorStartZ);
|
||||
HitData apply = predicate.apply(state, new Vector3i(floorStartX, floorStartY, floorStartZ));
|
||||
|
||||
if (apply != null) {
|
||||
return apply;
|
||||
}
|
||||
|
||||
double xDiff = endX - startX;
|
||||
double yDiff = endY - startY;
|
||||
double zDiff = endZ - startZ;
|
||||
double xSign = Math.signum(xDiff);
|
||||
double ySign = Math.signum(yDiff);
|
||||
double zSign = Math.signum(zDiff);
|
||||
|
||||
double posXInverse = xSign == 0 ? Double.MAX_VALUE : xSign / xDiff;
|
||||
double posYInverse = ySign == 0 ? Double.MAX_VALUE : ySign / yDiff;
|
||||
double posZInverse = zSign == 0 ? Double.MAX_VALUE : zSign / zDiff;
|
||||
|
||||
double d12 = posXInverse * (xSign > 0 ? 1.0D - GrimMath.frac(startX) : GrimMath.frac(startX));
|
||||
double d13 = posYInverse * (ySign > 0 ? 1.0D - GrimMath.frac(startY) : GrimMath.frac(startY));
|
||||
double d14 = posZInverse * (zSign > 0 ? 1.0D - GrimMath.frac(startZ) : GrimMath.frac(startZ));
|
||||
|
||||
// Can't figure out what this code does currently
|
||||
while (d12 <= 1.0D || d13 <= 1.0D || d14 <= 1.0D) {
|
||||
if (d12 < d13) {
|
||||
if (d12 < d14) {
|
||||
floorStartX += xSign;
|
||||
d12 += posXInverse;
|
||||
} else {
|
||||
floorStartZ += zSign;
|
||||
d14 += posZInverse;
|
||||
}
|
||||
} else if (d13 < d14) {
|
||||
floorStartY += ySign;
|
||||
d13 += posYInverse;
|
||||
} else {
|
||||
floorStartZ += zSign;
|
||||
d14 += posZInverse;
|
||||
}
|
||||
|
||||
state = player.compensatedWorld.getWrappedBlockStateAt(floorStartX, floorStartY, floorStartZ);
|
||||
apply = predicate.apply(state, new Vector3i(floorStartX, floorStartY, floorStartZ));
|
||||
|
||||
if (apply != null) {
|
||||
return apply;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void placeWaterLavaSnowBucket(GrimPlayer player, ItemStack held, StateType toPlace, InteractionHand hand) {
|
||||
HitData data = getNearestHitResult(player, StateTypes.AIR, false);
|
||||
HitData data = BlockRayTrace.getNearestHitResult(player, StateTypes.AIR, false);
|
||||
if (data != null) {
|
||||
BlockPlace blockPlace = new BlockPlace(player, hand, data.getPosition(), data.getClosestDirection().getFaceValue(), data.getClosestDirection(), held, data);
|
||||
|
||||
@@ -225,10 +150,11 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
}
|
||||
}
|
||||
|
||||
private static void handleBlockPlaceOrUseItem(PacketWrapper<?> packet, GrimPlayer player) {
|
||||
private static void handleBlockPlaceOrUseItem(PacketWrapper packet, GrimPlayer player) {
|
||||
// Legacy "use item" packet
|
||||
if (packet instanceof WrapperPlayClientPlayerBlockPlacement place &&
|
||||
if (packet instanceof WrapperPlayClientPlayerBlockPlacement &&
|
||||
PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_9)) {
|
||||
WrapperPlayClientPlayerBlockPlacement place = (WrapperPlayClientPlayerBlockPlacement) packet;
|
||||
|
||||
if (player.gamemode == GameMode.SPECTATOR || player.gamemode == GameMode.ADVENTURE) return;
|
||||
|
||||
@@ -243,7 +169,9 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
}
|
||||
}
|
||||
|
||||
if (packet instanceof WrapperPlayClientUseItem place) {
|
||||
if (packet instanceof WrapperPlayClientUseItem) {
|
||||
WrapperPlayClientUseItem place = (WrapperPlayClientUseItem) packet;
|
||||
|
||||
if (player.gamemode == GameMode.SPECTATOR || player.gamemode == GameMode.ADVENTURE) return;
|
||||
|
||||
ItemStack placedWith = player.getInventory().getHeldItem();
|
||||
@@ -255,7 +183,9 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
}
|
||||
|
||||
// Check for interactable first (door, etc)
|
||||
if (packet instanceof WrapperPlayClientPlayerBlockPlacement place) {
|
||||
if (packet instanceof WrapperPlayClientPlayerBlockPlacement) {
|
||||
WrapperPlayClientPlayerBlockPlacement place = (WrapperPlayClientPlayerBlockPlacement) packet;
|
||||
|
||||
ItemStack placedWith = player.getInventory().getHeldItem();
|
||||
ItemStack offhand = player.getInventory().getOffHand();
|
||||
|
||||
@@ -264,7 +194,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
// The offhand is unable to interact with blocks like this... try to stop some desync points before they happen
|
||||
if ((!player.isSneaking || onlyAir) && place.getHand() == InteractionHand.MAIN_HAND) {
|
||||
Vector3i blockPosition = place.getBlockPosition();
|
||||
BlockPlace blockPlace = new BlockPlace(player, place.getHand(), blockPosition, place.getFaceId(), place.getFace(), placedWith, getNearestHitResult(player, null, true));
|
||||
BlockPlace blockPlace = new BlockPlace(player, place.getHand(), blockPosition, place.getFaceId(), place.getFace(), placedWith, BlockRayTrace.getNearestHitResult(player, null, true));
|
||||
|
||||
// Right-clicking a trapdoor/door/etc.
|
||||
StateType placedAgainst = blockPlace.getPlacedAgainstMaterial();
|
||||
@@ -291,7 +221,8 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
}
|
||||
}
|
||||
|
||||
if (packet instanceof WrapperPlayClientPlayerBlockPlacement place) {
|
||||
if (packet instanceof WrapperPlayClientPlayerBlockPlacement) {
|
||||
WrapperPlayClientPlayerBlockPlacement place = (WrapperPlayClientPlayerBlockPlacement) packet;
|
||||
Vector3i blockPosition = place.getBlockPosition();
|
||||
BlockFace face = place.getFace();
|
||||
|
||||
@@ -303,7 +234,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
placedWith = player.getInventory().getOffHand();
|
||||
}
|
||||
|
||||
BlockPlace blockPlace = new BlockPlace(player, place.getHand(), blockPosition, place.getFaceId(), face, placedWith, getNearestHitResult(player, null, true));
|
||||
BlockPlace blockPlace = new BlockPlace(player, place.getHand(), blockPosition, place.getFaceId(), face, placedWith, BlockRayTrace.getNearestHitResult(player, null, true));
|
||||
// At this point, it is too late to cancel, so we can only flag, and cancel subsequent block places more aggressively
|
||||
if (!player.compensatedEntities.getSelf().inVehicle()) {
|
||||
player.checkManager.onPostFlyingBlockPlace(blockPlace);
|
||||
@@ -343,7 +274,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
// Additionally, only yaw/pitch matters: https://github.com/GrimAnticheat/Grim/issues/1275#issuecomment-1872444018
|
||||
// 1.9+ isn't impacted by this packet as much.
|
||||
if (PacketEvents.getAPI().getServerManager().getVersion().isOlderThanOrEquals(ServerVersion.V_1_9)) {
|
||||
if (player.isCancelDuplicatePacket()) {
|
||||
if (GrimAPI.INSTANCE.getConfigManager().getConfig().getBooleanElse("cancel-duplicate-packet", true)) {
|
||||
player.packetStateData.cancelDuplicatePacket = true;
|
||||
}
|
||||
} else {
|
||||
@@ -353,7 +284,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
|
||||
player.packetStateData.lastPacketWasOnePointSeventeenDuplicate = true;
|
||||
|
||||
if (!player.isIgnoreDuplicatePacketRotation()) {
|
||||
if (!GrimAPI.INSTANCE.getConfigManager().isIgnoreDuplicatePacketRotation()) {
|
||||
if (player.xRot != location.getYaw() || player.yRot != location.getPitch()) {
|
||||
player.lastXRot = player.xRot;
|
||||
player.lastYRot = player.yRot;
|
||||
@@ -370,11 +301,6 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getConnectionState() != ConnectionState.PLAY) return;
|
||||
@@ -428,7 +354,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) {
|
||||
WrapperPlayClientPlayerFlying flying = new WrapperPlayClientPlayerFlying(event);
|
||||
Location pos = flying.getLocation();
|
||||
boolean ignoreRotation = player.packetStateData.lastPacketWasOnePointSeventeenDuplicate && player.isIgnoreDuplicatePacketRotation();
|
||||
boolean ignoreRotation = player.packetStateData.lastPacketWasOnePointSeventeenDuplicate && GrimAPI.INSTANCE.getConfigManager().isIgnoreDuplicatePacketRotation();
|
||||
handleFlying(player, pos.getX(), pos.getY(), pos.getZ(), ignoreRotation ? player.xRot : pos.getYaw(), ignoreRotation ? player.yRot : pos.getPitch(), flying.hasPositionChanged(), flying.hasRotationChanged(), flying.isOnGround(), teleportData, event);
|
||||
}
|
||||
|
||||
@@ -456,24 +382,22 @@ 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();
|
||||
WrappedBlockState block = player.compensatedWorld.getWrappedBlockStateAt(dig.getBlockPosition());
|
||||
|
||||
player.checkManager.getPacketCheck(BadPacketsX.class).handle(event, dig, type);
|
||||
player.checkManager.getPacketCheck(BadPacketsX.class).handle(event, dig, block.getType());
|
||||
player.checkManager.getPacketCheck(BadPacketsZ.class).handle(event, dig);
|
||||
|
||||
if (dig.getAction() == DiggingAction.FINISHED_DIGGING) {
|
||||
// Not unbreakable
|
||||
if (BREAKABLE.apply(type) && !event.isCancelled()) {
|
||||
if (!block.getType().isAir() && block.getType().getHardness() != -1.0f && !event.isCancelled()) {
|
||||
player.compensatedWorld.startPredicting();
|
||||
player.compensatedWorld.updateBlock(digPosition.getX(), digPosition.getY(), digPosition.getZ(), 0);
|
||||
player.compensatedWorld.updateBlock(dig.getBlockPosition().getX(), dig.getBlockPosition().getY(), dig.getBlockPosition().getZ(), 0);
|
||||
player.compensatedWorld.stopPredicting(dig);
|
||||
}
|
||||
}
|
||||
|
||||
if (dig.getAction() == DiggingAction.START_DIGGING && !event.isCancelled()) {
|
||||
double damage = BlockBreakSpeed.getBlockDamage(player, digPosition);
|
||||
double damage = BlockBreakSpeed.getBlockDamage(player, dig.getBlockPosition());
|
||||
|
||||
//Instant breaking, no damage means it is unbreakable by creative players (with swords)
|
||||
if (damage >= 1) {
|
||||
@@ -481,9 +405,9 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
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));
|
||||
player.compensatedWorld.updateBlock(dig.getBlockPosition(), StateTypes.WATER.createBlockState(CompensatedWorld.blockVersion));
|
||||
} else {
|
||||
player.compensatedWorld.updateBlock(digPosition.getX(), digPosition.getY(), digPosition.getZ(), 0);
|
||||
player.compensatedWorld.updateBlock(dig.getBlockPosition().getX(), dig.getBlockPosition().getY(), dig.getBlockPosition().getZ(), 0);
|
||||
}
|
||||
player.compensatedWorld.stopPredicting(dig);
|
||||
}
|
||||
@@ -510,7 +434,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
player.placeUseItemPackets.add(new BlockPlaceSnapshot(packet, player.isSneaking));
|
||||
} else {
|
||||
// Anti-air place
|
||||
BlockPlace blockPlace = new BlockPlace(player, packet.getHand(), packet.getBlockPosition(), packet.getFaceId(), packet.getFace(), placedWith, getNearestHitResult(player, null, true));
|
||||
BlockPlace blockPlace = new BlockPlace(player, packet.getHand(), packet.getBlockPosition(), packet.getFaceId(), packet.getFace(), placedWith, BlockRayTrace.getNearestHitResult(player, null, true));
|
||||
blockPlace.setCursor(packet.getCursorPosition());
|
||||
|
||||
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_11) && player.getClientVersion().isOlderThan(ClientVersion.V_1_11)) {
|
||||
@@ -584,7 +508,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
}
|
||||
|
||||
private static void placeBucket(GrimPlayer player, InteractionHand hand) {
|
||||
HitData data = getNearestHitResult(player, null, true);
|
||||
HitData data = BlockRayTrace.getNearestHitResult(player, null, true);
|
||||
|
||||
if (data != null) {
|
||||
BlockPlace blockPlace = new BlockPlace(player, hand, data.getPosition(), data.getClosestDirection().getFaceValue(), data.getClosestDirection(), ItemStack.EMPTY, data);
|
||||
@@ -750,7 +674,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
}
|
||||
|
||||
private static void placeLilypad(GrimPlayer player, InteractionHand hand) {
|
||||
HitData data = getNearestHitResult(player, null, true);
|
||||
HitData data = BlockRayTrace.getNearestHitResult(player, null, true);
|
||||
|
||||
if (data != null) {
|
||||
// A lilypad cannot replace a fluid
|
||||
@@ -780,56 +704,6 @@ 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());
|
||||
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 endPos = new Vector3d(endVec.getX(), endVec.getY(), endVec.getZ());
|
||||
|
||||
return traverseBlocks(player, startingPos, endPos, (block, vector3i) -> {
|
||||
CollisionBox data = HitboxData.getBlockHitbox(player, heldItem, player.getClientVersion(), block, vector3i.getX(), vector3i.getY(), vector3i.getZ());
|
||||
List<SimpleCollisionBox> boxes = new ArrayList<>();
|
||||
data.downCast(boxes);
|
||||
|
||||
double bestHitResult = Double.MAX_VALUE;
|
||||
Vector bestHitLoc = null;
|
||||
BlockFace bestFace = null;
|
||||
|
||||
for (SimpleCollisionBox box : boxes) {
|
||||
Pair<Vector, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
if (intercept.first() == null) continue; // No intercept
|
||||
|
||||
Vector hitLoc = intercept.first();
|
||||
|
||||
if (hitLoc.distanceSquared(startingVec) < bestHitResult) {
|
||||
bestHitResult = hitLoc.distanceSquared(startingVec);
|
||||
bestHitLoc = hitLoc;
|
||||
bestFace = intercept.second();
|
||||
}
|
||||
}
|
||||
if (bestHitLoc != null) {
|
||||
return new HitData(vector3i, bestHitLoc, bestFace, block);
|
||||
}
|
||||
|
||||
if (sourcesHaveHitbox &&
|
||||
(player.compensatedWorld.isWaterSourceBlock(vector3i.getX(), vector3i.getY(), vector3i.getZ())
|
||||
|| player.compensatedWorld.getLavaFluidLevelAt(vector3i.getX(), vector3i.getY(), vector3i.getZ()) == (8 / 9f))) {
|
||||
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));
|
||||
|
||||
if (intercept.first() != null) {
|
||||
return new HitData(vector3i, intercept.first(), intercept.second(), block);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(PacketSendEvent event) {
|
||||
if (event.getConnectionState() != ConnectionState.PLAY) return;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package ac.grim.grimac.events.packets;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.checks.impl.movement.NoSlowC;
|
||||
import ac.grim.grimac.checks.impl.movement.NoSlowD;
|
||||
import ac.grim.grimac.checks.impl.movement.NoSlowE;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import com.github.retrooper.packetevents.event.PacketListenerPriority;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package ac.grim.grimac.events.packets;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
@@ -53,6 +53,7 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
private final List<Integer> despawnedEntitiesThisTransaction = new ArrayList<>();
|
||||
|
||||
// Maximum ping when a firework boost is removed from the player.
|
||||
private final int maxFireworkBoostPing = GrimAPI.INSTANCE.getConfigManager().getConfig().getIntElse("max-ping-firework-boost", 1000);
|
||||
|
||||
public PacketEntityReplication(GrimPlayer player) {
|
||||
super(player);
|
||||
@@ -227,8 +228,9 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
|
||||
if (status.getStatus() == 31) {
|
||||
PacketEntity hook = player.compensatedEntities.getEntity(status.getEntityId());
|
||||
if (!(hook instanceof PacketEntityHook hookEntity)) return;
|
||||
if (!(hook instanceof PacketEntityHook)) return;
|
||||
|
||||
PacketEntityHook hookEntity = (PacketEntityHook) hook;
|
||||
if (hookEntity.attached == player.entityID) {
|
||||
player.sendTransaction();
|
||||
// We don't transaction sandwich this, it's too rare to be a real problem.
|
||||
@@ -453,7 +455,8 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
player.latencyUtils.addRealTimeTask(lastTrans, () -> {
|
||||
PacketEntity entity = player.compensatedEntities.getEntity(entityId);
|
||||
if (entity == null) return;
|
||||
if (entity instanceof PacketEntityTrackXRot xRotEntity && yaw != null) {
|
||||
if (entity instanceof PacketEntityTrackXRot && yaw != null) {
|
||||
PacketEntityTrackXRot xRotEntity = (PacketEntityTrackXRot) entity;
|
||||
xRotEntity.packetYaw = yaw;
|
||||
xRotEntity.steps = entity.isBoat() ? 10 : 3;
|
||||
}
|
||||
@@ -497,12 +500,4 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
public void tickStartTick() {
|
||||
hasSentPreWavePacket = false;
|
||||
}
|
||||
|
||||
private int maxFireworkBoostPing = 1000;
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
maxFireworkBoostPing = config.getIntElse("max-ping-firework-boost", 1000);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package ac.grim.grimac.events.packets;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
@@ -37,6 +37,7 @@ public class PacketPlayerAbilities extends Check implements PacketCheck {
|
||||
|
||||
if (lastSentPlayerCanFly && !abilities.isFlightAllowed()) {
|
||||
int noFlying = player.lastTransactionSent.get();
|
||||
int maxFlyingPing = GrimAPI.INSTANCE.getConfigManager().getConfig().getIntElse("max-ping-out-of-flying", 1000);
|
||||
if (maxFlyingPing != -1) {
|
||||
player.runNettyTaskInMs(() -> {
|
||||
if (player.lastTransactionReceived.get() < noFlying) {
|
||||
@@ -55,12 +56,4 @@ public class PacketPlayerAbilities extends Check implements PacketCheck {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int maxFlyingPing = 1000;
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
maxFlyingPing = config.getIntElse("max-ping-out-of-flying", 1000);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,8 +8,6 @@ import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import com.github.retrooper.packetevents.event.PacketListenerPriority;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.protocol.item.enchantment.type.EnchantmentTypes;
|
||||
@@ -74,13 +72,6 @@ public class PacketPlayerAttack extends PacketListenerAbstract {
|
||||
player.maxPlayerAttackSlow = 1;
|
||||
}
|
||||
} else if (!isLegacyPlayer && player.isSprinting) {
|
||||
// 1.9+ players who have attack speed cannot slow themselves twice in one tick because their attack cooldown gets reset on swing.
|
||||
if (player.maxPlayerAttackSlow > 0
|
||||
&& PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9)
|
||||
&& player.compensatedEntities.getSelf().getAttributeValue(Attributes.GENERIC_ATTACK_SPEED) < 16) { // 16 is a reasonable limit
|
||||
return;
|
||||
}
|
||||
|
||||
// 1.9+ player who might have been slowed, but we can't be sure
|
||||
player.maxPlayerAttackSlow += 1;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package ac.grim.grimac.events.packets;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.checks.impl.movement.NoSlowA;
|
||||
import ac.grim.grimac.checks.impl.movement.NoSlowD;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
@@ -22,6 +23,7 @@ import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import com.github.retrooper.packetevents.protocol.player.InteractionHand;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.*;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class PacketPlayerDigging extends PacketListenerAbstract {
|
||||
|
||||
@@ -170,12 +172,10 @@ public class PacketPlayerDigging extends PacketListenerAbstract {
|
||||
|
||||
if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) {
|
||||
final GrimPlayer player = GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(event.getUser());
|
||||
if (player != null && player.packetStateData.isSlowedByUsingItem()
|
||||
&& !player.packetStateData.lastPacketWasTeleport
|
||||
&& !player.packetStateData.lastPacketWasOnePointSeventeenDuplicate) {
|
||||
if (player.packetStateData.eatingHand != InteractionHand.OFF_HAND
|
||||
&& player.packetStateData.getSlowedByUsingItemSlot() != player.packetStateData.lastSlotSelected
|
||||
|| player.getInventory().getItemInHand(player.packetStateData.eatingHand).isEmpty()) {
|
||||
if (player == null) return;
|
||||
|
||||
if (!player.packetStateData.lastPacketWasTeleport && !player.packetStateData.lastPacketWasOnePointSeventeenDuplicate) {
|
||||
if (player.packetStateData.isSlowedByUsingItem() && player.packetStateData.getSlowedByUsingItemSlot() != player.packetStateData.lastSlotSelected) {
|
||||
player.packetStateData.setSlowedByUsingItem(false);
|
||||
player.checkManager.getPostPredictionCheck(NoSlowA.class).didSlotChangeLastTick = true;
|
||||
}
|
||||
@@ -196,7 +196,7 @@ public class PacketPlayerDigging extends PacketListenerAbstract {
|
||||
|
||||
if (player.packetStateData.lastSlotSelected != slot) {
|
||||
// just assume they tick after this
|
||||
if (!player.isTickingReliablyFor(3) && player.skippedTickInActualMovement && player.packetStateData.eatingHand != InteractionHand.OFF_HAND) {
|
||||
if (!player.isTickingReliablyFor(3) && player.skippedTickInActualMovement) {
|
||||
player.packetStateData.setSlowedByUsingItem(false);
|
||||
}
|
||||
}
|
||||
@@ -220,7 +220,13 @@ public class PacketPlayerDigging extends PacketListenerAbstract {
|
||||
final ItemStack item = hand == InteractionHand.MAIN_HAND ?
|
||||
player.getInventory().getHeldItem() : player.getInventory().getOffHand();
|
||||
|
||||
final boolean wasSlow = player.packetStateData.isSlowedByUsingItem();
|
||||
|
||||
handleUseItem(player, item, hand);
|
||||
|
||||
if (!wasSlow) {
|
||||
player.checkManager.getPostPredictionCheck(NoSlowD.class).startedSprintingBeforeUse = player.packetStateData.isSlowedByUsingItem() && player.isSprinting;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -130,6 +130,7 @@ public class PacketPlayerRespawn extends PacketListenerAbstract {
|
||||
player.compensatedEntities.serverPositionsMap.clear();
|
||||
}
|
||||
|
||||
// TODO: What does keep all metadata do?
|
||||
player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get() + 1, () -> {
|
||||
player.isSneaking = false;
|
||||
player.lastOnGround = false;
|
||||
@@ -140,16 +141,8 @@ public class PacketPlayerRespawn extends PacketListenerAbstract {
|
||||
player.packetStateData.lastClaimedPosition = new Vector3d();
|
||||
player.filterMojangStupidityOnMojangStupidity = new Vector3d();
|
||||
|
||||
final boolean keepTrackedData = this.hasFlag(respawn, KEEP_TRACKED_DATA);
|
||||
|
||||
if (!keepTrackedData) {
|
||||
player.powderSnowFrozenTicks = 0;
|
||||
player.compensatedEntities.getSelf().hasGravity = true;
|
||||
player.playerEntityHasGravity = true;
|
||||
}
|
||||
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_19_4)) {
|
||||
if (!keepTrackedData) {
|
||||
if (!this.hasFlag(respawn, KEEP_TRACKED_DATA)) {
|
||||
player.isSprinting = false;
|
||||
}
|
||||
} else {
|
||||
@@ -191,6 +184,7 @@ public class PacketPlayerRespawn extends PacketListenerAbstract {
|
||||
player.compensatedWorld.setDimension(respawn.getDimensionType(), event.getUser());
|
||||
}
|
||||
|
||||
// TODO And there should probably be some attribute holder that we can just call reset() on.
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_16) && !this.hasFlag(respawn, KEEP_ATTRIBUTES)) {
|
||||
// Reset attributes if not kept
|
||||
player.compensatedEntities.getSelf().resetAttributes();
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import com.github.retrooper.packetevents.event.PacketListenerPriority;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientSteerVehicle;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package ac.grim.grimac.events.packets;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.checks.impl.movement.NoSlowD;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.nmsutil.WatchableIndexUtil;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
@@ -23,7 +24,6 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class PacketSelfMetadataListener extends PacketListenerAbstract {
|
||||
|
||||
public PacketSelfMetadataListener() {
|
||||
super(PacketListenerPriority.HIGH);
|
||||
}
|
||||
@@ -68,7 +68,6 @@ public class PacketSelfMetadataListener extends PacketListenerAbstract {
|
||||
// Remove the pose metadata from the list
|
||||
metadataStuff.removeIf(element -> element.getIndex() == 6);
|
||||
entityMetadata.setEntityMetadata(metadataStuff);
|
||||
event.markForReEncode(true);
|
||||
}
|
||||
|
||||
EntityData watchable = WatchableIndexUtil.getIndex(entityMetadata.getEntityMetadata(), 0);
|
||||
@@ -208,6 +207,8 @@ public class PacketSelfMetadataListener extends PacketListenerAbstract {
|
||||
// The above line is a hack to fake activate use item
|
||||
player.packetStateData.setSlowedByUsingItem(isActive);
|
||||
|
||||
player.checkManager.getPostPredictionCheck(NoSlowD.class).startedSprintingBeforeUse = player.packetStateData.isSlowedByUsingItem() && player.isSprinting;
|
||||
|
||||
if (isActive) {
|
||||
player.packetStateData.eatingHand = isOffhand ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND;
|
||||
}
|
||||
|
||||
@@ -6,12 +6,14 @@ import ac.grim.grimac.utils.data.Pair;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import com.github.retrooper.packetevents.event.PacketListenerPriority;
|
||||
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.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.teleport.RelativeFlag;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientTeleportConfirm;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerPositionAndLook;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerVehicleMove;
|
||||
import org.bukkit.Location;
|
||||
|
||||
+34
-15
@@ -5,11 +5,14 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import com.github.retrooper.packetevents.event.PacketListenerPriority;
|
||||
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.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import com.github.retrooper.packetevents.protocol.player.UserProfile;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfo;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoUpdate;
|
||||
|
||||
@@ -17,15 +20,22 @@ import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
public class PacketHidePlayerInfo extends PacketListenerAbstract {
|
||||
|
||||
public PacketHidePlayerInfo() {
|
||||
public class PacketSetWrapperNull extends PacketListenerAbstract {
|
||||
// It's faster (and less buggy) to simply not re-encode the wrapper unless we changed something
|
||||
// The two packets we change are clientbound entity metadata (to fix a netcode issue)
|
||||
// and the serverbound player flying packets (to patch NoFall)
|
||||
public PacketSetWrapperNull() {
|
||||
super(PacketListenerPriority.HIGHEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(PacketSendEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.PLAYER_INFO) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.ENTITY_METADATA) {
|
||||
WrapperPlayServerEntityMetadata wrapper = new WrapperPlayServerEntityMetadata(event);
|
||||
if (wrapper.getEntityId() != event.getUser().getEntityId()) {
|
||||
event.setLastUsedWrapper(null);
|
||||
}
|
||||
} else if (event.getPacketType() == PacketType.Play.Server.PLAYER_INFO) {
|
||||
//iterate through players and fake their game mode if they are spectating via grim spectate
|
||||
if (PacketEvents.getAPI().getServerManager().getVersion().isOlderThanOrEquals(ServerVersion.V_1_12_2))
|
||||
return;
|
||||
@@ -52,8 +62,8 @@ public class PacketHidePlayerInfo extends PacketListenerAbstract {
|
||||
//if amount of hidden players is the amount of players updated & is an update game mode action just cancel it
|
||||
if (hideCount == nmsPlayerInfoDataList.size() && info.getAction() == WrapperPlayServerPlayerInfo.Action.UPDATE_GAME_MODE) {
|
||||
event.setCancelled(true);
|
||||
} else if (hideCount > 0) {
|
||||
event.markForReEncode(true);
|
||||
} else if (hideCount <= 0) {
|
||||
event.setLastUsedWrapper(null);
|
||||
}
|
||||
}
|
||||
} else if (event.getPacketType() == PacketType.Play.Server.PLAYER_INFO_UPDATE) {
|
||||
@@ -71,13 +81,12 @@ public class PacketHidePlayerInfo extends PacketListenerAbstract {
|
||||
for (WrapperPlayServerPlayerInfoUpdate.PlayerInfo entry : wrapper.getEntries()) {
|
||||
//check if the player should be hidden
|
||||
WrapperPlayServerPlayerInfoUpdate.PlayerInfo modifiedPacket = null;
|
||||
final UserProfile gameProfile = entry.getGameProfile();
|
||||
if (GrimAPI.INSTANCE.getSpectateManager().shouldHidePlayer(receiver, gameProfile.getUUID())) {
|
||||
if (GrimAPI.INSTANCE.getSpectateManager().shouldHidePlayer(receiver, entry.getProfileId())) {
|
||||
hideCount++;
|
||||
//modify & create a new packet from pre-existing one if they are a spectator
|
||||
if (entry.getGameMode() == GameMode.SPECTATOR) {
|
||||
modifiedPacket = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo(
|
||||
gameProfile,
|
||||
entry.getGameProfile(),
|
||||
entry.isListed(),
|
||||
entry.getLatency(),
|
||||
GameMode.SURVIVAL,
|
||||
@@ -95,20 +104,30 @@ public class PacketHidePlayerInfo extends PacketListenerAbstract {
|
||||
} //if only the game mode was updated and the packet was modified, don't send anything
|
||||
|
||||
}
|
||||
|
||||
// if the amount of hidden players & modified entries are the same
|
||||
if (hideCount == modified.size()) {
|
||||
//if no hidden players, don't modify packet
|
||||
if (hideCount <= 0) {
|
||||
event.setLastUsedWrapper(null);
|
||||
} else if (hideCount == modified.size()) { //if the amount of hidden players & modified entries are the same
|
||||
if (onlyGameMode) { // if only the game mode changed, cancel
|
||||
event.setCancelled(true);
|
||||
} else { //if more than the game mode changed, remove the action
|
||||
wrapper.getActions().remove(WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_GAME_MODE);
|
||||
event.markForReEncode(true);
|
||||
}
|
||||
} else { //modify entries
|
||||
wrapper.setEntries(modified);
|
||||
event.markForReEncode(true);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (event.getPacketType() != PacketType.Play.Server.PLAYER_POSITION_AND_LOOK) {
|
||||
event.setLastUsedWrapper(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
PacketTypeCommon packetType = event.getPacketType();
|
||||
if (!WrapperPlayClientPlayerFlying.isFlying(packetType) && packetType != PacketType.Play.Client.CLIENT_SETTINGS && !event.isCancelled()) {
|
||||
event.setLastUsedWrapper(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,4 +99,4 @@ public class ProxyAlertMessenger extends PacketListenerAbstract {
|
||||
if (!file.exists()) return false;
|
||||
return YamlConfiguration.loadConfiguration(file).getBoolean(pathToValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,8 +37,7 @@ public class ResyncWorldUtil {
|
||||
|
||||
// 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(),
|
||||
minBlockX >> 4, minBlockZ >> 4, () -> {
|
||||
FoliaScheduler.getEntityScheduler().execute(player.bukkitPlayer, GrimAPI.INSTANCE.getPlugin(), () -> {
|
||||
boolean flat = PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_13);
|
||||
|
||||
if (player.bukkitPlayer == null) return;
|
||||
@@ -112,6 +111,6 @@ public class ResyncWorldUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}, null, 0);
|
||||
}
|
||||
}
|
||||
@@ -174,4 +174,4 @@ public class BasePacketWorldReader extends PacketListenerAbstract {
|
||||
player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(), () -> player.compensatedWorld.updateBlock(blockChange.getX(), blockChange.getY(), blockChange.getZ(), blockChange.getBlockId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import java.util.BitSet;
|
||||
public class PacketWorldReaderEight extends BasePacketWorldReader {
|
||||
@Override
|
||||
public void handleMapChunkBulk(final GrimPlayer player, final PacketSendEvent event) {
|
||||
PacketWrapper<?> wrapper = new PacketWrapper<>(event);
|
||||
PacketWrapper wrapper = new PacketWrapper(event);
|
||||
ByteBuf buffer = (ByteBuf) wrapper.getBuffer();
|
||||
|
||||
boolean skylight = wrapper.readBoolean();
|
||||
@@ -47,7 +47,7 @@ public class PacketWorldReaderEight extends BasePacketWorldReader {
|
||||
|
||||
@Override
|
||||
public void handleMapChunk(final GrimPlayer player, final PacketSendEvent event) {
|
||||
PacketWrapper<?> wrapper = new PacketWrapper<>(event);
|
||||
PacketWrapper wrapper = new PacketWrapper(event);
|
||||
|
||||
final int chunkX = wrapper.readInt();
|
||||
final int chunkZ = wrapper.readInt();
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package ac.grim.grimac.manager;
|
||||
|
||||
|
||||
import ac.grim.grimac.api.AbstractCheck;
|
||||
import ac.grim.grimac.checks.impl.aim.AimDuplicateLook;
|
||||
import ac.grim.grimac.checks.impl.aim.AimModulo360;
|
||||
import ac.grim.grimac.checks.impl.aim.processor.AimProcessor;
|
||||
import ac.grim.grimac.checks.impl.badpackets.*;
|
||||
import ac.grim.grimac.checks.impl.combat.MultiInteractA;
|
||||
import ac.grim.grimac.checks.impl.combat.MultiInteractB;
|
||||
import ac.grim.grimac.checks.impl.combat.Reach;
|
||||
import ac.grim.grimac.checks.impl.crash.*;
|
||||
import ac.grim.grimac.checks.impl.exploit.ExploitA;
|
||||
@@ -43,16 +42,8 @@ import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.event.PacketSendEvent;
|
||||
import com.google.common.collect.ClassToInstanceMap;
|
||||
import com.google.common.collect.ImmutableClassToInstanceMap;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class CheckManager {
|
||||
private static boolean inited;
|
||||
private static final AtomicBoolean initedAtomic = new AtomicBoolean(false);
|
||||
|
||||
ClassToInstanceMap<PacketCheck> packetChecks;
|
||||
ClassToInstanceMap<PositionCheck> positionCheck;
|
||||
ClassToInstanceMap<RotationCheck> rotationCheck;
|
||||
@@ -138,8 +129,6 @@ public class CheckManager {
|
||||
.put(NoSlowC.class, new NoSlowC(player))
|
||||
.put(NoSlowD.class, new NoSlowD(player))
|
||||
.put(NoSlowE.class, new NoSlowE(player))
|
||||
.put(MultiInteractA.class, new MultiInteractA(player))
|
||||
.put(MultiInteractB.class, new MultiInteractB(player))
|
||||
.put(SetbackTeleportUtil.class, new SetbackTeleportUtil(player)) // Avoid teleporting to new position, update safe pos last
|
||||
.put(CompensatedFireworks.class, player.compensatedFireworks)
|
||||
.put(SneakingEstimator.class, new SneakingEstimator(player))
|
||||
@@ -150,7 +139,6 @@ public class CheckManager {
|
||||
.put(InvalidPlaceA.class, new InvalidPlaceA(player))
|
||||
.put(InvalidPlaceB.class, new InvalidPlaceB(player))
|
||||
.put(AirLiquidPlace.class, new AirLiquidPlace(player))
|
||||
.put(MultiPlace.class, new MultiPlace(player))
|
||||
.put(FarPlace.class, new FarPlace(player))
|
||||
.put(FabricatedPlace.class, new FabricatedPlace(player))
|
||||
.put(PositionPlace.class, new PositionPlace(player))
|
||||
@@ -183,8 +171,6 @@ public class CheckManager {
|
||||
.putAll(blockPlaceCheck)
|
||||
.putAll(prePredictionChecks)
|
||||
.build();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -215,9 +201,6 @@ public class CheckManager {
|
||||
for (PostPredictionCheck check : postPredictionCheck.values()) {
|
||||
check.onPacketReceive(packet);
|
||||
}
|
||||
for (BlockPlaceCheck check : blockPlaceCheck.values()) {
|
||||
check.onPacketReceive(packet);
|
||||
}
|
||||
}
|
||||
|
||||
public void onPacketSend(final PacketSendEvent packet) {
|
||||
@@ -230,9 +213,6 @@ public class CheckManager {
|
||||
for (PostPredictionCheck check : postPredictionCheck.values()) {
|
||||
check.onPacketSend(packet);
|
||||
}
|
||||
for (BlockPlaceCheck check : blockPlaceCheck.values()) {
|
||||
check.onPacketSend(packet);
|
||||
}
|
||||
}
|
||||
|
||||
public void onPositionUpdate(final PositionUpdate position) {
|
||||
@@ -260,9 +240,6 @@ public class CheckManager {
|
||||
for (PostPredictionCheck check : postPredictionCheck.values()) {
|
||||
check.onPredictionComplete(complete);
|
||||
}
|
||||
for (BlockPlaceCheck check : blockPlaceCheck.values()) {
|
||||
check.onPredictionComplete(complete);
|
||||
}
|
||||
}
|
||||
|
||||
public void onBlockPlace(final BlockPlace place) {
|
||||
@@ -337,25 +314,4 @@ public class CheckManager {
|
||||
public <T extends PostPredictionCheck> T getPostPredictionCheck(Class<T> check) {
|
||||
return (T) postPredictionCheck.get(check);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
// Fast non-thread safe check
|
||||
if (inited) return;
|
||||
// Slow thread safe check
|
||||
if (!initedAtomic.compareAndSet(false, true)) return;
|
||||
inited = true;
|
||||
|
||||
for (AbstractCheck check : allChecks.values()) {
|
||||
if (check.getCheckName() != null) {
|
||||
String permissionName = "grim.exempt." + check.getCheckName().toLowerCase();
|
||||
Permission permission = Bukkit.getPluginManager().getPermission(permissionName);
|
||||
|
||||
if (permission == null) {
|
||||
Bukkit.getPluginManager().addPermission(new Permission(permissionName, PermissionDefault.FALSE));
|
||||
} else {
|
||||
permission.setDefault(PermissionDefault.FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+53
-63
@@ -1,43 +1,56 @@
|
||||
package ac.grim.grimac.manager.config;
|
||||
package ac.grim.grimac.manager;
|
||||
|
||||
import ac.grim.grimac.GrimAC;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.common.BasicReloadable;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import github.scarsz.configuralize.DynamicConfig;
|
||||
import github.scarsz.configuralize.Language;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
public class ConfigManagerFileImpl implements ConfigManager, BasicReloadable {
|
||||
|
||||
public class ConfigManager {
|
||||
@Getter
|
||||
private final DynamicConfig config;
|
||||
@Getter
|
||||
private final File configFile = new File(GrimAPI.INSTANCE.getPlugin().getDataFolder(), "config.yml");
|
||||
@Getter
|
||||
private final File messagesFile = new File(GrimAPI.INSTANCE.getPlugin().getDataFolder(), "messages.yml");
|
||||
@Getter
|
||||
private final File discordFile = new File(GrimAPI.INSTANCE.getPlugin().getDataFolder(), "discord.yml");
|
||||
@Getter
|
||||
private final File punishFile = new File(GrimAPI.INSTANCE.getPlugin().getDataFolder(), "punishments.yml");
|
||||
@Getter
|
||||
private int maxPingTransaction = 60; // This is just a really hot variable so cache it.
|
||||
@Getter
|
||||
private boolean ignoreDuplicatePacketRotation = false;
|
||||
|
||||
private File getConfigFile(String path) {
|
||||
return new File(GrimAPI.INSTANCE.getPlugin().getDataFolder(), path);
|
||||
}
|
||||
@Getter
|
||||
private boolean experimentalChecks = false;
|
||||
|
||||
public ConfigManagerFileImpl() {
|
||||
config = new DynamicConfig();
|
||||
}
|
||||
private final List<Pattern> ignoredClientPatterns = new ArrayList<>();
|
||||
|
||||
private boolean initialized = false;
|
||||
public ConfigManager() {
|
||||
upgrade();
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
// load config
|
||||
GrimAPI.INSTANCE.getPlugin().getDataFolder().mkdirs();
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
config.addSource(GrimAC.class, "config", getConfigFile("config.yml"));
|
||||
config.addSource(GrimAC.class, "messages", getConfigFile("messages.yml"));
|
||||
config.addSource(GrimAC.class, "discord", getConfigFile("discord.yml"));
|
||||
config.addSource(GrimAC.class, "punishments", getConfigFile("punishments.yml"));
|
||||
}
|
||||
//
|
||||
config = new DynamicConfig();
|
||||
config.addSource(GrimAC.class, "config", getConfigFile());
|
||||
config.addSource(GrimAC.class, "messages", getMessagesFile());
|
||||
config.addSource(GrimAC.class, "discord", getDiscordFile());
|
||||
config.addSource(GrimAC.class, "punishments", getPunishFile());
|
||||
|
||||
reload();
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
String languageCode = System.getProperty("user.language").toUpperCase();
|
||||
|
||||
try {
|
||||
@@ -64,6 +77,24 @@ public class ConfigManagerFileImpl implements ConfigManager, BasicReloadable {
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to load config", e);
|
||||
}
|
||||
maxPingTransaction = config.getIntElse("max-transaction-time", 60);
|
||||
ignoredClientPatterns.clear();
|
||||
for (String string : config.getStringList("client-brand.ignored-clients")) {
|
||||
try {
|
||||
ignoredClientPatterns.add(Pattern.compile(string));
|
||||
} catch (PatternSyntaxException e) {
|
||||
throw new RuntimeException("Failed to compile client pattern", e);
|
||||
}
|
||||
}
|
||||
experimentalChecks = config.getBooleanElse("experimental-checks", false);
|
||||
ignoreDuplicatePacketRotation = config.getBooleanElse("ignore-duplicate-packet-rotation", false);
|
||||
}
|
||||
|
||||
public boolean isIgnoredClient(String brand) {
|
||||
for (Pattern pattern : ignoredClientPatterns) {
|
||||
if (pattern.matcher(brand).find()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void upgrade() {
|
||||
@@ -286,45 +317,4 @@ public class ConfigManagerFileImpl implements ConfigManager, BasicReloadable {
|
||||
);
|
||||
Files.write(config.toPath(), configString.getBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStringElse(String key, String otherwise) {
|
||||
return config.getStringElse(key, otherwise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStringList(String key) {
|
||||
return config.getStringList(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStringListElse(String key, List<String> otherwise) {
|
||||
return config.getStringListElse(key, otherwise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntElse(String key, int other) {
|
||||
return config.getIntElse(key, other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLongElse(String key, long otherwise) {
|
||||
return config.getLongElse(key, otherwise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDoubleElse(String key, double otherwise) {
|
||||
return config.getDoubleElse(key, otherwise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBooleanElse(String key, boolean otherwise) {
|
||||
return config.getBooleanElse(key, otherwise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T get(String key) {
|
||||
return config.get(key);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,7 +19,6 @@ public class DiscordManager implements Initable {
|
||||
private static WebhookClient client;
|
||||
private int embedColor;
|
||||
private String staticContent = "";
|
||||
private String embedTitle = "";
|
||||
|
||||
public static final Pattern WEBHOOK_PATTERN = Pattern.compile("(?:https?://)?(?:\\w+\\.)?\\w+\\.\\w+/api(?:/v\\d+)?/webhooks/(\\d+)/([\\w-]+)(?:/(?:\\w+)?)?");
|
||||
|
||||
@@ -41,8 +40,6 @@ public class DiscordManager implements Initable {
|
||||
client = WebhookClient.withId(Long.parseUnsignedLong(matcher.group(1)), matcher.group(2));
|
||||
client.setTimeout(15000); // Requests expire after 15 seconds
|
||||
|
||||
embedTitle = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("embed-title", "**Grim Alert**");
|
||||
|
||||
try {
|
||||
embedColor = Color.decode(GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("embed-color", "#00FFFF")).getRGB();
|
||||
} catch (NumberFormatException e) {
|
||||
@@ -73,7 +70,7 @@ public class DiscordManager implements Initable {
|
||||
public void sendAlert(GrimPlayer player, String verbose, String checkName, String violations) {
|
||||
if (client != null) {
|
||||
|
||||
String content = staticContent;
|
||||
String content = staticContent + "";
|
||||
content = content.replace("%check%", checkName);
|
||||
content = content.replace("%violations%", violations);
|
||||
content = GrimAPI.INSTANCE.getExternalAPI().replaceVariables(player, content, false);
|
||||
@@ -83,7 +80,7 @@ public class DiscordManager implements Initable {
|
||||
.setImageUrl("https://i.stack.imgur.com/Fzh0w.png") // Constant width
|
||||
.setThumbnailUrl("https://crafthead.net/helm/" + player.user.getProfile().getUUID())
|
||||
.setColor(embedColor)
|
||||
.setTitle(new WebhookEmbed.EmbedTitle(embedTitle, null))
|
||||
.setTitle(new WebhookEmbed.EmbedTitle("**Grim Alert**", null))
|
||||
.setDescription(content)
|
||||
.setTimestamp(Instant.now())
|
||||
.setFooter(new WebhookEmbed.EmbedFooter("", "https://grim.ac/images/grim.png"));
|
||||
|
||||
@@ -1,72 +1,60 @@
|
||||
package ac.grim.grimac.manager;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.GrimExternalAPI;
|
||||
import ac.grim.grimac.manager.init.Initable;
|
||||
import ac.grim.grimac.manager.init.load.PacketEventsInit;
|
||||
import ac.grim.grimac.manager.init.start.*;
|
||||
import ac.grim.grimac.manager.init.stop.TerminatePacketEvents;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import lombok.Getter;
|
||||
import com.google.common.collect.ClassToInstanceMap;
|
||||
import com.google.common.collect.ImmutableClassToInstanceMap;
|
||||
|
||||
public class InitManager {
|
||||
|
||||
private final ImmutableList<Initable> initializersOnLoad;
|
||||
private final ImmutableList<Initable> initializersOnStart;
|
||||
private final ImmutableList<Initable> initializersOnStop;
|
||||
|
||||
@Getter private boolean loaded = false;
|
||||
@Getter private boolean started = false;
|
||||
@Getter private boolean stopped = false;
|
||||
ClassToInstanceMap<Initable> initializersOnLoad;
|
||||
ClassToInstanceMap<Initable> initializersOnStart;
|
||||
ClassToInstanceMap<Initable> initializersOnStop;
|
||||
|
||||
public InitManager() {
|
||||
initializersOnLoad = ImmutableList.<Initable>builder()
|
||||
.add(new PacketEventsInit())
|
||||
.add(() -> GrimAPI.INSTANCE.getExternalAPI().load())
|
||||
initializersOnLoad = new ImmutableClassToInstanceMap.Builder<Initable>()
|
||||
.put(PacketEventsInit.class, new PacketEventsInit())
|
||||
.build();
|
||||
|
||||
initializersOnStart = ImmutableList.<Initable>builder()
|
||||
.add(GrimAPI.INSTANCE.getExternalAPI())
|
||||
.add(new ExemptOnlinePlayers())
|
||||
.add(new EventManager())
|
||||
.add(new PacketManager())
|
||||
.add(new ViaBackwardsManager())
|
||||
.add(new TickRunner())
|
||||
.add(new TickEndEvent())
|
||||
.add(new CommandRegister())
|
||||
.add(new BStats())
|
||||
.add(new PacketLimiter())
|
||||
.add(GrimAPI.INSTANCE.getDiscordManager())
|
||||
.add(GrimAPI.INSTANCE.getSpectateManager())
|
||||
.add(new JavaVersion())
|
||||
.add(new ViaVersion())
|
||||
initializersOnStart = new ImmutableClassToInstanceMap.Builder<Initable>()
|
||||
.put(ExemptOnlinePlayers.class, new ExemptOnlinePlayers())
|
||||
.put(EventManager.class, new EventManager())
|
||||
.put(PacketManager.class, new PacketManager())
|
||||
.put(ViaBackwardsManager.class, new ViaBackwardsManager())
|
||||
.put(TickRunner.class, new TickRunner())
|
||||
.put(TickEndEvent.class, new TickEndEvent())
|
||||
.put(CommandRegister.class, new CommandRegister())
|
||||
.put(BStats.class, new BStats())
|
||||
.put(PacketLimiter.class, new PacketLimiter())
|
||||
.put(DiscordManager.class, GrimAPI.INSTANCE.getDiscordManager())
|
||||
.put(SpectateManager.class, GrimAPI.INSTANCE.getSpectateManager())
|
||||
.put(GrimExternalAPI.class, GrimAPI.INSTANCE.getExternalAPI())
|
||||
.put(JavaVersion.class, new JavaVersion())
|
||||
.build();
|
||||
|
||||
initializersOnStop = ImmutableList.<Initable>builder()
|
||||
.add(new TerminatePacketEvents())
|
||||
initializersOnStop = new ImmutableClassToInstanceMap.Builder<Initable>()
|
||||
.put(TerminatePacketEvents.class, new TerminatePacketEvents())
|
||||
.build();
|
||||
}
|
||||
|
||||
public void load() {
|
||||
for (Initable initable : initializersOnLoad) handle(initable);
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
for (Initable initable : initializersOnStart) handle(initable);
|
||||
started = true;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
for (Initable initable : initializersOnStop) handle(initable);
|
||||
stopped = true;
|
||||
}
|
||||
|
||||
private void handle(Initable initable) {
|
||||
try {
|
||||
for (Initable initable : initializersOnLoad.values()) {
|
||||
initable.start();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public void start() {
|
||||
for (Initable initable : initializersOnStart.values()) {
|
||||
initable.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
for (Initable initable : initializersOnStop.values()) {
|
||||
initable.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,16 +2,14 @@ package ac.grim.grimac.manager;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.AbstractCheck;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.api.config.ConfigReloadable;
|
||||
import ac.grim.grimac.api.events.CommandExecuteEvent;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.events.packets.ProxyAlertMessenger;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
import github.scarsz.configuralize.DynamicConfig;
|
||||
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;
|
||||
@@ -19,27 +17,21 @@ import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class PunishmentManager implements ConfigReloadable {
|
||||
public class PunishmentManager {
|
||||
GrimPlayer player;
|
||||
List<PunishGroup> groups = new ArrayList<>();
|
||||
String experimentalSymbol = "*";
|
||||
private String alertString;
|
||||
private boolean testMode;
|
||||
private boolean printToConsole;
|
||||
private String proxyAlertString = "";
|
||||
|
||||
public PunishmentManager(GrimPlayer player) {
|
||||
this.player = player;
|
||||
reload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload(ConfigManager config) {
|
||||
public void reload() {
|
||||
DynamicConfig config = GrimAPI.INSTANCE.getConfigManager().getConfig();
|
||||
List<String> punish = config.getStringListElse("Punishments", new ArrayList<>());
|
||||
experimentalSymbol = config.getStringElse("experimental-symbol", "*");
|
||||
alertString = config.getStringElse("alerts-format", "%prefix% &f%player% &bfailed &f%check_name% &f(x&c%vl%&f) &7%verbose%");
|
||||
testMode = config.getBooleanElse("test-mode", false);
|
||||
printToConsole = config.getBooleanElse("verbose.print-to-console", false);
|
||||
proxyAlertString = config.getStringElse("alerts-format-proxy", "%prefix% &f[&cproxy&f] &f%player% &bfailed &f%check_name% &f(x&c%vl%&f) &7%verbose%");
|
||||
|
||||
try {
|
||||
groups.clear();
|
||||
|
||||
@@ -106,7 +98,7 @@ public class PunishmentManager implements ConfigReloadable {
|
||||
original = MessageUtil.format(original
|
||||
.replace("[alert]", alertString)
|
||||
.replace("[proxy]", alertString)
|
||||
.replace("%check_name%", check.getDisplayName())
|
||||
.replace("%check_name%", check.getCheckName())
|
||||
.replace("%experimental%", check.isExperimental() ? experimentalSymbol : "")
|
||||
.replace("%vl%", vl)
|
||||
.replace("%verbose%", verbose)
|
||||
@@ -119,6 +111,8 @@ public class PunishmentManager implements ConfigReloadable {
|
||||
}
|
||||
|
||||
public boolean handleAlert(GrimPlayer player, String verbose, Check check) {
|
||||
String alertString = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("alerts-format", "%prefix% &f%player% &bfailed &f%check_name% &f(x&c%vl%&f) &7%verbose%");
|
||||
boolean testMode = GrimAPI.INSTANCE.getConfigManager().getConfig().getBooleanElse("test-mode", false);
|
||||
boolean sentDebug = false;
|
||||
|
||||
// Check commands
|
||||
@@ -134,7 +128,7 @@ public class PunishmentManager implements ConfigReloadable {
|
||||
for (Player bukkitPlayer : GrimAPI.INSTANCE.getAlertManager().getEnabledVerbose()) {
|
||||
bukkitPlayer.sendMessage(cmd);
|
||||
}
|
||||
if (printToConsole) {
|
||||
if (GrimAPI.INSTANCE.getConfigManager().getConfig().getBooleanElse("verbose.print-to-console", false)) {
|
||||
LogUtil.console(cmd); // Print verbose to console
|
||||
}
|
||||
}
|
||||
@@ -150,9 +144,11 @@ public class PunishmentManager implements ConfigReloadable {
|
||||
|
||||
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);
|
||||
GrimAPI.INSTANCE.getDiscordManager().sendAlert(player, verbose, check.getCheckName(), vl);
|
||||
} else if (command.command.equals("[proxy]")) {
|
||||
ProxyAlertMessenger.sendPluginMessage(replaceAlertPlaceholders(command.getCommand(), group, check, proxyAlertString, verbose));
|
||||
String proxyAlertString = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("alerts-format-proxy", "%prefix% &f[&cproxy&f] &f%player% &bfailed &f%check_name% &f(x&c%vl%&f) &7%verbose%");
|
||||
proxyAlertString = replaceAlertPlaceholders(command.getCommand(), group, check, proxyAlertString, verbose);
|
||||
ProxyAlertMessenger.sendPluginMessage(proxyAlertString);
|
||||
} else {
|
||||
if (command.command.equals("[alert]")) {
|
||||
sentDebug = true;
|
||||
@@ -164,8 +160,9 @@ public class PunishmentManager implements ConfigReloadable {
|
||||
}
|
||||
|
||||
String finalCmd = cmd;
|
||||
FoliaScheduler.getGlobalRegionScheduler().run(GrimAPI.INSTANCE.getPlugin(), (dummy) ->
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), finalCmd));
|
||||
FoliaScheduler.getGlobalRegionScheduler().run(GrimAPI.INSTANCE.getPlugin(), (dummy) -> {
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), finalCmd);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +181,7 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -196,7 +193,7 @@ class PunishGroup {
|
||||
@Getter
|
||||
List<ParsedCommand> commands;
|
||||
@Getter
|
||||
Long2ObjectOpenHashMap<Check> violations = new Long2ObjectOpenHashMap<>();
|
||||
HashMap<Long, Check> violations = new HashMap<>();
|
||||
@Getter
|
||||
int removeViolationsAfter;
|
||||
|
||||
|
||||
@@ -153,12 +153,12 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
VelocityData futureExplosion = player.checkManager.getExplosionHandler().getFutureExplosion();
|
||||
|
||||
// Velocity sets
|
||||
if (futureKb.first() != null) {
|
||||
clientVel = futureKb.second();
|
||||
if (futureKb.getFirst() != null) {
|
||||
clientVel = futureKb.getSecond();
|
||||
}
|
||||
|
||||
// Explosion adds
|
||||
if (futureExplosion != null && (futureKb.first() == null || futureKb.first().transaction < futureExplosion.transaction)) {
|
||||
if (futureExplosion != null && (futureKb.getFirst() == null || futureKb.getFirst().transaction < futureExplosion.transaction)) {
|
||||
clientVel.add(futureExplosion.vector);
|
||||
}
|
||||
|
||||
@@ -328,16 +328,16 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
while (true) {
|
||||
Pair<Integer, Vector3d> teleportPos = player.vehicleData.vehicleTeleports.peek();
|
||||
if (teleportPos == null) break;
|
||||
if (lastTransaction < teleportPos.first()) {
|
||||
if (lastTransaction < teleportPos.getFirst()) {
|
||||
break;
|
||||
}
|
||||
|
||||
Vector3d position = teleportPos.second();
|
||||
Vector3d position = teleportPos.getSecond();
|
||||
if (position.getX() == x && position.getY() == y && position.getZ() == z) {
|
||||
player.vehicleData.vehicleTeleports.poll();
|
||||
|
||||
return true;
|
||||
} else if (lastTransaction > teleportPos.first() + 1) {
|
||||
} else if (lastTransaction > teleportPos.getFirst() + 1) {
|
||||
player.vehicleData.vehicleTeleports.poll();
|
||||
|
||||
// Vehicles have terrible netcode so just ignore it if the teleport wasn't from us setting the player back
|
||||
|
||||
@@ -71,8 +71,14 @@ public class SpectateManager implements Initable {
|
||||
spectatingPlayers.remove(uuid);
|
||||
}
|
||||
|
||||
private record PreviousState(org.bukkit.GameMode gameMode, Location location) {
|
||||
private static class PreviousState {
|
||||
public PreviousState(org.bukkit.GameMode gameMode, Location location) {
|
||||
this.gameMode = gameMode;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
private final org.bukkit.GameMode gameMode;
|
||||
private final Location location;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package ac.grim.grimac.manager.config;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
public class BaseConfigManager {
|
||||
|
||||
/*
|
||||
This is to hold whatever config manager was set via the reload method in the API
|
||||
and any global variables that are the same between players.
|
||||
*/
|
||||
|
||||
@Getter
|
||||
private ConfigManager config = null;
|
||||
|
||||
// initialize the config
|
||||
public void load(ConfigManager config) {
|
||||
this.config = config;
|
||||
//
|
||||
int configuredMaxTransactionTime = config.getIntElse("max-transaction-time", 60);
|
||||
if (configuredMaxTransactionTime > 180 || configuredMaxTransactionTime < 1) {
|
||||
LogUtil.warn("Detected invalid max-transaction-time! This setting is clamped between 1 and 180 to prevent issues. Attempting to disable or set this too high can result in memory usage issues.");
|
||||
}
|
||||
|
||||
ignoredClientPatterns.clear();
|
||||
for (String string : config.getStringList("client-brand.ignored-clients")) {
|
||||
try {
|
||||
ignoredClientPatterns.add(Pattern.compile(string));
|
||||
} catch (PatternSyntaxException e) {
|
||||
throw new RuntimeException("Failed to compile client pattern", e);
|
||||
}
|
||||
}
|
||||
|
||||
printAlertsToConsole = config.getBooleanElse("alerts.print-to-console", true);
|
||||
prefix = config.getStringElse("prefix", "&bGrim &8»");
|
||||
}
|
||||
|
||||
// ran on start, can be used to handle things that can't be done while loading
|
||||
public void start() {
|
||||
|
||||
}
|
||||
|
||||
@Getter private boolean printAlertsToConsole = false;
|
||||
|
||||
@Getter private String prefix = "&bGrim &8»";
|
||||
|
||||
private final List<Pattern> ignoredClientPatterns = new ArrayList<>();
|
||||
|
||||
public boolean isIgnoredClient(String brand) {
|
||||
for (Pattern pattern : ignoredClientPatterns) {
|
||||
if (pattern.matcher(brand).find()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -4,17 +4,8 @@ import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.manager.init.Initable;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.protocol.chat.ChatTypes;
|
||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.github.retrooper.packetevents.protocol.item.enchantment.type.EnchantmentTypes;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class PacketEventsInit implements Initable {
|
||||
@Override
|
||||
public void start() {
|
||||
@@ -25,18 +16,7 @@ public class PacketEventsInit implements Initable {
|
||||
.fullStackTrace(true)
|
||||
.kickOnPacketException(true)
|
||||
.checkForUpdates(false)
|
||||
.reEncodeByDefault(false)
|
||||
.debug(false);
|
||||
PacketEvents.getAPI().load();
|
||||
// This may seem useless, but it causes java to start loading stuff async before we need it
|
||||
Executors.defaultThreadFactory().newThread(() -> {
|
||||
StateTypes.AIR.getName();
|
||||
ItemTypes.AIR.getName();
|
||||
EntityTypes.PLAYER.getParent();
|
||||
EntityDataTypes.BOOLEAN.getName();
|
||||
ChatTypes.CHAT.getName();
|
||||
EnchantmentTypes.ALL_DAMAGE_PROTECTION.getName();
|
||||
ParticleTypes.DUST.getName();
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ public class PacketManager implements Initable {
|
||||
}
|
||||
|
||||
PacketEvents.getAPI().getEventManager().registerListener(new ProxyAlertMessenger());
|
||||
PacketEvents.getAPI().getEventManager().registerListener(new PacketHidePlayerInfo());
|
||||
PacketEvents.getAPI().getEventManager().registerListener(new PacketSetWrapperNull());
|
||||
|
||||
PacketEvents.getAPI().init();
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@ import ac.grim.grimac.utils.lists.EvictingQueue;
|
||||
import ac.grim.grimac.utils.math.GrimMath;
|
||||
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;
|
||||
|
||||
@@ -22,7 +20,7 @@ import java.util.*;
|
||||
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<>();
|
||||
Map<StringBuilder, Integer> continuedDebug = new HashMap<>();
|
||||
|
||||
List<VectorData> predicted = new EvictingQueue<>(60);
|
||||
List<Vector> actually = new EvictingQueue<>(60);
|
||||
@@ -47,7 +45,7 @@ public final class SuperDebug extends Check implements PostPredictionCheck {
|
||||
|
||||
Location location = new Location(player.x, player.y, player.z, player.xRot, player.yRot, player.bukkitPlayer == null ? "null" : player.bukkitPlayer.getWorld().getName());
|
||||
|
||||
for (Iterator<Object2IntMap.Entry<StringBuilder>> it = continuedDebug.object2IntEntrySet().iterator(); it.hasNext(); ) {
|
||||
for (Iterator<Map.Entry<StringBuilder, Integer>> it = continuedDebug.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<StringBuilder, Integer> debug = it.next();
|
||||
appendDebug(debug.getKey(), player.predictedVelocity, player.actualMovement, location, player.startTickClientVel, player.baseTickAddition, player.baseTickWaterPushing);
|
||||
debug.setValue(debug.getValue() - 1);
|
||||
@@ -289,4 +287,4 @@ public final class SuperDebug extends Check implements PostPredictionCheck {
|
||||
return "x: " + x + " y: " + y + " z: " + z + " xRot: " + xRot + " yRot: " + yRot + " world: " + world;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public class TickEndEvent implements Initable {
|
||||
// but whatever. At least plugins can't break it, I guess.
|
||||
//
|
||||
// Pledge injects into another list, so we should be safe injecting into this one
|
||||
List<?> wrapper = Collections.synchronizedList(new HookedListWrapper<>(endOfTickObject) {
|
||||
List<?> wrapper = Collections.synchronizedList(new HookedListWrapper<Object>(endOfTickObject) {
|
||||
@Override
|
||||
public void onIterator() {
|
||||
hasTicked = true;
|
||||
@@ -58,4 +58,4 @@ public class TickEndEvent implements Initable {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package ac.grim.grimac.manager.init.start;
|
||||
|
||||
import ac.grim.grimac.manager.init.Initable;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import io.github.retrooper.packetevents.util.viaversion.ViaVersionUtil;
|
||||
|
||||
public class ViaVersion implements Initable {
|
||||
@Override
|
||||
public void start() {
|
||||
if (!ViaVersionUtil.isAvailable()) return;
|
||||
if (Via.getConfig().getValues().containsKey("fix-1_21-placement-rotation") && Via.getConfig().fix1_21PlacementRotation()) {
|
||||
LogUtil.warn("GrimAC has detected that you are using ViaVersion with the `fix-1_21-placement-rotation` option enabled.");
|
||||
LogUtil.warn("This option is known to cause issues with GrimAC and may result in false positives and bypasses.");
|
||||
LogUtil.warn("Please disable this option in your ViaVersion configuration to prevent these issues.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,6 @@ package ac.grim.grimac.player;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.AbstractCheck;
|
||||
import ac.grim.grimac.api.GrimUser;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.impl.aim.processor.AimProcessor;
|
||||
import ac.grim.grimac.checks.impl.misc.ClientBrand;
|
||||
import ac.grim.grimac.checks.impl.misc.TransactionOrder;
|
||||
@@ -37,6 +35,7 @@ import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.protocol.world.Dimension;
|
||||
import com.github.retrooper.packetevents.protocol.world.dimension.DimensionType;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
@@ -48,7 +47,6 @@ import io.github.retrooper.packetevents.adventure.serializer.legacy.LegacyCompon
|
||||
import io.github.retrooper.packetevents.util.folia.FoliaScheduler;
|
||||
import io.github.retrooper.packetevents.util.viaversion.ViaVersionUtil;
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -201,8 +199,6 @@ public class GrimPlayer implements GrimUser {
|
||||
public long lastBlockPlaceUseItem = 0;
|
||||
public AtomicInteger cancelledPackets = new AtomicInteger(0);
|
||||
public MainSupportingBlockData mainSupportingBlockData = new MainSupportingBlockData(null, false);
|
||||
// possibleEyeHeights[0] = Standing eye heights, [1] = Sneaking. [2] = Elytra, Swimming, and Riptide Trident which only exists in 1.9+
|
||||
public double[][] possibleEyeHeights = new double[3][];
|
||||
|
||||
public void onPacketCancel() {
|
||||
if (spamThreshold != -1 && cancelledPackets.incrementAndGet() > spamThreshold) {
|
||||
@@ -221,6 +217,7 @@ public class GrimPlayer implements GrimUser {
|
||||
public GrimPlayer(User user) {
|
||||
this.user = user;
|
||||
this.playerUUID = user.getUUID();
|
||||
onReload();
|
||||
|
||||
boundingBox = GetBoundingBox.getBoundingBoxFromPosAndSizeRaw(x, y, z, 0.6f, 1.8f);
|
||||
|
||||
@@ -243,24 +240,6 @@ public class GrimPlayer implements GrimUser {
|
||||
packetStateData = new PacketStateData();
|
||||
|
||||
uncertaintyHandler.collidingEntities.add(0);
|
||||
|
||||
if (getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14)) {
|
||||
final float scale = (float) compensatedEntities.getSelf().getAttributeValue(Attributes.GENERIC_SCALE);
|
||||
possibleEyeHeights[2] = new double[]{0.4 * scale, 1.62 * scale, 1.27 * scale}; // Elytra, standing, sneaking (1.14)
|
||||
possibleEyeHeights[1] = new double[]{1.27 * scale, 1.62 * scale, 0.4 * scale}; // sneaking (1.14), standing, Elytra
|
||||
possibleEyeHeights[0] = new double[]{1.62 * scale, 1.27 * scale, 0.4 * scale}; // standing, sneaking (1.14), Elytra
|
||||
|
||||
} else if (getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)) { // standing, sneaking Elytra
|
||||
possibleEyeHeights[2] = new double[]{0.4, 1.62, 1.54}; // Elytra, standing, sneaking (1.13)
|
||||
possibleEyeHeights[1] = new double[]{1.54, 1.62, 0.4}; // sneaking (1.9-1.13), standing, Elytra
|
||||
possibleEyeHeights[0] = new double[]{1.62, 1.54, 0.4}; // standing, sneaking (1.9-1.13), Elytra
|
||||
} else {
|
||||
possibleEyeHeights[1] = new double[]{(double) (1.62f - 0.08f), (double) (1.62f)}; // sneaking, standing
|
||||
possibleEyeHeights[0] = new double[]{(double) (1.62f), (double) (1.62f - 0.08f)}; // standing, sneaking
|
||||
}
|
||||
|
||||
// reload last
|
||||
reload();
|
||||
}
|
||||
|
||||
public Set<VectorData> getPossibleVelocities() {
|
||||
@@ -326,7 +305,7 @@ public class GrimPlayer implements GrimUser {
|
||||
boolean hasID = false;
|
||||
int skipped = 0;
|
||||
for (Pair<Short, Long> iterator : transactionsSent) {
|
||||
if (iterator.first() == id) {
|
||||
if (iterator.getFirst() == id) {
|
||||
hasID = true;
|
||||
break;
|
||||
}
|
||||
@@ -337,8 +316,7 @@ public class GrimPlayer implements GrimUser {
|
||||
// Transactions that we send don't count towards total limit
|
||||
if (packetTracker != null) packetTracker.setIntervalPackets(packetTracker.getIntervalPackets() - 1);
|
||||
|
||||
if (skipped > 0 && System.currentTimeMillis() - joinTime > 5000)
|
||||
checkManager.getPacketCheck(TransactionOrder.class).flagAndAlert("skipped: " + skipped);
|
||||
if (skipped > 0 && System.currentTimeMillis() - joinTime > 5000) checkManager.getPacketCheck(TransactionOrder.class).flagAndAlert("skipped: " + skipped);
|
||||
|
||||
do {
|
||||
data = transactionsSent.poll();
|
||||
@@ -347,9 +325,9 @@ public class GrimPlayer implements GrimUser {
|
||||
|
||||
lastTransactionReceived.incrementAndGet();
|
||||
lastTransReceived = System.currentTimeMillis();
|
||||
transactionPing = (System.nanoTime() - data.second());
|
||||
playerClockAtLeast = data.second();
|
||||
} while (data.first() != id);
|
||||
transactionPing = (System.nanoTime() - data.getSecond());
|
||||
playerClockAtLeast = data.getSecond();
|
||||
} while (data.getFirst() != id);
|
||||
|
||||
// A transaction means a new tick, so apply any block places
|
||||
CheckManagerListener.handleQueuedPlaces(this, false, 0, 0, System.currentTimeMillis());
|
||||
@@ -357,7 +335,7 @@ public class GrimPlayer implements GrimUser {
|
||||
}
|
||||
|
||||
// Were we the ones who sent the packet?
|
||||
return data != null && data.first() == id;
|
||||
return data != null && data.getFirst() == id;
|
||||
}
|
||||
|
||||
public void baseTickAddWaterPushing(Vector vector) {
|
||||
@@ -443,7 +421,8 @@ public class GrimPlayer implements GrimUser {
|
||||
|
||||
public void disconnect(Component reason) {
|
||||
String textReason;
|
||||
if (reason instanceof TranslatableComponent translatableComponent) {
|
||||
if (reason instanceof TranslatableComponent) {
|
||||
TranslatableComponent translatableComponent = (TranslatableComponent) reason;
|
||||
textReason = translatableComponent.key();
|
||||
} else {
|
||||
textReason = LegacyComponentSerializer.legacySection().serialize(reason);
|
||||
@@ -471,7 +450,7 @@ public class GrimPlayer implements GrimUser {
|
||||
if (lastTransSent != 0 && lastTransSent + 80 < System.currentTimeMillis()) {
|
||||
sendTransaction(true); // send on netty thread
|
||||
}
|
||||
if ((System.nanoTime() - getPlayerClockAtLeast()) > maxTransactionTime * 1e9) {
|
||||
if ((System.nanoTime() - getPlayerClockAtLeast()) > GrimAPI.INSTANCE.getConfigManager().getMaxPingTransaction() * 1e9) {
|
||||
timedOut();
|
||||
}
|
||||
|
||||
@@ -525,17 +504,14 @@ public class GrimPlayer implements GrimUser {
|
||||
if (bukkitPlayer == null) return;
|
||||
this.noModifyPacketPermission = bukkitPlayer.hasPermission("grim.nomodifypacket");
|
||||
this.noSetbackPermission = bukkitPlayer.hasPermission("grim.nosetback");
|
||||
FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(), t -> {
|
||||
for (AbstractCheck check : checkManager.allChecks.values()) {
|
||||
if (check instanceof Check) {
|
||||
((Check) check).updateExempted();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private int spamThreshold = 100;
|
||||
|
||||
public void onReload() {
|
||||
spamThreshold = GrimAPI.INSTANCE.getConfigManager().getConfig().getIntElse("packet-spam-threshold", 100);
|
||||
}
|
||||
|
||||
public boolean isPointThree() {
|
||||
return getClientVersion().isOlderThan(ClientVersion.V_1_18_2);
|
||||
}
|
||||
@@ -565,7 +541,7 @@ 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)
|
||||
return (getClientVersion().isOlderThan(ClientVersion.V_1_9)
|
||||
|| !uncertaintyHandler.lastPointThree.hasOccurredSince(ticks))
|
||||
|| compensatedEntities.getSelf().inVehicle();
|
||||
}
|
||||
@@ -578,23 +554,14 @@ public class GrimPlayer implements GrimUser {
|
||||
return checkManager.getInventory();
|
||||
}
|
||||
|
||||
public double[] getPossibleEyeHeights() { // We don't return sleeping eye height
|
||||
// 1.8 Players once again ruin my clean switch-case
|
||||
if (this.getClientVersion().isOlderThan(ClientVersion.V_1_9)) {
|
||||
return this.isSneaking ? this.possibleEyeHeights[1] : this.possibleEyeHeights[0];
|
||||
} else {
|
||||
// 1.8 players just have their pose set to standing all the time
|
||||
switch (pose) {
|
||||
case FALL_FLYING: // Elytra gliding
|
||||
case SPIN_ATTACK: // Riptide trident
|
||||
case SWIMMING: // Swimming (includes crawling in 1.14+)
|
||||
return this.possibleEyeHeights[2]; // [swimming/gliding/riptide height, standing height, sneaking height]
|
||||
case NINE_CROUCHING:
|
||||
case CROUCHING:
|
||||
return this.possibleEyeHeights[1]; // [sneaking height, standing height, swimming/gliding/riptide height]
|
||||
default:
|
||||
return this.possibleEyeHeights[0]; // [standing height, sneaking height, swimming/gliding/riptide height]
|
||||
}
|
||||
public List<Double> getPossibleEyeHeights() { // We don't return sleeping eye height
|
||||
if (getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14)) { // Elytra, sneaking (1.14), standing
|
||||
final float scale = (float) compensatedEntities.getSelf().getAttributeValue(Attributes.GENERIC_SCALE);
|
||||
return Arrays.asList(0.4 * scale, 1.27 * scale, 1.62 * scale);
|
||||
} else if (getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)) { // Elytra, sneaking, standing
|
||||
return Arrays.asList(0.4, 1.54, 1.62);
|
||||
} else { // Only sneaking or standing
|
||||
return Arrays.asList((double) (1.62f - 0.08f), (double) (1.62f));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -742,31 +709,10 @@ public class GrimPlayer implements GrimUser {
|
||||
return checkManager.allChecks.values();
|
||||
}
|
||||
|
||||
|
||||
public void runNettyTaskInMs(Runnable runnable, int ms) {
|
||||
Channel channel = (Channel) user.getChannel();
|
||||
channel.eventLoop().schedule(runnable, ms, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private int maxTransactionTime = 60;
|
||||
@Getter private boolean ignoreDuplicatePacketRotation = false;
|
||||
@Getter private boolean experimentalChecks = false;
|
||||
@Getter private boolean cancelDuplicatePacket = true;
|
||||
|
||||
@Override
|
||||
public void reload(ConfigManager config) {
|
||||
spamThreshold = config.getIntElse("packet-spam-threshold", 100);
|
||||
maxTransactionTime = (int) GrimMath.clamp(config.getIntElse("max-transaction-time", 60), 1, 180);
|
||||
experimentalChecks = config.getBooleanElse("experimental-checks", false);
|
||||
ignoreDuplicatePacketRotation = config.getBooleanElse("ignore-duplicate-packet-rotation", false);
|
||||
cancelDuplicatePacket = config.getBooleanElse("cancel-duplicate-packet", true);
|
||||
// reload all checks
|
||||
for (AbstractCheck value : checkManager.allChecks.values()) value.reload(config);
|
||||
// reload punishment manager
|
||||
punishmentManager.reload(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
reload(GrimAPI.INSTANCE.getConfigManager().getConfig());
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.update.PredictionComplete;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntity;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
|
||||
public class GhostBlockDetector extends Check implements PostPredictionCheck {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package ac.grim.grimac.predictionengine;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.impl.movement.EntityControl;
|
||||
import ac.grim.grimac.checks.impl.prediction.Phase;
|
||||
@@ -22,6 +22,7 @@ import ac.grim.grimac.utils.data.packetentity.PacketEntityHorse;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntityRideable;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntityTrackXRot;
|
||||
import ac.grim.grimac.utils.enums.Pose;
|
||||
import ac.grim.grimac.utils.inventory.EnchantmentHelper;
|
||||
import ac.grim.grimac.utils.latency.CompensatedWorld;
|
||||
import ac.grim.grimac.utils.math.GrimMath;
|
||||
import ac.grim.grimac.utils.math.VectorUtils;
|
||||
@@ -31,6 +32,7 @@ import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.protocol.item.enchantment.type.EnchantmentTypes;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
@@ -258,7 +260,8 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
// When in control of the entity, the player sets the entity position to their current position
|
||||
riding.setPositionRaw(GetBoundingBox.getPacketEntityBoundingBox(player, player.x, player.y, player.z, riding));
|
||||
|
||||
if (riding instanceof PacketEntityTrackXRot boat) {
|
||||
if (riding instanceof PacketEntityTrackXRot) {
|
||||
PacketEntityTrackXRot boat = (PacketEntityTrackXRot) riding;
|
||||
boat.packetYaw = player.xRot;
|
||||
boat.interpYaw = player.xRot;
|
||||
boat.steps = 0;
|
||||
@@ -338,7 +341,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
boolean clientClaimsRiptide = player.packetStateData.tryingToRiptide;
|
||||
if (player.packetStateData.tryingToRiptide) {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
boolean isInWater = player.compensatedWorld.isRaining || Collisions.hasMaterial(player, player.boundingBox.copy().expand(0.1f), (block) -> Materials.isWater(CompensatedWorld.blockVersion, block.first()));
|
||||
boolean isInWater = player.compensatedWorld.isRaining || Collisions.hasMaterial(player, player.boundingBox.copy().expand(0.1f), (block) -> Materials.isWater(CompensatedWorld.blockVersion, block.getFirst()));
|
||||
|
||||
if (currentTime - player.packetStateData.lastRiptide < 450 || !isInWater) {
|
||||
player.packetStateData.tryingToRiptide = false;
|
||||
@@ -349,7 +352,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
|
||||
SimpleCollisionBox steppingOnBB = GetBoundingBox.getCollisionBoxForPlayer(player, player.x, player.y, player.z).expand(0.03).offset(0, -1, 0);
|
||||
Collisions.hasMaterial(player, steppingOnBB, (pair) -> {
|
||||
WrappedBlockState data = pair.first();
|
||||
WrappedBlockState data = pair.getFirst();
|
||||
if (data.getType() == StateTypes.SLIME_BLOCK && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8)) {
|
||||
player.uncertaintyHandler.isSteppingOnSlime = true;
|
||||
player.uncertaintyHandler.isSteppingOnBouncyBlock = true;
|
||||
@@ -361,7 +364,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
}
|
||||
player.uncertaintyHandler.isSteppingOnHoney = true;
|
||||
}
|
||||
if (BlockTags.BEDS.contains(data.getType()) && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_12)) {
|
||||
if (BlockTags.BEDS.contains(data.getType()) && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8)) {
|
||||
player.uncertaintyHandler.isSteppingOnBouncyBlock = true;
|
||||
}
|
||||
if (BlockTags.ICE.contains(data.getType())) {
|
||||
@@ -395,8 +398,8 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
|
||||
player.uncertaintyHandler.isNearGlitchyBlock = player.getClientVersion().isOlderThan(ClientVersion.V_1_9)
|
||||
&& Collisions.hasMaterial(player, expandedBB.copy().expand(0.2),
|
||||
checkData -> BlockTags.ANVIL.contains(checkData.first().getType())
|
||||
|| checkData.first().getType() == StateTypes.CHEST || checkData.first().getType() == StateTypes.TRAPPED_CHEST);
|
||||
checkData -> BlockTags.ANVIL.contains(checkData.getFirst().getType())
|
||||
|| checkData.getFirst().getType() == StateTypes.CHEST || checkData.getFirst().getType() == StateTypes.TRAPPED_CHEST);
|
||||
|
||||
player.uncertaintyHandler.isOrWasNearGlitchyBlock = isGlitchy || player.uncertaintyHandler.isNearGlitchyBlock;
|
||||
player.uncertaintyHandler.checkForHardCollision();
|
||||
@@ -541,7 +544,8 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
player.checkManager.onPredictionFinish(new PredictionComplete(offset, update, wasChecked));
|
||||
|
||||
// Patch sprint jumping with elytra exploit
|
||||
if (player.bukkitPlayer != null && player.isGliding && player.predictedVelocity.isJump() && player.isSprinting && !allowSprintJumpingWithElytra) {
|
||||
if (player.bukkitPlayer != null && player.isGliding && player.predictedVelocity.isJump() && player.isSprinting
|
||||
&& !GrimAPI.INSTANCE.getConfigManager().getConfig().getBooleanElse("exploit.allow-sprint-jumping-when-using-elytra", true)) {
|
||||
SetbackTeleportUtil.SetbackPosWithVector lastKnownGoodPosition = player.getSetbackTeleportUtil().lastKnownGoodPosition;
|
||||
lastKnownGoodPosition.setVector(lastKnownGoodPosition.getVector().multiply(new Vector(0.6 * 0.91, 1, 0.6 * 0.91)));
|
||||
player.getSetbackTeleportUtil().executeNonSimulatingSetback();
|
||||
@@ -631,12 +635,4 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
// (Patches issues with slime and other desync's)
|
||||
return riptideDiffToGround < riptideDiffToBase;
|
||||
}
|
||||
|
||||
private boolean allowSprintJumpingWithElytra = true;
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
allowSprintJumpingWithElytra = config.getBooleanElse("exploit.allow-sprint-jumping-when-using-elytra", true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package ac.grim.grimac.predictionengine;
|
||||
|
||||
import ac.grim.grimac.checks.impl.movement.NoSlowC;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.attribute.ValuedAttribute;
|
||||
@@ -15,10 +16,9 @@ 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.World;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class PlayerBaseTick {
|
||||
GrimPlayer player;
|
||||
|
||||
@@ -87,6 +87,8 @@ public class PlayerBaseTick {
|
||||
|
||||
if (player.compensatedEntities.getSelf().inVehicle()) player.isSlowMovement = false;
|
||||
|
||||
if (wasSlowMovement != player.isSlowMovement) player.checkManager.getPostPredictionCheck(NoSlowC.class).startedSprintingBeforeSlowMovement = player.isSlowMovement && player.isSprinting;
|
||||
|
||||
// Players in boats don't care about being in blocks
|
||||
if (!player.compensatedEntities.getSelf().inVehicle()) {
|
||||
this.moveTowardsClosestSpace(player.lastX - (player.boundingBox.maxX - player.boundingBox.minX) * 0.35, player.lastZ + (player.boundingBox.maxZ - player.boundingBox.minZ) * 0.35);
|
||||
@@ -147,14 +149,9 @@ public class PlayerBaseTick {
|
||||
// Pre-1.17 clients don't have powder snow and therefore don't desync
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_16_4)) return;
|
||||
|
||||
final ValuedAttribute playerSpeed = player.compensatedEntities.getSelf().getAttribute(Attributes.GENERIC_MOVEMENT_SPEED).get();
|
||||
|
||||
// Might be null after respawn?
|
||||
final Optional<WrapperPlayServerUpdateAttributes.Property> property = playerSpeed.property();
|
||||
if (property.isEmpty()) return;
|
||||
|
||||
// The client first desync's this attribute
|
||||
property.get().getModifiers().removeIf(modifier -> modifier.getUUID().equals(CompensatedEntities.SNOW_MODIFIER_UUID) || modifier.getName().getKey().equals("powder_snow"));
|
||||
final ValuedAttribute playerSpeed = player.compensatedEntities.getSelf().getAttribute(Attributes.GENERIC_MOVEMENT_SPEED).get();
|
||||
playerSpeed.property().get().getModifiers().removeIf(modifier -> modifier.getUUID().equals(CompensatedEntities.SNOW_MODIFIER_UUID) || modifier.getName().getKey().equals("powder_snow"));
|
||||
playerSpeed.recalculate();
|
||||
|
||||
// And then re-adds it using purely what the server has sent it
|
||||
@@ -168,7 +165,7 @@ public class PlayerBaseTick {
|
||||
float percentFrozen = (float) Math.min(i, ticksToFreeze) / (float) ticksToFreeze;
|
||||
float percentFrozenReducedToSpeed = -0.05F * percentFrozen;
|
||||
|
||||
property.get().getModifiers().add(new WrapperPlayServerUpdateAttributes.PropertyModifier(CompensatedEntities.SNOW_MODIFIER_UUID, percentFrozenReducedToSpeed, WrapperPlayServerUpdateAttributes.PropertyModifier.Operation.ADDITION));
|
||||
playerSpeed.property().get().getModifiers().add(new WrapperPlayServerUpdateAttributes.PropertyModifier(CompensatedEntities.SNOW_MODIFIER_UUID, percentFrozenReducedToSpeed, WrapperPlayServerUpdateAttributes.PropertyModifier.Operation.ADDITION));
|
||||
playerSpeed.recalculate();
|
||||
}
|
||||
}
|
||||
@@ -360,12 +357,22 @@ public class PlayerBaseTick {
|
||||
double d7 = direction2 == BlockFace.WEST || direction2 == BlockFace.EAST ? relativeXMovement : relativeZMovement;
|
||||
d6 = direction2 == BlockFace.EAST || direction2 == BlockFace.SOUTH ? 1.0 - d7 : d7;
|
||||
// d7 and d6 flip the movement direction based on desired movement direction
|
||||
boolean doesSuffocate = switch (direction2) {
|
||||
case EAST -> this.suffocatesAt(blockX + 1, blockZ);
|
||||
case WEST -> this.suffocatesAt(blockX - 1, blockZ);
|
||||
case NORTH -> this.suffocatesAt(blockX, blockZ - 1);
|
||||
default -> this.suffocatesAt(blockX, blockZ + 1);
|
||||
};
|
||||
boolean doesSuffocate;
|
||||
switch (direction2) {
|
||||
case EAST:
|
||||
doesSuffocate = this.suffocatesAt(blockX + 1, blockZ);
|
||||
break;
|
||||
case WEST:
|
||||
doesSuffocate = this.suffocatesAt(blockX - 1, blockZ);
|
||||
break;
|
||||
case NORTH:
|
||||
doesSuffocate = this.suffocatesAt(blockX, blockZ - 1);
|
||||
break;
|
||||
default:
|
||||
case SOUTH:
|
||||
doesSuffocate = this.suffocatesAt(blockX, blockZ + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (d6 >= lowestValue || doesSuffocate) continue;
|
||||
lowestValue = d6;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ac.grim.grimac.predictionengine;
|
||||
|
||||
import ac.grim.grimac.checks.impl.combat.Reach;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.predictionengine.predictions.PredictionEngine;
|
||||
import ac.grim.grimac.utils.collisions.CollisionData;
|
||||
@@ -16,6 +17,7 @@ import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState
|
||||
import com.github.retrooper.packetevents.protocol.world.states.defaulttags.BlockTags;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.util.Vector;
|
||||
@@ -151,6 +153,8 @@ public class PointThreeEstimator {
|
||||
isNearFluid = true;
|
||||
}
|
||||
|
||||
player.checkManager.getPacketCheck(Reach.class).handleBlockChange(new Vector3i(x, y, z), state);
|
||||
|
||||
if (pointThreeBox.isIntersected(new SimpleCollisionBox(x, y, z))) {
|
||||
// https://github.com/MWHunter/Grim/issues/613
|
||||
int controllingEntityId = player.compensatedEntities.getSelf().inVehicle() ? player.getRidingVehicleId() : player.entityID;
|
||||
@@ -248,21 +252,21 @@ public class PointThreeEstimator {
|
||||
|
||||
// Check for flowing water
|
||||
Collisions.hasMaterial(player, pointThreeBox, (pair) -> {
|
||||
final WrappedBlockState state = pair.first();
|
||||
final WrappedBlockState state = pair.getFirst();
|
||||
final StateType stateType = state.getType();
|
||||
if (player.tagManager.block(SyncedTags.CLIMBABLE).contains(stateType) || (stateType == StateTypes.POWDER_SNOW && !player.compensatedEntities.getSelf().inVehicle() && player.getInventory().getBoots().getType() == ItemTypes.LEATHER_BOOTS)) {
|
||||
isNearClimbable = true;
|
||||
}
|
||||
|
||||
if (BlockTags.TRAPDOORS.contains(stateType)) {
|
||||
isNearClimbable = isNearClimbable || Collisions.trapdoorUsableAsLadder(player, pair.second().getX(), pair.second().getY(), pair.second().getZ(), state);
|
||||
isNearClimbable = isNearClimbable || Collisions.trapdoorUsableAsLadder(player, pair.getSecond().getX(), pair.getSecond().getY(), pair.getSecond().getZ(), state);
|
||||
}
|
||||
|
||||
if (stateType == StateTypes.BUBBLE_COLUMN) {
|
||||
isNearBubbleColumn = true;
|
||||
}
|
||||
|
||||
if (Materials.isWater(player.getClientVersion(), pair.first()) || pair.first().getType() == StateTypes.LAVA) {
|
||||
if (Materials.isWater(player.getClientVersion(), pair.getFirst()) || pair.getFirst().getType() == StateTypes.LAVA) {
|
||||
isNearFluid = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package ac.grim.grimac.predictionengine;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.type.PostPredictionCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.predictionengine.predictions.PredictionEngine;
|
||||
import ac.grim.grimac.utils.anticheat.update.PredictionComplete;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.VectorData;
|
||||
|
||||
@@ -303,7 +303,8 @@ public class UncertaintyHandler {
|
||||
// This is the end of that section.
|
||||
|
||||
// I can't figure out how the client exactly tracks boost time
|
||||
if (player.compensatedEntities.getSelf().getRiding() instanceof PacketEntityRideable vehicle) {
|
||||
if (player.compensatedEntities.getSelf().getRiding() instanceof PacketEntityRideable) {
|
||||
PacketEntityRideable vehicle = (PacketEntityRideable) player.compensatedEntities.getSelf().getRiding();
|
||||
if (vehicle.currentBoostTime < vehicle.boostTimeMax + 20)
|
||||
offset -= 0.01;
|
||||
}
|
||||
@@ -338,9 +339,10 @@ public class UncertaintyHandler {
|
||||
private boolean striderCollision(SimpleCollisionBox expandedBB) {
|
||||
// Stiders can walk on top of other striders
|
||||
if (player.compensatedEntities.getSelf().getRiding() instanceof PacketEntityStrider) {
|
||||
for (PacketEntity entity : player.compensatedEntities.entityMap.values()) {
|
||||
if (entity.getType() == EntityTypes.STRIDER && entity != player.compensatedEntities.getSelf().getRiding()
|
||||
&& !entity.hasPassenger(entity) && entity.getPossibleCollisionBoxes().isIntersected(expandedBB)) {
|
||||
for (Map.Entry<Integer, PacketEntity> entityPair : player.compensatedEntities.entityMap.int2ObjectEntrySet()) {
|
||||
PacketEntity entity = entityPair.getValue();
|
||||
if (entity.getType() == EntityTypes.STRIDER && entity != player.compensatedEntities.getSelf().getRiding() && !entity.hasPassenger(entityPair.getValue())
|
||||
&& entity.getPossibleCollisionBoxes().isIntersected(expandedBB)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -354,9 +356,9 @@ public class UncertaintyHandler {
|
||||
final PacketEntity riding = player.compensatedEntities.getSelf().getRiding();
|
||||
if (riding == null || !riding.isBoat()) return false;
|
||||
|
||||
for (PacketEntity entity : player.compensatedEntities.entityMap.values()) {
|
||||
if (entity != riding && entity.isPushable() && !riding.hasPassenger(entity)
|
||||
&& entity.getPossibleCollisionBoxes().isIntersected(expandedBB)) {
|
||||
for (Map.Entry<Integer, PacketEntity> entityPair : player.compensatedEntities.entityMap.int2ObjectEntrySet()) {
|
||||
PacketEntity entity = entityPair.getValue();
|
||||
if (entity != riding && entity.isPushable() && !riding.hasPassenger(entityPair.getValue()) && entity.getPossibleCollisionBoxes().isIntersected(expandedBB)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.github.retrooper.packetevents.protocol.world.states.defaulttags.Block
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import org.bukkit.Bukkit;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import io.github.retrooper.packetevents.util.viaversion.ViaVersionUtil;
|
||||
import org.bukkit.util.Vector;
|
||||
@@ -417,4 +418,4 @@ public class MovementTicker {
|
||||
public boolean canStandOnLava() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-35
@@ -1,20 +1,14 @@
|
||||
package ac.grim.grimac.predictionengine.movementtick;
|
||||
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.data.attribute.ValuedAttribute;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntityStrider;
|
||||
import ac.grim.grimac.utils.nmsutil.BlockProperties;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.defaulttags.BlockTags;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.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;
|
||||
|
||||
public class MovementTickerStrider extends MovementTickerRideable {
|
||||
|
||||
public MovementTickerStrider(GrimPlayer player) {
|
||||
@@ -40,45 +34,21 @@ public class MovementTickerStrider extends MovementTickerRideable {
|
||||
public void livingEntityAIStep() {
|
||||
super.livingEntityAIStep();
|
||||
|
||||
((PacketEntityStrider) player.compensatedEntities.getSelf().getRiding()).isShaking = true;
|
||||
|
||||
StateType posMaterial = player.compensatedWorld.getStateTypeAt(player.x, player.y, player.z);
|
||||
StateType belowMaterial = BlockProperties.getOnPos(player, player.mainSupportingBlockData, new Vector3d(player.x, player.y, player.z));
|
||||
|
||||
final PacketEntityStrider strider = (PacketEntityStrider) player.compensatedEntities.getSelf().getRiding();
|
||||
strider.isShaking = !BlockTags.STRIDER_WARM_BLOCKS.contains(posMaterial) &&
|
||||
((PacketEntityStrider) player.compensatedEntities.getSelf().getRiding()).isShaking =
|
||||
!BlockTags.STRIDER_WARM_BLOCKS.contains(posMaterial) &&
|
||||
!BlockTags.STRIDER_WARM_BLOCKS.contains(belowMaterial) &&
|
||||
!player.wasTouchingLava;
|
||||
}
|
||||
|
||||
private static final WrapperPlayServerUpdateAttributes.PropertyModifier SUFFOCATING_MODIFIER = new WrapperPlayServerUpdateAttributes.PropertyModifier(
|
||||
ResourceLocation.minecraft("suffocating"), -0.34F, WrapperPlayServerUpdateAttributes.PropertyModifier.Operation.MULTIPLY_BASE);
|
||||
|
||||
@Override
|
||||
public float getSteeringSpeed() {
|
||||
PacketEntityStrider strider = (PacketEntityStrider) player.compensatedEntities.getSelf().getRiding();
|
||||
// Unsure which version the speed changed in
|
||||
final boolean newSpeed = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_20);
|
||||
final float coldSpeed = newSpeed ? 0.35F : 0.23F;
|
||||
|
||||
// Client desyncs the attribute
|
||||
// Again I don't know when this was changed, or whether it always existed, so I will just put it behind 1.20+
|
||||
final ValuedAttribute movementSpeedAttr = strider.getAttribute(Attributes.GENERIC_MOVEMENT_SPEED).get();
|
||||
float updatedMovementSpeed = (float) movementSpeedAttr.get();
|
||||
if (newSpeed) {
|
||||
final WrapperPlayServerUpdateAttributes.Property lastProperty = movementSpeedAttr.property().orElse(null);
|
||||
if (lastProperty != null && (!strider.isShaking || lastProperty.getModifiers().stream().noneMatch(mod -> mod.getName().getKey().equals("suffocating")))) {
|
||||
WrapperPlayServerUpdateAttributes.Property newProperty = new WrapperPlayServerUpdateAttributes.Property(lastProperty.getAttribute(), lastProperty.getValue(), new ArrayList<>(lastProperty.getModifiers()));
|
||||
if (!strider.isShaking) {
|
||||
newProperty.getModifiers().removeIf(modifier -> modifier.getName().getKey().equals("suffocating"));
|
||||
} else {
|
||||
newProperty.getModifiers().add(SUFFOCATING_MODIFIER);
|
||||
}
|
||||
movementSpeedAttr.with(newProperty);
|
||||
updatedMovementSpeed = (float) movementSpeedAttr.get();
|
||||
movementSpeedAttr.with(lastProperty);
|
||||
}
|
||||
}
|
||||
|
||||
return updatedMovementSpeed * (strider.isShaking ? coldSpeed : 0.55F);
|
||||
return (float) strider.getAttributeValue(Attributes.GENERIC_MOVEMENT_SPEED) * (strider.isShaking ? 0.23F : 0.55F);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -12,6 +12,7 @@ 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 com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
@@ -133,8 +134,8 @@ public class PredictionEngine {
|
||||
|
||||
// Returns pair of primary push movement, and then outputvel
|
||||
Pair<Vector, Vector> output = doSeekingWallCollisions(player, primaryPushMovement, originalClientVel, clientVelAfterInput);
|
||||
primaryPushMovement = output.first();
|
||||
Vector outputVel = clampMovementToHardBorder(player, output.second());
|
||||
primaryPushMovement = output.getFirst();
|
||||
Vector outputVel = clampMovementToHardBorder(player, output.getSecond());
|
||||
|
||||
double resultAccuracy = outputVel.distanceSquared(player.actualMovement);
|
||||
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ public class PredictionEngineNormal extends PredictionEngine {
|
||||
// And 0.03 didn't affect onGround status
|
||||
// The player cannot jump
|
||||
final OptionalInt jumpBoost = player.compensatedEntities.getPotionLevelForPlayer(PotionTypes.JUMP_BOOST);
|
||||
if (((jumpBoost.isEmpty() || jumpBoost.getAsInt() >= 0) && player.onGround) || !player.lastOnGround)
|
||||
if (((!jumpBoost.isPresent() || jumpBoost.getAsInt() >= 0) && player.onGround) || !player.lastOnGround)
|
||||
return;
|
||||
|
||||
JumpPower.jumpFromGround(player, jump);
|
||||
|
||||
+3
-1
@@ -17,7 +17,9 @@ import java.util.Set;
|
||||
|
||||
public class PredictionEngineRideableUtils {
|
||||
public static Set<VectorData> handleJumps(GrimPlayer player, Set<VectorData> possibleVectors) {
|
||||
if (!(player.compensatedEntities.getSelf().getRiding() instanceof PacketEntityHorse horse)) return possibleVectors;
|
||||
if (!(player.compensatedEntities.getSelf().getRiding() instanceof PacketEntityHorse)) return possibleVectors;
|
||||
|
||||
PacketEntityHorse horse = (PacketEntityHorse) player.compensatedEntities.getSelf().getRiding();
|
||||
|
||||
// Setup player inputs
|
||||
float f = player.vehicleData.vehicleHorizontal * 0.5F;
|
||||
|
||||
@@ -3,8 +3,6 @@ package ac.grim.grimac.utils.anticheat;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.util.Vector3f;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
|
||||
@@ -13,13 +11,6 @@ import java.util.regex.Pattern;
|
||||
|
||||
@UtilityClass
|
||||
public class MessageUtil {
|
||||
public String toUnlabledString(Vector3i vec) {
|
||||
return vec == null ? "null" : vec.x + ", " + vec.y + ", " + vec.z;
|
||||
}
|
||||
|
||||
public String toUnlabledString(Vector3f vec) {
|
||||
return vec == null ? "null" : vec.x + ", " + vec.y + ", " + vec.z;
|
||||
}
|
||||
|
||||
public String format(String string) {
|
||||
string = formatWithNoColor(string);
|
||||
@@ -29,14 +20,13 @@ public class MessageUtil {
|
||||
}
|
||||
|
||||
public String formatWithNoColor(String string) {
|
||||
return string.replace("%prefix%", GrimAPI.INSTANCE.getConfigManager().getPrefix());
|
||||
return string.replace("%prefix%", GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("prefix", "&bGrim &8»"));
|
||||
}
|
||||
|
||||
private static final Pattern HEX_PATTERN = Pattern.compile("#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})");
|
||||
|
||||
private String translateHexCodes(String message) {
|
||||
Matcher matcher = HEX_PATTERN.matcher(message);
|
||||
StringBuilder sb = new StringBuilder(message.length());
|
||||
final String hexPattern = "#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})";
|
||||
Matcher matcher = Pattern.compile(hexPattern).matcher(message);
|
||||
StringBuffer sb = new StringBuffer(message.length());
|
||||
while (matcher.find()) {
|
||||
String hex = matcher.group(1);
|
||||
ChatColor color = ChatColor.of("#" + hex);
|
||||
@@ -45,5 +35,4 @@ public class MessageUtil {
|
||||
matcher.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,7 +7,6 @@ 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;
|
||||
@@ -38,6 +37,7 @@ import lombok.Setter;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@@ -72,9 +72,6 @@ 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;
|
||||
@@ -203,12 +200,12 @@ public class BlockPlace {
|
||||
if (BlockTags.LEAVES.contains(data.getType())) return false;
|
||||
if (BlockTags.FENCE_GATES.contains(data.getType())) return false;
|
||||
|
||||
int size = box.downCast(collisions);
|
||||
List<SimpleCollisionBox> collisions = new ArrayList<>();
|
||||
box.downCast(collisions);
|
||||
|
||||
AxisSelect axis = AxisUtil.getAxis(facing.getOppositeFace());
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
SimpleCollisionBox simpleBox = collisions[i];
|
||||
for (SimpleCollisionBox simpleBox : collisions) {
|
||||
simpleBox = axis.modify(simpleBox);
|
||||
if (simpleBox.minX <= 7 / 16d && simpleBox.maxX >= 7 / 16d
|
||||
&& simpleBox.minY <= 0 && simpleBox.maxY >= 10 / 16d
|
||||
@@ -228,12 +225,12 @@ public class BlockPlace {
|
||||
if (isFullFace(facing)) return true;
|
||||
if (BlockTags.LEAVES.contains(data.getType())) return false;
|
||||
|
||||
int size = box.downCast(collisions);
|
||||
List<SimpleCollisionBox> collisions = new ArrayList<>();
|
||||
box.downCast(collisions);
|
||||
|
||||
AxisSelect axis = AxisUtil.getAxis(facing.getOppositeFace());
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
SimpleCollisionBox simpleBox = collisions[i];
|
||||
for (SimpleCollisionBox simpleBox : collisions) {
|
||||
simpleBox = axis.modify(simpleBox);
|
||||
if (simpleBox.minX <= 2 / 16d && simpleBox.maxX >= 14 / 16d
|
||||
&& simpleBox.minY <= 0 && simpleBox.maxY >= 1
|
||||
@@ -292,10 +289,10 @@ public class BlockPlace {
|
||||
}
|
||||
}
|
||||
|
||||
int size = box.downCast(collisions);
|
||||
List<SimpleCollisionBox> collisions = new ArrayList<>();
|
||||
box.downCast(collisions);
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
SimpleCollisionBox simpleBox = collisions[i];
|
||||
for (SimpleCollisionBox simpleBox : collisions) {
|
||||
if (axis.modify(simpleBox).isFullBlockNoCache()) return true;
|
||||
}
|
||||
|
||||
@@ -321,12 +318,12 @@ public class BlockPlace {
|
||||
if (isFullFace(facing)) return true;
|
||||
if (BlockTags.LEAVES.contains(data.getType())) return false;
|
||||
|
||||
int size = box.downCast(collisions);
|
||||
List<SimpleCollisionBox> collisions = new ArrayList<>();
|
||||
box.downCast(collisions);
|
||||
|
||||
AxisSelect axis = AxisUtil.getAxis(facing.getOppositeFace());
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
SimpleCollisionBox simpleBox = collisions[i];
|
||||
for (SimpleCollisionBox simpleBox : collisions) {
|
||||
simpleBox = axis.modify(simpleBox);
|
||||
// If all sides to the box have width, there is collision.
|
||||
switch (facing) {
|
||||
@@ -540,14 +537,21 @@ public class BlockPlace {
|
||||
}
|
||||
|
||||
public Vector3i getNormalBlockFace() {
|
||||
return switch (face) {
|
||||
case DOWN -> new Vector3i(0, -1, 0);
|
||||
case SOUTH -> new Vector3i(0, 0, 1);
|
||||
case NORTH -> new Vector3i(0, 0, -1);
|
||||
case WEST -> new Vector3i(-1, 0, 0);
|
||||
case EAST -> new Vector3i(1, 0, 0);
|
||||
default -> new Vector3i(0, 1, 0);
|
||||
};
|
||||
switch (face) {
|
||||
default:
|
||||
case UP:
|
||||
return new Vector3i(0, 1, 0);
|
||||
case DOWN:
|
||||
return new Vector3i(0, -1, 0);
|
||||
case SOUTH:
|
||||
return new Vector3i(0, 0, 1);
|
||||
case NORTH:
|
||||
return new Vector3i(0, 0, -1);
|
||||
case WEST:
|
||||
return new Vector3i(-1, 0, 0);
|
||||
case EAST:
|
||||
return new Vector3i(1, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void set(StateType material) {
|
||||
@@ -668,7 +672,7 @@ public class BlockPlace {
|
||||
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();
|
||||
Vector intercept = ReachUtils.calculateIntercept(box, eyePos, endReachPos).getFirst();
|
||||
|
||||
// Bring this back to relative to the block
|
||||
// The player didn't even click the block... (we should force resync BEFORE we get here!)
|
||||
|
||||
@@ -16,4 +16,4 @@ public final class PositionUpdate {
|
||||
private final SetBackData setback;
|
||||
private final TeleportData teleportData;
|
||||
private boolean isTeleport;
|
||||
}
|
||||
}
|
||||
@@ -107,11 +107,17 @@ public class ConsumesBlockPlace {
|
||||
Attachment attachment = bell.getAttachment();
|
||||
BlockFace dir2 = BlockFace.valueOf(direction.name());
|
||||
|
||||
return switch (attachment) {
|
||||
case FLOOR -> AxisUtil.isSameAxis(dir, dir2);
|
||||
case SINGLE_WALL, DOUBLE_WALL -> !AxisUtil.isSameAxis(dir, dir2);
|
||||
case CEILING -> true;
|
||||
};
|
||||
switch (attachment) {
|
||||
case FLOOR:
|
||||
return AxisUtil.isSameAxis(dir, dir2);
|
||||
case SINGLE_WALL:
|
||||
case DOUBLE_WALL:
|
||||
return !AxisUtil.isSameAxis(dir, dir2);
|
||||
case CEILING:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -18,42 +18,64 @@ public class BlockFaceHelper {
|
||||
*/
|
||||
@Deprecated
|
||||
public static BlockFace fromBukkitFace(org.bukkit.block.BlockFace face) {
|
||||
return switch (face) {
|
||||
case NORTH -> BlockFace.NORTH;
|
||||
case SOUTH -> BlockFace.SOUTH;
|
||||
case WEST -> BlockFace.WEST;
|
||||
case EAST -> BlockFace.EAST;
|
||||
case UP -> BlockFace.UP;
|
||||
case DOWN -> BlockFace.DOWN;
|
||||
default -> BlockFace.OTHER;
|
||||
};
|
||||
switch (face) {
|
||||
case NORTH:
|
||||
return BlockFace.NORTH;
|
||||
case SOUTH:
|
||||
return BlockFace.SOUTH;
|
||||
case WEST:
|
||||
return BlockFace.WEST;
|
||||
case EAST:
|
||||
return BlockFace.EAST;
|
||||
case UP:
|
||||
return BlockFace.UP;
|
||||
case DOWN:
|
||||
return BlockFace.DOWN;
|
||||
default:
|
||||
return BlockFace.OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
public static BlockFace getClockWise(BlockFace face) {
|
||||
return switch (face) {
|
||||
case NORTH -> BlockFace.EAST;
|
||||
case SOUTH -> BlockFace.WEST;
|
||||
case WEST -> BlockFace.NORTH;
|
||||
default -> BlockFace.SOUTH;
|
||||
};
|
||||
switch (face) {
|
||||
case NORTH:
|
||||
return BlockFace.EAST;
|
||||
case SOUTH:
|
||||
return BlockFace.WEST;
|
||||
case WEST:
|
||||
return BlockFace.NORTH;
|
||||
case EAST:
|
||||
default:
|
||||
return BlockFace.SOUTH;
|
||||
}
|
||||
}
|
||||
|
||||
public static BlockFace getPEClockWise(BlockFace face) {
|
||||
return switch (face) {
|
||||
case NORTH -> BlockFace.EAST;
|
||||
case SOUTH -> BlockFace.WEST;
|
||||
case WEST -> BlockFace.NORTH;
|
||||
default -> BlockFace.SOUTH;
|
||||
};
|
||||
switch (face) {
|
||||
case NORTH:
|
||||
return BlockFace.EAST;
|
||||
case SOUTH:
|
||||
return BlockFace.WEST;
|
||||
case WEST:
|
||||
return BlockFace.NORTH;
|
||||
case EAST:
|
||||
default:
|
||||
return BlockFace.SOUTH;
|
||||
}
|
||||
}
|
||||
|
||||
public static BlockFace getCounterClockwise(BlockFace face) {
|
||||
return switch (face) {
|
||||
case NORTH -> BlockFace.WEST;
|
||||
case SOUTH -> BlockFace.EAST;
|
||||
case WEST -> BlockFace.SOUTH;
|
||||
default -> BlockFace.NORTH;
|
||||
};
|
||||
switch (face) {
|
||||
case NORTH:
|
||||
return BlockFace.WEST;
|
||||
case SOUTH:
|
||||
return BlockFace.EAST;
|
||||
case WEST:
|
||||
return BlockFace.SOUTH;
|
||||
case EAST:
|
||||
default:
|
||||
return BlockFace.NORTH;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector offset(Vector toOffset, BlockFace face) {
|
||||
|
||||
@@ -4,4 +4,4 @@ import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
|
||||
public interface AxisSelect {
|
||||
SimpleCollisionBox modify(SimpleCollisionBox box);
|
||||
}
|
||||
}
|
||||
@@ -54,22 +54,36 @@ public enum AxisUtil {
|
||||
}
|
||||
|
||||
public static AxisSelect getAxis(BlockFace face) {
|
||||
return switch (face) {
|
||||
case EAST -> EAST.select;
|
||||
case WEST -> WEST.select;
|
||||
case NORTH -> NORTH.select;
|
||||
case SOUTH -> SOUTH.select;
|
||||
case UP -> UP.select;
|
||||
default -> DOWN.select;
|
||||
};
|
||||
switch (face) {
|
||||
case EAST:
|
||||
return EAST.select;
|
||||
case WEST:
|
||||
return WEST.select;
|
||||
case NORTH:
|
||||
return NORTH.select;
|
||||
case SOUTH:
|
||||
return SOUTH.select;
|
||||
case UP:
|
||||
return UP.select;
|
||||
case DOWN:
|
||||
default:
|
||||
return DOWN.select;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isSameAxis(BlockFace one, BlockFace two) {
|
||||
return switch (one) {
|
||||
case WEST, EAST -> two == BlockFace.WEST || two == BlockFace.EAST;
|
||||
case NORTH, SOUTH -> two == BlockFace.NORTH || two == BlockFace.SOUTH;
|
||||
case UP, DOWN -> two == BlockFace.UP || two == BlockFace.DOWN;
|
||||
default -> false;
|
||||
};
|
||||
switch (one) {
|
||||
case WEST:
|
||||
case EAST:
|
||||
return two == BlockFace.WEST || two == BlockFace.EAST;
|
||||
case NORTH:
|
||||
case SOUTH:
|
||||
return two == BlockFace.NORTH || two == BlockFace.SOUTH;
|
||||
case UP:
|
||||
case DOWN:
|
||||
return two == BlockFace.UP || two == BlockFace.DOWN;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
Loaded 100 of 182 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user