From cf70b3b839713f5b630e88f33e482c722455c95a Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Thu, 1 Jan 2026 22:30:10 +0800 Subject: [PATCH 1/2] Add configurable delay for gamemode and flight enforcement on world change --- .../multiverse/core/config/CoreConfig.java | 10 ++++++ .../core/config/CoreConfigNodes.java | 10 ++++++ .../core/listeners/MVPlayerListener.java | 34 ++++++++++++------- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/mvplugins/multiverse/core/config/CoreConfig.java b/src/main/java/org/mvplugins/multiverse/core/config/CoreConfig.java index d8a1bec15..33e013289 100644 --- a/src/main/java/org/mvplugins/multiverse/core/config/CoreConfig.java +++ b/src/main/java/org/mvplugins/multiverse/core/config/CoreConfig.java @@ -186,6 +186,16 @@ public boolean getEnforceFlight() { return configHandle.get(configNodes.enforceFlight); } + @ApiStatus.AvailableSince("5.5") + public Try setGamemodeAndFlightEnforceDelay(int delayTicks) { + return configHandle.set(configNodes.gamemodeAndFlightEnforceDelay, delayTicks); + } + + @ApiStatus.AvailableSince("5.5") + public int getGamemodeAndFlightEnforceDelay() { + return configHandle.get(configNodes.gamemodeAndFlightEnforceDelay); + } + @ApiStatus.AvailableSince("5.3") public Try setApplyEntitySpawnRate(boolean applyEntitySpawnRate) { return configHandle.set(configNodes.applyEntitySpawnRate, applyEntitySpawnRate); diff --git a/src/main/java/org/mvplugins/multiverse/core/config/CoreConfigNodes.java b/src/main/java/org/mvplugins/multiverse/core/config/CoreConfigNodes.java index 0dc3f6dda..0ff28781d 100644 --- a/src/main/java/org/mvplugins/multiverse/core/config/CoreConfigNodes.java +++ b/src/main/java/org/mvplugins/multiverse/core/config/CoreConfigNodes.java @@ -135,6 +135,16 @@ private N node(N node) { .name("enforce-flight") .build()); + final ConfigNode gamemodeAndFlightEnforceDelay = node(ConfigNode.builder("world.gamemode-and-flight-enforce-delay", Integer.class) + .comment("") + .comment("Sets the delay in ticks before Multiverse enforces gamemode and flight ability on world change.") + .comment("Increase this value if you are experiencing issues with other plugins overriding gamemode or flight ability.") + .comment("Or set to 0 to enforce immediately during world change event.") + .defaultValue(1) + .name("gamemode-and-flight-enforce-delay") + .suggester((sender -> List.of("0", "1", "2", "5", "10"))) + .build()); + final ConfigNode applyEntitySpawnRate = node(ConfigNode.builder("world.apply-entity-spawn-rate", Boolean.class) .comment("") .comment("Sets whether Multiverse will apply the world's entity `tick-rate` config in worlds.yml.") diff --git a/src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java b/src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java index 9d459e9bc..1a407cfce 100644 --- a/src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java +++ b/src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java @@ -7,9 +7,7 @@ package org.mvplugins.multiverse.core.listeners; -import java.util.Map; import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; import com.dumptruckman.minecraft.util.Logging; import io.vavr.control.Option; @@ -402,21 +400,31 @@ void playerPortal(PlayerPortalEvent event) { } /** - * Handles the gamemode for the specified {@link Player}. + * Handles the gamemode for the specified {@link Player}. Delays the enforcement if configured to do so + * to ensure multiverse has final say over other plugins changing gamemodes. * * @param player The {@link Player}. * @param world The {@link World} the player is supposed to be in. */ private void handleGameModeAndFlight(final Player player, World world) { - // We perform this task one tick later to MAKE SURE that the player actually reaches the - // destination world, otherwise we'd be changing the player mode if they havent moved anywhere. - this.server.getScheduler().runTaskLater(this.plugin, () -> { - if (!player.isOnline() || !player.getWorld().equals(world)) { - return; - } - Logging.finer("Handling gamemode and flight for player %s in world '%s'", player.getName(), world.getName()); - enforcementHandler.handleFlightEnforcement(player); - enforcementHandler.handleGameModeEnforcement(player); - }, 1L); + if (config.getGamemodeAndFlightEnforceDelay() <= 0) { + doGameModeAndFlightEnforcement(player, world); + return; + } + server.getScheduler().runTaskLater( + this.plugin, + () -> doGameModeAndFlightEnforcement(player, world), + config.getGamemodeAndFlightEnforceDelay() + ); + } + + private void doGameModeAndFlightEnforcement(Player player, World world) { + if (!player.isOnline() || !player.getWorld().equals(world)) { + Logging.finer("Player %s is no longer online or not in the expected world '%s'", player.getName(), world.getName()); + return; + } + Logging.finer("Handling gamemode and flight for player %s in world '%s'", player.getName(), world.getName()); + enforcementHandler.handleFlightEnforcement(player); + enforcementHandler.handleGameModeEnforcement(player); } } From c505da76ec849a9922fe0d962f0144c52874b6ac Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Thu, 1 Jan 2026 22:36:26 +0800 Subject: [PATCH 2/2] Fix config test --- src/test/resources/configs/fresh_config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/resources/configs/fresh_config.yml b/src/test/resources/configs/fresh_config.yml index 556916250..54d53e679 100644 --- a/src/test/resources/configs/fresh_config.yml +++ b/src/test/resources/configs/fresh_config.yml @@ -4,6 +4,7 @@ world: enforce-access: false enforce-gamemode: true enforce-flight: true + gamemode-and-flight-enforce-delay: 1 apply-entity-spawn-rate: true apply-entity-spawn-limit: true auto-purge-entities: false