Initial packet experiment

This commit is contained in:
themode 2022-02-17 17:52:30 +01:00
parent 9b04e89552
commit adb426bcf1
4 changed files with 170 additions and 1 deletions

View File

@ -9,6 +9,7 @@ import net.minestom.demo.commands.*;
import net.minestom.server.MinecraftServer;
import net.minestom.server.command.CommandManager;
import net.minestom.server.event.server.ServerListPingEvent;
import net.minestom.server.extras.ac.AntiCheat;
import net.minestom.server.extras.lan.OpenToLAN;
import net.minestom.server.extras.lan.OpenToLANConfig;
import net.minestom.server.extras.optifine.OptifineSupport;
@ -94,6 +95,8 @@ public class Main {
//responseData.setPlayersHidden(true);
});
AntiCheat.enable();
PlayerInit.init();
OptifineSupport.enable();

View File

@ -0,0 +1,66 @@
package net.minestom.server.extras.ac;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Player;
import net.minestom.server.event.player.PlayerPacketEvent;
import net.minestom.server.event.player.PlayerPacketOutEvent;
import net.minestom.server.utils.PacketUtils;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
public final class AntiCheat {
private static final VarHandle ENABLED;
static {
try {
ENABLED = MethodHandles.lookup().findStaticVarHandle(AntiCheat.class, "enabled", boolean.class);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
@SuppressWarnings("unused")
private static boolean enabled;
private static final Cache<Player, ClientContext> CONTEXT = Caffeine.newBuilder().weakKeys().build();
public static void enable() {
if (PacketUtils.VIEWABLE_PACKET)
throw new IllegalStateException("Minestom anti-cheat is incompatible with the viewable packet feature.");
if (!ENABLED.compareAndSet(false, true))
MinecraftServer.LOGGER.warn("Minestom anti-cheat is already enabled.");
var eventHandler = MinecraftServer.getGlobalEventHandler();
eventHandler.addListener(PlayerPacketEvent.class, event -> {
var context = CONTEXT.get(event.getPlayer(), player -> new ClientContext());
context.queue.relaxedOffer(event.getPacket());
});
eventHandler.addListener(PlayerPacketOutEvent.class, event -> {
var context = CONTEXT.get(event.getPlayer(), player -> new ClientContext());
context.queue.relaxedOffer(event.getPacket());
});
Thread thread = new Thread(() -> {
while (true) {
try {
CONTEXT.asMap().forEach((player, context) -> {
try {
context.process();
} catch (Exception e) {
e.printStackTrace();
}
});
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "Ms-Watchdog");
thread.setDaemon(true);
thread.start();
}
}

View File

@ -0,0 +1,100 @@
package net.minestom.server.extras.ac;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.network.packet.client.play.ClientPlayerPositionAndRotationPacket;
import net.minestom.server.network.packet.client.play.ClientPlayerPositionPacket;
import net.minestom.server.network.packet.client.play.ClientSettingsPacket;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.play.ChunkDataPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.chunk.ChunkUtils;
import org.jctools.queues.MpscUnboundedXaddArrayQueue;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
final class ClientContext {
final MpscUnboundedXaddArrayQueue<Object> queue = new MpscUnboundedXaddArrayQueue<>(1024);
private final Map<Class<?>, Consumer<ClientPacket>> clientHandler = new HashMap<>();
private final Map<Class<?>, Consumer<ServerPacket>> serverHandler = new HashMap<>();
private Pos position;
private ClientSettingsPacket lastSettings;
private final Long2ObjectMap<Chunk> visibleChunks = new Long2ObjectOpenHashMap<>();
public ClientContext() {
registerClientPacket(ClientSettingsPacket.class, this::handleClientSettings);
registerClientPacket(ClientPlayerPositionAndRotationPacket.class, packet -> handleMovement(packet.position()));
registerClientPacket(ClientPlayerPositionPacket.class, packet -> handleMovement(packet.position()));
registerServerPacket(ChunkDataPacket.class, this::handleChunkData);
}
synchronized void process() {
this.queue.drain(e -> {
if (e instanceof ClientPacket) {
handleClient((ClientPacket) e);
} else if (e instanceof ServerPacket) {
handleServer((ServerPacket) e);
} else {
throw new IllegalArgumentException("Unknown packet type: " + e.getClass().getSimpleName());
}
});
}
private void handleClient(ClientPacket packet) {
var handler = clientHandler.get(packet.getClass());
if (handler != null) {
handler.accept(packet);
} else {
System.out.println("client " + packet.getClass().getSimpleName());
}
}
private void handleClientSettings(ClientSettingsPacket settings) {
this.lastSettings = settings;
}
private void handleMovement(Point position) {
this.position = position instanceof Pos pos ? pos : this.position.withCoord(position);
}
private void handleServer(ServerPacket packet) {
var handler = serverHandler.get(packet.getClass());
if (handler != null) {
handler.accept(packet);
} else {
System.out.println("server " + packet.getClass().getSimpleName());
}
}
private void handleChunkData(ChunkDataPacket chunkDataPacket) {
final long index = ChunkUtils.getChunkIndex(chunkDataPacket.chunkX(), chunkDataPacket.chunkZ());
this.visibleChunks.put(index, new Chunk(chunkDataPacket));
}
private <T> void registerClientPacket(Class<T> packetClass, Consumer<T> consumer) {
this.clientHandler.put(packetClass, (Consumer<ClientPacket>) consumer);
}
private <T> void registerServerPacket(Class<T> packetClass, Consumer<T> consumer) {
this.serverHandler.put(packetClass, (Consumer<ServerPacket>) consumer);
}
final class Chunk {
int x, z;
Chunk(ChunkDataPacket packet) {
var chunk = packet.chunkData();
var chunkData = chunk.data();
var reader = new BinaryReader(chunkData);
}
}
}

View File

@ -51,7 +51,7 @@ public final class PacketUtils {
public static final boolean GROUPED_PACKET = getBoolean("minestom.grouped-packet", true);
public static final boolean CACHED_PACKET = getBoolean("minestom.cached-packet", true);
public static final boolean VIEWABLE_PACKET = getBoolean("minestom.viewable-packet", true);
public static final boolean VIEWABLE_PACKET = getBoolean("minestom.viewable-packet", false);
// Viewable packets
private static final Cache<Viewable, ViewableStorage> VIEWABLE_STORAGE_MAP = Caffeine.newBuilder().weakKeys().build();