mirror of https://github.com/Minestom/Minestom.git
Initial packet experiment
This commit is contained in:
parent
9b04e89552
commit
adb426bcf1
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue