Edit Sessions¶
An EditSession
handles the configuration for getting and placing blocks, entities, and biomes. It sets up the
chain of extents to place blocks properly. It also handles turning on and off reorder mode, fast mode, and buffering.
Every operation targeting a world will use an EditSession
at some point to ensure that block placement is done properly and quickly.
The easiest way to make a simple EditSession
is using the helper methods on the WorldEdit
class,
newEditSession(World)
or newEditSession(Actor & Locatable)
. These are shorthands for using the full builder,
available from newEditSessionBuilder()
. The builder has all of the options that used to be available from the
EditSessionFactory
’s various methods, but in a easier-to-read form. If you use the builder, don’t forget to call
build()
at the end to get an actual EditSession
.
// Getting an edit session for a WorldEdit World
WorldEdit.getInstance().newEditSession(world)
// Getting an edit session for a WorldEdit World with a maximum block count
WorldEdit.getInstance().newEditSessionBuilder().world(world).maxBlocks(1000).build()
Edit sessions must be closed once all operations are complete, to ensure that block queues are flushed. They are not re-usable for edits after being closed, and a new one must be created for subsequent operations.
A clean way to close a EditSession
is to use the try-with-resources
statement:
try (EditSession editSession = WorldEdit.getInstance().newEditSession(world)) {
// use the edit session here ...
} // it is automatically closed/flushed when the code exits the block
For more information, see The try-with-resources Statement page from the Java Tutorials.
Once an edit session has been used for editing and is closed, it stores all the changes performed. If you want to undo these changes at a later time, you can hold a reference to the edit session. Then, to undo the changes, make a new EditSession as detailed above, and call editSession.undo(newEditSession)
.
The Extent Stack¶
The “extent stack” is a term used to describe the many extents that are composed to create an EditSession
.
At the very bottom of the stack is the World
that the changes will be committed to. That extent is wrapped in
other extents that all apply various fixes for oddities with Minecraft, and then the first event is posted with a stage
of Stage.BEFORE_CHANGE
. The resulting extent is used for EditSession.rawSetBlock()
. Then, that extent
is wrapped in some reordering / batching extents, and another event is posted with a stage of Stage.BEFORE_REORDER
.
The resulting extent is used for EditSession.smartSetBlock()
. Then, that extent is wrapped in change set, masking,
and limiting extents, and a final event is posted with a stage of Stage.BEFORE_HISTORY
. The resulting extent is
used for the normal EditSession.setBlock()
.
Edit Session Event¶
The EditSessionEvent
is the way to hook into WorldEdit’s changes in an efficient manner. It is fired as a part of
EditSession
creation, and allows hooking into the extent stack at various steps as described above. You can
subscribe to this event by registering with WorldEdit’s event bus:
WorldEdit.getInstance().getEventBus().register(new Object() /* [1] */ {
// Make sure you import WorldEdit's @Subscribe!
@Subscribe
public void onEditSessionEvent(EditSessionEvent event) {
if (event.getStage() == /* the stage you're interested in */) {
event.setExtent(new MyCustomExtent(event.getExtent()));
}
}
});
// [1]: You don't need to use an anonymous class, you can also store your method in its own separate class
// and construct it here instead.
When creating your own extent class, consider extending AbstractDelegateExtent
, which allows you to only override
the methods you’re interested in. Don’t forget to call the appropriate super
method to actually perform the changes!