This article is the second in a series of articles, the first can be found here.
Updating WorldEdit to Minecraft 1.13 has been a long and arduous process. With weeks of hard work, and hundreds of thousands of lines of code changed, it's finally in a complete state.
It's not without significant changes, however, and this article will cover them.
Firstly, I'll go over the user-facing changes. These are minimised where possible, except in some places they had to happen. The areas these mostly cover are block parsing and schematics.
Due to the significant changes to blocks and IDs in 1.13, block parsing required an entire rewrite. The officially supported format for referencing blocks is to use the official Minecraft format. For example, grass blocks are used by typing
minecraft:grass_block, and a snowy grass block would be accessed by typing
minecraft:grass_block[snowy=true]. If the block is from the vanilla game,
minecraft: can be omitted. For example,
grass_block[snowy=true] will still place a snowy grass block.
To retain some aspect of legacy support, most legacy numeric IDs can still be referenced. Doing this is, however, NOT officially supported. Placing wool using their colour is also supported (Eg,
red places red wool).
The other major change required, schematics, also contains some legacy support code. As the MCEdit Schematic format is built to leverage numerical IDs, WorldEdit has moved to the Sponge Schematic Format. The Sponge Schematic Format is very future proof and will be the supported way of saving and loading schematics going forwards.
For the end user, the transition period should be relatively seamless. Previously created schematics will still load, however with some oddities such as corner stairs losing their corner pieces due to format restrictions. Any newly created schematic will be created using the Sponge format. Any schematic generated on 1.13 will not be usable on prior Minecraft versions.
Everything else should still function the same. If you find an issue, please report it on our issue tracker.
This section is much larger and much less backwards compatible than the user-facing changes. Due to the large number of changes in 1.13, and the massive size and technical debt of the WorldEdit codebase, it was decided to remove all deprecated or quasi-deprecated code from the plugin. Any plugin using deprecated code will no longer function. However, any plugin accessing WorldEdit would have most likely had to be updated anyway.
The most obvious change is the removal of the
BlockID class. The class is replaced with a registry system, in
BlockTypes. The equivalent class has been created for
ItemID. To get a BlockType from a String ID, the
BlockType.get(String) method has been provided, the equivalent exists for all of the registries. The following registries currently exist in WorldEdit 7:
- FluidType (In 1.13, fluid blocks were moved to their own system. This is currently unused, however)
- BlockCategory (Mirrors the vanilla Tag system)
Another change is the migration of everything
BukkitUtil to the
BukkitAdapter class. Previously methods were spread across both files, causing confusion.
In WorldEdit 6 and earlier, there was a file called
BlockType, sharing the name of the new
BlockType class. This class contained a list of blocks, as well as some utility functions regarding blocks. These utility functions have been moved to
Blocks, as well as
BlockMaterial. Materials can be accessed via the
Also relating to blocks, in 1.13 properties have replaced the metadata system. WorldEdit has also been updated to access these. In prior versions, there was a class called
BaseBlock. Whilst this class still exists, it has a very different purpose now. Most usages of
BaseBlock should now be
BlockState, which is both immutable and cached. An instance of
BlockState should NEVER be made by a developer using the API. This system has been made to keep memory usage down and performance high, and creating new instances would break this. Properties can be accessed by name on
BlockType, and values can be applied and retrieved in
When dealing with NBT Data,
BaseBlock should be used. Instances are created by passing both a
BlockState and a
CompoundTag to the constructor. When getting blocks from the world, use
getBlock() to get the block itself, and
getFullBlock() to get the block with NBT data.
Another major change is the Selection API, however this only impacts Bukkit plugins using the 'native layer'. In an effort to make WorldEdit more standardised across platforms as well as clean up the codebase, the native layer has been removed. This layer was first talked about by sk89q back in 2013 in his blog.
To get a selection using WorldEdit 7, you need to do the following:
- Get a WorldEdit player using
- Get the
LocalSessionfor the player using
LocalSession#getSelection(World)using the WorldEdit Player's World.
This returns a
Region object. From here, you can call many functions on the region, as well as iterate over it to get all of the containing
BlockVectors. You can also check and cast into different shapes, such as
If a selection hasn't been made when this code is called,
getSelection(World) will throw a
IncompleteRegionException. This should be caught and shown to the user.
Schematics have also been changed somewhat significantly. Other plugins can now register schematic formats, and the Sponge Schematic Format was implemented. It is now the recommended format to use, and usage of the MCEdit format is deprecated for all non-legacy import purposes.
Schematic formats should be accessed using
BuiltInClipboardFormat.MCEDIT_SCHEMATIC to access specific formats, by using
ClipboardFormats.findByAlias(String) to find formats by name, or by using
ClipboardFormats.findByFile(File) to identify the format of a schematic file.
A more in-depth tutorial on this API change is available here.
If you have any issues with the API, please join the WorldEdit discord.
WorldEdit also now includes a much larger general Minecraft API for writing cross-platform plugins. This can be used to assist in making your plugin work across Sponge, Spigot, Forge, etc. This has been utilised in WorldGuard to make the plugin much more abstract, however, it still only supports Bukkit at this stage.
Part 3, focusing on the changes to WorldGuard, can be found here.