Updating WorldEdit to Minecraft 1.13

Posted on Fri 03 August 2018 in Minecraft

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.

User-Facing Changes

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.

Block Parsing

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).

Schematics

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.

Developer Changes

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.

Registries

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:

  • BlockType
  • ItemType
  • FluidType (In 1.13, fluid blocks were moved to their own system. This is currently unused, however)
  • EntityType
  • BlockCategory (Mirrors the vanilla Tag system)
  • ItemCategory
  • FluidCategory
  • GameMode
  • WeatherType

Another change is the migration of everything BukkitUtil to the BukkitAdapter class. Previously methods were spread across both files, causing confusion.

Block Material

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 BlockType#getMaterial() method.

Properties

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 BlockState.

NBT Data

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.

Selections

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:

  1. Get a WorldEdit player using BukkitAdapter.adapt(Player)
  2. Get the LocalSession for the player using WorldEdit.getInstance().getSessionManager().get(Player)
  3. Call 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 CuboidRegion or PolygonalRegion.

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

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.SPONGE_SCHEMATIC or 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.

If you have any issues with the API, please join the WorldEdit discord.

General API

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.

I've devoted countless hours to working on this project. If you'd like to support me, I have a Patreon and accept donations through PayPal. Thanks 😁