Compare commits
112
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15984b0a94 | ||
|
|
97de474b79 | ||
|
|
cea13a719d | ||
|
|
faa471b197 | ||
|
|
60f8812efd | ||
|
|
7e82f19961 | ||
|
|
27aae68f14 | ||
|
|
a65f24424f | ||
|
|
bfd3433423 | ||
|
|
09e6cec6ef | ||
|
|
4ffe6f4fc5 | ||
|
|
4aaeb579e7 | ||
|
|
487e9c6590 | ||
|
|
bdf7eb7c06 | ||
|
|
c70e5b8fff | ||
|
|
9599b1c631 | ||
|
|
85b42fa90e | ||
|
|
0c1a6c7775 | ||
|
|
d4508fa36b | ||
|
|
3cb1bb3792 | ||
|
|
faf0c7d3d6 | ||
|
|
c8ff1109e1 | ||
|
|
de0c28beab | ||
|
|
acdacffcc0 | ||
|
|
3cab3fe680 | ||
|
|
880a7b5e74 | ||
|
|
c4848efc8a | ||
|
|
0ddf0b5d22 | ||
|
|
fde6e03b98 | ||
|
|
55c084216d | ||
|
|
f3074e3934 | ||
|
|
748eb398b8 | ||
|
|
ea85282f52 | ||
|
|
d723dec820 | ||
|
|
de03945f42 | ||
|
|
dc7f6dca93 | ||
|
|
03ea36ad28 | ||
|
|
472415e0d4 | ||
|
|
b27678c753 | ||
|
|
6eb99263a2 | ||
|
|
bde44f5136 | ||
|
|
da61ff673a | ||
|
|
d5927578a9 | ||
|
|
01ca8c894e | ||
|
|
f724d6d78e | ||
|
|
ee6183db90 | ||
|
|
e959ef37db | ||
|
|
f62d8602b8 | ||
|
|
bf44dd6855 | ||
|
|
cc9273d05d | ||
|
|
c354b4481d | ||
|
|
ba8c411ed4 | ||
|
|
1beedd77c3 | ||
|
|
c34ad88a13 | ||
|
|
619e7f1404 | ||
|
|
da1468e858 | ||
|
|
927b330c4b | ||
|
|
bff6854189 | ||
|
|
290bf9032e | ||
|
|
2629536ad7 | ||
|
|
9708ebc821 | ||
|
|
fad39af575 | ||
|
|
4e4492e417 | ||
|
|
5374ee3c0d | ||
|
|
936662db2d | ||
|
|
7ac2319c07 | ||
|
|
89a795a7e6 | ||
|
|
510247f3b4 | ||
|
|
a61b710e81 | ||
|
|
049c30f8b1 | ||
|
|
21a7bdd395 | ||
|
|
598caa9259 | ||
|
|
0d28fa3a9d | ||
|
|
87c5c1d6c7 | ||
|
|
dde9cea757 | ||
|
|
1fe77a1dd6 | ||
|
|
72a2dfdde4 | ||
|
|
4c039e612b | ||
|
|
b0cd32622e | ||
|
|
3445a0220f | ||
|
|
f1a1e46edc | ||
|
|
343e9ef16d | ||
|
|
c4c063418a | ||
|
|
95955b81f6 | ||
|
|
f4cb19c113 | ||
|
|
f313d0897d | ||
|
|
0293606dc9 | ||
|
|
705f223a70 | ||
|
|
409b1ae646 | ||
|
|
13bd66de7b | ||
|
|
b3d59788b3 | ||
|
|
c58ae74a41 | ||
|
|
aa6d07f893 | ||
|
|
cef044c4fe | ||
|
|
e8c7b9066f | ||
|
|
7f0dbdbc28 | ||
|
|
3890d12105 | ||
|
|
d62755bc01 | ||
|
|
dfc8c988d1 | ||
|
|
508daaa472 | ||
|
|
a765065f98 | ||
|
|
7add2b6658 | ||
|
|
b3d780b52b | ||
|
|
1e46837fec | ||
|
|
ac516060c0 | ||
|
|
a5c34a0829 | ||
|
|
06fa4bab17 | ||
|
|
aabead19ec | ||
|
|
af60e07327 | ||
|
|
b72fafaa47 | ||
|
|
e35845cf7d | ||
|
|
0c78830524 |
No files matched your search
@@ -39,11 +39,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -68,4 +68,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
uses: github/codeql-action/analyze@v3
|
||||
@@ -19,9 +19,9 @@ jobs:
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
@@ -29,10 +29,10 @@ jobs:
|
||||
settings-path: ${{ github.workspace }} # location for the settings.xml file
|
||||
|
||||
- name: Build with Gradle
|
||||
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
with:
|
||||
arguments: build
|
||||
- name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v3.1.0
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: /home/runner/work/Grim/Grim/build/libs/**.jar
|
||||
+33
-25
@@ -9,10 +9,14 @@ plugins {
|
||||
}
|
||||
|
||||
group = "ac.grim.grimac"
|
||||
version = "2.3.67"
|
||||
version = "2.3.68"
|
||||
description = "Libre simulation anticheat designed for 1.21 with 1.8-1.21 support, powered by PacketEvents 2.0."
|
||||
java.sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
java.targetCompatibility = JavaVersion.VERSION_1_8
|
||||
java.sourceCompatibility = JavaVersion.VERSION_17
|
||||
java.targetCompatibility = JavaVersion.VERSION_17
|
||||
|
||||
// Set to false for debug builds
|
||||
// You cannot live reload classes if the jar relocates dependencies
|
||||
var relocate = true;
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
@@ -34,19 +38,20 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("com.github.retrooper:packetevents-spigot:2.5.0-SNAPSHOT")
|
||||
implementation("com.github.retrooper:packetevents-spigot:2.5.1-SNAPSHOT")
|
||||
implementation("co.aikar:acf-paper:0.5.1-SNAPSHOT")
|
||||
implementation("club.minnced:discord-webhooks:0.8.0") // Newer versions include kotlin-stdlib, which leads to incompatibility with plugins that use Kotlin
|
||||
implementation("it.unimi.dsi:fastutil:8.5.13")
|
||||
implementation("github.scarsz:configuralize:1.4.0")
|
||||
|
||||
implementation("com.github.grimanticheat:grimapi:1193c4fa41")
|
||||
// Used for local testing: implementation("ac.grim.grimac:grimapi:1.0")
|
||||
//implementation("com.github.grimanticheat:grimapi:1193c4fa41")
|
||||
// Used for local testing: implementation("ac.grim.grimac:GRIMAPI:1.0")
|
||||
implementation("com.github.grimanticheat:grimapi:fc5634e444")
|
||||
|
||||
implementation("org.jetbrains:annotations:24.1.0")
|
||||
compileOnly("org.geysermc.floodgate:api:2.0-SNAPSHOT")
|
||||
compileOnly("org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT")
|
||||
compileOnly("com.viaversion:viaversion-api:4.9.4-SNAPSHOT")
|
||||
compileOnly("com.viaversion:viaversion-api:5.0.4-SNAPSHOT")
|
||||
//
|
||||
compileOnly("io.netty:netty-all:4.1.85.Final")
|
||||
}
|
||||
@@ -55,6 +60,7 @@ bukkit {
|
||||
name = "GrimAC"
|
||||
author = "GrimAC"
|
||||
main = "ac.grim.grimac.GrimAC"
|
||||
website = "https://grim.ac/"
|
||||
apiVersion = "1.13"
|
||||
foliaSupported = true
|
||||
|
||||
@@ -133,21 +139,23 @@ publishing.publications.create<MavenPublication>("maven") {
|
||||
tasks.shadowJar {
|
||||
minimize()
|
||||
archiveFileName.set("${project.name}-${project.version}.jar")
|
||||
relocate("io.github.retrooper.packetevents", "ac.grim.grimac.shaded.io.github.retrooper.packetevents")
|
||||
relocate("com.github.retrooper.packetevents", "ac.grim.grimac.shaded.com.github.retrooper.packetevents")
|
||||
relocate("co.aikar.commands", "ac.grim.grimac.shaded.acf")
|
||||
relocate("co.aikar.locale", "ac.grim.grimac.shaded.locale")
|
||||
relocate("club.minnced", "ac.grim.grimac.shaded.discord-webhooks")
|
||||
relocate("github.scarsz.configuralize", "ac.grim.grimac.shaded.configuralize")
|
||||
relocate("com.github.puregero", "ac.grim.grimac.shaded.com.github.puregero")
|
||||
relocate("com.google.code.gson", "ac.grim.grimac.shaded.gson")
|
||||
relocate("alexh", "ac.grim.grimac.shaded.maps")
|
||||
relocate("it.unimi.dsi.fastutil", "ac.grim.grimac.shaded.fastutil")
|
||||
relocate("net.kyori", "ac.grim.grimac.shaded.kyori")
|
||||
relocate("okhttp3", "ac.grim.grimac.shaded.okhttp3")
|
||||
relocate("okio", "ac.grim.grimac.shaded.okio")
|
||||
relocate("org.yaml.snakeyaml", "ac.grim.grimac.shaded.snakeyaml")
|
||||
relocate("org.json", "ac.grim.grimac.shaded.json")
|
||||
relocate("org.intellij", "ac.grim.grimac.shaded.intellij")
|
||||
relocate("org.jetbrains", "ac.grim.grimac.shaded.jetbrains")
|
||||
}
|
||||
if (relocate) {
|
||||
relocate("io.github.retrooper.packetevents", "ac.grim.grimac.shaded.io.github.retrooper.packetevents")
|
||||
relocate("com.github.retrooper.packetevents", "ac.grim.grimac.shaded.com.github.retrooper.packetevents")
|
||||
relocate("co.aikar.commands", "ac.grim.grimac.shaded.acf")
|
||||
relocate("co.aikar.locale", "ac.grim.grimac.shaded.locale")
|
||||
relocate("club.minnced", "ac.grim.grimac.shaded.discord-webhooks")
|
||||
relocate("github.scarsz.configuralize", "ac.grim.grimac.shaded.configuralize")
|
||||
relocate("com.github.puregero", "ac.grim.grimac.shaded.com.github.puregero")
|
||||
relocate("com.google.code.gson", "ac.grim.grimac.shaded.gson")
|
||||
relocate("alexh", "ac.grim.grimac.shaded.maps")
|
||||
relocate("it.unimi.dsi.fastutil", "ac.grim.grimac.shaded.fastutil")
|
||||
relocate("net.kyori", "ac.grim.grimac.shaded.kyori")
|
||||
relocate("okhttp3", "ac.grim.grimac.shaded.okhttp3")
|
||||
relocate("okio", "ac.grim.grimac.shaded.okio")
|
||||
relocate("org.yaml.snakeyaml", "ac.grim.grimac.shaded.snakeyaml")
|
||||
relocate("org.json", "ac.grim.grimac.shaded.json")
|
||||
relocate("org.intellij", "ac.grim.grimac.shaded.intellij")
|
||||
relocate("org.jetbrains", "ac.grim.grimac.shaded.jetbrains")
|
||||
}
|
||||
}
|
||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
package ac.grim.grimac;
|
||||
|
||||
import ac.grim.grimac.api.GrimAbstractAPI;
|
||||
import ac.grim.grimac.manager.*;
|
||||
import ac.grim.grimac.manager.config.BaseConfigManager;
|
||||
import ac.grim.grimac.utils.anticheat.PlayerDataManager;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
@Getter
|
||||
public enum GrimAPI {
|
||||
INSTANCE;
|
||||
|
||||
private final BaseConfigManager configManager = new BaseConfigManager();
|
||||
private final AlertManagerImpl alertManager = new AlertManagerImpl();
|
||||
private final SpectateManager spectateManager = new SpectateManager();
|
||||
private final DiscordManager discordManager = new DiscordManager();
|
||||
@@ -19,12 +18,10 @@ public enum GrimAPI {
|
||||
private final TickManager tickManager = new TickManager();
|
||||
private final GrimExternalAPI externalAPI = new GrimExternalAPI(this);
|
||||
private InitManager initManager;
|
||||
private ConfigManager configManager;
|
||||
private JavaPlugin plugin;
|
||||
|
||||
public void load(final JavaPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.configManager = new ConfigManager();
|
||||
initManager = new InitManager();
|
||||
initManager.load();
|
||||
}
|
||||
@@ -32,7 +29,6 @@ public enum GrimAPI {
|
||||
public void start(final JavaPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
initManager.start();
|
||||
Bukkit.getServicesManager().register(GrimAbstractAPI.class, externalAPI, plugin, ServicePriority.Normal);
|
||||
}
|
||||
|
||||
public void stop(final JavaPlugin plugin) {
|
||||
|
||||
@@ -1,25 +1,34 @@
|
||||
package ac.grim.grimac;
|
||||
|
||||
import ac.grim.grimac.api.AbstractCheck;
|
||||
import ac.grim.grimac.api.GrimAbstractAPI;
|
||||
import ac.grim.grimac.api.GrimUser;
|
||||
import ac.grim.grimac.api.alerts.AlertManager;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.api.events.GrimReloadEvent;
|
||||
import ac.grim.grimac.manager.config.ConfigManagerFileImpl;
|
||||
import ac.grim.grimac.manager.init.Initable;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import ac.grim.grimac.utils.common.ConfigReloadObserver;
|
||||
import com.github.retrooper.packetevents.netty.channel.ChannelHelper;
|
||||
import io.github.retrooper.packetevents.util.SpigotReflectionUtil;
|
||||
import io.github.retrooper.packetevents.util.folia.FoliaScheduler;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
//This is used for grim's external API. It has its own class just for organization.
|
||||
public class GrimExternalAPI implements GrimAbstractAPI, Initable {
|
||||
|
||||
public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, Initable {
|
||||
|
||||
private final GrimAPI api;
|
||||
|
||||
@@ -41,7 +50,8 @@ public class GrimExternalAPI implements GrimAbstractAPI, Initable {
|
||||
@Getter
|
||||
private final Map<String, Function<GrimUser, String>> variableReplacements = new ConcurrentHashMap<>();
|
||||
|
||||
@Getter private final Map<String, String> staticReplacements = new ConcurrentHashMap<>();
|
||||
@Getter
|
||||
private final Map<String, String> staticReplacements = new ConcurrentHashMap<>();
|
||||
|
||||
public String replaceVariables(GrimUser user, String content, boolean colors) {
|
||||
if (colors) content = ChatColor.translateAlternateColorCodes('&', content);
|
||||
@@ -56,12 +66,20 @@ public class GrimExternalAPI implements GrimAbstractAPI, Initable {
|
||||
|
||||
@Override
|
||||
public void registerVariable(String string, Function<GrimUser, String> replacement) {
|
||||
variableReplacements.put(string, replacement);
|
||||
if (replacement == null) {
|
||||
variableReplacements.remove(string);
|
||||
} else {
|
||||
variableReplacements.put(string, replacement);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerVariable(String variable, String replacement) {
|
||||
staticReplacements.put(variable, replacement);
|
||||
if (replacement == null) {
|
||||
staticReplacements.remove(variable);
|
||||
} else {
|
||||
staticReplacements.put(variable, replacement);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,34 +88,20 @@ public class GrimExternalAPI implements GrimAbstractAPI, Initable {
|
||||
return description.getVersion();
|
||||
}
|
||||
|
||||
private final Map<String, Function<Object, Object>> functions = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void registerFunction(String key, Function<Object, Object> function) {
|
||||
|
||||
if (function == null) {
|
||||
functions.remove(key);
|
||||
} else {
|
||||
functions.put(key, function);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<Object, Object> getFunction(String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
GrimAPI.INSTANCE.getConfigManager().reload();
|
||||
//Reload checks for all players
|
||||
for (GrimPlayer grimPlayer : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
|
||||
ChannelHelper.runInEventLoop(grimPlayer.user.getChannel(), () -> {
|
||||
grimPlayer.onReload();
|
||||
grimPlayer.updatePermissions();
|
||||
grimPlayer.punishmentManager.reload();
|
||||
for (AbstractCheck value : grimPlayer.checkManager.allChecks.values()) {
|
||||
value.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
//Restart
|
||||
GrimAPI.INSTANCE.getDiscordManager().start();
|
||||
GrimAPI.INSTANCE.getSpectateManager().start();
|
||||
GrimAPI.INSTANCE.getExternalAPI().start();
|
||||
return functions.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -106,16 +110,106 @@ public class GrimExternalAPI implements GrimAbstractAPI, Initable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
variableReplacements.put("%player%", GrimUser::getName);
|
||||
variableReplacements.put("%uuid%", user -> user.getUniqueId().toString());
|
||||
variableReplacements.put("%ping%", user -> user.getTransactionPing() + "");
|
||||
variableReplacements.put("%brand%", GrimUser::getBrand);
|
||||
variableReplacements.put("%h_sensitivity%", user -> ((int) Math.round(user.getHorizontalSensitivity() * 200)) + "");
|
||||
variableReplacements.put("%v_sensitivity%", user -> ((int) Math.round(user.getVerticalSensitivity() * 200)) + "");
|
||||
variableReplacements.put("%fast_math%", user -> !user.isVanillaMath() + "");
|
||||
variableReplacements.put("%tps%", user -> String.format("%.2f", SpigotReflectionUtil.getTPS()));
|
||||
variableReplacements.put("%version%", GrimUser::getVersionName);
|
||||
variableReplacements.put("%prefix%", user -> ChatColor.translateAlternateColorCodes('&', GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("prefix", "&bGrim &8»")));
|
||||
public ConfigManager getConfigManager() {
|
||||
return configManager;
|
||||
}
|
||||
|
||||
private ConfigManager configManager = null;
|
||||
private final ConfigManagerFileImpl configManagerFile = new ConfigManagerFileImpl();
|
||||
private boolean started = false;
|
||||
|
||||
// on load, load the config & register the service
|
||||
public void load() {
|
||||
reload(configManagerFile);
|
||||
Bukkit.getServicesManager().register(GrimAbstractAPI.class, this, GrimAPI.INSTANCE.getPlugin(), ServicePriority.Normal);
|
||||
}
|
||||
|
||||
// handles any config loading that's needed to be done after load
|
||||
@Override
|
||||
public void start() {
|
||||
started = true;
|
||||
try {
|
||||
GrimAPI.INSTANCE.getConfigManager().start();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload(ConfigManager config) {
|
||||
if (config.isLoadedAsync() && started) {
|
||||
FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(),
|
||||
o -> successfulReload(config));
|
||||
} else {
|
||||
successfulReload(config);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> reloadAsync(ConfigManager config) {
|
||||
if (config.isLoadedAsync() && started) {
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(),
|
||||
o -> future.complete(successfulReload(config)));
|
||||
return future;
|
||||
}
|
||||
return CompletableFuture.completedFuture(successfulReload(config));
|
||||
}
|
||||
|
||||
private boolean successfulReload(ConfigManager config) {
|
||||
try {
|
||||
config.reload();
|
||||
GrimAPI.INSTANCE.getConfigManager().load(config);
|
||||
if (started) GrimAPI.INSTANCE.getConfigManager().start();
|
||||
onReload(config);
|
||||
if (started) FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(),
|
||||
o -> Bukkit.getPluginManager().callEvent(new GrimReloadEvent(true)));
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (started) FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(),
|
||||
o -> Bukkit.getPluginManager().callEvent(new GrimReloadEvent(false)));
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager newConfig) {
|
||||
if (newConfig == null) {
|
||||
LogUtil.warn("ConfigManager not set. Using default config file manager.");
|
||||
configManager = configManagerFile;
|
||||
} else {
|
||||
configManager = newConfig;
|
||||
}
|
||||
// Update variables
|
||||
updateVariables();
|
||||
// Restart
|
||||
GrimAPI.INSTANCE.getDiscordManager().start();
|
||||
GrimAPI.INSTANCE.getSpectateManager().start();
|
||||
// Don't reload players if the plugin hasn't started yet
|
||||
if (!started) return;
|
||||
// Reload checks for all players
|
||||
for (GrimPlayer grimPlayer : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
|
||||
ChannelHelper.runInEventLoop(grimPlayer.user.getChannel(), () -> {
|
||||
grimPlayer.updatePermissions();
|
||||
grimPlayer.reload(configManager);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void updateVariables() {
|
||||
variableReplacements.putIfAbsent("%player%", GrimUser::getName);
|
||||
variableReplacements.putIfAbsent("%uuid%", user -> user.getUniqueId().toString());
|
||||
variableReplacements.putIfAbsent("%ping%", user -> user.getTransactionPing() + "");
|
||||
variableReplacements.putIfAbsent("%brand%", GrimUser::getBrand);
|
||||
variableReplacements.putIfAbsent("%h_sensitivity%", user -> ((int) Math.round(user.getHorizontalSensitivity() * 200)) + "");
|
||||
variableReplacements.putIfAbsent("%v_sensitivity%", user -> ((int) Math.round(user.getVerticalSensitivity() * 200)) + "");
|
||||
variableReplacements.putIfAbsent("%fast_math%", user -> !user.isVanillaMath() + "");
|
||||
variableReplacements.putIfAbsent("%tps%", user -> String.format("%.2f", SpigotReflectionUtil.getTPS()));
|
||||
variableReplacements.putIfAbsent("%version%", GrimUser::getVersionName);
|
||||
// static variables
|
||||
staticReplacements.putIfAbsent("%prefix%", ChatColor.translateAlternateColorCodes('&', GrimAPI.INSTANCE.getConfigManager().getPrefix()));
|
||||
staticReplacements.putIfAbsent("%grim_version%", getGrimVersion());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,18 +2,20 @@ package ac.grim.grimac.checks;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.AbstractCheck;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.api.events.FlagEvent;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.common.ConfigReloadObserver;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
|
||||
import github.scarsz.configuralize.DynamicConfig;
|
||||
import io.github.retrooper.packetevents.util.folia.FoliaScheduler;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
// Class from https://github.com/Tecnio/AntiCheatBase/blob/master/src/main/java/me/tecnio/anticheat/check/Check.java
|
||||
@Getter
|
||||
public class Check implements AbstractCheck {
|
||||
public class Check implements AbstractCheck, ConfigReloadObserver {
|
||||
protected final GrimPlayer player;
|
||||
|
||||
public double violations;
|
||||
@@ -28,6 +30,7 @@ public class Check implements AbstractCheck {
|
||||
private boolean experimental;
|
||||
@Setter
|
||||
private boolean isEnabled;
|
||||
private boolean exempted;
|
||||
|
||||
@Override
|
||||
public boolean isExperimental() {
|
||||
@@ -51,12 +54,19 @@ public class Check implements AbstractCheck {
|
||||
this.experimental = checkData.experimental();
|
||||
this.description = checkData.description();
|
||||
}
|
||||
|
||||
//
|
||||
reload();
|
||||
}
|
||||
|
||||
public boolean shouldModifyPackets() {
|
||||
return isEnabled && !player.disableGrim && !player.noModifyPacketPermission;
|
||||
return isEnabled && !player.disableGrim && !player.noModifyPacketPermission && !exempted;
|
||||
}
|
||||
|
||||
public void updateExempted() {
|
||||
if (player.bukkitPlayer == null || checkName == null) return;
|
||||
FoliaScheduler.getEntityScheduler().run(player.bukkitPlayer, GrimAPI.INSTANCE.getPlugin(),
|
||||
t -> exempted = player.bukkitPlayer.hasPermission("grim.exempt." + checkName.toLowerCase()),
|
||||
() -> {});
|
||||
}
|
||||
|
||||
public final boolean flagAndAlert(String verbose) {
|
||||
@@ -72,7 +82,7 @@ public class Check implements AbstractCheck {
|
||||
}
|
||||
|
||||
public final boolean flag() {
|
||||
if (player.disableGrim || (experimental && !GrimAPI.INSTANCE.getConfigManager().isExperimentalChecks()))
|
||||
if (player.disableGrim || (experimental && !player.isExperimentalChecks()) || exempted)
|
||||
return false; // Avoid calling event if disabled
|
||||
|
||||
FlagEvent event = new FlagEvent(player, this);
|
||||
@@ -98,21 +108,24 @@ public class Check implements AbstractCheck {
|
||||
violations = Math.max(0, violations - decay);
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
decay = getConfig().getDoubleElse(configName + ".decay", decay);
|
||||
setbackVL = getConfig().getDoubleElse(configName + ".setbackvl", setbackVL);
|
||||
|
||||
@Override
|
||||
public void reload(ConfigManager configuration) {
|
||||
decay = configuration.getDoubleElse(configName + ".decay", decay);
|
||||
setbackVL = configuration.getDoubleElse(configName + ".setbackvl", setbackVL);
|
||||
if (setbackVL == -1) setbackVL = Double.MAX_VALUE;
|
||||
updateExempted();
|
||||
onReload(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
|
||||
}
|
||||
|
||||
public boolean alert(String verbose) {
|
||||
return player.punishmentManager.handleAlert(player, verbose, this);
|
||||
}
|
||||
|
||||
public DynamicConfig getConfig() {
|
||||
return GrimAPI.INSTANCE.getConfigManager().getConfig();
|
||||
}
|
||||
|
||||
public boolean setbackIfAboveSetbackVL() {
|
||||
if (getViolations() > setbackVL) {
|
||||
return player.getSetbackTeleportUtil().executeViolationSetback();
|
||||
@@ -133,5 +146,10 @@ public class Check implements AbstractCheck {
|
||||
packetType == PacketType.Play.Client.WINDOW_CONFIRMATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
reload(GrimAPI.INSTANCE.getConfigManager().getConfig());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,12 +19,14 @@ public class AimModulo360 extends Check implements RotationCheck {
|
||||
|
||||
@Override
|
||||
public void process(final RotationUpdate rotationUpdate) {
|
||||
lastDeltaYaw = rotationUpdate.getDeltaXRot();
|
||||
if (player.packetStateData.lastPacketWasTeleport) return;
|
||||
|
||||
if (player.xRot < 360 && player.xRot > -360 && Math.abs(rotationUpdate.getDeltaXRot()) > 320 && Math.abs(lastDeltaYaw) < 30) {
|
||||
flagAndAlert();
|
||||
} else {
|
||||
reward();
|
||||
}
|
||||
|
||||
lastDeltaYaw = rotationUpdate.getDeltaXRot();
|
||||
}
|
||||
}
|
||||
@@ -25,17 +25,16 @@ public class BadPacketsX extends Check implements PacketCheck {
|
||||
if (dig.getAction() != DiggingAction.START_DIGGING && dig.getAction() != DiggingAction.FINISHED_DIGGING)
|
||||
return;
|
||||
|
||||
final boolean invalid;
|
||||
|
||||
if (dig.getAction() == DiggingAction.FINISHED_DIGGING) {
|
||||
invalid = BlockBreakSpeed.getBlockDamage(player, dig.getBlockPosition()) >= 1 || block.getHardness() == -1.0f;
|
||||
} else invalid = (block == StateTypes.LIGHT && !(player.getInventory().getHeldItem().is(ItemTypes.LIGHT) || player.getInventory().getOffHand().is(ItemTypes.LIGHT)))
|
||||
// the block does not have a hitbox
|
||||
boolean invalid = (block == StateTypes.LIGHT && !(player.getInventory().getHeldItem().is(ItemTypes.LIGHT) || player.getInventory().getOffHand().is(ItemTypes.LIGHT)))
|
||||
|| block.isAir()
|
||||
|| block == StateTypes.WATER
|
||||
|| block == StateTypes.LAVA
|
||||
|| block == StateTypes.BUBBLE_COLUMN
|
||||
|| block == StateTypes.MOVING_PISTON
|
||||
|| (block == StateTypes.FIRE && noFireHitbox);
|
||||
|| (block == StateTypes.FIRE && noFireHitbox)
|
||||
// or the client claims to have broken an unbreakable block
|
||||
|| block.getHardness() == -1.0f && dig.getAction() == DiggingAction.FINISHED_DIGGING;
|
||||
|
||||
if (invalid && flagAndAlert("block=" + block.getName() + ", type=" + dig.getAction()) && shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
|
||||
@@ -4,7 +4,10 @@ import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.DiggingAction;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
@@ -21,7 +24,7 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
|
||||
private boolean lastBlockWasInstantBreak = false;
|
||||
private Vector3i lastBlock, lastCancelledBlock, lastLastBlock = null;
|
||||
private final int exemptedY = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8) ? 4095 : 255;
|
||||
private final int exemptedY = player.getClientVersion().isOlderThan(ClientVersion.V_1_8) ? 255 : (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_14) ? -1 : 4095);
|
||||
|
||||
// The client sometimes sends a wierd cancel packet
|
||||
private boolean shouldExempt(final Vector3i pos) {
|
||||
@@ -33,18 +36,10 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) && pos.y != exemptedY)
|
||||
return false;
|
||||
|
||||
// the client only sends this packet if the last block was an instant break
|
||||
if (getBlockDamage(player, lastBlock) < 1)
|
||||
return false;
|
||||
|
||||
// and if this block is not an instant break
|
||||
return player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) || getBlockDamage(player, pos) < 1;
|
||||
}
|
||||
|
||||
private String formatted(Vector3i vec) {
|
||||
return vec == null ? "null" : vec.x + ", " + vec.y + ", " + vec.z;
|
||||
}
|
||||
|
||||
public void handle(PacketReceiveEvent event, WrapperPlayClientPlayerDigging dig) {
|
||||
if (dig.getAction() == DiggingAction.START_DIGGING) {
|
||||
final Vector3i pos = dig.getBlockPosition();
|
||||
@@ -59,7 +54,7 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
final Vector3i pos = dig.getBlockPosition();
|
||||
|
||||
if (shouldExempt(pos)) {
|
||||
lastCancelledBlock = null;
|
||||
lastCancelledBlock = pos;
|
||||
lastLastBlock = null;
|
||||
lastBlock = null;
|
||||
return;
|
||||
@@ -68,7 +63,7 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
if (!pos.equals(lastBlock)) {
|
||||
// https://github.com/GrimAnticheat/Grim/issues/1512
|
||||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) || (!lastBlockWasInstantBreak && pos.equals(lastCancelledBlock))) {
|
||||
if (flagAndAlert("action=CANCELLED_DIGGING" + ", last=" + formatted(lastBlock) + ", pos=" + formatted(pos))) {
|
||||
if (flagAndAlert("action=CANCELLED_DIGGING" + ", last=" + MessageUtil.toUnlabledString(lastBlock) + ", pos=" + MessageUtil.toUnlabledString(pos))) {
|
||||
if (shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -89,7 +84,7 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
|
||||
// when a player looks away from the mined block, they send a cancel, and if they look at it again, they don't send another start. (thanks mojang!)
|
||||
if (!pos.equals(lastCancelledBlock) && (!lastBlockWasInstantBreak || player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4)) && !pos.equals(lastBlock)) {
|
||||
if (flagAndAlert("action=FINISHED_DIGGING" + ", last=" + formatted(lastBlock) + ", pos=" + formatted(pos))) {
|
||||
if (flagAndAlert("action=FINISHED_DIGGING" + ", last=" + MessageUtil.toUnlabledString(lastBlock) + ", pos=" + MessageUtil.toUnlabledString(pos))) {
|
||||
if (shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
package ac.grim.grimac.checks.impl.combat;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
@@ -201,8 +202,9 @@ public class Reach extends Check implements PacketCheck {
|
||||
|
||||
// +3 would be 3 + 3 = 6, which is the pre-1.20.5 behaviour, preventing "Missed Hitbox"
|
||||
final double distance = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_ENTITY_INTERACTION_RANGE) + 3;
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
for (Vector lookVec : possibleLookDirs) {
|
||||
for (double eye : player.getPossibleEyeHeights()) {
|
||||
for (double eye : possibleEyeHeights) {
|
||||
Vector eyePos = new Vector(from.getX(), from.getY() + eye, from.getZ());
|
||||
Vector endReachPos = eyePos.clone().add(new Vector(lookVec.getX() * distance, lookVec.getY() * distance, lookVec.getZ() * distance));
|
||||
|
||||
@@ -236,9 +238,8 @@ public class Reach extends Check implements PacketCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
super.reload();
|
||||
this.cancelImpossibleHits = getConfig().getBooleanElse("Reach.block-impossible-hits", true);
|
||||
this.threshold = getConfig().getDoubleElse("Reach.threshold", 0.0005);
|
||||
public void onReload(ConfigManager config) {
|
||||
this.cancelImpossibleHits = config.getBooleanElse("Reach.block-impossible-hits", true);
|
||||
this.threshold = config.getDoubleElse("Reach.threshold", 0.0005);
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,10 @@ public class NoFallA extends Check implements PacketCheck {
|
||||
if (!isNearGround(wrapper.isOnGround())) { // If player isn't near ground
|
||||
// 1.8 boats have a mind on their own... only flag if they're not near a boat or are on 1.9+
|
||||
if (!GhostBlockDetector.isGhostBlock(player) && flagWithSetback()) alert("");
|
||||
if (shouldModifyPackets()) wrapper.setOnGround(false);
|
||||
if (shouldModifyPackets()) {
|
||||
wrapper.setOnGround(false);
|
||||
event.markForReEncode(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,10 +62,16 @@ public class NoFallA extends Check implements PacketCheck {
|
||||
// Also flip teleports because I don't trust vanilla's handling of teleports and ground
|
||||
if (flipPlayerGroundStatus) {
|
||||
flipPlayerGroundStatus = false;
|
||||
if (shouldModifyPackets()) wrapper.setOnGround(!wrapper.isOnGround());
|
||||
if (shouldModifyPackets()) {
|
||||
wrapper.setOnGround(!wrapper.isOnGround());
|
||||
event.markForReEncode(true);
|
||||
}
|
||||
}
|
||||
if (player.packetStateData.lastPacketWasTeleport) {
|
||||
if (shouldModifyPackets()) wrapper.setOnGround(false);
|
||||
if (shouldModifyPackets()) {
|
||||
wrapper.setOnGround(false);
|
||||
event.markForReEncode(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ac.grim.grimac.checks.impl.misc;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.type.BlockPlaceCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.update.BlockPlace;
|
||||
@@ -63,10 +64,9 @@ public class GhostBlockMitigation extends BlockPlaceCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
super.reload();
|
||||
allow = getConfig().getBooleanElse("exploit.allow-building-on-ghostblocks", true);
|
||||
distance = getConfig().getIntElse("exploit.distance-to-check-for-ghostblocks", 2);
|
||||
public void onReload(ConfigManager config) {
|
||||
allow = config.getBooleanElse("exploit.allow-building-on-ghostblocks", true);
|
||||
distance = config.getIntElse("exploit.distance-to-check-for-ghostblocks", 2);
|
||||
|
||||
if (distance < 2 || distance > 4) distance = 2;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ac.grim.grimac.checks.impl.movement;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PostPredictionCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
@@ -35,8 +36,7 @@ public class NegativeTimerCheck extends TimerCheck implements PostPredictionChec
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
super.reload();
|
||||
clockDrift = (long) (getConfig().getDoubleElse(getConfigName() + ".drift", 1200.0) * 1e6);
|
||||
public void onReload(ConfigManager config) {
|
||||
clockDrift = (long) (config.getDoubleElse(getConfigName() + ".drift", 1200.0) * 1e6);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package ac.grim.grimac.checks.impl.movement;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PostPredictionCheck;
|
||||
@@ -51,8 +52,7 @@ public class NoSlowA extends Check implements PostPredictionCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
super.reload();
|
||||
offsetToFlag = getConfig().getDoubleElse("NoSlowA.threshold", 0.001);
|
||||
public void onReload(ConfigManager config) {
|
||||
offsetToFlag = config.getDoubleElse("NoSlowA.threshold", 0.001);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package ac.grim.grimac.checks.impl.movement;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
@@ -19,9 +20,9 @@ public class TimerCheck extends Check implements PacketCheck {
|
||||
|
||||
// How long should the player be able to fall back behind their ping?
|
||||
// Default: 120 milliseconds
|
||||
long clockDrift = (long) 120e6;
|
||||
long clockDrift;
|
||||
|
||||
long limitAbuseOverPing = 1000;
|
||||
long limitAbuseOverPing;
|
||||
|
||||
boolean hasGottenMovementAfterTransaction = false;
|
||||
|
||||
@@ -115,9 +116,8 @@ public class TimerCheck extends Check implements PacketCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
super.reload();
|
||||
clockDrift = (long) (getConfig().getDoubleElse(getConfigName() + ".drift", 120.0) * 1e6);
|
||||
limitAbuseOverPing = (long) (getConfig().getDoubleElse(getConfigName() + ".ping-abuse-limit-threshold", 1000));
|
||||
public void onReload(ConfigManager config) {
|
||||
clockDrift = (long) (config.getDoubleElse(getConfigName() + ".drift", 120.0) * 1e6);
|
||||
limitAbuseOverPing = (long) (config.getDoubleElse(getConfigName() + ".ping-abuse-limit-threshold", 1000));
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPl
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityAnimation;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
@@ -87,6 +86,7 @@ public class PostCheck extends Check implements PacketCheck, PostPredictionCheck
|
||||
post.clear();
|
||||
sentFlying = false;
|
||||
} else if (PLAYER_ABILITIES.equals(packetType)
|
||||
|| (HELD_ITEM_CHANGE.equals(packetType) && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8))
|
||||
|| INTERACT_ENTITY.equals(packetType) || PLAYER_BLOCK_PLACEMENT.equals(packetType)
|
||||
|| USE_ITEM.equals(packetType) || PLAYER_DIGGING.equals(packetType)) {
|
||||
if (sentFlying) post.add(event.getPacketType());
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ac.grim.grimac.checks.impl.prediction;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.api.events.CompletePredictionEvent;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
@@ -99,14 +100,12 @@ public class OffsetHandler extends Check implements PostPredictionCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
super.reload();
|
||||
setbackDecayMultiplier = getConfig().getDoubleElse("Simulation.setback-decay-multiplier", 0.999);
|
||||
threshold = getConfig().getDoubleElse("Simulation.threshold", 0.001);
|
||||
immediateSetbackThreshold = getConfig().getDoubleElse("Simulation.immediate-setback-threshold", 0.1);
|
||||
maxAdvantage = getConfig().getDoubleElse("Simulation.max-advantage", 1);
|
||||
maxCeiling = getConfig().getDoubleElse("Simulation.max-ceiling", 4);
|
||||
|
||||
public void onReload(ConfigManager config) {
|
||||
setbackDecayMultiplier = config.getDoubleElse("Simulation.setback-decay-multiplier", 0.999);
|
||||
threshold = config.getDoubleElse("Simulation.threshold", 0.001);
|
||||
immediateSetbackThreshold = config.getDoubleElse("Simulation.immediate-setback-threshold", 0.1);
|
||||
maxAdvantage = config.getDoubleElse("Simulation.max-advantage", 1);
|
||||
maxCeiling = config.getDoubleElse("Simulation.max-ceiling", 4);
|
||||
if (maxAdvantage == -1) maxAdvantage = Double.MAX_VALUE;
|
||||
if (immediateSetbackThreshold == -1) immediateSetbackThreshold = Double.MAX_VALUE;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ac.grim.grimac.checks.impl.scaffolding;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.BlockPlaceCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
@@ -29,8 +30,7 @@ public class AirLiquidPlace extends BlockPlaceCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
super.reload();
|
||||
this.cancelVL = getConfig().getIntElse(getConfigName() + ".cancelVL", 0);
|
||||
public void onReload(ConfigManager config) {
|
||||
this.cancelVL = config.getIntElse(getConfigName() + ".cancelVL", 0);
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,8 @@ public class FarPlace extends BlockPlaceCheck {
|
||||
if (place.getMaterial() == StateTypes.SCAFFOLDING) return;
|
||||
|
||||
double min = Double.MAX_VALUE;
|
||||
for (double d : player.getPossibleEyeHeights()) {
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
for (double d : possibleEyeHeights) {
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(blockPos);
|
||||
Vector eyes = new Vector(player.x, player.y + d, player.z);
|
||||
Vector best = VectorUtils.cutBoxToVector(eyes, box);
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package ac.grim.grimac.checks.impl.scaffolding;
|
||||
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.BlockPlaceCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
import ac.grim.grimac.utils.anticheat.update.BlockPlace;
|
||||
import ac.grim.grimac.utils.anticheat.update.PredictionComplete;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.util.Vector3f;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@CheckData(name = "MultiPlace", experimental = true)
|
||||
public class MultiPlace extends BlockPlaceCheck {
|
||||
public MultiPlace(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
private final List<String> flags = new ArrayList<>();
|
||||
|
||||
private boolean hasPlaced;
|
||||
private BlockFace lastFace;
|
||||
private Vector3f lastCursor;
|
||||
private Vector3i lastPos;
|
||||
|
||||
@Override
|
||||
public void onBlockPlace(final BlockPlace place) {
|
||||
final BlockFace face = place.getDirection();
|
||||
final Vector3f cursor = place.getCursor();
|
||||
final Vector3i pos = place.getPlacedAgainstBlockLocation();
|
||||
|
||||
if (hasPlaced && (face != lastFace || !cursor.equals(lastCursor) || !pos.equals(lastPos))) {
|
||||
final String verbose = "face=" + face + ", lastFace=" + lastFace
|
||||
+ ", cursor=" + MessageUtil.toUnlabledString(cursor) + ", lastCursor=" + MessageUtil.toUnlabledString(lastCursor)
|
||||
+ ", pos=" + MessageUtil.toUnlabledString(pos) + ", lastPos=" + MessageUtil.toUnlabledString(lastPos);
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) {
|
||||
if (flagAndAlert(verbose) && shouldModifyPackets() && shouldCancel()) {
|
||||
place.resync();
|
||||
}
|
||||
} else {
|
||||
flags.add(verbose);
|
||||
}
|
||||
}
|
||||
|
||||
lastFace = face;
|
||||
lastCursor = cursor;
|
||||
lastPos = pos;
|
||||
hasPlaced = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType()) && !player.packetStateData.lastPacketWasTeleport && !player.packetStateData.lastPacketWasOnePointSeventeenDuplicate) {
|
||||
hasPlaced = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (player.getClientVersion().isNewerThan(ClientVersion.V_1_8) && !player.skippedTickInActualMovement && predictionComplete.isChecked()) {
|
||||
for (String verbose : flags) {
|
||||
flagAndAlert(verbose);
|
||||
}
|
||||
}
|
||||
|
||||
flags.clear();
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,13 @@ public class PositionPlace extends BlockPlaceCheck {
|
||||
// Each position represents the best case scenario to have clicked
|
||||
//
|
||||
// We will now calculate the most optimal position for the player's head to be in
|
||||
double minEyeHeight = Collections.min(player.getPossibleEyeHeights());
|
||||
double maxEyeHeight = Collections.max(player.getPossibleEyeHeights());
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
double minEyeHeight = Double.MAX_VALUE;
|
||||
double maxEyeHeight = Double.MIN_VALUE;
|
||||
for (double height : possibleEyeHeights) {
|
||||
minEyeHeight = Math.min(minEyeHeight, height);
|
||||
maxEyeHeight = Math.max(maxEyeHeight, height);
|
||||
}
|
||||
// I love the idle packet, why did you remove it mojang :(
|
||||
// Don't give 0.03 lenience if the player is a 1.8 player and we know they couldn't have 0.03'd because idle packet
|
||||
double movementThreshold = !player.packetStateData.didLastMovementIncludePosition || player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? player.getMovementThreshold() : 0;
|
||||
|
||||
@@ -10,6 +10,7 @@ import ac.grim.grimac.utils.nmsutil.Ray;
|
||||
import ac.grim.grimac.utils.nmsutil.ReachUtils;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
@@ -33,6 +34,7 @@ public class RotationPlace extends BlockPlaceCheck {
|
||||
@Override
|
||||
public void onBlockPlace(final BlockPlace place) {
|
||||
if (place.getMaterial() == StateTypes.SCAFFOLDING) return;
|
||||
if (player.gamemode == GameMode.SPECTATOR) return; // you don't send flying packets when spectating entities
|
||||
if (flagBuffer > 0 && !didRayTraceHit(place)) {
|
||||
ignorePost = true;
|
||||
// If the player hit and has flagged this check recently
|
||||
@@ -46,6 +48,7 @@ public class RotationPlace extends BlockPlaceCheck {
|
||||
@Override
|
||||
public void onPostFlyingBlockPlace(BlockPlace place) {
|
||||
if (place.getMaterial() == StateTypes.SCAFFOLDING) return;
|
||||
if (player.gamemode == GameMode.SPECTATOR) return; // you don't send flying packets when spectating entities
|
||||
|
||||
// Don't flag twice
|
||||
if (ignorePost) {
|
||||
@@ -68,13 +71,19 @@ public class RotationPlace extends BlockPlaceCheck {
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(place.getPlacedAgainstBlockLocation());
|
||||
|
||||
List<Vector3f> possibleLookDirs = new ArrayList<>(Arrays.asList(
|
||||
new Vector3f(player.lastXRot, player.yRot, 0),
|
||||
new Vector3f(player.xRot, player.yRot, 0)
|
||||
new Vector3f(player.xRot, player.yRot, 0),
|
||||
new Vector3f(player.lastXRot, player.yRot, 0)
|
||||
));
|
||||
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
|
||||
// Start checking if player is in the block
|
||||
double minEyeHeight = Collections.min(player.getPossibleEyeHeights());
|
||||
double maxEyeHeight = Collections.max(player.getPossibleEyeHeights());
|
||||
double minEyeHeight = Double.MAX_VALUE;
|
||||
double maxEyeHeight = Double.MIN_VALUE;
|
||||
for (double height : possibleEyeHeights) {
|
||||
minEyeHeight = Math.min(minEyeHeight, height);
|
||||
maxEyeHeight = Math.max(maxEyeHeight, height);
|
||||
}
|
||||
|
||||
SimpleCollisionBox eyePositions = new SimpleCollisionBox(player.x, player.y + minEyeHeight, player.z, player.x, player.y + maxEyeHeight, player.z);
|
||||
eyePositions.expand(player.getMovementThreshold());
|
||||
@@ -96,7 +105,7 @@ public class RotationPlace extends BlockPlaceCheck {
|
||||
}
|
||||
|
||||
final double distance = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE);
|
||||
for (double d : player.getPossibleEyeHeights()) {
|
||||
for (double d : possibleEyeHeights) {
|
||||
for (Vector3f lookDir : possibleLookDirs) {
|
||||
// x, y, z are correct for the block placement even after post tick because of code elsewhere
|
||||
Vector3d starting = new Vector3d(player.x, player.y + d, player.z);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ac.grim.grimac.checks.impl.velocity;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PostPredictionCheck;
|
||||
@@ -18,7 +19,6 @@ import com.github.retrooper.packetevents.util.Vector3f;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerExplosion;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -256,12 +256,10 @@ public class ExplosionHandler extends Check implements PostPredictionCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
super.reload();
|
||||
|
||||
offsetToFlag = getConfig().getDoubleElse("Explosion.threshold", 0.00001);
|
||||
setbackVL = getConfig().getDoubleElse("Explosion.setbackvl", 10);
|
||||
|
||||
public void onReload(ConfigManager config) {
|
||||
offsetToFlag = config.getDoubleElse("Explosion.threshold", 0.00001);
|
||||
setbackVL = config.getDoubleElse("Explosion.setbackvl", 10);
|
||||
if (setbackVL == -1) setbackVL = Double.MAX_VALUE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package ac.grim.grimac.checks.impl.velocity;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PostPredictionCheck;
|
||||
@@ -240,15 +241,14 @@ public class KnockbackHandler extends Check implements PostPredictionCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
super.reload();
|
||||
offsetToFlag = getConfig().getDoubleElse("Knockback.threshold", 0.001);
|
||||
maxAdv = getConfig().getDoubleElse("Knockback.max-advantage", 1);
|
||||
immediate = getConfig().getDoubleElse("Knockback.immediate-setback-threshold", 0.1);
|
||||
multiplier = getConfig().getDoubleElse("Knockback.setback-decay-multiplier", 0.999);
|
||||
ceiling = getConfig().getDoubleElse("Knockback.max-ceiling", 4);
|
||||
|
||||
public void onReload(ConfigManager config) {
|
||||
offsetToFlag = config.getDoubleElse("Knockback.threshold", 0.001);
|
||||
maxAdv = config.getDoubleElse("Knockback.max-advantage", 1);
|
||||
immediate = config.getDoubleElse("Knockback.immediate-setback-threshold", 0.1);
|
||||
multiplier = config.getDoubleElse("Knockback.setback-decay-multiplier", 0.999);
|
||||
ceiling = config.getDoubleElse("Knockback.max-ceiling", 4);
|
||||
if (maxAdv < 0) maxAdv = Double.MAX_VALUE;
|
||||
if (immediate < 0) immediate = Double.MAX_VALUE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package ac.grim.grimac.checks.type;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.update.BlockPlace;
|
||||
@@ -14,7 +15,7 @@ import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BlockPlaceCheck extends Check implements RotationCheck {
|
||||
public class BlockPlaceCheck extends Check implements RotationCheck, PostPredictionCheck {
|
||||
private static final List<StateType> weirdBoxes = new ArrayList<>();
|
||||
private static final List<StateType> buggyBoxes = new ArrayList<>();
|
||||
|
||||
@@ -33,9 +34,8 @@ public class BlockPlaceCheck extends Check implements RotationCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
super.reload();
|
||||
this.cancelVL = getConfig().getIntElse(getConfigName() + ".cancelVL", 5);
|
||||
public void onReload(ConfigManager config) {
|
||||
this.cancelVL = config.getIntElse(getConfigName() + ".cancelVL", 5);
|
||||
}
|
||||
|
||||
protected boolean shouldCancel() {
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
package ac.grim.grimac.commands;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
import co.aikar.commands.BaseCommand;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import com.github.retrooper.packetevents.netty.channel.ChannelHelper;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
@CommandAlias("grim|grimac")
|
||||
@@ -18,14 +14,15 @@ public class GrimReload extends BaseCommand {
|
||||
@CommandPermission("grim.reload")
|
||||
public void onReload(CommandSender sender) {
|
||||
//reload config
|
||||
try {
|
||||
GrimAPI.INSTANCE.getExternalAPI().reload();
|
||||
} catch (RuntimeException e) {
|
||||
sender.sendMessage(ChatColor.RED + e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
sender.sendMessage(MessageUtil.format("%prefix% &fConfig has been reloaded."));
|
||||
sender.sendMessage(MessageUtil.format("%prefix% &7Reloading config..."));
|
||||
GrimAPI.INSTANCE.getExternalAPI().reloadAsync().exceptionally(throwable -> false)
|
||||
.thenAccept(bool -> {
|
||||
if (bool) {
|
||||
sender.sendMessage(MessageUtil.format("%prefix% &fConfig has been reloaded."));
|
||||
} else {
|
||||
sender.sendMessage(MessageUtil.format("%prefix% &cFailed to reload config."));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,7 +20,7 @@ public class GrimSendAlert extends BaseCommand {
|
||||
bukkitPlayer.sendMessage(string);
|
||||
}
|
||||
|
||||
if (GrimAPI.INSTANCE.getConfigManager().getConfig().getBooleanElse("alerts.print-to-console", true)) {
|
||||
if (GrimAPI.INSTANCE.getConfigManager().isPrintAlertsToConsole()) {
|
||||
LogUtil.console(string); // Print alert to console
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,7 +348,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
// Additionally, only yaw/pitch matters: https://github.com/GrimAnticheat/Grim/issues/1275#issuecomment-1872444018
|
||||
// 1.9+ isn't impacted by this packet as much.
|
||||
if (PacketEvents.getAPI().getServerManager().getVersion().isOlderThanOrEquals(ServerVersion.V_1_9)) {
|
||||
if (GrimAPI.INSTANCE.getConfigManager().getConfig().getBooleanElse("cancel-duplicate-packet", true)) {
|
||||
if (player.isCancelDuplicatePacket()) {
|
||||
player.packetStateData.cancelDuplicatePacket = true;
|
||||
}
|
||||
} else {
|
||||
@@ -358,7 +358,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
|
||||
player.packetStateData.lastPacketWasOnePointSeventeenDuplicate = true;
|
||||
|
||||
if (!GrimAPI.INSTANCE.getConfigManager().isIgnoreDuplicatePacketRotation()) {
|
||||
if (!player.isIgnoreDuplicatePacketRotation()) {
|
||||
if (player.xRot != location.getYaw() || player.yRot != location.getPitch()) {
|
||||
player.lastXRot = player.xRot;
|
||||
player.lastYRot = player.yRot;
|
||||
@@ -428,7 +428,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) {
|
||||
WrapperPlayClientPlayerFlying flying = new WrapperPlayClientPlayerFlying(event);
|
||||
Location pos = flying.getLocation();
|
||||
boolean ignoreRotation = player.packetStateData.lastPacketWasOnePointSeventeenDuplicate && GrimAPI.INSTANCE.getConfigManager().isIgnoreDuplicatePacketRotation();
|
||||
boolean ignoreRotation = player.packetStateData.lastPacketWasOnePointSeventeenDuplicate && player.isIgnoreDuplicatePacketRotation();
|
||||
handleFlying(player, pos.getX(), pos.getY(), pos.getZ(), ignoreRotation ? player.xRot : pos.getYaw(), ignoreRotation ? player.yRot : pos.getPitch(), flying.hasPositionChanged(), flying.hasRotationChanged(), flying.isOnGround(), teleportData, event);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package ac.grim.grimac.events.packets;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
@@ -53,7 +53,6 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
private final List<Integer> despawnedEntitiesThisTransaction = new ArrayList<>();
|
||||
|
||||
// Maximum ping when a firework boost is removed from the player.
|
||||
private final int maxFireworkBoostPing = GrimAPI.INSTANCE.getConfigManager().getConfig().getIntElse("max-ping-firework-boost", 1000);
|
||||
|
||||
public PacketEntityReplication(GrimPlayer player) {
|
||||
super(player);
|
||||
@@ -500,4 +499,12 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
public void tickStartTick() {
|
||||
hasSentPreWavePacket = false;
|
||||
}
|
||||
|
||||
private int maxFireworkBoostPing = 1000;
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
maxFireworkBoostPing = config.getIntElse("max-ping-firework-boost", 1000);
|
||||
}
|
||||
|
||||
}
|
||||
+15
-34
@@ -5,14 +5,11 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||
import com.github.retrooper.packetevents.event.PacketListenerPriority;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.event.PacketSendEvent;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
|
||||
import com.github.retrooper.packetevents.protocol.player.UserProfile;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfo;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoUpdate;
|
||||
|
||||
@@ -20,22 +17,15 @@ import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
public class PacketSetWrapperNull extends PacketListenerAbstract {
|
||||
// It's faster (and less buggy) to simply not re-encode the wrapper unless we changed something
|
||||
// The two packets we change are clientbound entity metadata (to fix a netcode issue)
|
||||
// and the serverbound player flying packets (to patch NoFall)
|
||||
public PacketSetWrapperNull() {
|
||||
public class PacketHidePlayerInfo extends PacketListenerAbstract {
|
||||
|
||||
public PacketHidePlayerInfo() {
|
||||
super(PacketListenerPriority.HIGHEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(PacketSendEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.ENTITY_METADATA) {
|
||||
WrapperPlayServerEntityMetadata wrapper = new WrapperPlayServerEntityMetadata(event);
|
||||
if (wrapper.getEntityId() != event.getUser().getEntityId()) {
|
||||
event.setLastUsedWrapper(null);
|
||||
}
|
||||
} else if (event.getPacketType() == PacketType.Play.Server.PLAYER_INFO) {
|
||||
if (event.getPacketType() == PacketType.Play.Server.PLAYER_INFO) {
|
||||
//iterate through players and fake their game mode if they are spectating via grim spectate
|
||||
if (PacketEvents.getAPI().getServerManager().getVersion().isOlderThanOrEquals(ServerVersion.V_1_12_2))
|
||||
return;
|
||||
@@ -62,8 +52,8 @@ public class PacketSetWrapperNull extends PacketListenerAbstract {
|
||||
//if amount of hidden players is the amount of players updated & is an update game mode action just cancel it
|
||||
if (hideCount == nmsPlayerInfoDataList.size() && info.getAction() == WrapperPlayServerPlayerInfo.Action.UPDATE_GAME_MODE) {
|
||||
event.setCancelled(true);
|
||||
} else if (hideCount <= 0) {
|
||||
event.setLastUsedWrapper(null);
|
||||
} else if (hideCount > 0) {
|
||||
event.markForReEncode(true);
|
||||
}
|
||||
}
|
||||
} else if (event.getPacketType() == PacketType.Play.Server.PLAYER_INFO_UPDATE) {
|
||||
@@ -81,12 +71,13 @@ public class PacketSetWrapperNull extends PacketListenerAbstract {
|
||||
for (WrapperPlayServerPlayerInfoUpdate.PlayerInfo entry : wrapper.getEntries()) {
|
||||
//check if the player should be hidden
|
||||
WrapperPlayServerPlayerInfoUpdate.PlayerInfo modifiedPacket = null;
|
||||
if (GrimAPI.INSTANCE.getSpectateManager().shouldHidePlayer(receiver, entry.getProfileId())) {
|
||||
final UserProfile gameProfile = entry.getGameProfile();
|
||||
if (GrimAPI.INSTANCE.getSpectateManager().shouldHidePlayer(receiver, gameProfile.getUUID())) {
|
||||
hideCount++;
|
||||
//modify & create a new packet from pre-existing one if they are a spectator
|
||||
if (entry.getGameMode() == GameMode.SPECTATOR) {
|
||||
modifiedPacket = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo(
|
||||
entry.getGameProfile(),
|
||||
gameProfile,
|
||||
entry.isListed(),
|
||||
entry.getLatency(),
|
||||
GameMode.SURVIVAL,
|
||||
@@ -104,30 +95,20 @@ public class PacketSetWrapperNull extends PacketListenerAbstract {
|
||||
} //if only the game mode was updated and the packet was modified, don't send anything
|
||||
|
||||
}
|
||||
//if no hidden players, don't modify packet
|
||||
if (hideCount <= 0) {
|
||||
event.setLastUsedWrapper(null);
|
||||
} else if (hideCount == modified.size()) { //if the amount of hidden players & modified entries are the same
|
||||
|
||||
// if the amount of hidden players & modified entries are the same
|
||||
if (hideCount == modified.size()) {
|
||||
if (onlyGameMode) { // if only the game mode changed, cancel
|
||||
event.setCancelled(true);
|
||||
} else { //if more than the game mode changed, remove the action
|
||||
wrapper.getActions().remove(WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_GAME_MODE);
|
||||
event.markForReEncode(true);
|
||||
}
|
||||
} else { //modify entries
|
||||
wrapper.setEntries(modified);
|
||||
event.markForReEncode(true);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (event.getPacketType() != PacketType.Play.Server.PLAYER_POSITION_AND_LOOK) {
|
||||
event.setLastUsedWrapper(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
PacketTypeCommon packetType = event.getPacketType();
|
||||
if (!WrapperPlayClientPlayerFlying.isFlying(packetType) && packetType != PacketType.Play.Client.CLIENT_SETTINGS && !event.isCancelled()) {
|
||||
event.setLastUsedWrapper(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package ac.grim.grimac.events.packets;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
@@ -37,7 +37,6 @@ public class PacketPlayerAbilities extends Check implements PacketCheck {
|
||||
|
||||
if (lastSentPlayerCanFly && !abilities.isFlightAllowed()) {
|
||||
int noFlying = player.lastTransactionSent.get();
|
||||
int maxFlyingPing = GrimAPI.INSTANCE.getConfigManager().getConfig().getIntElse("max-ping-out-of-flying", 1000);
|
||||
if (maxFlyingPing != -1) {
|
||||
player.runNettyTaskInMs(() -> {
|
||||
if (player.lastTransactionReceived.get() < noFlying) {
|
||||
@@ -56,4 +55,12 @@ public class PacketPlayerAbilities extends Check implements PacketCheck {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int maxFlyingPing = 1000;
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
maxFlyingPing = config.getIntElse("max-ping-out-of-flying", 1000);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -175,7 +175,7 @@ public class PacketPlayerDigging extends PacketListenerAbstract {
|
||||
if (player == null) return;
|
||||
|
||||
if (!player.packetStateData.lastPacketWasTeleport && !player.packetStateData.lastPacketWasOnePointSeventeenDuplicate) {
|
||||
if (player.packetStateData.isSlowedByUsingItem() && player.packetStateData.getSlowedByUsingItemSlot() != player.packetStateData.lastSlotSelected) {
|
||||
if (player.packetStateData.isSlowedByUsingItem() && player.packetStateData.eatingHand != InteractionHand.OFF_HAND && player.packetStateData.getSlowedByUsingItemSlot() != player.packetStateData.lastSlotSelected) {
|
||||
player.packetStateData.setSlowedByUsingItem(false);
|
||||
player.checkManager.getPostPredictionCheck(NoSlowA.class).didSlotChangeLastTick = true;
|
||||
}
|
||||
@@ -196,7 +196,7 @@ public class PacketPlayerDigging extends PacketListenerAbstract {
|
||||
|
||||
if (player.packetStateData.lastSlotSelected != slot) {
|
||||
// just assume they tick after this
|
||||
if (!player.isTickingReliablyFor(3) && player.skippedTickInActualMovement) {
|
||||
if (!player.isTickingReliablyFor(3) && player.skippedTickInActualMovement && player.packetStateData.eatingHand != InteractionHand.OFF_HAND) {
|
||||
player.packetStateData.setSlowedByUsingItem(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,6 @@ public class PacketPlayerRespawn extends PacketListenerAbstract {
|
||||
player.compensatedEntities.serverPositionsMap.clear();
|
||||
}
|
||||
|
||||
// TODO: What does keep all metadata do?
|
||||
player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get() + 1, () -> {
|
||||
player.isSneaking = false;
|
||||
player.lastOnGround = false;
|
||||
@@ -141,8 +140,16 @@ public class PacketPlayerRespawn extends PacketListenerAbstract {
|
||||
player.packetStateData.lastClaimedPosition = new Vector3d();
|
||||
player.filterMojangStupidityOnMojangStupidity = new Vector3d();
|
||||
|
||||
final boolean keepTrackedData = this.hasFlag(respawn, KEEP_TRACKED_DATA);
|
||||
|
||||
if (!keepTrackedData) {
|
||||
player.powderSnowFrozenTicks = 0;
|
||||
player.compensatedEntities.getSelf().hasGravity = true;
|
||||
player.playerEntityHasGravity = true;
|
||||
}
|
||||
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_19_4)) {
|
||||
if (!this.hasFlag(respawn, KEEP_TRACKED_DATA)) {
|
||||
if (!keepTrackedData) {
|
||||
player.isSprinting = false;
|
||||
}
|
||||
} else {
|
||||
@@ -184,7 +191,6 @@ public class PacketPlayerRespawn extends PacketListenerAbstract {
|
||||
player.compensatedWorld.setDimension(respawn.getDimensionType(), event.getUser());
|
||||
}
|
||||
|
||||
// TODO And there should probably be some attribute holder that we can just call reset() on.
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_16) && !this.hasFlag(respawn, KEEP_ATTRIBUTES)) {
|
||||
// Reset attributes if not kept
|
||||
player.compensatedEntities.getSelf().resetAttributes();
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class PacketSelfMetadataListener extends PacketListenerAbstract {
|
||||
|
||||
public PacketSelfMetadataListener() {
|
||||
super(PacketListenerPriority.HIGH);
|
||||
}
|
||||
@@ -68,6 +69,7 @@ public class PacketSelfMetadataListener extends PacketListenerAbstract {
|
||||
// Remove the pose metadata from the list
|
||||
metadataStuff.removeIf(element -> element.getIndex() == 6);
|
||||
entityMetadata.setEntityMetadata(metadataStuff);
|
||||
event.markForReEncode(true);
|
||||
}
|
||||
|
||||
EntityData watchable = WatchableIndexUtil.getIndex(entityMetadata.getEntityMetadata(), 0);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package ac.grim.grimac.manager;
|
||||
|
||||
|
||||
import ac.grim.grimac.api.AbstractCheck;
|
||||
import ac.grim.grimac.checks.impl.aim.AimDuplicateLook;
|
||||
import ac.grim.grimac.checks.impl.aim.AimModulo360;
|
||||
@@ -33,6 +32,7 @@ import ac.grim.grimac.manager.init.start.SuperDebug;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.predictionengine.GhostBlockDetector;
|
||||
import ac.grim.grimac.predictionengine.SneakingEstimator;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import ac.grim.grimac.utils.anticheat.update.*;
|
||||
import ac.grim.grimac.utils.latency.CompensatedCooldown;
|
||||
import ac.grim.grimac.utils.latency.CompensatedFireworks;
|
||||
@@ -42,8 +42,13 @@ import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.event.PacketSendEvent;
|
||||
import com.google.common.collect.ClassToInstanceMap;
|
||||
import com.google.common.collect.ImmutableClassToInstanceMap;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
|
||||
public class CheckManager {
|
||||
private static boolean inited;
|
||||
|
||||
ClassToInstanceMap<PacketCheck> packetChecks;
|
||||
ClassToInstanceMap<PositionCheck> positionCheck;
|
||||
ClassToInstanceMap<RotationCheck> rotationCheck;
|
||||
@@ -139,6 +144,7 @@ public class CheckManager {
|
||||
.put(InvalidPlaceA.class, new InvalidPlaceA(player))
|
||||
.put(InvalidPlaceB.class, new InvalidPlaceB(player))
|
||||
.put(AirLiquidPlace.class, new AirLiquidPlace(player))
|
||||
.put(MultiPlace.class, new MultiPlace(player))
|
||||
.put(FarPlace.class, new FarPlace(player))
|
||||
.put(FabricatedPlace.class, new FabricatedPlace(player))
|
||||
.put(PositionPlace.class, new PositionPlace(player))
|
||||
@@ -171,6 +177,8 @@ public class CheckManager {
|
||||
.putAll(blockPlaceCheck)
|
||||
.putAll(prePredictionChecks)
|
||||
.build();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -201,6 +209,9 @@ public class CheckManager {
|
||||
for (PostPredictionCheck check : postPredictionCheck.values()) {
|
||||
check.onPacketReceive(packet);
|
||||
}
|
||||
for (BlockPlaceCheck check : blockPlaceCheck.values()) {
|
||||
check.onPacketReceive(packet);
|
||||
}
|
||||
}
|
||||
|
||||
public void onPacketSend(final PacketSendEvent packet) {
|
||||
@@ -213,6 +224,9 @@ public class CheckManager {
|
||||
for (PostPredictionCheck check : postPredictionCheck.values()) {
|
||||
check.onPacketSend(packet);
|
||||
}
|
||||
for (BlockPlaceCheck check : blockPlaceCheck.values()) {
|
||||
check.onPacketSend(packet);
|
||||
}
|
||||
}
|
||||
|
||||
public void onPositionUpdate(final PositionUpdate position) {
|
||||
@@ -240,6 +254,9 @@ public class CheckManager {
|
||||
for (PostPredictionCheck check : postPredictionCheck.values()) {
|
||||
check.onPredictionComplete(complete);
|
||||
}
|
||||
for (BlockPlaceCheck check : blockPlaceCheck.values()) {
|
||||
check.onPredictionComplete(complete);
|
||||
}
|
||||
}
|
||||
|
||||
public void onBlockPlace(final BlockPlace place) {
|
||||
@@ -314,4 +331,22 @@ public class CheckManager {
|
||||
public <T extends PostPredictionCheck> T getPostPredictionCheck(Class<T> check) {
|
||||
return (T) postPredictionCheck.get(check);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
if (inited) return;
|
||||
for (AbstractCheck check : allChecks.values()) {
|
||||
if (check.getCheckName() != null) {
|
||||
String permissionName = "grim.exempt." + check.getCheckName().toLowerCase();
|
||||
Permission permission = Bukkit.getPluginManager().getPermission(permissionName);
|
||||
|
||||
if (permission == null) {
|
||||
Bukkit.getPluginManager().addPermission(new Permission(permissionName, PermissionDefault.FALSE));
|
||||
} else {
|
||||
permission.setDefault(PermissionDefault.FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inited = true;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ public class DiscordManager implements Initable {
|
||||
private static WebhookClient client;
|
||||
private int embedColor;
|
||||
private String staticContent = "";
|
||||
private String embedTitle = "";
|
||||
|
||||
public static final Pattern WEBHOOK_PATTERN = Pattern.compile("(?:https?://)?(?:\\w+\\.)?\\w+\\.\\w+/api(?:/v\\d+)?/webhooks/(\\d+)/([\\w-]+)(?:/(?:\\w+)?)?");
|
||||
|
||||
@@ -40,6 +41,8 @@ public class DiscordManager implements Initable {
|
||||
client = WebhookClient.withId(Long.parseUnsignedLong(matcher.group(1)), matcher.group(2));
|
||||
client.setTimeout(15000); // Requests expire after 15 seconds
|
||||
|
||||
embedTitle = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("embed-title", "**Grim Alert**");
|
||||
|
||||
try {
|
||||
embedColor = Color.decode(GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("embed-color", "#00FFFF")).getRGB();
|
||||
} catch (NumberFormatException e) {
|
||||
@@ -70,7 +73,7 @@ public class DiscordManager implements Initable {
|
||||
public void sendAlert(GrimPlayer player, String verbose, String checkName, String violations) {
|
||||
if (client != null) {
|
||||
|
||||
String content = staticContent + "";
|
||||
String content = staticContent;
|
||||
content = content.replace("%check%", checkName);
|
||||
content = content.replace("%violations%", violations);
|
||||
content = GrimAPI.INSTANCE.getExternalAPI().replaceVariables(player, content, false);
|
||||
@@ -80,7 +83,7 @@ public class DiscordManager implements Initable {
|
||||
.setImageUrl("https://i.stack.imgur.com/Fzh0w.png") // Constant width
|
||||
.setThumbnailUrl("https://crafthead.net/helm/" + player.user.getProfile().getUUID())
|
||||
.setColor(embedColor)
|
||||
.setTitle(new WebhookEmbed.EmbedTitle("**Grim Alert**", null))
|
||||
.setTitle(new WebhookEmbed.EmbedTitle(embedTitle, null))
|
||||
.setDescription(content)
|
||||
.setTimestamp(Instant.now())
|
||||
.setFooter(new WebhookEmbed.EmbedFooter("", "https://grim.ac/images/grim.png"));
|
||||
|
||||
@@ -1,60 +1,72 @@
|
||||
package ac.grim.grimac.manager;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.GrimExternalAPI;
|
||||
import ac.grim.grimac.manager.init.Initable;
|
||||
import ac.grim.grimac.manager.init.load.PacketEventsInit;
|
||||
import ac.grim.grimac.manager.init.start.*;
|
||||
import ac.grim.grimac.manager.init.stop.TerminatePacketEvents;
|
||||
import com.google.common.collect.ClassToInstanceMap;
|
||||
import com.google.common.collect.ImmutableClassToInstanceMap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import lombok.Getter;
|
||||
|
||||
public class InitManager {
|
||||
ClassToInstanceMap<Initable> initializersOnLoad;
|
||||
ClassToInstanceMap<Initable> initializersOnStart;
|
||||
ClassToInstanceMap<Initable> initializersOnStop;
|
||||
|
||||
private final ImmutableList<Initable> initializersOnLoad;
|
||||
private final ImmutableList<Initable> initializersOnStart;
|
||||
private final ImmutableList<Initable> initializersOnStop;
|
||||
|
||||
@Getter private boolean loaded = false;
|
||||
@Getter private boolean started = false;
|
||||
@Getter private boolean stopped = false;
|
||||
|
||||
public InitManager() {
|
||||
initializersOnLoad = new ImmutableClassToInstanceMap.Builder<Initable>()
|
||||
.put(PacketEventsInit.class, new PacketEventsInit())
|
||||
initializersOnLoad = ImmutableList.<Initable>builder()
|
||||
.add(new PacketEventsInit())
|
||||
.add(() -> GrimAPI.INSTANCE.getExternalAPI().load())
|
||||
.build();
|
||||
|
||||
initializersOnStart = new ImmutableClassToInstanceMap.Builder<Initable>()
|
||||
.put(ExemptOnlinePlayers.class, new ExemptOnlinePlayers())
|
||||
.put(EventManager.class, new EventManager())
|
||||
.put(PacketManager.class, new PacketManager())
|
||||
.put(ViaBackwardsManager.class, new ViaBackwardsManager())
|
||||
.put(TickRunner.class, new TickRunner())
|
||||
.put(TickEndEvent.class, new TickEndEvent())
|
||||
.put(CommandRegister.class, new CommandRegister())
|
||||
.put(BStats.class, new BStats())
|
||||
.put(PacketLimiter.class, new PacketLimiter())
|
||||
.put(DiscordManager.class, GrimAPI.INSTANCE.getDiscordManager())
|
||||
.put(SpectateManager.class, GrimAPI.INSTANCE.getSpectateManager())
|
||||
.put(GrimExternalAPI.class, GrimAPI.INSTANCE.getExternalAPI())
|
||||
.put(JavaVersion.class, new JavaVersion())
|
||||
initializersOnStart = ImmutableList.<Initable>builder()
|
||||
.add(GrimAPI.INSTANCE.getExternalAPI())
|
||||
.add(new ExemptOnlinePlayers())
|
||||
.add(new EventManager())
|
||||
.add(new PacketManager())
|
||||
.add(new ViaBackwardsManager())
|
||||
.add(new TickRunner())
|
||||
.add(new TickEndEvent())
|
||||
.add(new CommandRegister())
|
||||
.add(new BStats())
|
||||
.add(new PacketLimiter())
|
||||
.add(GrimAPI.INSTANCE.getDiscordManager())
|
||||
.add(GrimAPI.INSTANCE.getSpectateManager())
|
||||
.add(new JavaVersion())
|
||||
.add(new ViaVersion())
|
||||
.build();
|
||||
|
||||
initializersOnStop = new ImmutableClassToInstanceMap.Builder<Initable>()
|
||||
.put(TerminatePacketEvents.class, new TerminatePacketEvents())
|
||||
initializersOnStop = ImmutableList.<Initable>builder()
|
||||
.add(new TerminatePacketEvents())
|
||||
.build();
|
||||
}
|
||||
|
||||
public void load() {
|
||||
for (Initable initable : initializersOnLoad.values()) {
|
||||
initable.start();
|
||||
}
|
||||
for (Initable initable : initializersOnLoad) handle(initable);
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
for (Initable initable : initializersOnStart.values()) {
|
||||
initable.start();
|
||||
}
|
||||
for (Initable initable : initializersOnStart) handle(initable);
|
||||
started = true;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
for (Initable initable : initializersOnStop.values()) {
|
||||
for (Initable initable : initializersOnStop) handle(initable);
|
||||
stopped = true;
|
||||
}
|
||||
|
||||
private void handle(Initable initable) {
|
||||
try {
|
||||
initable.start();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,13 +2,14 @@ package ac.grim.grimac.manager;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.AbstractCheck;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.api.config.ConfigReloadable;
|
||||
import ac.grim.grimac.api.events.CommandExecuteEvent;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.events.packets.ProxyAlertMessenger;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
import github.scarsz.configuralize.DynamicConfig;
|
||||
import io.github.retrooper.packetevents.util.folia.FoliaScheduler;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -17,21 +18,27 @@ import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class PunishmentManager {
|
||||
public class PunishmentManager implements ConfigReloadable {
|
||||
GrimPlayer player;
|
||||
List<PunishGroup> groups = new ArrayList<>();
|
||||
String experimentalSymbol = "*";
|
||||
private String alertString;
|
||||
private boolean testMode;
|
||||
private boolean printToConsole;
|
||||
private String proxyAlertString = "";
|
||||
|
||||
public PunishmentManager(GrimPlayer player) {
|
||||
this.player = player;
|
||||
reload();
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
DynamicConfig config = GrimAPI.INSTANCE.getConfigManager().getConfig();
|
||||
@Override
|
||||
public void reload(ConfigManager config) {
|
||||
List<String> punish = config.getStringListElse("Punishments", new ArrayList<>());
|
||||
experimentalSymbol = config.getStringElse("experimental-symbol", "*");
|
||||
|
||||
alertString = config.getStringElse("alerts-format", "%prefix% &f%player% &bfailed &f%check_name% &f(x&c%vl%&f) &7%verbose%");
|
||||
testMode = config.getBooleanElse("test-mode", false);
|
||||
printToConsole = config.getBooleanElse("verbose.print-to-console", false);
|
||||
proxyAlertString = config.getStringElse("alerts-format-proxy", "%prefix% &f[&cproxy&f] &f%player% &bfailed &f%check_name% &f(x&c%vl%&f) &7%verbose%");
|
||||
try {
|
||||
groups.clear();
|
||||
|
||||
@@ -111,8 +118,6 @@ public class PunishmentManager {
|
||||
}
|
||||
|
||||
public boolean handleAlert(GrimPlayer player, String verbose, Check check) {
|
||||
String alertString = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("alerts-format", "%prefix% &f%player% &bfailed &f%check_name% &f(x&c%vl%&f) &7%verbose%");
|
||||
boolean testMode = GrimAPI.INSTANCE.getConfigManager().getConfig().getBooleanElse("test-mode", false);
|
||||
boolean sentDebug = false;
|
||||
|
||||
// Check commands
|
||||
@@ -128,7 +133,7 @@ public class PunishmentManager {
|
||||
for (Player bukkitPlayer : GrimAPI.INSTANCE.getAlertManager().getEnabledVerbose()) {
|
||||
bukkitPlayer.sendMessage(cmd);
|
||||
}
|
||||
if (GrimAPI.INSTANCE.getConfigManager().getConfig().getBooleanElse("verbose.print-to-console", false)) {
|
||||
if (printToConsole) {
|
||||
LogUtil.console(cmd); // Print verbose to console
|
||||
}
|
||||
}
|
||||
@@ -146,9 +151,7 @@ public class PunishmentManager {
|
||||
String vl = group.violations.values().stream().filter((e) -> e == check).count() + "";
|
||||
GrimAPI.INSTANCE.getDiscordManager().sendAlert(player, verbose, check.getCheckName(), vl);
|
||||
} else if (command.command.equals("[proxy]")) {
|
||||
String proxyAlertString = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("alerts-format-proxy", "%prefix% &f[&cproxy&f] &f%player% &bfailed &f%check_name% &f(x&c%vl%&f) &7%verbose%");
|
||||
proxyAlertString = replaceAlertPlaceholders(command.getCommand(), group, check, proxyAlertString, verbose);
|
||||
ProxyAlertMessenger.sendPluginMessage(proxyAlertString);
|
||||
ProxyAlertMessenger.sendPluginMessage(replaceAlertPlaceholders(command.getCommand(), group, check, proxyAlertString, verbose));
|
||||
} else {
|
||||
if (command.command.equals("[alert]")) {
|
||||
sentDebug = true;
|
||||
@@ -160,9 +163,8 @@ public class PunishmentManager {
|
||||
}
|
||||
|
||||
String finalCmd = cmd;
|
||||
FoliaScheduler.getGlobalRegionScheduler().run(GrimAPI.INSTANCE.getPlugin(), (dummy) -> {
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), finalCmd);
|
||||
});
|
||||
FoliaScheduler.getGlobalRegionScheduler().run(GrimAPI.INSTANCE.getPlugin(), (dummy) ->
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), finalCmd));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package ac.grim.grimac.manager.config;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
public class BaseConfigManager {
|
||||
|
||||
/*
|
||||
This is to hold whatever config manager was set via the reload method in the API
|
||||
and any global variables that are the same between players.
|
||||
*/
|
||||
|
||||
@Getter
|
||||
private ConfigManager config = null;
|
||||
|
||||
// initialize the config
|
||||
public void load(ConfigManager config) {
|
||||
this.config = config;
|
||||
//
|
||||
int configuredMaxTransactionTime = config.getIntElse("max-transaction-time", 60);
|
||||
if (configuredMaxTransactionTime > 180 || configuredMaxTransactionTime < 1) {
|
||||
LogUtil.warn("Detected invalid max-transaction-time! This setting is clamped between 1 and 180 to prevent issues. Attempting to disable or set this too high can result in memory usage issues.");
|
||||
}
|
||||
|
||||
ignoredClientPatterns.clear();
|
||||
for (String string : config.getStringList("client-brand.ignored-clients")) {
|
||||
try {
|
||||
ignoredClientPatterns.add(Pattern.compile(string));
|
||||
} catch (PatternSyntaxException e) {
|
||||
throw new RuntimeException("Failed to compile client pattern", e);
|
||||
}
|
||||
}
|
||||
|
||||
printAlertsToConsole = config.getBooleanElse("alerts.print-to-console", true);
|
||||
prefix = config.getStringElse("prefix", "&bGrim &8»");
|
||||
}
|
||||
|
||||
// ran on start, can be used to handle things that can't be done while loading
|
||||
public void start() {
|
||||
|
||||
}
|
||||
|
||||
@Getter private boolean printAlertsToConsole = false;
|
||||
|
||||
@Getter private String prefix = "&bGrim &8»";
|
||||
|
||||
private final List<Pattern> ignoredClientPatterns = new ArrayList<>();
|
||||
|
||||
public boolean isIgnoredClient(String brand) {
|
||||
for (Pattern pattern : ignoredClientPatterns) {
|
||||
if (pattern.matcher(brand).find()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+64
-54
@@ -1,56 +1,43 @@
|
||||
package ac.grim.grimac.manager;
|
||||
package ac.grim.grimac.manager.config;
|
||||
|
||||
import ac.grim.grimac.GrimAC;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.common.BasicReloadable;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import github.scarsz.configuralize.DynamicConfig;
|
||||
import github.scarsz.configuralize.Language;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
public class ConfigManager {
|
||||
@Getter
|
||||
public class ConfigManagerFileImpl implements ConfigManager, BasicReloadable {
|
||||
|
||||
private final DynamicConfig config;
|
||||
@Getter
|
||||
private final File configFile = new File(GrimAPI.INSTANCE.getPlugin().getDataFolder(), "config.yml");
|
||||
@Getter
|
||||
private final File messagesFile = new File(GrimAPI.INSTANCE.getPlugin().getDataFolder(), "messages.yml");
|
||||
@Getter
|
||||
private final File discordFile = new File(GrimAPI.INSTANCE.getPlugin().getDataFolder(), "discord.yml");
|
||||
@Getter
|
||||
private final File punishFile = new File(GrimAPI.INSTANCE.getPlugin().getDataFolder(), "punishments.yml");
|
||||
@Getter
|
||||
private int maxPingTransaction = 60; // This is just a really hot variable so cache it.
|
||||
@Getter
|
||||
private boolean ignoreDuplicatePacketRotation = false;
|
||||
|
||||
@Getter
|
||||
private boolean experimentalChecks = false;
|
||||
|
||||
private final List<Pattern> ignoredClientPatterns = new ArrayList<>();
|
||||
|
||||
public ConfigManager() {
|
||||
upgrade();
|
||||
|
||||
// load config
|
||||
GrimAPI.INSTANCE.getPlugin().getDataFolder().mkdirs();
|
||||
config = new DynamicConfig();
|
||||
config.addSource(GrimAC.class, "config", getConfigFile());
|
||||
config.addSource(GrimAC.class, "messages", getMessagesFile());
|
||||
config.addSource(GrimAC.class, "discord", getDiscordFile());
|
||||
config.addSource(GrimAC.class, "punishments", getPunishFile());
|
||||
|
||||
reload();
|
||||
private File getConfigFile(String path) {
|
||||
return new File(GrimAPI.INSTANCE.getPlugin().getDataFolder(), path);
|
||||
}
|
||||
|
||||
public ConfigManagerFileImpl() {
|
||||
config = new DynamicConfig();
|
||||
}
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
GrimAPI.INSTANCE.getPlugin().getDataFolder().mkdirs();
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
config.addSource(GrimAC.class, "config", getConfigFile("config.yml"));
|
||||
config.addSource(GrimAC.class, "messages", getConfigFile("messages.yml"));
|
||||
config.addSource(GrimAC.class, "discord", getConfigFile("discord.yml"));
|
||||
config.addSource(GrimAC.class, "punishments", getConfigFile("punishments.yml"));
|
||||
}
|
||||
//
|
||||
String languageCode = System.getProperty("user.language").toUpperCase();
|
||||
|
||||
try {
|
||||
@@ -77,24 +64,6 @@ public class ConfigManager {
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to load config", e);
|
||||
}
|
||||
maxPingTransaction = config.getIntElse("max-transaction-time", 60);
|
||||
ignoredClientPatterns.clear();
|
||||
for (String string : config.getStringList("client-brand.ignored-clients")) {
|
||||
try {
|
||||
ignoredClientPatterns.add(Pattern.compile(string));
|
||||
} catch (PatternSyntaxException e) {
|
||||
throw new RuntimeException("Failed to compile client pattern", e);
|
||||
}
|
||||
}
|
||||
experimentalChecks = config.getBooleanElse("experimental-checks", false);
|
||||
ignoreDuplicatePacketRotation = config.getBooleanElse("ignore-duplicate-packet-rotation", false);
|
||||
}
|
||||
|
||||
public boolean isIgnoredClient(String brand) {
|
||||
for (Pattern pattern : ignoredClientPatterns) {
|
||||
if (pattern.matcher(brand).find()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void upgrade() {
|
||||
@@ -317,4 +286,45 @@ public class ConfigManager {
|
||||
);
|
||||
Files.write(config.toPath(), configString.getBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStringElse(String key, String otherwise) {
|
||||
return config.getStringElse(key, otherwise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStringList(String key) {
|
||||
return config.getStringList(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStringListElse(String key, List<String> otherwise) {
|
||||
return config.getStringListElse(key, otherwise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntElse(String key, int other) {
|
||||
return config.getIntElse(key, other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLongElse(String key, long otherwise) {
|
||||
return config.getLongElse(key, otherwise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDoubleElse(String key, double otherwise) {
|
||||
return config.getDoubleElse(key, otherwise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBooleanElse(String key, boolean otherwise) {
|
||||
return config.getBooleanElse(key, otherwise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T get(String key) {
|
||||
return config.get(key);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,8 +4,17 @@ import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.manager.init.Initable;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.protocol.chat.ChatTypes;
|
||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.github.retrooper.packetevents.protocol.item.enchantment.type.EnchantmentTypes;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class PacketEventsInit implements Initable {
|
||||
@Override
|
||||
public void start() {
|
||||
@@ -16,7 +25,18 @@ public class PacketEventsInit implements Initable {
|
||||
.fullStackTrace(true)
|
||||
.kickOnPacketException(true)
|
||||
.checkForUpdates(false)
|
||||
.reEncodeByDefault(false)
|
||||
.debug(false);
|
||||
PacketEvents.getAPI().load();
|
||||
// This may seem useless, but it causes java to start loading stuff async before we need it
|
||||
Executors.defaultThreadFactory().newThread(() -> {
|
||||
StateTypes.AIR.getName();
|
||||
ItemTypes.AIR.getName();
|
||||
EntityTypes.PLAYER.getParent();
|
||||
EntityDataTypes.BOOLEAN.getName();
|
||||
ChatTypes.CHAT.getName();
|
||||
EnchantmentTypes.ALL_DAMAGE_PROTECTION.getName();
|
||||
ParticleTypes.DUST.getName();
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ public class PacketManager implements Initable {
|
||||
}
|
||||
|
||||
PacketEvents.getAPI().getEventManager().registerListener(new ProxyAlertMessenger());
|
||||
PacketEvents.getAPI().getEventManager().registerListener(new PacketSetWrapperNull());
|
||||
PacketEvents.getAPI().getEventManager().registerListener(new PacketHidePlayerInfo());
|
||||
|
||||
PacketEvents.getAPI().init();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package ac.grim.grimac.manager.init.start;
|
||||
|
||||
import ac.grim.grimac.manager.init.Initable;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import io.github.retrooper.packetevents.util.viaversion.ViaVersionUtil;
|
||||
|
||||
public class ViaVersion implements Initable {
|
||||
@Override
|
||||
public void start() {
|
||||
if (!ViaVersionUtil.isAvailable()) return;
|
||||
if (Via.getConfig().getValues().containsKey("fix-1_21-placement-rotation") && Via.getConfig().fix1_21PlacementRotation()) {
|
||||
LogUtil.warn("GrimAC has detected that you are using ViaVersion with the `fix-1_21-placement-rotation` option enabled.");
|
||||
LogUtil.warn("This option is known to cause issues with GrimAC and may result in false positives and bypasses.");
|
||||
LogUtil.warn("Please disable this option in your ViaVersion configuration to prevent these issues.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ package ac.grim.grimac.player;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.AbstractCheck;
|
||||
import ac.grim.grimac.api.GrimUser;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.impl.aim.processor.AimProcessor;
|
||||
import ac.grim.grimac.checks.impl.misc.ClientBrand;
|
||||
import ac.grim.grimac.checks.impl.misc.TransactionOrder;
|
||||
@@ -35,7 +37,6 @@ import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.protocol.world.Dimension;
|
||||
import com.github.retrooper.packetevents.protocol.world.dimension.DimensionType;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
@@ -47,6 +48,7 @@ import io.github.retrooper.packetevents.adventure.serializer.legacy.LegacyCompon
|
||||
import io.github.retrooper.packetevents.util.folia.FoliaScheduler;
|
||||
import io.github.retrooper.packetevents.util.viaversion.ViaVersionUtil;
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -199,6 +201,8 @@ public class GrimPlayer implements GrimUser {
|
||||
public long lastBlockPlaceUseItem = 0;
|
||||
public AtomicInteger cancelledPackets = new AtomicInteger(0);
|
||||
public MainSupportingBlockData mainSupportingBlockData = new MainSupportingBlockData(null, false);
|
||||
// possibleEyeHeights[0] = Standing eye heights, [1] = Sneaking. [2] = Elytra, Swimming, and Riptide Trident which only exists in 1.9+
|
||||
public double[][] possibleEyeHeights = new double[3][];
|
||||
|
||||
public void onPacketCancel() {
|
||||
if (spamThreshold != -1 && cancelledPackets.incrementAndGet() > spamThreshold) {
|
||||
@@ -217,7 +221,6 @@ public class GrimPlayer implements GrimUser {
|
||||
public GrimPlayer(User user) {
|
||||
this.user = user;
|
||||
this.playerUUID = user.getUUID();
|
||||
onReload();
|
||||
|
||||
boundingBox = GetBoundingBox.getBoundingBoxFromPosAndSizeRaw(x, y, z, 0.6f, 1.8f);
|
||||
|
||||
@@ -240,6 +243,24 @@ public class GrimPlayer implements GrimUser {
|
||||
packetStateData = new PacketStateData();
|
||||
|
||||
uncertaintyHandler.collidingEntities.add(0);
|
||||
|
||||
if (getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14)) {
|
||||
final float scale = (float) compensatedEntities.getSelf().getAttributeValue(Attributes.GENERIC_SCALE);
|
||||
possibleEyeHeights[2] = new double[]{0.4 * scale, 1.62 * scale, 1.27 * scale}; // Elytra, standing, sneaking (1.14)
|
||||
possibleEyeHeights[1] = new double[]{1.27 * scale, 1.62 * scale, 0.4 * scale}; // sneaking (1.14), standing, Elytra
|
||||
possibleEyeHeights[0] = new double[]{1.62 * scale, 1.27 * scale, 0.4 * scale}; // standing, sneaking (1.14), Elytra
|
||||
|
||||
} else if (getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)) { // standing, sneaking Elytra
|
||||
possibleEyeHeights[2] = new double[]{0.4, 1.62, 1.54}; // Elytra, standing, sneaking (1.13)
|
||||
possibleEyeHeights[1] = new double[]{1.54, 1.62, 0.4}; // sneaking (1.9-1.13), standing, Elytra
|
||||
possibleEyeHeights[0] = new double[]{1.62, 1.54, 0.4}; // standing, sneaking (1.9-1.13), Elytra
|
||||
} else {
|
||||
possibleEyeHeights[1] = new double[]{(double) (1.62f - 0.08f), (double) (1.62f)}; // sneaking, standing
|
||||
possibleEyeHeights[0] = new double[]{(double) (1.62f), (double) (1.62f - 0.08f)}; // standing, sneaking
|
||||
}
|
||||
|
||||
// reload last
|
||||
reload();
|
||||
}
|
||||
|
||||
public Set<VectorData> getPossibleVelocities() {
|
||||
@@ -316,7 +337,8 @@ public class GrimPlayer implements GrimUser {
|
||||
// Transactions that we send don't count towards total limit
|
||||
if (packetTracker != null) packetTracker.setIntervalPackets(packetTracker.getIntervalPackets() - 1);
|
||||
|
||||
if (skipped > 0 && System.currentTimeMillis() - joinTime > 5000) checkManager.getPacketCheck(TransactionOrder.class).flagAndAlert("skipped: " + skipped);
|
||||
if (skipped > 0 && System.currentTimeMillis() - joinTime > 5000)
|
||||
checkManager.getPacketCheck(TransactionOrder.class).flagAndAlert("skipped: " + skipped);
|
||||
|
||||
do {
|
||||
data = transactionsSent.poll();
|
||||
@@ -450,7 +472,7 @@ public class GrimPlayer implements GrimUser {
|
||||
if (lastTransSent != 0 && lastTransSent + 80 < System.currentTimeMillis()) {
|
||||
sendTransaction(true); // send on netty thread
|
||||
}
|
||||
if ((System.nanoTime() - getPlayerClockAtLeast()) > GrimAPI.INSTANCE.getConfigManager().getMaxPingTransaction() * 1e9) {
|
||||
if ((System.nanoTime() - getPlayerClockAtLeast()) > maxTransactionTime * 1e9) {
|
||||
timedOut();
|
||||
}
|
||||
|
||||
@@ -504,14 +526,17 @@ public class GrimPlayer implements GrimUser {
|
||||
if (bukkitPlayer == null) return;
|
||||
this.noModifyPacketPermission = bukkitPlayer.hasPermission("grim.nomodifypacket");
|
||||
this.noSetbackPermission = bukkitPlayer.hasPermission("grim.nosetback");
|
||||
FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(), t -> {
|
||||
for (AbstractCheck check : checkManager.allChecks.values()) {
|
||||
if (check instanceof Check) {
|
||||
((Check) check).updateExempted();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private int spamThreshold = 100;
|
||||
|
||||
public void onReload() {
|
||||
spamThreshold = GrimAPI.INSTANCE.getConfigManager().getConfig().getIntElse("packet-spam-threshold", 100);
|
||||
}
|
||||
|
||||
public boolean isPointThree() {
|
||||
return getClientVersion().isOlderThan(ClientVersion.V_1_18_2);
|
||||
}
|
||||
@@ -541,7 +566,7 @@ public class GrimPlayer implements GrimUser {
|
||||
// - 3 ticks is a magic value, but it should buffer out incorrect predictions somewhat.
|
||||
// 2. The player is in a vehicle
|
||||
public boolean isTickingReliablyFor(int ticks) {
|
||||
return (getClientVersion().isOlderThan(ClientVersion.V_1_9)
|
||||
return (getClientVersion().isOlderThan(ClientVersion.V_1_9)
|
||||
|| !uncertaintyHandler.lastPointThree.hasOccurredSince(ticks))
|
||||
|| compensatedEntities.getSelf().inVehicle();
|
||||
}
|
||||
@@ -554,14 +579,23 @@ public class GrimPlayer implements GrimUser {
|
||||
return checkManager.getInventory();
|
||||
}
|
||||
|
||||
public List<Double> getPossibleEyeHeights() { // We don't return sleeping eye height
|
||||
if (getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14)) { // Elytra, sneaking (1.14), standing
|
||||
final float scale = (float) compensatedEntities.getSelf().getAttributeValue(Attributes.GENERIC_SCALE);
|
||||
return Arrays.asList(0.4 * scale, 1.27 * scale, 1.62 * scale);
|
||||
} else if (getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)) { // Elytra, sneaking, standing
|
||||
return Arrays.asList(0.4, 1.54, 1.62);
|
||||
} else { // Only sneaking or standing
|
||||
return Arrays.asList((double) (1.62f - 0.08f), (double) (1.62f));
|
||||
public double[] getPossibleEyeHeights() { // We don't return sleeping eye height
|
||||
// 1.8 Players once again ruin my clean switch-case
|
||||
if (this.getClientVersion().isOlderThan(ClientVersion.V_1_9)) {
|
||||
return this.isSneaking ? this.possibleEyeHeights[1] : this.possibleEyeHeights[0];
|
||||
} else {
|
||||
// 1.8 players just have their pose set to standing all the time
|
||||
switch (pose) {
|
||||
case FALL_FLYING: // Elytra gliding
|
||||
case SPIN_ATTACK: // Riptide trident
|
||||
case SWIMMING: // Swimming (includes crawling in 1.14+)
|
||||
return this.possibleEyeHeights[2]; // [swimming/gliding/riptide height, standing height, sneaking height]
|
||||
case NINE_CROUCHING:
|
||||
case CROUCHING:
|
||||
return this.possibleEyeHeights[1]; // [sneaking height, standing height, swimming/gliding/riptide height]
|
||||
default:
|
||||
return this.possibleEyeHeights[0]; // [standing height, sneaking height, swimming/gliding/riptide height]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -709,10 +743,31 @@ public class GrimPlayer implements GrimUser {
|
||||
return checkManager.allChecks.values();
|
||||
}
|
||||
|
||||
|
||||
public void runNettyTaskInMs(Runnable runnable, int ms) {
|
||||
Channel channel = (Channel) user.getChannel();
|
||||
channel.eventLoop().schedule(runnable, ms, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private int maxTransactionTime = 60;
|
||||
@Getter private boolean ignoreDuplicatePacketRotation = false;
|
||||
@Getter private boolean experimentalChecks = false;
|
||||
@Getter private boolean cancelDuplicatePacket = true;
|
||||
|
||||
@Override
|
||||
public void reload(ConfigManager config) {
|
||||
spamThreshold = config.getIntElse("packet-spam-threshold", 100);
|
||||
maxTransactionTime = (int) GrimMath.clamp(config.getIntElse("max-transaction-time", 60), 1, 180);
|
||||
experimentalChecks = config.getBooleanElse("experimental-checks", false);
|
||||
ignoreDuplicatePacketRotation = config.getBooleanElse("ignore-duplicate-packet-rotation", false);
|
||||
cancelDuplicatePacket = config.getBooleanElse("cancel-duplicate-packet", true);
|
||||
// reload all checks
|
||||
for (AbstractCheck value : checkManager.allChecks.values()) value.reload(config);
|
||||
// reload punishment manager
|
||||
punishmentManager.reload(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
reload(GrimAPI.INSTANCE.getConfigManager().getConfig());
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package ac.grim.grimac.predictionengine;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.impl.movement.EntityControl;
|
||||
import ac.grim.grimac.checks.impl.prediction.Phase;
|
||||
@@ -22,7 +22,6 @@ import ac.grim.grimac.utils.data.packetentity.PacketEntityHorse;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntityRideable;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntityTrackXRot;
|
||||
import ac.grim.grimac.utils.enums.Pose;
|
||||
import ac.grim.grimac.utils.inventory.EnchantmentHelper;
|
||||
import ac.grim.grimac.utils.latency.CompensatedWorld;
|
||||
import ac.grim.grimac.utils.math.GrimMath;
|
||||
import ac.grim.grimac.utils.math.VectorUtils;
|
||||
@@ -32,7 +31,6 @@ import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.protocol.item.enchantment.type.EnchantmentTypes;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
@@ -364,7 +362,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
}
|
||||
player.uncertaintyHandler.isSteppingOnHoney = true;
|
||||
}
|
||||
if (BlockTags.BEDS.contains(data.getType()) && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8)) {
|
||||
if (BlockTags.BEDS.contains(data.getType()) && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_12)) {
|
||||
player.uncertaintyHandler.isSteppingOnBouncyBlock = true;
|
||||
}
|
||||
if (BlockTags.ICE.contains(data.getType())) {
|
||||
@@ -544,8 +542,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
player.checkManager.onPredictionFinish(new PredictionComplete(offset, update, wasChecked));
|
||||
|
||||
// Patch sprint jumping with elytra exploit
|
||||
if (player.bukkitPlayer != null && player.isGliding && player.predictedVelocity.isJump() && player.isSprinting
|
||||
&& !GrimAPI.INSTANCE.getConfigManager().getConfig().getBooleanElse("exploit.allow-sprint-jumping-when-using-elytra", true)) {
|
||||
if (player.bukkitPlayer != null && player.isGliding && player.predictedVelocity.isJump() && player.isSprinting && !allowSprintJumpingWithElytra) {
|
||||
SetbackTeleportUtil.SetbackPosWithVector lastKnownGoodPosition = player.getSetbackTeleportUtil().lastKnownGoodPosition;
|
||||
lastKnownGoodPosition.setVector(lastKnownGoodPosition.getVector().multiply(new Vector(0.6 * 0.91, 1, 0.6 * 0.91)));
|
||||
player.getSetbackTeleportUtil().executeNonSimulatingSetback();
|
||||
@@ -635,4 +632,12 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
// (Patches issues with slime and other desync's)
|
||||
return riptideDiffToGround < riptideDiffToBase;
|
||||
}
|
||||
|
||||
private boolean allowSprintJumpingWithElytra = true;
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
allowSprintJumpingWithElytra = config.getBooleanElse("exploit.allow-sprint-jumping-when-using-elytra", true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,9 +16,10 @@ import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class PlayerBaseTick {
|
||||
GrimPlayer player;
|
||||
|
||||
@@ -149,9 +150,14 @@ public class PlayerBaseTick {
|
||||
// Pre-1.17 clients don't have powder snow and therefore don't desync
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_16_4)) return;
|
||||
|
||||
// The client first desync's this attribute
|
||||
final ValuedAttribute playerSpeed = player.compensatedEntities.getSelf().getAttribute(Attributes.GENERIC_MOVEMENT_SPEED).get();
|
||||
playerSpeed.property().get().getModifiers().removeIf(modifier -> modifier.getUUID().equals(CompensatedEntities.SNOW_MODIFIER_UUID) || modifier.getName().getKey().equals("powder_snow"));
|
||||
|
||||
// Might be null after respawn?
|
||||
final Optional<WrapperPlayServerUpdateAttributes.Property> property = playerSpeed.property();
|
||||
if (!property.isPresent()) return;
|
||||
|
||||
// The client first desync's this attribute
|
||||
property.get().getModifiers().removeIf(modifier -> modifier.getUUID().equals(CompensatedEntities.SNOW_MODIFIER_UUID) || modifier.getName().getKey().equals("powder_snow"));
|
||||
playerSpeed.recalculate();
|
||||
|
||||
// And then re-adds it using purely what the server has sent it
|
||||
@@ -165,7 +171,7 @@ public class PlayerBaseTick {
|
||||
float percentFrozen = (float) Math.min(i, ticksToFreeze) / (float) ticksToFreeze;
|
||||
float percentFrozenReducedToSpeed = -0.05F * percentFrozen;
|
||||
|
||||
playerSpeed.property().get().getModifiers().add(new WrapperPlayServerUpdateAttributes.PropertyModifier(CompensatedEntities.SNOW_MODIFIER_UUID, percentFrozenReducedToSpeed, WrapperPlayServerUpdateAttributes.PropertyModifier.Operation.ADDITION));
|
||||
property.get().getModifiers().add(new WrapperPlayServerUpdateAttributes.PropertyModifier(CompensatedEntities.SNOW_MODIFIER_UUID, percentFrozenReducedToSpeed, WrapperPlayServerUpdateAttributes.PropertyModifier.Operation.ADDITION));
|
||||
playerSpeed.recalculate();
|
||||
}
|
||||
}
|
||||
|
||||
+35
-5
@@ -1,14 +1,20 @@
|
||||
package ac.grim.grimac.predictionengine.movementtick;
|
||||
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.data.attribute.ValuedAttribute;
|
||||
import ac.grim.grimac.utils.data.packetentity.PacketEntityStrider;
|
||||
import ac.grim.grimac.utils.nmsutil.BlockProperties;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.defaulttags.BlockTags;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class MovementTickerStrider extends MovementTickerRideable {
|
||||
|
||||
public MovementTickerStrider(GrimPlayer player) {
|
||||
@@ -34,21 +40,45 @@ public class MovementTickerStrider extends MovementTickerRideable {
|
||||
public void livingEntityAIStep() {
|
||||
super.livingEntityAIStep();
|
||||
|
||||
((PacketEntityStrider) player.compensatedEntities.getSelf().getRiding()).isShaking = true;
|
||||
|
||||
StateType posMaterial = player.compensatedWorld.getStateTypeAt(player.x, player.y, player.z);
|
||||
StateType belowMaterial = BlockProperties.getOnPos(player, player.mainSupportingBlockData, new Vector3d(player.x, player.y, player.z));
|
||||
|
||||
((PacketEntityStrider) player.compensatedEntities.getSelf().getRiding()).isShaking =
|
||||
!BlockTags.STRIDER_WARM_BLOCKS.contains(posMaterial) &&
|
||||
final PacketEntityStrider strider = (PacketEntityStrider) player.compensatedEntities.getSelf().getRiding();
|
||||
strider.isShaking = !BlockTags.STRIDER_WARM_BLOCKS.contains(posMaterial) &&
|
||||
!BlockTags.STRIDER_WARM_BLOCKS.contains(belowMaterial) &&
|
||||
!player.wasTouchingLava;
|
||||
}
|
||||
|
||||
private static final WrapperPlayServerUpdateAttributes.PropertyModifier SUFFOCATING_MODIFIER = new WrapperPlayServerUpdateAttributes.PropertyModifier(
|
||||
ResourceLocation.minecraft("suffocating"), -0.34F, WrapperPlayServerUpdateAttributes.PropertyModifier.Operation.MULTIPLY_BASE);
|
||||
|
||||
@Override
|
||||
public float getSteeringSpeed() {
|
||||
PacketEntityStrider strider = (PacketEntityStrider) player.compensatedEntities.getSelf().getRiding();
|
||||
return (float) strider.getAttributeValue(Attributes.GENERIC_MOVEMENT_SPEED) * (strider.isShaking ? 0.23F : 0.55F);
|
||||
// Unsure which version the speed changed in
|
||||
final boolean newSpeed = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_20);
|
||||
final float coldSpeed = newSpeed ? 0.35F : 0.23F;
|
||||
|
||||
// Client desyncs the attribute
|
||||
// Again I don't know when this was changed, or whether it always existed, so I will just put it behind 1.20+
|
||||
final ValuedAttribute movementSpeedAttr = strider.getAttribute(Attributes.GENERIC_MOVEMENT_SPEED).get();
|
||||
float updatedMovementSpeed = (float) movementSpeedAttr.get();
|
||||
if (newSpeed) {
|
||||
final WrapperPlayServerUpdateAttributes.Property lastProperty = movementSpeedAttr.property().orElse(null);
|
||||
if (lastProperty != null && (!strider.isShaking || lastProperty.getModifiers().stream().noneMatch(mod -> mod.getName().getKey().equals("suffocating")))) {
|
||||
WrapperPlayServerUpdateAttributes.Property newProperty = new WrapperPlayServerUpdateAttributes.Property(lastProperty.getAttribute(), lastProperty.getValue(), new ArrayList<>(lastProperty.getModifiers()));
|
||||
if (!strider.isShaking) {
|
||||
newProperty.getModifiers().removeIf(modifier -> modifier.getName().getKey().equals("suffocating"));
|
||||
} else {
|
||||
newProperty.getModifiers().add(SUFFOCATING_MODIFIER);
|
||||
}
|
||||
movementSpeedAttr.with(newProperty);
|
||||
updatedMovementSpeed = (float) movementSpeedAttr.get();
|
||||
movementSpeedAttr.with(lastProperty);
|
||||
}
|
||||
}
|
||||
|
||||
return updatedMovementSpeed * (strider.isShaking ? coldSpeed : 0.55F);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,6 +3,8 @@ package ac.grim.grimac.utils.anticheat;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.util.Vector3f;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
|
||||
@@ -11,6 +13,13 @@ import java.util.regex.Pattern;
|
||||
|
||||
@UtilityClass
|
||||
public class MessageUtil {
|
||||
public String toUnlabledString(Vector3i vec) {
|
||||
return vec == null ? "null" : vec.x + ", " + vec.y + ", " + vec.z;
|
||||
}
|
||||
|
||||
public String toUnlabledString(Vector3f vec) {
|
||||
return vec == null ? "null" : vec.x + ", " + vec.y + ", " + vec.z;
|
||||
}
|
||||
|
||||
public String format(String string) {
|
||||
string = formatWithNoColor(string);
|
||||
@@ -20,13 +29,14 @@ public class MessageUtil {
|
||||
}
|
||||
|
||||
public String formatWithNoColor(String string) {
|
||||
return string.replace("%prefix%", GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("prefix", "&bGrim &8»"));
|
||||
return string.replace("%prefix%", GrimAPI.INSTANCE.getConfigManager().getPrefix());
|
||||
}
|
||||
|
||||
private static final Pattern HEX_PATTERN = Pattern.compile("#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})");
|
||||
|
||||
private String translateHexCodes(String message) {
|
||||
final String hexPattern = "#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})";
|
||||
Matcher matcher = Pattern.compile(hexPattern).matcher(message);
|
||||
StringBuffer sb = new StringBuffer(message.length());
|
||||
Matcher matcher = HEX_PATTERN.matcher(message);
|
||||
StringBuilder sb = new StringBuilder(message.length());
|
||||
while (matcher.find()) {
|
||||
String hex = matcher.group(1);
|
||||
ChatColor color = ChatColor.of("#" + hex);
|
||||
@@ -35,4 +45,5 @@ public class MessageUtil {
|
||||
matcher.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -567,7 +567,14 @@ public enum CollisionData {
|
||||
|
||||
}, StateTypes.GRINDSTONE),
|
||||
|
||||
PANE(new DynamicPane(), Materials.getPanes().toArray(new StateType[0])),
|
||||
|
||||
CHAIN_BLOCK((player, version, data, x, y, z) -> {
|
||||
if (version.isOlderThan(ClientVersion.V_1_16)) {
|
||||
// viaversion replacement - iron bars
|
||||
return CollisionData.PANE.dynamic.fetch(player, version, data, x, y, z);
|
||||
}
|
||||
|
||||
if (data.getAxis() == Axis.X) {
|
||||
return new HexCollisionBox(0.0D, 6.5D, 6.5D, 16.0D, 9.5D, 9.5D);
|
||||
} else if (data.getAxis() == Axis.Y) {
|
||||
@@ -599,8 +606,6 @@ public enum CollisionData {
|
||||
|
||||
FENCE(new DynamicFence(), BlockTags.FENCES.getStates().toArray(new StateType[0])),
|
||||
|
||||
PANE(new DynamicPane(), Materials.getPanes().toArray(new StateType[0])),
|
||||
|
||||
SNOW((player, version, data, x, y, z) -> {
|
||||
if (data.getLayers() == 1 && version.isNewerThanOrEquals(ClientVersion.V_1_13)) {
|
||||
// Via doesn't touch this
|
||||
|
||||
@@ -112,7 +112,7 @@ public enum HitboxData {
|
||||
}
|
||||
|
||||
List<SimpleCollisionBox> boxes = new ArrayList<>();
|
||||
CollisionData.getData(state.getType()).getMovementCollisionBox(player, version, state, x, y, z).downCast(boxes);
|
||||
CollisionData.getData(state.getType()).getMovementCollisionBox(player, version, state).downCast(boxes);
|
||||
|
||||
for (SimpleCollisionBox box : boxes) {
|
||||
box.maxY = 1;
|
||||
|
||||
@@ -84,7 +84,7 @@ public class DynamicPane extends DynamicConnecting implements CollisionFactory {
|
||||
|
||||
@Override
|
||||
public boolean checkCanConnect(GrimPlayer player, WrappedBlockState state, StateType one, StateType two, BlockFace direction) {
|
||||
if (BlockTags.GLASS_PANES.contains(one) || one == StateTypes.IRON_BARS)
|
||||
if (BlockTags.GLASS_PANES.contains(one) || one == StateTypes.IRON_BARS || one == StateTypes.CHAIN && player.getClientVersion().isOlderThan(ClientVersion.V_1_16))
|
||||
return true;
|
||||
else
|
||||
return CollisionData.getData(one).getMovementCollisionBox(player, player.getClientVersion(), state, 0, 0, 0).isSideFullBlock(direction);
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package ac.grim.grimac.utils.common;
|
||||
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
|
||||
public interface ConfigReloadObserver {
|
||||
|
||||
void onReload(ConfigManager config);
|
||||
|
||||
}
|
||||
@@ -80,6 +80,7 @@ public final class ValuedAttribute {
|
||||
|
||||
public void reset() {
|
||||
this.value = defaultValue;
|
||||
this.lastProperty = null; // Remove the old property with its modifiers so we don't accidentally use it again, messing up the calculation.
|
||||
}
|
||||
|
||||
public double get() {
|
||||
@@ -100,29 +101,29 @@ public final class ValuedAttribute {
|
||||
}
|
||||
|
||||
public double with(WrapperPlayServerUpdateAttributes.Property property) {
|
||||
double d0 = property.getValue();
|
||||
double baseValue = property.getValue();
|
||||
double additionSum = 0;
|
||||
double multiplyBaseSum = 0;
|
||||
double multiplyTotalProduct = 1.0;
|
||||
|
||||
List<WrapperPlayServerUpdateAttributes.PropertyModifier> modifiers = property.getModifiers();
|
||||
modifiers.removeIf(modifier -> modifier.getUUID().equals(SPRINTING_MODIFIER_UUID) || modifier.getName().getKey().equals("sprinting"));
|
||||
|
||||
for (WrapperPlayServerUpdateAttributes.PropertyModifier attributemodifier : modifiers) {
|
||||
if (attributemodifier.getOperation() == WrapperPlayServerUpdateAttributes.PropertyModifier.Operation.ADDITION)
|
||||
d0 += attributemodifier.getAmount();
|
||||
for (WrapperPlayServerUpdateAttributes.PropertyModifier modifier : modifiers) {
|
||||
switch (modifier.getOperation()) {
|
||||
case ADDITION:
|
||||
additionSum += modifier.getAmount();
|
||||
break;
|
||||
case MULTIPLY_BASE:
|
||||
multiplyBaseSum += modifier.getAmount();
|
||||
break;
|
||||
case MULTIPLY_TOTAL:
|
||||
multiplyTotalProduct *= (1.0 + modifier.getAmount());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
double d1 = d0;
|
||||
|
||||
for (WrapperPlayServerUpdateAttributes.PropertyModifier attributemodifier : modifiers) {
|
||||
if (attributemodifier.getOperation() == WrapperPlayServerUpdateAttributes.PropertyModifier.Operation.MULTIPLY_BASE)
|
||||
d1 += d0 * attributemodifier.getAmount();
|
||||
}
|
||||
|
||||
for (WrapperPlayServerUpdateAttributes.PropertyModifier attributemodifier : modifiers) {
|
||||
if (attributemodifier.getOperation() == WrapperPlayServerUpdateAttributes.PropertyModifier.Operation.MULTIPLY_TOTAL)
|
||||
d1 *= 1.0D + attributemodifier.getAmount();
|
||||
}
|
||||
|
||||
double newValue = GrimMath.clampFloat((float) d1, (float) min, (float) max);
|
||||
double newValue = GrimMath.clamp((baseValue + additionSum) * (1 + multiplyBaseSum) * multiplyTotalProduct, min, max);
|
||||
if (setRewriter != null) {
|
||||
newValue = setRewriter.apply(this.value, newValue);
|
||||
}
|
||||
|
||||
@@ -99,14 +99,19 @@ public class PacketEntity extends TypedPacketEntity {
|
||||
}
|
||||
|
||||
public void setAttribute(Attribute attribute, double value) {
|
||||
ValuedAttribute property = getAttribute(attribute).orElse(null);
|
||||
if (property == null) throw new IllegalArgumentException("Cannot set attribute " + attribute.getName() + " for entity " + getType().getName().toString() + "!");
|
||||
ValuedAttribute property = attributeMap.get(attribute);
|
||||
if (property == null) {
|
||||
throw new IllegalArgumentException("Cannot set attribute " + attribute.getName() + " for entity " + getType().getName().toString() + "!");
|
||||
}
|
||||
property.override(value);
|
||||
}
|
||||
|
||||
public double getAttributeValue(Attribute attribute) {
|
||||
return getAttribute(attribute).map(ValuedAttribute::get)
|
||||
.orElseThrow(() -> new IllegalArgumentException("Cannot get attribute " + attribute.getName() + " for entity " + getType().getName().toString() + "!"));
|
||||
final ValuedAttribute property = attributeMap.get(attribute);
|
||||
if (property == null) {
|
||||
throw new IllegalArgumentException("Cannot get attribute " + attribute.getName() + " for entity " + getType().getName().toString() + "!");
|
||||
}
|
||||
return property.get();
|
||||
}
|
||||
|
||||
public void resetAttributes() {
|
||||
|
||||
@@ -2,6 +2,8 @@ package ac.grim.grimac.utils.data.packetentity;
|
||||
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.data.attribute.ValuedAttribute;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
@@ -20,7 +22,16 @@ public class PacketEntityHorse extends PacketEntityTrackXRot {
|
||||
setAttribute(Attributes.GENERIC_STEP_HEIGHT, 1.0f);
|
||||
|
||||
final boolean preAttribute = player.getClientVersion().isOlderThan(ClientVersion.V_1_20_5);
|
||||
trackAttribute(ValuedAttribute.ranged(Attributes.GENERIC_JUMP_STRENGTH, 0.7, 0, preAttribute ? 2 : 32));
|
||||
// This was horse.jump_strength pre-attribute
|
||||
trackAttribute(ValuedAttribute.ranged(Attributes.GENERIC_JUMP_STRENGTH, 0.7, 0, preAttribute ? 2 : 32)
|
||||
.withSetRewriter((oldValue, newValue) -> {
|
||||
// Seems viabackwards doesn't rewrite this (?)
|
||||
if (preAttribute && PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_20_5)) {
|
||||
return oldValue;
|
||||
}
|
||||
// Modern player OR an old server setting legacy horse.jump_strength attribute
|
||||
return newValue;
|
||||
}));
|
||||
trackAttribute(ValuedAttribute.ranged(Attributes.GENERIC_MOVEMENT_SPEED, 0.225f, 0, 1024));
|
||||
|
||||
if (EntityTypes.isTypeInstanceOf(type, EntityTypes.CHESTED_HORSE)) {
|
||||
|
||||
@@ -47,6 +47,28 @@ public class PacketEntitySelf extends PacketEntity {
|
||||
setAttribute(Attributes.GENERIC_STEP_HEIGHT, 0.5f);
|
||||
}
|
||||
|
||||
getAttribute(Attributes.GENERIC_SCALE).get().withSetRewriter((oldValue, newValue) -> {
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_20_5) || (newValue).equals(oldValue)) {
|
||||
return oldValue;
|
||||
} else {
|
||||
// Elytra, standing, sneaking (1.14)
|
||||
player.possibleEyeHeights[2][0] = 0.4 * newValue;
|
||||
player.possibleEyeHeights[2][1] = 1.62 * newValue;
|
||||
player.possibleEyeHeights[2][2] = 1.27 * newValue;
|
||||
|
||||
// sneaking (1.14), standing, Elytra
|
||||
player.possibleEyeHeights[1][0] = 1.27 * newValue;
|
||||
player.possibleEyeHeights[1][1] = 1.62 * newValue;
|
||||
player.possibleEyeHeights[1][2] = 0.4 * newValue;
|
||||
|
||||
// standing, sneaking (1.14), Elytra
|
||||
player.possibleEyeHeights[0][0] = 1.62 * newValue;
|
||||
player.possibleEyeHeights[0][1] = 1.27 * newValue;
|
||||
player.possibleEyeHeights[0][2] = 0.4 * newValue;
|
||||
return newValue;
|
||||
}
|
||||
});
|
||||
|
||||
final ValuedAttribute movementSpeed = ValuedAttribute.ranged(Attributes.GENERIC_MOVEMENT_SPEED, 0.1f, 0, 1024);
|
||||
movementSpeed.with(new WrapperPlayServerUpdateAttributes.Property("MOVEMENT_SPEED", 0.1f, new ArrayList<>()));
|
||||
trackAttribute(movementSpeed);
|
||||
|
||||
@@ -110,10 +110,11 @@ public class BlockBreakSpeed {
|
||||
if (tool.getType().hasAttribute(ItemTypes.ItemAttribute.SWORD)) {
|
||||
if (block.getType() == StateTypes.COBWEB) {
|
||||
speedMultiplier = 15.0f;
|
||||
} else if (block.getType().getMaterialType() == MaterialType.PLANT ||
|
||||
BlockTags.LEAVES.contains(block.getType()) ||
|
||||
block.getType() == StateTypes.PUMPKIN ||
|
||||
block.getType() == StateTypes.MELON) {
|
||||
} else if (block.getType().getMaterialType() == MaterialType.PLANT
|
||||
|| BlockTags.LEAVES.contains(block.getType())
|
||||
|| block.getType() == StateTypes.VINE
|
||||
|| block.getType() == StateTypes.PUMPKIN
|
||||
|| block.getType() == StateTypes.MELON) {
|
||||
speedMultiplier = 1.5f;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,11 @@ public class BlockProperties {
|
||||
}
|
||||
|
||||
if (player.compensatedEntities.getSelf().getRiding() instanceof PacketEntityStrider) {
|
||||
// Unsure which version the speed changed in
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_20)) {
|
||||
return (float) player.speed * 0.1f;
|
||||
}
|
||||
|
||||
PacketEntityStrider strider = (PacketEntityStrider) player.compensatedEntities.getSelf().getRiding();
|
||||
// Vanilla multiplies by 0.1 to calculate speed
|
||||
return (float) strider.getAttributeValue(Attributes.GENERIC_MOVEMENT_SPEED) * (strider.isShaking ? 0.66F : 1.0F) * 0.1f;
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.bukkit.util.Vector;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class Collisions {
|
||||
@@ -699,7 +700,7 @@ public class Collisions {
|
||||
int x = currX | chunkXGlobalPos;
|
||||
int z = currZ | chunkZGlobalPos;
|
||||
|
||||
WrappedBlockState data = section.get(CompensatedWorld.blockVersion, x & 0xF, y & 0xF, z & 0xF);
|
||||
WrappedBlockState data = section.get(CompensatedWorld.blockVersion, x & 0xF, y & 0xF, z & 0xF, false);
|
||||
|
||||
if (searchingFor.test(new Pair<>(data, new Vector3d(x, y, z)))) return true;
|
||||
}
|
||||
@@ -710,6 +711,85 @@ public class Collisions {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Thanks Tuinity
|
||||
public static void forEachCollisionBox(GrimPlayer player, SimpleCollisionBox checkBox, Consumer<Vector3d> searchingFor) {
|
||||
int minBlockX = (int) Math.floor(checkBox.minX - COLLISION_EPSILON) - 1;
|
||||
int maxBlockX = (int) Math.floor(checkBox.maxX + COLLISION_EPSILON) + 1;
|
||||
int minBlockY = (int) Math.floor(checkBox.minY - COLLISION_EPSILON) - 1;
|
||||
int maxBlockY = (int) Math.floor(checkBox.maxY + COLLISION_EPSILON) + 1;
|
||||
int minBlockZ = (int) Math.floor(checkBox.minZ - COLLISION_EPSILON) - 1;
|
||||
int maxBlockZ = (int) Math.floor(checkBox.maxZ + COLLISION_EPSILON) + 1;
|
||||
|
||||
final int minSection = player.compensatedWorld.getMinHeight() >> 4;
|
||||
final int minBlock = minSection << 4;
|
||||
final int maxBlock = player.compensatedWorld.getMaxHeight() - 1;
|
||||
|
||||
int minChunkX = minBlockX >> 4;
|
||||
int maxChunkX = maxBlockX >> 4;
|
||||
|
||||
int minChunkZ = minBlockZ >> 4;
|
||||
int maxChunkZ = maxBlockZ >> 4;
|
||||
|
||||
int minYIterate = Math.max(minBlock, minBlockY);
|
||||
int maxYIterate = Math.min(maxBlock, maxBlockY);
|
||||
|
||||
for (int currChunkZ = minChunkZ; currChunkZ <= maxChunkZ; ++currChunkZ) {
|
||||
int minZ = currChunkZ == minChunkZ ? minBlockZ & 15 : 0; // coordinate in chunk
|
||||
int maxZ = currChunkZ == maxChunkZ ? maxBlockZ & 15 : 15; // coordinate in chunk
|
||||
|
||||
for (int currChunkX = minChunkX; currChunkX <= maxChunkX; ++currChunkX) {
|
||||
int minX = currChunkX == minChunkX ? minBlockX & 15 : 0; // coordinate in chunk
|
||||
int maxX = currChunkX == maxChunkX ? maxBlockX & 15 : 15; // coordinate in chunk
|
||||
|
||||
int chunkXGlobalPos = currChunkX << 4;
|
||||
int chunkZGlobalPos = currChunkZ << 4;
|
||||
|
||||
Column chunk = player.compensatedWorld.getChunk(currChunkX, currChunkZ);
|
||||
|
||||
if (chunk == null) continue;
|
||||
BaseChunk[] sections = chunk.getChunks();
|
||||
|
||||
for (int y = minYIterate; y <= maxYIterate; ++y) {
|
||||
BaseChunk section = sections[(y >> 4) - minSection];
|
||||
|
||||
if (section == null || (IS_FOURTEEN && section.isEmpty())) { // Check for empty on 1.13+ servers
|
||||
// empty
|
||||
// skip to next section
|
||||
y = (y & ~(15)) + 15; // increment by 15: iterator loop increments by the extra one
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int currZ = minZ; currZ <= maxZ; ++currZ) {
|
||||
for (int currX = minX; currX <= maxX; ++currX) {
|
||||
int x = currX | chunkXGlobalPos;
|
||||
int z = currZ | chunkZGlobalPos;
|
||||
|
||||
WrappedBlockState data = section.get(CompensatedWorld.blockVersion, x & 0xF, y & 0xF, z & 0xF, false);
|
||||
|
||||
// Works on both legacy and modern! Faster than checking for material types, most common case
|
||||
if (data.getGlobalId() == 0) continue;
|
||||
|
||||
// Thanks SpottedLeaf for this optimization, I took edgeCount from Tuinity
|
||||
int edgeCount = ((x == minBlockX || x == maxBlockX) ? 1 : 0) +
|
||||
((y == minBlockY || y == maxBlockY) ? 1 : 0) +
|
||||
((z == minBlockZ || z == maxBlockZ) ? 1 : 0);
|
||||
|
||||
final StateType type = data.getType();
|
||||
if (edgeCount != 3 && (edgeCount != 1 || Materials.isShapeExceedsCube(type))
|
||||
&& (edgeCount != 2 || type == StateTypes.PISTON_HEAD)) {
|
||||
final CollisionBox collisionBox = CollisionData.getData(type).getMovementCollisionBox(player, player.getClientVersion(), data, x, y, z);
|
||||
|
||||
if (collisionBox.isIntersected(checkBox)) {
|
||||
searchingFor.accept(new Vector3d(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean onClimbable(GrimPlayer player, double x, double y, double z) {
|
||||
WrappedBlockState blockState = player.compensatedWorld.getWrappedBlockStateAt(x, y, z);
|
||||
StateType blockMaterial = blockState.getType();
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package ac.grim.grimac.utils.nmsutil;
|
||||
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.collisions.CollisionData;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.CollisionBox;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.MainSupportingBlockData;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
@@ -42,12 +40,8 @@ public class MainSupportingBlockPosFinder {
|
||||
AtomicReference<Vector3i> bestBlockPos = new AtomicReference<>();
|
||||
AtomicDouble blockPosDistance = new AtomicDouble(Double.MAX_VALUE);
|
||||
|
||||
Collisions.hasMaterial(player, searchBox, (thing) -> {
|
||||
Vector3i blockPos = thing.getSecond().toVector3i();
|
||||
|
||||
CollisionBox collision = CollisionData.getData(thing.getFirst().getType()).getMovementCollisionBox(player, player.getClientVersion(), thing.getFirst(), blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||
if (!collision.isIntersected(searchBox)) return false;
|
||||
|
||||
Collisions.forEachCollisionBox(player, searchBox, (pos) -> {
|
||||
Vector3i blockPos = pos.toVector3i();
|
||||
Vector3d blockPosAsVector3d = new Vector3d(blockPos.getX() + 0.5, blockPos.getY() + 0.5, blockPos.getZ() + 0.5);
|
||||
double distance = playerPos.distanceSquared(blockPosAsVector3d);
|
||||
|
||||
@@ -55,8 +49,6 @@ public class MainSupportingBlockPosFinder {
|
||||
bestBlockPos.set(blockPos);
|
||||
blockPosDistance.set(distance);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -181,7 +181,8 @@ public class ReachUtils {
|
||||
|
||||
double lowest = Double.MAX_VALUE;
|
||||
|
||||
for (double eyes : player.getPossibleEyeHeights()) {
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
for (double eyes : possibleEyeHeights) {
|
||||
if (giveMovementThresholdLenience) targetBox.expand(player.getMovementThreshold());
|
||||
Vector from = new Vector(player.x, player.y + eyes, player.z);
|
||||
Vector closestPoint = VectorUtils.cutBoxToVector(from, targetBox);
|
||||
|
||||
@@ -87,7 +87,7 @@ RotationPlace:
|
||||
# Vérification de no-slow basée sur la prédiction.
|
||||
# Grim tient compte des problèmes de netcode ici... difficile à tromper même en spamant le clic droit et le bouton de la main secondaire.
|
||||
# Bien plus stable que les autres anti-triche, mais veuillez signaler toute fausse détection... J'ai corrigé de nombreux problèmes de netcode ici.
|
||||
NoSlow:
|
||||
NoSlowA:
|
||||
# Quel est le niveau d'écart considéré comme "triche"
|
||||
# Par défaut, cela est inférieur à d'autres écarts.
|
||||
# Génère des avertissements avec des valeurs comprises entre 0,03 et 0,2 lors de l'utilisation de NoSlow
|
||||
|
||||
@@ -10,16 +10,17 @@ alerts:
|
||||
# Isso controla se/como os alertas são compartilhados entre os servidores conectados ao proxy.
|
||||
# Deve-se ter 'bungee-plugin-message-channel' habilitado na configuração do Velocity se estiver usando.
|
||||
proxy:
|
||||
# Os alertas deveriam ser enviados para outros servidores conectados no mesmo proxy?
|
||||
# Deviam os alertas ser enviados para outros servidores conectados no mesmo proxy?
|
||||
send: false
|
||||
# Os alertas deveriam ser recebidos de outros servidores conectados no mesmo proxy?
|
||||
# Deviam os alertas ser recebidos de outros servidores conectados no mesmo proxy?
|
||||
receive: false
|
||||
|
||||
verbose:
|
||||
print-to-console: false
|
||||
|
||||
client-brand:
|
||||
# Isso signifia que, caso o nome do cliente seja igual aos listados abaixo, não será notificados aos operadores.
|
||||
# Isso signifia que, caso a marca do cliente seja igual às listadas abaixo, não será notificado aos
|
||||
# administradores.
|
||||
ignored-clients:
|
||||
- "^vanilla$"
|
||||
- "^fabric$"
|
||||
@@ -27,7 +28,7 @@ client-brand:
|
||||
- "^Feather Fabric$"
|
||||
|
||||
spectators:
|
||||
# Esconde todos espectadores com a permissão 'grim.spectator' mesmo se não estiverem espectando ativamente.
|
||||
# Esconde todos espectadores com a permissão 'grim.spectator' mesmo se não estiverem ativamente espectando.
|
||||
hide-regardless: false
|
||||
# Fará os espectadores serem escondidos apenas nos mundos listados abaixo, deixe em branco para habilitar em todos os mundos.
|
||||
allowed-worlds:
|
||||
@@ -36,35 +37,35 @@ spectators:
|
||||
# Quanto tempo os jogadores tem até expulsarmos eles por inatividade? Padrão = 60 segundos.
|
||||
max-transaction-time: 60
|
||||
|
||||
# Should the duplicate movement packet be cancelled?
|
||||
# Mojang has fixed this issue in 1.21. This was their attempt to fix the "bucket desync". https://bugs.mojang.com/browse/MC-12363
|
||||
# This setting only applies to 1.17-1.20.5 clients on 1.8 servers.
|
||||
# Deve-se cancelar o pacote de movimento duplicado?
|
||||
# A Mojang arrumou esse erro na 1.21, sendo sua tentativa de concertar a dessincronização do balde. https://bugs.mojang.com/browse/MC-12363
|
||||
# Isso só se aplica à clientes da 1.17-1.20.5 em servidores da 1.8.
|
||||
cancel-duplicate-packet: true
|
||||
|
||||
# Whether or not to ignore the rotation in duplicate packets
|
||||
# Deve-se ignorar rotação em pacotes duplicados?
|
||||
ignore-duplicate-packet-rotation: false
|
||||
|
||||
Simulation:
|
||||
# Por quanto deveríamos multiplicar a vantagem caso o jogador não tenha falhado em nem uma verificação?
|
||||
# Por quanto deve-se multiplicar a vantagem desde a última vez que falhou uma verificação?
|
||||
# Isso é como a configuração padrão se parece (eixo X = segundos, eixo Y = 1/1000 blocos): https://www.desmos.com/calculator/d4ufgxrxer
|
||||
setback-decay-multiplier: 0.999
|
||||
# O quão longe o jogador deve estar da área simulada para adicionarmos violações?
|
||||
# O quão longe o jogador deve estar da área simulada para registrar violações?
|
||||
# Medido em blocos do último movimento legítmo.
|
||||
# Aceitamos o Optifine trocando as tabelas trigonométricas, mas abaixar para 0.001 reduzirá o 'FastMath'
|
||||
# de falhar, caso esta compensação não funcionar...
|
||||
# Incluímos o Optifine trocando as tabelas trigonométricas; entretanto, abaixar para 0.001 reduzirá o 'FastMath'
|
||||
# de falhar, caso essa compensação não funcionar.
|
||||
threshold: 0.001
|
||||
# O quão longe o jogador deve estar da área simulada para imediatamente recuá-lo?
|
||||
# -1 desabilitará
|
||||
immediate-setback-threshold: 0.1
|
||||
# O quão longe da área simulada sobre todos os ticks para começarmos a recuar?
|
||||
# Qual é a soma do desalinhamento da simulação em todos os ticks até começarmos a recuar?
|
||||
# -1 desabilitará
|
||||
max-advantage: 1
|
||||
# Depois de 50 segundos, com a configuração padrão, o jogador irá de 4 blocos -> 1 bloco de vantagem.
|
||||
# Depois de 50 segundos, com a configuração padrão, o jogador irá de 4 blocos a 1 bloco de vantagem.
|
||||
# Isso serve para previnir o jogador de alcançar violações demais e nunca conseguir se livrar delas.
|
||||
# Cela de vantagens padrão (eixo X = segundos, eixo Y = 1/1000 blocos): https://www.desmos.com/calculator/4lovswdarj
|
||||
max-ceiling: 4
|
||||
|
||||
# Verifica se um jogador entrou em um bloco durante o movimento.
|
||||
# Verifica se um jogador entrou em um bloco ao se mover.
|
||||
Phase:
|
||||
setbackvl: 1 # Entrar em blocos possibilita escalar paredes, além disso, essa verificação é relativamente estável.
|
||||
decay: 0.005
|
||||
@@ -85,29 +86,29 @@ RotationPlace:
|
||||
cancelvl: 5
|
||||
|
||||
# Verificação de NoSlow por simulação.
|
||||
# Grim considera erros no netcode... difícil de gerar falsos positivos, até mesmo spamando o blotão direito e a offhand.
|
||||
# Muito mais estável que outros anticheats, mas por favor, reporte quaisquer falsos positivos... eu já arrumei diversos
|
||||
# Grim considera erros no netcode. Difícil de gerar falsos positivos, até mesmo spamando o blotão direito e a offhand.
|
||||
# Muito mais estável que outros anticheats, mas por favor, reporte quaisquer falsos positivos. Eu já arrumei diversos
|
||||
# erros de netcode.
|
||||
NoSlowA:
|
||||
# Quanto de desvio da simulação é considerado trapaça?
|
||||
# Por padrão isso é menor que outros desvios.
|
||||
# Acusa com 0.03-0.2 com consistência com o NoSlow ativo.
|
||||
# Quanto de desalinhamento é considerado trapaça?
|
||||
# Por padrão é menor que os outros.
|
||||
# Em 0.03-0.2 detecta com consistência.
|
||||
threshold: 0.001
|
||||
# Recua rapidamente no primeiro item para remover quaisquer vantagens que o NoSlow dá.
|
||||
# Recuo imediato para inibir as vantagens rapidamente.
|
||||
setbackvl: 5
|
||||
# Decai quando o jogador usa um item E é desasceletado por isso.
|
||||
# Decai quando o jogador usa um item e é efetivamente desacelerado.
|
||||
decay: 0.05
|
||||
|
||||
Knockback:
|
||||
# Por quanto deveriamos multiplicar a vantagem caso o jogador não tenha falhado nessa verificação?
|
||||
# Por quanto deve-se multiplicar a vantagem desde a última vez que falhou na verificação?
|
||||
setback-decay-multiplier: 0.999
|
||||
# O quão longe da área do recuo recebido o jogador deve estar para adicionarmos uma violação?
|
||||
# O quão longe da área do recuo recebido o jogador deve estar para registrar violações?
|
||||
# Medido em blocos do recuo recebido.
|
||||
threshold: 0.001
|
||||
# O quão longe o jogador deve estar da área simulada para imediatamente recuá-lo?
|
||||
# -1 desabilitará.
|
||||
immediate-setback-threshold: 0.1
|
||||
# O quão longe da área simulada sobre todos os ticks deverá ser para começarmos a recuar?
|
||||
# Qual é a soma do desalinhamento da simulação em todos os ticks até começarmos a recuar?
|
||||
# -1 desabilitará.
|
||||
max-advantage: 1
|
||||
# Isso serve para previnir o jogador de alcançar violações demais e nunca conseguir se livrar delas.
|
||||
@@ -120,16 +121,16 @@ Explosion:
|
||||
TimerA:
|
||||
setbackvl: 10
|
||||
# Milissegundos que o jogador pode acumular para depois usar quando eles têm um atraso no ping.
|
||||
# Pode permitir o uso de fast use / fast heal / fast bow na 1.8 caso o valor seja definido muito alto. 120ms parece
|
||||
# um bom balanceamento.
|
||||
# Pode ignorar o uso de fast use / fast heal / fast bow na 1.8 caso o valor seja definido muito alto.
|
||||
# 120ms parece um bom balanceamento.
|
||||
drift: 120
|
||||
# Ping no qual a verificação vai começar a limitar o balançeamento do timer para previnir abuso.
|
||||
# Pode causar recuos a jogadores legítmos, mas somente se estiverem acima deste ping.
|
||||
# Pode causar recuos a jogadores legítmos, mas somente se estiverem acima desse ping.
|
||||
# -1 desabilitará.
|
||||
ping-abuse-limit-threshold: 1000
|
||||
|
||||
NegativeTimer:
|
||||
# Número de milissegundos perdidos ao se mover antes de começarmos a adicionar violações.
|
||||
# Número de milissegundos perdidos ao se mover antes de começarmos a registrar violações.
|
||||
drift: 1200
|
||||
|
||||
# Mesmo método usado no TimerA, mas para veículos.
|
||||
@@ -141,56 +142,54 @@ EntityControl:
|
||||
setbackvl: 25
|
||||
|
||||
Reach:
|
||||
# Por quanto devíamos expandir as caixas de colisão? 0.0005 deve detectar 3.0005+ de alcance.
|
||||
# Por quanto deve-se expandir as caixas de colisão? 0.0005 deve detectar 3.0005+ de alcance.
|
||||
#
|
||||
# Há 0.03 de expansão forçada nas versões 1.9-1.18.1 (não a 1.18.2), ou algumas combinações de cliente/servidor por
|
||||
# conta de mudanças no protocolo e limitações. Essa verificação é mais poderosa com clientes da 1.7/1.8 em servidores
|
||||
# da 1.8.
|
||||
threshold: 0.0005
|
||||
# Deveríamos cancelar hits que sabemos que são impossíveis?
|
||||
# O alcance de 3.00-3.03 pode acabar passando, mas continuarão adicionando violações, por conta de limitações na
|
||||
# ordem de pacotes.
|
||||
# Deve-se cancelar hits que sabemos que são impossíveis?
|
||||
# O alcance de 3.00-3.03 pode acabar passando, por conta da ordem de pacotes, mas continuará registrando violações.
|
||||
block-impossible-hits: true
|
||||
# Isso enviará um pacote adicional no final de todos os ticks para aumentar a probabilidade de detectarmos trapaceiros.
|
||||
# Isso injeta na lista de conecção do servidor para envar um pacote final logo antes do servidor recarregar.
|
||||
# Habilitando isso, irá aumentar o uso de banda para todos os jogadores.
|
||||
# Isso não irá interferir na performance do servidor.
|
||||
# Habilitando isso, aumentará a probabilidade de detectarmos trapaceiros.
|
||||
# Deixando-o desabilitado, continuará detectando cheaters e não irá causar falsos positivos.
|
||||
# A menos que estiver em um servidor focado em PvP esse pacote adicional não é recomendado.
|
||||
# Deixando-o desabilitado, continuará detectando trapaceiros e não irá causar falsos positivos.
|
||||
# A menos que estiver em um servidor focado em PvP, esse pacote adicional não é recomendado.
|
||||
enable-post-packet: false
|
||||
|
||||
exploit:
|
||||
# Você pode ganhar altas velocidades enquanto pular correndo com uma elytra, isso previne o exploitação de ocorrer quando
|
||||
# definido falso.
|
||||
# Você pode ganhar altas velocidades se pular correndo com uma elytra, previne isso de ocorrer quando definido falso.
|
||||
# A Mojang vacilou com o netcode por fazer a Elytra iniciar pelo lado do cliente.
|
||||
# As Elytras levam 0.99 de fricção horizontal, então constantemente adicionando 0.2 de velocidade horizontal resulta
|
||||
# em velocidades altíssimas.
|
||||
allow-sprint-jumping-when-using-elytra: true
|
||||
# Essa opção mitiga o posicionamento de blocos em blocos fantasmas, ressincronizando o jogador quando isso ocorrer.
|
||||
# Essa opção mitiga posicionar blocos em blocos fantasma, ressincronizando o jogador quando isso ocorrer.
|
||||
allow-building-on-ghostblocks: true
|
||||
# Este ajuste, influenciado pelo booleano acima, define a distância para verificar blocos fantasmas.
|
||||
# Seu intervalo válido é limitado de 2 a 4.
|
||||
# Esse ajuste, influído pela opção acima, define a distância para verificar blocos fantasmas.
|
||||
# O valor válido é limitado de 2 a 4.
|
||||
distance-to-check-if-ghostblocks: 2
|
||||
|
||||
# Habilita registrar plugins que são injetados na netty ao entrar para depurar erros de compatibilidade.
|
||||
# Registra plugins que são injetados na netty ao entrar para depurar erros de compatibilidade.
|
||||
debug-pipeline-on-join: false
|
||||
|
||||
# Habilita verificações experimentais.
|
||||
experimental-checks: false
|
||||
|
||||
# Grim às vezes cancela pacotes ilegais como com o timer, depois de X pacotes em um segundo que foram cancelados, quando
|
||||
# devemos simplesmente expulsar o jogador? Isso é requirido já que alguns limitadores de pacotes não contam pacotes
|
||||
# deve-se simplesmente expulsar o jogador? Isso é requirido já que alguns limitadores de pacotes não contam pacotes
|
||||
# cancelados pelo Grim.
|
||||
packet-spam-threshold: 100
|
||||
|
||||
# Grim é capaz de garantir que um jogador fora do estado de voo não possa ter mais de X milissegundos de ping.
|
||||
# Grim pode impor que o jogador fora do estado de voo não possa ter mais de X milissegundos de ping.
|
||||
# Isso ocorre porque o Grim atualmente não verifica os jogadores que estão voando.
|
||||
# To disable, use -1
|
||||
# -1 desabilitará.
|
||||
max-ping-out-of-flying: 1000
|
||||
|
||||
# Maximum ping when a firework boost is removed from the player.
|
||||
# This prevents high latency players from being able to use 1 firework boost with an elytra forever.
|
||||
# Ping máximo quando o impulso do foguete acaba.
|
||||
# Previne jogadores com ping alto de usarem um foguete ara voar indefinidamente.
|
||||
max-ping-firework-boost: 1000
|
||||
|
||||
config-version: 9
|
||||
@@ -0,0 +1,192 @@
|
||||
# GrimAC ana konfigrasyon dosyası
|
||||
# Kaynak kodu: https://github.com/MWHunter/Grim
|
||||
# Telif Hakkı 2024 DefineOutside ve katkıda bulunanlar, GPLv3 altında lisanslanmıştır.
|
||||
# Değiştirilmiş ikili dosyalar veya kopyalanmış grim kodlu eklentiler özel olmalıdır,
|
||||
# veya ek ücret ödemeden alıcılara sunulan tam kaynak kodu ile.
|
||||
|
||||
alerts:
|
||||
# Oyunculara uyarı yayınlamanın yanı sıra, uyarılar konsola da gönderilmeli mi?
|
||||
print-to-console: true
|
||||
# Bu, uyarıların proxy'nize bağlı sunucular arasında paylaşılıp paylaşılmayacağını/nasıl paylaşılacağını kontrol eder.
|
||||
# Velocity kullanılıyorsa, Velocity yapılandırmanızda 'bungee-plugin-message-channel' etkinleştirilmiş olmalıdır.
|
||||
proxy:
|
||||
# Proxy'nize bağlı diğer sunuculara uyarılar gönderilmeli mi?
|
||||
send: false
|
||||
# Diğer sunuculardan alınan uyarılar bu sunucuya duyurulmalı mı?
|
||||
receive: false
|
||||
|
||||
verbose:
|
||||
print-to-console: false
|
||||
|
||||
client-brand:
|
||||
# Bu, giriş yapılan clientin aşağıdaki regex'lerle eşleşmesi durumunda markalarını operatörlere yayınlamayacağı anlamına gelir
|
||||
ignored-clients:
|
||||
- "^vanilla$"
|
||||
- "^fabric$"
|
||||
- "^lunarclient:v\\d+\\.\\d+\\.\\d+-\\d{4}$"
|
||||
- "^Feather Fabric$"
|
||||
|
||||
spectators:
|
||||
# Seyirciler aktif olarak izliyor olsalar bile, grim.spectator iznine sahip tüm seyircileri gizle
|
||||
hide-regardless: false
|
||||
# Sadece bu dünyalarda seyircileri gizleyecek, tüm dünyalara izin vermek için boş bırakın
|
||||
allowed-worlds:
|
||||
- ""
|
||||
|
||||
# Oyuncuların zaman aşımından dolayı sunucudan atılmadan önce ne kadar süreleri olmalı? Varsayılan = 60 saniye
|
||||
max-transaction-time: 60
|
||||
|
||||
# Kopya hareket paketinin iptal edilip edilmemesi gerektiği
|
||||
# Mojang bu sorunu 1.21'de çözdü. Bu, "kova senkronizasyonu" sorununu düzeltme girişimiydi. https://bugs.mojang.com/browse/MC-12363
|
||||
# Bu ayar yalnızca 1.17-1.20.5 istemcileri için 1.8 sunucularında geçerlidir.
|
||||
cancel-duplicate-packet: true
|
||||
|
||||
# Eşya çoğaltma paketlerindeki rotayı göz ardı edip etmeyeceğimiz
|
||||
ignore-duplicate-packet-rotation: false
|
||||
|
||||
Simulation:
|
||||
# Oyuncu meşru olduğunda toplam avantajı ne kadar çarpmalıyız?
|
||||
# Varsayılan yapılandırma bu şekilde görünür (x ekseni = saniye, y ekseni = 1/1000 blok): https://www.desmos.com/calculator/d4ufgxrxer
|
||||
setback-decay-multiplier: 0.999
|
||||
# Oyuncunun hareketinden ne kadar büyük bir sapma ihlal oluşturmalıyız?
|
||||
# Mümkün olan hareketten blok cinsinden ölçülür
|
||||
# Optifine için trig tablolarını değiştirerek hesaba katıyoruz, ancak bunu 0.001'e düşürmek FastMath'ı azaltır
|
||||
# Bu telafi işe yaramazsa anticheat'i işaretle...
|
||||
threshold: 0.001
|
||||
# Bir tik içinde ne kadar büyük bir ihlal olmalı ki oyuncu hemen geri dönsün?
|
||||
# Devre dışı bırakmak için -1 yazın
|
||||
immediate-setback-threshold: 0.1
|
||||
# Tüm tikler boyunca ne kadar büyük bir avantaja sahip olmalıyız ki geri dönüş yapmaya başlayalım?
|
||||
# Devre dışı bırakmak için -1 yazın
|
||||
max-advantage: 1
|
||||
# Varsayılan config ile 50 saniye sonra, oyuncu 4 bloktan -> 1 bloğa kadar avantaj kazanır
|
||||
# Bu, oyuncunun çok fazla ihlal biriktirmesini ve bunların hepsini temizleyememesini önlemek içindir
|
||||
# Varsayılan avantaj tavanı (x ekseni = saniye, y ekseni = 1/1000 blok): https://www.desmos.com/calculator/4lovswdarj
|
||||
max-ceiling: 4
|
||||
|
||||
# Bir oyuncunun bir hareket sırasında bir bloğa girip girmediğini kontrol eder
|
||||
Phase:
|
||||
setbackvl: 1 # Blokların içinde glitch yapmak duvara tırmanmaya izin verebilir, ayrıca bu kontrol nispeten stabildir
|
||||
decay: 0.005
|
||||
|
||||
AirLiquidPlace:
|
||||
cancelvl: 0
|
||||
|
||||
FabricatedPlace:
|
||||
cancelvl: 5
|
||||
|
||||
FarPlace:
|
||||
cancelvl: 5
|
||||
|
||||
PositionPlace:
|
||||
cancelvl: 5
|
||||
|
||||
RotationPlace:
|
||||
cancelvl: 5
|
||||
|
||||
# Tahmin tabanlı yavaşlama kontrolü
|
||||
# Grim burada hatalı ağ kodunu dikkate alır... sağ tıklama ve el yan tuşunu spam yapsanız bile yanlış pozitiflik oluşturması zordur
|
||||
# Diğer anti-hilelerden çok daha stabil, ancak herhangi bir yanlış pozitif rapor edin... burada birçok ağ kodu sorununu çözdüm.
|
||||
NoSlowA:
|
||||
# Ne kadar bir sapma "hile" olarak kabul edilir?
|
||||
# Varsayılan olarak bu, diğer sapmalardan daha düşüktür
|
||||
# NoSlow açıkken 0.03-0.2 aralığında sürekli olarak uyarı verir
|
||||
threshold: 0.001
|
||||
# NoSlow'un sağladığı avantajı ortadan kaldırmak için ilk itemi hızlı bir şekilde geri alın
|
||||
setbackvl: 5
|
||||
# Oyuncu bir eşya kullandığında VE onun tarafından yavaşlatıldığında beklenilen zaman
|
||||
decay: 0.05
|
||||
|
||||
Knockback:
|
||||
# Oyuncu legit olduğunda toplam avantajı ne kadarla çarpmalıyız
|
||||
setback-decay-multiplier: 0.999
|
||||
# Oyuncunun hızından ne kadar büyük bir sapma ihlal oluşturmalıyız?
|
||||
# Mümkün olan hızdan blok cinsinden ölçülür
|
||||
threshold: 0.001
|
||||
# Bir tik içinde ne kadar büyük bir ihlal olmalı ki oyuncu hemen geri dönsün?
|
||||
# Devre dışı bırakmak için -1 yazın
|
||||
immediate-setback-threshold: 0.1
|
||||
# Tüm tikler boyunca ne kadar büyük bir avantaja sahip olmalıyız ki geri dönüş yapmaya başlayalım?
|
||||
# Devre dışı bırakmak için -1 yazın
|
||||
max-advantage: 1
|
||||
# Bu, oyuncunun çok fazla ihlal toplamasını ve asla hepsini temizleyememesini engellemek içindir
|
||||
max-ceiling: 4
|
||||
|
||||
Explosion:
|
||||
threshold: 0.001
|
||||
setbackvl: 3
|
||||
|
||||
TimerA:
|
||||
setbackvl: 10
|
||||
# Oyuncunun geri kaldığında biriktirebileceği milisaniye miktarı
|
||||
# Çok yüksek ayarlandığında 1.8 hızlı kullanma/hızlı iyileşme/hızlı yay atlama durumlarına izin verebilir, 120 ms iyi bir denge gibi görünüyor
|
||||
drift: 120
|
||||
# Kontrolün zamanlayıcı dengesini sınırlamaya başlayacağı ping değeri, kötüye kullanımı önlemek için.
|
||||
# Bu, yalnızca bu ping eşiğini aşan meşru oyuncular için bazı geri dönüşlere neden olabilir.
|
||||
# Devre dışı bırakmak için -1 yazın
|
||||
ping-abuse-limit-threshold: 1000
|
||||
|
||||
NegativeTimer:
|
||||
# Uyarı vermeye başlamadan önce hareket halindeyken kaybedilen milisaniye sayısı
|
||||
drift: 1200
|
||||
|
||||
# TimerA ile aynı kontrol yöntemi, ancak araçlar için
|
||||
TimerVehicle:
|
||||
# Hedef 1.005 timer
|
||||
setbackvl: 10
|
||||
|
||||
EntityControl:
|
||||
setbackvl: 25
|
||||
|
||||
Reach:
|
||||
# Hitbox'ları ne kadar genişletmeliyiz? 0.0005, 3.0005+ menzili tespit etmelidir
|
||||
#
|
||||
# 1.9-1.18.1 (1.18.2 değil) ile zorunlu olarak 0.03 genişletme vardır veya bazı istemci/sunucu kombinasyonları nedeniyle
|
||||
# protokol değişiklikleri ve sınırlamaları nedeniyle. Bu kontrol, 1.7/1.8 istemcilerle 1.8 sunucularda en güçlüdür.
|
||||
threshold: 0.0005
|
||||
# İmkansız olduğunu bildiğimiz vuruşları iptal etmeli miyiz?
|
||||
# Paket sırası sınırlamaları nedeniyle 3.00-3.03 arası vuruşlar gerçekleşebilir, ancak yine de işaretlenebilir
|
||||
block-impossible-hits: true
|
||||
# Bu, hileleri yakalama olasılığını artırmak için her tikin sonunda ek bir paket gönderecektir
|
||||
# Bu, sunucunun bağlantı listesine enjekte edilerek sunucu boşaltmadan hemen önce son bir paket göndermek için yapılır
|
||||
# Bunu etkinleştirmek, tüm oyuncular için bant genişliği kullanımını artıracaktır
|
||||
# Bu, genel sunucu performansını düşürmez
|
||||
# Bunu etkinleştirmek, daha fazla hilecinin yakalanmasını sağlar
|
||||
# Bu özellik devre dışı bırakılsa bile hileciler yakalanır ve yanlış pozitifler oluşmaz
|
||||
# 1.8 PvP odaklı bir sunucu değilseniz, bu ek paket önerilmez
|
||||
enable-post-packet: false
|
||||
|
||||
exploit:
|
||||
# Elytra ile sprint zıplarken yüksek hızlar kazanabilirsiniz, bu ayar false olarak ayarlandığında bu istismarı önler
|
||||
# Mojang, elytra'nın istemci tarafında başlamasını ve sunucu tarafında bitmesini sağlayarak netcode'u bozdu
|
||||
# Elytra'lar 0.99 yatay sürtünme alır, bu yüzden sürekli olarak 0.2 yatay hız eklemek çok yüksek hızlara yol açar
|
||||
allow-sprint-jumping-when-using-elytra: true
|
||||
# Bu seçenek, oyuncunun hayalet bloklar üzerindeki yerleşimini, gerçekleştiğinde oyuncuyu yeniden senkronize ederek hafifletir
|
||||
allow-building-on-ghostblocks: true
|
||||
# Bu ayar, yukarıdaki boolean ile etkilenen hayalet blokları kontrol etmek için mesafeyi tanımlar
|
||||
# Geçerli aralığı 2 ile 4 arasında sınırlıdır
|
||||
distance-to-check-if-ghostblocks: 2
|
||||
|
||||
# Netty'ye enjekte olan eklentileri giriş sırasında günlüklemeyi etkinleştirerek uyumluluk sorunlarını gider
|
||||
debug-pipeline-on-join: false
|
||||
|
||||
# Deneysel kontrolleri etkinleştir
|
||||
experimental-checks: false
|
||||
|
||||
# Grim bazen timer gibi yasa dışı paketleri iptal eder; bir saniyede X paket iptal edildikten sonra, ne zaman
|
||||
# oyuncuyu basitçe atmalıyız? Bu, bazı paket sınırlayıcılarının Grim tarafından iptal edilen paketleri saymaması gerektiğindendir.
|
||||
packet-spam-threshold: 100
|
||||
|
||||
# Grim, uçma durumundan çıkmış bir oyuncunun X milisaniyeden fazla ping'e sahip olamayacağını uygulayabilir
|
||||
# Bu, Grim'in şu anda uçan oyuncuları kontrol etmemesindendir
|
||||
# Devre dışı bırakmak için -1 yazın
|
||||
max-ping-out-of-flying: 1000
|
||||
|
||||
# Bir havai fişek ivmesi oyuncudan çıkarıldığında maksimum ping.
|
||||
# Bu, yüksek gecikmeli oyuncuların bir havai fişek ivmesini elytra ile sonsuza kadar kullanmalarını engeller.
|
||||
max-ping-firework-boost: 1000
|
||||
|
||||
config-version: 9
|
||||
|
||||
# Translated by Kayera
|
||||
# Have a nice day :)
|
||||
@@ -2,7 +2,7 @@
|
||||
# 源代码链接: https://github.com/MWHunter/Grim
|
||||
# 版权归 DefineOutside 和 贡献者所有,基于GPLv3开源协议。
|
||||
# 修改过的二进制文件,或带有复制的Grim代码的插件,必须是私有仓库,不得公开售卖此插件。
|
||||
# 中文翻译提供 nuym ,如有错误请提交 Issues 并@我
|
||||
# 中文翻译提供 nuym/Dg32z_ ,如有错误请提交 Issues 并@我
|
||||
|
||||
alerts:
|
||||
# 是否在控制台显示作弊消息?
|
||||
@@ -27,21 +27,22 @@ client-brand:
|
||||
- "^Feather Fabric$"
|
||||
|
||||
spectators:
|
||||
# 把所有拥有 grim.spectartor 权限的人都隐藏起来,不管他是否观察玩家。
|
||||
# 将拥有 grim.spectator 权限的人进行隐藏,不管他是否在观察玩家
|
||||
hide-regardless: false
|
||||
# 观察者这些世界不会隐藏
|
||||
allowed-worlds:
|
||||
- ""
|
||||
|
||||
# 在我们让他们超时之前,玩家应该有多长时间? 此处的60 指60s
|
||||
# 在玩家无法接收 GrimAC的 transaction 数据包后,多少秒对玩家进行踢出
|
||||
# 踢出原因为: disconnect.timeout
|
||||
max-transaction-time: 60
|
||||
|
||||
# Should the duplicate movement packet be cancelled?
|
||||
# Mojang has fixed this issue in 1.21. This was their attempt to fix the "bucket desync". https://bugs.mojang.com/browse/MC-12363
|
||||
# This setting only applies to 1.17-1.20.5 clients on 1.8 servers.
|
||||
# 是否对重复的移动数据包进行撤销?
|
||||
# 这可以修复 "bucket desync". https://bugs.mojang.com/browse/MC-12363,不过Mojang已经在1.21修复了这个问题
|
||||
# 这仅仅适用于1.8服务器中使用1.17-1.20.5版本的玩家
|
||||
cancel-duplicate-packet: true
|
||||
|
||||
# Whether or not to ignore the rotation in duplicate packets
|
||||
# 是否忽视重复的数据包中的玩家转头
|
||||
ignore-duplicate-packet-rotation: false
|
||||
|
||||
Simulation:
|
||||
@@ -84,7 +85,7 @@ PositionPlace:
|
||||
RotationPlace:
|
||||
cancelvl: 5
|
||||
|
||||
# Prediction-based NoSlow 检查
|
||||
# 使用模拟移动进行的NoSlow(使用物品时不会减速)检查
|
||||
# 在这里解释错误的服务器代码......即使在发送垃圾数据包时右键单击和副手按钮也很分辨
|
||||
# 比其他反作弊更稳定,但请报告任何错误......我在这里修复了大量的代码问题。
|
||||
NoSlowA:
|
||||
@@ -121,13 +122,13 @@ TimerA:
|
||||
# 玩家卡顿时可以累积以供以后使用的毫秒数
|
||||
# 如果设置得太高,可能会允许 1.8 快速使用/快速治疗/快速弓箭绕过,120 毫秒似乎是一个很好的平衡
|
||||
drift: 120
|
||||
# Ping at which the check will start to limit timer balance, to prevent abuse.
|
||||
# Can cause some setbacks for legitimate players but only if they are over this ping threshold.
|
||||
# -1 to disable
|
||||
# 在检查玩家的延迟时对timer balance进行限制, 防止滥用
|
||||
# 在合法玩家的延迟超过这个延迟阈值时可能会造成误拉回
|
||||
# 填写-1则关闭
|
||||
ping-abuse-limit-threshold: 1000
|
||||
|
||||
NegativeTimer:
|
||||
# Number of milliseconds lost while moving before we should start flagging
|
||||
# 在开始检查玩家时,玩家的移动丢失了多少毫秒数
|
||||
drift: 1200
|
||||
|
||||
# 与 TimerA 相同的检查方法,但适用于坐骑
|
||||
@@ -157,8 +158,10 @@ Reach:
|
||||
enable-post-packet: false
|
||||
|
||||
exploit:
|
||||
#是否允许玩家在使用鞘翅时候进行的疾跑跳跃
|
||||
allow-sprint-jumping-when-using-elytra: true
|
||||
# 该选项可在发生鬼块时重新同步玩家,从而减轻玩家在鬼块上的位置。
|
||||
# 这可以在玩家遇到幽灵方块时进行同步,这可以减少玩家所碰到幽灵方块
|
||||
allow-building-on-ghostblocks: true
|
||||
distance-to-check-if-ghostblocks: 2
|
||||
|
||||
@@ -173,11 +176,12 @@ experimental-checks: false
|
||||
packet-spam-threshold: 100
|
||||
|
||||
# Grim 能够强制执行一个规则:被设置为非飞行状态的玩家的 ping 值不能超过 X 毫秒。这是因为 Grim 目前不检查处于飞行状态的玩家。
|
||||
# To disable, use -1
|
||||
# 填写-1则关闭
|
||||
max-ping-out-of-flying: 1000
|
||||
|
||||
# Maximum ping when a firework boost is removed from the player.
|
||||
# This prevents high latency players from being able to use 1 firework boost with an elytra forever.
|
||||
# 限制玩家在使用鞘翅飞行时使用烟花加速的延迟
|
||||
# 这可以解决高延迟的玩家可以使用鞘翅时一直使用 1 个烟花就可以加速
|
||||
# 填写-1则关闭
|
||||
max-ping-firework-boost: 1000
|
||||
|
||||
config-version: 9
|
||||
@@ -1,6 +1,7 @@
|
||||
# Ob Discord Webhook aktiviert werden soll
|
||||
enabled: false
|
||||
webhook: ""
|
||||
embed-title: "**Grim Alert**"
|
||||
embed-color: "#00FFFF"
|
||||
violation-content:
|
||||
- "**Spieler**: %player%"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
enabled: false
|
||||
webhook: ""
|
||||
embed-title: "**Grim Alert**"
|
||||
embed-color: "#00FFFF"
|
||||
violation-content:
|
||||
- "**Player**: %player%"
|
||||
|
||||
@@ -7,6 +7,8 @@ enabled: false
|
||||
# La URL del webhook.
|
||||
webhook: ""
|
||||
|
||||
embed-title: "**Grim Alert**"
|
||||
|
||||
# El color del embed que se mandara por este webhook.
|
||||
embed-color: "#00FFFF"
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
enabled: false
|
||||
webhook: ""
|
||||
embed-title: "**Grim Alert**"
|
||||
embed-color: "#00FFFF"
|
||||
violation-content:
|
||||
- "**Joueur**: %player%"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
enabled: false
|
||||
webhook: ""
|
||||
embed-title: "**Grim Alert**"
|
||||
embed-color: "#00FFFF"
|
||||
violation-content:
|
||||
- "**Giocatore**: %player%"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
enabled: false
|
||||
webhook: ""
|
||||
embed-title: "**Grim Alert**"
|
||||
embed-color: "#00FFFF"
|
||||
violation-content:
|
||||
- "**Speler**: %player%"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
enabled: false
|
||||
webhook: ""
|
||||
embed-title: "**Grim Alert**"
|
||||
embed-color: "#00FFFF"
|
||||
violation-content:
|
||||
- "**Jogador**: %player%"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Включать ли веб-крючок discord
|
||||
enabled: false
|
||||
webhook: ""
|
||||
embed-title: "**Grim Alert**"
|
||||
embed-color: "#00FFFF"
|
||||
violation-content:
|
||||
- "**Игрок**: %player%"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
enabled: false
|
||||
webhook: ""
|
||||
embed-color: "#00FFFF"
|
||||
violation-content:
|
||||
- "**Oyuncu**: %player%"
|
||||
- "**Kontrol**: %check%"
|
||||
- "**İhlaller**: %violations%"
|
||||
- "**Client Versiyonu**: %version%"
|
||||
- "**Kullanılan Client**: %brand%"
|
||||
- "**Gecikme**: %ping%"
|
||||
- "**TPS**: %tps%"
|
||||
@@ -1,12 +1,13 @@
|
||||
# 是否启用discord webhook
|
||||
enabled: false
|
||||
webhook: ""
|
||||
embed-title: "**Grim Alert**"
|
||||
embed-color: "#00FFFF"
|
||||
violation-content:
|
||||
- "**Player**: %player%"
|
||||
- "**Check**: %check%"
|
||||
- "**Violations**: %violations%"
|
||||
- "**Client Version**: %version%"
|
||||
- "**Brand**: %brand%"
|
||||
- "**Ping**: %ping%"
|
||||
- "**TPS**: %tps%"
|
||||
- "**玩家名**: %player%"
|
||||
- "**检查**: %check%"
|
||||
- "**违规率**: %violations%"
|
||||
- "**游戏版本**: %version%"
|
||||
- "**客户端品牌**: %brand%"
|
||||
- "**延迟**: %ping%"
|
||||
- "**服务器卡顿程度**: %tps%"
|
||||
@@ -1,34 +1,31 @@
|
||||
# Você pode usar códigos hexadecimais também, no formato #FFFFFF ou #ffffff.
|
||||
|
||||
# \u00BB é » (>> duplo), ANSI e UTF-8 interpretam isso diferentemente... você pode acabar vendo '?' por conta disso.
|
||||
prefix: "&bGrim &8\u00BB"
|
||||
|
||||
alerts-enabled: "%prefix% &fAlertas do AntiCheat foram habilitados para você."
|
||||
alerts-disabled: "%prefix% &fAlertas do AntiCheat foram desabilitados para você."
|
||||
client-brand-format: "%prefix% &f%player% entrou usando: &c%brand%"
|
||||
console-specify-target: "%prefix% &cVocê deve especificar o nome do alvo como o terminal!"
|
||||
alerts-enabled: "%prefix% &fAlertas habilitados."
|
||||
alerts-disabled: "%prefix% &fAlertas desabilitados."
|
||||
client-brand-format: "%prefix% &f%player% entrou usando %brand%."
|
||||
console-specify-target: "%prefix% &cVocê deve especificar o nome do alvo!"
|
||||
player-not-found: "%prefix% &cJogador não encontrado!"
|
||||
player-not-this-server: "%prefix% &cO jogador não está nesse servidor!"
|
||||
player-not-this-server: "%prefix% &cO jogador não está no servidor!"
|
||||
spectate-return: "\n%prefix% &fClique aqui para retornar a localização anterior\n"
|
||||
cannot-spectate-return: "%prefix% &cVocê só pode fazer isso enquanto estiver espectando alguém."
|
||||
cannot-run-on-self: "%prefix% &cVocê não pode usar esse comando em você mesmo!"
|
||||
upload-log: "%prefix% &fLogs enviadas para: %url%"
|
||||
upload-log-start: "%prefix% &fEnviando a log... Por favor, aguarde..."
|
||||
upload-log-not-found: "%prefix% &cNão foi possível encontrar essa log."
|
||||
upload-log-upload-failure: "%prefix% &cAlgo deu errado ao enviar essa log, veja o terminal para mais informações."
|
||||
cannot-spectate-return: "%prefix% &cVocê só pode fazer isso após espectar um jogador."
|
||||
cannot-run-on-self: "%prefix% &cVocê não pode usar esse comando em sí mesmo!"
|
||||
upload-log: "%prefix% &fRegistro enviado para: %url%"
|
||||
upload-log-start: "%prefix% &fEnviando o registro. Aguarde."
|
||||
upload-log-not-found: "%prefix% &cNúmero do registro não encontrado."
|
||||
upload-log-upload-failure: "%prefix% &cAlgo deu errado ao enviar o registro, veja o terminal para mais informações."
|
||||
|
||||
# Placeholders válidos:
|
||||
# %prefix%
|
||||
# %player%
|
||||
# %check_name%
|
||||
# %description%
|
||||
# %experimental%
|
||||
# %vl% - violações
|
||||
# %verbose% - Informação extra da verificação, como os desvios, nem todas as verifiações terão essa informação.
|
||||
# %verbose% - Informação extra da verificação, como os desalinhamentos, nem todas as verifiações terão essa informação.
|
||||
alerts-format: "%prefix% &f%player% &bfalhou em &f%check_name%%experimental% &f(x&c%vl%&f) &7%verbose%"
|
||||
alerts-format-proxy: "%prefix% &f[&cproxy&f] &f%player% &bfalhou em &f%check_name%%experimental% &f(x&c%vl%&f) &7%verbose%"
|
||||
experimental-symbol: "*"
|
||||
|
||||
profile:
|
||||
- "&7======================"
|
||||
- "%prefix% &bPerfil de &f%player%"
|
||||
@@ -41,13 +38,13 @@ profile:
|
||||
- "&7======================"
|
||||
help:
|
||||
- "&7======================"
|
||||
- "/grim alerts &f- &7Alterna entre &aon&f/&coff &7as notificações."
|
||||
- "/grim alerts &f- &7Alterna noificações."
|
||||
- "/grim profile <player> &f- &7Mosta as informações do jogador."
|
||||
- "/grim help &f- &7Mostra essa mensagem de ajuda."
|
||||
- "/grim debug <player> &f- &7Modo de depuração do plugin."
|
||||
- "/grim perf &f- &7Informações de performance do plugin."
|
||||
- "/grim reload &f- &7Recarregar configurações do AntiCheat."
|
||||
- "/grim spectate <player> &f- &7Espectar um jogador."
|
||||
- "/grim verbose &f- &7Mostra todos os flags para você sem os buffers."
|
||||
- "/grim log [0-255] &f- &7Envie um log para visualização externa."
|
||||
- "/grim debug <player> &f- &7Depura a simulação."
|
||||
- "/grim perf &f- &7Depura a performance."
|
||||
- "/grim reload &f- &7Recarrega as configurações."
|
||||
- "/grim spectate <player> &f- &7Especta um jogador."
|
||||
- "/grim verbose &f- &7Esconde as informações extra."
|
||||
- "/grim log [0-255] &f- &7Envia o registro da simulação."
|
||||
- "&7======================"
|
||||
@@ -0,0 +1,56 @@
|
||||
# Hex kodlarını #FFFFFF veya #ffffff formatında kullanabilirsiniz :)
|
||||
|
||||
# \u00BB eşittir » (çift >>), ANSI ve UTF-8 bunu farklı yorumlar. bu nedenle ? bile görebilirsiniz
|
||||
prefix: "&bGrim &8\u00BB"
|
||||
|
||||
alerts-enabled: "%prefix% &fUyarılar aktif edildi."
|
||||
alerts-disabled: "%prefix% &fUyarılar deaktif edildi."
|
||||
client-brand-format: "%prefix% &f%player% adlı oyuncu %brand% kullanarak giriş yaptı."
|
||||
console-specify-target: "%prefix% &cKonsol olarak bir hedef belirtmelisiniz!"
|
||||
player-not-found: "%prefix% &cOyuncu bulunamadı veya aktif değil!"
|
||||
player-not-this-server: "%prefix% &cBu oyuncu sunucuda değil!"
|
||||
spectate-return: "\n%prefix% &fBir önceki konuma dönmek için buraya tıklayın.\n"
|
||||
cannot-spectate-return: "%prefix% &cBunu yalnızca bir oyuncuyu izledikten sonra yapabilirsiniz."
|
||||
cannot-run-on-self: "%prefix% &cBu komutu kendi üzerinizde kullanamazsınız!"
|
||||
upload-log: "%prefix% &fDebug şu adrese yüklendi: %url%"
|
||||
upload-log-start: "%prefix% &fLog yükleniyor... lütfen bekleyin."
|
||||
upload-log-not-found: "%prefix% &cLog bulunamadı."
|
||||
upload-log-upload-failure: "%prefix% &cLog yüklenirken bir problem oluştu, lütfen konsolu kontrol edin."
|
||||
|
||||
# Geçerli placeholderlar:
|
||||
# %prefix%
|
||||
# %player%
|
||||
# %check_name%
|
||||
# %description%
|
||||
# %experimental%
|
||||
# %vl% - ihlal uyarıları
|
||||
# %verbose% - detaylı olarak verilen tüm uyarılar, checkler tüm bilgileri vermez
|
||||
alerts-format: "%prefix% &b%player% &fadlı oyuncuda &f(x&c%vl%&f) &fadet &b%check_name%%experimental% &ftespit edildi: &7%verbose%"
|
||||
alerts-format-proxy: "%prefix% &f[&cproxy&f] &b%player% &fadlı oyuncuda &f(x&c%vl%&f) &fadet &b%check_name%%experimental% &ftespit edildi: &7%verbose%"
|
||||
experimental-symbol: "*"
|
||||
|
||||
profile:
|
||||
- "&7======================"
|
||||
- "%prefix% &f%player% &badlı oyuncunun profili:"
|
||||
- "&bGecikme: &f%ping%"
|
||||
- "&bVersiyon: &f%version%"
|
||||
- "&bKullanılan Client: &f%brand%"
|
||||
- "&bDikey Hassasiyet: &f%h_sensitivity%%"
|
||||
- "&bYatay Hassasiyet: &f%v_sensitivity%%"
|
||||
- "&bFastMath Ayarı: &f%fast_math%"
|
||||
- "&7======================"
|
||||
help:
|
||||
- "&7======================"
|
||||
- "/grim alerts &f- &7Uyarıları aktif/deaktif eder"
|
||||
- "/grim profile (oyuncu) &f- &7Oyuncu profilini gösterir"
|
||||
- "/grim help &f- &7Bu yardım mesajını gösterir"
|
||||
- "/grim debug <player> &f- &7Geliştirici Debug'ını verir"
|
||||
- "/grim perf &f- &7Geliştirici Performansını verir"
|
||||
- "/grim reload &f- &7Configi yeniden yükler"
|
||||
- "/grim spectate (oyuncu) &f- &7Bir oyuncuyu izlemenizi sağlar"
|
||||
- "/grim verbose &f- &7Arabelleğe almadan tüm uyarıları görmenizi sağlar"
|
||||
- "/grim log (0-255) &f- &7Uyarılar için bir debug logu çıktısı verir"
|
||||
- "&7======================"
|
||||
|
||||
# Translated by Kayera
|
||||
# Have a nice day ;)
|
||||
@@ -17,12 +17,12 @@ upload-log-start: "%prefix% &f上传中...请等待"
|
||||
upload-log-not-found: "%prefix% &c找不到该日志."
|
||||
upload-log-upload-failure: "%prefix% &c上载此日志时出错, 有关详细信息, 请参阅控制台"
|
||||
|
||||
# Valid placeholders:
|
||||
# 变量:
|
||||
# %prefix% - 前缀
|
||||
# %player% - 玩家
|
||||
# %check_name% - 检查名字
|
||||
# %description%
|
||||
# %experimental%
|
||||
# %description% - 检查的介绍
|
||||
# %experimental% - 检查是否是实验性
|
||||
# %vl% - VL值
|
||||
# %verbose% - 检查中的额外信息,例如偏移量,并非所有检查都会添加信息
|
||||
alerts-format: "%prefix% &f%player% &b触发了 &f%check_name%%experimental% &f(x&c%vl%&f) &7%verbose%"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# %check_name% - nome da verificação
|
||||
# %description% - description of the check
|
||||
# %description% - descrição da verificação
|
||||
# %vl% - violações
|
||||
# %verbose% - informação extra
|
||||
# %player% - nome do jogador
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
# %check_name% - Kontrolün ismi
|
||||
# %description% - Kontrolün açıklaması
|
||||
# %vl% - Yapılan ihlaller
|
||||
# %verbose% - Ekstra bilgilendirme
|
||||
# %player% - Oyuncu ismi
|
||||
# [alert] - Uyarılar için bunu kullanın
|
||||
# [webhook] - Discord webhook için bunu kullanın
|
||||
# [proxy] - Proxy'nize bağlı diğer sunuculara uyarı göndermek için bunu kullanın (BungeeCord/Velocity)
|
||||
Punishments:
|
||||
Simulation:
|
||||
# Kaç saniye sonra ihlaller kaldırılsın?
|
||||
remove-violations-after: 300
|
||||
# Bu bölüm, aşağıdaki adlara sahip tüm kontrollerle eşleşecektir,
|
||||
# Aksi takdirde eşleşecek bir denetimi hariç tutmak için, isminin önüne ünlem işareti koyun
|
||||
# Örnek olarak, !BadPacketsN
|
||||
checks:
|
||||
- "Simulation"
|
||||
- "GroundSpoof"
|
||||
- "Timer"
|
||||
- "NoFall"
|
||||
# Eşik:Aralık Komutu
|
||||
#
|
||||
# Örnek: 100 ihlalde "yanlış hareket!" mesajıyla oyuncuyu atmak için, aralık komutu olmadan:
|
||||
# - "100:0 kick %player% Yanlış hareket!"
|
||||
# 0, tam olarak bir kez çalıştırılmasını ifade eder
|
||||
# - "100:50 say %player% Hile yapıyor!"
|
||||
# Kullanıcı 100 işaretine ulaştığında çalışır ve bundan sonra, 100'ün üzerindeki her 50. işarette çalışır
|
||||
commands:
|
||||
- "100:40 [alert]"
|
||||
- "100:100 [webhook]"
|
||||
- "100:100 [proxy]"
|
||||
Knockback:
|
||||
remove-violations-after: 300
|
||||
checks:
|
||||
- "Knockback"
|
||||
- "Explosion"
|
||||
commands:
|
||||
- "5:5 [alert]"
|
||||
- "20:20 [webhook]"
|
||||
- "20:20 [proxy]"
|
||||
Post:
|
||||
remove-violations-after: 300
|
||||
checks:
|
||||
- "Post"
|
||||
commands:
|
||||
- "20:20 [alert]"
|
||||
- "40:40 [webhook]"
|
||||
- "40:40 [proxy]"
|
||||
BadPackets:
|
||||
remove-violations-after: 300
|
||||
checks:
|
||||
- "BadPackets"
|
||||
- "Crash"
|
||||
commands:
|
||||
- "20:20 [alert]"
|
||||
- "40:40 [webhook]"
|
||||
- "40:40 [proxy]"
|
||||
Reach:
|
||||
remove-violations-after: 300
|
||||
checks:
|
||||
- "Reach"
|
||||
commands:
|
||||
- "5:5 [alert]"
|
||||
- "5:5 [webhook]"
|
||||
- "5:5 [proxy]"
|
||||
Misc:
|
||||
remove-violations-after: 300
|
||||
checks:
|
||||
- "EntityControl"
|
||||
- "NoSlow"
|
||||
- "Place"
|
||||
- "Baritone"
|
||||
- "FastBreak"
|
||||
- "TransactionOrder"
|
||||
commands:
|
||||
- "10:5 [alert]"
|
||||
- "20:10 [webhook]"
|
||||
- "20:10 [proxy]"
|
||||
Combat:
|
||||
remove-violations-after: 300
|
||||
checks:
|
||||
- "Killaura"
|
||||
- "Aim"
|
||||
commands:
|
||||
- "20:40 [alert]"
|
||||
# 2.2.10 itibarıyla, AutoClicker denetimleri yoktur ve bu bir yer tutucudur. Grim, gelecekte AutoClicker denetimlerini dahil edecektir.
|
||||
Autoclicker:
|
||||
remove-violations-after: 300
|
||||
checks:
|
||||
- "Autoclicker"
|
||||
commands:
|
||||
- "20:40 [alert]"
|
||||
@@ -1,31 +1,31 @@
|
||||
# %check_name% - 检查名称
|
||||
# %description% - description of the check
|
||||
# %description% - 检查的介绍
|
||||
# %vl% - 违规
|
||||
# %verbose% - 额外信息
|
||||
# %player% - 玩家名字
|
||||
# [alert] - 警告的特殊命令
|
||||
# [webhook] - 警告discord webhook 的特殊命令
|
||||
# [proxy] - special command to alert to other servers connected to your proxy (BungeeCord/Velocity)
|
||||
# [proxy] - 用于使用(BungeeCord/Velocity)服务器时的警报
|
||||
Punishments:
|
||||
Simulation:
|
||||
# 多少秒后重置VL
|
||||
remove-violations-after: 300
|
||||
# This section will match all checks with the name,
|
||||
# To exclude a check that would otherwise be matched, put an exclamation mark in front of the name
|
||||
# For example, !BadPacketsN
|
||||
# 这个部分将会匹配检查的名字
|
||||
# 要关闭掉一个检查就在检查前面加感叹号
|
||||
# 例如, !BadPacketsN
|
||||
checks:
|
||||
- "Simulation"
|
||||
- "GroundSpoof"
|
||||
- "Timer"
|
||||
- "NoFall"
|
||||
# Threshold:Interval Command
|
||||
# 最大vl:下一次执行需要的vl
|
||||
#
|
||||
# 这是个例子, 当到达100VL时为了以 "incorrect movement!" 为理由踢出玩家
|
||||
# commands:
|
||||
# - "100:0 kick %player% incorrect movement!"
|
||||
# 0 means execute exactly once
|
||||
# 后面的数如果使用0就代表只执行一次
|
||||
# - "100:50 say %player% is cheating"
|
||||
# Execute when the user hits flag 100, and after that, every 50th flag after 100
|
||||
# 在100vl后执行say %player% is cheating,之后的每50vl都执行一次say %player% is cheating
|
||||
#
|
||||
commands:
|
||||
- "100:40 [alert]"
|
||||
|
||||
Reference in new issue
Block a user