Skip to content

Commit 05d0188

Browse files
authored
Merge pull request #3405 from Multiverse/feat/papi-unloaded-world
Allow placerholders to work on unloaded worlds
2 parents 72ee0d5 + 65c3997 commit 05d0188

3 files changed

Lines changed: 87 additions & 94 deletions

File tree

Lines changed: 62 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.mvplugins.multiverse.core;
22

33
import com.google.common.collect.Lists;
4+
import io.vavr.control.Option;
45
import jakarta.annotation.PostConstruct;
56
import jakarta.inject.Inject;
67
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
@@ -17,6 +18,7 @@
1718
import org.mvplugins.multiverse.core.utils.REPatterns;
1819
import org.mvplugins.multiverse.core.utils.StringFormatter;
1920
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
21+
import org.mvplugins.multiverse.core.world.MultiverseWorld;
2022
import org.mvplugins.multiverse.core.world.WorldManager;
2123

2224
import java.util.List;
@@ -80,14 +82,16 @@ public boolean persist() {
8082
return null;
8183
}
8284

83-
final var placeholder = paramsArray.remove(0);
85+
final var placeholder = paramsArray.remove(0).toLowerCase(Locale.ENGLISH);
8486

8587
String worldName = parseWorldName(offlinePlayer, paramsArray);
8688
if (worldName == null) return null;
8789

88-
return worldManager.getLoadedWorld(worldName)
90+
return worldManager.getWorld(worldName)
8991
.onEmpty(() -> warning("Multiverse World not found: " + worldName))
90-
.map(world -> getWorldPlaceHolderValue(placeholder, paramsArray, world))
92+
.flatMap(world -> world.asLoadedWorld()
93+
.flatMap(loadedWorld -> getLoadedWorldPlaceHolderValue(placeholder, paramsArray, loadedWorld))
94+
.orElse(() -> getWorldPlaceHolderValue(placeholder, paramsArray, world)))
9195
.getOrNull();
9296
}
9397

@@ -104,7 +108,7 @@ public boolean persist() {
104108

105109
// Try get from params
106110
String paramWorldName = paramsArray.get(paramsArray.size() - 1);
107-
if (worldManager.isLoadedWorld(paramWorldName)) {
111+
if (worldManager.isWorld(paramWorldName)) {
108112
paramsArray.remove(paramsArray.size() - 1);
109113
return paramWorldName;
110114
}
@@ -117,99 +121,64 @@ public boolean persist() {
117121
return null;
118122
}
119123

120-
private @Nullable String getWorldPlaceHolderValue(@NotNull String placeholder,
121-
@NotNull List<String> placeholderParams,
122-
@NotNull LoadedMultiverseWorld world) {
123-
// Switch to find what specific placeholder we want
124-
switch (placeholder.toLowerCase(Locale.ENGLISH)) {
125-
case "alias" -> {
126-
return world.getAliasOrName();
124+
private @NotNull Option<String> getWorldPlaceHolderValue(@NotNull String placeholder,
125+
@NotNull List<String> placeholderParams,
126+
@NotNull MultiverseWorld world) {
127+
return Option.of(switch (placeholder) {
128+
case "alias" -> world.getAliasOrName();
129+
case "animalspawn" -> String.valueOf(world.getEntitySpawnConfig()
130+
.getSpawnCategoryConfig(SpawnCategory.ANIMAL)
131+
.isSpawn());
132+
case "autoheal" -> String.valueOf(world.getAutoHeal());
133+
case "blacklist" -> String.join(", ", world.getWorldBlacklist());
134+
case "currency" -> String.valueOf(world.getCurrency());
135+
case "difficulty" -> world.getDifficulty().toString();
136+
case "entryfee" -> economist.formatPrice(world.getPrice(), world.getCurrency());
137+
case "environment" -> world.getEnvironment().toString().toLowerCase();
138+
case "flight" -> String.valueOf(world.isAllowFlight());
139+
case "gamemode" -> world.getGameMode().toString().toLowerCase();
140+
case "generator" -> world.getGenerator();
141+
case "hunger" -> String.valueOf(world.isHunger());
142+
case "monstersspawn" -> String.valueOf(world.getEntitySpawnConfig()
143+
.getSpawnCategoryConfig(SpawnCategory.MONSTER)
144+
.isSpawn());
145+
case "name" -> world.getName();
146+
case "playerlimit" -> String.valueOf(world.getPlayerLimit());
147+
case "price" -> String.valueOf(world.getPrice());
148+
case "pvp" -> String.valueOf(world.getPvp());
149+
case "seed" -> String.valueOf(world.getSeed());
150+
case "weather" -> String.valueOf(world.isAllowWeather());
151+
case "playercount", "time", "type" -> {
152+
warning("Placeholder '" + placeholder + "' is only available for loaded worlds.");
153+
yield null;
127154
}
128-
case "animalspawn" -> {
129-
return String.valueOf(world.getEntitySpawnConfig().getSpawnCategoryConfig(SpawnCategory.ANIMAL).isSpawn());
130-
}
131-
case "autoheal" -> {
132-
return String.valueOf(world.getAutoHeal());
133-
}
134-
case "blacklist" -> {
135-
return String.join(", ", world.getWorldBlacklist());
136-
}
137-
case "currency" -> {
138-
return String.valueOf(world.getCurrency());
139-
}
140-
case "difficulty" -> {
141-
return world.getDifficulty().toString();
142-
}
143-
case "entryfee" -> {
144-
return economist.formatPrice(world.getPrice(), world.getCurrency());
145-
}
146-
case "environment" -> {
147-
return world.getEnvironment().toString().toLowerCase();
148-
}
149-
case "flight" -> {
150-
return String.valueOf(world.isAllowFlight());
151-
}
152-
case "gamemode" -> {
153-
return world.getGameMode().toString().toLowerCase();
154-
}
155-
case "generator" -> {
156-
return world.getGenerator();
157-
}
158-
case "hunger" -> {
159-
return String.valueOf(world.isHunger());
160-
}
161-
case "monstersspawn" -> {
162-
return String.valueOf(world.getEntitySpawnConfig().getSpawnCategoryConfig(SpawnCategory.MONSTER).isSpawn());
163-
}
164-
case "name" -> {
165-
return world.getName();
166-
}
167-
case "playercount" -> {
168-
return String.valueOf(world.getBukkitWorld()
169-
.map(World::getPlayers)
170-
.map(List::size)
171-
.getOrElse(-1));
172-
}
173-
case "playerlimit" -> {
174-
return String.valueOf(world.getPlayerLimit());
175-
}
176-
case "price" -> {
177-
return String.valueOf(world.getPrice());
178-
}
179-
case "pvp" -> {
180-
return String.valueOf(world.getPvp());
181-
}
182-
case "seed" -> {
183-
return String.valueOf(world.getSeed());
155+
default -> {
156+
warning("Unknown Placeholder: " + placeholder);
157+
yield null;
184158
}
159+
});
160+
}
161+
162+
private @NotNull Option<String> getLoadedWorldPlaceHolderValue(@NotNull String placeholder,
163+
@NotNull List<String> placeholderParams,
164+
@NotNull LoadedMultiverseWorld world) {
165+
return Option.of(switch (placeholder) {
166+
case "playercount" -> String.valueOf(world.getBukkitWorld()
167+
.map(World::getPlayers)
168+
.map(List::size)
169+
.getOrElse(-1));
185170
case "time" -> {
186171
String timeFormat = !placeholderParams.isEmpty() ? placeholderParams.get(0) : "";
187172
long time = world.getBukkitWorld().map(World::getTime).getOrElse(0L);
188-
switch (timeFormat) {
189-
case "" -> {
190-
return String.valueOf(time);
191-
}
192-
case "12h" -> {
193-
return MinecraftTimeFormatter.format12h(time);
194-
}
195-
case "24h" -> {
196-
return MinecraftTimeFormatter.format24h(time);
197-
}
198-
default -> {
199-
return MinecraftTimeFormatter.formatTime(time, timeFormat);
200-
}
201-
}
202-
}
203-
case "type" -> {
204-
return world.getBukkitWorld().map(World::getWorldType).map(Enum::name).getOrElse("null");
205-
}
206-
case "weather" -> {
207-
return String.valueOf(world.isAllowWeather());
208-
}
209-
default -> {
210-
warning("Unknown placeholder: " + placeholder);
211-
return null;
212-
}
213-
}
173+
yield switch (timeFormat) {
174+
case "" -> String.valueOf(time);
175+
case "12h" -> MinecraftTimeFormatter.format12h(time);
176+
case "24h" -> MinecraftTimeFormatter.format24h(time);
177+
default -> MinecraftTimeFormatter.formatTime(time, timeFormat);
178+
};
179+
}
180+
case "type" -> world.getBukkitWorld().map(World::getWorldType).map(Enum::name).getOrElse("null");
181+
default -> null;
182+
});
214183
}
215184
}

src/main/java/org/mvplugins/multiverse/core/world/MultiverseWorld.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
import java.util.List;
44

55
import com.google.common.base.Strings;
6+
import io.vavr.control.Option;
67
import io.vavr.control.Try;
78
import org.bukkit.Bukkit;
89
import org.bukkit.Difficulty;
910
import org.bukkit.GameMode;
1011
import org.bukkit.Location;
1112
import org.bukkit.Material;
1213
import org.bukkit.World;
14+
import org.jetbrains.annotations.ApiStatus;
1315
import org.jetbrains.annotations.NotNull;
1416
import org.jetbrains.annotations.Nullable;
1517

@@ -66,14 +68,32 @@ public String getTabCompleteName() {
6668
}
6769

6870
/**
69-
* Gets whether this world is loaded.
71+
* Gets whether this world is loaded. Note that this may return false even if this is a stored instance of
72+
* {@link LoadedMultiverseWorld} as worlds can be unloaded anytime.
7073
*
7174
* @return True if the world is loaded, else false.
7275
*/
7376
public boolean isLoaded() {
7477
return worldConfig.isLoadedWorld();
7578
}
7679

80+
/**
81+
* Attempts to get loaded world instance. Only returns a value if the world is loaded at the time of calling, even
82+
* if this is a stored instance of {@link LoadedMultiverseWorld}.
83+
* <br/>
84+
* You may use {@link #isLoaded()} to check if the world is loaded first.
85+
*
86+
* @return Loaded world instance wrapped in an Option, or None if the world is not loaded.
87+
*
88+
* @since 5.5
89+
*/
90+
@ApiStatus.AvailableSince("5.5")
91+
public Option<LoadedMultiverseWorld> asLoadedWorld() {
92+
return Option.of(worldConfig.getMVWorld())
93+
.filter(world -> world instanceof LoadedMultiverseWorld)
94+
.map(world -> (LoadedMultiverseWorld) world);
95+
}
96+
7797
/**
7898
* Gets the properties handler of this world.
7999
*

src/main/java/org/mvplugins/multiverse/core/world/WorldConfig.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,10 @@ void setMVWorld(@NotNull MultiverseWorld world) {
381381
configNodes.setWorld(world);
382382
}
383383

384+
MultiverseWorld getMVWorld() {
385+
return configNodes.getWorld();
386+
}
387+
384388
boolean isLoadedWorld() {
385389
return configNodes.getWorld() instanceof LoadedMultiverseWorld;
386390
}

0 commit comments

Comments
 (0)