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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## 7.0.16
* Replace deprecated PlayerLoginEvent with AsyncPlayerPreLoginEvent

## 7.0.14

* Update to 1.21.5
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
group=com.sk89q.worldguard
version=7.0.15-SNAPSHOT
version=7.0.16-SNAPSHOT

org.gradle.parallel=true
Original file line number Diff line number Diff line change
Expand Up @@ -49,24 +49,19 @@
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerGameModeChangeEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.*;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.inventory.ItemStack;

import java.util.Iterator;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.annotation.Nullable;

import static org.bukkit.Bukkit.getPlayer;

/**
* Handles all events thrown in relation to a player.
*/
Expand Down Expand Up @@ -134,6 +129,10 @@ public void onPlayerJoin(PlayerJoinEvent event) {
Events.fire(new ProcessPlayerEvent(player));
WorldGuard.getInstance().getExecutorService().submit(() ->
WorldGuard.getInstance().getProfileCache().put(new Profile(player.getUniqueId(), player.getName())));

if (cfg.deopOnJoin) {
player.setOp(false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible for the player to perform any actions (eg, send commands) prior to this event being fired?

From memory, this event is fired once everything was loaded, and at least in the past the player had partial capabilities prior to this point. Not sure if that's been resolved with the various new stages in the protocol during login though.

If that's the case, it might actually remove some of the purpose of this config option

Copy link
Author

@Woodstop Woodstop Jul 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's correct. Moving the deopOnJoin logic to PlayerJoinEvent could introduce a small window in which an OP player could technically execute a privileged command before being deopped. Since AsyncPlayerPreLoginEvent doesn’t provide a Player object, there might not be a clean way to deop earlier without relying on deprecated methods.

Here's a possible workaround that will check if the player is OP when the config is set to de-op on join before they send a command. The issue is that if the player meets both requirements (is both an OP and should be de-opped on join), it will prevent them from sending any commands at all until everything has fully loaded. Because that is a small or even negligible time window, this could be acceptable. I can't think of another way at the moment.

    @EventHandler(priority = EventPriority.HIGHEST)
    public void onCommand(PlayerCommandPreprocessEvent event) {
        Player player = event.getPlayer();
        ConfigurationManager cfg = getConfig();
        if (player.isOp() && cfg.deopOnJoin) {
            event.setCancelled(true);
            player.sendMessage(ChatColor.RED + "Please wait until you've fully joined.");
        }
    }

}
}

@EventHandler(ignoreCancelled = true)
Expand Down Expand Up @@ -168,13 +167,14 @@ public void onPlayerChat(AsyncPlayerChatEvent event) {
}

@EventHandler(ignoreCancelled = true)
public void onPlayerLogin(PlayerLoginEvent event) {
Player player = event.getPlayer();
public void onPlayerLogin(AsyncPlayerPreLoginEvent event) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this retain Spigot compatibility? From memory, that was the early concern with moving to this event

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is compatible with Spigot API. It has been stable for many versions and is still present up to version 1.21.8. This event is safe to use for async pre-login logic that doesn't require access to the Player object.

UUID uuid = event.getUniqueId();
String name = event.getName();
ConfigurationManager cfg = getConfig();

String hostKey = cfg.hostKeys.get(player.getUniqueId().toString());
String hostKey = cfg.hostKeys.get(uuid);
if (hostKey == null) {
hostKey = cfg.hostKeys.get(player.getName().toLowerCase());
hostKey = cfg.hostKeys.get(name.toLowerCase());
}

if (hostKey != null) {
Expand All @@ -187,18 +187,14 @@ public void onPlayerLogin(PlayerLoginEvent event) {
if (!hostname.equals(hostKey)
&& !(cfg.hostKeysAllowFMLClients &&
(hostname.equals(hostKey + "\u0000FML\u0000") || hostname.equals(hostKey + "\u0000FML2\u0000")))) {
event.disallow(PlayerLoginEvent.Result.KICK_OTHER,
event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER,
"You did not join with the valid host key!");
log.warning("WorldGuard host key check: " +
player.getName() + " joined with '" + hostname +
name + " joined with '" + hostname +
"' but '" + hostKey + "' was expected. Kicked!");
return;
}
}

if (cfg.deopOnJoin) {
player.setOp(false);
}
}

@EventHandler(priority = EventPriority.HIGH)
Expand Down