Uses KnarLib methods
All checks were successful
KnarCraft/PermissionSigns/pipeline/head This commit looks good

This commit is contained in:
Kristian Knarvik 2024-01-25 15:08:56 +01:00
parent e77402c164
commit a3578fe754
17 changed files with 363 additions and 594 deletions

View File

@ -1,38 +1,33 @@
package net.knarcraft.permissionsigns; package net.knarcraft.permissionsigns;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.knarlib.formatting.Translator;
import net.knarcraft.knarlib.util.UpdateChecker;
import net.knarcraft.permissionsigns.command.PermissionSignsCommand; import net.knarcraft.permissionsigns.command.PermissionSignsCommand;
import net.knarcraft.permissionsigns.command.PermissionSignsTabCompleter; import net.knarcraft.permissionsigns.command.PermissionSignsTabCompleter;
import net.knarcraft.permissionsigns.container.PermissionSign; import net.knarcraft.permissionsigns.config.Configuration;
import net.knarcraft.permissionsigns.container.SignCreationRequest; import net.knarcraft.permissionsigns.config.Translatable;
import net.knarcraft.permissionsigns.formatting.Translator;
import net.knarcraft.permissionsigns.listener.BlockListener; import net.knarcraft.permissionsigns.listener.BlockListener;
import net.knarcraft.permissionsigns.listener.PlayerListener; import net.knarcraft.permissionsigns.listener.PlayerListener;
import net.knarcraft.permissionsigns.listener.SignListener; import net.knarcraft.permissionsigns.listener.SignListener;
import net.knarcraft.permissionsigns.manager.EconomyManager; import net.knarcraft.permissionsigns.manager.EconomyManager;
import net.knarcraft.permissionsigns.manager.PermissionManager; import net.knarcraft.permissionsigns.manager.PermissionManager;
import net.knarcraft.permissionsigns.manager.SignCreationManager;
import net.knarcraft.permissionsigns.manager.SignManager; import net.knarcraft.permissionsigns.manager.SignManager;
import net.knarcraft.permissionsigns.thread.PermissionTimeoutThread; import net.knarcraft.permissionsigns.thread.PermissionTimeoutThread;
import net.knarcraft.permissionsigns.thread.SignCreationRequestTimeoutThread;
import net.knarcraft.permissionsigns.utility.UpdateChecker;
import net.milkbowl.vault.economy.Economy; import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.permission.Permission; import net.milkbowl.vault.permission.Permission;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand; import org.bukkit.command.PluginCommand;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicesManager; import org.bukkit.plugin.ServicesManager;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitScheduler;
import org.jetbrains.annotations.NotNull;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.UUID;
import java.util.stream.Stream;
/* /*
PermissionSigns - A permission shop plugin for Spigot PermissionSigns - A permission shop plugin for Spigot
@ -59,13 +54,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
public final class PermissionSigns extends JavaPlugin { public final class PermissionSigns extends JavaPlugin {
private static final Queue<SignCreationRequest> signCreationRequests = new PriorityQueue<>();
private static String pluginVersion;
private static PermissionSigns instance; private static PermissionSigns instance;
private static boolean perWorldPermissions; private Translator translator;
private static boolean enableExtensiveSignProtection; private StringFormatter stringFormatter;
private static boolean enableIndirectSignProtection; private Configuration configuration;
private static boolean removePermissionSignIfMissing;
/** /**
* Instantiates the permission signs class * Instantiates the permission signs class
@ -85,96 +77,46 @@ public final class PermissionSigns extends JavaPlugin {
return instance; return instance;
} }
/**
* Gets the translator
*
* @return <p>The translator</p>
*/
public @NotNull Translator getTranslator() {
return translator;
}
/**
* Gets the string formatter
*
* @return <p>The string formatter</p>
*/
public @NotNull StringFormatter stringFormatter() {
return stringFormatter;
}
/**
* Gets this plugin's configuration
*
* @return <p>This plugin's configuration</p>
*/
public Configuration getConfiguration() {
return configuration;
}
/** /**
* Gets the version of this plugin * Gets the version of this plugin
* *
* @return <p>This plugin's version</p> * @return <p>This plugin's version</p>
*/ */
public static String getPluginVersion() { public String getPluginVersion() {
return pluginVersion; return this.getDescription().getVersion();
}
/**
* Adds a new sign creation request
*
* @param player <p>The player that initiated the sign creation</p>
* @param sign <p>The sign the player is about to create</p>
*/
public static void addSignCreationRequest(Player player, PermissionSign sign) {
signCreationRequests.add(new SignCreationRequest(sign, player, System.currentTimeMillis()));
}
/**
* Gets the sign creation request for the player with the given UUID
*
* @param uuid <p>The UUID to get a sign creation request for</p>
* @return <p>A sign creation request, or null if the UUID is not found</p>
*/
public static SignCreationRequest getSignCreationRequest(UUID uuid) {
Stream<SignCreationRequest> matchingRequests = signCreationRequests.stream().filter(
(item) -> item.getPlayer().getUniqueId().equals(uuid));
List<SignCreationRequest> requestList = matchingRequests.toList();
if (!requestList.isEmpty()) {
return requestList.get(0);
} else {
return null;
}
}
/**
* Cancels the sign creation request triggered by the user
*
* @param uuid <p>The UUID of the player to cancel the request for</p>
*/
public static void cancelSignCreationRequest(UUID uuid) {
Stream<SignCreationRequest> matchingRequests = signCreationRequests.stream().filter(
(item) -> item.getPlayer().getUniqueId().equals(uuid));
List<SignCreationRequest> requestList = matchingRequests.toList();
if (requestList.size() > 0) {
signCreationRequests.remove(requestList.get(0));
}
}
/**
* Checks whether permissions should always be set for the world the sign belongs to
*
* @return <p>Whether permissions should be set for the current world</p>
*/
public static boolean usePerWorldPermissions() {
return perWorldPermissions;
}
/**
* Gets whether permission signs on falling blocks should be protected
*
* @return <p>Whether permission signs on falling blocks should be protected</p>
*/
public static boolean extensiveSignProtectionEnabled() {
return enableExtensiveSignProtection;
}
/**
* Gets whether permission sign explosion and piston protection is enabled
*
* @return <p>Whether permission sign explosion and piston protection is enabled</p>
*/
public static boolean indirectProtectionEnabled() {
return enableIndirectSignProtection;
}
/**
* Gets whether to remove permissions signs if their physical signs are missing
*
* @return <p>Whether tor remove permission signs if their signs are missing</p>
*/
public static boolean removePermissionSignIfMissing() {
return removePermissionSignIfMissing;
} }
@Override @Override
public void reloadConfig() { public void reloadConfig() {
super.reloadConfig(); super.reloadConfig();
Translator.loadLanguages(loadConfig()); loadConfig();
} }
@Override @Override
@ -182,15 +124,15 @@ public final class PermissionSigns extends JavaPlugin {
//Check if vault is loaded //Check if vault is loaded
setupVault(); setupVault();
//Get plugin info
PluginDescriptionFile pluginDescriptionFile = this.getDescription();
pluginVersion = pluginDescriptionFile.getVersion();
//Load config and write the default config if necessary //Load config and write the default config if necessary
FileConfiguration config = this.getConfig(); FileConfiguration config = this.getConfig();
this.saveDefaultConfig(); this.saveDefaultConfig();
config.options().copyDefaults(true); config.options().copyDefaults(true);
Translator.loadLanguages(loadConfig());
translator = new Translator();
translator.registerMessageCategory(Translatable.ALREADY_HAS_PERMISSIONS);
stringFormatter = new StringFormatter(this.getDescription().getName(), translator);
configuration = new Configuration(this.getConfig(), translator, this.getDataFolder());
registerListeners(); registerListeners();
registerCommands(); registerCommands();
@ -200,23 +142,26 @@ public final class PermissionSigns extends JavaPlugin {
PermissionManager.loadTemporaryPermissions(); PermissionManager.loadTemporaryPermissions();
UpdateChecker.checkForUpdate(this, "https://api.spigotmc.org/legacy/update.php?resource=99426", UpdateChecker.checkForUpdate(this, "https://api.spigotmc.org/legacy/update.php?resource=99426",
() -> pluginVersion, null); () -> this.getDescription().getVersion(), null);
}
@Override
public void onDisable() {
try {
SignManager.saveSigns();
} catch (IOException e) {
e.printStackTrace();
}
SignCreationManager.stopTimeoutTimer();
} }
/** /**
* Loads the config file * Loads the config file
*
* @return <p>The currently selected language</p>
*/ */
private String loadConfig() { private void loadConfig() {
FileConfiguration config = this.getConfig(); this.reloadConfig();
String language = config.getString("language", "en"); configuration.loadConfig(this.getConfig());
perWorldPermissions = config.getBoolean("perWorldPermissions", false);
enableExtensiveSignProtection = config.getBoolean("enableExtensiveSignProtection", false);
enableIndirectSignProtection = config.getBoolean("enableIndirectSignProtection", true);
removePermissionSignIfMissing = config.getBoolean("removePermissionSignIfMissing", true);
saveConfig(); saveConfig();
return language;
} }
/** /**
@ -224,7 +169,7 @@ public final class PermissionSigns extends JavaPlugin {
*/ */
private void runThreads() { private void runThreads() {
BukkitScheduler scheduler = Bukkit.getScheduler(); BukkitScheduler scheduler = Bukkit.getScheduler();
scheduler.runTaskTimer(this, new SignCreationRequestTimeoutThread(signCreationRequests), 0L, 100L); SignCreationManager.runTimeoutTimer();
scheduler.runTaskTimer(this, new PermissionTimeoutThread(), 0L, 25L); scheduler.runTaskTimer(this, new PermissionTimeoutThread(), 0L, 25L);
} }
@ -264,13 +209,4 @@ public final class PermissionSigns extends JavaPlugin {
} }
} }
@Override
public void onDisable() {
try {
SignManager.saveSigns();
} catch (IOException e) {
e.printStackTrace();
}
}
} }

View File

@ -1,7 +1,7 @@
package net.knarcraft.permissionsigns.command; package net.knarcraft.permissionsigns.command;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.permissionsigns.PermissionSigns; import net.knarcraft.permissionsigns.PermissionSigns;
import net.knarcraft.permissionsigns.formatting.StringFormatter;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
@ -14,11 +14,13 @@ import org.jetbrains.annotations.NotNull;
public class AboutCommand implements CommandExecutor { public class AboutCommand implements CommandExecutor {
@Override @Override
public boolean onCommand(CommandSender sender, @NotNull Command command, @NotNull String label, public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
@NotNull String[] args) { @NotNull String[] args) {
sender.sendMessage(StringFormatter.formatInfoMessage("Permission Signs plugin created by " + ChatColor.GOLD + StringFormatter stringFormatter = PermissionSigns.getInstance().stringFormatter();
"EpicKnarvik97")); stringFormatter.displaySuccessMessage(sender, "Permission Signs plugin created by " + ChatColor.GOLD +
sender.sendMessage(StringFormatter.formatInfoMessage("Plugin version: " + PermissionSigns.getPluginVersion())); "EpicKnarvik97");
stringFormatter.displaySuccessMessage(sender, "Plugin version: " +
PermissionSigns.getInstance().getPluginVersion());
return true; return true;
} }

View File

@ -1,8 +1,9 @@
package net.knarcraft.permissionsigns.command; package net.knarcraft.permissionsigns.command;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.permissionsigns.PermissionSigns; import net.knarcraft.permissionsigns.PermissionSigns;
import net.knarcraft.permissionsigns.formatting.StringFormatter; import net.knarcraft.permissionsigns.config.Translatable;
import net.knarcraft.permissionsigns.formatting.TranslatableMessage; import net.knarcraft.permissionsigns.manager.SignCreationManager;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@ -17,15 +18,17 @@ public class CancelCommand implements CommandExecutor {
@Override @Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
@NotNull String[] args) { @NotNull String[] args) {
StringFormatter stringFormatter = PermissionSigns.getInstance().stringFormatter();
if (sender instanceof Player player) { if (sender instanceof Player player) {
if (sender.hasPermission("permissionsigns.admin.create")) { if (sender.hasPermission("permissionsigns.admin.create")) {
PermissionSigns.cancelSignCreationRequest(player.getUniqueId()); SignCreationManager.cancelSignCreationRequest(player.getUniqueId());
sender.sendMessage(StringFormatter.getTranslatedInfoMessage(TranslatableMessage.CREATION_REQUEST_CANCELLED)); stringFormatter.displaySuccessMessage(sender, Translatable.CREATION_REQUEST_CANCELLED);
} else { } else {
sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.COMMAND_PERMISSION_DENIED)); stringFormatter.displayErrorMessage(sender, Translatable.COMMAND_PERMISSION_DENIED);
} }
} else { } else {
sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.COMMAND_PLAYER_ONLY)); stringFormatter.displayErrorMessage(sender, Translatable.COMMAND_PLAYER_ONLY);
} }
return true; return true;
} }

View File

@ -1,9 +1,10 @@
package net.knarcraft.permissionsigns.command; package net.knarcraft.permissionsigns.command;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.permissionsigns.PermissionSigns; import net.knarcraft.permissionsigns.PermissionSigns;
import net.knarcraft.permissionsigns.config.Translatable;
import net.knarcraft.permissionsigns.container.PermissionSign; import net.knarcraft.permissionsigns.container.PermissionSign;
import net.knarcraft.permissionsigns.formatting.StringFormatter; import net.knarcraft.permissionsigns.manager.SignCreationManager;
import net.knarcraft.permissionsigns.formatting.TranslatableMessage;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
@ -25,16 +26,18 @@ public class CreateCommand implements CommandExecutor {
//Name and permission(s) required, but duration and cost optional //Name and permission(s) required, but duration and cost optional
String usage = "/ps create <name> <description> <permission,permission> [cost] [duration] - Used for creating" + String usage = "/ps create <name> <description> <permission,permission> [cost] [duration] - Used for creating" +
" a new permission sign"; " a new permission sign";
StringFormatter stringFormatter = PermissionSigns.getInstance().stringFormatter();
if (!(sender instanceof Player)) { if (!(sender instanceof Player)) {
sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.COMMAND_PLAYER_ONLY)); stringFormatter.displayErrorMessage(sender, Translatable.COMMAND_PLAYER_ONLY);
return false; return false;
} }
if (!sender.hasPermission("permissionsigns.admin.create")) { if (!sender.hasPermission("permissionsigns.admin.create")) {
sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.COMMAND_PERMISSION_DENIED)); stringFormatter.displayErrorMessage(sender, Translatable.COMMAND_PERMISSION_DENIED);
return false; return false;
} }
if (args.length < 3) { if (args.length < 3) {
sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.MISSING_CREATION_INFO)); stringFormatter.displayErrorMessage(sender, Translatable.MISSING_CREATION_INFO);
sender.sendMessage(usage); sender.sendMessage(usage);
return true; return true;
} }
@ -44,50 +47,55 @@ public class CreateCommand implements CommandExecutor {
sender.sendMessage(usage); sender.sendMessage(usage);
return true; return true;
} }
PermissionSigns.addSignCreationRequest((Player) sender, newSign); SignCreationManager.addSignCreationRequest((Player) sender, newSign);
sender.sendMessage(StringFormatter.getTranslatedInfoMessage(TranslatableMessage.CREATION_REQUEST_CREATED)); stringFormatter.displaySuccessMessage(sender, Translatable.CREATION_REQUEST_CREATED);
return true; return true;
} }
/** /**
* Parses the permission sign given in user input * Parses the permission sign given in user input
* *
* @param sender <p>The sender that initiated the command</p> * @param sender <p>The sender that initiated the command</p>
* @param args <p>The given command arguments</p> * @param arguments <p>The given command arguments</p>
* @return <p>The parsed sign, or null if it could not be parsed</p> * @return <p>The parsed sign, or null if it could not be parsed</p>
*/ */
private PermissionSign parseSign(@NotNull CommandSender sender, @NotNull String[] args) { private PermissionSign parseSign(@NotNull CommandSender sender, @NotNull String[] arguments) {
String name = args[0]; String name = arguments[0];
String description = replaceUnderscoresWithSpaces(args[1]); String description = replaceUnderscoresWithSpaces(arguments[1]);
String[] permissions = args[2].replaceAll("\\?", " ").split(","); String[] permissions = arguments[2].replaceAll("\\?", " ").split(",");
StringFormatter stringFormatter = PermissionSigns.getInstance().stringFormatter();
for (String permission : permissions) { for (String permission : permissions) {
if (permission.contains(":")) { if (!permission.contains(":")) {
String world = permission.split(":")[0]; continue;
if (!world.equalsIgnoreCase("all") && !world.equalsIgnoreCase("any") && }
Bukkit.getWorld(world) == null) {
sender.sendMessage(StringFormatter.replacePlaceholder(StringFormatter.getTranslatedErrorMessage( String world = permission.split(":")[0];
TranslatableMessage.PERMISSION_WORLD_INVALID), "{world}", world)); if (!world.equalsIgnoreCase("all") && !world.equalsIgnoreCase("any") &&
return null; Bukkit.getWorld(world) == null) {
}
stringFormatter.displayErrorMessage(sender, stringFormatter.replacePlaceholder(
Translatable.PERMISSION_WORLD_INVALID, "{world}", world));
return null;
} }
} }
double cost = 0; double cost = 0;
int duration = 0; int duration = 0;
if (args.length > 3) { if (arguments.length > 3) {
try { try {
cost = Double.parseDouble(args[3]); cost = Double.parseDouble(arguments[3]);
} catch (NumberFormatException exception) { } catch (NumberFormatException exception) {
sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.COST_INVALID_NUMBER)); stringFormatter.displayErrorMessage(sender, Translatable.COST_INVALID_NUMBER);
return null; return null;
} }
} }
if (args.length > 4) { if (arguments.length > 4) {
try { try {
duration = Integer.parseInt(args[4]); duration = Integer.parseInt(arguments[4]);
} catch (NumberFormatException exception) { } catch (NumberFormatException exception) {
sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.DURATION_INVALID_NUMBER)); stringFormatter.displayErrorMessage(sender, Translatable.DURATION_INVALID_NUMBER);
return null; return null;
} }
} }

View File

@ -1,8 +1,8 @@
package net.knarcraft.permissionsigns.command; package net.knarcraft.permissionsigns.command;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.permissionsigns.PermissionSigns; import net.knarcraft.permissionsigns.PermissionSigns;
import net.knarcraft.permissionsigns.formatting.StringFormatter; import net.knarcraft.permissionsigns.config.Translatable;
import net.knarcraft.permissionsigns.formatting.TranslatableMessage;
import net.knarcraft.permissionsigns.manager.PermissionManager; import net.knarcraft.permissionsigns.manager.PermissionManager;
import net.knarcraft.permissionsigns.manager.SignManager; import net.knarcraft.permissionsigns.manager.SignManager;
import org.bukkit.command.Command; import org.bukkit.command.Command;
@ -18,13 +18,14 @@ public class ReloadCommand implements CommandExecutor {
@Override @Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
@NotNull String[] args) { @NotNull String[] args) {
StringFormatter stringFormatter = PermissionSigns.getInstance().stringFormatter();
if (sender.hasPermission("permissionsigns.admin.reload")) { if (sender.hasPermission("permissionsigns.admin.reload")) {
SignManager.loadSigns(); SignManager.loadSigns();
PermissionManager.loadTemporaryPermissions(); PermissionManager.loadTemporaryPermissions();
PermissionSigns.getInstance().reloadConfig(); PermissionSigns.getInstance().reloadConfig();
sender.sendMessage(StringFormatter.getTranslatedInfoMessage(TranslatableMessage.RELOAD_SUCCESSFUL)); stringFormatter.displaySuccessMessage(sender, Translatable.RELOAD_SUCCESSFUL);
} else { } else {
sender.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.COMMAND_PERMISSION_DENIED)); stringFormatter.displayErrorMessage(sender, Translatable.COMMAND_PERMISSION_DENIED);
} }
return true; return true;
} }

View File

@ -0,0 +1,85 @@
package net.knarcraft.permissionsigns.config;
import net.knarcraft.knarlib.formatting.Translator;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import java.io.File;
/**
* PermissionSigns' configuration file
*/
public class Configuration {
private final Translator translator;
private final File dataFolder;
private boolean perWorldPermissions;
private boolean enableExtensiveSignProtection;
private boolean enableIndirectSignProtection;
private boolean removePermissionSignIfMissing;
/**
* Instantiates a new configuration
*
* @param fileConfiguration <p>The file configuration to load</p>
* @param translator <p>The translator to load translations for</p>
* @param dataFolder <p>This plugin's data folder</p>
*/
public Configuration(@NotNull FileConfiguration fileConfiguration, @NotNull Translator translator,
@NotNull File dataFolder) {
this.translator = translator;
this.dataFolder = dataFolder;
loadConfig(fileConfiguration);
}
/**
* Loads the current configuration
*
* @param fileConfiguration <p>The file configuration to load</p>
*/
public void loadConfig(@NotNull FileConfiguration fileConfiguration) {
String language = fileConfiguration.getString("language", "en");
perWorldPermissions = fileConfiguration.getBoolean("perWorldPermissions", false);
enableExtensiveSignProtection = fileConfiguration.getBoolean("enableExtensiveSignProtection", false);
enableIndirectSignProtection = fileConfiguration.getBoolean("enableIndirectSignProtection", true);
removePermissionSignIfMissing = fileConfiguration.getBoolean("removePermissionSignIfMissing", true);
translator.loadLanguages(dataFolder, "en", language);
}
/**
* Checks whether permissions should always be set for the world the sign belongs to
*
* @return <p>Whether permissions should be set for the current world</p>
*/
public boolean usePerWorldPermissions() {
return perWorldPermissions;
}
/**
* Gets whether permission signs on falling blocks should be protected
*
* @return <p>Whether permission signs on falling blocks should be protected</p>
*/
public boolean extensiveSignProtectionEnabled() {
return enableExtensiveSignProtection;
}
/**
* Gets whether permission sign explosion and piston protection is enabled
*
* @return <p>Whether permission sign explosion and piston protection is enabled</p>
*/
public boolean indirectProtectionEnabled() {
return enableIndirectSignProtection;
}
/**
* Gets whether to remove permissions signs if their physical signs are missing
*
* @return <p>Whether tor remove permission signs if their signs are missing</p>
*/
public boolean removePermissionSignIfMissing() {
return removePermissionSignIfMissing;
}
}

View File

@ -1,9 +1,12 @@
package net.knarcraft.permissionsigns.formatting; package net.knarcraft.permissionsigns.config;
import net.knarcraft.knarlib.formatting.TranslatableMessage;
import org.jetbrains.annotations.NotNull;
/** /**
* An enum representing all translatable messages * An enum representing all translatable messages
*/ */
public enum TranslatableMessage { public enum Translatable implements TranslatableMessage {
/** /**
* The prefix to display in messages * The prefix to display in messages
@ -173,6 +176,11 @@ public enum TranslatableMessage {
/** /**
* The format used for each permission displayed in a list when displaying permission sign info * The format used for each permission displayed in a list when displaying permission sign info
*/ */
SIGN_INFO_PERMISSION_FORMAT SIGN_INFO_PERMISSION_FORMAT;
@Override
public @NotNull TranslatableMessage[] getAllMessages() {
return Translatable.values();
}
} }

View File

@ -1,7 +1,9 @@
package net.knarcraft.permissionsigns.container; package net.knarcraft.permissionsigns.container;
import net.knarcraft.permissionsigns.formatting.TranslatableMessage; import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.permissionsigns.formatting.Translator; import net.knarcraft.knarlib.formatting.Translator;
import net.knarcraft.permissionsigns.PermissionSigns;
import net.knarcraft.permissionsigns.config.Translatable;
import net.knarcraft.permissionsigns.manager.EconomyManager; import net.knarcraft.permissionsigns.manager.EconomyManager;
import org.bukkit.Location; import org.bukkit.Location;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -13,8 +15,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static net.knarcraft.permissionsigns.formatting.StringFormatter.replacePlaceholder;
/** /**
* This class represents a placed and active permission sign * This class represents a placed and active permission sign
*/ */
@ -27,7 +27,7 @@ public class PermissionSign {
private final int duration; private final int duration;
private final double cost; private final double cost;
private static Map<Double, TranslatableMessage[]> timeUnits; private static Map<Double, Translatable[]> timeUnits;
private static List<Double> sortedUnits; private static List<Double> sortedUnits;
/** /**
@ -147,10 +147,11 @@ public class PermissionSign {
* @return <p>The lines used to draw this permission sign</p> * @return <p>The lines used to draw this permission sign</p>
*/ */
public @NotNull String[] getSignLines() { public @NotNull String[] getSignLines() {
Translator translator = PermissionSigns.getInstance().getTranslator();
String[] lines = new String[4]; String[] lines = new String[4];
lines[0] = Translator.getTranslatedMessage(TranslatableMessage.SIGN_PREFIX); lines[0] = translator.getTranslatedMessage(Translatable.SIGN_PREFIX);
lines[1] = replacePlaceholder(Translator.getTranslatedMessage( lines[1] = StringFormatter.replacePlaceholder(translator.getTranslatedMessage(
TranslatableMessage.SIGN_NAME_FORMAT), "{name}", getName()); Translatable.SIGN_NAME_FORMAT), "{name}", getName());
lines[2] = getDurationString(); lines[2] = getDurationString();
lines[3] = getCostString(); lines[3] = getCostString();
return lines; return lines;
@ -175,7 +176,7 @@ public class PermissionSign {
*/ */
public @NotNull String getDurationString() { public @NotNull String getDurationString() {
if (duration == 0) { if (duration == 0) {
return Translator.getTranslatedMessage(TranslatableMessage.SIGN_PERMANENT); return PermissionSigns.getInstance().getTranslator().getTranslatedMessage(Translatable.SIGN_PERMANENT);
} else { } else {
if (sortedUnits == null) { if (sortedUnits == null) {
initializeUnits(); initializeUnits();
@ -187,7 +188,7 @@ public class PermissionSign {
(units * 10) % 10 == 0); (units * 10) % 10 == 0);
} }
} }
return formatDurationString(duration, TranslatableMessage.UNIT_SECONDS, false); return formatDurationString(duration, Translatable.UNIT_SECONDS, false);
} }
} }
@ -198,7 +199,7 @@ public class PermissionSign {
*/ */
public @NotNull String getCostString() { public @NotNull String getCostString() {
if (cost == 0) { if (cost == 0) {
return Translator.getTranslatedMessage(TranslatableMessage.SIGN_COST_FREE); return PermissionSigns.getInstance().getTranslator().getTranslatedMessage(Translatable.SIGN_COST_FREE);
} else { } else {
return EconomyManager.format(cost); return EconomyManager.format(cost);
} }
@ -217,18 +218,19 @@ public class PermissionSign {
/** /**
* Formats a duration string * Formats a duration string
* *
* @param duration <p>The duration to display</p> * @param duration <p>The duration to display</p>
* @param translatableMessage <p>The time unit to display</p> * @param translatable <p>The time unit to display</p>
* @param castToInt <p>Whether to cast the duration to an int</p> * @param castToInt <p>Whether to cast the duration to an int</p>
* @return <p>The formatted duration string</p> * @return <p>The formatted duration string</p>
*/ */
private @NotNull String formatDurationString(double duration, @NotNull TranslatableMessage translatableMessage, private @NotNull String formatDurationString(double duration, @NotNull Translatable translatable,
boolean castToInt) { boolean castToInt) {
String durationFormat = Translator.getTranslatedMessage(TranslatableMessage.SIGN_DURATION_FORMAT); Translator translator = PermissionSigns.getInstance().getTranslator();
durationFormat = replacePlaceholder(durationFormat, "{unit}", String durationFormat = translator.getTranslatedMessage(Translatable.SIGN_DURATION_FORMAT);
Translator.getTranslatedMessage(translatableMessage)); durationFormat = StringFormatter.replacePlaceholder(durationFormat, "{unit}",
return replacePlaceholder(durationFormat, "{duration}", castToInt ? String.valueOf((int) duration) : translator.getTranslatedMessage(translatable));
String.valueOf(duration)); return StringFormatter.replacePlaceholder(durationFormat, "{duration}",
castToInt ? String.valueOf((int) duration) : String.valueOf(duration));
} }
/** /**
@ -240,10 +242,10 @@ public class PermissionSign {
double day = hour * 24; double day = hour * 24;
timeUnits = new HashMap<>(); timeUnits = new HashMap<>();
timeUnits.put(day, new TranslatableMessage[]{TranslatableMessage.UNIT_DAY, TranslatableMessage.UNIT_DAYS}); timeUnits.put(day, new Translatable[]{Translatable.UNIT_DAY, Translatable.UNIT_DAYS});
timeUnits.put(hour, new TranslatableMessage[]{TranslatableMessage.UNIT_HOUR, TranslatableMessage.UNIT_HOURS}); timeUnits.put(hour, new Translatable[]{Translatable.UNIT_HOUR, Translatable.UNIT_HOURS});
timeUnits.put(minute, new TranslatableMessage[]{TranslatableMessage.UNIT_MINUTE, TranslatableMessage.UNIT_MINUTES}); timeUnits.put(minute, new Translatable[]{Translatable.UNIT_MINUTE, Translatable.UNIT_MINUTES});
timeUnits.put(1D, new TranslatableMessage[]{TranslatableMessage.UNIT_SECOND, TranslatableMessage.UNIT_SECONDS}); timeUnits.put(1D, new Translatable[]{Translatable.UNIT_SECOND, Translatable.UNIT_SECONDS});
sortedUnits = new ArrayList<>(timeUnits.keySet()); sortedUnits = new ArrayList<>(timeUnits.keySet());
Collections.sort(sortedUnits); Collections.sort(sortedUnits);

View File

@ -1,110 +0,0 @@
package net.knarcraft.permissionsigns.formatting;
import net.md_5.bungee.api.ChatColor;
import org.jetbrains.annotations.NotNull;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A formatter for formatting displayed messages
*/
public class StringFormatter {
/**
* Replaces a placeholder in a string
*
* @param input <p>The input string to replace in</p>
* @param placeholder <p>The placeholder to replace</p>
* @param replacement <p>The replacement value</p>
* @return <p>The input string with the placeholder replaced</p>
*/
public static @NotNull String replacePlaceholder(@NotNull String input, @NotNull String placeholder,
@NotNull String replacement) {
return input.replace(placeholder, replacement);
}
/**
* Replaces placeholders in a string
*
* @param input <p>The input string to replace in</p>
* @param placeholders <p>The placeholders to replace</p>
* @param replacements <p>The replacement values</p>
* @return <p>The input string with placeholders replaced</p>
*/
public static @NotNull String replacePlaceholders(@NotNull String input, @NotNull String[] placeholders,
@NotNull String[] replacements) {
for (int i = 0; i < Math.min(placeholders.length, replacements.length); i++) {
input = replacePlaceholder(input, placeholders[i], replacements[i]);
}
return input;
}
/**
* Gets a translated and formatted info message
*
* @param translatableMessage <p>The translatable message to translate and format</p>
* @return <p>The translated and formatted message</p>
*/
public static @NotNull String getTranslatedInfoMessage(@NotNull TranslatableMessage translatableMessage) {
return formatInfoMessage(Translator.getTranslatedMessage(translatableMessage));
}
/**
* Gets a translated and formatted error message
*
* @param translatableMessage <p>The translatable message to translate and format</p>
* @return <p>The translated and formatted message</p>
*/
public static @NotNull String getTranslatedErrorMessage(@NotNull TranslatableMessage translatableMessage) {
return formatErrorMessage(Translator.getTranslatedMessage(translatableMessage));
}
/**
* Formats an information message by adding the prefix and text color
*
* @param message <p>The message to format</p>
* @return <p>The formatted message</p>
*/
public static @NotNull String formatInfoMessage(@NotNull String message) {
return ChatColor.DARK_GREEN + formatMessage(message);
}
/**
* Formats an error message by adding the prefix and text color
*
* @param message <p>The message to format</p>
* @return <p>The formatted message</p>
*/
public static @NotNull String formatErrorMessage(@NotNull String message) {
return ChatColor.DARK_RED + formatMessage(message);
}
/**
* Formats a message by adding the prefix and text color
*
* @param message <p>The message to format</p>
* @return <p>The formatted message</p>
*/
private static @NotNull String formatMessage(@NotNull String message) {
return Translator.getTranslatedMessage(TranslatableMessage.PREFIX) + " " +
ChatColor.RESET + message;
}
/**
* Translates all found color codes to formatting in a string
*
* @param message <p>The string to search for color codes</p>
* @return <p>The message with color codes translated</p>
*/
public static @NotNull String translateAllColorCodes(@NotNull String message) {
message = ChatColor.translateAlternateColorCodes('&', message);
Pattern pattern = Pattern.compile("(#[a-fA-F0-9]{6})");
Matcher matcher = pattern.matcher(message);
while (matcher.find()) {
message = message.replace(matcher.group(), "" + ChatColor.of(matcher.group()));
}
return message;
}
}

View File

@ -1,122 +0,0 @@
package net.knarcraft.permissionsigns.formatting;
import net.knarcraft.permissionsigns.PermissionSigns;
import net.knarcraft.permissionsigns.utility.FileHelper;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
/**
* A tool to get strings translated to the correct language
*/
public final class Translator {
private static Map<TranslatableMessage, String> translatedMessages;
private static Map<TranslatableMessage, String> backupTranslatedMessages;
private Translator() {
}
/**
* Loads the languages used by this translator
*/
public static void loadLanguages(@NotNull String selectedLanguage) {
backupTranslatedMessages = loadTranslatedMessages("en");
translatedMessages = loadCustomTranslatedMessages(selectedLanguage);
if (translatedMessages == null) {
translatedMessages = loadTranslatedMessages(selectedLanguage);
}
}
/**
* Gets a translated version of the given translatable message
*
* @param translatableMessage <p>The message to translate</p>
* @return <p>The translated message</p>
*/
public static @NotNull String getTranslatedMessage(@NotNull TranslatableMessage translatableMessage) {
if (translatedMessages == null) {
return "Translated strings not loaded";
}
String translatedMessage;
if (translatedMessages.containsKey(translatableMessage)) {
translatedMessage = translatedMessages.get(translatableMessage);
} else if (backupTranslatedMessages.containsKey(translatableMessage)) {
translatedMessage = backupTranslatedMessages.get(translatableMessage);
} else {
translatedMessage = translatableMessage.toString();
}
return StringFormatter.translateAllColorCodes(translatedMessage);
}
/**
* Loads all translated messages for the given language
*
* @param language <p>The language chosen by the user</p>
* @return <p>A mapping of all strings for the given language</p>
*/
public static @Nullable Map<TranslatableMessage, String> loadTranslatedMessages(@NotNull String language) {
try {
BufferedReader reader = FileHelper.getBufferedReaderForInternalFile("/strings.yml");
return loadTranslatableMessages(language, reader);
} catch (FileNotFoundException e) {
PermissionSigns.getInstance().getLogger().log(Level.SEVERE, "Unable to load translated messages");
return null;
}
}
/**
* Tries to load translated messages from a custom strings.yml file
*
* @param language <p>The selected language</p>
* @return <p>The loaded translated strings, or null if no custom language file exists</p>
*/
public static @Nullable Map<TranslatableMessage, String> loadCustomTranslatedMessages(@NotNull String language) {
File strings = new File(PermissionSigns.getInstance().getDataFolder(), "strings.yml");
if (!strings.exists()) {
PermissionSigns.getInstance().getLogger().log(Level.FINEST, "Strings file not found");
return null;
}
try {
PermissionSigns.getInstance().getLogger().log(Level.WARNING, "Loading custom strings...");
return loadTranslatableMessages(language, new BufferedReader(new InputStreamReader(
new FileInputStream(strings), StandardCharsets.UTF_8)));
} catch (FileNotFoundException e) {
PermissionSigns.getInstance().getLogger().log(Level.WARNING, "Unable to load custom messages");
return null;
}
}
/**
* Loads translatable messages from the given reader
*
* @param language <p>The selected language</p>
* @param reader <p>The buffered reader to read from</p>
* @return <p>The loaded translated strings</p>
*/
private static Map<TranslatableMessage, String> loadTranslatableMessages(String language, BufferedReader reader) {
Map<TranslatableMessage, String> translatedMessages = new HashMap<>();
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(reader);
for (TranslatableMessage message : TranslatableMessage.values()) {
String translated = configuration.getString(language + "." + message.toString());
if (translated != null) {
translatedMessages.put(message, translated);
}
}
return translatedMessages;
}
}

View File

@ -1,8 +1,8 @@
package net.knarcraft.permissionsigns.listener; package net.knarcraft.permissionsigns.listener;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.permissionsigns.PermissionSigns; import net.knarcraft.permissionsigns.PermissionSigns;
import net.knarcraft.permissionsigns.formatting.StringFormatter; import net.knarcraft.permissionsigns.config.Translatable;
import net.knarcraft.permissionsigns.formatting.TranslatableMessage;
import net.knarcraft.permissionsigns.manager.SignManager; import net.knarcraft.permissionsigns.manager.SignManager;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
@ -27,8 +27,6 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static net.knarcraft.permissionsigns.PermissionSigns.extensiveSignProtectionEnabled;
/** /**
* A listener for relevant block events such as signs being broken * A listener for relevant block events such as signs being broken
*/ */
@ -66,7 +64,7 @@ public class BlockListener implements Listener {
//Protect the permission sign itself //Protect the permission sign itself
protectBlockIfPermissionSign(event, block, player); protectBlockIfPermissionSign(event, block, player);
if (extensiveSignProtectionEnabled()) { if (PermissionSigns.getInstance().getConfiguration().extensiveSignProtectionEnabled()) {
protectSignsInDirection(event, block, player, BlockFace.UP); protectSignsInDirection(event, block, player, BlockFace.UP);
if (event.isCancelled()) { if (event.isCancelled()) {
return; return;
@ -105,7 +103,7 @@ public class BlockListener implements Listener {
*/ */
private void preventDestruction(@NotNull List<Block> blocks, @NotNull Cancellable event) { private void preventDestruction(@NotNull List<Block> blocks, @NotNull Cancellable event) {
//Don't do anything if indirect protection is disabled //Don't do anything if indirect protection is disabled
if (!PermissionSigns.indirectProtectionEnabled()) { if (!PermissionSigns.getInstance().getConfiguration().indirectProtectionEnabled()) {
return; return;
} }
for (Block block : blocks) { for (Block block : blocks) {
@ -114,7 +112,7 @@ public class BlockListener implements Listener {
return; return;
} }
if (extensiveSignProtectionEnabled()) { if (PermissionSigns.getInstance().getConfiguration().extensiveSignProtectionEnabled()) {
protectSignsInDirection(event, block, null, BlockFace.UP); protectSignsInDirection(event, block, null, BlockFace.UP);
if (event.isCancelled()) { if (event.isCancelled()) {
return; return;
@ -186,21 +184,24 @@ public class BlockListener implements Listener {
if (!registered) { if (!registered) {
return; return;
} }
if (player == null) { if (player == null) {
event.setCancelled(true); event.setCancelled(true);
return; return;
} }
StringFormatter stringFormatter = PermissionSigns.getInstance().stringFormatter();
if (!player.hasPermission("permissionsigns.admin.create")) { if (!player.hasPermission("permissionsigns.admin.create")) {
event.setCancelled(true); event.setCancelled(true);
player.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.PERMISSION_SIGN_DESTROY_DENY)); stringFormatter.displayErrorMessage(player, Translatable.PERMISSION_SIGN_DESTROY_DENY);
} else { } else {
if (!player.isSneaking() && player.getGameMode() == GameMode.CREATIVE) { if (!player.isSneaking() && player.getGameMode() == GameMode.CREATIVE) {
event.setCancelled(true); event.setCancelled(true);
player.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.PERMISSION_SIGN_DESTROY_SNEAK)); stringFormatter.displayErrorMessage(player, Translatable.PERMISSION_SIGN_DESTROY_SNEAK);
return; return;
} }
SignManager.removeSign(sign.getLocation()); SignManager.removeSign(sign.getLocation());
player.sendMessage(StringFormatter.getTranslatedInfoMessage(TranslatableMessage.PERMISSION_SIGN_REMOVED)); stringFormatter.displaySuccessMessage(player, Translatable.PERMISSION_SIGN_REMOVED);
} }
} }

View File

@ -1,13 +1,14 @@
package net.knarcraft.permissionsigns.listener; package net.knarcraft.permissionsigns.listener;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.knarlib.formatting.Translator;
import net.knarcraft.permissionsigns.PermissionSigns; import net.knarcraft.permissionsigns.PermissionSigns;
import net.knarcraft.permissionsigns.config.Translatable;
import net.knarcraft.permissionsigns.container.PermissionSign; import net.knarcraft.permissionsigns.container.PermissionSign;
import net.knarcraft.permissionsigns.container.SignCreationRequest; import net.knarcraft.permissionsigns.container.SignCreationRequest;
import net.knarcraft.permissionsigns.formatting.StringFormatter;
import net.knarcraft.permissionsigns.formatting.TranslatableMessage;
import net.knarcraft.permissionsigns.formatting.Translator;
import net.knarcraft.permissionsigns.manager.EconomyManager; import net.knarcraft.permissionsigns.manager.EconomyManager;
import net.knarcraft.permissionsigns.manager.PermissionManager; import net.knarcraft.permissionsigns.manager.PermissionManager;
import net.knarcraft.permissionsigns.manager.SignCreationManager;
import net.knarcraft.permissionsigns.manager.SignManager; import net.knarcraft.permissionsigns.manager.SignManager;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
@ -76,7 +77,8 @@ public class SignListener implements Listener {
return; return;
} }
if (!player.hasPermission("permissionsigns.use")) { if (!player.hasPermission("permissionsigns.use")) {
player.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.INTERACT_PERMISSION_MISSING)); PermissionSigns.getInstance().stringFormatter().displayErrorMessage(player,
Translatable.INTERACT_PERMISSION_MISSING);
return; return;
} }
//Prevent placement of any blocks, and sign clicking //Prevent placement of any blocks, and sign clicking
@ -90,7 +92,7 @@ public class SignListener implements Listener {
} }
//Check if the player has a creation request that can be fulfilled //Check if the player has a creation request that can be fulfilled
SignCreationRequest request = PermissionSigns.getSignCreationRequest(player.getUniqueId()); SignCreationRequest request = SignCreationManager.getSignCreationRequest(player.getUniqueId());
if (request != null) { if (request != null) {
registerPermissionSign(sign, request, player); registerPermissionSign(sign, request, player);
} }
@ -103,14 +105,15 @@ public class SignListener implements Listener {
* @return <p>The information to display</p> * @return <p>The information to display</p>
*/ */
private String getSignInfoText(@NotNull PermissionSign sign) { private String getSignInfoText(@NotNull PermissionSign sign) {
String rawSignInfo = Translator.getTranslatedMessage(TranslatableMessage.SIGN_INFO); Translator translator = PermissionSigns.getInstance().getTranslator();
String rawSignInfo = translator.getTranslatedMessage(Translatable.SIGN_INFO);
StringBuilder permissionString = new StringBuilder(); StringBuilder permissionString = new StringBuilder();
List<String> permissionNodes = sign.getPermissionNodes(); List<String> permissionNodes = sign.getPermissionNodes();
if (permissionNodes.size() == 1) { if (permissionNodes.size() == 1) {
permissionString = new StringBuilder(permissionNodes.get(0)); permissionString = new StringBuilder(permissionNodes.get(0));
} else { } else {
for (String permissionNode : permissionNodes) { for (String permissionNode : permissionNodes) {
String format = Translator.getTranslatedMessage(TranslatableMessage.SIGN_INFO_PERMISSION_FORMAT); String format = translator.getTranslatedMessage(Translatable.SIGN_INFO_PERMISSION_FORMAT);
permissionString.append(StringFormatter.replacePlaceholder(format, "{permission}", permissionNode)); permissionString.append(StringFormatter.replacePlaceholder(format, "{permission}", permissionNode));
} }
} }
@ -139,15 +142,16 @@ public class SignListener implements Listener {
hasAllPermissions = false; hasAllPermissions = false;
} }
} }
StringFormatter stringFormatter = PermissionSigns.getInstance().stringFormatter();
if (hasAllPermissions) { if (hasAllPermissions) {
player.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.ALREADY_HAS_PERMISSIONS)); stringFormatter.displayErrorMessage(player, Translatable.ALREADY_HAS_PERMISSIONS);
return; return;
} }
if (EconomyManager.canAfford(player, permissionSign.getCost())) { if (EconomyManager.canAfford(player, permissionSign.getCost())) {
performPermissionTransaction(player, permissionSign); performPermissionTransaction(player, permissionSign);
} else { } else {
player.sendMessage(StringFormatter.getTranslatedErrorMessage(TranslatableMessage.CANNOT_AFFORD)); stringFormatter.displayErrorMessage(player, Translatable.CANNOT_AFFORD);
} }
} }
@ -179,14 +183,15 @@ public class SignListener implements Listener {
} }
} }
StringFormatter stringFormatter = PermissionSigns.getInstance().stringFormatter();
String grantedPermissions = permissionsJoiner.toString(); String grantedPermissions = permissionsJoiner.toString();
if (permissionSign.getDuration() > 0) { if (permissionSign.getDuration() > 0) {
String successMessage = StringFormatter.getTranslatedInfoMessage(TranslatableMessage.PERMISSIONS_GRANTED); stringFormatter.displaySuccessMessage(player, stringFormatter.replacePlaceholders(
player.sendMessage(StringFormatter.replacePlaceholders(successMessage, new String[]{"{permissions}", "{time}"}, Translatable.PERMISSIONS_GRANTED, new String[]{"{permissions}", "{time}"},
new String[]{grantedPermissions, permissionSign.getDurationString()})); new String[]{grantedPermissions, permissionSign.getDurationString()}));
} else { } else {
player.sendMessage(StringFormatter.replacePlaceholder(StringFormatter.getTranslatedInfoMessage( stringFormatter.displaySuccessMessage(player, stringFormatter.replacePlaceholder(
TranslatableMessage.PERMISSIONS_GRANTED_PERMANENTLY), "{permissions}", grantedPermissions)); Translatable.PERMISSIONS_GRANTED_PERMANENTLY, "{permissions}", grantedPermissions));
} }
} }
@ -210,7 +215,7 @@ public class SignListener implements Listener {
PermissionSign permissionSign = request.getPermissionSign(); PermissionSign permissionSign = request.getPermissionSign();
permissionSign.setSignLocation(sign.getLocation()); permissionSign.setSignLocation(sign.getLocation());
SignManager.addSign(permissionSign); SignManager.addSign(permissionSign);
PermissionSigns.cancelSignCreationRequest(player.getUniqueId()); SignCreationManager.cancelSignCreationRequest(player.getUniqueId());
//Display the permission sign information on the sign //Display the permission sign information on the sign
String[] signLines = permissionSign.getSignLines(); String[] signLines = permissionSign.getSignLines();
@ -219,7 +224,9 @@ public class SignListener implements Listener {
} }
sign.setWaxed(true); sign.setWaxed(true);
sign.update(); sign.update();
player.sendMessage(StringFormatter.getTranslatedInfoMessage(TranslatableMessage.PERMISSION_SIGN_CREATED));
PermissionSigns.getInstance().stringFormatter().displaySuccessMessage(player,
Translatable.PERMISSION_SIGN_CREATED);
} }
} }

View File

@ -61,7 +61,7 @@ public final class PermissionManager {
if (permissionNode.contains(":")) { if (permissionNode.contains(":")) {
grantWorldPermission(player, permissionNode, false); grantWorldPermission(player, permissionNode, false);
} else { } else {
boolean perWorldPermissions = PermissionSigns.usePerWorldPermissions(); boolean perWorldPermissions = PermissionSigns.getInstance().getConfiguration().usePerWorldPermissions();
permission.playerAdd(perWorldPermissions ? player.getWorld().getName() : null, player, permissionNode); permission.playerAdd(perWorldPermissions ? player.getWorld().getName() : null, player, permissionNode);
} }
} }
@ -79,7 +79,7 @@ public final class PermissionManager {
if (permissionNode.contains(":")) { if (permissionNode.contains(":")) {
grantWorldPermission(player, permissionNode, true); grantWorldPermission(player, permissionNode, true);
} else { } else {
boolean perWorldPermissions = PermissionSigns.usePerWorldPermissions(); boolean perWorldPermissions = PermissionSigns.getInstance().getConfiguration().usePerWorldPermissions();
permission.playerAddTransient(perWorldPermissions ? worldName : null, player, permissionNode); permission.playerAddTransient(perWorldPermissions ? worldName : null, player, permissionNode);
} }
} }

View File

@ -0,0 +1,89 @@
package net.knarcraft.permissionsigns.manager;
import net.knarcraft.permissionsigns.PermissionSigns;
import net.knarcraft.permissionsigns.container.PermissionSign;
import net.knarcraft.permissionsigns.container.SignCreationRequest;
import net.knarcraft.permissionsigns.thread.SignCreationRequestTimeoutThread;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.UUID;
import java.util.stream.Stream;
/**
* A manager for keeping track of sign creation requests
*/
public final class SignCreationManager {
private static final Queue<SignCreationRequest> signCreationRequests = new PriorityQueue<>();
private static BukkitTask timeoutTask = null;
private SignCreationManager() {
}
/**
* Runs the task for timing out permission sign creation requests
*/
public static void runTimeoutTimer() {
timeoutTask = Bukkit.getScheduler().runTaskTimer(PermissionSigns.getInstance(),
new SignCreationRequestTimeoutThread(signCreationRequests), 0L, 1000L);
}
/**
* Stops the task for timing out permission sign creation requests
*/
public static void stopTimeoutTimer() {
if (timeoutTask != null) {
timeoutTask.cancel();
}
}
/**
* Adds a new sign creation request
*
* @param player <p>The player that initiated the sign creation</p>
* @param sign <p>The sign the player is about to create</p>
*/
public static void addSignCreationRequest(@NotNull Player player, @NotNull PermissionSign sign) {
signCreationRequests.add(new SignCreationRequest(sign, player, System.currentTimeMillis()));
}
/**
* Gets the sign creation request for the player with the given UUID
*
* @param uuid <p>The UUID to get a sign creation request for</p>
* @return <p>A sign creation request, or null if the UUID is not found</p>
*/
public static @Nullable SignCreationRequest getSignCreationRequest(@NotNull UUID uuid) {
Stream<SignCreationRequest> matchingRequests = signCreationRequests.stream().filter(
(item) -> item.getPlayer().getUniqueId().equals(uuid));
List<SignCreationRequest> requestList = matchingRequests.toList();
if (!requestList.isEmpty()) {
return requestList.get(0);
} else {
return null;
}
}
/**
* Cancels the sign creation request triggered by the user
*
* @param uuid <p>The UUID of the player to cancel the request for</p>
*/
public static void cancelSignCreationRequest(UUID uuid) {
Stream<SignCreationRequest> matchingRequests = signCreationRequests.stream().filter(
(item) -> item.getPlayer().getUniqueId().equals(uuid));
List<SignCreationRequest> requestList = matchingRequests.toList();
if (requestList.size() > 0) {
signCreationRequests.remove(requestList.get(0));
}
}
}

View File

@ -125,7 +125,7 @@ public final class SignManager {
Block signBlock = key.getBlock(); Block signBlock = key.getBlock();
BlockState state = signBlock.getState(); BlockState state = signBlock.getState();
if (!(state instanceof Sign sign)) { if (!(state instanceof Sign sign)) {
if (PermissionSigns.removePermissionSignIfMissing()) { if (PermissionSigns.getInstance().getConfiguration().removePermissionSignIfMissing()) {
invalidPermissionSigns.add(permissionSign.getSignLocation()); invalidPermissionSigns.add(permissionSign.getSignLocation());
} }
continue; continue;

View File

@ -1,45 +0,0 @@
package net.knarcraft.permissionsigns.utility;
import org.jetbrains.annotations.NotNull;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
/**
* A helper class for dealing with files
*/
public final class FileHelper {
private FileHelper() {
}
/**
* Gets a buffered reader for
*
* @return <p>A buffered read for reading the file</p>
* @throws FileNotFoundException <p>If unable to get an input stream for the given file</p>
*/
public static @NotNull BufferedReader getBufferedReaderForInternalFile(@NotNull String file) throws FileNotFoundException {
InputStream inputStream = FileHelper.class.getResourceAsStream(file);
if (inputStream == null) {
throw new FileNotFoundException("Unable to read the given file");
}
return new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
}
/**
* Gets a buffered reader given an input stream
*
* @param inputStream <p>The input stream to read</p>
* @return <p>A buffered reader reading the input stream</p>
*/
public static @NotNull BufferedReader getBufferedReaderFromInputStream(@NotNull InputStream inputStream) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
return new BufferedReader(inputStreamReader);
}
}

View File

@ -1,96 +0,0 @@
package net.knarcraft.permissionsigns.utility;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitScheduler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.logging.Level;
/**
* The update checker is responsible for looking for new updates
*/
public final class UpdateChecker {
private final static String updateNotice = "A new update is available: %s (You are still on %s)";
private UpdateChecker() {
}
/**
* Checks if there's a new update available, and alerts the user if necessary
*/
public static void checkForUpdate(@NotNull Plugin plugin, @NotNull String apiResourceURL,
@NotNull Supplier<String> getVersionMethod,
@Nullable Consumer<String> setVersionMethod) {
BukkitScheduler scheduler = plugin.getServer().getScheduler();
scheduler.runTaskAsynchronously(plugin, () -> UpdateChecker.queryAPI(plugin, apiResourceURL, getVersionMethod,
setVersionMethod));
}
/**
* Queries the spigot API to check for a newer version, and informs the user
*/
private static void queryAPI(@NotNull Plugin plugin, @NotNull String APIResourceURL,
@NotNull Supplier<String> getVersionMethod,
@Nullable Consumer<String> setVersionMethod) {
try {
InputStream inputStream = new URL(APIResourceURL).openStream();
BufferedReader reader = FileHelper.getBufferedReaderFromInputStream(inputStream);
//There should only be one line of output
String newVersion = reader.readLine();
reader.close();
String oldVersion = getVersionMethod.get();
//If there is a newer version, notify the user
if (isVersionHigher(oldVersion, newVersion)) {
plugin.getLogger().log(Level.INFO, getUpdateAvailableString(newVersion, oldVersion));
if (setVersionMethod != null) {
setVersionMethod.accept(newVersion);
}
}
} catch (IOException e) {
plugin.getLogger().log(Level.WARNING, "Unable to get newest version.");
}
}
/**
* Gets the string to display to a user to alert about a new update
*
* @param newVersion <p>The new available plugin version</p>
* @param oldVersion <p>The old (current) plugin version</p>
* @return <p>The string to display</p>
*/
public static @NotNull String getUpdateAvailableString(@NotNull String newVersion, @NotNull String oldVersion) {
return String.format(updateNotice, newVersion, oldVersion);
}
/**
* Decides whether one version number is higher than another
*
* @param oldVersion <p>The old version to check</p>
* @param newVersion <p>The new version to check</p>
* @return <p>True if the new version is higher than the old one</p>
*/
public static boolean isVersionHigher(@NotNull String oldVersion, @NotNull String newVersion) {
String[] oldVersionParts = oldVersion.split("\\.");
String[] newVersionParts = newVersion.split("\\.");
int versionLength = Math.max(oldVersionParts.length, newVersionParts.length);
for (int i = 0; i < versionLength; i++) {
int oldVersionNumber = oldVersionParts.length > i ? Integer.parseInt(oldVersionParts[i]) : 0;
int newVersionNumber = newVersionParts.length > i ? Integer.parseInt(newVersionParts[i]) : 0;
if (newVersionNumber != oldVersionNumber) {
return newVersionNumber > oldVersionNumber;
}
}
return false;
}
}