mirror of
https://github.com/plexusorg/Plex.git
synced 2026-06-04 05:26:55 +00:00
Allow installing/uninstalling modules in-game
This commit is contained in:
@@ -36,6 +36,7 @@ public abstract class PlexModule
|
|||||||
private ModuleConfiguration messages;
|
private ModuleConfiguration messages;
|
||||||
private PlexModuleFile plexModuleFile;
|
private PlexModuleFile plexModuleFile;
|
||||||
private File dataFolder;
|
private File dataFolder;
|
||||||
|
private File moduleJar;
|
||||||
private Logger logger;
|
private Logger logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -228,6 +229,16 @@ public abstract class PlexModule
|
|||||||
return dataFolder;
|
return dataFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the JAR file this module was loaded from.
|
||||||
|
*
|
||||||
|
* @return the JAR file this module was loaded from
|
||||||
|
*/
|
||||||
|
public File getModuleJar()
|
||||||
|
{
|
||||||
|
return moduleJar;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the module logger.
|
* Returns the module logger.
|
||||||
*
|
*
|
||||||
@@ -362,6 +373,16 @@ public abstract class PlexModule
|
|||||||
this.dataFolder = dataFolder;
|
this.dataFolder = dataFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the JAR file this module was loaded from.
|
||||||
|
*
|
||||||
|
* @param moduleJar JAR file this module was loaded from
|
||||||
|
*/
|
||||||
|
public void setModuleJar(File moduleJar)
|
||||||
|
{
|
||||||
|
this.moduleJar = moduleJar;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the module logger.
|
* Sets the module logger.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import dev.plex.command.PlexCommand;
|
|||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import dev.plex.command.ServerCommand;
|
import dev.plex.command.ServerCommand;
|
||||||
import dev.plex.command.ServerCommandContext;
|
import dev.plex.command.ServerCommandContext;
|
||||||
|
import dev.plex.command.exception.CommandFailException;
|
||||||
import dev.plex.menu.impl.MaterialMenu;
|
import dev.plex.menu.impl.MaterialMenu;
|
||||||
import dev.plex.util.GameRuleUtil;
|
import dev.plex.util.GameRuleUtil;
|
||||||
import dev.plex.util.PlexLog;
|
import dev.plex.util.PlexLog;
|
||||||
@@ -26,7 +27,7 @@ public class DebugCMD extends ServerCommand
|
|||||||
{
|
{
|
||||||
super(command("pdebug")
|
super(command("pdebug")
|
||||||
.description("Plex's debug command")
|
.description("Plex's debug command")
|
||||||
.usage("/<command> <aliases <command> | redis-reset <player> | gamerules>")
|
.usage("/<command> <aliases <command> | redis | redis-reset <player> | gamerules>")
|
||||||
.permission("plex.debug")
|
.permission("plex.debug")
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
@@ -34,6 +35,8 @@ public class DebugCMD extends ServerCommand
|
|||||||
protected void buildCommand(LiteralArgumentBuilder<CommandSourceStack> command)
|
protected void buildCommand(LiteralArgumentBuilder<CommandSourceStack> command)
|
||||||
{
|
{
|
||||||
command.executes(context -> executeCommand(context));
|
command.executes(context -> executeCommand(context));
|
||||||
|
command.then(literal("redis")
|
||||||
|
.executes(context -> executeCommand(context, "redis")));
|
||||||
command.then(literal("redis-reset")
|
command.then(literal("redis-reset")
|
||||||
.then(playerArgument("player")
|
.then(playerArgument("player")
|
||||||
.executes(context -> executeCommand(context, "redis-reset", string(context, "player")))));
|
.executes(context -> executeCommand(context, "redis-reset", string(context, "player")))));
|
||||||
@@ -56,6 +59,18 @@ public class DebugCMD extends ServerCommand
|
|||||||
{
|
{
|
||||||
return context.usage();
|
return context.usage();
|
||||||
}
|
}
|
||||||
|
if (args[0].equalsIgnoreCase("redis"))
|
||||||
|
{
|
||||||
|
if (!plugin.getRedisConnection().isEnabled())
|
||||||
|
{
|
||||||
|
throw new CommandFailException("&cRedis is not enabled.");
|
||||||
|
}
|
||||||
|
plugin.getRedisConnection().execute(jedis -> jedis.set("test", "123"));
|
||||||
|
context.send(sender, "Set test to 123. Now outputting key test...");
|
||||||
|
String test = plugin.getRedisConnection().query(jedis -> jedis.get("test"));
|
||||||
|
context.send(sender, test);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (args[0].equalsIgnoreCase("redis-reset"))
|
if (args[0].equalsIgnoreCase("redis-reset"))
|
||||||
{
|
{
|
||||||
if (args.length == 2)
|
if (args.length == 2)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package dev.plex.command.impl;
|
|||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import dev.plex.command.ServerCommand;
|
import dev.plex.command.ServerCommand;
|
||||||
import dev.plex.command.ServerCommandContext;
|
import dev.plex.command.ServerCommandContext;
|
||||||
import dev.plex.command.exception.CommandFailException;
|
import dev.plex.module.ModuleManager;
|
||||||
import dev.plex.module.PlexModule;
|
import dev.plex.module.PlexModule;
|
||||||
import dev.plex.module.PlexModuleFile;
|
import dev.plex.module.PlexModuleFile;
|
||||||
import dev.plex.util.BuildInfo;
|
import dev.plex.util.BuildInfo;
|
||||||
@@ -17,10 +17,7 @@ import java.util.stream.Collectors;
|
|||||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.OfflinePlayer;
|
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class PlexCMD extends ServerCommand
|
public class PlexCMD extends ServerCommand
|
||||||
@@ -29,7 +26,7 @@ public class PlexCMD extends ServerCommand
|
|||||||
{
|
{
|
||||||
super(command("plex")
|
super(command("plex")
|
||||||
.description("Show information about Plex or reload it")
|
.description("Show information about Plex or reload it")
|
||||||
.usage("/<command> [reload | redis | update | modules [reload | update]]")
|
.usage("/<command> [reload | update | modules [reload | update | install <name> | uninstall <name> [-rmdir]]]")
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
// Don't modify this command
|
// Don't modify this command
|
||||||
@@ -39,8 +36,6 @@ public class PlexCMD extends ServerCommand
|
|||||||
command.executes(context -> executeCommand(context));
|
command.executes(context -> executeCommand(context));
|
||||||
command.then(literal("reload")
|
command.then(literal("reload")
|
||||||
.executes(context -> executeCommand(context, "reload")));
|
.executes(context -> executeCommand(context, "reload")));
|
||||||
command.then(literal("redis")
|
|
||||||
.executes(context -> executeCommand(context, "redis")));
|
|
||||||
command.then(literal("update")
|
command.then(literal("update")
|
||||||
.executes(context -> executeCommand(context, "update")));
|
.executes(context -> executeCommand(context, "update")));
|
||||||
command.then(literal("modules")
|
command.then(literal("modules")
|
||||||
@@ -48,14 +43,24 @@ public class PlexCMD extends ServerCommand
|
|||||||
.then(literal("reload")
|
.then(literal("reload")
|
||||||
.executes(context -> executeCommand(context, "modules", "reload")))
|
.executes(context -> executeCommand(context, "modules", "reload")))
|
||||||
.then(literal("update")
|
.then(literal("update")
|
||||||
.executes(context -> executeCommand(context, "modules", "update"))));
|
.executes(context -> executeCommand(context, "modules", "update")))
|
||||||
|
.then(literal("install")
|
||||||
|
.then(word("name")
|
||||||
|
.executes(context -> executeCommand(context, "modules", "install", string(context, "name")))))
|
||||||
|
.then(literal("uninstall")
|
||||||
|
.then(word("name")
|
||||||
|
.suggests(suggest(() -> plugin.getModuleManager().getModules().stream()
|
||||||
|
.map(module -> module.getPlexModuleFile().getName())
|
||||||
|
.collect(Collectors.toList())))
|
||||||
|
.executes(context -> executeCommand(context, "modules", "uninstall", string(context, "name")))
|
||||||
|
.then(literal("-rmdir")
|
||||||
|
.executes(context -> executeCommand(context, "modules", "uninstall", string(context, "name"), "-rmdir"))))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Component execute(@NotNull ServerCommandContext context)
|
protected Component execute(@NotNull ServerCommandContext context)
|
||||||
{
|
{
|
||||||
CommandSender sender = context.sender();
|
CommandSender sender = context.sender();
|
||||||
Player playerSender = context.player();
|
|
||||||
String[] args = context.args();
|
String[] args = context.args();
|
||||||
if (args.length == 0)
|
if (args.length == 0)
|
||||||
{
|
{
|
||||||
@@ -91,19 +96,6 @@ public class PlexCMD extends ServerCommand
|
|||||||
context.send(sender, "Plex successfully reloaded.");
|
context.send(sender, "Plex successfully reloaded.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else if (args[0].equalsIgnoreCase("redis"))
|
|
||||||
{
|
|
||||||
context.checkPermission(sender, "plex.redis");
|
|
||||||
if (!plugin.getRedisConnection().isEnabled())
|
|
||||||
{
|
|
||||||
throw new CommandFailException("&cRedis is not enabled.");
|
|
||||||
}
|
|
||||||
plugin.getRedisConnection().execute(jedis -> jedis.set("test", "123"));
|
|
||||||
context.send(sender, "Set test to 123. Now outputting key test...");
|
|
||||||
String test = plugin.getRedisConnection().query(jedis -> jedis.get("test"));
|
|
||||||
context.send(sender, test);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else if (args[0].equalsIgnoreCase("modules"))
|
else if (args[0].equalsIgnoreCase("modules"))
|
||||||
{
|
{
|
||||||
if (args.length == 1)
|
if (args.length == 1)
|
||||||
@@ -118,10 +110,7 @@ public class PlexCMD extends ServerCommand
|
|||||||
}
|
}
|
||||||
else if (args[1].equalsIgnoreCase("update"))
|
else if (args[1].equalsIgnoreCase("update"))
|
||||||
{
|
{
|
||||||
if (!hasUpdateAccess(context, playerSender, sender))
|
context.checkPermission(sender, "plex.modules.update");
|
||||||
{
|
|
||||||
return context.mmString("<red>You must be a Developer to use this command.");
|
|
||||||
}
|
|
||||||
for (PlexModule module : plugin.getModuleManager().getModules())
|
for (PlexModule module : plugin.getModuleManager().getModules())
|
||||||
{
|
{
|
||||||
plugin.getUpdateChecker().updateModuleJar(sender, module);
|
plugin.getUpdateChecker().updateModuleJar(sender, module);
|
||||||
@@ -129,13 +118,42 @@ public class PlexCMD extends ServerCommand
|
|||||||
plugin.getModuleManager().reloadModules();
|
plugin.getModuleManager().reloadModules();
|
||||||
return context.mmString("<green>All modules updated and reloaded!");
|
return context.mmString("<green>All modules updated and reloaded!");
|
||||||
}
|
}
|
||||||
|
else if (args[1].equalsIgnoreCase("install"))
|
||||||
|
{
|
||||||
|
context.checkPermission(sender, "plex.modules.install");
|
||||||
|
if (args.length < 3)
|
||||||
|
{
|
||||||
|
return context.usage();
|
||||||
|
}
|
||||||
|
String moduleName = args[2];
|
||||||
|
plugin.getUpdateChecker().installModuleJar(sender, moduleName);
|
||||||
|
return context.mmString("<green>Installing module <yellow>" + moduleName + "<green>...");
|
||||||
|
}
|
||||||
|
else if (args[1].equalsIgnoreCase("uninstall"))
|
||||||
|
{
|
||||||
|
context.checkPermission(sender, "plex.modules.uninstall");
|
||||||
|
if (args.length < 3)
|
||||||
|
{
|
||||||
|
return context.usage();
|
||||||
|
}
|
||||||
|
String moduleName = args[2];
|
||||||
|
boolean removeData = args.length >= 4 && args[3].equalsIgnoreCase("-rmdir");
|
||||||
|
ModuleManager.UninstallResult result = plugin.getModuleManager().uninstallModule(moduleName, removeData);
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case NOT_FOUND:
|
||||||
|
return context.mmString("<red>No installed module named <yellow>" + moduleName + "<red> was found.");
|
||||||
|
case FAILED:
|
||||||
|
return context.mmString("<red>Failed to delete the JAR for <yellow>" + moduleName + "<red>. Check the server log.");
|
||||||
|
case REMOVED:
|
||||||
|
context.send(sender, context.mmString("<green>Uninstalled module <yellow>" + moduleName + "<green>" + (removeData ? " and its data folder" : "") + "."));
|
||||||
|
return context.messageComponent("moduleRestartRequired");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (args[0].equalsIgnoreCase("update"))
|
else if (args[0].equalsIgnoreCase("update"))
|
||||||
{
|
{
|
||||||
if (!hasUpdateAccess(context, playerSender, sender))
|
context.checkPermission(sender, "plex.update");
|
||||||
{
|
|
||||||
return context.mmString("<red>You must be a Developer to use this command.");
|
|
||||||
}
|
|
||||||
if (!plugin.getUpdateChecker().getUpdateStatusMessage(sender, false, 0))
|
if (!plugin.getUpdateChecker().getUpdateStatusMessage(sender, false, 0))
|
||||||
{
|
{
|
||||||
return context.mmString("<red>Plex is already up to date!");
|
return context.mmString("<red>Plex is already up to date!");
|
||||||
@@ -149,25 +167,4 @@ public class PlexCMD extends ServerCommand
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Owners and developers only have access
|
|
||||||
private boolean hasUpdateAccess(ServerCommandContext context, Player player, CommandSender sender)
|
|
||||||
{
|
|
||||||
// Allow CONSOLE, get OfflinePlayer for Telnet
|
|
||||||
if (context.isConsole(sender))
|
|
||||||
{
|
|
||||||
if (sender.getName().equalsIgnoreCase("CONSOLE"))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(sender.getName());
|
|
||||||
if (offlinePlayer.hasPlayedBefore())
|
|
||||||
{
|
|
||||||
return PlexUtils.DEVELOPERS.contains(offlinePlayer.getUniqueId().toString());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
assert player != null;
|
|
||||||
return PlexUtils.DEVELOPERS.contains(player.getUniqueId().toString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ public class ModuleManager
|
|||||||
PlexModule plexModule = module.getConstructor().newInstance();
|
PlexModule plexModule = module.getConstructor().newInstance();
|
||||||
plexModule.setApi(plugin.getApi());
|
plexModule.setApi(plugin.getApi());
|
||||||
plexModule.setPlexModuleFile(plexModuleFile);
|
plexModule.setPlexModuleFile(plexModuleFile);
|
||||||
|
plexModule.setModuleJar(file);
|
||||||
|
|
||||||
plexModule.setDataFolder(new File(plugin.getModulesFolder() + File.separator + plexModuleFile.getName()));
|
plexModule.setDataFolder(new File(plugin.getModulesFolder() + File.separator + plexModuleFile.getName()));
|
||||||
if (!plexModule.getDataFolder().exists())
|
if (!plexModule.getDataFolder().exists())
|
||||||
@@ -217,6 +218,11 @@ public class ModuleManager
|
|||||||
public void reloadModules()
|
public void reloadModules()
|
||||||
{
|
{
|
||||||
unloadModules();
|
unloadModules();
|
||||||
|
reloadFromDisk();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reloadFromDisk()
|
||||||
|
{
|
||||||
loadAllModules();
|
loadAllModules();
|
||||||
loadModules();
|
loadModules();
|
||||||
enableModules();
|
enableModules();
|
||||||
@@ -225,4 +231,65 @@ public class ModuleManager
|
|||||||
PlexLog.warn("Module command changes were staged after Paper's Brigadier command lifecycle. Restart the server for the live command dispatcher to match the loaded modules.");
|
PlexLog.warn("Module command changes were staged after Paper's Brigadier command lifecycle. Restart the server for the live command dispatcher to match the loaded modules.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outcome of an uninstall request.
|
||||||
|
*/
|
||||||
|
public enum UninstallResult
|
||||||
|
{
|
||||||
|
NOT_FOUND,
|
||||||
|
REMOVED,
|
||||||
|
FAILED
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uninstalls a loaded module by name: deletes its JAR and, optionally, its data
|
||||||
|
* folder, then reloads the remaining modules.
|
||||||
|
*
|
||||||
|
* @param name module name as declared in the module's module.yml
|
||||||
|
* @param removeData whether to also delete the module's data folder
|
||||||
|
* @return the outcome of the uninstall request
|
||||||
|
*/
|
||||||
|
public UninstallResult uninstallModule(String name, boolean removeData)
|
||||||
|
{
|
||||||
|
PlexModule target = modules.stream()
|
||||||
|
.filter(module -> module.getPlexModuleFile().getName().equalsIgnoreCase(name))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
if (target == null)
|
||||||
|
{
|
||||||
|
return UninstallResult.NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
File moduleJar = target.getModuleJar();
|
||||||
|
File dataFolder = target.getDataFolder();
|
||||||
|
|
||||||
|
unloadModules();
|
||||||
|
|
||||||
|
boolean deleted = moduleJar.delete();
|
||||||
|
if (deleted && removeData && dataFolder.isDirectory())
|
||||||
|
{
|
||||||
|
deleteRecursively(dataFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
reloadFromDisk();
|
||||||
|
|
||||||
|
return deleted ? UninstallResult.REMOVED : UninstallResult.FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteRecursively(File file)
|
||||||
|
{
|
||||||
|
File[] children = file.listFiles();
|
||||||
|
if (children != null)
|
||||||
|
{
|
||||||
|
for (File child : children)
|
||||||
|
{
|
||||||
|
deleteRecursively(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!file.delete())
|
||||||
|
{
|
||||||
|
PlexLog.warn("Unable to delete " + file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,6 +91,15 @@ public class UpdateChecker
|
|||||||
updateJar(sender, name, module, List.of());
|
updateJar(sender, name, module, List.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void installModuleJar(CommandSender sender, String name)
|
||||||
|
{
|
||||||
|
updateJar(sender, name, true, List.of(), () -> plugin.getApi().scheduler().runGlobal(() ->
|
||||||
|
{
|
||||||
|
plugin.getModuleManager().reloadModules();
|
||||||
|
sendMessage(sender, PlexUtils.messageComponent("moduleRestartRequired"));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
public void updateModuleJar(CommandSender sender, PlexModule module)
|
public void updateModuleJar(CommandSender sender, PlexModule module)
|
||||||
{
|
{
|
||||||
PlexModuleFile moduleFile = module.getPlexModuleFile();
|
PlexModuleFile moduleFile = module.getPlexModuleFile();
|
||||||
@@ -103,6 +112,11 @@ public class UpdateChecker
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateJar(CommandSender sender, String name, boolean module, List<String> moduleUpdateUrls)
|
private void updateJar(CommandSender sender, String name, boolean module, List<String> moduleUpdateUrls)
|
||||||
|
{
|
||||||
|
updateJar(sender, name, module, moduleUpdateUrls, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateJar(CommandSender sender, String name, boolean module, List<String> moduleUpdateUrls, Runnable onSuccess)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -121,7 +135,7 @@ public class UpdateChecker
|
|||||||
: new File(Bukkit.getUpdateFolderFile(), metadata.fileName());
|
: new File(Bukkit.getUpdateFolderFile(), metadata.fileName());
|
||||||
|
|
||||||
sendMessage(sender, PlexUtils.messageComponent("updateDownloading", metadata.fileName()));
|
sendMessage(sender, PlexUtils.messageComponent("updateDownloading", metadata.fileName()));
|
||||||
plugin.getApi().scheduler().runAsync(() -> downloadAndInstall(sender, metadata, copyTo));
|
plugin.getApi().scheduler().runAsync(() -> downloadAndInstall(sender, metadata, copyTo, onSuccess));
|
||||||
}
|
}
|
||||||
catch (UpdateMetadataClient.MetadataException e)
|
catch (UpdateMetadataClient.MetadataException e)
|
||||||
{
|
{
|
||||||
@@ -174,7 +188,7 @@ public class UpdateChecker
|
|||||||
return System.currentTimeMillis() - latestPlexMetadataFailureAtMillis < PLEX_METADATA_FAILURE_CACHE_MILLIS;
|
return System.currentTimeMillis() - latestPlexMetadataFailureAtMillis < PLEX_METADATA_FAILURE_CACHE_MILLIS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void downloadAndInstall(CommandSender sender, ArtifactMetadata metadata, File copyTo)
|
private void downloadAndInstall(CommandSender sender, ArtifactMetadata metadata, File copyTo, Runnable onSuccess)
|
||||||
{
|
{
|
||||||
File parent = copyTo.getParentFile();
|
File parent = copyTo.getParentFile();
|
||||||
if (parent != null && !parent.exists() && !parent.mkdirs())
|
if (parent != null && !parent.exists() && !parent.mkdirs())
|
||||||
@@ -190,6 +204,10 @@ public class UpdateChecker
|
|||||||
validateDownloadedFile(metadata, temporaryFile);
|
validateDownloadedFile(metadata, temporaryFile);
|
||||||
Files.move(temporaryFile.toPath(), copyTo.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
Files.move(temporaryFile.toPath(), copyTo.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||||
sendMessage(sender, PlexUtils.messageComponent("updateDownloaded"));
|
sendMessage(sender, PlexUtils.messageComponent("updateDownloaded"));
|
||||||
|
if (onSuccess != null)
|
||||||
|
{
|
||||||
|
onSuccess.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -357,3 +357,4 @@ updateMetadataNotFound: "<red>No compatible update is available on the {0} chann
|
|||||||
# 0 - The error message
|
# 0 - The error message
|
||||||
updateMetadataError: "<red>There was an error checking update metadata: {0}"
|
updateMetadataError: "<red>There was an error checking update metadata: {0}"
|
||||||
moduleUpdateDisabled: "<yellow>Skipping {0}; module updates are disabled."
|
moduleUpdateDisabled: "<yellow>Skipping {0}; module updates are disabled."
|
||||||
|
moduleRestartRequired: "<yellow>Module changes applied. Restart the server if module commands do not appear or disappear."
|
||||||
|
|||||||
Reference in New Issue
Block a user