#421 Create SpawnLoader

- Non-static service class which handles the spawnpoints used in AuthMe
This commit is contained in:
ljacqu 2016-03-12 10:27:15 +01:00
parent 8b27444a49
commit 8293766f98
18 changed files with 464 additions and 274 deletions

View File

@ -21,7 +21,6 @@ import fr.xephi.authme.datasource.FlatFile;
import fr.xephi.authme.datasource.MySQL;
import fr.xephi.authme.datasource.SQLite;
import fr.xephi.authme.hooks.BungeeCordMessage;
import fr.xephi.authme.hooks.EssSpawn;
import fr.xephi.authme.hooks.PluginHooks;
import fr.xephi.authme.listener.AuthMeBlockListener;
import fr.xephi.authme.listener.AuthMeEntityListener;
@ -45,8 +44,7 @@ import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.crypts.SHA256;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.SettingsMigrationService;
import fr.xephi.authme.settings.Spawn;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.properties.DatabaseSettings;
import fr.xephi.authme.settings.properties.EmailSettings;
import fr.xephi.authme.settings.properties.HooksSettings;
@ -55,6 +53,7 @@ import fr.xephi.authme.settings.properties.PurgeSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.util.CollectionUtils;
import fr.xephi.authme.util.FileUtils;
import fr.xephi.authme.util.GeoLiteAPI;
import fr.xephi.authme.util.MigrationService;
import fr.xephi.authme.util.StringUtils;
@ -116,7 +115,6 @@ public class AuthMe extends JavaPlugin {
public NewAPI api;
public SendMailSSL mail;
public DataManager dataManager;
public Location essentialsSpawn;
/*
* Plugin Hooks
* TODO: Move into modules
@ -134,6 +132,7 @@ public class AuthMe extends JavaPlugin {
private DataSource database;
private IpAddressManager ipAddressManager;
private PluginHooks pluginHooks;
private SpawnLoader spawnLoader;
/**
* Get the plugin's instance.
@ -249,10 +248,13 @@ public class AuthMe extends JavaPlugin {
passwordSecurity = new PasswordSecurity(getDataSource(), newSettings, Bukkit.getPluginManager());
ipAddressManager = new IpAddressManager(newSettings);
// Initialize spawn loader
spawnLoader = new SpawnLoader(getDataFolder(), newSettings, pluginHooks);
// Set up the permissions manager and command handler
permsMan = initializePermissionsManager();
commandHandler = initializeCommandHandler(permsMan, messages, passwordSecurity, newSettings, ipAddressManager,
pluginHooks);
pluginHooks, spawnLoader);
// Set up Metrics
MetricsStarter.setupMetrics(plugin, newSettings);
@ -269,10 +271,6 @@ public class AuthMe extends JavaPlugin {
// Set up the mail API
setupMailApi();
// Hooks
// Check Essentials
checkEssentialsSpawn();
// Check if the ProtocolLib is available. If so we could listen for
// inventory protection
checkProtocolLib();
@ -293,7 +291,7 @@ public class AuthMe extends JavaPlugin {
// Set up the management
ProcessService processService = new ProcessService(newSettings, messages, this, ipAddressManager,
passwordSecurity, pluginHooks);
passwordSecurity, pluginHooks, spawnLoader);
management = new Management(this, processService, database, PlayerCache.getInstance());
// Set up the BungeeCord hook
@ -303,7 +301,7 @@ public class AuthMe extends JavaPlugin {
reloadSupportHook();
// Register event listeners
registerEventListeners();
registerEventListeners(messages, pluginHooks, spawnLoader);
// Purge on start if enabled
autoPurge();
@ -337,7 +335,7 @@ public class AuthMe extends JavaPlugin {
database.reload();
messages.reload(newSettings.getMessagesFile());
passwordSecurity.reload(newSettings);
Spawn.reload();
spawnLoader.initialize(newSettings);
}
/**
@ -369,7 +367,7 @@ public class AuthMe extends JavaPlugin {
/**
* Register all event listeners.
*/
private void registerEventListeners() {
private void registerEventListeners(Messages messages, PluginHooks pluginHooks, SpawnLoader spawnLoader) {
// Get the plugin manager instance
PluginManager pluginManager = server.getPluginManager();
@ -377,7 +375,7 @@ public class AuthMe extends JavaPlugin {
pluginManager.registerEvents(new AuthMePlayerListener(this), this);
pluginManager.registerEvents(new AuthMeBlockListener(), this);
pluginManager.registerEvents(new AuthMeEntityListener(), this);
pluginManager.registerEvents(new AuthMeServerListener(this, messages, pluginHooks), this);
pluginManager.registerEvents(new AuthMeServerListener(this, messages, pluginHooks, spawnLoader), this);
// Try to register 1.6 player listeners
try {
@ -425,12 +423,13 @@ public class AuthMe extends JavaPlugin {
private CommandHandler initializeCommandHandler(PermissionsManager permissionsManager, Messages messages,
PasswordSecurity passwordSecurity, NewSetting settings,
IpAddressManager ipAddressManager, PluginHooks pluginHooks) {
IpAddressManager ipAddressManager, PluginHooks pluginHooks,
SpawnLoader spawnLoader) {
HelpProvider helpProvider = new HelpProvider(permissionsManager, settings.getProperty(HELP_HEADER));
Set<CommandDescription> baseCommands = CommandInitializer.buildCommands();
CommandMapper mapper = new CommandMapper(baseCommands, permissionsManager);
CommandService commandService = new CommandService(this, mapper, helpProvider, messages, passwordSecurity,
permissionsManager, settings, ipAddressManager, pluginHooks);
permissionsManager, settings, ipAddressManager, pluginHooks, spawnLoader);
return new CommandHandler(commandService);
}
@ -465,7 +464,7 @@ public class AuthMe extends JavaPlugin {
private NewSetting createNewSetting() {
File configFile = new File(getDataFolder(), "config.yml");
return SettingsMigrationService.copyFileFromResource(configFile, "config.yml")
return FileUtils.copyFileFromResource(configFile, "config.yml")
? new NewSetting(configFile, getDataFolder())
: null;
}
@ -633,21 +632,6 @@ public class AuthMe extends JavaPlugin {
});
}
// Get the Essentials plugin
public void checkEssentialsSpawn() {
if (server.getPluginManager().isPluginEnabled("EssentialsSpawn")) {
try {
essentialsSpawn = new EssSpawn().getLocation();
ConsoleLogger.info("Hooked correctly with EssentialsSpawn");
} catch (Exception e) {
essentialsSpawn = null;
ConsoleLogger.showError("Can't read the /plugins/Essentials/spawn.yml file!");
}
} else {
essentialsSpawn = null;
}
}
// Check the presence of the ProtocolLib plugin
public void checkProtocolLib() {
if (!server.getPluginManager().isPluginEnabled("ProtocolLib")) {
@ -748,7 +732,7 @@ public class AuthMe extends JavaPlugin {
// Return the spawn location of a player
@Deprecated
public Location getSpawnLocation(Player player) {
return Spawn.getInstance().getSpawnLocation(player);
return spawnLoader.getSpawnLocation(player);
}
private void scheduleRecallEmailTask() {

View File

@ -159,7 +159,7 @@ public final class CommandInitializer {
.labels("getip", "ip")
.description("Get player's IP")
.detailedDescription("Get the IP address of the specified online player.")
.withArgument("player", "Player Name", false)
.withArgument("player", "Player name", false)
.permissions(OP_ONLY, AdminPermission.GET_IP)
.executableCommand(new GetIpCommand())
.build();
@ -170,7 +170,6 @@ public final class CommandInitializer {
.labels("spawn", "home")
.description("Teleport to spawn")
.detailedDescription("Teleport to the spawn.")
.withArgument("player", "Player Name", false)
.permissions(OP_ONLY, AdminPermission.SPAWN)
.executableCommand(new SpawnCommand())
.build();

View File

@ -12,6 +12,7 @@ import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.process.Management;
import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.domain.Property;
import org.bukkit.command.CommandSender;
@ -32,6 +33,7 @@ public class CommandService {
private final NewSetting settings;
private final IpAddressManager ipAddressManager;
private final PluginHooks pluginHooks;
private final SpawnLoader spawnLoader;
/**
* Constructor.
@ -47,7 +49,7 @@ public class CommandService {
*/
public CommandService(AuthMe authMe, CommandMapper commandMapper, HelpProvider helpProvider, Messages messages,
PasswordSecurity passwordSecurity, PermissionsManager permissionsManager, NewSetting settings,
IpAddressManager ipAddressManager, PluginHooks pluginHooks) {
IpAddressManager ipAddressManager, PluginHooks pluginHooks, SpawnLoader spawnLoader) {
this.authMe = authMe;
this.messages = messages;
this.helpProvider = helpProvider;
@ -57,6 +59,7 @@ public class CommandService {
this.settings = settings;
this.ipAddressManager = ipAddressManager;
this.pluginHooks = pluginHooks;
this.spawnLoader = spawnLoader;
}
/**
@ -202,4 +205,8 @@ public class CommandService {
return pluginHooks;
}
public SpawnLoader getSpawnLoader() {
return spawnLoader;
}
}

View File

@ -1,9 +1,7 @@
package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.settings.Spawn;
import org.bukkit.entity.Player;
import java.util.List;
@ -12,16 +10,10 @@ public class FirstSpawnCommand extends PlayerCommand {
@Override
public void runCommand(Player player, List<String> arguments, CommandService commandService) {
// Make sure the command executor is a player
try {
if (Spawn.getInstance().getFirstSpawn() != null) {
player.teleport(Spawn.getInstance().getFirstSpawn());
} else {
player.sendMessage("[AuthMe] First spawn has failed, please try to define the first spawn");
}
} catch (NullPointerException ex) {
// TODO ljacqu 20151119: Catching NullPointerException is never a good idea. Find what can cause one instead
ConsoleLogger.showError(ex.getMessage());
if (commandService.getSpawnLoader().getFirstSpawn() != null) {
player.teleport(commandService.getSpawnLoader().getFirstSpawn());
} else {
player.sendMessage("[AuthMe] First spawn has failed, please try to define the first spawn");
}
}
}

View File

@ -1,9 +1,7 @@
package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.settings.Spawn;
import org.bukkit.entity.Player;
import java.util.List;
@ -12,14 +10,10 @@ public class SetFirstSpawnCommand extends PlayerCommand {
@Override
public void runCommand(Player player, List<String> arguments, CommandService commandService) {
try {
if (Spawn.getInstance().setFirstSpawn(player.getLocation())) {
player.sendMessage("[AuthMe] Correctly defined new first spawn point");
} else {
player.sendMessage("[AuthMe] SetFirstSpawn has failed, please retry");
}
} catch (NullPointerException ex) {
ConsoleLogger.showError(ex.getMessage());
if (commandService.getSpawnLoader().setFirstSpawn(player.getLocation())) {
player.sendMessage("[AuthMe] Correctly defined new first spawn point");
} else {
player.sendMessage("[AuthMe] SetFirstSpawn has failed, please retry");
}
}
}

View File

@ -1,9 +1,7 @@
package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.settings.Spawn;
import org.bukkit.entity.Player;
import java.util.List;
@ -12,14 +10,10 @@ public class SetSpawnCommand extends PlayerCommand {
@Override
public void runCommand(Player player, List<String> arguments, CommandService commandService) {
try {
if (Spawn.getInstance().setSpawn(player.getLocation())) {
player.sendMessage("[AuthMe] Correctly defined new spawn point");
} else {
player.sendMessage("[AuthMe] SetSpawn has failed, please retry");
}
} catch (NullPointerException ex) {
ConsoleLogger.showError(ex.getMessage());
if (commandService.getSpawnLoader().setSpawn(player.getLocation())) {
player.sendMessage("[AuthMe] Correctly defined new spawn point");
} else {
player.sendMessage("[AuthMe] SetSpawn has failed, please retry");
}
}
}

View File

@ -1,9 +1,7 @@
package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.settings.Spawn;
import org.bukkit.entity.Player;
import java.util.List;
@ -12,14 +10,10 @@ public class SpawnCommand extends PlayerCommand {
@Override
public void runCommand(Player player, List<String> arguments, CommandService commandService) {
try {
if (Spawn.getInstance().getSpawn() != null) {
player.teleport(Spawn.getInstance().getSpawn());
} else {
player.sendMessage("[AuthMe] Spawn has failed, please try to define the spawn");
}
} catch (NullPointerException ex) {
ConsoleLogger.showError(ex.getMessage());
if (commandService.getSpawnLoader().getSpawn() != null) {
player.teleport(commandService.getSpawnLoader().getSpawn());
} else {
player.sendMessage("[AuthMe] Spawn has failed, please try to define the spawn");
}
}
}

View File

@ -6,6 +6,7 @@ import fr.xephi.authme.hooks.PluginHooks;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.util.GeoLiteAPI;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@ -21,11 +22,13 @@ public class AuthMeServerListener implements Listener {
private final AuthMe plugin;
private final Messages messages;
private final PluginHooks pluginHooks;
private final SpawnLoader spawnLoader;
public AuthMeServerListener(AuthMe plugin, Messages messages, PluginHooks pluginHooks) {
public AuthMeServerListener(AuthMe plugin, Messages messages, PluginHooks pluginHooks, SpawnLoader spawnLoader) {
this.plugin = plugin;
this.messages = messages;
this.pluginHooks = pluginHooks;
this.spawnLoader = spawnLoader;
}
@EventHandler(priority = EventPriority.HIGHEST)
@ -60,7 +63,7 @@ public class AuthMeServerListener implements Listener {
pluginHooks.unhookCombatPlus();
ConsoleLogger.info("CombatTagPlus has been disabled: unhooking");
} else if ("EssentialsSpawn".equalsIgnoreCase(pluginName)) {
plugin.essentialsSpawn = null;
spawnLoader.unloadEssentialsSpawn();
ConsoleLogger.info("EssentialsSpawn has been disabled: unhooking");
}
@ -87,7 +90,7 @@ public class AuthMeServerListener implements Listener {
} else if ("CombatTagPlus".equalsIgnoreCase(pluginName)) {
pluginHooks.tryHookToCombatPlus();
} else if ("EssentialsSpawn".equalsIgnoreCase(pluginName)) {
plugin.checkEssentialsSpawn();
spawnLoader.loadEssentialsSpawn();
}
if (pluginName.equalsIgnoreCase("ProtocolLib")) {

View File

@ -8,6 +8,7 @@ import fr.xephi.authme.output.Messages;
import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.domain.Property;
import org.bukkit.command.CommandSender;
import org.bukkit.event.Event;
@ -24,15 +25,17 @@ public class ProcessService {
private final IpAddressManager ipAddressManager;
private final PasswordSecurity passwordSecurity;
private final PluginHooks pluginHooks;
private final SpawnLoader spawnLoader;
public ProcessService(NewSetting settings, Messages messages, AuthMe authMe, IpAddressManager ipAddressManager,
PasswordSecurity passwordSecurity, PluginHooks pluginHooks) {
PasswordSecurity passwordSecurity, PluginHooks pluginHooks, SpawnLoader spawnLoader) {
this.settings = settings;
this.messages = messages;
this.authMe = authMe;
this.ipAddressManager = ipAddressManager;
this.passwordSecurity = passwordSecurity;
this.pluginHooks = pluginHooks;
this.spawnLoader = spawnLoader;
}
public <T> T getProperty(Property<T> property) {
@ -91,4 +94,8 @@ public class ProcessService {
return pluginHooks;
}
public SpawnLoader getSpawnLoader() {
return spawnLoader;
}
}

View File

@ -16,7 +16,6 @@ import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.Spawn;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.PluginSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
@ -90,7 +89,7 @@ public class AsynchronousJoin implements Process {
});
return;
}
final Location spawnLoc = Spawn.getInstance().getSpawnLocation(player);
final Location spawnLoc = service.getSpawnLoader().getSpawnLocation(player);
final boolean isAuthAvailable = database.isAuthAvailable(name);
if (isAuthAvailable) {
if (!Settings.noTeleport) {
@ -212,11 +211,14 @@ public class AsynchronousJoin implements Process {
}
private boolean needFirstSpawn() {
if (player.hasPlayedBefore())
if (player.hasPlayedBefore()) {
return false;
Location firstSpawn = Spawn.getInstance().getFirstSpawn();
if (firstSpawn == null || firstSpawn.getWorld() == null)
}
Location firstSpawn = service.getSpawnLoader().getFirstSpawn();
if (firstSpawn == null) {
return false;
}
FirstSpawnTeleportEvent tpEvent = new FirstSpawnTeleportEvent(player, player.getLocation(), firstSpawn);
plugin.getServer().getPluginManager().callEvent(tpEvent);
if (!tpEvent.isCancelled()) {

View File

@ -24,7 +24,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import static fr.xephi.authme.settings.SettingsMigrationService.copyFileFromResource;
import static fr.xephi.authme.util.FileUtils.copyFileFromResource;
/**
* The new settings manager.

View File

@ -1,7 +1,6 @@
package fr.xephi.authme.settings;
import com.google.common.annotations.VisibleForTesting;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.settings.domain.Property;
import fr.xephi.authme.settings.propertymap.PropertyMap;
@ -10,14 +9,11 @@ import org.bukkit.configuration.file.FileConfiguration;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import static fr.xephi.authme.settings.properties.RegistrationSettings.DELAY_JOIN_MESSAGE;
import static fr.xephi.authme.settings.properties.RegistrationSettings.REMOVE_JOIN_MESSAGE;
import static fr.xephi.authme.settings.properties.RegistrationSettings.REMOVE_LEAVE_MESSAGE;
import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOWED_NICKNAME_CHARACTERS;
import static java.lang.String.format;
/**
* Service for verifying that the configuration is up-to-date.
@ -131,41 +127,4 @@ public final class SettingsMigrationService {
return false;
}
// -------
// Utilities
// -------
/**
* Copy a resource file (from the JAR) to the given file if it doesn't exist.
*
* @param destinationFile The file to check and copy to (outside of JAR)
* @param resourcePath Absolute path to the resource file (path to file within JAR)
* @return False if the file does not exist and could not be copied, true otherwise
*/
public static boolean copyFileFromResource(File destinationFile, String resourcePath) {
if (destinationFile.exists()) {
return true;
} else if (!destinationFile.getParentFile().exists() && !destinationFile.getParentFile().mkdirs()) {
ConsoleLogger.showError("Cannot create parent directories for '" + destinationFile + "'");
return false;
}
// ClassLoader#getResourceAsStream does not deal with the '\' path separator: replace to '/'
final String normalizedPath = resourcePath.replace("\\", "/");
try (InputStream is = AuthMe.class.getClassLoader().getResourceAsStream(normalizedPath)) {
if (is == null) {
ConsoleLogger.showError(format("Cannot copy resource '%s' to file '%s': cannot load resource",
resourcePath, destinationFile.getPath()));
} else {
Files.copy(is, destinationFile.toPath());
return true;
}
} catch (IOException e) {
ConsoleLogger.logException(format("Cannot copy resource '%s' to file '%s':",
resourcePath, destinationFile.getPath()), e);
}
return false;
}
}

View File

@ -1,144 +0,0 @@
package fr.xephi.authme.settings;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.util.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.io.File;
/**
* @author Xephi59
* @version $Revision: 1.0 $
*/
public class Spawn extends CustomConfiguration {
private static Spawn spawn;
private static String[] spawnPriority;
private Spawn() {
super(new File(Settings.PLUGIN_FOLDER, "spawn.yml"));
load();
save();
spawnPriority = Settings.spawnPriority.split(",");
}
public static void reload() {
spawn = new Spawn();
}
/**
* Method getInstance.
*
* @return Spawn
*/
public static Spawn getInstance() {
if (spawn == null) {
spawn = new Spawn();
}
return spawn;
}
public boolean setSpawn(Location location) {
if (location == null || location.getWorld() == null) {
return false;
}
set("spawn.world", location.getWorld().getName());
set("spawn.x", location.getX());
set("spawn.y", location.getY());
set("spawn.z", location.getZ());
set("spawn.yaw", location.getYaw());
set("spawn.pitch", location.getPitch());
save();
return true;
}
public boolean setFirstSpawn(Location location) {
if (location == null || location.getWorld() == null) {
return false;
}
set("firstspawn.world", location.getWorld().getName());
set("firstspawn.x", location.getX());
set("firstspawn.y", location.getY());
set("firstspawn.z", location.getZ());
set("firstspawn.yaw", location.getYaw());
set("firstspawn.pitch", location.getPitch());
save();
return true;
}
public Location getSpawn() {
if (containsAll("spawn.world", "spawn.x", "spawn.y", "spawn.z", "spawn.yaw", "spawn.pitch")) {
String worldName = getString("spawn.world");
World world = Bukkit.getWorld(worldName);
if (!StringUtils.isEmpty(worldName) && world != null) {
return new Location(
world, getDouble("spawn.x"), getDouble("spawn.y"), getDouble("spawn.z"),
Float.parseFloat(getString("spawn.yaw")), Float.parseFloat(getString("spawn.pitch"))
);
}
}
return null;
}
public Location getFirstSpawn() {
if (containsAll("firstspawn.world", "firstspawn.x", "firstspawn.y",
"firstspawn.z", "firstspawn.yaw", "firstspawn.pitch")) {
String worldName = getString("firstspawn.world");
World world = Bukkit.getWorld(worldName);
if (!StringUtils.isEmpty(worldName) && world != null) {
return new Location(
world, getDouble("firstspawn.x"), getDouble("firstspawn.y"), getDouble("firstspawn.z"),
Float.parseFloat(getString("firstspawn.yaw")), Float.parseFloat(getString("firstspawn.pitch"))
);
}
}
return null;
}
// Return the spawn location of a player
public Location getSpawnLocation(Player player) {
AuthMe plugin = AuthMe.getInstance();
if (plugin == null || player == null || player.getWorld() == null) {
return null;
}
World world = player.getWorld();
Location spawnLoc = null;
for (String priority : spawnPriority) {
switch (priority.toLowerCase()) {
case "default":
if (world.getSpawnLocation() != null) {
spawnLoc = world.getSpawnLocation();
}
break;
case "multiverse":
if (Settings.multiverse) {
spawnLoc = plugin.getPluginHooks().getMultiverseSpawn(world);
}
break;
case "essentials":
spawnLoc = plugin.essentialsSpawn;
break;
case "authme":
String playerNameLower = player.getName().toLowerCase();
if (PlayerCache.getInstance().isAuthenticated(playerNameLower)) {
spawnLoc = getSpawn();
} else if ((getFirstSpawn() != null) && (!player.hasPlayedBefore() ||
(!plugin.getDataSource().isAuthAvailable(playerNameLower)))) {
spawnLoc = getFirstSpawn();
} else {
spawnLoc = getSpawn();
}
break;
}
if (spawnLoc != null) {
return spawnLoc;
}
}
return world.getSpawnLocation(); // return default location
}
}

View File

@ -0,0 +1,261 @@
package fr.xephi.authme.settings;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.hooks.PluginHooks;
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 java.io.File;
import java.io.IOException;
/**
* 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 {
private final File authMeConfigurationFile;
private final PluginHooks pluginHooks;
private FileConfiguration authMeConfiguration;
private String[] spawnPriority;
private Location essentialsSpawn;
/**
* Constructor.
*
* @param pluginFolder The AuthMe data folder
* @param settings The setting instance
* @param pluginHooks The plugin hooks instance
*/
public SpawnLoader(File pluginFolder, NewSetting settings, PluginHooks pluginHooks) {
File spawnFile = new File(pluginFolder, "spawn.yml");
// TODO ljacqu 20160312: Check if resource could be copied and handle the case if not
FileUtils.copyFileFromResource(spawnFile, "spawn.yml");
this.authMeConfigurationFile = new File(pluginFolder, "spawn.yml");
this.pluginHooks = pluginHooks;
initialize(settings);
}
/**
* Retrieve the relevant settings and load the AuthMe spawn.yml file.
*
* @param settings The settings instance
*/
public void initialize(NewSetting settings) {
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 = pluginHooks.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;
ConsoleLogger.info("Essentials spawn file not found: '" + essentialsSpawnFile.getAbsolutePath() + "'");
}
}
/**
* Unset the spawn point defined in EssentialsSpawn.
*/
public void unloadEssentialsSpawn() {
essentialsSpawn = 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) {
AuthMe plugin = AuthMe.getInstance();
if (plugin == null || player == null || player.getWorld() == null) {
return null;
}
World world = player.getWorld();
Location spawnLoc = null;
// TODO ljacqu 20160312: We should trim() the entries
for (String priority : spawnPriority) {
switch (priority.toLowerCase()) {
case "default":
if (world.getSpawnLocation() != null) {
spawnLoc = world.getSpawnLocation();
}
break;
case "multiverse":
if (Settings.multiverse) {
spawnLoc = pluginHooks.getMultiverseSpawn(world);
}
break;
case "essentials":
spawnLoc = essentialsSpawn;
break;
case "authme":
String playerNameLower = player.getName().toLowerCase();
if (PlayerCache.getInstance().isAuthenticated(playerNameLower)) {
spawnLoc = getSpawn();
} else if (getFirstSpawn() != null && (!player.hasPlayedBefore() ||
!plugin.getDataSource().isAuthAvailable(playerNameLower))) {
spawnLoc = getFirstSpawn();
} else {
spawnLoc = getSpawn();
}
break;
}
if (spawnLoc != null) {
return spawnLoc;
}
}
return world.getSpawnLocation(); // return default location
}
/**
* 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() {
// TODO ljacqu 20160312: Investigate whether this utility should be put in a Utils class
try {
authMeConfiguration.save(authMeConfigurationFile);
return true;
} catch (IOException e) {
ConsoleLogger.logException("Could not save spawn config (" + authMeConfigurationFile + ")", e);
}
return false;
}
/**
* 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.isEmpty(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;
}
/**
* 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;
}
}

View File

@ -0,0 +1,52 @@
package fr.xephi.authme.util;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import static java.lang.String.format;
/**
* File utilities.
*/
public class FileUtils {
private FileUtils() {
}
/**
* Copy a resource file (from the JAR) to the given file if it doesn't exist.
*
* @param destinationFile The file to check and copy to (outside of JAR)
* @param resourcePath Absolute path to the resource file (path to file within JAR)
* @return False if the file does not exist and could not be copied, true otherwise
*/
public static boolean copyFileFromResource(File destinationFile, String resourcePath) {
if (destinationFile.exists()) {
return true;
} else if (!destinationFile.getParentFile().exists() && !destinationFile.getParentFile().mkdirs()) {
ConsoleLogger.showError("Cannot create parent directories for '" + destinationFile + "'");
return false;
}
// ClassLoader#getResourceAsStream does not deal with the '\' path separator: replace to '/'
final String normalizedPath = resourcePath.replace("\\", "/");
try (InputStream is = AuthMe.class.getClassLoader().getResourceAsStream(normalizedPath)) {
if (is == null) {
ConsoleLogger.showError(format("Cannot copy resource '%s' to file '%s': cannot load resource",
resourcePath, destinationFile.getPath()));
} else {
Files.copy(is, destinationFile.toPath());
return true;
}
} catch (IOException e) {
ConsoleLogger.logException(format("Cannot copy resource '%s' to file '%s':",
resourcePath, destinationFile.getPath()), e);
}
return false;
}
}

View File

@ -11,6 +11,7 @@ import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.process.Management;
import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.domain.Property;
import fr.xephi.authme.settings.properties.SecuritySettings;
import org.bukkit.command.CommandSender;
@ -44,6 +45,7 @@ public class CommandServiceTest {
private NewSetting settings;
private IpAddressManager ipAddressManager;
private PluginHooks pluginHooks;
private SpawnLoader spawnLoader;
@Before
public void setUpService() {
@ -56,8 +58,9 @@ public class CommandServiceTest {
settings = mock(NewSetting.class);
ipAddressManager = mock(IpAddressManager.class);
pluginHooks = mock(PluginHooks.class);
spawnLoader = mock(SpawnLoader.class);
commandService = new CommandService(authMe, commandMapper, helpProvider, messages, passwordSecurity,
permissionsManager, settings, ipAddressManager, pluginHooks);
permissionsManager, settings, ipAddressManager, pluginHooks, spawnLoader);
}
@Test

View File

@ -0,0 +1,68 @@
package fr.xephi.authme.settings;
import com.google.common.io.Files;
import fr.xephi.authme.TestHelper;
import fr.xephi.authme.hooks.PluginHooks;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.configuration.file.YamlConfiguration;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Test for {@link SpawnLoader}.
*/
public class SpawnLoaderTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
private File testFolder;
private NewSetting settings;
@Before
public void setup() throws IOException {
// Copy test config into a new temporary folder
testFolder = temporaryFolder.newFolder();
File source = TestHelper.getJarFile("/spawn/spawn-firstspawn.yml");
File destination = new File(testFolder, "spawn.yml");
Files.copy(source, destination);
// Create a settings mock with default values
settings = mock(NewSetting.class);
given(settings.getProperty(RestrictionSettings.SPAWN_PRIORITY))
.willReturn("authme, essentials, multiverse, default");
}
@Test
public void shouldSetSpawn() {
// given
SpawnLoader spawnLoader = new SpawnLoader(testFolder, settings, mock(PluginHooks.class));
World world = mock(World.class);
given(world.getName()).willReturn("new_world");
Location newSpawn = new Location(world, 123, 45.0, -67.89);
// when
boolean result = spawnLoader.setSpawn(newSpawn);
// then
assertThat(result, equalTo(true));
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(new File(testFolder, "spawn.yml"));
assertThat(configuration.getDouble("spawn.x"), equalTo(123.0));
assertThat(configuration.getDouble("spawn.y"), equalTo(45.0));
assertThat(configuration.getDouble("spawn.z"), equalTo(-67.89));
assertThat(configuration.getString("spawn.world"), equalTo("new_world"));
}
}

View File

@ -0,0 +1,15 @@
# Sample spawn.yml file with both spawn and firstspawn defined
spawn:
world: 'world'
x: 300.12
y: 120.34
z: -89.12
yaw: 0.23
pitch: 112.25
firstspawn:
world: 'firstspawn'
x: -30.12
y: 204.43
z: 10.32
yaw: 0.00
pitch: 10.23