diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java index dd1ab796..cb01fd96 100644 --- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java @@ -191,7 +191,9 @@ public class FaweBukkit implements IFawe, Listener { } catch (Throwable ignore) {} try { return plugin.getQueue(world); - } catch (Throwable ignore) {} + } catch (Throwable ignore) { + ignore.printStackTrace(); + } // Disable incompatible settings Settings.PARALLEL_THREADS = 1; // BukkitAPI placer is too slow to parallel thread at the chunk level Settings.COMBINE_HISTORY_STAGE = false; // Performing a chunk copy (if possible) wouldn't be faster using the BukkitAPI diff --git a/core/src/main/java/com/boydti/fawe/Fawe.java b/core/src/main/java/com/boydti/fawe/Fawe.java index 26fec2ac..b987c755 100644 --- a/core/src/main/java/com/boydti/fawe/Fawe.java +++ b/core/src/main/java/com/boydti/fawe/Fawe.java @@ -30,6 +30,7 @@ import com.sk89q.worldedit.command.SchematicCommands; import com.sk89q.worldedit.command.ScriptingCommands; import com.sk89q.worldedit.command.composition.SelectionCommand; import com.sk89q.worldedit.command.tool.brush.GravityBrush; +import com.sk89q.worldedit.event.extent.EditSessionEvent; import com.sk89q.worldedit.extension.platform.CommandManager; import com.sk89q.worldedit.extension.platform.PlatformManager; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; @@ -244,6 +245,7 @@ public class Fawe { */ try { EditSession.inject(); // Custom block placer + optimizations + EditSessionEvent.inject(); // Add EditSession to event LocalSession.inject(); // Add remember order / queue flushing // Commands BrushCommands.inject(); // Translations + heightmap diff --git a/core/src/main/java/com/boydti/fawe/object/HistoryExtent.java b/core/src/main/java/com/boydti/fawe/object/HistoryExtent.java index afee1fc5..b6847010 100644 --- a/core/src/main/java/com/boydti/fawe/object/HistoryExtent.java +++ b/core/src/main/java/com/boydti/fawe/object/HistoryExtent.java @@ -26,7 +26,7 @@ import static com.google.common.base.Preconditions.checkNotNull; */ public class HistoryExtent extends AbstractDelegateExtent { - private final com.boydti.fawe.object.changeset.FaweChangeSet changeSet; + private com.boydti.fawe.object.changeset.FaweChangeSet changeSet; private final FaweQueue queue; private final FaweLimit limit; private final EditSession session; @@ -46,6 +46,10 @@ public class HistoryExtent extends AbstractDelegateExtent { this.session = session; } + public void setChangeSet(FaweChangeSet fcs) { + this.changeSet = fcs; + } + @Override public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException { int x = location.getBlockX(); diff --git a/core/src/main/java/com/boydti/fawe/util/MathMan.java b/core/src/main/java/com/boydti/fawe/util/MathMan.java index 494c47aa..72b60541 100644 --- a/core/src/main/java/com/boydti/fawe/util/MathMan.java +++ b/core/src/main/java/com/boydti/fawe/util/MathMan.java @@ -43,6 +43,18 @@ public class MathMan { 253, 254, 254, 255 }; + public static long pairInt(int x, int y) { + return (((long)x) << 32) | (y & 0xffffffffL); + } + + public static int unpairIntX(long pair) { + return (int)(pair >> 32); + } + + public static int unpairIntY(long pair) { + return (int)pair; + } + public static byte pair16(byte x, byte y) { return (byte) (x + (y << 4)); } diff --git a/core/src/main/java/com/sk89q/worldedit/EditSession.java b/core/src/main/java/com/sk89q/worldedit/EditSession.java index e0aba620..1ed33661 100644 --- a/core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -171,6 +171,7 @@ public class EditSession implements Extent { private MaskingExtent maskingExtent; private FaweRegionExtent regionExtent; private Extent primaryExtent; + private HistoryExtent history; private Extent bypassReorderHistory; private Extent bypassHistory; private Extent bypassNone; @@ -221,10 +222,11 @@ public class EditSession implements Extent { * @param blockBag an optional {@link BlockBag} to use, otherwise null * @param event the event to call with the extent */ - public EditSession(final EventBus eventBus, World world, final int maxBlocks, @Nullable final BlockBag blockBag, final EditSessionEvent event) { + public EditSession(final EventBus eventBus, World world, final int maxBlocks, @Nullable final BlockBag blockBag, EditSessionEvent event) { checkNotNull(eventBus); checkArgument(maxBlocks >= -1, "maxBlocks >= -1 required"); checkNotNull(event); + event.setEditSession(this); this.actor = event.getActor(); // TODO block bag @@ -261,7 +263,7 @@ public class EditSession implements Extent { if (Settings.COMBINE_HISTORY_STAGE) { changeSet.addChangeTask(queue); } else { - extent = new HistoryExtent(this, limit, extent, changeSet, queue); + extent = history = new HistoryExtent(this, limit, extent, changeSet, queue); } } extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_HISTORY); @@ -348,7 +350,7 @@ public class EditSession implements Extent { if (Settings.COMBINE_HISTORY_STAGE) { changeSet.addChangeTask(queue); } else { - extent = new HistoryExtent(this, limit, extent, changeSet, queue); + extent = history = new HistoryExtent(this, limit, extent, changeSet, queue); } // Region restrictions if mask is not null if (mask != null) { @@ -476,6 +478,9 @@ public class EditSession implements Extent { } public void setChangeSet(FaweChangeSet set) { + if (history != null) { + history.setChangeSet(set); + } changes++; this.changeSet = set; } diff --git a/core/src/main/java/com/sk89q/worldedit/event/extent/EditSessionEvent.java b/core/src/main/java/com/sk89q/worldedit/event/extent/EditSessionEvent.java new file mode 100644 index 00000000..c0400e8d --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/event/extent/EditSessionEvent.java @@ -0,0 +1,166 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.event.extent; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.event.Event; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.world.World; + +import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.EditSession.Stage; + +/** + * Raised (several times) when a new {@link EditSession} is being instantiated. + * + *

Block loggers, as well as block set interceptors, can use this event to wrap + * the given {@link Extent} with their own, which would allow them to intercept + * all changes made to the world. For example, the code below would wrap the + * existing extent with a custom one, and the custom extent would receive + * all method calls before the extent fetched from + * {@link #getExtent()} would.

+ * + *
+ * event.setExtent(new MyExtent(event.getExtent())
+ * 
+ * + *

This event is fired several times during the creation of a single + * {@link EditSession}, but {@link #getStage()} will differ each time. + * The stage determines at which point {@link Extent}s added to this event + * will be called. For example, if you inject an extent when the stage + * is set to {@link Stage#BEFORE_HISTORY}, then you can drop (or log) changes + * before the change has reached the history, reordering, and actual change + * extents, but that means that any changes made with + * {@link EditSession#rawSetBlock(Vector, BaseBlock)} will skip your + * custom {@link Extent} because that method bypasses history (and reorder). + * It is thus recommended that loggers intercept at {@link Stage#BEFORE_CHANGE} + * and block interceptors intercept at BOTH {@link Stage#BEFORE_CHANGE} and + * {@link Stage#BEFORE_HISTORY}.

+ */ +public class EditSessionEvent extends Event { + + private final World world; + private final Actor actor; + private final int maxBlocks; + private final Stage stage; + private Extent extent; + private EditSession session; + + /** + * Create a new event. + * + * @param world the world + * @param actor the actor, or null if there is no actor specified + * @param maxBlocks the maximum number of block changes + * @param stage the stage + */ + public EditSessionEvent(@Nullable World world, Actor actor, int maxBlocks, Stage stage) { + this.world = world; + this.actor = actor; + this.maxBlocks = maxBlocks; + this.stage = stage; + } + + public void setEditSession(EditSession session) { + this.session = session; + } + + public EditSession getEditSession() { + return session; + } + + /** + * Get the actor for this event. + * + * @return the actor, which may be null if unavailable + */ + public @Nullable Actor getActor() { + return actor; + } + + /** + * Get the world. + * + * @return the world + */ + public @Nullable World getWorld() { + return world; + } + + /** + * Get the maximum number of blocks that may be set. + * + * @return the maximum number of blocks, which is -1 if unlimited + */ + public int getMaxBlocks() { + return maxBlocks; + } + + /** + * Get the {@link Extent} that can be wrapped. + * + * @return the extent + */ + public Extent getExtent() { + return extent; + } + + /** + * Get the stage that is being wrapped. + * + * @return the stage + */ + public Stage getStage() { + return stage; + } + + /** + * Set a new extent that should be used. It should wrap the extent + * returned from {@link #getExtent()}. + * + * @param extent the extent + */ + public void setExtent(Extent extent) { + checkNotNull(extent); + this.extent = extent; + } + + /** + * Create a clone of this event with the given stage. + * + * @param stage the stage + * @return a new event + */ + public EditSessionEvent clone(Stage stage) { + EditSessionEvent clone = new EditSessionEvent(world, actor, maxBlocks, stage); + clone.setEditSession(session); + return clone; + } + + public static Class inject() { + return EditSessionEvent.class; + } + +}