#1015 Implement lazy replace of tags for welcome message
- Check which tags are used when loading the welcome message and only apply their replacements afterwards - Moves AuthMe#replaceAllInfo to a more appropriate place - Avoid fetching data again for each line
This commit is contained in:
@@ -27,7 +27,6 @@ import fr.xephi.authme.permission.PermissionsSystemType;
|
||||
import fr.xephi.authme.security.crypts.SHA256;
|
||||
import fr.xephi.authme.service.BackupService;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.GeoIpService;
|
||||
import fr.xephi.authme.service.MigrationService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
@@ -35,11 +34,9 @@ import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
import fr.xephi.authme.task.CleanupTask;
|
||||
import fr.xephi.authme.task.purge.PurgeService;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
@@ -72,8 +69,6 @@ public class AuthMe extends JavaPlugin {
|
||||
private DataSource database;
|
||||
private BukkitService bukkitService;
|
||||
private Injector injector;
|
||||
private GeoIpService geoIpService;
|
||||
private PlayerCache playerCache;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -242,14 +237,13 @@ public class AuthMe extends JavaPlugin {
|
||||
*/
|
||||
protected void instantiateServices(Injector injector) {
|
||||
// PlayerCache is still injected statically sometimes
|
||||
playerCache = PlayerCache.getInstance();
|
||||
PlayerCache playerCache = PlayerCache.getInstance();
|
||||
injector.register(PlayerCache.class, playerCache);
|
||||
|
||||
database = injector.getSingleton(DataSource.class);
|
||||
permsMan = injector.getSingleton(PermissionsManager.class);
|
||||
bukkitService = injector.getSingleton(BukkitService.class);
|
||||
commandHandler = injector.getSingleton(CommandHandler.class);
|
||||
geoIpService = injector.getSingleton(GeoIpService.class);
|
||||
|
||||
// Trigger construction of API classes; they will keep track of the singleton
|
||||
injector.getSingleton(NewAPI.class);
|
||||
@@ -344,24 +338,6 @@ public class AuthMe extends JavaPlugin {
|
||||
ConsoleLogger.close();
|
||||
}
|
||||
|
||||
public String replaceAllInfo(String message, Player player) {
|
||||
String playersOnline = Integer.toString(bukkitService.getOnlinePlayers().size());
|
||||
String ipAddress = PlayerUtils.getPlayerIp(player);
|
||||
Server server = getServer();
|
||||
return message
|
||||
.replace("&", "\u00a7")
|
||||
.replace("{PLAYER}", player.getName())
|
||||
.replace("{ONLINE}", playersOnline)
|
||||
.replace("{MAXPLAYERS}", Integer.toString(server.getMaxPlayers()))
|
||||
.replace("{IP}", ipAddress)
|
||||
.replace("{LOGINS}", Integer.toString(playerCache.getLogged()))
|
||||
.replace("{WORLD}", player.getWorld().getName())
|
||||
.replace("{SERVER}", server.getServerName())
|
||||
.replace("{VERSION}", server.getBukkitVersion())
|
||||
// TODO: We should cache info like this, maybe with a class that extends Player?
|
||||
.replace("{COUNTRY}", geoIpService.getCountryName(ipAddress));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Bukkit commands.
|
||||
*
|
||||
|
||||
@@ -13,15 +13,16 @@ import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.BungeeService;
|
||||
import fr.xephi.authme.service.TeleportationService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.WelcomeMessageConfiguration;
|
||||
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
import static fr.xephi.authme.settings.properties.RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN;
|
||||
|
||||
@@ -54,6 +55,9 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
||||
@Inject
|
||||
private Settings settings;
|
||||
|
||||
@Inject
|
||||
private WelcomeMessageConfiguration welcomeMessageConfiguration;
|
||||
|
||||
ProcessSyncPlayerLogin() {
|
||||
}
|
||||
|
||||
@@ -103,15 +107,12 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
||||
player.saveData();
|
||||
|
||||
// Login is done, display welcome message
|
||||
List<String> welcomeMessage = welcomeMessageConfiguration.getWelcomeMessage(player);
|
||||
if (settings.getProperty(RegistrationSettings.USE_WELCOME_MESSAGE)) {
|
||||
if (settings.getProperty(RegistrationSettings.BROADCAST_WELCOME_MESSAGE)) {
|
||||
for (String s : settings.getWelcomeMessage()) {
|
||||
Bukkit.getServer().broadcastMessage(plugin.replaceAllInfo(s, player));
|
||||
}
|
||||
welcomeMessage.forEach(bukkitService::broadcastMessage);
|
||||
} else {
|
||||
for (String s : settings.getWelcomeMessage()) {
|
||||
player.sendMessage(plugin.replaceAllInfo(s, player));
|
||||
}
|
||||
welcomeMessage.forEach(player::sendMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ import static fr.xephi.authme.util.FileUtils.copyFileFromResource;
|
||||
public class Settings extends SettingsManager {
|
||||
|
||||
private final File pluginFolder;
|
||||
private String[] welcomeMessage;
|
||||
private String passwordEmailMessage;
|
||||
private String recoveryCodeEmailMessage;
|
||||
|
||||
@@ -56,19 +55,9 @@ public class Settings extends SettingsManager {
|
||||
return recoveryCodeEmailMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the lines to output after an in-game registration.
|
||||
*
|
||||
* @return The welcome message
|
||||
*/
|
||||
public String[] getWelcomeMessage() {
|
||||
return welcomeMessage;
|
||||
}
|
||||
|
||||
private void loadSettingsFromFiles() {
|
||||
passwordEmailMessage = readFile("email.html");
|
||||
recoveryCodeEmailMessage = readFile("recovery_code_email.html");
|
||||
welcomeMessage = readFile("welcome.txt").split("\\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
package fr.xephi.authme.settings;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.initialization.DataFolder;
|
||||
import fr.xephi.authme.initialization.Reloadable;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.GeoIpService;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
import fr.xephi.authme.util.lazytags.Tag;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static fr.xephi.authme.util.FileUtils.copyFileFromResource;
|
||||
|
||||
/**
|
||||
* Configuration for the welcome message (welcome.txt).
|
||||
*/
|
||||
public class WelcomeMessageConfiguration implements Reloadable {
|
||||
|
||||
@DataFolder
|
||||
@Inject
|
||||
private File pluginFolder;
|
||||
|
||||
@Inject
|
||||
private Server server;
|
||||
|
||||
@Inject
|
||||
private GeoIpService geoIpService;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
/** List of all supported tags for the welcome message. */
|
||||
private final List<Tag> availableTags = Arrays.asList(
|
||||
new Tag("&", () -> "\u00a7"),
|
||||
new Tag("{PLAYER}", pl -> pl.getName()),
|
||||
new Tag("{ONLINE}", () -> Integer.toString(bukkitService.getOnlinePlayers().size())),
|
||||
new Tag("{MAXPLAYERS}", () -> Integer.toString(server.getMaxPlayers())),
|
||||
new Tag("{IP}", pl -> PlayerUtils.getPlayerIp(pl)),
|
||||
new Tag("{LOGINS}", () -> Integer.toString(playerCache.getLogged())),
|
||||
new Tag("{WORLD}", pl -> pl.getWorld().getName()),
|
||||
new Tag("{SERVER}", () -> server.getServerName()),
|
||||
new Tag("{VERSION}", () -> server.getBukkitVersion()),
|
||||
new Tag("{COUNTRY}", pl -> geoIpService.getCountryName(PlayerUtils.getPlayerIp(pl))));
|
||||
|
||||
/** Welcome message, by lines. */
|
||||
private List<String> welcomeMessage;
|
||||
/** Tags used in the welcome message. */
|
||||
private List<Tag> usedTags;
|
||||
|
||||
@PostConstruct
|
||||
@Override
|
||||
public void reload() {
|
||||
welcomeMessage = readWelcomeFile();
|
||||
usedTags = determineUsedTags(welcomeMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the welcome message for the given player.
|
||||
*
|
||||
* @param player the player for whom the welcome message should be prepared
|
||||
* @return the welcome message
|
||||
*/
|
||||
public List<String> getWelcomeMessage(Player player) {
|
||||
// Note ljacqu 20170121: Using a Map might seem more natural here but we avoid doing so for performance
|
||||
// Although the performance gain here is probably minimal...
|
||||
List<TagValue> tagValues = new LinkedList<>();
|
||||
for (Tag tag : usedTags) {
|
||||
tagValues.add(new TagValue(tag.getName(), tag.getValue(player)));
|
||||
}
|
||||
|
||||
List<String> adaptedMessages = new LinkedList<>();
|
||||
for (String line : welcomeMessage) {
|
||||
String adaptedLine = line;
|
||||
for (TagValue tagValue : tagValues) {
|
||||
adaptedLine = adaptedLine.replace(tagValue.tag, tagValue.value);
|
||||
}
|
||||
adaptedMessages.add(adaptedLine);
|
||||
}
|
||||
return adaptedMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the lines of the welcome message file
|
||||
*/
|
||||
private List<String> readWelcomeFile() {
|
||||
File welcomeFile = new File(pluginFolder, "welcome.txt");
|
||||
if (copyFileFromResource(welcomeFile, "welcome.txt")) {
|
||||
try {
|
||||
return Files.readAllLines(welcomeFile.toPath(), StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
ConsoleLogger.logException("Failed to read welcome.txt file:", e);
|
||||
}
|
||||
} else {
|
||||
ConsoleLogger.warning("Failed to copy welcome.txt from JAR");
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines which tags are used in the message.
|
||||
*
|
||||
* @param welcomeMessage the lines of the welcome message
|
||||
* @return the tags
|
||||
*/
|
||||
private List<Tag> determineUsedTags(List<String> welcomeMessage) {
|
||||
return availableTags.stream()
|
||||
.filter(tag -> welcomeMessage.stream().anyMatch(msg -> msg.contains(tag.getName())))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static final class TagValue {
|
||||
|
||||
private final String tag;
|
||||
private final String value;
|
||||
|
||||
TagValue(String tag, String value) {
|
||||
this.tag = tag;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TagValue[tag='" + tag + "', value='" + value + "']";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package fr.xephi.authme.util.lazytags;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Represents a tag in a text that can be replaced with data (which may depend on the Player).
|
||||
*/
|
||||
public class Tag {
|
||||
|
||||
private final String name;
|
||||
private final Function<Player, String> replacementFunction;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param name the tag (placeholder) that will be replaced
|
||||
* @param replacementFunction the function producing the replacement
|
||||
*/
|
||||
public Tag(String name, Function<Player, String> replacementFunction) {
|
||||
this.name = name;
|
||||
this.replacementFunction = replacementFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param name the tag (placeholder) that will be replaced
|
||||
* @param replacementFunction supplier providing the text to replace the tag with
|
||||
*/
|
||||
public Tag(String name, Supplier<String> replacementFunction) {
|
||||
this(name, p -> replacementFunction.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the tag
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value to replace the tag with for the given player.
|
||||
*
|
||||
* @param player the player to evaluate the replacement for
|
||||
* @return the replacement
|
||||
*/
|
||||
public String getValue(Player player) {
|
||||
return replacementFunction.apply(player);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user