From 34376b5143794bf8a8251fb8b34f5c03b8b0c0bb Mon Sep 17 00:00:00 2001 From: IzzelAliz Date: Tue, 9 Jun 2020 14:22:17 +0800 Subject: [PATCH] Implement hostname support for PlayerLoginEvent, as well as connection throttling support. Tried to support BungeeCord. --- .../bridge/network/NetworkManagerBridge.java | 19 +++ .../login/ServerLoginNetHandlerBridge.java | 8 ++ .../server/management/PlayerListBridge.java | 5 + .../core/network/NetworkManagerMixin.java | 48 +++++++ .../ServerHandshakeNetHandlerMixin.java | 124 ++++++++++++++++++ .../client/CHandshakePacketMixin.java | 16 +++ ...n.java => ServerLoginNetHandlerMixin.java} | 74 ++++++++++- .../server/management/PlayerListMixin.java | 57 ++++---- .../main/resources/mixins.arclight.core.json | 5 +- 9 files changed, 324 insertions(+), 32 deletions(-) create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/bridge/network/NetworkManagerBridge.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/bridge/network/login/ServerLoginNetHandlerBridge.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/NetworkManagerMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/handshake/ServerHandshakeNetHandlerMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/handshake/client/CHandshakePacketMixin.java rename arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/login/{ServerLoginNetHandler1Mixin.java => ServerLoginNetHandlerMixin.java} (74%) diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/network/NetworkManagerBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/network/NetworkManagerBridge.java new file mode 100644 index 00000000..ccd257e3 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/network/NetworkManagerBridge.java @@ -0,0 +1,19 @@ +package io.izzel.arclight.common.bridge.network; + +import com.mojang.authlib.properties.Property; + +import java.net.SocketAddress; +import java.util.UUID; + +public interface NetworkManagerBridge { + + UUID bridge$getSpoofedUUID(); + + void bridge$setSpoofedUUID(UUID spoofedUUID); + + Property[] bridge$getSpoofedProfile(); + + void bridge$setSpoofedProfile(Property[] spoofedProfile); + + SocketAddress bridge$getRawAddress(); +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/network/login/ServerLoginNetHandlerBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/network/login/ServerLoginNetHandlerBridge.java new file mode 100644 index 00000000..be4daf2f --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/network/login/ServerLoginNetHandlerBridge.java @@ -0,0 +1,8 @@ +package io.izzel.arclight.common.bridge.network.login; + +public interface ServerLoginNetHandlerBridge { + + String bridge$getHostname(); + + void bridge$setHostname(String hostname); +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/server/management/PlayerListBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/server/management/PlayerListBridge.java index 851918af..3be6399c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/server/management/PlayerListBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/server/management/PlayerListBridge.java @@ -1,8 +1,11 @@ package io.izzel.arclight.common.bridge.server.management; +import com.mojang.authlib.GameProfile; import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.network.login.ServerLoginNetHandler; import org.bukkit.craftbukkit.v.CraftServer; +import java.net.SocketAddress; import java.util.List; public interface PlayerListBridge { @@ -12,4 +15,6 @@ public interface PlayerListBridge { List bridge$getPlayers(); CraftServer bridge$getCraftServer(); + + ServerPlayerEntity bridge$canPlayerLogin(SocketAddress socketAddress, GameProfile gameProfile, ServerLoginNetHandler handler); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/NetworkManagerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/NetworkManagerMixin.java new file mode 100644 index 00000000..25ed0a74 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/NetworkManagerMixin.java @@ -0,0 +1,48 @@ +package io.izzel.arclight.common.mixin.core.network; + +import com.mojang.authlib.properties.Property; +import io.izzel.arclight.common.bridge.network.NetworkManagerBridge; +import io.netty.channel.Channel; +import net.minecraft.network.NetworkManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.net.SocketAddress; +import java.util.UUID; + +@Mixin(NetworkManager.class) +public class NetworkManagerMixin implements NetworkManagerBridge { + + @Shadow public Channel channel; + public java.util.UUID spoofedUUID; + public com.mojang.authlib.properties.Property[] spoofedProfile; + + @Override + public UUID bridge$getSpoofedUUID() { + return spoofedUUID; + } + + @Override + public void bridge$setSpoofedUUID(UUID spoofedUUID) { + this.spoofedUUID = spoofedUUID; + } + + @Override + public Property[] bridge$getSpoofedProfile() { + return spoofedProfile; + } + + @Override + public void bridge$setSpoofedProfile(Property[] spoofedProfile) { + this.spoofedProfile = spoofedProfile; + } + + public SocketAddress getRawAddress() { + return this.channel.remoteAddress(); + } + + @Override + public SocketAddress bridge$getRawAddress() { + return getRawAddress(); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/handshake/ServerHandshakeNetHandlerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/handshake/ServerHandshakeNetHandlerMixin.java new file mode 100644 index 00000000..9f0fd97b --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/handshake/ServerHandshakeNetHandlerMixin.java @@ -0,0 +1,124 @@ +package io.izzel.arclight.common.mixin.core.network.handshake; + +import com.google.gson.Gson; +import com.mojang.authlib.properties.Property; +import com.mojang.util.UUIDTypeAdapter; +import io.izzel.arclight.common.bridge.network.NetworkManagerBridge; +import io.izzel.arclight.common.bridge.network.login.ServerLoginNetHandlerBridge; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.ProtocolType; +import net.minecraft.network.handshake.ServerHandshakeNetHandler; +import net.minecraft.network.handshake.client.CHandshakePacket; +import net.minecraft.network.login.ServerLoginNetHandler; +import net.minecraft.network.login.server.SDisconnectLoginPacket; +import net.minecraft.network.status.ServerStatusNetHandler; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.SharedConstants; +import net.minecraft.util.text.TranslationTextComponent; +import net.minecraftforge.fml.server.ServerLifecycleHooks; +import org.apache.logging.log4j.LogManager; +import org.bukkit.Bukkit; +import org.spigotmc.SpigotConfig; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.text.MessageFormat; +import java.util.HashMap; + +@Mixin(ServerHandshakeNetHandler.class) +public class ServerHandshakeNetHandlerMixin { + + private static final Gson gson = new Gson(); + private static final HashMap throttleTracker = new HashMap<>(); + private static int throttleCounter = 0; + + @Shadow @Final private NetworkManager networkManager; + @Shadow @Final private MinecraftServer server; + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + public void processHandshake(CHandshakePacket packetIn) { + if (!ServerLifecycleHooks.handleServerLogin(packetIn, this.networkManager)) return; + switch (packetIn.getRequestedState()) { + case LOGIN: { + this.networkManager.setConnectionState(ProtocolType.LOGIN); + + + try { + long currentTime = System.currentTimeMillis(); + long connectionThrottle = Bukkit.getServer().getConnectionThrottle(); + InetAddress address = ((InetSocketAddress) this.networkManager.getRemoteAddress()).getAddress(); + synchronized (throttleTracker) { + if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { + throttleTracker.put(address, currentTime); + TranslationTextComponent component = new TranslationTextComponent("Connection throttled! Please wait before reconnecting."); + this.networkManager.sendPacket(new SDisconnectLoginPacket(component)); + this.networkManager.closeChannel(component); + return; + } + throttleTracker.put(address, currentTime); + ++throttleCounter; + if (throttleCounter > 200) { + throttleCounter = 0; + throttleTracker.entrySet().removeIf(entry -> entry.getValue() > connectionThrottle); + } + } + } catch (Throwable t) { + LogManager.getLogger().debug("Failed to check connection throttle", t); + } + + + if (packetIn.getProtocolVersion() > SharedConstants.getVersion().getProtocolVersion()) { + TranslationTextComponent component = new TranslationTextComponent(MessageFormat.format(SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getVersion().getName())); + this.networkManager.sendPacket(new SDisconnectLoginPacket(component)); + this.networkManager.closeChannel(component); + break; + } + if (packetIn.getProtocolVersion() < SharedConstants.getVersion().getProtocolVersion()) { + TranslationTextComponent component = new TranslationTextComponent(MessageFormat.format(SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getVersion().getName())); + this.networkManager.sendPacket(new SDisconnectLoginPacket(component)); + this.networkManager.closeChannel(component); + break; + } + this.networkManager.setNetHandler(new ServerLoginNetHandler(this.server, this.networkManager)); + + + if (SpigotConfig.bungee) { + String[] split = packetIn.ip.split("\00"); + if (split.length == 3 || split.length == 4) { + packetIn.ip = split[0]; + this.networkManager.socketAddress = new InetSocketAddress(split[1], ((InetSocketAddress) this.networkManager.getRemoteAddress()).getPort()); + ((NetworkManagerBridge) this.networkManager).bridge$setSpoofedUUID(UUIDTypeAdapter.fromString(split[2])); + } else { + TranslationTextComponent component = new TranslationTextComponent("If you wish to use IP forwarding, please enable it in your BungeeCord config as well!"); + this.networkManager.sendPacket(new SDisconnectLoginPacket(component)); + this.networkManager.closeChannel(component); + return; + } + if (split.length == 4) { + ((NetworkManagerBridge) this.networkManager).bridge$setSpoofedProfile(gson.fromJson(split[3], Property[].class)); + } + } + ((ServerLoginNetHandlerBridge) this.networkManager.getNetHandler()).bridge$setHostname(packetIn.ip + ":" + packetIn.port); + + + break; + } + case STATUS: { + this.networkManager.setConnectionState(ProtocolType.STATUS); + this.networkManager.setNetHandler(new ServerStatusNetHandler(this.server, this.networkManager)); + break; + } + default: { + throw new UnsupportedOperationException("Invalid intention " + packetIn.getRequestedState()); + } + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/handshake/client/CHandshakePacketMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/handshake/client/CHandshakePacketMixin.java new file mode 100644 index 00000000..301141f7 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/handshake/client/CHandshakePacketMixin.java @@ -0,0 +1,16 @@ +package io.izzel.arclight.common.mixin.core.network.handshake.client; + +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.handshake.client.CHandshakePacket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(CHandshakePacket.class) +public class CHandshakePacketMixin { + + @Redirect(method = "readPacketData", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/PacketBuffer;readString(I)Ljava/lang/String;")) + private String arclight$bungeeHostname(PacketBuffer packetBuffer, int maxLength) { + return packetBuffer.readString(Short.MAX_VALUE); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/login/ServerLoginNetHandler1Mixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/login/ServerLoginNetHandlerMixin.java similarity index 74% rename from arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/login/ServerLoginNetHandler1Mixin.java rename to arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/login/ServerLoginNetHandlerMixin.java index 04d58bff..655eecf6 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/login/ServerLoginNetHandler1Mixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/login/ServerLoginNetHandlerMixin.java @@ -1,14 +1,21 @@ package io.izzel.arclight.common.mixin.core.network.login; import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; +import io.izzel.arclight.common.bridge.network.NetworkManagerBridge; +import io.izzel.arclight.common.bridge.network.login.ServerLoginNetHandlerBridge; import io.izzel.arclight.common.bridge.server.MinecraftServerBridge; +import io.izzel.arclight.common.bridge.server.management.PlayerListBridge; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.network.NetworkManager; import net.minecraft.network.login.ServerLoginNetHandler; import net.minecraft.network.login.client.CEncryptionResponsePacket; import net.minecraft.network.login.client.CLoginStartPacket; import net.minecraft.network.login.server.SDisconnectLoginPacket; +import net.minecraft.network.login.server.SEnableCompressionPacket; import net.minecraft.network.login.server.SEncryptionRequestPacket; +import net.minecraft.network.login.server.SLoginSuccessPacket; import net.minecraft.server.MinecraftServer; import net.minecraft.util.CryptManager; import net.minecraft.util.DefaultUncaughtExceptionHandler; @@ -40,7 +47,7 @@ import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; @Mixin(ServerLoginNetHandler.class) -public abstract class ServerLoginNetHandler1Mixin { +public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandlerBridge { // @formatter:off @Shadow private ServerLoginNetHandler.State currentLoginState; @@ -56,6 +63,19 @@ public abstract class ServerLoginNetHandler1Mixin { @Shadow public abstract String getConnectionInfo(); // @formatter:on + @Shadow private ServerPlayerEntity player; + public String hostname; + + @Override + public String bridge$getHostname() { + return hostname; + } + + @Override + public void bridge$setHostname(String hostname) { + this.hostname = hostname; + } + public void disconnect(final String s) { try { final ITextComponent ichatbasecomponent = new StringTextComponent(s); @@ -67,6 +87,40 @@ public abstract class ServerLoginNetHandler1Mixin { } } + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + public void tryAcceptPlayer() { + /* + if (!this.loginGameProfile.isComplete()) { + this.loginGameProfile = this.getOfflineProfile(this.loginGameProfile); + } + */ + + ServerPlayerEntity entity = ((PlayerListBridge) this.server.getPlayerList()).bridge$canPlayerLogin(this.networkManager.getRemoteAddress(), this.loginGameProfile, (ServerLoginNetHandler) (Object) this); + if (entity == null) { + // this.disconnect(itextcomponent); + } else { + this.currentLoginState = ServerLoginNetHandler.State.ACCEPTED; + if (this.server.getNetworkCompressionThreshold() >= 0 && !this.networkManager.isLocalChannel()) { + this.networkManager.sendPacket(new SEnableCompressionPacket(this.server.getNetworkCompressionThreshold()), (p_210149_1_) -> { + this.networkManager.setCompressionThreshold(this.server.getNetworkCompressionThreshold()); + }); + } + + this.networkManager.sendPacket(new SLoginSuccessPacket(this.loginGameProfile)); + ServerPlayerEntity serverplayerentity = this.server.getPlayerList().getPlayerByUUID(this.loginGameProfile.getId()); + if (serverplayerentity != null) { + this.currentLoginState = ServerLoginNetHandler.State.DELAY_ACCEPT; + this.player = entity; + } else { + this.server.getPlayerList().initializeConnectionToPlayer(this.networkManager, entity); + } + } + } + /** * @author IzzelAliz * @reason @@ -102,8 +156,20 @@ public abstract class ServerLoginNetHandler1Mixin { } public void initUUID() { - UUID uuid = PlayerEntity.getOfflineUUID(this.loginGameProfile.getName()); + UUID uuid; + if (((NetworkManagerBridge) this.networkManager).bridge$getSpoofedUUID() != null) { + uuid = ((NetworkManagerBridge) this.networkManager).bridge$getSpoofedUUID(); + } else { + uuid = PlayerEntity.getOfflineUUID(this.loginGameProfile.getName()); + } this.loginGameProfile = new GameProfile(uuid, this.loginGameProfile.getName()); + if (((NetworkManagerBridge) this.networkManager).bridge$getSpoofedProfile() != null) { + Property[] spoofedProfile; + for (int length = (spoofedProfile = ((NetworkManagerBridge) this.networkManager).bridge$getSpoofedProfile()).length, i = 0; i < length; ++i) { + final Property property = spoofedProfile[i]; + this.loginGameProfile.getProperties().put(property.getName(), property); + } + } } /** @@ -131,7 +197,7 @@ public abstract class ServerLoginNetHandler1Mixin { try { String s = (new BigInteger(CryptManager.getServerIdHash("", server.getKeyPair().getPublic(), secretKey))).toString(16); - loginGameProfile = server.getMinecraftSessionService().hasJoinedServer(new GameProfile((UUID) null, gameprofile.getName()), s, this.getAddress()); + loginGameProfile = server.getMinecraftSessionService().hasJoinedServer(new GameProfile(null, gameprofile.getName()), s, this.getAddress()); if (loginGameProfile != null) { if (!networkManager.isChannelOpen()) { return; @@ -143,7 +209,7 @@ public abstract class ServerLoginNetHandler1Mixin { currentLoginState = ServerLoginNetHandler.State.NEGOTIATING; } else { disconnect(new TranslationTextComponent("multiplayer.disconnect.unverified_username")); - LOGGER.error("Username '{}' tried to join with an invalid session", (Object) gameprofile.getName()); + LOGGER.error("Username '{}' tried to join with an invalid session", gameprofile.getName()); } } catch (Exception var3) { if (server.isSinglePlayer()) { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java index 7407aac8..54c69302 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java @@ -4,14 +4,19 @@ import com.google.common.collect.Lists; import com.mojang.authlib.GameProfile; import io.izzel.arclight.common.bridge.entity.player.PlayerEntityBridge; import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge; +import io.izzel.arclight.common.bridge.network.NetworkManagerBridge; +import io.izzel.arclight.common.bridge.network.login.ServerLoginNetHandlerBridge; import io.izzel.arclight.common.bridge.server.MinecraftServerBridge; import io.izzel.arclight.common.bridge.server.management.PlayerListBridge; import io.izzel.arclight.common.bridge.world.WorldBridge; +import io.izzel.arclight.common.mod.ArclightMod; import io.izzel.arclight.common.mod.server.BukkitRegistry; +import io.izzel.arclight.common.mod.util.ArclightCaptures; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.network.IPacket; import net.minecraft.network.NetworkManager; +import net.minecraft.network.login.ServerLoginNetHandler; import net.minecraft.network.play.server.SChangeGameStatePacket; import net.minecraft.network.play.server.SChatPacket; import net.minecraft.network.play.server.SEntityStatusPacket; @@ -55,6 +60,7 @@ import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerRespawnEvent; +import org.spigotmc.SpigotConfig; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -64,11 +70,9 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import io.izzel.arclight.common.mod.ArclightMod; -import io.izzel.arclight.common.mod.util.ArclightCaptures; -import javax.annotation.Nullable; import java.io.File; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.text.SimpleDateFormat; @@ -150,16 +154,11 @@ public abstract class PlayerListMixin implements PlayerListBridge { } } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - @Nullable - public ITextComponent canPlayerLogin(SocketAddress socketAddress, GameProfile gameProfile) { - final UUID uuid = PlayerEntity.getUUID(gameProfile); - final List list = Lists.newArrayList(); - for (final ServerPlayerEntity entityplayer : this.players) { + @Override + public ServerPlayerEntity bridge$canPlayerLogin(SocketAddress socketAddress, GameProfile gameProfile, ServerLoginNetHandler handler) { + UUID uuid = PlayerEntity.getUUID(gameProfile); + List list = Lists.newArrayList(); + for (ServerPlayerEntity entityplayer : this.players) { if (entityplayer.getUniqueID().equals(uuid)) { list.add(entityplayer); } @@ -168,36 +167,40 @@ public abstract class PlayerListMixin implements PlayerListBridge { this.writePlayerData(entityplayer); entityplayer.connection.disconnect(new TranslationTextComponent("multiplayer.disconnect.duplicate_login")); } - final ServerPlayerEntity entity = new ServerPlayerEntity(this.server, this.server.func_71218_a(DimensionType.OVERWORLD), gameProfile, new PlayerInteractionManager(this.server.func_71218_a(DimensionType.OVERWORLD))); - final Player player = ((ServerPlayerEntityBridge) entity).bridge$getBukkitEntity(); - // todo hostname - final PlayerLoginEvent event = new PlayerLoginEvent(player, "", ((InetSocketAddress) socketAddress).getAddress()); + ServerPlayerEntity entity = new ServerPlayerEntity(this.server, this.server.func_71218_a(DimensionType.OVERWORLD), gameProfile, new PlayerInteractionManager(this.server.func_71218_a(DimensionType.OVERWORLD))); + Player player = ((ServerPlayerEntityBridge) entity).bridge$getBukkitEntity(); + + String hostname = handler == null ? "" : ((ServerLoginNetHandlerBridge) handler).bridge$getHostname(); + InetAddress realAddress = handler == null ? ((InetSocketAddress) socketAddress).getAddress() : ((InetSocketAddress) ((NetworkManagerBridge) handler.networkManager).bridge$getRawAddress()).getAddress(); + + PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((InetSocketAddress) socketAddress).getAddress(), realAddress); if (this.getBannedPlayers().isBanned(gameProfile) && !this.getBannedPlayers().getEntry(gameProfile).hasBanExpired()) { - final ProfileBanEntry gameprofilebanentry = this.bannedPlayers.getEntry(gameProfile); - final TranslationTextComponent chatmessage = new TranslationTextComponent("multiplayer.disconnect.banned.reason", gameprofilebanentry.getBanReason()); + ProfileBanEntry gameprofilebanentry = this.bannedPlayers.getEntry(gameProfile); + TranslationTextComponent chatmessage = new TranslationTextComponent("multiplayer.disconnect.banned.reason", gameprofilebanentry.getBanReason()); if (gameprofilebanentry.getBanEndDate() != null) { chatmessage.appendSibling(new TranslationTextComponent("multiplayer.disconnect.banned.expiration", DATE_FORMAT.format(gameprofilebanentry.getBanEndDate()))); } event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); } else if (!this.canJoin(gameProfile)) { - final TranslationTextComponent chatmessage = new TranslationTextComponent("multiplayer.disconnect.not_whitelisted"); - event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, CraftChatMessage.fromComponent(chatmessage)); + event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, SpigotConfig.whitelistMessage); } else if (this.getBannedIPs().isBanned(socketAddress) && !this.getBannedIPs().getBanEntry(socketAddress).hasBanExpired()) { - final IPBanEntry ipbanentry = this.bannedIPs.getBanEntry(socketAddress); - final TranslationTextComponent chatmessage = new TranslationTextComponent("multiplayer.disconnect.banned_ip.reason", ipbanentry.getBanReason()); + IPBanEntry ipbanentry = this.bannedIPs.getBanEntry(socketAddress); + TranslationTextComponent chatmessage = new TranslationTextComponent("multiplayer.disconnect.banned_ip.reason", ipbanentry.getBanReason()); if (ipbanentry.getBanEndDate() != null) { chatmessage.appendSibling(new TranslationTextComponent("multiplayer.disconnect.banned_ip.expiration", DATE_FORMAT.format(ipbanentry.getBanEndDate()))); } event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); } else if (this.players.size() >= this.maxPlayers && !this.bypassesPlayerLimit(gameProfile)) { - event.disallow(PlayerLoginEvent.Result.KICK_FULL, "The server is full"); + event.disallow(PlayerLoginEvent.Result.KICK_FULL, SpigotConfig.serverFullMessage); } this.cserver.getPluginManager().callEvent(event); if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) { - return CraftChatMessage.fromStringOrNull(event.getKickMessage()); - } else { + if (handler != null) { + handler.disconnect(CraftChatMessage.fromStringOrNull(event.getKickMessage())); + } return null; } + return entity; } public ServerPlayerEntity moveToWorld(ServerPlayerEntity playerIn, DimensionType dimension, boolean conqueredEnd, Location location, boolean avoidSuffocation) { @@ -385,7 +388,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { @Inject(method = "playerLoggedOut", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/management/PlayerList;writePlayerData(Lnet/minecraft/entity/player/ServerPlayerEntity;)V")) public void arclight$playerQuitPre(ServerPlayerEntity playerIn, CallbackInfo ci) { CraftEventFactory.handleInventoryCloseEvent(playerIn); - PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(playerIn), "\u00A7e" + playerIn.getName() + " left the game"); + PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(playerIn), "\u00A7e" + playerIn.getName().getFormattedText() + " left the game"); cserver.getPluginManager().callEvent(playerQuitEvent); ((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); playerIn.playerTick(); diff --git a/arclight-common/src/main/resources/mixins.arclight.core.json b/arclight-common/src/main/resources/mixins.arclight.core.json index 81c909d9..a6deb4b7 100644 --- a/arclight-common/src/main/resources/mixins.arclight.core.json +++ b/arclight-common/src/main/resources/mixins.arclight.core.json @@ -308,8 +308,11 @@ "item.crafting.StonecuttingRecipeMixin", "item.crafting.SuspiciousStewRecipeMixin", "item.crafting.TippedArrowRecipeMixin", + "network.NetworkManagerMixin", "network.datasync.EntityDataManagerMixin", - "network.login.ServerLoginNetHandler1Mixin", + "network.handshake.ServerHandshakeNetHandlerMixin", + "network.handshake.client.CHandshakePacketMixin", + "network.login.ServerLoginNetHandlerMixin", "network.play.ServerPlayNetHandlerMixin", "network.play.client.CCloseWindowPacketMixin", "network.play.server.SChatPacketMixin",