Compare commits
42
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3059f21ce6 | ||
|
|
b48f898c77 | ||
|
|
6f63743bd8 | ||
|
|
21e15f9b8a | ||
|
|
e505d2b2cd | ||
|
|
c83b374830 | ||
|
|
1bdca2dae5 | ||
|
|
91241dec7d | ||
|
|
651b0bd83e | ||
|
|
7f71f809c0 | ||
|
|
05444e6f56 | ||
|
|
e9e84f5548 | ||
|
|
62cb82de6a | ||
|
|
d10f7619e4 | ||
|
|
16e464719b | ||
|
|
21f22a8446 | ||
|
|
f02d1383c8 | ||
|
|
28be03b978 | ||
|
|
e3ccbe2449 | ||
|
|
5782d356fb | ||
|
|
999d7c7016 | ||
|
|
270db6995c | ||
|
|
bafb169b76 | ||
|
|
5bc0f06500 | ||
|
|
1e244ed37b | ||
|
|
8b8a9b5ce7 | ||
|
|
129549bf2d | ||
|
|
ed7f9d80f8 | ||
|
|
c1054142e0 | ||
|
|
9ee0b82eab | ||
|
|
76f5f81f6a | ||
|
|
0c51152477 | ||
|
|
9b8a0b4969 | ||
|
|
a2528beaf9 | ||
|
|
a3de70d498 | ||
|
|
bb08c78e8a | ||
|
|
4da8ddbd12 | ||
|
|
8f89d3615b | ||
|
|
8a09be435e | ||
|
|
7af6cfbb3b | ||
|
|
ce8aee5b8c | ||
|
|
16bb09aee0 |
No files matched your search
+4
-5
@@ -11,8 +11,8 @@ plugins {
|
||||
group = "ac.grim.grimac"
|
||||
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_17
|
||||
java.targetCompatibility = JavaVersion.VERSION_17
|
||||
java.sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
java.targetCompatibility = JavaVersion.VERSION_1_8
|
||||
|
||||
// Set to false for debug builds
|
||||
// You cannot live reload classes if the jar relocates dependencies
|
||||
@@ -44,9 +44,8 @@ dependencies {
|
||||
implementation("it.unimi.dsi:fastutil:8.5.13")
|
||||
implementation("github.scarsz:configuralize:1.4.0")
|
||||
|
||||
//implementation("com.github.grimanticheat:grimapi:1193c4fa41")
|
||||
// Used for local testing: implementation("ac.grim.grimac:GRIMAPI:1.0")
|
||||
implementation("com.github.grimanticheat:grimapi:fc5634e444")
|
||||
implementation("com.github.grimanticheat:grimapi:1193c4fa41")
|
||||
// Used for local testing: implementation("ac.grim.grimac:grimapi:1.0")
|
||||
|
||||
implementation("org.jetbrains:annotations:24.1.0")
|
||||
compileOnly("org.geysermc.floodgate:api:2.0-SNAPSHOT")
|
||||
|
||||
@@ -19,12 +19,12 @@ public enum GrimAPI {
|
||||
private final TickManager tickManager = new TickManager();
|
||||
private final GrimExternalAPI externalAPI = new GrimExternalAPI(this);
|
||||
private InitManager initManager;
|
||||
private ConfigManagerImpl configManager;
|
||||
private ConfigManager configManager;
|
||||
private JavaPlugin plugin;
|
||||
|
||||
public void load(final JavaPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.configManager = new ConfigManagerImpl();
|
||||
this.configManager = new ConfigManager();
|
||||
initManager = new InitManager();
|
||||
initManager.load();
|
||||
}
|
||||
|
||||
@@ -4,29 +4,22 @@ 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.init.Initable;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
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.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
//This is used for grim's external API. It has its own class just for organization.
|
||||
|
||||
public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, Initable {
|
||||
public class GrimExternalAPI implements GrimAbstractAPI, Initable {
|
||||
|
||||
private final GrimAPI api;
|
||||
|
||||
@@ -48,8 +41,7 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, I
|
||||
@Getter
|
||||
private final Map<String, Function<GrimUser, String>> variableReplacements = new ConcurrentHashMap<>();
|
||||
|
||||
@Getter
|
||||
private final Map<String, String> staticReplacements = new ConcurrentHashMap<>();
|
||||
@Getter private final Map<String, String> staticReplacements = new ConcurrentHashMap<>();
|
||||
|
||||
public String replaceVariables(GrimUser user, String content, boolean colors) {
|
||||
if (colors) content = ChatColor.translateAlternateColorCodes('&', content);
|
||||
@@ -64,20 +56,12 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, I
|
||||
|
||||
@Override
|
||||
public void registerVariable(String string, Function<GrimUser, String> replacement) {
|
||||
if (replacement == null) {
|
||||
variableReplacements.remove(string);
|
||||
} else {
|
||||
variableReplacements.put(string, replacement);
|
||||
}
|
||||
variableReplacements.put(string, replacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerVariable(String variable, String replacement) {
|
||||
if (replacement == null) {
|
||||
staticReplacements.remove(variable);
|
||||
} else {
|
||||
staticReplacements.put(variable, replacement);
|
||||
}
|
||||
staticReplacements.put(variable, replacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,20 +70,34 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, I
|
||||
return description.getVersion();
|
||||
}
|
||||
|
||||
private final Map<String, Function<Object, Object>> functions = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void registerFunction(String key, Function<Object, Object> function) {
|
||||
if (function == null) {
|
||||
functions.remove(key);
|
||||
} else {
|
||||
functions.put(key, function);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<Object, Object> getFunction(String key) {
|
||||
return functions.get(key);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
GrimAPI.INSTANCE.getConfigManager().reload();
|
||||
//Reload checks for all players
|
||||
for (GrimPlayer grimPlayer : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
|
||||
ChannelHelper.runInEventLoop(grimPlayer.user.getChannel(), () -> {
|
||||
grimPlayer.onReload();
|
||||
grimPlayer.updatePermissions();
|
||||
grimPlayer.punishmentManager.reload();
|
||||
for (AbstractCheck value : grimPlayer.checkManager.allChecks.values()) {
|
||||
value.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
//Restart
|
||||
GrimAPI.INSTANCE.getDiscordManager().start();
|
||||
GrimAPI.INSTANCE.getSpectateManager().start();
|
||||
GrimAPI.INSTANCE.getExternalAPI().start();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -107,16 +105,8 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, I
|
||||
return GrimAPI.INSTANCE.getAlertManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigManager getConfigManager() {
|
||||
return configManager;
|
||||
}
|
||||
|
||||
private ConfigManager configManager = null;
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (configManager == null) configManager = GrimAPI.INSTANCE.getConfigManager();
|
||||
variableReplacements.put("%player%", GrimUser::getName);
|
||||
variableReplacements.put("%uuid%", user -> user.getUniqueId().toString());
|
||||
variableReplacements.put("%ping%", user -> user.getTransactionPing() + "");
|
||||
@@ -128,61 +118,4 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, I
|
||||
variableReplacements.put("%version%", GrimUser::getVersionName);
|
||||
variableReplacements.put("%prefix%", user -> ChatColor.translateAlternateColorCodes('&', GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("prefix", "&bGrim &8»")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload(ConfigManager config) {
|
||||
if (config.isLoadedAsync()) {
|
||||
FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(),
|
||||
o -> successfulReload(config));
|
||||
} else {
|
||||
successfulReload(config);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> reloadAsync(ConfigManager config) {
|
||||
if (config.isLoadedAsync()) {
|
||||
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();
|
||||
onReload(config);
|
||||
FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(),
|
||||
o -> Bukkit.getPluginManager().callEvent(new GrimReloadEvent(true)));
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(),
|
||||
o -> Bukkit.getPluginManager().callEvent(new GrimReloadEvent(false)));
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager newConfig) {
|
||||
configManager = newConfig != null ? newConfig : configManager;
|
||||
//Reload checks for all players
|
||||
for (GrimPlayer grimPlayer : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
|
||||
ChannelHelper.runInEventLoop(grimPlayer.user.getChannel(), () -> {
|
||||
grimPlayer.reload(configManager);
|
||||
grimPlayer.updatePermissions();
|
||||
grimPlayer.punishmentManager.reload(configManager);
|
||||
for (AbstractCheck value : grimPlayer.checkManager.allChecks.values()) {
|
||||
value.reload(configManager);
|
||||
}
|
||||
});
|
||||
}
|
||||
//Restart
|
||||
GrimAPI.INSTANCE.getDiscordManager().start();
|
||||
GrimAPI.INSTANCE.getSpectateManager().start();
|
||||
GrimAPI.INSTANCE.getExternalAPI().start();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,12 +2,11 @@ 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;
|
||||
@@ -15,7 +14,7 @@ import org.bukkit.Bukkit;
|
||||
|
||||
// Class from https://github.com/Tecnio/AntiCheatBase/blob/master/src/main/java/me/tecnio/anticheat/check/Check.java
|
||||
@Getter
|
||||
public class Check implements AbstractCheck, ConfigReloadObserver {
|
||||
public class Check implements AbstractCheck {
|
||||
protected final GrimPlayer player;
|
||||
|
||||
public double violations;
|
||||
@@ -54,8 +53,8 @@ public class Check implements AbstractCheck, ConfigReloadObserver {
|
||||
this.experimental = checkData.experimental();
|
||||
this.description = checkData.description();
|
||||
}
|
||||
//
|
||||
reload(GrimAPI.INSTANCE.getConfigManager().getConfig());
|
||||
|
||||
reload();
|
||||
}
|
||||
|
||||
public boolean shouldModifyPackets() {
|
||||
@@ -108,24 +107,23 @@ public class Check implements AbstractCheck, ConfigReloadObserver {
|
||||
violations = Math.max(0, violations - decay);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload(ConfigManager configuration) {
|
||||
decay = configuration.getDoubleElse(configName + ".decay", decay);
|
||||
setbackVL = configuration.getDoubleElse(configName + ".setbackvl", setbackVL);
|
||||
public void reload() {
|
||||
decay = getConfig().getDoubleElse(configName + ".decay", decay);
|
||||
setbackVL = getConfig().getDoubleElse(configName + ".setbackvl", setbackVL);
|
||||
|
||||
if (setbackVL == -1) setbackVL = Double.MAX_VALUE;
|
||||
|
||||
updateExempted();
|
||||
onReload(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
|
||||
}
|
||||
|
||||
public boolean alert(String verbose) {
|
||||
return player.punishmentManager.handleAlert(player, verbose, this);
|
||||
}
|
||||
|
||||
public DynamicConfig getConfig() {
|
||||
return GrimAPI.INSTANCE.getConfigManager().getConfig();
|
||||
}
|
||||
|
||||
public boolean setbackIfAboveSetbackVL() {
|
||||
if (getViolations() > setbackVL) {
|
||||
return player.getSetbackTeleportUtil().executeViolationSetback();
|
||||
@@ -146,10 +144,5 @@ public class Check implements AbstractCheck, ConfigReloadObserver {
|
||||
packetType == PacketType.Play.Client.WINDOW_CONFIRMATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
reload(GrimAPI.INSTANCE.getConfigManager().getConfig());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
@@ -40,6 +39,10 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
return player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) || getBlockDamage(player, pos) < 1;
|
||||
}
|
||||
|
||||
private String formatted(Vector3i vec) {
|
||||
return vec == null ? "null" : vec.x + ", " + vec.y + ", " + vec.z;
|
||||
}
|
||||
|
||||
public void handle(PacketReceiveEvent event, WrapperPlayClientPlayerDigging dig) {
|
||||
if (dig.getAction() == DiggingAction.START_DIGGING) {
|
||||
final Vector3i pos = dig.getBlockPosition();
|
||||
@@ -54,7 +57,7 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
final Vector3i pos = dig.getBlockPosition();
|
||||
|
||||
if (shouldExempt(pos)) {
|
||||
lastCancelledBlock = pos;
|
||||
lastCancelledBlock = null;
|
||||
lastLastBlock = null;
|
||||
lastBlock = null;
|
||||
return;
|
||||
@@ -63,7 +66,7 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
if (!pos.equals(lastBlock)) {
|
||||
// https://github.com/GrimAnticheat/Grim/issues/1512
|
||||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4) || (!lastBlockWasInstantBreak && pos.equals(lastCancelledBlock))) {
|
||||
if (flagAndAlert("action=CANCELLED_DIGGING" + ", last=" + MessageUtil.toUnlabledString(lastBlock) + ", pos=" + MessageUtil.toUnlabledString(pos))) {
|
||||
if (flagAndAlert("action=CANCELLED_DIGGING" + ", last=" + formatted(lastBlock) + ", pos=" + formatted(pos))) {
|
||||
if (shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
@@ -84,7 +87,7 @@ public class BadPacketsZ extends Check implements PacketCheck {
|
||||
|
||||
// when a player looks away from the mined block, they send a cancel, and if they look at it again, they don't send another start. (thanks mojang!)
|
||||
if (!pos.equals(lastCancelledBlock) && (!lastBlockWasInstantBreak || player.getClientVersion().isOlderThan(ClientVersion.V_1_14_4)) && !pos.equals(lastBlock)) {
|
||||
if (flagAndAlert("action=FINISHED_DIGGING" + ", last=" + MessageUtil.toUnlabledString(lastBlock) + ", pos=" + MessageUtil.toUnlabledString(pos))) {
|
||||
if (flagAndAlert("action=FINISHED_DIGGING" + ", last=" + formatted(lastBlock) + ", pos=" + formatted(pos))) {
|
||||
if (shouldModifyPackets()) {
|
||||
event.setCancelled(true);
|
||||
player.onPacketCancel();
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
// 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;
|
||||
@@ -202,9 +201,8 @@ public class Reach extends Check implements PacketCheck {
|
||||
|
||||
// +3 would be 3 + 3 = 6, which is the pre-1.20.5 behaviour, preventing "Missed Hitbox"
|
||||
final double distance = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_ENTITY_INTERACTION_RANGE) + 3;
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
for (Vector lookVec : possibleLookDirs) {
|
||||
for (double eye : possibleEyeHeights) {
|
||||
for (double eye : player.getPossibleEyeHeights()) {
|
||||
Vector eyePos = new Vector(from.getX(), from.getY() + eye, from.getZ());
|
||||
Vector endReachPos = eyePos.clone().add(new Vector(lookVec.getX() * distance, lookVec.getY() * distance, lookVec.getZ() * distance));
|
||||
|
||||
@@ -238,8 +236,9 @@ public class Reach extends Check implements PacketCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
this.cancelImpossibleHits = config.getBooleanElse("Reach.block-impossible-hits", true);
|
||||
this.threshold = config.getDoubleElse("Reach.threshold", 0.0005);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
this.cancelImpossibleHits = getConfig().getBooleanElse("Reach.block-impossible-hits", true);
|
||||
this.threshold = getConfig().getDoubleElse("Reach.threshold", 0.0005);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package ac.grim.grimac.checks.impl.misc;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.type.BlockPlaceCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.update.BlockPlace;
|
||||
@@ -64,9 +63,10 @@ public class GhostBlockMitigation extends BlockPlaceCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
allow = config.getBooleanElse("exploit.allow-building-on-ghostblocks", true);
|
||||
distance = config.getIntElse("exploit.distance-to-check-for-ghostblocks", 2);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
allow = getConfig().getBooleanElse("exploit.allow-building-on-ghostblocks", true);
|
||||
distance = getConfig().getIntElse("exploit.distance-to-check-for-ghostblocks", 2);
|
||||
|
||||
if (distance < 2 || distance > 4) distance = 2;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
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;
|
||||
@@ -36,7 +35,8 @@ public class NegativeTimerCheck extends TimerCheck implements PostPredictionChec
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
clockDrift = (long) (config.getDoubleElse(getConfigName() + ".drift", 1200.0) * 1e6);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
clockDrift = (long) (getConfig().getDoubleElse(getConfigName() + ".drift", 1200.0) * 1e6);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package ac.grim.grimac.checks.impl.movement;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PostPredictionCheck;
|
||||
@@ -52,7 +51,8 @@ public class NoSlowA extends Check implements PostPredictionCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
offsetToFlag = config.getDoubleElse("NoSlowA.threshold", 0.001);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
offsetToFlag = getConfig().getDoubleElse("NoSlowA.threshold", 0.001);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package ac.grim.grimac.checks.impl.movement;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PacketCheck;
|
||||
@@ -116,8 +115,9 @@ public class TimerCheck extends Check implements PacketCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
clockDrift = (long) (config.getDoubleElse(getConfigName() + ".drift", 120.0) * 1e6);
|
||||
limitAbuseOverPing = (long) (config.getDoubleElse(getConfigName() + ".ping-abuse-limit-threshold", 1000));
|
||||
public void reload() {
|
||||
super.reload();
|
||||
clockDrift = (long) (getConfig().getDoubleElse(getConfigName() + ".drift", 120.0) * 1e6);
|
||||
limitAbuseOverPing = (long) (getConfig().getDoubleElse(getConfigName() + ".ping-abuse-limit-threshold", 1000));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package ac.grim.grimac.checks.impl.prediction;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.api.events.CompletePredictionEvent;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
@@ -100,12 +99,14 @@ public class OffsetHandler extends Check implements PostPredictionCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
setbackDecayMultiplier = config.getDoubleElse("Simulation.setback-decay-multiplier", 0.999);
|
||||
threshold = config.getDoubleElse("Simulation.threshold", 0.001);
|
||||
immediateSetbackThreshold = config.getDoubleElse("Simulation.immediate-setback-threshold", 0.1);
|
||||
maxAdvantage = config.getDoubleElse("Simulation.max-advantage", 1);
|
||||
maxCeiling = config.getDoubleElse("Simulation.max-ceiling", 4);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
setbackDecayMultiplier = getConfig().getDoubleElse("Simulation.setback-decay-multiplier", 0.999);
|
||||
threshold = getConfig().getDoubleElse("Simulation.threshold", 0.001);
|
||||
immediateSetbackThreshold = getConfig().getDoubleElse("Simulation.immediate-setback-threshold", 0.1);
|
||||
maxAdvantage = getConfig().getDoubleElse("Simulation.max-advantage", 1);
|
||||
maxCeiling = getConfig().getDoubleElse("Simulation.max-ceiling", 4);
|
||||
|
||||
if (maxAdvantage == -1) maxAdvantage = Double.MAX_VALUE;
|
||||
if (immediateSetbackThreshold == -1) immediateSetbackThreshold = Double.MAX_VALUE;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package ac.grim.grimac.checks.impl.scaffolding;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.BlockPlaceCheck;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
@@ -30,7 +29,8 @@ public class AirLiquidPlace extends BlockPlaceCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
this.cancelVL = config.getIntElse(getConfigName() + ".cancelVL", 0);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
this.cancelVL = getConfig().getIntElse(getConfigName() + ".cancelVL", 0);
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,7 @@ public class FarPlace extends BlockPlaceCheck {
|
||||
if (place.getMaterial() == StateTypes.SCAFFOLDING) return;
|
||||
|
||||
double min = Double.MAX_VALUE;
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
for (double d : possibleEyeHeights) {
|
||||
for (double d : player.getPossibleEyeHeights()) {
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(blockPos);
|
||||
Vector eyes = new Vector(player.x, player.y + d, player.z);
|
||||
Vector best = VectorUtils.cutBoxToVector(eyes, box);
|
||||
|
||||
@@ -1,196 +0,0 @@
|
||||
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;
|
||||
import ac.grim.grimac.utils.anticheat.update.BlockPlace;
|
||||
import ac.grim.grimac.utils.collisions.HitboxData;
|
||||
import ac.grim.grimac.utils.collisions.RaycastData;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.HitData;
|
||||
import ac.grim.grimac.utils.nmsutil.BlockRayTrace;
|
||||
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.StateType;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
@CheckData(name = "LineOfSightPlace")
|
||||
public class LineOfSightPlace extends BlockPlaceCheck {
|
||||
|
||||
private double flagBuffer = 0; // If the player flags once, force them to play legit, or we will cancel the tick before.
|
||||
private boolean ignorePost = false;
|
||||
private boolean useBlockWhitelist;
|
||||
private HashSet<StateType> blockWhitelist;
|
||||
|
||||
public LineOfSightPlace(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockPlace(final BlockPlace place) {
|
||||
if (checkIfShouldSkip(place)) return;
|
||||
|
||||
if (flagBuffer > 0 && !didRayTraceHit(place)) {
|
||||
ignorePost = true;
|
||||
// If the player hit and has flagged this check recently
|
||||
if (flagAndAlert("pre-flying: " + player.compensatedWorld.getWrappedBlockStateAt(place.getPlacedAgainstBlockLocation()).getType()) && shouldModifyPackets() && shouldCancel()) {
|
||||
place.resync(); // Deny the block placement.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use post flying because it has the correct rotation, and can't false easily.
|
||||
@Override
|
||||
public void onPostFlyingBlockPlace(BlockPlace place) {
|
||||
if (checkIfShouldSkip(place)) return;
|
||||
|
||||
// Don't flag twice
|
||||
if (ignorePost) {
|
||||
ignorePost = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Ray trace to try and hit the target block.
|
||||
boolean hit = didRayTraceHit(place);
|
||||
// This can false with rapidly moving yaw in 1.8+ clients
|
||||
if (!hit) {
|
||||
flagBuffer = 1;
|
||||
flagAndAlert("post-flying: " + player.compensatedWorld.getWrappedBlockStateAt(place.getPlacedAgainstBlockLocation()).getType());
|
||||
} else {
|
||||
flagBuffer = Math.max(0, flagBuffer - 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkIfShouldSkip(BlockPlace place) {
|
||||
StateType targetBlockStateType = player.compensatedWorld.getWrappedBlockStateAt(place.getPlacedAgainstBlockLocation()).getType();
|
||||
if (player.gamemode == GameMode.SPECTATOR) return true; // A waste to check creative mode players
|
||||
if (targetBlockStateType == StateTypes.REDSTONE_WIRE) return true; // Redstone too buggy
|
||||
if (player.compensatedWorld.isNearHardEntity(player.boundingBox.copy().expand(4))) return true; // Shulkers and Pistons are too buggy
|
||||
|
||||
if (useBlockWhitelist) {
|
||||
return !isBlockTypeWhitelisted(targetBlockStateType);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean didRayTraceHit(BlockPlace place) {
|
||||
double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
|
||||
// Start checking if player is in the block
|
||||
double minEyeHeight = Double.MAX_VALUE;
|
||||
double maxEyeHeight = Double.MIN_VALUE;
|
||||
for (double height : possibleEyeHeights) {
|
||||
minEyeHeight = Math.min(minEyeHeight, height);
|
||||
maxEyeHeight = Math.max(maxEyeHeight, height);
|
||||
}
|
||||
|
||||
double movementThreshold = player.getMovementThreshold();
|
||||
|
||||
SimpleCollisionBox eyePositions = new SimpleCollisionBox(player.x, player.y + minEyeHeight, player.z, player.x, player.y + maxEyeHeight, player.z);
|
||||
eyePositions.expand(movementThreshold);
|
||||
|
||||
int[] interactBlockVec = new int[]{place.blockPosition.x, place.blockPosition.y, place.blockPosition.z};
|
||||
BlockFace expectedBlockFace = place.getDirection();
|
||||
|
||||
// If the player is inside a block, then they can ray trace through the block and hit the other side of the block
|
||||
// This may potentially be exploitable as a minor bypass
|
||||
if (eyePositions.isIntersected(new SimpleCollisionBox(interactBlockVec[0], interactBlockVec[1], interactBlockVec[2]))) {
|
||||
return true;
|
||||
}
|
||||
// End checking if the player is in the block
|
||||
double[][] possibleLookDirs;
|
||||
// 1.9+ players could be a tick behind because we don't get skipped ticks
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)) {
|
||||
possibleLookDirs = new double[][]{
|
||||
{player.xRot, player.yRot},
|
||||
{player.lastXRot, player.lastYRot},
|
||||
{player.lastXRot, player.yRot}
|
||||
};
|
||||
} else if (player.getClientVersion().isOlderThan(ClientVersion.V_1_8)) {
|
||||
// 1.7 players do not have any of these issues! They are always on the latest look vector
|
||||
possibleLookDirs = new double[][]{{player.xRot, player.yRot}};
|
||||
} else {
|
||||
possibleLookDirs = new double[][]{
|
||||
{player.xRot, player.yRot},
|
||||
{player.lastXRot, player.yRot}
|
||||
};
|
||||
}
|
||||
|
||||
// We do not need to add 0.03/0.0002 to maxDistance to ensure our raytrace hits blocks
|
||||
// Since we expand the hitboxes of the expectedTargetBlock by 0.03/0.002 already later
|
||||
double maxDistance = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE);
|
||||
|
||||
// Define possible offsets
|
||||
// TODO, vectorize this with SIMD or AVX for performance
|
||||
double[][] offsets = {
|
||||
{0, 0, 0},
|
||||
{movementThreshold, 0, 0},
|
||||
{-movementThreshold, 0, 0},
|
||||
{0, movementThreshold, 0},
|
||||
{0, -movementThreshold, 0},
|
||||
{0, 0, movementThreshold},
|
||||
{0, 0, -movementThreshold}
|
||||
};
|
||||
|
||||
double[] eyePosition = new double[3];
|
||||
double[] eyeLookDir = new double[3];
|
||||
|
||||
for (double eyeHeight : possibleEyeHeights) {
|
||||
for (double[] lookDir : possibleLookDirs) {
|
||||
for (double[] offset : offsets) {
|
||||
eyePosition[0] = player.x + offset[0];
|
||||
eyePosition[1] = player.y + eyeHeight + offset[1];
|
||||
eyePosition[2] = player.z + offset[2];
|
||||
|
||||
calculateDirection(eyeLookDir, lookDir[0], lookDir[1]);
|
||||
|
||||
if (getTargetBlock(eyePosition, eyeLookDir, maxDistance, interactBlockVec, expectedBlockFace)) {
|
||||
return true; // If any possible face matches the client-side placement, assume it's legitimate
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false; // No matching face found
|
||||
}
|
||||
|
||||
// Helper method to calculate direction (replace the Ray class method)
|
||||
private void calculateDirection(double[] result, double xRot, double yRot) {
|
||||
float rotX = (float) Math.toRadians(xRot);
|
||||
float rotY = (float) Math.toRadians(yRot);
|
||||
result[1] = -player.trigHandler.sin(rotY);
|
||||
double xz = player.trigHandler.cos(rotY);
|
||||
result[0] = -xz * player.trigHandler.sin(rotX);
|
||||
result[2] = xz * player.trigHandler.cos(rotX);
|
||||
}
|
||||
|
||||
private boolean getTargetBlock(double[] eyePos, double[] eyeDir, double maxDistance, int[] targetBlockVec, BlockFace expectedBlockFace) {
|
||||
HitData hitData = BlockRayTrace.getNearestReachHitResult(player, eyePos, eyeDir, maxDistance, maxDistance, targetBlockVec, false);
|
||||
|
||||
|
||||
// we check for hitdata != null because of being in expanded hitbox, or there was no result, do we still need this?
|
||||
return hitData != null && new Vector3i(targetBlockVec[0], targetBlockVec[1], targetBlockVec[2]).equals(hitData.getPosition()) && hitData.getClosestDirection() == expectedBlockFace;
|
||||
}
|
||||
|
||||
private boolean isBlockTypeWhitelisted(StateType type) {
|
||||
return blockWhitelist.contains(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
useBlockWhitelist = config.getBooleanElse("LineOfSightPlace.use-block-whitelist", false);
|
||||
blockWhitelist = new HashSet<>();
|
||||
List<String> blocks = config.getStringList("LineOfSightPlace.block-whitelist");
|
||||
for (String block : blocks) {
|
||||
blockWhitelist.add(StateTypes.getByName(block));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public class MultiPlace extends BlockPlaceCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (player.getClientVersion().isNewerThan(ClientVersion.V_1_8) && !player.skippedTickInActualMovement && predictionComplete.isChecked()) {
|
||||
if (player.getClientVersion().isNewerThan(ClientVersion.V_1_8) && !player.skippedTickInActualMovement) {
|
||||
for (String verbose : flags) {
|
||||
flagAndAlert(verbose);
|
||||
}
|
||||
|
||||
@@ -28,13 +28,8 @@ public class PositionPlace extends BlockPlaceCheck {
|
||||
// Each position represents the best case scenario to have clicked
|
||||
//
|
||||
// We will now calculate the most optimal position for the player's head to be in
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
double minEyeHeight = Double.MAX_VALUE;
|
||||
double maxEyeHeight = Double.MIN_VALUE;
|
||||
for (double height : possibleEyeHeights) {
|
||||
minEyeHeight = Math.min(minEyeHeight, height);
|
||||
maxEyeHeight = Math.max(maxEyeHeight, height);
|
||||
}
|
||||
double minEyeHeight = Collections.min(player.getPossibleEyeHeights());
|
||||
double maxEyeHeight = Collections.max(player.getPossibleEyeHeights());
|
||||
// I love the idle packet, why did you remove it mojang :(
|
||||
// Don't give 0.03 lenience if the player is a 1.8 player and we know they couldn't have 0.03'd because idle packet
|
||||
double movementThreshold = !player.packetStateData.didLastMovementIncludePosition || player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) ? player.getMovementThreshold() : 0;
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
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.update.BlockPlace;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.Pair;
|
||||
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;
|
||||
import com.github.retrooper.packetevents.util.Vector3f;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@CheckData(name = "RotationPlace")
|
||||
public class RotationPlace extends BlockPlaceCheck {
|
||||
double flagBuffer = 0; // If the player flags once, force them to play legit, or we will cancel the tick before.
|
||||
boolean ignorePost = false;
|
||||
|
||||
public RotationPlace(GrimPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@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
|
||||
if (flagAndAlert("pre-flying") && shouldModifyPackets() && shouldCancel()) {
|
||||
place.resync(); // Deny the block placement.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use post flying because it has the correct rotation, and can't false easily.
|
||||
@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) {
|
||||
ignorePost = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Ray trace to try and hit the target block.
|
||||
boolean hit = didRayTraceHit(place);
|
||||
// This can false with rapidly moving yaw in 1.8+ clients
|
||||
if (!hit) {
|
||||
flagBuffer = 1;
|
||||
flagAndAlert("post-flying");
|
||||
} else {
|
||||
flagBuffer = Math.max(0, flagBuffer - 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean didRayTraceHit(BlockPlace place) {
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(place.getPlacedAgainstBlockLocation());
|
||||
|
||||
List<Vector3f> possibleLookDirs = new ArrayList<>(Arrays.asList(
|
||||
new Vector3f(player.xRot, player.yRot, 0),
|
||||
new Vector3f(player.lastXRot, player.yRot, 0)
|
||||
));
|
||||
|
||||
// Start checking if player is in the block
|
||||
double minEyeHeight = Collections.min(player.getPossibleEyeHeights());
|
||||
double maxEyeHeight = Collections.max(player.getPossibleEyeHeights());
|
||||
|
||||
SimpleCollisionBox eyePositions = new SimpleCollisionBox(player.x, player.y + minEyeHeight, player.z, player.x, player.y + maxEyeHeight, player.z);
|
||||
eyePositions.expand(player.getMovementThreshold());
|
||||
|
||||
// If the player is inside a block, then they can ray trace through the block and hit the other side of the block
|
||||
if (eyePositions.isIntersected(box)) {
|
||||
return true;
|
||||
}
|
||||
// End checking if the player is in the block
|
||||
|
||||
// 1.9+ players could be a tick behind because we don't get skipped ticks
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)) {
|
||||
possibleLookDirs.add(new Vector3f(player.lastXRot, player.lastYRot, 0));
|
||||
}
|
||||
|
||||
// 1.7 players do not have any of these issues! They are always on the latest look vector
|
||||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_8)) {
|
||||
possibleLookDirs = Collections.singletonList(new Vector3f(player.xRot, player.yRot, 0));
|
||||
}
|
||||
|
||||
final double distance = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE);
|
||||
for (double d : player.getPossibleEyeHeights()) {
|
||||
for (Vector3f lookDir : possibleLookDirs) {
|
||||
// x, y, z are correct for the block placement even after post tick because of code elsewhere
|
||||
Vector3d starting = new Vector3d(player.x, player.y + d, player.z);
|
||||
// xRot and yRot are a tick behind
|
||||
Ray trace = new Ray(player, starting.getX(), starting.getY(), starting.getZ(), lookDir.getX(), lookDir.getY());
|
||||
Pair<Vector, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
|
||||
if (intercept.getFirst() != null) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package ac.grim.grimac.checks.impl.velocity;
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PostPredictionCheck;
|
||||
@@ -19,6 +18,7 @@ import com.github.retrooper.packetevents.util.Vector3f;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerExplosion;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -256,10 +256,12 @@ public class ExplosionHandler extends Check implements PostPredictionCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
offsetToFlag = config.getDoubleElse("Explosion.threshold", 0.00001);
|
||||
setbackVL = config.getDoubleElse("Explosion.setbackvl", 10);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
|
||||
offsetToFlag = getConfig().getDoubleElse("Explosion.threshold", 0.00001);
|
||||
setbackVL = getConfig().getDoubleElse("Explosion.setbackvl", 10);
|
||||
|
||||
if (setbackVL == -1) setbackVL = Double.MAX_VALUE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package ac.grim.grimac.checks.impl.velocity;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.checks.CheckData;
|
||||
import ac.grim.grimac.checks.type.PostPredictionCheck;
|
||||
@@ -241,14 +240,15 @@ public class KnockbackHandler extends Check implements PostPredictionCheck {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
offsetToFlag = config.getDoubleElse("Knockback.threshold", 0.001);
|
||||
maxAdv = config.getDoubleElse("Knockback.max-advantage", 1);
|
||||
immediate = config.getDoubleElse("Knockback.immediate-setback-threshold", 0.1);
|
||||
multiplier = config.getDoubleElse("Knockback.setback-decay-multiplier", 0.999);
|
||||
ceiling = config.getDoubleElse("Knockback.max-ceiling", 4);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
offsetToFlag = getConfig().getDoubleElse("Knockback.threshold", 0.001);
|
||||
maxAdv = getConfig().getDoubleElse("Knockback.max-advantage", 1);
|
||||
immediate = getConfig().getDoubleElse("Knockback.immediate-setback-threshold", 0.1);
|
||||
multiplier = getConfig().getDoubleElse("Knockback.setback-decay-multiplier", 0.999);
|
||||
ceiling = getConfig().getDoubleElse("Knockback.max-ceiling", 4);
|
||||
|
||||
if (maxAdv < 0) maxAdv = Double.MAX_VALUE;
|
||||
if (immediate < 0) immediate = Double.MAX_VALUE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
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;
|
||||
@@ -34,8 +33,9 @@ public class BlockPlaceCheck extends Check implements RotationCheck, PostPredict
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload(ConfigManager config) {
|
||||
this.cancelVL = config.getIntElse(getConfigName() + ".cancelVL", 5);
|
||||
public void reload() {
|
||||
super.reload();
|
||||
this.cancelVL = getConfig().getIntElse(getConfigName() + ".cancelVL", 5);
|
||||
}
|
||||
|
||||
protected boolean shouldCancel() {
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package ac.grim.grimac.commands;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.checks.Check;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
import co.aikar.commands.BaseCommand;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import com.github.retrooper.packetevents.netty.channel.ChannelHelper;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
@CommandAlias("grim|grimac")
|
||||
@@ -14,15 +18,14 @@ public class GrimReload extends BaseCommand {
|
||||
@CommandPermission("grim.reload")
|
||||
public void onReload(CommandSender sender) {
|
||||
//reload config
|
||||
sender.sendMessage(MessageUtil.format("%prefix% &7Reloading config..."));
|
||||
GrimAPI.INSTANCE.getExternalAPI().reloadAsync().exceptionally(throwable -> false)
|
||||
.thenAccept(bool -> {
|
||||
if (bool) {
|
||||
sender.sendMessage(MessageUtil.format("%prefix% &fConfig has been reloaded."));
|
||||
} else {
|
||||
sender.sendMessage(MessageUtil.format("%prefix% &cFailed to reload config."));
|
||||
}
|
||||
});
|
||||
try {
|
||||
GrimAPI.INSTANCE.getExternalAPI().reload();
|
||||
} catch (RuntimeException e) {
|
||||
sender.sendMessage(ChatColor.RED + e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
sender.sendMessage(MessageUtil.format("%prefix% &fConfig has been reloaded."));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,9 +8,13 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.anticheat.update.*;
|
||||
import ac.grim.grimac.utils.blockplace.BlockPlaceResult;
|
||||
import ac.grim.grimac.utils.blockplace.ConsumesBlockPlace;
|
||||
import ac.grim.grimac.utils.collisions.HitboxData;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.CollisionBox;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.*;
|
||||
import ac.grim.grimac.utils.inventory.Inventory;
|
||||
import ac.grim.grimac.utils.latency.CompensatedWorld;
|
||||
import ac.grim.grimac.utils.math.GrimMath;
|
||||
import ac.grim.grimac.utils.math.VectorUtils;
|
||||
import ac.grim.grimac.utils.nmsutil.*;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
@@ -20,6 +24,7 @@ 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.ConnectionState;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
@@ -31,7 +36,6 @@ import com.github.retrooper.packetevents.protocol.player.InteractionHand;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.protocol.world.Location;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.defaulttags.BlockTags;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateValue;
|
||||
@@ -43,6 +47,11 @@ import com.github.retrooper.packetevents.wrapper.play.client.*;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerAcknowledgeBlockChanges;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetSlot;
|
||||
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class CheckManagerListener extends PacketListenerAbstract {
|
||||
|
||||
@@ -50,8 +59,79 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
super(PacketListenerPriority.LOW);
|
||||
}
|
||||
|
||||
// Copied from MCP...
|
||||
// Returns null if there isn't anything.
|
||||
//
|
||||
// I do have to admit that I'm starting to like bifunctions/new java 8 things more than I originally did.
|
||||
// although I still don't understand Mojang's obsession with streams in some of the hottest methods... that kills performance
|
||||
public static HitData traverseBlocks(GrimPlayer player, Vector3d start, Vector3d end, BiFunction<WrappedBlockState, Vector3i, HitData> predicate) {
|
||||
// I guess go back by the collision epsilon?
|
||||
double endX = GrimMath.lerp(-1.0E-7D, end.x, start.x);
|
||||
double endY = GrimMath.lerp(-1.0E-7D, end.y, start.y);
|
||||
double endZ = GrimMath.lerp(-1.0E-7D, end.z, start.z);
|
||||
double startX = GrimMath.lerp(-1.0E-7D, start.x, end.x);
|
||||
double startY = GrimMath.lerp(-1.0E-7D, start.y, end.y);
|
||||
double startZ = GrimMath.lerp(-1.0E-7D, start.z, end.z);
|
||||
int floorStartX = GrimMath.floor(startX);
|
||||
int floorStartY = GrimMath.floor(startY);
|
||||
int floorStartZ = GrimMath.floor(startZ);
|
||||
|
||||
|
||||
if (start.equals(end)) return null;
|
||||
|
||||
WrappedBlockState state = player.compensatedWorld.getWrappedBlockStateAt(floorStartX, floorStartY, floorStartZ);
|
||||
HitData apply = predicate.apply(state, new Vector3i(floorStartX, floorStartY, floorStartZ));
|
||||
|
||||
if (apply != null) {
|
||||
return apply;
|
||||
}
|
||||
|
||||
double xDiff = endX - startX;
|
||||
double yDiff = endY - startY;
|
||||
double zDiff = endZ - startZ;
|
||||
double xSign = Math.signum(xDiff);
|
||||
double ySign = Math.signum(yDiff);
|
||||
double zSign = Math.signum(zDiff);
|
||||
|
||||
double posXInverse = xSign == 0 ? Double.MAX_VALUE : xSign / xDiff;
|
||||
double posYInverse = ySign == 0 ? Double.MAX_VALUE : ySign / yDiff;
|
||||
double posZInverse = zSign == 0 ? Double.MAX_VALUE : zSign / zDiff;
|
||||
|
||||
double d12 = posXInverse * (xSign > 0 ? 1.0D - GrimMath.frac(startX) : GrimMath.frac(startX));
|
||||
double d13 = posYInverse * (ySign > 0 ? 1.0D - GrimMath.frac(startY) : GrimMath.frac(startY));
|
||||
double d14 = posZInverse * (zSign > 0 ? 1.0D - GrimMath.frac(startZ) : GrimMath.frac(startZ));
|
||||
|
||||
// Can't figure out what this code does currently
|
||||
while (d12 <= 1.0D || d13 <= 1.0D || d14 <= 1.0D) {
|
||||
if (d12 < d13) {
|
||||
if (d12 < d14) {
|
||||
floorStartX += xSign;
|
||||
d12 += posXInverse;
|
||||
} else {
|
||||
floorStartZ += zSign;
|
||||
d14 += posZInverse;
|
||||
}
|
||||
} else if (d13 < d14) {
|
||||
floorStartY += ySign;
|
||||
d13 += posYInverse;
|
||||
} else {
|
||||
floorStartZ += zSign;
|
||||
d14 += posZInverse;
|
||||
}
|
||||
|
||||
state = player.compensatedWorld.getWrappedBlockStateAt(floorStartX, floorStartY, floorStartZ);
|
||||
apply = predicate.apply(state, new Vector3i(floorStartX, floorStartY, floorStartZ));
|
||||
|
||||
if (apply != null) {
|
||||
return apply;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void placeWaterLavaSnowBucket(GrimPlayer player, ItemStack held, StateType toPlace, InteractionHand hand) {
|
||||
HitData data = BlockRayTrace.getNearestHitResult(player, StateTypes.AIR, false);
|
||||
HitData data = getNearestHitResult(player, StateTypes.AIR, false);
|
||||
if (data != null) {
|
||||
BlockPlace blockPlace = new BlockPlace(player, hand, data.getPosition(), data.getClosestDirection().getFaceValue(), data.getClosestDirection(), held, data);
|
||||
|
||||
@@ -188,7 +268,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
// The offhand is unable to interact with blocks like this... try to stop some desync points before they happen
|
||||
if ((!player.isSneaking || onlyAir) && place.getHand() == InteractionHand.MAIN_HAND) {
|
||||
Vector3i blockPosition = place.getBlockPosition();
|
||||
BlockPlace blockPlace = new BlockPlace(player, place.getHand(), blockPosition, place.getFaceId(), place.getFace(), placedWith, BlockRayTrace.getNearestHitResult(player, null, true));
|
||||
BlockPlace blockPlace = new BlockPlace(player, place.getHand(), blockPosition, place.getFaceId(), place.getFace(), placedWith, getNearestHitResult(player, null, true));
|
||||
|
||||
// Right-clicking a trapdoor/door/etc.
|
||||
StateType placedAgainst = blockPlace.getPlacedAgainstMaterial();
|
||||
@@ -228,7 +308,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
placedWith = player.getInventory().getOffHand();
|
||||
}
|
||||
|
||||
BlockPlace blockPlace = new BlockPlace(player, place.getHand(), blockPosition, place.getFaceId(), face, placedWith, BlockRayTrace.getNearestHitResult(player, null, true));
|
||||
BlockPlace blockPlace = new BlockPlace(player, place.getHand(), blockPosition, place.getFaceId(), face, placedWith, getNearestHitResult(player, null, true));
|
||||
// At this point, it is too late to cancel, so we can only flag, and cancel subsequent block places more aggressively
|
||||
if (!player.compensatedEntities.getSelf().inVehicle()) {
|
||||
player.checkManager.onPostFlyingBlockPlace(blockPlace);
|
||||
@@ -428,7 +508,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
player.placeUseItemPackets.add(new BlockPlaceSnapshot(packet, player.isSneaking));
|
||||
} else {
|
||||
// Anti-air place
|
||||
BlockPlace blockPlace = new BlockPlace(player, packet.getHand(), packet.getBlockPosition(), packet.getFaceId(), packet.getFace(), placedWith, BlockRayTrace.getNearestHitResult(player, null, true));
|
||||
BlockPlace blockPlace = new BlockPlace(player, packet.getHand(), packet.getBlockPosition(), packet.getFaceId(), packet.getFace(), placedWith, getNearestHitResult(player, null, true));
|
||||
blockPlace.setCursor(packet.getCursorPosition());
|
||||
|
||||
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_11) && player.getClientVersion().isOlderThan(ClientVersion.V_1_11)) {
|
||||
@@ -502,7 +582,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
}
|
||||
|
||||
private static void placeBucket(GrimPlayer player, InteractionHand hand) {
|
||||
HitData data = BlockRayTrace.getNearestHitResult(player, null, true);
|
||||
HitData data = getNearestHitResult(player, null, true);
|
||||
|
||||
if (data != null) {
|
||||
BlockPlace blockPlace = new BlockPlace(player, hand, data.getPosition(), data.getClosestDirection().getFaceValue(), data.getClosestDirection(), ItemStack.EMPTY, data);
|
||||
@@ -668,7 +748,7 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
}
|
||||
|
||||
private static void placeLilypad(GrimPlayer player, InteractionHand hand) {
|
||||
HitData data = BlockRayTrace.getNearestHitResult(player, null, true);
|
||||
HitData data = getNearestHitResult(player, null, true);
|
||||
|
||||
if (data != null) {
|
||||
// A lilypad cannot replace a fluid
|
||||
@@ -698,6 +778,56 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
}
|
||||
}
|
||||
|
||||
private static HitData getNearestHitResult(GrimPlayer player, StateType heldItem, boolean sourcesHaveHitbox) {
|
||||
Vector3d startingPos = new Vector3d(player.x, player.y + player.getEyeHeight(), player.z);
|
||||
Vector startingVec = new Vector(startingPos.getX(), startingPos.getY(), startingPos.getZ());
|
||||
Ray trace = new Ray(player, startingPos.getX(), startingPos.getY(), startingPos.getZ(), player.xRot, player.yRot);
|
||||
final double distance = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE);
|
||||
Vector endVec = trace.getPointAtDistance(distance);
|
||||
Vector3d endPos = new Vector3d(endVec.getX(), endVec.getY(), endVec.getZ());
|
||||
|
||||
return traverseBlocks(player, startingPos, endPos, (block, vector3i) -> {
|
||||
CollisionBox data = HitboxData.getBlockHitbox(player, heldItem, player.getClientVersion(), block, vector3i.getX(), vector3i.getY(), vector3i.getZ());
|
||||
List<SimpleCollisionBox> boxes = new ArrayList<>();
|
||||
data.downCast(boxes);
|
||||
|
||||
double bestHitResult = Double.MAX_VALUE;
|
||||
Vector bestHitLoc = null;
|
||||
BlockFace bestFace = null;
|
||||
|
||||
for (SimpleCollisionBox box : boxes) {
|
||||
Pair<Vector, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
if (intercept.getFirst() == null) continue; // No intercept
|
||||
|
||||
Vector hitLoc = intercept.getFirst();
|
||||
|
||||
if (hitLoc.distanceSquared(startingVec) < bestHitResult) {
|
||||
bestHitResult = hitLoc.distanceSquared(startingVec);
|
||||
bestHitLoc = hitLoc;
|
||||
bestFace = intercept.getSecond();
|
||||
}
|
||||
}
|
||||
if (bestHitLoc != null) {
|
||||
return new HitData(vector3i, bestHitLoc, bestFace, block);
|
||||
}
|
||||
|
||||
if (sourcesHaveHitbox &&
|
||||
(player.compensatedWorld.isWaterSourceBlock(vector3i.getX(), vector3i.getY(), vector3i.getZ())
|
||||
|| player.compensatedWorld.getLavaFluidLevelAt(vector3i.getX(), vector3i.getY(), vector3i.getZ()) == (8 / 9f))) {
|
||||
double waterHeight = player.compensatedWorld.getFluidLevelAt(vector3i.getX(), vector3i.getY(), vector3i.getZ());
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(vector3i.getX(), vector3i.getY(), vector3i.getZ(), vector3i.getX() + 1, vector3i.getY() + waterHeight, vector3i.getZ() + 1);
|
||||
|
||||
Pair<Vector, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
|
||||
if (intercept.getFirst() != null) {
|
||||
return new HitData(vector3i, intercept.getFirst(), intercept.getSecond(), block);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(PacketSendEvent event) {
|
||||
if (event.getConnectionState() != ConnectionState.PLAY) return;
|
||||
@@ -706,8 +836,4 @@ public class CheckManagerListener extends PacketListenerAbstract {
|
||||
|
||||
player.checkManager.onPacketSend(event);
|
||||
}
|
||||
|
||||
private static boolean isFence(StateType state) {
|
||||
return BlockTags.FENCES.contains(state);
|
||||
}
|
||||
}
|
||||
@@ -143,8 +143,8 @@ public class CheckManager {
|
||||
.put(FarPlace.class, new FarPlace(player))
|
||||
.put(FabricatedPlace.class, new FabricatedPlace(player))
|
||||
.put(PositionPlace.class, new PositionPlace(player))
|
||||
.put(RotationPlace.class, new RotationPlace(player))
|
||||
.put(DuplicateRotPlace.class, new DuplicateRotPlace(player))
|
||||
.put(LineOfSightPlace.class, new LineOfSightPlace(player))
|
||||
.put(GhostBlockMitigation.class, new GhostBlockMitigation(player))
|
||||
.build();
|
||||
|
||||
|
||||
+13
-55
@@ -2,9 +2,8 @@ package ac.grim.grimac.manager;
|
||||
|
||||
import ac.grim.grimac.GrimAC;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.common.BasicReloadable;
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import ac.grim.grimac.utils.math.GrimMath;
|
||||
import github.scarsz.configuralize.DynamicConfig;
|
||||
import github.scarsz.configuralize.Language;
|
||||
import lombok.Getter;
|
||||
@@ -17,13 +16,8 @@ import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
public class ConfigManagerImpl implements ConfigManager, BasicReloadable {
|
||||
|
||||
public ConfigManager getConfig() {
|
||||
if (GrimAPI.INSTANCE.getInitManager().isStarted()) return GrimAPI.INSTANCE.getExternalAPI().getConfigManager();
|
||||
return this;
|
||||
}
|
||||
|
||||
public class ConfigManager {
|
||||
@Getter
|
||||
private final DynamicConfig config;
|
||||
@Getter
|
||||
private final File configFile = new File(GrimAPI.INSTANCE.getPlugin().getDataFolder(), "config.yml");
|
||||
@@ -34,6 +28,8 @@ public class ConfigManagerImpl implements ConfigManager, BasicReloadable {
|
||||
@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
|
||||
@@ -41,8 +37,9 @@ public class ConfigManagerImpl implements ConfigManager, BasicReloadable {
|
||||
|
||||
private final List<Pattern> ignoredClientPatterns = new ArrayList<>();
|
||||
|
||||
public ConfigManagerImpl() {
|
||||
public ConfigManager() {
|
||||
upgrade();
|
||||
|
||||
// load config
|
||||
GrimAPI.INSTANCE.getPlugin().getDataFolder().mkdirs();
|
||||
config = new DynamicConfig();
|
||||
@@ -54,7 +51,6 @@ public class ConfigManagerImpl implements ConfigManager, BasicReloadable {
|
||||
reload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
String languageCode = System.getProperty("user.language").toUpperCase();
|
||||
|
||||
@@ -83,9 +79,12 @@ public class ConfigManagerImpl implements ConfigManager, BasicReloadable {
|
||||
throw new RuntimeException("Failed to load config", e);
|
||||
}
|
||||
|
||||
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.");
|
||||
final int configuredMaxTransactionTime = config.getIntElse("max-transaction-time", 60);
|
||||
maxPingTransaction = (int) GrimMath.clamp(configuredMaxTransactionTime, 1, 180);
|
||||
if (maxPingTransaction != configuredMaxTransactionTime) {
|
||||
LogUtil.warn("Detected invalid max-transaction-time! This setting is clamped between 1 and 180 to prevent issues. " +
|
||||
"Changed: " + configuredMaxTransactionTime + " -> " + maxPingTransaction);
|
||||
LogUtil.warn("Attempting to disable or set this too high can result in memory usage issues.");
|
||||
}
|
||||
|
||||
ignoredClientPatterns.clear();
|
||||
@@ -327,45 +326,4 @@ public class ConfigManagerImpl implements ConfigManager, BasicReloadable {
|
||||
);
|
||||
Files.write(config.toPath(), configString.getBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStringElse(String key, String otherwise) {
|
||||
return config.getStringElse(key, otherwise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStringList(String key) {
|
||||
return config.getStringList(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStringListElse(String key, List<String> otherwise) {
|
||||
return config.getStringListElse(key, otherwise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntElse(String key, int other) {
|
||||
return config.getIntElse(key, other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLongElse(String key, long otherwise) {
|
||||
return config.getLongElse(key, otherwise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDoubleElse(String key, double otherwise) {
|
||||
return config.getDoubleElse(key, otherwise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBooleanElse(String key, boolean otherwise) {
|
||||
return config.getBooleanElse(key, otherwise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T get(String key) {
|
||||
return config.get(key);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,16 +8,11 @@ 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 lombok.Getter;
|
||||
|
||||
public class InitManager {
|
||||
private final ClassToInstanceMap<Initable> initializersOnLoad;
|
||||
private final ClassToInstanceMap<Initable> initializersOnStart;
|
||||
private final ClassToInstanceMap<Initable> initializersOnStop;
|
||||
|
||||
@Getter private boolean loaded = false;
|
||||
@Getter private boolean started = false;
|
||||
@Getter private boolean stopped = false;
|
||||
ClassToInstanceMap<Initable> initializersOnLoad;
|
||||
ClassToInstanceMap<Initable> initializersOnStart;
|
||||
ClassToInstanceMap<Initable> initializersOnStop;
|
||||
|
||||
public InitManager() {
|
||||
initializersOnLoad = new ImmutableClassToInstanceMap.Builder<Initable>()
|
||||
@@ -25,7 +20,6 @@ public class InitManager {
|
||||
.build();
|
||||
|
||||
initializersOnStart = new ImmutableClassToInstanceMap.Builder<Initable>()
|
||||
.put(GrimExternalAPI.class, GrimAPI.INSTANCE.getExternalAPI())
|
||||
.put(ExemptOnlinePlayers.class, new ExemptOnlinePlayers())
|
||||
.put(EventManager.class, new EventManager())
|
||||
.put(PacketManager.class, new PacketManager())
|
||||
@@ -37,6 +31,7 @@ public class InitManager {
|
||||
.put(PacketLimiter.class, new PacketLimiter())
|
||||
.put(DiscordManager.class, GrimAPI.INSTANCE.getDiscordManager())
|
||||
.put(SpectateManager.class, GrimAPI.INSTANCE.getSpectateManager())
|
||||
.put(GrimExternalAPI.class, GrimAPI.INSTANCE.getExternalAPI())
|
||||
.put(JavaVersion.class, new JavaVersion())
|
||||
.build();
|
||||
|
||||
@@ -49,20 +44,17 @@ public class InitManager {
|
||||
for (Initable initable : initializersOnLoad.values()) {
|
||||
initable.start();
|
||||
}
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
for (Initable initable : initializersOnStart.values()) {
|
||||
initable.start();
|
||||
}
|
||||
started = true;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
for (Initable initable : initializersOnStop.values()) {
|
||||
initable.start();
|
||||
}
|
||||
stopped = true;
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,13 @@ 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;
|
||||
@@ -18,18 +17,18 @@ import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class PunishmentManager implements ConfigReloadable {
|
||||
public class PunishmentManager {
|
||||
GrimPlayer player;
|
||||
List<PunishGroup> groups = new ArrayList<>();
|
||||
String experimentalSymbol = "*";
|
||||
|
||||
public PunishmentManager(GrimPlayer player) {
|
||||
this.player = player;
|
||||
reload(GrimAPI.INSTANCE.getConfigManager().getConfig());
|
||||
reload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload(ConfigManager config) {
|
||||
public void reload() {
|
||||
DynamicConfig config = GrimAPI.INSTANCE.getConfigManager().getConfig();
|
||||
List<String> punish = config.getStringListElse("Punishments", new ArrayList<>());
|
||||
experimentalSymbol = config.getStringElse("experimental-symbol", "*");
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package ac.grim.grimac.player;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.AbstractCheck;
|
||||
import ac.grim.grimac.api.GrimUser;
|
||||
import ac.grim.grimac.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;
|
||||
@@ -53,7 +52,6 @@ import net.kyori.adventure.text.TranslatableComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -201,8 +199,6 @@ public class GrimPlayer implements GrimUser {
|
||||
public long lastBlockPlaceUseItem = 0;
|
||||
public AtomicInteger cancelledPackets = new AtomicInteger(0);
|
||||
public MainSupportingBlockData mainSupportingBlockData = new MainSupportingBlockData(null, false);
|
||||
// possibleEyeHeights[0] = Standing eye heights, [1] = Sneaking. [2] = Elytra, Swimming, and Riptide Trident which only exists in 1.9+
|
||||
public double[][] possibleEyeHeights = new double[3][];
|
||||
|
||||
public void onPacketCancel() {
|
||||
if (spamThreshold != -1 && cancelledPackets.incrementAndGet() > spamThreshold) {
|
||||
@@ -221,7 +217,7 @@ public class GrimPlayer implements GrimUser {
|
||||
public GrimPlayer(User user) {
|
||||
this.user = user;
|
||||
this.playerUUID = user.getUUID();
|
||||
reload(GrimAPI.INSTANCE.getConfigManager().getConfig());
|
||||
onReload();
|
||||
|
||||
boundingBox = GetBoundingBox.getBoundingBoxFromPosAndSizeRaw(x, y, z, 0.6f, 1.8f);
|
||||
|
||||
@@ -244,21 +240,6 @@ public class GrimPlayer implements GrimUser {
|
||||
packetStateData = new PacketStateData();
|
||||
|
||||
uncertaintyHandler.collidingEntities.add(0);
|
||||
|
||||
if (getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14)) {
|
||||
final float scale = (float) compensatedEntities.getSelf().getAttributeValue(Attributes.GENERIC_SCALE);
|
||||
possibleEyeHeights[2] = new double[]{0.4 * scale, 1.62 * scale, 1.27 * scale}; // Elytra, standing, sneaking (1.14)
|
||||
possibleEyeHeights[1] = new double[]{1.27 * scale, 1.62 * scale, 0.4 * scale}; // sneaking (1.14), standing, Elytra
|
||||
possibleEyeHeights[0] = new double[]{1.62 * scale, 1.27 * scale, 0.4 * scale}; // standing, sneaking (1.14), Elytra
|
||||
|
||||
} else if (getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)) { // standing, sneaking Elytra
|
||||
possibleEyeHeights[2] = new double[]{0.4, 1.62, 1.54}; // Elytra, standing, sneaking (1.13)
|
||||
possibleEyeHeights[1] = new double[]{1.54, 1.62, 0.4}; // sneaking (1.9-1.13), standing, Elytra
|
||||
possibleEyeHeights[0] = new double[]{1.62, 1.54, 0.4}; // standing, sneaking (1.9-1.13), Elytra
|
||||
} else {
|
||||
possibleEyeHeights[1] = new double[]{(double) (1.62f - 0.08f), (double) (1.62f)}; // sneaking, standing
|
||||
possibleEyeHeights[0] = new double[]{(double) (1.62f), (double) (1.62f - 0.08f)}; // standing, sneaking
|
||||
}
|
||||
}
|
||||
|
||||
public Set<VectorData> getPossibleVelocities() {
|
||||
@@ -335,8 +316,7 @@ public class GrimPlayer implements GrimUser {
|
||||
// Transactions that we send don't count towards total limit
|
||||
if (packetTracker != null) packetTracker.setIntervalPackets(packetTracker.getIntervalPackets() - 1);
|
||||
|
||||
if (skipped > 0 && System.currentTimeMillis() - joinTime > 5000)
|
||||
checkManager.getPacketCheck(TransactionOrder.class).flagAndAlert("skipped: " + skipped);
|
||||
if (skipped > 0 && System.currentTimeMillis() - joinTime > 5000) checkManager.getPacketCheck(TransactionOrder.class).flagAndAlert("skipped: " + skipped);
|
||||
|
||||
do {
|
||||
data = transactionsSent.poll();
|
||||
@@ -470,7 +450,7 @@ public class GrimPlayer implements GrimUser {
|
||||
if (lastTransSent != 0 && lastTransSent + 80 < System.currentTimeMillis()) {
|
||||
sendTransaction(true); // send on netty thread
|
||||
}
|
||||
if ((System.nanoTime() - getPlayerClockAtLeast()) > maxTransactionTime * 1e9) {
|
||||
if ((System.nanoTime() - getPlayerClockAtLeast()) > GrimAPI.INSTANCE.getConfigManager().getMaxPingTransaction() * 1e9) {
|
||||
timedOut();
|
||||
}
|
||||
|
||||
@@ -535,6 +515,10 @@ public class GrimPlayer implements GrimUser {
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -564,7 +548,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();
|
||||
}
|
||||
@@ -577,23 +561,14 @@ public class GrimPlayer implements GrimUser {
|
||||
return checkManager.getInventory();
|
||||
}
|
||||
|
||||
public double[] getPossibleEyeHeights() { // We don't return sleeping eye height
|
||||
// 1.8 Players once again ruin my clean switch-case
|
||||
if (this.getClientVersion().isOlderThan(ClientVersion.V_1_9)) {
|
||||
return this.isSneaking ? this.possibleEyeHeights[1] : this.possibleEyeHeights[0];
|
||||
} else {
|
||||
// 1.8 players just have their pose set to standing all the time
|
||||
switch (pose) {
|
||||
case FALL_FLYING: // Elytra gliding
|
||||
case SPIN_ATTACK: // Riptide trident
|
||||
case SWIMMING: // Swimming (includes crawling in 1.14+)
|
||||
return this.possibleEyeHeights[2]; // [swimming/gliding/riptide height, standing height, sneaking height]
|
||||
case NINE_CROUCHING:
|
||||
case CROUCHING:
|
||||
return this.possibleEyeHeights[1]; // [sneaking height, standing height, swimming/gliding/riptide height]
|
||||
default:
|
||||
return this.possibleEyeHeights[0]; // [standing height, sneaking height, swimming/gliding/riptide height]
|
||||
}
|
||||
public List<Double> getPossibleEyeHeights() { // We don't return sleeping eye height
|
||||
if (getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14)) { // Elytra, sneaking (1.14), standing
|
||||
final float scale = (float) compensatedEntities.getSelf().getAttributeValue(Attributes.GENERIC_SCALE);
|
||||
return Arrays.asList(0.4 * scale, 1.27 * scale, 1.62 * scale);
|
||||
} else if (getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)) { // Elytra, sneaking, standing
|
||||
return Arrays.asList(0.4, 1.54, 1.62);
|
||||
} else { // Only sneaking or standing
|
||||
return Arrays.asList((double) (1.62f - 0.08f), (double) (1.62f));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -741,21 +716,10 @@ public class GrimPlayer implements GrimUser {
|
||||
return checkManager.allChecks.values();
|
||||
}
|
||||
|
||||
|
||||
public void runNettyTaskInMs(Runnable runnable, int ms) {
|
||||
Channel channel = (Channel) user.getChannel();
|
||||
channel.eventLoop().schedule(runnable, ms, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private int maxTransactionTime = 60;
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
reload(GrimAPI.INSTANCE.getConfigManager().getConfig());
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ public class BlockPlace {
|
||||
private static final BlockFace[] BY_2D = new BlockFace[]{BlockFace.SOUTH, BlockFace.WEST, BlockFace.NORTH, BlockFace.EAST};
|
||||
static final BlockFace[] BY_3D = new BlockFace[]{BlockFace.DOWN, BlockFace.UP, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.WEST, BlockFace.EAST};
|
||||
@Setter
|
||||
public Vector3i blockPosition;
|
||||
Vector3i blockPosition;
|
||||
@Getter
|
||||
InteractionHand hand;
|
||||
@Getter
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
package ac.grim.grimac.utils.collisions;
|
||||
|
||||
/*
|
||||
|
||||
*/
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.*;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.defaulttags.BlockTags;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
// Expansion to the CollisionData class, which is different than regular ray tracing hitboxes
|
||||
public enum RaycastData {
|
||||
|
||||
HOPPER((player, item, version, data, x, y, z) -> {
|
||||
CollisionBox insideShape = new HexCollisionBox(2.0, 11.0, 2.0, 14.0, 16.0, 14.0);
|
||||
switch (data.getFacing()) {
|
||||
case NORTH:
|
||||
new ComplexCollisionBox(insideShape, new HexCollisionBox(6.0, 8.0, 0.0, 10.0, 10.0, 4.0));
|
||||
case SOUTH:
|
||||
new ComplexCollisionBox(insideShape, new HexCollisionBox(6.0, 8.0, 12.0, 10.0, 10.0, 16.0));
|
||||
case WEST:
|
||||
new ComplexCollisionBox(insideShape, new HexCollisionBox(0.0, 8.0, 6.0, 4.0, 10.0, 10.0));
|
||||
case EAST:
|
||||
new ComplexCollisionBox(insideShape, new HexCollisionBox(12.0, 8.0, 6.0, 16.0, 10.0, 10.0));
|
||||
default:
|
||||
return insideShape;
|
||||
}
|
||||
}, StateTypes.HOPPER),
|
||||
|
||||
CAULDRON((player, item, version, data, x, y, z) -> {
|
||||
return new HexCollisionBox(2.0, 4.0, 2.0, 14.0, 16.0, 14.0);
|
||||
}, BlockTags.CAULDRONS.getStates().toArray(new StateType[0])),
|
||||
|
||||
FULL_BLOCK((player, item, version, data, x, y, z) -> {
|
||||
return new SimpleCollisionBox(0, 0, 0, 1, 1, 1, true);
|
||||
}, StateTypes.COMPOSTER, StateTypes.SCAFFOLDING);
|
||||
|
||||
|
||||
private static final Map<StateType, RaycastData> lookup = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (RaycastData data : RaycastData.values()) {
|
||||
for (StateType type : data.materials) {
|
||||
lookup.put(type, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final StateType[] materials;
|
||||
private CollisionBox box;
|
||||
private HitBoxFactory dynamic;
|
||||
|
||||
RaycastData(CollisionBox box, StateType... materials) {
|
||||
this.box = box;
|
||||
Set<StateType> mList = new HashSet<>(Arrays.asList(materials));
|
||||
mList.remove(null); // Sets can contain one null
|
||||
this.materials = mList.toArray(new StateType[0]);
|
||||
}
|
||||
|
||||
RaycastData(HitBoxFactory dynamic, StateType... materials) {
|
||||
this.dynamic = dynamic;
|
||||
Set<StateType> mList = new HashSet<>(Arrays.asList(materials));
|
||||
mList.remove(null); // Sets can contain one null
|
||||
this.materials = mList.toArray(new StateType[0]);
|
||||
}
|
||||
|
||||
public static RaycastData getData(StateType material) {
|
||||
return lookup.get(material);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CollisionBox getBlockHitbox(GrimPlayer player, StateType heldItem, ClientVersion version, WrappedBlockState block, int x, int y, int z) {
|
||||
RaycastData data = getData(block.getType());
|
||||
|
||||
if (data == null) {
|
||||
// We explicitly do not want to fallback on HitBoxData or CollisionBox
|
||||
// Because we only ever use this as a 2nd ray trace
|
||||
return NoCollisionBox.INSTANCE;
|
||||
}
|
||||
|
||||
// Simple collision box to override
|
||||
if (data.box != null)
|
||||
return data.box.copy().offset(x, y, z);
|
||||
|
||||
// Allow this class to override collision boxes when they aren't the same as regular boxes
|
||||
HitBoxFactory hitBoxFactory = data.dynamic;
|
||||
CollisionBox collisionBox = hitBoxFactory.fetch(player, heldItem, version, block, x, y, z);
|
||||
collisionBox.offset(x, y, z);
|
||||
return collisionBox;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package ac.grim.grimac.utils.common;
|
||||
|
||||
|
||||
import ac.grim.grimac.api.config.ConfigManager;
|
||||
|
||||
public interface ConfigReloadObserver {
|
||||
|
||||
void onReload(ConfigManager config);
|
||||
|
||||
}
|
||||
@@ -101,29 +101,29 @@ public final class ValuedAttribute {
|
||||
}
|
||||
|
||||
public double with(WrapperPlayServerUpdateAttributes.Property property) {
|
||||
double baseValue = property.getValue();
|
||||
double additionSum = 0;
|
||||
double multiplyBaseSum = 0;
|
||||
double multiplyTotalProduct = 1.0;
|
||||
double d0 = property.getValue();
|
||||
|
||||
List<WrapperPlayServerUpdateAttributes.PropertyModifier> modifiers = property.getModifiers();
|
||||
modifiers.removeIf(modifier -> modifier.getUUID().equals(SPRINTING_MODIFIER_UUID) || modifier.getName().getKey().equals("sprinting"));
|
||||
|
||||
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;
|
||||
}
|
||||
for (WrapperPlayServerUpdateAttributes.PropertyModifier attributemodifier : modifiers) {
|
||||
if (attributemodifier.getOperation() == WrapperPlayServerUpdateAttributes.PropertyModifier.Operation.ADDITION)
|
||||
d0 += attributemodifier.getAmount();
|
||||
}
|
||||
|
||||
double newValue = GrimMath.clamp((baseValue + additionSum) * (1 + multiplyBaseSum) * multiplyTotalProduct, min, max);
|
||||
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);
|
||||
if (setRewriter != null) {
|
||||
newValue = setRewriter.apply(this.value, newValue);
|
||||
}
|
||||
|
||||
@@ -47,28 +47,6 @@ 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);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package ac.grim.grimac.utils.math;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -1,309 +0,0 @@
|
||||
package ac.grim.grimac.utils.nmsutil;
|
||||
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.collisions.HitboxData;
|
||||
import ac.grim.grimac.utils.collisions.RaycastData;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.CollisionBox;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.NoCollisionBox;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.HitData;
|
||||
import ac.grim.grimac.utils.data.Pair;
|
||||
import ac.grim.grimac.utils.math.GrimMath;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class BlockRayTrace {
|
||||
// Copied from MCP...
|
||||
// Returns null if there isn't anything.
|
||||
//
|
||||
// I do have to admit that I'm starting to like bifunctions/new java 8 things more than I originally did.
|
||||
// although I still don't understand Mojang's obsession with streams in some of the hottest methods... that kills performance
|
||||
@Nullable
|
||||
public static Pair<int[], BlockFace> traverseBlocksLOSP(GrimPlayer player, double[] start, double[] end, BiFunction<WrappedBlockState, int[], Pair<int[], BlockFace>> predicate) {
|
||||
// I guess go back by the collision epsilon?
|
||||
double endX = GrimMath.lerp(-1.0E-7D, end[0], start[0]);
|
||||
double endY = GrimMath.lerp(-1.0E-7D, end[1], start[1]);
|
||||
double endZ = GrimMath.lerp(-1.0E-7D, end[2], start[2]);
|
||||
double startX = GrimMath.lerp(-1.0E-7D, start[0], end[0]);
|
||||
double startY = GrimMath.lerp(-1.0E-7D, start[1], end[1]);
|
||||
double startZ = GrimMath.lerp(-1.0E-7D, start[2], end[2]);
|
||||
|
||||
int[] floorStart = new int[]{GrimMath.floor(startX), GrimMath.floor(startY), GrimMath.floor(startZ)};
|
||||
|
||||
if (start[0] == end[0] && start[1] == end[1] && start[2] == end[2]) return null;
|
||||
|
||||
WrappedBlockState state = player.compensatedWorld.getWrappedBlockStateAt(floorStart[0], floorStart[1], floorStart[2]);
|
||||
Pair<int[], BlockFace> apply = predicate.apply(state, floorStart);
|
||||
|
||||
if (apply != null) {
|
||||
return apply;
|
||||
}
|
||||
|
||||
double xDiff = endX - startX;
|
||||
double yDiff = endY - startY;
|
||||
double zDiff = endZ - startZ;
|
||||
double xSign = Math.signum(xDiff);
|
||||
double ySign = Math.signum(yDiff);
|
||||
double zSign = Math.signum(zDiff);
|
||||
|
||||
double posXInverse = xSign == 0 ? Double.MAX_VALUE : xSign / xDiff;
|
||||
double posYInverse = ySign == 0 ? Double.MAX_VALUE : ySign / yDiff;
|
||||
double posZInverse = zSign == 0 ? Double.MAX_VALUE : zSign / zDiff;
|
||||
|
||||
double tMaxX = posXInverse * (xSign > 0 ? 1.0D - GrimMath.frac(startX) : GrimMath.frac(startX));
|
||||
double tMaxY = posYInverse * (ySign > 0 ? 1.0D - GrimMath.frac(startY) : GrimMath.frac(startY));
|
||||
double tMaxZ = posZInverse * (zSign > 0 ? 1.0D - GrimMath.frac(startZ) : GrimMath.frac(startZ));
|
||||
|
||||
// tMax represents the maximum distance along each axis before crossing a block boundary
|
||||
// The loop continues as long as the ray hasn't reached its end point along at least one axis.
|
||||
// In each iteration, it moves to the next block boundary along the axis with the smallest tMax value,
|
||||
// updates the corresponding coordinate, and checks for a hit in the new block, Google "3D DDA" for more info
|
||||
while (tMaxX <= 1.0D || tMaxY <= 1.0D || tMaxZ <= 1.0D) {
|
||||
if (tMaxX < tMaxY) {
|
||||
if (tMaxX < tMaxZ) {
|
||||
floorStart[0] += xSign;
|
||||
tMaxX += posXInverse;
|
||||
} else {
|
||||
floorStart[2] += zSign;
|
||||
tMaxZ += posZInverse;
|
||||
}
|
||||
} else if (tMaxY < tMaxZ) {
|
||||
floorStart[1] += ySign;
|
||||
tMaxY += posYInverse;
|
||||
} else {
|
||||
floorStart[2] += zSign;
|
||||
tMaxZ += posZInverse;
|
||||
}
|
||||
|
||||
state = player.compensatedWorld.getWrappedBlockStateAt(floorStart[0], floorStart[1], floorStart[2]);
|
||||
apply = predicate.apply(state, floorStart);
|
||||
|
||||
if (apply != null) {
|
||||
return apply;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static HitData traverseBlocks(GrimPlayer player, double[] start, double[] end, BiFunction<WrappedBlockState, Vector3i, HitData> predicate) {
|
||||
// I guess go back by the collision epsilon?
|
||||
double endX = GrimMath.lerp(-1.0E-7D, end[0], start[0]);
|
||||
double endY = GrimMath.lerp(-1.0E-7D, end[1], start[1]);
|
||||
double endZ = GrimMath.lerp(-1.0E-7D, end[2], start[2]);
|
||||
double startX = GrimMath.lerp(-1.0E-7D, start[0], end[0]);
|
||||
double startY = GrimMath.lerp(-1.0E-7D, start[1], end[1]);
|
||||
double startZ = GrimMath.lerp(-1.0E-7D, start[2], end[2]);
|
||||
int floorStartX = GrimMath.floor(startX);
|
||||
int floorStartY = GrimMath.floor(startY);
|
||||
int floorStartZ = GrimMath.floor(startZ);
|
||||
|
||||
if (start[0] == end[0] && start[1] == end[1] && start[2] == end[2]) return null;
|
||||
|
||||
WrappedBlockState state = player.compensatedWorld.getWrappedBlockStateAt(floorStartX, floorStartY, floorStartZ);
|
||||
HitData apply = predicate.apply(state, new Vector3i(floorStartX, floorStartY, floorStartZ));
|
||||
|
||||
if (apply != null) {
|
||||
return apply;
|
||||
}
|
||||
|
||||
double xDiff = endX - startX;
|
||||
double yDiff = endY - startY;
|
||||
double zDiff = endZ - startZ;
|
||||
double xSign = Math.signum(xDiff);
|
||||
double ySign = Math.signum(yDiff);
|
||||
double zSign = Math.signum(zDiff);
|
||||
|
||||
double posXInverse = xSign == 0 ? Double.MAX_VALUE : xSign / xDiff;
|
||||
double posYInverse = ySign == 0 ? Double.MAX_VALUE : ySign / yDiff;
|
||||
double posZInverse = zSign == 0 ? Double.MAX_VALUE : zSign / zDiff;
|
||||
|
||||
double tMaxX = posXInverse * (xSign > 0 ? 1.0D - GrimMath.frac(startX) : GrimMath.frac(startX));
|
||||
double tMaxY = posYInverse * (ySign > 0 ? 1.0D - GrimMath.frac(startY) : GrimMath.frac(startY));
|
||||
double tMaxZ = posZInverse * (zSign > 0 ? 1.0D - GrimMath.frac(startZ) : GrimMath.frac(startZ));
|
||||
|
||||
// tMax represents the maximum distance along each axis before crossing a block boundary
|
||||
// The loop continues as long as the ray hasn't reached its end point along at least one axis.
|
||||
// In each iteration, it moves to the next block boundary along the axis with the smallest tMax value,
|
||||
// updates the corresponding coordinate, and checks for a hit in the new block, Google "3D DDA" for more info
|
||||
while (tMaxX <= 1.0D || tMaxY <= 1.0D || tMaxZ <= 1.0D) {
|
||||
if (tMaxX < tMaxY) {
|
||||
if (tMaxX < tMaxZ) {
|
||||
floorStartX += xSign;
|
||||
tMaxX += posXInverse;
|
||||
} else {
|
||||
floorStartZ += zSign;
|
||||
tMaxZ += posZInverse;
|
||||
}
|
||||
} else if (tMaxY < tMaxZ) {
|
||||
floorStartY += ySign;
|
||||
tMaxY += posYInverse;
|
||||
} else {
|
||||
floorStartZ += zSign;
|
||||
tMaxZ += posZInverse;
|
||||
}
|
||||
|
||||
state = player.compensatedWorld.getWrappedBlockStateAt(floorStartX, floorStartY, floorStartZ);
|
||||
apply = predicate.apply(state, new Vector3i(floorStartX, floorStartY, floorStartZ));
|
||||
|
||||
if (apply != null) {
|
||||
return apply;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static HitData traverseBlocks(GrimPlayer player, Vector3d start, Vector3d end, BiFunction<WrappedBlockState, Vector3i, HitData> predicate) {
|
||||
return traverseBlocks(player, new double[]{start.x, start.y, start.z}, new double[]{end.x, end.y, end.z}, predicate);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static HitData getNearestReachHitResult(GrimPlayer player, double[] startPos, double[] lookVec, double currentDistance, double maxDistance, int[] targetBlockVec, boolean raycastContext) {
|
||||
double[] endPos = new double[]{
|
||||
startPos[0] + lookVec[0] * maxDistance,
|
||||
startPos[1] + lookVec[1] * maxDistance,
|
||||
startPos[2] + lookVec[2] * maxDistance
|
||||
};
|
||||
|
||||
return traverseBlocks(player, startPos, endPos, (block, vector3i) -> {
|
||||
CollisionBox data;
|
||||
if (!raycastContext) {
|
||||
data = HitboxData.getBlockHitbox(player, player.getInventory().getHeldItem().getType().getPlacedType(), player.getClientVersion(), block, vector3i.x, vector3i.y, vector3i.z);
|
||||
} else {
|
||||
data = RaycastData.getBlockHitbox(player, null, player.getClientVersion(), block, vector3i.x, vector3i.y, vector3i.z);
|
||||
}
|
||||
if (data == NoCollisionBox.INSTANCE) return null;
|
||||
List<SimpleCollisionBox> boxes = new ArrayList<>();
|
||||
data.downCast(boxes);
|
||||
|
||||
double bestHitResult = Double.MAX_VALUE;
|
||||
double[] bestHitLoc = null;
|
||||
BlockFace bestFace = null;
|
||||
|
||||
// BEWARE OF https://bugs.mojang.com/browse/MC-85109 FOR 1.8 PLAYERS
|
||||
// 1.8 Brewing Stand hitbox is a fullblock until it is hit sometimes, can be caused be restarting client and joining server
|
||||
if (block.getType() == StateTypes.BREWING_STAND && player.getClientVersion().equals(ClientVersion.V_1_8) && Arrays.equals(new int[]{vector3i.x, vector3i.y, vector3i.z}, targetBlockVec)) {
|
||||
boxes.add(new SimpleCollisionBox(0, 0, 0, 1, 1, 1, true));
|
||||
}
|
||||
|
||||
double[] currentEnd = new double[]{
|
||||
startPos[0] + lookVec[0] * currentDistance,
|
||||
startPos[1] + lookVec[1] * currentDistance,
|
||||
startPos[2] + lookVec[2] * currentDistance
|
||||
};
|
||||
|
||||
for (SimpleCollisionBox box : boxes) {
|
||||
Pair<double[], BlockFace> intercept = ReachUtilsPrimitives.calculateIntercept(box, startPos, currentEnd);
|
||||
if (intercept.getFirst() == null) continue; // No intercept or wrong blockFace
|
||||
|
||||
double[] hitLoc = intercept.getFirst();
|
||||
|
||||
double distSq = distanceSquared(hitLoc, startPos);
|
||||
if (distSq < bestHitResult) {
|
||||
bestHitResult = distSq;
|
||||
bestHitLoc = hitLoc;
|
||||
bestFace = intercept.getSecond();
|
||||
}
|
||||
}
|
||||
|
||||
// Yes, this is not the most optimal algorithm for handling Cauldrons, Hoppers, Composters, and Scaffolding
|
||||
// that is to say, blocks that have a different outline/hitbox shape from the box used to calculate placement blockfaces
|
||||
// but it is the one vanilla uses
|
||||
// No we will not
|
||||
// 1. Calculate the ray trace from a new closer startPos to reduce iterations
|
||||
// because it adds a lot of code complexity for very little performance gain
|
||||
// 2. Run a switch case on the target block and check if the index of the SimpleCollisionBox corresponds to a wall with an inside face
|
||||
// and hardcode in blockface fixes for placements against those compnents above a certain relative y level
|
||||
// because that is version-specific, will break if the implementation of the returned ComplexCollisionBox changes
|
||||
// and again, lots of code complexity for little performance gain
|
||||
if (bestHitLoc != null) {
|
||||
HitData hitData = new HitData(vector3i, new Vector(bestHitLoc[0], bestHitLoc[1], bestHitLoc[2]), bestFace, block);
|
||||
if (!raycastContext) {
|
||||
HitData hitData2 = BlockRayTrace.getNearestReachHitResult(player, startPos, lookVec, maxDistance, maxDistance, targetBlockVec, true);
|
||||
if (hitData2 != null) {
|
||||
Vector startVector = new Vector(startPos[0], startPos[1], startPos[2]);
|
||||
if (hitData2.getBlockHitLocation().subtract(startVector).lengthSquared() <
|
||||
hitData.getBlockHitLocation().subtract(startVector).lengthSquared()) {
|
||||
return new HitData(vector3i, hitData.getBlockHitLocation(), hitData2.getClosestDirection(), block);
|
||||
}
|
||||
}
|
||||
}
|
||||
return hitData;
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private static double distanceSquared(double[] vec1, double[] vec2) {
|
||||
double dx = vec1[0] - vec2[0];
|
||||
double dy = vec1[1] - vec2[1];
|
||||
double dz = vec1[2] - vec2[2];
|
||||
return dx * dx + dy * dy + dz * dz;
|
||||
}
|
||||
|
||||
public static HitData getNearestHitResult(GrimPlayer player, StateType heldItem, boolean sourcesHaveHitbox) {
|
||||
Vector3d startingPos = new Vector3d(player.x, player.y + player.getEyeHeight(), player.z);
|
||||
Vector startingVec = new Vector(startingPos.getX(), startingPos.getY(), startingPos.getZ());
|
||||
Ray trace = new Ray(player, startingPos.getX(), startingPos.getY(), startingPos.getZ(), player.xRot, player.yRot);
|
||||
final double distance = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE);
|
||||
Vector endVec = trace.getPointAtDistance(distance);
|
||||
Vector3d endPos = new Vector3d(endVec.getX(), endVec.getY(), endVec.getZ());
|
||||
|
||||
return traverseBlocks(player, startingPos, endPos, (block, vector3i) -> {
|
||||
CollisionBox data = HitboxData.getBlockHitbox(player, heldItem, player.getClientVersion(), block, vector3i.getX(), vector3i.getY(), vector3i.getZ());
|
||||
List<SimpleCollisionBox> boxes = new ArrayList<>();
|
||||
data.downCast(boxes);
|
||||
|
||||
double bestHitResult = Double.MAX_VALUE;
|
||||
Vector bestHitLoc = null;
|
||||
BlockFace bestFace = null;
|
||||
|
||||
for (SimpleCollisionBox box : boxes) {
|
||||
Pair<Vector, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
if (intercept.getFirst() == null) continue; // No intercept
|
||||
|
||||
Vector hitLoc = intercept.getFirst();
|
||||
|
||||
if (hitLoc.distanceSquared(startingVec) < bestHitResult) {
|
||||
bestHitResult = hitLoc.distanceSquared(startingVec);
|
||||
bestHitLoc = hitLoc;
|
||||
bestFace = intercept.getSecond();
|
||||
}
|
||||
}
|
||||
if (bestHitLoc != null) {
|
||||
return new HitData(vector3i, bestHitLoc, bestFace, block);
|
||||
}
|
||||
|
||||
if (sourcesHaveHitbox &&
|
||||
(player.compensatedWorld.isWaterSourceBlock(vector3i.getX(), vector3i.getY(), vector3i.getZ())
|
||||
|| player.compensatedWorld.getLavaFluidLevelAt(vector3i.getX(), vector3i.getY(), vector3i.getZ()) == (8 / 9f))) {
|
||||
double waterHeight = player.compensatedWorld.getFluidLevelAt(vector3i.getX(), vector3i.getY(), vector3i.getZ());
|
||||
SimpleCollisionBox box = new SimpleCollisionBox(vector3i.getX(), vector3i.getY(), vector3i.getZ(), vector3i.getX() + 1, vector3i.getY() + waterHeight, vector3i.getZ() + 1);
|
||||
|
||||
Pair<Vector, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance));
|
||||
|
||||
if (intercept.getFirst() != null) {
|
||||
return new HitData(vector3i, intercept.getFirst(), intercept.getSecond(), block);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -181,8 +181,7 @@ public class ReachUtils {
|
||||
|
||||
double lowest = Double.MAX_VALUE;
|
||||
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
for (double eyes : possibleEyeHeights) {
|
||||
for (double eyes : player.getPossibleEyeHeights()) {
|
||||
if (giveMovementThresholdLenience) targetBox.expand(player.getMovementThreshold());
|
||||
Vector from = new Vector(player.x, player.y + eyes, player.z);
|
||||
Vector closestPoint = VectorUtils.cutBoxToVector(from, targetBox);
|
||||
|
||||
@@ -1,184 +0,0 @@
|
||||
package ac.grim.grimac.utils.nmsutil;
|
||||
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
|
||||
import ac.grim.grimac.utils.data.Pair;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ReachUtilsPrimitives {
|
||||
public static @NotNull Pair<@Nullable double[], @Nullable BlockFace> calculateIntercept(SimpleCollisionBox self, double[] origin, double[] end) {
|
||||
double[] minX = getIntermediateWithXValue(origin, end, self.minX);
|
||||
double[] maxX = getIntermediateWithXValue(origin, end, self.maxX);
|
||||
double[] minY = getIntermediateWithYValue(origin, end, self.minY);
|
||||
double[] maxY = getIntermediateWithYValue(origin, end, self.maxY);
|
||||
double[] minZ = getIntermediateWithZValue(origin, end, self.minZ);
|
||||
double[] maxZ = getIntermediateWithZValue(origin, end, self.maxZ);
|
||||
|
||||
BlockFace bestFace = null;
|
||||
|
||||
if (!isVecInYZ(self, minX)) minX = null;
|
||||
if (!isVecInYZ(self, maxX)) maxX = null;
|
||||
if (!isVecInXZ(self, minY)) minY = null;
|
||||
if (!isVecInXZ(self, maxY)) maxY = null;
|
||||
if (!isVecInXY(self, minZ)) minZ = null;
|
||||
if (!isVecInXY(self, maxZ)) maxZ = null;
|
||||
|
||||
double[] best = null;
|
||||
double bestDistSq = Double.MAX_VALUE;
|
||||
|
||||
if (minX != null) {
|
||||
best = minX;
|
||||
bestDistSq = distanceSquared(origin, minX);
|
||||
bestFace = BlockFace.WEST;
|
||||
}
|
||||
|
||||
if (maxX != null) {
|
||||
double distSq = distanceSquared(origin, maxX);
|
||||
if (best == null || distSq < bestDistSq) {
|
||||
best = maxX;
|
||||
bestDistSq = distSq;
|
||||
bestFace = BlockFace.EAST;
|
||||
}
|
||||
}
|
||||
|
||||
if (minY != null) {
|
||||
double distSq = distanceSquared(origin, minY);
|
||||
if (best == null || distSq < bestDistSq) {
|
||||
best = minY;
|
||||
bestDistSq = distSq;
|
||||
bestFace = BlockFace.DOWN;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxY != null) {
|
||||
double distSq = distanceSquared(origin, maxY);
|
||||
if (best == null || distSq < bestDistSq) {
|
||||
best = maxY;
|
||||
bestDistSq = distSq;
|
||||
bestFace = BlockFace.UP;
|
||||
}
|
||||
}
|
||||
|
||||
if (minZ != null) {
|
||||
double distSq = distanceSquared(origin, minZ);
|
||||
if (best == null || distSq < bestDistSq) {
|
||||
best = minZ;
|
||||
bestDistSq = distSq;
|
||||
bestFace = BlockFace.NORTH;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxZ != null) {
|
||||
double distSq = distanceSquared(origin, maxZ);
|
||||
if (best == null || distSq < bestDistSq) {
|
||||
best = maxZ;
|
||||
bestFace = BlockFace.SOUTH;
|
||||
}
|
||||
}
|
||||
|
||||
return new Pair<>(best, bestFace);
|
||||
}
|
||||
|
||||
private static double[] getIntermediateWithXValue(double[] self, double[] other, double x) {
|
||||
double d0 = other[0] - self[0];
|
||||
double d1 = other[1] - self[1];
|
||||
double d2 = other[2] - self[2];
|
||||
|
||||
if (d0 * d0 < 1.0000000116860974E-7D) {
|
||||
return null;
|
||||
} else {
|
||||
double d3 = (x - self[0]) / d0;
|
||||
return d3 >= 0.0D && d3 <= 1.0D ? new double[]{self[0] + d0 * d3, self[1] + d1 * d3, self[2] + d2 * d3} : null;
|
||||
}
|
||||
}
|
||||
|
||||
private static double[] getIntermediateWithYValue(double[] self, double[] other, double y) {
|
||||
double d0 = other[0] - self[0];
|
||||
double d1 = other[1] - self[1];
|
||||
double d2 = other[2] - self[2];
|
||||
|
||||
if (d1 * d1 < 1.0000000116860974E-7D) {
|
||||
return null;
|
||||
} else {
|
||||
double d3 = (y - self[1]) / d1;
|
||||
return d3 >= 0.0D && d3 <= 1.0D ? new double[]{self[0] + d0 * d3, self[1] + d1 * d3, self[2] + d2 * d3} : null;
|
||||
}
|
||||
}
|
||||
|
||||
private static double[] getIntermediateWithZValue(double[] self, double[] other, double z) {
|
||||
double d0 = other[0] - self[0];
|
||||
double d1 = other[1] - self[1];
|
||||
double d2 = other[2] - self[2];
|
||||
|
||||
if (d2 * d2 < 1.0000000116860974E-7D) {
|
||||
return null;
|
||||
} else {
|
||||
double d3 = (z - self[2]) / d2;
|
||||
return d3 >= 0.0D && d3 <= 1.0D ? new double[]{self[0] + d0 * d3, self[1] + d1 * d3, self[2] + d2 * d3} : null;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isVecInYZ(SimpleCollisionBox self, double[] vec) {
|
||||
return vec != null && vec[1] >= self.minY && vec[1] <= self.maxY && vec[2] >= self.minZ && vec[2] <= self.maxZ;
|
||||
}
|
||||
|
||||
private static boolean isVecInXZ(SimpleCollisionBox self, double[] vec) {
|
||||
return vec != null && vec[0] >= self.minX && vec[0] <= self.maxX && vec[2] >= self.minZ && vec[2] <= self.maxZ;
|
||||
}
|
||||
|
||||
private static boolean isVecInXY(SimpleCollisionBox self, double[] vec) {
|
||||
return vec != null && vec[0] >= self.minX && vec[0] <= self.maxX && vec[1] >= self.minY && vec[1] <= self.maxY;
|
||||
}
|
||||
|
||||
public static boolean isVecInside(SimpleCollisionBox self, double[] vec) {
|
||||
return vec[0] > self.minX && vec[0] < self.maxX &&
|
||||
vec[1] > self.minY && vec[1] < self.maxY &&
|
||||
vec[2] > self.minZ && vec[2] < self.maxZ;
|
||||
}
|
||||
|
||||
private static double distanceSquared(double[] vec1, double[] vec2) {
|
||||
double dx = vec1[0] - vec2[0];
|
||||
double dy = vec1[1] - vec2[1];
|
||||
double dz = vec1[2] - vec2[2];
|
||||
return dx * dx + dy * dy + dz * dz;
|
||||
}
|
||||
|
||||
// The following methods remain unchanged but are included for completeness
|
||||
|
||||
public static double[] getLook(GrimPlayer player, float yaw, float pitch) {
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_12_2)) {
|
||||
float f = player.trigHandler.cos(-yaw * 0.017453292F - (float)Math.PI);
|
||||
float f1 = player.trigHandler.sin(-yaw * 0.017453292F - (float)Math.PI);
|
||||
float f2 = -player.trigHandler.cos(-pitch * 0.017453292F);
|
||||
float f3 = player.trigHandler.sin(-pitch * 0.017453292F);
|
||||
return new double[]{f1 * f2, f3, f * f2};
|
||||
} else {
|
||||
float f = pitch * ((float) Math.PI / 180F);
|
||||
float f1 = -yaw * ((float) Math.PI / 180F);
|
||||
float f2 = player.trigHandler.cos(f1);
|
||||
float f3 = player.trigHandler.sin(f1);
|
||||
float f4 = player.trigHandler.cos(f);
|
||||
float f5 = player.trigHandler.sin(f);
|
||||
return new double[]{f3 * f4, -f5, f2 * f4};
|
||||
}
|
||||
}
|
||||
|
||||
// public static double getMinReachToBox(GrimPlayer player, SimpleCollisionBox targetBox) {
|
||||
// boolean giveMovementThresholdLenience = player.packetStateData.didLastMovementIncludePosition || player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9);
|
||||
// if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) targetBox.expand(0.1);
|
||||
//
|
||||
// double lowest = Double.MAX_VALUE;
|
||||
//
|
||||
// for (double eyes : player.getPossibleEyeHeights()) {
|
||||
// if (giveMovementThresholdLenience) targetBox.expand(player.getMovementThreshold());
|
||||
// double[] from = new double[]{player.x, player.y + eyes, player.z};
|
||||
// double[] closestPoint = VectorUtils.cutBoxToVector(from, targetBox);
|
||||
// lowest = Math.min(lowest, Math.sqrt(distanceSquared(from, closestPoint)));
|
||||
// }
|
||||
//
|
||||
// return lowest;
|
||||
// }
|
||||
}
|
||||
@@ -81,53 +81,9 @@ FarPlace:
|
||||
PositionPlace:
|
||||
cancelvl: 5
|
||||
|
||||
RotationPlace:
|
||||
cancelvl: 5
|
||||
|
||||
LineOfSightPlace:
|
||||
cancelvl: 1
|
||||
# Determines whether to only run the LineOfSightPlace check on specific blocks
|
||||
# Increases performance, mainly intended for mini-game servers which already prevent block placement
|
||||
# And want to stop container or workstation access through walls
|
||||
use-block-whitelist: false
|
||||
block-whitelist:
|
||||
- ANVIL
|
||||
- BARREL
|
||||
- BEACON
|
||||
- BEEHIVE
|
||||
- BEE_NEST
|
||||
- BLAST_FURNACE
|
||||
- BREWING_STAND
|
||||
- CAMPFIRE
|
||||
- CARTOGRAPHY_TABLE
|
||||
- CHEST
|
||||
- CHEST_MINECART
|
||||
- CHIPPED_ANVIL
|
||||
- COMPOSTER
|
||||
- CRAFTING_TABLE
|
||||
- DAMAGED_ANVIL
|
||||
- DISPENSER
|
||||
- DROPPER
|
||||
- ENCHANTING_TABLE
|
||||
- ENDER_CHEST
|
||||
- FURNACE
|
||||
- FURNACE_MINECART
|
||||
- FLETCHING_TABLE
|
||||
- GRINDSTONE
|
||||
- HOPPER
|
||||
- HOPPER_MINECART
|
||||
- ITEM_FRAME
|
||||
- JUKEBOX
|
||||
- LECTERN
|
||||
- LOOM
|
||||
- RESPAWN_ANCHOR
|
||||
- SHULKER_BOX
|
||||
- SMITHING_TABLE
|
||||
- SMOKER
|
||||
- SOUL_CAMPFIRE
|
||||
- STONECUTTER
|
||||
- TRAPPED_CHEST
|
||||
- COMMAND_BLOCK
|
||||
- STRUCTURE_BLOCK
|
||||
- JIGSAW
|
||||
# Prediction-based no slow check
|
||||
# Grim ist verantwortlich für den fehlerhaften Netcode hier... schwer zu falsen, selbst wenn man Rechtsklick und Offhand-Taste spammt.
|
||||
# Viel stabiler als andere Anticheats, aber bitte melde alle Falses... Ich habe hier eine Menge Netcode-Probleme behoben.
|
||||
|
||||
@@ -81,52 +81,8 @@ FarPlace:
|
||||
PositionPlace:
|
||||
cancelvl: 5
|
||||
|
||||
LineOfSightPlace:
|
||||
cancelvl: 1
|
||||
# Determines whether to only run the LineOfSightPlace check on specific blocks
|
||||
# Increases performance, mainly intended for mini-game servers which already prevent block placement
|
||||
# And want to stop container or workstation access through walls
|
||||
use-block-whitelist: false
|
||||
block-whitelist:
|
||||
- ANVIL
|
||||
- BARREL
|
||||
- BEACON
|
||||
- BEEHIVE
|
||||
- BEE_NEST
|
||||
- BLAST_FURNACE
|
||||
- BREWING_STAND
|
||||
- CAMPFIRE
|
||||
- CARTOGRAPHY_TABLE
|
||||
- CHEST
|
||||
- CHEST_MINECART
|
||||
- CHIPPED_ANVIL
|
||||
- COMPOSTER
|
||||
- CRAFTING_TABLE
|
||||
- DAMAGED_ANVIL
|
||||
- DISPENSER
|
||||
- DROPPER
|
||||
- ENCHANTING_TABLE
|
||||
- ENDER_CHEST
|
||||
- FURNACE
|
||||
- FURNACE_MINECART
|
||||
- FLETCHING_TABLE
|
||||
- GRINDSTONE
|
||||
- HOPPER
|
||||
- HOPPER_MINECART
|
||||
- ITEM_FRAME
|
||||
- JUKEBOX
|
||||
- LECTERN
|
||||
- LOOM
|
||||
- RESPAWN_ANCHOR
|
||||
- SHULKER_BOX
|
||||
- SMITHING_TABLE
|
||||
- SMOKER
|
||||
- SOUL_CAMPFIRE
|
||||
- STONECUTTER
|
||||
- TRAPPED_CHEST
|
||||
- COMMAND_BLOCK
|
||||
- STRUCTURE_BLOCK
|
||||
- JIGSAW
|
||||
RotationPlace:
|
||||
cancelvl: 5
|
||||
|
||||
# Prediction-based no slow check
|
||||
# Grim accounts for buggy netcode here... hard to false even when spamming right click and offhand button
|
||||
|
||||
@@ -82,52 +82,9 @@ FarPlace:
|
||||
PositionPlace:
|
||||
cancelvl: 5
|
||||
|
||||
LineOfSightPlace:
|
||||
cancelvl: 1
|
||||
# Determines whether to only run the LineOfSightPlace check on specific blocks
|
||||
# Increases performance, mainly intended for mini-game servers which already prevent block placement
|
||||
# And want to stop container or workstation access through walls
|
||||
use-block-whitelist: false
|
||||
block-whitelist:
|
||||
- ANVIL
|
||||
- BARREL
|
||||
- BEACON
|
||||
- BEEHIVE
|
||||
- BEE_NEST
|
||||
- BLAST_FURNACE
|
||||
- BREWING_STAND
|
||||
- CAMPFIRE
|
||||
- CARTOGRAPHY_TABLE
|
||||
- CHEST
|
||||
- CHEST_MINECART
|
||||
- CHIPPED_ANVIL
|
||||
- COMPOSTER
|
||||
- CRAFTING_TABLE
|
||||
- DAMAGED_ANVIL
|
||||
- DISPENSER
|
||||
- DROPPER
|
||||
- ENCHANTING_TABLE
|
||||
- ENDER_CHEST
|
||||
- FURNACE
|
||||
- FURNACE_MINECART
|
||||
- FLETCHING_TABLE
|
||||
- GRINDSTONE
|
||||
- HOPPER
|
||||
- HOPPER_MINECART
|
||||
- ITEM_FRAME
|
||||
- JUKEBOX
|
||||
- LECTERN
|
||||
- LOOM
|
||||
- RESPAWN_ANCHOR
|
||||
- SHULKER_BOX
|
||||
- SMITHING_TABLE
|
||||
- SMOKER
|
||||
- SOUL_CAMPFIRE
|
||||
- STONECUTTER
|
||||
- TRAPPED_CHEST
|
||||
- COMMAND_BLOCK
|
||||
- STRUCTURE_BLOCK
|
||||
- JIGSAW
|
||||
RotationPlace:
|
||||
cancelvl: 5
|
||||
|
||||
# Comprobación de NoSlow basado en predicciones
|
||||
# Grim compensa por código de red con errores aquí... difícil de sacar un falso positivo incluso haciendo spam del
|
||||
# clic derecho y la mano secundaria.
|
||||
|
||||
@@ -81,52 +81,9 @@ FarPlace:
|
||||
PositionPlace:
|
||||
cancelvl: 5
|
||||
|
||||
LineOfSightPlace:
|
||||
cancelvl: 1
|
||||
# Determines whether to only run the LineOfSightPlace check on specific blocks
|
||||
# Increases performance, mainly intended for mini-game servers which already prevent block placement
|
||||
# And want to stop container or workstation access through walls
|
||||
use-block-whitelist: false
|
||||
block-whitelist:
|
||||
- ANVIL
|
||||
- BARREL
|
||||
- BEACON
|
||||
- BEEHIVE
|
||||
- BEE_NEST
|
||||
- BLAST_FURNACE
|
||||
- BREWING_STAND
|
||||
- CAMPFIRE
|
||||
- CARTOGRAPHY_TABLE
|
||||
- CHEST
|
||||
- CHEST_MINECART
|
||||
- CHIPPED_ANVIL
|
||||
- COMPOSTER
|
||||
- CRAFTING_TABLE
|
||||
- DAMAGED_ANVIL
|
||||
- DISPENSER
|
||||
- DROPPER
|
||||
- ENCHANTING_TABLE
|
||||
- ENDER_CHEST
|
||||
- FURNACE
|
||||
- FURNACE_MINECART
|
||||
- FLETCHING_TABLE
|
||||
- GRINDSTONE
|
||||
- HOPPER
|
||||
- HOPPER_MINECART
|
||||
- ITEM_FRAME
|
||||
- JUKEBOX
|
||||
- LECTERN
|
||||
- LOOM
|
||||
- RESPAWN_ANCHOR
|
||||
- SHULKER_BOX
|
||||
- SMITHING_TABLE
|
||||
- SMOKER
|
||||
- SOUL_CAMPFIRE
|
||||
- STONECUTTER
|
||||
- TRAPPED_CHEST
|
||||
- COMMAND_BLOCK
|
||||
- STRUCTURE_BLOCK
|
||||
- JIGSAW
|
||||
RotationPlace:
|
||||
cancelvl: 5
|
||||
|
||||
# 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.
|
||||
|
||||
@@ -78,52 +78,9 @@ PositionPlace:
|
||||
# Livello di violazione per il piazzamento in una posizione specifica
|
||||
cancelvl: 5
|
||||
|
||||
LineOfSightPlace:
|
||||
cancelvl: 1
|
||||
# Determines whether to only run the LineOfSightPlace check on specific blocks
|
||||
# Increases performance, mainly intended for mini-game servers which already prevent block placement
|
||||
# And want to stop container or workstation access through walls
|
||||
use-block-whitelist: false
|
||||
block-whitelist:
|
||||
- ANVIL
|
||||
- BARREL
|
||||
- BEACON
|
||||
- BEEHIVE
|
||||
- BEE_NEST
|
||||
- BLAST_FURNACE
|
||||
- BREWING_STAND
|
||||
- CAMPFIRE
|
||||
- CARTOGRAPHY_TABLE
|
||||
- CHEST
|
||||
- CHEST_MINECART
|
||||
- CHIPPED_ANVIL
|
||||
- COMPOSTER
|
||||
- CRAFTING_TABLE
|
||||
- DAMAGED_ANVIL
|
||||
- DISPENSER
|
||||
- DROPPER
|
||||
- ENCHANTING_TABLE
|
||||
- ENDER_CHEST
|
||||
- FURNACE
|
||||
- FURNACE_MINECART
|
||||
- FLETCHING_TABLE
|
||||
- GRINDSTONE
|
||||
- HOPPER
|
||||
- HOPPER_MINECART
|
||||
- ITEM_FRAME
|
||||
- JUKEBOX
|
||||
- LECTERN
|
||||
- LOOM
|
||||
- RESPAWN_ANCHOR
|
||||
- SHULKER_BOX
|
||||
- SMITHING_TABLE
|
||||
- SMOKER
|
||||
- SOUL_CAMPFIRE
|
||||
- STONECUTTER
|
||||
- TRAPPED_CHEST
|
||||
- COMMAND_BLOCK
|
||||
- STRUCTURE_BLOCK
|
||||
- JIGSAW
|
||||
RotationPlace:
|
||||
# Livello di violazione per il piazzamento con rotazione specifica
|
||||
cancelvl: 5
|
||||
|
||||
NoSlowA:
|
||||
# Limite per rilevare l'uso scorretto dell'oggetto
|
||||
|
||||
@@ -81,52 +81,9 @@ FarPlace:
|
||||
PositionPlace:
|
||||
cancelvl: 5
|
||||
|
||||
LineOfSightPlace:
|
||||
cancelvl: 1
|
||||
# Determines whether to only run the LineOfSightPlace check on specific blocks
|
||||
# Increases performance, mainly intended for mini-game servers which already prevent block placement
|
||||
# And want to stop container or workstation access through walls
|
||||
use-block-whitelist: false
|
||||
block-whitelist:
|
||||
- ANVIL
|
||||
- BARREL
|
||||
- BEACON
|
||||
- BEEHIVE
|
||||
- BEE_NEST
|
||||
- BLAST_FURNACE
|
||||
- BREWING_STAND
|
||||
- CAMPFIRE
|
||||
- CARTOGRAPHY_TABLE
|
||||
- CHEST
|
||||
- CHEST_MINECART
|
||||
- CHIPPED_ANVIL
|
||||
- COMPOSTER
|
||||
- CRAFTING_TABLE
|
||||
- DAMAGED_ANVIL
|
||||
- DISPENSER
|
||||
- DROPPER
|
||||
- ENCHANTING_TABLE
|
||||
- ENDER_CHEST
|
||||
- FURNACE
|
||||
- FURNACE_MINECART
|
||||
- FLETCHING_TABLE
|
||||
- GRINDSTONE
|
||||
- HOPPER
|
||||
- HOPPER_MINECART
|
||||
- ITEM_FRAME
|
||||
- JUKEBOX
|
||||
- LECTERN
|
||||
- LOOM
|
||||
- RESPAWN_ANCHOR
|
||||
- SHULKER_BOX
|
||||
- SMITHING_TABLE
|
||||
- SMOKER
|
||||
- SOUL_CAMPFIRE
|
||||
- STONECUTTER
|
||||
- TRAPPED_CHEST
|
||||
- COMMAND_BLOCK
|
||||
- STRUCTURE_BLOCK
|
||||
- JIGSAW
|
||||
RotationPlace:
|
||||
cancelvl: 5
|
||||
|
||||
# Op voorspelling gebaseerde NoSlow-controle
|
||||
# Grim is verantwoordelijk voor buggy netcode hier... moeilijk om vals te spelen, zelfs als je met rechts klikt en de offhand-knop spamt
|
||||
# Veel stabieler dan andere anticheats, maar rapporteer alsjeblieft alle falses... Ik heb hier een heleboel netcode-problemen opgelost.
|
||||
|
||||
@@ -82,52 +82,9 @@ FarPlace:
|
||||
PositionPlace:
|
||||
cancelvl: 5
|
||||
|
||||
LineOfSightPlace:
|
||||
cancelvl: 1
|
||||
# Determines whether to only run the LineOfSightPlace check on specific blocks
|
||||
# Increases performance, mainly intended for mini-game servers which already prevent block placement
|
||||
# And want to stop container or workstation access through walls
|
||||
use-block-whitelist: false
|
||||
block-whitelist:
|
||||
- ANVIL
|
||||
- BARREL
|
||||
- BEACON
|
||||
- BEEHIVE
|
||||
- BEE_NEST
|
||||
- BLAST_FURNACE
|
||||
- BREWING_STAND
|
||||
- CAMPFIRE
|
||||
- CARTOGRAPHY_TABLE
|
||||
- CHEST
|
||||
- CHEST_MINECART
|
||||
- CHIPPED_ANVIL
|
||||
- COMPOSTER
|
||||
- CRAFTING_TABLE
|
||||
- DAMAGED_ANVIL
|
||||
- DISPENSER
|
||||
- DROPPER
|
||||
- ENCHANTING_TABLE
|
||||
- ENDER_CHEST
|
||||
- FURNACE
|
||||
- FURNACE_MINECART
|
||||
- FLETCHING_TABLE
|
||||
- GRINDSTONE
|
||||
- HOPPER
|
||||
- HOPPER_MINECART
|
||||
- ITEM_FRAME
|
||||
- JUKEBOX
|
||||
- LECTERN
|
||||
- LOOM
|
||||
- RESPAWN_ANCHOR
|
||||
- SHULKER_BOX
|
||||
- SMITHING_TABLE
|
||||
- SMOKER
|
||||
- SOUL_CAMPFIRE
|
||||
- STONECUTTER
|
||||
- TRAPPED_CHEST
|
||||
- COMMAND_BLOCK
|
||||
- STRUCTURE_BLOCK
|
||||
- JIGSAW
|
||||
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
|
||||
|
||||
@@ -81,52 +81,9 @@ FarPlace:
|
||||
PositionPlace:
|
||||
cancelvl: 5
|
||||
|
||||
LineOfSightPlace:
|
||||
cancelvl: 1
|
||||
# Determines whether to only run the LineOfSightPlace check on specific blocks
|
||||
# Increases performance, mainly intended for mini-game servers which already prevent block placement
|
||||
# And want to stop container or workstation access through walls
|
||||
use-block-whitelist: false
|
||||
block-whitelist:
|
||||
- ANVIL
|
||||
- BARREL
|
||||
- BEACON
|
||||
- BEEHIVE
|
||||
- BEE_NEST
|
||||
- BLAST_FURNACE
|
||||
- BREWING_STAND
|
||||
- CAMPFIRE
|
||||
- CARTOGRAPHY_TABLE
|
||||
- CHEST
|
||||
- CHEST_MINECART
|
||||
- CHIPPED_ANVIL
|
||||
- COMPOSTER
|
||||
- CRAFTING_TABLE
|
||||
- DAMAGED_ANVIL
|
||||
- DISPENSER
|
||||
- DROPPER
|
||||
- ENCHANTING_TABLE
|
||||
- ENDER_CHEST
|
||||
- FURNACE
|
||||
- FURNACE_MINECART
|
||||
- FLETCHING_TABLE
|
||||
- GRINDSTONE
|
||||
- HOPPER
|
||||
- HOPPER_MINECART
|
||||
- ITEM_FRAME
|
||||
- JUKEBOX
|
||||
- LECTERN
|
||||
- LOOM
|
||||
- RESPAWN_ANCHOR
|
||||
- SHULKER_BOX
|
||||
- SMITHING_TABLE
|
||||
- SMOKER
|
||||
- SOUL_CAMPFIRE
|
||||
- STONECUTTER
|
||||
- TRAPPED_CHEST
|
||||
- COMMAND_BLOCK
|
||||
- STRUCTURE_BLOCK
|
||||
- JIGSAW
|
||||
RotationPlace:
|
||||
cancelvl: 5
|
||||
|
||||
# Основанная на предсказаниях проверка на отсутствие замедления
|
||||
# Grim учитывает баги неткода здесь... трудно ошибиться, даже если спамить правым кликом и кнопкой оффхенд.
|
||||
# Намного стабильнее, чем другие античиты, но, пожалуйста, сообщайте о любых фейлах... Я исправил тонну проблем с неткодом.
|
||||
|
||||
@@ -81,52 +81,8 @@ FarPlace:
|
||||
PositionPlace:
|
||||
cancelvl: 5
|
||||
|
||||
LineOfSightPlace:
|
||||
cancelvl: 1
|
||||
# Determines whether to only run the LineOfSightPlace check on specific blocks
|
||||
# Increases performance, mainly intended for mini-game servers which already prevent block placement
|
||||
# And want to stop container or workstation access through walls
|
||||
use-block-whitelist: false
|
||||
block-whitelist:
|
||||
- ANVIL
|
||||
- BARREL
|
||||
- BEACON
|
||||
- BEEHIVE
|
||||
- BEE_NEST
|
||||
- BLAST_FURNACE
|
||||
- BREWING_STAND
|
||||
- CAMPFIRE
|
||||
- CARTOGRAPHY_TABLE
|
||||
- CHEST
|
||||
- CHEST_MINECART
|
||||
- CHIPPED_ANVIL
|
||||
- COMPOSTER
|
||||
- CRAFTING_TABLE
|
||||
- DAMAGED_ANVIL
|
||||
- DISPENSER
|
||||
- DROPPER
|
||||
- ENCHANTING_TABLE
|
||||
- ENDER_CHEST
|
||||
- FURNACE
|
||||
- FURNACE_MINECART
|
||||
- FLETCHING_TABLE
|
||||
- GRINDSTONE
|
||||
- HOPPER
|
||||
- HOPPER_MINECART
|
||||
- ITEM_FRAME
|
||||
- JUKEBOX
|
||||
- LECTERN
|
||||
- LOOM
|
||||
- RESPAWN_ANCHOR
|
||||
- SHULKER_BOX
|
||||
- SMITHING_TABLE
|
||||
- SMOKER
|
||||
- SOUL_CAMPFIRE
|
||||
- STONECUTTER
|
||||
- TRAPPED_CHEST
|
||||
- COMMAND_BLOCK
|
||||
- STRUCTURE_BLOCK
|
||||
- JIGSAW
|
||||
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
|
||||
|
||||
@@ -82,52 +82,8 @@ FarPlace:
|
||||
PositionPlace:
|
||||
cancelvl: 5
|
||||
|
||||
LineOfSightPlace:
|
||||
cancelvl: 1
|
||||
# Determines whether to only run the LineOfSightPlace check on specific blocks
|
||||
# Increases performance, mainly intended for mini-game servers which already prevent block placement
|
||||
# And want to stop container or workstation access through walls
|
||||
use-block-whitelist: false
|
||||
block-whitelist:
|
||||
- ANVIL
|
||||
- BARREL
|
||||
- BEACON
|
||||
- BEEHIVE
|
||||
- BEE_NEST
|
||||
- BLAST_FURNACE
|
||||
- BREWING_STAND
|
||||
- CAMPFIRE
|
||||
- CARTOGRAPHY_TABLE
|
||||
- CHEST
|
||||
- CHEST_MINECART
|
||||
- CHIPPED_ANVIL
|
||||
- COMPOSTER
|
||||
- CRAFTING_TABLE
|
||||
- DAMAGED_ANVIL
|
||||
- DISPENSER
|
||||
- DROPPER
|
||||
- ENCHANTING_TABLE
|
||||
- ENDER_CHEST
|
||||
- FURNACE
|
||||
- FURNACE_MINECART
|
||||
- FLETCHING_TABLE
|
||||
- GRINDSTONE
|
||||
- HOPPER
|
||||
- HOPPER_MINECART
|
||||
- ITEM_FRAME
|
||||
- JUKEBOX
|
||||
- LECTERN
|
||||
- LOOM
|
||||
- RESPAWN_ANCHOR
|
||||
- SHULKER_BOX
|
||||
- SMITHING_TABLE
|
||||
- SMOKER
|
||||
- SOUL_CAMPFIRE
|
||||
- STONECUTTER
|
||||
- TRAPPED_CHEST
|
||||
- COMMAND_BLOCK
|
||||
- STRUCTURE_BLOCK
|
||||
- JIGSAW
|
||||
RotationPlace:
|
||||
cancelvl: 5
|
||||
|
||||
# 使用模拟移动进行的NoSlow(使用物品时不会减速)检查
|
||||
# 在这里解释错误的服务器代码......即使在发送垃圾数据包时右键单击和副手按钮也很分辨
|
||||
|
||||
Reference in new issue
Block a user