use of org.spongepowered.api.network.ServerSideConnection in project SpongeCommon by SpongePowered.
the class ServerLoginPacketListenerImplMixin method handleAcceptedLogin.
/**
* @author morph - April 27th, 2021
* @author dualspiral - July 17th, 2021
*
* @reason support async ban/whitelist service and user->player syncing.
*/
@Overwrite
public void handleAcceptedLogin() {
if (!this.gameProfile.isComplete()) {
this.gameProfile = this.shadow$createFakeProfile(this.gameProfile);
}
// Sponge start - avoid #tick calling handleAcceptedLogin more than once.
if (this.impl$accepted) {
return;
}
this.impl$accepted = true;
final PlayerList playerList = this.server.getPlayerList();
// Sponge end
// Sponge start - completable future
((PlayerListBridge) playerList).bridge$canPlayerLogin(this.connection.getRemoteAddress(), this.gameProfile).handle((componentOpt, throwable) -> {
if (throwable != null) {
// An error occurred during login checks so we ask to abort.
((ConnectionBridge) this.connection).bridge$setKickReason(new TextComponent("An error occurred checking ban/whitelist status."));
SpongeCommon.logger().error("An error occurred when checking the ban/whitelist status of {}.", this.gameProfile.getId().toString());
SpongeCommon.logger().error(throwable);
} else if (componentOpt != null) {
// We handle this later
((ConnectionBridge) this.connection).bridge$setKickReason(componentOpt);
}
try {
((SpongeServer) SpongeCommon.server()).userManager().handlePlayerLogin(this.gameProfile);
} catch (final IOException e) {
throw new CompletionException(e);
}
return null;
}).handleAsync((ignored, throwable) -> {
if (throwable != null) {
// We're just going to disconnect here, because something went horribly wrong.
if (throwable instanceof CompletionException) {
throw (CompletionException) throwable;
} else {
throw new CompletionException(throwable);
}
}
// Sponge end
this.state = ServerLoginPacketListenerImpl.State.ACCEPTED;
if (this.server.getCompressionThreshold() >= 0 && !this.connection.isMemoryConnection()) {
this.connection.send(new ClientboundLoginCompressionPacket(this.server.getCompressionThreshold()), (param0) -> this.connection.setupCompression(this.server.getCompressionThreshold()));
}
this.connection.send(new ClientboundGameProfilePacket(this.gameProfile));
final ServerPlayer var1 = this.server.getPlayerList().getPlayer(this.gameProfile.getId());
if (var1 != null) {
this.state = ServerLoginPacketListenerImpl.State.DELAY_ACCEPT;
this.delayedAcceptPlayer = this.server.getPlayerList().getPlayerForLogin(this.gameProfile);
} else {
// Sponge start - Also send the channel registrations using the minecraft channel, for compatibility
final ServerSideConnection connection = (ServerSideConnection) this;
((SpongeChannelManager) Sponge.channelManager()).sendChannelRegistrations(connection);
try {
this.server.getPlayerList().placeNewPlayer(this.connection, this.server.getPlayerList().getPlayerForLogin(this.gameProfile));
// invalidate just to be sure there is no user cached for the online player anymore
Sponge.server().userManager().removeFromCache(this.gameProfile.getId());
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
return null;
}, SpongeCommon.server()).exceptionally(throwable -> {
// If a throwable exists, we're just going to disconnect the user, better than leaving them in limbo.
if (throwable != null) {
this.impl$disconnectError(throwable, this.state == ServerLoginPacketListenerImpl.State.ACCEPTED || this.state == ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT);
}
return null;
// Sponge End
});
}
use of org.spongepowered.api.network.ServerSideConnection 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;
}
}
}
}
use of org.spongepowered.api.network.ServerSideConnection in project SpongeCommon by SpongePowered.
the class PlayerListMixin method impl$onInitPlayer_join.
@Inject(method = "placeNewPlayer", at = @At(value = "RETURN"))
private void impl$onInitPlayer_join(final Connection networkManager, final net.minecraft.server.level.ServerPlayer mcPlayer, final CallbackInfo ci) {
final ServerPlayer player = (ServerPlayer) mcPlayer;
final ServerSideConnection connection = player.connection();
final Cause cause = Cause.of(EventContext.empty(), connection, player);
final Audience audience = Audiences.onlinePlayers();
final Component joinComponent = SpongeAdventure.asAdventure(((ServerPlayerBridge) mcPlayer).bridge$getConnectionMessageToSend());
final ServerSideConnectionEvent.Join event = SpongeEventFactory.createServerSideConnectionEventJoin(cause, audience, Optional.of(audience), joinComponent, joinComponent, connection, player, false);
SpongeCommon.post(event);
if (!event.isMessageCancelled()) {
event.audience().ifPresent(audience1 -> audience1.sendMessage(Identity.nil(), event.message()));
}
((ServerPlayerBridge) mcPlayer).bridge$setConnectionMessageToSend(null);
final PhaseContext<?> context = PhaseTracker.SERVER.getPhaseContext();
PhaseTracker.SERVER.pushCause(event);
final TransactionalCaptureSupplier transactor = context.getTransactor();
transactor.logPlayerInventoryChange(mcPlayer, PlayerInventoryTransaction.EventCreator.STANDARD);
try (EffectTransactor ignored = BroadcastInventoryChangesEffect.transact(transactor)) {
// in case plugins modified it
mcPlayer.inventoryMenu.broadcastChanges();
}
}
use of org.spongepowered.api.network.ServerSideConnection in project SpongeCommon by SpongePowered.
the class PlayerListMixin method impl$onInitPlayer_getWorld.
@Redirect(method = "placeNewPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getLevel(Lnet/minecraft/resources/ResourceKey;)Lnet/minecraft/server/level/ServerLevel;"))
private net.minecraft.server.level.ServerLevel impl$onInitPlayer_getWorld(final MinecraftServer minecraftServer, final ResourceKey<Level> dimension, final Connection networkManager, final net.minecraft.server.level.ServerPlayer mcPlayer) {
@Nullable final net.minecraft.network.chat.Component kickReason = ((ConnectionBridge) networkManager).bridge$getKickReason();
final Component disconnectMessage;
if (kickReason != null) {
disconnectMessage = SpongeAdventure.asAdventure(kickReason);
} else {
disconnectMessage = Component.text("You are not allowed to log in to this server.");
}
net.minecraft.server.level.ServerLevel mcWorld = minecraftServer.getLevel(dimension);
if (mcWorld == null) {
SpongeCommon.logger().warn("The player '{}' was located in a world that isn't loaded or doesn't exist. This is not safe so " + "the player will be moved to the spawn of the default world.", mcPlayer.getGameProfile().getName());
mcWorld = minecraftServer.overworld();
final BlockPos spawnPoint = mcWorld.getSharedSpawnPos();
mcPlayer.setPos(spawnPoint.getX() + 0.5, spawnPoint.getY() + 0.5, spawnPoint.getZ() + 0.5);
}
mcPlayer.setLevel(mcWorld);
final ServerPlayer player = (ServerPlayer) mcPlayer;
final ServerLocation location = player.serverLocation();
final Vector3d rotation = player.rotation();
// player.connection() cannot be used here, because it's still be null at this point
final ServerSideConnection connection = (ServerSideConnection) networkManager.getPacketListener();
// The user is not yet in the player list, so we need to make special provision.
final User user = SpongeUserView.createLoginEventUser(player);
final Cause cause = Cause.of(EventContext.empty(), connection, user);
final ServerSideConnectionEvent.Login event = SpongeEventFactory.createServerSideConnectionEventLogin(cause, disconnectMessage, disconnectMessage, location, location, rotation, rotation, connection, user);
if (kickReason != null) {
event.setCancelled(true);
}
if (SpongeCommon.post(event)) {
this.impl$disconnectClient(networkManager, event.message(), player.profile());
return null;
}
final ServerLocation toLocation = event.toLocation();
final Vector3d toRotation = event.toRotation();
mcPlayer.absMoveTo(toLocation.x(), toLocation.y(), toLocation.z(), (float) toRotation.y(), (float) toRotation.x());
return (net.minecraft.server.level.ServerLevel) toLocation.world();
}
use of org.spongepowered.api.network.ServerSideConnection in project SpongeCommon by SpongePowered.
the class ChannelTest method onConnectionJoin.
@Listener
public void onConnectionJoin(final ServerSideConnectionEvent.Join event) {
this.plugin.logger().info("Player \"" + event.player().name() + "\" joined.");
final ServerSideConnection connection = event.connection();
final PingPacket pingPacket1 = new PingPacket(789);
this.channel.sendTo(connection, pingPacket1).thenAccept(response1 -> this.logReceived(this.channel, response1, connection)).exceptionally(cause -> {
this.plugin.logger().error("Failed to get a response to {}", pingPacket1, cause);
return null;
});
this.basicChannel.play().sendTo(connection, new PrintTextPacket("You successfully joined the server.")).exceptionally(cause -> {
this.plugin.logger().error(cause);
return null;
});
}
Aggregations