Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 45 additions & 39 deletions src/main/java/pw/kaboom/extras/modules/player/PlayerConnection.java
Original file line number Diff line number Diff line change
@@ -1,30 +1,34 @@
package pw.kaboom.extras.modules.player;

import com.destroystokyo.paper.event.profile.PreLookupProfileEvent;
import com.destroystokyo.paper.profile.PlayerProfile;
import com.google.common.base.Charsets;
import io.papermc.paper.event.player.AsyncPlayerSpawnLocationEvent;
import io.papermc.paper.event.connection.PlayerConnectionValidateLoginEvent;
import io.papermc.paper.event.player.PlayerServerFullCheckEvent;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.kyori.adventure.title.Title;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.*;
import org.bukkit.event.player.PlayerLoginEvent.Result;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.java.JavaPlugin;
import pw.kaboom.extras.Main;
import pw.kaboom.extras.modules.server.ServerTabComplete;
import pw.kaboom.extras.modules.player.skin.SkinManager;
import pw.kaboom.extras.util.Utility;

import java.time.Duration;
import java.util.EnumSet;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

public final class PlayerConnection implements Listener {
Expand Down Expand Up @@ -75,6 +79,8 @@ public final class PlayerConnection implements Listener {
PlayerKickEvent.Cause.TOO_MANY_PENDING_CHATS
);

private final Set<UUID> disallowedLogins = Collections.newSetFromMap(new WeakHashMap<>());

@EventHandler
void onAsyncPlayerPreLogin(final AsyncPlayerPreLoginEvent event) {
final Player player = Utility.getPlayerExactIgnoreCase(event.getName());
Expand All @@ -83,32 +89,27 @@ void onAsyncPlayerPreLogin(final AsyncPlayerPreLoginEvent event) {
event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER,
Component.text("A player with that username is already logged in"));
}

/*try {
final PlayerProfile profile = event.getPlayerProfile();

UUID offlineUUID = UUID.nameUUIDFromBytes(
("OfflinePlayer:" + event.getName()).getBytes(Charsets.UTF_8));

profile.setId(offlineUUID);

SkinDownloader skinDownloader = new SkinDownloader();
skinDownloader.fillJoinProfile(profile, event.getName(), event.getUniqueId());
} catch (Exception ignored) {
}*/
}

@EventHandler
void onPlayerJoin(final PlayerJoinEvent event) {
final Player player = event.getPlayer();

if (OP_ON_JOIN && !player.isOp()) {
player.setOp(true);
}

player.showTitle(Title.title(
TITLE,
SUBTITLE,
Title.Times.times(FADE_IN, STAY, FADE_OUT)
));

ServerTabComplete.getLoginNameList().put(player.getUniqueId(), player.getName());

if (!player.getPlayerProfile().hasTextures()) {
SkinManager.applySkin(player, player.getName(), false);
}
}

@EventHandler(ignoreCancelled = true)
Expand All @@ -122,35 +123,40 @@ void onPlayerKick(final PlayerKickEvent event) {
event.setCancelled(true);
}

@EventHandler
void onPlayerLogin(final PlayerLoginEvent event) {
// #312 - If allow join on full server is off,
// but join restrictions are disabled,
// player can still join on full server

// Full server kicks should be handled differently from other join restrictions
// since we have a separate configuration value for it

if (!ENABLE_JOIN_RESTRICTIONS && !Result.KICK_FULL.equals(event.getResult())) {
event.allow();
}
@EventHandler(priority = EventPriority.HIGHEST)
void onPlayerServerFullCheck(final PlayerServerFullCheckEvent event) {
if (event.isAllowed()) return;

if (Result.KICK_FULL.equals(event.getResult()) && ALLOW_JOIN_ON_FULL_SERVER) {
event.allow();
if (ALLOW_JOIN_ON_FULL_SERVER) {
event.allow(true);
return;
}

final Player player = event.getPlayer();
// #312 - If allow join on full server is off, but join restrictions are disabled, player
// can still join on full server

if (OP_ON_JOIN && !player.isOp()) {
player.setOp(true);
// Full server kicks should be handled differently from other join restrictions since we
// have a separate configuration value for it
if (!ENABLE_JOIN_RESTRICTIONS) {
this.disallowedLogins.add(event.getPlayerProfile().getId());
}
}

final Server server = Bukkit.getServer();
// Note that this event gets fired even if FullCheckEvent returns disallowed.
@SuppressWarnings("UnstableApiUsage")
@EventHandler(priority = EventPriority.HIGHEST)
void onPlayerConnectionValidate(final PlayerConnectionValidateLoginEvent event) {
final PlayerProfile profile = Utility.getConnectionUuid(event.getConnection());
final Player player = Utility.getPlayerExactIgnoreCase(profile.getName());
if (player != null) {
event.kickMessage(Component.text("A player with that username is already logged in"));
return;
}

if (ENABLE_JOIN_RESTRICTIONS) return;

if (!server.getOnlineMode()) {
SkinManager.applySkin(player, player.getName(), false);
}
final boolean disallowed = this.disallowedLogins.remove(profile.getId());
if (!disallowed) event.allow();
}

@EventHandler
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitScheduler;
Expand Down Expand Up @@ -110,7 +110,7 @@ private static void onUpdate(Player player) throws IOException {
}

@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerLoginEvent(PlayerLoginEvent event) throws IOException {
public void onPlayerJoinEvent(PlayerJoinEvent event) throws IOException {
final Player player = event.getPlayer();
final boolean isOp = player.isOp();

Expand Down
21 changes: 21 additions & 0 deletions src/main/java/pw/kaboom/extras/util/Utility.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package pw.kaboom.extras.util;

import com.destroystokyo.paper.profile.PlayerProfile;
import io.papermc.paper.connection.PlayerConfigurationConnection;
import io.papermc.paper.connection.PlayerConnection;
import io.papermc.paper.connection.PlayerLoginConnection;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
Expand All @@ -10,13 +14,30 @@
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.jetbrains.annotations.NotNull;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.concurrent.Callable;
import java.util.function.Function;

public final class Utility {
@SuppressWarnings("UnstableApiUsage")
public static @NotNull PlayerProfile getConnectionUuid(final PlayerConnection conn) {
final PlayerProfile profile;

if ((conn instanceof final PlayerLoginConnection login)) {
profile = login.getAuthenticatedProfile(); // This is present even in offline-mode.
} else if ((conn instanceof final PlayerConfigurationConnection config)) {
profile = config.getProfile();
} else {
throw new IllegalStateException("Invalid phase");
}

if (profile == null) throw new IllegalStateException("Connection has no profile");
return profile;
}

public static void teleportToSpawn(final Player player,
final PlayerTeleportEvent.TeleportCause cause) {
final World world = player.getServer().getRespawnWorld();
Expand Down