Compare commits

..
Author SHA1 Message Date
Axionize 187ef354e0 Deobfuscate and document purpose of misunderstood code in traverseBlocks() 2024-08-24 19:05:28 -04:00
Axionize b6cc8ce57c Merge reach wall hit check
(cherry picked from commit 335c33b109)
2024-08-24 19:05:26 -04:00
Axionize e07f02a05f Add .gradle.yml 2024-08-24 19:05:24 -04:00
53 changed files with 533 additions and 1048 deletions

No files matched your search

-71
View File
@@ -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@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
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@v1
# ℹ️ 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@v1
-38
View File
@@ -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@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
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/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
with:
arguments: build
- name: Upload a Build Artifact
uses: actions/upload-artifact@v3.1.0
with:
path: /home/runner/work/Grim/Grim/build/libs/**.jar
+95
View File
@@ -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'
+20 -26
View File
@@ -9,15 +9,11 @@ plugins {
}
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.sourceCompatibility = JavaVersion.VERSION_1_8
java.targetCompatibility = JavaVersion.VERSION_1_8
// Set to false for debug builds
// You cannot live reload classes if the jar relocates dependencies
var relocate = true;
repositories {
mavenLocal()
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") // Spigot
@@ -38,7 +34,7 @@ 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")
@@ -137,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")
}
+2 -13
View File
@@ -7,7 +7,6 @@ import ac.grim.grimac.player.GrimPlayer;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
import github.scarsz.configuralize.DynamicConfig;
import io.github.retrooper.packetevents.util.folia.FoliaScheduler;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.Bukkit;
@@ -29,7 +28,6 @@ public class Check implements AbstractCheck {
private boolean experimental;
@Setter
private boolean isEnabled;
private boolean exempted;
@Override
public boolean isExperimental() {
@@ -58,14 +56,7 @@ public class Check implements AbstractCheck {
}
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) {
@@ -81,7 +72,7 @@ public class Check implements AbstractCheck {
}
public final boolean flag() {
if (player.disableGrim || (experimental && !GrimAPI.INSTANCE.getConfigManager().isExperimentalChecks()) || exempted)
if (player.disableGrim || (experimental && !GrimAPI.INSTANCE.getConfigManager().isExperimentalChecks()))
return false; // Avoid calling event if disabled
FlagEvent event = new FlagEvent(player, this);
@@ -112,8 +103,6 @@ public class Check implements AbstractCheck {
setbackVL = getConfig().getDoubleElse(configName + ".setbackvl", setbackVL);
if (setbackVL == -1) setbackVL = Double.MAX_VALUE;
updateExempted();
}
public boolean alert(String verbose) {
@@ -25,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,9 +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 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;
@@ -23,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) {
@@ -35,6 +33,10 @@ 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;
}
@@ -15,12 +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.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;
@@ -30,12 +34,22 @@ 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 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)
@@ -43,6 +57,9 @@ 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 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,
@@ -105,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);
}
}
@@ -140,7 +158,7 @@ public class Reach extends Check implements PacketCheck {
}
}
private void tickBetterReachCheckWithAngle() {
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) {
@@ -155,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) {
@@ -219,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)) {
@@ -235,6 +273,45 @@ 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 reload() {
super.reload();
@@ -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;
@@ -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,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.skippedTickInActualMovement) {
for (String verbose : flags) {
flagAndAlert(verbose);
}
}
flags.clear();
}
}
@@ -71,8 +71,8 @@ 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)
));
// Start checking if player is in the block
@@ -14,7 +14,7 @@ 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<>();
@@ -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,11 +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 org.bukkit.util.Vector;
public class CheckManagerListener extends PacketListenerAbstract {
@@ -59,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);
@@ -268,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();
@@ -308,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);
@@ -508,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)) {
@@ -582,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);
@@ -748,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
@@ -778,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.getFirst() == null) continue; // No intercept
Vector hitLoc = intercept.getFirst();
if (hitLoc.distanceSquared(startingVec) < bestHitResult) {
bestHitResult = hitLoc.distanceSquared(startingVec);
bestHitLoc = hitLoc;
bestFace = intercept.getSecond();
}
}
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.getFirst() != null) {
return new HitData(vector3i, intercept.getFirst(), intercept.getSecond(), block);
}
}
return null;
});
}
@Override
public void onPacketSend(PacketSendEvent event) {
if (event.getConnectionState() != ConnectionState.PLAY) return;
@@ -175,7 +175,7 @@ public class PacketPlayerDigging extends PacketListenerAbstract {
if (player == null) return;
if (!player.packetStateData.lastPacketWasTeleport && !player.packetStateData.lastPacketWasOnePointSeventeenDuplicate) {
if (player.packetStateData.isSlowedByUsingItem() && player.packetStateData.eatingHand != InteractionHand.OFF_HAND && player.packetStateData.getSlowedByUsingItemSlot() != player.packetStateData.lastSlotSelected) {
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);
}
}
@@ -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();
@@ -139,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))
@@ -202,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) {
@@ -217,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) {
@@ -247,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) {
@@ -3,7 +3,6 @@ package ac.grim.grimac.manager;
import ac.grim.grimac.GrimAC;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.utils.anticheat.LogUtil;
import ac.grim.grimac.utils.math.GrimMath;
import github.scarsz.configuralize.DynamicConfig;
import github.scarsz.configuralize.Language;
import lombok.Getter;
@@ -78,15 +77,7 @@ public class ConfigManager {
} catch (Exception e) {
throw new RuntimeException("Failed to load config", e);
}
final int configuredMaxTransactionTime = config.getIntElse("max-transaction-time", 60);
maxPingTransaction = (int) GrimMath.clamp(configuredMaxTransactionTime, 1, 180);
if (maxPingTransaction != configuredMaxTransactionTime) {
LogUtil.warn("Detected invalid max-transaction-time! This setting is clamped between 1 and 180 to prevent issues. " +
"Changed: " + configuredMaxTransactionTime + " -> " + maxPingTransaction);
LogUtil.warn("Attempting to disable or set this too high can result in memory usage issues.");
}
maxPingTransaction = config.getIntElse("max-transaction-time", 60);
ignoredClientPatterns.clear();
for (String string : config.getStringList("client-brand.ignored-clients")) {
try {
@@ -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"));
@@ -3,7 +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.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;
@@ -36,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;
@@ -504,13 +504,6 @@ 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;
@@ -364,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())) {
@@ -16,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;
@@ -150,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.isPresent()) 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
@@ -171,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();
}
}
@@ -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;
@@ -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
@@ -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);
@@ -567,14 +567,7 @@ public enum CollisionData {
}, StateTypes.GRINDSTONE),
PANE(new DynamicPane(), Materials.getPanes().toArray(new StateType[0])),
CHAIN_BLOCK((player, version, data, x, y, z) -> {
if (version.isOlderThan(ClientVersion.V_1_16)) {
// viaversion replacement - iron bars
return CollisionData.PANE.dynamic.fetch(player, version, data, x, y, z);
}
if (data.getAxis() == Axis.X) {
return new HexCollisionBox(0.0D, 6.5D, 6.5D, 16.0D, 9.5D, 9.5D);
} else if (data.getAxis() == Axis.Y) {
@@ -606,6 +599,8 @@ public enum CollisionData {
FENCE(new DynamicFence(), BlockTags.FENCES.getStates().toArray(new StateType[0])),
PANE(new DynamicPane(), Materials.getPanes().toArray(new StateType[0])),
SNOW((player, version, data, x, y, z) -> {
if (data.getLayers() == 1 && version.isNewerThanOrEquals(ClientVersion.V_1_13)) {
// Via doesn't touch this
@@ -112,7 +112,7 @@ public enum HitboxData {
}
List<SimpleCollisionBox> boxes = new ArrayList<>();
CollisionData.getData(state.getType()).getMovementCollisionBox(player, version, state).downCast(boxes);
CollisionData.getData(state.getType()).getMovementCollisionBox(player, version, state, x, y, z).downCast(boxes);
for (SimpleCollisionBox box : boxes) {
box.maxY = 1;
@@ -84,7 +84,7 @@ public class DynamicPane extends DynamicConnecting implements CollisionFactory {
@Override
public boolean checkCanConnect(GrimPlayer player, WrappedBlockState state, StateType one, StateType two, BlockFace direction) {
if (BlockTags.GLASS_PANES.contains(one) || one == StateTypes.IRON_BARS || one == StateTypes.CHAIN && player.getClientVersion().isOlderThan(ClientVersion.V_1_16))
if (BlockTags.GLASS_PANES.contains(one) || one == StateTypes.IRON_BARS)
return true;
else
return CollisionData.getData(one).getMovementCollisionBox(player, player.getClientVersion(), state, 0, 0, 0).isSideFullBlock(direction);
@@ -80,7 +80,6 @@ public final class ValuedAttribute {
public void reset() {
this.value = defaultValue;
this.lastProperty = null; // Remove the old property with its modifiers so we don't accidentally use it again, messing up the calculation.
}
public double get() {
@@ -123,7 +122,7 @@ public final class ValuedAttribute {
d1 *= 1.0D + attributemodifier.getAmount();
}
double newValue = GrimMath.clamp(d1, min, max);
double newValue = GrimMath.clampFloat((float) d1, (float) min, (float) max);
if (setRewriter != null) {
newValue = setRewriter.apply(this.value, newValue);
}
@@ -2,8 +2,6 @@ package ac.grim.grimac.utils.data.packetentity;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.data.attribute.ValuedAttribute;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
@@ -22,16 +20,7 @@ public class PacketEntityHorse extends PacketEntityTrackXRot {
setAttribute(Attributes.GENERIC_STEP_HEIGHT, 1.0f);
final boolean preAttribute = player.getClientVersion().isOlderThan(ClientVersion.V_1_20_5);
// This was horse.jump_strength pre-attribute
trackAttribute(ValuedAttribute.ranged(Attributes.GENERIC_JUMP_STRENGTH, 0.7, 0, preAttribute ? 2 : 32)
.withSetRewriter((oldValue, newValue) -> {
// Seems viabackwards doesn't rewrite this (?)
if (preAttribute && PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_20_5)) {
return oldValue;
}
// Modern player OR an old server setting legacy horse.jump_strength attribute
return newValue;
}));
trackAttribute(ValuedAttribute.ranged(Attributes.GENERIC_JUMP_STRENGTH, 0.7, 0, preAttribute ? 2 : 32));
trackAttribute(ValuedAttribute.ranged(Attributes.GENERIC_MOVEMENT_SPEED, 0.225f, 0, 1024));
if (EntityTypes.isTypeInstanceOf(type, EntityTypes.CHESTED_HORSE)) {
@@ -110,11 +110,10 @@ public class BlockBreakSpeed {
if (tool.getType().hasAttribute(ItemTypes.ItemAttribute.SWORD)) {
if (block.getType() == StateTypes.COBWEB) {
speedMultiplier = 15.0f;
} else if (block.getType().getMaterialType() == MaterialType.PLANT
|| BlockTags.LEAVES.contains(block.getType())
|| block.getType() == StateTypes.VINE
|| block.getType() == StateTypes.PUMPKIN
|| block.getType() == StateTypes.MELON) {
} else if (block.getType().getMaterialType() == MaterialType.PLANT ||
BlockTags.LEAVES.contains(block.getType()) ||
block.getType() == StateTypes.PUMPKIN ||
block.getType() == StateTypes.MELON) {
speedMultiplier = 1.5f;
}
@@ -30,11 +30,6 @@ public class BlockProperties {
}
if (player.compensatedEntities.getSelf().getRiding() instanceof PacketEntityStrider) {
// Unsure which version the speed changed in
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_20)) {
return (float) player.speed * 0.1f;
}
PacketEntityStrider strider = (PacketEntityStrider) player.compensatedEntities.getSelf().getRiding();
// Vanilla multiplies by 0.1 to calculate speed
return (float) strider.getAttributeValue(Attributes.GENERIC_MOVEMENT_SPEED) * (strider.isShaking ? 0.66F : 1.0F) * 0.1f;
@@ -0,0 +1,166 @@
package ac.grim.grimac.utils.nmsutil;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.collisions.HitboxData;
import ac.grim.grimac.utils.collisions.datatypes.CollisionBox;
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.math.GrimMath;
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
import com.github.retrooper.packetevents.protocol.world.BlockFace;
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.util.Vector3i;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
public class BlockRayTrace {
// 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 tMaxX = posXInverse * (xSign > 0 ? 1.0D - GrimMath.frac(startX) : GrimMath.frac(startX));
double tMaxY = posYInverse * (ySign > 0 ? 1.0D - GrimMath.frac(startY) : GrimMath.frac(startY));
double tMaxZ = posZInverse * (zSign > 0 ? 1.0D - GrimMath.frac(startZ) : GrimMath.frac(startZ));
// tMax represents the maximum distance along each axis before crossing a block boundary
// The loop continues until the ray has crossed a block boundary along all axes
while (tMaxX <= 1.0D || tMaxY <= 1.0D || tMaxZ <= 1.0D) {
if (tMaxX < tMaxY) {
if (tMaxX < tMaxZ) {
floorStartX += xSign;
tMaxX += posXInverse;
} else {
floorStartZ += zSign;
tMaxZ += posZInverse;
}
} else if (tMaxY < tMaxZ) {
floorStartY += ySign;
tMaxY += posYInverse;
} else {
floorStartZ += zSign;
tMaxZ += posZInverse;
}
state = player.compensatedWorld.getWrappedBlockStateAt(floorStartX, floorStartY, floorStartZ);
apply = predicate.apply(state, new Vector3i(floorStartX, floorStartY, floorStartZ));
if (apply != null) {
return apply;
}
}
return null;
}
public 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 getTraverseResult(player, heldItem, startingPos, startingVec, trace, endPos, sourcesHaveHitbox, false, distance + 3);
}
@Nullable
public static HitData getNearestReachHitResult(GrimPlayer player, Vector eyePos, Vector lookVec, double currentDistance, double maxDistance) {
Vector3d startingPos = new Vector3d(eyePos.getX(), eyePos.getY(), eyePos.getZ());
Vector startingVec = new Vector(startingPos.getX(), startingPos.getY(), startingPos.getZ());
Ray trace = new Ray(eyePos, lookVec);
Vector endVec = trace.getPointAtDistance(maxDistance);
Vector3d endPos = new Vector3d(endVec.getX(), endVec.getY(), endVec.getZ());
return getTraverseResult(player, null, startingPos, startingVec, trace, endPos, false, true, currentDistance);
}
private static HitData getTraverseResult(GrimPlayer player, @Nullable StateType heldItem, Vector3d startingPos, Vector startingVec, Ray trace, Vector3d endPos, boolean sourcesHaveHitbox, boolean checkInside, double knownDistance) {
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(knownDistance));
if (intercept.getFirst() == null) continue; // No intercept
Vector hitLoc = intercept.getFirst();
// If inside a block, return empty result for reach check (don't bother checking this?)
if (checkInside && ReachUtils.isVecInside(box, trace.getOrigin())) {
return null;
}
if (hitLoc.distanceSquared(startingVec) < bestHitResult) {
bestHitResult = hitLoc.distanceSquared(startingVec);
bestHitLoc = hitLoc;
bestFace = intercept.getSecond();
}
}
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(knownDistance));
if (intercept.getFirst() != null) {
return new HitData(vector3i, intercept.getFirst(), intercept.getSecond(), block);
}
}
return null;
});
}
}
@@ -31,7 +31,6 @@ import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
public class Collisions {
@@ -700,7 +699,7 @@ public class Collisions {
int x = currX | chunkXGlobalPos;
int z = currZ | chunkZGlobalPos;
WrappedBlockState data = section.get(CompensatedWorld.blockVersion, x & 0xF, y & 0xF, z & 0xF, false);
WrappedBlockState data = section.get(CompensatedWorld.blockVersion, x & 0xF, y & 0xF, z & 0xF);
if (searchingFor.test(new Pair<>(data, new Vector3d(x, y, z)))) return true;
}
@@ -711,85 +710,6 @@ public class Collisions {
return false;
}
// Thanks Tuinity
public static void forEachCollisionBox(GrimPlayer player, SimpleCollisionBox checkBox, Consumer<Vector3d> searchingFor) {
int minBlockX = (int) Math.floor(checkBox.minX - COLLISION_EPSILON) - 1;
int maxBlockX = (int) Math.floor(checkBox.maxX + COLLISION_EPSILON) + 1;
int minBlockY = (int) Math.floor(checkBox.minY - COLLISION_EPSILON) - 1;
int maxBlockY = (int) Math.floor(checkBox.maxY + COLLISION_EPSILON) + 1;
int minBlockZ = (int) Math.floor(checkBox.minZ - COLLISION_EPSILON) - 1;
int maxBlockZ = (int) Math.floor(checkBox.maxZ + COLLISION_EPSILON) + 1;
final int minSection = player.compensatedWorld.getMinHeight() >> 4;
final int minBlock = minSection << 4;
final int maxBlock = player.compensatedWorld.getMaxHeight() - 1;
int minChunkX = minBlockX >> 4;
int maxChunkX = maxBlockX >> 4;
int minChunkZ = minBlockZ >> 4;
int maxChunkZ = maxBlockZ >> 4;
int minYIterate = Math.max(minBlock, minBlockY);
int maxYIterate = Math.min(maxBlock, maxBlockY);
for (int currChunkZ = minChunkZ; currChunkZ <= maxChunkZ; ++currChunkZ) {
int minZ = currChunkZ == minChunkZ ? minBlockZ & 15 : 0; // coordinate in chunk
int maxZ = currChunkZ == maxChunkZ ? maxBlockZ & 15 : 15; // coordinate in chunk
for (int currChunkX = minChunkX; currChunkX <= maxChunkX; ++currChunkX) {
int minX = currChunkX == minChunkX ? minBlockX & 15 : 0; // coordinate in chunk
int maxX = currChunkX == maxChunkX ? maxBlockX & 15 : 15; // coordinate in chunk
int chunkXGlobalPos = currChunkX << 4;
int chunkZGlobalPos = currChunkZ << 4;
Column chunk = player.compensatedWorld.getChunk(currChunkX, currChunkZ);
if (chunk == null) continue;
BaseChunk[] sections = chunk.getChunks();
for (int y = minYIterate; y <= maxYIterate; ++y) {
BaseChunk section = sections[(y >> 4) - minSection];
if (section == null || (IS_FOURTEEN && section.isEmpty())) { // Check for empty on 1.13+ servers
// empty
// skip to next section
y = (y & ~(15)) + 15; // increment by 15: iterator loop increments by the extra one
continue;
}
for (int currZ = minZ; currZ <= maxZ; ++currZ) {
for (int currX = minX; currX <= maxX; ++currX) {
int x = currX | chunkXGlobalPos;
int z = currZ | chunkZGlobalPos;
WrappedBlockState data = section.get(CompensatedWorld.blockVersion, x & 0xF, y & 0xF, z & 0xF, false);
// Works on both legacy and modern! Faster than checking for material types, most common case
if (data.getGlobalId() == 0) continue;
// Thanks SpottedLeaf for this optimization, I took edgeCount from Tuinity
int edgeCount = ((x == minBlockX || x == maxBlockX) ? 1 : 0) +
((y == minBlockY || y == maxBlockY) ? 1 : 0) +
((z == minBlockZ || z == maxBlockZ) ? 1 : 0);
final StateType type = data.getType();
if (edgeCount != 3 && (edgeCount != 1 || Materials.isShapeExceedsCube(type))
&& (edgeCount != 2 || type == StateTypes.PISTON_HEAD)) {
final CollisionBox collisionBox = CollisionData.getData(type).getMovementCollisionBox(player, player.getClientVersion(), data, x, y, z);
if (collisionBox.isIntersected(checkBox)) {
searchingFor.accept(new Vector3d(x, y, z));
}
}
}
}
}
}
}
}
public static boolean onClimbable(GrimPlayer player, double x, double y, double z) {
WrappedBlockState blockState = player.compensatedWorld.getWrappedBlockStateAt(x, y, z);
StateType blockMaterial = blockState.getType();
@@ -1,6 +1,8 @@
package ac.grim.grimac.utils.nmsutil;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.collisions.CollisionData;
import ac.grim.grimac.utils.collisions.datatypes.CollisionBox;
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
import ac.grim.grimac.utils.data.MainSupportingBlockData;
import com.github.retrooper.packetevents.util.Vector3d;
@@ -40,8 +42,12 @@ public class MainSupportingBlockPosFinder {
AtomicReference<Vector3i> bestBlockPos = new AtomicReference<>();
AtomicDouble blockPosDistance = new AtomicDouble(Double.MAX_VALUE);
Collisions.forEachCollisionBox(player, searchBox, (pos) -> {
Vector3i blockPos = pos.toVector3i();
Collisions.hasMaterial(player, searchBox, (thing) -> {
Vector3i blockPos = thing.getSecond().toVector3i();
CollisionBox collision = CollisionData.getData(thing.getFirst().getType()).getMovementCollisionBox(player, player.getClientVersion(), thing.getFirst(), blockPos.getX(), blockPos.getY(), blockPos.getZ());
if (!collision.isIntersected(searchBox)) return false;
Vector3d blockPosAsVector3d = new Vector3d(blockPos.getX() + 0.5, blockPos.getY() + 0.5, blockPos.getZ() + 0.5);
double distance = playerPos.distanceSquared(blockPosAsVector3d);
@@ -49,6 +55,8 @@ public class MainSupportingBlockPosFinder {
bestBlockPos.set(blockPos);
blockPosDistance.set(distance);
}
return false;
});
+46 -45
View File
@@ -10,17 +10,16 @@ alerts:
# Isso controla se/como os alertas são compartilhados entre os servidores conectados ao proxy.
# Deve-se ter 'bungee-plugin-message-channel' habilitado na configuração do Velocity se estiver usando.
proxy:
# Deviam os alertas ser enviados para outros servidores conectados no mesmo proxy?
# Os alertas deveriam ser enviados para outros servidores conectados no mesmo proxy?
send: false
# Deviam os alertas ser recebidos de outros servidores conectados no mesmo proxy?
# Os alertas deveriam ser recebidos de outros servidores conectados no mesmo proxy?
receive: false
verbose:
print-to-console: false
client-brand:
# Isso signifia que, caso a marca do cliente seja igual às listadas abaixo, não será notificado aos
# administradores.
# Isso signifia que, caso o nome do cliente seja igual aos listados abaixo, não será notificados aos operadores.
ignored-clients:
- "^vanilla$"
- "^fabric$"
@@ -28,7 +27,7 @@ client-brand:
- "^Feather Fabric$"
spectators:
# Esconde todos espectadores com a permissão 'grim.spectator' mesmo se não estiverem ativamente espectando.
# Esconde todos espectadores com a permissão 'grim.spectator' mesmo se não estiverem espectando ativamente.
hide-regardless: false
# Fará os espectadores serem escondidos apenas nos mundos listados abaixo, deixe em branco para habilitar em todos os mundos.
allowed-worlds:
@@ -37,35 +36,35 @@ spectators:
# Quanto tempo os jogadores tem até expulsarmos eles por inatividade? Padrão = 60 segundos.
max-transaction-time: 60
# Deve-se cancelar o pacote de movimento duplicado?
# A Mojang arrumou esse erro na 1.21, sendo sua tentativa de concertar a dessincronização do balde. https://bugs.mojang.com/browse/MC-12363
# Isso só se aplica à clientes da 1.17-1.20.5 em servidores da 1.8.
# Should the duplicate movement packet be cancelled?
# Mojang has fixed this issue in 1.21. This was their attempt to fix the "bucket desync". https://bugs.mojang.com/browse/MC-12363
# This setting only applies to 1.17-1.20.5 clients on 1.8 servers.
cancel-duplicate-packet: true
# Deve-se ignorar rotação em pacotes duplicados?
# Whether or not to ignore the rotation in duplicate packets
ignore-duplicate-packet-rotation: false
Simulation:
# Por quanto deve-se multiplicar a vantagem desde a última vez que falhou uma verificação?
# Por quanto deveríamos multiplicar a vantagem caso o jogador não tenha falhado em nem uma verificação?
# Isso é como a configuração padrão se parece (eixo X = segundos, eixo Y = 1/1000 blocos): https://www.desmos.com/calculator/d4ufgxrxer
setback-decay-multiplier: 0.999
# O quão longe o jogador deve estar da área simulada para registrar violações?
# O quão longe o jogador deve estar da área simulada para adicionarmos violações?
# Medido em blocos do último movimento legítmo.
# Incluímos o Optifine trocando as tabelas trigonométricas; entretanto, abaixar para 0.001 reduzirá o 'FastMath'
# de falhar, caso essa compensação não funcionar.
# Aceitamos o Optifine trocando as tabelas trigonométricas, mas abaixar para 0.001 reduzirá o 'FastMath'
# de falhar, caso esta compensação não funcionar...
threshold: 0.001
# O quão longe o jogador deve estar da área simulada para imediatamente recuá-lo?
# -1 desabilitará
immediate-setback-threshold: 0.1
# Qual é a soma do desalinhamento da simulação em todos os ticks até começarmos a recuar?
# O quão longe da área simulada sobre todos os ticks para começarmos a recuar?
# -1 desabilitará
max-advantage: 1
# Depois de 50 segundos, com a configuração padrão, o jogador irá de 4 blocos a 1 bloco de vantagem.
# Depois de 50 segundos, com a configuração padrão, o jogador irá de 4 blocos -> 1 bloco de vantagem.
# Isso serve para previnir o jogador de alcançar violações demais e nunca conseguir se livrar delas.
# Cela de vantagens padrão (eixo X = segundos, eixo Y = 1/1000 blocos): https://www.desmos.com/calculator/4lovswdarj
max-ceiling: 4
# Verifica se um jogador entrou em um bloco ao se mover.
# Verifica se um jogador entrou em um bloco durante o movimento.
Phase:
setbackvl: 1 # Entrar em blocos possibilita escalar paredes, além disso, essa verificação é relativamente estável.
decay: 0.005
@@ -86,29 +85,29 @@ RotationPlace:
cancelvl: 5
# Verificação de NoSlow por simulação.
# Grim considera erros no netcode. Difícil de gerar falsos positivos, até mesmo spamando o blotão direito e a offhand.
# Muito mais estável que outros anticheats, mas por favor, reporte quaisquer falsos positivos. Eu já arrumei diversos
# Grim considera erros no netcode... difícil de gerar falsos positivos, até mesmo spamando o blotão direito e a offhand.
# Muito mais estável que outros anticheats, mas por favor, reporte quaisquer falsos positivos... eu já arrumei diversos
# erros de netcode.
NoSlowA:
# Quanto de desalinhamento é considerado trapaça?
# Por padrão é menor que os outros.
# Em 0.03-0.2 detecta com consistência.
# Quanto de desvio da simulação é considerado trapaça?
# Por padrão isso é menor que outros desvios.
# Acusa com 0.03-0.2 com consistência com o NoSlow ativo.
threshold: 0.001
# Recuo imediato para inibir as vantagens rapidamente.
# Recua rapidamente no primeiro item para remover quaisquer vantagens que o NoSlow dá.
setbackvl: 5
# Decai quando o jogador usa um item e é efetivamente desacelerado.
# Decai quando o jogador usa um item E é desasceletado por isso.
decay: 0.05
Knockback:
# Por quanto deve-se multiplicar a vantagem desde a última vez que falhou na verificação?
# Por quanto deveriamos multiplicar a vantagem caso o jogador não tenha falhado nessa verificação?
setback-decay-multiplier: 0.999
# O quão longe da área do recuo recebido o jogador deve estar para registrar violações?
# O quão longe da área do recuo recebido o jogador deve estar para adicionarmos uma violação?
# Medido em blocos do recuo recebido.
threshold: 0.001
# O quão longe o jogador deve estar da área simulada para imediatamente recuá-lo?
# -1 desabilitará.
immediate-setback-threshold: 0.1
# Qual é a soma do desalinhamento da simulação em todos os ticks até começarmos a recuar?
# O quão longe da área simulada sobre todos os ticks deverá ser para começarmos a recuar?
# -1 desabilitará.
max-advantage: 1
# Isso serve para previnir o jogador de alcançar violações demais e nunca conseguir se livrar delas.
@@ -121,16 +120,16 @@ Explosion:
TimerA:
setbackvl: 10
# Milissegundos que o jogador pode acumular para depois usar quando eles têm um atraso no ping.
# Pode ignorar o uso de fast use / fast heal / fast bow na 1.8 caso o valor seja definido muito alto.
# 120ms parece um bom balanceamento.
# Pode permitir o uso de fast use / fast heal / fast bow na 1.8 caso o valor seja definido muito alto. 120ms parece
# um bom balanceamento.
drift: 120
# Ping no qual a verificação vai começar a limitar o balançeamento do timer para previnir abuso.
# Pode causar recuos a jogadores legítmos, mas somente se estiverem acima desse ping.
# Pode causar recuos a jogadores legítmos, mas somente se estiverem acima deste ping.
# -1 desabilitará.
ping-abuse-limit-threshold: 1000
NegativeTimer:
# Número de milissegundos perdidos ao se mover antes de começarmos a registrar violações.
# Número de milissegundos perdidos ao se mover antes de começarmos a adicionar violações.
drift: 1200
# Mesmo método usado no TimerA, mas para veículos.
@@ -142,54 +141,56 @@ EntityControl:
setbackvl: 25
Reach:
# Por quanto deve-se expandir as caixas de colisão? 0.0005 deve detectar 3.0005+ de alcance.
# Por quanto devíamos expandir as caixas de colisão? 0.0005 deve detectar 3.0005+ de alcance.
#
# Há 0.03 de expansão forçada nas versões 1.9-1.18.1 (não a 1.18.2), ou algumas combinações de cliente/servidor por
# conta de mudanças no protocolo e limitações. Essa verificação é mais poderosa com clientes da 1.7/1.8 em servidores
# da 1.8.
threshold: 0.0005
# Deve-se cancelar hits que sabemos que são impossíveis?
# O alcance de 3.00-3.03 pode acabar passando, por conta da ordem de pacotes, mas continuará registrando violações.
# Deveríamos cancelar hits que sabemos que são impossíveis?
# O alcance de 3.00-3.03 pode acabar passando, mas continuarão adicionando violações, por conta de limitações na
# ordem de pacotes.
block-impossible-hits: true
# Isso enviará um pacote adicional no final de todos os ticks para aumentar a probabilidade de detectarmos trapaceiros.
# Isso injeta na lista de conecção do servidor para envar um pacote final logo antes do servidor recarregar.
# Habilitando isso, irá aumentar o uso de banda para todos os jogadores.
# Isso não irá interferir na performance do servidor.
# Habilitando isso, aumentará a probabilidade de detectarmos trapaceiros.
# Deixando-o desabilitado, continuará detectando trapaceiros e não irá causar falsos positivos.
# A menos que estiver em um servidor focado em PvP, esse pacote adicional não é recomendado.
# Deixando-o desabilitado, continuará detectando cheaters e não irá causar falsos positivos.
# A menos que estiver em um servidor focado em PvP esse pacote adicional não é recomendado.
enable-post-packet: false
exploit:
# Você pode ganhar altas velocidades se pular correndo com uma elytra, previne isso de ocorrer quando definido falso.
# Você pode ganhar altas velocidades enquanto pular correndo com uma elytra, isso previne o exploitação de ocorrer quando
# definido falso.
# A Mojang vacilou com o netcode por fazer a Elytra iniciar pelo lado do cliente.
# As Elytras levam 0.99 de fricção horizontal, então constantemente adicionando 0.2 de velocidade horizontal resulta
# em velocidades altíssimas.
allow-sprint-jumping-when-using-elytra: true
# Essa opção mitiga posicionar blocos em blocos fantasma, ressincronizando o jogador quando isso ocorrer.
# Essa opção mitiga o posicionamento de blocos em blocos fantasmas, ressincronizando o jogador quando isso ocorrer.
allow-building-on-ghostblocks: true
# Esse ajuste, influído pela opção acima, define a distância para verificar blocos fantasmas.
# O valor válido é limitado de 2 a 4.
# Este ajuste, influenciado pelo booleano acima, define a distância para verificar blocos fantasmas.
# Seu intervalo válido é limitado de 2 a 4.
distance-to-check-if-ghostblocks: 2
# Registra plugins que são injetados na netty ao entrar para depurar erros de compatibilidade.
# Habilita registrar plugins que são injetados na netty ao entrar para depurar erros de compatibilidade.
debug-pipeline-on-join: false
# Habilita verificações experimentais.
experimental-checks: false
# Grim às vezes cancela pacotes ilegais como com o timer, depois de X pacotes em um segundo que foram cancelados, quando
# deve-se simplesmente expulsar o jogador? Isso é requirido já que alguns limitadores de pacotes não contam pacotes
# devemos simplesmente expulsar o jogador? Isso é requirido já que alguns limitadores de pacotes não contam pacotes
# cancelados pelo Grim.
packet-spam-threshold: 100
# Grim pode impor que o jogador fora do estado de voo não possa ter mais de X milissegundos de ping.
# Grim é capaz de garantir que um jogador fora do estado de voo não possa ter mais de X milissegundos de ping.
# Isso ocorre porque o Grim atualmente não verifica os jogadores que estão voando.
# -1 desabilitará.
# To disable, use -1
max-ping-out-of-flying: 1000
# Ping máximo quando o impulso do foguete acaba.
# Previne jogadores com ping alto de usarem um foguete ara voar indefinidamente.
# Maximum ping when a firework boost is removed from the player.
# This prevents high latency players from being able to use 1 firework boost with an elytra forever.
max-ping-firework-boost: 1000
config-version: 9
-192
View File
@@ -1,192 +0,0 @@
# GrimAC ana konfigrasyon dosyası
# Kaynak kodu: https://github.com/MWHunter/Grim
# Telif Hakkı 2024 DefineOutside ve katkıda bulunanlar, GPLv3 altında lisanslanmıştır.
# Değiştirilmiş ikili dosyalar veya kopyalanmış grim kodlu eklentiler özel olmalıdır,
# veya ek ücret ödemeden alıcılara sunulan tam kaynak kodu ile.
alerts:
# Oyunculara uyarı yayınlamanın yanı sıra, uyarılar konsola da gönderilmeli mi?
print-to-console: true
# Bu, uyarıların proxy'nize bağlı sunucular arasında paylaşılıp paylaşılmayacağını/nasıl paylaşılacağını kontrol eder.
# Velocity kullanılıyorsa, Velocity yapılandırmanızda 'bungee-plugin-message-channel' etkinleştirilmiş olmalıdır.
proxy:
# Proxy'nize bağlı diğer sunuculara uyarılar gönderilmeli mi?
send: false
# Diğer sunuculardan alınan uyarılar bu sunucuya duyurulmalı mı?
receive: false
verbose:
print-to-console: false
client-brand:
# Bu, giriş yapılan clientin aşağıdaki regex'lerle eşleşmesi durumunda markalarını operatörlere yayınlamayacağı anlamına gelir
ignored-clients:
- "^vanilla$"
- "^fabric$"
- "^lunarclient:v\\d+\\.\\d+\\.\\d+-\\d{4}$"
- "^Feather Fabric$"
spectators:
# Seyirciler aktif olarak izliyor olsalar bile, grim.spectator iznine sahip tüm seyircileri gizle
hide-regardless: false
# Sadece bu dünyalarda seyircileri gizleyecek, tüm dünyalara izin vermek için boş bırakın
allowed-worlds:
- ""
# Oyuncuların zaman aşımından dolayı sunucudan atılmadan önce ne kadar süreleri olmalı? Varsayılan = 60 saniye
max-transaction-time: 60
# Kopya hareket paketinin iptal edilip edilmemesi gerektiği
# Mojang bu sorunu 1.21'de çözdü. Bu, "kova senkronizasyonu" sorununu düzeltme girişimiydi. https://bugs.mojang.com/browse/MC-12363
# Bu ayar yalnızca 1.17-1.20.5 istemcileri için 1.8 sunucularında geçerlidir.
cancel-duplicate-packet: true
# Eşya çoğaltma paketlerindeki rotayı göz ardı edip etmeyeceğimiz
ignore-duplicate-packet-rotation: false
Simulation:
# Oyuncu meşru olduğunda toplam avantajı ne kadar çarpmalıyız?
# Varsayılan yapılandırma bu şekilde görünür (x ekseni = saniye, y ekseni = 1/1000 blok): https://www.desmos.com/calculator/d4ufgxrxer
setback-decay-multiplier: 0.999
# Oyuncunun hareketinden ne kadar büyük bir sapma ihlal oluşturmalıyız?
# Mümkün olan hareketten blok cinsinden ölçülür
# Optifine için trig tablolarını değiştirerek hesaba katıyoruz, ancak bunu 0.001'e düşürmek FastMath'ı azaltır
# Bu telafi işe yaramazsa anticheat'i işaretle...
threshold: 0.001
# Bir tik içinde ne kadar büyük bir ihlal olmalı ki oyuncu hemen geri dönsün?
# Devre dışı bırakmak için -1 yazın
immediate-setback-threshold: 0.1
# Tüm tikler boyunca ne kadar büyük bir avantaja sahip olmalıyız ki geri dönüş yapmaya başlayalım?
# Devre dışı bırakmak için -1 yazın
max-advantage: 1
# Varsayılan config ile 50 saniye sonra, oyuncu 4 bloktan -> 1 bloğa kadar avantaj kazanır
# Bu, oyuncunun çok fazla ihlal biriktirmesini ve bunların hepsini temizleyememesini önlemek içindir
# Varsayılan avantaj tavanı (x ekseni = saniye, y ekseni = 1/1000 blok): https://www.desmos.com/calculator/4lovswdarj
max-ceiling: 4
# Bir oyuncunun bir hareket sırasında bir bloğa girip girmediğini kontrol eder
Phase:
setbackvl: 1 # Blokların içinde glitch yapmak duvara tırmanmaya izin verebilir, ayrıca bu kontrol nispeten stabildir
decay: 0.005
AirLiquidPlace:
cancelvl: 0
FabricatedPlace:
cancelvl: 5
FarPlace:
cancelvl: 5
PositionPlace:
cancelvl: 5
RotationPlace:
cancelvl: 5
# Tahmin tabanlı yavaşlama kontrolü
# Grim burada hatalı ağ kodunu dikkate alır... sağ tıklama ve el yan tuşunu spam yapsanız bile yanlış pozitiflik oluşturması zordur
# Diğer anti-hilelerden çok daha stabil, ancak herhangi bir yanlış pozitif rapor edin... burada birçok ağ kodu sorununu çözdüm.
NoSlowA:
# Ne kadar bir sapma "hile" olarak kabul edilir?
# Varsayılan olarak bu, diğer sapmalardan daha düşüktür
# NoSlow açıkken 0.03-0.2 aralığında sürekli olarak uyarı verir
threshold: 0.001
# NoSlow'un sağladığı avantajı ortadan kaldırmak için ilk itemi hızlı bir şekilde geri alın
setbackvl: 5
# Oyuncu bir eşya kullandığında VE onun tarafından yavaşlatıldığında beklenilen zaman
decay: 0.05
Knockback:
# Oyuncu legit olduğunda toplam avantajı ne kadarla çarpmalıyız
setback-decay-multiplier: 0.999
# Oyuncunun hızından ne kadar büyük bir sapma ihlal oluşturmalıyız?
# Mümkün olan hızdan blok cinsinden ölçülür
threshold: 0.001
# Bir tik içinde ne kadar büyük bir ihlal olmalı ki oyuncu hemen geri dönsün?
# Devre dışı bırakmak için -1 yazın
immediate-setback-threshold: 0.1
# Tüm tikler boyunca ne kadar büyük bir avantaja sahip olmalıyız ki geri dönüş yapmaya başlayalım?
# Devre dışı bırakmak için -1 yazın
max-advantage: 1
# Bu, oyuncunun çok fazla ihlal toplamasını ve asla hepsini temizleyememesini engellemek içindir
max-ceiling: 4
Explosion:
threshold: 0.001
setbackvl: 3
TimerA:
setbackvl: 10
# Oyuncunun geri kaldığında biriktirebileceği milisaniye miktarı
# Çok yüksek ayarlandığında 1.8 hızlı kullanma/hızlı iyileşme/hızlı yay atlama durumlarına izin verebilir, 120 ms iyi bir denge gibi görünüyor
drift: 120
# Kontrolün zamanlayıcı dengesini sınırlamaya başlayacağı ping değeri, kötüye kullanımı önlemek için.
# Bu, yalnızca bu ping eşiğini aşan meşru oyuncular için bazı geri dönüşlere neden olabilir.
# Devre dışı bırakmak için -1 yazın
ping-abuse-limit-threshold: 1000
NegativeTimer:
# Uyarı vermeye başlamadan önce hareket halindeyken kaybedilen milisaniye sayısı
drift: 1200
# TimerA ile aynı kontrol yöntemi, ancak araçlar için
TimerVehicle:
# Hedef 1.005 timer
setbackvl: 10
EntityControl:
setbackvl: 25
Reach:
# Hitbox'ları ne kadar genişletmeliyiz? 0.0005, 3.0005+ menzili tespit etmelidir
#
# 1.9-1.18.1 (1.18.2 değil) ile zorunlu olarak 0.03 genişletme vardır veya bazı istemci/sunucu kombinasyonları nedeniyle
# protokol değişiklikleri ve sınırlamaları nedeniyle. Bu kontrol, 1.7/1.8 istemcilerle 1.8 sunucularda en güçlüdür.
threshold: 0.0005
# İmkansız olduğunu bildiğimiz vuruşları iptal etmeli miyiz?
# Paket sırası sınırlamaları nedeniyle 3.00-3.03 arası vuruşlar gerçekleşebilir, ancak yine de işaretlenebilir
block-impossible-hits: true
# Bu, hileleri yakalama olasılığını artırmak için her tikin sonunda ek bir paket gönderecektir
# Bu, sunucunun bağlantı listesine enjekte edilerek sunucu boşaltmadan hemen önce son bir paket göndermek için yapılır
# Bunu etkinleştirmek, tüm oyuncular için bant genişliği kullanımını artıracaktır
# Bu, genel sunucu performansını düşürmez
# Bunu etkinleştirmek, daha fazla hilecinin yakalanmasını sağlar
# Bu özellik devre dışı bırakılsa bile hileciler yakalanır ve yanlış pozitifler oluşmaz
# 1.8 PvP odaklı bir sunucu değilseniz, bu ek paket önerilmez
enable-post-packet: false
exploit:
# Elytra ile sprint zıplarken yüksek hızlar kazanabilirsiniz, bu ayar false olarak ayarlandığında bu istismarı önler
# Mojang, elytra'nın istemci tarafında başlamasını ve sunucu tarafında bitmesini sağlayarak netcode'u bozdu
# Elytra'lar 0.99 yatay sürtünme alır, bu yüzden sürekli olarak 0.2 yatay hız eklemek çok yüksek hızlara yol açar
allow-sprint-jumping-when-using-elytra: true
# Bu seçenek, oyuncunun hayalet bloklar üzerindeki yerleşimini, gerçekleştiğinde oyuncuyu yeniden senkronize ederek hafifletir
allow-building-on-ghostblocks: true
# Bu ayar, yukarıdaki boolean ile etkilenen hayalet blokları kontrol etmek için mesafeyi tanımlar
# Geçerli aralığı 2 ile 4 arasında sınırlıdır
distance-to-check-if-ghostblocks: 2
# Netty'ye enjekte olan eklentileri giriş sırasında günlüklemeyi etkinleştirerek uyumluluk sorunlarını gider
debug-pipeline-on-join: false
# Deneysel kontrolleri etkinleştir
experimental-checks: false
# Grim bazen timer gibi yasa dışı paketleri iptal eder; bir saniyede X paket iptal edildikten sonra, ne zaman
# oyuncuyu basitçe atmalıyız? Bu, bazı paket sınırlayıcılarının Grim tarafından iptal edilen paketleri saymaması gerektiğindendir.
packet-spam-threshold: 100
# Grim, uçma durumundan çıkmış bir oyuncunun X milisaniyeden fazla ping'e sahip olamayacağını uygulayabilir
# Bu, Grim'in şu anda uçan oyuncuları kontrol etmemesindendir
# Devre dışı bırakmak için -1 yazın
max-ping-out-of-flying: 1000
# Bir havai fişek ivmesi oyuncudan çıkarıldığında maksimum ping.
# Bu, yüksek gecikmeli oyuncuların bir havai fişek ivmesini elytra ile sonsuza kadar kullanmalarını engeller.
max-ping-firework-boost: 1000
config-version: 9
# Translated by Kayera
# Have a nice day :)
+15 -19
View File
@@ -2,7 +2,7 @@
# 源代码链接: https://github.com/MWHunter/Grim
# 版权归 DefineOutside 和 贡献者所有,基于GPLv3开源协议。
# 修改过的二进制文件,或带有复制的Grim代码的插件,必须是私有仓库,不得公开售卖此插件。
# 中文翻译提供 nuym/Dg32z_ ,如有错误请提交 Issues 并@我
# 中文翻译提供 nuym ,如有错误请提交 Issues 并@我
alerts:
# 是否在控制台显示作弊消息?
@@ -27,22 +27,21 @@ client-brand:
- "^Feather Fabric$"
spectators:
# 将拥有 grim.spectator 权限的人进行隐藏,不管他是否在观察玩家
# 把所有拥有 grim.spectartor 权限的人都隐藏起来,不管他是否观察玩家。
hide-regardless: false
# 观察者这些世界不会隐藏
allowed-worlds:
- ""
# 在玩家无法接收 GrimAC的 transaction 数据包后,多少秒对玩家进行踢出
# 踢出原因为: disconnect.timeout
# 在我们让他们超时之前,玩家应该有多长时间? 此处的60 指60s
max-transaction-time: 60
# 是否对重复的移动数据包进行撤销?
# 这可以修复 "bucket desync". https://bugs.mojang.com/browse/MC-12363,不过Mojang已经在1.21修复了这个问题
# 这仅仅适用于1.8服务器中使用1.17-1.20.5版本的玩家
# Should the duplicate movement packet be cancelled?
# Mojang has fixed this issue in 1.21. This was their attempt to fix the "bucket desync". https://bugs.mojang.com/browse/MC-12363
# This setting only applies to 1.17-1.20.5 clients on 1.8 servers.
cancel-duplicate-packet: true
# 是否忽视重复的数据包中的玩家转头
# Whether or not to ignore the rotation in duplicate packets
ignore-duplicate-packet-rotation: false
Simulation:
@@ -85,7 +84,7 @@ PositionPlace:
RotationPlace:
cancelvl: 5
# 使用模拟移动进行的NoSlow(使用物品时不会减速)检查
# Prediction-based NoSlow 检查
# 在这里解释错误的服务器代码......即使在发送垃圾数据包时右键单击和副手按钮也很分辨
# 比其他反作弊更稳定,但请报告任何错误......我在这里修复了大量的代码问题。
NoSlowA:
@@ -122,13 +121,13 @@ TimerA:
# 玩家卡顿时可以累积以供以后使用的毫秒数
# 如果设置得太高,可能会允许 1.8 快速使用/快速治疗/快速弓箭绕过,120 毫秒似乎是一个很好的平衡
drift: 120
# 在检查玩家的延迟时对timer balance进行限制, 防止滥用
# 在合法玩家的延迟超过这个延迟阈值时可能会造成误拉回
# 填写-1则关闭
# Ping at which the check will start to limit timer balance, to prevent abuse.
# Can cause some setbacks for legitimate players but only if they are over this ping threshold.
# -1 to disable
ping-abuse-limit-threshold: 1000
NegativeTimer:
# 在开始检查玩家时,玩家的移动丢失了多少毫秒数
# Number of milliseconds lost while moving before we should start flagging
drift: 1200
# 与 TimerA 相同的检查方法,但适用于坐骑
@@ -158,10 +157,8 @@ Reach:
enable-post-packet: false
exploit:
#是否允许玩家在使用鞘翅时候进行的疾跑跳跃
allow-sprint-jumping-when-using-elytra: true
# 该选项可在发生鬼块时重新同步玩家,从而减轻玩家在鬼块上的位置。
# 这可以在玩家遇到幽灵方块时进行同步,这可以减少玩家所碰到幽灵方块
allow-building-on-ghostblocks: true
distance-to-check-if-ghostblocks: 2
@@ -176,12 +173,11 @@ experimental-checks: false
packet-spam-threshold: 100
# Grim 能够强制执行一个规则:被设置为非飞行状态的玩家的 ping 值不能超过 X 毫秒。这是因为 Grim 目前不检查处于飞行状态的玩家。
# 填写-1则关闭
# To disable, use -1
max-ping-out-of-flying: 1000
# 限制玩家在使用鞘翅飞行时使用烟花加速的延迟
# 这可以解决高延迟的玩家可以使用鞘翅时一直使用 1 个烟花就可以加速
# 填写-1则关闭
# Maximum ping when a firework boost is removed from the player.
# This prevents high latency players from being able to use 1 firework boost with an elytra forever.
max-ping-firework-boost: 1000
config-version: 9
-1
View File
@@ -1,7 +1,6 @@
# Ob Discord Webhook aktiviert werden soll
enabled: false
webhook: ""
embed-title: "**Grim Alert**"
embed-color: "#00FFFF"
violation-content:
- "**Spieler**: %player%"
-1
View File
@@ -1,6 +1,5 @@
enabled: false
webhook: ""
embed-title: "**Grim Alert**"
embed-color: "#00FFFF"
violation-content:
- "**Player**: %player%"
-2
View File
@@ -7,8 +7,6 @@ enabled: false
# La URL del webhook.
webhook: ""
embed-title: "**Grim Alert**"
# El color del embed que se mandara por este webhook.
embed-color: "#00FFFF"
-1
View File
@@ -1,6 +1,5 @@
enabled: false
webhook: ""
embed-title: "**Grim Alert**"
embed-color: "#00FFFF"
violation-content:
- "**Joueur**: %player%"
-1
View File
@@ -1,6 +1,5 @@
enabled: false
webhook: ""
embed-title: "**Grim Alert**"
embed-color: "#00FFFF"
violation-content:
- "**Giocatore**: %player%"
-1
View File
@@ -1,6 +1,5 @@
enabled: false
webhook: ""
embed-title: "**Grim Alert**"
embed-color: "#00FFFF"
violation-content:
- "**Speler**: %player%"
-1
View File
@@ -1,6 +1,5 @@
enabled: false
webhook: ""
embed-title: "**Grim Alert**"
embed-color: "#00FFFF"
violation-content:
- "**Jogador**: %player%"
-1
View File
@@ -1,7 +1,6 @@
# Включать ли веб-крючок discord
enabled: false
webhook: ""
embed-title: "**Grim Alert**"
embed-color: "#00FFFF"
violation-content:
- "**Игрок**: %player%"
-11
View File
@@ -1,11 +0,0 @@
enabled: false
webhook: ""
embed-color: "#00FFFF"
violation-content:
- "**Oyuncu**: %player%"
- "**Kontrol**: %check%"
- "**İhlaller**: %violations%"
- "**Client Versiyonu**: %version%"
- "**Kullanılan Client**: %brand%"
- "**Gecikme**: %ping%"
- "**TPS**: %tps%"
+7 -8
View File
@@ -1,13 +1,12 @@
# 是否启用discord webhook
enabled: false
webhook: ""
embed-title: "**Grim Alert**"
embed-color: "#00FFFF"
violation-content:
- "**玩家名**: %player%"
- "**检查**: %check%"
- "**违规率**: %violations%"
- "**游戏版本**: %version%"
- "**客户端品牌**: %brand%"
- "**延迟**: %ping%"
- "**服务器卡顿程度**: %tps%"
- "**Player**: %player%"
- "**Check**: %check%"
- "**Violations**: %violations%"
- "**Client Version**: %version%"
- "**Brand**: %brand%"
- "**Ping**: %ping%"
- "**TPS**: %tps%"
+22 -19
View File
@@ -1,31 +1,34 @@
# Você pode usar códigos hexadecimais também, no formato #FFFFFF ou #ffffff.
# \u00BB é » (>> duplo), ANSI e UTF-8 interpretam isso diferentemente... você pode acabar vendo '?' por conta disso.
prefix: "&bGrim &8\u00BB"
alerts-enabled: "%prefix% &fAlertas habilitados."
alerts-disabled: "%prefix% &fAlertas desabilitados."
client-brand-format: "%prefix% &f%player% entrou usando %brand%."
console-specify-target: "%prefix% &cVocê deve especificar o nome do alvo!"
alerts-enabled: "%prefix% &fAlertas do AntiCheat foram habilitados para você."
alerts-disabled: "%prefix% &fAlertas do AntiCheat foram desabilitados para você."
client-brand-format: "%prefix% &f%player% entrou usando: &c%brand%"
console-specify-target: "%prefix% &cVocê deve especificar o nome do alvo como o terminal!"
player-not-found: "%prefix% &cJogador não encontrado!"
player-not-this-server: "%prefix% &cO jogador não está no servidor!"
player-not-this-server: "%prefix% &cO jogador não está nesse servidor!"
spectate-return: "\n%prefix% &fClique aqui para retornar a localização anterior\n"
cannot-spectate-return: "%prefix% &cVocê só pode fazer isso após espectar um jogador."
cannot-run-on-self: "%prefix% &cVocê não pode usar esse comando em sí mesmo!"
upload-log: "%prefix% &fRegistro enviado para: %url%"
upload-log-start: "%prefix% &fEnviando o registro. Aguarde."
upload-log-not-found: "%prefix% &cNúmero do registro não encontrado."
upload-log-upload-failure: "%prefix% &cAlgo deu errado ao enviar o registro, veja o terminal para mais informações."
cannot-spectate-return: "%prefix% &cVocê só pode fazer isso enquanto estiver espectando alguém."
cannot-run-on-self: "%prefix% &cVocê não pode usar esse comando em você mesmo!"
upload-log: "%prefix% &fLogs enviadas para: %url%"
upload-log-start: "%prefix% &fEnviando a log... Por favor, aguarde..."
upload-log-not-found: "%prefix% &cNão foi possível encontrar essa log."
upload-log-upload-failure: "%prefix% &cAlgo deu errado ao enviar essa log, veja o terminal para mais informações."
# Placeholders válidos:
# %prefix%
# %player%
# %check_name%
# %description%
# %experimental%
# %vl% - violações
# %verbose% - Informação extra da verificação, como os desalinhamentos, nem todas as verifiações terão essa informação.
# %verbose% - Informação extra da verificação, como os desvios, nem todas as verifiações terão essa informação.
alerts-format: "%prefix% &f%player% &bfalhou em &f%check_name%%experimental% &f(x&c%vl%&f) &7%verbose%"
alerts-format-proxy: "%prefix% &f[&cproxy&f] &f%player% &bfalhou em &f%check_name%%experimental% &f(x&c%vl%&f) &7%verbose%"
experimental-symbol: "*"
profile:
- "&7======================"
- "%prefix% &bPerfil de &f%player%"
@@ -38,13 +41,13 @@ profile:
- "&7======================"
help:
- "&7======================"
- "/grim alerts &f- &7Alterna noificações."
- "/grim alerts &f- &7Alterna entre &aon&f/&coff &7as notificações."
- "/grim profile <player> &f- &7Mosta as informações do jogador."
- "/grim help &f- &7Mostra essa mensagem de ajuda."
- "/grim debug <player> &f- &7Depura a simulação."
- "/grim perf &f- &7Depura a performance."
- "/grim reload &f- &7Recarrega as configurações."
- "/grim spectate <player> &f- &7Especta um jogador."
- "/grim verbose &f- &7Esconde as informações extra."
- "/grim log [0-255] &f- &7Envia o registro da simulação."
- "/grim debug <player> &f- &7Modo de depuração do plugin."
- "/grim perf &f- &7Informações de performance do plugin."
- "/grim reload &f- &7Recarregar configurações do AntiCheat."
- "/grim spectate <player> &f- &7Espectar um jogador."
- "/grim verbose &f- &7Mostra todos os flags para você sem os buffers."
- "/grim log [0-255] &f- &7Envie um log para visualização externa."
- "&7======================"
-56
View File
@@ -1,56 +0,0 @@
# Hex kodlarını #FFFFFF veya #ffffff formatında kullanabilirsiniz :)
# \u00BB eşittir » (çift >>), ANSI ve UTF-8 bunu farklı yorumlar. bu nedenle ? bile görebilirsiniz
prefix: "&bGrim &8\u00BB"
alerts-enabled: "%prefix% &fUyarılar aktif edildi."
alerts-disabled: "%prefix% &fUyarılar deaktif edildi."
client-brand-format: "%prefix% &f%player% adlı oyuncu %brand% kullanarak giriş yaptı."
console-specify-target: "%prefix% &cKonsol olarak bir hedef belirtmelisiniz!"
player-not-found: "%prefix% &cOyuncu bulunamadı veya aktif değil!"
player-not-this-server: "%prefix% &cBu oyuncu sunucuda değil!"
spectate-return: "\n%prefix% &fBir önceki konuma dönmek için buraya tıklayın.\n"
cannot-spectate-return: "%prefix% &cBunu yalnızca bir oyuncuyu izledikten sonra yapabilirsiniz."
cannot-run-on-self: "%prefix% &cBu komutu kendi üzerinizde kullanamazsınız!"
upload-log: "%prefix% &fDebug şu adrese yüklendi: %url%"
upload-log-start: "%prefix% &fLog yükleniyor... lütfen bekleyin."
upload-log-not-found: "%prefix% &cLog bulunamadı."
upload-log-upload-failure: "%prefix% &cLog yüklenirken bir problem oluştu, lütfen konsolu kontrol edin."
# Geçerli placeholderlar:
# %prefix%
# %player%
# %check_name%
# %description%
# %experimental%
# %vl% - ihlal uyarıları
# %verbose% - detaylı olarak verilen tüm uyarılar, checkler tüm bilgileri vermez
alerts-format: "%prefix% &b%player% &fadlı oyuncuda &f(x&c%vl%&f) &fadet &b%check_name%%experimental% &ftespit edildi: &7%verbose%"
alerts-format-proxy: "%prefix% &f[&cproxy&f] &b%player% &fadlı oyuncuda &f(x&c%vl%&f) &fadet &b%check_name%%experimental% &ftespit edildi: &7%verbose%"
experimental-symbol: "*"
profile:
- "&7======================"
- "%prefix% &f%player% &badlı oyuncunun profili:"
- "&bGecikme: &f%ping%"
- "&bVersiyon: &f%version%"
- "&bKullanılan Client: &f%brand%"
- "&bDikey Hassasiyet: &f%h_sensitivity%%"
- "&bYatay Hassasiyet: &f%v_sensitivity%%"
- "&bFastMath Ayarı: &f%fast_math%"
- "&7======================"
help:
- "&7======================"
- "/grim alerts &f- &7Uyarıları aktif/deaktif eder"
- "/grim profile (oyuncu) &f- &7Oyuncu profilini gösterir"
- "/grim help &f- &7Bu yardım mesajını gösterir"
- "/grim debug <player> &f- &7Geliştirici Debug'ını verir"
- "/grim perf &f- &7Geliştirici Performansını verir"
- "/grim reload &f- &7Configi yeniden yükler"
- "/grim spectate (oyuncu) &f- &7Bir oyuncuyu izlemenizi sağlar"
- "/grim verbose &f- &7Arabelleğe almadan tüm uyarıları görmenizi sağlar"
- "/grim log (0-255) &f- &7Uyarılar için bir debug logu çıktısı verir"
- "&7======================"
# Translated by Kayera
# Have a nice day ;)
+3 -3
View File
@@ -17,12 +17,12 @@ upload-log-start: "%prefix% &f上传中...请等待"
upload-log-not-found: "%prefix% &c找不到该日志."
upload-log-upload-failure: "%prefix% &c上载此日志时出错, 有关详细信息, 请参阅控制台"
# 变量:
# Valid placeholders:
# %prefix% - 前缀
# %player% - 玩家
# %check_name% - 检查名字
# %description% - 检查的介绍
# %experimental% - 检查是否是实验性
# %description%
# %experimental%
# %vl% - VL值
# %verbose% - 检查中的额外信息,例如偏移量,并非所有检查都会添加信息
alerts-format: "%prefix% &f%player% &b触发了 &f%check_name%%experimental% &f(x&c%vl%&f) &7%verbose%"
+1 -1
View File
@@ -1,5 +1,5 @@
# %check_name% - nome da verificação
# %description% - descrição da verificação
# %description% - description of the check
# %vl% - violações
# %verbose% - informação extra
# %player% - nome do jogador
-92
View File
@@ -1,92 +0,0 @@
# %check_name% - Kontrolün ismi
# %description% - Kontrolün açıklaması
# %vl% - Yapılan ihlaller
# %verbose% - Ekstra bilgilendirme
# %player% - Oyuncu ismi
# [alert] - Uyarılar için bunu kullanın
# [webhook] - Discord webhook için bunu kullanın
# [proxy] - Proxy'nize bağlı diğer sunuculara uyarı göndermek için bunu kullanın (BungeeCord/Velocity)
Punishments:
Simulation:
# Kaç saniye sonra ihlaller kaldırılsın?
remove-violations-after: 300
# Bu bölüm, aşağıdaki adlara sahip tüm kontrollerle eşleşecektir,
# Aksi takdirde eşleşecek bir denetimi hariç tutmak için, isminin önüne ünlem işareti koyun
# Örnek olarak, !BadPacketsN
checks:
- "Simulation"
- "GroundSpoof"
- "Timer"
- "NoFall"
# Eşik:Aralık Komutu
#
# Örnek: 100 ihlalde "yanlış hareket!" mesajıyla oyuncuyu atmak için, aralık komutu olmadan:
# - "100:0 kick %player% Yanlış hareket!"
# 0, tam olarak bir kez çalıştırılmasını ifade eder
# - "100:50 say %player% Hile yapıyor!"
# Kullanıcı 100 işaretine ulaştığında çalışır ve bundan sonra, 100'ün üzerindeki her 50. işarette çalışır
commands:
- "100:40 [alert]"
- "100:100 [webhook]"
- "100:100 [proxy]"
Knockback:
remove-violations-after: 300
checks:
- "Knockback"
- "Explosion"
commands:
- "5:5 [alert]"
- "20:20 [webhook]"
- "20:20 [proxy]"
Post:
remove-violations-after: 300
checks:
- "Post"
commands:
- "20:20 [alert]"
- "40:40 [webhook]"
- "40:40 [proxy]"
BadPackets:
remove-violations-after: 300
checks:
- "BadPackets"
- "Crash"
commands:
- "20:20 [alert]"
- "40:40 [webhook]"
- "40:40 [proxy]"
Reach:
remove-violations-after: 300
checks:
- "Reach"
commands:
- "5:5 [alert]"
- "5:5 [webhook]"
- "5:5 [proxy]"
Misc:
remove-violations-after: 300
checks:
- "EntityControl"
- "NoSlow"
- "Place"
- "Baritone"
- "FastBreak"
- "TransactionOrder"
commands:
- "10:5 [alert]"
- "20:10 [webhook]"
- "20:10 [proxy]"
Combat:
remove-violations-after: 300
checks:
- "Killaura"
- "Aim"
commands:
- "20:40 [alert]"
# 2.2.10 itibarıyla, AutoClicker denetimleri yoktur ve bu bir yer tutucudur. Grim, gelecekte AutoClicker denetimlerini dahil edecektir.
Autoclicker:
remove-violations-after: 300
checks:
- "Autoclicker"
commands:
- "20:40 [alert]"
+8 -8
View File
@@ -1,31 +1,31 @@
# %check_name% - 检查名称
# %description% - 检查的介绍
# %description% - description of the check
# %vl% - 违规
# %verbose% - 额外信息
# %player% - 玩家名字
# [alert] - 警告的特殊命令
# [webhook] - 警告discord webhook 的特殊命令
# [proxy] - 用于使用(BungeeCord/Velocity)服务器时的警报
# [proxy] - special command to alert to other servers connected to your proxy (BungeeCord/Velocity)
Punishments:
Simulation:
# 多少秒后重置VL
remove-violations-after: 300
# 这个部分将会匹配检查的名字
# 要关闭掉一个检查就在检查前面加感叹号
# 例如, !BadPacketsN
# This section will match all checks with the name,
# To exclude a check that would otherwise be matched, put an exclamation mark in front of the name
# For example, !BadPacketsN
checks:
- "Simulation"
- "GroundSpoof"
- "Timer"
- "NoFall"
# 最大vl:下一次执行需要的vl
# Threshold:Interval Command
#
# 这是个例子, 当到达100VL时为了以 "incorrect movement!" 为理由踢出玩家
# commands:
# - "100:0 kick %player% incorrect movement!"
# 后面的数如果使用0就代表只执行一次
# 0 means execute exactly once
# - "100:50 say %player% is cheating"
# 在100vl后执行say %player% is cheating,之后的每50vl都执行一次say %player% is cheating
# Execute when the user hits flag 100, and after that, every 50th flag after 100
#
commands:
- "100:40 [alert]"