SteamWar/FightSystem
Archiviert
13
1

WIP anti cheat
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful

Signed-off-by: Lixfel <agga-games@gmx.de>
Dieser Commit ist enthalten in:
Lixfel 2022-12-07 12:02:26 +01:00
Ursprung 6d574bd89d
Commit 36fd4941b5
2 geänderte Dateien mit 119 neuen und 0 gelöschten Zeilen

Datei anzeigen

@ -93,6 +93,7 @@ public class FightSystem extends JavaPlugin {
new ClickAnalyzer();
new HotbarKit.HotbarKitListener();
new OneShotStateDependent(ArenaMode.All, FightState.PreSchemSetup, () -> Fight.playSound(SWSound.BLOCK_NOTE_PLING.getSound(), 100.0f, 2.0f));
new AntiCheat();
new EnterHandler();
techHider = new TechHiderWrapper();

Datei anzeigen

@ -0,0 +1,118 @@
/*
This file is a part of the SteamWar software.
Copyright (C) 2022 SteamWar.de-Serverteam
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.listener;
import com.comphenix.tinyprotocol.Reflection;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.sql.SWException;
import de.steamwar.techhider.ProtocolUtils;
import de.steamwar.techhider.TechHider;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
public class AntiCheat {
public AntiCheat() {
TinyProtocol.instance.addFilter(teleport, this::onTeleport);
TinyProtocol.instance.addFilter(position, this::onMove);
TinyProtocol.instance.addFilter(positionLook, this::onMove);
TinyProtocol.instance.addFilter(blockDig, this::onDig);
}
private static final Class<?> flying = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInFlying");
private static final Reflection.FieldAccessor<Double> moveX = Reflection.getField(flying, double.class, 0);
private static final Reflection.FieldAccessor<Double> moveY = Reflection.getField(flying, double.class, 1);
private static final Reflection.FieldAccessor<Double> moveZ = Reflection.getField(flying, double.class, 2);
private static final Class<?> position = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInFlying$PacketPlayInPosition");
private static final Class<?> positionLook = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInFlying$PacketPlayInPositionLook");
private static final Class<?> teleport = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutPosition");
private static final Reflection.FieldAccessor<Double> tpX = Reflection.getField(teleport, double.class, 0);
private static final Reflection.FieldAccessor<Double> tpY = Reflection.getField(teleport, double.class, 1);
private static final Reflection.FieldAccessor<Double> tpZ = Reflection.getField(teleport, double.class, 2);
private final ConcurrentHashMap<Player, Movement> lastMovement = new ConcurrentHashMap<>();
private Object onTeleport(Player player, Object packet) {
//TODO Possible false flag through crouching into forbidden area?
//TODO circumvention through fast consecutive movements? (checks are synchronous)
//TODO uncertainty through moving pistons/desync etc.? (slow limit with timer to check for occurances?)
//TODO: Clearing with movement events?
Movement last = lastMovement.get(player);
if(last != null && tpX.get(packet) == last.x && tpY.get(packet) == last.y && tpZ.get(packet) == last.z) {
FightSystem.getPlugin().getLogger().log(Level.INFO, player.getName() + " was backported after small movement");
}
return packet;
}
private Object onMove(Player player, Object packet) {
//TODO Idee: Messung kleiner Movements, bei nächstem Movement mit folgendem Teleport für illegal movement trigger
Location location = player.getLocation();
double x = moveX.get(packet);
double dx = x - location.getX();
double y = moveY.get(packet);
double dy = x - location.getY();
double z = moveZ.get(packet);
double dz = z - location.getZ();
double lSqared = dx*dx + dy*dy + dz*dz;
lastMovement.compute(player, (p, previous) -> {
if(lSqared <= 0.00390625) {
return new Movement(x, y, z);
} else if(previous != null && previous.last) {
previous.last = false;
return previous;
}
return null;
});
return packet;
}
private static final Class<?> blockDig = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInBlockDig");
private static final Reflection.FieldAccessor<?> digPosition = Reflection.getField(blockDig, TechHider.blockPosition, 0);
private Object onDig(Player player, Object packet) {
Object pos = digPosition.get(packet);
int x = TechHider.blockPositionX.get(pos);
int z = TechHider.blockPositionZ.get(pos);
if(!player.getWorld().isChunkLoaded(ProtocolUtils.posToChunk(x), ProtocolUtils.posToChunk(z))) {
Bukkit.getScheduler().runTask(FightSystem.getPlugin(), () -> player.kickPlayer(null));
SWException.log(player.getName() + " tried to dig an unloaded block", "");
return null;
}
return packet;
}
private static class Movement {
private final double x;
private final double y;
private final double z;
private boolean last;
private Movement(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
last = true;
}
}
}