Compare commits
249
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf80d63c4a | ||
|
|
540fc454b9 | ||
|
|
cad28d6342 | ||
|
|
978cbb293c | ||
|
|
42ce2122a8 | ||
|
|
096b01213c | ||
|
|
f8a5315fff | ||
|
|
22e9a649c5 | ||
|
|
8e470d82bc | ||
|
|
de083b7b84 | ||
|
|
3f86a097de | ||
|
|
1b3b3d7b1d | ||
|
|
40aa1eadbe | ||
|
|
fac7d98530 | ||
|
|
b9f16762f1 | ||
|
|
441af405b7 | ||
|
|
71fb934a7e | ||
|
|
fe1d3b2b93 | ||
|
|
a408946c0e | ||
|
|
f1192069ae | ||
|
|
09139062c6 | ||
|
|
813551a093 | ||
|
|
3028b4d274 | ||
|
|
7daaca95eb | ||
|
|
102b5842e7 | ||
|
|
a76bf9ce09 | ||
|
|
4f3e715f94 | ||
|
|
1b47e31776 | ||
|
|
b69906f809 | ||
|
|
9ba4052c35 | ||
|
|
a86bf57a39 | ||
|
|
a82f2b888a | ||
|
|
89cf181772 | ||
|
|
6e5ec332dd | ||
|
|
79bf7e4fd1 | ||
|
|
d0aafdd9f7 | ||
|
|
3f19abc859 | ||
|
|
8a6863b9d3 | ||
|
|
26492fd8e3 | ||
|
|
15e809835b | ||
|
|
1eae5484c7 | ||
|
|
90036e2bf2 | ||
|
|
faf2fb3afb | ||
|
|
7461aca13f | ||
|
|
f381805cad | ||
|
|
2fa022eb00 | ||
|
|
44900e584b | ||
|
|
a2f4dc1979 | ||
|
|
0237f956ff | ||
|
|
e222df8e87 | ||
|
|
bbab7e222c | ||
|
|
41c7e41a0e | ||
|
|
5551ef68e1 | ||
|
|
ca6e83de4d | ||
|
|
4d6ac75c73 | ||
|
|
1317ae0bb4 | ||
|
|
d538c59a79 | ||
|
|
6a223a30c7 | ||
|
|
2e1c79b4e3 | ||
|
|
bb143d7993 | ||
|
|
322d2567c0 | ||
|
|
8d7a4cce87 | ||
|
|
832194a1e9 | ||
|
|
0321e0bceb | ||
|
|
63854605b6 | ||
|
|
5c4602188e | ||
|
|
163e120f00 | ||
|
|
ce6e1d3e9f | ||
|
|
f6024a4308 | ||
|
|
b4d031c81e | ||
|
|
d7cb4aa4e3 | ||
|
|
b85c65d623 | ||
|
|
c208824b16 | ||
|
|
7f6b7d0bfa | ||
|
|
a56e99e3e2 | ||
|
|
9e7dabea34 | ||
|
|
42c6d08ff1 | ||
|
|
0bbf472c55 | ||
|
|
d9e279a949 | ||
|
|
cccc5fdfb6 | ||
|
|
a7bdc869d4 | ||
|
|
513633c645 | ||
|
|
c3eb0e4196 | ||
|
|
7137b36d62 | ||
|
|
2c0b4a2a60 | ||
|
|
8f437d6bec | ||
|
|
c0bd2dd685 | ||
|
|
258d94b525 | ||
|
|
6a02c93204 | ||
|
|
0c86d017ac | ||
|
|
6d3aa4784d | ||
|
|
cec4a85454 | ||
|
|
438e1accf9 | ||
|
|
f9fff4ee0c | ||
|
|
b102afb8c8 | ||
|
|
ef0ea352ad | ||
|
|
e36e61987d | ||
|
|
3cf06bf00b | ||
|
|
7b243d3a44 | ||
|
|
d24726c7df | ||
|
|
1bb95e796d | ||
|
|
642e580e61 | ||
|
|
8884b0a126 | ||
|
|
7c5aae956e | ||
|
|
0e6d116ec6 | ||
|
|
141ccae1c2 | ||
|
|
662d02cc2a | ||
|
|
c42217375b | ||
|
|
258ef064ba | ||
|
|
12e79a1ea0 | ||
|
|
e0093897dc | ||
|
|
8d1ee003d9 | ||
|
|
aa4c6e0f1d | ||
|
|
0fd2a96aca | ||
|
|
d15a2dd23a | ||
|
|
0095f8acc1 | ||
|
|
b824ce107d | ||
|
|
50f3d84207 | ||
|
|
a26951cc95 | ||
|
|
b72485da7e | ||
|
|
2f8a4738b3 | ||
|
|
a74e10e888 | ||
|
|
dda13325cf | ||
|
|
2df4c23bf2 | ||
|
|
8f785564d7 | ||
|
|
cbc2f51a0c | ||
|
|
3ac26d0601 | ||
|
|
cc10288e0d | ||
|
|
c10e74cd72 | ||
|
|
fb926ab0fb | ||
|
|
4be254939d | ||
|
|
40a4c081c7 | ||
|
|
1f16d7b0de | ||
|
|
8d25519ace | ||
|
|
fefaa57044 | ||
|
|
01ff3ecea7 | ||
|
|
f54ceb6531 | ||
|
|
18d1602b3a | ||
|
|
c90d7ab941 | ||
|
|
c428bf65be | ||
|
|
088621faff | ||
|
|
2a5979cc3c | ||
|
|
9618912072 | ||
|
|
a0bd388109 | ||
|
|
2403bc5df7 | ||
|
|
9b2b080d1e | ||
|
|
b70abbe6cd | ||
|
|
293f6ea8b1 | ||
|
|
fe7a263b01 | ||
|
|
cb13221b8d | ||
|
|
c2a07bd6f1 | ||
|
|
184050bfc6 | ||
|
|
e368bc88ad | ||
|
|
becbba3647 | ||
|
|
db92c6587e | ||
|
|
a02f49ef87 | ||
|
|
846e9ad4ed | ||
|
|
57a9f8f432 | ||
|
|
b7c5837305 | ||
|
|
f739b1e396 | ||
|
|
070116b037 | ||
|
|
a8693c300e | ||
|
|
0586ea5bf6 | ||
|
|
bd4cd314c6 | ||
|
|
0bf3a21677 | ||
|
|
dc030603c8 | ||
|
|
4e1320f032 | ||
|
|
9f4c321f44 | ||
|
|
2b037554fb | ||
|
|
64ebdf21b2 | ||
|
|
e26cf0f73d | ||
|
|
42d247b641 | ||
|
|
ea5ed0610c | ||
|
|
3f1755722c | ||
|
|
d2a8dceb2d | ||
|
|
f87a077e23 | ||
|
|
9ea389bc6a | ||
|
|
566dc9bf3b | ||
|
|
b44dd89136 | ||
|
|
eddb14b92c | ||
|
|
21ef46a291 | ||
|
|
cecf5fbab2 | ||
|
|
b37393c75d | ||
|
|
aab6908da0 | ||
|
|
d71239bb22 | ||
|
|
345502b43c | ||
|
|
a7f8c7790e | ||
|
|
ff9af985bf | ||
|
|
dbac8bc43e | ||
|
|
4702add980 | ||
|
|
090d1a843b | ||
|
|
8f1e993913 | ||
|
|
17a8d3b3c9 | ||
|
|
1c46546c15 | ||
|
|
97c1bddc16 | ||
|
|
b997b6b10f | ||
|
|
28d83206c1 | ||
|
|
6320fa68ce | ||
|
|
0340e07547 | ||
|
|
fd59498b9b | ||
|
|
c0b96ea512 | ||
|
|
38ccc559eb | ||
|
|
0dec74390f | ||
|
|
a953f501cd | ||
|
|
03e15141d7 | ||
|
|
57618963e7 | ||
|
|
8cb4189554 | ||
|
|
94813c0566 | ||
|
|
b0906d936f | ||
|
|
6ce610e0b5 | ||
|
|
ba305cf224 | ||
|
|
a3108c7850 | ||
|
|
1ba072fe80 | ||
|
|
376e7a9344 | ||
|
|
380e3d9094 | ||
|
|
796a573ca1 | ||
|
|
e433652ca3 | ||
|
|
7376468701 | ||
|
|
d2df1b76d2 | ||
|
|
6787d1bcd1 | ||
|
|
0a4a6cd7ef | ||
|
|
be120f062f | ||
|
|
2bf1260a22 | ||
|
|
2e625e260c | ||
|
|
4287f62cd7 | ||
|
|
b5c14f47ff | ||
|
|
647b13c083 | ||
|
|
cd8d78dd5d | ||
|
|
a9a203466c | ||
|
|
a695dac39b | ||
|
|
5183ad8631 | ||
|
|
0374b8c345 | ||
|
|
a2395606de | ||
|
|
61f7ad8f71 | ||
|
|
1136936ba1 | ||
|
|
25b0582074 | ||
|
|
cec0738e32 | ||
|
|
31107ec4b5 | ||
|
|
4b514e7098 | ||
|
|
527c87e4cf | ||
|
|
3875a6b238 | ||
|
|
5a4471c585 | ||
|
|
ba4bbef66f | ||
|
|
29e0c6e42c | ||
|
|
2528ff525d | ||
|
|
77c165cfa8 | ||
|
|
fe1c6bf3dd | ||
|
|
3de670eb1c | ||
|
|
533ae70f05 |
No files matched your search
@@ -7,6 +7,8 @@ indent_style = space
|
||||
insert_final_newline = true
|
||||
max_line_length = 100
|
||||
tab_width = 4
|
||||
end_of_line = crlf
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
# intellij specific configuration
|
||||
ij_continuation_indent_size = 8
|
||||
|
||||
@@ -30,6 +30,14 @@ body:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Client version
|
||||
description: |
|
||||
Provide the version of your Minecraft client.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Plugins
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
name: Reusable Build and Publish
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
is-release-build:
|
||||
description: 'True if this is a release build, which affects versioning and publishing.'
|
||||
required: true
|
||||
type: boolean
|
||||
release-version-type:
|
||||
description: 'The version type for Modrinth (e.g., release, beta, alpha).'
|
||||
required: true
|
||||
type: string
|
||||
release-changelog:
|
||||
description: 'The changelog content for the release.'
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
run-build-scan:
|
||||
description: 'Whether to enable Develocity build scan'
|
||||
required: true
|
||||
type: boolean
|
||||
publish-artifacts:
|
||||
description: 'If true, uploads artifacts to Modrinth and other distribution sites.'
|
||||
required: true
|
||||
type: boolean
|
||||
secrets:
|
||||
MODRINTH_ID:
|
||||
required: false
|
||||
MODRINTH_TOKEN:
|
||||
required: false
|
||||
BUILD_UPDATE_TOKEN:
|
||||
required: true
|
||||
BUILD_UPDATE_URL:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
env:
|
||||
MODRINTH_ID: ${{ secrets.MODRINTH_ID }}
|
||||
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
|
||||
GRIM_MAIN_BRANCH: ${{ github.event.repository.default_branch }}
|
||||
BUILD_UPDATE_TOKEN: ${{ secrets.BUILD_UPDATE_TOKEN }}
|
||||
|
||||
steps:
|
||||
- name: Checkout repository with full history
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 200
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'temurin'
|
||||
server-id: github
|
||||
settings-path: ${{ github.workspace }}
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
with:
|
||||
cache-read-only: ${{ github.ref_name != github.event.repository.default_branch && github.ref_name != 'dev' }}
|
||||
|
||||
- name: Cache Gradle Loom Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .gradle/loom-cache
|
||||
key: loom-cache-${{ runner.os }}-${{ hashFiles('**/libs.versions.toml', 'fabric/**/build.gradle.kts') }}
|
||||
restore-keys: |
|
||||
loom-cache-${{ runner.os }}
|
||||
|
||||
- name: Set Git Environment Variables
|
||||
run: |
|
||||
echo "GRIM_GIT_REPO=${{ github.event.repository.name }}" >> $GITHUB_ENV
|
||||
echo "GRIM_GIT_ORG=${{ github.repository_owner }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Compute version and Build with Gradle
|
||||
id: build_with_version
|
||||
run: |
|
||||
# If any command in a pipeline fails, treat the pipeline as failed.
|
||||
set -o pipefail
|
||||
|
||||
BUILD_ARGS="build"
|
||||
if [[ "${{ inputs.is-release-build }}" == "true" ]]; then
|
||||
BUILD_ARGS="$BUILD_ARGS -Prelease=true"
|
||||
fi
|
||||
# Conditionally add the --scan flag
|
||||
if [[ "${{ inputs.run-build-scan }}" == "true" ]]; then
|
||||
BUILD_ARGS="$BUILD_ARGS --scan"
|
||||
fi
|
||||
|
||||
echo "Running: ./gradlew printVersion $BUILD_ARGS"
|
||||
|
||||
# Use 'tee' to both display the output live and save it to a file for parsing
|
||||
VERSION=$(./gradlew printVersion $BUILD_ARGS | tee build-output.log | grep '^VERSION=' | tail -n1 | cut -d'=' -f2)
|
||||
|
||||
echo "build_version=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "BUILD_VERSION=$VERSION" >> $GITHUB_ENV
|
||||
echo "Build version: $VERSION"
|
||||
|
||||
- name: Publish Build Scan URL
|
||||
# Only run this step if a scan was requested
|
||||
if: ${{ inputs.run-build-scan == true }}
|
||||
run: |
|
||||
# Search the log file for the build scan URL and extract it
|
||||
SCAN_URL=$(grep -o 'https://gradle.com/s/[^ ]*' build-output.log | head -n 1 || true)
|
||||
|
||||
if [[ -n "$SCAN_URL" ]]; then
|
||||
echo "Found build scan URL: $SCAN_URL"
|
||||
# Post a highly visible link to the Job Summary page
|
||||
echo "### Gradle Build Scan" >> $GITHUB_STEP_SUMMARY
|
||||
echo "A public build scan has been published and is available for inspection." >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "[**View Build Scan →**]($SCAN_URL)" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "Could not find build scan URL in build-output.log" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
- name: Upload Bukkit Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: grimac-bukkit
|
||||
path: ${{ github.workspace }}/bukkit/build/libs/grimac-bukkit-${{ env.BUILD_VERSION }}.jar
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload Fabric Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: grimac-fabric
|
||||
path: ${{ github.workspace }}/fabric/build/libs/grimac-fabric-${{ env.BUILD_VERSION }}.jar
|
||||
if-no-files-found: error
|
||||
|
||||
#------------------------------------------------------------------
|
||||
# Generate/Prepare Changelog
|
||||
#------------------------------------------------------------------
|
||||
- name: Generate Changelog with git-cliff (for Dev Builds)
|
||||
if: ${{ !inputs.is-release-build }}
|
||||
id: git-cliff
|
||||
uses: orhun/git-cliff-action@v4
|
||||
with:
|
||||
config: cliff.toml
|
||||
args: --verbose ${{ github.event.before }}..${{ github.event.after }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # git-cliff needs a token
|
||||
|
||||
- name: Prepare Final Changelog
|
||||
id: changelog
|
||||
# Add this 'env' block to safely load the changelogs as environment variables
|
||||
env:
|
||||
RELEASE_NOTES: ${{ inputs.release-changelog }}
|
||||
DEV_NOTES: ${{ steps.git-cliff.outputs.content }}
|
||||
run: |
|
||||
NOTES=""
|
||||
if [[ "${{ inputs.is-release-build }}" == "true" ]]; then
|
||||
# Use the environment variable for the release changelog.
|
||||
# The double quotes are critical to preserve newlines!
|
||||
NOTES="$RELEASE_NOTES"
|
||||
else
|
||||
# Use the environment variable for the dev changelog.
|
||||
NOTES="$DEV_NOTES"
|
||||
fi
|
||||
|
||||
if [ -z "$NOTES" ]; then
|
||||
NOTES="* No new code changes in this build."
|
||||
fi
|
||||
|
||||
# This is the correct way to set a multi-line output variable in Actions
|
||||
{
|
||||
echo "notes<<EOF"
|
||||
echo "$NOTES"
|
||||
echo "EOF"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
#------------------------------------------------------------------
|
||||
# Publish to Modrinth & API
|
||||
#------------------------------------------------------------------
|
||||
- name: Publish Bukkit to Modrinth
|
||||
if: ${{ inputs.publish-artifacts == true && env.MODRINTH_ID != '' && env.MODRINTH_TOKEN != '' }}
|
||||
uses: Kir-Antipov/mc-publish@v3.3
|
||||
with:
|
||||
modrinth-id: ${{ secrets.MODRINTH_ID }}
|
||||
modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
|
||||
modrinth-featured: ${{ inputs.is-release-build }} # Only feature release builds
|
||||
|
||||
files: bukkit/build/libs/grimac-bukkit-${{ env.BUILD_VERSION }}.jar
|
||||
name: Grim Anticheat (Bukkit) ${{ env.BUILD_VERSION }}
|
||||
version: ${{ env.BUILD_VERSION }}
|
||||
version-type: ${{ inputs.release-version-type }}
|
||||
changelog: ${{ steps.changelog.outputs.notes }}
|
||||
loaders: |
|
||||
bukkit
|
||||
spigot
|
||||
paper
|
||||
folia
|
||||
purpur
|
||||
game-versions: '>=1.7 <=1.21.8'
|
||||
|
||||
- name: Publish Fabric to Modrinth
|
||||
if: ${{ inputs.publish-artifacts == true && env.MODRINTH_ID != '' && env.MODRINTH_TOKEN != '' }}
|
||||
uses: Kir-Antipov/mc-publish@v3.3
|
||||
with:
|
||||
modrinth-id: ${{ secrets.MODRINTH_ID }}
|
||||
modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
|
||||
modrinth-featured: ${{ inputs.is-release-build }} # Only feature release builds
|
||||
|
||||
files: fabric/build/libs/grimac-fabric-${{ env.BUILD_VERSION }}.jar
|
||||
name: Grim Anticheat (Fabric) ${{ env.BUILD_VERSION }}
|
||||
version: ${{ env.BUILD_VERSION }}
|
||||
version-type: ${{ inputs.release-version-type }}
|
||||
changelog: ${{ steps.changelog.outputs.notes }}
|
||||
loaders: |
|
||||
fabric
|
||||
game-versions: '>=1.16.1 <=1.21.8'
|
||||
dependencies: 'fabric-api'
|
||||
|
||||
- name: Publish to API
|
||||
if: ${{ inputs.publish-artifacts == true && env.BUILD_UPDATE_TOKEN != '' }}
|
||||
run: |
|
||||
curl -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "User-Agent: GrimACBuilder/v1" \
|
||||
-H "Authorization: Bearer ${{ secrets.BUILD_UPDATE_TOKEN }}" \
|
||||
-d '{"org": "${{ github.repository_owner }}", "repository": "${{ github.event.repository.name }}", "branch": "${{ github.ref_name }}", "version": "${{ env.BUILD_VERSION }}"}' \
|
||||
"${{ secrets.BUILD_UPDATE_URL }}"
|
||||
@@ -12,13 +12,9 @@
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ master ]
|
||||
schedule:
|
||||
- cron: '30 15 * * 2'
|
||||
branches: [ dev ]
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
@@ -32,14 +28,14 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'java' ]
|
||||
language: [ 'java-kotlin' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||
# Learn more:
|
||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
@@ -51,6 +47,14 @@ jobs:
|
||||
# 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
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version: '21'
|
||||
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
|
||||
|
||||
# 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
|
||||
|
||||
@@ -1,59 +1,44 @@
|
||||
# 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]
|
||||
name: Gradle Package (Development)
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
run-build-scan:
|
||||
description: 'Run with public build scan (adds --scan)'
|
||||
required: true
|
||||
type: boolean
|
||||
default: false
|
||||
publish-artifacts:
|
||||
description: 'Upload to Modrinth & API? (Uncheck for a dry run)'
|
||||
type: boolean
|
||||
default: true
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
- '2.0'
|
||||
- 'dev'
|
||||
- 'release'
|
||||
- 'release/**'
|
||||
paths:
|
||||
- '.github/workflows/**'
|
||||
- 'buildSrc/**'
|
||||
- 'bukkit/**'
|
||||
- 'common/**'
|
||||
- 'fabric/**'
|
||||
- '**.java'
|
||||
- '**.kt'
|
||||
- '**.kts'
|
||||
- '**.toml'
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '21'
|
||||
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: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4 # Handles Gradle wrapper validation and basic caching
|
||||
|
||||
- name: Cache Gradle Loom Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .gradle/loom-cache # Path to Loom cache relative to workspace root
|
||||
key: loom-cache-${{ runner.os }}-${{ hashFiles('**/libs.versions.toml', 'fabric/**/build.gradle.kts') }}
|
||||
restore-keys: |
|
||||
loom-cache-${{ runner.os }}
|
||||
|
||||
- name: Build with Gradle (Actual Build for Artifacts)
|
||||
run: ./gradlew build
|
||||
|
||||
- name: Upload Bukkit Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: grimac-bukkit
|
||||
# Adding if-no-files-found for robustness
|
||||
path: ${{ github.workspace }}/bukkit/build/libs/grimac-bukkit-*.jar
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload Fabric Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: grimac-fabric
|
||||
# Adding if-no-files-found for robustness
|
||||
path: ${{ github.workspace }}/fabric/build/libs/grimac-fabric-*.jar
|
||||
if-no-files-found: error
|
||||
|
||||
call-build-workflow:
|
||||
uses: ./.github/workflows/build-and-publish.yml
|
||||
with:
|
||||
is-release-build: false
|
||||
release-version-type: alpha # Dev builds are always 'alpha'
|
||||
run-build-scan: ${{ github.event.inputs.run-build-scan == 'true' }}
|
||||
publish-artifacts: ${{ github.event.inputs.publish-artifacts != 'false' }}
|
||||
secrets:
|
||||
MODRINTH_ID: ${{ secrets.MODRINTH_ID }}
|
||||
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
|
||||
BUILD_UPDATE_TOKEN: ${{ secrets.BUILD_UPDATE_TOKEN }}
|
||||
BUILD_UPDATE_URL: ${{ secrets.BUILD_UPDATE_URL }}
|
||||
@@ -0,0 +1,21 @@
|
||||
name: Publish Release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
call-release-workflow:
|
||||
uses: ./.github/workflows/build-and-publish.yml
|
||||
with:
|
||||
is-release-build: true
|
||||
release-version-type: release # Official releases are 'release'
|
||||
# Use the body of the GitHub Release as the changelog
|
||||
release-changelog: ${{ github.event.release.body }}
|
||||
run-build-scan: false
|
||||
publish-artifacts: true
|
||||
secrets:
|
||||
MODRINTH_ID: ${{ secrets.MODRINTH_ID }}
|
||||
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
|
||||
BUILD_UPDATE_TOKEN: ${{ secrets.BUILD_UPDATE_TOKEN }}
|
||||
BUILD_UPDATE_URL: ${{ secrets.BUILD_UPDATE_URL }}
|
||||
+23
-15
@@ -5,26 +5,34 @@ making pull
|
||||
requests to the project. *We're usually pretty lenient with pull requests, but this guide will help
|
||||
make the process go more smoothly.*
|
||||
|
||||
### Acceptable Pull Requests
|
||||
|
||||
**Bug fixes** and **new features** are welcome. However, some things like heuristic-based checks
|
||||
will **not** be accepted.
|
||||
|
||||
### Pull Request Guidelines
|
||||
|
||||
- Ensure any changes are compatible with
|
||||
the [supported environments](https://github.com/GrimAnticheat/Grim/wiki/Supported-environments).
|
||||
- Create a new branch for your feature or fix when forking the repository.
|
||||
- Write clear and descriptive commit messages.
|
||||
- Reference related issues in your pull request description if applicable.
|
||||
- Add code comments for complex logic or significant changes.
|
||||
- Try to keep your code clean and avoid duplication.
|
||||
- Thoroughly test your changes before submitting your pull request.
|
||||
- **Compatibility**
|
||||
- Any changes must be compatible with
|
||||
the [supported environments](https://github.com/GrimAnticheat/Grim/wiki/Supported-environments) (Spigot, Paper, Folia, Fabric, etc.)
|
||||
- The plugin must be compatible with minecraft versions 1.8 and higher. Exempting checks from specific versions is acceptable.
|
||||
- The plugin must be able to run on Java 17 or higher. Changes that don't support Java 17 at runtime will not be accepted.
|
||||
|
||||
- **Non-acceptable pull requests**
|
||||
- Heuristic-based checks will not be accepted; however, basic rate limiting such as blocking attacks based on CPS is acceptable.
|
||||
- Checks that can be easily circumvented that don't block packets or fix anything are likely to not be accepted.
|
||||
- Checks or features that are too specific to a single environment or minecraft version are likely to not be accepted.
|
||||
- Changes that require large or unnecessary dependencies will likely not be accepted.
|
||||
|
||||
- **Pull request formatting**
|
||||
- Create a new branch for your feature or fix when forking the repository.
|
||||
- Reference related issues in your pull request description if applicable.
|
||||
- Write clear and descriptive commit messages.
|
||||
|
||||
- **Code styling**
|
||||
- Add code comments for complex logic or significant changes.
|
||||
- Try to keep your code clean and avoid duplication.
|
||||
- Thoroughly test your changes before submitting your pull request.
|
||||
|
||||
### Development Notes
|
||||
|
||||
- GrimAC is built using [Gradle](https://gradle.org/).
|
||||
- Java 21 is currently required to build the project, but it is not required to run it.
|
||||
- GrimAC is built using [Gradle](https://gradle.org/) kotlin scripts.
|
||||
- Java 21 is currently required to build the project. A minimum of Java 17 is required to run it.
|
||||
|
||||
### Questions & Support
|
||||
|
||||
|
||||
@@ -3,28 +3,35 @@
|
||||
|
||||
<div>
|
||||
<a href="https://github.com/GrimAnticheat/Grim/actions/workflows/gradle-publish.yml">
|
||||
<img alt="Workflow" src="https://github.com/GrimAnticheat/Grim/actions/workflows/gradle-publish.yml/badge.svg" />
|
||||
</a>
|
||||
<img alt="Workflow" src="https://img.shields.io/github/actions/workflow/status/GrimAnticheat/Grim/gradle-publish.yml?style=flat&logo=github"/>
|
||||
</a>
|
||||
<a href="https://modrinth.com/plugin/grimac">
|
||||
<img alt="Modrinth" src="https://img.shields.io/modrinth/v/LJNGWSvH?style=flat&label=version&logo=modrinth">
|
||||
</a>
|
||||
<a href="https://modrinth.com/plugin/grimac#download">
|
||||
<img alt="Downloads" src="https://img.shields.io/modrinth/dt/LJNGWSvH?style=flat&logo=modrinth&label=downloads&link=https%3A%2F%2Fmodrinth.com%2Fplugin%2Fgrimac%23download">
|
||||
</a>
|
||||
<a href="https://discord.grim.ac">
|
||||
<img alt="Discord" src="https://img.shields.io/discord/811396969670901800?style=flat&label=Discord&logo=discord">
|
||||
<img alt="Discord" src="https://img.shields.io/discord/811396969670901800?style=flat&label=discord&logo=discord">
|
||||
</a>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
GrimAC is an open source minecraft anticheat designed for the latest versions of minecraft with
|
||||
support for versions 1.8 and higher. Geyser players are fully exempt from the anticheat to prevent
|
||||
false positives. This project is currently free and open source, but future versions will eventually
|
||||
become paid and/or will include additional subscription based paid checks. If you would like a
|
||||
bugfix or enhancement and cannot sponsor the work, pull requests are welcome.
|
||||
GrimAC is an open source Minecraft anticheat designed to support the latest versions of Minecraft.
|
||||
It currently supports minecraft versions 1.8–1.21. Geyser players are fully exempt from the anticheat to prevent false positives.
|
||||
This project is considered feature-complete for the 2.0 (open-source) branch. If you would like a bug fix or enhancement and cannot sponsor the work, pull requests are welcome.
|
||||
A premium version is planned, which will offer additional subscription-based paid checks, such as heuristics.
|
||||
|
||||
## Downloads
|
||||
|
||||
- [Modrinth](https://modrinth.com/plugin/grimac)
|
||||
- [Hangar](https://hangar.papermc.io/GrimAnticheat/GrimAnticheat)
|
||||
- [SpigotMC](https://www.spigotmc.org/resources/grim-anticheat.99923/)
|
||||
- *For bleeding edge builds use GitHub
|
||||
artifacts*: [Bukkit](https://nightly.link/GrimAnticheat/Grim/workflows/gradle-publish/2.0/grimac-bukkit.zip), [Fabric](https://nightly.link/GrimAnticheat/Grim/workflows/gradle-publish/2.0/grimac-fabric.zip)
|
||||
- Latest updates:
|
||||
- **[Modrinth](https://modrinth.com/plugin/grimac)** *(recommended)*
|
||||
- GitHub
|
||||
artifacts: [Bukkit](https://nightly.link/GrimAnticheat/Grim/workflows/gradle-publish/2.0/grimac-bukkit.zip), [Fabric](https://nightly.link/GrimAnticheat/Grim/workflows/gradle-publish/2.0/grimac-fabric.zip) *(bleeding edge)*
|
||||
- Major releases only:
|
||||
- ~~[Hangar](https://hangar.papermc.io/GrimAnticheat/GrimAnticheat)~~
|
||||
- ~~[SpigotMC](https://www.spigotmc.org/resources/grim-anticheat.99923/)~~
|
||||
|
||||
## Resources
|
||||
|
||||
@@ -32,6 +39,13 @@ bugfix or enhancement and cannot sponsor the work, pull requests are welcome.
|
||||
- For answers to commonly asked questions visit the [FAQ](https://github.com/GrimAnticheat/Grim/wiki/FAQ).
|
||||
- For community support and project discussion join our [Discord](https://discord.grim.ac).
|
||||
|
||||
|
||||
## Pull Requests
|
||||
|
||||
See [Contributing](CONTRIBUTING.md) for more information about contributing and what our guidelines
|
||||
are.
|
||||
|
||||
|
||||
## Requirements & Installation
|
||||
|
||||
- Java 17 or higher. *For more details
|
||||
@@ -56,11 +70,6 @@ information.
|
||||
3. `./gradlew build`
|
||||
4. The final jars will compile into the `<platform>/build/libs` folders
|
||||
|
||||
## Pull Requests
|
||||
|
||||
See [Contributing](CONTRIBUTING.md) for more information about contributing and what our guidelines
|
||||
are.
|
||||
|
||||
## Grim Supremacy
|
||||
|
||||
What makes Grim stand out against other anticheats?
|
||||
|
||||
+19
-15
@@ -1,12 +1,10 @@
|
||||
/**
|
||||
* ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
* ┃ GrimAC Build Configuration ┃
|
||||
* ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
||||
* GrimAC Build Configuration
|
||||
*
|
||||
* 🔧 Build Flags:
|
||||
* -PshadePE=true → Enables 'lite' mode
|
||||
* -Prelocate=false → Adds 'no_relocate' modifier
|
||||
* -Prelease=true → Removes commit/modifiers for release build
|
||||
* Build Flags:
|
||||
* -PshadePE=true - Enables 'lite' mode
|
||||
* -Prelocate=false - Adds 'no_relocate' modifier
|
||||
* -Prelease=true - Removes commit/modifiers for release build
|
||||
*
|
||||
* Logic in: buildSrc/versioning/BuildConfig.kt & VersionUtil.kt
|
||||
*/
|
||||
@@ -16,17 +14,23 @@ import versioning.VersionUtil
|
||||
|
||||
BuildConfig.init(project)
|
||||
|
||||
val baseVersion = "2.3.72"
|
||||
val baseVersion = "2.3.73"
|
||||
group = "ac.grim.grimac"
|
||||
version = VersionUtil.computeVersion(baseVersion)
|
||||
description = "Libre simulation anticheat designed for 1.21 with 1.8–1.21 support, powered by PacketEvents 2.0."
|
||||
|
||||
println("⚙️ Build configuration:")
|
||||
println(" shadePE = ${BuildConfig.shadePE}")
|
||||
println(" relocate = ${BuildConfig.relocate}")
|
||||
println(" mavenLocalOverride = ${BuildConfig.mavenLocalOverride}")
|
||||
println(" release = ${BuildConfig.release}")
|
||||
println(" version = $version")
|
||||
ext["timestamp"] = System.currentTimeMillis().toString()
|
||||
ext["git_branch"] = VersionUtil.getGitBranch(true)
|
||||
ext["git_commit"] = VersionUtil.getGitCommitHash(true)
|
||||
ext["git_org"] = System.getenv("GRIM_GIT_ORG") ?: VersionUtil.getGitUser()
|
||||
ext["git_repo"] = System.getenv("GRIM_GIT_REPO") ?: "Grim"
|
||||
|
||||
println("Build configuration:")
|
||||
println(" shadePE = ${BuildConfig.shadePE}")
|
||||
println(" relocate = ${BuildConfig.relocate}")
|
||||
println(" mavenLocalOverride = ${BuildConfig.mavenLocalOverride}")
|
||||
println(" release = ${BuildConfig.release}")
|
||||
println(" version = $version")
|
||||
|
||||
tasks.register("printVersion") {
|
||||
group = "versioning"
|
||||
@@ -42,4 +46,4 @@ subprojects {
|
||||
options.isFork = true
|
||||
options.isIncremental = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ plugins {
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import versioning.BuildConfig
|
||||
|
||||
plugins {
|
||||
`java-library`
|
||||
id("io.freefair.lombok")
|
||||
@@ -16,11 +18,6 @@ java {
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
// Lombok configuration
|
||||
//lombok {
|
||||
// version.set("1.18.30") // Use the version from your version catalog if available
|
||||
//}
|
||||
|
||||
// Spotless configuration
|
||||
spotless {
|
||||
java {
|
||||
@@ -38,7 +35,6 @@ spotless {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tasks {
|
||||
withType<JavaCompile>().configureEach {
|
||||
options.encoding = "UTF-8"
|
||||
@@ -52,11 +48,29 @@ tasks {
|
||||
|
||||
// Process resources (e.g., for plugin metadata files)
|
||||
processResources {
|
||||
inputs.property("version", project.version)
|
||||
filesMatching(listOf( // "plugin.yml", Bukkit variable expansion taken care of by net.minecrell.plugin-yml.bukkit
|
||||
"bungee.yml", "velocity-plugin.json", "fabric.mod.json")
|
||||
val properties = mapOf(
|
||||
"timestamp" to rootProject.ext["timestamp"],
|
||||
"version" to project.version.toString(),
|
||||
"git_commit" to rootProject.ext["git_commit"],
|
||||
"git_branch" to rootProject.ext["git_branch"],
|
||||
"git_repo" to rootProject.ext["git_repo"],
|
||||
"git_org" to rootProject.ext["git_org"],
|
||||
"build_shade_pe" to BuildConfig.shadePE,
|
||||
"build_relocate" to BuildConfig.relocate,
|
||||
"build_release" to BuildConfig.release,
|
||||
)
|
||||
|
||||
properties.forEach { (key, value) -> inputs.property(key, value) }
|
||||
|
||||
filesMatching(
|
||||
listOf(
|
||||
"bungee.yml",
|
||||
"velocity-plugin.json",
|
||||
"fabric.mod.json",
|
||||
"grimac.properties"
|
||||
)
|
||||
) {
|
||||
expand("version" to project.version)
|
||||
expand(properties)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ fun extractEmbeddedJars(jarFile: File, project: Project): Set<DependencyIdentifi
|
||||
?: throw IllegalStateException("Missing 'id' in fabric.mod.json of embedded JAR: $entryName")
|
||||
val idWithDots = id.replace("_", ".")
|
||||
val lastDotIndex = idWithDots.lastIndexOf(".")
|
||||
val group = if (lastDotIndex != -1) idWithDots.substring(0, lastDotIndex) else ""
|
||||
val group = if (lastDotIndex != -1) idWithDots.take(lastDotIndex) else ""
|
||||
|
||||
// Extract name and version from the JAR filename
|
||||
val jarName = entryName.substringAfterLast("/").removeSuffix(".jar")
|
||||
@@ -127,7 +127,7 @@ fun parseNameAndVersionFromJarName(jarName: String): Pair<String, String>? {
|
||||
val versionStartIndex = versionStartMatch.range.first
|
||||
|
||||
// Split the JAR name into name and version at the version start index
|
||||
val name = jarName.substring(0, versionStartIndex)
|
||||
val name = jarName.take(versionStartIndex)
|
||||
val version = jarName.substring(versionStartIndex + 1) // Skip the hyphen
|
||||
|
||||
return if (name.isNotEmpty() && version.isNotEmpty()) {
|
||||
@@ -300,7 +300,7 @@ project.afterEvaluate {
|
||||
val allEmbeddedDependencies = mutableMapOf<DependencyIdentifier, File>()
|
||||
val actuallyIncludedDependencies = mutableSetOf<DependencyIdentifier>()
|
||||
|
||||
fun collectAllEmbeddedDependencies(dependencies: Set<ResolvedDependency>) {
|
||||
fun collectAllEmbeddedDependenciesForAfterEvaluate(dependencies: Set<ResolvedDependency>) {
|
||||
dependencies.forEach { dep ->
|
||||
val classifier = dep.moduleArtifacts.firstOrNull()?.classifier ?: ""
|
||||
val depKey = "${dep.moduleGroup}:${dep.moduleName}:${dep.moduleVersion}${if (classifier.isNotEmpty()) ":$classifier" else ""}"
|
||||
@@ -318,13 +318,13 @@ project.afterEvaluate {
|
||||
)
|
||||
}
|
||||
}
|
||||
collectAllEmbeddedDependencies(dep.children)
|
||||
collectAllEmbeddedDependenciesForAfterEvaluate(dep.children)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processed.clear()
|
||||
collectAllEmbeddedDependencies(resolvedDependencies)
|
||||
collectAllEmbeddedDependenciesForAfterEvaluate(resolvedDependencies)
|
||||
|
||||
processed.clear()
|
||||
processDependencies(
|
||||
@@ -345,7 +345,7 @@ tasks.withType<Jar>().configureEach {
|
||||
val allEmbeddedDependencies = mutableMapOf<DependencyIdentifier, File>()
|
||||
val actuallyIncludedDependencies = mutableSetOf<DependencyIdentifier>()
|
||||
|
||||
fun collectAllEmbeddedDependencies(dependencies: Set<ResolvedDependency>) {
|
||||
fun collectAllEmbeddedDependenciesForJar(dependencies: Set<ResolvedDependency>) {
|
||||
dependencies.forEach { dep ->
|
||||
val depKey = "${dep.moduleGroup}:${dep.moduleName}:${dep.moduleVersion}"
|
||||
if (!processed.contains(depKey)) {
|
||||
@@ -362,13 +362,13 @@ tasks.withType<Jar>().configureEach {
|
||||
)
|
||||
}
|
||||
}
|
||||
collectAllEmbeddedDependencies(dep.children)
|
||||
collectAllEmbeddedDependenciesForJar(dep.children)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processed.clear()
|
||||
collectAllEmbeddedDependencies(resolvedDependencies)
|
||||
collectAllEmbeddedDependenciesForJar(resolvedDependencies)
|
||||
|
||||
processed.clear()
|
||||
|
||||
|
||||
@@ -5,17 +5,10 @@ plugins {
|
||||
id("com.gradleup.shadow")
|
||||
}
|
||||
|
||||
// Create a configuration for shading dependencies from common
|
||||
val shadowCommon: Configuration by project.configurations.creating {
|
||||
isCanBeResolved = true
|
||||
isCanBeConsumed = false
|
||||
extendsFrom(project.configurations.getByName("implementation"))
|
||||
}
|
||||
|
||||
tasks.named<ShadowJar>("shadowJar") {
|
||||
minimize()
|
||||
archiveFileName.set("${rootProject.name}-${project.name}-${rootProject.version}.jar")
|
||||
from(shadowCommon) // Use from() instead of direct assignment
|
||||
archiveFileName = "${rootProject.name}-${project.name}-${rootProject.version}.jar"
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
|
||||
if (BuildConfig.relocate) {
|
||||
if (BuildConfig.shadePE) {
|
||||
|
||||
@@ -2,6 +2,11 @@ package versioning
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.internal.extensions.stdlib.toDefaultLowerCase
|
||||
import versioning.BuildConfig.init
|
||||
import versioning.BuildConfig.mavenLocalOverride
|
||||
import versioning.BuildConfig.release
|
||||
import versioning.BuildConfig.relocate
|
||||
import versioning.BuildConfig.shadePE
|
||||
|
||||
/**
|
||||
* BuildConfig provides access to user-defined build flags that control how a Grim
|
||||
@@ -10,9 +15,9 @@ import org.gradle.internal.extensions.stdlib.toDefaultLowerCase
|
||||
*
|
||||
* Flags can be defined in three ways:
|
||||
*
|
||||
* ① JVM system properties (-Dflag=value)
|
||||
* ② Gradle project properties (-Pflag=value or in gradle.properties)
|
||||
* ③ Environment variables (FLAG=value)
|
||||
* 1. JVM system properties (-Dflag=value)
|
||||
* 2. Gradle project properties (-Pflag=value or in gradle.properties)
|
||||
* 3. Environment variables (FLAG=value)
|
||||
*
|
||||
* You can use these to enable/disable features like shading, relocation, or release mode.
|
||||
*
|
||||
@@ -56,24 +61,15 @@ object BuildConfig {
|
||||
|
||||
// Unified resolution logic (System > Gradle > Env)
|
||||
private fun resolveRaw(project: Project, key: String): String? =
|
||||
System.getProperty(key) // ① JVM (-Dkey=value)
|
||||
?: project.findProperty(key)?.toString() // ② Gradle (-Pkey=value or gradle.properties)
|
||||
?: System.getenv(key.uppercase()) // ③ ENV (KEY=value)
|
||||
System.getProperty(key) // 1. JVM (-Dkey=value)
|
||||
?: project.findProperty(key)?.toString() // 2. Gradle (-Pkey=value or gradle.properties)
|
||||
?: System.getenv(key.uppercase()) // 3. ENV (KEY=value)
|
||||
|
||||
private fun resolveBool(project: Project, key: String, altKey: String? = null, default: Boolean): Boolean {
|
||||
val primaryValue = resolveRaw(project, key)?.toDefaultLowerCase()?.toBooleanStrictOrNull()
|
||||
if (primaryValue != null) {
|
||||
return primaryValue
|
||||
}
|
||||
|
||||
if (altKey != null) {
|
||||
val altValue = resolveRaw(project, altKey)?.toDefaultLowerCase()?.toBooleanStrictOrNull()
|
||||
if (altValue != null) {
|
||||
return altValue
|
||||
}
|
||||
}
|
||||
|
||||
return default
|
||||
return resolveRaw(project, key)?.toDefaultLowerCase()?.toBooleanStrictOrNull()
|
||||
?: altKey?.let {
|
||||
resolveRaw(project, it)?.toDefaultLowerCase()?.toBooleanStrictOrNull()
|
||||
} ?: default
|
||||
}
|
||||
|
||||
// Private backing vars (nullable because we can't use lateinit with primitives)
|
||||
@@ -96,4 +92,5 @@ object BuildConfig {
|
||||
|
||||
val mavenLocalOverride: Boolean get() = _mavenLocalOverride
|
||||
?: error("BuildConfig.release accessed before init() was called")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,29 +37,31 @@ object VersionUtil {
|
||||
val modifiers = buildList {
|
||||
if (!BuildConfig.shadePE) add("lite")
|
||||
if (!BuildConfig.relocate) add("no_relocate")
|
||||
}.takeIf { it.isNotEmpty() }?.joinToString("-")
|
||||
}.joinToString("-").takeIf { it.isNotEmpty() }
|
||||
|
||||
return buildString {
|
||||
append(baseVersion)
|
||||
append("-")
|
||||
branch?.let { append("$it-") }
|
||||
append(commitHash)
|
||||
modifiers?.let { append("+$modifiers") }
|
||||
modifiers?.let { append("+$it") }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current Git commit as a short hash.
|
||||
* Retrieves the current Git commit
|
||||
*/
|
||||
private fun getGitCommitHash(): String {
|
||||
fun getGitCommitHash(full: Boolean = false): String {
|
||||
val stdout = ByteArrayOutputStream()
|
||||
ProcessBuilder("git", "rev-parse", "--short", "HEAD")
|
||||
val command = listOfNotNull("git", "rev-parse", if (full) null else "--short", "HEAD")
|
||||
ProcessBuilder(command)
|
||||
.redirectErrorStream(true)
|
||||
.start()
|
||||
.apply { waitFor() }
|
||||
.inputStream
|
||||
.use { stdout.writeBytes(it.readAllBytes()) }
|
||||
return stdout.toString().trim()
|
||||
val fullCommit = stdout.toString().trim()
|
||||
return fullCommit.take(minOf(fullCommit.length, 7))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,7 +71,7 @@ object VersionUtil {
|
||||
* Any slash (/) in the branch name is replaced with an underscore (_)
|
||||
* to avoid filesystem issues.
|
||||
*/
|
||||
private fun getGitBranch(): String? {
|
||||
fun getGitBranch(raw: Boolean = false): String? {
|
||||
val stdout = ByteArrayOutputStream()
|
||||
|
||||
ProcessBuilder("git", "rev-parse", "--abbrev-ref", "HEAD")
|
||||
@@ -78,11 +80,34 @@ object VersionUtil {
|
||||
.apply { waitFor() }
|
||||
.inputStream.use { stdout.writeBytes(it.readAllBytes()) }
|
||||
|
||||
if (raw) return stdout.toString().trim()
|
||||
|
||||
val branch = stdout.toString().trim()
|
||||
.replace(Regex("[^a-zA-Z0-9_.-]+"), "_")
|
||||
.replace(Regex("_{2,}"), "_")
|
||||
.trim(' ', '.', '_', '-')
|
||||
.removePrefix("heads_")
|
||||
|
||||
val mainBranch = System.getenv("GRIM_MAIN_BRANCH") ?: "2.0"
|
||||
|
||||
return when (branch) {
|
||||
"main", "2.0" -> null // ← ignore these branches
|
||||
else -> branch.replace("/", "_")
|
||||
"main", mainBranch -> null // ← ignore these branches
|
||||
else -> branch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getGitUser(): String {
|
||||
try {
|
||||
val stdout = ByteArrayOutputStream()
|
||||
ProcessBuilder("git", "config", "user.name")
|
||||
.redirectErrorStream(true)
|
||||
.start()
|
||||
.apply { waitFor() }
|
||||
.inputStream.use { stdout.writeBytes(it.readAllBytes()) }
|
||||
return stdout.toString().trim()
|
||||
} catch (_: Exception) {
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+68
-17
@@ -5,34 +5,78 @@ plugins {
|
||||
`maven-publish`
|
||||
grim.`base-conventions`
|
||||
grim.`shadow-conventions`
|
||||
id("net.minecrell.plugin-yml.bukkit") version "0.6.0"
|
||||
id("xyz.jpenilla.run-paper") version "2.3.1"
|
||||
id("de.eldoria.plugin-yml.bukkit") version "0.8.0"
|
||||
id("xyz.jpenilla.run-paper") version "3.0.0-beta.1"
|
||||
}
|
||||
|
||||
repositories {
|
||||
if (BuildConfig.mavenLocalOverride) {
|
||||
mavenLocal()
|
||||
}
|
||||
maven {
|
||||
name = "papermc"
|
||||
url = uri("https://repo.papermc.io/repository/maven-public/")
|
||||
|
||||
// For paper-api
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven {
|
||||
name = "papermc"
|
||||
url = uri("https://repo.papermc.io/repository/maven-public/")
|
||||
}
|
||||
}
|
||||
filter {
|
||||
includeGroup("io.papermc.paper")
|
||||
includeGroup("net.md-5")
|
||||
}
|
||||
}
|
||||
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") // Spigot
|
||||
maven("https://repo.grim.ac/snapshots") { // Grim API
|
||||
content {
|
||||
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven("https://libraries.minecraft.net") { // Brigadier
|
||||
mavenContent { releasesOnly() }
|
||||
}
|
||||
}
|
||||
filter {
|
||||
includeModule("com.mojang", "brigadier")
|
||||
}
|
||||
}
|
||||
|
||||
// For placeholderapi
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven("https://repo.extendedclip.com/content/repositories/placeholderapi/")
|
||||
}
|
||||
filter {
|
||||
includeGroup("me.clip")
|
||||
}
|
||||
}
|
||||
|
||||
// For GrimAPI and PacketEvents (transitive from :common, direct in :bukkit)
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven("https://repo.grim.ac/snapshots")
|
||||
}
|
||||
filter {
|
||||
includeGroup("ac.grim.grimac")
|
||||
includeGroup("com.github.retrooper")
|
||||
}
|
||||
}
|
||||
maven("https://repo.viaversion.com") // ViaVersion
|
||||
maven("https://nexus.scarsz.me/content/repositories/releases") // Configuralize
|
||||
maven("https://repo.opencollab.dev/maven-snapshots/") // Floodgate
|
||||
maven("https://repo.opencollab.dev/maven-releases/") // Cumulus (for Floodgate)
|
||||
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||
maven("https://repo.extendedclip.com/content/repositories/placeholderapi/") // placeholderapi
|
||||
mavenCentral() // FastUtil
|
||||
|
||||
// For Configuralize (transitive from :common)
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven("https://nexus.scarsz.me/content/repositories/releases") {
|
||||
mavenContent { releasesOnly() }
|
||||
}
|
||||
}
|
||||
filter {
|
||||
includeGroup("github.scarsz")
|
||||
}
|
||||
}
|
||||
|
||||
// Maven Central Fallback
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.paper.api)
|
||||
compileOnly(libs.placeholderapi)
|
||||
@@ -126,15 +170,22 @@ bukkit {
|
||||
}
|
||||
|
||||
register("grim.verbose") {
|
||||
description = "Receive verbose alerts for violations. Requires grim.alerts"
|
||||
description = "Receive verbose alerts for violations"
|
||||
default = Permission.Default.OP
|
||||
}
|
||||
|
||||
register("grim.verbose.enable-on-join") {
|
||||
description =
|
||||
"Enable verbose alerts on join. Requires grim.alerts and grim.alerts.enable-on-join"
|
||||
"Enable verbose alerts on join"
|
||||
default = Permission.Default.FALSE
|
||||
}
|
||||
|
||||
register("grim.list") {
|
||||
description =
|
||||
"Shows lists of specific data"
|
||||
default = Permission.Default.FALSE
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ public class BukkitPlatformPlugin implements PlatformPlugin {
|
||||
return plugin.getName();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return plugin.getDescription().getVersion();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package ac.grim.grimac.platform.bukkit;
|
||||
|
||||
import ac.grim.grimac.api.plugin.BasicGrimPlugin;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.GrimAPIProvider;
|
||||
import ac.grim.grimac.api.GrimAbstractAPI;
|
||||
import ac.grim.grimac.api.plugin.GrimPlugin;
|
||||
import ac.grim.grimac.events.GrimExtensionManager;
|
||||
import ac.grim.grimac.manager.init.Initable;
|
||||
import ac.grim.grimac.manager.init.start.ExemptOnlinePlayersOnReload;
|
||||
import ac.grim.grimac.manager.init.start.StartableInitable;
|
||||
@@ -14,7 +14,6 @@ import ac.grim.grimac.platform.api.PlatformServer;
|
||||
import ac.grim.grimac.platform.api.manager.ItemResetHandler;
|
||||
import ac.grim.grimac.platform.api.manager.MessagePlaceHolderManager;
|
||||
import ac.grim.grimac.platform.api.manager.CommandAdapter;
|
||||
import ac.grim.grimac.platform.api.manager.PermissionRegistrationManager;
|
||||
import ac.grim.grimac.platform.api.manager.PlatformPluginManager;
|
||||
import ac.grim.grimac.platform.api.player.PlatformPlayerFactory;
|
||||
import ac.grim.grimac.platform.api.scheduler.PlatformScheduler;
|
||||
@@ -29,6 +28,7 @@ import ac.grim.grimac.platform.bukkit.manager.BukkitParserDescriptorFactory;
|
||||
import ac.grim.grimac.platform.bukkit.manager.BukkitPermissionRegistrationManager;
|
||||
import ac.grim.grimac.platform.bukkit.manager.BukkitPlatformPluginManager;
|
||||
import ac.grim.grimac.platform.bukkit.player.BukkitPlatformPlayerFactory;
|
||||
import ac.grim.grimac.platform.bukkit.resolver.BukkitResolverRegistrar;
|
||||
import ac.grim.grimac.platform.bukkit.scheduler.bukkit.BukkitPlatformScheduler;
|
||||
import ac.grim.grimac.platform.bukkit.scheduler.folia.FoliaPlatformScheduler;
|
||||
import ac.grim.grimac.platform.bukkit.sender.BukkitSenderFactory;
|
||||
@@ -36,6 +36,7 @@ import ac.grim.grimac.platform.bukkit.utils.placeholder.PlaceholderAPIExpansion;
|
||||
import ac.grim.grimac.utils.lazy.LazyHolder;
|
||||
import com.github.retrooper.packetevents.PacketEventsAPI;
|
||||
import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
@@ -47,7 +48,7 @@ import org.incendo.cloud.bukkit.CloudBukkitCapabilities;
|
||||
import org.incendo.cloud.execution.ExecutionCoordinator;
|
||||
import org.incendo.cloud.paper.LegacyPaperCommandManager;
|
||||
import org.incendo.cloud.setting.Configurable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public final class GrimACBukkitLoaderPlugin extends JavaPlugin implements PlatformLoader {
|
||||
|
||||
@@ -59,22 +60,19 @@ public final class GrimACBukkitLoaderPlugin extends JavaPlugin implements Platfo
|
||||
private final LazyHolder<CommandManager<Sender>> commandManager = LazyHolder.simple(this::createCommandManager);
|
||||
private final LazyHolder<ItemResetHandler> itemResetHandler = LazyHolder.simple(BukkitItemResetHandler::new);
|
||||
|
||||
private final PlatformPlayerFactory playerFactory = new BukkitPlatformPlayerFactory();
|
||||
private final CommandAdapter parserFactory = new BukkitParserDescriptorFactory();
|
||||
private final PlatformPluginManager platformPluginManager = new BukkitPlatformPluginManager();
|
||||
private final GrimPlugin plugin;
|
||||
private final PlatformServer platformServer = new BukkitPlatformServer();
|
||||
private final MessagePlaceHolderManager messagePlaceHolderManager = new BukkitMessagePlaceHolderManager();
|
||||
private final BukkitPermissionRegistrationManager bukkitPermissionRegistrationManager = new BukkitPermissionRegistrationManager();
|
||||
@Getter private final PlatformPlayerFactory platformPlayerFactory = new BukkitPlatformPlayerFactory();
|
||||
@Getter private final CommandAdapter commandAdapter = new BukkitParserDescriptorFactory();
|
||||
@Getter private final PlatformPluginManager pluginManager = new BukkitPlatformPluginManager();
|
||||
@Getter private final GrimPlugin plugin;
|
||||
@Getter private final PlatformServer platformServer = new BukkitPlatformServer();
|
||||
@Getter private final MessagePlaceHolderManager messagePlaceHolderManager = new BukkitMessagePlaceHolderManager();
|
||||
@Getter private final BukkitPermissionRegistrationManager permissionManager = new BukkitPermissionRegistrationManager();
|
||||
|
||||
public GrimACBukkitLoaderPlugin() {
|
||||
this.plugin = new BasicGrimPlugin(
|
||||
this.getLogger(),
|
||||
this.getDataFolder(),
|
||||
this.getDescription().getVersion(),
|
||||
this.getDescription().getDescription(),
|
||||
this.getDescription().getAuthors()
|
||||
);
|
||||
GrimExtensionManager extensionManager = GrimAPI.INSTANCE.getExtensionManager();
|
||||
BukkitResolverRegistrar registrar = new BukkitResolverRegistrar(extensionManager);
|
||||
registrar.registerAll();
|
||||
this.plugin = registrar.resolvePlugin(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,16 +110,6 @@ public final class GrimACBukkitLoaderPlugin extends JavaPlugin implements Platfo
|
||||
return scheduler.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformPlayerFactory getPlatformPlayerFactory() {
|
||||
return playerFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandAdapter getCommandAdapter() {
|
||||
return parserFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketEventsAPI<?> getPacketEvents() {
|
||||
return packetEvents.get();
|
||||
@@ -142,37 +130,12 @@ public final class GrimACBukkitLoaderPlugin extends JavaPlugin implements Platfo
|
||||
return senderFactory.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GrimPlugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformPluginManager getPluginManager() {
|
||||
return platformPluginManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformServer getPlatformServer() {
|
||||
return platformServer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerAPIService() {
|
||||
GrimAPIProvider.init(GrimAPI.INSTANCE.getExternalAPI());
|
||||
Bukkit.getServicesManager().register(GrimAbstractAPI.class, GrimAPI.INSTANCE.getExternalAPI(), GrimACBukkitLoaderPlugin.LOADER, ServicePriority.Normal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull MessagePlaceHolderManager getMessagePlaceHolderManager() {
|
||||
return messagePlaceHolderManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionRegistrationManager getPermissionManager() {
|
||||
return bukkitPermissionRegistrationManager;
|
||||
}
|
||||
|
||||
private PlatformScheduler createScheduler() {
|
||||
return GrimAPI.INSTANCE.getPlatform() == Platform.FOLIA ? new FoliaPlatformScheduler() : new BukkitPlatformScheduler();
|
||||
}
|
||||
|
||||
+4
-5
@@ -4,16 +4,15 @@ import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.platform.api.command.PlayerSelector;
|
||||
import ac.grim.grimac.platform.api.sender.Sender;
|
||||
import ac.grim.grimac.platform.bukkit.sender.BukkitSenderFactory;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.incendo.cloud.bukkit.data.SinglePlayerSelector;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class BukkitPlayerSelectorAdapter implements PlayerSelector {
|
||||
private final org.incendo.cloud.bukkit.data.SinglePlayerSelector bukkitSelector;
|
||||
|
||||
public BukkitPlayerSelectorAdapter(org.incendo.cloud.bukkit.data.SinglePlayerSelector bukkitSelector) {
|
||||
this.bukkitSelector = bukkitSelector;
|
||||
}
|
||||
private final SinglePlayerSelector bukkitSelector;
|
||||
|
||||
@Override
|
||||
public boolean isSingle() {
|
||||
|
||||
@@ -6,8 +6,10 @@ import ac.grim.grimac.platform.bukkit.utils.convert.BukkitConversionUtils;
|
||||
import ac.grim.grimac.platform.bukkit.utils.reflection.PaperUtils;
|
||||
import ac.grim.grimac.platform.bukkit.world.BukkitPlatformWorld;
|
||||
import ac.grim.grimac.utils.math.Location;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
@@ -15,12 +17,13 @@ import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class BukkitGrimEntity implements GrimEntity {
|
||||
|
||||
protected static final boolean CAN_USE_DIRECT_GETTERS = PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_20_1) && PaperUtils.PAPER;
|
||||
|
||||
private final Entity entity;
|
||||
private BukkitPlatformWorld bukkitPlatformWorld;
|
||||
|
||||
public BukkitGrimEntity(Entity entity) {
|
||||
Objects.requireNonNull(entity);
|
||||
this.entity = entity;
|
||||
this.entity = Objects.requireNonNull(entity);
|
||||
}
|
||||
|
||||
public Entity getBukkitEntity() {
|
||||
@@ -44,7 +47,7 @@ public class BukkitGrimEntity implements GrimEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
@NotNull
|
||||
public Entity getNative() {
|
||||
return entity;
|
||||
}
|
||||
@@ -76,4 +79,26 @@ public class BukkitGrimEntity implements GrimEntity {
|
||||
location.getPitch()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double distanceSquared(double oX, double oY, double oZ) {
|
||||
if (CAN_USE_DIRECT_GETTERS) {
|
||||
double x = this.entity.getX();
|
||||
double y = this.entity.getY();
|
||||
double z = this.entity.getZ();
|
||||
double distX = (x - oX) * (x - oX);
|
||||
double distY = (y - oY) * (y - oY);
|
||||
double distZ = (z - oZ) * (z - oZ);
|
||||
return distX + distY + distZ;
|
||||
} else {
|
||||
org.bukkit.Location location = this.entity.getLocation();
|
||||
double x = location.getX();
|
||||
double y = location.getY();
|
||||
double z = location.getZ();
|
||||
double distX = (x - oX) * (x - oX);
|
||||
double distY = (y - oY) * (y - oY);
|
||||
double distZ = (z - oZ) * (z - oZ);
|
||||
return distX + distY + distZ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,8 @@ import ac.grim.grimac.platform.bukkit.utils.convert.BukkitConversionUtils;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.PistonData;
|
||||
import ac.grim.grimac.utils.data.TrackedPosition;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@@ -28,10 +27,11 @@ public class PistonEvent implements Listener {
|
||||
private static final double MAX_VERTICAL_DISTANCE = 64.0;
|
||||
|
||||
// accuracy isn't that important, it's close enough and performant
|
||||
private static boolean isCloseEnough(Vector3i vectorA, Vector3d vectorB) {
|
||||
return Math.abs(vectorA.getX() - vectorB.getX()) <= MAX_HORIZONTAL_DISTANCE
|
||||
&& Math.abs(vectorA.getY() - vectorB.getY()) <= MAX_VERTICAL_DISTANCE
|
||||
&& Math.abs(vectorA.getZ() - vectorB.getZ()) <= MAX_HORIZONTAL_DISTANCE;
|
||||
private static boolean isCloseEnough(final int aX, final int aY, final int aZ,
|
||||
final double bX, final double bY, final double bZ) {
|
||||
return Math.abs(aX - bX) <= MAX_HORIZONTAL_DISTANCE
|
||||
&& Math.abs(aY - bY) <= MAX_VERTICAL_DISTANCE
|
||||
&& Math.abs(aZ - bZ) <= MAX_HORIZONTAL_DISTANCE;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
@@ -71,10 +71,13 @@ public class PistonEvent implements Listener {
|
||||
final int chunkX = event.getBlock().getX() >> 4;
|
||||
final int chunkZ = event.getBlock().getZ() >> 4;
|
||||
final BlockFace blockFace = BukkitConversionUtils.fromBukkitFace(event.getDirection());
|
||||
final Vector3i sourcePos = new Vector3i(piston.getX(), piston.getY(), piston.getZ());
|
||||
final int sourceX = piston.getX();
|
||||
final int sourceY = piston.getY();
|
||||
final int sourceZ = piston.getZ();
|
||||
|
||||
for (GrimPlayer player : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
|
||||
if (player.compensatedWorld.isChunkLoaded(chunkX, chunkZ) && isCloseEnough(sourcePos, player.compensatedEntities.self.trackedServerPosition.getPos())) {
|
||||
TrackedPosition position = player.compensatedEntities.self.trackedServerPosition;
|
||||
if (player.compensatedWorld.isChunkLoaded(chunkX, chunkZ) && isCloseEnough(sourceX, sourceY, sourceZ, position.getX(), position.getY(), position.getZ())) {
|
||||
final int lastTrans = player.lastTransactionSent.get();
|
||||
PistonData data = new PistonData(blockFace, boxes, lastTrans, true, hasSlimeBlock, hasHoneyBlock);
|
||||
player.latencyUtils.addRealTimeTaskAsync(lastTrans, () -> player.compensatedWorld.activePistons.add(data));
|
||||
@@ -127,12 +130,16 @@ public class PistonEvent implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
final int chunkX = event.getBlock().getX() >> 4;
|
||||
final int chunkZ = event.getBlock().getZ() >> 4;
|
||||
Vector3i sourcePos = new Vector3i(event.getBlock().getX(), event.getBlock().getY(), event.getBlock().getZ());
|
||||
final Block block = event.getBlock();
|
||||
final int chunkX = block.getX() >> 4;
|
||||
final int chunkZ = block.getZ() >> 4;
|
||||
final int sourceX = block.getX();
|
||||
final int sourceY = block.getY();
|
||||
final int sourceZ = block.getZ();
|
||||
|
||||
for (GrimPlayer player : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
|
||||
if (player.compensatedWorld.isChunkLoaded(chunkX, chunkZ) && isCloseEnough(sourcePos, player.compensatedEntities.self.trackedServerPosition.getPos())) {
|
||||
TrackedPosition position = player.compensatedEntities.self.trackedServerPosition;
|
||||
if (player.compensatedWorld.isChunkLoaded(chunkX, chunkZ) && isCloseEnough(sourceX, sourceY, sourceZ, position.getX(), position.getY(), position.getZ())) {
|
||||
int lastTrans = player.lastTransactionSent.get();
|
||||
PistonData data = new PistonData(face, boxes, lastTrans, false, hasSlimeBlock, hasHoneyBlock);
|
||||
player.latencyUtils.addRealTimeTaskAsync(lastTrans, () -> player.compensatedWorld.activePistons.add(data));
|
||||
|
||||
@@ -2,15 +2,14 @@ package ac.grim.grimac.platform.bukkit.initables;
|
||||
|
||||
import ac.grim.grimac.manager.init.start.StartableInitable;
|
||||
import ac.grim.grimac.platform.bukkit.GrimACBukkitLoaderPlugin;
|
||||
import ac.grim.grimac.utils.anticheat.Constants;
|
||||
import io.github.retrooper.packetevents.bstats.bukkit.Metrics;
|
||||
|
||||
public class BukkitBStats implements StartableInitable {
|
||||
@Override
|
||||
public void start() {
|
||||
int pluginId = 12820; // <-- Replace with the id of your plugin!
|
||||
try {
|
||||
new Metrics(GrimACBukkitLoaderPlugin.LOADER, pluginId);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
new Metrics(GrimACBukkitLoaderPlugin.LOADER, Constants.BSTATS_PLUGIN_ID);
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
}
|
||||
+181
-173
@@ -2,204 +2,212 @@ package ac.grim.grimac.platform.bukkit.manager;
|
||||
|
||||
import ac.grim.grimac.platform.api.manager.ItemResetHandler;
|
||||
import ac.grim.grimac.platform.api.player.PlatformPlayer;
|
||||
import ac.grim.grimac.platform.bukkit.player.BukkitPlatformPlayer;
|
||||
import ac.grim.grimac.platform.bukkit.utils.reflection.PaperUtils;
|
||||
import ac.grim.grimac.utils.reflection.ReflectionUtils;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.InteractionHand;
|
||||
import lombok.SneakyThrows;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class BukkitItemResetHandler implements ItemResetHandler {
|
||||
private final @NotNull ItemUsageReset resetItemUsage = createItemUsageResetFunction();
|
||||
private final @NotNull ItemUsageHandGetter itemUsageHandGetter = createItemUsageHandGetterFunction();
|
||||
private static final Consumer<Player> resetItemUsage;
|
||||
private static final Predicate<Player> isUsingItem;
|
||||
private static final Function<Player, InteractionHand> getItemUsageHand;
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void resetItemUsage(@Nullable PlatformPlayer player) {
|
||||
if (player != null) {
|
||||
resetItemUsage.accept(((BukkitPlatformPlayer) player).getNative());
|
||||
}
|
||||
if (player != null) resetItemUsage.accept((Player) player.getNative());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public @Nullable InteractionHand getItemUsageHand(@Nullable PlatformPlayer platformPlayer) {
|
||||
return platformPlayer == null ? null
|
||||
: itemUsageHandGetter.apply(((BukkitPlatformPlayer) platformPlayer).getNative());
|
||||
public @Nullable InteractionHand getItemUsageHand(@Nullable PlatformPlayer player) {
|
||||
return player == null ? null : getItemUsageHand.apply((Player) player.getNative());
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private @NotNull ItemUsageReset createItemUsageResetFunction() {
|
||||
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
|
||||
if (version.isNewerThan(ServerVersion.V_1_17) && PaperUtils.PAPER) {
|
||||
if (version.isOlderThan(ServerVersion.V_1_19)) {
|
||||
return LivingEntity::clearActiveItem;
|
||||
}
|
||||
|
||||
Class<?> CraftLivingEntity;
|
||||
boolean obfuscated = false;
|
||||
try {
|
||||
CraftLivingEntity = Class.forName("org.bukkit.craftbukkit.entity.CraftLivingEntity");
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
String nmsPackage = Bukkit.getServer().getClass().getPackageName().split("\\.")[3];
|
||||
CraftLivingEntity = Class.forName("org.bukkit.craftbukkit." + nmsPackage + ".entity.CraftLivingEntity");
|
||||
obfuscated = true;
|
||||
}
|
||||
|
||||
Method getHandle = CraftLivingEntity.getMethod("getHandle");
|
||||
Method setLivingEntityFlag = getHandle.getReturnType().getDeclaredMethod(
|
||||
obfuscated ? "c" : "setLivingEntityFlag", int.class, boolean.class
|
||||
);
|
||||
setLivingEntityFlag.setAccessible(true);
|
||||
|
||||
return player -> {
|
||||
// no gameevent, no exception
|
||||
setLivingEntityFlag.invoke(getHandle.invoke(player), 1, false);
|
||||
player.clearActiveItem();
|
||||
};
|
||||
}
|
||||
|
||||
if (version == ServerVersion.V_1_8_8) {
|
||||
Method getHandle = Class.forName("org.bukkit.craftbukkit.v1_8_R3.entity.CraftHumanEntity").getMethod("getHandle");
|
||||
Method clearActiveItem = getHandle.getReturnType().getMethod("bV");
|
||||
Method isUsingItem = getHandle.getReturnType().getMethod("bS");
|
||||
|
||||
return player -> {
|
||||
Object handle = getHandle.invoke(player);
|
||||
clearActiveItem.invoke(handle);
|
||||
|
||||
// in 1.8 we need to resync item usage manually,
|
||||
// only do so if the player was using an item
|
||||
if ((boolean) isUsingItem.invoke(handle)) {
|
||||
player.updateInventory();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
String nmsPackage = Bukkit.getServer().getClass().getPackageName().split("\\.")[3];
|
||||
Method getHandle = Class.forName("org.bukkit.craftbukkit." + nmsPackage + ".entity.CraftLivingEntity").getMethod("getHandle");
|
||||
Method clearActiveItem = getHandle.getReturnType().getMethod(switch (nmsPackage) {
|
||||
case "v1_9_R1" -> "cz";
|
||||
case "v1_9_R2" -> "cA";
|
||||
case "v1_10_R1" -> "cE";
|
||||
case "v1_11_R1" -> "cF";
|
||||
case "v1_12_R1" -> "cN";
|
||||
case "v1_13_R1", "v1_13_R2" -> "da";
|
||||
case "v1_14_R1" -> "dp";
|
||||
case "v1_15_R1" -> "dH";
|
||||
case "v1_16_R1", "v1_16_R2", "v1_16_R3", "v1_17_R1" -> "clearActiveItem";
|
||||
case "v1_18_R1" -> "eR";
|
||||
case "v1_18_R2" -> "eS";
|
||||
case "v1_19_R1" -> "eZ";
|
||||
case "v1_19_R2" -> "ff";
|
||||
case "v1_19_R3" -> "fk";
|
||||
case "v1_20_R1" -> "fo";
|
||||
case "v1_20_R2" -> "fs";
|
||||
case "v1_20_R3" -> "ft";
|
||||
case "v1_20_R4" -> "fB";
|
||||
case "v1_21_R1" -> "fx";
|
||||
case "v1_21_R2", "v1_21_R3", "v1_21_R4" -> "fF";
|
||||
default -> throw new IllegalStateException("You are using an unsupported server version! (" + version.getReleaseName() + ")");
|
||||
});
|
||||
|
||||
if (version.isOlderThan(ServerVersion.V_1_19)) {
|
||||
return player -> clearActiveItem.invoke(getHandle.invoke(player));
|
||||
} else {
|
||||
Method setLivingEntityFlag = getHandle.getReturnType().getDeclaredMethod("c", int.class, boolean.class);
|
||||
setLivingEntityFlag.setAccessible(true);
|
||||
|
||||
return player -> {
|
||||
final Object handle = getHandle.invoke(player);
|
||||
// no gameevent, no exception
|
||||
setLivingEntityFlag.invoke(handle, 1, false);
|
||||
clearActiveItem.invoke(handle);
|
||||
};
|
||||
}
|
||||
@Override
|
||||
public boolean isUsingItem(@Nullable PlatformPlayer player) {
|
||||
return player != null && isUsingItem.test((Player) player.getNative());
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private @NotNull ItemUsageHandGetter createItemUsageHandGetterFunction() {
|
||||
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
|
||||
if (version.isNewerThanOrEquals(ServerVersion.V_1_16_5) && PaperUtils.PAPER) {
|
||||
return player -> player.isHandRaised()
|
||||
? player.getHandRaised() == EquipmentSlot.OFF_HAND
|
||||
static {
|
||||
final ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
|
||||
|
||||
boolean legacy = version.isOlderThanOrEquals(ServerVersion.V_1_8_8);
|
||||
|
||||
try {
|
||||
Method getHandle_ = null;
|
||||
|
||||
if (PaperUtils.PAPER && version.isNewerThanOrEquals(ServerVersion.V_1_20_5)) {
|
||||
Class<?> cls = ReflectionUtils.getClass("org.bukkit.craftbukkit.entity.CraftLivingEntity");
|
||||
if (cls != null) getHandle_ = cls.getMethod("getHandle");
|
||||
}
|
||||
|
||||
boolean obfuscated = getHandle_ == null;
|
||||
String nmsPackage = obfuscated ? Bukkit.getServer().getClass().getPackageName().split("\\.")[3] : null;
|
||||
|
||||
if (obfuscated) {
|
||||
String clazzName = legacy ? "CraftHumanEntity" : "CraftLivingEntity";
|
||||
getHandle_ = Class.forName("org.bukkit.craftbukkit." + nmsPackage + ".entity." + clazzName).getMethod("getHandle");
|
||||
}
|
||||
|
||||
final Method getHandle = getHandle_;
|
||||
Class<?> clazz = getHandle_.getReturnType();
|
||||
|
||||
if (version.isNewerThanOrEquals(ServerVersion.V_1_10)) {
|
||||
isUsingItem = Player::isHandRaised;
|
||||
} else {
|
||||
Method method = clazz.getMethod(switch (Objects.requireNonNull(nmsPackage)) {
|
||||
case "v1_8_R3" -> "bS";
|
||||
case "v1_9_R1" -> "cs";
|
||||
case "v1_9_R2" -> "ct";
|
||||
default -> throw new IllegalStateException("You are using an unsupported server version! (" + version.getReleaseName() + ")");
|
||||
});
|
||||
isUsingItem = player -> {
|
||||
try {
|
||||
return (boolean) method.invoke(getHandle.invoke(player));
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (legacy) {
|
||||
getItemUsageHand = player -> isUsingItem.test(player) ? InteractionHand.MAIN_HAND : null;
|
||||
} else if (PaperUtils.PAPER && version.isNewerThanOrEquals(ServerVersion.V_1_16_5)) {
|
||||
getItemUsageHand = player -> player.isHandRaised()
|
||||
? player.getHandRaised() == EquipmentSlot.OFF_HAND
|
||||
? InteractionHand.OFF_HAND
|
||||
: InteractionHand.MAIN_HAND
|
||||
: null;
|
||||
: null;
|
||||
} else {
|
||||
Method method = clazz.getMethod(switch (Objects.requireNonNull(nmsPackage)) {
|
||||
case "v1_9_R1" -> "ct";
|
||||
case "v1_9_R2" -> "cu";
|
||||
case "v1_10_R1" -> "cy";
|
||||
case "v1_11_R1" -> "cz";
|
||||
case "v1_12_R1" -> "cH";
|
||||
case "v1_13_R1", "v1_13_R2", "v1_14_R1" -> "cU";
|
||||
case "v1_15_R1", "v1_16_R1", "v1_16_R2", "v1_16_R3", "v1_17_R1" -> "getRaisedHand";
|
||||
case "v1_18_R1" -> "eM";
|
||||
case "v1_18_R2" -> "eN";
|
||||
case "v1_19_R1" -> "eU";
|
||||
case "v1_19_R2" -> "fa";
|
||||
case "v1_19_R3" -> "ff";
|
||||
case "v1_20_R1" -> "fj";
|
||||
case "v1_20_R2" -> "fn";
|
||||
case "v1_20_R3" -> "fo";
|
||||
case "v1_20_R4" -> "fw";
|
||||
case "v1_21_R1" -> "fs";
|
||||
case "v1_21_R2", "v1_21_R3", "v1_21_R4" -> "fA";
|
||||
case "v1_21_R5" -> "fH";
|
||||
case "v1_21_R6" -> "fP";
|
||||
default -> throw new IllegalStateException("You are using an unsupported server version! (" + version.getReleaseName() + ")");
|
||||
});
|
||||
getItemUsageHand = player -> {
|
||||
try {
|
||||
return isUsingItem.test(player)
|
||||
? ((Enum<?>) method.invoke(getHandle.invoke(player))).ordinal() == 0
|
||||
? InteractionHand.MAIN_HAND
|
||||
: InteractionHand.OFF_HAND
|
||||
: null;
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Method setLivingEntityFlag;
|
||||
|
||||
if (version.isNewerThanOrEquals(ServerVersion.V_1_19)) {
|
||||
String name = obfuscated ? "c" : "setLivingEntityFlag";
|
||||
setLivingEntityFlag = clazz.getDeclaredMethod(name, int.class, boolean.class);
|
||||
setLivingEntityFlag.setAccessible(true);
|
||||
} else {
|
||||
setLivingEntityFlag = null;
|
||||
}
|
||||
|
||||
if (PaperUtils.PAPER && version.isNewerThan(ServerVersion.V_1_17)) {
|
||||
resetItemUsage = setLivingEntityFlag == null ? LivingEntity::clearActiveItem : player -> {
|
||||
try {
|
||||
setLivingEntityFlag.invoke(getHandle.invoke(player), 1, false);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
player.clearActiveItem();
|
||||
};
|
||||
} else {
|
||||
Method method = clazz.getMethod(switch (Objects.requireNonNull(nmsPackage)) {
|
||||
case "v1_8_R3" -> "bV";
|
||||
case "v1_9_R1" -> "cz";
|
||||
case "v1_9_R2" -> "cA";
|
||||
case "v1_10_R1" -> "cE";
|
||||
case "v1_11_R1" -> "cF";
|
||||
case "v1_12_R1" -> "cN";
|
||||
case "v1_13_R1", "v1_13_R2" -> "da";
|
||||
case "v1_14_R1" -> "dp";
|
||||
case "v1_15_R1" -> "dH";
|
||||
case "v1_16_R1", "v1_16_R2", "v1_16_R3", "v1_17_R1" -> "clearActiveItem";
|
||||
case "v1_18_R1" -> "eR";
|
||||
case "v1_18_R2" -> "eS";
|
||||
case "v1_19_R1" -> "eZ";
|
||||
case "v1_19_R2" -> "ff";
|
||||
case "v1_19_R3" -> "fk";
|
||||
case "v1_20_R1" -> "fo";
|
||||
case "v1_20_R2" -> "fs";
|
||||
case "v1_20_R3" -> "ft";
|
||||
case "v1_20_R4" -> "fB";
|
||||
case "v1_21_R1" -> "fx";
|
||||
case "v1_21_R2", "v1_21_R3", "v1_21_R4" -> "fF";
|
||||
case "v1_21_R5" -> "fM";
|
||||
case "v1_21_R6" -> "fU";
|
||||
default -> throw new IllegalStateException("You are using an unsupported server version! (" + version.getReleaseName() + ")");
|
||||
});
|
||||
|
||||
if (legacy) { // 1.8.8
|
||||
resetItemUsage = player -> {
|
||||
try {
|
||||
method.invoke(getHandle.invoke(player));
|
||||
|
||||
// in 1.8 we need to resync item usage manually,
|
||||
// only do so if the player is using an item
|
||||
if (isUsingItem.test(player)) player.updateInventory();
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
} else if (setLivingEntityFlag == null) { // 1.9-1.18.2
|
||||
resetItemUsage = player -> {
|
||||
try {
|
||||
method.invoke(getHandle.invoke(player));
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
} else { // 1.19+
|
||||
resetItemUsage = player -> {
|
||||
try {
|
||||
Object handle = getHandle.invoke(player);
|
||||
setLivingEntityFlag.invoke(handle, 1, false);
|
||||
method.invoke(handle);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
throw t instanceof RuntimeException e ? e : new RuntimeException(t);
|
||||
}
|
||||
|
||||
if (version == ServerVersion.V_1_8_8) {
|
||||
Method getHandle = Class.forName("org.bukkit.craftbukkit.v1_8_R3.entity.CraftHumanEntity").getMethod("getHandle");
|
||||
Method isUsingItem = getHandle.getReturnType().getMethod("bS");
|
||||
return player -> (boolean) isUsingItem.invoke(getHandle.invoke(player)) ? InteractionHand.MAIN_HAND : null;
|
||||
}
|
||||
|
||||
String nmsPackage = Bukkit.getServer().getClass().getPackageName().split("\\.")[3];
|
||||
Method getHandle = Class.forName("org.bukkit.craftbukkit." + nmsPackage + ".entity.CraftLivingEntity").getMethod("getHandle");
|
||||
Method isUsingItem = getHandle.getReturnType().getMethod(switch (nmsPackage) {
|
||||
case "v1_9_R1" -> "cs";
|
||||
case "v1_9_R2" -> "ct";
|
||||
case "v1_10_R1" -> "cx";
|
||||
case "v1_11_R1", "v1_12_R1", "v1_13_R1", "v1_13_R2", "v1_14_R1",
|
||||
"v1_15_R1", "v1_16_R1", "v1_16_R2", "v1_16_R3", "v1_17_R1" -> "isHandRaised";
|
||||
case "v1_18_R1" -> "eL";
|
||||
case "v1_18_R2" -> "eM";
|
||||
case "v1_19_R1" -> "eT";
|
||||
case "v1_19_R2" -> "eZ";
|
||||
case "v1_19_R3" -> "fe";
|
||||
case "v1_20_R1" -> "fi";
|
||||
case "v1_20_R2" -> "fm";
|
||||
case "v1_20_R3" -> "fn";
|
||||
case "v1_20_R4" -> "fv";
|
||||
case "v1_21_R1" -> "fr";
|
||||
case "v1_21_R2", "v1_21_R3", "v1_21_R4" -> "fz";
|
||||
default -> throw new IllegalStateException("You are using an unsupported server version! (" + version.getReleaseName() + ")");
|
||||
});
|
||||
Method getUsingItemHand = getHandle.getReturnType().getMethod(switch (nmsPackage) {
|
||||
case "v1_9_R1" -> "ct";
|
||||
case "v1_9_R2" -> "cu";
|
||||
case "v1_10_R1" -> "cy";
|
||||
case "v1_11_R1" -> "cz";
|
||||
case "v1_12_R1" -> "cH";
|
||||
case "v1_13_R1", "v1_13_R2", "v1_14_R1" -> "cU";
|
||||
case "v1_15_R1", "v1_16_R1", "v1_16_R2", "v1_16_R3", "v1_17_R1" -> "getRaisedHand";
|
||||
case "v1_18_R1" -> "eM";
|
||||
case "v1_18_R2" -> "eN";
|
||||
case "v1_19_R1" -> "eU";
|
||||
case "v1_19_R2" -> "fa";
|
||||
case "v1_19_R3" -> "ff";
|
||||
case "v1_20_R1" -> "fj";
|
||||
case "v1_20_R2" -> "fn";
|
||||
case "v1_20_R3" -> "fo";
|
||||
case "v1_20_R4" -> "fw";
|
||||
case "v1_21_R1" -> "fs";
|
||||
case "v1_21_R2", "v1_21_R3", "v1_21_R4" -> "fA";
|
||||
default -> throw new IllegalStateException("You are using an unsupported server version! (" + version.getReleaseName() + ")");
|
||||
});
|
||||
|
||||
return player -> {
|
||||
final Object handle = getHandle.invoke(player);
|
||||
return (boolean) isUsingItem.invoke(handle)
|
||||
? ((Enum<?>) getUsingItemHand.invoke(handle)).ordinal() == 0
|
||||
? InteractionHand.MAIN_HAND
|
||||
: InteractionHand.OFF_HAND
|
||||
: null;
|
||||
};
|
||||
}
|
||||
|
||||
private interface ItemUsageReset {
|
||||
void accept(@NotNull Player player) throws Throwable;
|
||||
}
|
||||
|
||||
private interface ItemUsageHandGetter {
|
||||
InteractionHand apply(@NotNull Player player) throws Throwable;
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -5,14 +5,14 @@ import ac.grim.grimac.platform.api.player.PlatformPlayer;
|
||||
import ac.grim.grimac.platform.bukkit.player.BukkitPlatformPlayer;
|
||||
import com.github.retrooper.packetevents.util.reflection.Reflection;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class BukkitMessagePlaceHolderManager implements MessagePlaceHolderManager {
|
||||
public static final boolean hasPlaceholderAPI = Reflection.getClassByNameWithoutException("me.clip.placeholderapi.PlaceholderAPI") != null;
|
||||
|
||||
@Override
|
||||
public @NonNull String replacePlaceholders(@Nullable PlatformPlayer player, @NonNull String string) {
|
||||
public @NotNull String replacePlaceholders(@Nullable PlatformPlayer player, @NotNull String string) {
|
||||
if (!hasPlaceholderAPI) return string;
|
||||
return PlaceholderAPI.setPlaceholders(player instanceof BukkitPlatformPlayer bukkitPlatformPlayer ? bukkitPlatformPlayer.getBukkitPlayer() : null, string);
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ import ac.grim.grimac.platform.api.manager.PlatformPluginManager;
|
||||
import ac.grim.grimac.platform.bukkit.BukkitPlatformPlugin;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class BukkitPlatformPluginManager implements PlatformPluginManager {
|
||||
|
||||
|
||||
+2
-1
@@ -1,13 +1,14 @@
|
||||
package ac.grim.grimac.platform.bukkit.player;
|
||||
|
||||
import ac.grim.grimac.platform.api.player.OfflinePlatformPlayer;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
@lombok.RequiredArgsConstructor
|
||||
@RequiredArgsConstructor
|
||||
public class BukkitOfflinePlatformPlayer implements OfflinePlatformPlayer {
|
||||
private final OfflinePlayer offlinePlayer;
|
||||
|
||||
|
||||
+2
-4
@@ -3,16 +3,14 @@ package ac.grim.grimac.platform.bukkit.player;
|
||||
import ac.grim.grimac.platform.api.player.PlatformInventory;
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class BukkitPlatformInventory implements PlatformInventory {
|
||||
|
||||
private final Player bukkitPlayer;
|
||||
|
||||
public BukkitPlatformInventory(Player bukkitPlayer) {
|
||||
this.bukkitPlayer = bukkitPlayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemInHand() {
|
||||
return SpigotConversionUtil.fromBukkitItemStack(bukkitPlayer.getInventory().getItemInHand());
|
||||
|
||||
+32
-12
@@ -9,8 +9,11 @@ import ac.grim.grimac.platform.bukkit.entity.BukkitGrimEntity;
|
||||
import ac.grim.grimac.platform.bukkit.utils.anticheat.MultiLibUtil;
|
||||
import ac.grim.grimac.platform.bukkit.utils.convert.BukkitConversionUtils;
|
||||
import ac.grim.grimac.platform.bukkit.utils.reflection.PaperUtils;
|
||||
import ac.grim.grimac.utils.common.arguments.CommonGrimArguments;
|
||||
import ac.grim.grimac.utils.math.Location;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
|
||||
import lombok.Getter;
|
||||
@@ -20,23 +23,33 @@ import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class BukkitPlatformPlayer extends BukkitGrimEntity implements PlatformPlayer {
|
||||
|
||||
private static final BukkitAudiences audiences = BukkitAudiences.create(GrimACBukkitLoaderPlugin.LOADER);
|
||||
|
||||
@Getter
|
||||
private final Player bukkitPlayer;
|
||||
@Getter
|
||||
private final PlatformInventory inventory;
|
||||
|
||||
private final @Nullable User user;
|
||||
|
||||
public BukkitPlatformPlayer(Player bukkitPlayer) {
|
||||
super(bukkitPlayer);
|
||||
this.bukkitPlayer = bukkitPlayer;
|
||||
this.inventory = new BukkitPlatformInventory(bukkitPlayer);
|
||||
if (CommonGrimArguments.USE_CHAT_FAST_BYPASS.value()) {
|
||||
Object channel = PacketEvents.getAPI().getProtocolManager().getChannel(bukkitPlayer.getUniqueId());
|
||||
this.user = PacketEvents.getAPI().getProtocolManager().getUser(channel);
|
||||
} else {
|
||||
this.user = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,12 +79,20 @@ public class BukkitPlatformPlayer extends BukkitGrimEntity implements PlatformPl
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
bukkitPlayer.sendMessage(message);
|
||||
if (CommonGrimArguments.USE_CHAT_FAST_BYPASS.value() && user != null) {
|
||||
user.sendMessage(message);
|
||||
} else {
|
||||
bukkitPlayer.sendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(Component message) {
|
||||
audiences.player(bukkitPlayer).sendMessage(message);
|
||||
if (CommonGrimArguments.USE_CHAT_FAST_BYPASS.value() && user != null) {
|
||||
user.sendMessage(message);
|
||||
} else {
|
||||
audiences.player(bukkitPlayer).sendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,13 +112,12 @@ public class BukkitPlatformPlayer extends BukkitGrimEntity implements PlatformPl
|
||||
|
||||
@Override
|
||||
public Vector3d getPosition() {
|
||||
org.bukkit.Location location = this.bukkitPlayer.getLocation();
|
||||
return new Vector3d(location.getX(), location.getY(), location.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformInventory getInventory() {
|
||||
return inventory;
|
||||
if (CAN_USE_DIRECT_GETTERS) {
|
||||
return new Vector3d(this.bukkitPlayer.getX(), this.bukkitPlayer.getY(), this.bukkitPlayer.getZ());
|
||||
} else {
|
||||
org.bukkit.Location location = this.bukkitPlayer.getLocation();
|
||||
return new Vector3d(location.getX(), location.getY(), location.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -151,7 +171,7 @@ public class BukkitPlatformPlayer extends BukkitGrimEntity implements PlatformPl
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
@NotNull
|
||||
public Player getNative() {
|
||||
return this.bukkitPlayer;
|
||||
}
|
||||
|
||||
+1
-2
@@ -6,7 +6,6 @@ import ac.grim.grimac.platform.api.player.PlatformPlayer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -21,7 +20,7 @@ public class BukkitPlatformPlayerFactory extends AbstractPlatformPlayerFactory<P
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Player getNativePlayer(@NonNull String name) {
|
||||
protected Player getNativePlayer(@NotNull String name) {
|
||||
return Bukkit.getPlayer(name);
|
||||
}
|
||||
|
||||
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
package ac.grim.grimac.platform.bukkit.resolver;
|
||||
|
||||
import ac.grim.grimac.api.plugin.BasicGrimPlugin;
|
||||
import ac.grim.grimac.api.plugin.GrimPlugin;
|
||||
import ac.grim.grimac.events.GrimExtensionManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Manages the registration of Bukkit-specific resolvers with the GrimExtensionManager.
|
||||
* This class is designed to be instantiated once during plugin startup.
|
||||
*/
|
||||
public final class BukkitResolverRegistrar {
|
||||
|
||||
private final GrimExtensionManager extensionManager;
|
||||
|
||||
// Cache to ensure we only create one GrimPlugin wrapper per Bukkit Plugin instance.
|
||||
private final Map<Plugin, GrimPlugin> pluginCache = new ConcurrentHashMap<>();
|
||||
|
||||
public BukkitResolverRegistrar(GrimExtensionManager extensionManager) {
|
||||
this.extensionManager = extensionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all the Bukkit-specific resolvers in order of performance (fastest to slowest).
|
||||
*/
|
||||
public void registerAll() {
|
||||
extensionManager.setFailureHandler(this::createFailureException);
|
||||
extensionManager.registerResolver(this::resolvePluginInstance);
|
||||
extensionManager.registerResolver(this::resolveStringName);
|
||||
extensionManager.registerResolver(this::resolveClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* The core logic for converting a Bukkit Plugin into a GrimPlugin, with caching.
|
||||
*/
|
||||
public GrimPlugin resolvePlugin(Plugin bukkitPlugin) {
|
||||
return pluginCache.computeIfAbsent(bukkitPlugin, plugin -> {
|
||||
PluginDescriptionFile desc = plugin.getDescription();
|
||||
return new BasicGrimPlugin(
|
||||
plugin.getLogger(),
|
||||
plugin.getDataFolder(),
|
||||
desc.getVersion(),
|
||||
desc.getDescription(),
|
||||
desc.getAuthors()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Resolver for raw Plugin instances (the most common case).
|
||||
*/
|
||||
private GrimPlugin resolvePluginInstance(Object context) {
|
||||
if (context instanceof Plugin bukkitPlugin) {
|
||||
return resolvePlugin(bukkitPlugin);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 2. Resolver for String plugin names.
|
||||
*/
|
||||
private GrimPlugin resolveStringName(Object context) {
|
||||
if (context instanceof String pluginName) {
|
||||
// Use the Bukkit API to look up the plugin by name. This returns null if not found.
|
||||
Plugin bukkitPlugin = Bukkit.getPluginManager().getPlugin(pluginName);
|
||||
// We must check for null before applying the logic to avoid a NullPointerException.
|
||||
return (bukkitPlugin != null) ? resolvePlugin(bukkitPlugin) : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 3. Resolver for Class objects.
|
||||
*/
|
||||
private GrimPlugin resolveClass(Object context) {
|
||||
if (context instanceof Class) {
|
||||
try {
|
||||
// First, resolve the Class to a Plugin instance.
|
||||
JavaPlugin providingPlugin = JavaPlugin.getProvidingPlugin((Class<?>) context);
|
||||
// Then, use our shared logic directly to get the GrimPlugin wrapper.
|
||||
return resolvePlugin(providingPlugin);
|
||||
} catch (IllegalArgumentException | IllegalStateException e) {
|
||||
// This is an expected failure if the class is not from a plugin
|
||||
// or is called from a static initializer. We simply indicate that
|
||||
// this resolver cannot handle this context.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// This resolver only handles Classes.
|
||||
return null;
|
||||
}
|
||||
|
||||
private RuntimeException createFailureException(Object failedContext) {
|
||||
String message = """
|
||||
Failed to resolve GrimPlugin context from the provided object of type '%s'.
|
||||
|
||||
Please ensure you are passing one of the following:
|
||||
- The main instance of your plugin (e.g., 'this' from your class extending JavaPlugin).
|
||||
- The plugin name as a String (e.g., "MyPluginName").
|
||||
- Any Class from your plugin's JAR file (e.g., MyListener.class).
|
||||
- A pre-existing GrimPlugin instance.
|
||||
""".formatted(failedContext.getClass().getName());
|
||||
return new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -2,12 +2,12 @@ package ac.grim.grimac.platform.bukkit.scheduler.bukkit;
|
||||
|
||||
import ac.grim.grimac.platform.api.scheduler.PlatformScheduler;
|
||||
import lombok.Getter;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@Getter
|
||||
public class BukkitPlatformScheduler implements PlatformScheduler {
|
||||
private final @NonNull BukkitAsyncScheduler asyncScheduler = new BukkitAsyncScheduler();
|
||||
private final @NonNull BukkitGlobalRegionScheduler globalRegionScheduler = new BukkitGlobalRegionScheduler();
|
||||
private final @NonNull BukkitEntityScheduler entityScheduler = new BukkitEntityScheduler();
|
||||
private final @NonNull BukkitRegionScheduler regionScheduler = new BukkitRegionScheduler();
|
||||
private final @NotNull BukkitAsyncScheduler asyncScheduler = new BukkitAsyncScheduler();
|
||||
private final @NotNull BukkitGlobalRegionScheduler globalRegionScheduler = new BukkitGlobalRegionScheduler();
|
||||
private final @NotNull BukkitEntityScheduler entityScheduler = new BukkitEntityScheduler();
|
||||
private final @NotNull BukkitRegionScheduler regionScheduler = new BukkitRegionScheduler();
|
||||
}
|
||||
+5
-4
@@ -15,14 +15,14 @@ public class FoliaAsyncScheduler implements AsyncScheduler {
|
||||
|
||||
@Override
|
||||
public TaskHandle runNow(@NotNull GrimPlugin plugin, @NotNull Runnable task) {
|
||||
return new FoliaTaskHandle(scheduler.runNow(GrimACBukkitLoaderPlugin.LOADER, (ignored) -> task.run()));
|
||||
return new FoliaTaskHandle(scheduler.runNow(GrimACBukkitLoaderPlugin.LOADER, ignored -> task.run()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle runDelayed(@NotNull GrimPlugin plugin, @NotNull Runnable task, long delay, @NotNull TimeUnit timeUnit) {
|
||||
return new FoliaTaskHandle(scheduler.runDelayed(
|
||||
GrimACBukkitLoaderPlugin.LOADER,
|
||||
(ignored) -> task.run(),
|
||||
ignored -> task.run(),
|
||||
delay,
|
||||
timeUnit
|
||||
));
|
||||
@@ -31,7 +31,8 @@ public class FoliaAsyncScheduler implements AsyncScheduler {
|
||||
@Override
|
||||
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull Runnable task, long delay, long period, @NotNull TimeUnit timeUnit) {
|
||||
return new FoliaTaskHandle(scheduler.runAtFixedRate(
|
||||
GrimACBukkitLoaderPlugin.LOADER, (ignored) -> task.run(),
|
||||
GrimACBukkitLoaderPlugin.LOADER,
|
||||
ignored -> task.run(),
|
||||
delay,
|
||||
period,
|
||||
timeUnit
|
||||
@@ -42,7 +43,7 @@ public class FoliaAsyncScheduler implements AsyncScheduler {
|
||||
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull Runnable task, long initialDelayTicks, long periodTicks) {
|
||||
return new FoliaTaskHandle(scheduler.runAtFixedRate(
|
||||
GrimACBukkitLoaderPlugin.LOADER,
|
||||
(ignored) -> task.run(),
|
||||
ignored -> task.run(),
|
||||
initialDelayTicks * 50,
|
||||
periodTicks * 50,
|
||||
TimeUnit.MILLISECONDS
|
||||
|
||||
+24
-4
@@ -6,6 +6,7 @@ import ac.grim.grimac.platform.api.scheduler.EntityScheduler;
|
||||
import ac.grim.grimac.platform.api.scheduler.TaskHandle;
|
||||
import ac.grim.grimac.platform.bukkit.GrimACBukkitLoaderPlugin;
|
||||
import ac.grim.grimac.platform.bukkit.entity.BukkitGrimEntity;
|
||||
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -18,18 +19,37 @@ public class FoliaEntityScheduler implements EntityScheduler {
|
||||
|
||||
@Override
|
||||
public TaskHandle run(@NotNull GrimEntity entity, @NotNull GrimPlugin plugin, @NotNull Runnable task, @Nullable Runnable retired) {
|
||||
return new FoliaTaskHandle(((BukkitGrimEntity) entity).getBukkitEntity().getScheduler().run(GrimACBukkitLoaderPlugin.LOADER, (ignored) -> task.run(), retired));
|
||||
ScheduledTask scheduled = ((BukkitGrimEntity) entity).getBukkitEntity().getScheduler().run(
|
||||
GrimACBukkitLoaderPlugin.LOADER,
|
||||
ignored -> task.run(),
|
||||
retired
|
||||
);
|
||||
|
||||
return scheduled == null ? null : new FoliaTaskHandle(scheduled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle runDelayed(@NotNull GrimEntity entity, @NotNull GrimPlugin plugin, @NotNull Runnable task, @Nullable Runnable retired, long delayTicks) {
|
||||
return new FoliaTaskHandle(
|
||||
((BukkitGrimEntity) entity).getBukkitEntity().getScheduler().runDelayed(GrimACBukkitLoaderPlugin.LOADER, (ignored) -> task.run(), retired, delayTicks)
|
||||
ScheduledTask scheduled = ((BukkitGrimEntity) entity).getBukkitEntity().getScheduler().runDelayed(
|
||||
GrimACBukkitLoaderPlugin.LOADER,
|
||||
ignored -> task.run(),
|
||||
retired,
|
||||
delayTicks
|
||||
);
|
||||
|
||||
return scheduled == null ? null : new FoliaTaskHandle(scheduled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle runAtFixedRate(@NotNull GrimEntity entity, @NotNull GrimPlugin plugin, @NotNull Runnable task, @Nullable Runnable retired, long initialDelayTicks, long periodTicks) {
|
||||
return new FoliaTaskHandle(((BukkitGrimEntity) entity).getBukkitEntity().getScheduler().runAtFixedRate(GrimACBukkitLoaderPlugin.LOADER, (ignored) -> task.run(), retired, initialDelayTicks, periodTicks));
|
||||
ScheduledTask scheduled = ((BukkitGrimEntity) entity).getBukkitEntity().getScheduler().runAtFixedRate(
|
||||
GrimACBukkitLoaderPlugin.LOADER,
|
||||
ignored -> task.run(),
|
||||
retired,
|
||||
initialDelayTicks,
|
||||
periodTicks
|
||||
);
|
||||
|
||||
return scheduled == null ? null : new FoliaTaskHandle(scheduled);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -18,17 +18,17 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
|
||||
|
||||
@Override
|
||||
public TaskHandle run(@NotNull GrimPlugin plugin, @NotNull Runnable task) {
|
||||
return new FoliaTaskHandle(globalRegionScheduler.run(GrimACBukkitLoaderPlugin.LOADER, (ignored) -> task.run()));
|
||||
return new FoliaTaskHandle(globalRegionScheduler.run(GrimACBukkitLoaderPlugin.LOADER, ignored -> task.run()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle runDelayed(@NotNull GrimPlugin plugin, @NotNull Runnable task, long delay) {
|
||||
return new FoliaTaskHandle(globalRegionScheduler.runDelayed(GrimACBukkitLoaderPlugin.LOADER, (ignored) -> task.run(), delay));
|
||||
return new FoliaTaskHandle(globalRegionScheduler.runDelayed(GrimACBukkitLoaderPlugin.LOADER, ignored -> task.run(), delay));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull Runnable task, long initialDelayTicks, long periodTicks) {
|
||||
return new FoliaTaskHandle(globalRegionScheduler.runAtFixedRate(GrimACBukkitLoaderPlugin.LOADER, (ignored) -> task.run(), initialDelayTicks, periodTicks));
|
||||
return new FoliaTaskHandle(globalRegionScheduler.runAtFixedRate(GrimACBukkitLoaderPlugin.LOADER, ignored -> task.run(), initialDelayTicks, periodTicks));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-5
@@ -2,12 +2,12 @@ package ac.grim.grimac.platform.bukkit.scheduler.folia;
|
||||
|
||||
import ac.grim.grimac.platform.api.scheduler.PlatformScheduler;
|
||||
import lombok.Getter;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@Getter
|
||||
public class FoliaPlatformScheduler implements PlatformScheduler {
|
||||
private final @NonNull FoliaAsyncScheduler asyncScheduler = new FoliaAsyncScheduler();
|
||||
private final @NonNull FoliaGlobalRegionScheduler globalRegionScheduler = new FoliaGlobalRegionScheduler();
|
||||
private final @NonNull FoliaEntityScheduler entityScheduler = new FoliaEntityScheduler();
|
||||
private final @NonNull FoliaRegionScheduler regionScheduler = new FoliaRegionScheduler();
|
||||
private final @NotNull FoliaAsyncScheduler asyncScheduler = new FoliaAsyncScheduler();
|
||||
private final @NotNull FoliaGlobalRegionScheduler globalRegionScheduler = new FoliaGlobalRegionScheduler();
|
||||
private final @NotNull FoliaEntityScheduler entityScheduler = new FoliaEntityScheduler();
|
||||
private final @NotNull FoliaRegionScheduler regionScheduler = new FoliaRegionScheduler();
|
||||
}
|
||||
+3
-3
@@ -31,7 +31,7 @@ public class FoliaRegionScheduler implements RegionScheduler {
|
||||
((BukkitPlatformWorld) world).getBukkitWorld(),
|
||||
chunkX,
|
||||
chunkZ,
|
||||
(ignored) -> task.run()
|
||||
ignored -> task.run()
|
||||
));
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public class FoliaRegionScheduler implements RegionScheduler {
|
||||
((BukkitPlatformWorld) world).getBukkitWorld(),
|
||||
chunkX,
|
||||
chunkZ,
|
||||
(ignored) -> task.run(),
|
||||
ignored -> task.run(),
|
||||
delayTicks
|
||||
));
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public class FoliaRegionScheduler implements RegionScheduler {
|
||||
((BukkitPlatformWorld) world).getBukkitWorld(),
|
||||
chunkX,
|
||||
chunkZ,
|
||||
(ignored) -> task.run(),
|
||||
ignored -> task.run(),
|
||||
initialDelayTicks,
|
||||
periodTicks
|
||||
));
|
||||
|
||||
@@ -12,8 +12,8 @@ import org.bukkit.command.RemoteConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.SenderMapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -78,12 +78,12 @@ public class BukkitSenderFactory extends SenderFactory<CommandSender> implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Sender map(@NonNull CommandSender base) {
|
||||
public @NotNull Sender map(@NotNull CommandSender base) {
|
||||
return this.wrap(base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CommandSender reverse(@NonNull Sender mapped) {
|
||||
public @NotNull CommandSender reverse(@NotNull Sender mapped) {
|
||||
return this.unwrap(mapped);
|
||||
}
|
||||
}
|
||||
-5
@@ -31,11 +31,6 @@ public class BukkitConversionUtils {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* For use with bukkit events only
|
||||
* Grim is not meant to be restrained by bukkit!
|
||||
*/
|
||||
@Deprecated
|
||||
public static BlockFace fromBukkitFace(org.bukkit.block.BlockFace face) {
|
||||
return switch (face) {
|
||||
case NORTH -> BlockFace.NORTH;
|
||||
|
||||
@@ -6,6 +6,7 @@ import ac.grim.grimac.platform.api.world.PlatformChunk;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -15,14 +16,11 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class BukkitPlatformChunk implements PlatformChunk {
|
||||
private static final Map<BlockData, Integer> blockDataToId = GrimAPI.INSTANCE.getPlatform() == Platform.FOLIA ? new ConcurrentHashMap<>() : new HashMap<>();
|
||||
private static final boolean isFlat = PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_13);
|
||||
private final Chunk chunk;
|
||||
|
||||
public BukkitPlatformChunk(@NotNull Chunk chunk) {
|
||||
this.chunk = chunk;
|
||||
}
|
||||
private final @NotNull Chunk chunk;
|
||||
|
||||
@Override
|
||||
public int getBlockID(int x, int y, int z) {
|
||||
@@ -30,6 +28,11 @@ public class BukkitPlatformChunk implements PlatformChunk {
|
||||
|
||||
return isFlat // Cache blockDataToID because Strings are expensive
|
||||
? blockDataToId.computeIfAbsent(block.getBlockData(), data -> WrappedBlockState.getByString(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), data.getAsString(false)).getGlobalId())
|
||||
: (block.getType().getId() << 4) | block.getData();
|
||||
: getLegacyBlockID(block);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "deprecation", "UnstableApiUsage" })
|
||||
private static int getLegacyBlockID(@NotNull Block block) {
|
||||
return (block.getType().getId() << 4) | block.getData();
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
@@ -16,14 +17,11 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public class BukkitPlatformWorld implements PlatformWorld {
|
||||
|
||||
private static final boolean LEGACY_SERVER_VERSION = PacketEvents.getAPI().getServerManager().getVersion().isOlderThanOrEquals(ServerVersion.V_1_12_2);
|
||||
private final World bukkitWorld;
|
||||
|
||||
public BukkitPlatformWorld(@NotNull World world) {
|
||||
this.bukkitWorld = world;
|
||||
}
|
||||
private final @NotNull World bukkitWorld;
|
||||
|
||||
@Override
|
||||
public boolean isChunkLoaded(int chunkX, int chunkZ) {
|
||||
@@ -34,6 +32,7 @@ public class BukkitPlatformWorld implements PlatformWorld {
|
||||
public WrappedBlockState getBlockAt(int x, int y, int z) {
|
||||
if (LEGACY_SERVER_VERSION) {
|
||||
Block block = bukkitWorld.getBlockAt(x, y, z);
|
||||
@SuppressWarnings({"deprecation", "UnstableApiUsage"})
|
||||
int blockId = (block.getType().getId() << 4) | block.getData();
|
||||
return WrappedBlockState.getByGlobalId(blockId);
|
||||
} else {
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
# cliff.toml - DEV BUILDS - Now with Author Info
|
||||
|
||||
[changelog]
|
||||
body = """
|
||||
## Changes in this Build (since previous push)
|
||||
{%- for group, commits in commits | group_by(attribute="group") %}
|
||||
### {{ group | striptags | upper_first }}
|
||||
{%- for commit in commits %}
|
||||
- {{ commit.message | upper_first }} - *by {{ commit.author.name }}* {% if commit.breaking %}**[BREAKING]**{% endif %} \
|
||||
{%- if commit.remote and commit.remote.url -%}
|
||||
([`{{ commit.id | truncate(length=7, end="") }}`]({{ commit.remote.url }}/commit/{{- commit.id -}}))
|
||||
{%- else -%}
|
||||
(`{{ commit.id | truncate(length=7, end="") }}`)
|
||||
{%- endif -%}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
"""
|
||||
trim = true
|
||||
|
||||
[git]
|
||||
# Your previous settings here are perfect, no changes needed
|
||||
filter_unconventional = false
|
||||
skip_unconventional = false
|
||||
remote = "https://github.com/GrimAnticheat/Grim"
|
||||
commit_parsers = [
|
||||
{ message = "^feat", group = "🚀 Features" },
|
||||
{ message = "^fix", group = "🐛 Fixes" },
|
||||
{ message = "^perf", group = "⚡️ Performance" },
|
||||
{ message = "^refactor", group = "♻️ Refactoring" },
|
||||
{ message = "^docs", group = "📖 Documentation" },
|
||||
{ message = "^test", group = "✅ Tests" },
|
||||
{ message = "^chore", group = "🤖 Maintenance & CI" },
|
||||
{ body = ".*BREAKING CHANGE.*", group = "🚨 Breaking Changes" },
|
||||
{ message = ".*", group = "Miscellaneous" } # CHANGED THIS LINE
|
||||
]
|
||||
commit_preprocessors = [
|
||||
{ pattern = 'src/main/java/ac/grim/grimac/checks/.*', group = "✔️ Checks" },
|
||||
{ pattern = 'src/main/java/ac/grim/grimac/api/.*', group = "🔌 API" },
|
||||
{ pattern = 'src/main/java/ac/grim/grimac/platform/.*', group = "🏗️ Platform" },
|
||||
{ pattern = 'src/main/java/ac/grim/grimac/engine/.*', group = "⚙️ Core Engine" },
|
||||
{ pattern = 'src/main/java/ac/grim/grimac/config/.*', group = "⚙️ Configuration" },
|
||||
{ pattern = 'pom.xml', group = "🤖 Maintenance & CI" },
|
||||
{ pattern = '.github/.*', group = "🤖 Maintenance & CI" },
|
||||
{ pattern = 'build.gradle.kts', group = "🤖 Maintenance & CI" },
|
||||
{ pattern = 'src/.*', group = "⚙️ Core Engine" },
|
||||
]
|
||||
sort_commits = "oldest"
|
||||
+69
-20
@@ -9,23 +9,65 @@ repositories {
|
||||
if (BuildConfig.mavenLocalOverride) {
|
||||
mavenLocal()
|
||||
}
|
||||
maven {
|
||||
name = "papermc"
|
||||
url = uri("https://repo.papermc.io/repository/maven-public/")
|
||||
}
|
||||
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") // Spigot
|
||||
maven("https://repo.grim.ac/snapshots") { // Grim API
|
||||
content {
|
||||
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven("https://repo.grim.ac/snapshots") // Grim API
|
||||
}
|
||||
filter {
|
||||
includeGroup("ac.grim.grimac")
|
||||
includeGroup("com.github.retrooper")
|
||||
}
|
||||
}
|
||||
maven("https://repo.viaversion.com") // ViaVersion
|
||||
maven("https://nexus.scarsz.me/content/repositories/releases") // Configuralize
|
||||
maven("https://repo.opencollab.dev/maven-snapshots/") // Floodgate
|
||||
maven("https://repo.opencollab.dev/maven-releases/") // Cumulus (for Floodgate)
|
||||
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||
mavenCentral() // FastUtil
|
||||
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven("https://repo.viaversion.com") { // ViaVersion
|
||||
mavenContent { releasesOnly() }
|
||||
}
|
||||
}
|
||||
filter {
|
||||
includeGroup("com.viaversion")
|
||||
}
|
||||
}
|
||||
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven("https://nexus.scarsz.me/content/repositories/releases") { // Configuralize
|
||||
mavenContent { releasesOnly() }
|
||||
}
|
||||
}
|
||||
filter {
|
||||
includeGroup("github.scarsz")
|
||||
}
|
||||
}
|
||||
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven("https://repo.opencollab.dev/maven-releases/") { // Cumulus (for Floodgate)
|
||||
mavenContent { releasesOnly() }
|
||||
}
|
||||
}
|
||||
filter {
|
||||
includeGroup("org.geysermc.api")
|
||||
}
|
||||
}
|
||||
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven("https://repo.opencollab.dev/maven-snapshots/") { // Floodgate
|
||||
mavenContent { snapshotsOnly() }
|
||||
}
|
||||
}
|
||||
filter {
|
||||
includeGroup("org.geysermc.floodgate")
|
||||
includeGroup("org.geysermc.cumulus")
|
||||
includeModule("org.geysermc", "common")
|
||||
includeModule("org.geysermc", "geyser-parent")
|
||||
}
|
||||
}
|
||||
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -35,21 +77,28 @@ dependencies {
|
||||
compileOnly(libs.packetevents.api)
|
||||
}
|
||||
api(libs.cloud.core)
|
||||
api("org.incendo:cloud-processors-requirements:1.0.0-rc.1")
|
||||
api("github.scarsz:configuralize:1.4.1:slim") {
|
||||
api(libs.cloud.processors.requirements)
|
||||
api(libs.configuralize) {
|
||||
artifact {
|
||||
classifier = "slim"
|
||||
}
|
||||
exclude(group = "org.yaml", module = "snakeyaml")
|
||||
}
|
||||
// Bump snakeyaml (transitive dep of configuralize) 1.29 -> 2.2 for geyser-fabric
|
||||
api("org.yaml:snakeyaml:2.2")
|
||||
// Bump snakeyaml (transitive dep of configuralize) 1.29 -> 2.2+ for geyser-fabric
|
||||
api(libs.snakeyaml)
|
||||
api(libs.fastutil)
|
||||
api(libs.adventure.text.minimessage)
|
||||
api(libs.jetbrains.annotations)
|
||||
api("com.zaxxer:HikariCP:4.0.3")
|
||||
api(libs.hikaricp)
|
||||
|
||||
api("ac.grim.grimac:GrimAPI:1.1.0.0")
|
||||
api(libs.grim.api)
|
||||
|
||||
compileOnly(libs.geyser.base.api) {
|
||||
isTransitive = false // messes with guava otherwise
|
||||
}
|
||||
|
||||
compileOnly(libs.floodgate.api)
|
||||
compileOnly(libs.via.version.api)
|
||||
compileOnly(libs.viaversion)
|
||||
compileOnly(libs.netty)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package ac.grim.grimac;
|
||||
|
||||
import ac.grim.grimac.api.event.EventBus;
|
||||
import ac.grim.grimac.api.event.OptimizedEventBus;
|
||||
import ac.grim.grimac.api.plugin.GrimPlugin;
|
||||
import ac.grim.grimac.events.GrimExtensionManager;
|
||||
import ac.grim.grimac.events.OptimizedEventBus;
|
||||
import ac.grim.grimac.manager.AlertManagerImpl;
|
||||
import ac.grim.grimac.manager.DiscordManager;
|
||||
import ac.grim.grimac.manager.InitManager;
|
||||
@@ -24,6 +25,7 @@ import ac.grim.grimac.platform.api.scheduler.PlatformScheduler;
|
||||
import ac.grim.grimac.platform.api.sender.Sender;
|
||||
import ac.grim.grimac.platform.api.sender.SenderFactory;
|
||||
import ac.grim.grimac.utils.anticheat.PlayerDataManager;
|
||||
import ac.grim.grimac.utils.common.arguments.CommonGrimArguments;
|
||||
import ac.grim.grimac.utils.reflection.ReflectionUtils;
|
||||
import lombok.Getter;
|
||||
import org.incendo.cloud.CommandManager;
|
||||
@@ -42,6 +44,7 @@ public final class GrimAPI {
|
||||
private final DiscordManager discordManager;
|
||||
private final PlayerDataManager playerDataManager;
|
||||
private final TickManager tickManager;
|
||||
private final GrimExtensionManager extensionManager;
|
||||
private final EventBus eventBus;
|
||||
private final GrimExternalAPI externalAPI;
|
||||
private ViolationDatabaseManager violationDatabaseManager;
|
||||
@@ -57,12 +60,15 @@ public final class GrimAPI {
|
||||
this.discordManager = new DiscordManager();
|
||||
this.playerDataManager = new PlayerDataManager();
|
||||
this.tickManager = new TickManager();
|
||||
this.eventBus = new OptimizedEventBus();
|
||||
this.extensionManager = new GrimExtensionManager();
|
||||
this.eventBus = new OptimizedEventBus(extensionManager);
|
||||
this.externalAPI = new GrimExternalAPI(this);
|
||||
}
|
||||
|
||||
// the order matters
|
||||
private static Platform detectPlatform() {
|
||||
Platform override = CommonGrimArguments.PLATFORM_OVERRIDE.value();
|
||||
if (override != null) return override;
|
||||
if (ReflectionUtils.hasClass("io.papermc.paper.threadedregions.RegionizedServer")) return Platform.FOLIA;
|
||||
if (ReflectionUtils.hasClass("org.bukkit.Bukkit")) return Platform.BUKKIT;
|
||||
if (ReflectionUtils.hasClass("net.fabricmc.loader.api.FabricLoader")) return Platform.FABRIC;
|
||||
@@ -136,4 +142,8 @@ public final class GrimAPI {
|
||||
public PermissionRegistrationManager getPermissionManager() {
|
||||
return loader.getPermissionManager();
|
||||
}
|
||||
|
||||
public GrimExtensionManager getExtensionManager() {
|
||||
return extensionManager;
|
||||
}
|
||||
}
|
||||
@@ -12,9 +12,8 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
import ac.grim.grimac.utils.common.ConfigReloadObserver;
|
||||
import com.github.retrooper.packetevents.netty.channel.ChannelHelper;
|
||||
import lombok.Getter;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -42,7 +41,7 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, S
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull EventBus getEventBus() {
|
||||
public @NotNull EventBus getEventBus() {
|
||||
return api.getEventBus();
|
||||
}
|
||||
|
||||
@@ -183,11 +182,8 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, S
|
||||
// Don't reload players if the plugin hasn't started yet
|
||||
if (!started) return;
|
||||
// Reload checks for all players
|
||||
for (GrimPlayer grimPlayer : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
|
||||
ChannelHelper.runInEventLoop(grimPlayer.user.getChannel(), () -> {
|
||||
grimPlayer.updatePermissions();
|
||||
grimPlayer.reload(configManager);
|
||||
});
|
||||
for (GrimPlayer player : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
|
||||
player.runSafely(() -> player.reload(configManager));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,13 +8,14 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying.isFlying;
|
||||
|
||||
// Class from https://github.com/Tecnio/AntiCheatBase/blob/master/src/main/java/me/tecnio/anticheat/check/Check.java
|
||||
@Getter
|
||||
public class Check extends GrimProcessor implements AbstractCheck {
|
||||
@@ -62,19 +63,12 @@ public class Check extends GrimProcessor implements AbstractCheck {
|
||||
return isEnabled && !player.disableGrim && !player.noModifyPacketPermission && !exemptPermission;
|
||||
}
|
||||
|
||||
public void updatePermissions() {
|
||||
if (player.platformPlayer == null || configName == null) return;
|
||||
GrimAPI.INSTANCE.getScheduler().getEntityScheduler().run(
|
||||
player.platformPlayer,
|
||||
GrimAPI.INSTANCE.getGrimPlugin(),
|
||||
() -> {
|
||||
final String id = configName.toLowerCase();
|
||||
exemptPermission = player.platformPlayer.hasPermission("grim.exempt." + id);
|
||||
noSetbackPermission = player.platformPlayer.hasPermission("grim.nosetback." + id);
|
||||
noModifyPacketPermission = player.platformPlayer.hasPermission("grim.nomodifypacket." + id);
|
||||
},
|
||||
() -> {}
|
||||
);
|
||||
public final void updatePermissions() {
|
||||
if (configName == null || player.platformPlayer == null) return;
|
||||
final String id = configName.toLowerCase();
|
||||
exemptPermission = player.platformPlayer.hasPermission("grim.exempt." + id);
|
||||
noSetbackPermission = player.platformPlayer.hasPermission("grim.nosetback." + id);
|
||||
noModifyPacketPermission = player.platformPlayer.hasPermission("grim.nomodifypacket." + id);
|
||||
}
|
||||
|
||||
public final boolean flagAndAlert(String verbose) {
|
||||
@@ -136,14 +130,13 @@ public class Check extends GrimProcessor implements AbstractCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload(ConfigManager configuration) {
|
||||
public final void reload(ConfigManager configuration) {
|
||||
decay = configuration.getDoubleElse(configName + ".decay", decay);
|
||||
setbackVL = configuration.getDoubleElse(configName + ".setbackvl", setbackVL);
|
||||
displayName = configuration.getStringElse(configName + ".displayname", checkName);
|
||||
description = configuration.getStringElse(configName + ".description", description);
|
||||
|
||||
if (setbackVL == -1) setbackVL = Double.MAX_VALUE;
|
||||
updatePermissions();
|
||||
onReload(configuration);
|
||||
}
|
||||
|
||||
@@ -171,13 +164,13 @@ public class Check extends GrimProcessor implements AbstractCheck {
|
||||
return offset > 0.001 ? String.format("%.5f", offset) : String.format("%.2E", offset);
|
||||
}
|
||||
|
||||
public boolean isTransaction(PacketTypeCommon packetType) {
|
||||
public static boolean isTransaction(PacketTypeCommon packetType) {
|
||||
return packetType == PacketType.Play.Client.PONG ||
|
||||
packetType == PacketType.Play.Client.WINDOW_CONFIRMATION;
|
||||
}
|
||||
|
||||
public boolean isFlying(PacketTypeCommon packetType) {
|
||||
return WrapperPlayClientPlayerFlying.isFlying(packetType);
|
||||
public static boolean isAsync(PacketTypeCommon packetType) {
|
||||
return packetType == PacketType.Play.Client.KEEP_ALIVE;
|
||||
}
|
||||
|
||||
public boolean isUpdate(PacketTypeCommon packetType) {
|
||||
|
||||
@@ -28,7 +28,7 @@ public class AimModulo360 extends Check implements RotationCheck {
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.xRot < 360 && player.xRot > -360 && Math.abs(rotationUpdate.getDeltaXRot()) > 320 && Math.abs(lastDeltaYaw) < 30) {
|
||||
if (player.yaw < 360 && player.yaw > -360 && Math.abs(rotationUpdate.getDeltaXRot()) > 320 && Math.abs(lastDeltaYaw) < 30) {
|
||||
flagAndAlert();
|
||||
} else {
|
||||
reward();
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientHe
|
||||
|
||||
@CheckData(name = "BadPacketsA", description = "Sent duplicate slot id")
|
||||
public class BadPacketsA extends Check implements PacketCheck {
|
||||
int lastSlot = -1;
|
||||
private int lastSlot = -1;
|
||||
|
||||
public BadPacketsA(final GrimPlayer player) {
|
||||
super(player);
|
||||
|
||||
@@ -22,15 +22,13 @@ public class BadPacketsD extends Check implements PacketCheck {
|
||||
final float pitch = new WrapperPlayClientPlayerFlying(event).getLocation().getPitch();
|
||||
if (pitch > 90 || pitch < -90) {
|
||||
// Ban.
|
||||
if (flagAndAlert("pitch=" + pitch)) {
|
||||
if (shouldModifyPackets()) {
|
||||
// prevent other checks from using an invalid pitch
|
||||
if (player.yRot > 90) player.yRot = 90;
|
||||
if (player.yRot < -90) player.yRot = -90;
|
||||
if (flagAndAlert("pitch=" + pitch) && shouldModifyPackets()) {
|
||||
// prevent other checks from using an invalid pitch
|
||||
if (player.pitch > 90) player.pitch = 90;
|
||||
if (player.pitch < -90) player.pitch = -90;
|
||||
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,15 +54,11 @@ public class BadPacketsH extends BlockPlaceCheck {
|
||||
}
|
||||
|
||||
public boolean shouldCancel(int sequence) {
|
||||
if (isSupportedVersion && sequence != lastSequence + 1) {
|
||||
if (flagAndAlert("expected=" + (lastSequence + 1) + ", id=" + sequence) && shouldModifyPackets()) {
|
||||
lastSequence = sequence;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int expected = lastSequence + 1;
|
||||
lastSequence = sequence;
|
||||
return false;
|
||||
return isSupportedVersion && sequence != expected
|
||||
&& flagAndAlert("expected=" + expected + ", id=" + sequence)
|
||||
&& shouldModifyPackets();
|
||||
}
|
||||
|
||||
public void onWorldChange() {
|
||||
|
||||
@@ -16,13 +16,11 @@ public class BadPacketsI extends Check implements PacketCheck {
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.PLAYER_ABILITIES) {
|
||||
if (new WrapperPlayClientPlayerAbilities(event).isFlying() && !player.canFly) {
|
||||
if (flagAndAlert() && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
}
|
||||
if (event.getPacketType() == PacketType.Play.Client.PLAYER_ABILITIES
|
||||
&& new WrapperPlayClientPlayerAbilities(event).isFlying() && !player.canFly
|
||||
&& flagAndAlert() && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,14 +39,14 @@ public class BadPacketsJ extends Check implements PacketCheck {
|
||||
|
||||
if (isTickPacket(event.getPacketType())) {
|
||||
// due to tick skipping, the rotations sent could be last tick's
|
||||
boolean allowLast = player.canSkipTicksPreVia() && (event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION || event.getPacketType() == PacketType.Play.Client.PLAYER_ROTATION);
|
||||
boolean allowLast = player.canSkipTicks() && (event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION || event.getPacketType() == PacketType.Play.Client.PLAYER_ROTATION);
|
||||
for (HeadRotation rotation : rotations) {
|
||||
if (rotation.getYaw() == player.xRot && rotation.getPitch() == player.yRot) {
|
||||
if (rotation.yaw() == player.yaw && rotation.pitch() == player.pitch) {
|
||||
allowLast = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rotation.getYaw() == player.lastXRot && rotation.getPitch() == player.lastYRot && allowLast) {
|
||||
if (rotation.yaw() == player.lastYaw && rotation.pitch() == player.lastPitch && allowLast) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,13 +16,11 @@ public class BadPacketsK extends Check implements PacketCheck {
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.SPECTATE) {
|
||||
if (player.gamemode != GameMode.SPECTATOR) {
|
||||
if (flagAndAlert() && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
}
|
||||
if (event.getPacketType() == PacketType.Play.Client.SPECTATE
|
||||
&& player.gamemode != GameMode.SPECTATOR
|
||||
&& flagAndAlert() && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,11 +16,11 @@ public class BadPacketsS extends Check implements PacketCheck {
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.WINDOW_CONFIRMATION) {
|
||||
if (!new WrapperPlayClientWindowConfirmation(event).isAccepted() && flagAndAlert() && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
if (event.getPacketType() == PacketType.Play.Client.WINDOW_CONFIRMATION
|
||||
&& !new WrapperPlayClientWindowConfirmation(event).isAccepted()
|
||||
&& flagAndAlert() && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,16 +14,20 @@ import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientIn
|
||||
|
||||
@CheckData(name = "BadPacketsT")
|
||||
public class BadPacketsT extends Check implements PacketCheck {
|
||||
// 1.7 and 1.8 seem to have different hitbox "expansion" values than 1.9+
|
||||
// https://github.com/GrimAnticheat/Grim/pull/1274#issuecomment-1872458702
|
||||
// https://github.com/GrimAnticheat/Grim/pull/1274#issuecomment-1872533497
|
||||
private final boolean hasLegacyExpansion = player.getClientVersion().isOlderThan(ClientVersion.V_1_9);
|
||||
private final double maxHorizontalDisplacement = 0.3001 + (hasLegacyExpansion ? 0.1 : 0);
|
||||
private final double minVerticalDisplacement = -0.0001 - (hasLegacyExpansion ? 0.1 : 0);
|
||||
private final double maxVerticalDisplacement = 1.8001 + (hasLegacyExpansion ? 0.1 : 0);
|
||||
|
||||
private final double maxHorizontalDisplacement;
|
||||
private final double minVerticalDisplacement;
|
||||
private final double maxVerticalDisplacement;
|
||||
|
||||
public BadPacketsT(final GrimPlayer player) {
|
||||
super(player);
|
||||
// 1.7 and 1.8 seem to have different hitbox "expansion" values than 1.9+
|
||||
// https://github.com/GrimAnticheat/Grim/pull/1274#issuecomment-1872458702
|
||||
// https://github.com/GrimAnticheat/Grim/pull/1274#issuecomment-1872533497
|
||||
double expansion = player.getClientVersion().isOlderThan(ClientVersion.V_1_9) ? 0.1 : 0;
|
||||
maxHorizontalDisplacement = 0.3001 + expansion;
|
||||
minVerticalDisplacement = -0.0001 - expansion;
|
||||
maxVerticalDisplacement = 1.8001 + expansion;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -31,7 +31,9 @@ public class BadPacketsU extends Check implements PacketCheck {
|
||||
// except y gets wrapped?
|
||||
final int expectedY = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8) ? 4095 : 255;
|
||||
|
||||
final boolean failedItemCheck = packet.getItemStack().isPresent() && isEmpty(packet.getItemStack().get());
|
||||
final boolean failedItemCheck = packet.getItemStack().isPresent() && isEmpty(packet.getItemStack().get())
|
||||
// ViaVersion can sometimes cause this part of the check to false
|
||||
&& player.getClientVersion().isOlderThan(ClientVersion.V_1_9);
|
||||
|
||||
final Vector3i pos = packet.getBlockPosition();
|
||||
final Vector3f cursor = packet.getCursorPosition();
|
||||
|
||||
@@ -20,7 +20,7 @@ public class BadPacketsV extends Check implements PacketCheck {
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (!player.canSkipTicksPreVia() && isTickPacket(event.getPacketType())) {
|
||||
if (!player.canSkipTicks() && isTickPacket(event.getPacketType())) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION || event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION) {
|
||||
int positionAtLeastEveryNTicks = player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8) ? 20 : 19;
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ public class BadPacketsX extends Check implements PostPredictionCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(final PredictionComplete predictionComplete) {
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (flags > 0) {
|
||||
setbackIfAboveSetbackVL();
|
||||
}
|
||||
@@ -51,7 +51,7 @@ public class BadPacketsX extends Check implements PostPredictionCheck {
|
||||
switch (new WrapperPlayClientEntityAction(event).getAction()) {
|
||||
case START_SNEAKING, STOP_SNEAKING -> {
|
||||
if (sneak) {
|
||||
if (player.canSkipTicksPreVia() || flagAndAlert()) {
|
||||
if (player.canSkipTicks() || flagAndAlert()) {
|
||||
flags++;
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public class BadPacketsX extends Check implements PostPredictionCheck {
|
||||
}
|
||||
|
||||
if (sprint) {
|
||||
if (player.canSkipTicksPreVia() || flagAndAlert()) {
|
||||
if (player.canSkipTicks() || flagAndAlert()) {
|
||||
flags++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package ac.grim.grimac.checks.impl.badpackets;
|
||||
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
|
||||
@CheckData(name = "BadPacketsZ", experimental = true)
|
||||
public class BadPacketsZ extends Check implements PacketCheck {
|
||||
private boolean sent;
|
||||
|
||||
public BadPacketsZ(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.CLIENT_TICK_END) {
|
||||
sent = false;
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Client.PLAYER_INPUT) {
|
||||
if (sent) {
|
||||
flagAndAlert();
|
||||
}
|
||||
|
||||
sent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,10 +23,10 @@ public class Baritone extends Check implements RotationCheck {
|
||||
final HeadRotation from = rotationUpdate.getFrom();
|
||||
final HeadRotation to = rotationUpdate.getTo();
|
||||
|
||||
final float deltaPitch = Math.abs(to.getPitch() - from.getPitch());
|
||||
final float deltaPitch = Math.abs(to.pitch() - from.pitch());
|
||||
|
||||
// Baritone works with small degrees, limit to 1 degree to pick up on baritone slightly moving aim to bypass anticheats
|
||||
if (rotationUpdate.getDeltaXRot() == 0 && deltaPitch > 0 && deltaPitch < 1 && Math.abs(to.getPitch()) != 90.0f) {
|
||||
if (rotationUpdate.getDeltaXRot() == 0 && deltaPitch > 0 && deltaPitch < 1 && Math.abs(to.pitch()) != 90.0f) {
|
||||
if (rotationUpdate.getProcessor().divisorY < GrimMath.MINIMUM_DIVISOR) {
|
||||
verbose++;
|
||||
if (verbose > 8) {
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.github.retrooper.packetevents.protocol.player.DiggingAction;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@CheckData(name = "AirLiquidBreak", description = "Breaking a block that cannot be broken")
|
||||
public class AirLiquidBreak extends Check implements BlockBreakCheck {
|
||||
@@ -20,8 +20,8 @@ public class AirLiquidBreak extends Check implements BlockBreakCheck {
|
||||
private int lastTick;
|
||||
private boolean didLastFlag;
|
||||
// Initialize to non-null values to prevent NPE when checking for blockType properties and if position equals old position
|
||||
private @NonNull Vector3i lastBreakLoc = new Vector3i();
|
||||
private @NonNull StateType lastBlockType = StateTypes.AIR;
|
||||
private int lastX, lastY, lastZ;
|
||||
private float lastHardness, lastBlastResistance;
|
||||
|
||||
public AirLiquidBreak(GrimPlayer player) {
|
||||
super(player);
|
||||
@@ -40,18 +40,23 @@ public class AirLiquidBreak extends Check implements BlockBreakCheck {
|
||||
// I am explicitly making this patch as narrow and specific as possible to potentially discover other blocks that exhibit similar behaviour
|
||||
int newTick = GrimAPI.INSTANCE.getTickManager().currentTick;
|
||||
if (lastTick == newTick
|
||||
&& lastBreakLoc.equals(blockBreak.position)
|
||||
&& lastX == blockBreak.x
|
||||
&& lastY == blockBreak.y
|
||||
&& lastZ == blockBreak.z
|
||||
&& !didLastFlag
|
||||
&& lastBlockType.getHardness() == 0.0F
|
||||
&& lastBlockType.getBlastResistance() == 0.0F
|
||||
&& lastHardness == 0.0F
|
||||
&& lastBlastResistance == 0.0F
|
||||
&& block == StateTypes.WATER
|
||||
) return;
|
||||
lastTick = newTick;
|
||||
lastBreakLoc = blockBreak.position;
|
||||
lastBlockType = block;
|
||||
lastX = blockBreak.x;
|
||||
lastY = blockBreak.y;
|
||||
lastZ = blockBreak.z;
|
||||
lastHardness = block.getHardness();
|
||||
lastBlastResistance = block.getBlastResistance();
|
||||
|
||||
// the block does not have a hitbox
|
||||
boolean invalid = (block == StateTypes.LIGHT && !(player.getInventory().getHeldItem().is(ItemTypes.LIGHT) || player.getInventory().getOffHand().is(ItemTypes.LIGHT)))
|
||||
boolean invalid = (block == StateTypes.LIGHT && !(player.inventory.getHeldItem().is(ItemTypes.LIGHT) || player.inventory.getOffHand().is(ItemTypes.LIGHT)))
|
||||
|| block.isAir()
|
||||
|| block == StateTypes.WATER
|
||||
|| block == StateTypes.LAVA
|
||||
|
||||
@@ -25,10 +25,9 @@ public class FarBreak extends Check implements BlockBreakCheck {
|
||||
|
||||
double min = Double.MAX_VALUE;
|
||||
for (double d : player.getPossibleEyeHeights()) {
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(blockBreak.position);
|
||||
Vector3dm eyes = new Vector3dm(player.x, player.y + d, player.z);
|
||||
Vector3dm best = VectorUtils.cutBoxToVector(eyes, box);
|
||||
min = Math.min(min, eyes.distanceSquared(best));
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(blockBreak.x, blockBreak.y, blockBreak.z);
|
||||
Vector3dm best = VectorUtils.cutBoxToVector(player.x, player.y + d, player.z, box);
|
||||
min = Math.min(min, best.distanceSquared(player.x, player.y + d, player.z));
|
||||
}
|
||||
|
||||
// getPickRange() determines this?
|
||||
|
||||
@@ -36,8 +36,11 @@ public class FastBreak extends Check implements BlockBreakCheck {
|
||||
super(playerData);
|
||||
}
|
||||
|
||||
// The block the player is currently breaking
|
||||
Vector3i targetBlockPosition = null;
|
||||
// The block the player is currently breaking, represented by primitives for performance.
|
||||
// `targetBlockIsSet` tracks nullness of the position, since primitives can't be null
|
||||
private boolean targetBlockIsSet;
|
||||
private int targetBlockX, targetBlockY, targetBlockZ;
|
||||
|
||||
// The maximum amount of damage the player deals to the block
|
||||
//
|
||||
double maximumBlockDamage = 0;
|
||||
@@ -53,7 +56,7 @@ public class FastBreak extends Check implements BlockBreakCheck {
|
||||
@Override
|
||||
public void onBlockBreak(BlockBreak blockBreak) {
|
||||
if (blockBreak.action == DiggingAction.START_DIGGING) {
|
||||
if (!ViaVersionUtil.isAvailable()) {
|
||||
if (!ViaVersionUtil.isAvailable) {
|
||||
// Exempt all blocks that do not exist in the player version
|
||||
final WrappedBlockState defaultState = WrappedBlockState.getDefaultState(player.getClientVersion(), blockBreak.block.getType());
|
||||
if (defaultState.getType() == StateTypes.AIR || EXEMPT_STATES.contains(defaultState.getType())) {
|
||||
@@ -67,8 +70,11 @@ public class FastBreak extends Check implements BlockBreakCheck {
|
||||
// * can we translate back "up" to server version and run check against server version to avoid loading older registries?
|
||||
WrappedBlockState block = clientOlderThanServer ? WrappedBlockState.getByGlobalId(player.getClientVersion(), player.getViaTranslatedClientBlockID(blockBreak.block.getGlobalId())) : blockBreak.block;
|
||||
|
||||
startBreak = System.currentTimeMillis() - (targetBlockPosition == null ? 50 : 0); // ???
|
||||
targetBlockPosition = blockBreak.position;
|
||||
startBreak = System.currentTimeMillis() - (!targetBlockIsSet ? 50 : 0); // ???
|
||||
targetBlockIsSet = true;
|
||||
targetBlockX = blockBreak.x;
|
||||
targetBlockY = blockBreak.y;
|
||||
targetBlockZ = blockBreak.z;
|
||||
|
||||
maximumBlockDamage = BlockBreakSpeed.getBlockDamage(player, block);
|
||||
|
||||
@@ -87,9 +93,7 @@ public class FastBreak extends Check implements BlockBreakCheck {
|
||||
}
|
||||
|
||||
clampBalance();
|
||||
}
|
||||
|
||||
if (blockBreak.action == DiggingAction.FINISHED_DIGGING && targetBlockPosition != null) {
|
||||
} else if (blockBreak.action == DiggingAction.FINISHED_DIGGING && targetBlockIsSet) {
|
||||
double predictedTime = Math.ceil(1 / maximumBlockDamage) * 50;
|
||||
double realTime = System.currentTimeMillis() - startBreak;
|
||||
double diff = predictedTime - realTime;
|
||||
@@ -117,8 +121,8 @@ public class FastBreak extends Check implements BlockBreakCheck {
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
// Find the most optimal block damage using the animation packet, which is sent at least once a tick when breaking blocks
|
||||
// On 1.8 clients, via screws with this packet meaning we must fall back to the 1.8 idle flying packet
|
||||
if ((player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? event.getPacketType() == PacketType.Play.Client.ANIMATION : WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) && targetBlockPosition != null) {
|
||||
maximumBlockDamage = Math.max(maximumBlockDamage, BlockBreakSpeed.getBlockDamage(player, player.compensatedWorld.getBlock(targetBlockPosition)));
|
||||
if ((player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? event.getPacketType() == PacketType.Play.Client.ANIMATION : WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) && targetBlockIsSet) {
|
||||
maximumBlockDamage = Math.max(maximumBlockDamage, BlockBreakSpeed.getBlockDamage(player, player.compensatedWorld.getBlock(targetBlockX, targetBlockY, targetBlockZ)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,9 @@ public class MultiBreak extends Check implements BlockBreakCheck {
|
||||
private final List<String> flags = new ArrayList<>();
|
||||
private boolean hasBroken;
|
||||
private BlockFace lastFace;
|
||||
private Vector3i lastPos;
|
||||
private int lastX;
|
||||
private int lastY;
|
||||
private int lastZ;
|
||||
|
||||
public MultiBreak(GrimPlayer player) {
|
||||
super(player);
|
||||
@@ -33,11 +35,23 @@ public class MultiBreak extends Check implements BlockBreakCheck {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasBroken && (blockBreak.face != lastFace || !blockBreak.position.equals(lastPos))) {
|
||||
final int currentX = blockBreak.x;
|
||||
final int currentY = blockBreak.y;
|
||||
final int currentZ = blockBreak.z;
|
||||
|
||||
if (hasBroken && (blockBreak.face != lastFace ||
|
||||
currentX != lastX ||
|
||||
currentY != lastY ||
|
||||
currentZ != lastZ)) {
|
||||
|
||||
final String currentPosString = MessageUtil.toUnlabeledString(currentX, currentY, currentZ);
|
||||
final String lastPosString = MessageUtil.toUnlabeledString(lastX, lastY, lastZ);
|
||||
|
||||
final String verbose = "face=" + blockBreak.face + ", lastFace=" + lastFace
|
||||
+ ", pos=" + MessageUtil.toUnlabledString(blockBreak.position)
|
||||
+ ", lastPos=" + MessageUtil.toUnlabledString(lastPos);
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
+ ", pos=" + currentPosString
|
||||
+ ", lastPos=" + lastPosString;
|
||||
|
||||
if (!player.canSkipTicks()) {
|
||||
if (flagAndAlert(verbose) && shouldModifyPackets()) {
|
||||
blockBreak.cancel();
|
||||
}
|
||||
@@ -47,7 +61,9 @@ public class MultiBreak extends Check implements BlockBreakCheck {
|
||||
}
|
||||
|
||||
lastFace = blockBreak.face;
|
||||
lastPos = blockBreak.position;
|
||||
lastX = currentX;
|
||||
lastY = currentY;
|
||||
lastZ = currentZ;
|
||||
hasBroken = true;
|
||||
}
|
||||
|
||||
@@ -60,7 +76,7 @@ public class MultiBreak extends Check implements BlockBreakCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (!player.canSkipTicksPreVia()) return;
|
||||
if (!player.canSkipTicks()) return;
|
||||
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
for (String verbose : flags) {
|
||||
|
||||
@@ -9,7 +9,7 @@ import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.DiggingAction;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
|
||||
@CheckData(name = "PositionBreakB", experimental = true)
|
||||
@CheckData(name = "PositionBreakB")
|
||||
public class PositionBreakB extends Check implements BlockBreakCheck {
|
||||
private final int releaseFace = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8) ? 0 : 255;
|
||||
private BlockFace lastFace;
|
||||
|
||||
@@ -7,6 +7,7 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.update.BlockBreak;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.Pair;
|
||||
import ac.grim.grimac.utils.data.TeleportData;
|
||||
import ac.grim.grimac.utils.math.Vector3dm;
|
||||
import ac.grim.grimac.utils.nmsutil.Ray;
|
||||
import ac.grim.grimac.utils.nmsutil.ReachUtils;
|
||||
@@ -14,6 +15,7 @@ import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.DiggingAction;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import com.github.retrooper.packetevents.protocol.teleport.RelativeFlag;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.util.Vector3f;
|
||||
@@ -70,7 +72,7 @@ public class RotationBreak extends Check implements BlockBreakCheck {
|
||||
}
|
||||
|
||||
private boolean didRayTraceHit(BlockBreak blockBreak) {
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(blockBreak.position);
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(blockBreak.x, blockBreak.y, blockBreak.z);
|
||||
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
|
||||
@@ -92,18 +94,18 @@ public class RotationBreak extends Check implements BlockBreakCheck {
|
||||
// End checking if the player is in the block
|
||||
|
||||
List<Vector3f> possibleLookDirs = new ArrayList<>(Arrays.asList(
|
||||
new Vector3f(player.lastXRot, player.yRot, 0),
|
||||
new Vector3f(player.xRot, player.yRot, 0)
|
||||
new Vector3f(player.lastYaw, player.pitch, 0),
|
||||
new Vector3f(player.yaw, player.pitch, 0)
|
||||
));
|
||||
|
||||
// 1.9+ players could be a tick behind because we don't get skipped ticks
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)) {
|
||||
possibleLookDirs.add(new Vector3f(player.lastXRot, player.lastYRot, 0));
|
||||
possibleLookDirs.add(new Vector3f(player.lastYaw, player.lastPitch, 0));
|
||||
}
|
||||
|
||||
// 1.7 players do not have any of these issues! They are always on the latest look vector
|
||||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_8)) {
|
||||
possibleLookDirs = Collections.singletonList(new Vector3f(player.xRot, player.yRot, 0));
|
||||
possibleLookDirs = Collections.singletonList(new Vector3f(player.yaw, player.pitch, 0));
|
||||
}
|
||||
|
||||
final double distance = player.compensatedEntities.self.getAttributeValue(Attributes.BLOCK_INTERACTION_RANGE);
|
||||
@@ -111,7 +113,8 @@ public class RotationBreak extends Check implements BlockBreakCheck {
|
||||
for (Vector3f lookDir : possibleLookDirs) {
|
||||
Vector3d starting = new Vector3d(player.x, player.y + d, player.z);
|
||||
Ray trace = new Ray(player, starting.getX(), starting.getY(), starting.getZ(), lookDir.getX(), lookDir.getY());
|
||||
Pair<Vector3dm, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
Vector3dm pointAtDistance = trace.getPointAtDistance(distance);
|
||||
Pair<Vector3dm, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOriginX(), trace.getOriginY(), trace.getOriginZ(), pointAtDistance.getX(), pointAtDistance.getY(), pointAtDistance.getZ());
|
||||
|
||||
if (intercept.first() != null) return true;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import ac.grim.grimac.checks.type.BlockBreakCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
import ac.grim.grimac.utils.anticheat.update.BlockBreak;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.DiggingAction;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||
@@ -15,9 +17,16 @@ import static ac.grim.grimac.utils.nmsutil.BlockBreakSpeed.getBlockDamage;
|
||||
|
||||
@CheckData(name = "WrongBreak")
|
||||
public class WrongBreak extends Check implements BlockBreakCheck {
|
||||
private final int exemptedY = player.getClientVersion().isOlderThan(ClientVersion.V_1_8) ? 255 : (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14) ? -1 : 4095);
|
||||
private final int exemptedY = player.getClientVersion().isOlderThan(ClientVersion.V_1_8) ? 255 : (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_14) ? -1 : 4095);
|
||||
private boolean lastBlockWasInstantBreak = false;
|
||||
private Vector3i lastBlock, lastCancelledBlock, lastLastBlock = null;
|
||||
|
||||
private boolean lastBlockIsSet;
|
||||
private int lastBlockX, lastBlockY, lastBlockZ;
|
||||
|
||||
private boolean lastCancelledBlockIsSet;
|
||||
private int lastCancelledBlockX, lastCancelledBlockY, lastCancelledBlockZ;
|
||||
|
||||
private boolean lastLastBlockIsSet;
|
||||
|
||||
public WrongBreak(final GrimPlayer player) {
|
||||
super(player);
|
||||
@@ -25,8 +34,7 @@ public class WrongBreak extends Check implements BlockBreakCheck {
|
||||
|
||||
// The client sometimes sends a wierd cancel packet
|
||||
private boolean shouldExempt(final WrappedBlockState block, int yPos) {
|
||||
// lastLastBlock is always null when this happens, and lastBlock isn't
|
||||
if (lastLastBlock != null || lastBlock == null)
|
||||
if (lastLastBlockIsSet || !lastBlockIsSet)
|
||||
return false;
|
||||
|
||||
// on pre 1.14.4 clients, the YPos of this packet is always the same
|
||||
@@ -39,22 +47,29 @@ public class WrongBreak extends Check implements BlockBreakCheck {
|
||||
|
||||
@Override
|
||||
public void onBlockBreak(BlockBreak blockBreak) {
|
||||
final int x = blockBreak.x;
|
||||
final int y = blockBreak.y;
|
||||
final int z = blockBreak.z;
|
||||
|
||||
if (blockBreak.action == DiggingAction.START_DIGGING) {
|
||||
final Vector3i pos = blockBreak.position;
|
||||
|
||||
lastBlockWasInstantBreak = getBlockDamage(player, blockBreak.block) >= 1;
|
||||
lastCancelledBlock = null;
|
||||
lastLastBlock = lastBlock;
|
||||
lastBlock = pos;
|
||||
}
|
||||
lastCancelledBlockIsSet = false;
|
||||
|
||||
if (blockBreak.action == DiggingAction.CANCELLED_DIGGING) {
|
||||
final Vector3i pos = blockBreak.position;
|
||||
lastLastBlockIsSet = lastBlockIsSet;
|
||||
|
||||
if (!shouldExempt(blockBreak.block, pos.y) && !pos.equals(lastBlock)) {
|
||||
lastBlockIsSet = true;
|
||||
lastBlockX = x;
|
||||
lastBlockY = y;
|
||||
lastBlockZ = z;
|
||||
} else if (blockBreak.action == DiggingAction.CANCELLED_DIGGING) {
|
||||
boolean notLastBlock = !lastBlockIsSet || x != lastBlockX || y != lastBlockY || z != lastBlockZ;
|
||||
|
||||
if (!shouldExempt(blockBreak.block, y) && notLastBlock) {
|
||||
// https://github.com/GrimAnticheat/Grim/issues/1512
|
||||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) || (!lastBlockWasInstantBreak && pos.equals(lastCancelledBlock))) {
|
||||
if (flagAndAlert("action=CANCELLED_DIGGING" + ", last=" + MessageUtil.toUnlabledString(lastBlock) + ", pos=" + MessageUtil.toUnlabledString(pos))) {
|
||||
boolean isLastCancelled = lastCancelledBlockIsSet && x == lastCancelledBlockX && y == lastCancelledBlockY && z == lastCancelledBlockZ;
|
||||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) || (!lastBlockWasInstantBreak && isLastCancelled)) {
|
||||
String lastBlockStr = lastBlockIsSet ? MessageUtil.toUnlabeledString(lastBlockX, lastBlockY, lastBlockZ) : "null";
|
||||
if (flagAndAlert("action=CANCELLED_DIGGING" + ", last=" + lastBlockStr + ", pos=" + MessageUtil.toUnlabeledString(x, y, z))) {
|
||||
if (shouldModifyPackets()) {
|
||||
blockBreak.cancel();
|
||||
}
|
||||
@@ -62,18 +77,20 @@ public class WrongBreak extends Check implements BlockBreakCheck {
|
||||
}
|
||||
}
|
||||
|
||||
lastCancelledBlock = pos;
|
||||
lastLastBlock = null;
|
||||
lastBlock = null;
|
||||
return;
|
||||
}
|
||||
lastCancelledBlockIsSet = true;
|
||||
lastCancelledBlockX = x;
|
||||
lastCancelledBlockY = y;
|
||||
lastCancelledBlockZ = z;
|
||||
|
||||
if (blockBreak.action == DiggingAction.FINISHED_DIGGING) {
|
||||
final Vector3i pos = blockBreak.position;
|
||||
lastLastBlockIsSet = lastBlockIsSet = false;
|
||||
} else if (blockBreak.action == DiggingAction.FINISHED_DIGGING) {
|
||||
boolean notLastCancelled = !lastCancelledBlockIsSet || x != lastCancelledBlockX || y != lastCancelledBlockY || z != lastCancelledBlockZ;
|
||||
boolean notLastBlock = !lastBlockIsSet || x != lastBlockX || y != lastBlockY || z != lastBlockZ;
|
||||
|
||||
// when a player looks away from the mined block, they send a cancel, and if they look at it again, they don't send another start. (thanks mojang!)
|
||||
if (!pos.equals(lastCancelledBlock) && (!lastBlockWasInstantBreak || player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4)) && !pos.equals(lastBlock)) {
|
||||
if (flagAndAlert("action=FINISHED_DIGGING" + ", last=" + MessageUtil.toUnlabledString(lastBlock) + ", pos=" + MessageUtil.toUnlabledString(pos))) {
|
||||
if (notLastCancelled && (!lastBlockWasInstantBreak || player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4)) && notLastBlock) {
|
||||
String lastBlockStr = lastBlockIsSet ? MessageUtil.toUnlabeledString(lastBlockX, lastBlockY, lastBlockZ) : "null";
|
||||
if (flagAndAlert("action=FINISHED_DIGGING" + ", last=" + lastBlockStr + ", pos=" + MessageUtil.toUnlabeledString(x, y, z))) {
|
||||
if (shouldModifyPackets()) {
|
||||
blockBreak.cancel();
|
||||
}
|
||||
@@ -82,9 +99,7 @@ public class WrongBreak extends Check implements BlockBreakCheck {
|
||||
|
||||
// 1.14.4+ clients don't send another start break in protected regions
|
||||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4)) {
|
||||
lastCancelledBlock = null;
|
||||
lastLastBlock = null;
|
||||
lastBlock = null;
|
||||
lastCancelledBlockIsSet = lastLastBlockIsSet = lastBlockIsSet = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,10 @@ 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.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientTabComplete;
|
||||
|
||||
@CheckData(name = "ChatA", experimental = true)
|
||||
@@ -18,7 +19,7 @@ public class ChatA extends Check implements PacketCheck {
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.TAB_COMPLETE && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_13)) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.TAB_COMPLETE && PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_13)) {
|
||||
WrapperPlayClientTabComplete wrapper = new WrapperPlayClientTabComplete(event);
|
||||
String text = wrapper.getText();
|
||||
if (text.equals("/") || text.trim().isEmpty()) {
|
||||
|
||||
@@ -4,9 +4,12 @@ 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.reflection.ViaVersionUtil;
|
||||
import ac.grim.grimac.utils.via.ViaHooks;
|
||||
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.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientChatCommand;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientChatCommandUnsigned;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientChatMessage;
|
||||
@@ -23,11 +26,8 @@ public class ChatB extends Check implements PacketCheck {
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.CHAT_MESSAGE) {
|
||||
String message = new WrapperPlayClientChatMessage(event).getMessage();
|
||||
if (message.isEmpty() || !message.trim().equals(message) || message.startsWith("/") && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_19)) {
|
||||
if (flagAndAlert("message=" + message)) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
if (checkChatMessage(message)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ public class ChatB extends Check implements PacketCheck {
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Client.CHAT_COMMAND) {
|
||||
// TODO make previa after making wrapper parse by client version instead of server version
|
||||
String command = "/" + new WrapperPlayClientChatCommand(event).getCommand();
|
||||
if (!command.trim().equals(command)) {
|
||||
if (flagAndAlert("command=" + command)) {
|
||||
@@ -51,4 +52,21 @@ public class ChatB extends Check implements PacketCheck {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// returns whether the packet should be cancelled
|
||||
public boolean checkChatMessage(String message) {
|
||||
if (message.isEmpty() || !message.trim().equals(message) || message.startsWith("/") && PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_19)) {
|
||||
if (flagAndAlert("message=" + message) && shouldModifyPackets()) {
|
||||
player.onPacketCancel();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static {
|
||||
if (ViaVersionUtil.isAvailable && PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_11)) {
|
||||
ViaHooks.injectVia();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ public class ChatC extends Check implements PacketCheck {
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.CHAT_MESSAGE) {
|
||||
// TODO make previa after making wrapper parse by client version instead of server version
|
||||
check(new WrapperPlayClientChatMessage(event).getMessage(), event);
|
||||
}
|
||||
|
||||
@@ -36,6 +37,7 @@ public class ChatC extends Check implements PacketCheck {
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Client.CHAT_COMMAND) {
|
||||
// TODO make previa after making wrapper parse by client version instead of server version
|
||||
check("/" + new WrapperPlayClientChatCommand(event).getCommand(), event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public class MultiInteractA extends Check implements PostPredictionCheck {
|
||||
if (hasInteracted && entity != lastEntity) {
|
||||
String verbose = "lastEntity=" + lastEntity + ", entity=" + entity
|
||||
+ ", lastSneaking=" + lastSneaking + ", sneaking=" + sneaking;
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (flagAndAlert(verbose) && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -55,7 +55,7 @@ public class MultiInteractA extends Check implements PostPredictionCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (!player.canSkipTicksPreVia()) return;
|
||||
if (!player.canSkipTicks()) return;
|
||||
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
for (String verbose : flags) {
|
||||
|
||||
@@ -35,7 +35,7 @@ public class MultiInteractB extends Check implements PostPredictionCheck {
|
||||
|
||||
if (hasInteracted && !pos.equals(lastPos)) {
|
||||
String verbose = "pos=" + MessageUtil.toUnlabledString(pos) + ", lastPos=" + MessageUtil.toUnlabledString(lastPos);
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (flagAndAlert(verbose) && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -56,7 +56,7 @@ public class MultiInteractB extends Check implements PostPredictionCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (!player.canSkipTicksPreVia()) return;
|
||||
if (!player.canSkipTicks()) return;
|
||||
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
for (String verbose : flags) {
|
||||
|
||||
@@ -143,7 +143,10 @@ public class Reach extends Check implements PacketCheck {
|
||||
} else {
|
||||
SimpleCollisionBox targetBox = reachEntity.getPossibleCollisionBoxes();
|
||||
if (reachEntity.type == EntityTypes.END_CRYSTAL) {
|
||||
targetBox = new SimpleCollisionBox(reachEntity.trackedServerPosition.getPos().subtract(1, 0, 1), reachEntity.trackedServerPosition.getPos().add(1, 2, 1));
|
||||
final double x = reachEntity.trackedServerPosition.getX();
|
||||
final double y = reachEntity.trackedServerPosition.getX();
|
||||
final double z = reachEntity.trackedServerPosition.getX();
|
||||
targetBox = new SimpleCollisionBox(x - 1, y, z - 1, x + 1, y + 2, z + 1);
|
||||
}
|
||||
return ReachUtils.getMinReachToBox(player, targetBox) > player.compensatedEntities.self.getAttributeValue(Attributes.ENTITY_INTERACTION_RANGE);
|
||||
}
|
||||
@@ -175,7 +178,10 @@ public class Reach extends Check implements PacketCheck {
|
||||
SimpleCollisionBox targetBox = reachEntity.getPossibleCollisionBoxes();
|
||||
|
||||
if (reachEntity.type == EntityTypes.END_CRYSTAL) { // Hardcode end crystal box
|
||||
targetBox = new SimpleCollisionBox(reachEntity.trackedServerPosition.getPos().subtract(1, 0, 1), reachEntity.trackedServerPosition.getPos().add(1, 2, 1));
|
||||
final double x = reachEntity.trackedServerPosition.getX();
|
||||
final double y = reachEntity.trackedServerPosition.getX();
|
||||
final double z = reachEntity.trackedServerPosition.getX();
|
||||
targetBox = new SimpleCollisionBox(x - 1, y, z - 1, x + 1, y + 2, z + 1);
|
||||
}
|
||||
|
||||
// 1.7 and 1.8 players get a bit of extra hitbox (this is why you should use 1.8 on cross version servers)
|
||||
@@ -197,20 +203,20 @@ public class Reach extends Check implements PacketCheck {
|
||||
double minDistance = Double.MAX_VALUE;
|
||||
|
||||
// https://bugs.mojang.com/browse/MC-67665
|
||||
List<Vector3dm> possibleLookDirs = new ArrayList<>(Collections.singletonList(ReachUtils.getLook(player, player.xRot, player.yRot)));
|
||||
List<Vector3dm> possibleLookDirs = new ArrayList<>(Collections.singletonList(ReachUtils.getLook(player, player.yaw, player.pitch)));
|
||||
|
||||
// If we are a tick behind, we don't know their next look so don't bother doing this
|
||||
if (!isPrediction) {
|
||||
possibleLookDirs.add(ReachUtils.getLook(player, player.lastXRot, player.yRot));
|
||||
possibleLookDirs.add(ReachUtils.getLook(player, player.lastYaw, player.pitch));
|
||||
|
||||
// 1.9+ players could be a tick behind because we don't get skipped ticks
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)) {
|
||||
possibleLookDirs.add(ReachUtils.getLook(player, player.lastXRot, player.lastYRot));
|
||||
possibleLookDirs.add(ReachUtils.getLook(player, player.lastYaw, player.lastPitch));
|
||||
}
|
||||
|
||||
// 1.7 players do not have any of these issues! They are always on the latest look vector
|
||||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_8)) {
|
||||
possibleLookDirs = Collections.singletonList(ReachUtils.getLook(player, player.xRot, player.yRot));
|
||||
possibleLookDirs = Collections.singletonList(ReachUtils.getLook(player, player.yaw, player.pitch));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,21 +224,27 @@ public class Reach extends Check implements PacketCheck {
|
||||
// +3 would be 3 + 3 = 6, which is the pre-1.20.5 behaviour, preventing "Missed Hitbox"
|
||||
final double distance = maxReach + 3;
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
final Vector3dm eyePos = new Vector3dm(from.getX(), 0, from.getZ());
|
||||
|
||||
final double eyePosX = from.getX();
|
||||
final double eyePosZ = from.getZ();
|
||||
|
||||
for (Vector3dm lookVec : possibleLookDirs) {
|
||||
for (double eye : possibleEyeHeights) {
|
||||
eyePos.setY(from.getY() + eye);
|
||||
Vector3dm endReachPos = eyePos.clone().add(new Vector3dm(lookVec.getX() * distance, lookVec.getY() * distance, lookVec.getZ() * distance));
|
||||
final double eyePosY = from.getY() + eye;
|
||||
|
||||
Vector3dm intercept = ReachUtils.calculateIntercept(targetBox, eyePos, endReachPos).first();
|
||||
final double endX = eyePosX + lookVec.getX() * distance;
|
||||
final double endY = eyePosY + lookVec.getY() * distance;
|
||||
final double endZ = eyePosZ + lookVec.getZ() * distance;
|
||||
|
||||
if (ReachUtils.isVecInside(targetBox, eyePos)) {
|
||||
Vector3dm intercept = ReachUtils.calculateIntercept(targetBox, eyePosX, eyePosY, eyePosZ, endX, endY, endZ).first();
|
||||
|
||||
if (ReachUtils.isVecInside(targetBox, eyePosX, eyePosY, eyePosZ)) {
|
||||
minDistance = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (intercept != null) {
|
||||
minDistance = Math.min(eyePos.distance(intercept), minDistance);
|
||||
minDistance = Math.min(intercept.distance(eyePosX, eyePosY, eyePosZ), minDistance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public class CrashH extends Check implements PacketCheck {
|
||||
String text = wrapper.getText();
|
||||
final int length = text.length();
|
||||
// general length limit
|
||||
if (length > 256) {
|
||||
if (length > (!player.canUseGameMasterBlocks() ? 256 : 32500)) {
|
||||
if (shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEntityAction;
|
||||
|
||||
@CheckData(name = "ElytraA", description = "Started gliding while already gliding", experimental = true)
|
||||
@CheckData(name = "ElytraA", description = "Started gliding while already gliding")
|
||||
public class ElytraA extends Check implements PostPredictionCheck {
|
||||
private boolean setback;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEntityAction;
|
||||
|
||||
@CheckData(name = "ElytraB", description = "Started gliding without jumping", experimental = true)
|
||||
@CheckData(name = "ElytraB", description = "Started gliding without jumping")
|
||||
public class ElytraB extends Check implements PostPredictionCheck {
|
||||
private boolean glide;
|
||||
private boolean setback;
|
||||
@@ -22,7 +22,7 @@ public class ElytraB extends Check implements PostPredictionCheck {
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.ENTITY_ACTION
|
||||
&& new WrapperPlayClientEntityAction(event).getAction() == WrapperPlayClientEntityAction.Action.START_FLYING_WITH_ELYTRA
|
||||
&& player.supportsEndTickPreVia()
|
||||
&& player.supportsEndTick()
|
||||
) {
|
||||
if (player.packetStateData.knownInput.jump()) {
|
||||
if (flagAndAlert("no release")) {
|
||||
|
||||
@@ -11,7 +11,7 @@ import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEntityAction;
|
||||
|
||||
@CheckData(name = "ElytraC", description = "Started gliding too frequently", experimental = true)
|
||||
@CheckData(name = "ElytraC", description = "Started gliding too frequently")
|
||||
public class ElytraC extends Check implements PostPredictionCheck {
|
||||
private boolean glideThisTick, glideLastTick, setback;
|
||||
private int flags;
|
||||
@@ -33,7 +33,7 @@ public class ElytraC extends Check implements PostPredictionCheck {
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Client.ENTITY_ACTION && new WrapperPlayClientEntityAction(event).getAction() == WrapperPlayClientEntityAction.Action.START_FLYING_WITH_ELYTRA && !exempt) {
|
||||
if (glideThisTick || glideLastTick) {
|
||||
if (player.canSkipTicksPreVia()) {
|
||||
if (player.canSkipTicks()) {
|
||||
flags++;
|
||||
} else {
|
||||
if (flagAndAlert()) {
|
||||
@@ -58,7 +58,7 @@ public class ElytraC extends Check implements PostPredictionCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (player.canSkipTicksPreVia()) {
|
||||
if (player.canSkipTicks()) {
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
for (; flags > 0; flags--) {
|
||||
flagAndAlert();
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEntityAction;
|
||||
|
||||
@CheckData(name = "ElytraF", description = "Started gliding while on ground", experimental = true)
|
||||
@CheckData(name = "ElytraF", description = "Started gliding while on ground")
|
||||
public class ElytraF extends Check implements PostPredictionCheck {
|
||||
private boolean setback;
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@ import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.payload.PayloadItemName;
|
||||
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.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientNameItem;
|
||||
@@ -24,7 +26,7 @@ public class ExploitA extends Check implements PacketCheck {
|
||||
check(new WrapperPlayClientNameItem(event).getItemName(), event);
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Client.PLUGIN_MESSAGE && player.getClientVersion().isOlderThan(ClientVersion.V_1_13)) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.PLUGIN_MESSAGE && PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_13)) {
|
||||
WrapperPlayClientPluginMessage wrapper = new WrapperPlayClientPluginMessage(event);
|
||||
if (wrapper.getChannelName().equals("MC|ItemName")) {
|
||||
check(PayloadItemName.CODEC.read(wrapper.getData()).itemName(), event);
|
||||
|
||||
@@ -5,7 +5,9 @@ import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.payload.PayloadBookEdit;
|
||||
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.component.ComponentTypes;
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||
@@ -35,6 +37,7 @@ import java.util.Set;
|
||||
|
||||
@CheckData(name = "ExploitB", description = "Invalid book edit")
|
||||
public class ExploitB extends Check implements PacketCheck {
|
||||
private static final boolean IS_1_8 = PacketEvents.getAPI().getServerManager().getVersion().isOlderThanOrEquals(ServerVersion.V_1_8_8);
|
||||
private ItemStack oldBook;
|
||||
private InteractionHand hand;
|
||||
|
||||
@@ -44,13 +47,11 @@ public class ExploitB extends Check implements PacketCheck {
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)
|
||||
? event.getPacketType() == PacketType.Play.Client.PLAYER_BLOCK_PLACEMENT
|
||||
if (IS_1_8 ? event.getPacketType() == PacketType.Play.Client.PLAYER_BLOCK_PLACEMENT
|
||||
&& new WrapperPlayClientPlayerBlockPlacement(event).getFaceId() == 255
|
||||
: event.getPacketType() == PacketType.Play.Client.USE_ITEM) {
|
||||
hand = player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)
|
||||
? InteractionHand.MAIN_HAND : new WrapperPlayClientUseItem(event).getHand();
|
||||
oldBook = player.getInventory().getItemInHand(hand).copy();
|
||||
hand = IS_1_8 ? InteractionHand.MAIN_HAND : new WrapperPlayClientUseItem(event).getHand();
|
||||
oldBook = player.inventory.getItemInHand(hand).copy();
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Client.EDIT_BOOK) {
|
||||
@@ -59,7 +60,7 @@ public class ExploitB extends Check implements PacketCheck {
|
||||
}
|
||||
|
||||
// 1.13-
|
||||
if (event.getPacketType() == PacketType.Play.Client.PLUGIN_MESSAGE && player.getClientVersion().isOlderThan(ClientVersion.V_1_13)) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.PLUGIN_MESSAGE && PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_13)) {
|
||||
WrapperPlayClientPluginMessage wrapper = new WrapperPlayClientPluginMessage(event);
|
||||
|
||||
boolean signing;
|
||||
@@ -106,8 +107,7 @@ public class ExploitB extends Check implements PacketCheck {
|
||||
private void checkItemStack(ItemStack newBook, boolean signing, PacketReceiveEvent event) {
|
||||
if (checkEditingBook(event)) return;
|
||||
|
||||
ItemType expectedType = signing && player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)
|
||||
? ItemTypes.WRITTEN_BOOK : ItemTypes.WRITABLE_BOOK;
|
||||
ItemType expectedType = signing && IS_1_8 ? ItemTypes.WRITTEN_BOOK : ItemTypes.WRITABLE_BOOK;
|
||||
if (!newBook.is(expectedType)) {
|
||||
if (flagAndAlert("expectedType=" + expectedType.getName().getKey() + ", type=" + newBook.getType().getName().getKey()) && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
@@ -176,7 +176,7 @@ public class ExploitB extends Check implements PacketCheck {
|
||||
|
||||
String last = null;
|
||||
for (NBTString string : newPagesNBT.getTags()) {
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8) && signing) {
|
||||
if (IS_1_8 && signing) {
|
||||
try {
|
||||
JsonReader reader = new JsonReader(new StringReader(string.getValue()));
|
||||
if (reader.peek() != JsonToken.BEGIN_OBJECT) throw new JsonSyntaxException("");
|
||||
@@ -238,7 +238,7 @@ public class ExploitB extends Check implements PacketCheck {
|
||||
player.onPacketCancel();
|
||||
}
|
||||
return true;
|
||||
} else if (title.isEmpty() || !title.trim().equals(title) || containsInvalidCharacters(title)) {
|
||||
} else if (title.isEmpty() || !title.trim().equals(title) || containsInvalidCharacters(title, false)) {
|
||||
if (flagAndAlert("invalid title '" + title + "'") && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -287,7 +287,7 @@ public class ExploitB extends Check implements PacketCheck {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (containsInvalidCharacters(page)) {
|
||||
if (containsInvalidCharacters(page, true)) {
|
||||
if (flagAndAlert("invalid page characters") && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -310,10 +310,10 @@ public class ExploitB extends Check implements PacketCheck {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean containsInvalidCharacters(@NotNull String string) {
|
||||
private static boolean containsInvalidCharacters(@NotNull String string, boolean allowLineBreak) {
|
||||
for (int i = 0; i < string.length(); ++i) {
|
||||
char character = string.charAt(i);
|
||||
if (character == 167 || character < 32 || character == 127) {
|
||||
if (character == 167 || character < 32 && (!allowLineBreak || character != 10) || character == 127) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,11 +35,10 @@ public class NoFall extends Check implements PacketCheck {
|
||||
if (player.getSetbackTeleportUtil().blockOffsets) return;
|
||||
|
||||
WrapperPlayClientPlayerFlying wrapper = new WrapperPlayClientPlayerFlying(event);
|
||||
boolean hasPosition = false;
|
||||
|
||||
// If the player claims to be on the ground
|
||||
// Run this code IFF the player doesn't send the position, as that won't get processed by predictions
|
||||
if (wrapper.isOnGround() && !hasPosition) {
|
||||
if (wrapper.isOnGround() && !wrapper.hasPositionChanged()) {
|
||||
if (!isNearGround(wrapper.isOnGround())) { // If player isn't near ground
|
||||
// 1.8 boats have a mind on their own... only flag if they're not near a boat or are on 1.9+
|
||||
if (!GhostBlockDetector.isGhostBlock(player)) flagAndAlertWithSetback();
|
||||
@@ -76,7 +75,7 @@ public class NoFall extends Check implements PacketCheck {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isNearGround(boolean onGround) {
|
||||
private boolean isNearGround(boolean onGround) {
|
||||
if (onGround) {
|
||||
SimpleCollisionBox feetBB = GetBoundingBox.getBoundingBoxFromPosAndSize(player, player.x, player.y, player.z, 0.6f, 0.001f);
|
||||
feetBB.expand(player.getMovementThreshold()); // Movement threshold can be in any direction
|
||||
|
||||
@@ -14,8 +14,8 @@ public class NoSlow extends Check implements PostPredictionCheck {
|
||||
// to another item that can be used. What the fuck mojang. Affects 1.8 (and most likely 1.7) clients.
|
||||
public boolean didSlotChangeLastTick = false;
|
||||
public boolean flaggedLastTick = false;
|
||||
double offsetToFlag;
|
||||
double bestOffset = 1;
|
||||
private double offsetToFlag;
|
||||
private double bestOffset = 1;
|
||||
|
||||
public NoSlow(GrimPlayer player) {
|
||||
super(player);
|
||||
|
||||
+3
-1
@@ -15,6 +15,8 @@ public class VehiclePredictionRunner extends Check implements VehicleCheck {
|
||||
public void process(final VehiclePositionUpdate vehicleUpdate) {
|
||||
// Vehicle onGround = false always
|
||||
// We don't do vehicle setbacks because vehicle netcode sucks.
|
||||
player.movementCheckRunner.processAndCheckMovementPacket(new PositionUpdate(vehicleUpdate.getFrom(), vehicleUpdate.getTo(), false, null, null, vehicleUpdate.isTeleport()));
|
||||
player.movementCheckRunner.processAndCheckMovementPacket(new PositionUpdate(
|
||||
vehicleUpdate.fromX(), vehicleUpdate.fromY(), vehicleUpdate.fromZ(), vehicleUpdate.toX(), vehicleUpdate.toY(), vehicleUpdate.toZ(),
|
||||
false, null, null, vehicleUpdate.isTeleport()));
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ public class MultiActionsA extends Check implements PacketCheck {
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (player.packetStateData.isSlowedByUsingItem() && (player.packetStateData.lastSlotSelected == player.packetStateData.getSlowedByUsingItemSlot() || player.packetStateData.eatingHand == InteractionHand.OFF_HAND) && event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY) {
|
||||
if (player.packetStateData.isSlowedByUsingItem() && (player.packetStateData.lastSlotSelected == player.packetStateData.getSlowedByUsingItemSlot() || player.packetStateData.itemInUseHand == InteractionHand.OFF_HAND) && event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY) {
|
||||
if (new WrapperPlayClientInteractEntity(event).getAction() == WrapperPlayClientInteractEntity.InteractAction.ATTACK) {
|
||||
if (flagAndAlert() && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
|
||||
@@ -16,7 +16,7 @@ public class MultiActionsB extends Check implements BlockBreakCheck {
|
||||
|
||||
@Override
|
||||
public void onBlockBreak(BlockBreak blockBreak) {
|
||||
if (player.packetStateData.isSlowedByUsingItem() && (player.packetStateData.lastSlotSelected == player.packetStateData.getSlowedByUsingItemSlot() || player.packetStateData.eatingHand == InteractionHand.OFF_HAND)) {
|
||||
if (player.packetStateData.isSlowedByUsingItem() && (player.packetStateData.lastSlotSelected == player.packetStateData.getSlowedByUsingItemSlot() || player.packetStateData.itemInUseHand == InteractionHand.OFF_HAND)) {
|
||||
// this is vanilla on 1.7
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_7_10)) {
|
||||
return;
|
||||
|
||||
@@ -12,12 +12,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.StringJoiner;
|
||||
|
||||
@CheckData(name = "MultiActionsC", description = "Clicked in inventory while moving", experimental = true)
|
||||
@CheckData(name = "MultiActionsC", description = "Clicked in inventory while moving")
|
||||
public class MultiActionsC extends Check implements PacketCheck {
|
||||
public MultiActionsC(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
// TODO: move this to a bett spot? not sure where to put this
|
||||
@Contract(pure = true)
|
||||
public static String getVerbose(@NotNull GrimPlayer player) {
|
||||
StringJoiner verbose = new StringJoiner(", ");
|
||||
@@ -29,7 +30,7 @@ public class MultiActionsC extends Check implements PacketCheck {
|
||||
verbose.add("sneaking");
|
||||
}
|
||||
|
||||
if (player.supportsEndTickPreVia() && player.packetStateData.knownInput.moving()) {
|
||||
if (player.supportsEndTick() && player.packetStateData.knownInput.moving()) {
|
||||
verbose.add("input");
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
|
||||
@CheckData(name = "MultiActionsD", description = "Closed inventory while moving", experimental = true)
|
||||
@CheckData(name = "MultiActionsD", description = "Closed inventory while moving")
|
||||
public class MultiActionsD extends Check implements PacketCheck {
|
||||
public MultiActionsD(GrimPlayer player) {
|
||||
super(player);
|
||||
|
||||
@@ -21,7 +21,7 @@ public class MultiActionsE extends Check implements PacketCheck {
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (!dropping && player.packetStateData.isSlowedByUsingItem() && (player.packetStateData.lastSlotSelected == player.packetStateData.getSlowedByUsingItemSlot() || player.packetStateData.eatingHand == InteractionHand.OFF_HAND) && event.getPacketType() == PacketType.Play.Client.ANIMATION) {
|
||||
if (!dropping && player.packetStateData.isSlowedByUsingItem() && (player.packetStateData.lastSlotSelected == player.packetStateData.getSlowedByUsingItemSlot() || player.packetStateData.itemInUseHand == InteractionHand.OFF_HAND) && event.getPacketType() == PacketType.Play.Client.ANIMATION) {
|
||||
// this is possible to false on 1.7
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_7_10)) {
|
||||
return;
|
||||
@@ -33,7 +33,7 @@ public class MultiActionsE extends Check implements PacketCheck {
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getPacketType() != PacketType.Play.Client.KEEP_ALIVE) {
|
||||
if (!isAsync(event.getPacketType())) {
|
||||
dropping = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.List;
|
||||
@CheckData(name = "MultiActionsF", description = "Interacting with a block and an entity in the same tick", experimental = true)
|
||||
public class MultiActionsF extends BlockPlaceCheck {
|
||||
private final List<String> flags = new ArrayList<>();
|
||||
boolean entity, block;
|
||||
private boolean entity, block;
|
||||
|
||||
public MultiActionsF(GrimPlayer player) {
|
||||
super(player);
|
||||
|
||||
@@ -25,7 +25,7 @@ public class PacketOrderA extends Check implements PostPredictionCheck {
|
||||
|
||||
if ((clickType == WindowClickType.PICKUP || clickType == WindowClickType.PICKUP_ALL) && player.packetOrderProcessor.isQuickMoveClicking()
|
||||
|| clickType == WindowClickType.QUICK_MOVE && player.packetOrderProcessor.isPickUpClicking()) {
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (flagAndAlert() && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -39,7 +39,7 @@ public class PacketOrderA extends Check implements PostPredictionCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (!player.canSkipTicksPreVia()) return;
|
||||
if (!player.canSkipTicks()) return;
|
||||
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
for (; invalid >= 1; invalid--) {
|
||||
|
||||
@@ -4,7 +4,9 @@ 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.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
|
||||
@@ -16,6 +18,18 @@ public class PacketOrderB extends Check implements PacketCheck {
|
||||
// I personally think 1.8 made much more sense. You swing and THEN you hit!
|
||||
private final boolean is1_9 = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9);
|
||||
|
||||
// There is a "bug" in ViaRewind
|
||||
// 1.8 packet order: ANIMATION -> INTERACT
|
||||
// 1.9 packet order: INTERACT -> ANIMATION
|
||||
// ViaRewind, on 1.9+ servers, delays a 1.8 client's ANIMATION to be after INTERACT (but before flying).
|
||||
// Which means we see 1.9 packet order for 1.8 clients
|
||||
// Due to ViaRewind also delaying the swings, we then see packet order above 20CPS like:
|
||||
// INTERACT -> INTERACT -> ANIMATION -> ANIMATION
|
||||
// I will simply disable this check for 1.8- clients on 1.9+ servers as I can't be bothered to find a way around this.
|
||||
// Stop supporting such old clients on modern servers!
|
||||
private final boolean exempt = player.getClientVersion().isOlderThan(ClientVersion.V_1_9)
|
||||
&& PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9);
|
||||
|
||||
private boolean sentAnimationSinceLastAttack = player.getClientVersion().isNewerThan(ClientVersion.V_1_8);
|
||||
private boolean sentAttack, sentAnimation, sentSlotSwitch;
|
||||
|
||||
@@ -25,6 +39,8 @@ public class PacketOrderB extends Check implements PacketCheck {
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (exempt) return;
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Client.ANIMATION) {
|
||||
sentAnimationSinceLastAttack = sentAnimation = true;
|
||||
sentAttack = sentSlotSwitch = false;
|
||||
@@ -54,7 +70,7 @@ public class PacketOrderB extends Check implements PacketCheck {
|
||||
return; // do not set sentAnimation to false
|
||||
}
|
||||
|
||||
if (event.getPacketType() != PacketType.Play.Client.KEEP_ALIVE) {
|
||||
if (!isAsync(event.getPacketType())) {
|
||||
if (sentAttack && is1_9) {
|
||||
flagAndAlert("post-attack");
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public class PacketOrderE extends Check implements PostPredictionCheck {
|
||||
+ ", sprinting=" + player.packetOrderProcessor.isSprinting()
|
||||
+ ", gliding=" + player.packetOrderProcessor.isStartingToGlide()
|
||||
+ ", mountJumping=" + player.packetOrderProcessor.isJumpingWithMount();
|
||||
if (player.canSkipTicksPreVia() && flags.add(verbose) || flagAndAlert(verbose)) {
|
||||
if (player.canSkipTicks() && flags.add(verbose) || flagAndAlert(verbose)) {
|
||||
if (player.packetOrderProcessor.isUsing()) {
|
||||
setback = true;
|
||||
}
|
||||
@@ -53,7 +53,7 @@ public class PacketOrderE extends Check implements PostPredictionCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (setback) {
|
||||
setback = false;
|
||||
setbackIfAboveSetbackVL();
|
||||
|
||||
@@ -39,7 +39,7 @@ public class PacketOrderF extends Check implements PostPredictionCheck {
|
||||
: "openInventory")
|
||||
+ ", sprinting=" + player.packetOrderProcessor.isSprinting()
|
||||
+ ", sneaking=" + player.packetOrderProcessor.isSneaking();
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (flagAndAlert(verbose) && shouldModifyPackets()) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.PLAYER_DIGGING
|
||||
&& new WrapperPlayClientPlayerDigging(event).getAction() == DiggingAction.RELEASE_USE_ITEM
|
||||
@@ -56,7 +56,7 @@ public class PacketOrderF extends Check implements PostPredictionCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (!player.canSkipTicksPreVia()) return;
|
||||
if (!player.canSkipTicks()) return;
|
||||
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
for (String verbose : flags) {
|
||||
|
||||
@@ -47,7 +47,7 @@ public class PacketOrderG extends Check implements PostPredictionCheck {
|
||||
+ ", rightClicking=" + player.packetOrderProcessor.isRightClicking()
|
||||
+ ", picking=" + player.packetOrderProcessor.isPicking()
|
||||
+ ", digging=" + player.packetOrderProcessor.isDigging();
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (flagAndAlert(verbose) && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -61,7 +61,7 @@ public class PacketOrderG extends Check implements PostPredictionCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (!player.canSkipTicksPreVia()) return;
|
||||
if (!player.canSkipTicks()) return;
|
||||
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
for (String verbose : flags) {
|
||||
|
||||
@@ -24,7 +24,7 @@ public class PacketOrderH extends Check implements PostPredictionCheck {
|
||||
switch (new WrapperPlayClientEntityAction(event).getAction()) {
|
||||
case START_SPRINTING, STOP_SPRINTING -> {
|
||||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_21_2) && player.packetOrderProcessor.isSneaking()) {
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
flagAndAlert();
|
||||
} else {
|
||||
invalid++;
|
||||
@@ -33,7 +33,7 @@ public class PacketOrderH extends Check implements PostPredictionCheck {
|
||||
}
|
||||
case START_SNEAKING, STOP_SNEAKING -> {
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21_2) && player.packetOrderProcessor.isSprinting()) {
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
flagAndAlert();
|
||||
} else {
|
||||
invalid++;
|
||||
@@ -46,7 +46,7 @@ public class PacketOrderH extends Check implements PostPredictionCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (!player.canSkipTicksPreVia()) return;
|
||||
if (!player.canSkipTicks()) return;
|
||||
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
for (; invalid >= 1; invalid--) {
|
||||
|
||||
@@ -37,7 +37,7 @@ public class PacketOrderI extends Check implements PostPredictionCheck {
|
||||
+ ", picking=" + player.packetOrderProcessor.isPicking()
|
||||
+ ", releasing=" + player.packetOrderProcessor.isReleasing()
|
||||
+ ", digging=" + player.packetOrderProcessor.isDigging();
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (flagAndAlert(verbose) && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -48,7 +48,7 @@ public class PacketOrderI extends Check implements PostPredictionCheck {
|
||||
}
|
||||
} else if (player.packetOrderProcessor.isReleasing() || player.packetOrderProcessor.isDigging()) {
|
||||
String verbose = "type=interact, releasing=" + player.packetOrderProcessor.isReleasing() + ", digging=" + player.packetOrderProcessor.isDigging();
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (flagAndAlert(verbose) && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -62,7 +62,7 @@ public class PacketOrderI extends Check implements PostPredictionCheck {
|
||||
if (event.getPacketType() == PacketType.Play.Client.PLAYER_BLOCK_PLACEMENT || event.getPacketType() == PacketType.Play.Client.USE_ITEM) {
|
||||
if (player.packetOrderProcessor.isReleasing() || digging) {
|
||||
String verbose = "type=place/use, releasing=" + player.packetOrderProcessor.isReleasing() + ", digging=" + digging;
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (flagAndAlert(verbose) && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -83,7 +83,7 @@ public class PacketOrderI extends Check implements PostPredictionCheck {
|
||||
+ ", rightClicking=" + player.packetOrderProcessor.isRightClicking()
|
||||
+ ", picking=" + player.packetOrderProcessor.isPicking()
|
||||
+ ", digging=" + player.packetOrderProcessor.isDigging();
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (flagAndAlert(verbose)) {
|
||||
setback = true;
|
||||
}
|
||||
@@ -113,7 +113,7 @@ public class PacketOrderI extends Check implements PostPredictionCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (setback) {
|
||||
setbackIfAboveSetbackVL();
|
||||
setback = false;
|
||||
|
||||
@@ -20,7 +20,7 @@ public class PacketOrderJ extends Check implements PostPredictionCheck {
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.PLAYER_BLOCK_PLACEMENT || event.getPacketType() == PacketType.Play.Client.USE_ITEM) {
|
||||
if (player.packetOrderProcessor.isAttacking() && !player.packetOrderProcessor.isInteracting()) {
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (flagAndAlert() && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -34,7 +34,7 @@ public class PacketOrderJ extends Check implements PostPredictionCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (!player.canSkipTicksPreVia()) return;
|
||||
if (!player.canSkipTicks()) return;
|
||||
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
for (; invalid >= 1; invalid--) {
|
||||
|
||||
@@ -25,7 +25,7 @@ public class PacketOrderK extends Check implements PostPredictionCheck {
|
||||
if (new WrapperPlayClientClientStatus(event).getAction() == WrapperPlayClientClientStatus.Action.OPEN_INVENTORY_ACHIEVEMENT) {
|
||||
if (player.packetOrderProcessor.isClickingInInventory() || player.packetOrderProcessor.isClosingInventory()) {
|
||||
String verbose = "open, clicking=" + player.packetOrderProcessor.isClickingInInventory() + ", closing=" + player.packetOrderProcessor.isClosingInventory();
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
flagAndAlert(verbose);
|
||||
} else {
|
||||
flags.add(verbose);
|
||||
@@ -37,7 +37,7 @@ public class PacketOrderK extends Check implements PostPredictionCheck {
|
||||
if (event.getPacketType() == PacketType.Play.Client.CLICK_WINDOW || event.getPacketType() == PacketType.Play.Client.CLOSE_WINDOW) {
|
||||
if (player.packetOrderProcessor.isOpeningInventory()) {
|
||||
String verbose = event.getPacketType() == PacketType.Play.Client.CLICK_WINDOW ? "click" : "close";
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (flagAndAlert(verbose) && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -51,7 +51,7 @@ public class PacketOrderK extends Check implements PostPredictionCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (!player.canSkipTicksPreVia()) return;
|
||||
if (!player.canSkipTicks()) return;
|
||||
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
for (String verbose : flags) {
|
||||
|
||||
@@ -26,7 +26,7 @@ public class PacketOrderL extends Check implements PostPredictionCheck {
|
||||
if (event.getPacketType() == PacketType.Play.Client.CLIENT_STATUS) {
|
||||
if (new WrapperPlayClientClientStatus(event).getAction() == WrapperPlayClientClientStatus.Action.OPEN_INVENTORY_ACHIEVEMENT) {
|
||||
if (player.packetOrderProcessor.isDropping()) {
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (flagAndAlert("inventory") && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -41,7 +41,7 @@ public class PacketOrderL extends Check implements PostPredictionCheck {
|
||||
if (event.getPacketType() == PacketType.Play.Client.PLAYER_DIGGING) {
|
||||
if (new WrapperPlayClientPlayerDigging(event).getAction() == DiggingAction.SWAP_ITEM_WITH_OFFHAND) {
|
||||
if (player.packetOrderProcessor.isDropping()) {
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (flagAndAlert("swap") && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -56,7 +56,7 @@ public class PacketOrderL extends Check implements PostPredictionCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (!player.canSkipTicksPreVia()) return;
|
||||
if (!player.canSkipTicks()) return;
|
||||
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
for (String verbose : flags) {
|
||||
|
||||
@@ -27,7 +27,7 @@ public class PacketOrderM extends Check implements PostPredictionCheck {
|
||||
if (new WrapperPlayClientInteractEntity(event).getAction() != WrapperPlayClientInteractEntity.InteractAction.ATTACK) {
|
||||
interacting = true;
|
||||
if (usingWithoutInteract) {
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (flagAndAlert() && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -56,7 +56,7 @@ public class PacketOrderM extends Check implements PostPredictionCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (!player.canSkipTicksPreVia()) return;
|
||||
if (!player.canSkipTicks()) return;
|
||||
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
for (; invalid >= 1; invalid--) {
|
||||
|
||||
@@ -24,7 +24,7 @@ public class PacketOrderN extends BlockPlaceCheck {
|
||||
public void onBlockPlace(BlockPlace place) {
|
||||
placing = true;
|
||||
if (usingWithoutPlacing) {
|
||||
if (!player.canSkipTicksPreVia()) {
|
||||
if (!player.canSkipTicks()) {
|
||||
if (flagAndAlert() && shouldModifyPackets() && shouldCancel()) {
|
||||
place.resync();
|
||||
}
|
||||
@@ -53,7 +53,7 @@ public class PacketOrderN extends BlockPlaceCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (!player.canSkipTicksPreVia()) return;
|
||||
if (!player.canSkipTicks()) return;
|
||||
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
for (; invalid >= 1; invalid--) {
|
||||
|
||||
Loaded 100 of 377 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user