use of org.spongepowered.common.network.channel.TransactionStore 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.common.network.channel.TransactionStore 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();
}
});
}
use of org.spongepowered.common.network.channel.TransactionStore in project SpongeCommon by SpongePowered.
the class SpongeRawLoginDataChannel method sendTo.
@Override
public CompletableFuture<ChannelBuf> sendTo(final EngineConnection connection, final Consumer<ChannelBuf> payload) {
ConnectionUtil.checkHandshakePhase(connection);
final CompletableFuture<ChannelBuf> future = new CompletableFuture<>();
final ChannelBuf buf;
try {
buf = this.parent.encodePayload(payload);
} catch (final Throwable t) {
this.parent.handleException(connection, t, future);
return future;
}
final TransactionStore transactionStore = ConnectionUtil.getTransactionStore(connection);
final int transactionId = transactionStore.nextId();
final Consumer<TransactionResult> resultConsumer = result -> {
if (result.isSuccess()) {
future.complete(result.getPayload());
} else {
this.parent.handleException(connection, result.getCause(), future);
}
};
final Packet<?> mcPacket = PacketUtil.createLoginPayloadRequest(this.parent.key(), buf, transactionId);
PacketSender.sendTo(connection, mcPacket, sendFuture -> {
if (sendFuture.isSuccess()) {
transactionStore.put(transactionId, this.parent, resultConsumer);
} else {
// The packet already failed before it could reach the client
future.completeExceptionally(sendFuture.cause());
}
});
return future;
}
use of org.spongepowered.common.network.channel.TransactionStore in project SpongeCommon by SpongePowered.
the class ServerLoginPacketListenerImplMixin_Vanilla method impl$onTick.
@Inject(method = "tick", at = @At("HEAD"))
private void impl$onTick(final CallbackInfo ci) {
if (this.state == ServerLoginPacketListenerImpl.State.NEGOTIATING) {
final ServerSideConnection connection = (ServerSideConnection) this;
if (this.impl$handshakeState == ServerLoginPacketListenerImplMixin_Vanilla.HANDSHAKE_NOT_STARTED) {
this.impl$handshakeState = ServerLoginPacketListenerImplMixin_Vanilla.HANDSHAKE_CLIENT_TYPE;
((SpongeChannelManager) Sponge.channelManager()).requestClientType(connection).thenAccept(result -> {
this.impl$handshakeState = ServerLoginPacketListenerImplMixin_Vanilla.HANDSHAKE_SYNC_CHANNEL_REGISTRATIONS;
});
} else if (this.impl$handshakeState == ServerLoginPacketListenerImplMixin_Vanilla.HANDSHAKE_SYNC_CHANNEL_REGISTRATIONS) {
((SpongeChannelManager) Sponge.channelManager()).sendLoginChannelRegistry(connection).thenAccept(result -> {
final Cause cause = Cause.of(EventContext.empty(), this);
final ServerSideConnectionEvent.Handshake event = SpongeEventFactory.createServerSideConnectionEventHandshake(cause, connection);
SpongeCommon.post(event);
this.impl$handshakeState = ServerLoginPacketListenerImplMixin_Vanilla.HANDSHAKE_SYNC_PLUGIN_DATA;
});
} else if (this.impl$handshakeState == ServerLoginPacketListenerImplMixin_Vanilla.HANDSHAKE_SYNC_PLUGIN_DATA) {
final TransactionStore store = ConnectionUtil.getTransactionStore(connection);
if (store.isEmpty()) {
this.state = ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT;
}
}
}
}
Aggregations