diff --git a/build.gradle b/build.gradle index da3523496..4d1c7a86a 100644 --- a/build.gradle +++ b/build.gradle @@ -139,7 +139,7 @@ dependencies { shade("com.github.rfresh2.Discord4j:discord4j-core:33c208f6ac") { exclude group: 'io.netty' } - shade("com.github.rfresh2:MCProtocolLib:82ec73716d") { + shade("com.github.rfresh2:MCProtocolLib:4d1be8669e") { exclude group: 'io.netty.incubator' exclude group: 'io.netty' } diff --git a/src/main/java/com/zenith/Shared.java b/src/main/java/com/zenith/Shared.java index 70c301db1..3765ecbf0 100644 --- a/src/main/java/com/zenith/Shared.java +++ b/src/main/java/com/zenith/Shared.java @@ -4,33 +4,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.github.steveice10.mc.protocol.MinecraftConstants; -import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundCustomPayloadPacket; -import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundKeepAlivePacket; -import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundPingPacket; -import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket; -import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundClientInformationPacket; -import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundKeepAlivePacket; -import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundPongPacket; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.*; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.*; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.*; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddEntityPacket; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddExperienceOrbPacket; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddPlayerPacket; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.*; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.*; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.border.ClientboundInitializeBorderPacket; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.title.ClientboundSetActionBarTextPacket; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.title.ClientboundSetSubtitleTextPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatCommandPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundClientCommandPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClickPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundMoveVehiclePacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundTeleportToEntityPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.*; -import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundGameProfilePacket; -import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundHelloPacket; import com.google.common.io.Files; import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.gson.Gson; @@ -48,35 +21,7 @@ import com.zenith.feature.tps.TPSCalculator; import com.zenith.feature.whitelist.WhitelistManager; import com.zenith.module.ModuleManager; -import com.zenith.network.client.ClientSession; -import com.zenith.network.client.handler.incoming.*; -import com.zenith.network.client.handler.incoming.entity.*; -import com.zenith.network.client.handler.incoming.inventory.*; -import com.zenith.network.client.handler.incoming.level.*; -import com.zenith.network.client.handler.incoming.spawn.AddEntityHandler; -import com.zenith.network.client.handler.incoming.spawn.AddExperienceOrbHandler; -import com.zenith.network.client.handler.incoming.spawn.AddPlayerHandler; -import com.zenith.network.client.handler.incoming.spawn.SpawnPositionHandler; -import com.zenith.network.client.handler.outgoing.OutgoingChatHandler; -import com.zenith.network.client.handler.outgoing.OutgoingContainerClickHandler; -import com.zenith.network.client.handler.postoutgoing.*; -import com.zenith.network.registry.HandlerRegistry; -import com.zenith.network.server.ServerConnection; import com.zenith.network.server.handler.player.InGameCommandManager; -import com.zenith.network.server.handler.player.incoming.*; -import com.zenith.network.server.handler.player.outgoing.SystemChatOutgoingHandler; -import com.zenith.network.server.handler.player.postoutgoing.LoginPostHandler; -import com.zenith.network.server.handler.shared.incoming.HelloHandler; -import com.zenith.network.server.handler.shared.incoming.KeepAliveHandler; -import com.zenith.network.server.handler.shared.outgoing.GameProfileOutgoingHandler; -import com.zenith.network.server.handler.shared.outgoing.PingOutgoingHandler; -import com.zenith.network.server.handler.shared.outgoing.ServerTablistDataOutgoingHandler; -import com.zenith.network.server.handler.spectator.incoming.*; -import com.zenith.network.server.handler.spectator.incoming.movement.PlayerPositionRotationSpectatorHandler; -import com.zenith.network.server.handler.spectator.incoming.movement.PlayerPositionSpectatorHandler; -import com.zenith.network.server.handler.spectator.incoming.movement.PlayerRotationSpectatorHandler; -import com.zenith.network.server.handler.spectator.outgoing.*; -import com.zenith.network.server.handler.spectator.postoutgoing.LoginSpectatorPostHandler; import com.zenith.terminal.TerminalManager; import com.zenith.util.Config; import com.zenith.util.LaunchConfig; @@ -153,160 +98,6 @@ public static boolean isReconnectableDisconnect(final String reason) { public static final VcApi VC_API; public static volatile boolean SHOULD_RECONNECT; - public static final HandlerRegistry SERVER_PLAYER_HANDLERS = new HandlerRegistry.Builder() - .setLogger(SERVER_LOG) - .allowUnhandled(true) - // - // Inbound packets - // - .registerInbound(ServerboundHelloPacket.class, new HelloHandler()) - .registerInbound(ServerboundKeepAlivePacket.class, new KeepAliveHandler()) - .registerInbound(ServerboundChatCommandPacket.class, new ChatCommandHandler()) - .registerInbound(ServerboundChatPacket.class, new ChatHandler()) - .registerInbound(ServerboundClientInformationPacket.class, new ClientInformationHandler()) - .registerInbound(ServerboundPongPacket.class, new PongHandler()) - .registerInbound(ServerboundClientCommandPacket.class, new ClientCommandHandler()) - // - // Outbound packets - // - .registerOutbound(ClientboundGameProfilePacket.class, new GameProfileOutgoingHandler()) - .registerOutbound(ClientboundPingPacket.class, new PingOutgoingHandler()) - .registerOutbound(ClientboundTabListPacket.class, new ServerTablistDataOutgoingHandler()) - .registerOutbound(ClientboundSystemChatPacket.class, new SystemChatOutgoingHandler()) - // - // Post-outbound packets - // - .registerPostOutbound(ClientboundLoginPacket.class, new LoginPostHandler()) - .build(); - public static final HandlerRegistry SERVER_SPECTATOR_HANDLERS = new HandlerRegistry.Builder() - .setLogger(SERVER_LOG) - .allowUnhandled(false) - - .registerInbound(ServerboundHelloPacket.class, new HelloHandler()) - .registerInbound(ServerboundKeepAlivePacket.class, new KeepAliveHandler()) - .registerInbound(ServerboundPongPacket.class, new SpectatorPongHandler()) - .registerInbound(ServerboundMovePlayerPosRotPacket.class, new PlayerPositionRotationSpectatorHandler()) - .registerInbound(ServerboundMovePlayerPosPacket.class, new PlayerPositionSpectatorHandler()) - .registerInbound(ServerboundMovePlayerRotPacket.class, new PlayerRotationSpectatorHandler()) - .registerInbound(ServerboundChatPacket.class, new ServerChatSpectatorHandler()) - .registerInbound(ServerboundPlayerCommandPacket.class, new PlayerCommandSpectatorHandler()) - .registerInbound(ServerboundTeleportToEntityPacket.class, new TeleportToEntitySpectatorHandler()) - .registerInbound(ServerboundInteractPacket.class, new InteractEntitySpectatorHandler()) - - .registerOutbound(ClientboundGameProfilePacket.class, new GameProfileOutgoingHandler()) - .registerOutbound(ClientboundPingPacket.class, new PingOutgoingHandler()) - - .registerOutbound(ClientboundContainerClosePacket.class, new ContainerCloseSpectatorOutgoingHandler()) - .registerOutbound(ClientboundContainerSetContentPacket.class, new ContainerSetContentSpectatorOutgoingHandler()) - .registerOutbound(ClientboundPlaceGhostRecipePacket.class, new PlaceGhostRecipeSpectatorOutgoingHandler()) - .registerOutbound(ClientboundOpenScreenPacket.class, new OpenScreenSpectatorOutgoingHandler()) - .registerOutbound(ClientboundSetCarriedItemPacket.class, new SetCarriedItemSpectatorOutgoingHandler()) - .registerOutbound(ClientboundSetHealthPacket.class, new SetHealthSpectatorOutgoingHandler()) - .registerOutbound(ClientboundPlayerPositionPacket.class, new PlayerPositionSpectatorOutgoingHandler()) - .registerOutbound(ClientboundSetExperiencePacket.class, new SetExperienceSpectatorOutgoingHandler()) - .registerOutbound(ClientboundOpenBookPacket.class, new OpenBookSpectatorOutgoingHandler()) - .registerOutbound(ClientboundContainerSetSlotPacket.class, new ContainerSetSlotSpectatorOutgoingHandler()) - .registerOutbound(ClientboundGameEventPacket.class, new GameEventSpectatorOutgoingHandler()) - .registerOutbound(ClientboundMoveVehiclePacket.class, new MoveVehicleSpectatorOutgoingHandler()) - .registerOutbound(ClientboundHorseScreenOpenPacket.class, new HorseScreenOpenSpectatorOutgoingHandler()) - .registerOutbound(ClientboundContainerSetDataPacket.class, new ContainerSetDataSpectatorOutgoingHandler()) - .registerOutbound(ClientboundTabListPacket.class, new ServerTablistDataOutgoingHandler()) - .registerOutbound(ClientboundPlayerAbilitiesPacket.class, new PlayerAbilitiesSpectatorOutgoingHandler()) - .registerOutbound(ClientboundRespawnPacket.class, new RespawnSpectatorOutgoingPacket()) - - .registerPostOutbound(ClientboundLoginPacket.class, new LoginSpectatorPostHandler()) - .build(); - - public static final HandlerRegistry CLIENT_HANDLERS = new HandlerRegistry.Builder() - .setLogger(CLIENT_LOG) - .allowUnhandled(true) - // - // Inbound packets - // - .registerInbound(ClientboundUpdateAdvancementsPacket.class, new UpdateAdvancementsHandler()) - .registerInbound(ClientboundBlockUpdatePacket.class, new BlockUpdateHandler()) - .registerInbound(ClientboundChunkBatchFinishedPacket.class, new ChunkBatchFinishedHandler()) - .registerInbound(ClientboundChangeDifficultyPacket.class, new ChangeDifficultyHandler()) - .registerInbound(ClientboundBossEventPacket.class, new BossEventHandler()) - .registerInbound(ClientboundChunksBiomesPacket.class, new ChunksBiomesHandler()) - .registerInbound(ClientboundSystemChatPacket.class, new SystemChatHandler()) - .registerInbound(ClientboundPlayerChatPacket.class, new PlayerChatHandler()) - .registerInbound(ClientboundLevelChunkWithLightPacket.class, new LevelChunkWithLightHandler()) - .registerInbound(ClientboundLightUpdatePacket.class, new LightUpdateHandler()) - .registerInbound(ClientboundKeepAlivePacket.class, new ClientKeepaliveHandler()) - .registerInbound(ClientboundCommandsPacket.class, new CommandsHandler()) - .registerInbound(ClientboundGameEventPacket.class, new GameEventHandler()) - .registerInbound(ClientboundLoginPacket.class, new LoginHandler()) - .registerInbound(ClientboundGameProfilePacket.class, new GameProfileHandler()) - .registerInbound(ClientboundSectionBlocksUpdatePacket.class, new SectionBlocksUpdateHandler()) - .registerInbound(ClientboundSetCarriedItemPacket.class, new SetCarriedItemHandler()) - .registerInbound(ClientboundSetChunkCacheCenterPacket.class, new SetChunkCacheCenterHandler()) - .registerInbound(ClientboundSetChunkCacheRadiusPacket.class, new SetChunkCacheRadiusHandler()) - .registerInbound(ClientboundSetSimulationDistancePacket.class, new SetSimulationDistanceHandler()) - .registerInbound(ClientboundSetHealthPacket.class, new SetHealthHandler()) - .registerInbound(ClientboundSetSubtitleTextPacket.class, new SetSubtitleTextHandler()) - .registerInbound(ClientboundPlayerPositionPacket.class, new PlayerPositionHandler()) - .registerInbound(ClientboundSoundPacket.class, new SoundHandler()) - .registerInbound(ClientboundSetExperiencePacket.class, new SetExperienceHandler()) - .registerInbound(ClientboundRespawnPacket.class, new RespawnHandler()) - .registerInbound(ClientboundContainerSetSlotPacket.class, new ContainerSetSlotHandler()) - .registerInbound(ClientboundContainerSetContentPacket.class, new ContainerSetContentHandler()) - .registerInbound(ClientboundAwardStatsPacket.class, new AwardStatsHandler()) - .registerInbound(ClientboundTabListPacket.class, new TabListDataHandler()) - .registerInbound(ClientboundUpdateEnabledFeaturesPacket.class, new UpdateEnabledFeaturesHandler()) - .registerInbound(ClientboundPlayerInfoUpdatePacket.class, new PlayerInfoUpdateHandler()) - .registerInbound(ClientboundExplodePacket.class, new ExplodeHandler()) - .registerInbound(ClientboundPlayerInfoRemovePacket.class, new PlayerInfoRemoveHandler()) - .registerInbound(ClientboundSetActionBarTextPacket.class, new SetActionBarTextHandler()) - .registerInbound(ClientboundSetEntityMotionPacket.class, new SetEntityMotionHandler()) - .registerInbound(ClientboundForgetLevelChunkPacket.class, new ForgetLevelChunkHandler()) - .registerInbound(ClientboundUpdateRecipesPacket.class, new SyncRecipesHandler()) - .registerInbound(ClientboundUpdateTagsPacket.class, new UpdateTagsHandler()) - .registerInbound(ClientboundInitializeBorderPacket.class, new WorldBorderInitializeHandler()) - .registerInbound(ClientboundBlockEntityDataPacket.class, new BlockEntityDataHandler()) - .registerInbound(ClientboundSetTimePacket.class, new SetTimeHandler()) - .registerInbound(ClientboundPlayerCombatKillPacket.class, new PlayerCombatKillHandler()) - .registerInbound(ClientboundMapItemDataPacket.class, new MapDataHandler()) - .registerInbound(ClientboundPingPacket.class, new PingHandler()) - .registerInbound(ClientboundPlayerAbilitiesPacket.class, new PlayerAbilitiesHandler()) - .registerInbound(ClientboundCustomPayloadPacket.class, new CustomPayloadHandler()) - .registerInbound(ClientboundRecipePacket.class, new UnlockRecipeHandler()) - //ENTITY - .registerInbound(ClientboundEntityEventPacket.class, new EntityEventHandler()) - .registerInbound(ClientboundSetEntityLinkPacket.class, new SetEntityLinkHandler()) - .registerInbound(ClientboundTakeItemEntityPacket.class, new TakeItemEntityHandler()) - .registerInbound(ClientboundRemoveEntitiesPacket.class, new RemoveEntitiesHandler()) - .registerInbound(ClientboundUpdateMobEffectPacket.class, new UpdateMobEffectHandler()) - .registerInbound(ClientboundRemoveMobEffectPacket.class, new RemoveMobEffectHandler()) - .registerInbound(ClientboundSetEquipmentPacket.class, new SetEquipmentHandler()) - .registerInbound(ClientboundRotateHeadPacket.class, new RotateHeadHandler()) - .registerInbound(ClientboundSetEntityDataPacket.class, new SetEntityDataHandler()) - .registerInbound(ClientboundMoveEntityPosPacket.class, new MoveEntityPosHandler()) - .registerInbound(ClientboundMoveEntityPosRotPacket.class, new MoveEntityPosRotHandler()) - .registerInbound(ClientboundUpdateAttributesPacket.class, new UpdateAttributesHandler()) - .registerInbound(ClientboundMoveEntityRotPacket.class, new MoveEntityRotHandler()) - .registerInbound(ClientboundMoveVehiclePacket.class, new MoveVehicleHandler()) - .registerInbound(ClientboundSetPassengersPacket.class, new EntitySetPassengersHandler()) - .registerInbound(ClientboundTeleportEntityPacket.class, new TeleportEntityHandler()) - //SPAWN - .registerInbound(ClientboundAddExperienceOrbPacket.class, new AddExperienceOrbHandler()) - .registerInbound(ClientboundAddEntityPacket.class, new AddEntityHandler()) - .registerInbound(ClientboundAddPlayerPacket.class, new AddPlayerHandler()) - .registerInbound(ClientboundSetDefaultSpawnPositionPacket.class, new SpawnPositionHandler()) - // Outbound - .registerOutbound(ServerboundChatPacket.class, new OutgoingChatHandler()) - .registerOutbound(ServerboundContainerClickPacket.class, new OutgoingContainerClickHandler()) - //Postoutgoing - .registerPostOutbound(ServerboundMoveVehiclePacket.class, new PostOutgoingMoveVehicleHandler()) - .registerPostOutbound(ServerboundPlayerCommandPacket.class, new PostOutgoingPlayerCommandHandler()) - .registerPostOutbound(ServerboundSetCarriedItemPacket.class, new PostOutgoingSetCarriedItemHandler()) - .registerPostOutbound(ServerboundMovePlayerPosPacket.class, new PostOutgoingPlayerPositionHandler()) - .registerPostOutbound(ServerboundMovePlayerPosRotPacket.class, new PostOutgoingPlayerPositionRotationHandler()) - .registerPostOutbound(ServerboundMovePlayerRotPacket.class, new PostOutgoingPlayerRotationHandler()) - .registerPostOutbound(ServerboundMovePlayerStatusOnlyPacket.class, new PostOutgoingPlayerStatusOnlyHandler()) - .registerPostOutbound(ServerboundSwingPacket.class, new PostOutgoingSwingHandler()) - .build(); - public static synchronized void loadConfig() { try { DEFAULT_LOG.info("Loading config..."); diff --git a/src/main/java/com/zenith/cache/data/PlayerCache.java b/src/main/java/com/zenith/cache/data/PlayerCache.java index 40ddb58ea..6088a717c 100644 --- a/src/main/java/com/zenith/cache/data/PlayerCache.java +++ b/src/main/java/com/zenith/cache/data/PlayerCache.java @@ -9,7 +9,6 @@ import com.github.steveice10.mc.protocol.data.game.inventory.CreativeGrabAction; import com.github.steveice10.mc.protocol.data.game.level.notify.GameEvent; import com.github.steveice10.mc.protocol.data.game.setting.Difficulty; -import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundChangeDifficultyPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundEntityEventPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerAbilitiesPacket; @@ -33,7 +32,10 @@ import lombok.experimental.Accessors; import org.cloudburstmc.math.vector.Vector3i; -import java.util.*; +import java.util.Arrays; +import java.util.EnumMap; +import java.util.Map; +import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; @@ -71,7 +73,6 @@ public class PlayerCache implements CachedData { protected float walkSpeed; protected boolean isSneaking = false; protected boolean isSprinting = false; - protected Map> tags = new HashMap<>(); protected EntityEvent opLevel = EntityEvent.PLAYER_OP_PERMISSION_LEVEL_0; protected AtomicInteger actionId = new AtomicInteger(0); private static final MutableVec3i DEFAULT_SPAWN_POSITION = new MutableVec3i(0, 0, 0); @@ -86,7 +87,6 @@ public void getPackets(@NonNull Consumer consumer) { // todo: may need to move this out so spectators don't get sent wrong abilities consumer.accept(new ClientboundPlayerAbilitiesPacket(this.invincible, this.canFly, this.flying, this.creative, this.flySpeed, this.walkSpeed)); consumer.accept(new ClientboundChangeDifficultyPacket(this.difficulty, this.isDifficultyLocked)); - consumer.accept(new ClientboundUpdateTagsPacket(this.tags)); consumer.accept(new ClientboundGameEventPacket(GameEvent.CHANGE_GAMEMODE, this.gameMode)); consumer.accept(new ClientboundEntityEventPacket(this.thePlayer.getEntityId(), this.opLevel)); consumer.accept(new ClientboundContainerSetContentPacket(0, diff --git a/src/main/java/com/zenith/cache/data/config/ConfigurationCache.java b/src/main/java/com/zenith/cache/data/config/ConfigurationCache.java index 8fcf1f230..58f7c7f58 100644 --- a/src/main/java/com/zenith/cache/data/config/ConfigurationCache.java +++ b/src/main/java/com/zenith/cache/data/config/ConfigurationCache.java @@ -1,9 +1,9 @@ package com.zenith.cache.data.config; import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundResourcePackPushPacket; +import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundUpdateEnabledFeaturesPacket; import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket; import com.github.steveice10.mc.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket; -import com.github.steveice10.mc.protocol.packet.configuration.clientbound.ClientboundUpdateEnabledFeaturesPacket; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.packetlib.packet.Packet; import com.zenith.cache.CachedData; diff --git a/src/main/java/com/zenith/feature/spectator/SpectatorUtils.java b/src/main/java/com/zenith/feature/spectator/SpectatorUtils.java index 080f628d9..8a74fc61b 100644 --- a/src/main/java/com/zenith/feature/spectator/SpectatorUtils.java +++ b/src/main/java/com/zenith/feature/spectator/SpectatorUtils.java @@ -152,7 +152,6 @@ public static void initSpectator(ServerConnection session, Supplier handlerRegistry; + private PacketHandlerCodec codec; private final HashSet limitedConnections = new HashSet<>(); public ActionLimiter() { @@ -37,23 +39,25 @@ public ActionLimiter() { } private void initializeHandlers() { - handlerRegistry = new HandlerRegistry.Builder() + codec = PacketHandlerCodec.builder() .setLogger(MODULE_LOG) - .allowUnhandled(true) - .registerInbound(ServerboundChatCommandPacket.class, new ALChatCommandHandler()) - .registerInbound(ServerboundChatPacket.class, new ALChatHandler()) - .registerInbound(ServerboundClientCommandPacket.class, new ALClientCommandHandler()) - .registerInbound(ServerboundContainerClickPacket.class, new ALContainerClickHandler()) - .registerInbound(ServerboundInteractPacket.class, new ALInteractHandler()) - .registerInbound(ServerboundMovePlayerPosPacket.class, new ALMovePlayerPosHandler()) - .registerInbound(ServerboundMovePlayerPosRotPacket.class, new ALMovePlayerPosRotHandler()) - .registerInbound(ServerboundMoveVehiclePacket.class, new ALMoveVehicleHandler()) - .registerInbound(ServerboundPlayerActionPacket.class, new ALPlayerActionHandler()) - .registerInbound(ServerboundUseItemOnPacket.class, new ALUseItemOnHandler()) - .registerInbound(ServerboundUseItemPacket.class, new ALUseItemHandler()) - .registerOutbound(ClientboundMoveVehiclePacket.class, new ALCMoveVehicleHandler()) - .registerOutbound(ClientboundLoginPacket.class, new ALLoginHandler()) - .registerOutbound(ClientboundPlayerPositionPacket.class, new ALPlayerPositionHandler()) + .state(ProtocolState.GAME, PacketHandlerStateCodec.builder() + .allowUnhandled(true) + .registerInbound(ServerboundChatCommandPacket.class, new ALChatCommandHandler()) + .registerInbound(ServerboundChatPacket.class, new ALChatHandler()) + .registerInbound(ServerboundClientCommandPacket.class, new ALClientCommandHandler()) + .registerInbound(ServerboundContainerClickPacket.class, new ALContainerClickHandler()) + .registerInbound(ServerboundInteractPacket.class, new ALInteractHandler()) + .registerInbound(ServerboundMovePlayerPosPacket.class, new ALMovePlayerPosHandler()) + .registerInbound(ServerboundMovePlayerPosRotPacket.class, new ALMovePlayerPosRotHandler()) + .registerInbound(ServerboundMoveVehiclePacket.class, new ALMoveVehicleHandler()) + .registerInbound(ServerboundPlayerActionPacket.class, new ALPlayerActionHandler()) + .registerInbound(ServerboundUseItemOnPacket.class, new ALUseItemOnHandler()) + .registerInbound(ServerboundUseItemPacket.class, new ALUseItemHandler()) + .registerOutbound(ClientboundMoveVehiclePacket.class, new ALCMoveVehicleHandler()) + .registerOutbound(ClientboundLoginPacket.class, new ALLoginHandler()) + .registerOutbound(ClientboundPlayerPositionPacket.class, new ALPlayerPositionHandler()) + .build()) .build(); } diff --git a/src/main/java/com/zenith/network/KeepAliveTask.java b/src/main/java/com/zenith/network/KeepAliveTask.java new file mode 100644 index 000000000..55889f10d --- /dev/null +++ b/src/main/java/com/zenith/network/KeepAliveTask.java @@ -0,0 +1,26 @@ +package com.zenith.network; + +import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundKeepAlivePacket; +import com.zenith.network.server.ServerConnection; + +import java.util.concurrent.TimeUnit; + +import static com.zenith.Shared.SCHEDULED_EXECUTOR_SERVICE; + +public class KeepAliveTask implements Runnable { + private final ServerConnection session; + + public KeepAliveTask(ServerConnection session) { + this.session = session; + } + + @Override + public void run() { + if (this.session.isConnected()) { + session.setLastPingTime(System.currentTimeMillis()); + session.setLastPingId((int) session.getLastPingTime()); + this.session.sendAsync(new ClientboundKeepAlivePacket(session.getLastPingId())); + SCHEDULED_EXECUTOR_SERVICE.schedule(this, 2L, TimeUnit.SECONDS); + } + } +} diff --git a/src/main/java/com/zenith/network/UserAuthTask.java b/src/main/java/com/zenith/network/UserAuthTask.java new file mode 100644 index 000000000..2ecb85669 --- /dev/null +++ b/src/main/java/com/zenith/network/UserAuthTask.java @@ -0,0 +1,52 @@ +package com.zenith.network; + +import com.github.steveice10.mc.auth.data.GameProfile; +import com.github.steveice10.mc.auth.exception.request.RequestException; +import com.github.steveice10.mc.auth.service.SessionService; +import com.github.steveice10.mc.protocol.MinecraftConstants; +import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundLoginCompressionPacket; +import com.zenith.network.server.ServerConnection; + +import javax.crypto.SecretKey; +import java.util.UUID; + +public class UserAuthTask implements Runnable { + private ServerConnection session; + private SecretKey key; + + public UserAuthTask(ServerConnection session, SecretKey key) { + this.key = key; + this.session = session; + } + + @Override + public void run() { + GameProfile profile; + if (this.key != null) { + SessionService sessionService = this.session.getFlag(MinecraftConstants.SESSION_SERVICE_KEY, + new SessionService()); + try { + profile = sessionService.getProfileByServer(session.getUsername(), + sessionService.getServerId(session.getServerId(), + session.getKeyPair().getPublic(), + this.key)); + } catch (RequestException e) { + this.session.disconnect("Failed to make session service request.", e); + return; + } + + if (profile == null) { + this.session.disconnect("Failed to verify username."); + } + } else { + profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + session.getUsername()).getBytes()), + session.getUsername()); + } + + this.session.setFlag(MinecraftConstants.PROFILE_KEY, profile); + + int threshold = session.getFlag(MinecraftConstants.SERVER_COMPRESSION_THRESHOLD, + ServerConnection.DEFAULT_COMPRESSION_THRESHOLD); + this.session.send(new ClientboundLoginCompressionPacket(threshold)); + } +} diff --git a/src/main/java/com/zenith/network/client/ClientListener.java b/src/main/java/com/zenith/network/client/ClientListener.java index 7a1276c30..21b6189e2 100644 --- a/src/main/java/com/zenith/network/client/ClientListener.java +++ b/src/main/java/com/zenith/network/client/ClientListener.java @@ -1,61 +1,29 @@ package com.zenith.network.client; -import com.github.steveice10.mc.auth.data.GameProfile; -import com.github.steveice10.mc.auth.exception.request.InvalidCredentialsException; -import com.github.steveice10.mc.auth.exception.request.RequestException; -import com.github.steveice10.mc.auth.exception.request.ServiceUnavailableException; -import com.github.steveice10.mc.auth.service.SessionService; -import com.github.steveice10.mc.protocol.MinecraftConstants; -import com.github.steveice10.mc.protocol.MinecraftProtocol; import com.github.steveice10.mc.protocol.data.ProtocolState; -import com.github.steveice10.mc.protocol.data.UnexpectedEncryptionException; import com.github.steveice10.mc.protocol.data.handshake.HandshakeIntent; -import com.github.steveice10.mc.protocol.data.status.ServerStatusInfo; -import com.github.steveice10.mc.protocol.data.status.handler.ServerInfoHandler; -import com.github.steveice10.mc.protocol.data.status.handler.ServerPingTimeHandler; -import com.github.steveice10.mc.protocol.packet.common.clientbound.*; -import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundKeepAlivePacket; -import com.github.steveice10.mc.protocol.packet.configuration.clientbound.ClientboundFinishConfigurationPacket; -import com.github.steveice10.mc.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket; -import com.github.steveice10.mc.protocol.packet.configuration.clientbound.ClientboundUpdateEnabledFeaturesPacket; -import com.github.steveice10.mc.protocol.packet.configuration.serverbound.ServerboundFinishConfigurationPacket; import com.github.steveice10.mc.protocol.packet.handshake.serverbound.ClientIntentionPacket; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundStartConfigurationPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundConfigurationAcknowledgedPacket; -import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundGameProfilePacket; -import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundHelloPacket; -import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundLoginCompressionPacket; -import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundLoginDisconnectPacket; -import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundHelloPacket; -import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundKeyPacket; -import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundLoginAcknowledgedPacket; -import com.github.steveice10.mc.protocol.packet.status.clientbound.ClientboundPongResponsePacket; -import com.github.steveice10.mc.protocol.packet.status.clientbound.ClientboundStatusResponsePacket; -import com.github.steveice10.mc.protocol.packet.status.serverbound.ServerboundPingRequestPacket; -import com.github.steveice10.mc.protocol.packet.status.serverbound.ServerboundStatusRequestPacket; import com.github.steveice10.packetlib.Session; import com.github.steveice10.packetlib.event.session.SessionListener; import com.github.steveice10.packetlib.packet.Packet; import com.zenith.Proxy; -import com.zenith.cache.data.config.ResourcePack; import com.zenith.event.proxy.ConnectEvent; import com.zenith.event.proxy.DisconnectEvent; +import com.zenith.network.registry.ZenithHandlerCodec; import com.zenith.network.server.ServerConnection; import com.zenith.util.ComponentSerializer; +import lombok.Getter; import lombok.NonNull; import net.kyori.adventure.text.Component; import org.jetbrains.annotations.NotNull; -import javax.crypto.KeyGenerator; -import javax.crypto.SecretKey; -import java.security.NoSuchAlgorithmException; - -import static com.zenith.Shared.*; +import static com.zenith.Shared.CLIENT_LOG; +import static com.zenith.Shared.EVENT_BUS; import static java.util.Objects.isNull; +@Getter public class ClientListener implements SessionListener { @NonNull ClientSession session; - private final @NonNull ProtocolState targetState = ProtocolState.LOGIN; public ClientListener(final @NotNull ClientSession session) { this.session = session; @@ -64,10 +32,9 @@ public ClientListener(final @NotNull ClientSession session) { @Override public void packetReceived(Session session, Packet packet) { try { - defaultPacketReceived(session, packet); - if (((MinecraftProtocol) session.getPacketProtocol()).getState() != ProtocolState.GAME) return; - Packet p = CLIENT_HANDLERS.handleInbound(packet, this.session); - if (p != null) { + var state = session.getPacketProtocol().getState(); + Packet p = ZenithHandlerCodec.CLIENT_CODEC.handleInbound(packet, this.session); + if (p != null && state == ProtocolState.GAME) { for (ServerConnection connection : Proxy.getInstance().getActiveConnections()) { connection.sendAsync(packet); // sends on each connection's own event loop } @@ -78,100 +45,10 @@ public void packetReceived(Session session, Packet packet) { } } - private void defaultPacketReceived(Session session, Packet packet) { - MinecraftProtocol protocol = (MinecraftProtocol) session.getPacketProtocol(); - if (protocol.getState() == ProtocolState.LOGIN) { - if (packet instanceof ClientboundHelloPacket helloPacket) { - GameProfile profile = session.getFlag(MinecraftConstants.PROFILE_KEY); - String accessToken = session.getFlag(MinecraftConstants.ACCESS_TOKEN_KEY); - - if (profile == null || accessToken == null) { - throw new UnexpectedEncryptionException(); - } - SecretKey key; - try { - KeyGenerator gen = KeyGenerator.getInstance("AES"); - gen.init(128); - key = gen.generateKey(); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException("Failed to generate shared key.", e); - } - - SessionService sessionService = session.getFlag(MinecraftConstants.SESSION_SERVICE_KEY, new SessionService()); - String serverId = sessionService.getServerId(helloPacket.getServerId(), helloPacket.getPublicKey(), key); - try { - sessionService.joinServer(profile, accessToken, serverId); - } catch (ServiceUnavailableException e) { - session.disconnect("Login failed: Authentication service unavailable.", e); - return; - } catch (InvalidCredentialsException e) { - session.disconnect("Login failed: Invalid login session.", e); - return; - } catch (RequestException e) { - session.disconnect("Login failed: Authentication error: " + e.getMessage(), e); - return; - } - - session.send(new ServerboundKeyPacket(helloPacket.getPublicKey(), key, helloPacket.getChallenge())); - session.enableEncryption(key); - } else if (packet instanceof ClientboundGameProfilePacket) { - session.send(new ServerboundLoginAcknowledgedPacket()); - } else if (packet instanceof ClientboundLoginDisconnectPacket p) { - session.disconnect(p.getReason()); - } else if (packet instanceof ClientboundLoginCompressionPacket p) { - session.setCompressionThreshold(p.getThreshold(), false); - } - } else if (protocol.getState() == ProtocolState.STATUS) { - if (packet instanceof ClientboundStatusResponsePacket p) { - ServerStatusInfo info = p.getInfo(); - ServerInfoHandler handler = session.getFlag(MinecraftConstants.SERVER_INFO_HANDLER_KEY); - if (handler != null) { - handler.handle(session, info); - } - - session.send(new ServerboundPingRequestPacket(System.currentTimeMillis())); - } else if (packet instanceof ClientboundPongResponsePacket p) { - long time = System.currentTimeMillis() - p.getPingTime(); - ServerPingTimeHandler handler = session.getFlag(MinecraftConstants.SERVER_PING_TIME_HANDLER_KEY); - if (handler != null) { - handler.handle(session, time); - } - - session.disconnect("Finished"); - } - } else if (protocol.getState() == ProtocolState.GAME) { - if (packet instanceof ClientboundKeepAlivePacket p && session.getFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, true)) { - session.send(new ServerboundKeepAlivePacket(p.getPingId())); - } else if (packet instanceof ClientboundDisconnectPacket p) { - session.disconnect(p.getReason()); - } else if (packet instanceof ClientboundStartConfigurationPacket) { - session.send(new ServerboundConfigurationAcknowledgedPacket()); - } - } else if (protocol.getState() == ProtocolState.CONFIGURATION) { - if (packet instanceof ClientboundFinishConfigurationPacket) { - session.send(new ServerboundFinishConfigurationPacket()); - } else if (packet instanceof ClientboundRegistryDataPacket p) { - CACHE.getConfigurationCache().setRegistry(p.getRegistry()); - CACHE.getChunkCache().updateRegistryTag(p.getRegistry()); - } else if (packet instanceof ClientboundUpdateEnabledFeaturesPacket p) { - CACHE.getConfigurationCache().setEnabledFeatures(p.getFeatures()); - } else if (packet instanceof ClientboundResourcePackPushPacket p) { - CACHE.getConfigurationCache().getResourcePacks().put(p.getId(), new ResourcePack(p.getId(), p.getUrl(), p.getHash(), p.isRequired(), p.getPrompt())); - } else if (packet instanceof ClientboundResourcePackPopPacket p) { - CACHE.getConfigurationCache().getResourcePacks().remove(p.getId()); - } else if (packet instanceof ClientboundUpdateTagsPacket p) { - CACHE.getConfigurationCache().setTags(p.getTags()); - } else if (packet instanceof ClientboundCustomPayloadPacket p) { - if (p.getChannel().equalsIgnoreCase("minecraft:brand")) - CACHE.getChunkCache().setServerBrand(p.getData()); - } - } - } - @Override public Packet packetSending(final Session session, final Packet packet) { try { - return CLIENT_HANDLERS.handleOutgoing(packet, this.session); + return ZenithHandlerCodec.CLIENT_CODEC.handleOutgoing(packet, this.session); } catch (Exception e) { CLIENT_LOG.error("", e); throw new RuntimeException(e); @@ -181,35 +58,13 @@ public Packet packetSending(final Session session, final Packet packet) { @Override public void packetSent(Session session, Packet packet) { try { - defaultPacketSent(session, packet); - CLIENT_HANDLERS.handlePostOutgoing(packet, this.session); + ZenithHandlerCodec.CLIENT_CODEC.handlePostOutgoing(packet, this.session); } catch (Exception e) { CLIENT_LOG.error("", e); throw new RuntimeException(e); } } - private void defaultPacketSent(Session session, Packet packet) { - MinecraftProtocol protocol = (MinecraftProtocol) session.getPacketProtocol(); - if (packet instanceof ClientIntentionPacket) { - // Once the HandshakePacket has been sent, switch to the next protocol mode. - protocol.setState(this.targetState); - - if (this.targetState == ProtocolState.LOGIN) { - GameProfile profile = session.getFlag(MinecraftConstants.PROFILE_KEY); - session.send(new ServerboundHelloPacket(profile.getName(), profile.getId())); - } else { - session.send(new ServerboundStatusRequestPacket()); - } - } else if (packet instanceof ServerboundLoginAcknowledgedPacket) { - protocol.setState(ProtocolState.CONFIGURATION); // LOGIN -> CONFIGURATION - } else if (packet instanceof ServerboundFinishConfigurationPacket) { - protocol.setState(ProtocolState.GAME); // CONFIGURATION -> GAME - } else if (packet instanceof ServerboundConfigurationAcknowledgedPacket) { - protocol.setState(ProtocolState.CONFIGURATION); // GAME -> CONFIGURATION - } - } - @Override public boolean packetError(final Session session, final Throwable throwable) { CLIENT_LOG.debug("", throwable); @@ -220,12 +75,7 @@ public boolean packetError(final Session session, final Throwable throwable) { public void connected(final Session session) { CLIENT_LOG.info("Connected to {}!", session.getRemoteAddress()); this.session.setDisconnected(false); - MinecraftProtocol protocol = (MinecraftProtocol) session.getPacketProtocol(); - if (this.targetState == ProtocolState.LOGIN) { - session.send(new ClientIntentionPacket(protocol.getCodec().getProtocolVersion(), session.getHost(), session.getPort(), HandshakeIntent.LOGIN)); - } else if (this.targetState == ProtocolState.STATUS) { - session.send(new ClientIntentionPacket(protocol.getCodec().getProtocolVersion(), session.getHost(), session.getPort(), HandshakeIntent.STATUS)); - } + session.send(new ClientIntentionPacket(session.getPacketProtocol().getCodec().getProtocolVersion(), session.getHost(), session.getPort(), HandshakeIntent.LOGIN)); EVENT_BUS.postAsync(new ConnectEvent()); } diff --git a/src/main/java/com/zenith/network/client/ClientSession.java b/src/main/java/com/zenith/network/client/ClientSession.java index 40f07e95c..d905a3fcc 100644 --- a/src/main/java/com/zenith/network/client/ClientSession.java +++ b/src/main/java/com/zenith/network/client/ClientSession.java @@ -1,6 +1,6 @@ package com.zenith.network.client; -import com.github.steveice10.packetlib.packet.PacketProtocol; +import com.github.steveice10.mc.protocol.MinecraftProtocol; import com.github.steveice10.packetlib.tcp.TcpClientSession; import com.zenith.Proxy; import lombok.Getter; @@ -26,7 +26,7 @@ public class ClientSession extends TcpClientSession { private boolean online = false; private boolean disconnected = true; - public ClientSession(String host, int port, String bindAddress, PacketProtocol protocol, @NonNull Proxy proxy) { + public ClientSession(String host, int port, String bindAddress, MinecraftProtocol protocol, @NonNull Proxy proxy) { super(host, port, bindAddress, 0, protocol); this.proxy = proxy; this.addListener(new ClientListener(this)); diff --git a/src/main/java/com/zenith/network/client/handler/incoming/CDisconnectHandler.java b/src/main/java/com/zenith/network/client/handler/incoming/CDisconnectHandler.java new file mode 100644 index 000000000..a2ed8bc9c --- /dev/null +++ b/src/main/java/com/zenith/network/client/handler/incoming/CDisconnectHandler.java @@ -0,0 +1,13 @@ +package com.zenith.network.client.handler.incoming; + +import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundDisconnectPacket; +import com.zenith.network.client.ClientSession; +import com.zenith.network.registry.PacketHandler; + +public class CDisconnectHandler implements PacketHandler { + @Override + public ClientboundDisconnectPacket apply(final ClientboundDisconnectPacket packet, final ClientSession session) { + session.disconnect(packet.getReason()); + return null; + } +} diff --git a/src/main/java/com/zenith/network/client/handler/incoming/CFinishConfigurationHandler.java b/src/main/java/com/zenith/network/client/handler/incoming/CFinishConfigurationHandler.java new file mode 100644 index 000000000..212cd6852 --- /dev/null +++ b/src/main/java/com/zenith/network/client/handler/incoming/CFinishConfigurationHandler.java @@ -0,0 +1,14 @@ +package com.zenith.network.client.handler.incoming; + +import com.github.steveice10.mc.protocol.packet.configuration.clientbound.ClientboundFinishConfigurationPacket; +import com.github.steveice10.mc.protocol.packet.configuration.serverbound.ServerboundFinishConfigurationPacket; +import com.zenith.network.client.ClientSession; +import com.zenith.network.registry.PacketHandler; + +public class CFinishConfigurationHandler implements PacketHandler { + @Override + public ClientboundFinishConfigurationPacket apply(final ClientboundFinishConfigurationPacket packet, final ClientSession session) { + session.send(new ServerboundFinishConfigurationPacket()); + return null; + } +} diff --git a/src/main/java/com/zenith/network/client/handler/incoming/CGameProfileHandler.java b/src/main/java/com/zenith/network/client/handler/incoming/CGameProfileHandler.java new file mode 100644 index 000000000..f35b58bea --- /dev/null +++ b/src/main/java/com/zenith/network/client/handler/incoming/CGameProfileHandler.java @@ -0,0 +1,14 @@ +package com.zenith.network.client.handler.incoming; + +import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundGameProfilePacket; +import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundLoginAcknowledgedPacket; +import com.zenith.network.client.ClientSession; +import com.zenith.network.registry.PacketHandler; + +public class CGameProfileHandler implements PacketHandler { + @Override + public ClientboundGameProfilePacket apply(final ClientboundGameProfilePacket packet, final ClientSession session) { + session.send(new ServerboundLoginAcknowledgedPacket()); + return null; + } +} diff --git a/src/main/java/com/zenith/network/client/handler/incoming/CHelloHandler.java b/src/main/java/com/zenith/network/client/handler/incoming/CHelloHandler.java new file mode 100644 index 000000000..b282ce62a --- /dev/null +++ b/src/main/java/com/zenith/network/client/handler/incoming/CHelloHandler.java @@ -0,0 +1,60 @@ +package com.zenith.network.client.handler.incoming; + +import com.github.steveice10.mc.auth.data.GameProfile; +import com.github.steveice10.mc.auth.exception.request.InvalidCredentialsException; +import com.github.steveice10.mc.auth.exception.request.RequestException; +import com.github.steveice10.mc.auth.exception.request.ServiceUnavailableException; +import com.github.steveice10.mc.auth.service.SessionService; +import com.github.steveice10.mc.protocol.MinecraftConstants; +import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundHelloPacket; +import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundKeyPacket; +import com.zenith.network.client.ClientSession; +import com.zenith.network.registry.PacketHandler; + +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import java.security.NoSuchAlgorithmException; + +import static com.zenith.Shared.CLIENT_LOG; + +public class CHelloHandler implements PacketHandler { + @Override + public ClientboundHelloPacket apply(final ClientboundHelloPacket packet, final ClientSession session) { + GameProfile profile = session.getFlag(MinecraftConstants.PROFILE_KEY); + String accessToken = session.getFlag(MinecraftConstants.ACCESS_TOKEN_KEY); + + if (profile == null || accessToken == null) { + session.disconnect("No Profile or Access Token provided."); + return null; + } + SecretKey key; + try { + KeyGenerator gen = KeyGenerator.getInstance("AES"); + gen.init(128); + key = gen.generateKey(); + } catch (NoSuchAlgorithmException e) { + session.disconnect("Failed to generate shared key."); + CLIENT_LOG.error("Failed to generate shared key.", e); + return null; + } + + SessionService sessionService = session.getFlag(MinecraftConstants.SESSION_SERVICE_KEY, new SessionService()); + String serverId = sessionService.getServerId(packet.getServerId(), packet.getPublicKey(), key); + try { + sessionService.joinServer(profile, accessToken, serverId); + } catch (ServiceUnavailableException e) { + session.disconnect("Login failed: Authentication service unavailable.", e); + return null; + } catch (InvalidCredentialsException e) { + session.disconnect("Login failed: Invalid login session.", e); + return null; + } catch (RequestException e) { + session.disconnect("Login failed: Authentication error: " + e.getMessage(), e); + return null; + } + + session.send(new ServerboundKeyPacket(packet.getPublicKey(), key, packet.getChallenge())); + session.enableEncryption(key); + return null; + } +} diff --git a/src/main/java/com/zenith/network/client/handler/incoming/CKeepAliveHandler.java b/src/main/java/com/zenith/network/client/handler/incoming/CKeepAliveHandler.java new file mode 100644 index 000000000..10c70d42f --- /dev/null +++ b/src/main/java/com/zenith/network/client/handler/incoming/CKeepAliveHandler.java @@ -0,0 +1,18 @@ +package com.zenith.network.client.handler.incoming; + +import com.github.steveice10.mc.protocol.MinecraftConstants; +import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundKeepAlivePacket; +import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundKeepAlivePacket; +import com.zenith.network.client.ClientSession; +import com.zenith.network.registry.PacketHandler; + +public class CKeepAliveHandler implements PacketHandler { + @Override + public ClientboundKeepAlivePacket apply(final ClientboundKeepAlivePacket packet, final ClientSession session) { + if (session.getFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, true)) { + session.send(new ServerboundKeepAlivePacket(packet.getPingId())); + return null; + } + return packet; + } +} diff --git a/src/main/java/com/zenith/network/client/handler/incoming/CLoginCompressionHandler.java b/src/main/java/com/zenith/network/client/handler/incoming/CLoginCompressionHandler.java new file mode 100644 index 000000000..4b75bb7ce --- /dev/null +++ b/src/main/java/com/zenith/network/client/handler/incoming/CLoginCompressionHandler.java @@ -0,0 +1,13 @@ +package com.zenith.network.client.handler.incoming; + +import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundLoginCompressionPacket; +import com.zenith.network.client.ClientSession; +import com.zenith.network.registry.PacketHandler; + +public class CLoginCompressionHandler implements PacketHandler { + @Override + public ClientboundLoginCompressionPacket apply(final ClientboundLoginCompressionPacket packet, final ClientSession session) { + session.setCompressionThreshold(packet.getThreshold(), false); + return null; + } +} diff --git a/src/main/java/com/zenith/network/client/handler/incoming/CRegistryDataHandler.java b/src/main/java/com/zenith/network/client/handler/incoming/CRegistryDataHandler.java new file mode 100644 index 000000000..593973ba5 --- /dev/null +++ b/src/main/java/com/zenith/network/client/handler/incoming/CRegistryDataHandler.java @@ -0,0 +1,16 @@ +package com.zenith.network.client.handler.incoming; + +import com.github.steveice10.mc.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket; +import com.zenith.network.client.ClientSession; +import com.zenith.network.registry.PacketHandler; + +import static com.zenith.Shared.CACHE; + +public class CRegistryDataHandler implements PacketHandler { + @Override + public ClientboundRegistryDataPacket apply(final ClientboundRegistryDataPacket packet, final ClientSession session) { + CACHE.getConfigurationCache().setRegistry(packet.getRegistry()); + CACHE.getChunkCache().updateRegistryTag(packet.getRegistry()); + return null; + } +} diff --git a/src/main/java/com/zenith/network/client/handler/incoming/CStartConfigurationHandler.java b/src/main/java/com/zenith/network/client/handler/incoming/CStartConfigurationHandler.java new file mode 100644 index 000000000..91f960302 --- /dev/null +++ b/src/main/java/com/zenith/network/client/handler/incoming/CStartConfigurationHandler.java @@ -0,0 +1,18 @@ +package com.zenith.network.client.handler.incoming; + +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundStartConfigurationPacket; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundConfigurationAcknowledgedPacket; +import com.zenith.Proxy; +import com.zenith.network.client.ClientSession; +import com.zenith.network.registry.PacketHandler; + +public class CStartConfigurationHandler implements PacketHandler { + @Override + public ClientboundStartConfigurationPacket apply(final ClientboundStartConfigurationPacket packet, final ClientSession session) { + if (!Proxy.getInstance().hasActivePlayer()) { + session.send(new ServerboundConfigurationAcknowledgedPacket()); + return null; + } + return packet; + } +} diff --git a/src/main/java/com/zenith/network/client/handler/incoming/CStatusResponseHandler.java b/src/main/java/com/zenith/network/client/handler/incoming/CStatusResponseHandler.java new file mode 100644 index 000000000..0d4bde00b --- /dev/null +++ b/src/main/java/com/zenith/network/client/handler/incoming/CStatusResponseHandler.java @@ -0,0 +1,22 @@ +package com.zenith.network.client.handler.incoming; + +import com.github.steveice10.mc.protocol.MinecraftConstants; +import com.github.steveice10.mc.protocol.data.status.ServerStatusInfo; +import com.github.steveice10.mc.protocol.data.status.handler.ServerInfoHandler; +import com.github.steveice10.mc.protocol.packet.status.clientbound.ClientboundStatusResponsePacket; +import com.github.steveice10.mc.protocol.packet.status.serverbound.ServerboundPingRequestPacket; +import com.zenith.network.client.ClientSession; +import com.zenith.network.registry.PacketHandler; + +public class CStatusResponseHandler implements PacketHandler { + @Override + public ClientboundStatusResponsePacket apply(final ClientboundStatusResponsePacket packet, final ClientSession session) { + ServerStatusInfo info = packet.getInfo(); + ServerInfoHandler handler = session.getFlag(MinecraftConstants.SERVER_INFO_HANDLER_KEY); + if (handler != null) { + handler.handle(session, info); + } + session.send(new ServerboundPingRequestPacket(System.currentTimeMillis())); + return null; + } +} diff --git a/src/main/java/com/zenith/network/client/handler/incoming/ClientKeepaliveHandler.java b/src/main/java/com/zenith/network/client/handler/incoming/ClientKeepaliveHandler.java deleted file mode 100644 index 5752ecd5a..000000000 --- a/src/main/java/com/zenith/network/client/handler/incoming/ClientKeepaliveHandler.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.zenith.network.client.handler.incoming; - -import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundKeepAlivePacket; -import com.zenith.network.client.ClientSession; -import com.zenith.network.registry.PacketHandler; -import lombok.NonNull; - -public class ClientKeepaliveHandler implements PacketHandler { - @Override - public ClientboundKeepAlivePacket apply(@NonNull ClientboundKeepAlivePacket packet, @NonNull ClientSession session) { - return null; - } -} diff --git a/src/main/java/com/zenith/network/client/handler/incoming/CustomPayloadHandler.java b/src/main/java/com/zenith/network/client/handler/incoming/CustomPayloadHandler.java index 0f6f0b1b6..e42d38c27 100644 --- a/src/main/java/com/zenith/network/client/handler/incoming/CustomPayloadHandler.java +++ b/src/main/java/com/zenith/network/client/handler/incoming/CustomPayloadHandler.java @@ -2,15 +2,15 @@ import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundCustomPayloadPacket; import com.zenith.network.client.ClientSession; -import com.zenith.network.registry.AsyncPacketHandler; +import com.zenith.network.registry.PacketHandler; import static com.zenith.Shared.CACHE; -public class CustomPayloadHandler implements AsyncPacketHandler { +public class CustomPayloadHandler implements PacketHandler { @Override - public boolean applyAsync(ClientboundCustomPayloadPacket packet, ClientSession session) { + public ClientboundCustomPayloadPacket apply(ClientboundCustomPayloadPacket packet, ClientSession session) { if (packet.getChannel().equalsIgnoreCase("minecraft:brand")) CACHE.getChunkCache().setServerBrand(packet.getData()); - return true; + return packet; } } diff --git a/src/main/java/com/zenith/network/client/handler/incoming/LoginDisconnectHandler.java b/src/main/java/com/zenith/network/client/handler/incoming/LoginDisconnectHandler.java new file mode 100644 index 000000000..9a917e687 --- /dev/null +++ b/src/main/java/com/zenith/network/client/handler/incoming/LoginDisconnectHandler.java @@ -0,0 +1,13 @@ +package com.zenith.network.client.handler.incoming; + +import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundLoginDisconnectPacket; +import com.zenith.network.client.ClientSession; +import com.zenith.network.registry.PacketHandler; + +public class LoginDisconnectHandler implements PacketHandler { + @Override + public ClientboundLoginDisconnectPacket apply(final ClientboundLoginDisconnectPacket packet, final ClientSession session) { + session.disconnect(packet.getReason()); + return null; + } +} diff --git a/src/main/java/com/zenith/network/client/handler/incoming/PongResponseHandler.java b/src/main/java/com/zenith/network/client/handler/incoming/PongResponseHandler.java new file mode 100644 index 000000000..9172637fc --- /dev/null +++ b/src/main/java/com/zenith/network/client/handler/incoming/PongResponseHandler.java @@ -0,0 +1,20 @@ +package com.zenith.network.client.handler.incoming; + +import com.github.steveice10.mc.protocol.MinecraftConstants; +import com.github.steveice10.mc.protocol.data.status.handler.ServerPingTimeHandler; +import com.github.steveice10.mc.protocol.packet.status.clientbound.ClientboundPongResponsePacket; +import com.zenith.network.client.ClientSession; +import com.zenith.network.registry.PacketHandler; + +public class PongResponseHandler implements PacketHandler { + @Override + public ClientboundPongResponsePacket apply(final ClientboundPongResponsePacket packet, final ClientSession session) { + long time = System.currentTimeMillis() - packet.getPingTime(); + ServerPingTimeHandler handler = session.getFlag(MinecraftConstants.SERVER_PING_TIME_HANDLER_KEY); + if (handler != null) { + handler.handle(session, time); + } + session.disconnect("Finished"); + return null; + } +} diff --git a/src/main/java/com/zenith/network/client/handler/incoming/ResourcePackPopHandler.java b/src/main/java/com/zenith/network/client/handler/incoming/ResourcePackPopHandler.java new file mode 100644 index 000000000..05e8d98d3 --- /dev/null +++ b/src/main/java/com/zenith/network/client/handler/incoming/ResourcePackPopHandler.java @@ -0,0 +1,17 @@ +package com.zenith.network.client.handler.incoming; + +import com.github.steveice10.mc.protocol.data.ProtocolState; +import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundResourcePackPopPacket; +import com.zenith.network.client.ClientSession; +import com.zenith.network.registry.PacketHandler; + +import static com.zenith.Shared.CACHE; + +public class ResourcePackPopHandler implements PacketHandler { + @Override + public ClientboundResourcePackPopPacket apply(final ClientboundResourcePackPopPacket packet, final ClientSession session) { + CACHE.getConfigurationCache().getResourcePacks().remove(packet.getId()); + if (session.getPacketProtocol().getState() == ProtocolState.GAME) return packet; + else return null; + } +} diff --git a/src/main/java/com/zenith/network/client/handler/incoming/ResourcePackPushHandler.java b/src/main/java/com/zenith/network/client/handler/incoming/ResourcePackPushHandler.java new file mode 100644 index 000000000..96c5c1393 --- /dev/null +++ b/src/main/java/com/zenith/network/client/handler/incoming/ResourcePackPushHandler.java @@ -0,0 +1,18 @@ +package com.zenith.network.client.handler.incoming; + +import com.github.steveice10.mc.protocol.data.ProtocolState; +import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundResourcePackPushPacket; +import com.zenith.cache.data.config.ResourcePack; +import com.zenith.network.client.ClientSession; +import com.zenith.network.registry.PacketHandler; + +import static com.zenith.Shared.CACHE; + +public class ResourcePackPushHandler implements PacketHandler { + @Override + public ClientboundResourcePackPushPacket apply(final ClientboundResourcePackPushPacket packet, final ClientSession session) { + CACHE.getConfigurationCache().getResourcePacks().put(packet.getId(), new ResourcePack(packet.getId(), packet.getUrl(), packet.getHash(), packet.isRequired(), packet.getPrompt())); + if (session.getPacketProtocol().getState() == ProtocolState.GAME) return packet; + else return null; + } +} diff --git a/src/main/java/com/zenith/network/client/handler/incoming/UpdateEnabledFeaturesHandler.java b/src/main/java/com/zenith/network/client/handler/incoming/UpdateEnabledFeaturesHandler.java index ec2caae4d..82ec35662 100644 --- a/src/main/java/com/zenith/network/client/handler/incoming/UpdateEnabledFeaturesHandler.java +++ b/src/main/java/com/zenith/network/client/handler/incoming/UpdateEnabledFeaturesHandler.java @@ -1,6 +1,6 @@ package com.zenith.network.client.handler.incoming; -import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundUpdateEnabledFeaturesPacket; +import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundUpdateEnabledFeaturesPacket; import com.zenith.network.client.ClientSession; import com.zenith.network.registry.AsyncPacketHandler; diff --git a/src/main/java/com/zenith/network/client/handler/incoming/UpdateTagsHandler.java b/src/main/java/com/zenith/network/client/handler/incoming/UpdateTagsHandler.java index 09f3c0b53..b14a3af95 100644 --- a/src/main/java/com/zenith/network/client/handler/incoming/UpdateTagsHandler.java +++ b/src/main/java/com/zenith/network/client/handler/incoming/UpdateTagsHandler.java @@ -1,15 +1,17 @@ package com.zenith.network.client.handler.incoming; +import com.github.steveice10.mc.protocol.data.ProtocolState; import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket; import com.zenith.network.client.ClientSession; -import com.zenith.network.registry.AsyncPacketHandler; +import com.zenith.network.registry.PacketHandler; import static com.zenith.Shared.CACHE; -public class UpdateTagsHandler implements AsyncPacketHandler { +public class UpdateTagsHandler implements PacketHandler { @Override - public boolean applyAsync(final ClientboundUpdateTagsPacket packet, final ClientSession session) { - CACHE.getPlayerCache().setTags(packet.getTags()); - return true; + public ClientboundUpdateTagsPacket apply(final ClientboundUpdateTagsPacket packet, final ClientSession session) { + CACHE.getConfigurationCache().setTags(packet.getTags()); + if (session.getPacketProtocol().getState() == ProtocolState.GAME) return packet; + else return null; } } diff --git a/src/main/java/com/zenith/network/client/handler/postoutgoing/PostOutgoingClientIntentionHandler.java b/src/main/java/com/zenith/network/client/handler/postoutgoing/PostOutgoingClientIntentionHandler.java new file mode 100644 index 000000000..b65594e0a --- /dev/null +++ b/src/main/java/com/zenith/network/client/handler/postoutgoing/PostOutgoingClientIntentionHandler.java @@ -0,0 +1,18 @@ +package com.zenith.network.client.handler.postoutgoing; + +import com.github.steveice10.mc.auth.data.GameProfile; +import com.github.steveice10.mc.protocol.MinecraftConstants; +import com.github.steveice10.mc.protocol.data.ProtocolState; +import com.github.steveice10.mc.protocol.packet.handshake.serverbound.ClientIntentionPacket; +import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundHelloPacket; +import com.zenith.network.client.ClientSession; +import com.zenith.network.registry.PostOutgoingPacketHandler; + +public class PostOutgoingClientIntentionHandler implements PostOutgoingPacketHandler { + @Override + public void accept(final ClientIntentionPacket packet, final ClientSession session) { + session.getPacketProtocol().setState(ProtocolState.LOGIN); + GameProfile profile = session.getFlag(MinecraftConstants.PROFILE_KEY); + session.send(new ServerboundHelloPacket(profile.getName(), profile.getId())); + } +} diff --git a/src/main/java/com/zenith/network/client/handler/postoutgoing/PostOutgoingConfigurationAckHandler.java b/src/main/java/com/zenith/network/client/handler/postoutgoing/PostOutgoingConfigurationAckHandler.java new file mode 100644 index 000000000..f366c0eed --- /dev/null +++ b/src/main/java/com/zenith/network/client/handler/postoutgoing/PostOutgoingConfigurationAckHandler.java @@ -0,0 +1,13 @@ +package com.zenith.network.client.handler.postoutgoing; + +import com.github.steveice10.mc.protocol.data.ProtocolState; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundConfigurationAcknowledgedPacket; +import com.zenith.network.client.ClientSession; +import com.zenith.network.registry.PostOutgoingPacketHandler; + +public class PostOutgoingConfigurationAckHandler implements PostOutgoingPacketHandler { + @Override + public void accept(final ServerboundConfigurationAcknowledgedPacket packet, final ClientSession session) { + session.getPacketProtocol().setState(ProtocolState.CONFIGURATION); // GAME -> CONFIGURATION + } +} diff --git a/src/main/java/com/zenith/network/client/handler/postoutgoing/PostOutgoingFinishConfigurationHandler.java b/src/main/java/com/zenith/network/client/handler/postoutgoing/PostOutgoingFinishConfigurationHandler.java new file mode 100644 index 000000000..a36e0936b --- /dev/null +++ b/src/main/java/com/zenith/network/client/handler/postoutgoing/PostOutgoingFinishConfigurationHandler.java @@ -0,0 +1,13 @@ +package com.zenith.network.client.handler.postoutgoing; + +import com.github.steveice10.mc.protocol.data.ProtocolState; +import com.github.steveice10.mc.protocol.packet.configuration.serverbound.ServerboundFinishConfigurationPacket; +import com.zenith.network.client.ClientSession; +import com.zenith.network.registry.PostOutgoingPacketHandler; + +public class PostOutgoingFinishConfigurationHandler implements PostOutgoingPacketHandler { + @Override + public void accept(final ServerboundFinishConfigurationPacket packet, final ClientSession session) { + session.getPacketProtocol().setState(ProtocolState.GAME); // CONFIGURATION -> GAME + } +} diff --git a/src/main/java/com/zenith/network/client/handler/postoutgoing/PostOutgoingLoginAckHandler.java b/src/main/java/com/zenith/network/client/handler/postoutgoing/PostOutgoingLoginAckHandler.java new file mode 100644 index 000000000..6031db9aa --- /dev/null +++ b/src/main/java/com/zenith/network/client/handler/postoutgoing/PostOutgoingLoginAckHandler.java @@ -0,0 +1,13 @@ +package com.zenith.network.client.handler.postoutgoing; + +import com.github.steveice10.mc.protocol.data.ProtocolState; +import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundLoginAcknowledgedPacket; +import com.zenith.network.client.ClientSession; +import com.zenith.network.registry.PostOutgoingPacketHandler; + +public class PostOutgoingLoginAckHandler implements PostOutgoingPacketHandler { + @Override + public void accept(final ServerboundLoginAcknowledgedPacket packet, final ClientSession session) { + session.getPacketProtocol().setState(ProtocolState.CONFIGURATION); // LOGIN -> CONFIGURATION + } +} diff --git a/src/main/java/com/zenith/network/registry/AsyncPacketHandler.java b/src/main/java/com/zenith/network/registry/AsyncPacketHandler.java index 3f18e54f5..f72f944d9 100644 --- a/src/main/java/com/zenith/network/registry/AsyncPacketHandler.java +++ b/src/main/java/com/zenith/network/registry/AsyncPacketHandler.java @@ -2,16 +2,34 @@ import com.github.steveice10.packetlib.Session; import com.github.steveice10.packetlib.packet.Packet; +import com.google.common.util.concurrent.ThreadFactoryBuilder; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; import static com.zenith.Shared.CLIENT_LOG; import static java.util.concurrent.TimeUnit.MILLISECONDS; public interface AsyncPacketHandler

extends PacketHandler { + static final ExecutorService ASYNC_EXECUTOR_SERVICE = + Executors.newFixedThreadPool(1, + new ThreadFactoryBuilder() + .setNameFormat("ZenithProxy Async PacketHandler #%d") + .setDaemon(true) + .build()); + static final ScheduledExecutorService RETRY_EXECUTOR_SERVICE = + Executors.newScheduledThreadPool(1, + new ThreadFactoryBuilder() + .setNameFormat("ZenithProxy Async PacketHandler Retry #%d") + .setDaemon(true) + .build()); + boolean applyAsync(P packet, S session); default P apply(P packet, S session) { if (packet == null) return null; - HandlerRegistry.ASYNC_EXECUTOR_SERVICE.execute(() -> { + ASYNC_EXECUTOR_SERVICE.execute(() -> { applyWithRetries(packet, session, 0); }); return packet; @@ -24,7 +42,7 @@ private void applyWithRetries(P packet, S session, final int tryCount) { CLIENT_LOG.warn("Unable to apply async handler for packet: " + packet.getClass().getSimpleName()); return; } - HandlerRegistry.RETRY_EXECUTOR_SERVICE.schedule(() -> { + RETRY_EXECUTOR_SERVICE.schedule(() -> { applyWithRetries(packet, session, tryCount + 1); }, 250, MILLISECONDS); } diff --git a/src/main/java/com/zenith/network/registry/HandlerRegistry.java b/src/main/java/com/zenith/network/registry/HandlerRegistry.java deleted file mode 100644 index 60bf26481..000000000 --- a/src/main/java/com/zenith/network/registry/HandlerRegistry.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.zenith.network.registry; - -import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundKeepAlivePacket; -import com.github.steveice10.packetlib.Session; -import com.github.steveice10.packetlib.packet.Packet; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import com.zenith.network.server.handler.shared.incoming.KeepAliveHandler; -import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; -import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; -import lombok.*; -import lombok.experimental.Accessors; -import org.slf4j.Logger; - -import java.time.Instant; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; - -import static com.zenith.Shared.CONFIG; - - -@RequiredArgsConstructor(access = AccessLevel.PRIVATE) -public class HandlerRegistry { - @NonNull - protected final Reference2ObjectMap, PacketHandler> inboundHandlers; - @NonNull - protected final Reference2ObjectMap, PacketHandler> outboundHandlers; - @NonNull - protected final Reference2ObjectMap, PacketHandler> postOutboundHandlers; - @NonNull - protected final Logger logger; - protected final boolean allowUnhandled; - protected static final ExecutorService ASYNC_EXECUTOR_SERVICE = - Executors.newFixedThreadPool(1, - new ThreadFactoryBuilder() - .setNameFormat("ZenithProxy Async PacketHandler #%d") - .setDaemon(true) - .build()); - protected static final ScheduledExecutorService RETRY_EXECUTOR_SERVICE = - Executors.newScheduledThreadPool(1, - new ThreadFactoryBuilder() - .setNameFormat("ZenithProxy Async PacketHandler Retry #%d") - .setDaemon(true) - .build()); - - @SuppressWarnings("unchecked") - public

P handleInbound(@NonNull P packet, @NonNull S session) { - if (CONFIG.debug.packet.received) { - if (!(packet instanceof ClientboundKeepAlivePacket || packet instanceof KeepAliveHandler)) { - this.logger.debug("[{}] Received: {}", Instant.now().toEpochMilli(), CONFIG.debug.packet.receivedBody ? packet : packet.getClass()); - } -// if (allowedPackets.stream().anyMatch(allowPacket -> packet.getClass() == allowPacket)) { -// this.logger.debug("Received packet: {}@%08x", CONFIG.debug.packet.receivedBody ? packet : packet.getClass(), System.identityHashCode(packet)); -// } - } - PacketHandler handler = (PacketHandler) this.inboundHandlers.get(packet.getClass()); - if (handler == null) { - if (allowUnhandled) return packet; - else return null; - } else { - return handler.apply(packet, session); - } - } - - @SuppressWarnings("unchecked") - public

P handleOutgoing(@NonNull P packet, @NonNull S session) { - if (CONFIG.debug.packet.preSent) { - this.logger.debug("[{}] Sending: {}", Instant.now().toEpochMilli(), CONFIG.debug.packet.preSentBody ? packet : packet.getClass()); - } - PacketHandler handler = (PacketHandler) this.outboundHandlers.get(packet.getClass()); - if (handler == null) { - // allowUnhandled has no effect here - return packet; - } else { - return handler.apply(packet, session); - } - } - - @SuppressWarnings("unchecked") - public

void handlePostOutgoing(@NonNull P packet, @NonNull S session) { - if (CONFIG.debug.packet.postSent) { - if (!(packet instanceof ClientboundKeepAlivePacket || packet instanceof KeepAliveHandler)) - this.logger.debug("[{}] Sent: {}", Instant.now().toEpochMilli(), CONFIG.debug.packet.postSentBody ? packet : packet.getClass()); -// if (allowedPackets.stream().anyMatch(allowPacket -> packet.getClass() == allowPacket)) { -// this.logger.debug("Sent packet: {}@%08x", CONFIG.debug.packet.postSentBody ? packet : packet.getClass(), System.identityHashCode(packet)); -// } - } - PacketHandler handler = (PacketHandler) this.postOutboundHandlers.get(packet.getClass()); - if (handler != null) { - handler.apply(packet, session); - } - } - - @Getter - @Setter - @Accessors(chain = true) - public static class Builder { - - protected final Reference2ObjectMap, PacketHandler> inboundHandlers = new Reference2ObjectOpenHashMap<>(); - - protected final Reference2ObjectMap, PacketHandler> outboundHandlers = new Reference2ObjectOpenHashMap<>(); - - protected final Reference2ObjectMap, PacketHandler> postOutboundHandlers = new Reference2ObjectOpenHashMap<>(); - @NonNull - protected Logger logger; - protected boolean allowUnhandled = true; - - public Builder registerInbound(@NonNull Class packetClass, @NonNull PacketHandler handler) { - this.inboundHandlers.put(packetClass, handler); - return this; - } - - public Builder registerOutbound(@NonNull Class packetClass, @NonNull PacketHandler handler) { - this.outboundHandlers.put(packetClass, handler); - return this; - } - - public Builder registerPostOutbound(@NonNull Class packetClass, @NonNull PostOutgoingPacketHandler handler) { - this.postOutboundHandlers.put(packetClass, handler); - return this; - } - - public Builder registerPostOutbound(@NonNull Class packetClass, @NonNull AsyncPacketHandler handler) { - this.postOutboundHandlers.put(packetClass, handler); - return this; - } - - public Builder allowUnhandled(final boolean allowUnhandled) { - this.allowUnhandled = allowUnhandled; - return this; - } - - public HandlerRegistry build() { - return new HandlerRegistry<>(this.inboundHandlers, this.outboundHandlers, this.postOutboundHandlers, this.logger, this.allowUnhandled); - } - } -} diff --git a/src/main/java/com/zenith/network/registry/PacketHandlerCodec.java b/src/main/java/com/zenith/network/registry/PacketHandlerCodec.java new file mode 100644 index 000000000..5c5329045 --- /dev/null +++ b/src/main/java/com/zenith/network/registry/PacketHandlerCodec.java @@ -0,0 +1,67 @@ +package com.zenith.network.registry; + +import com.github.steveice10.mc.protocol.data.ProtocolState; +import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.packet.Packet; +import lombok.*; +import lombok.experimental.Accessors; +import org.slf4j.Logger; + +import java.time.Instant; +import java.util.EnumMap; + +import static com.zenith.Shared.CONFIG; + +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +public class PacketHandlerCodec { + private final EnumMap> stateCodecs; + @NonNull + private final Logger logger; + + public static Builder builder() { + return new Builder(); + } + + public PacketHandlerStateCodec getCodec(ProtocolState state) { + return (PacketHandlerStateCodec) this.stateCodecs.get(state); + } + + public

P handleInbound(@NonNull P packet, @NonNull S session) { + if (CONFIG.debug.packet.received) { + this.logger.debug("[{}] [{}] Received: {}", Instant.now().toEpochMilli(), session.getClass().getSimpleName(), CONFIG.debug.packet.receivedBody ? packet : packet.getClass()); + } + return getCodec(session.getPacketProtocol().getState()).handleInbound(packet, session); + } + + public

P handleOutgoing(@NonNull P packet, @NonNull S session) { + if (CONFIG.debug.packet.preSent) { + this.logger.debug("[{}] [{}] Sending: {}", Instant.now().toEpochMilli(), session.getClass().getSimpleName(), CONFIG.debug.packet.preSentBody ? packet : packet.getClass()); + } + return getCodec(session.getPacketProtocol().getState()).handleOutgoing(packet, session); + } + + public

void handlePostOutgoing(@NonNull P packet, @NonNull S session) { + if (CONFIG.debug.packet.postSent) { + this.logger.debug("[{}] [{}] Sent: {}", Instant.now().toEpochMilli(), session.getClass().getSimpleName(), CONFIG.debug.packet.postSentBody ? packet : packet.getClass()); + } + getCodec(session.getPacketProtocol().getState()).handlePostOutgoing(packet, session); + } + + @Getter + @Setter + @Accessors(chain = true) + public static class Builder { + private final EnumMap> aStateCodecs = new EnumMap<>(ProtocolState.class); + @NonNull + private Logger logger; + + public Builder state(ProtocolState state, PacketHandlerStateCodec codec) { + this.aStateCodecs.put(state, codec); + return this; + } + + public PacketHandlerCodec build() { + return new PacketHandlerCodec(this.aStateCodecs, logger); + } + } +} diff --git a/src/main/java/com/zenith/network/registry/PacketHandlerStateCodec.java b/src/main/java/com/zenith/network/registry/PacketHandlerStateCodec.java new file mode 100644 index 000000000..26f6f8a45 --- /dev/null +++ b/src/main/java/com/zenith/network/registry/PacketHandlerStateCodec.java @@ -0,0 +1,95 @@ +package com.zenith.network.registry; + +import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.packet.Packet; +import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; +import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; +import lombok.*; +import lombok.experimental.Accessors; + +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +public class PacketHandlerStateCodec { + @NonNull + protected final Reference2ObjectMap, PacketHandler> inboundHandlers; + @NonNull + protected final Reference2ObjectMap, PacketHandler> outboundHandlers; + @NonNull + protected final Reference2ObjectMap, PacketHandler> postOutboundHandlers; + protected final boolean allowUnhandled; + + public static Builder builder() { + return new Builder<>(); + } + + public

P handleInbound(@NonNull P packet, @NonNull S session) { + PacketHandler handler = (PacketHandler) this.inboundHandlers.get(packet.getClass()); + if (handler == null) { + if (allowUnhandled) return packet; + else return null; + } else { + return handler.apply(packet, session); + } + } + + @SuppressWarnings("unchecked") + public

P handleOutgoing(@NonNull P packet, @NonNull S session) { + PacketHandler handler = (PacketHandler) this.outboundHandlers.get(packet.getClass()); + if (handler == null) { + // allowUnhandled has no effect here + return packet; + } else { + return handler.apply(packet, session); + } + } + + @SuppressWarnings("unchecked") + public

void handlePostOutgoing(@NonNull P packet, @NonNull S session) { + + PacketHandler handler = (PacketHandler) this.postOutboundHandlers.get(packet.getClass()); + if (handler != null) { + handler.apply(packet, session); + } + } + + @Getter + @Setter + @Accessors(chain = true) + public static class Builder { + + protected final Reference2ObjectMap, PacketHandler> inboundHandlers = new Reference2ObjectOpenHashMap<>(); + + protected final Reference2ObjectMap, PacketHandler> outboundHandlers = new Reference2ObjectOpenHashMap<>(); + + protected final Reference2ObjectMap, PacketHandler> postOutboundHandlers = new Reference2ObjectOpenHashMap<>(); + protected boolean allowUnhandled = true; + + public PacketHandlerStateCodec.Builder registerInbound(@NonNull Class packetClass, @NonNull PacketHandler handler) { + this.inboundHandlers.put(packetClass, handler); + return this; + } + + public PacketHandlerStateCodec.Builder registerOutbound(@NonNull Class packetClass, @NonNull PacketHandler handler) { + this.outboundHandlers.put(packetClass, handler); + return this; + } + + public PacketHandlerStateCodec.Builder registerPostOutbound(@NonNull Class packetClass, @NonNull PostOutgoingPacketHandler handler) { + this.postOutboundHandlers.put(packetClass, handler); + return this; + } + + public PacketHandlerStateCodec.Builder registerPostOutbound(@NonNull Class packetClass, @NonNull AsyncPacketHandler handler) { + this.postOutboundHandlers.put(packetClass, handler); + return this; + } + + public PacketHandlerStateCodec.Builder allowUnhandled(final boolean allowUnhandled) { + this.allowUnhandled = allowUnhandled; + return this; + } + + public PacketHandlerStateCodec build() { + return new PacketHandlerStateCodec<>(this.inboundHandlers, this.outboundHandlers, this.postOutboundHandlers, this.allowUnhandled); + } + } +} diff --git a/src/main/java/com/zenith/network/registry/ZenithHandlerCodec.java b/src/main/java/com/zenith/network/registry/ZenithHandlerCodec.java new file mode 100644 index 000000000..c1c93ebee --- /dev/null +++ b/src/main/java/com/zenith/network/registry/ZenithHandlerCodec.java @@ -0,0 +1,293 @@ +package com.zenith.network.registry; + +import com.github.steveice10.mc.protocol.data.ProtocolState; +import com.github.steveice10.mc.protocol.packet.common.clientbound.*; +import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundClientInformationPacket; +import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundKeepAlivePacket; +import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundPongPacket; +import com.github.steveice10.mc.protocol.packet.configuration.clientbound.ClientboundFinishConfigurationPacket; +import com.github.steveice10.mc.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket; +import com.github.steveice10.mc.protocol.packet.configuration.serverbound.ServerboundFinishConfigurationPacket; +import com.github.steveice10.mc.protocol.packet.handshake.serverbound.ClientIntentionPacket; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.*; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.*; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.*; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddEntityPacket; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddExperienceOrbPacket; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddPlayerPacket; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.*; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.*; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.border.ClientboundInitializeBorderPacket; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.title.ClientboundSetActionBarTextPacket; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.title.ClientboundSetSubtitleTextPacket; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatCommandPacket; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatPacket; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundClientCommandPacket; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundConfigurationAcknowledgedPacket; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClickPacket; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundMoveVehiclePacket; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundTeleportToEntityPacket; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.*; +import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundGameProfilePacket; +import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundHelloPacket; +import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundLoginCompressionPacket; +import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundLoginDisconnectPacket; +import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundHelloPacket; +import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundKeyPacket; +import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundLoginAcknowledgedPacket; +import com.github.steveice10.mc.protocol.packet.status.clientbound.ClientboundPongResponsePacket; +import com.github.steveice10.mc.protocol.packet.status.clientbound.ClientboundStatusResponsePacket; +import com.github.steveice10.mc.protocol.packet.status.serverbound.ServerboundPingRequestPacket; +import com.github.steveice10.mc.protocol.packet.status.serverbound.ServerboundStatusRequestPacket; +import com.zenith.network.client.ClientSession; +import com.zenith.network.client.handler.incoming.*; +import com.zenith.network.client.handler.incoming.entity.*; +import com.zenith.network.client.handler.incoming.inventory.*; +import com.zenith.network.client.handler.incoming.level.*; +import com.zenith.network.client.handler.incoming.spawn.AddEntityHandler; +import com.zenith.network.client.handler.incoming.spawn.AddExperienceOrbHandler; +import com.zenith.network.client.handler.incoming.spawn.AddPlayerHandler; +import com.zenith.network.client.handler.incoming.spawn.SpawnPositionHandler; +import com.zenith.network.client.handler.outgoing.OutgoingChatHandler; +import com.zenith.network.client.handler.outgoing.OutgoingContainerClickHandler; +import com.zenith.network.client.handler.postoutgoing.*; +import com.zenith.network.server.ServerConnection; +import com.zenith.network.server.handler.player.incoming.*; +import com.zenith.network.server.handler.player.outgoing.SystemChatOutgoingHandler; +import com.zenith.network.server.handler.player.postoutgoing.LoginPostHandler; +import com.zenith.network.server.handler.shared.incoming.*; +import com.zenith.network.server.handler.shared.outgoing.LoginCompressionOutgoingHandler; +import com.zenith.network.server.handler.shared.outgoing.PingOutgoingHandler; +import com.zenith.network.server.handler.shared.outgoing.SGameProfileOutgoingHandler; +import com.zenith.network.server.handler.shared.outgoing.ServerTablistDataOutgoingHandler; +import com.zenith.network.server.handler.spectator.incoming.*; +import com.zenith.network.server.handler.spectator.incoming.movement.PlayerPositionRotationSpectatorHandler; +import com.zenith.network.server.handler.spectator.incoming.movement.PlayerPositionSpectatorHandler; +import com.zenith.network.server.handler.spectator.incoming.movement.PlayerRotationSpectatorHandler; +import com.zenith.network.server.handler.spectator.outgoing.*; +import com.zenith.network.server.handler.spectator.postoutgoing.LoginSpectatorPostHandler; +import lombok.experimental.UtilityClass; + +import static com.zenith.Shared.CLIENT_LOG; +import static com.zenith.Shared.SERVER_LOG; + +@UtilityClass +public class ZenithHandlerCodec { + public final PacketHandlerCodec CLIENT_CODEC = PacketHandlerCodec.builder() + .setLogger(CLIENT_LOG) + .state(ProtocolState.HANDSHAKE, PacketHandlerStateCodec.builder() + .allowUnhandled(false) + .registerPostOutbound(ClientIntentionPacket.class, new PostOutgoingClientIntentionHandler()) + .build()) + .state(ProtocolState.STATUS, PacketHandlerStateCodec.builder() + .allowUnhandled(false) + .registerInbound(ClientboundStatusResponsePacket.class, new CStatusResponseHandler()) + .registerInbound(ClientboundPongResponsePacket.class, new PongResponseHandler()) + .build()) + .state(ProtocolState.LOGIN, PacketHandlerStateCodec.builder() + .allowUnhandled(false) + .registerInbound(ClientboundHelloPacket.class, new CHelloHandler()) + .registerInbound(ClientboundLoginCompressionPacket.class, new CLoginCompressionHandler()) + .registerInbound(ClientboundGameProfilePacket.class, new CGameProfileHandler()) + .registerInbound(ClientboundLoginDisconnectPacket.class, new LoginDisconnectHandler()) + .registerPostOutbound(ServerboundLoginAcknowledgedPacket.class, new PostOutgoingLoginAckHandler()) + .build()) + .state(ProtocolState.CONFIGURATION, PacketHandlerStateCodec.builder() + .allowUnhandled(false) + .registerInbound(ClientboundFinishConfigurationPacket.class, new CFinishConfigurationHandler()) + .registerInbound(ClientboundRegistryDataPacket.class, new CRegistryDataHandler()) + .registerInbound(ClientboundUpdateEnabledFeaturesPacket.class, new UpdateEnabledFeaturesHandler()) + // todo: handle serverbound resourcepack status packets + .registerInbound(ClientboundResourcePackPushPacket.class, new ResourcePackPushHandler()) + .registerInbound(ClientboundResourcePackPopPacket.class, new ResourcePackPopHandler()) + .registerInbound(ClientboundUpdateTagsPacket.class, new UpdateTagsHandler()) + .registerInbound(ClientboundCustomPayloadPacket.class, new CustomPayloadHandler()) + .registerInbound(ClientboundPingPacket.class, new PingHandler()) + .registerInbound(ClientboundKeepAlivePacket.class, new CKeepAliveHandler()) + .registerInbound(ClientboundDisconnectPacket.class, new CDisconnectHandler()) + .registerPostOutbound(ServerboundFinishConfigurationPacket.class, new PostOutgoingFinishConfigurationHandler()) + .build()) + .state(ProtocolState.GAME, PacketHandlerStateCodec.builder() + .allowUnhandled(true) + // + // Inbound packets + // + .registerInbound(ClientboundDisconnectPacket.class, new CDisconnectHandler()) + .registerInbound(ClientboundStartConfigurationPacket.class, new CStartConfigurationHandler()) + .registerInbound(ClientboundUpdateAdvancementsPacket.class, new UpdateAdvancementsHandler()) + .registerInbound(ClientboundBlockUpdatePacket.class, new BlockUpdateHandler()) + .registerInbound(ClientboundChunkBatchFinishedPacket.class, new ChunkBatchFinishedHandler()) + .registerInbound(ClientboundChangeDifficultyPacket.class, new ChangeDifficultyHandler()) + .registerInbound(ClientboundBossEventPacket.class, new BossEventHandler()) + .registerInbound(ClientboundChunksBiomesPacket.class, new ChunksBiomesHandler()) + .registerInbound(ClientboundSystemChatPacket.class, new SystemChatHandler()) + .registerInbound(ClientboundPlayerChatPacket.class, new PlayerChatHandler()) + .registerInbound(ClientboundLevelChunkWithLightPacket.class, new LevelChunkWithLightHandler()) + .registerInbound(ClientboundLightUpdatePacket.class, new LightUpdateHandler()) + .registerInbound(ClientboundKeepAlivePacket.class, new CKeepAliveHandler()) + .registerInbound(ClientboundCommandsPacket.class, new CommandsHandler()) + .registerInbound(ClientboundGameEventPacket.class, new GameEventHandler()) + .registerInbound(ClientboundLoginPacket.class, new LoginHandler()) + .registerInbound(ClientboundGameProfilePacket.class, new GameProfileHandler()) + .registerInbound(ClientboundSectionBlocksUpdatePacket.class, new SectionBlocksUpdateHandler()) + .registerInbound(ClientboundSetCarriedItemPacket.class, new SetCarriedItemHandler()) + .registerInbound(ClientboundSetChunkCacheCenterPacket.class, new SetChunkCacheCenterHandler()) + .registerInbound(ClientboundSetChunkCacheRadiusPacket.class, new SetChunkCacheRadiusHandler()) + .registerInbound(ClientboundSetSimulationDistancePacket.class, new SetSimulationDistanceHandler()) + .registerInbound(ClientboundSetHealthPacket.class, new SetHealthHandler()) + .registerInbound(ClientboundSetSubtitleTextPacket.class, new SetSubtitleTextHandler()) + .registerInbound(ClientboundPlayerPositionPacket.class, new PlayerPositionHandler()) + .registerInbound(ClientboundSoundPacket.class, new SoundHandler()) + .registerInbound(ClientboundSetExperiencePacket.class, new SetExperienceHandler()) + .registerInbound(ClientboundRespawnPacket.class, new RespawnHandler()) + .registerInbound(ClientboundContainerSetSlotPacket.class, new ContainerSetSlotHandler()) + .registerInbound(ClientboundContainerSetContentPacket.class, new ContainerSetContentHandler()) + .registerInbound(ClientboundAwardStatsPacket.class, new AwardStatsHandler()) + .registerInbound(ClientboundTabListPacket.class, new TabListDataHandler()) + .registerInbound(ClientboundPlayerInfoUpdatePacket.class, new PlayerInfoUpdateHandler()) + .registerInbound(ClientboundExplodePacket.class, new ExplodeHandler()) + .registerInbound(ClientboundPlayerInfoRemovePacket.class, new PlayerInfoRemoveHandler()) + .registerInbound(ClientboundSetActionBarTextPacket.class, new SetActionBarTextHandler()) + .registerInbound(ClientboundSetEntityMotionPacket.class, new SetEntityMotionHandler()) + .registerInbound(ClientboundForgetLevelChunkPacket.class, new ForgetLevelChunkHandler()) + .registerInbound(ClientboundUpdateRecipesPacket.class, new SyncRecipesHandler()) + .registerInbound(ClientboundUpdateTagsPacket.class, new UpdateTagsHandler()) + .registerInbound(ClientboundInitializeBorderPacket.class, new WorldBorderInitializeHandler()) + .registerInbound(ClientboundBlockEntityDataPacket.class, new BlockEntityDataHandler()) + .registerInbound(ClientboundSetTimePacket.class, new SetTimeHandler()) + .registerInbound(ClientboundPlayerCombatKillPacket.class, new PlayerCombatKillHandler()) + .registerInbound(ClientboundMapItemDataPacket.class, new MapDataHandler()) + .registerInbound(ClientboundPingPacket.class, new PingHandler()) + .registerInbound(ClientboundPlayerAbilitiesPacket.class, new PlayerAbilitiesHandler()) + .registerInbound(ClientboundCustomPayloadPacket.class, new CustomPayloadHandler()) + .registerInbound(ClientboundRecipePacket.class, new UnlockRecipeHandler()) + //ENTITY + .registerInbound(ClientboundEntityEventPacket.class, new EntityEventHandler()) + .registerInbound(ClientboundSetEntityLinkPacket.class, new SetEntityLinkHandler()) + .registerInbound(ClientboundTakeItemEntityPacket.class, new TakeItemEntityHandler()) + .registerInbound(ClientboundRemoveEntitiesPacket.class, new RemoveEntitiesHandler()) + .registerInbound(ClientboundUpdateMobEffectPacket.class, new UpdateMobEffectHandler()) + .registerInbound(ClientboundRemoveMobEffectPacket.class, new RemoveMobEffectHandler()) + .registerInbound(ClientboundSetEquipmentPacket.class, new SetEquipmentHandler()) + .registerInbound(ClientboundRotateHeadPacket.class, new RotateHeadHandler()) + .registerInbound(ClientboundSetEntityDataPacket.class, new SetEntityDataHandler()) + .registerInbound(ClientboundMoveEntityPosPacket.class, new MoveEntityPosHandler()) + .registerInbound(ClientboundMoveEntityPosRotPacket.class, new MoveEntityPosRotHandler()) + .registerInbound(ClientboundUpdateAttributesPacket.class, new UpdateAttributesHandler()) + .registerInbound(ClientboundMoveEntityRotPacket.class, new MoveEntityRotHandler()) + .registerInbound(ClientboundMoveVehiclePacket.class, new MoveVehicleHandler()) + .registerInbound(ClientboundSetPassengersPacket.class, new EntitySetPassengersHandler()) + .registerInbound(ClientboundTeleportEntityPacket.class, new TeleportEntityHandler()) + //SPAWN + .registerInbound(ClientboundAddExperienceOrbPacket.class, new AddExperienceOrbHandler()) + .registerInbound(ClientboundAddEntityPacket.class, new AddEntityHandler()) + .registerInbound(ClientboundAddPlayerPacket.class, new AddPlayerHandler()) + .registerInbound(ClientboundSetDefaultSpawnPositionPacket.class, new SpawnPositionHandler()) + // Outbound + .registerOutbound(ServerboundChatPacket.class, new OutgoingChatHandler()) + .registerOutbound(ServerboundContainerClickPacket.class, new OutgoingContainerClickHandler()) + //Postoutgoing + .registerPostOutbound(ServerboundConfigurationAcknowledgedPacket.class, new PostOutgoingConfigurationAckHandler()) + .registerPostOutbound(ServerboundMoveVehiclePacket.class, new PostOutgoingMoveVehicleHandler()) + .registerPostOutbound(ServerboundPlayerCommandPacket.class, new PostOutgoingPlayerCommandHandler()) + .registerPostOutbound(ServerboundSetCarriedItemPacket.class, new PostOutgoingSetCarriedItemHandler()) + .registerPostOutbound(ServerboundMovePlayerPosPacket.class, new PostOutgoingPlayerPositionHandler()) + .registerPostOutbound(ServerboundMovePlayerPosRotPacket.class, new PostOutgoingPlayerPositionRotationHandler()) + .registerPostOutbound(ServerboundMovePlayerRotPacket.class, new PostOutgoingPlayerRotationHandler()) + .registerPostOutbound(ServerboundMovePlayerStatusOnlyPacket.class, new PostOutgoingPlayerStatusOnlyHandler()) + .registerPostOutbound(ServerboundSwingPacket.class, new PostOutgoingSwingHandler()) + .build()) + .build(); + + public final PacketHandlerCodec SERVER_PLAYER_CODEC = PacketHandlerCodec.builder() + .setLogger(SERVER_LOG) + .state(ProtocolState.HANDSHAKE, PacketHandlerStateCodec.builder() + .allowUnhandled(false) + .registerInbound(ClientIntentionPacket.class, new IntentionHandler()) + .build()) + .state(ProtocolState.LOGIN, PacketHandlerStateCodec.builder() + .allowUnhandled(false) + .registerInbound(ServerboundHelloPacket.class, new SHelloHandler()) + .registerInbound(ServerboundKeyPacket.class, new KeyHandler()) + .registerInbound(ServerboundLoginAcknowledgedPacket.class, new LoginAckHandler()) + .registerPostOutbound(ClientboundLoginCompressionPacket.class, new LoginCompressionOutgoingHandler()) + .registerOutbound(ClientboundGameProfilePacket.class, new SGameProfileOutgoingHandler()) + .build()) + .state(ProtocolState.STATUS, PacketHandlerStateCodec.builder() + .allowUnhandled(false) + .registerInbound(ServerboundStatusRequestPacket.class, new StatusRequestHandler()) + .registerInbound(ServerboundPingRequestPacket.class, new PingRequestHandler()) + .build()) + .state(ProtocolState.CONFIGURATION, PacketHandlerStateCodec.builder() + .allowUnhandled(false) + .registerInbound(ServerboundFinishConfigurationPacket.class, new FinishConfigurationHandler()) + .registerInbound(ServerboundClientInformationPacket.class, new ClientInformationHandler()) + .registerInbound(ServerboundKeepAlivePacket.class, new KeepAliveHandler()) + .build()) + .state(ProtocolState.GAME, PacketHandlerStateCodec.builder() + .allowUnhandled(true) + // + // Inbound packets + // + .registerInbound(ServerboundKeepAlivePacket.class, new KeepAliveHandler()) + .registerInbound(ServerboundConfigurationAcknowledgedPacket.class, new ConfigurationAckHandler()) + .registerInbound(ServerboundChatCommandPacket.class, new ChatCommandHandler()) + .registerInbound(ServerboundChatPacket.class, new ChatHandler()) + .registerInbound(ServerboundClientInformationPacket.class, new ClientInformationHandler()) + .registerInbound(ServerboundPongPacket.class, new PongHandler()) + .registerInbound(ServerboundClientCommandPacket.class, new ClientCommandHandler()) + .registerInbound(ServerboundPingRequestPacket.class, new PingRequestHandler()) + // + // Outbound packets + // + .registerOutbound(ClientboundPingPacket.class, new PingOutgoingHandler()) + .registerOutbound(ClientboundTabListPacket.class, new ServerTablistDataOutgoingHandler()) + .registerOutbound(ClientboundSystemChatPacket.class, new SystemChatOutgoingHandler()) + // + // Post-outbound packets + // + .registerPostOutbound(ClientboundLoginPacket.class, new LoginPostHandler()) + .build()) + .build(); + + public final PacketHandlerCodec SERVER_SPECTATOR_CODEC = PacketHandlerCodec.builder() + .setLogger(SERVER_LOG) + .state(ProtocolState.GAME, PacketHandlerStateCodec.builder() + .allowUnhandled(false) + + .registerInbound(ServerboundHelloPacket.class, new SHelloHandler()) + .registerInbound(ServerboundKeepAlivePacket.class, new KeepAliveHandler()) + .registerInbound(ServerboundPongPacket.class, new SpectatorPongHandler()) + .registerInbound(ServerboundMovePlayerPosRotPacket.class, new PlayerPositionRotationSpectatorHandler()) + .registerInbound(ServerboundMovePlayerPosPacket.class, new PlayerPositionSpectatorHandler()) + .registerInbound(ServerboundMovePlayerRotPacket.class, new PlayerRotationSpectatorHandler()) + .registerInbound(ServerboundChatPacket.class, new ServerChatSpectatorHandler()) + .registerInbound(ServerboundPlayerCommandPacket.class, new PlayerCommandSpectatorHandler()) + .registerInbound(ServerboundTeleportToEntityPacket.class, new TeleportToEntitySpectatorHandler()) + .registerInbound(ServerboundInteractPacket.class, new InteractEntitySpectatorHandler()) + + .registerOutbound(ClientboundGameProfilePacket.class, new SGameProfileOutgoingHandler()) + .registerOutbound(ClientboundPingPacket.class, new PingOutgoingHandler()) + + .registerOutbound(ClientboundContainerClosePacket.class, new ContainerCloseSpectatorOutgoingHandler()) + .registerOutbound(ClientboundContainerSetContentPacket.class, new ContainerSetContentSpectatorOutgoingHandler()) + .registerOutbound(ClientboundPlaceGhostRecipePacket.class, new PlaceGhostRecipeSpectatorOutgoingHandler()) + .registerOutbound(ClientboundOpenScreenPacket.class, new OpenScreenSpectatorOutgoingHandler()) + .registerOutbound(ClientboundSetCarriedItemPacket.class, new SetCarriedItemSpectatorOutgoingHandler()) + .registerOutbound(ClientboundSetHealthPacket.class, new SetHealthSpectatorOutgoingHandler()) + .registerOutbound(ClientboundPlayerPositionPacket.class, new PlayerPositionSpectatorOutgoingHandler()) + .registerOutbound(ClientboundSetExperiencePacket.class, new SetExperienceSpectatorOutgoingHandler()) + .registerOutbound(ClientboundOpenBookPacket.class, new OpenBookSpectatorOutgoingHandler()) + .registerOutbound(ClientboundContainerSetSlotPacket.class, new ContainerSetSlotSpectatorOutgoingHandler()) + .registerOutbound(ClientboundGameEventPacket.class, new GameEventSpectatorOutgoingHandler()) + .registerOutbound(ClientboundMoveVehiclePacket.class, new MoveVehicleSpectatorOutgoingHandler()) + .registerOutbound(ClientboundHorseScreenOpenPacket.class, new HorseScreenOpenSpectatorOutgoingHandler()) + .registerOutbound(ClientboundContainerSetDataPacket.class, new ContainerSetDataSpectatorOutgoingHandler()) + .registerOutbound(ClientboundTabListPacket.class, new ServerTablistDataOutgoingHandler()) + .registerOutbound(ClientboundPlayerAbilitiesPacket.class, new PlayerAbilitiesSpectatorOutgoingHandler()) + .registerOutbound(ClientboundRespawnPacket.class, new RespawnSpectatorOutgoingPacket()) + + .registerPostOutbound(ClientboundLoginPacket.class, new LoginSpectatorPostHandler()) + .build()) + .build(); +} diff --git a/src/main/java/com/zenith/network/server/ServerConnection.java b/src/main/java/com/zenith/network/server/ServerConnection.java index 989fe1410..e90e151b4 100644 --- a/src/main/java/com/zenith/network/server/ServerConnection.java +++ b/src/main/java/com/zenith/network/server/ServerConnection.java @@ -1,48 +1,23 @@ package com.zenith.network.server; import com.github.steveice10.mc.auth.data.GameProfile; -import com.github.steveice10.mc.auth.exception.request.RequestException; -import com.github.steveice10.mc.auth.service.SessionService; import com.github.steveice10.mc.protocol.MinecraftConstants; import com.github.steveice10.mc.protocol.MinecraftProtocol; -import com.github.steveice10.mc.protocol.ServerLoginHandler; import com.github.steveice10.mc.protocol.data.ProtocolState; import com.github.steveice10.mc.protocol.data.game.scoreboard.CollisionRule; import com.github.steveice10.mc.protocol.data.game.scoreboard.NameTagVisibility; import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamAction; import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor; -import com.github.steveice10.mc.protocol.data.status.PlayerInfo; -import com.github.steveice10.mc.protocol.data.status.ServerStatusInfo; -import com.github.steveice10.mc.protocol.data.status.VersionInfo; -import com.github.steveice10.mc.protocol.data.status.handler.ServerInfoBuilder; -import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundCustomPayloadPacket; import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundDisconnectPacket; -import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundKeepAlivePacket; -import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundKeepAlivePacket; -import com.github.steveice10.mc.protocol.packet.configuration.clientbound.ClientboundFinishConfigurationPacket; -import com.github.steveice10.mc.protocol.packet.configuration.serverbound.ServerboundFinishConfigurationPacket; -import com.github.steveice10.mc.protocol.packet.handshake.serverbound.ClientIntentionPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSystemChatPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundRemoveEntitiesPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundSetEntityDataPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetPlayerTeamPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundConfigurationAcknowledgedPacket; -import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundGameProfilePacket; -import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundHelloPacket; -import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundLoginCompressionPacket; import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundLoginDisconnectPacket; -import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundHelloPacket; -import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundKeyPacket; -import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundLoginAcknowledgedPacket; -import com.github.steveice10.mc.protocol.packet.status.clientbound.ClientboundPongResponsePacket; -import com.github.steveice10.mc.protocol.packet.status.clientbound.ClientboundStatusResponsePacket; -import com.github.steveice10.mc.protocol.packet.status.serverbound.ServerboundPingRequestPacket; -import com.github.steveice10.mc.protocol.packet.status.serverbound.ServerboundStatusRequestPacket; import com.github.steveice10.packetlib.Session; import com.github.steveice10.packetlib.codec.PacketCodecHelper; import com.github.steveice10.packetlib.event.session.SessionListener; import com.github.steveice10.packetlib.packet.Packet; -import com.github.steveice10.packetlib.packet.PacketProtocol; import com.zenith.Proxy; import com.zenith.cache.data.PlayerCache; import com.zenith.cache.data.ServerProfileCache; @@ -53,6 +28,7 @@ import com.zenith.feature.spectator.SpectatorEntityRegistry; import com.zenith.feature.spectator.entity.SpectatorEntity; import com.zenith.module.impl.ActionLimiter; +import com.zenith.network.registry.ZenithHandlerCodec; import com.zenith.util.ComponentSerializer; import lombok.Getter; import lombok.NonNull; @@ -67,7 +43,6 @@ import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; import java.util.*; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; @@ -81,7 +56,7 @@ public class ServerConnection implements Session, SessionListener { protected final Session session; - private static final int DEFAULT_COMPRESSION_THRESHOLD = 256; + public static final int DEFAULT_COMPRESSION_THRESHOLD = 256; // Always empty post-1.7 private static final String SERVER_ID = ""; @@ -140,29 +115,31 @@ public ServerConnection(final Session session) { private static final boolean friendlyFire = false; private static final boolean seeFriendlyInvisibles = false; + public KeyPair getKeyPair() { + return KEY_PAIR; + } + + public String getServerId() { + return SERVER_ID; + } + @Override public void packetReceived(Session session, Packet packet) { try { - if (!defaultPacketReceived(session, packet)) return; - if (this.isLoggedIn) { - Packet p = packet; - if (CONFIG.client.extra.actionLimiter.enabled && !MODULE_MANAGER.get(ActionLimiter.class).bypassesLimits(this)) { - p = MODULE_MANAGER.get(ActionLimiter.class).getHandlerRegistry().handleInbound(p, this); - if (p == null) return; - } - if (isSpectator()) { - p = SERVER_SPECTATOR_HANDLERS.handleInbound(p, this); - if (p != null) { - // there's no use case for this so I'm just disabling sending it to the client - // we still want spectator handlers to process the packet though -// Proxy.getInstance().getClient().sendAsync(packet); - } - } else { - this.lastPacket = System.currentTimeMillis(); - p = SERVER_PLAYER_HANDLERS.handleInbound(p, this); - if (p != null) { - Proxy.getInstance().getClient().sendAsync(p); - } + Packet p = packet; + if (CONFIG.client.extra.actionLimiter.enabled && !MODULE_MANAGER.get(ActionLimiter.class).bypassesLimits(this)) { + p = MODULE_MANAGER.get(ActionLimiter.class).getCodec().handleInbound(p, this); + if (p == null) return; + } + if (isSpectator()) { + p = ZenithHandlerCodec.SERVER_SPECTATOR_CODEC.handleInbound(p, this); + // not passing through ever + } else { + this.lastPacket = System.currentTimeMillis(); + var state = session.getPacketProtocol().getState(); // storing this before handlers might mutate it on the session + p = ZenithHandlerCodec.SERVER_PLAYER_CODEC.handleInbound(p, this); + if (p != null && state == ProtocolState.GAME) { + Proxy.getInstance().getClient().sendAsync(p); } } } catch (final Exception e) { @@ -170,116 +147,14 @@ public void packetReceived(Session session, Packet packet) { } } - private boolean defaultPacketReceived(Session session, Packet packet) { - MinecraftProtocol protocol = (MinecraftProtocol) session.getPacketProtocol(); - if (protocol.getState() == ProtocolState.HANDSHAKE) { - if (packet instanceof ClientIntentionPacket intentionPacket) { - switch (intentionPacket.getIntent()) { - case STATUS: - protocol.setState(ProtocolState.STATUS); - break; - case LOGIN: - protocol.setState(ProtocolState.LOGIN); - if (intentionPacket.getProtocolVersion() > protocol.getCodec().getProtocolVersion()) { - session.disconnect("Outdated server! I'm still on " + protocol.getCodec().getMinecraftVersion() + "."); - } else if (intentionPacket.getProtocolVersion() < protocol.getCodec().getProtocolVersion()) { - session.disconnect("Outdated client! Please use " + protocol.getCodec().getMinecraftVersion() + "."); - } - - break; - default: - throw new UnsupportedOperationException("Invalid client intent: " + intentionPacket.getIntent()); - } - } - return false; - } else if (protocol.getState() == ProtocolState.LOGIN) { - if (packet instanceof ServerboundHelloPacket p) { - this.username = p.getUsername(); - - if (session.getFlag(MinecraftConstants.VERIFY_USERS_KEY, true)) { - session.send(new ClientboundHelloPacket(SERVER_ID, KEY_PAIR.getPublic(), this.challenge)); - } else { - new Thread(new UserAuthTask(session, null)).start(); - } - } else if (packet instanceof ServerboundKeyPacket keyPacket) { - PrivateKey privateKey = KEY_PAIR.getPrivate(); - - if (!Arrays.equals(this.challenge, keyPacket.getEncryptedChallenge(privateKey))) { - session.disconnect("Invalid challenge!"); - return false; - } - - SecretKey key = keyPacket.getSecretKey(privateKey); - session.enableEncryption(key); - new Thread(new UserAuthTask(session, key)).start(); - } else if (packet instanceof ServerboundLoginAcknowledgedPacket) { - ((MinecraftProtocol) session.getPacketProtocol()).setState(ProtocolState.CONFIGURATION); - // todo: handle this more gracefully, connect and wait until we have configuration set (assuming session is auth'd) - if (!Proxy.getInstance().isConnected()) { - session.disconnect("Proxy is not connected to a server."); - return false; - } - CACHE.getConfigurationCache().getPackets(session::sendAsync); - session.sendAsync(new ClientboundCustomPayloadPacket("minecraft:brand", CACHE.getChunkCache().getServerBrand())); - session.sendAsync(new ClientboundFinishConfigurationPacket()); - } - return false; - } else if (protocol.getState() == ProtocolState.STATUS) { - if (packet instanceof ServerboundStatusRequestPacket) { - ServerInfoBuilder builder = session.getFlag(MinecraftConstants.SERVER_INFO_BUILDER_KEY); - if (builder == null) { - builder = $ -> new ServerStatusInfo( - new VersionInfo(protocol.getCodec().getMinecraftVersion(), protocol.getCodec().getProtocolVersion()), - new PlayerInfo(0, 20, new ArrayList<>()), - Component.text("A Minecraft Server"), - null, - false - ); - } - - ServerStatusInfo info = builder.buildInfo(session); - if (info == null) session.disconnect("bye"); - else session.send(new ClientboundStatusResponsePacket(info)); - } else if (packet instanceof ServerboundPingRequestPacket p) { - session.send(new ClientboundPongResponsePacket(p.getPingTime())); - } - return false; - } else if (protocol.getState() == ProtocolState.GAME) { - if (packet instanceof ServerboundKeepAlivePacket p) { - if (p.getPingId() == this.lastPingId) { - long time = System.currentTimeMillis() - this.lastPingTime; - session.setFlag(MinecraftConstants.PING_KEY, time); - } - } else if (packet instanceof ServerboundConfigurationAcknowledgedPacket) { - protocol.setState(ProtocolState.CONFIGURATION); - } else if (packet instanceof ServerboundPingRequestPacket) { - session.send(new ClientboundPongResponsePacket(((ServerboundPingRequestPacket) packet).getPingTime())); - } - } else if (protocol.getState() == ProtocolState.CONFIGURATION) { - if (packet instanceof ServerboundFinishConfigurationPacket) { - protocol.setState(ProtocolState.GAME); - ServerLoginHandler handler = session.getFlag(MinecraftConstants.SERVER_LOGIN_HANDLER_KEY); - if (handler != null) { - handler.loggedIn(session); - } - - if (session.getFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, true)) { - new Thread(new KeepAliveTask(session)).start(); - } - } - return false; - } - return true; - } - @Override public Packet packetSending(final Session session, final Packet packet) { try { Packet p = isSpectator() - ? SERVER_SPECTATOR_HANDLERS.handleOutgoing(packet, this) - : SERVER_PLAYER_HANDLERS.handleOutgoing(packet, this); + ? ZenithHandlerCodec.SERVER_SPECTATOR_CODEC.handleOutgoing(packet, this) + : ZenithHandlerCodec.SERVER_PLAYER_CODEC.handleOutgoing(packet, this); if (p != null && CONFIG.client.extra.actionLimiter.enabled) { - p = MODULE_MANAGER.get(ActionLimiter.class).getHandlerRegistry().handleOutgoing(p, this); + p = MODULE_MANAGER.get(ActionLimiter.class).getCodec().handleOutgoing(p, this); } return p; } catch (final Exception e) { @@ -291,15 +166,11 @@ public Packet packetSending(final Session session, final Packet packet) { @Override public void packetSent(Session session, Packet packet) { - if (packet instanceof ClientboundLoginCompressionPacket) { - session.setCompressionThreshold(((ClientboundLoginCompressionPacket) packet).getThreshold(), true); - session.send(new ClientboundGameProfilePacket(session.getFlag(MinecraftConstants.PROFILE_KEY))); - } try { if (isSpectator()) - SERVER_SPECTATOR_HANDLERS.handlePostOutgoing(packet, this); + ZenithHandlerCodec.SERVER_SPECTATOR_CODEC.handlePostOutgoing(packet, this); else - SERVER_PLAYER_HANDLERS.handlePostOutgoing(packet, this); + ZenithHandlerCodec.SERVER_PLAYER_CODEC.handlePostOutgoing(packet, this); } catch (final Exception e) { SERVER_LOG.error("Failed handling PostOutgoing packet: " + packet.getClass().getSimpleName(), e); } @@ -323,7 +194,7 @@ public void connected(final Session session) { @Override public void disconnecting(final Session session, final Component reason, final Throwable cause) { - MinecraftProtocol protocol = (MinecraftProtocol) session.getPacketProtocol(); + MinecraftProtocol protocol = session.getPacketProtocol(); if (protocol.getState() == ProtocolState.LOGIN) { session.send(new ClientboundLoginDisconnectPacket(reason)); } else if (protocol.getState() == ProtocolState.GAME) { @@ -548,7 +419,7 @@ public SocketAddress getRemoteAddress() { } @Override - public PacketProtocol getPacketProtocol() { + public MinecraftProtocol getPacketProtocol() { return this.session.getPacketProtocol(); } @@ -702,61 +573,4 @@ public void disconnect(@Nullable final Component reason, final Throwable cause) this.session.disconnect(reason, cause); } - private class UserAuthTask implements Runnable { - private Session session; - private SecretKey key; - - public UserAuthTask(Session session, SecretKey key) { - this.key = key; - this.session = session; - } - - @Override - public void run() { - GameProfile profile; - if (this.key != null) { - SessionService sessionService = this.session.getFlag(MinecraftConstants.SESSION_SERVICE_KEY, new SessionService()); - try { - profile = sessionService.getProfileByServer(username, sessionService.getServerId(SERVER_ID, KEY_PAIR.getPublic(), this.key)); - } catch (RequestException e) { - this.session.disconnect("Failed to make session service request.", e); - return; - } - - if (profile == null) { - this.session.disconnect("Failed to verify username."); - } - } else { - profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes()), username); - } - - this.session.setFlag(MinecraftConstants.PROFILE_KEY, profile); - - int threshold = session.getFlag(MinecraftConstants.SERVER_COMPRESSION_THRESHOLD, DEFAULT_COMPRESSION_THRESHOLD); - this.session.send(new ClientboundLoginCompressionPacket(threshold)); - } - } - - private class KeepAliveTask implements Runnable { - private Session session; - - public KeepAliveTask(Session session) { - this.session = session; - } - - @Override - public void run() { - while (this.session.isConnected()) { - lastPingTime = System.currentTimeMillis(); - lastPingId = (int) lastPingTime; - this.session.send(new ClientboundKeepAlivePacket(lastPingId)); - - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - break; - } - } - } - } } diff --git a/src/main/java/com/zenith/network/server/handler/ProxyServerLoginHandler.java b/src/main/java/com/zenith/network/server/handler/ProxyServerLoginHandler.java index 460df7aec..38ee2776a 100644 --- a/src/main/java/com/zenith/network/server/handler/ProxyServerLoginHandler.java +++ b/src/main/java/com/zenith/network/server/handler/ProxyServerLoginHandler.java @@ -14,7 +14,6 @@ import com.zenith.event.proxy.ProxyClientConnectedEvent; import com.zenith.event.proxy.ProxySpectatorConnectedEvent; import com.zenith.network.server.CustomServerInfoBuilder; -import com.zenith.network.server.ProxyServerListener; import com.zenith.network.server.ServerConnection; import com.zenith.util.Wait; import net.kyori.adventure.text.Component; @@ -37,10 +36,7 @@ public ProxyServerLoginHandler(final Proxy proxy) { public void loggedIn(Session session) { final GameProfile clientGameProfile = session.getFlag(MinecraftConstants.PROFILE_KEY); SERVER_LOG.info("Player connected: UUID: {}, Username: {}, Address: {}", clientGameProfile.getId(), clientGameProfile.getName(), session.getRemoteAddress()); - ServerConnection connection = ((ProxyServerListener) this.proxy.getServer().getListeners().stream() - .filter(ProxyServerListener.class::isInstance) - .findAny().orElseThrow(IllegalStateException::new)) - .getConnections().get(session); + ServerConnection connection = (ServerConnection) session; if (!Wait.waitUntilCondition(() -> Proxy.getInstance().isConnected() && this.proxy.getConnectTime().isBefore(Instant.now().minus(Duration.of(3, ChronoUnit.SECONDS))) @@ -89,7 +85,7 @@ && nonNull(CACHE.getTabListCache().get(CACHE.getProfileCache().getProfile().getI } else { EVENT_BUS.post(new ProxyClientConnectedEvent(clientGameProfile)); session.send(new ClientboundLoginPacket( - connection.getSpectatorEntityId(), + CACHE.getPlayerCache().getEntityId(), CACHE.getPlayerCache().isHardcore(), CACHE.getChunkCache().getDimensionRegistry().keySet().toArray(new String[0]), // todo: is this correct? CACHE.getPlayerCache().getMaxPlayers(), diff --git a/src/main/java/com/zenith/network/server/handler/shared/incoming/ConfigurationAckHandler.java b/src/main/java/com/zenith/network/server/handler/shared/incoming/ConfigurationAckHandler.java new file mode 100644 index 000000000..0acae8a34 --- /dev/null +++ b/src/main/java/com/zenith/network/server/handler/shared/incoming/ConfigurationAckHandler.java @@ -0,0 +1,14 @@ +package com.zenith.network.server.handler.shared.incoming; + +import com.github.steveice10.mc.protocol.data.ProtocolState; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundConfigurationAcknowledgedPacket; +import com.zenith.network.registry.PacketHandler; +import com.zenith.network.server.ServerConnection; + +public class ConfigurationAckHandler implements PacketHandler { + @Override + public ServerboundConfigurationAcknowledgedPacket apply(final ServerboundConfigurationAcknowledgedPacket packet, final ServerConnection session) { + session.getPacketProtocol() .setState(ProtocolState.CONFIGURATION); + return packet; + } +} diff --git a/src/main/java/com/zenith/network/server/handler/shared/incoming/FinishConfigurationHandler.java b/src/main/java/com/zenith/network/server/handler/shared/incoming/FinishConfigurationHandler.java new file mode 100644 index 000000000..a8e091953 --- /dev/null +++ b/src/main/java/com/zenith/network/server/handler/shared/incoming/FinishConfigurationHandler.java @@ -0,0 +1,26 @@ +package com.zenith.network.server.handler.shared.incoming; + +import com.github.steveice10.mc.protocol.MinecraftConstants; +import com.github.steveice10.mc.protocol.ServerLoginHandler; +import com.github.steveice10.mc.protocol.data.ProtocolState; +import com.github.steveice10.mc.protocol.packet.configuration.serverbound.ServerboundFinishConfigurationPacket; +import com.zenith.network.KeepAliveTask; +import com.zenith.network.registry.PacketHandler; +import com.zenith.network.server.ServerConnection; + +import static com.zenith.Shared.SCHEDULED_EXECUTOR_SERVICE; + +public class FinishConfigurationHandler implements PacketHandler { + @Override + public ServerboundFinishConfigurationPacket apply(final ServerboundFinishConfigurationPacket packet, final ServerConnection session) { + session.getPacketProtocol().setState(ProtocolState.GAME); + ServerLoginHandler handler = session.getFlag(MinecraftConstants.SERVER_LOGIN_HANDLER_KEY); + if (handler != null) { + handler.loggedIn(session); + } + if (session.getFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, true)) { + SCHEDULED_EXECUTOR_SERVICE.execute(new KeepAliveTask(session)); + } + return null; + } +} diff --git a/src/main/java/com/zenith/network/server/handler/shared/incoming/HelloHandler.java b/src/main/java/com/zenith/network/server/handler/shared/incoming/HelloHandler.java deleted file mode 100644 index efb991d0d..000000000 --- a/src/main/java/com/zenith/network/server/handler/shared/incoming/HelloHandler.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.zenith.network.server.handler.shared.incoming; - -import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundHelloPacket; -import com.zenith.network.registry.PacketHandler; -import com.zenith.network.server.ServerConnection; -import lombok.NonNull; - -public class HelloHandler implements PacketHandler { - @Override - public ServerboundHelloPacket apply(@NonNull ServerboundHelloPacket packet, @NonNull ServerConnection session) { - return null; - } -} diff --git a/src/main/java/com/zenith/network/server/handler/shared/incoming/IntentionHandler.java b/src/main/java/com/zenith/network/server/handler/shared/incoming/IntentionHandler.java new file mode 100644 index 000000000..ac2778a3e --- /dev/null +++ b/src/main/java/com/zenith/network/server/handler/shared/incoming/IntentionHandler.java @@ -0,0 +1,29 @@ +package com.zenith.network.server.handler.shared.incoming; + +import com.github.steveice10.mc.protocol.MinecraftProtocol; +import com.github.steveice10.mc.protocol.data.ProtocolState; +import com.github.steveice10.mc.protocol.packet.handshake.serverbound.ClientIntentionPacket; +import com.zenith.network.registry.PacketHandler; +import com.zenith.network.server.ServerConnection; + +public class IntentionHandler implements PacketHandler { + @Override + public ClientIntentionPacket apply(final ClientIntentionPacket packet, final ServerConnection session) { + MinecraftProtocol protocol = session.getPacketProtocol(); + switch (packet.getIntent()) { + case STATUS -> protocol.setState(ProtocolState.STATUS); + case LOGIN -> { + protocol.setState(ProtocolState.LOGIN); + if (packet.getProtocolVersion() > protocol.getCodec().getProtocolVersion()) { + session.disconnect("Outdated server! I'm still on " + protocol.getCodec() + .getMinecraftVersion() + "."); + } else if (packet.getProtocolVersion() < protocol.getCodec().getProtocolVersion()) { + session.disconnect("Outdated client! Please use " + protocol.getCodec() + .getMinecraftVersion() + "."); + } + } + default -> session.disconnect("Invalid client intention: " + packet.getIntent()); + } + return null; + } +} diff --git a/src/main/java/com/zenith/network/server/handler/shared/incoming/KeepAliveHandler.java b/src/main/java/com/zenith/network/server/handler/shared/incoming/KeepAliveHandler.java index 4f54416f3..6e57244d0 100644 --- a/src/main/java/com/zenith/network/server/handler/shared/incoming/KeepAliveHandler.java +++ b/src/main/java/com/zenith/network/server/handler/shared/incoming/KeepAliveHandler.java @@ -1,5 +1,6 @@ package com.zenith.network.server.handler.shared.incoming; +import com.github.steveice10.mc.protocol.MinecraftConstants; import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundKeepAlivePacket; import com.zenith.network.registry.PacketHandler; import com.zenith.network.server.ServerConnection; @@ -7,6 +8,10 @@ public class KeepAliveHandler implements PacketHandler { @Override public ServerboundKeepAlivePacket apply(final ServerboundKeepAlivePacket packet, final ServerConnection session) { + if (packet.getPingId() == session.getLastPingId()) { + long time = System.currentTimeMillis() - session.getLastPingTime(); + session.setFlag(MinecraftConstants.PING_KEY, time); + } return null; } } diff --git a/src/main/java/com/zenith/network/server/handler/shared/incoming/KeyHandler.java b/src/main/java/com/zenith/network/server/handler/shared/incoming/KeyHandler.java new file mode 100644 index 000000000..cde027611 --- /dev/null +++ b/src/main/java/com/zenith/network/server/handler/shared/incoming/KeyHandler.java @@ -0,0 +1,28 @@ +package com.zenith.network.server.handler.shared.incoming; + +import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundKeyPacket; +import com.zenith.network.UserAuthTask; +import com.zenith.network.registry.PacketHandler; +import com.zenith.network.server.ServerConnection; + +import javax.crypto.SecretKey; +import java.security.PrivateKey; +import java.util.Arrays; + +import static com.zenith.Shared.SCHEDULED_EXECUTOR_SERVICE; + +public class KeyHandler implements PacketHandler { + + @Override + public ServerboundKeyPacket apply(final ServerboundKeyPacket packet, final ServerConnection session) { + PrivateKey privateKey = session.getKeyPair().getPrivate(); + if (!Arrays.equals(session.getChallenge(), packet.getEncryptedChallenge(privateKey))) { + session.disconnect("Invalid challenge!"); + return null; + } + SecretKey key = packet.getSecretKey(privateKey); + session.enableEncryption(key); + SCHEDULED_EXECUTOR_SERVICE.execute(new UserAuthTask(session, key)); + return null; + } +} diff --git a/src/main/java/com/zenith/network/server/handler/shared/incoming/LoginAckHandler.java b/src/main/java/com/zenith/network/server/handler/shared/incoming/LoginAckHandler.java new file mode 100644 index 000000000..d72136f0f --- /dev/null +++ b/src/main/java/com/zenith/network/server/handler/shared/incoming/LoginAckHandler.java @@ -0,0 +1,27 @@ +package com.zenith.network.server.handler.shared.incoming; + +import com.github.steveice10.mc.protocol.data.ProtocolState; +import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundCustomPayloadPacket; +import com.github.steveice10.mc.protocol.packet.configuration.clientbound.ClientboundFinishConfigurationPacket; +import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundLoginAcknowledgedPacket; +import com.zenith.Proxy; +import com.zenith.network.registry.PacketHandler; +import com.zenith.network.server.ServerConnection; + +import static com.zenith.Shared.CACHE; + +public class LoginAckHandler implements PacketHandler { + @Override + public ServerboundLoginAcknowledgedPacket apply(final ServerboundLoginAcknowledgedPacket packet, final ServerConnection session) { + session.getPacketProtocol().setState(ProtocolState.CONFIGURATION); + // todo: handle this more gracefully, connect and wait until we have configuration set (assuming session is auth'd) + if (!Proxy.getInstance().isConnected()) { + session.disconnect("Proxy is not connected to a server."); + return null; + } + CACHE.getConfigurationCache().getPackets(session::sendAsync); + session.sendAsync(new ClientboundCustomPayloadPacket("minecraft:brand", CACHE.getChunkCache().getServerBrand())); + session.sendAsync(new ClientboundFinishConfigurationPacket()); + return null; + } +} diff --git a/src/main/java/com/zenith/network/server/handler/shared/incoming/PingRequestHandler.java b/src/main/java/com/zenith/network/server/handler/shared/incoming/PingRequestHandler.java new file mode 100644 index 000000000..0f72ea01a --- /dev/null +++ b/src/main/java/com/zenith/network/server/handler/shared/incoming/PingRequestHandler.java @@ -0,0 +1,14 @@ +package com.zenith.network.server.handler.shared.incoming; + +import com.github.steveice10.mc.protocol.packet.status.clientbound.ClientboundPongResponsePacket; +import com.github.steveice10.mc.protocol.packet.status.serverbound.ServerboundPingRequestPacket; +import com.zenith.network.registry.PacketHandler; +import com.zenith.network.server.ServerConnection; + +public class PingRequestHandler implements PacketHandler { + @Override + public ServerboundPingRequestPacket apply(final ServerboundPingRequestPacket packet, final ServerConnection session) { + session.send(new ClientboundPongResponsePacket(packet.getPingTime())); + return null; + } +} diff --git a/src/main/java/com/zenith/network/server/handler/shared/incoming/SHelloHandler.java b/src/main/java/com/zenith/network/server/handler/shared/incoming/SHelloHandler.java new file mode 100644 index 000000000..846b67f3f --- /dev/null +++ b/src/main/java/com/zenith/network/server/handler/shared/incoming/SHelloHandler.java @@ -0,0 +1,24 @@ +package com.zenith.network.server.handler.shared.incoming; + +import com.github.steveice10.mc.protocol.MinecraftConstants; +import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundHelloPacket; +import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundHelloPacket; +import com.zenith.network.UserAuthTask; +import com.zenith.network.registry.PacketHandler; +import com.zenith.network.server.ServerConnection; +import lombok.NonNull; + +import static com.zenith.Shared.SCHEDULED_EXECUTOR_SERVICE; + +public class SHelloHandler implements PacketHandler { + @Override + public ServerboundHelloPacket apply(@NonNull ServerboundHelloPacket packet, @NonNull ServerConnection session) { + session.setUsername(packet.getUsername()); + if (session.getFlag(MinecraftConstants.VERIFY_USERS_KEY, true)) { + session.send(new ClientboundHelloPacket(session.getServerId(), session.getKeyPair().getPublic(), session.getChallenge())); + } else { + SCHEDULED_EXECUTOR_SERVICE.execute(new UserAuthTask(session, null)); + } + return null; + } +} diff --git a/src/main/java/com/zenith/network/server/handler/shared/incoming/StatusRequestHandler.java b/src/main/java/com/zenith/network/server/handler/shared/incoming/StatusRequestHandler.java new file mode 100644 index 000000000..ee73e84ed --- /dev/null +++ b/src/main/java/com/zenith/network/server/handler/shared/incoming/StatusRequestHandler.java @@ -0,0 +1,35 @@ +package com.zenith.network.server.handler.shared.incoming; + +import com.github.steveice10.mc.protocol.MinecraftConstants; +import com.github.steveice10.mc.protocol.data.status.PlayerInfo; +import com.github.steveice10.mc.protocol.data.status.ServerStatusInfo; +import com.github.steveice10.mc.protocol.data.status.VersionInfo; +import com.github.steveice10.mc.protocol.data.status.handler.ServerInfoBuilder; +import com.github.steveice10.mc.protocol.packet.status.clientbound.ClientboundStatusResponsePacket; +import com.github.steveice10.mc.protocol.packet.status.serverbound.ServerboundStatusRequestPacket; +import com.zenith.network.registry.PacketHandler; +import com.zenith.network.server.ServerConnection; +import net.kyori.adventure.text.Component; + +import java.util.ArrayList; + +public class StatusRequestHandler implements PacketHandler { + @Override + public ServerboundStatusRequestPacket apply(final ServerboundStatusRequestPacket packet, final ServerConnection session) { + ServerInfoBuilder builder = session.getFlag(MinecraftConstants.SERVER_INFO_BUILDER_KEY); + if (builder == null) { + builder = $ -> new ServerStatusInfo( + new VersionInfo(session.getPacketProtocol().getCodec().getMinecraftVersion(), session.getPacketProtocol().getCodec().getProtocolVersion()), + new PlayerInfo(0, 20, new ArrayList<>()), + Component.text("A Minecraft Server"), + null, + false + ); + } + + ServerStatusInfo info = builder.buildInfo(session); + if (info == null) session.disconnect("bye"); + else session.send(new ClientboundStatusResponsePacket(info)); + return null; + } +} diff --git a/src/main/java/com/zenith/network/server/handler/shared/outgoing/LoginCompressionOutgoingHandler.java b/src/main/java/com/zenith/network/server/handler/shared/outgoing/LoginCompressionOutgoingHandler.java new file mode 100644 index 000000000..6d9d5146e --- /dev/null +++ b/src/main/java/com/zenith/network/server/handler/shared/outgoing/LoginCompressionOutgoingHandler.java @@ -0,0 +1,15 @@ +package com.zenith.network.server.handler.shared.outgoing; + +import com.github.steveice10.mc.protocol.MinecraftConstants; +import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundGameProfilePacket; +import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundLoginCompressionPacket; +import com.zenith.network.registry.PostOutgoingPacketHandler; +import com.zenith.network.server.ServerConnection; + +public class LoginCompressionOutgoingHandler implements PostOutgoingPacketHandler { + @Override + public void accept(final ClientboundLoginCompressionPacket packet, final ServerConnection session) { + session.setCompressionThreshold(packet.getThreshold(), true); + session.send(new ClientboundGameProfilePacket(session.getFlag(MinecraftConstants.PROFILE_KEY))); + } +} diff --git a/src/main/java/com/zenith/network/server/handler/shared/outgoing/GameProfileOutgoingHandler.java b/src/main/java/com/zenith/network/server/handler/shared/outgoing/SGameProfileOutgoingHandler.java similarity index 97% rename from src/main/java/com/zenith/network/server/handler/shared/outgoing/GameProfileOutgoingHandler.java rename to src/main/java/com/zenith/network/server/handler/shared/outgoing/SGameProfileOutgoingHandler.java index 6c94e12bf..d7fa94748 100644 --- a/src/main/java/com/zenith/network/server/handler/shared/outgoing/GameProfileOutgoingHandler.java +++ b/src/main/java/com/zenith/network/server/handler/shared/outgoing/SGameProfileOutgoingHandler.java @@ -13,7 +13,7 @@ import static com.zenith.Shared.*; import static java.util.Objects.isNull; -public class GameProfileOutgoingHandler implements PacketHandler { +public class SGameProfileOutgoingHandler implements PacketHandler { @Override public ClientboundGameProfilePacket apply(@NonNull ClientboundGameProfilePacket packet, @NonNull ServerConnection session) { try {