Class PluginInstallCommands
- All Implemented Interfaces:
org.bukkit.command.CommandExecutor,org.bukkit.command.TabCompleter,org.bukkit.command.TabExecutor
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static final StringThe literal Bukkitname:prefixisSameModule(com.ultikits.ultitools.abstracts.UltiToolsPlugin, com.ultikits.ultitools.entities.PluginEntity)strips before comparing a loaded module's runtime name against the catalogue's display name (#439). -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidcheckUpdates(org.bukkit.command.CommandSender sender) private static voidcollectNamedFiles(FileSystemException failure, List<String> files) Collects the file named byfailureand by everyFileSystemExceptionattached to it, at any depth -- a file the operator is not told about is one they leave behind.private static voidcollectNamedFiles(FileSystemException failure, List<String> files, Set<Throwable> seen) collectNamedFiles(FileSystemException, List), remembering what it has already walked, for the same reasoncollectUndetermined(Throwable, List, java.util.Set)does.private static voidcollectUndetermined(Throwable failure, List<String> files) Collects the undetermined entries a failure carries, wherever in its suppressed chain they sit.private static voidcollectUndetermined(Throwable, List), remembering what it has already walked.protected voidhandleHelp(org.bukkit.command.CommandSender sender) Handles the help command.voidinstallPlugin(org.bukkit.command.CommandSender sender, String plugin) voidinstallPlugin(org.bukkit.command.CommandSender sender, String plugin, String version) (package private) static booleanisSameModule(UltiToolsPlugin installedPlugin, PluginEntity catalogueEntry) Decides whetherinstalledPlugin(a currently loaded module) andcatalogueEntry(a directory entry from the UltiCloud catalogue) refer to the SAME module (#439).voidlistPlugins(org.bukkit.command.CommandSender sender) voidlistPlugins(org.bukkit.command.CommandSender sender, String page) voidlistVersions(org.bukkit.command.CommandSender sender, String plugin) private static StringnormalizeIdentifyString(String value) Trims and lower-cases an identify string, the same normalisationPluginInstallUtils's own (private)normalizeIdentifyStringapplies before every install/update/lookup comparison elsewhere in this package (gate-2 Codex round 1) -- kept as a small local copy rather than widening that method's visibility, since the transform itself is a one-line, well-established convention, not shared mutable state.(package private) static StringresolveInstalledRuntimeName(List<UltiToolsPlugin> installedPlugins, PluginEntity catalogueEntry) Resolves the runtime name to use for the/upm uninstallclick command inlistPlugins(CommandSender, String)'s player branch: the LOADED module's owngetPluginName(), not the catalogue entry's display name (gate-2 Codex round 1).(package private) static voidsendComponentMessage(org.bukkit.entity.Player player, net.kyori.adventure.text.TextComponent text) Send a TextComponent message to a player.private static voidsendJarOutcomeAfterUnloadError(org.bukkit.command.CommandSender sender, PluginInstallUtils.ModuleUnloadFailedException unloadError) Reports the jar outcomePluginInstallUtils.uninstallPlugin(java.lang.String)attached to its unload-error exception: none attached means every matching jar was deleted.(package private) static voidsendStringMessage(org.bukkit.command.CommandSender sender, String message) Send a string message to a command sender.private static voidsendUndeletedJars(org.bukkit.command.CommandSender sender, FileSystemException failure) Names every jar the uninstall could not delete.private static voidsendUndeterminedEntries(org.bukkit.command.CommandSender sender, PluginInstallUtils.UninstallReport report) Says what the uninstall could not determine: entries it could not read at all.private static voidsendUnlistableFolder(org.bukkit.command.CommandSender sender, String folder) The modules folder is there and its contents are unknown, so nothing may be claimed about what it still holds -- including whether a JAR of this module is among it.private static voidsendUnreadableEntriesOf(org.bukkit.command.CommandSender sender, Throwable failure) Names the entries a no-JAR-found failure carries with it: state C survives that answer, and one of those entries may be the module's own JAR.private static StringstripVendorPrefix(String runtimeName) undeterminedOf(Throwable failure) The undetermined entries a failure carries.voiduninstallPlugin(org.bukkit.command.CommandSender sender, String plugin) private voidupdateAllPlugins(org.bukkit.command.CommandSender sender) voidupdatePlugin(org.bukkit.command.CommandSender sender, String pluginName) Methods inherited from class com.ultikits.ultitools.abstracts.command.BaseCommandExecutor
addValidator, buildMethodParams, createDefaultValidatorChain, executeCommand, getHelpCommand, getMappings, matchMethod, onCommand, onTabComplete, parseParameters, parseParameterValue, removeValidator, suggest, validateParameterCount
-
Field Details
-
VENDOR_PREFIX
The literal Bukkitname:prefixisSameModule(com.ultikits.ultitools.abstracts.UltiToolsPlugin, com.ultikits.ultitools.entities.PluginEntity)strips before comparing a loaded module's runtime name against the catalogue's display name (#439).- See Also:
-
-
Constructor Details
-
PluginInstallCommands
public PluginInstallCommands()
-
-
Method Details
-
listPlugins
-
sendComponentMessage
static void sendComponentMessage(org.bukkit.entity.Player player, net.kyori.adventure.text.TextComponent text) Send a TextComponent message to a player. This method is extracted from BukkitRunnable for testability.- Parameters:
player- the player to send the message totext- the text component to send
-
sendStringMessage
Send a string message to a command sender. This method is extracted from BukkitRunnable for testability.- Parameters:
sender- the sender to send the message tomessage- the message to send
-
listPlugins
public void listPlugins(org.bukkit.command.CommandSender sender) -
installPlugin
-
installPlugin
-
listVersions
-
uninstallPlugin
-
sendUnlistableFolder
The modules folder is there and its contents are unknown, so nothing may be claimed about what it still holds -- including whether a JAR of this module is among it. -
sendUnreadableEntriesOf
private static void sendUnreadableEntriesOf(org.bukkit.command.CommandSender sender, Throwable failure) Names the entries a no-JAR-found failure carries with it: state C survives that answer, and one of those entries may be the module's own JAR. -
sendUndeterminedEntries
private static void sendUndeterminedEntries(org.bukkit.command.CommandSender sender, PluginInstallUtils.UninstallReport report) Says what the uninstall could not determine: entries it could not read at all. They are not called copies of the module, because nothing established that they are -- what the operator needs is the count and what follows from it if one of them turns out to be one. -
sendJarOutcomeAfterUnloadError
private static void sendJarOutcomeAfterUnloadError(org.bukkit.command.CommandSender sender, PluginInstallUtils.ModuleUnloadFailedException unloadError) Reports the jar outcomePluginInstallUtils.uninstallPlugin(java.lang.String)attached to its unload-error exception: none attached means every matching jar was deleted. -
undeterminedOf
The undetermined entries a failure carries. -
collectUndetermined
Collects the undetermined entries a failure carries, wherever in its suppressed chain they sit. -
collectUndetermined
collectUndetermined(Throwable, List), remembering what it has already walked.`addSuppressed` refuses a throwable suppressing itself but not a longer loop, and a walk that meets one never returns. Nothing here builds such a chain today; the uninstall's replies are not the place to find out that something else did.
- Parameters:
failure- the failure to walkfiles- the paths collected so farseen- the throwables already visited, by identity
-
sendUndeletedJars
private static void sendUndeletedJars(org.bukkit.command.CommandSender sender, FileSystemException failure) Names every jar the uninstall could not delete. Each one loads the module again at the next start, so an instruction that names only the first is one the operator cannot act on (#501). -
collectNamedFiles
Collects the file named byfailureand by everyFileSystemExceptionattached to it, at any depth -- a file the operator is not told about is one they leave behind.- Parameters:
failure- the failure to walkfiles- the names collected so far, in the order they were found
-
collectNamedFiles
private static void collectNamedFiles(FileSystemException failure, List<String> files, Set<Throwable> seen) collectNamedFiles(FileSystemException, List), remembering what it has already walked, for the same reasoncollectUndetermined(Throwable, List, java.util.Set)does.- Parameters:
failure- the failure to walkfiles- the paths collected so farseen- the throwables already visited, by identity
-
checkUpdates
public void checkUpdates(org.bukkit.command.CommandSender sender) -
updatePlugin
-
updateAllPlugins
private void updateAllPlugins(org.bukkit.command.CommandSender sender) -
isSameModule
Decides whetherinstalledPlugin(a currently loaded module) andcatalogueEntry(a directory entry from the UltiCloud catalogue) refer to the SAME module (#439). The prior check comparedinstalledPlugin.getPluginName()(the module's Bukkitplugin.ymlname:) againstcatalogueEntry.getName()(the catalogue's own display name) with plain string equality -- correct only when the two strings genuinely agree, which they do not for every module.Preferred key, but inert today:
identifyString. This is the fieldPluginInstallUtilsandUpdateManageralready treat as this framework's stable module identity for install/update/version lookups, and the one fieldPluginEntityandUltiToolsPluginboth carry under the same name. Compared only when BOTH sides carry a non-blank value -- two identify-string-less entries are never treated as a match on that basis alone, or every such module would appear installed against every such catalogue entry, which is worse than the bug being fixed. Measured as of 6.3.0 (WR-01, `16-REVIEW-command.md`): zero of the seventeen module directories underModules/declareidentify-string:inplugin.yml(verified:grep -rl "identify-string:" Modules/*/src/main/resources/plugin.ymlreturns nothing), soinstalledPlugin.getIdentifyString()isnullfor every module that exists today, including both modules #439 names, and this branch does not fire for any of them. It exists so a module that DOES declare one -- and any future migration towardidentify-string:-based identity -- is matched correctly without this method needing to change again; today it is aspirational, not load-bearing.What actually fires today: exact name equality, plus one fixed, deterministic prefix strip. Measured (WR-01): only 4 of the 15 active modules declare a Bukkit
name:carrying the literal"UltiTools-"prefix --UltiTools-Chat(Modules/UltiChat/src/main/resources/plugin.yml:1),UltiTools-Economy(Modules/UltiEconomy/.../plugin.yml:1),UltiTools-Kits(Modules/UltiKits/.../plugin.yml:1), andUltiTools-Menu(Modules/UltiMenu/.../plugin.yml:1) -- the last two ARE #439's own two named modules. The other 11 modules declare their bare folder name with no prefix at all (e.g.UltiLogin,UltiWorlds). This is NOT a declared or tool-enforced convention:Tooling/ultikits-cli/src/lib/templates.ts:152templatesname:directly from the author-supplied module name with no prefix logic, andTooling/UltiTools-Maven-Archetypeships noplugin.ymltemplate at all -- it is simply each of these 4 authors' own historical choice. Stripping that one fixed prefix before comparing is a single deterministic transform, not a similarity/fuzzy heuristic: it accepts precisely the pairs that differ by nothing, or by exactly that one literal prefix, and rejects every other pair -- including one that merely shares a prefix or substring (a catalogue name that only resembles a loaded module's, such as one ending in"Pro", is rejected, not matched).Two present identifiers are authoritative, even on a mismatch (gate-2 Codex round 1). When BOTH sides carry a non-blank
identifyString, that comparison alone decides the outcome -- a match returnstrueimmediately, and a MISMATCH returnsfalseimmediately, without ever falling through to the name/prefix heuristic below. Two present, different stable identifiers prove the modules are different; the name heuristic must not override that proof (a loadedUltiTools-Foowith idauthor-a.foomust not be reported as the catalogue's unrelatedFoowith idauthor-b.foo, even though the name/prefix rule alone would match them). The comparison is normalised (trimmed, lower-cased) via the same conventionPluginInstallUtils's own (private)normalizeIdentifyStringalready applies before every install/update/lookup comparison elsewhere in this package, so a module and a catalogue entry that agree except for case are still recognised as the same.Residual collision risk (WR-01), disclosed rather than papered over: the risk above is closed whenever BOTH sides carry an identifier. It remains open only when at least one side's
identifyStringis blank -- true for every module today (0/17) -- in which case a THIRD-PARTY module that names itselfUltiTools-Fooin its ownplugin.ymlwould still be reported installed against a different, unrelated author's unaffiliated catalogue entry literally namedFoo, since neitherUltiToolsPluginnorPluginEntityexposes anything else (a developer/author ID) this method could cross-check in that case. Still strictly better than the defect being fixed: today, EVERY module whose name doesn't already match its catalogue display name byte-for-byte is unconditionally reported not installed, a guaranteed false negative for real, correctly-loaded modules. Closing the remaining gap needs a stable identifier populated on both sides (#474), not a looser name heuristic.- Parameters:
installedPlugin- a currently loaded modulecatalogueEntry- a directory entry from the catalogue- Returns:
trueiff the two are judged to refer to the same module
-
resolveInstalledRuntimeName
static String resolveInstalledRuntimeName(List<UltiToolsPlugin> installedPlugins, PluginEntity catalogueEntry) Resolves the runtime name to use for the/upm uninstallclick command inlistPlugins(CommandSender, String)'s player branch: the LOADED module's owngetPluginName(), not the catalogue entry's display name (gate-2 Codex round 1).PluginInstallUtils.uninstallPlugin(java.lang.String)matches only against the runtime name -- for exactly the display-name-mismatch caseisSameModule(com.ultikits.ultitools.abstracts.UltiToolsPlugin, com.ultikits.ultitools.entities.PluginEntity)exists to recognise as installed, using the catalogue's display name here would build an uninstall command that silently fails (no unregister, no file delete, a generic failure message).- Parameters:
installedPlugins- every currently-loaded modulecatalogueEntry- the catalogue entry being rendered- Returns:
- the matched module's own runtime name, or
nullif none matches
-
normalizeIdentifyString
Trims and lower-cases an identify string, the same normalisationPluginInstallUtils's own (private)normalizeIdentifyStringapplies before every install/update/lookup comparison elsewhere in this package (gate-2 Codex round 1) -- kept as a small local copy rather than widening that method's visibility, since the transform itself is a one-line, well-established convention, not shared mutable state.- Parameters:
value- the raw identify string, possiblynullor blank- Returns:
- the normalised value, or
nullif the input wasnullor blank
-
stripVendorPrefix
-
handleHelp
protected void handleHelp(org.bukkit.command.CommandSender sender) Description copied from class:BaseCommandExecutorHandles the help command. Override to provide custom help.- Specified by:
handleHelpin classBaseCommandExecutor- Parameters:
sender- the command sender
-