Skip to content

Commit

Permalink
Removed script dependency system and replaced with load priority system
Browse files Browse the repository at this point in the history
  • Loading branch information
magicmq committed Aug 14, 2024
1 parent 16da697 commit e412613
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 136 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ public boolean onCommand(CommandSender sender, String[] args) {
RunResult result = ScriptManager.get().loadScript(args[0]);
if (result == RunResult.SUCCESS)
sender.sendMessage(ChatColor.GREEN + "Successfully loaded and ran script '" + args[0] + "'.");
else if (result == RunResult.FAIL_SCRIPT_DEPENDENCY)
sender.sendMessage(ChatColor.RED + "Script '" + args[0] + "' was not run due to missing script dependencies. See console for details.");
else if (result == RunResult.FAIL_PLUGIN_DEPENDENCY)
sender.sendMessage(ChatColor.RED + "Script '" + args[0] + "' was not run due to missing plugin dependencies. See console for details.");
else if (result == RunResult.FAIL_DISABLED)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ public boolean onCommand(CommandSender sender, String[] args) {
RunResult result = ScriptManager.get().loadScript(args[0]);
if (result == RunResult.SUCCESS)
sender.sendMessage(ChatColor.GREEN + "Successfully reloaded and script '" + args[0] + "'.");
else if (result == RunResult.FAIL_SCRIPT_DEPENDENCY)
sender.sendMessage(ChatColor.RED + "Script '" + args[0] + "' was not reloaded due to missing script dependencies. See console for details.");
else if (result == RunResult.FAIL_PLUGIN_DEPENDENCY)
sender.sendMessage(ChatColor.RED + "Script '" + args[0] + "' was not reloaded due to missing plugin dependencies. See console for details.");
else if (result == RunResult.FAIL_DISABLED)
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/dev/magicmq/pyspigot/config/PluginConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ public static boolean scriptOptionEnabled() {
return config.getBoolean("script-option-defaults.enabled");
}

public static List<String> scriptOptionDepend() {
return config.getStringList("script-option-defaults.depend");
public static int scriptOptionLoadPriority() {
return config.getInt("script-option-defaults.load-priority");
}

public static List<String> scriptOptionPluginDepend() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,6 @@ public enum RunResult {
*/
FAIL_DISABLED,

/**
* Returned if the script was not loaded because it has one or more missing script dependencies.
*/
FAIL_SCRIPT_DEPENDENCY,

/**
* Returned if the script was not loaded because it has one or more missing plugin dependencies.
*/
Expand Down
19 changes: 18 additions & 1 deletion src/main/java/dev/magicmq/pyspigot/manager/script/Script.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
/**
* An object that represents a loaded script. Because this object is instantiated some time before the script is actually executed (in order to fetch its options and order scripts to load according to dependencies), there may be a brief time when this object represents a loaded <i>but not running </i> script. To check if this script object represents a running script, call {@link ScriptManager#isScriptRunning(String)}.
*/
public class Script {
public class Script implements Comparable<Script> {

private final Path path;
private final String name;
Expand Down Expand Up @@ -174,6 +174,23 @@ public long getUptime() {
return System.currentTimeMillis() - loadTime;
}

/**
* Compares this script to another script, using load order as the primary comparison. If the load order of this script is higher than other, then this script will be considered "less" than other (I.E. sorted earlier in a set than the other script). If the load order of this script is lower than other, then this script will be considered "greater" than the other script (I.E. sorted later in a set than other).
* <p>
* If the load priority of this script is equal to other, then a comparison is performed based on the name of the two scripts (alphabetical).
* @param other The other script to be compared
* @return 1 if this script is greater than other, -1 if this script is less than other, and 0 if the two scripts are equal
*/
@Override
public int compareTo(Script other) {
//Normally, would compare this to other, however we need descending order (higher numbers first), so reverse the comparison
int compare = Integer.compare(other.options.getLoadPriority(), this.options.getLoadPriority());
if (compare == 0) {
return this.name.compareTo(other.name);
} else
return compare;
}

/**
* Check if this script is the same as another script. Will check the names of both scripts to see if they match.
* @param other The other script to check against this script
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import dev.magicmq.pyspigot.manager.protocol.ProtocolManager;
import dev.magicmq.pyspigot.manager.redis.RedisManager;
import dev.magicmq.pyspigot.manager.task.TaskManager;
import dev.magicmq.pyspigot.util.ScriptSorter;
import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitTask;
import org.python.core.*;
Expand All @@ -39,7 +38,6 @@
import java.nio.file.Path;
import java.util.*;
import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
Expand All @@ -53,13 +51,13 @@ public class ScriptManager {
private static ScriptManager manager;

private final Path scriptsFolder;
private final HashMap<String, Script> scripts;
private final LinkedHashMap<String, Script> scripts;

private BukkitTask startScriptTask;

private ScriptManager() {
scriptsFolder = PySpigot.get().getDataFolderPath().resolve("scripts");
this.scripts = new HashMap<>();
this.scripts = new LinkedHashMap<>();

if (PluginConfig.getScriptLoadDelay() > 0L)
startScriptTask = Bukkit.getScheduler().runTaskLater(PySpigot.get(), this::loadScripts, PluginConfig.getScriptLoadDelay());
Expand All @@ -80,7 +78,7 @@ public void shutdown() {
}

/**
* Loads and runs all scripts contained within the scripts folder. Called on plugin load (I.E. during server start).
* Loads and runs all scripts contained within the scripts folder. Called on plugin load (I.E. during server start). Loads in the appropriate load order (see {@link Script#compareTo(Script)}).
*/
public void loadScripts() {
PySpigot.get().getLogger().log(Level.INFO, "Loading scripts...");
Expand All @@ -95,7 +93,7 @@ public void loadScripts() {
}

//Init scripts and parse options
List<Script> toLoad = new ArrayList<>();
SortedSet<Script> toLoad = new TreeSet<>();
for (Map.Entry<String, Path> entry : scriptFiles.entrySet()) {
ScriptOptions options;
if (PySpigot.get().getScriptOptionsConfig().contains(entry.getKey()))
Expand All @@ -106,27 +104,8 @@ public void loadScripts() {
toLoad.add(script);
}

//Check that all dependencies are available
List<String> scriptNames = toLoad.stream().map(Script::getName).collect(Collectors.toList());
for (Iterator<Script> scriptIterator = toLoad.iterator(); scriptIterator.hasNext();) {
Script script = scriptIterator.next();
List<String> dependencies = script.getOptions().getScriptDependencies();
for (String dependency : dependencies) {
if (!scriptNames.contains(dependency)) {
PySpigot.get().getLogger().log(Level.WARNING, "Script '" + script.getName() + "' has an unknown script dependency '" + dependency + "'. This script will not be loaded.");
scriptIterator.remove();
scriptNames.remove(script.getName());
break;
}
}
}

//Sort scripts with respect to dependencies
ScriptSorter sorter = new ScriptSorter(toLoad);
LinkedList<Script> sorted = sorter.getOptimalLoadOrder();

//Run scripts in the proper load order
for (Script script : sorted) {
//Run scripts in order with respect to load priority
for (Script script : toLoad) {
try {
loadScript(script);
} catch (IOException e) {
Expand Down Expand Up @@ -225,18 +204,6 @@ public RunResult loadScript(Script script) throws IOException {
return RunResult.FAIL_PLUGIN_DEPENDENCY;
}

//Check if the script's other script dependencies are all running
List<String> unresolvedScriptDependencies = new ArrayList<>();
for (String dependency : script.getOptions().getScriptDependencies()) {
if (getScript(dependency) == null) {
unresolvedScriptDependencies.add(dependency);
}
}
if (!unresolvedScriptDependencies.isEmpty()) {
PySpigot.get().getLogger().log(Level.WARNING, "The following script dependencies for script '" + script.getName() + "' are missing: " + unresolvedScriptDependencies + ". This script will not be loaded.");
return RunResult.FAIL_SCRIPT_DEPENDENCY;
}

if (PluginConfig.doScriptActionLogging())
PySpigot.get().getLogger().log(Level.INFO, "Loading script '" + script.getName() + "'");

Expand Down Expand Up @@ -277,10 +244,12 @@ public RunResult loadScript(Script script) throws IOException {
}

/**
* Unload all currently loaded scripts.
* Unload all currently loaded scripts. Unloads in the reverse order that they were loaded (I.E. the opposite of the load order).
*/
public void unloadScripts() {
for (Script script : scripts.values()) {
List<Script> toUnload = new ArrayList<>(scripts.values());
Collections.reverse(toUnload);
for (Script script : toUnload) {
ScriptUnloadEvent event = new ScriptUnloadEvent(script, false);
Bukkit.getPluginManager().callEvent(event);
stopScript(script, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
public class ScriptOptions {

private final boolean enabled;
private final List<String> scriptDepend;
private final int loadPriority;
private final List<String> pluginDepend;
private final boolean fileLoggingEnabled;
private final Level minLoggingLevel;
Expand All @@ -54,10 +54,7 @@ public ScriptOptions() {
public ScriptOptions(ConfigurationSection config) {
if (config != null) {
this.enabled = config.getBoolean("enabled", PluginConfig.scriptOptionEnabled());
if (config.contains("depend"))
this.scriptDepend = config.getStringList("depend");
else
this.scriptDepend = PluginConfig.scriptOptionDepend();
this.loadPriority = config.getInt("load-priority", PluginConfig.scriptOptionLoadPriority());
if (config.contains("plugin-depend"))
this.pluginDepend = config.getStringList("plugin-depend");
else
Expand All @@ -71,7 +68,7 @@ public ScriptOptions(ConfigurationSection config) {
this.permissions = Permission.loadPermissions(PluginConfig.scriptOptionPermissions(), "Permission node '%s' in script_options.yml for '" + config.getName() + "' is invalid", permissionDefault);
} else {
this.enabled = PluginConfig.scriptOptionEnabled();
this.scriptDepend = PluginConfig.scriptOptionDepend();
this.loadPriority = PluginConfig.scriptOptionLoadPriority();
this.pluginDepend = PluginConfig.scriptOptionPluginDepend();
this.fileLoggingEnabled = PluginConfig.scriptOptionFileLoggingEnabled();
this.minLoggingLevel = Level.parse(PluginConfig.scriptOptionMinLoggingLevel());
Expand All @@ -89,11 +86,11 @@ public boolean isEnabled() {
}

/**
* Get a list of script dependencies for this script.
* @return A list of script dependencies for this script. Will return an empty list if this script has no script dependencies
* Get the load priority for this script. Scripts with greater load priority will load before scripts with lower load priority.
* @return The script's load priority
*/
public List<String> getScriptDependencies() {
return scriptDepend;
public int getLoadPriority() {
return loadPriority;
}

/**
Expand Down Expand Up @@ -142,6 +139,6 @@ public List<Permission> getPermissions() {
*/
@Override
public String toString() {
return String.format("ScriptOptions[Enabled: %b, Depend: %s, File Logging Enabled: %b, Minimum Logging Level: %s, Permission Default: %s, Permissions: %s", enabled, scriptDepend, fileLoggingEnabled, minLoggingLevel, permissionDefault, permissions);
return String.format("ScriptOptions[Enabled: %b, Load Priority: %d, Plugin Dependencies: %s, File Logging Enabled: %b, Minimum Logging Level: %s, Permission Default: %s, Permissions: %s", enabled, loadPriority, pluginDepend, fileLoggingEnabled, minLoggingLevel, permissionDefault, permissions);
}
}
71 changes: 0 additions & 71 deletions src/main/java/dev/magicmq/pyspigot/util/ScriptSorter.java

This file was deleted.

2 changes: 1 addition & 1 deletion src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ script-option-defaults:
# Whether the script is enabled
enabled: true
# A list of other scripts the script depends on
depend: []
load-priority: 1
# A list of plugins the script depends on
plugin-depend: []
# Whether script log messages should be logged to its respective log file
Expand Down

0 comments on commit e412613

Please sign in to comment.