diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/ABukkitMain.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/ABukkitMain.java index a8db7ef1..5b31f638 100644 --- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/ABukkitMain.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/ABukkitMain.java @@ -19,7 +19,6 @@ public abstract class ABukkitMain extends JavaPlugin { @Override public void onEnable() { FaweBukkit imp = new FaweBukkit(this); - try { SnipeData.inject(); Sniper.inject(); 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 4ba6db2d..ef1ba078 100644 --- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java @@ -62,7 +62,6 @@ public class FaweBukkit implements IFawe, Listener { public FaweBukkit(ABukkitMain plugin) { this.plugin = plugin; try { - Bukkit.getPluginManager().registerEvents(this, plugin); Fawe.set(this); if (Bukkit.getVersion().contains("git-Spigot") && FaweAPI.checkVersion(this.getVersion(), 1, 7, 10)) { debug("====== USE PAPER SPIGOT ======"); @@ -79,6 +78,7 @@ public class FaweBukkit implements IFawe, Listener { TaskManager.IMP.task(new Runnable() { @Override public void run() { + Bukkit.getPluginManager().registerEvents(FaweBukkit.this, FaweBukkit.this.plugin); new ChunkListener(); } }); diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/logging/LoggingExtent.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/logging/LoggingExtent.java index c773f3f4..6f69922f 100644 --- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/logging/LoggingExtent.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/logging/LoggingExtent.java @@ -100,7 +100,6 @@ public class LoggingExtent extends AbstractDelegateExtent { case 11: case 73: case 74: - case 78: case 79: case 80: case 81: diff --git a/core/src/main/java/com/boydti/fawe/Fawe.java b/core/src/main/java/com/boydti/fawe/Fawe.java index 75107d04..cae5be4b 100644 --- a/core/src/main/java/com/boydti/fawe/Fawe.java +++ b/core/src/main/java/com/boydti/fawe/Fawe.java @@ -38,6 +38,7 @@ import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.SchematicReader; import com.sk89q.worldedit.extent.clipboard.io.SchematicWriter; import com.sk89q.worldedit.extent.transform.BlockTransformExtent; +import com.sk89q.worldedit.function.entity.ExtentEntityCopy; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.visitor.BreadthFirstSearch; import com.sk89q.worldedit.function.visitor.DownwardVisitor; @@ -275,6 +276,7 @@ public class Fawe { NonRisingVisitor.inject(); // Optimizations RecursiveVisitor.inject(); // Optimizations RegionVisitor.inject(); // Translations + Optimizations + ExtentEntityCopy.inject(); // Async entity create fix // Entity create/remove EntityCreate.inject(); // Optimizations EntityRemove.inject(); // Optimizations diff --git a/core/src/main/java/com/boydti/fawe/FaweCache.java b/core/src/main/java/com/boydti/fawe/FaweCache.java index 4c3b1ed5..e17accde 100644 --- a/core/src/main/java/com/boydti/fawe/FaweCache.java +++ b/core/src/main/java/com/boydti/fawe/FaweCache.java @@ -201,7 +201,6 @@ public class FaweCache { case 11: case 73: case 74: - case 78: case 79: case 80: case 81: diff --git a/core/src/main/java/com/boydti/fawe/config/Settings.java b/core/src/main/java/com/boydti/fawe/config/Settings.java index fd790abe..9c985733 100644 --- a/core/src/main/java/com/boydti/fawe/config/Settings.java +++ b/core/src/main/java/com/boydti/fawe/config/Settings.java @@ -4,7 +4,6 @@ import com.boydti.fawe.configuration.file.YamlConfiguration; import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.util.MainUtil; -import com.sk89q.worldedit.LocalSession; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -170,9 +169,7 @@ public class Settings { WEB_URL = config.getString("web.url"); - if (STORE_HISTORY_ON_DISK = config.getBoolean("history.use-disk")) { - LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE; - } + STORE_HISTORY_ON_DISK = config.getBoolean("history.use-disk"); try { config.save(file); diff --git a/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java b/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java index 431b28fa..22a7d7be 100644 --- a/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java +++ b/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java @@ -234,7 +234,6 @@ public abstract class CharFaweChunk extends FaweChunk { case 7: case 9: case 73: - case 78: case 79: case 80: case 81: diff --git a/core/src/main/java/com/boydti/fawe/object/RegionWrapper.java b/core/src/main/java/com/boydti/fawe/object/RegionWrapper.java index 0e90b7f3..164c8010 100644 --- a/core/src/main/java/com/boydti/fawe/object/RegionWrapper.java +++ b/core/src/main/java/com/boydti/fawe/object/RegionWrapper.java @@ -26,6 +26,10 @@ public class RegionWrapper { this.maxZ = Math.max(pos1.getBlockZ(), pos2.getBlockZ()); } + public RegionWrapper[] toArray() { + return new RegionWrapper[]{this}; + } + public boolean isIn(final int x, final int z) { return ((x >= this.minX) && (x <= this.maxX) && (z >= this.minZ) && (z <= this.maxZ)); } diff --git a/core/src/main/java/com/boydti/fawe/object/changeset/FaweChangeSet.java b/core/src/main/java/com/boydti/fawe/object/changeset/FaweChangeSet.java index 884a5796..b1d4bc68 100644 --- a/core/src/main/java/com/boydti/fawe/object/changeset/FaweChangeSet.java +++ b/core/src/main/java/com/boydti/fawe/object/changeset/FaweChangeSet.java @@ -6,6 +6,7 @@ import com.boydti.fawe.object.BytePair; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FaweQueue; +import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.RunnableVal2; import com.boydti.fawe.util.EditSessionBuilder; import com.boydti.fawe.util.MainUtil; @@ -70,7 +71,7 @@ public abstract class FaweChangeSet implements ChangeSet { public abstract Iterator getIterator(boolean redo); public EditSession toEditSession(FawePlayer player) { - return new EditSessionBuilder(world).player(player).autoQueue(false).fastmode(true).checkMemory(false).changeSet(this).build(); + return new EditSessionBuilder(world).player(player).autoQueue(false).fastmode(true).checkMemory(false).changeSet(this).allowedRegions(RegionWrapper.GLOBAL().toArray()).build(); } public void add(EntityCreate change) { diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java b/core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java index f7badf69..61a1d0b3 100644 --- a/core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java +++ b/core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java @@ -247,7 +247,6 @@ public class MemoryOptimizedClipboard extends FaweClipboard { case 11: case 73: case 74: - case 78: case 79: case 80: case 81: diff --git a/core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java b/core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java index 2dee8951..dc4f9685 100644 --- a/core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java +++ b/core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java @@ -101,6 +101,11 @@ public class EditSessionBuilder { return this; } + public EditSessionBuilder allowedRegions(@Nullable RegionWrapper allowedRegion) { + this.allowedRegions = allowedRegion == null ? null : allowedRegion.toArray(); + return this; + } + public EditSessionBuilder allowedRegionsEverywhere() { return allowedRegions(new RegionWrapper[]{RegionWrapper.GLOBAL()}); } diff --git a/core/src/main/java/com/boydti/fawe/util/SetQueue.java b/core/src/main/java/com/boydti/fawe/util/SetQueue.java index 7f7a6447..06c5751d 100644 --- a/core/src/main/java/com/boydti/fawe/util/SetQueue.java +++ b/core/src/main/java/com/boydti/fawe/util/SetQueue.java @@ -90,7 +90,8 @@ public class SetQueue { throw new IllegalStateException("This shouldn't be possible for placement to occur off the main thread"); } // Disable the async catcher as it can't discern async vs parallel - SET_TASK.value2.startSet(true); + boolean parallel = Settings.PARALLEL_THREADS > 1; + SET_TASK.value2.startSet(parallel); try { if (Settings.PARALLEL_THREADS <= 1) { SET_TASK.run(); @@ -114,7 +115,7 @@ public class SetQueue { MainUtil.handleError(e); } finally { // Enable it again (note that we are still on the main thread) - SET_TASK.value2.endSet(true); + SET_TASK.value2.endSet(parallel); } } }, 1); @@ -187,7 +188,7 @@ public class SetQueue { throw new IllegalStateException("Must be flushed on the main thread!"); } // Disable the async catcher as it can't discern async vs parallel - boolean parallel = Settings.PARALLEL_THREADS <= 1; + boolean parallel = Settings.PARALLEL_THREADS > 1; SET_TASK.value2.startSet(parallel); try { if (parallel) { diff --git a/core/src/main/java/com/boydti/fawe/wrappers/WorldWrapper.java b/core/src/main/java/com/boydti/fawe/wrappers/WorldWrapper.java index 54c25952..2d4100a4 100644 --- a/core/src/main/java/com/boydti/fawe/wrappers/WorldWrapper.java +++ b/core/src/main/java/com/boydti/fawe/wrappers/WorldWrapper.java @@ -240,26 +240,26 @@ public class WorldWrapper extends AbstractWorld { queue.setChangeTask(null); final FaweChangeSet fcs = (FaweChangeSet) session.getChangeSet(); final FaweRegionExtent fe = session.getRegionExtent(); - session.setChangeSet(fcs); + session.setSize(1); final boolean cuboid = region instanceof CuboidRegion; Set chunks = region.getChunks(); for (Vector2D chunk : chunks) { + final int cx = chunk.getBlockX(); + final int cz = chunk.getBlockZ(); + final int bx = cx << 4; + final int bz = cz << 4; + Vector cmin = new Vector(bx, 0, bz); + Vector cmax = cmin.add(15, getMaxY(), 15); + final boolean containsBot1 = (fe == null || fe.contains(cmin.getBlockX(), cmin.getBlockY(), cmin.getBlockZ())); + final boolean containsBot2 = region.contains(cmin); + final boolean containsTop1 = (fe == null || fe.contains(cmax.getBlockX(), cmax.getBlockY(), cmax.getBlockZ())); + final boolean containsTop2 = region.contains(cmax); + if ((containsBot2 && containsTop2 && !containsBot1 && !containsTop1)) { + continue; + } RunnableVal r = new RunnableVal() { @Override public void run(Vector2D chunk) { - int cx = chunk.getBlockX(); - int cz = chunk.getBlockZ(); - int bx = cx << 4; - int bz = cz << 4; - Vector cmin = new Vector(bx, 0, bz); - Vector cmax = cmin.add(15, getMaxY(), 15); - boolean containsBot1 = (fe == null || fe.contains(cmin.getBlockX(), cmin.getBlockY(), cmin.getBlockZ())); - boolean containsBot2 = region.contains(cmin); - boolean containsTop1 = (fe == null || fe.contains(cmax.getBlockX(), cmax.getBlockY(), cmax.getBlockZ())); - boolean containsTop2 = region.contains(cmax); - if ((containsBot2 && containsTop2 && !containsBot1 && !containsTop1)) { - return; - } if (cuboid && containsBot1 && containsBot2 && containsTop1 && containsTop2) { if (fcs != null) { for (int x = 0; x < 16; x++) { @@ -339,7 +339,7 @@ public class WorldWrapper extends AbstractWorld { @Override public void run(Boolean ignore) { try { - this.value = parent.generateTree(editSession, position); + this.value = parent.generateTree(type, editSession, position); } catch (MaxChangedBlocksException e) { MainUtil.handleError(e); } diff --git a/core/src/main/java/com/sk89q/worldedit/CuboidClipboard.java b/core/src/main/java/com/sk89q/worldedit/CuboidClipboard.java index 5d1ea51f..cdcde4e7 100644 --- a/core/src/main/java/com/sk89q/worldedit/CuboidClipboard.java +++ b/core/src/main/java/com/sk89q/worldedit/CuboidClipboard.java @@ -299,7 +299,6 @@ public class CuboidClipboard { case 11: case 73: case 74: - case 78: case 79: case 80: case 81: diff --git a/core/src/main/java/com/sk89q/worldedit/EditSession.java b/core/src/main/java/com/sk89q/worldedit/EditSession.java index b0ed4b4f..20528b59 100644 --- a/core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -924,7 +924,9 @@ public class EditSession implements Extent { @Override @Nullable public Entity createEntity(final com.sk89q.worldedit.util.Location location, final BaseEntity entity) { - return this.bypassNone.createEntity(location, entity); + Entity result = this.bypassNone.createEntity(location, entity); + System.out.println("RESULT: " + result); + return result; } /** @@ -988,6 +990,10 @@ public class EditSession implements Extent { return this.getBlockChangeCount(); } + public void setSize(int size) { + this.changes = size; + } + @Override public Vector getMinimumPoint() { return this.getWorld().getMinimumPoint(); diff --git a/core/src/main/java/com/sk89q/worldedit/LocalSession.java b/core/src/main/java/com/sk89q/worldedit/LocalSession.java index 6a4f3cb0..897cbdbd 100644 --- a/core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -204,6 +204,8 @@ public class LocalSession { editSession.flushQueue(); if (Settings.STORE_HISTORY_ON_DISK) { MAX_HISTORY_SIZE = Integer.MAX_VALUE; + } else if (MAX_HISTORY_SIZE == Integer.MAX_VALUE) { + MAX_HISTORY_SIZE = 15; } // Don't store anything if no changes were made if (editSession.size() == 0 || editSession.hasFastMode()) { diff --git a/core/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java b/core/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java new file mode 100644 index 00000000..cc8e1828 --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java @@ -0,0 +1,170 @@ +/* + * 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.function.entity; + +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.CompoundTagBuilder; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.function.EntityFunction; +import com.sk89q.worldedit.function.operation.ForwardExtentCopy; +import com.sk89q.worldedit.internal.helper.MCDirections; +import com.sk89q.worldedit.math.transform.Transform; +import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.Direction.Flag; +import com.sk89q.worldedit.util.Location; + + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Copies entities provided to the function to the provided destination + * {@code Extent}. + */ +public class ExtentEntityCopy implements EntityFunction { + + private final Extent destination; + private final Vector from; + private final Vector to; + private final Transform transform; + private boolean removing; + + /** + * Create a new instance. + * + * @param from the from position + * @param destination the destination {@code Extent} + * @param to the destination position + * @param transform the transformation to apply to both position and orientation + */ + public ExtentEntityCopy(Vector from, Extent destination, Vector to, Transform transform) { + checkNotNull(from); + checkNotNull(destination); + checkNotNull(to); + checkNotNull(transform); + this.destination = destination; + this.from = from; + this.to = to; + this.transform = transform; + } + + /** + * Return whether entities that are copied should be removed. + * + * @return true if removing + */ + public boolean isRemoving() { + return removing; + } + + /** + * Set whether entities that are copied should be removed. + * + * @param removing true if removing + */ + public void setRemoving(boolean removing) { + this.removing = removing; + } + + @Override + public boolean apply(Entity entity) throws WorldEditException { + BaseEntity state = entity.getState(); + if (state != null) { + Location newLocation; + Location location = entity.getLocation(); + + Vector pivot = from.round().add(0.5, 0.5, 0.5); + Vector newPosition = transform.apply(location.toVector().subtract(pivot)); + Vector newDirection; + + newDirection = transform.isIdentity() ? + entity.getLocation().getDirection() + : transform.apply(location.getDirection()).subtract(transform.apply(Vector.ZERO)).normalize(); + newLocation = new Location(destination, newPosition.add(to.round().add(0.5, 0.5, 0.5)), newDirection); + + // Some entities store their position data in NBT + state = transformNbtData(state); + + boolean success = destination.createEntity(newLocation, state) != null; + + // Remove + if (isRemoving()) { + entity.remove(); + } + + return success; + } else { + return false; + } + } + + /** + * Transform NBT data in the given entity state and return a new instance + * if the NBT data needs to be transformed. + * + * @param state the existing state + * @return a new state or the existing one + */ + private BaseEntity transformNbtData(BaseEntity state) { + CompoundTag tag = state.getNbtData(); + + if (tag != null) { + // Handle hanging entities (paintings, item frames, etc.) + boolean hasTilePosition = tag.containsKey("TileX") && tag.containsKey("TileY") && tag.containsKey("TileZ"); + boolean hasDirection = tag.containsKey("Direction"); + boolean hasLegacyDirection = tag.containsKey("Dir"); + + if (hasTilePosition) { + Vector tilePosition = new Vector(tag.asInt("TileX"), tag.asInt("TileY"), tag.asInt("TileZ")); + Vector newTilePosition = transform.apply(tilePosition.subtract(from)).add(to); + + CompoundTagBuilder builder = tag.createBuilder() + .putInt("TileX", newTilePosition.getBlockX()) + .putInt("TileY", newTilePosition.getBlockY()) + .putInt("TileZ", newTilePosition.getBlockZ()); + + if (hasDirection || hasLegacyDirection) { + int d = hasDirection ? tag.asInt("Direction") : MCDirections.fromLegacyHanging((byte) tag.asInt("Dir")); + Direction direction = MCDirections.fromHanging(d); + + if (direction != null) { + Vector vector = transform.apply(direction.toVector()).subtract(transform.apply(Vector.ZERO)).normalize(); + Direction newDirection = Direction.findClosest(vector, Flag.CARDINAL); + + builder.putByte("Direction", (byte) MCDirections.toHanging(newDirection)); + builder.putByte("Dir", MCDirections.toLegacyHanging(MCDirections.toHanging(newDirection))); + } + } + + return new BaseEntity(state.getTypeId(), builder.build()); + } + } + + return state; + } + + public static Class inject() { + return ExtentEntityCopy.class; + } + +} diff --git a/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java b/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java index 9f17a8b8..b35f71fd 100644 --- a/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java +++ b/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java @@ -90,7 +90,6 @@ public class ForgeChunk_All extends CharFaweChunk { case 7: case 9: case 73: - case 78: case 79: case 80: case 81: