Search in sources :

Example 1 with ChannelBuf

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

the class SpongeBasicPacketChannel method handleTransactionResponse.

private <P extends RequestPacket<R>, R extends Packet> void handleTransactionResponse(final EngineConnection connection, final TransactionData<P, R> transactionData, final TransactionResult result) {
    final SpongeTransactionalPacketBinding<P, R> binding = transactionData.binding;
    final P request = transactionData.request;
    if (result.isSuccess()) {
        ChannelBuf responsePayload = result.getPayload();
        // FML wrapper channel key
        responsePayload.readString();
        final int actualLength = responsePayload.readVarInt();
        responsePayload = responsePayload.readSlice(actualLength);
        try {
            final int opcode = this.readOpcode(responsePayload);
            final Supplier<R> responseConstructor;
            if (binding instanceof SpongeFixedTransactionalPacketBinding) {
                // The response packet uses the same binding and opcode,
                // so the returned opcode can be ignored.
                responseConstructor = ((SpongeFixedTransactionalPacketBinding<P, R>) binding).getResponsePacketConstructor();
            } else {
                // The response type was registered separately to a different
                // opcode, so lookup using the opcode.
                final SpongeHandlerPacketBinding<R> responseBinding = (SpongeHandlerPacketBinding<R>) this.byOpcode.get(opcode);
                if (responseBinding == null) {
                    throw new ChannelIOException("Unknown packet opcode: " + opcode);
                }
                responseConstructor = responseBinding.getPacketConstructor();
            }
            final R responsePacket = this.decodePayload(responseConstructor, responsePayload);
            if (transactionData.success != null) {
                transactionData.success.accept(responsePacket);
            }
            this.handleResponse(connection, binding, request, responsePacket);
        } catch (final Throwable ex) {
            this.handleException(connection, ex, transactionData.future);
        }
    } else {
        this.handleException(connection, result.getCause(), transactionData.future);
        this.handleResponseFailure(connection, binding, request, result.getCause());
    }
}
Also used : ChannelIOException(org.spongepowered.api.network.channel.ChannelIOException) ChannelBuf(org.spongepowered.api.network.channel.ChannelBuf)

Example 2 with ChannelBuf

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

the class SpongeBasicPacketChannel method encodePayload.

private ChannelBuf encodePayload(final int opcode, final Packet packet) {
    final ChannelBuf payload = this.manager().getBufferAllocator().buffer();
    payload.writeByte((byte) opcode);
    this.encodePayload(payload, packet);
    return payload;
}
Also used : ChannelBuf(org.spongepowered.api.network.channel.ChannelBuf)

Example 3 with ChannelBuf

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

the class SpongePacketChannel method sendResponsePacketTo.

private <P extends RequestPacket<R>, R extends Packet> void sendResponsePacketTo(final EngineConnection connection, @Nullable final SpongeTransactionalPacketBinding<P, R> requestBinding, @Nullable final R packet, final int transactionId) {
    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 (packet == null || requestBinding instanceof SpongeFixedTransactionalPacketBinding) {
        final int type = packet == null ? SpongePacketChannel.TYPE_NO_RESPONSE : SpongePacketChannel.TYPE_RESPONSE;
        if (isLoginPhase) {
            if (side == EngineConnectionSide.CLIENT) {
                payload.writeVarLong(SpongePacketChannel.packTypeAndValue(type, 0));
                mcPacketSupplier = () -> PacketUtil.createLoginPayloadResponse(payload, transactionId);
            } else {
                payload.writeVarLong(SpongePacketChannel.packTypeAndValue(type, transactionId));
                mcPacketSupplier = () -> PacketUtil.createLoginPayloadRequest(this.key(), payload, Constants.Channels.LOGIN_PAYLOAD_TRANSACTION_ID);
            }
        } else {
            payload.writeVarLong(SpongePacketChannel.packTypeAndValue(type, transactionId));
            mcPacketSupplier = () -> PacketUtil.createPlayPayload(this.key(), payload, side);
        }
    } else {
        // Dynamic opcode
        final int opcode = this.requireBinding(packet.getClass()).opcode();
        if (isLoginPhase) {
            if (side == EngineConnectionSide.CLIENT) {
                payload.writeVarLong(SpongePacketChannel.packTypeAndValue(SpongePacketChannel.TYPE_DYNAMIC_RESPONSE, opcode));
                mcPacketSupplier = () -> PacketUtil.createLoginPayloadResponse(payload, transactionId);
            } else {
                payload.writeVarLong(SpongePacketChannel.packTypeAndValue(SpongePacketChannel.TYPE_DYNAMIC_RESPONSE, transactionId));
                payload.writeVarInt(opcode);
                mcPacketSupplier = () -> PacketUtil.createLoginPayloadRequest(this.key(), payload, Constants.Channels.LOGIN_PAYLOAD_TRANSACTION_ID);
            }
        } else {
            payload.writeVarLong(SpongePacketChannel.packTypeAndValue(SpongePacketChannel.TYPE_DYNAMIC_RESPONSE, transactionId));
            payload.writeVarInt(opcode);
            mcPacketSupplier = () -> PacketUtil.createPlayPayload(this.key(), payload, side);
        }
    }
    try {
        this.encodePayload(payload, packet);
    } catch (final Throwable ex) {
        this.handleException(connection, new ChannelIOException("Failed to encode request response", ex), null);
        return;
    }
    final net.minecraft.network.protocol.Packet<?> mcPacket = mcPacketSupplier.get();
    PacketSender.sendTo(connection, mcPacket);
}
Also used : RequestPacket(org.spongepowered.api.network.channel.packet.RequestPacket) Packet(org.spongepowered.api.network.channel.packet.Packet) ChannelIOException(org.spongepowered.api.network.channel.ChannelIOException) ChannelBuf(org.spongepowered.api.network.channel.ChannelBuf)

Example 4 with ChannelBuf

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

the class SpongePacketChannel method handleTransactionResponse.

@Override
protected void handleTransactionResponse(final EngineConnection connection, final Object stored, final TransactionResult result) {
    if (result.isSuccess()) {
        final ChannelBuf payload = result.getPayload();
        final long typeAndValue = payload.readVarLong();
        final int type = SpongePacketChannel.extractType(typeAndValue);
        final int value = SpongePacketChannel.extractValue(typeAndValue);
        if (type == SpongePacketChannel.TYPE_RESPONSE || type == SpongePacketChannel.TYPE_NO_RESPONSE || type == SpongePacketChannel.TYPE_DYNAMIC_RESPONSE) {
            final TransactionData<RequestPacket<Packet>, Packet> transactionData = (TransactionData<RequestPacket<Packet>, Packet>) stored;
            if (type == SpongePacketChannel.TYPE_RESPONSE) {
                this.handleTransactionResponse(connection, transactionData, result, SpongePacketChannel.NO_DYNAMIC_OPCODE);
            } else if (type == SpongePacketChannel.TYPE_NO_RESPONSE) {
                this.handleTransactionResponse(connection, transactionData, TransactionResult.failure(new NoResponseException()), SpongePacketChannel.NO_DYNAMIC_OPCODE);
            } else {
                this.handleTransactionResponse(connection, transactionData, result, value);
            }
        } else {
            this.handleException(connection, new ChannelIOException("Unknown packet type: " + type), null);
        }
    }
}
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) NoResponseException(org.spongepowered.api.network.channel.NoResponseException)

Example 5 with ChannelBuf

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

the class SpongeRawLoginDataChannel method handleRequestPayload.

<C extends EngineConnection> void handleRequestPayload(final C connection, final ChannelBuf payload, final int transactionId) {
    final RawHandshakeDataRequestHandler<? super C> handler = this.getRequestHandler(connection);
    final RawHandshakeDataRequestResponse response = new RawHandshakeDataRequestResponse() {

        private boolean completed;

        private void checkCompleted() {
            if (this.completed) {
                throw new ChannelException("The request response was already completed.");
            }
            this.completed = true;
        }

        @Override
        public void fail(final ChannelException exception) {
            Objects.requireNonNull(exception, "exception");
            this.checkCompleted();
            PacketSender.sendTo(connection, PacketUtil.createLoginPayloadResponse(null, transactionId));
        }

        @Override
        public void success(final Consumer<ChannelBuf> response) {
            Objects.requireNonNull(response, "response");
            this.checkCompleted();
            final ChannelBuf payload;
            try {
                payload = SpongeRawLoginDataChannel.this.parent.encodePayload(response);
            } catch (final Throwable t) {
                SpongeRawLoginDataChannel.this.parent.handleException(connection, new ChannelException("Failed to encode login data response", t), null);
                PacketSender.sendTo(connection, PacketUtil.createLoginPayloadResponse(null, transactionId));
                return;
            }
            PacketSender.sendTo(connection, PacketUtil.createLoginPayloadResponse(payload, transactionId));
        }
    };
    boolean success = false;
    if (handler != null) {
        try {
            handler.handleRequest(payload, connection, response);
            success = true;
        } catch (final Throwable t) {
            this.parent.handleException(connection, new ChannelException("Failed to handle login data request", t), null);
        }
    }
    if (!success) {
        PacketSender.sendTo(connection, PacketUtil.createLoginPayloadResponse(null, transactionId));
    }
}
Also used : Consumer(java.util.function.Consumer) RawHandshakeDataRequestResponse(org.spongepowered.api.network.channel.raw.handshake.RawHandshakeDataRequestResponse) ChannelBuf(org.spongepowered.api.network.channel.ChannelBuf) ChannelException(org.spongepowered.api.network.channel.ChannelException)

Aggregations

ChannelBuf (org.spongepowered.api.network.channel.ChannelBuf)24 Packet (org.spongepowered.api.network.channel.packet.Packet)6 RequestPacket (org.spongepowered.api.network.channel.packet.RequestPacket)6 ChannelIOException (org.spongepowered.api.network.channel.ChannelIOException)5 CompletableFuture (java.util.concurrent.CompletableFuture)4 ResourceKey (org.spongepowered.api.ResourceKey)4 ChannelException (org.spongepowered.api.network.channel.ChannelException)4 Consumer (java.util.function.Consumer)2 EngineConnection (org.spongepowered.api.network.EngineConnection)2 RawHandshakeDataRequestResponse (org.spongepowered.api.network.channel.raw.handshake.RawHandshakeDataRequestResponse)2 TransactionStore (org.spongepowered.common.network.channel.TransactionStore)2 Map (java.util.Map)1 Objects (java.util.Objects)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 Supplier (java.util.function.Supplier)1 CompoundTag (net.minecraft.nbt.CompoundTag)1 Packet (net.minecraft.network.protocol.Packet)1 EngineConnectionSide (org.spongepowered.api.network.EngineConnectionSide)1 NoResponseException (org.spongepowered.api.network.channel.NoResponseException)1 RequestPacketHandler (org.spongepowered.api.network.channel.packet.RequestPacketHandler)1