Move over identified packages from old impl

This commit is contained in:
Manuel Frohn
2026-05-13 15:33:08 +02:00
parent 164a7f5826
commit 744dc67ca9
2 changed files with 128 additions and 0 deletions
@@ -38,6 +38,7 @@ dependencies {
compileOnly(libs.netty)
compileOnly(libs.authlib)
compileOnly(libs.fastutil)
compileOnly(libs.nms21)
implementation(libs.anvilgui)
}
@@ -0,0 +1,127 @@
package de.steamwar.techhider;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import com.comphenix.tinyprotocol.TinyProtocol;
import io.netty.channel.Channel;
import net.minecraft.network.PacketListener;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.common.ClientCommonPacketListener;
import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket;
import net.minecraft.network.protocol.common.ClientboundKeepAlivePacket;
import net.minecraft.network.protocol.common.ClientboundPingPacket;
import net.minecraft.network.protocol.game.ClientboundBlockChangedAckPacket;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.network.protocol.game.ClientboundBlockEventPacket;
import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
import net.minecraft.network.protocol.game.ClientboundBossEventPacket;
import net.minecraft.network.protocol.game.ClientboundClearTitlesPacket;
import net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket;
import net.minecraft.network.protocol.game.ClientboundCommandsPacket;
import net.minecraft.network.protocol.game.ClientboundDisguisedChatPacket;
import net.minecraft.network.protocol.game.ClientboundGameEventPacket;
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket;
import net.minecraft.network.protocol.game.ClientboundPlayerChatPacket;
import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket;
import net.minecraft.network.protocol.game.ClientboundServerDataPacket;
import net.minecraft.network.protocol.game.ClientboundSetDefaultSpawnPositionPacket;
import net.minecraft.network.protocol.game.ClientboundSetExperiencePacket;
import net.minecraft.network.protocol.game.ClientboundSetHealthPacket;
import net.minecraft.network.protocol.game.ClientboundSetSubtitleTextPacket;
import net.minecraft.network.protocol.game.ClientboundSetTimePacket;
import net.minecraft.network.protocol.game.ClientboundSetTitleTextPacket;
import net.minecraft.network.protocol.game.ClientboundSetTitlesAnimationPacket;
import net.minecraft.network.protocol.game.ClientboundSystemChatPacket;
import net.minecraft.network.protocol.game.ClientboundTabListPacket;
import net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket;
import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket;
import net.minecraft.network.protocol.login.ClientboundHelloPacket;
import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket;
import net.minecraft.network.protocol.login.ClientboundLoginFinishedPacket;
/**
* The TechHider follows the default-deny security principle,
* any packet must be explicitly whitelisted or processed in a
* way that is also compliant with the principle of default-deny.
*/
public class TechHiderUpdated {
private final Set<Class<? extends Packet<? extends PacketListener>>> bypassingPackets;
private final Map<Class<? extends Packet<? extends PacketListener>>, BiFunction<Player, Packet<? extends PacketListener>, Packet<? extends PacketListener>>> packetProcessors;
private final TinyProtocol interceptor;
public TechHiderUpdated(Plugin plugin) {
this.bypassingPackets = Set.of(
// --- Handshake & Login Protocol ---
// These must be whitelisted to allow the player to actually reach the 'Play'
// state
ClientboundHelloPacket.class, // Encryption request
ClientboundLoginFinishedPacket.class, // Login Success
ClientboundLoginCompressionPacket.class, // Set Compression
ClientboundCustomQueryPacket.class, // Velocity/Bungee/Mod identity checks
// --- Protocol & Connection ---
ClientboundKeepAlivePacket.class,
ClientboundPingPacket.class,
ClientboundCustomPayloadPacket.class,
ClientboundServerDataPacket.class,
// --- UI & Communication ---
ClientboundSystemChatPacket.class,
ClientboundDisguisedChatPacket.class,
ClientboundBossEventPacket.class,
ClientboundTabListPacket.class,
ClientboundSetTitleTextPacket.class,
ClientboundSetSubtitleTextPacket.class,
ClientboundSetTitlesAnimationPacket.class,
ClientboundClearTitlesPacket.class,
ClientboundPlayerChatPacket.class,
// --- Player Stats & Logic ---
ClientboundSetExperiencePacket.class,
ClientboundSetHealthPacket.class,
ClientboundPlayerAbilitiesPacket.class,
ClientboundUpdateAttributesPacket.class,
ClientboundCommandSuggestionsPacket.class,
// --- World Metadata (Non-Structural) ---
ClientboundSetTimePacket.class,
ClientboundSetDefaultSpawnPositionPacket.class,
ClientboundGameEventPacket.class, // Weather, Gamemode changes, etc.
ClientboundCommandsPacket.class // Command tree for tab-complete
);
BiFunction<Player, Packet<? extends PacketListener>, Packet<? extends PacketListener>> tossPacket = (p, packet) -> null;
this.packetProcessors = Map.of(
ClientboundBlockEventPacket.class, tossPacket,
ClientboundBlockUpdatePacket.class, tossPacket,
ClientboundBlockEntityDataPacket.class, tossPacket,
ClientboundSectionBlocksUpdatePacket.class, tossPacket,
ClientboundLevelChunkWithLightPacket.class, tossPacket
);
this.interceptor = new TinyProtocol(plugin) {
@Override
public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) {
if (bypassingPackets.stream().anyMatch(clazz -> clazz.isInstance(packet))) {
return packet;
}
else if (packetProcessors.containsKey(packet.getClass())) {
return packetProcessors.get(packet.getClass()).apply(receiver, (Packet<? extends PacketListener>) packet);
}
else {
return null;
}
}
};
}
}