Upgrading
Developer's Note:
Please select your current version and the version you want to upgrade to below. The page will automatically display the steps you need to follow.
If you are upgrading from a version that is not listed, please select the next version that is slightly larger than your version.
e.g., if you are upgrading from 8.7.4, you should select to upgrading from 8.8.0.
6.5.2 → 7.0.0
Maven repository
The Maven repository used to serve the CommandAPI has changed from JitPack.io to Maven Central. For Maven projects, you no longer require wan explicit <repository> entry for the CommandAPI. For Gradle projects, you need to ensure mavenCentral() in present in your repositories section.
The group ID has changed from dev.jorel.CommandAPI to dev.jorel
More information about setting up your development environment can be found in Setting up your development environment.
CommandAPI command failures
The CommandAPI.fail() no longer automatically throws the exception that it creates, and instead now requires you to manually throw the exception yourself. This improves upon invalid states in command executors and allows invalid states to be identified more easily at compile time. To update, simply add the throw keyword before you call CommandAPI.fail():
new CommandAPICommand("mycommand")
.executes((sender, args) -> {
if(!sender.hasPermission("some.permission")) {
CommandAPI.fail("You don't have permission to run /mycommand!");
return;
throw CommandAPI.fail("You don't have permission to run /mycommand!");
}
sender.sendMessage("Hello!");
})Suggestions
Suggestions have been overhauled and no longer take in a Function<SuggestionsInfo, String[]> anymore. Instead, they now take in a ArgumentSuggestions object which represents argument suggestions (and whether they are executed asynchronously or have tooltips).
Normal (string) suggestions
These normal suggestions methods have been replaced with an ArgumentSuggestions parameter instead of a function:
Argument replaceSuggestions(Function<SuggestionInfo, String[]> suggestions);
Argument includeSuggestions(Function<SuggestionInfo, String[]> suggestions);
Argument replaceSuggestions(ArgumentSuggestions suggestions);
Argument includeSuggestions(ArgumentSuggestions suggestions); The same functionality can be reproduced by wrapping your existing functions in ArgumentSuggestions.strings:
List<Argument> arguments = new ArrayList<>();
arguments.add(new StringArgument("world").replaceSuggestions(info ->
arguments.add(new StringArgument("world").replaceSuggestions(ArgumentSuggestions.strings(info ->
new String[] {"northland", "eastland", "southland", "westland" }
)));Normal (strings with tooltips) suggestions
The ...T() methods have been replaced with the normal methods above, and can use the ArgumentSuggestions.stringsWithTooltips method:
Argument replaceSuggestionsT(Function<SuggestionInfo, IStringTooltip[]> suggestions);
Argument includeSuggestionsT(Function<SuggestionInfo, IStringTooltip[]> suggestions);
Argument replaceSuggestions(ArgumentSuggestions suggestions);
Argument includeSuggestions(ArgumentSuggestions suggestions); For example:
List<Argument> arguments = new ArrayList<>();
arguments.add(new StringArgument("emote")
.replaceSuggestionsT( info -> new IStringTooltip[] {
.replaceSuggestions(ArgumentSuggestions.stringsWithTooltips(info -> new IStringTooltip[] {
StringTooltip.of("wave", "Waves at a player"),
StringTooltip.of("hug", "Gives a player a hug"),
StringTooltip.of("glare", "Gives a player the death glare")
}
))
);Safe suggestions
Similar to above with normal suggestions, safe suggestions have been replaced with replaceSafeSuggestions and includeSafeSuggestions respectively:
Argument replaceWithSafeSuggestions(Function<SuggestionInfo, S[]> suggestions);
Argument includeWithSafeSuggestions(Function<SuggestionInfo, S[]> suggestions);
Argument replaceSafeSuggestions(SafeSuggestions<T> suggestions);
Argument includeSafeSuggestions(SafeSuggestions<T> suggestions); These can be used with the SafeSuggestions.suggest and SafeSuggestions.tooltips methods to wrap existing functions. For example:
List<Argument> arguments = new ArrayList<>();
arguments.add(new RecipeArgument("recipe").replaceWithSafeSuggestions(info ->
arguments.add(new RecipeArgument("recipe").replaceSafeSuggestions(SafeSuggestions.suggest(info ->
new Recipe[] { emeraldSwordRecipe, /* Other recipes here */ }
)));7.0.0 → 8.0.0
Particle arguments
Particle arguments no longer return Bukkit's org.bukkit.Particle enum, but now return a wrapper dev.jorel.commandapi.wrappers.ParticleData instead. More information about this wrapper class and how to use it can be found on the particle arguments page. To update, change any Particle casts into a ParticleData cast instead:
new CommandAPICommand("mycommand")
.withArgument(new ParticleArgument("particle"))
.executes((sender, args) -> {
Particle particle = (Particle) args[0];
ParticleData particleData = (ParticleData) args[0];
Particle particle = particleData.particle();
Object data = particleData.data();
// Do stuff with particle
})
.register();8.0.0 → 8.1.0
Arguments are now parameterized over a generic type. This does very little in terms of the running of the CommandAPI, but does ensure type safety with its internals. Instances of the Argument type now have to be parameterized. In general, this basically means:
Argument myArgument = new GreedyStringArgument("arg");
Argument<?> myArgument = new GreedyStringArgument("arg"); Arguments that have multiple return types also need to be parameterized over their return type. This includes:
CustomArgumentEntitySelectorArgumentScoreholderArgument
For example:
new EntitySelectorArgument("target", EntitySelector.ONE_PLAYER);
new EntitySelectorArgument<Player>("target", EntitySelector.ONE_PLAYER); 8.3.1 → 8.4.0
Getting a list of registered commands
In 8.2.1, the CommandAPI exposed CommandAPIHandler.getInstance().registeredCommands to get a list of registered commands. This has now been changed and properly implemented as a getter method which can be accessed from CommandAPI:
CommandAPIHandler.getInstance().registeredCommands
CommandAPI.getRegisteredCommands() Entity selector arguments
The import for EntitySelector for the EntitySelectorArgument has moved to improve CommandAPI shading support with jar minimization:
dev.jorel.commandapi.arguments.EntitySelectorArgument.EntitySelector
dev.jorel.commandapi.arguments.EntitySelector Custom arguments
Custom arguments are no longer restricted to a string-based argument or a keyed-based argument and can now be implemented over any existing argument "base". This argument is now parameterized over two types: the first type being the return type of this custom argument and the second type being the return type of the "base" argument. Custom arguments should now use the new constructor that accepts an argument - more information on how to do that can be found on the Custom arguments page. It's recommended to review your implementation of custom arguments and upgrade them if you feel that you need a more powerful argument parser (for example, you might want to use a greedy string argument as the base argument instead of a string argument).
Custom arguments that are not keyed can be drop-in replaced with a StringArgument:
new CustomArgument<T>("nodename", inputInfo -> {
new CustomArgument<T, String>(new StringArgument("nodename"), inputInfo -> {
// Code here
return T;
});Keyed custom arguments can be drop-in replaced with a NamespacedKeyArgument:
new CustomArgument<T>("nodename", inputInfo -> {
new CustomArgument<T, NamespacedKey>(new NamespacedKeyArgument("nodename"), inputInfo -> {
// Code here
return T;
});NBT arguments
NBT arguments now have a different implementation if you're using the plugin version of the CommandAPI or shading the CommandAPI.
NBTCompoundArguments are now parameterized over their implemented NBTCompound implementation. For the NBT API, this means:
new NBTCompoundArgument("nbt");
new NBTCompoundArgument<NBTContainer>("nbt"); If you're using the plugin version of the CommandAPI
You no longer have to include the NBT API separately; the CommandAPI comes with the NBT API built-in:
de.tr7zw.nbtapi.NBTContainer
dev.jorel.commandapi.nbtapi.NBTContainer If you're shading the CommandAPI
You now need to shade the NBT API into your plugin (as well as the CommandAPI). So the CommandAPI knows how to use the underlying implementation of the NBT API, you have to configure it using the CommandAPIConfig.initializeNBTAPI() method in CommandAPI.onLoad(). More information on how to do that can be found on the NBT arguments page, under Shading usage setup.
8.5.0 → 8.5.1
Brigadier arguments
In 8.5.1, the methods Brigadier.fromArgument and Brigadier.toSuggestions were changed to use Argument based parameters instead of String based parameters. Instead of providing the node name, you now have to provide the whole argument:
Argument<?> myArgument = new StringArgument("myargument");
List<Argument<?>> argumentList = List.of(myArgument);
Brigadier.fromArgument(argumentList, "myargument");
Brigadier.toSuggestions("myargument", argumentList);
Brigadier.fromArgument(argumentList, myArgument);
Brigadier.toSuggestions(myArgument, argumentList); 8.5.1 → 8.6.0
Sound arguments
In 8.6.0, the SoundArgument now supports returning a Sound or NamespacedKey object. More information on how to use this can be found in the Sound arguments page. SoundArgument objects now require a generic type parameter to specify what the return type will be (either Sound or NamespacedKey). For the default behavior, use Sound as the generic type parameter:
new SoundArgument("sound");
new SoundArgument<Sound>("sound"); Tooltips
In 8.6.0, tooltips have been reworked to provide support for Spigot's BaseComponent[]s, and Adventure's Components. As a result, the default method StringTooltip.of() and Tooltip.of() have been deprecated in favour of the better named StringTooltip.ofString() and Tooltip.ofString() methods:
StringTooltip.of("wave", "Waves at a player");
Tooltip.of(player.getWorld().getSpawnLocation(), "World spawn");
StringTooltip.ofString("wave", "Waves at a player");
Tooltip.ofString(player.getWorld().getSpawnLocation(), "World spawn"); Additionally, the IStringTooltip interface's getTooltip method was changed to return a Brigadier Message object instead of a String. To use the IStringTooltip directly, you now have to add Brigadier to your project's dependencies (info on how to do that can be found here).
You can use the Tooltip.messageFromString(String) to easily upgrade to the new Message return type:
@Override
public String getTooltip() {
return this.itemstack.getItemMeta().getLore().get(0);
return Tooltip.messageFromString(this.itemstack.getItemMeta().getLore().get(0));
}Command failures
To support Spigot's BaseComponent[]s and Adventure's Components, the CommandAPI.fail() method has now been deprecated in favour of the better named CommandAPI.failWithString() method:
throw CommandAPI.fail("Error message");
throw CommandAPI.failWithString("Error message"); List arguments
List arguments can now be implemented using an underlying text argument, instead of requiring it to be a greedy string. This allows you to use multiple lists in a command, in any position. As such, the ListArgumentBuilder.build() method has been deprecated and replaced with ListArgumentBuilder.buildGreedy() instead:
new ListArgumentBuilder<Material>("materials")
.withList(List.of(Material.values()))
.withMapper(material -> material.name().toLowerCase())
.build();
.buildGreedy(); 8.6.0 → 8.7.0
Sound arguments
This update introduces a backwards-incompatible change to the SoundArgument which was introduced in 8.6.0. SoundArguments no longer need a generic type parameter:
new SoundArgument<Sound>("sound");
new SoundArgument("sound"); NamespacedKey SoundArguments no longer need a SoundType parameter, instead the NamespacedKey constructor should be used:
new SoundArgument<NamespacedKey>("sound", SoundType.NAMESPACED_KEY);
new SoundArgument.NamespacedKey("sound"); Entity selector arguments
Entity selector arguments no longer need a generic type parameter or a EntitySelector parameter. Instead, the corresponding constructor should be used instead:
new EntitySelectorArgument<Player>("target", EntitySelector.ONE_PLAYER);
new EntitySelectorArgument<Collection<Player>>("target", EntitySelector.MANY_PLAYERS);
new EntitySelectorArgument<Entity>("target", EntitySelector.ONE_ENTITY);
new EntitySelectorArgument<Collection<Entity>>("target", EntitySelector.MANY_ENTITIES);
new EntitySelectorArgument.OnePlayer("target");
new EntitySelectorArgument.ManyPlayers("target");
new EntitySelectorArgument.OneEntity("target");
new EntitySelectorArgument.ManyEntities("target"); Scoreholder arguments
The ScoreHolderArgument no longer needs a generic type parameter or a ScoreHolderType parameter. Instead, the corresponding constructor should be used instead:
new ScoreHolderArgument<String>(nodeName, ScoreHolderType.SINGLE);
new ScoreHolderArgument<Collection<String>>(nodeName, ScoreHolderType.MULTIPLE);
new ScoreHolderArgument.Single(nodeName);
new ScoreHolderArgument.Multiple(nodeName); 8.8.0 → 9.0.0
CommandAPI 9.0.0 is arguably the biggest change in the CommandAPI's project structure and usage. This update was designed to allow the CommandAPI to be generalized for other platforms (e.g. Velocity, Fabric, Sponge), and as a result this update is incompatible with previous versions of the CommandAPI.
All deprecated methods from 8.8.x have been removed in this update. Please ensure that you use the relevant replacement methods (these are described in the JavaDocs for the various deprecated methods) before upgrading to 9.0.0.
Project dependencies
For Bukkit/Spigot/Paper plugins, the commandapi-core and commandapi-shade modules should no longer be used. Instead, use the new commandapi-bukkit-core and commandapi-bukkit-shade modules:
not shaded
<dependencies>
<dependency>
<groupId>dev.jorel</groupId>
<artifactId>commandapi-core</artifactId> // [!code --]
<artifactId>commandapi-bukkit-core</artifactId> // [!code ++]
<version>9.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>dependencies {
compileOnly "dev.jorel:commandapi-core:9.0.0"
compileOnly "dev.jorel:commandapi-bukkit-core:9.0.0"
}dependencies {
compileOnly("dev.jorel:commandapi-core:9.0.0")
compileOnly("dev.jorel:commandapi-bukkit-core:9.0.0")
}shaded
<dependencies>
<dependency>
<groupId>dev.jorel</groupId>
<artifactId>commandapi-shade</artifactId> // [!code --]
<artifactId>commandapi-bukkit-shade</artifactId> // [!code ++]
<version>9.0.0</version>
</dependency>
</dependencies>dependencies {
implementation "dev.jorel:commandapi-shade:9.0.0"
implementation "dev.jorel:commandapi-bukkit-shade:9.0.0"
}dependencies {
implementation("dev.jorel:commandapi-shade:9.0.0")
implementation("dev.jorel:commandapi-bukkit-shade:9.0.0")
}Additionally, when using the Kotlin DSL for Bukkit, instead of using commandapi-kotlin, use commandapi-bukkit-kotlin:
<dependencies>
<dependency>
<groupId>dev.jorel</groupId>
<artifactId>commandapi-kotlin</artifactId> // [!code --]
<artifactId>commandapi-bukkit-kotlin</artifactId> // [!code ++]
<version>9.0.0</version>
</dependency>
</dependencies>dependencies {
implementation "dev.jorel:commandapi-kotlin:9.0.0"
implementation "dev.jorel:commandapi-bukkit-kotlin:9.0.0"
}dependencies {
implementation("dev.jorel:commandapi-kotlin:9.0.0")
implementation("dev.jorel:commandapi-bukkit-kotlin:9.0.0")
}Loading and enabling the CommandAPI when shading
The CommandAPI.onLoad() method has changed in this update. Instead of using the CommandAPIConfig object, use the CommandAPIBukkitConfig and pass in the current plugin reference (this).
and CommandAPI.onEnable() method has also changed, and now no longer requires the plugin reference (this), as it is now included in CommandAPI.onLoad() instead.:
public void onLoad() {
CommandAPI.onLoad(new CommandAPIConfig());
CommandAPI.onLoad(new CommandAPIBukkitConfig(this));
}
public void onEnable() {
CommandAPI.onEnable(this);
CommandAPI.onEnable();
}Accessing arguments
Arguments for commands are no longer an Object[] and have now been replaced with a more powerful CommandArguments object. This object now lets you access arguments in a number of ways:
Using the args.get(int) method
If you're in a rush and just want to upgrade quickly, call the .get(int) method instead of accessing the arguments using the array access notation:
new CommandAPICommand("cmd")
.withArguments(new StringArgument("mystring"))
.withArguments(new PotionEffectArgument("mypotion"))
.withArguments(new LocationArgument("mylocation"))
.executes((sender, args) -> {
String stringArg = (String) args[0];
PotionEffectType potionArg = (PotionEffectType) args[1];
Location locationArg = (Location) args[2];
String stringArg = (String) args.get(0);
PotionEffectType potionArg = (PotionEffectType) args.get(1);
Location locationArg = (Location) args.get(2);
})
.register();Using the args.get(String) method (recommended)
The CommandAPI introduces a new args.get(String) method to access arguments using the argument node name. This method also makes your code much more compatible with optional arguments:
new CommandAPICommand("cmd")
.withArguments(new StringArgument("mystring"))
.withArguments(new PotionEffectArgument("mypotion"))
.withArguments(new LocationArgument("mylocation"))
.executes((sender, args) -> {
String stringArg = (String) args[0];
PotionEffectType potionArg = (PotionEffectType) args[1];
Location locationArg = (Location) args[2];
String stringArg = (String) args.get("mystring");
PotionEffectType potionArg = (PotionEffectType) args.get("mypotion");
Location locationArg = (Location) args.get("mylocation");
})
.register();CommandAPI helper methods
The CommandAPI.failWithBaseComponents(message) and CommandAPI.failWithAdventureComponent(message) methods have now been moved from CommandAPI to CommandAPIBukkit, because these methods are Bukkit/Spigot/Paper specific and don't exist for other platforms (e.g. Velocity, Fabric, Sponge):
CommandAPI.failWithBaseComponents(...);
CommandAPI.failWithAdventureComponent(...);
CommandAPIBukkit.failWithBaseComponents(...);
CommandAPIBukkit.failWithAdventureComponent(...); Removal of the EnvironmentArgument
The EnvironmentArgument has been removed in this update, as it was implemented incorrectly and is not fit for purpose. Instead, the CommandAPI has the more accurate WorldArgument.
Changes to the TeamArgument
The TeamArgument has been updated to no longer use a String as its return type. Instead, you can now just use a Team object directly:
new CommandAPICommand("team")
.withArguments(new TeamArgument("team"))
.executes((sender, args) -> {
String teamName = (String) args.get("team");
Team team = Bukkit.getScoreboardManager().getMainScoreboard().getTeam(teamName);
Team team = (Team) args.get("team");
})
.register();Changes to the ObjectiveArgument
The ObjectiveArgument has been updated to no longer use a String as its return type. Instead, you can now just use an Objective object directly:
new CommandAPICommand("objective")
.withArguments(new ObjectiveArgument("objective"))
.executes((sender, args) -> {
String objectiveName = (String) args.get("objective");
Objective objective = Bukkit.getScoreboardManager().getMainScoreboard().getObjective(objectiveName);
Objective objective = (Objective) args.get("objective");
})
.register();Changes to the ListArgumentBuilder
The ListArgumentBuilder no longer has withList(Function<CommandSender, Collection<T>> list) and instead uses SuggestionInfo to have withList(Function<SuggestionInfo<CommandSender>, Collection<T>> list).
This now allows you to access more information when generating a list dynamically instead of just the command sender. To access the original command sender, you can use the sender() method from SuggestionInfo:
ListArgument<?> arg = new ListArgumentBuilder<>("values", ", ")
.withList(sender -> List.of("cat", "wolf", "axolotl", sender.getName()))
.withList(info -> List.of("cat", "wolf", "axolotl", info.sender().getName()))
.withStringMapper()
.buildGreedy();Changes to the Rotation wrapper
The Rotation class now uses a constructor which has the yaw first, and the pitch second, instead of the pitch first and the yaw second.
new Rotation(20, 80); // Yaw = 80, Pitch = 20
new Rotation(20, 80); // Yaw = 20, Pitch = 80Changes to the ScoreboardSlot wrapper
The ScoreboardSlot wrapper is now an enum that has direct support for sidebar team colors, via the SIDEBAR_TEAM_### enum values, for example SIDEBAR_TEAM_RED;
ScoreboardSlot slot = ... ; // Some ScoreboardSlot
DisplaySlot displaySlot = slot.getDisplaySlot(); // Returns SIDEBAR, PLAYER_LIST or BELOW_NAME
DisplaySlot displaySlot = slot.getDisplaySlot(); // Returns SIDEBAR_TEAM_###, PLAYER_LIST or BELOW_NAME
// Extract the color if necessary
if (slot.hasTeamColor()) {
ChatColor color = slot.getTeamColor();
} 9.0.0 → 9.0.1
CustomArgumentException changes
For 9.0.1, the CustomArgumentException constructors have been deprecated and should no longer be used. Instead, use the CustomArgumentException static factory methods:
throw new CustomArgumentException(new MessageBuilder(...));
throw new CustomArgumentException("Error message");
throw CustomArgumentException.fromMessageBuilder(new MessageBuilder(...));
throw CustomArgumentException.fromString("Error message"); CommandArguments changes
For 9.0.1 the various CommandArguments#getOrDefault() and CommandArguments#getOrDefaultUnchecked() have been deprecated and should no longer be used. Instead, use the CommandArguments#getOptional() and CommandArguments#getOptionalUnchecked() methods:
new CommandAPICommand("mycommand")
.withOptionalArguments(new StringArgument("string"))
.executes((sender, args) -> {
String string = (String) args.getOrDefault("string", "Default Value");
String string = (String) args.getOptional("string").orElse("Default Value");
})
.register();
new CommandAPICommand("mycommand")
.withOptionalArguments(new StringArgument("string"))
.executes((sender, args) -> {
String string = args.getOrDefaultUnchecked("string", "Default Value");
String string = args.getOptionalUnchecked("string").orElse("Default Value");
})
.register();9.0.1 → 9.0.2
MultiLiteralArgument and LiteralArgument changes
In previous versions, the ability has been introduced to access arguments by their node names. However, while this was possible for every other argument, it wasn't possible for MultiLiteralArguments. This was now changed because the values from the MultiLiteralArgument are included in the CommandArguments of a command.
Therefore, the current constructor has been deprecated and the new one should be used:
withArguments(new MultiLiteralArgument("survival", "creative", "adventure", "spectator"))
withArguments(new MultiLiteralArgument("gamemodes", List.of("survival", "creative", "adventure", "spectator"))) Because it is possible to list LiteralArguments in the CommandArguments of a command, there was also an additional constructor added to the LiteralArgument class. The other one is not deprecated.
Now, the LiteralArgument class contains two possible constructors:
public LiteralArgument(String literal) // Recommended if the literal is not listed
public LiteralArgument(String nodeName, String literal)9.0.3 → 9.1.0
MultiLiteralArgument changes
All MultiLiteralArgument constructors have been deprecated in 9.1.0! Instead, the new MultiLiteralArgument constructor should be used:
withArguments(new MultiLiteralArgument("gamemodes", List.of("survival", "creative", "adventure", "spectator")))
withArguments(new MultiLiteralArgument("gamemodes", "survival", "creative", "adventure", "spectator")) CommandArguments changes
For 9.1.0 all deprecated methods are no longer deprecated. To learn about all the methods now available, refer to the CommandArguments page.
9.2.0 → 9.3.0
The BukkitTooltip.generateAdvenureComponents methods have now been deprecated in favour of the correctly named BukkitTooltip.generateAdventureComponents methods:
BukkitTooltip.generateAdvenureComponents()
BukkitTooltip.generateAdventureComponents() 9.7.0 → 10.0.0
Deprecated methods
For 10.0.0, all previously deprecated methods have been removed. Please make sure you use the replacement methods for the deprecated methods. The replacement methods should be described in the JavaDocs of deprecated methods.
Default namespace changes
The default namespace has been updated from minecraft to the plugin's name. If you are not shading, the default namespace is going to be commandapi. If you are shading, the default namespace is going to be your plugin's name.
Along with this change, the CommandAPIBukkitConfig#usePluginNamespace() has been deprecated since it is now default behaviour.
NativeProxyCommandSender changes
NativeProxyCommandSender used to be a class, but this version changed it to an interface. Any code compiled against an earlier version that references any method of NativeProxyCommandSender may throw the following IncompatibleClassChangeError when run using the new version of the API:
java.lang.IncompatibleClassChangeError: Found interface dev.jorel.commandapi.wrappers.NativeProxyCommandSender, but class was expectedIf this happens, the original code simply needs to be recompiled using the new API version.
Additionally, the constructor of NativeProxyCommandSender is no longer available. Instead, the static from method should be used:
new NativeProxyCommandSender(caller, callee, location, world);
NativeProxyCommandSender.from(caller, callee, location, world); 10.1.2 → 11.0.0
CommandAPI restructure
General module changes
For 11.0.0, the commandapi-bukkit-xxx modules have mostly been removed in favour of new platform specific modules that have been made for Paper or Spigot respectively:
commandapi-paper-xxxcommandapi-spigot-xxx
In order to update please replace your commandapi-bukkit-xxx dependency with either commandapi-paper-xxx or commandapi-spigot-xxx.
More dependency-related changes have taken place, here they all are listed:
- commandapi-bukkit-xxx
+ commandapi-paper-xxx
+ commandapi-spigot-xxx
- commandapi-core-kotlin
+ commandapi-kotlin-core
- commandapi-bukkit-kotlin
+ commandapi-kotlin-paper
+ commandapi-kotlin-spigot
- commandapi-bukkit-test-toolkit
+ commandapi-paper-test-toolkit
+ commandapi-spigot-test-toolkit
- commandapi-annotations
+ commandapi-paper-annotations
+ commandapi-spigot-annotationsDeveloper's Note:
The fact that Paper is a fork of Spigot does not mean that the Spigot modules work on Paper. Paper has, especially in newer versions, made changes to internal systems the CommandAPI uses. There are no guarantees that the Spigot modules will work on Paper in any kind or form.
Similarly, if you try to use the Paper modules on Spigot you will face registration issues and potential NoClassDefFoundErrors, depending on the server version you use. There again is no guarantee for any kind of compatibility.
Code changes
The CommandAPIBukkitConfig class has been converted into an abstract class and is no longer used to construct a config instance. Instead, use the new CommandAPIPaperConfig or CommandAPISpigotConfig classes, depending on the module you use. If you were using CommandAPIVersionHandler#usePlatformImplementation from the test toolkit, MockCommandAPIBukkit has been changed to MockCommandAPIPaper or MockCommandAPISpigot. See the new documentation for that method for details.
Further changes have been made to arguments that work with components. The classes AdventureChatArgument, AdventureChatComponentArgument and AdventureChatColorArgument have been removed. Instead, the ChatArgument, ChatComponentArgument and ChatColorArgument have been implemented platform specific and return different types on Paper and Spigot. On Paper, Adventure components are used while Spigot uses BungeeCord components.
More argument changes have been made:
- The
FloatRangeArgumenthas been renamed toDoubleRangeArgumentand now returns aDoubleRangeobject - The
PlayerArgumentandOfflinePlayerArgumenthave been replaced by thePlayerProfileArgumentwhich returns aList<PlayerProfile>. ThePlayerProfileclass changes depending on if you are on Paper or on Spigot. Use theEntitySelectorArgument.OnePlayerif you want aPlayerobject. - The
AsyncOfflinePlayerArgumenthas been replaced by theAsyncPlayerProfileArgument - The
ChatArgument,ChatComponentArgumentandChatColorArgumentdo no longer have anyAdventureprefixes and return different types depending on the platform. - The
ChatArgumentreturns aSignedMessageobject on Paper - The
BlockStateArgumentnow returns aBlockStateobject instead of aBlockDataobject
Config changes
The use-latest-nms-version and be-lenient-for-minor-versions config options have been removed and have been replaced by the new fallback-to-latest-nms config option. This config options combines the functionality of the former config options by first trying to load the correct version and if it can't find a matching implementation for the current version, it, if set to true, will load the latest implementation. On Paper it is set to true by default and on Spigot it is set to false.
Furthermore, any config options relating to reloading datapacks have been removed on Paper as they are not needed anymore.
You do not need to do anything to upgrading from 10.1.2 to 11.0.0