mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2025-02-10 09:21:31 +01:00
Added 'api-version' parameter to addon.yml to allow specifying a minimum required BentoBox version
Implements https://github.com/BentoBoxWorld/BentoBox/issues/1131 API: added InvalidAddonDescriptionException, AddonDescription#getApiVersion()
This commit is contained in:
parent
d8dda75ca5
commit
d8d9061f84
@ -20,6 +20,7 @@ import org.bukkit.util.permissions.DefaultPermissions;
|
|||||||
import org.eclipse.jdt.annotation.NonNull;
|
import org.eclipse.jdt.annotation.NonNull;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
|
||||||
|
import world.bentobox.bentobox.api.addons.exceptions.InvalidAddonDescriptionException;
|
||||||
import world.bentobox.bentobox.api.addons.exceptions.InvalidAddonFormatException;
|
import world.bentobox.bentobox.api.addons.exceptions.InvalidAddonFormatException;
|
||||||
import world.bentobox.bentobox.api.addons.exceptions.InvalidAddonInheritException;
|
import world.bentobox.bentobox.api.addons.exceptions.InvalidAddonInheritException;
|
||||||
import world.bentobox.bentobox.managers.AddonsManager;
|
import world.bentobox.bentobox.managers.AddonsManager;
|
||||||
@ -39,6 +40,7 @@ public class AddonClassLoader extends URLClassLoader {
|
|||||||
throws InvalidAddonInheritException,
|
throws InvalidAddonInheritException,
|
||||||
MalformedURLException,
|
MalformedURLException,
|
||||||
InvalidDescriptionException,
|
InvalidDescriptionException,
|
||||||
|
InvalidAddonDescriptionException,
|
||||||
InstantiationException,
|
InstantiationException,
|
||||||
IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
||||||
super(new URL[]{path.toURI().toURL()}, parent);
|
super(new URL[]{path.toURI().toURL()}, parent);
|
||||||
@ -94,7 +96,7 @@ public class AddonClassLoader extends URLClassLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private AddonDescription asDescription(YamlConfiguration data) {
|
private AddonDescription asDescription(YamlConfiguration data) throws InvalidAddonDescriptionException {
|
||||||
AddonDescription.Builder builder = new AddonDescription.Builder(data.getString("main"), data.getString("name"), data.getString("version"))
|
AddonDescription.Builder builder = new AddonDescription.Builder(data.getString("main"), data.getString("name"), data.getString("version"))
|
||||||
.authors(data.getString("authors"))
|
.authors(data.getString("authors"))
|
||||||
.metrics(data.getBoolean("metrics", true))
|
.metrics(data.getBoolean("metrics", true))
|
||||||
@ -110,6 +112,14 @@ public class AddonClassLoader extends URLClassLoader {
|
|||||||
}
|
}
|
||||||
builder.icon(Material.getMaterial(data.getString("icon", "PAPER")));
|
builder.icon(Material.getMaterial(data.getString("icon", "PAPER")));
|
||||||
|
|
||||||
|
String apiVersion = data.getString("api-version");
|
||||||
|
if (apiVersion != null) {
|
||||||
|
if (!apiVersion.matches("^(\\d+\\.)?(\\d+\\.)?(\\*|\\d+)$")) {
|
||||||
|
throw new InvalidAddonDescriptionException("Provided API version '" + apiVersion + "' is not valid. It must only contain digits and dots and not end with a dot.");
|
||||||
|
}
|
||||||
|
builder.apiVersion(apiVersion);
|
||||||
|
}
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,12 @@ public final class AddonDescription {
|
|||||||
* @since 1.5.0
|
* @since 1.5.0
|
||||||
*/
|
*/
|
||||||
private final @NonNull Material icon;
|
private final @NonNull Material icon;
|
||||||
|
/**
|
||||||
|
* Minimum BentoBox version this addon requires in order to work properly.
|
||||||
|
* Defaults to {@code "1"}.
|
||||||
|
* @since 1.11.0
|
||||||
|
*/
|
||||||
|
private final @NonNull String apiVersion;
|
||||||
|
|
||||||
private AddonDescription(@NonNull Builder builder) {
|
private AddonDescription(@NonNull Builder builder) {
|
||||||
this.main = builder.main;
|
this.main = builder.main;
|
||||||
@ -47,6 +53,7 @@ public final class AddonDescription {
|
|||||||
this.metrics = builder.metrics;
|
this.metrics = builder.metrics;
|
||||||
this.repository = builder.repository;
|
this.repository = builder.repository;
|
||||||
this.icon = builder.icon;
|
this.icon = builder.icon;
|
||||||
|
this.apiVersion = builder.apiVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -120,6 +127,29 @@ public final class AddonDescription {
|
|||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the minimum BentoBox version this addon requires in order to work properly.
|
||||||
|
* <br/>
|
||||||
|
* Examples:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code "1"} means that the addon relies on BentoBox {@code 1.0.0} or higher.</li>
|
||||||
|
* <li>Similarly, {@code "2"} sets the requirement to BentoBox {@code 2.0.0} or higher.</li>
|
||||||
|
* <li>
|
||||||
|
* More specific versions can be provided:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code "1.10"} -> BentoBox {@code 1.10.0} or higher.</li>
|
||||||
|
* <li>{@code "1.9.2"} -> BentoBox {@code 1.9.2} or higher.</li>
|
||||||
|
* </ul>
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
|
* Defaults to {@code "1"}.
|
||||||
|
* @return the minimum BentoBox version this addon requires in order to work properly.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public String getApiVersion() {
|
||||||
|
return apiVersion;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
private @NonNull String main;
|
private @NonNull String main;
|
||||||
private @NonNull String name;
|
private @NonNull String name;
|
||||||
@ -131,6 +161,7 @@ public final class AddonDescription {
|
|||||||
private boolean metrics = true;
|
private boolean metrics = true;
|
||||||
private @NonNull String repository = "";
|
private @NonNull String repository = "";
|
||||||
private @NonNull Material icon = Material.PAPER;
|
private @NonNull Material icon = Material.PAPER;
|
||||||
|
private @NonNull String apiVersion = "1";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 1.1
|
* @since 1.1
|
||||||
@ -196,6 +227,18 @@ public final class AddonDescription {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the minimum BentoBox version this addon requires in order to work properly.
|
||||||
|
* @param apiVersion the minimum BentoBox version this addon requires in order to work properly.
|
||||||
|
* @since 1.11.0
|
||||||
|
* @see AddonDescription#getApiVersion()
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public Builder apiVersion(@NonNull String apiVersion) {
|
||||||
|
this.apiVersion = apiVersion;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public AddonDescription build() {
|
public AddonDescription build() {
|
||||||
return new AddonDescription(this);
|
return new AddonDescription(this);
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
package world.bentobox.bentobox.api.addons.exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 1.11.0
|
||||||
|
*/
|
||||||
|
public class InvalidAddonDescriptionException extends AddonException {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 7741502900847049986L;
|
||||||
|
|
||||||
|
public InvalidAddonDescriptionException(String errorMessage) {
|
||||||
|
super(errorMessage);
|
||||||
|
}
|
||||||
|
}
|
@ -117,6 +117,16 @@ public class AddonsManager {
|
|||||||
// Add to the list of loaders
|
// Add to the list of loaders
|
||||||
loaders.put(addon, addonClassLoader);
|
loaders.put(addon, addonClassLoader);
|
||||||
|
|
||||||
|
// Checks if this addon is compatible with the current BentoBox version.
|
||||||
|
if (!isAddonCompatibleWithBentoBox(addon)) {
|
||||||
|
// It is not, abort.
|
||||||
|
plugin.logWarning("Skipping " + addon.getDescription().getName() + " as it can only run on a more recent BentoBox version.");
|
||||||
|
plugin.logWarning("NOTE: The addon relies on API that is not available in the BentoBox version you are using.");
|
||||||
|
plugin.logWarning("NOTE: Please update BentoBox.");
|
||||||
|
addon.setState(State.INCOMPATIBLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Run the onLoad.
|
// Run the onLoad.
|
||||||
addon.onLoad();
|
addon.onLoad();
|
||||||
@ -204,6 +214,32 @@ public class AddonsManager {
|
|||||||
plugin.log("NOTE: DO NOT report this as a bug from BentoBox.");
|
plugin.log("NOTE: DO NOT report this as a bug from BentoBox.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the addon does not explicitly rely on API from a more recent BentoBox version.
|
||||||
|
* @param addon instance of the Addon.
|
||||||
|
* @return {@code true} if the addon relies on available BentoBox API, {@code false} otherwise.
|
||||||
|
* @since 1.11.0
|
||||||
|
*/
|
||||||
|
private boolean isAddonCompatibleWithBentoBox(@NonNull Addon addon) {
|
||||||
|
// We have to use lists instead of arrays for dynamic changes and optimization (appending something to an array is O(n) whereas O(1) with lists).
|
||||||
|
List<String> apiVersion = Arrays.asList(addon.getDescription().getApiVersion().split("\\."));
|
||||||
|
List<String> bentoboxVersion = Arrays.asList(plugin.getDescription().getVersion().split("\\."));
|
||||||
|
|
||||||
|
while (bentoboxVersion.size() < apiVersion.size()) {
|
||||||
|
bentoboxVersion.add("0");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < apiVersion.size(); i++) {
|
||||||
|
int apiNumber = Integer.parseInt(apiVersion.get(i));
|
||||||
|
int bentoboxNumber = Integer.parseInt(bentoboxVersion.get(i));
|
||||||
|
if (bentoboxNumber < apiNumber) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles an addon which failed to load due to an error.
|
* Handles an addon which failed to load due to an error.
|
||||||
* @param addon instance of the Addon.
|
* @param addon instance of the Addon.
|
||||||
|
Loading…
Reference in New Issue
Block a user