Search in sources :

Example 6 with Packet

use of org.spongepowered.api.network.channel.packet.Packet in project SpongeCommon by SpongePowered.

the class SpongeBasicPacketChannel method handleLoginRequestPayload.

@Override
protected void handleLoginRequestPayload(final EngineConnection connection, final int transactionId, final ChannelBuf payload) {
    // Is currently always executed on the client,
    // the server always expects a response
    final int opcode = this.readOpcode(payload);
    final SpongePacketBinding<Packet> binding = this.requireBinding(opcode);
    final Packet packet = this.decodePayload(() -> binding.getPacketConstructor().get(), payload);
    // A normal packet binding
    if (binding instanceof SpongeHandlerPacketBinding) {
        final SpongeHandlerPacketBinding<Packet> handlerBinding = (SpongeHandlerPacketBinding<Packet>) binding;
        this.handle(connection, handlerBinding, packet);
        // The server always expects a response
        PacketSender.sendTo(connection, PacketUtil.createLoginPayloadResponse(null, transactionId));
    } else {
        // A transactional packet binding
        final SpongeTransactionalPacketBinding<RequestPacket<Packet>, Packet> transactionalBinding = (SpongeTransactionalPacketBinding) binding;
        final RequestPacketHandler<Packet, Packet, EngineConnection> handler = (RequestPacketHandler<Packet, Packet, EngineConnection>) transactionalBinding.getRequestHandler(connection);
        boolean success = false;
        if (handler != null) {
            final SpongeRequestPacketResponse<Packet> response = new SpongeRequestPacketResponse<Packet>() {

                @Override
                protected void fail0(final ChannelException exception) {
                    final net.minecraft.network.protocol.Packet<?> mcPacket = PacketUtil.createLoginPayloadResponse(null, transactionId);
                    PacketSender.sendTo(connection, mcPacket);
                }

                @Override
                protected void success0(final Packet response) {
                    try {
                        final ChannelBuf responsePayload = SpongeBasicPacketChannel.this.encodeLoginPayload(transactionalBinding.opcode(), response);
                        final net.minecraft.network.protocol.Packet<?> mcPacket = PacketUtil.createLoginPayloadResponse(responsePayload, transactionId);
                        PacketSender.sendTo(connection, mcPacket);
                    } catch (final Throwable ex) {
                        SpongeBasicPacketChannel.this.handleException(connection, new ChannelIOException("Failed to encode response packet", ex), null);
                    }
                }
            };
            try {
                handler.handleRequest(packet, connection, response);
                success = true;
            } catch (final Throwable ex) {
                this.handleException(connection, new ChannelIOException("Failed to handle request packet", ex), null);
            }
        }
        if (!success) {
            final net.minecraft.network.protocol.Packet<?> mcPacket = PacketUtil.createLoginPayloadResponse(null, transactionId);
            PacketSender.sendTo(connection, mcPacket);
        }
    }
}
Also used : RequestPacket(org.spongepowered.api.network.channel.packet.RequestPacket) Packet(org.spongepowered.api.network.channel.packet.Packet) RequestPacket(org.spongepowered.api.network.channel.packet.RequestPacket) ChannelIOException(org.spongepowered.api.network.channel.ChannelIOException) ChannelBuf(org.spongepowered.api.network.channel.ChannelBuf) RequestPacketHandler(org.spongepowered.api.network.channel.packet.RequestPacketHandler) EngineConnection(org.spongepowered.api.network.EngineConnection) ChannelException(org.spongepowered.api.network.channel.ChannelException)

Example 7 with Packet

use of org.spongepowered.api.network.channel.packet.Packet in project SpongeCommon by SpongePowered.

the class SpongeBasicPacketChannel method handlePlayPayload.

@Override
protected void handlePlayPayload(final EngineConnection connection, final ChannelBuf payload) {
    final int opcode = this.readOpcode(payload);
    final SpongePacketBinding<Packet> binding = this.requireBinding(opcode);
    final Packet packet = this.decodePayload(() -> binding.getPacketConstructor().get(), payload);
    if (binding instanceof SpongeHandlerPacketBinding) {
        this.handle(connection, (SpongeHandlerPacketBinding<Packet>) binding, packet);
    }
}
Also used : RequestPacket(org.spongepowered.api.network.channel.packet.RequestPacket) Packet(org.spongepowered.api.network.channel.packet.Packet)

Example 8 with Packet

use of org.spongepowered.api.network.channel.packet.Packet in project SpongeCommon by SpongePowered.

the class SpongePacketChannel method sendNormalPacketTo.

private <P extends Packet> void sendNormalPacketTo(final EngineConnection connection, final P packet, final CompletableFuture<Void> future) {
    final SpongePacketBinding<P> binding = (SpongePacketBinding) this.requireBinding(packet.getClass());
    final boolean isLoginPhase = ConnectionUtil.isLoginPhase(connection);
    final EngineConnectionSide<?> side = connection.side();
    final ChannelBuf payload = this.manager().getBufferAllocator().buffer();
    final Supplier<net.minecraft.network.protocol.Packet<?>> mcPacketSupplier;
    if (isLoginPhase) {
        if (side == EngineConnectionSide.CLIENT) {
            payload.writeString(this.key().formatted());
            payload.writeVarLong(SpongePacketChannel.packTypeAndValue(SpongePacketChannel.TYPE_NORMAL, binding.opcode()));
            mcPacketSupplier = () -> PacketUtil.createLoginPayloadResponse(payload, Constants.Channels.LOGIN_PAYLOAD_TRANSACTION_ID);
        } else {
            payload.writeVarLong(SpongePacketChannel.packTypeAndValue(SpongePacketChannel.TYPE_NORMAL, binding.opcode()));
            final int transactionId = ConnectionUtil.getTransactionStore(connection).nextId();
            mcPacketSupplier = () -> PacketUtil.createLoginPayloadRequest(this.key(), payload, transactionId);
        }
    } else {
        payload.writeVarLong(SpongePacketChannel.packTypeAndValue(SpongePacketChannel.TYPE_NORMAL, binding.opcode()));
        mcPacketSupplier = () -> PacketUtil.createPlayPayload(this.key(), payload, side);
    }
    try {
        this.encodePayload(payload, packet);
    } catch (final Throwable ex) {
        future.completeExceptionally(ex);
        return;
    }
    final net.minecraft.network.protocol.Packet<?> mcPacket = mcPacketSupplier.get();
    PacketSender.sendTo(connection, mcPacket, future);
}
Also used : RequestPacket(org.spongepowered.api.network.channel.packet.RequestPacket) Packet(org.spongepowered.api.network.channel.packet.Packet) ChannelBuf(org.spongepowered.api.network.channel.ChannelBuf)

Example 9 with Packet

use of org.spongepowered.api.network.channel.packet.Packet in project SpongeCommon by SpongePowered.

the class SpongePacketChannel method sendRequestPacketTo.

private <P extends RequestPacket<R>, R extends Packet> void sendRequestPacketTo(final EngineConnection connection, final P packet, final CompletableFuture<?> future, @Nullable final Consumer<R> response, @Nullable final Runnable sendSuccess) {
    final SpongeTransactionalPacketBinding<P, R> binding = (SpongeTransactionalPacketBinding) this.requireBinding(packet.getClass());
    final TransactionStore transactionStore = ConnectionUtil.getTransactionStore(connection);
    final int transactionId = transactionStore.nextId();
    final boolean isLoginPhase = ConnectionUtil.isLoginPhase(connection);
    final EngineConnectionSide<?> side = connection.side();
    final ChannelBuf payload = this.manager().getBufferAllocator().buffer();
    final Supplier<net.minecraft.network.protocol.Packet<?>> mcPacketSupplier;
    if (isLoginPhase) {
        if (side == EngineConnectionSide.CLIENT) {
            payload.writeString(this.key().formatted());
            payload.writeVarLong(SpongePacketChannel.packTypeAndValue(SpongePacketChannel.TYPE_REQUEST, transactionId));
            payload.writeVarInt(binding.opcode());
            mcPacketSupplier = () -> PacketUtil.createLoginPayloadResponse(payload, Constants.Channels.LOGIN_PAYLOAD_TRANSACTION_ID);
        } else {
            payload.writeVarLong(SpongePacketChannel.packTypeAndValue(SpongePacketChannel.TYPE_REQUEST, binding.opcode()));
            mcPacketSupplier = () -> PacketUtil.createLoginPayloadRequest(this.key(), payload, transactionId);
        }
    } else {
        payload.writeVarLong(SpongePacketChannel.packTypeAndValue(SpongePacketChannel.TYPE_REQUEST, transactionId));
        payload.writeVarInt(binding.opcode());
        mcPacketSupplier = () -> PacketUtil.createPlayPayload(this.key(), payload, side);
    }
    try {
        this.encodePayload(payload, packet);
    } catch (final Throwable ex) {
        this.handleException(connection, ex, future);
        return;
    }
    if (response != null) {
        final TransactionData<P, R> transactionData = new TransactionData<>(packet, binding, response, future);
        transactionStore.put(transactionId, this, transactionData);
    }
    final net.minecraft.network.protocol.Packet<?> mcPacket = mcPacketSupplier.get();
    PacketSender.sendTo(connection, mcPacket, sendFuture -> {
        if (!sendFuture.isSuccess()) {
            this.handleException(connection, sendFuture.cause(), future);
            // and remove it from the store
            if (response != null) {
                transactionStore.remove(transactionId);
            }
        } else if (sendSuccess != null) {
            sendSuccess.run();
        }
    });
}
Also used : RequestPacket(org.spongepowered.api.network.channel.packet.RequestPacket) Packet(org.spongepowered.api.network.channel.packet.Packet) ChannelBuf(org.spongepowered.api.network.channel.ChannelBuf) TransactionStore(org.spongepowered.common.network.channel.TransactionStore)

Example 10 with Packet

use of org.spongepowered.api.network.channel.packet.Packet in project SpongeCommon by SpongePowered.

the class SpongePacketChannel method handleTransactionResponse.

private <P extends RequestPacket<R>, R extends Packet> void handleTransactionResponse(final EngineConnection connection, final TransactionData<P, R> transactionData, final TransactionResult result, final int dynamicOpcode) {
    if (result.isSuccess()) {
        final ChannelBuf payload = result.getPayload();
        SpongePacketBinding<R> responseBinding = null;
        final Supplier<R> packetSupplier;
        if (dynamicOpcode != SpongePacketChannel.NO_DYNAMIC_OPCODE) {
            responseBinding = (SpongePacketBinding<R>) this.requireBinding(dynamicOpcode);
            packetSupplier = responseBinding.getPacketConstructor();
        } else if (transactionData.binding instanceof SpongeFixedTransactionalPacketBinding) {
            packetSupplier = (Supplier<R>) ((SpongeFixedTransactionalPacketBinding<RequestPacket<Packet>, Packet>) transactionData.binding).getResponsePacketConstructor();
        } else {
            throw new ChannelException("A fixed response was send but no fixed response was bound to the request: " + transactionData.request.getClass());
        }
        final R packet;
        try {
            packet = this.decodePayload(packetSupplier, payload);
        } catch (final Throwable ex) {
            this.handleException(connection, new ChannelIOException("Failed to decode packet", ex), transactionData.future);
            return;
        }
        if (responseBinding != null) {
            this.handle(connection, (SpongeHandlerPacketBinding<Packet>) responseBinding, packet);
        } else {
            this.handleResponse(connection, transactionData.binding, transactionData.request, packet);
        }
        if (transactionData.success != null) {
            transactionData.success.accept(packet);
        }
    } else {
        this.handleException(connection, result.getCause(), transactionData.future);
        this.handleResponseFailure(connection, transactionData.binding, transactionData.request, result.getCause());
    }
}
Also used : RequestPacket(org.spongepowered.api.network.channel.packet.RequestPacket) Packet(org.spongepowered.api.network.channel.packet.Packet) RequestPacket(org.spongepowered.api.network.channel.packet.RequestPacket) ChannelIOException(org.spongepowered.api.network.channel.ChannelIOException) Supplier(java.util.function.Supplier) ChannelBuf(org.spongepowered.api.network.channel.ChannelBuf) ChannelException(org.spongepowered.api.network.channel.ChannelException)

Aggregations

Packet (org.spongepowered.api.network.channel.packet.Packet)11 RequestPacket (org.spongepowered.api.network.channel.packet.RequestPacket)10 ChannelBuf (org.spongepowered.api.network.channel.ChannelBuf)6 ChannelIOException (org.spongepowered.api.network.channel.ChannelIOException)5 ChannelException (org.spongepowered.api.network.channel.ChannelException)3 NoResponseException (org.spongepowered.api.network.channel.NoResponseException)2 TransactionStore (org.spongepowered.common.network.channel.TransactionStore)2 Supplier (java.util.function.Supplier)1 FriendlyByteBuf (net.minecraft.network.FriendlyByteBuf)1 ClientboundCustomPayloadPacket (net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket)1 ServerboundCustomPayloadPacket (net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket)1 ClientboundCustomQueryPacket (net.minecraft.network.protocol.login.ClientboundCustomQueryPacket)1 ServerboundCustomQueryPacket (net.minecraft.network.protocol.login.ServerboundCustomQueryPacket)1 ResourceLocation (net.minecraft.resources.ResourceLocation)1 EngineConnection (org.spongepowered.api.network.EngineConnection)1 RequestPacketHandler (org.spongepowered.api.network.channel.packet.RequestPacketHandler)1 ClientboundCustomPayloadPacketAccessor (org.spongepowered.common.accessor.network.protocol.game.ClientboundCustomPayloadPacketAccessor)1 ServerboundCustomPayloadPacketAccessor (org.spongepowered.common.accessor.network.protocol.game.ServerboundCustomPayloadPacketAccessor)1 TransactionResult (org.spongepowered.common.network.channel.TransactionResult)1