Compare commits
31
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4933fd9d4f | ||
|
|
c2c044f61b | ||
|
|
2d785fdc2c | ||
|
|
403fd36830 | ||
|
|
e386b936ff | ||
|
|
3fc985c8f3 | ||
|
|
499bf7e2f9 | ||
|
|
ba91251307 | ||
|
|
8ddd7f18a5 | ||
|
|
3f67272721 | ||
|
|
3380d7f9fd | ||
|
|
e1bd2edc7c | ||
|
|
9b500a2617 | ||
|
|
6df484bcc6 | ||
|
|
a46d29620f | ||
|
|
b14628c578 | ||
|
|
5c715315c9 | ||
|
|
ba1d1dbc16 | ||
|
|
def21633e2 | ||
|
|
918e6575e8 | ||
|
|
ea1f1615b6 | ||
|
|
c323cf06ce | ||
|
|
0ba331780e | ||
|
|
fc47c5b663 | ||
|
|
17cf067d58 | ||
|
|
6280b28e16 | ||
|
|
bfd2bd0e22 | ||
|
|
0df77dd32a | ||
|
|
b373e5f1c4 | ||
|
|
115c32916f | ||
|
|
5f8692deda |
No files matched your search
@@ -17,3 +17,6 @@ ij_formatter_on_tag = @formatter:on
|
||||
ij_formatter_tags_enabled = false
|
||||
ij_smart_tabs = false
|
||||
ij_wrap_on_typing = false
|
||||
|
||||
[.github/ISSUE_TEMPLATE/*.yml]
|
||||
indent_size = 2
|
||||
@@ -5,7 +5,7 @@ body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the bypass and how to replicate it
|
||||
description: Provide a video, or detailed instructions to help replicate it.
|
||||
description: Provide a video or detailed instructions to help replicate it.
|
||||
placeholder: |
|
||||
Step 1. Do this
|
||||
Step 2. Then do this
|
||||
@@ -17,8 +17,8 @@ body:
|
||||
attributes:
|
||||
label: Grim version
|
||||
description: |
|
||||
Provide the git commit or the version in the jar's name.
|
||||
placeholder: A example would be b85c2d0 or grim version 2.3.5, etc
|
||||
Provide the version of Grim running on the server. You can run `/grim version` to check.
|
||||
placeholder: Examples include 2.3.73-8ddd7f1, 2.3.72, etc.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -26,23 +26,23 @@ body:
|
||||
attributes:
|
||||
label: Server version
|
||||
description: |
|
||||
Run `/version` on your server to check. Provide both the server type (paper, airplane, etc) & the minecraft version.
|
||||
Run `/version` on your server to check. Provide both the server type (ie Paper, Airplane, etc) & the Minecraft version.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Client version
|
||||
description: |
|
||||
Provide the version of your Minecraft client.
|
||||
label: Client version
|
||||
description: |
|
||||
Provide the version of your Minecraft client. Also provide the protocol version if changed.
|
||||
validations:
|
||||
required: true
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Plugins
|
||||
label: Plugins/Mods
|
||||
description: |
|
||||
List all plugins or mods running on your server. To list plugins on bukkit, run `/plugins`.
|
||||
List all plugins or mods installed on your server. To list plugins on Bukkit-based servers, run `/plugins`.
|
||||
If your server is behind a proxy such as Bungeecord, you should list the proxy's plugins as well.
|
||||
validations:
|
||||
required: true
|
||||
@@ -6,7 +6,7 @@ body:
|
||||
attributes:
|
||||
label: Stack trace
|
||||
description: |
|
||||
Please include the entire stack trace with no attachments. If you would like, you can use a text pasting site such as https://paste.gg.
|
||||
Provide the entire stack trace with no attachments. If you would like, you can use a text pasting site such as https://mclo.gs.
|
||||
placeholder: Paste the stack trace or link to the stack trace here
|
||||
validations:
|
||||
required: true
|
||||
@@ -14,7 +14,7 @@ body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: How to replicate it if known
|
||||
description: A video, or detailed instructions to help replicate the issue would help.
|
||||
description: A video or detailed instructions to help replicate the issue would help.
|
||||
placeholder: |
|
||||
Step 1. Do this
|
||||
Step 2. Then do this
|
||||
@@ -26,8 +26,8 @@ body:
|
||||
attributes:
|
||||
label: Grim version
|
||||
description: |
|
||||
Provide the git commit or the version in the jar's name.
|
||||
placeholder: A example would be b85c2d0 or grim version 2.3.5, etc
|
||||
Provide the version of Grim running on the server. You can run `/grim version` to check.
|
||||
placeholder: Examples include 2.3.73-8ddd7f1, 2.3.72, etc.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -35,27 +35,27 @@ body:
|
||||
attributes:
|
||||
label: Server version
|
||||
description: |
|
||||
Run `/version` on your server to check. Provide both the server type (paper, airplane, etc) & the minecraft version.
|
||||
Run `/version` on your server to check. Provide both the server type (ie Paper, Airplane, etc) & the Minecraft version.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: type
|
||||
attributes:
|
||||
label: Affected Platform(s)
|
||||
description: Which platforms does this issue affect? If you aren't sure, select both.
|
||||
options:
|
||||
- "Bukkit"
|
||||
- "Fabric"
|
||||
multiple: true
|
||||
label: Affected Platform(s)
|
||||
description: Which platforms does this issue affect? If you aren't sure, select both.
|
||||
options:
|
||||
- "Bukkit"
|
||||
- "Fabric"
|
||||
multiple: true
|
||||
validations:
|
||||
required: true
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Plugins/mods
|
||||
label: Plugins/Mods
|
||||
description: |
|
||||
List all plugins or mods running on your server. To list plugins on bukkit, run `/plugins`.
|
||||
List all plugins or mods installed on your server. To list plugins on Bukkit-based servers, run `/plugins`.
|
||||
If your server is behind a proxy such as Bungeecord, you should list the proxy's plugins as well.
|
||||
validations:
|
||||
required: true
|
||||
@@ -20,8 +20,8 @@ body:
|
||||
attributes:
|
||||
label: Grim version
|
||||
description: |
|
||||
Provide the git commit or the version in the jar's name.
|
||||
placeholder: A example would be b85c2d0 or grim version 2.3.5, etc
|
||||
Provide the version of Grim running on the server. You can run `/grim version` to check.
|
||||
placeholder: Examples include 2.3.73-8ddd7f1, 2.3.72, etc.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -29,7 +29,7 @@ body:
|
||||
attributes:
|
||||
label: Server version
|
||||
description: |
|
||||
Run `/version` on your server to check. Provide both the server type (paper, airplane, etc) & the minecraft version.
|
||||
Run `/version` on your server to check. Provide both the server type (ie Paper, Airplane, etc) & the Minecraft version.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -37,16 +37,16 @@ body:
|
||||
attributes:
|
||||
label: Client version
|
||||
description: |
|
||||
Provide the version of your Minecraft client. You must be able to reproduce the false positive using the vanilla client.
|
||||
Lunar Client, TLauncher etc. will result in your issue being closed.
|
||||
Provide the version of your Minecraft client. You must be able to reproduce the false positive using a vanilla client.
|
||||
Using Lunar Client, TLauncher, Fabric, etc, will result in your issue being closed.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Plugins
|
||||
label: Plugins/Mods
|
||||
description: |
|
||||
List all plugins or mods running on your server. To list plugins on bukkit, run `/plugins`.
|
||||
List all plugins or mods installed on your server. To list plugins on Bukkit-based servers, run `/plugins`.
|
||||
If your server is behind a proxy such as Bungeecord, you should list the proxy's plugins as well.
|
||||
validations:
|
||||
required: true
|
||||
@@ -5,6 +5,6 @@ body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Feature description
|
||||
description: Describe the feature and why it should be added
|
||||
description: Describe the feature and why it should be added.
|
||||
validations:
|
||||
required: true
|
||||
required: true
|
||||
@@ -5,7 +5,7 @@ body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the bug and how to replicate it
|
||||
description: A video, or detailed instructions to help replicate the issue would help.
|
||||
description: A video or detailed instructions to help replicate the issue would help.
|
||||
placeholder: |
|
||||
Step 1. Do this
|
||||
Step 2. Then do this
|
||||
@@ -16,9 +16,8 @@ body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Grim version
|
||||
description: |
|
||||
Provide the git commit or the version in the jar's name.
|
||||
placeholder: A example would be b85c2d0 or grim version 2.3.5, etc
|
||||
description: Provide the version of Grim running on the server. You can run `/grim version` to check.
|
||||
placeholder: Examples include 2.3.73-8ddd7f1, 2.3.72, etc.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -26,27 +25,27 @@ body:
|
||||
attributes:
|
||||
label: Server version
|
||||
description: |
|
||||
Run `/version` on your server to check. Provide both the server type (paper, airplane, etc) & the minecraft version.
|
||||
Run `/version` on your server to check. Provide both the server type (ie Paper, Airplane, etc) & the Minecraft version.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: type
|
||||
attributes:
|
||||
label: Affected Platform(s)
|
||||
description: Which platforms does this issue affect? If you aren't sure, select both.
|
||||
options:
|
||||
- "Bukkit"
|
||||
- "Fabric"
|
||||
multiple: true
|
||||
label: Affected Platform(s)
|
||||
description: Which platforms does this issue affect? If you aren't sure, select both.
|
||||
options:
|
||||
- "Bukkit"
|
||||
- "Fabric"
|
||||
multiple: true
|
||||
validations:
|
||||
required: true
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Plugins
|
||||
label: Plugins/Mods
|
||||
description: |
|
||||
List all plugins or mods running on your server. To list plugins on bukkit, run `/plugins`.
|
||||
List all plugins or mods installed on your server. To list plugins on Bukkit-based servers, run `/plugins`.
|
||||
If your server is behind a proxy such as Bungeecord, you should list the proxy's plugins as well.
|
||||
validations:
|
||||
required: true
|
||||
@@ -19,8 +19,15 @@ body:
|
||||
- type: input
|
||||
attributes:
|
||||
label: Grim Log
|
||||
description: |
|
||||
Provide the generated /grim log link.
|
||||
description: Provide the generated /grim log link.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Grim version
|
||||
description: Provide the version of Grim running on the server. You can run `/grim version` to check.
|
||||
placeholder: Examples include 2.3.73-8ddd7f1, 2.3.72, etc.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -28,7 +35,7 @@ body:
|
||||
attributes:
|
||||
label: Server version
|
||||
description: |
|
||||
Run `/version` on your server to check. Provide both the server type (paper, airplane, etc) & the minecraft version.
|
||||
Run `/version` on your server to check. Provide both the server type (ie Paper, Airplane, etc) & the Minecraft version.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -36,16 +43,16 @@ body:
|
||||
attributes:
|
||||
label: Client version
|
||||
description: |
|
||||
Provide the version of your Minecraft client. You must be able to reproduce the false positive using the vanilla client.
|
||||
Lunar Client, TLauncher etc. will result in your issue being closed.
|
||||
Provide the version of your Minecraft client. You must be able to reproduce the false positive using a vanilla client.
|
||||
Using Lunar Client, TLauncher, Fabric, etc, will result in your issue being closed.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Plugins
|
||||
label: Plugins/Mods
|
||||
description: |
|
||||
List all plugins or mods running on your server. To list plugins on bukkit, run `/plugins`.
|
||||
List all plugins or mods installed on your server. To list plugins on Bukkit-based servers, run `/plugins`.
|
||||
If your server is behind a proxy such as Bungeecord, you should list the proxy's plugins as well.
|
||||
validations:
|
||||
required: true
|
||||
required: true
|
||||
@@ -36,7 +36,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: tenki-standard-autoscale
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
@@ -85,7 +85,7 @@ jobs:
|
||||
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"
|
||||
@@ -94,23 +94,23 @@ jobs:
|
||||
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
|
||||
# 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
|
||||
@@ -151,7 +151,7 @@ jobs:
|
||||
|
||||
- name: Prepare Final Changelog
|
||||
id: changelog
|
||||
# Add this 'env' block to safely load the changelogs as environment variables
|
||||
# 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 }}
|
||||
@@ -165,17 +165,36 @@ jobs:
|
||||
# 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"
|
||||
|
||||
- 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.21.5 <=1.21.10'
|
||||
dependencies: 'fabric-api'
|
||||
|
||||
#------------------------------------------------------------------
|
||||
# Publish to Modrinth & API
|
||||
#------------------------------------------------------------------
|
||||
@@ -183,7 +202,7 @@ jobs:
|
||||
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-id: ${{ secrets.MODRINTH_ID }}
|
||||
modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
|
||||
modrinth-featured: ${{ inputs.is-release-build }} # Only feature release builds
|
||||
|
||||
@@ -198,25 +217,7 @@ jobs:
|
||||
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'
|
||||
game-versions: '>=1.7 <=1.21.10'
|
||||
|
||||
- name: Publish to API
|
||||
if: ${{ inputs.publish-artifacts == true && env.BUILD_UPDATE_TOKEN != '' }}
|
||||
@@ -226,4 +227,4 @@ jobs:
|
||||
-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 }}"
|
||||
"${{ secrets.BUILD_UPDATE_URL }}"
|
||||
@@ -14,12 +14,12 @@ name: "CodeQL"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ dev ]
|
||||
branches: [dev]
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: tenki-standard-autoscale
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'java-kotlin' ]
|
||||
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
|
||||
@@ -60,6 +60,7 @@ jobs:
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
@@ -70,6 +71,5 @@ jobs:
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v3
|
||||
@@ -20,8 +20,6 @@ on:
|
||||
- 'release'
|
||||
- 'release/**'
|
||||
paths:
|
||||
- '.github/workflows/**'
|
||||
- 'buildSrc/**'
|
||||
- 'bukkit/**'
|
||||
- 'common/**'
|
||||
- 'fabric/**'
|
||||
|
||||
@@ -33,30 +33,27 @@ A premium version is planned, which will offer additional subscription-based pai
|
||||
- ~~[Hangar](https://hangar.papermc.io/GrimAnticheat/GrimAnticheat)~~
|
||||
- ~~[SpigotMC](https://www.spigotmc.org/resources/grim-anticheat.99923/)~~
|
||||
|
||||
## Requirements & Installation
|
||||
|
||||
- Java 17 or higher. *For more details, see [Updating-to-Java-17](https://github.com/GrimAnticheat/Grim/wiki/Updating-to-Java-17).*
|
||||
- A Spigot, Paper, Folia, or Fabric server environment. *For more details, see [Supported-environments](https://github.com/GrimAnticheat/Grim/wiki/Supported-environments).*
|
||||
|
||||
If you use a proxy such as Velocity or Bungeecord:
|
||||
- If you use Geyser, Floodgate must be installed on the backend server (where Grim is) so Grim can access the Floodgate API.
|
||||
- If you use ViaVersion, it must be installed on the backend server (where Grim is) ONLY.
|
||||
Grim does not support having ViaVersion installed on the proxy, even if it is also installed on the backend.
|
||||
|
||||
## Resources
|
||||
|
||||
- For documentation and examples visit the [Wiki](https://github.com/GrimAnticheat/Grim/wiki).
|
||||
- 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
|
||||
see [Updating-to-Java-17](https://github.com/GrimAnticheat/Grim/wiki/Updating-to-Java-17).*
|
||||
- A Spigot, Paper, Folia, or Fabric server environment. *For more details
|
||||
see [Supported-environments](https://github.com/GrimAnticheat/Grim/wiki/Supported-environments).*
|
||||
- If you use Geyser, place Floodgate on the backend server so grim can exempt bedrock players. Grim
|
||||
cannot access the Floodgate API if it is on the proxy.
|
||||
- If you use ViaVersion, it should be on the backend server as movement is highly dependent on
|
||||
client version.
|
||||
|
||||
## Developer Plugin API
|
||||
|
||||
Grim's plugin API allows you to integrate Grim into your own plugins. Visit
|
||||
|
||||
@@ -195,7 +195,7 @@ publishing.publications.create<MavenPublication>("maven") {
|
||||
|
||||
tasks {
|
||||
runServer {
|
||||
minecraftVersion("1.21.4")
|
||||
minecraftVersion("1.21.10")
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
|
||||
@@ -74,7 +74,7 @@ public class PistonEvent implements Listener {
|
||||
final Vector3i sourcePos = new Vector3i(piston.getX(), piston.getY(), piston.getZ());
|
||||
|
||||
for (GrimPlayer player : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
|
||||
if (player.compensatedWorld.isChunkLoaded(chunkX, chunkZ) && isCloseEnough(sourcePos, player.compensatedEntities.self.trackedServerPosition.getPos())) {
|
||||
if (isCloseEnough(sourcePos, player.compensatedEntities.self.trackedServerPosition.getPos()) && player.compensatedWorld.isChunkLoaded(chunkX, chunkZ)) {
|
||||
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));
|
||||
@@ -132,7 +132,7 @@ public class PistonEvent implements Listener {
|
||||
Vector3i sourcePos = new Vector3i(event.getBlock().getX(), event.getBlock().getY(), event.getBlock().getZ());
|
||||
|
||||
for (GrimPlayer player : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
|
||||
if (player.compensatedWorld.isChunkLoaded(chunkX, chunkZ) && isCloseEnough(sourcePos, player.compensatedEntities.self.trackedServerPosition.getPos())) {
|
||||
if (isCloseEnough(sourcePos, player.compensatedEntities.self.trackedServerPosition.getPos()) && player.compensatedWorld.isChunkLoaded(chunkX, chunkZ)) {
|
||||
int lastTrans = player.lastTransactionSent.get();
|
||||
PistonData data = new PistonData(face, boxes, lastTrans, false, hasSlimeBlock, hasHoneyBlock);
|
||||
player.latencyUtils.addRealTimeTaskAsync(lastTrans, () -> player.compensatedWorld.activePistons.add(data));
|
||||
|
||||
@@ -96,7 +96,7 @@ public class Check extends GrimProcessor implements AbstractCheck {
|
||||
if (event.isCancelled()) return false;
|
||||
|
||||
player.punishmentManager.handleViolation(this);
|
||||
lastViolationTime = System.currentTimeMillis();
|
||||
lastViolationTime = player.now();
|
||||
violations++;
|
||||
return true;
|
||||
}
|
||||
@@ -170,7 +170,8 @@ public class Check extends GrimProcessor implements AbstractCheck {
|
||||
}
|
||||
|
||||
public static boolean isAsync(PacketTypeCommon packetType) {
|
||||
return packetType == PacketType.Play.Client.KEEP_ALIVE;
|
||||
return packetType == PacketType.Play.Client.KEEP_ALIVE
|
||||
|| packetType == PacketType.Play.Client.CHUNK_BATCH_ACK;
|
||||
}
|
||||
|
||||
public boolean isUpdate(PacketTypeCommon packetType) {
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package ac.grim.grimac.checks.debug;
|
||||
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DebugGrimPlayer extends GrimPlayer {
|
||||
|
||||
private static final long THRESHOLD_NANO = 200_000_000L; // 200ms
|
||||
private static final long THRESHOLD_MILLIS = 200;
|
||||
|
||||
// Global Offsets: Volatile so all threads see the pause adjustment immediately.
|
||||
// When the Netty thread pauses for 60s, it updates this.
|
||||
// The Scheduler thread sees the update and "stops" the timeout check.
|
||||
private volatile long offsetNano = 0;
|
||||
private volatile long offsetMillis = 0;
|
||||
|
||||
// ThreadLocal: Each thread tracks its OWN execution time.
|
||||
// This prevents the Scheduler Thread (pollData) from resetting the timer
|
||||
// while the Netty Thread is sitting at a breakpoint.
|
||||
private final ThreadLocal<Long> packetStartNano = ThreadLocal.withInitial(System::nanoTime);
|
||||
private final ThreadLocal<Long> packetStartMillis = ThreadLocal.withInitial(System::currentTimeMillis);
|
||||
|
||||
public DebugGrimPlayer(@NotNull User user) {
|
||||
super(user, System.currentTimeMillis(), System.nanoTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processingPacket() {
|
||||
// Reset the timer ONLY for the current thread (Netty or Scheduler)
|
||||
this.packetStartNano.set(System.nanoTime());
|
||||
this.packetStartMillis.set(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long nano() {
|
||||
// SAFETY CHECK:
|
||||
// If something in the parent constructor calls nano() BEFORE we are fully initialized,
|
||||
// packetStartNano will be null. We must fallback to System time to prevent NPE.
|
||||
if (packetStartNano == null) return System.nanoTime();
|
||||
|
||||
long sysTime = System.nanoTime();
|
||||
|
||||
// 1. Get start time for THIS thread
|
||||
long start = packetStartNano.get();
|
||||
long executionTime = sysTime - start;
|
||||
|
||||
// 2. Check if THIS thread was paused/stuck
|
||||
if (executionTime > THRESHOLD_NANO) {
|
||||
// Update the global offset so ALL threads know to skip this time
|
||||
synchronized (this) {
|
||||
offsetNano += executionTime;
|
||||
}
|
||||
// Reset this thread's timer so we don't loop
|
||||
packetStartNano.set(sysTime);
|
||||
} else if (executionTime < 0) {
|
||||
// Self-healing for rare thread-local init edge cases or system clock jumps
|
||||
packetStartNano.set(sysTime);
|
||||
}
|
||||
|
||||
// 3. Return System Time minus the Global Pause Offset
|
||||
return sysTime - offsetNano;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long now() {
|
||||
if (packetStartMillis == null) return System.currentTimeMillis();
|
||||
|
||||
long sysTime = System.currentTimeMillis();
|
||||
long start = packetStartMillis.get();
|
||||
long executionTime = sysTime - start;
|
||||
|
||||
if (executionTime > THRESHOLD_MILLIS) {
|
||||
synchronized (this) {
|
||||
offsetMillis += executionTime;
|
||||
}
|
||||
packetStartMillis.set(sysTime);
|
||||
}
|
||||
|
||||
return sysTime - offsetMillis;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package ac.grim.grimac.checks.debug;
|
||||
|
||||
import ac.grim.grimac.utils.common.arguments.CommonGrimArguments;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
|
||||
public class GrimDebugSettings {
|
||||
|
||||
public static boolean shouldEnable() {
|
||||
// 1. If the argument is disabled, never enable debug mode.
|
||||
if (!CommonGrimArguments.DEBUG_BREAKPOINT_MODE.value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. Check for Debugger (Startup Agent OR Dynamic Attach)
|
||||
return isDebuggerAttached();
|
||||
}
|
||||
|
||||
private static boolean isDebuggerAttached() {
|
||||
// Fast Path: Check startup arguments for -agentlib:jdwp
|
||||
if (ManagementFactory.getRuntimeMXBean().getInputArguments().toString().contains("jdwp")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Slow Path (Dynamic Attach): Scan threads for JDWP/Signal Dispatcher
|
||||
try {
|
||||
for (Thread t : Thread.getAllStackTraces().keySet()) {
|
||||
String name = t.getName();
|
||||
if (name.contains("JDWP")) return true;
|
||||
}
|
||||
} catch (Throwable ignored) {}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ public class BadPacketsR extends Check implements PacketCheck {
|
||||
public void onPacketReceive(final PacketReceiveEvent event) {
|
||||
if (isTransaction(event.getPacketType()) && player.packetStateData.lastTransactionPacketWasValid) {
|
||||
long ms = (player.getPlayerClockAtLeast() - clock) / 1000000L;
|
||||
long diff = (System.currentTimeMillis() - lastTransTime);
|
||||
long diff = (player.now() - lastTransTime);
|
||||
if (diff > 2000 && ms > 2000) {
|
||||
if (positions == 0 && clock != 0 && player.gamemode != GameMode.SPECTATOR && !player.compensatedEntities.self.isDead) {
|
||||
flag("time=" + ms + "ms, " + "lst=" + diff + "ms, positions=" + positions);
|
||||
@@ -34,7 +34,7 @@ public class BadPacketsR extends Check implements PacketCheck {
|
||||
player.compensatedWorld.removeInvalidPistonLikeStuff(oldTransId);
|
||||
positions = 0;
|
||||
clock = player.getPlayerClockAtLeast();
|
||||
lastTransTime = System.currentTimeMillis();
|
||||
lastTransTime = player.now();
|
||||
oldTransId = player.lastTransactionSent.get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.update.BlockBreak;
|
||||
import ac.grim.grimac.utils.math.GrimMath;
|
||||
import ac.grim.grimac.utils.nmsutil.BlockBreakSpeed;
|
||||
import ac.grim.grimac.utils.reflection.ViaVersionUtil;
|
||||
import ac.grim.grimac.utils.viaversion.ViaVersionUtil;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
@@ -67,12 +67,12 @@ 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); // ???
|
||||
startBreak = player.now() - (targetBlockPosition == null ? 50 : 0); // ???
|
||||
targetBlockPosition = blockBreak.position;
|
||||
|
||||
maximumBlockDamage = BlockBreakSpeed.getBlockDamage(player, block);
|
||||
|
||||
double breakDelay = System.currentTimeMillis() - lastFinishBreak;
|
||||
double breakDelay = player.now() - lastFinishBreak;
|
||||
|
||||
if (breakDelay >= 275) { // Reduce buffer if "close enough"
|
||||
blockDelayBalance *= 0.9;
|
||||
@@ -91,7 +91,7 @@ public class FastBreak extends Check implements BlockBreakCheck {
|
||||
|
||||
if (blockBreak.action == DiggingAction.FINISHED_DIGGING && targetBlockPosition != null) {
|
||||
double predictedTime = Math.ceil(1 / maximumBlockDamage) * 50;
|
||||
double realTime = System.currentTimeMillis() - startBreak;
|
||||
double realTime = player.now() - startBreak;
|
||||
double diff = predictedTime - realTime;
|
||||
|
||||
clampBalance();
|
||||
@@ -109,7 +109,7 @@ public class FastBreak extends Check implements BlockBreakCheck {
|
||||
}
|
||||
|
||||
// also set start time because the breaking netcode is fucked on 1.14.4+
|
||||
lastFinishBreak = startBreak = System.currentTimeMillis();
|
||||
lastFinishBreak = startBreak = player.now();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ 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;
|
||||
@@ -63,10 +61,4 @@ public class ChatB extends Check implements PacketCheck {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static {
|
||||
if (ViaVersionUtil.isAvailable && PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_11)) {
|
||||
ViaHooks.injectVia();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntity;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntitySizeable;
|
||||
import ac.grim.grimac.utils.data.packetentity.dragon.PacketEntityEnderDragonPart;
|
||||
import ac.grim.grimac.utils.math.Vector3dm;
|
||||
import ac.grim.grimac.utils.nmsutil.ReachUtils;
|
||||
@@ -94,7 +95,10 @@ public class Reach extends Check implements PacketCheck {
|
||||
// TODO: Remove when in front of via
|
||||
if (entity.type == EntityTypes.ARMOR_STAND && player.getClientVersion().isOlderThan(ClientVersion.V_1_8))
|
||||
return;
|
||||
|
||||
//Prevents Happy Ghast Reach false on 1.21.6+ servers with ViaBackwards set up
|
||||
if (entity.type == EntityTypes.HAPPY_GHAST && player.getClientVersion().isOlderThan(ClientVersion.V_1_21_6)) {
|
||||
return;
|
||||
}
|
||||
if (player.gamemode == GameMode.CREATIVE || player.gamemode == GameMode.SPECTATOR)
|
||||
return;
|
||||
if (player.inVehicle()) return;
|
||||
@@ -158,10 +162,16 @@ public class Reach extends Check implements PacketCheck {
|
||||
switch (result.type()) {
|
||||
case REACH -> {
|
||||
String added = ", type=" + reachEntity.type.getName().getKey();
|
||||
if (reachEntity instanceof PacketEntitySizeable sizeable) {
|
||||
added += ", size=" + sizeable.size;
|
||||
}
|
||||
flagAndAlert(result.verbose() + added);
|
||||
}
|
||||
case HITBOX -> {
|
||||
String added = "type=" + reachEntity.type.getName().getKey();
|
||||
if (reachEntity instanceof PacketEntitySizeable sizeable) {
|
||||
added += ", size=" + sizeable.size;
|
||||
}
|
||||
player.checkManager.getCheck(Hitboxes.class).flagAndAlert(result.verbose() + added);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,9 @@ public class CrashC extends Check implements PacketCheck {
|
||||
WrapperPlayClientPlayerFlying flying = new WrapperPlayClientPlayerFlying(event);
|
||||
if (flying.hasPositionChanged()) {
|
||||
Location pos = flying.getLocation();
|
||||
if (Double.isNaN(pos.getX()) || Double.isNaN(pos.getY()) || Double.isNaN(pos.getZ())
|
||||
|| Double.isInfinite(pos.getX()) || Double.isInfinite(pos.getY()) || Double.isInfinite(pos.getZ()) ||
|
||||
Float.isNaN(pos.getYaw()) || Float.isNaN(pos.getPitch()) ||
|
||||
Float.isInfinite(pos.getYaw()) || Float.isInfinite(pos.getPitch())) {
|
||||
if (!Double.isFinite(pos.getX()) || !Double.isFinite(pos.getY()) || !Double.isFinite(pos.getZ())
|
||||
|| !Float.isFinite(pos.getYaw()) || !Float.isFinite(pos.getPitch())
|
||||
) {
|
||||
flagAndAlert("xyzYP: " + pos.getX() + ", " + pos.getY() + ", " + pos.getZ() + ", " + pos.getYaw() + ", " + pos.getPitch());
|
||||
player.getSetbackTeleportUtil().executeViolationSetback();
|
||||
event.setCancelled(true);
|
||||
|
||||
@@ -29,7 +29,7 @@ public class ExploitA extends Check implements PacketCheck {
|
||||
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);
|
||||
check(new PayloadItemName(wrapper.getData()).itemName(), event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public class ExploitB extends Check implements PacketCheck {
|
||||
}
|
||||
}
|
||||
|
||||
ItemStack newBook = PayloadBookEdit.CODEC.read(wrapper.getData()).itemStack();
|
||||
ItemStack newBook = new PayloadBookEdit(wrapper.getData()).itemStack();
|
||||
checkItemStack(newBook, signing, event);
|
||||
oldBook = null;
|
||||
}
|
||||
@@ -287,13 +287,14 @@ public class ExploitB extends Check implements PacketCheck {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (containsInvalidCharacters(page, true)) {
|
||||
if (flagAndAlert("invalid page characters") && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// commented out because existing characters are not considered
|
||||
// if (containsInvalidCharacters(page, true)) {
|
||||
// if (flagAndAlert("invalid page characters") && shouldModifyPackets()) {
|
||||
// event.setCancelled(true);
|
||||
// player.onPacketCancel();
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -12,18 +12,18 @@ public class NegativeTimer extends Timer implements PostPredictionCheck {
|
||||
|
||||
public NegativeTimer(GrimPlayer player) {
|
||||
super(player);
|
||||
timerBalanceRealTime = System.nanoTime() + clockDrift;
|
||||
timerBalanceRealTime = player.nano() + clockDrift;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(final PredictionComplete predictionComplete) {
|
||||
// We can't negative timer check a 1.9+ player who is standing still.
|
||||
if (player.uncertaintyHandler.lastPointThree.hasOccurredSince(2) || !predictionComplete.isChecked()) {
|
||||
timerBalanceRealTime = System.nanoTime() + clockDrift;
|
||||
timerBalanceRealTime = player.nano() + clockDrift;
|
||||
}
|
||||
|
||||
if (timerBalanceRealTime < lastMovementPlayerClock - clockDrift) {
|
||||
int lostMS = (int) ((System.nanoTime() - timerBalanceRealTime) / 1e6);
|
||||
int lostMS = (int) ((player.nano() - timerBalanceRealTime) / 1e6);
|
||||
flagAndAlertWithSetback("-" + lostMS);
|
||||
timerBalanceRealTime += 50e6;
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ public class Timer extends Check implements PacketCheck {
|
||||
protected long timerBalanceRealTime = 0;
|
||||
|
||||
// Default value is real time minus max keep-alive time
|
||||
protected long knownPlayerClockTime = (long) (System.nanoTime() - 6e10);
|
||||
protected long lastMovementPlayerClock = (long) (System.nanoTime() - 6e10);
|
||||
protected long knownPlayerClockTime = (long) (player.nano() - 6e10);
|
||||
protected long lastMovementPlayerClock = (long) (player.nano() - 6e10);
|
||||
|
||||
// How long should the player be able to fall back behind their ping? (nanos)
|
||||
// Default: 120 milliseconds
|
||||
@@ -71,7 +71,7 @@ public class Timer extends Check implements PacketCheck {
|
||||
}
|
||||
|
||||
public void doCheck(final PacketReceiveEvent event) {
|
||||
if (timerBalanceRealTime > System.nanoTime()) {
|
||||
if (timerBalanceRealTime > player.nano()) {
|
||||
if (flagAndAlert()) {
|
||||
// Cancel the packet
|
||||
if (shouldModifyPackets()) {
|
||||
|
||||
@@ -19,7 +19,7 @@ public class TimerLimit extends Timer {
|
||||
@Override
|
||||
public void doCheck(final PacketReceiveEvent event) {
|
||||
// 1:1 with Timer minus cancelling the packet
|
||||
if (timerBalanceRealTime > System.nanoTime()) {
|
||||
if (timerBalanceRealTime > player.nano()) {
|
||||
// If timer check already flagged, don't flag.
|
||||
if (!event.isCancelled()) {
|
||||
if (flagAndAlert() && shouldSetback()) {
|
||||
@@ -38,8 +38,8 @@ public class TimerLimit extends Timer {
|
||||
protected void limitFallBehind() {
|
||||
// Limit using transaction ping if over 1000ms (default)
|
||||
long playerClock = lastMovementPlayerClock;
|
||||
if (limitAbuseOverPing != -1 && System.nanoTime() - playerClock > limitAbuseOverPing) {
|
||||
playerClock = System.nanoTime() - limitAbuseOverPing;
|
||||
if (limitAbuseOverPing != -1 && player.nano() - playerClock > limitAbuseOverPing) {
|
||||
playerClock = player.nano() - limitAbuseOverPing;
|
||||
}
|
||||
timerBalanceRealTime = Math.max(timerBalanceRealTime, playerClock - clockDrift);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package ac.grim.grimac.checks.impl.velocity;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
@@ -46,9 +45,6 @@ public class KnockbackHandler extends Check implements PostPredictionCheck {
|
||||
WrapperPlayServerEntityVelocity velocity = new WrapperPlayServerEntityVelocity(event);
|
||||
int entityId = velocity.getEntityId();
|
||||
|
||||
GrimPlayer player = GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(event.getUser());
|
||||
if (player == null) return;
|
||||
|
||||
// Detect whether this knockback packet affects the player or if it is useless
|
||||
// Mojang sends extra useless knockback packets for no apparent reason
|
||||
if (player.compensatedEntities.serverPlayerVehicle != null && entityId != player.compensatedEntities.serverPlayerVehicle) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import ac.grim.grimac.platform.api.sender.Sender;
|
||||
import ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
import ac.grim.grimac.utils.common.PropertiesUtil;
|
||||
import ac.grim.grimac.utils.reflection.ReflectionUtils;
|
||||
import ac.grim.grimac.utils.reflection.ViaVersionUtil;
|
||||
import ac.grim.grimac.utils.viaversion.ViaVersionUtil;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
@@ -51,9 +51,9 @@ public class GrimDump implements BuildableCommand {
|
||||
GrimLog.sendLogAsync(sender, generateDump(), string -> link = string, "text/yaml");
|
||||
}
|
||||
|
||||
public static JsonObject getBasicInfo(String type) {
|
||||
public static JsonObject getDumpInfo() {
|
||||
JsonObject base = new JsonObject();
|
||||
base.addProperty("type", type);
|
||||
base.addProperty("type", "dump");
|
||||
base.addProperty("timestamp", System.currentTimeMillis());
|
||||
// versions
|
||||
JsonObject versions = new JsonObject();
|
||||
@@ -68,6 +68,11 @@ public class GrimDump implements BuildableCommand {
|
||||
if (GrimAPI.INSTANCE.isInitialized()) states.addProperty("platform", GrimAPI.INSTANCE.getPlatform().toString());
|
||||
if (ViaVersionUtil.isAvailable) states.addProperty("has_viaversion", true);
|
||||
if (PAPER) states.addProperty("has_paper", true);
|
||||
// include some relevant settings if not default
|
||||
JsonObject settings = new JsonObject();
|
||||
if (GrimAPI.INSTANCE.getAlertManager().hasConsoleVerboseEnabled()) settings.addProperty("console_verbose", true);
|
||||
if (!GrimAPI.INSTANCE.getAlertManager().hasConsoleAlertsEnabled()) settings.addProperty("console_alerts", false);
|
||||
if (settings.size() > 0) states.add("settings", settings);
|
||||
// system
|
||||
JsonObject system = new JsonObject();
|
||||
base.add("system", system);
|
||||
@@ -75,8 +80,17 @@ public class GrimDump implements BuildableCommand {
|
||||
system.addProperty("java_version", System.getProperty("java.version"));
|
||||
system.addProperty("user_language", System.getProperty("user.language"));
|
||||
// build
|
||||
JsonObject build = new JsonObject();
|
||||
base.add("build", getBuildInfo());
|
||||
// plugins
|
||||
JsonArray plugins = new JsonArray();
|
||||
base.add("plugins", plugins);
|
||||
for (PlatformPlugin plugin : GrimAPI.INSTANCE.getPluginManager().getPlugins()) {
|
||||
JsonObject pluginJson = new JsonObject();
|
||||
pluginJson.addProperty("enabled", plugin.isEnabled());
|
||||
pluginJson.addProperty("name", plugin.getName());
|
||||
pluginJson.addProperty("version", plugin.getVersion());
|
||||
plugins.add(pluginJson);
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
@@ -98,17 +112,7 @@ public class GrimDump implements BuildableCommand {
|
||||
* @return A JSON-formatted string containing the diagnostic dump.
|
||||
*/
|
||||
private String generateDump() {
|
||||
JsonObject base = getBasicInfo("dump");
|
||||
// plugins
|
||||
JsonArray plugins = new JsonArray();
|
||||
base.add("plugins", plugins);
|
||||
for (PlatformPlugin plugin : GrimAPI.INSTANCE.getPluginManager().getPlugins()) {
|
||||
JsonObject pluginJson = new JsonObject();
|
||||
pluginJson.addProperty("enabled", plugin.isEnabled());
|
||||
pluginJson.addProperty("name", plugin.getName());
|
||||
pluginJson.addProperty("version", plugin.getVersion());
|
||||
plugins.add(pluginJson);
|
||||
}
|
||||
JsonObject base = getDumpInfo();
|
||||
return gson.toJson(base);
|
||||
}
|
||||
}
|
||||
@@ -495,7 +495,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Client.PLAYER_BLOCK_PLACEMENT) {
|
||||
WrapperPlayClientPlayerBlockPlacement packet = new WrapperPlayClientPlayerBlockPlacement(event);
|
||||
player.lastBlockPlaceUseItem = System.currentTimeMillis();
|
||||
player.lastBlockPlaceUseItem = player.now();
|
||||
|
||||
ItemStack placedWith = player.inventory.getHeldItem();
|
||||
if (packet.getHand() == InteractionHand.OFF_HAND) {
|
||||
@@ -562,7 +562,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
if (event.getPacketType() == PacketType.Play.Client.USE_ITEM) {
|
||||
WrapperPlayClientUseItem packet = new WrapperPlayClientUseItem(event);
|
||||
player.placeUseItemPackets.add(new BlockPlaceSnapshot(packet, player.isSneaking));
|
||||
player.lastBlockPlaceUseItem = System.currentTimeMillis();
|
||||
player.lastBlockPlaceUseItem = player.now();
|
||||
}
|
||||
|
||||
// Call the packet checks last as they can modify the contents of the packet
|
||||
@@ -663,7 +663,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
}
|
||||
|
||||
private static void handleFlying(GrimPlayer player, double x, double y, double z, float yaw, float pitch, boolean hasPosition, boolean hasLook, boolean onGround, TeleportAcceptData teleportData, PacketReceiveEvent event) {
|
||||
long now = System.currentTimeMillis();
|
||||
long now = player.now();
|
||||
|
||||
if (!hasPosition) {
|
||||
// This may need to be secured later, although nothing that is very important relies on this
|
||||
@@ -759,7 +759,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
}
|
||||
|
||||
private static void handleDigging(GrimPlayer player, PacketReceiveEvent event) {
|
||||
player.lastBlockBreak = System.currentTimeMillis();
|
||||
player.lastBlockBreak = player.now();
|
||||
|
||||
final WrapperPlayClientPlayerDigging packet = new WrapperPlayClientPlayerDigging(event);
|
||||
final DiggingAction action = packet.getAction();
|
||||
|
||||
@@ -44,7 +44,7 @@ public class PacketEntityAction extends PacketListenerAbstract {
|
||||
break;
|
||||
case START_FLYING_WITH_ELYTRA:
|
||||
if (player.onGround || player.lastOnGround) {
|
||||
player.getSetbackTeleportUtil().executeForceResync();
|
||||
player.getSetbackTeleportUtil().executeNonSimulatingForceResync();
|
||||
|
||||
if (player.platformPlayer != null) {
|
||||
// Client ignores sneaking, use it to resync
|
||||
@@ -66,7 +66,7 @@ public class PacketEntityAction extends PacketListenerAbstract {
|
||||
player.pointThreeEstimator.updatePlayerGliding();
|
||||
} else {
|
||||
// A client is flying with a ghost elytra, resync
|
||||
player.getSetbackTeleportUtil().executeForceResync();
|
||||
player.getSetbackTeleportUtil().executeNonSimulatingForceResync();
|
||||
if (player.platformPlayer != null) {
|
||||
// Client ignores sneaking, use it to resync
|
||||
player.platformPlayer.setSneaking(!player.platformPlayer.isSneaking());
|
||||
|
||||
@@ -10,7 +10,7 @@ import ac.grim.grimac.utils.data.TrackerData;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntity;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntityHook;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntityTrackXRot;
|
||||
import ac.grim.grimac.utils.reflection.ViaVersionUtil;
|
||||
import ac.grim.grimac.utils.viaversion.ViaVersionUtil;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.event.PacketSendEvent;
|
||||
|
||||
@@ -72,7 +72,7 @@ public class PacketPingListener extends PacketListenerAbstract {
|
||||
if (id <= 0) {
|
||||
if (player.didWeSendThatTrans.remove(id)) {
|
||||
player.packetStateData.lastServerTransWasValid = true;
|
||||
player.transactionsSent.add(new Pair<>(id, System.nanoTime()));
|
||||
player.transactionsSent.add(new Pair<>(id, player.nano()));
|
||||
player.lastTransactionSent.getAndIncrement();
|
||||
}
|
||||
}
|
||||
@@ -91,7 +91,7 @@ public class PacketPingListener extends PacketListenerAbstract {
|
||||
Short shortID = ((short) id);
|
||||
if (player.didWeSendThatTrans.remove(shortID)) {
|
||||
player.packetStateData.lastServerTransWasValid = true;
|
||||
player.transactionsSent.add(new Pair<>(shortID, System.nanoTime()));
|
||||
player.transactionsSent.add(new Pair<>(shortID, player.nano()));
|
||||
player.lastTransactionSent.getAndIncrement();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ public class PacketPlayerDigging extends PacketListenerAbstract {
|
||||
|
||||
// do we need to do this with block breaks too?
|
||||
// Prevent issues if the player switches slots, while lagging, standing still, and is placing blocks
|
||||
CheckManagerListener.handleQueuedPlaces(player, false, 0, 0, System.currentTimeMillis());
|
||||
CheckManagerListener.handleQueuedPlaces(player, false, 0, 0, player.now());
|
||||
|
||||
if (player.packetStateData.lastSlotSelected != slot) {
|
||||
if (player.isResetItemUsageOnSlotChange() && GrimAPI.INSTANCE.getItemResetHandler().getItemUsageHand(player.platformPlayer) == InteractionHand.MAIN_HAND) {
|
||||
|
||||
@@ -210,7 +210,9 @@ public class PacketPlayerRespawn extends PacketListenerAbstract {
|
||||
}
|
||||
player.pose = Pose.STANDING;
|
||||
player.clientVelocity = new Vector3dm();
|
||||
player.gamemode = respawn.getGameMode();
|
||||
if (!GrimAPI.INSTANCE.getSpectateManager().isSpectating(player.uuid)) {
|
||||
player.gamemode = respawn.getGameMode();
|
||||
}
|
||||
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_17)) {
|
||||
player.compensatedWorld.setDimension(respawn.getDimensionType(), event.getUser());
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public class PacketWorldBorder extends Check implements PacketCheck {
|
||||
}
|
||||
|
||||
public double getCurrentDiameter() {
|
||||
double d0 = (double) (System.currentTimeMillis() - startTime) / ((double) endTime - startTime);
|
||||
double d0 = (double) (player.now() - startTime) / ((double) endTime - startTime);
|
||||
return d0 < 1.0D ? GrimMath.lerp(d0, oldDiameter, newDiameter) : newDiameter;
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ public class PacketWorldBorder extends Check implements PacketCheck {
|
||||
private void setLerp(double oldDiameter, double newDiameter, long length) {
|
||||
this.oldDiameter = oldDiameter;
|
||||
this.newDiameter = newDiameter;
|
||||
this.startTime = System.currentTimeMillis();
|
||||
this.startTime = player.now();
|
||||
this.endTime = this.startTime + length;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -158,7 +158,7 @@ public class BasePacketWorldReader extends PacketListenerAbstract {
|
||||
Vector3i blockPosition = blockChange.getBlockPosition();
|
||||
// Don't spam transactions (block changes are sent in batches)
|
||||
if (Math.abs(blockPosition.getX() - player.x) < range && Math.abs(blockPosition.getY() - player.y) < range && Math.abs(blockPosition.getZ() - player.z) < range &&
|
||||
player.lastTransSent + 2 < System.currentTimeMillis())
|
||||
player.lastTransSent + 2 < player.now())
|
||||
player.sendTransaction();
|
||||
|
||||
player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(), () -> player.compensatedWorld.updateBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), blockChange.getBlockId()));
|
||||
@@ -172,7 +172,7 @@ public class BasePacketWorldReader extends PacketListenerAbstract {
|
||||
final var blocks = multiBlockChange.getBlocks();
|
||||
for (WrapperPlayServerMultiBlockChange.EncodedBlock blockChange : blocks) {
|
||||
// Don't send a transaction unless it's within 16 blocks of the player
|
||||
if (Math.abs(blockChange.getX() - player.x) < range && Math.abs(blockChange.getY() - player.y) < range && Math.abs(blockChange.getZ() - player.z) < range && player.lastTransSent + 2 < System.currentTimeMillis()) {
|
||||
if (Math.abs(blockChange.getX() - player.x) < range && Math.abs(blockChange.getY() - player.y) < range && Math.abs(blockChange.getZ() - player.z) < range && player.lastTransSent + 2 < player.now()) {
|
||||
player.sendTransaction();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public class ActionManager extends Check implements PacketCheck {
|
||||
if (action.getAction() == WrapperPlayClientInteractEntity.InteractAction.ATTACK) {
|
||||
player.totalFlyingPacketsSent = 0;
|
||||
attacking = true;
|
||||
lastAttack = System.currentTimeMillis();
|
||||
lastAttack = player.now();
|
||||
}
|
||||
} else if (isTickPacketIncludingNonMovement(event.getPacketType())) {
|
||||
player.totalFlyingPacketsSent++;
|
||||
@@ -33,6 +33,6 @@ public class ActionManager extends Check implements PacketCheck {
|
||||
}
|
||||
|
||||
public boolean hasAttackedSince(long time) {
|
||||
return System.currentTimeMillis() - lastAttack < time;
|
||||
return player.now() - lastAttack < time;
|
||||
}
|
||||
}
|
||||
@@ -75,8 +75,10 @@ public class CheckManager {
|
||||
private final ClassToInstanceMap<BlockPlaceCheck> blockPlaceChecks;
|
||||
private final ClassToInstanceMap<PostPredictionCheck> postPredictionChecks;
|
||||
private PacketEntityReplication packetEntityReplication = null;
|
||||
private final GrimPlayer player;
|
||||
|
||||
public CheckManager(GrimPlayer player) {
|
||||
this.player = player;
|
||||
packetChecks = new ImmutableClassToInstanceMap.Builder<PacketCheck>()
|
||||
.put(PacketOrderProcessor.class, player.packetOrderProcessor)
|
||||
.put(Reach.class, new Reach(player))
|
||||
@@ -125,7 +127,7 @@ public class CheckManager {
|
||||
.put(PacketOrderC.class, new PacketOrderC(player))
|
||||
.put(PacketOrderD.class, new PacketOrderD(player))
|
||||
.put(PacketOrderO.class, new PacketOrderO(player))
|
||||
.put(PacketOrderP.class, new PacketOrderP(player))
|
||||
// .put(PacketOrderP.class, new PacketOrderP(player))
|
||||
.put(SprintA.class, new SprintA(player))
|
||||
.put(VehicleA.class, new VehicleA(player))
|
||||
.put(VehicleB.class, new VehicleB(player))
|
||||
@@ -294,6 +296,8 @@ public class CheckManager {
|
||||
}
|
||||
|
||||
public void onPacketReceive(final PacketReceiveEvent packet) {
|
||||
player.processingPacket();
|
||||
|
||||
for (PacketCheck check : packetChecks.values()) {
|
||||
check.onPacketReceive(packet);
|
||||
}
|
||||
@@ -309,6 +313,8 @@ public class CheckManager {
|
||||
}
|
||||
|
||||
public void onPacketSend(final PacketSendEvent packet) {
|
||||
player.processingPacket();
|
||||
|
||||
for (PacketCheck check : prePredictionChecks.values()) {
|
||||
check.onPacketSend(packet);
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ public class PunishmentManager implements ConfigReloadable {
|
||||
public void handleViolation(Check check) {
|
||||
for (PunishGroup group : groups) {
|
||||
if (group.checks.contains(check)) {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
long currentTime = player.now();
|
||||
|
||||
group.violations.put(currentTime, check);
|
||||
// Remove violations older than the defined time in the config
|
||||
|
||||
@@ -100,6 +100,13 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
blockMovementsUntilResync(true, true);
|
||||
}
|
||||
|
||||
public void executeNonSimulatingForceResync() {
|
||||
if (player.gamemode == GameMode.SPECTATOR || player.disableGrim)
|
||||
return; // We don't care about spectators, they don't flag
|
||||
if (lastKnownGoodPosition == null) return; // Player hasn't spawned yet
|
||||
blockMovementsUntilResync(false, true);
|
||||
}
|
||||
|
||||
public void executeNonSimulatingSetback() {
|
||||
if (player.gamemode == GameMode.SPECTATOR || player.disableGrim)
|
||||
return; // We don't care about spectators, they don't flag
|
||||
@@ -137,9 +144,11 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
vector.setY(vector.getY() - 0.05); // Make the player fall a bit
|
||||
} else { // Gliding doesn't have friction, we handle it differently
|
||||
PredictionEngineNormal.staticVectorEndOfTick(player, vector); // Lava and normal movement
|
||||
vector.multiply(player.stuckSpeedMultiplier); // Prevent abusing setbacks to move out of blocks like webs
|
||||
}
|
||||
|
||||
// Prevent abusing setbacks to move out of blocks like webs
|
||||
vector.multiply(player.stuckSpeedMultiplier);
|
||||
|
||||
// stop 1.8 players from stepping onto 1.25 high blocks, because why not?
|
||||
new PredictionEngine().applyMovementThreshold(player, new HashSet<>(Collections.singletonList(new VectorData(vector, VectorData.VectorType.BestVelPicked))));
|
||||
}
|
||||
@@ -152,9 +161,9 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
if (isPendingSetback()) return; // Don't spam setbacks
|
||||
|
||||
// Only let us full resync once every five seconds to prevent unneeded bukkit load
|
||||
if (System.currentTimeMillis() - lastWorldResync > 5 * 1000) {
|
||||
if (player.now() - lastWorldResync > 5 * 1000) {
|
||||
player.resyncPositions(player.boundingBox.copy().expand(1));
|
||||
lastWorldResync = System.currentTimeMillis();
|
||||
lastWorldResync = player.now();
|
||||
}
|
||||
|
||||
Vector3dm clientVel = lastKnownGoodPosition.vector.clone();
|
||||
@@ -208,7 +217,7 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
blockOffsets = true;
|
||||
}
|
||||
|
||||
SetBackData data = new SetBackData(new TeleportData(position, new Vector3d(), new RelativeFlag(0b11000), player.lastTransactionSent.get(), 0), player.yaw, player.pitch, clientVel, player.inVehicle(), false);
|
||||
SetBackData data = new SetBackData(new TeleportData(position, new Vector3d(), RelativeFlag.YAW.or(RelativeFlag.PITCH), player.lastTransactionSent.get(), 0), player.yaw, player.pitch, clientVel, player.inVehicle(), false);
|
||||
sendSetback(data);
|
||||
}
|
||||
|
||||
@@ -375,7 +384,7 @@ public class SetbackTeleportUtil extends Check implements PostPredictionCheck {
|
||||
|
||||
private boolean isPendingSetback() {
|
||||
// Relative setbacks shouldn't count
|
||||
if (requiredSetBack.getTeleportData().isRelativeX() || requiredSetBack.getTeleportData().isRelativeY() || requiredSetBack.getTeleportData().isRelativeZ()) {
|
||||
if (requiredSetBack != null && (requiredSetBack.getTeleportData().isRelativeX() || requiredSetBack.getTeleportData().isRelativeY() || requiredSetBack.getTeleportData().isRelativeZ())) {
|
||||
return false;
|
||||
}
|
||||
// The setback is not complete
|
||||
|
||||
@@ -2,7 +2,7 @@ package ac.grim.grimac.manager.init.start;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import ac.grim.grimac.utils.reflection.ViaVersionUtil;
|
||||
import ac.grim.grimac.utils.viaversion.ViaVersionUtil;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package ac.grim.grimac.manager.init.start;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import ac.grim.grimac.utils.reflection.ViaVersionUtil;
|
||||
import ac.grim.grimac.utils.viaversion.ViaVersionUtil;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
@@ -12,6 +12,7 @@ public class ViaVersion implements StartableInitable {
|
||||
@Override
|
||||
public void start() {
|
||||
if (!ViaVersionUtil.isAvailable) return;
|
||||
ViaVersionUtil.injectHooks();
|
||||
|
||||
ServerVersion serverVersion = PacketEvents.getAPI().getServerManager().getVersion();
|
||||
|
||||
|
||||
+23
@@ -6,6 +6,7 @@ import ac.grim.grimac.api.plugin.GrimPlugin;
|
||||
import ac.grim.grimac.manager.init.ReloadableInitable;
|
||||
import ac.grim.grimac.manager.init.start.StartableInitable;
|
||||
import ac.grim.grimac.manager.violationdatabase.mysql.MySQLViolationDatabase;
|
||||
import ac.grim.grimac.manager.violationdatabase.postgresql.PostgresqlViolationDatabase;
|
||||
import ac.grim.grimac.manager.violationdatabase.sqlite.SQLiteViolationDatabase;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
@@ -93,6 +94,28 @@ public class ViolationDatabaseManager implements StartableInitable, ReloadableIn
|
||||
}
|
||||
}
|
||||
|
||||
case "POSTGRESQL" -> {
|
||||
String host = cfg.getStringElse("history.database.host", "localhost:3306");
|
||||
String db = cfg.getStringElse("history.database.database", "grimac");
|
||||
String user = cfg.getStringElse("history.database.username", "root");
|
||||
String pwd = cfg.getStringElse("history.database.password", "password");
|
||||
|
||||
if (database instanceof PostgresqlViolationDatabase postgresql
|
||||
&& postgresql.sameConfig(host, db, user, pwd)) {
|
||||
break; // nothing changed → keep pool
|
||||
}
|
||||
database.disconnect();
|
||||
database = new PostgresqlViolationDatabase(host, db, user, pwd);
|
||||
try {
|
||||
database.connect();
|
||||
loaded = true;
|
||||
} catch (SQLException e) {
|
||||
LogUtil.error(e);
|
||||
this.database = NoOpViolationDatabase.INSTANCE;
|
||||
loaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
default -> { // NOOP or invalid
|
||||
if (!(database instanceof NoOpViolationDatabase)) {
|
||||
database.disconnect();
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package ac.grim.grimac.manager.violationdatabase.postgresql;
|
||||
|
||||
import ac.grim.grimac.manager.violationdatabase.DatabaseDialect;
|
||||
|
||||
public class PostgresqlDialect implements DatabaseDialect {
|
||||
|
||||
@Override
|
||||
public String getUuidColumnType() {
|
||||
return "UUID";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAutoIncrementPrimaryKeySyntax() {
|
||||
return "BIGSERIAL PRIMARY KEY";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInsertOrIgnoreSyntax(String tableName, String columnNames) {
|
||||
return "INSERT INTO " + tableName + " (" + columnNames + ") VALUES (?) ON CONFLICT DO NOTHING";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueConstraintViolationSQLState() {
|
||||
return "23505"; // Postgresql duplicate key error
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUniqueConstraintViolationErrorCode() {
|
||||
return 0; // Postgresql is not using numbers
|
||||
}
|
||||
}
|
||||
+286
@@ -0,0 +1,286 @@
|
||||
package ac.grim.grimac.manager.violationdatabase.postgresql;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.manager.violationdatabase.*;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PostgresqlViolationDatabase implements ViolationDatabase {
|
||||
|
||||
private static String quoteVerboseColumn() {
|
||||
return "\"" + DatabaseConstants.VIOLATIONS_VERBOSE_COLUMN + "\"";
|
||||
}
|
||||
|
||||
private HikariDataSource dataSource;
|
||||
private final DatabaseDialect dialect;
|
||||
|
||||
public PostgresqlViolationDatabase(String url, String database, String username, String password) {
|
||||
this.dialect = new PostgresqlDialect();
|
||||
setupDataSource(url, database, username, password);
|
||||
}
|
||||
|
||||
private void setupDataSource(String url, String database, String username, String password) {
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setJdbcUrl("jdbc:postgresql://" + url + "/" + database);
|
||||
config.setUsername(username);
|
||||
config.setPassword(password);
|
||||
config.setMaximumPoolSize(10);
|
||||
config.setAutoCommit(true);
|
||||
dataSource = new HikariDataSource(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() throws SQLException {
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
String pkSyntax = dialect.getAutoIncrementPrimaryKeySyntax();
|
||||
String uuidType = dialect.getUuidColumnType();
|
||||
|
||||
// 1. Create Lookup Table for Server Names
|
||||
connection.prepareStatement(
|
||||
"CREATE TABLE IF NOT EXISTS " + DatabaseConstants.SERVERS_TABLE + "(" +
|
||||
"id " + pkSyntax + ", " +
|
||||
DatabaseConstants.SERVERS_STRING_COLUMN + " VARCHAR(255) NOT NULL UNIQUE" +
|
||||
")"
|
||||
).execute();
|
||||
connection.prepareStatement(
|
||||
"CREATE INDEX IF NOT EXISTS idx_" + DatabaseConstants.SERVERS_TABLE + "_name ON " + DatabaseConstants.SERVERS_TABLE + "(" + DatabaseConstants.SERVERS_STRING_COLUMN + ");"
|
||||
).execute();
|
||||
|
||||
// 2. Create Lookup Table for Check Names
|
||||
connection.prepareStatement(
|
||||
"CREATE TABLE IF NOT EXISTS " + DatabaseConstants.CHECK_NAMES_TABLE + "(" +
|
||||
"id " + pkSyntax + ", " +
|
||||
DatabaseConstants.CHECK_NAMES_STRING_COLUMN + " VARCHAR(255) NOT NULL UNIQUE" +
|
||||
")"
|
||||
).execute();
|
||||
connection.prepareStatement(
|
||||
"CREATE INDEX IF NOT EXISTS idx_" + DatabaseConstants.CHECK_NAMES_TABLE + "_string ON " + DatabaseConstants.CHECK_NAMES_TABLE + "(" + DatabaseConstants.CHECK_NAMES_STRING_COLUMN + ");"
|
||||
).execute();
|
||||
|
||||
// --- NEW LOOKUP TABLES ---
|
||||
// 3. Create Lookup Table for Grim Versions
|
||||
connection.prepareStatement(
|
||||
"CREATE TABLE IF NOT EXISTS " + DatabaseConstants.GRIM_VERSIONS_TABLE + "(" +
|
||||
"id " + pkSyntax + ", " +
|
||||
DatabaseConstants.GRIM_VERSIONS_STRING_COLUMN + " VARCHAR(255) NOT NULL UNIQUE" +
|
||||
")"
|
||||
).execute();
|
||||
connection.prepareStatement(
|
||||
"CREATE INDEX IF NOT EXISTS idx_" + DatabaseConstants.GRIM_VERSIONS_TABLE + "_string ON " + DatabaseConstants.GRIM_VERSIONS_TABLE + "(" + DatabaseConstants.GRIM_VERSIONS_STRING_COLUMN + ");"
|
||||
).execute();
|
||||
|
||||
// 4. Create Lookup Table for Client Brands
|
||||
connection.prepareStatement(
|
||||
"CREATE TABLE IF NOT EXISTS " + DatabaseConstants.CLIENT_BRANDS_TABLE + "(" +
|
||||
"id " + pkSyntax + ", " +
|
||||
DatabaseConstants.CLIENT_BRANDS_STRING_COLUMN + " VARCHAR(255) NOT NULL UNIQUE" +
|
||||
")"
|
||||
).execute();
|
||||
connection.prepareStatement(
|
||||
"CREATE INDEX IF NOT EXISTS idx_" + DatabaseConstants.CLIENT_BRANDS_TABLE + "_string ON " + DatabaseConstants.CLIENT_BRANDS_TABLE + "(" + DatabaseConstants.CLIENT_BRANDS_STRING_COLUMN + ");"
|
||||
).execute();
|
||||
|
||||
// 5. Create Lookup Table for Client Versions
|
||||
connection.prepareStatement(
|
||||
"CREATE TABLE IF NOT EXISTS " + DatabaseConstants.CLIENT_VERSIONS_TABLE + "(" +
|
||||
"id " + pkSyntax + ", " +
|
||||
DatabaseConstants.CLIENT_VERSIONS_STRING_COLUMN + " VARCHAR(255) NOT NULL UNIQUE" +
|
||||
")"
|
||||
).execute();
|
||||
connection.prepareStatement(
|
||||
"CREATE INDEX IF NOT EXISTS idx_" + DatabaseConstants.CLIENT_VERSIONS_TABLE + "_string ON " + DatabaseConstants.CLIENT_VERSIONS_TABLE + "(" + DatabaseConstants.CLIENT_VERSIONS_STRING_COLUMN + ");"
|
||||
).execute();
|
||||
|
||||
// 6. Create Lookup Table for Server Versions
|
||||
connection.prepareStatement(
|
||||
"CREATE TABLE IF NOT EXISTS " + DatabaseConstants.SERVER_VERSIONS_TABLE + "(" +
|
||||
"id " + pkSyntax + ", " +
|
||||
DatabaseConstants.SERVER_VERSIONS_STRING_COLUMN + " VARCHAR(255) NOT NULL UNIQUE" +
|
||||
")"
|
||||
).execute();
|
||||
connection.prepareStatement(
|
||||
"CREATE INDEX IF NOT EXISTS idx_" + DatabaseConstants.SERVER_VERSIONS_TABLE + "_string ON " + DatabaseConstants.SERVER_VERSIONS_TABLE + "(" + DatabaseConstants.SERVER_VERSIONS_STRING_COLUMN + ");"
|
||||
).execute();
|
||||
// --- END NEW LOOKUP TABLES ---
|
||||
|
||||
// 7. Create Main Violations Table with ALL Foreign Keys and optimized UUID
|
||||
connection.prepareStatement(
|
||||
"CREATE TABLE IF NOT EXISTS " + DatabaseConstants.VIOLATIONS_TABLE + "(" +
|
||||
"id " + pkSyntax + ", " +
|
||||
DatabaseConstants.VIOLATIONS_SERVER_ID_COLUMN + " BIGINT NOT NULL, " +
|
||||
DatabaseConstants.VIOLATIONS_UUID_COLUMN + " " + uuidType + " NOT NULL, " +
|
||||
DatabaseConstants.VIOLATIONS_CHECK_NAME_ID_COLUMN + " BIGINT NOT NULL, " +
|
||||
quoteVerboseColumn() + " TEXT NOT NULL, " +
|
||||
DatabaseConstants.VIOLATIONS_VL_COLUMN + " INT NOT NULL, " +
|
||||
DatabaseConstants.VIOLATIONS_CREATED_AT_COLUMN + " BIGINT NOT NULL, " +
|
||||
DatabaseConstants.VIOLATIONS_GRIM_VERSION_ID_COLUMN + " BIGINT NOT NULL, " + // NEW
|
||||
DatabaseConstants.VIOLATIONS_CLIENT_BRAND_ID_COLUMN + " BIGINT NOT NULL, " + // NEW
|
||||
DatabaseConstants.VIOLATIONS_CLIENT_VERSION_ID_COLUMN + " BIGINT NOT NULL, " + // NEW
|
||||
DatabaseConstants.VIOLATIONS_SERVER_VERSION_ID_COLUMN + " BIGINT NOT NULL, " + // NEW
|
||||
"FOREIGN KEY (" + DatabaseConstants.VIOLATIONS_SERVER_ID_COLUMN + ") REFERENCES " + DatabaseConstants.SERVERS_TABLE + "(id), " +
|
||||
"FOREIGN KEY (" + DatabaseConstants.VIOLATIONS_CHECK_NAME_ID_COLUMN + ") REFERENCES " + DatabaseConstants.CHECK_NAMES_TABLE + "(id), " +
|
||||
"FOREIGN KEY (" + DatabaseConstants.VIOLATIONS_GRIM_VERSION_ID_COLUMN + ") REFERENCES " + DatabaseConstants.GRIM_VERSIONS_TABLE + "(id), " + // NEW
|
||||
"FOREIGN KEY (" + DatabaseConstants.VIOLATIONS_CLIENT_BRAND_ID_COLUMN + ") REFERENCES " + DatabaseConstants.CLIENT_BRANDS_TABLE + "(id), " + // NEW
|
||||
"FOREIGN KEY (" + DatabaseConstants.VIOLATIONS_CLIENT_VERSION_ID_COLUMN + ") REFERENCES " + DatabaseConstants.CLIENT_VERSIONS_TABLE + "(id), " + // NEW
|
||||
"FOREIGN KEY (" + DatabaseConstants.VIOLATIONS_SERVER_VERSION_ID_COLUMN + ") REFERENCES " + DatabaseConstants.SERVER_VERSIONS_TABLE + "(id)" + // NEW
|
||||
")"
|
||||
).execute();
|
||||
|
||||
// 8. Create Indexes for efficient querying on main table (includes new FKs)
|
||||
connection.prepareStatement(
|
||||
"CREATE INDEX IF NOT EXISTS idx_" + DatabaseConstants.VIOLATIONS_TABLE + "_uuid ON " + DatabaseConstants.VIOLATIONS_TABLE + "(" + DatabaseConstants.VIOLATIONS_UUID_COLUMN + ");"
|
||||
).execute();
|
||||
connection.prepareStatement(
|
||||
"CREATE INDEX IF NOT EXISTS idx_" + DatabaseConstants.VIOLATIONS_TABLE + "_created_at ON " + DatabaseConstants.VIOLATIONS_TABLE + "(" + DatabaseConstants.VIOLATIONS_CREATED_AT_COLUMN + ");"
|
||||
).execute();
|
||||
connection.prepareStatement(
|
||||
"CREATE INDEX IF NOT EXISTS idx_" + DatabaseConstants.VIOLATIONS_TABLE + "_server_id ON " + DatabaseConstants.VIOLATIONS_TABLE + "(" + DatabaseConstants.VIOLATIONS_SERVER_ID_COLUMN + ");"
|
||||
).execute();
|
||||
connection.prepareStatement(
|
||||
"CREATE INDEX IF NOT EXISTS idx_" + DatabaseConstants.VIOLATIONS_TABLE + "_check_name_id ON " + DatabaseConstants.VIOLATIONS_TABLE + "(" + DatabaseConstants.VIOLATIONS_CHECK_NAME_ID_COLUMN + ");"
|
||||
).execute();
|
||||
connection.prepareStatement(
|
||||
"CREATE INDEX IF NOT EXISTS idx_" + DatabaseConstants.VIOLATIONS_TABLE + "_grim_version_id ON " + DatabaseConstants.VIOLATIONS_TABLE + "(" + DatabaseConstants.VIOLATIONS_GRIM_VERSION_ID_COLUMN + ");" // NEW
|
||||
).execute();
|
||||
connection.prepareStatement(
|
||||
"CREATE INDEX IF NOT EXISTS idx_" + DatabaseConstants.VIOLATIONS_TABLE + "_client_brand_id ON " + DatabaseConstants.VIOLATIONS_TABLE + "(" + DatabaseConstants.VIOLATIONS_CLIENT_BRAND_ID_COLUMN + ");" // NEW
|
||||
).execute();
|
||||
connection.prepareStatement(
|
||||
"CREATE INDEX IF NOT EXISTS idx_" + DatabaseConstants.VIOLATIONS_TABLE + "_client_version_id ON " + DatabaseConstants.VIOLATIONS_TABLE + "(" + DatabaseConstants.VIOLATIONS_CLIENT_VERSION_ID_COLUMN + ");" // NEW
|
||||
).execute();
|
||||
connection.prepareStatement(
|
||||
"CREATE INDEX IF NOT EXISTS idx_" + DatabaseConstants.VIOLATIONS_TABLE + "_server_version_id ON " + DatabaseConstants.VIOLATIONS_TABLE + "(" + DatabaseConstants.VIOLATIONS_SERVER_VERSION_ID_COLUMN + ");" // NEW
|
||||
).execute();
|
||||
|
||||
} catch (SQLException ex) {
|
||||
LogUtil.error("Failed to generate violations database:", ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
// Updated method signature to accept all new parameters
|
||||
public synchronized void logAlert(GrimPlayer player, String grimVersion, String verbose, String checkName, int vls) {
|
||||
try (Connection connection = dataSource.getConnection();
|
||||
// Updated INSERT statement with all new columns
|
||||
PreparedStatement insertAlert = connection.prepareStatement(
|
||||
"INSERT INTO " + DatabaseConstants.VIOLATIONS_TABLE + " (" +
|
||||
DatabaseConstants.VIOLATIONS_SERVER_ID_COLUMN + ", " +
|
||||
DatabaseConstants.VIOLATIONS_UUID_COLUMN + ", " +
|
||||
DatabaseConstants.VIOLATIONS_CHECK_NAME_ID_COLUMN + ", " +
|
||||
quoteVerboseColumn() + ", " +
|
||||
DatabaseConstants.VIOLATIONS_VL_COLUMN + ", " +
|
||||
DatabaseConstants.VIOLATIONS_CREATED_AT_COLUMN + ", " +
|
||||
DatabaseConstants.VIOLATIONS_GRIM_VERSION_ID_COLUMN + ", " + // NEW
|
||||
DatabaseConstants.VIOLATIONS_CLIENT_BRAND_ID_COLUMN + ", " + // NEW
|
||||
DatabaseConstants.VIOLATIONS_CLIENT_VERSION_ID_COLUMN + ", " + // NEW
|
||||
DatabaseConstants.VIOLATIONS_SERVER_VERSION_ID_COLUMN + // NEW
|
||||
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" // Total 10 parameters now
|
||||
)
|
||||
) {
|
||||
// Get or create IDs for all deduplicated strings
|
||||
String serverName = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("history.server-name", "Prison");
|
||||
long serverId = DatabaseUtils.getOrCreateId(connection, dialect, DatabaseConstants.SERVERS_TABLE, DatabaseConstants.SERVERS_STRING_COLUMN, serverName);
|
||||
long checkNameId = DatabaseUtils.getOrCreateId(connection, dialect, DatabaseConstants.CHECK_NAMES_TABLE, DatabaseConstants.CHECK_NAMES_STRING_COLUMN, checkName);
|
||||
long grimVersionId = DatabaseUtils.getOrCreateId(connection, dialect, DatabaseConstants.GRIM_VERSIONS_TABLE, DatabaseConstants.GRIM_VERSIONS_STRING_COLUMN, grimVersion);
|
||||
long clientBrandId = DatabaseUtils.getOrCreateId(connection, dialect, DatabaseConstants.CLIENT_BRANDS_TABLE, DatabaseConstants.CLIENT_BRANDS_STRING_COLUMN, player.getBrand());
|
||||
long clientVersionId = DatabaseUtils.getOrCreateId(connection, dialect, DatabaseConstants.CLIENT_VERSIONS_TABLE, DatabaseConstants.CLIENT_VERSIONS_STRING_COLUMN, player.getClientVersion().getReleaseName());
|
||||
long serverVersionId = DatabaseUtils.getOrCreateId(connection, dialect, DatabaseConstants.SERVER_VERSIONS_TABLE, DatabaseConstants.SERVER_VERSIONS_STRING_COLUMN, PacketEvents.getAPI().getServerManager().getVersion().toString());
|
||||
|
||||
// Set parameters for the PreparedStatement
|
||||
insertAlert.setLong(1, serverId);
|
||||
insertAlert.setObject(2, player.getUniqueId());
|
||||
insertAlert.setLong(3, checkNameId);
|
||||
insertAlert.setString(4, verbose);
|
||||
insertAlert.setInt(5, vls);
|
||||
insertAlert.setLong(6, System.currentTimeMillis());
|
||||
insertAlert.setLong(7, grimVersionId); // NEW
|
||||
insertAlert.setLong(8, clientBrandId); // NEW
|
||||
insertAlert.setLong(9, clientVersionId); // NEW
|
||||
insertAlert.setLong(10, serverVersionId); // NEW
|
||||
|
||||
insertAlert.execute();
|
||||
} catch (SQLException ex) {
|
||||
LogUtil.error("Failed to log alert", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int getLogCount(UUID uuid) {
|
||||
try (Connection connection = dataSource.getConnection();
|
||||
PreparedStatement countLogs = connection.prepareStatement(
|
||||
"SELECT COUNT(*) FROM " + DatabaseConstants.VIOLATIONS_TABLE + " WHERE " + DatabaseConstants.VIOLATIONS_UUID_COLUMN + " = ?"
|
||||
)
|
||||
) {
|
||||
countLogs.setObject(1, uuid);
|
||||
ResultSet result = countLogs.executeQuery();
|
||||
if (result.next()) {
|
||||
return result.getInt(1);
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
LogUtil.error("Failed to count logs", ex);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized List<Violation> getViolations(UUID uuid, int page, int limit) {
|
||||
try (Connection connection = dataSource.getConnection();
|
||||
// Updated SELECT statement with all new joins and column selections
|
||||
PreparedStatement fetchLogs = connection.prepareStatement(
|
||||
"SELECT " +
|
||||
"v." + DatabaseConstants.VIOLATIONS_ID_COLUMN + ", " +
|
||||
"s." + DatabaseConstants.SERVERS_STRING_COLUMN + ", " +
|
||||
"v." + DatabaseConstants.VIOLATIONS_UUID_COLUMN + ", " +
|
||||
"cn." + DatabaseConstants.CHECK_NAMES_STRING_COLUMN + ", " +
|
||||
"v." + quoteVerboseColumn() + ", " +
|
||||
"v." + DatabaseConstants.VIOLATIONS_VL_COLUMN + ", " +
|
||||
"v." + DatabaseConstants.VIOLATIONS_CREATED_AT_COLUMN + ", " +
|
||||
"gv." + DatabaseConstants.GRIM_VERSIONS_STRING_COLUMN + ", " + // NEW
|
||||
"cb." + DatabaseConstants.CLIENT_BRANDS_STRING_COLUMN + ", " + // NEW
|
||||
"clv." + DatabaseConstants.CLIENT_VERSIONS_STRING_COLUMN + ", " + // NEW
|
||||
"srv." + DatabaseConstants.SERVER_VERSIONS_STRING_COLUMN + " " + // NEW
|
||||
"FROM " + DatabaseConstants.VIOLATIONS_TABLE + " v " +
|
||||
"JOIN " + DatabaseConstants.SERVERS_TABLE + " s ON v." + DatabaseConstants.VIOLATIONS_SERVER_ID_COLUMN + " = s.id " +
|
||||
"JOIN " + DatabaseConstants.CHECK_NAMES_TABLE + " cn ON v." + DatabaseConstants.VIOLATIONS_CHECK_NAME_ID_COLUMN + " = cn.id " +
|
||||
"JOIN " + DatabaseConstants.GRIM_VERSIONS_TABLE + " gv ON v." + DatabaseConstants.VIOLATIONS_GRIM_VERSION_ID_COLUMN + " = gv.id " + // NEW
|
||||
"JOIN " + DatabaseConstants.CLIENT_BRANDS_TABLE + " cb ON v." + DatabaseConstants.VIOLATIONS_CLIENT_BRAND_ID_COLUMN + " = cb.id " + // NEW
|
||||
"JOIN " + DatabaseConstants.CLIENT_VERSIONS_TABLE + " clv ON v." + DatabaseConstants.VIOLATIONS_CLIENT_VERSION_ID_COLUMN + " = clv.id " + // NEW
|
||||
"JOIN " + DatabaseConstants.SERVER_VERSIONS_TABLE + " srv ON v." + DatabaseConstants.VIOLATIONS_SERVER_VERSION_ID_COLUMN + " = srv.id " + // NEW
|
||||
"WHERE v." + DatabaseConstants.VIOLATIONS_UUID_COLUMN + " = ? ORDER BY v." + DatabaseConstants.VIOLATIONS_CREATED_AT_COLUMN + " DESC LIMIT ? OFFSET ?"
|
||||
)
|
||||
) {
|
||||
fetchLogs.setObject(1, uuid);
|
||||
fetchLogs.setInt(2, limit);
|
||||
fetchLogs.setInt(3, Math.max(0, (page - 1)) * limit); // postgresql is not allowing negative numbers
|
||||
return Violation.fromResultSet(fetchLogs.executeQuery());
|
||||
} catch (SQLException ex) {
|
||||
LogUtil.error("Failed to fetch logs", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
if (dataSource != null && !dataSource.isClosed()) {
|
||||
dataSource.close();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean sameConfig(String host, String db, String user, String pwd) {
|
||||
String wantUrl = "jdbc:postgresql://" + host + "/" + db;
|
||||
return wantUrl.equalsIgnoreCase(dataSource.getJdbcUrl())
|
||||
&& user.equals(dataSource.getUsername())
|
||||
&& pwd.equals(dataSource.getPassword());
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ import ac.grim.grimac.utils.nmsutil.BlockProperties;
|
||||
import ac.grim.grimac.utils.nmsutil.Collisions;
|
||||
import ac.grim.grimac.utils.nmsutil.GetBoundingBox;
|
||||
import ac.grim.grimac.utils.nmsutil.Materials;
|
||||
import ac.grim.grimac.utils.reflection.ViaVersionUtil;
|
||||
import ac.grim.grimac.utils.viaversion.ViaVersionUtil;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.event.PacketSendEvent;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
@@ -120,13 +120,13 @@ public class GrimPlayer implements GrimUser {
|
||||
public long lastTransSent = 0;
|
||||
public long lastTransReceived = 0;
|
||||
@Getter
|
||||
private long playerClockAtLeast = System.nanoTime();
|
||||
private long playerClockAtLeast;
|
||||
public double lastWasClimbing = 0;
|
||||
public boolean canSwimHop = false;
|
||||
public int riptideSpinAttackTicks = 0;
|
||||
public int powderSnowFrozenTicks = 0;
|
||||
public boolean hasGravity = true;
|
||||
public final long joinTime = System.currentTimeMillis();
|
||||
public final long joinTime;
|
||||
public boolean playerEntityHasGravity = true;
|
||||
public VectorData predictedVelocity = new VectorData(new Vector3dm(), VectorData.VectorType.Normal);
|
||||
public Vector3dm actualMovement = new Vector3dm();
|
||||
@@ -272,6 +272,12 @@ public class GrimPlayer implements GrimUser {
|
||||
public boolean lastJumping;
|
||||
|
||||
public GrimPlayer(@NotNull User user) {
|
||||
this(user, System.currentTimeMillis(), System.nanoTime());
|
||||
}
|
||||
|
||||
protected GrimPlayer(@NotNull User user, long joinTime, long clockStart) {
|
||||
this.joinTime = joinTime;
|
||||
this.playerClockAtLeast = clockStart;
|
||||
this.user = user;
|
||||
this.uuid = user.getUUID();
|
||||
fireworks = new CompensatedFireworks(this); // Must be before checkmanager
|
||||
@@ -397,7 +403,7 @@ public class GrimPlayer implements GrimUser {
|
||||
// Transactions that we send don't count towards total limit
|
||||
if (viaPacketTracker != null) viaPacketTracker.setIntervalPackets(viaPacketTracker.getIntervalPackets() - 1);
|
||||
|
||||
if (skipped > 0 && System.currentTimeMillis() - joinTime > 5000)
|
||||
if (skipped > 0 && now() - joinTime > 5000)
|
||||
checkManager.getCheck(TransactionOrder.class).flagAndAlert("skipped: " + skipped);
|
||||
|
||||
do {
|
||||
@@ -406,14 +412,14 @@ public class GrimPlayer implements GrimUser {
|
||||
break;
|
||||
|
||||
lastTransactionReceived.incrementAndGet();
|
||||
lastTransReceived = System.currentTimeMillis();
|
||||
transactionPing = (System.nanoTime() - data.second());
|
||||
lastTransReceived = now();
|
||||
transactionPing = (this.nano() - data.second());
|
||||
playerClockAtLeast = data.second();
|
||||
} while (data.first() != id);
|
||||
|
||||
// A transaction means a new tick, so handle any block interactions
|
||||
CheckManagerListener.handleQueuedPlaces(this, false, 0, 0, System.currentTimeMillis());
|
||||
CheckManagerListener.handleQueuedBreaks(this, false, 0, 0, System.currentTimeMillis());
|
||||
CheckManagerListener.handleQueuedPlaces(this, false, 0, 0, now());
|
||||
CheckManagerListener.handleQueuedBreaks(this, false, 0, 0, now());
|
||||
latencyUtils.handleNettySyncTransaction(lastTransactionReceived.get());
|
||||
}
|
||||
|
||||
@@ -461,11 +467,11 @@ public class GrimPlayer implements GrimUser {
|
||||
if (user.getEncoderState() != ConnectionState.PLAY) return;
|
||||
|
||||
// Send a packet once every 15 seconds to avoid any memory leaks
|
||||
if (disableGrim && (System.nanoTime() - getPlayerClockAtLeast()) > 15e9) {
|
||||
if (disableGrim && (this.nano() - getPlayerClockAtLeast()) > 15e9) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastTransSent = System.currentTimeMillis();
|
||||
lastTransSent = now();
|
||||
short transactionID = (short) (-1 * (transactionIDCounter.getAndIncrement() & 0x7FFF));
|
||||
try {
|
||||
|
||||
@@ -524,15 +530,20 @@ public class GrimPlayer implements GrimUser {
|
||||
}
|
||||
|
||||
public void pollData() {
|
||||
// Reset the debug timer for the Scheduler Thread.
|
||||
// In Production: This is a no-op (0 cost).
|
||||
// In Debug: This tells the clock "I am starting a new tick, don't freeze time."
|
||||
this.processingPacket();
|
||||
|
||||
// Send a transaction at least once a tick, for timer and post check purposes
|
||||
// Don't be the first to send the transaction, or we will stack overflow
|
||||
//
|
||||
// This will only really activate if there's no entities around the player being tracked
|
||||
// 80 is a magic value that is roughly every other tick, we don't want to spam too many packets.
|
||||
if (lastTransSent != 0 && lastTransSent + 80 < System.currentTimeMillis()) {
|
||||
if (lastTransSent != 0 && lastTransSent + 80 < now()) {
|
||||
sendTransaction(true); // send on netty thread
|
||||
}
|
||||
if ((System.nanoTime() - getPlayerClockAtLeast()) > maxTransactionTime * 1e9) {
|
||||
if ((this.nano() - getPlayerClockAtLeast()) > maxTransactionTime * 1e9) {
|
||||
timedOut();
|
||||
}
|
||||
|
||||
@@ -988,4 +999,27 @@ public class GrimPlayer implements GrimUser {
|
||||
|
||||
return blockStateId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current high-resolution time in nanoseconds.
|
||||
* In Debug Mode, this will subtract time spent paused at breakpoints.
|
||||
*/
|
||||
public long nano() {
|
||||
return System.nanoTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current wall-clock time in milliseconds.
|
||||
* In Debug Mode, this will subtract time spent paused at breakpoints.
|
||||
*/
|
||||
public long now() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called immediately when a packet starts processing.
|
||||
* Used by DebugGrimPlayer to differentiate "Lag" (Pre-Packet) from "Breakpoints" (Intra-Packet).
|
||||
* Optimized away (Dead Code Elimination) in production.
|
||||
*/
|
||||
public void processingPacket() {}
|
||||
}
|
||||
@@ -70,13 +70,14 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
|
||||
if (!invalidVehicle && !data.isTeleport()) {
|
||||
// Teleport the player back to avoid players being able to simply ignore transactions
|
||||
player.getSetbackTeleportUtil().executeForceResync();
|
||||
// We shouldn't simulate movement in unloaded chunks
|
||||
player.getSetbackTeleportUtil().executeNonSimulatingForceResync();
|
||||
}
|
||||
}
|
||||
|
||||
long start = System.nanoTime();
|
||||
long start = player.nano();
|
||||
check(data);
|
||||
long length = System.nanoTime() - start;
|
||||
long length = player.nano() - start;
|
||||
|
||||
if (!player.disableGrim) {
|
||||
predictionNanos = (predictionNanos * 499 / 500d) + (length / 500d);
|
||||
@@ -351,7 +352,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
|
||||
boolean clientClaimsRiptide = player.packetStateData.tryingToRiptide;
|
||||
if (player.packetStateData.tryingToRiptide) {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
long currentTime = player.now();
|
||||
boolean isInWater = player.isInWaterOrRain();
|
||||
|
||||
if (currentTime - player.packetStateData.lastRiptide < 450 || !isInWater) {
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import ac.grim.grimac.utils.nmsutil.Collisions;
|
||||
import ac.grim.grimac.utils.nmsutil.FluidFallingAdjustedMovement;
|
||||
import ac.grim.grimac.utils.nmsutil.GetBoundingBox;
|
||||
import ac.grim.grimac.utils.nmsutil.MainSupportingBlockPosFinder;
|
||||
import ac.grim.grimac.utils.reflection.ViaVersionUtil;
|
||||
import ac.grim.grimac.utils.viaversion.ViaVersionUtil;
|
||||
import ac.grim.grimac.utils.team.EntityPredicates;
|
||||
import ac.grim.grimac.utils.team.EntityTeam;
|
||||
import ac.grim.grimac.utils.team.TeamHandler;
|
||||
|
||||
@@ -3,6 +3,8 @@ package ac.grim.grimac.utils.anticheat;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.event.events.GrimJoinEvent;
|
||||
import ac.grim.grimac.api.event.events.GrimQuitEvent;
|
||||
import ac.grim.grimac.checks.debug.DebugGrimPlayer;
|
||||
import ac.grim.grimac.checks.debug.GrimDebugSettings;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.reflection.GeyserUtil;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
@@ -66,12 +68,21 @@ public class PlayerDataManager {
|
||||
|
||||
public void addUser(final @NotNull User user) {
|
||||
if (shouldCheck(user)) {
|
||||
GrimPlayer player = new GrimPlayer(user);
|
||||
GrimPlayer player = this.createPlayer(user);
|
||||
playerDataMap.put(user, player);
|
||||
GrimAPI.INSTANCE.getEventBus().post(new GrimJoinEvent(player));
|
||||
}
|
||||
}
|
||||
|
||||
public GrimPlayer createPlayer(User user) {
|
||||
// Simple Global Check
|
||||
if (GrimDebugSettings.shouldEnable()) {
|
||||
return new DebugGrimPlayer(user);
|
||||
} else {
|
||||
return new GrimPlayer(user);
|
||||
}
|
||||
}
|
||||
|
||||
public GrimPlayer remove(final @NotNull User user) {
|
||||
return playerDataMap.remove(user);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import ac.grim.grimac.utils.collisions.datatypes.NoCollisionBox;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntityStrider;
|
||||
import ac.grim.grimac.utils.nmsutil.Materials;
|
||||
import ac.grim.grimac.utils.reflection.ViaVersionUtil;
|
||||
import ac.grim.grimac.utils.viaversion.ViaVersionUtil;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
|
||||
@@ -29,4 +29,10 @@ public class CommonGrimArguments {
|
||||
* This setting is opt-in (default: false) and requires a server restart to change.
|
||||
*/
|
||||
public final static SystemArgument<Boolean> USE_CHAT_FAST_BYPASS = FACTORY.create(string("ChatFastBypass", true));
|
||||
/**
|
||||
* If TRUE, and a Debugger is detected attached to the JVM, Grim will use the
|
||||
* DebugGrimPlayer implementation which absorbs breakpoint pauses > 200ms.
|
||||
* Default: false (Safety).
|
||||
*/
|
||||
public final static SystemArgument<Boolean> DEBUG_BREAKPOINT_MODE = FACTORY.create(string("DebugBreakpointMode", false));
|
||||
}
|
||||
@@ -287,9 +287,9 @@ public class CompensatedEntities {
|
||||
if (sizeObject != null) {
|
||||
Object value = sizeObject.getValue();
|
||||
if (value instanceof Integer) {
|
||||
sizeable.size = Math.max((int) value, 1);
|
||||
sizeable.size = (int) value;
|
||||
} else if (value instanceof Byte) {
|
||||
sizeable.size = Math.max((byte) value, 1);
|
||||
sizeable.size = (byte) value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,6 +501,7 @@ public class CompensatedInventory extends Check implements PacketCheck {
|
||||
* Closes the player's currently open inventory on the client by resetting to the player's inventory.
|
||||
*/
|
||||
private void closeActiveInventory() {
|
||||
isPacketInventoryActive = true;
|
||||
openWindowID = 0;
|
||||
menu = inventory;
|
||||
menu.setCarried(ItemStack.EMPTY); // Reset carried item
|
||||
|
||||
@@ -27,33 +27,33 @@ public final class BoundingBoxSize {
|
||||
|
||||
private static float getWidthMinusBaby(GrimPlayer player, PacketEntity packetEntity) {
|
||||
final EntityType type = packetEntity.type;
|
||||
if (EntityTypes.AXOLOTL.equals(type)) {
|
||||
if (type == EntityTypes.AXOLOTL) {
|
||||
return 0.75f;
|
||||
} else if (EntityTypes.PANDA.equals(type)) {
|
||||
} else if (type == EntityTypes.PANDA) {
|
||||
return 1.3f;
|
||||
} else if (EntityTypes.BAT.equals(type) || EntityTypes.PARROT.equals(type) || EntityTypes.COD.equals(type) || EntityTypes.EVOKER_FANGS.equals(type) || EntityTypes.TROPICAL_FISH.equals(type) || EntityTypes.FROG.equals(type) || EntityTypes.COPPER_GOLEM.equals(type)) {
|
||||
} else if (type == EntityTypes.BAT || type == EntityTypes.PARROT || type == EntityTypes.COD || type == EntityTypes.EVOKER_FANGS || type == EntityTypes.TROPICAL_FISH || type == EntityTypes.FROG || type == EntityTypes.COPPER_GOLEM) {
|
||||
return 0.5f;
|
||||
} else if (EntityTypes.ARMADILLO.equals(type) || EntityTypes.BEE.equals(type) || EntityTypes.PUFFERFISH.equals(type) || EntityTypes.SALMON.equals(type) || EntityTypes.SNOW_GOLEM.equals(type) || EntityTypes.CAVE_SPIDER.equals(type)) {
|
||||
} else if (type == EntityTypes.ARMADILLO || type == EntityTypes.BEE || type == EntityTypes.PUFFERFISH || type == EntityTypes.SALMON || type == EntityTypes.SNOW_GOLEM || type == EntityTypes.CAVE_SPIDER) {
|
||||
return 0.7f;
|
||||
} else if (EntityTypes.WITHER_SKELETON.equals(type)) {
|
||||
} else if (type == EntityTypes.WITHER_SKELETON) {
|
||||
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? 0.7f : 0.72f;
|
||||
} else if (EntityTypes.WITHER_SKULL.equals(type) || EntityTypes.SHULKER_BULLET.equals(type)) {
|
||||
} else if (type == EntityTypes.WITHER_SKULL || type == EntityTypes.SHULKER_BULLET) {
|
||||
return 0.3125f;
|
||||
} else if (EntityTypes.HOGLIN.equals(type) || EntityTypes.ZOGLIN.equals(type)) {
|
||||
} else if (type == EntityTypes.HOGLIN || type == EntityTypes.ZOGLIN) {
|
||||
return 1.3964844f;
|
||||
} else if (EntityTypes.SKELETON_HORSE.equals(type) || EntityTypes.ZOMBIE_HORSE.equals(type) || EntityTypes.HORSE.equals(type) || EntityTypes.DONKEY.equals(type) || EntityTypes.MULE.equals(type)) {
|
||||
} else if (type == EntityTypes.SKELETON_HORSE || type == EntityTypes.ZOMBIE_HORSE || type == EntityTypes.HORSE || type == EntityTypes.DONKEY || type == EntityTypes.MULE) {
|
||||
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? 1.3964844f : 1.4f;
|
||||
} else if (EntityTypes.isTypeInstanceOf(type, EntityTypes.BOAT)) {
|
||||
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? 1.375f : 1.5f;
|
||||
} else if (EntityTypes.HAPPY_GHAST.equals(type)) {
|
||||
} else if (type == EntityTypes.HAPPY_GHAST) {
|
||||
return 4.0f;
|
||||
} else if (EntityTypes.CHICKEN.equals(type) || EntityTypes.ENDERMITE.equals(type) || EntityTypes.SILVERFISH.equals(type) || EntityTypes.VEX.equals(type) || EntityTypes.TADPOLE.equals(type)) {
|
||||
} else if (type == EntityTypes.CHICKEN || type == EntityTypes.ENDERMITE || type == EntityTypes.SILVERFISH || type == EntityTypes.VEX || type == EntityTypes.TADPOLE) {
|
||||
return 0.4f;
|
||||
} else if (EntityTypes.RABBIT.equals(type)) {
|
||||
} else if (type == EntityTypes.RABBIT) {
|
||||
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? 0.4f : 0.6f;
|
||||
} else if (EntityTypes.CREAKING.equals(type) || EntityTypes.STRIDER.equals(type) || EntityTypes.COW.equals(type) || EntityTypes.SHEEP.equals(type) || EntityTypes.MOOSHROOM.equals(type) || EntityTypes.PIG.equals(type) || EntityTypes.LLAMA.equals(type) || EntityTypes.DOLPHIN.equals(type) || EntityTypes.WITHER.equals(type) || EntityTypes.TRADER_LLAMA.equals(type) || EntityTypes.WARDEN.equals(type) || EntityTypes.GOAT.equals(type)) {
|
||||
} else if (type == EntityTypes.CREAKING || type == EntityTypes.STRIDER || type == EntityTypes.COW || type == EntityTypes.SHEEP || type == EntityTypes.MOOSHROOM || type == EntityTypes.PIG || type == EntityTypes.LLAMA || type == EntityTypes.DOLPHIN || type == EntityTypes.WITHER || type == EntityTypes.TRADER_LLAMA || type == EntityTypes.WARDEN || type == EntityTypes.GOAT) {
|
||||
return 0.9f;
|
||||
} else if (EntityTypes.PHANTOM.equals(type)) {
|
||||
} else if (type == EntityTypes.PHANTOM) {
|
||||
if (packetEntity instanceof PacketEntitySizeable sizeable) {
|
||||
return 0.9f + sizeable.size * 0.2f;
|
||||
}
|
||||
@@ -61,21 +61,21 @@ public final class BoundingBoxSize {
|
||||
return 1.5f;
|
||||
} else if (packetEntity instanceof PacketEntityGuardian packetEntityGuardian) { // TODO: 2.35 * guardian?
|
||||
return packetEntityGuardian.isElder ? 1.9975f : 0.85f;
|
||||
} else if (EntityTypes.END_CRYSTAL.equals(type)) {
|
||||
} else if (type == EntityTypes.END_CRYSTAL) {
|
||||
return 2f;
|
||||
} else if (EntityTypes.ENDER_DRAGON.equals(type)) {
|
||||
} else if (type == EntityTypes.ENDER_DRAGON) {
|
||||
return 16f;
|
||||
} else if (EntityTypes.FIREBALL.equals(type)) {
|
||||
} else if (type == EntityTypes.FIREBALL) {
|
||||
return 1f;
|
||||
} else if (EntityTypes.GHAST.equals(type)) {
|
||||
} else if (type == EntityTypes.GHAST) {
|
||||
return 4f;
|
||||
} else if (EntityTypes.GIANT.equals(type)) {
|
||||
} else if (type == EntityTypes.GIANT) {
|
||||
return 3.6f;
|
||||
} else if (EntityTypes.GUARDIAN.equals(type)) {
|
||||
} else if (type == EntityTypes.GUARDIAN) {
|
||||
return 0.85f;
|
||||
} else if (EntityTypes.IRON_GOLEM.equals(type)) {
|
||||
} else if (type == EntityTypes.IRON_GOLEM) {
|
||||
return 1.4f;
|
||||
} else if (EntityTypes.MAGMA_CUBE.equals(type)) {
|
||||
} else if (type == EntityTypes.MAGMA_CUBE) {
|
||||
if (packetEntity instanceof PacketEntitySizeable sizeable) {
|
||||
float size = sizeable.size;
|
||||
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_20_5)
|
||||
@@ -87,15 +87,15 @@ public final class BoundingBoxSize {
|
||||
return 0.98f;
|
||||
} else if (EntityTypes.isTypeInstanceOf(type, EntityTypes.MINECART_ABSTRACT)) {
|
||||
return 0.98f;
|
||||
} else if (EntityTypes.PLAYER.equals(type) || EntityTypes.MANNEQUIN.equals(type)) {
|
||||
} else if (type == EntityTypes.PLAYER || type == EntityTypes.MANNEQUIN) {
|
||||
return 0.6f;
|
||||
} else if (EntityTypes.POLAR_BEAR.equals(type)) {
|
||||
} else if (type == EntityTypes.POLAR_BEAR) {
|
||||
return 1.4f;
|
||||
} else if (EntityTypes.RAVAGER.equals(type)) {
|
||||
} else if (type == EntityTypes.RAVAGER) {
|
||||
return 1.95f;
|
||||
} else if (EntityTypes.SHULKER.equals(type)) {
|
||||
} else if (type == EntityTypes.SHULKER) {
|
||||
return 1f;
|
||||
} else if (EntityTypes.SLIME.equals(type)) {
|
||||
} else if (type == EntityTypes.SLIME) {
|
||||
if (packetEntity instanceof PacketEntitySizeable sizeable) {
|
||||
float size = sizeable.size;
|
||||
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_20_5)
|
||||
@@ -104,27 +104,27 @@ public final class BoundingBoxSize {
|
||||
}
|
||||
|
||||
return 0.3125f;
|
||||
} else if (EntityTypes.SMALL_FIREBALL.equals(type)) {
|
||||
} else if (type == EntityTypes.SMALL_FIREBALL) {
|
||||
return 0.3125f;
|
||||
} else if (EntityTypes.SPIDER.equals(type)) {
|
||||
} else if (type == EntityTypes.SPIDER) {
|
||||
return 1.4f;
|
||||
} else if (EntityTypes.SQUID.equals(type)) {
|
||||
} else if (type == EntityTypes.SQUID) {
|
||||
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? 0.8f : 0.95f;
|
||||
} else if (EntityTypes.TURTLE.equals(type)) {
|
||||
} else if (type == EntityTypes.TURTLE) {
|
||||
return 1.2f;
|
||||
} else if (EntityTypes.ALLAY.equals(type)) {
|
||||
} else if (type == EntityTypes.ALLAY) {
|
||||
return 0.35f;
|
||||
} else if (EntityTypes.SNIFFER.equals(type)) {
|
||||
} else if (type == EntityTypes.SNIFFER) {
|
||||
return 1.9f;
|
||||
} else if (EntityTypes.CAMEL.equals(type)) {
|
||||
} else if (type == EntityTypes.CAMEL) {
|
||||
return 1.7f;
|
||||
} else if (EntityTypes.WIND_CHARGE.equals(type)) {
|
||||
} else if (type == EntityTypes.WIND_CHARGE) {
|
||||
return 0.3125f;
|
||||
} else if (EntityTypes.ARMOR_STAND.equals(type)) {
|
||||
} else if (type == EntityTypes.ARMOR_STAND) {
|
||||
return 0.5F;
|
||||
} else if (EntityTypes.FALLING_BLOCK.equals(type)) {
|
||||
} else if (type == EntityTypes.FALLING_BLOCK) {
|
||||
return 0.98F;
|
||||
} else if (EntityTypes.FIREWORK_ROCKET.equals(type)) {
|
||||
} else if (type == EntityTypes.FIREWORK_ROCKET) {
|
||||
return 0.25F;
|
||||
}
|
||||
return 0.6f;
|
||||
@@ -191,15 +191,15 @@ public final class BoundingBoxSize {
|
||||
|
||||
public static double getMyRidingOffset(PacketEntity packetEntity) {
|
||||
final EntityType type = packetEntity.type;
|
||||
if (EntityTypes.PIGLIN.equals(type) || EntityTypes.ZOMBIFIED_PIGLIN.equals(type) || EntityTypes.ZOMBIE.equals(type)) {
|
||||
if (type == EntityTypes.PIGLIN || type == EntityTypes.ZOMBIFIED_PIGLIN || type == EntityTypes.ZOMBIE) {
|
||||
return packetEntity.isBaby ? -0.05 : -0.45;
|
||||
} else if (EntityTypes.SKELETON.equals(type)) {
|
||||
} else if (type == EntityTypes.SKELETON) {
|
||||
return -0.6;
|
||||
} else if (EntityTypes.ENDERMITE.equals(type) || EntityTypes.SILVERFISH.equals(type)) {
|
||||
} else if (type == EntityTypes.ENDERMITE || type == EntityTypes.SILVERFISH) {
|
||||
return 0.1;
|
||||
} else if (EntityTypes.EVOKER.equals(type) || EntityTypes.ILLUSIONER.equals(type) || EntityTypes.PILLAGER.equals(type) || EntityTypes.RAVAGER.equals(type) || EntityTypes.VINDICATOR.equals(type) || EntityTypes.WITCH.equals(type)) {
|
||||
} else if (type == EntityTypes.EVOKER || type == EntityTypes.ILLUSIONER || type == EntityTypes.PILLAGER || type == EntityTypes.RAVAGER || type == EntityTypes.VINDICATOR || type == EntityTypes.WITCH) {
|
||||
return -0.45;
|
||||
} else if (EntityTypes.PLAYER.equals(type) || EntityTypes.MANNEQUIN.equals(type)) {
|
||||
} else if (type == EntityTypes.PLAYER || type == EntityTypes.MANNEQUIN) {
|
||||
return -0.35;
|
||||
}
|
||||
|
||||
@@ -219,21 +219,21 @@ public final class BoundingBoxSize {
|
||||
return 0;
|
||||
} else if (EntityTypes.isTypeInstanceOf(type, EntityTypes.BOAT)) {
|
||||
return -0.1;
|
||||
} else if (EntityTypes.HAPPY_GHAST.equals(type)) {
|
||||
} else if (type == EntityTypes.HAPPY_GHAST) {
|
||||
return 0.5;
|
||||
} else if (EntityTypes.HOGLIN.equals(type) || EntityTypes.ZOGLIN.equals(type)) {
|
||||
} else if (type == EntityTypes.HOGLIN || type == EntityTypes.ZOGLIN) {
|
||||
return getHeight(player, packetEntity) - (packetEntity.isBaby ? 0.2 : 0.15);
|
||||
} else if (EntityTypes.LLAMA.equals(type)) {
|
||||
} else if (type == EntityTypes.LLAMA) {
|
||||
return getHeight(player, packetEntity) * 0.67;
|
||||
} else if (EntityTypes.PIGLIN.equals(type)) {
|
||||
} else if (type == EntityTypes.PIGLIN) {
|
||||
return getHeight(player, packetEntity) * 0.92;
|
||||
} else if (EntityTypes.RAVAGER.equals(type)) {
|
||||
} else if (type == EntityTypes.RAVAGER) {
|
||||
return 2.1;
|
||||
} else if (EntityTypes.SKELETON.equals(type)) {
|
||||
} else if (type == EntityTypes.SKELETON) {
|
||||
return (getHeight(player, packetEntity) * 0.75) - 0.1875;
|
||||
} else if (EntityTypes.SPIDER.equals(type)) {
|
||||
} else if (type == EntityTypes.SPIDER) {
|
||||
return getHeight(player, packetEntity) * 0.5;
|
||||
} else if (EntityTypes.STRIDER.equals(type)) {// depends on animation position, good luck getting it exactly, this is the best you can do though
|
||||
} else if (type == EntityTypes.STRIDER) {// depends on animation position, good luck getting it exactly, this is the best you can do though
|
||||
return getHeight(player, packetEntity) - 0.19;
|
||||
}
|
||||
return getHeight(player, packetEntity) * 0.75;
|
||||
@@ -241,77 +241,77 @@ public final class BoundingBoxSize {
|
||||
|
||||
private static float getHeightMinusBaby(GrimPlayer player, PacketEntity packetEntity) {
|
||||
final EntityType type = packetEntity.type;
|
||||
if (EntityTypes.ARMADILLO.equals(type)) {
|
||||
if (type == EntityTypes.ARMADILLO) {
|
||||
return 0.65f;
|
||||
} else if (EntityTypes.AXOLOTL.equals(type)) {
|
||||
} else if (type == EntityTypes.AXOLOTL) {
|
||||
return 0.42f;
|
||||
} else if (EntityTypes.BEE.equals(type) || EntityTypes.DOLPHIN.equals(type) || EntityTypes.ALLAY.equals(type)) {
|
||||
} else if (type == EntityTypes.BEE || type == EntityTypes.DOLPHIN || type == EntityTypes.ALLAY) {
|
||||
return 0.6f;
|
||||
} else if (EntityTypes.EVOKER_FANGS.equals(type) || EntityTypes.VEX.equals(type)) {
|
||||
} else if (type == EntityTypes.EVOKER_FANGS || type == EntityTypes.VEX) {
|
||||
return 0.8f;
|
||||
} else if (EntityTypes.SQUID.equals(type)) {
|
||||
} else if (type == EntityTypes.SQUID) {
|
||||
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? 0.8f : 0.95f;
|
||||
} else if (EntityTypes.PARROT.equals(type) || EntityTypes.BAT.equals(type) || EntityTypes.PIG.equals(type) || EntityTypes.SPIDER.equals(type)) {
|
||||
} else if (type == EntityTypes.PARROT || type == EntityTypes.BAT || type == EntityTypes.PIG || type == EntityTypes.SPIDER) {
|
||||
return 0.9f;
|
||||
} else if (EntityTypes.WITHER_SKULL.equals(type) || EntityTypes.SHULKER_BULLET.equals(type)) {
|
||||
} else if (type == EntityTypes.WITHER_SKULL || type == EntityTypes.SHULKER_BULLET) {
|
||||
return 0.3125f;
|
||||
} else if (EntityTypes.BLAZE.equals(type)) {
|
||||
} else if (type == EntityTypes.BLAZE) {
|
||||
return 1.8f;
|
||||
} else if (EntityTypes.isTypeInstanceOf(type, EntityTypes.BOAT)) {
|
||||
// WHY DOES VIAVERSION OFFSET BOATS? THIS MAKES IT HARD TO SUPPORT, EVEN IF WE INTERPOLATE RIGHT.
|
||||
// I gave up and just exempted boats from the reach check and gave up with interpolation for collisions
|
||||
return 0.5625f;
|
||||
} else if (EntityTypes.HAPPY_GHAST.equals(type)) {
|
||||
} else if (type == EntityTypes.HAPPY_GHAST) {
|
||||
return 4.0f;
|
||||
} else if (EntityTypes.CAT.equals(type)) {
|
||||
} else if (type == EntityTypes.CAT) {
|
||||
return 0.7f;
|
||||
} else if (EntityTypes.CAVE_SPIDER.equals(type)) {
|
||||
} else if (type == EntityTypes.CAVE_SPIDER) {
|
||||
return 0.5f;
|
||||
} else if (EntityTypes.FROG.equals(type)) {
|
||||
} else if (type == EntityTypes.FROG) {
|
||||
return 0.55f;
|
||||
} else if (EntityTypes.CHICKEN.equals(type)) {
|
||||
} else if (type == EntityTypes.CHICKEN) {
|
||||
return 0.7f;
|
||||
} else if (EntityTypes.HOGLIN.equals(type) || EntityTypes.ZOGLIN.equals(type)) {
|
||||
} else if (type == EntityTypes.HOGLIN || type == EntityTypes.ZOGLIN) {
|
||||
return 1.4f;
|
||||
} else if (EntityTypes.COW.equals(type)) {
|
||||
} else if (type == EntityTypes.COW) {
|
||||
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? 1.4f : 1.3f;
|
||||
} else if (EntityTypes.STRIDER.equals(type)) {
|
||||
} else if (type == EntityTypes.STRIDER) {
|
||||
return 1.7f;
|
||||
} else if (EntityTypes.CREEPER.equals(type)) {
|
||||
} else if (type == EntityTypes.CREEPER) {
|
||||
return 1.7f;
|
||||
} else if (EntityTypes.DONKEY.equals(type)) {
|
||||
} else if (type == EntityTypes.DONKEY) {
|
||||
return 1.5f;
|
||||
} else if (packetEntity instanceof PacketEntityGuardian packetEntityGuardian) { // TODO: 2.35 * guardian?
|
||||
return packetEntityGuardian.isElder ? 1.9975f : 0.85f;
|
||||
} else if (EntityTypes.ENDERMAN.equals(type) || EntityTypes.WARDEN.equals(type)) {
|
||||
} else if (type == EntityTypes.ENDERMAN || type == EntityTypes.WARDEN) {
|
||||
return 2.9f;
|
||||
} else if (EntityTypes.ENDERMITE.equals(type) || EntityTypes.COD.equals(type)) {
|
||||
} else if (type == EntityTypes.ENDERMITE || type == EntityTypes.COD) {
|
||||
return 0.3f;
|
||||
} else if (EntityTypes.END_CRYSTAL.equals(type)) {
|
||||
} else if (type == EntityTypes.END_CRYSTAL) {
|
||||
return 2f;
|
||||
} else if (EntityTypes.ENDER_DRAGON.equals(type)) {
|
||||
} else if (type == EntityTypes.ENDER_DRAGON) {
|
||||
return 8f;
|
||||
} else if (EntityTypes.FIREBALL.equals(type)) {
|
||||
} else if (type == EntityTypes.FIREBALL) {
|
||||
return 1f;
|
||||
} else if (EntityTypes.FOX.equals(type)) {
|
||||
} else if (type == EntityTypes.FOX) {
|
||||
return 0.7f;
|
||||
} else if (EntityTypes.GHAST.equals(type)) {
|
||||
} else if (type == EntityTypes.GHAST) {
|
||||
return 4f;
|
||||
} else if (EntityTypes.GIANT.equals(type)) {
|
||||
} else if (type == EntityTypes.GIANT) {
|
||||
return 12f;
|
||||
} else if (EntityTypes.GUARDIAN.equals(type)) {
|
||||
} else if (type == EntityTypes.GUARDIAN) {
|
||||
return 0.85f;
|
||||
} else if (EntityTypes.HORSE.equals(type)) {
|
||||
} else if (type == EntityTypes.HORSE) {
|
||||
return 1.6f;
|
||||
} else if (EntityTypes.IRON_GOLEM.equals(type)) {
|
||||
} else if (type == EntityTypes.IRON_GOLEM) {
|
||||
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? 2.7f : 2.9f;
|
||||
} else if (EntityTypes.CREAKING.equals(type)) {
|
||||
} else if (type == EntityTypes.CREAKING) {
|
||||
return 2.7f;
|
||||
} else if (EntityTypes.LLAMA.equals(type) || EntityTypes.TRADER_LLAMA.equals(type)) {
|
||||
} else if (type == EntityTypes.LLAMA || type == EntityTypes.TRADER_LLAMA) {
|
||||
return 1.87f;
|
||||
} else if (EntityTypes.TROPICAL_FISH.equals(type)) {
|
||||
} else if (type == EntityTypes.TROPICAL_FISH) {
|
||||
return 0.4f;
|
||||
} else if (EntityTypes.MAGMA_CUBE.equals(type)) {
|
||||
} else if (type == EntityTypes.MAGMA_CUBE) {
|
||||
if (packetEntity instanceof PacketEntitySizeable sizeable) {
|
||||
float size = sizeable.size;
|
||||
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_20_5)
|
||||
@@ -323,43 +323,43 @@ public final class BoundingBoxSize {
|
||||
return 0.7f;
|
||||
} else if (EntityTypes.isTypeInstanceOf(type, EntityTypes.MINECART_ABSTRACT)) {
|
||||
return 0.7f;
|
||||
} else if (EntityTypes.MULE.equals(type)) {
|
||||
} else if (type == EntityTypes.MULE) {
|
||||
return 1.6f;
|
||||
} else if (EntityTypes.MOOSHROOM.equals(type)) {
|
||||
} else if (type == EntityTypes.MOOSHROOM) {
|
||||
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? 1.4f : 1.3f;
|
||||
} else if (EntityTypes.OCELOT.equals(type)) {
|
||||
} else if (type == EntityTypes.OCELOT) {
|
||||
return 0.7f;
|
||||
} else if (EntityTypes.PANDA.equals(type)) {
|
||||
} else if (type == EntityTypes.PANDA) {
|
||||
return 1.25f;
|
||||
} else if (EntityTypes.PHANTOM.equals(type)) {
|
||||
} else if (type == EntityTypes.PHANTOM) {
|
||||
if (packetEntity instanceof PacketEntitySizeable sizeable) {
|
||||
return 0.5f + sizeable.size * 0.1f;
|
||||
}
|
||||
|
||||
return 1.8f;
|
||||
} else if (EntityTypes.PLAYER.equals(type) || EntityTypes.MANNEQUIN.equals(type)) {
|
||||
} else if (type == EntityTypes.PLAYER || type == EntityTypes.MANNEQUIN) {
|
||||
return 1.8f;
|
||||
} else if (EntityTypes.POLAR_BEAR.equals(type)) {
|
||||
} else if (type == EntityTypes.POLAR_BEAR) {
|
||||
return 1.4f;
|
||||
} else if (EntityTypes.PUFFERFISH.equals(type)) {
|
||||
} else if (type == EntityTypes.PUFFERFISH) {
|
||||
return 0.7f;
|
||||
} else if (EntityTypes.RABBIT.equals(type)) {
|
||||
} else if (type == EntityTypes.RABBIT) {
|
||||
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? 0.5f : 0.7f;
|
||||
} else if (EntityTypes.RAVAGER.equals(type)) {
|
||||
} else if (type == EntityTypes.RAVAGER) {
|
||||
return 2.2f;
|
||||
} else if (EntityTypes.SALMON.equals(type)) {
|
||||
} else if (type == EntityTypes.SALMON) {
|
||||
return 0.4f;
|
||||
} else if (EntityTypes.SHEEP.equals(type) || EntityTypes.GOAT.equals(type)) {
|
||||
} else if (type == EntityTypes.SHEEP || type == EntityTypes.GOAT) {
|
||||
return 1.3f;
|
||||
} else if (EntityTypes.SHULKER.equals(type)) { // Could maybe guess peek size, although seems useless
|
||||
} else if (type == EntityTypes.SHULKER) { // Could maybe guess peek size, although seems useless
|
||||
return 2f;
|
||||
} else if (EntityTypes.SILVERFISH.equals(type)) {
|
||||
} else if (type == EntityTypes.SILVERFISH) {
|
||||
return 0.3f;
|
||||
} else if (EntityTypes.SKELETON.equals(type)) {
|
||||
} else if (type == EntityTypes.SKELETON) {
|
||||
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? 1.99f : 1.95f;
|
||||
} else if (EntityTypes.SKELETON_HORSE.equals(type)) {
|
||||
} else if (type == EntityTypes.SKELETON_HORSE) {
|
||||
return 1.6f;
|
||||
} else if (EntityTypes.SLIME.equals(type)) {
|
||||
} else if (type == EntityTypes.SLIME) {
|
||||
if (packetEntity instanceof PacketEntitySizeable sizeable) {
|
||||
float size = sizeable.size;
|
||||
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_20_5)
|
||||
@@ -369,43 +369,43 @@ public final class BoundingBoxSize {
|
||||
}
|
||||
|
||||
return 0.3125f;
|
||||
} else if (EntityTypes.SMALL_FIREBALL.equals(type)) {
|
||||
} else if (type == EntityTypes.SMALL_FIREBALL) {
|
||||
return 0.3125f;
|
||||
} else if (EntityTypes.SNOW_GOLEM.equals(type)) {
|
||||
} else if (type == EntityTypes.SNOW_GOLEM) {
|
||||
return 1.9f;
|
||||
} else if (EntityTypes.STRAY.equals(type)) {
|
||||
} else if (type == EntityTypes.STRAY) {
|
||||
return 1.99f;
|
||||
} else if (EntityTypes.TURTLE.equals(type)) {
|
||||
} else if (type == EntityTypes.TURTLE) {
|
||||
return 0.4f;
|
||||
} else if (EntityTypes.WITHER.equals(type)) {
|
||||
} else if (type == EntityTypes.WITHER) {
|
||||
return 3.5f;
|
||||
} else if (EntityTypes.WITHER_SKELETON.equals(type)) {
|
||||
} else if (type == EntityTypes.WITHER_SKELETON) {
|
||||
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? 2.4f : 2.535f;
|
||||
} else if (EntityTypes.WOLF.equals(type)) {
|
||||
} else if (type == EntityTypes.WOLF) {
|
||||
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? 0.85f : 0.8f;
|
||||
} else if (EntityTypes.ZOMBIE_HORSE.equals(type)) {
|
||||
} else if (type == EntityTypes.ZOMBIE_HORSE) {
|
||||
return 1.6f;
|
||||
} else if (EntityTypes.TADPOLE.equals(type)) {
|
||||
} else if (type == EntityTypes.TADPOLE) {
|
||||
return 0.3f;
|
||||
} else if (EntityTypes.SNIFFER.equals(type)) {
|
||||
} else if (type == EntityTypes.SNIFFER) {
|
||||
return 1.75f;
|
||||
} else if (EntityTypes.CAMEL.equals(type)) {
|
||||
} else if (type == EntityTypes.CAMEL) {
|
||||
return 2.375f;
|
||||
} else if (EntityTypes.BREEZE.equals(type)) {
|
||||
} else if (type == EntityTypes.BREEZE) {
|
||||
return 1.77f;
|
||||
} else if (EntityTypes.BOGGED.equals(type)) {
|
||||
} else if (type == EntityTypes.BOGGED) {
|
||||
return 1.99f;
|
||||
} else if (EntityTypes.WIND_CHARGE.equals(type)) {
|
||||
} else if (type == EntityTypes.WIND_CHARGE) {
|
||||
return 0.3125f;
|
||||
} else if (EntityTypes.ARMOR_STAND.equals(type)) {
|
||||
} else if (type == EntityTypes.ARMOR_STAND) {
|
||||
return 1.975F;
|
||||
} else if (EntityTypes.FALLING_BLOCK.equals(type)) {
|
||||
} else if (type == EntityTypes.FALLING_BLOCK) {
|
||||
return 0.98F;
|
||||
} else if (EntityTypes.VILLAGER.equals(type) && player.getClientVersion().isOlderThan(ClientVersion.V_1_9)) {
|
||||
} else if (type == EntityTypes.VILLAGER && player.getClientVersion().isOlderThan(ClientVersion.V_1_9)) {
|
||||
return 1.8F;
|
||||
} else if (EntityTypes.FIREWORK_ROCKET.equals(type)) {
|
||||
} else if (type == EntityTypes.FIREWORK_ROCKET) {
|
||||
return 0.25F;
|
||||
} else if (EntityTypes.COPPER_GOLEM.equals(type)) {
|
||||
} else if (type == EntityTypes.COPPER_GOLEM) {
|
||||
return 1.0F;
|
||||
}
|
||||
return 1.95f;
|
||||
|
||||
@@ -51,7 +51,17 @@ public class GetBoundingBox {
|
||||
double minZ = centerZ - (width / 2f);
|
||||
double maxZ = centerZ + (width / 2f);
|
||||
|
||||
return new SimpleCollisionBox(minX, minY, minZ, maxX, maxY, maxZ, false);
|
||||
// it's possible for width and/or height to be negative,
|
||||
// correct the order of min and max
|
||||
return new SimpleCollisionBox(
|
||||
Math.min(minX, maxX),
|
||||
Math.min(minY, maxY),
|
||||
Math.min(minZ, maxZ),
|
||||
Math.max(minX, maxX),
|
||||
Math.max(minY, maxY),
|
||||
Math.max(minZ, maxZ),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
public static double @NotNull [] getEntityDimensions(GrimPlayer player, @NotNull PacketEntity entity) {
|
||||
@@ -67,11 +77,20 @@ public class GetBoundingBox {
|
||||
double height = dimensions[1];
|
||||
double halfDepth = dimensions[2] / 2.0;
|
||||
|
||||
box.minX -= halfWidth;
|
||||
box.minY -= 0; // No downward expansion
|
||||
box.minZ -= halfDepth;
|
||||
box.maxX += halfWidth;
|
||||
box.maxY += height;
|
||||
box.maxZ += halfDepth;
|
||||
double minX = box.minX - halfWidth;
|
||||
double minY = box.minY; // No downward expansion
|
||||
double minZ = box.minZ - halfDepth;
|
||||
double maxX = box.maxX + halfWidth;
|
||||
double maxY = box.maxY + height;
|
||||
double maxZ = box.maxZ + halfDepth;
|
||||
|
||||
// it's possible for width and/or height to be negative,
|
||||
// correct the order of min and max
|
||||
box.minX = Math.min(minX, maxX);
|
||||
box.minY = Math.min(minY, maxY);
|
||||
box.minZ = Math.min(minZ, maxZ);
|
||||
box.maxX = Math.max(minX, maxX);
|
||||
box.maxY = Math.max(minY, maxY);
|
||||
box.maxZ = Math.max(minZ, maxZ);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package ac.grim.grimac.utils.payload;
|
||||
|
||||
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.ApiStatus.NonExtendable;
|
||||
import org.jetbrains.annotations.ApiStatus.OverrideOnly;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.github.retrooper.packetevents.netty.buffer.UnpooledByteBufAllocationHelper.buffer;
|
||||
import static com.github.retrooper.packetevents.netty.buffer.UnpooledByteBufAllocationHelper.wrappedBuffer;
|
||||
import static com.github.retrooper.packetevents.wrapper.PacketWrapper.createUniversalPacketWrapper;
|
||||
|
||||
public interface Payload {
|
||||
@NonExtendable
|
||||
default byte[] write() {
|
||||
Object buffer = buffer();
|
||||
write(createUniversalPacketWrapper(buffer));
|
||||
return ByteBufHelper.array(buffer);
|
||||
}
|
||||
|
||||
@OverrideOnly
|
||||
void write(PacketWrapper<?> wrapper);
|
||||
|
||||
static @NotNull PacketWrapper<?> wrapper(byte[] data) {
|
||||
return createUniversalPacketWrapper(wrappedBuffer(data));
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,20 @@
|
||||
package ac.grim.grimac.utils.payload;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEditBook;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Payload wrapper for {@code MC|BEdit} and {@code MC|BSign}
|
||||
* Payload wrapper for serverbound {@code MC|BEdit} and {@code MC|BSign}, replaced by the {@link WrapperPlayClientEditBook EDIT_BOOK} packet in 1.13
|
||||
*/
|
||||
public record PayloadBookEdit(ItemStack itemStack) {
|
||||
public static final PayloadCodec<PayloadBookEdit> CODEC = new PayloadCodec<>(
|
||||
wrapper -> new PayloadBookEdit(wrapper.readItemStack()),
|
||||
(wrapper, payload) -> wrapper.writeItemStack(payload.itemStack)
|
||||
);
|
||||
public record PayloadBookEdit(@NotNull ItemStack itemStack) implements Payload {
|
||||
public PayloadBookEdit(byte[] data) {
|
||||
this(Payload.wrapper(data).readItemStack());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketWrapper<?> wrapper) {
|
||||
wrapper.writeItemStack(itemStack);
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package ac.grim.grimac.utils.payload;
|
||||
|
||||
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static com.github.retrooper.packetevents.netty.buffer.UnpooledByteBufAllocationHelper.buffer;
|
||||
import static com.github.retrooper.packetevents.netty.buffer.UnpooledByteBufAllocationHelper.copiedBuffer;
|
||||
import static com.github.retrooper.packetevents.wrapper.PacketWrapper.createUniversalPacketWrapper;
|
||||
|
||||
public final class PayloadCodec<P> {
|
||||
private final Function<PacketWrapper<?>, P> reader;
|
||||
private final BiConsumer<PacketWrapper<?>, P> writer;
|
||||
|
||||
@Contract(pure = true)
|
||||
public PayloadCodec(Function<PacketWrapper<?>, P> reader, BiConsumer<PacketWrapper<?>, P> writer) {
|
||||
this.reader = reader;
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
public P read(byte[] data) {
|
||||
Object buffer = copiedBuffer(data);
|
||||
P payload = reader.apply(createUniversalPacketWrapper(buffer));
|
||||
ByteBufHelper.release(buffer);
|
||||
return payload;
|
||||
}
|
||||
|
||||
public byte @NotNull [] write(P payload) {
|
||||
Object buffer = buffer();
|
||||
writer.accept(createUniversalPacketWrapper(buffer), payload);
|
||||
byte[] bytes = ByteBufHelper.array(buffer);
|
||||
ByteBufHelper.release(buffer);
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,19 @@
|
||||
package ac.grim.grimac.utils.payload;
|
||||
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientNameItem;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public record PayloadItemName(@NotNull String itemName) {
|
||||
public static final PayloadCodec<PayloadItemName> CODEC = new PayloadCodec<>(
|
||||
wrapper -> new PayloadItemName(wrapper.readString()),
|
||||
(wrapper, payload) -> wrapper.writeString(payload.itemName)
|
||||
);
|
||||
/**
|
||||
* Payload wrapper for serverbound {@code MC|ItemName}, replaced by the {@link WrapperPlayClientNameItem NAME_ITEM} packet in 1.13
|
||||
*/
|
||||
public record PayloadItemName(@NotNull String itemName) implements Payload {
|
||||
public PayloadItemName(byte[] data) {
|
||||
this(Payload.wrapper(data).readString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketWrapper<?> wrapper) {
|
||||
wrapper.writeString(itemName);
|
||||
}
|
||||
}
|
||||
+19
-4
@@ -1,19 +1,34 @@
|
||||
package ac.grim.grimac.utils.via;
|
||||
package ac.grim.grimac.utils.viaversion;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.checks.impl.chat.ChatB;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.protocols.v1_10to1_11.Protocol1_10To1_11;
|
||||
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ServerboundPackets1_9_3;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ViaHooks {
|
||||
public static void injectVia() {
|
||||
final var protocol = Via.getManager().getProtocolManager().getProtocol(Protocol1_10To1_11.class);
|
||||
@UtilityClass
|
||||
class ViaVersionHooks {
|
||||
// this method's only purpose is getting <clinit> called
|
||||
static void load() {}
|
||||
|
||||
static {
|
||||
inject1_11ChatHook();
|
||||
}
|
||||
|
||||
private static void inject1_11ChatHook() {
|
||||
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_11)) {
|
||||
return; // not needed
|
||||
}
|
||||
|
||||
final Protocol1_10To1_11 protocol = Via.getManager().getProtocolManager().getProtocol(Protocol1_10To1_11.class);
|
||||
if (protocol == null) {
|
||||
LogUtil.warn("Failed to inject ViaVersion message hook for 1.11+ clients: Protocol1_10To1_11 isn't registered!");
|
||||
return;
|
||||
+6
-1
@@ -1,6 +1,7 @@
|
||||
package ac.grim.grimac.utils.reflection;
|
||||
package ac.grim.grimac.utils.viaversion;
|
||||
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import ac.grim.grimac.utils.reflection.ReflectionUtils;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
@UtilityClass
|
||||
@@ -12,4 +13,8 @@ public class ViaVersionUtil {
|
||||
LogUtil.error("Using unsupported ViaVersion 4.0 API, update ViaVersion to 5.0");
|
||||
}
|
||||
}
|
||||
|
||||
public static void injectHooks() {
|
||||
if (isAvailable) ViaVersionHooks.load();
|
||||
}
|
||||
}
|
||||
@@ -218,9 +218,9 @@ history:
|
||||
# Welcher Servername soll für den History‑Befehl eingetragen werden? Nützlich, wenn dieselbe Datenbank für mehrere Server verwendet wird
|
||||
server-name: Prison
|
||||
database:
|
||||
# SQLITE für lokale Speicherung, MYSQL für eine externe MySQL‑Datenbank. Wird nur nach Serverneustart aktualisiert
|
||||
# SQLITE für lokale Speicherung, MYSQL oder POSTGRESQL für eine externe Datenbank. Wird nur nach Serverneustart aktualisiert
|
||||
type: SQLITE
|
||||
# MySQL‑Verbindungsdetails
|
||||
# Datenbank verbindungsdetails
|
||||
host: localhost
|
||||
port: 3306
|
||||
database: grim
|
||||
|
||||
@@ -218,9 +218,9 @@ history:
|
||||
# What should the inserted server name be for the history command? This is useful if you use the same database for multiple servers
|
||||
server-name: Prison
|
||||
database:
|
||||
# Use SQLITE for local storage, use MYSQL if you have an external MySQL database. This is only updated on server restart
|
||||
# Use SQLITE for local storage, use MYSQL or POSTGRESQL if you have an external database. This is only updated on server restart
|
||||
type: SQLITE
|
||||
# MySQL connection details
|
||||
# database connection details
|
||||
host: localhost
|
||||
port: 3306
|
||||
database: grim
|
||||
|
||||
@@ -220,9 +220,9 @@ history:
|
||||
# ¿Qué nombre de servidor debe insertarse para el comando history? Útil si compartes la misma base de datos entre varios servidores
|
||||
server-name: Prison
|
||||
database:
|
||||
# Usa SQLITE para almacenamiento local o MYSQL si tienes una base de datos MySQL externa. Solo se actualiza al reiniciar el servidor
|
||||
# Use SQLITE para almacenamiento local, use MYSQL o POSTGRESQL si tiene una base de datos externa. Esto solo se actualiza al reiniciar el servidor
|
||||
type: SQLITE
|
||||
# Detalles de conexión MySQL
|
||||
# Detalles de conexión de la base de datos
|
||||
host: localhost
|
||||
port: 3306
|
||||
database: grim
|
||||
|
||||
@@ -215,9 +215,9 @@ history:
|
||||
# Quel nom de serveur doit être inséré pour la commande history ? Utile si vous utilisez la même base de données pour plusieurs serveurs
|
||||
server-name: Prison
|
||||
database:
|
||||
# Utilisez SQLITE pour un stockage local, MYSQL si vous disposez d’une base MySQL externe. Mis à jour seulement au redémarrage du serveur
|
||||
# Utilisez SQLITE pour le stockage local, utilisez MYSQL ou POSTGRESQL si vous avez une base de données externe. Ceci n'est mis à jour qu'au redémarrage du serveur
|
||||
type: SQLITE
|
||||
# Détails de connexion MySQL
|
||||
# Détails de connexion à la base de données
|
||||
host: localhost
|
||||
port: 3306
|
||||
database: grim
|
||||
|
||||
@@ -196,9 +196,9 @@ history:
|
||||
# Quale nome server deve essere inserito per il comando history? Utile se usi lo stesso database per più server
|
||||
server-name: Prison
|
||||
database:
|
||||
# Usa SQLITE per l’archiviazione locale, MYSQL se hai un database MySQL esterno. Aggiornato solo al riavvio del server
|
||||
# Usa SQLITE per l'archiviazione locale, usa MYSQL o POSTGRESQL se hai un database esterno. Questo viene aggiornato solo al riavvio del server
|
||||
type: SQLITE
|
||||
# Dettagli di connessione MySQL
|
||||
# Dettagli di connessione al database
|
||||
host: localhost
|
||||
port: 3306
|
||||
database: grim
|
||||
|
||||
@@ -227,9 +227,9 @@ history:
|
||||
# history コマンドで挿入されるサーバー名は? 複数サーバーで同じデータベースを使用する場合に便利
|
||||
server-name: Prison
|
||||
database:
|
||||
# ローカル保存には SQLITE、外部 MySQL データベースには MYSQL を使用します。サーバー再起動時にのみ反映
|
||||
# ローカルストレージにはSQLITEを使用し、外部データベースがある場合はMYSQLまたはPOSTGRESQLを使用してください。これはサーバー再起動時にのみ更新されます
|
||||
type: SQLITE
|
||||
# MySQL 接続情報
|
||||
# データベース接続の詳細
|
||||
host: localhost
|
||||
port: 3306
|
||||
database: grim
|
||||
|
||||
@@ -218,9 +218,9 @@ history:
|
||||
# Welke servernaam moet voor het history‑commando worden ingevoerd? Handig als je dezelfde database voor meerdere servers gebruikt
|
||||
server-name: Prison
|
||||
database:
|
||||
# Gebruik SQLITE voor lokale opslag, MYSQL voor een externe MySQL‑database. Alleen bijgewerkt na een serverherstart
|
||||
# Gebruik SQLITE voor lokale opslag, gebruik MYSQL of POSTGRESQL als u een externe database heeft. Dit wordt alleen bijgewerkt bij het herstarten van de server
|
||||
type: SQLITE
|
||||
# MySQL‑verbindingsgegevens
|
||||
# Databaseverbindingsgegevens
|
||||
host: localhost
|
||||
port: 3306
|
||||
database: grim
|
||||
|
||||
@@ -223,9 +223,9 @@ history:
|
||||
# Qual nome de servidor deve ser inserido no comando history? Útil se você usa o mesmo banco de dados para vários servidores
|
||||
server-name: Prison
|
||||
database:
|
||||
# Use SQLITE para armazenamento local ou MYSQL para um banco MySQL externo. Atualizado somente ao reiniciar o servidor
|
||||
# Use SQLITE para armazenamento local, use MYSQL ou POSTGRESQL se você tiver um banco de dados externo. Isso só é atualizado ao reiniciar o servidor
|
||||
type: SQLITE
|
||||
# Detalhes de conexão MySQL
|
||||
# Detalhes de conexão do banco de dados
|
||||
host: localhost
|
||||
port: 3306
|
||||
database: grim
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
# Configurația principală GrimAC
|
||||
# Cod sursă: https://github.com/MWHunter/Grim
|
||||
# Drepturi de autor 2025 DefineOutside și colaboratorii, licențiat sub GPLv3.
|
||||
# Binarele modificate sau pluginurile cu cod Grim copiat trebuie să fie private,
|
||||
# sau cu întregul cod sursă disponibil cumpărătorilor fără costuri suplimentare.
|
||||
|
||||
alerts:
|
||||
# Pe lângă transmiterea alertelor către jucători, ar trebui să fie trimise și în consolă?
|
||||
print-to-console: true
|
||||
# Aceasta controlează dacă/și cum sunt partajate alertele între serverele conectate la proxy.
|
||||
# Trebuie să ai 'bungee-plugin-message-channel' activat în configurația Velocity dacă Velocity este folosit.
|
||||
proxy:
|
||||
# Ar trebui ca alertele să fie trimise către alte servere conectate la proxy?
|
||||
send: false
|
||||
# Ar trebui ca alertele primite de la alte servere să fie anunțate pe acest server?
|
||||
receive: false
|
||||
|
||||
verbose:
|
||||
print-to-console: false
|
||||
|
||||
check-for-updates: true
|
||||
|
||||
client-brand:
|
||||
# Aceasta înseamnă că nu va transmite operatorilor brandul clientului dacă brandul se potrivește cu regex-urile de mai jos
|
||||
ignored-clients:
|
||||
- "^vanilla$"
|
||||
- "^fabric$"
|
||||
- "^lunarclient:v\\d+\\.\\d+\\.\\d+-\\d{4}$"
|
||||
- "^Feather Fabric$"
|
||||
- "^labymod$"
|
||||
# Grim va bloca anumite versiuni Forge care includ hackuri Reach integrate (Forge 1.18.2 până la 1.19.3).
|
||||
# Setarea acestei opțiuni la false va permite acestor clienți să se conecteze la server. Dezactivează pe propriul risc.
|
||||
disconnect-blacklisted-forge-versions: true
|
||||
|
||||
spectators:
|
||||
# Ascunde toți spectatorii cu permisiunea grim.spectator indiferent dacă spectează activ sau nu
|
||||
hide-regardless: false
|
||||
# Va face spectatorii invizibili doar în aceste lumi, lasă gol pentru a permite în toate lumile
|
||||
allowed-worlds:
|
||||
- ""
|
||||
|
||||
# Cât timp au jucătorii până să fie deconectați pentru timeout? Implicit = 60 secunde
|
||||
max-transaction-time: 60
|
||||
|
||||
# Activează pentru a opri Grim din a anula pongs primite de la jucători.
|
||||
# Poate îmbunătăți compatibilitatea cu alte anticheaturi. Poate cauza probleme cu limitatoarele de pachete.
|
||||
# Nu activa dacă nu ești sigur ce faci.
|
||||
disable-pong-cancelling: false
|
||||
|
||||
# Ar trebui să fie anulat pachetul de mișcare duplicat?
|
||||
# Mojang a reparat această problemă în 1.21. A fost încercarea lor de a rezolva „bucket desync”. https://bugs.mojang.com/browse/MC-12363
|
||||
# Această setare se aplică doar clienților 1.17-1.20.5 pe servere 1.8.
|
||||
cancel-duplicate-packet: true
|
||||
|
||||
# Dacă să se ignore rotația în pachetele duplicate
|
||||
ignore-duplicate-packet-rotation: false
|
||||
|
||||
Simulation:
|
||||
# Cu cât ar trebui să înmulțim avantajul total atunci când jucătorul este legitim
|
||||
# Așa arată configurația implicită (axa X = secunde, axa Y = 1/1000 bloc): https://www.desmos.com/calculator/d4ufgxrxer
|
||||
setback-decay-multiplier: 0.999
|
||||
# Cât de mare trebuie să fie abaterea de la mișcarea jucătorului pentru a crea o încălcare?
|
||||
# Măsurat în blocuri față de mișcarea posibilă
|
||||
# Luăm în considerare Optifine schimbând tabelele trig, dar scăderea la 0.001 va reduce FastMath
|
||||
# și ar putea marca anticheatul dacă această compensație nu funcționează...
|
||||
threshold: 0.001
|
||||
# Cât de mare trebuie să fie încălcarea într-un tick pentru a da setback imediat?
|
||||
# -1 pentru a dezactiva
|
||||
immediate-setback-threshold: 0.1
|
||||
# Cât de mare avantaj acumulat înainte să începem setback?
|
||||
# -1 pentru a dezactiva
|
||||
max-advantage: 1
|
||||
# După 50 de secunde cu setările implicite, jucătorul va trece de la 4 blocuri -> 1 bloc avantaj
|
||||
# Aceasta previne acumularea prea multor încălcări fără șansă de reset
|
||||
# Grafic implicit avantaj (axa X = secunde, axa Y = 1/1000 bloc): https://www.desmos.com/calculator/4lovswdarj
|
||||
max-ceiling: 4
|
||||
# Pragul de încălcare pentru setback
|
||||
# 1 pentru comportamentul vechi
|
||||
setback-violation-threshold: 1
|
||||
|
||||
# Verifică dacă un jucător a intrat într-un bloc în timpul mișcării
|
||||
Phase:
|
||||
setbackvl: 1 # Glitch-ul în blocuri poate permite escaladarea pereților, iar acest check e relativ stabil
|
||||
decay: 0.005
|
||||
|
||||
AirLiquidPlace:
|
||||
cancelvl: 0
|
||||
|
||||
FabricatedPlace:
|
||||
cancelvl: 5
|
||||
|
||||
FarPlace:
|
||||
cancelvl: 5
|
||||
|
||||
PositionPlace:
|
||||
cancelvl: 5
|
||||
|
||||
RotationPlace:
|
||||
cancelvl: 5
|
||||
|
||||
# Verificare NoSlow bazată pe predicție
|
||||
# Grim ține cont de netcode-ul buguit aici... greu de fals chiar și când spamezi click dreapta și butonul offhand
|
||||
# Mult mai stabil decât alte anticheaturi, dar raportează orice falsuri... am reparat multe probleme de netcode aici.
|
||||
NoSlow:
|
||||
# Cât de mare abatere e considerată „cheating”
|
||||
# Implicit este mai mică decât alte offs
|
||||
# Marchează între 0.03-0.2 constant cu NoSlow activ
|
||||
threshold: 0.001
|
||||
# Setback rapid la primul obiect pentru a elimina orice avantaj dat de NoSlow
|
||||
setbackvl: 5
|
||||
# Scade atunci când jucătorul folosește un item ȘI este încetinit de acesta
|
||||
decay: 0.05
|
||||
|
||||
Knockback:
|
||||
# Cu cât ar trebui să înmulțim avantajul total atunci când jucătorul este legitim
|
||||
setback-decay-multiplier: 0.999
|
||||
# Cât de mare trebuie să fie abaterea față de viteza jucătorului pentru a crea o încălcare?
|
||||
# Măsurat în blocuri față de viteza posibilă
|
||||
threshold: 0.001
|
||||
# Cât de mare trebuie să fie încălcarea într-un tick pentru setback imediat?
|
||||
# -1 pentru a dezactiva
|
||||
immediate-setback-threshold: 0.1
|
||||
# Cât de mare avantaj acumulat înainte să începem setback?
|
||||
# -1 pentru a dezactiva
|
||||
max-advantage: 1
|
||||
# Previne acumularea prea multor încălcări imposibil de resetat
|
||||
max-ceiling: 4
|
||||
|
||||
Explosion:
|
||||
threshold: 0.001
|
||||
setbackvl: 3
|
||||
|
||||
TimerA:
|
||||
setbackvl: 10
|
||||
# Milisecunde pe care jucătorul le poate acumula pentru folosire ulterioară când rămâne în urmă
|
||||
# Poate permite bypass-uri fast use/fast heal/fast bow pe 1.8 dacă e setat prea mare, 120 ms e un echilibru bun
|
||||
drift: 120
|
||||
|
||||
# Acest check limitează abuzul TimerA prevenind mișcarea jucătorului să rămână prea mult în urmă față de timpul real
|
||||
TimerLimit:
|
||||
# Ping la care check-ul începe să limiteze balanța timer, pentru a preveni abuzul.
|
||||
# Poate cauza setback pentru jucători legitimi doar dacă sunt peste acest prag de ping.
|
||||
# -1 pentru a dezactiva
|
||||
ping-abuse-limit-threshold: 1000
|
||||
|
||||
NegativeTimer:
|
||||
# Număr de milisecunde pierdute în timp ce se mișcă înainte de a începe să marcheze
|
||||
drift: 1200
|
||||
|
||||
# Aceeași metodă de verificare ca TimerA, dar pentru vehicule
|
||||
VehicleTimer:
|
||||
# Țintă timer 1.005
|
||||
setbackvl: 10
|
||||
|
||||
PacketOrderI:
|
||||
# activează dacă jucătorii sunt marcați folosind moduri de animații 1.7
|
||||
exempt-placing-while-digging: false
|
||||
|
||||
Reach:
|
||||
# Cu cât să mărim hitboxurile? 0.0005 ar trebui să detecteze reach 3.0005+
|
||||
#
|
||||
# Există o extindere forțată de 0.03 cu clienți 1.9-1.18.1 (nu 1.18.2), sau unele combinații client/server datorită
|
||||
# schimbărilor și limitărilor protocolului. Acest check este cel mai puternic cu clienți 1.7/1.8 pe servere 1.8.
|
||||
threshold: 0.0005
|
||||
# Ar trebui să anulăm loviturile imposibile?
|
||||
# Lovituri de 3.00-3.03 pot trece dar tot vor fi marcate, din cauza limitărilor de ordine a pachetelor
|
||||
block-impossible-hits: true
|
||||
# Va trimite un pachet suplimentar la sfârșitul fiecărui tick pentru a crește șansele de a prinde cheat-uri
|
||||
# Injectează în lista de conexiuni a serverului pentru a trimite un pachet final chiar înainte ca serverul să facă flush
|
||||
# Activarea va crește traficul pentru toți jucătorii
|
||||
# Nu va scădea performanța serverului
|
||||
# Activarea va prinde mai mulți cheateri.
|
||||
# Lăsarea dezactivată va prinde totuși cheateri și nu va cauza false positive
|
||||
# Dacă nu ești server PvP 1.8, acest pachet suplimentar nu este recomandat
|
||||
enable-post-packet: false
|
||||
|
||||
exploit:
|
||||
# Poți obține viteze mari sărind sprint cu elytra, aceasta previne exploitul dacă e setat pe false
|
||||
# Mojang a stricat netcode-ul făcând startul elytra client-side și finalul server-side
|
||||
# Elytra are fricțiune orizontală 0.99, așa că adăugând constant 0.2 viteză rezultă în viteze foarte mari.
|
||||
allow-sprint-jumping-when-using-elytra: true
|
||||
# Această opțiune reduce efectul ghostblocks prin resincronizarea jucătorului când se întâmplă
|
||||
allow-building-on-ghostblocks: true
|
||||
# Această setare, influențată de booleanul de mai sus, definește distanța verificată pentru ghostblocks
|
||||
# Interval valid: 2 până la 4
|
||||
distance-to-check-if-ghostblocks: 2
|
||||
|
||||
# Activează logarea pluginurilor care s-au injectat în netty la intrare pentru debugging de compatibilitate
|
||||
debug-pipeline-on-join: false
|
||||
|
||||
# Activează verificări experimentale
|
||||
experimental-checks: false
|
||||
|
||||
reset-item-usage-on-item-update: true
|
||||
reset-item-usage-on-attack: true
|
||||
reset-item-usage-on-slot-change: true
|
||||
|
||||
# Grim uneori anulează pachete ilegale precum timer, după X pachete anulate într-o secundă, când să
|
||||
# deconectăm jucătorul? Este necesar deoarece unele limitatoare de pachete nu numără pachetele anulate de Grim.
|
||||
packet-spam-threshold: 100
|
||||
# Activează pentru a afișa stacktrace când un jucător e deconectat din cauza packet-spam-threshold
|
||||
debug-packet-cancel: false
|
||||
|
||||
# Grim poate aplica ca un jucător scos din starea de zbor să nu aibă mai mult de X ms ping
|
||||
# Deoarece Grim nu verifică în prezent jucătorii care zboară
|
||||
# Pentru dezactivare, folosește -1
|
||||
max-ping-out-of-flying: 1000
|
||||
|
||||
# Ping maxim când boost-ul cu artificii este eliminat de la jucător.
|
||||
# Previne jucătorii cu latență mare să folosească un boost cu artificii la infinit cu elytra.
|
||||
max-ping-firework-boost: 1000
|
||||
|
||||
history:
|
||||
enabled: true
|
||||
# Câte înregistrări să fie afișate pe pagină cu /grim history <player>
|
||||
entries-per-page: 15
|
||||
# Ce nume de server să fie inserat pentru comanda history? Util dacă folosești aceeași bază de date pentru mai multe servere
|
||||
server-name: Prison
|
||||
database:
|
||||
# Folosiți SQLITE pentru stocare locală, folosiți MYSQL sau POSTGRESQL dacă aveți o bază de date externă. Aceasta este actualizată doar la repornirea serverului
|
||||
type: SQLITE
|
||||
# Detalii de conectare la baza de date
|
||||
host: localhost
|
||||
port: 3306
|
||||
database: grim
|
||||
username: root
|
||||
password: ""
|
||||
|
||||
config-version: 9
|
||||
@@ -214,9 +214,9 @@ history:
|
||||
# Какое имя сервера вставлять для команды history? Полезно при использовании одной базы для нескольких серверов
|
||||
server-name: Prison
|
||||
database:
|
||||
# Используйте SQLITE для локального хранения или MYSQL для внешней MySQL‑БД. Изменения применяются после перезапуска сервера
|
||||
# Используйте SQLITE для локального хранения, используйте MYSQL или POSTGRESQL, если у вас есть внешняя база данных. Это обновляется только при перезапуске сервера
|
||||
type: SQLITE
|
||||
# Параметры подключения MySQL
|
||||
# анные для подключения к базе данных
|
||||
host: localhost
|
||||
port: 3306
|
||||
database: grim
|
||||
|
||||
@@ -218,9 +218,9 @@ history:
|
||||
# History komutu için eklenecek sunucu adı nedir? Aynı veritabanını birden fazla sunucuda kullanıyorsanız faydalıdır
|
||||
server-name: Prison
|
||||
database:
|
||||
# Yerel saklama için SQLITE, harici MySQL veritabanı için MYSQL kullanın. Sadece sunucu yeniden başlatıldığında güncellenir
|
||||
# Yerel depolama için SQLITE kullanın, harici bir veritabanınız varsa MYSQL veya POSTGRESQL kullanın. Bu yalnızca sunucu yeniden başlatıldığında güncellenir
|
||||
type: SQLITE
|
||||
# MySQL bağlantı bilgileri
|
||||
# veritabanı bağlantı detayları
|
||||
host: localhost
|
||||
port: 3306
|
||||
database: grim
|
||||
|
||||
@@ -221,9 +221,9 @@ history:
|
||||
# history 指令中插入的服务器名称?如果多个服务器共用同一数据库则很有用
|
||||
server-name: Prison
|
||||
database:
|
||||
# 本地存储使用 SQLITE,外部数据库使用 MYSQL。仅在重启服务器后生效
|
||||
# 本地存储使用SQLITE,如有外部数据库请使用MYSQL或POSTGRESQL。此设置仅在服务器重启时更新
|
||||
type: SQLITE
|
||||
# MySQL 连接详情
|
||||
# 数据库连接详情
|
||||
host: localhost
|
||||
port: 3306
|
||||
database: grim
|
||||
|
||||
@@ -13,7 +13,7 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
minecraft("com.mojang:minecraft:$minecraft_version")
|
||||
mappings("net.fabricmc:yarn:$yarn_mappings")
|
||||
mappings(loom.officialMojangMappings())
|
||||
modImplementation(fabricApi.module("fabric-lifecycle-events-v1", fabric_version))
|
||||
|
||||
modImplementation("me.lucko:fabric-permissions-api:0.3.1")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
dependencies {
|
||||
minecraft("com.mojang:minecraft:1.16.1")
|
||||
mappings("net.fabricmc:yarn:1.16.1+build.21:v2")
|
||||
mappings(loom.officialMojangMappings())
|
||||
|
||||
modImplementation(fabricApi.module("fabric-lifecycle-events-v1", "0.42.0+1.16"))
|
||||
modImplementation("me.lucko:fabric-permissions-api:0.1-SNAPSHOT")
|
||||
|
||||
+4
-4
@@ -3,19 +3,19 @@ package ac.grim.grimac.platform.fabric.mc1161;
|
||||
import ac.grim.grimac.platform.api.sender.Sender;
|
||||
import ac.grim.grimac.platform.fabric.AbstractFabricPlatformServer;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
|
||||
public class Fabric1140PlatformServer extends AbstractFabricPlatformServer {
|
||||
|
||||
@Override
|
||||
public void dispatchCommand(Sender sender, String command) {
|
||||
ServerCommandSource commandSource = GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory().reverse(sender);
|
||||
GrimACFabricLoaderPlugin.FABRIC_SERVER.getCommandManager().execute(commandSource, command);
|
||||
CommandSourceStack commandSource = GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory().reverse(sender);
|
||||
GrimACFabricLoaderPlugin.FABRIC_SERVER.getCommands().performCommand(commandSource, command);
|
||||
}
|
||||
|
||||
// TODO (Cross-platform) implement proper bukkit equivalent for getting TPS over time
|
||||
@Override
|
||||
public double getTPS() {
|
||||
return Math.min(1000.0 / GrimACFabricLoaderPlugin.FABRIC_SERVER.getTickTime(), 20.0);
|
||||
return Math.min(1000.0 / GrimACFabricLoaderPlugin.FABRIC_SERVER.getAverageTickTime(), 20.0);
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1161.command;
|
||||
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.platform.api.command.PlayerSelector;
|
||||
import ac.grim.grimac.platform.api.sender.Sender;
|
||||
@@ -24,7 +23,7 @@ public class Fabric1161PlayerSelectorAdapter implements PlayerSelector {
|
||||
|
||||
@Override
|
||||
public Sender getSinglePlayer() {
|
||||
return ((FabricSenderFactory) GrimAPI.INSTANCE.getSenderFactory()).map(fabricSelector.single().getCommandSource());
|
||||
return ((FabricSenderFactory) GrimAPI.INSTANCE.getSenderFactory()).map(fabricSelector.single().createCommandSourceStack());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+6
-7
@@ -3,11 +3,10 @@ package ac.grim.grimac.platform.fabric.mc1161.entity;
|
||||
import ac.grim.grimac.platform.fabric.entity.AbstractFabricGrimEntity;
|
||||
import ac.grim.grimac.platform.fabric.utils.thread.FabricFutureUtil;
|
||||
import ac.grim.grimac.utils.math.Location;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
|
||||
public class Fabric1161GrimEntity extends AbstractFabricGrimEntity {
|
||||
|
||||
@@ -18,8 +17,8 @@ public class Fabric1161GrimEntity extends AbstractFabricGrimEntity {
|
||||
@Override
|
||||
public CompletableFuture<Boolean> teleportAsync(Location location) {
|
||||
return FabricFutureUtil.supplySync(() -> {
|
||||
if (entity.getEntityWorld() instanceof ServerWorld) {
|
||||
entity.teleport(
|
||||
if (entity.getCommandSenderWorld() instanceof ServerLevel) {
|
||||
entity.teleportToWithTicket(
|
||||
location.getX(),
|
||||
location.getY(),
|
||||
location.getZ()
|
||||
@@ -32,6 +31,6 @@ public class Fabric1161GrimEntity extends AbstractFabricGrimEntity {
|
||||
|
||||
@Override
|
||||
public boolean isDead() {
|
||||
return entity instanceof LivingEntity living ? living.isDead() : entity.removed;
|
||||
return entity instanceof LivingEntity living ? living.isDeadOrDying() : entity.removed;
|
||||
}
|
||||
}
|
||||
+18
-18
@@ -1,16 +1,16 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1161.player;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.player.AbstractFabricPlatformInventory;
|
||||
import net.minecraft.screen.PlayerScreenHandler;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.InventoryMenu;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class Fabric1161PlatformInventory extends AbstractFabricPlatformInventory {
|
||||
public Fabric1161PlatformInventory(ServerPlayerEntity player) {
|
||||
public Fabric1161PlatformInventory(ServerPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@@ -23,13 +23,13 @@ public class Fabric1161PlatformInventory extends AbstractFabricPlatformInventory
|
||||
// And is slated to be replaced by packet based behaviour, this should do for now
|
||||
@Override
|
||||
public String getOpenInventoryKey() {
|
||||
ScreenHandler handler = fabricPlayer.currentScreenHandler;
|
||||
ScreenHandlerType<?> type = getSafeType(handler);
|
||||
AbstractContainerMenu handler = fabricPlayer.containerMenu;
|
||||
MenuType<?> type = getSafeType(handler);
|
||||
|
||||
// Handle null types (player crafting and creative)
|
||||
if (type == null) {
|
||||
// 4x4 CRAFTING -> CRAFTING
|
||||
if (handler instanceof PlayerScreenHandler) {
|
||||
if (handler instanceof InventoryMenu) {
|
||||
return "CRAFTING";
|
||||
// Not sure if creative mode check here is correct
|
||||
} else if (this.isPlayerCreative()) {
|
||||
@@ -39,23 +39,23 @@ public class Fabric1161PlatformInventory extends AbstractFabricPlatformInventory
|
||||
|
||||
// should we handle crafters here also??
|
||||
// CRAFTING -> CRAFTING
|
||||
if (type == ScreenHandlerType.CRAFTING) {
|
||||
if (type == MenuType.CRAFTING) {
|
||||
return "CRAFTING";
|
||||
// PLAYER -> PLAYER
|
||||
} else if (type == ScreenHandlerType.GENERIC_9X4) {
|
||||
} else if (type == MenuType.GENERIC_9x4) {
|
||||
return "PLAYER";
|
||||
// CHEST, ENDER_CHEST, or BARREL -> CHEST
|
||||
} else if (type == ScreenHandlerType.GENERIC_9X3) {
|
||||
} else if (type == MenuType.GENERIC_9x3) {
|
||||
return "CHEST";
|
||||
// DISPENSER, DROPPER -> DISPENSER
|
||||
} else if (type == ScreenHandlerType.GENERIC_3X3) {
|
||||
} else if (type == MenuType.GENERIC_3x3) {
|
||||
return "DISPENSER";
|
||||
} else {
|
||||
// Registry handles:
|
||||
// SHULKER_BOX -> SHULKER_BOX
|
||||
// CRAFTIING -> CRAFTING
|
||||
|
||||
Identifier registryKey = this.getScreenID(type);
|
||||
ResourceLocation registryKey = this.getScreenID(type);
|
||||
if (registryKey != null) {
|
||||
return registryKey.getPath();
|
||||
}
|
||||
@@ -64,15 +64,15 @@ public class Fabric1161PlatformInventory extends AbstractFabricPlatformInventory
|
||||
}
|
||||
}
|
||||
|
||||
protected Identifier getScreenID(ScreenHandlerType<?> type) {
|
||||
return Registry.SCREEN_HANDLER.getId(type);
|
||||
protected ResourceLocation getScreenID(MenuType<?> type) {
|
||||
return Registry.MENU.getKey(type);
|
||||
}
|
||||
|
||||
protected boolean isPlayerCreative() {
|
||||
return fabricPlayer.isCreative();
|
||||
}
|
||||
|
||||
protected @Nullable ScreenHandlerType<?> getSafeType(ScreenHandler handler) {
|
||||
protected @Nullable MenuType<?> getSafeType(AbstractContainerMenu handler) {
|
||||
try {
|
||||
return handler.getType();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
|
||||
+6
-17
@@ -5,36 +5,25 @@ import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.player.AbstractFabricPlatformPlayer;
|
||||
import ac.grim.grimac.platform.fabric.utils.thread.FabricFutureUtil;
|
||||
import ac.grim.grimac.utils.math.Location;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
|
||||
public class Fabric1161PlatformPlayer extends AbstractFabricPlatformPlayer {
|
||||
public Fabric1161PlatformPlayer(ServerPlayerEntity player) {
|
||||
public Fabric1161PlatformPlayer(ServerPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory().map(entity.getCommandSource()).hasPermission(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String s, boolean defaultIfUnset) {
|
||||
return GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory().map(entity.getCommandSource()).hasPermission(s, defaultIfUnset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getSender() {
|
||||
return GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory().map(entity.getCommandSource());
|
||||
return GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory().map(entity.createCommandSourceStack());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> teleportAsync(Location location) {
|
||||
return FabricFutureUtil.supplySync(() -> {
|
||||
fabricPlayer.teleport(
|
||||
(ServerWorld) location.getWorld(),
|
||||
fabricPlayer.teleportTo(
|
||||
(ServerLevel) location.getWorld(),
|
||||
location.getX(),
|
||||
location.getY(),
|
||||
location.getZ(),
|
||||
|
||||
+6
-7
@@ -9,19 +9,18 @@ import io.github.retrooper.packetevents.adventure.serializer.gson.GsonComponentS
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.PooledByteBufAllocator;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
public class Fabric1140ConversionUtil implements IFabricConversionUtil {
|
||||
public ItemStack fromFabricItemStack(net.minecraft.item.ItemStack fabricStack) {
|
||||
public ItemStack fromFabricItemStack(net.minecraft.world.item.ItemStack fabricStack) {
|
||||
if (fabricStack.isEmpty()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
ByteBuf buffer = PooledByteBufAllocator.DEFAULT.buffer();
|
||||
try {
|
||||
PacketByteBuf packetByteBuf = new PacketByteBuf(buffer);
|
||||
packetByteBuf.writeItemStack(fabricStack);
|
||||
FriendlyByteBuf packetByteBuf = new FriendlyByteBuf(buffer);
|
||||
packetByteBuf.writeItem(fabricStack);
|
||||
PacketWrapper<?> wrapper = PacketWrapper.createUniversalPacketWrapper(buffer);
|
||||
return wrapper.readItemStack();
|
||||
} catch (Exception e) {
|
||||
@@ -32,7 +31,7 @@ public class Fabric1140ConversionUtil implements IFabricConversionUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public Text toNativeText(Component component) {
|
||||
return Text.Serializer.fromJson(GsonComponentSerializer.gson().serializeToTree(component));
|
||||
public net.minecraft.network.chat.Component toNativeText(Component component) {
|
||||
return net.minecraft.network.chat.Component.Serializer.fromJson(GsonComponentSerializer.gson().serializeToTree(component));
|
||||
}
|
||||
}
|
||||
+7
-7
@@ -1,18 +1,18 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1161.util.convert;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.utils.message.IFabricMessageUtil;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
|
||||
public class Fabric1161MessageUtil implements IFabricMessageUtil {
|
||||
@Override
|
||||
public Text textLiteral(String message) {
|
||||
return new LiteralText(message);
|
||||
public Component textLiteral(String message) {
|
||||
return new TextComponent(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(ServerCommandSource target, Text message, boolean overlay) {
|
||||
target.sendFeedback(message, overlay);
|
||||
public void sendMessage(CommandSourceStack target, Component message, boolean overlay) {
|
||||
target.sendSuccess(message, overlay);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
accessWidener v2 named
|
||||
accessible field net/minecraft/server/world/ServerWorld worldProperties Lnet/minecraft/world/level/ServerWorldProperties;
|
||||
accessible field net/minecraft/server/command/ServerCommandSource output Lnet/minecraft/server/command/CommandOutput;
|
||||
accessible field net/minecraft/server/level/ServerLevel serverLevelData Lnet/minecraft/world/level/storage/ServerLevelData;
|
||||
accessible field net/minecraft/commands/CommandSourceStack source Lnet/minecraft/commands/CommandSource;
|
||||
@@ -1,6 +1,6 @@
|
||||
dependencies {
|
||||
minecraft("com.mojang:minecraft:1.17.1")
|
||||
mappings("net.fabricmc:yarn:1.17.1+build.65:v2")
|
||||
mappings(loom.officialMojangMappings())
|
||||
compileOnly(project(":fabric:mc1161", configuration = "namedElements"))
|
||||
|
||||
modImplementation(fabricApi.module("fabric-lifecycle-events-v1", "0.46.1+1.17"))
|
||||
|
||||
+3
-5
@@ -7,12 +7,10 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
public class Fabric1171PlatformServer extends Fabric1140PlatformServer {
|
||||
|
||||
@Override @Nullable
|
||||
public GameProfile getProfileByName(String name) {
|
||||
Optional<GameProfile> gameProfile = GrimACFabricLoaderPlugin.FABRIC_SERVER.getUserCache().findByName(name);
|
||||
@Override
|
||||
public @Nullable GameProfile getProfileByName(String name) {
|
||||
Optional<GameProfile> gameProfile = GrimACFabricLoaderPlugin.FABRIC_SERVER.getProfileCache().get(name);
|
||||
return gameProfile.orElse(null);
|
||||
}
|
||||
}
|
||||
+3
-6
@@ -1,9 +1,8 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1171.entity;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.mc1161.entity.Fabric1161GrimEntity;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
|
||||
public class Fabric1170GrimEntity extends Fabric1161GrimEntity {
|
||||
|
||||
@@ -13,8 +12,6 @@ public class Fabric1170GrimEntity extends Fabric1161GrimEntity {
|
||||
|
||||
@Override
|
||||
public boolean isDead() {
|
||||
if (this.entity instanceof LivingEntity)
|
||||
return ((LivingEntity) entity).isDead();
|
||||
return this.entity.isRemoved();
|
||||
return this.entity instanceof LivingEntity living ? living.isDeadOrDying() : this.entity.isRemoved();
|
||||
}
|
||||
}
|
||||
+3
-4
@@ -3,16 +3,15 @@ package ac.grim.grimac.platform.fabric.mc1171.player;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.player.Fabric1161PlatformPlayer;
|
||||
import ac.grim.grimac.platform.fabric.utils.convert.FabricConversionUtil;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
|
||||
public class Fabric1170PlatformPlayer extends Fabric1161PlatformPlayer {
|
||||
public Fabric1170PlatformPlayer(ServerPlayerEntity player) {
|
||||
public Fabric1170PlatformPlayer(ServerPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGameMode(GameMode gameMode) {
|
||||
fabricPlayer.changeGameMode(FabricConversionUtil.toFabricGameMode(gameMode));
|
||||
fabricPlayer.setGameMode(FabricConversionUtil.toFabricGameMode(gameMode));
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
accessWidener v2 named
|
||||
accessible field net/minecraft/server/world/ServerWorld worldProperties Lnet/minecraft/world/level/ServerWorldProperties;
|
||||
accessible field net/minecraft/server/command/ServerCommandSource output Lnet/minecraft/server/command/CommandOutput;
|
||||
accessible field net/minecraft/server/level/ServerLevel serverLevelData Lnet/minecraft/world/level/storage/ServerLevelData;
|
||||
accessible field net/minecraft/commands/CommandSourceStack source Lnet/minecraft/commands/CommandSource;
|
||||
@@ -1,6 +1,6 @@
|
||||
dependencies {
|
||||
minecraft("com.mojang:minecraft:1.19.4")
|
||||
mappings("net.fabricmc:yarn:1.19.4+build.2:v2")
|
||||
mappings(loom.officialMojangMappings())
|
||||
compileOnly(project(":fabric:mc1161", configuration = "namedElements"))
|
||||
compileOnly(project(":fabric:mc1171", configuration = "namedElements"))
|
||||
|
||||
|
||||
+3
-3
@@ -3,12 +3,12 @@ package ac.grim.grimac.platform.fabric.mc1194;
|
||||
import ac.grim.grimac.platform.api.sender.Sender;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.mc1171.Fabric1171PlatformServer;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
|
||||
public class Fabric1190PlatformServer extends Fabric1171PlatformServer {
|
||||
@Override
|
||||
public void dispatchCommand(Sender sender, String command) {
|
||||
ServerCommandSource commandSource = GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory().reverse(sender);
|
||||
GrimACFabricLoaderPlugin.FABRIC_SERVER.getCommandManager().executeWithPrefix(commandSource, command);
|
||||
CommandSourceStack commandSource = GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory().reverse(sender);
|
||||
GrimACFabricLoaderPlugin.FABRIC_SERVER.getCommands().performPrefixedCommand(commandSource, command);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1194.convert;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.mc1161.util.convert.Fabric1161MessageUtil;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
public class Fabric1190MessageUtil extends Fabric1161MessageUtil {
|
||||
@Override
|
||||
public Text textLiteral(String message) {
|
||||
return Text.literal(message);
|
||||
public Component textLiteral(String message) {
|
||||
return Component.literal(message);
|
||||
}
|
||||
}
|
||||
+7
-8
@@ -3,12 +3,11 @@ package ac.grim.grimac.platform.fabric.mc1194.entity;
|
||||
import ac.grim.grimac.platform.fabric.mc1171.entity.Fabric1170GrimEntity;
|
||||
import ac.grim.grimac.platform.fabric.utils.thread.FabricFutureUtil;
|
||||
import ac.grim.grimac.utils.math.Location;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.network.packet.s2c.play.PositionFlag;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.RelativeMovement;
|
||||
|
||||
public class Fabric1194GrimEntity extends Fabric1170GrimEntity {
|
||||
|
||||
@@ -19,13 +18,13 @@ public class Fabric1194GrimEntity extends Fabric1170GrimEntity {
|
||||
@Override
|
||||
public CompletableFuture<Boolean> teleportAsync(Location location) {
|
||||
return FabricFutureUtil.supplySync(() -> {
|
||||
if (entity.getWorld() instanceof ServerWorld) {
|
||||
entity.teleport(
|
||||
(ServerWorld) location.getWorld(),
|
||||
if (entity.getLevel() instanceof ServerLevel) {
|
||||
entity.teleportTo(
|
||||
(ServerLevel) location.getWorld(),
|
||||
location.getX(),
|
||||
location.getY(),
|
||||
location.getZ(),
|
||||
EnumSet.noneOf(PositionFlag.class), // todo change to match paper? Do they do this?
|
||||
EnumSet.noneOf(RelativeMovement.class), // todo change to match paper? Do they do this?
|
||||
location.getYaw(),
|
||||
location.getPitch()
|
||||
|
||||
|
||||
+7
-7
@@ -1,18 +1,18 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1194.player;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.mc1161.player.Fabric1161PlatformInventory;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
|
||||
public class Fabric1193PlatformInventory extends Fabric1161PlatformInventory {
|
||||
public Fabric1193PlatformInventory(ServerPlayerEntity player) {
|
||||
public Fabric1193PlatformInventory(ServerPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Identifier getScreenID(ScreenHandlerType<?> type) {
|
||||
return Registries.SCREEN_HANDLER.getId(type);
|
||||
protected ResourceLocation getScreenID(MenuType<?> type) {
|
||||
return BuiltInRegistries.MENU.getKey(type);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
accessWidener v2 named
|
||||
accessible field net/minecraft/server/world/ServerWorld worldProperties Lnet/minecraft/world/level/ServerWorldProperties;
|
||||
accessible field net/minecraft/server/command/ServerCommandSource output Lnet/minecraft/server/command/CommandOutput;
|
||||
accessible field net/minecraft/server/level/ServerLevel serverLevelData Lnet/minecraft/world/level/storage/ServerLevelData;
|
||||
accessible field net/minecraft/commands/CommandSourceStack source Lnet/minecraft/commands/CommandSource;
|
||||
@@ -1,6 +1,6 @@
|
||||
dependencies {
|
||||
minecraft("com.mojang:minecraft:1.20.5")
|
||||
mappings("net.fabricmc:yarn:1.20.5+build.1:v2")
|
||||
mappings(loom.officialMojangMappings())
|
||||
compileOnly(project(":fabric:mc1161", configuration = "namedElements"))
|
||||
compileOnly(project(":fabric:mc1171", configuration = "namedElements"))
|
||||
compileOnly(project(":fabric:mc1194", configuration = "namedElements"))
|
||||
|
||||
+4
-4
@@ -3,20 +3,20 @@ package ac.grim.grimac.platform.fabric.mc1205;
|
||||
import ac.grim.grimac.platform.api.sender.Sender;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.mc1194.Fabric1190PlatformServer;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
|
||||
public class Fabric1203PlatformServer extends Fabric1190PlatformServer {
|
||||
|
||||
// TODO (Cross-platform) implement proper bukkit equivalent for getting TPS over time
|
||||
@Override
|
||||
public double getTPS() {
|
||||
return Math.min(1000.0 / GrimACFabricLoaderPlugin.FABRIC_SERVER.getAverageTickTime(), GrimACFabricLoaderPlugin.FABRIC_SERVER.getTickManager().getTickRate());
|
||||
return Math.min(1000.0 / GrimACFabricLoaderPlugin.FABRIC_SERVER.getCurrentSmoothedTickTime(), GrimACFabricLoaderPlugin.FABRIC_SERVER.tickRateManager().tickrate());
|
||||
}
|
||||
|
||||
// Return type changed from int -> void in 1.20.3
|
||||
@Override
|
||||
public void dispatchCommand(Sender sender, String command) {
|
||||
ServerCommandSource commandSource = GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory().reverse(sender);
|
||||
GrimACFabricLoaderPlugin.FABRIC_SERVER.getCommandManager().executeWithPrefix(commandSource, command);
|
||||
CommandSourceStack commandSource = GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory().reverse(sender);
|
||||
GrimACFabricLoaderPlugin.FABRIC_SERVER.getCommands().performPrefixedCommand(commandSource, command);
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -1,12 +1,12 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1205.convert;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.mc1194.convert.Fabric1190MessageUtil;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
public class Fabric1200MessageUtil extends Fabric1190MessageUtil {
|
||||
@Override
|
||||
public void sendMessage(ServerCommandSource target, Text message, boolean overlay) {
|
||||
target.sendFeedback(() -> message, overlay);
|
||||
public void sendMessage(CommandSourceStack target, Component message, boolean overlay) {
|
||||
target.sendSuccess(() -> message, overlay);
|
||||
}
|
||||
}
|
||||
+8
-9
@@ -10,12 +10,11 @@ import io.github.retrooper.packetevents.adventure.serializer.gson.GsonComponentS
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.PooledByteBufAllocator;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.network.RegistryByteBuf;
|
||||
import net.minecraft.registry.DynamicRegistryManager;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||
|
||||
public class Fabric1205ConversionUtil implements IFabricConversionUtil {
|
||||
public ItemStack fromFabricItemStack(net.minecraft.item.ItemStack fabricStack) {
|
||||
public ItemStack fromFabricItemStack(net.minecraft.world.item.ItemStack fabricStack) {
|
||||
if (fabricStack.isEmpty()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
@@ -24,13 +23,13 @@ public class Fabric1205ConversionUtil implements IFabricConversionUtil {
|
||||
ByteBuf buffer = PooledByteBufAllocator.DEFAULT.buffer();
|
||||
try {
|
||||
// Obtain the DynamicRegistryManager (you need to provide this from your context)
|
||||
DynamicRegistryManager registryManager = GrimACFabricLoaderPlugin.FABRIC_SERVER.getRegistryManager(); // Replace with actual method to get registry manager
|
||||
RegistryAccess registryManager = GrimACFabricLoaderPlugin.FABRIC_SERVER.registryAccess(); // Replace with actual method to get registry manager
|
||||
|
||||
// Create a RegistryByteBuf
|
||||
RegistryByteBuf registryByteBuf = new RegistryByteBuf(buffer, registryManager);
|
||||
RegistryFriendlyByteBuf registryByteBuf = new RegistryFriendlyByteBuf(buffer, registryManager);
|
||||
|
||||
// Encode the ItemStack using the appropriate PacketCodec
|
||||
net.minecraft.item.ItemStack.PACKET_CODEC.encode(registryByteBuf, fabricStack);
|
||||
net.minecraft.world.item.ItemStack.STREAM_CODEC.encode(registryByteBuf, fabricStack);
|
||||
|
||||
// Create a PacketWrapper to read the ItemStack back (if needed)
|
||||
PacketWrapper<?> wrapper = PacketWrapper.createUniversalPacketWrapper(buffer);
|
||||
@@ -46,7 +45,7 @@ public class Fabric1205ConversionUtil implements IFabricConversionUtil {
|
||||
}
|
||||
|
||||
// TODO proper registry support?
|
||||
public Text toNativeText(Component component) {
|
||||
return Text.Serialization.fromJsonTree(GsonComponentSerializer.gson().serializeToTree(component), DynamicRegistryManager.EMPTY);
|
||||
public net.minecraft.network.chat.Component toNativeText(Component component) {
|
||||
return net.minecraft.network.chat.Component.Serializer.fromJson(GsonComponentSerializer.gson().serializeToTree(component), RegistryAccess.EMPTY);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -2,15 +2,15 @@ package ac.grim.grimac.platform.fabric.mc1205.player;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.mc1171.player.Fabric1170PlatformPlayer;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
|
||||
public class Fabric1202PlatformPlayer extends Fabric1170PlatformPlayer {
|
||||
public Fabric1202PlatformPlayer(ServerPlayerEntity player) {
|
||||
public Fabric1202PlatformPlayer(ServerPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void kickPlayer(String textReason) {
|
||||
fabricPlayer.networkHandler.disconnect(GrimACFabricLoaderPlugin.LOADER.getFabricMessageUtils().textLiteral(textReason));
|
||||
fabricPlayer.connection.disconnect(GrimACFabricLoaderPlugin.LOADER.getFabricMessageUtils().textLiteral(textReason));
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
accessWidener v2 named
|
||||
accessible field net/minecraft/server/world/ServerWorld worldProperties Lnet/minecraft/world/level/ServerWorldProperties;
|
||||
accessible field net/minecraft/server/command/ServerCommandSource output Lnet/minecraft/server/command/CommandOutput;
|
||||
accessible field net/minecraft/server/level/ServerLevel serverLevelData Lnet/minecraft/world/level/storage/ServerLevelData;
|
||||
accessible field net/minecraft/commands/CommandSourceStack source Lnet/minecraft/commands/CommandSource;
|
||||
Loaded 100 of 135 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user