Skip to content

Commit

Permalink
Implement default-respawn-to-world-spawn config option and refactor r…
Browse files Browse the repository at this point in the history
…espawn event
  • Loading branch information
benwoo1110 committed Jan 16, 2025
1 parent 971a159 commit ed5a13b
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 40 deletions.
12 changes: 12 additions & 0 deletions src/main/java/org/mvplugins/multiverse/core/api/MVConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,18 @@ public interface MVConfig {
*/
String getJoinDestination();

/**
* Sets defaultRespawnToWorldSpawn.
* @param defaultRespawnToWorldSpawn The new value
*/
void setDefaultRespawnToWorldSpawn(boolean defaultRespawnToWorldSpawn);

/**
* Gets defaultRespawnToWorldSpawn
* @return defaultRespawnToWorldSpawn
*/
boolean getDefaultRespawnToWorldSpawn();

/**
* Sets whether or not to let Bukkit determine portal search radius on its own or if Multiverse should give input.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,16 @@ public String getJoinDestination() {
return configHandle.get(configNodes.JOIN_DESTINATION);
}

@Override
public void setDefaultRespawnToWorldSpawn(boolean defaultRespawnToWorldSpawn) {
configHandle.set(configNodes.DEFAULT_RESPAWN_TO_WORLD_SPAWN, defaultRespawnToWorldSpawn);
}

@Override
public boolean getDefaultRespawnToWorldSpawn() {
return configHandle.get(configNodes.DEFAULT_RESPAWN_TO_WORLD_SPAWN);
}

@Override
public void setUseCustomPortalSearch(boolean useDefaultPortalSearch) {
configHandle.set(configNodes.USE_CUSTOM_PORTAL_SEARCH, useDefaultPortalSearch);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,16 @@ private <N extends Node> N node(N node) {
.name("join-destination")
.build());

final ConfigNode<Boolean> DEFAULT_RESPAWN_TO_WORLD_SPAWN = node(ConfigNode.builder("spawn.default-respawn-to-world-spawn", Boolean.class)
.comment("")
.comment("By default when `respawn-world` is not set, players will respawn at the world's spawn location that they died in.")
.comment("If you want another plugin to handle respawn, or use vanilla /spawnpoint, set this to false.")
.comment("This only applies if the `respawn-world` property is not set for the world that the player died in.")
.comment("You can set `respawn-world` property by running the command: `/mv modify <worldname> set respawn-world <worldname>`")
.defaultValue(true)
.name("default-respawn-to-world-spawn")
.build());

private final ConfigHeaderNode PORTAL_HEADER = node(ConfigHeaderNode.builder("portal")
.comment("")
.comment("")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import io.vavr.control.Option;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Server;
Expand Down Expand Up @@ -119,48 +120,43 @@ public Map<String, String> getPlayerWorld() {
*/
@EventHandler(priority = EventPriority.LOW)
public void playerRespawn(PlayerRespawnEvent event) {
World world = event.getPlayer().getWorld();
LoadedMultiverseWorld mvWorld = getWorldManager().getLoadedWorld(world.getName()).getOrNull();
// If it's not a World MV manages we stop.
if (mvWorld == null) {
return;
}

if (mvWorld.getBedRespawn() && event.isBedSpawn()) {
Logging.fine("Spawning %s at their bed.", event.getPlayer().getName());
return;
}

if (mvWorld.getAnchorRespawn() && event.isAnchorSpawn()) {
Logging.fine("Spawning %s at their anchor.", event.getPlayer().getName());
return;
}

// Get the instance of the World the player should respawn at.
LoadedMultiverseWorld respawnWorld = null;
if (getWorldManager().isLoadedWorld(mvWorld.getRespawnWorld())) {
respawnWorld = getWorldManager().getLoadedWorld(mvWorld.getRespawnWorld()).getOrNull();
}

// If it's null then it either means the World doesn't exist or the value is blank, so we don't handle it.
// NOW: We'll always handle it to get more accurate spawns
if (respawnWorld != null) {
world = respawnWorld.getBukkitWorld().getOrNull();
}
// World has been set to the appropriate world
Location respawnLocation = getMostAccurateRespawnLocation(world);

MVRespawnEvent respawnEvent = new MVRespawnEvent(respawnLocation, event.getPlayer(), "compatability");
this.server.getPluginManager().callEvent(respawnEvent);
event.setRespawnLocation(respawnEvent.getPlayersRespawnLocation());
Player player = event.getPlayer();
getWorldManager().getLoadedWorld(player.getWorld())
.onEmpty(() -> Logging.fine("Player '%s' is in a world that is not managed by Multiverse.", player.getName()))
.filter(mvWorld -> {
if (mvWorld.getBedRespawn() && event.isBedSpawn()) {
Logging.fine("Spawning %s at their bed.", player.getName());
return false;
}
if (mvWorld.getAnchorRespawn() && event.isAnchorSpawn()) {
Logging.fine("Spawning %s at their anchor.", player.getName());
return false;
}
if (!config.getDefaultRespawnToWorldSpawn() && mvWorld.getRespawnWorldName().isBlank()) {
Logging.fine("Not overriding respawn location for player '%s' as " +
"default-respawn-to-world-spawn is disabled and no respawn-world is set.", player.getName());
return false;
}
return true;
})
.flatMap(mvWorld -> getMostAccurateRespawnLocation (player, mvWorld))
.peek(newRespawnLocation -> {
MVRespawnEvent respawnEvent = new MVRespawnEvent(newRespawnLocation, event.getPlayer(), "compatability");
this.server.getPluginManager().callEvent(respawnEvent);
event.setRespawnLocation(respawnEvent.getPlayersRespawnLocation());
});
}

private Location getMostAccurateRespawnLocation(World w) {
LoadedMultiverseWorld mvw = getWorldManager().getLoadedWorld(w.getName()).getOrNull();
if (mvw != null) {
return mvw.getSpawnLocation();
}
return w.getSpawnLocation();
private Option<Location> getMostAccurateRespawnLocation(Player player, LoadedMultiverseWorld mvWorld) {
return Option.of(mvWorld.getRespawnWorldName().isBlank()
? player.getWorld()
: server.getWorld(mvWorld.getRespawnWorldName()))
.onEmpty(() -> Logging.warning("World '%s' has respawn-world property of '%s' that does not exist!",
player.getWorld().getName(), mvWorld.getRespawnWorldName()))
.map(newRespawnWorld -> getWorldManager()
.getLoadedWorld(newRespawnWorld)
.map(newMVRespawnWorld -> (Location) newMVRespawnWorld.getSpawnLocation())
.getOrElse(newRespawnWorld::getSpawnLocation));
}

@EventHandler
Expand Down
1 change: 1 addition & 0 deletions src/test/resources/fresh_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ spawn:
first-spawn-location: ''
enable-join-destination: false
join-destination: ''
default-respawn-to-world-spawn: true

portal:
use-custom-portal-search: false
Expand Down

0 comments on commit ed5a13b

Please sign in to comment.