use of org.spongepowered.api.network.channel.packet.RequestPacket in project SpongeCommon by SpongePowered.
the class SpongePacketChannel method handleResponsePacket.
private void handleResponsePacket(final EngineConnection connection, final int transactionId, @Nullable final ChannelBuf payload, final int dynamicOpcode) {
final TransactionStore store = ConnectionUtil.getTransactionStore(connection);
final TransactionStore.Entry stored = store.remove(transactionId);
if (stored == null) {
return;
}
final TransactionData<RequestPacket<Packet>, Packet> transactionData = (TransactionData<RequestPacket<Packet>, Packet>) stored.getData();
final TransactionResult result = payload == null ? TransactionResult.failure(new NoResponseException()) : TransactionResult.success(payload);
this.handleTransactionResponse(connection, transactionData, result, dynamicOpcode);
}
use of org.spongepowered.api.network.channel.packet.RequestPacket 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.packet.RequestPacket 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.packet.RequestPacket in project SpongeCommon by SpongePowered.
the class SpongePacketChannel method handleRequestPacket.
private <C extends EngineConnection> void handleRequestPacket(final C connection, final int opcode, final int transactionId, final ChannelBuf payload) {
final SpongePacketBinding<Packet> binding = this.requireBinding(opcode);
final Packet request;
try {
request = this.decodePayload(binding.getPacketConstructor(), payload);
} catch (final Throwable ex) {
this.sendResponsePacketTo(connection, null, null, transactionId);
this.handleException(connection, new ChannelIOException("Failed to decode request packet", ex), null);
return;
}
boolean success = false;
Throwable responseFailure = null;
// TODO: Send cause of failure somehow?
if (binding instanceof SpongeTransactionalPacketBinding) {
final RequestPacketHandler<RequestPacket<Packet>, Packet, C> handler = ((SpongeTransactionalPacketBinding) binding).getRequestHandler(connection);
if (handler != null) {
final SpongeRequestPacketResponse<Packet> requestPacketResponse = new SpongeRequestPacketResponse<Packet>() {
@Override
protected void fail0(final ChannelException exception) {
// TODO: Use response failure?
SpongePacketChannel.this.sendResponsePacketTo(connection, null, null, transactionId);
}
@Override
protected void success0(final Packet response) {
SpongePacketChannel.this.sendResponsePacketTo(connection, (SpongeTransactionalPacketBinding) binding, response, transactionId);
}
};
try {
handler.handleRequest((RequestPacket) request, connection, requestPacketResponse);
success = true;
} catch (final Throwable ex) {
this.handleException(connection, new ChannelException("Failed to handle request packet", ex), null);
responseFailure = ex;
}
}
}
if (!success) {
// TODO: Use response failure?
this.sendResponsePacketTo(connection, null, null, transactionId);
}
}
use of org.spongepowered.api.network.channel.packet.RequestPacket 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);
}
}
}
Aggregations