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());
}
}
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;
}
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);
}
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);
}
}
}
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));
}
}
Aggregations