Resource WorldEdit Utilities - Modify/paste schematics

Discussion in 'Spigot Plugin Development' started by Kage0x3B, Sep 24, 2017.

  1. I recently had a problem with the provided WorldEdit API which took quite some time to solve and I saw some other posts about the same problems so I decided to turn the utility I wrote back then into a resource here.

    I wrote a set of classes wrapping the WorldEdit "API" to work with schematics all in your code, loading, saving and modifying them.

    Using the utility
    The utility is a part of a huge utility plugin having a lot of classes for inventory guis, nms helpers etc, called KageCore, but I also created a gist with just the WorldEdit utilities, which you can get right here.
    Just paste all the classes into your project, fix the packages, imports and add a depend or soft-depend on WorldEdit to your plugin.yml. (If WorldEdit is not loaded, the classes will do nothing and all methods immediately return).

    Documentation
    Loading schematics is as simple as:
    PHP:
    Schematic mySchematic = SchematicLoader.load(bukkitWorld, schematicFile);
    bukkitWorld should be the world you want to paste your schematic into or just a random world because WorldEdit somehow needs one to load a schematic. Usually obtained with pasteLocation.getWorld();

    schematicFile
    is the File pointing to your schematic. Can also be replaced by a string which then searches for a file with the given name in the WorldEdit schematics directory.

    When you have a schematic, either by loading it from a file or loading an area in a world into a schematic, you can paste it like this:
    PHP:
    mySchematic.paste(pasteLocation, ignoreAirBlocks);
    pasteLocation is the Bukkit Location where the schematic should be pasted to.

    ignoreAirBlocks
    is a boolean whether WorldEdit should replace existing blocks by air blocks in a schematic. Not always required and this should be set to false which should make pasting the schematic faster.

    You can also create Schematic objects by copying an area in the world, similiar to the //copy command.
    PHP:
    BoundingBox boundingBox = new BoundingBox(minLocation, maxLocation);
    Schematic mySchematic = SchematicLoader.loadArea(bukkitWorld, boundingBox, origin);
    First, you need to create an instance of the BoundingBox class, also contained in this utility, by giving it the min and max Location of the cube you want to copy into a schematic (Watch out: they don't actually have to be the lower and the upper point, the BoundingBox class takes care of that so you can just pass in two locations, set, for example, by the player. Also, you can also pass in a CuboidSelection, like the players current selection, obtained directly from WorldEdit.)

    The parameters for the loadArea function are:

    bukkitWorld
    , the world in which the area you want to copy is

    boundingBox
    is the earlier created BoundingBox

    origin
    is a Bukkit Vector for the origin of the created schematic, when using //copy WorldEdit uses the players relative position to the schematic. Can often be set to just 0,0,0.

    From this, you get a schematic which can be pasted at another location or saved to a file. I, for example, use this in a command which automatically saves all structures from a world to different schematic files which are then later used by a generator. Saves a lot of time because there are houndreds of different structures where it does all the copying with the right origin, saving etc for me.

    When you have loaded an area in the world to a schematic for example, you can use this to save it to a schematic file:
    PHP:
    SchematicSaver.save(mySchematic, schematicFile);
    mySchematic is the Schematic instance created by loading it from an area in the world for example

    schematicFile
    is the File you want the schematic to be saved to

    I included this in the utility because in my use case, I had to rotate room schematics according to a room layout file. So instead of saving each rotation as a new schematic file, you can easily rotate the Schematic instances with code:
    PHP:
    mySchematic.rotate(x, y, z);
    x, y and z are the amounts you want to rotate the schematic on the x/y/z axis. These rotation amounts should be in degrees. You can also just use rotateX(rotationAmount) and rotateY/rotateZ, they'll do exactly the same thing.

    Watch out: Rotating the schematic via this method will only apply a transform to the schematic. When pasted into the world, the schematic will be rotated as expected but it will not change the actual blocks wrapped by the Schematic object. To do this, you can use bakeTransform(), which will rotate the actual blocks.
    Another thing to remember: WorldEdit has some problems with pasting schematics, especially when the schematic is rotated and when it contains special (not full) blocks like torches or similiar blocks which sometimes fall off when pasted into the world.
    I prevented this, by, after rotating the schematic, baking the transform and then modifying the internal blocks to remove all torches and affected blocks, saving them to another place and then pasting them in by myself after the schematic. If you want a further explanation on how I solved torches etc falling off, please contact me.

    Look through the spoilers for information on how to use these utilities. This utility should work (at least) on Minecraft 1.11 and 1.12 servers, I haven't tested it on other versions yet and only with the normal WorldEdit. It may behave very strange or not work at all with plugins modifying WorldEdit like FastAsyncWorldEdit.


    I hope this contribution helps some of you. Yes, I haven't added any Javadocs but I hope the documentation up there is enough to work with this and if not, please ask any question here in this thread after carefully reading the documentation and the notes there.
     
    • Useful Useful x 3