379 lines
14 KiB
Java
379 lines
14 KiB
Java
package fr.xephi.authme.settings;
|
|
|
|
import fr.xephi.authme.ConsoleLogger;
|
|
import fr.xephi.authme.initialization.DataFolder;
|
|
import fr.xephi.authme.initialization.Reloadable;
|
|
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
|
import fr.xephi.authme.service.PluginHookService;
|
|
import fr.xephi.authme.settings.properties.HooksSettings;
|
|
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
|
import fr.xephi.authme.util.FileUtils;
|
|
import fr.xephi.authme.util.StringUtils;
|
|
import org.bukkit.Bukkit;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.World;
|
|
import org.bukkit.configuration.file.FileConfiguration;
|
|
import org.bukkit.configuration.file.YamlConfiguration;
|
|
import org.bukkit.entity.Player;
|
|
|
|
import javax.inject.Inject;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.util.Locale;
|
|
|
|
/**
|
|
* Manager for spawn points. It loads spawn definitions from AuthMe and third-party plugins
|
|
* and is responsible for returning the correct spawn point as per the settings.
|
|
* <p>
|
|
* The spawn priority setting defines from which sources and in which order the spawn point
|
|
* should be taken from. In AuthMe, we can distinguish between the regular spawn and a "first spawn",
|
|
* to which players will be teleported who have joined for the first time.
|
|
*/
|
|
public class SpawnLoader implements Reloadable {
|
|
|
|
private final ConsoleLogger logger = ConsoleLoggerFactory.get(SpawnLoader.class);
|
|
|
|
private final File authMeConfigurationFile;
|
|
private final Settings settings;
|
|
private final PluginHookService pluginHookService;
|
|
private FileConfiguration authMeConfiguration;
|
|
private String[] spawnPriority;
|
|
private Location essentialsSpawn;
|
|
private Location cmiSpawn;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param pluginFolder The AuthMe data folder
|
|
* @param settings The setting instance
|
|
* @param pluginHookService The plugin hooks instance
|
|
*/
|
|
@Inject
|
|
SpawnLoader(@DataFolder File pluginFolder, Settings settings, PluginHookService pluginHookService) {
|
|
File spawnFile = new File(pluginFolder, "spawn.yml");
|
|
FileUtils.copyFileFromResource(spawnFile, "spawn.yml");
|
|
this.authMeConfigurationFile = spawnFile;
|
|
this.settings = settings;
|
|
this.pluginHookService = pluginHookService;
|
|
reload();
|
|
}
|
|
|
|
/**
|
|
* (Re)loads the spawn file and relevant settings.
|
|
*/
|
|
@Override
|
|
public void reload() {
|
|
spawnPriority = settings.getProperty(RestrictionSettings.SPAWN_PRIORITY).split(",");
|
|
authMeConfiguration = YamlConfiguration.loadConfiguration(authMeConfigurationFile);
|
|
loadEssentialsSpawn();
|
|
}
|
|
|
|
/**
|
|
* Return the AuthMe spawn location.
|
|
*
|
|
* @return The location of the regular AuthMe spawn point
|
|
*/
|
|
public Location getSpawn() {
|
|
return getLocationFromConfiguration(authMeConfiguration, "spawn");
|
|
}
|
|
|
|
/**
|
|
* Set the AuthMe spawn point.
|
|
*
|
|
* @param location The location to use
|
|
*
|
|
* @return True upon success, false otherwise
|
|
*/
|
|
public boolean setSpawn(Location location) {
|
|
return setLocation("spawn", location);
|
|
}
|
|
|
|
/**
|
|
* Return the AuthMe first spawn location.
|
|
*
|
|
* @return The location of the AuthMe spawn point for first timers
|
|
*/
|
|
public Location getFirstSpawn() {
|
|
return getLocationFromConfiguration(authMeConfiguration, "firstspawn");
|
|
}
|
|
|
|
/**
|
|
* Set the AuthMe first spawn location.
|
|
*
|
|
* @param location The location to use
|
|
*
|
|
* @return True upon success, false otherwise
|
|
*/
|
|
public boolean setFirstSpawn(Location location) {
|
|
return setLocation("firstspawn", location);
|
|
}
|
|
|
|
/**
|
|
* Load the spawn point defined in EssentialsSpawn.
|
|
*/
|
|
public void loadEssentialsSpawn() {
|
|
// EssentialsSpawn cannot run without Essentials, so it's fine to get the Essentials data folder
|
|
File essentialsFolder = pluginHookService.getEssentialsDataFolder();
|
|
if (essentialsFolder == null) {
|
|
return;
|
|
}
|
|
|
|
File essentialsSpawnFile = new File(essentialsFolder, "spawn.yml");
|
|
if (essentialsSpawnFile.exists()) {
|
|
essentialsSpawn = getLocationFromConfiguration(
|
|
YamlConfiguration.loadConfiguration(essentialsSpawnFile), "spawns.default");
|
|
} else {
|
|
essentialsSpawn = null;
|
|
logger.info("Essentials spawn file not found: '" + essentialsSpawnFile.getAbsolutePath() + "'");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Unset the spawn point defined in EssentialsSpawn.
|
|
*/
|
|
public void unloadEssentialsSpawn() {
|
|
essentialsSpawn = null;
|
|
}
|
|
|
|
/**
|
|
* Load the spawn point defined in CMI.
|
|
*/
|
|
public void loadCmiSpawn() {
|
|
File cmiFolder = pluginHookService.getCmiDataFolder();
|
|
if (cmiFolder == null) {
|
|
return;
|
|
}
|
|
|
|
File cmiConfig = new File(cmiFolder, "config.yml");
|
|
if (cmiConfig.exists()) {
|
|
cmiSpawn = getLocationFromCmiConfiguration(YamlConfiguration.loadConfiguration(cmiConfig));
|
|
} else {
|
|
cmiSpawn = null;
|
|
logger.info("CMI config file not found: '" + cmiConfig.getAbsolutePath() + "'");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Unset the spawn point defined in CMI.
|
|
*/
|
|
public void unloadCmiSpawn() {
|
|
cmiSpawn = null;
|
|
}
|
|
|
|
/**
|
|
* Return the spawn location for the given player. The source of the spawn location varies
|
|
* depending on the spawn priority setting.
|
|
*
|
|
* @param player The player to retrieve the spawn point for
|
|
*
|
|
* @return The spawn location, or the default spawn location upon failure
|
|
*
|
|
* @see RestrictionSettings#SPAWN_PRIORITY
|
|
*/
|
|
public Location getSpawnLocation(Player player) {
|
|
if (player == null || player.getWorld() == null) {
|
|
return null;
|
|
}
|
|
|
|
World world = player.getWorld();
|
|
Location spawnLoc = null;
|
|
for (String priority : spawnPriority) {
|
|
switch (priority.toLowerCase(Locale.ROOT).trim()) {
|
|
case "default":
|
|
if (world.getSpawnLocation() != null) {
|
|
if (!isValidSpawnPoint(world.getSpawnLocation())) {
|
|
for (World spawnWorld : Bukkit.getWorlds()) {
|
|
if (isValidSpawnPoint(spawnWorld.getSpawnLocation())) {
|
|
world = spawnWorld;
|
|
break;
|
|
}
|
|
}
|
|
logger.warning("Seems like AuthMe is unable to find a proper spawn location. "
|
|
+ "Set a location with the command '/authme setspawn'");
|
|
}
|
|
spawnLoc = world.getSpawnLocation();
|
|
}
|
|
break;
|
|
case "multiverse":
|
|
if (settings.getProperty(HooksSettings.MULTIVERSE)) {
|
|
spawnLoc = pluginHookService.getMultiverseSpawn(world);
|
|
}
|
|
break;
|
|
case "essentials":
|
|
spawnLoc = essentialsSpawn;
|
|
break;
|
|
case "cmi":
|
|
spawnLoc = cmiSpawn;
|
|
break;
|
|
case "authme":
|
|
spawnLoc = getSpawn();
|
|
break;
|
|
default:
|
|
// ignore
|
|
}
|
|
if (spawnLoc != null) {
|
|
logger.debug("Spawn location determined as `{0}` for world `{1}`", spawnLoc, world.getName());
|
|
return spawnLoc;
|
|
}
|
|
}
|
|
logger.debug("Fall back to default world spawn location. World: `{0}`", world.getName());
|
|
|
|
return world.getSpawnLocation(); // return default location
|
|
}
|
|
|
|
/**
|
|
* Checks if a given location is a valid spawn point [!= (0,0,0)].
|
|
*
|
|
* @param location The location to check
|
|
*
|
|
* @return True upon success, false otherwise
|
|
*/
|
|
private boolean isValidSpawnPoint(Location location) {
|
|
if (location.getX() == 0 && location.getY() == 0 && location.getZ() == 0) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Save the location under the given prefix.
|
|
*
|
|
* @param prefix The prefix to save the spawn under
|
|
* @param location The location to persist
|
|
*
|
|
* @return True upon success, false otherwise
|
|
*/
|
|
private boolean setLocation(String prefix, Location location) {
|
|
if (location != null && location.getWorld() != null) {
|
|
authMeConfiguration.set(prefix + ".world", location.getWorld().getName());
|
|
authMeConfiguration.set(prefix + ".x", location.getX());
|
|
authMeConfiguration.set(prefix + ".y", location.getY());
|
|
authMeConfiguration.set(prefix + ".z", location.getZ());
|
|
authMeConfiguration.set(prefix + ".yaw", location.getYaw());
|
|
authMeConfiguration.set(prefix + ".pitch", location.getPitch());
|
|
return saveAuthMeConfig();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private boolean saveAuthMeConfig() {
|
|
try {
|
|
authMeConfiguration.save(authMeConfigurationFile);
|
|
return true;
|
|
} catch (IOException e) {
|
|
logger.logException("Could not save spawn config (" + authMeConfigurationFile + ")", e);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Return player's location if player is alive, or player's spawn location if dead.
|
|
*
|
|
* @param player player to retrieve
|
|
*
|
|
* @return location of the given player if alive, spawn location if dead.
|
|
*/
|
|
public Location getPlayerLocationOrSpawn(Player player) {
|
|
if (player.getHealth() <= 0.0) {
|
|
return getSpawnLocation(player);
|
|
}
|
|
return player.getLocation();
|
|
}
|
|
|
|
/**
|
|
* Build a {@link Location} object from the given path in the file configuration.
|
|
*
|
|
* @param configuration The file configuration to read from
|
|
* @param pathPrefix The path to get the spawn point from
|
|
*
|
|
* @return Location corresponding to the values in the path
|
|
*/
|
|
private static Location getLocationFromConfiguration(FileConfiguration configuration, String pathPrefix) {
|
|
if (containsAllSpawnFields(configuration, pathPrefix)) {
|
|
String prefix = pathPrefix + ".";
|
|
String worldName = configuration.getString(prefix + "world");
|
|
World world = Bukkit.getWorld(worldName);
|
|
if (!StringUtils.isBlank(worldName) && world != null) {
|
|
return new Location(world, configuration.getDouble(prefix + "x"),
|
|
configuration.getDouble(prefix + "y"), configuration.getDouble(prefix + "z"),
|
|
getFloat(configuration, prefix + "yaw"), getFloat(configuration, prefix + "pitch"));
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Build a {@link Location} object based on the CMI configuration.
|
|
*
|
|
* @param configuration The CMI file configuration to read from
|
|
*
|
|
* @return Location corresponding to the values in the path
|
|
*/
|
|
private static Location getLocationFromCmiConfiguration(FileConfiguration configuration) {
|
|
final String pathPrefix = "Spawn.Main";
|
|
if (isLocationCompleteInCmiConfig(configuration, pathPrefix)) {
|
|
String prefix = pathPrefix + ".";
|
|
String worldName = configuration.getString(prefix + "World");
|
|
World world = Bukkit.getWorld(worldName);
|
|
if (!StringUtils.isBlank(worldName) && world != null) {
|
|
return new Location(world, configuration.getDouble(prefix + "X"),
|
|
configuration.getDouble(prefix + "Y"), configuration.getDouble(prefix + "Z"),
|
|
getFloat(configuration, prefix + "Yaw"), getFloat(configuration, prefix + "Pitch"));
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Return whether the file configuration contains all fields necessary to define a spawn
|
|
* under the given path.
|
|
*
|
|
* @param configuration The file configuration to use
|
|
* @param pathPrefix The path to verify
|
|
*
|
|
* @return True if all spawn fields are present, false otherwise
|
|
*/
|
|
private static boolean containsAllSpawnFields(FileConfiguration configuration, String pathPrefix) {
|
|
String[] fields = {"world", "x", "y", "z", "yaw", "pitch"};
|
|
for (String field : fields) {
|
|
if (!configuration.contains(pathPrefix + "." + field)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Return whether the CMI file configuration contains all spawn fields under the given path.
|
|
*
|
|
* @param cmiConfiguration The file configuration from CMI
|
|
* @param pathPrefix The path to verify
|
|
*
|
|
* @return True if all spawn fields are present, false otherwise
|
|
*/
|
|
private static boolean isLocationCompleteInCmiConfig(FileConfiguration cmiConfiguration, String pathPrefix) {
|
|
String[] fields = {"World", "X", "Y", "Z", "Yaw", "Pitch"};
|
|
for (String field : fields) {
|
|
if (!cmiConfiguration.contains(pathPrefix + "." + field)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Retrieve a property as a float from the given file configuration.
|
|
*
|
|
* @param configuration The file configuration to use
|
|
* @param path The path of the property to retrieve
|
|
*
|
|
* @return The float
|
|
*/
|
|
private static float getFloat(FileConfiguration configuration, String path) {
|
|
Object value = configuration.get(path);
|
|
// This behavior is consistent with FileConfiguration#getDouble
|
|
return (value instanceof Number) ? ((Number) value).floatValue() : 0;
|
|
}
|
|
|
|
}
|