Skip to content

Commit bfb7459

Browse files
authored
Merge pull request #58 from ez-plugins/57-rtp-without-gui-auto-world-current
57 rtp without gui auto world current
2 parents 24827de + 70c7346 commit bfb7459

10 files changed

Lines changed: 195 additions & 20 deletions

File tree

ezrtp-common/src/main/java/com/skyblockexp/ezrtp/command/ForceRtpCommand.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,21 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command
7171
worldName = forceConfig.getDefaultWorld();
7272
}
7373

74+
// Resolve "auto" to the target player's current world
75+
if ("auto".equalsIgnoreCase(worldName)) {
76+
worldName = target.getWorld().getName();
77+
}
78+
7479
EzRtpConfiguration configuration = configurationSupplier.get();
7580
RandomTeleportSettings settings = configuration != null ? configuration.getSettingsForWorld(worldName) : null;
7681
if (settings == null) {
7782
com.skyblockexp.ezrtp.util.MessageUtil.send(sender, plugin.getMessageProvider().format(MessageKey.FORCERTP_WORLD_MISSING, Map.of("world", worldName != null ? worldName : "default")));
7883
return false;
7984
}
85+
// If getSettingsForWorld returned fallback defaults for a different world, override the world name
86+
if (!worldName.equals(settings.getWorldName())) {
87+
settings = settings.withWorldName(worldName);
88+
}
8089

8190
RandomTeleportService service = teleportServiceSupplier.get();
8291
if (service == null) {
@@ -114,8 +123,9 @@ public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Comman
114123
}
115124

116125
if (args.length == 2) {
117-
// Suggest world names
126+
// Suggest world names and the special "auto" sentinel
118127
List<String> suggestions = new ArrayList<>();
128+
suggestions.add("auto");
119129
for (org.bukkit.World world : Bukkit.getWorlds()) {
120130
suggestions.add(world.getName());
121131
}

ezrtp-common/src/main/java/com/skyblockexp/ezrtp/command/subcommands/ForcertpSubcommand.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,21 @@ public boolean execute(@NotNull CommandSender sender, @NotNull String[] args) {
5858
// Parse optional world argument
5959
String worldName = args.length >= 2 ? args[1] : null;
6060

61+
// Resolve "auto" to the target player's current world
62+
if ("auto".equalsIgnoreCase(worldName)) {
63+
worldName = target.getWorld().getName();
64+
}
65+
6166
EzRtpConfiguration configuration = configurationSupplier.get();
6267
RandomTeleportSettings settings = configuration != null ? configuration.getSettingsForWorld(worldName) : null;
6368
if (settings == null) {
6469
MessageUtil.send(sender, plugin.getMessageProvider().format(MessageKey.FORCERTP_WORLD_MISSING, Map.of("world", worldName != null ? worldName : "default")));
6570
return false;
6671
}
72+
// If getSettingsForWorld returned fallback defaults for a different world, override the world name
73+
if (worldName != null && !worldName.equals(settings.getWorldName())) {
74+
settings = settings.withWorldName(worldName);
75+
}
6776

6877
RandomTeleportService service = teleportServiceSupplier.get();
6978
if (service == null) {
@@ -97,8 +106,9 @@ public List<String> tabComplete(@NotNull CommandSender sender, @NotNull String[]
97106
}
98107

99108
if (args.length == 2) {
100-
// Suggest world names
109+
// Suggest world names and the special "auto" sentinel
101110
List<String> suggestions = new ArrayList<>();
111+
suggestions.add("auto");
102112
for (org.bukkit.World world : Bukkit.getWorlds()) {
103113
suggestions.add(world.getName());
104114
}

ezrtp-common/src/main/java/com/skyblockexp/ezrtp/config/RandomTeleportSettings.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,32 @@ public boolean isHeatmapEnabled() {
156156
return configSection != null && configSection.getBoolean("heatmap.enabled", false);
157157
}
158158

159+
/**
160+
* Returns {@code true} when the configured world name is the special sentinel value {@code "auto"},
161+
* meaning the player's current world should be used as the teleport destination world.
162+
*/
163+
public boolean isAutoWorld() {
164+
return "auto".equalsIgnoreCase(worldName);
165+
}
166+
167+
/**
168+
* Returns a new {@link RandomTeleportSettings} identical to this one, except with the given world name.
169+
* Used to resolve {@code world: auto} to the player's actual current world at teleport time.
170+
*/
171+
public RandomTeleportSettings withWorldName(String newWorldName) {
172+
return new RandomTeleportSettings(
173+
configSection, newWorldName, centerX, centerZ, minimumRadius, maximumRadius,
174+
maxAttempts, useWorldBorderRadius, unsafeBlocks,
175+
messages, particleSettings, onJoinTeleportSettings,
176+
countdownBossBarSettings, countdownParticleSettings,
177+
teleportCost, countdownSeconds, countdownChatMessagesEnabled, debugRejectionLogging,
178+
minY, maxY, biomeInclude, biomeExclude,
179+
protectionSettings, preCacheSettings, rareBiomeOptimizationSettings,
180+
chunkLoadingSettings, enableFallbackToCache, biomeSearchSettings,
181+
biomeFilteringEnabled, biomeSystemEnabled, safetySettings,
182+
searchPattern, chunkyIntegrationSettings);
183+
}
184+
159185
public static RandomTeleportSettings fromConfiguration(ConfigurationSection section, java.util.logging.Logger logger) {
160186
if (section == null) {
161187
return new RandomTeleportSettings(null, "world", 0, 0, 100, 1000, 10, false, java.util.Collections.emptySet(),

ezrtp-common/src/main/java/com/skyblockexp/ezrtp/gui/GuiOptionsBuilder.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,12 @@ private void addWorldOptions(Inventory inventory,
6868
continue;
6969
}
7070

71-
boolean bypass = hasBypass(player, option.getSettings().getWorldName());
71+
// Resolve "auto" to the player's current world for permission and cooldown checks
72+
String worldForChecks =
73+
option.getSettings().isAutoWorld()
74+
? player.getWorld().getName()
75+
: option.getSettings().getWorldName();
76+
boolean bypass = hasBypass(player, worldForChecks);
7277

7378
CooldownInfo cooldownInfo = bypass ? CooldownInfo.inactive() : evaluateCooldown(option);
7479
if (cooldownInfo.active() && !configuration.isAllowGuiDuringCooldown()) {
@@ -94,13 +99,17 @@ private void addWorldOptions(Inventory inventory,
9499
}
95100

96101
private CooldownInfo evaluateCooldown(GuiWorldOption option) {
97-
RtpLimitSettings limit = configuration.getLimitSettings(
98-
option.getSettings().getWorldName(), null);
102+
// Resolve "auto" to the player's current world so storage lookups use the real world key
103+
String worldName =
104+
option.getSettings().isAutoWorld()
105+
? player.getWorld().getName()
106+
: option.getSettings().getWorldName();
107+
RtpLimitSettings limit = configuration.getLimitSettings(worldName, null);
99108
if (limit == null || limit.getCooldownSeconds() <= 0) {
100109
return CooldownInfo.inactive();
101110
}
102111

103-
long lastRtp = usageStorage.getLastRtpTime(player.getUniqueId(), option.getSettings().getWorldName());
112+
long lastRtp = usageStorage.getLastRtpTime(player.getUniqueId(), worldName);
104113
if (lastRtp <= 0) {
105114
return CooldownInfo.inactive();
106115
}
@@ -134,8 +143,13 @@ private boolean meetsCacheRequirements(GuiWorldOption option) {
134143
return false;
135144
}
136145

146+
// Resolve "auto" to the player's current world for cache lookup
147+
String worldName =
148+
option.getSettings().isAutoWorld()
149+
? player.getWorld().getName()
150+
: option.getSettings().getWorldName();
137151
return biomeCache.getCachedLocationCount(
138-
org.bukkit.Bukkit.getWorld(option.getSettings().getWorldName()),
152+
org.bukkit.Bukkit.getWorld(worldName),
139153
option.getSettings().getBiomeInclude()) >= option.getMinimumCached();
140154
}
141155

ezrtp-common/src/main/java/com/skyblockexp/ezrtp/gui/RandomTeleportGuiManager.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,8 @@ public void onInventoryClick(InventoryClickEvent event) {
228228
return;
229229
}
230230

231-
String worldName = settings.getWorldName();
231+
// Resolve "auto" to the player's actual current world for limit checking and usage tracking
232+
String worldName = settings.isAutoWorld() ? player.getWorld().getName() : settings.getWorldName();
232233
boolean bypass = player.isOp();
233234
if (!bypass) {
234235
for (String perm : configuration.getBypassPermissions()) {

ezrtp-common/src/main/java/com/skyblockexp/ezrtp/teleport/TeleportExecutor.java

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,13 @@ private void performTeleport(Player player,
180180
TeleportReason reason,
181181
Consumer<Boolean> callback,
182182
Runnable completionHook) {
183-
World world = plugin.getServer().getWorld(teleportSettings.getWorldName());
183+
final RandomTeleportSettings effectiveSettings = teleportSettings.isAutoWorld()
184+
? teleportSettings.withWorldName(player.getWorld().getName())
185+
: teleportSettings;
186+
World world = plugin.getServer().getWorld(effectiveSettings.getWorldName());
184187
if (world == null) {
185188
com.skyblockexp.ezrtp.util.MessageUtil.send(player, messageProvider.format(MessageKey.WORLD_MISSING,
186-
Map.of("world", teleportSettings.getWorldName()), player));
189+
Map.of("world", effectiveSettings.getWorldName()), player));
187190
if (callback != null) callback.accept(false);
188191
if (completionHook != null) completionHook.run();
189192
return;
@@ -196,9 +199,9 @@ private void performTeleport(Player player,
196199
}
197200

198201
long startTime = System.currentTimeMillis();
199-
CompletableFuture<SearchResult> locationSearchFuture = locationFinder.findSafeLocationAsync(world, teleportSettings);
200-
boolean rareSearch = locationFinder.isRareSearch(teleportSettings);
201-
long searchTimeoutMillis = resolveSearchTimeoutMillis(teleportSettings, rareSearch);
202+
CompletableFuture<SearchResult> locationSearchFuture = locationFinder.findSafeLocationAsync(world, effectiveSettings);
203+
boolean rareSearch = locationFinder.isRareSearch(effectiveSettings);
204+
long searchTimeoutMillis = resolveSearchTimeoutMillis(effectiveSettings, rareSearch);
202205
CompletableFuture<SearchResult> completionFuture = locationSearchFuture;
203206
if (searchTimeoutMillis > 0) {
204207
completionFuture = locationSearchFuture.orTimeout(searchTimeoutMillis, TimeUnit.MILLISECONDS);
@@ -215,21 +218,21 @@ private void performTeleport(Player player,
215218

216219
try {
217220
if (throwable != null || result == null || result.location().isEmpty()) {
218-
if (throwable != null && teleportSettings.isDebugRejectionLoggingEnabled()) {
221+
if (throwable != null && effectiveSettings.isDebugRejectionLoggingEnabled()) {
219222
plugin.getLogger().warning("EzRTP debug: location search failed for player '"
220223
+ player.getName() + "' in world '" + world.getName() + "' after "
221224
+ duration + "ms: " + throwable.getClass().getSimpleName() + " - "
222225
+ throwable.getMessage());
223226
}
224-
resultHandler.handleFailure(player, teleportSettings, result, duration, biome, cacheHit, cacheChecked);
227+
resultHandler.handleFailure(player, effectiveSettings, result, duration, biome, cacheHit, cacheChecked);
225228
if (callback != null) callback.accept(false);
226229
return;
227230
}
228231

229232
validLocation = result.location().get();
230233

231234
if (!player.isOnline()) {
232-
locationFinder.cacheValidLocation(validLocation, teleportSettings);
235+
locationFinder.cacheValidLocation(validLocation, effectiveSettings);
233236
statistics.recordPlayerOfflineOrCancelledFailure();
234237
statistics.recordAttempt(false, duration, biome, cacheHit, cacheChecked);
235238
if (callback != null) callback.accept(false);
@@ -248,15 +251,15 @@ private void performTeleport(Player player,
248251
return;
249252
}
250253

251-
Location destination = TeleportDestinationAdjuster.adjustForSafety(validLocation, teleportSettings);
254+
Location destination = TeleportDestinationAdjuster.adjustForSafety(validLocation, effectiveSettings);
252255
biome = destination.getBlock().getBiome();
253256
Location oldLocation = player.getLocation(); // Store old location before teleport
254257
success = player.teleport(destination);
255258

256259
if (success) {
257-
resultHandler.handleSuccess(player, destination, result, teleportSettings, duration, biome, cacheHit, cacheChecked, validLocation);
260+
resultHandler.handleSuccess(player, destination, result, effectiveSettings, duration, biome, cacheHit, cacheChecked, validLocation);
258261
} else {
259-
locationFinder.cacheValidLocation(validLocation, teleportSettings);
262+
locationFinder.cacheValidLocation(validLocation, effectiveSettings);
260263
com.skyblockexp.ezrtp.util.MessageUtil.send(player, messageProvider.format(MessageKey.TELEPORT_FAILED, player));
261264
statistics.recordTeleportApiFailure();
262265
statistics.recordAttempt(false, duration, biome, cacheHit, cacheChecked);
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package com.skyblockexp.ezrtp.config;
2+
3+
import org.bukkit.configuration.file.YamlConfiguration;
4+
import org.junit.jupiter.api.Test;
5+
6+
import java.util.logging.Logger;
7+
8+
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
import static org.junit.jupiter.api.Assertions.assertFalse;
10+
import static org.junit.jupiter.api.Assertions.assertTrue;
11+
12+
class RandomTeleportSettingsAutoWorldTest {
13+
14+
private static final Logger LOGGER = Logger.getLogger("RandomTeleportSettingsAutoWorldTest");
15+
16+
@Test
17+
void isAutoWorldFalseByDefault() {
18+
YamlConfiguration config = new YamlConfiguration();
19+
20+
RandomTeleportSettings settings = RandomTeleportSettings.fromConfiguration(config, LOGGER);
21+
22+
assertFalse(settings.isAutoWorld(),
23+
"isAutoWorld() should be false when no world key is present");
24+
}
25+
26+
@Test
27+
void isAutoWorldFalseForExplicitWorld() {
28+
YamlConfiguration config = new YamlConfiguration();
29+
config.set("world", "myworld");
30+
31+
RandomTeleportSettings settings = RandomTeleportSettings.fromConfiguration(config, LOGGER);
32+
33+
assertFalse(settings.isAutoWorld(),
34+
"isAutoWorld() should be false for an explicit world name");
35+
}
36+
37+
@Test
38+
void isAutoWorldTrueForAutoLowercase() {
39+
YamlConfiguration config = new YamlConfiguration();
40+
config.set("world", "auto");
41+
42+
RandomTeleportSettings settings = RandomTeleportSettings.fromConfiguration(config, LOGGER);
43+
44+
assertTrue(settings.isAutoWorld(),
45+
"isAutoWorld() should be true when world is 'auto'");
46+
}
47+
48+
@Test
49+
void isAutoWorldTrueForAutoUppercase() {
50+
YamlConfiguration config = new YamlConfiguration();
51+
config.set("world", "AUTO");
52+
53+
RandomTeleportSettings settings = RandomTeleportSettings.fromConfiguration(config, LOGGER);
54+
55+
assertTrue(settings.isAutoWorld(),
56+
"isAutoWorld() should be true when world is 'AUTO' (case-insensitive)");
57+
}
58+
59+
@Test
60+
void withWorldNameReplacesWorldName() {
61+
YamlConfiguration config = new YamlConfiguration();
62+
config.set("world", "auto");
63+
64+
RandomTeleportSettings original = RandomTeleportSettings.fromConfiguration(config, LOGGER);
65+
RandomTeleportSettings resolved = original.withWorldName("farm_nether");
66+
67+
assertEquals("farm_nether", resolved.getWorldName(),
68+
"withWorldName() should set the new world name");
69+
assertFalse(resolved.isAutoWorld(),
70+
"isAutoWorld() should return false after withWorldName() replaces the sentinel");
71+
}
72+
73+
@Test
74+
void withWorldNamePreservesOtherFields() {
75+
YamlConfiguration config = new YamlConfiguration();
76+
config.set("world", "auto");
77+
config.set("radius.min", 200);
78+
config.set("radius.max", 3000);
79+
config.set("max-attempts", 20);
80+
config.set("search-pattern", "circle");
81+
82+
RandomTeleportSettings original = RandomTeleportSettings.fromConfiguration(config, LOGGER);
83+
RandomTeleportSettings resolved = original.withWorldName("some_world");
84+
85+
assertEquals(200, resolved.getMinimumRadius(),
86+
"withWorldName() should preserve minimumRadius");
87+
assertEquals(3000, resolved.getMaximumRadius(),
88+
"withWorldName() should preserve maximumRadius");
89+
assertEquals(20, resolved.getMaxAttempts(),
90+
"withWorldName() should preserve maxAttempts");
91+
assertEquals(com.skyblockexp.ezrtp.config.teleport.SearchPattern.CIRCLE, resolved.getSearchPattern(),
92+
"withWorldName() should preserve searchPattern");
93+
}
94+
}

src/main/resources/force-rtp.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Force RTP configuration
22
# This file controls the behavior of the /forcertp command
33

4-
# Default world to use when no world is specified
4+
# Default world to use when no world is specified.
5+
# Set to a world name (e.g. 'world') or 'auto' to use the target player's current world.
56
default-world: world
67

78
# Bypass settings for the /forcertp command

src/main/resources/gui.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@ filler:
3333
material: GLASS_PANE
3434
name: "<dark_gray> </dark_gray>"
3535
worlds:
36+
# "Current world" option — teleports the player within whichever world they are currently in.
37+
# Useful on multi-world servers so a single button always works regardless of where the player is.
38+
# Uncomment and adjust the slot/icon to add it to your GUI.
39+
# current-world:
40+
# slot: 13
41+
# permission: ""
42+
# icon:
43+
# material: COMPASS
44+
# name: "<aqua><bold>Current World</bold></aqua>"
45+
# lore:
46+
# - "<gray>Teleport randomly within</gray>"
47+
# - "<gray>your current world.</gray>"
48+
# settings:
49+
# world: auto
3650
overworld:
3751
# Slot within the GUI (0-53). When omitted entries are placed in order.
3852
slot: 22

src/main/resources/rtp.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ rtp:
1515
# Optional: restrict random teleport Y-levels (inclusive).
1616
min-y: 54
1717
max-y: 320
18+
# World to teleport players into. Use a world name (e.g. 'world') to always RTP to that world,
19+
# or set to 'auto' to teleport players within their current world (useful for multi-world servers).
1820
world: world
1921
center:
2022
x: 0

0 commit comments

Comments
 (0)