Apollo
Developers
Lightweight
Protobuf
Serverbound Packets

Serverbound Packets

Overview

Players using Lunar Client may send packets to the server for specific Apollo modules, such as the PacketEnrichment Module and/or when the player is joining the server. This example demonstrates how to handle packets sent from the client that are related to Apollo.

Additionally, the Transfer Module expects a response packet from the client after the server sends a request. For an example of how to handle roundtrip packets, visit Packet Roundtrip Example

Integration

public class ApolloPacketReceiveProtoListener implements PluginMessageListener {
 
    public ApolloPacketReceiveProtoListener(ApolloExamplePlugin plugin) {
        Bukkit.getServer().getMessenger().registerIncomingPluginChannel(plugin, "lunar:apollo", this);
    }
 
    @Override
    public void onPluginMessageReceived(@NonNull String channel, @NonNull Player player, byte[] bytes) {
        try {
            Any any = Any.parseFrom(bytes);
 
            if (any.is(PlayerHandshakeMessage.class)) {
                this.onPlayerHandshake(any.unpack(PlayerHandshakeMessage.class));
            }
 
            // Packet Enrichment Module
            if (any.is(PlayerAttackMessage.class)) {
                this.onPlayerAttack(any.unpack(PlayerAttackMessage.class));
            } else if (any.is(PlayerChatOpenMessage.class)) {
                this.onPlayerChatOpen(any.unpack(PlayerChatOpenMessage.class));
            } else if (any.is(PlayerChatCloseMessage.class)) {
                this.onPlayerChatClose(any.unpack(PlayerChatCloseMessage.class));
            } else if (any.is(PlayerUseItemMessage.class)) {
                this.onPlayerUseItem(any.unpack(PlayerUseItemMessage.class));
            } else if (any.is(PlayerUseItemBucketMessage.class)) {
                this.onPlayerUseItemBucket(any.unpack(PlayerUseItemBucketMessage.class));
            }
        } catch (InvalidProtocolBufferException e) {
            throw new RuntimeException(e);
        }
    }
 
    private void onPlayerHandshake(PlayerHandshakeMessage message) {
        EmbeddedCheckoutSupport checkoutSupport = message.getEmbeddedCheckoutSupport();
        MinecraftVersion minecraftVersion = message.getMinecraftVersion();
 
        LunarClientVersion lunarClientVersion = message.getLunarClientVersion();
        String gitBranch = lunarClientVersion.getGitBranch();
        String gitCommit = lunarClientVersion.getGitCommit();
        String semVer = lunarClientVersion.getSemver();
 
        List<ModMessage> installedMods = message.getInstalledModsList();
        for (ModMessage mod : installedMods) {
            String modId = mod.getId();
            String displayName = mod.getName();
            String version = mod.getVersion();
            ModMessage.Type type = mod.getType();
        }
    }
 
    private void onPlayerAttack(PlayerAttackMessage message) {
         long instantiationTimeMs = ProtobufUtil.toJavaTimestamp(message.getPacketInfo().getInstantiationTime());
 
        PlayerInfo targetInfo = message.getTargetInfo();
        PlayerInfo attackerInfo = message.getAttackerInfo();
 
        this.onPlayerInfo(targetInfo);
        this.onPlayerInfo(attackerInfo);
    }
 
    private void onPlayerChatOpen(PlayerChatOpenMessage message) {
        long instantiationTimeMs = ProtobufUtil.toJavaTimestamp(message.getPacketInfo().getInstantiationTime());
 
        PlayerInfo playerInfo = message.getPlayerInfo();
        this.onPlayerInfo(playerInfo);
    }
 
    private void onPlayerChatClose(PlayerChatCloseMessage message) {
        long instantiationTimeMs = ProtobufUtil.toJavaTimestamp(message.getPacketInfo().getInstantiationTime());
 
        PlayerInfo playerInfo = message.getPlayerInfo();
        this.onPlayerInfo(playerInfo);
    }
 
    private void onPlayerUseItem(PlayerUseItemMessage message) {
        long instantiationTimeMs = ProtobufUtil.toJavaTimestamp(message.getPacketInfo().getInstantiationTime());
 
        PlayerInfo playerInfo = message.getPlayerInfo();
        this.onPlayerInfo(playerInfo);
 
        boolean mainHand = message.getMainHand();
    }
 
    private void onPlayerUseItemBucket(PlayerUseItemBucketMessage message) {
        long instantiationTimeMs = ProtobufUtil.toJavaTimestamp(message.getPacketInfo().getInstantiationTime());
 
        PlayerInfo playerInfo = message.getPlayerInfo();
        this.onPlayerInfo(playerInfo);
 
        RayTraceResult rayTraceResult = message.getRayTraceResult();
 
        if (rayTraceResult.hasBlock()) {
            BlockHit blockHit = rayTraceResult.getBlock();
 
            Location hitLocation = blockHit.getHitLocation();
            BlockLocation blockLocation = blockHit.getBlockLocation();
            Direction direction = blockHit.getDirection();
        } else if (rayTraceResult.hasEntity()) {
            EntityHit entityHit = rayTraceResult.getEntity();
            Location hitLocation = entityHit.getHitLocation();
            EntityId entityId = entityHit.getEntityId();
        } else {
            // Miss
        }
    }
 
    private void onPlayerInfo(PlayerInfo info) {
        UUID uuid = ProtobufUtil.toJavaUuid(info.getPlayerUuid());
        org.bukkit.Location location = ProtobufUtil.toBukkitLocation(info.getLocation());
        boolean sneaking = info.getSneaking();
        boolean sprinting = info.getSprinting();
        boolean jumping = info.getJumping();
        float forwardSpeed = info.getForwardSpeed();
        float strafeSpeed = info.getStrafeSpeed();
    }
}