diff --git a/worldedit-bukkit/build.gradle b/worldedit-bukkit/build.gradle index fd0bfff5a..7b3173bab 100644 --- a/worldedit-bukkit/build.gradle +++ b/worldedit-bukkit/build.gradle @@ -25,7 +25,7 @@ dependencies { compile 'com.destroystokyo.paper:paper-api:1.14.3-R0.1-SNAPSHOT' implementation('io.papermc:paperlib:1.0.2'){transitive = false} compile 'org.spigotmc:spigot:1.13.2-R0.1-SNAPSHOT' - compile 'BuildTools:lastSuccessfulBuild:spigot-1.14@jar' + compile 'BuildTools:lastSuccessfulBuild:spigot-1.14.3@jar' implementation('com.sk89q.worldguard:worldguard-core:7.0.0-20190215.210421-39'){transitive = false} implementation('com.sk89q.worldguard:worldguard-legacy:7.0.0-20190215.210421-39'){transitive = false} implementation('com.massivecraft:factions:2.8.0'){transitive = false} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitQueue.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitQueue.java index c336e3005..4cb3896bf 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitQueue.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitQueue.java @@ -199,13 +199,9 @@ public class BukkitQueue extends SimpleCharQueueExtent { } public static Chunk ensureLoaded(net.minecraft.server.v1_14_R1.World nmsWorld, int X, int Z) { - ChunkProviderServer provider = (ChunkProviderServer) nmsWorld.getChunkProvider(); - IChunkAccess nmsChunk = provider.getChunkAt(X, Z, ChunkStatus.FEATURES, false); + Chunk nmsChunk = nmsWorld.getChunkIfLoaded(X, Z); if (nmsChunk != null) { - if (nmsChunk instanceof ProtoChunkExtension) { - return ((ProtoChunkExtension) nmsChunk).u(); - } - return (Chunk) nmsChunk; + return nmsChunk; } if (Fawe.isMainThread()) { return nmsWorld.getChunkAt(X, Z); diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All.java deleted file mode 100644 index f06b31a1b..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All.java +++ /dev/null @@ -1,356 +0,0 @@ -package com.boydti.fawe.bukkit.v0; - -import com.boydti.fawe.Fawe; -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.example.IntFaweChunk; -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.FaweQueue; -import com.boydti.fawe.object.RunnableVal2; -import com.boydti.fawe.util.MainUtil; -import com.boydti.fawe.util.ReflectionUtils; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.LongTag; -import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.entity.BaseEntity; -import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.block.BlockTypes; -import com.sk89q.worldedit.world.entity.EntityTypes; -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.ChunkSnapshot; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.block.Biome; -import org.bukkit.block.Block; -import org.bukkit.block.BlockState; -import org.bukkit.entity.Entity; - -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -public class BukkitChunk_All extends IntFaweChunk { - - private int layer = -1; - private int index; - private boolean place = true; - - /** - * A FaweSections object represents a chunk and the blocks that you wish to change in it. - * - * @param parent - * @param x - * @param z - */ - public BukkitChunk_All(FaweQueue parent, int x, int z) { - super(parent, x, z); - } - - public BukkitChunk_All(FaweQueue parent, int x, int z, int[][] ids, short[] count, short[] air) { - super(parent, x, z, ids, count, air); - } - - private static boolean canTick(BlockType type) { - return type.getMaterial().isTicksRandomly(); - } - - @Override - public IntFaweChunk copy(boolean shallow) { - BukkitChunk_All copy; - if (shallow) { - copy = new BukkitChunk_All(getParent(), getX(), getZ(), setBlocks, count, air); - copy.biomes = biomes; - } else { - copy = new BukkitChunk_All(getParent(), getX(), getZ(), (int[][]) MainUtil.copyNd(setBlocks), count.clone(), air.clone()); - copy.biomes = biomes != null ? biomes.clone() : null; - } - copy.chunk = chunk; - return copy; - } - - @Override - public Chunk getNewChunk() { - return Bukkit.getWorld(getParent().getWorldName()).getChunkAt(getX(), getZ()); - } - - @Override - public void start() { - getChunk().load(true); - } - - /** - * @return - */ - @Override - public FaweChunk call() { - long start = System.currentTimeMillis(); - int recommended = 25 + Settings.IMP.QUEUE.EXTRA_TIME_MS; - boolean more = true; - final BukkitQueue_All parent = getParent(); - BukkitImplAdapter adapter = BukkitQueue_0.getAdapter(); - final Chunk chunk = getChunk(); - Object[] disableResult = parent.disableLighting(chunk); - final World world = chunk.getWorld(); - int[][] sections = getCombinedIdArrays(); - final int bx = getX() << 4; - final int bz = getZ() << 4; - boolean update = adapter == null || adapter.isChunkInUse(chunk); - if (layer == -1) { - if (adapter != null) { - // Run change task - RunnableVal2 task = parent.getChangeTask(); - BukkitChunk_All_ReadonlySnapshot previous; - if (task != null) { - ChunkSnapshot snapshot = parent.ensureChunkLoaded(getX(), getZ()); - previous = new BukkitChunk_All_ReadonlySnapshot(parent, this, snapshot, biomes != null); - for (BlockState tile : chunk.getTileEntities()) { - int x = tile.getX(); - int y = tile.getY(); - int z = tile.getZ(); - if (getBlockCombinedId(x & 15, y, z & 15) != 0) { - CompoundTag nbt = adapter.getBlock(new Location(world, x, y, z)).getNbtData(); - if (nbt != null) { - previous.setTile(x & 15, y, z & 15, nbt); - } - } - } - } else { - previous = null; - } - // Set entities - if (adapter != null) { - Set entitiesToSpawn = this.getEntities(); - if (!entitiesToSpawn.isEmpty()) { - for (CompoundTag tag : entitiesToSpawn) { - String id = tag.getString("Id"); - ListTag posTag = tag.getListTag("Pos"); - ListTag rotTag = tag.getListTag("Rotation"); - if (id == null || posTag == null || rotTag == null) { - Fawe.debug("Unknown entity tag: " + tag); - continue; - } - double x = posTag.getDouble(0); - double y = posTag.getDouble(1); - double z = posTag.getDouble(2); - float yaw = rotTag.getFloat(0); - float pitch = rotTag.getFloat(1); - Location loc = new Location(world, x, y, z, yaw, pitch); - Entity created = adapter.createEntity(loc, new BaseEntity(EntityTypes.get(id), tag)); - if (created != null) { - UUID uuid = created.getUniqueId(); - Map map = ReflectionUtils.getMap(tag.getValue()); - map.put("UUIDLeast", new LongTag(uuid.getLeastSignificantBits())); - map.put("UUIDMost", new LongTag(uuid.getMostSignificantBits())); - } - } - } - HashSet entsToRemove = this.getEntityRemoves(); - if (!entsToRemove.isEmpty()) { - for (Entity entity : chunk.getEntities()) { - if (entsToRemove.contains(entity.getUniqueId()) && !(entity instanceof Player)) { - entity.remove(); - } - } - } - } - if (previous != null) { - task.run(previous, this); - } - } - - // Biomes - final BiomeType[] biomes = getBiomeArray(); - if (biomes != null) { - int index = 0; - for (int z = 0; z < 16; z++) { - int zz = bz + z; - for (int x = 0; x < 16; x++, index++) { - int xx = bx + x; - BiomeType biome = biomes[index]; - if (biome == null) continue; - Biome bukkitBiome = adapter.adapt(biome); - if (bukkitBiome != null) { - world.setBiome(xx, zz, bukkitBiome); - } - } - } - } - } else if (index != 0) { - if (place) { - layer--; - } else { - layer++; - } - } - mainloop: - do { - if (place) { - if (++layer >= sections.length) { - place = false; - layer = sections.length - 1; - } - } else if (--layer < 0) { - more = false; - break; - } - try { - // Efficiently merge sections - int changes = getCount(layer); - if (changes == 0) { - continue; - } - final int[] newArray = sections[layer]; - if (newArray == null) { - continue; - } -// final byte[] cacheX = FaweCache.CACHE_X[layer]; -// final short[] cacheY = FaweCache.CACHE_Y[layer]; -// final byte[] cacheZ = FaweCache.CACHE_Z[layer]; - boolean checkTime = !((getAir(layer) == 4096 || (getCount(layer) == 4096 && getAir(layer) == 0) || (getCount(layer) == getAir(layer)))); - - Location mutableLoc = new Location(world, 0, 0, 0); - - if (!checkTime) { - int index = 0; - for (int y = 0; y < 16; y++) { - int yy = (layer << 4) + y; - for (int z = 0; z < 16; z++) { - int zz = bz + z; - for (int x = 0; x < 16; x++, index++) { - int combined = newArray[index]; - if (combined == 0) continue; - int xx = bx + x; - - BlockType type = BlockTypes.getFromStateId(combined); - if (type == BlockTypes.__RESERVED__) continue; - if (type.getMaterial().isAir()) { - if (!place) { - mutableLoc.setX(xx); - mutableLoc.setY(yy); - mutableLoc.setZ(zz); - setBlock(adapter, chunk, mutableLoc, combined, update); - } - continue; - } - if (place) { - if (type.getMaterial().hasContainer() && adapter != null) { - CompoundTag nbt = getTile(x, yy, z); - if (nbt != null) { - synchronized (BukkitChunk_All.this) { - BaseBlock state = - BaseBlock.getFromInternalId(combined, nbt); - adapter.setBlock(chunk, xx, yy, zz, state, update); - } - continue; - } - } - if (type.getMaterial().isTicksRandomly()) { - synchronized (BukkitChunk_All.this) { - setBlock(adapter, chunk, mutableLoc, combined, update); - } - } else { - mutableLoc.setX(xx); - mutableLoc.setY(yy); - mutableLoc.setZ(zz); - setBlock(adapter, chunk, mutableLoc, combined, update); - } - } - } - } - } - } else { - int yStart = layer << 4; - for (; index < 4096; index++) { - int j = place ? index : 4095 - index; - int combined = newArray[j]; - if (combined == 0) continue; - BlockType type = BlockTypes.getFromStateId(combined); - if (type.getMaterial().isAir()) { - if (!place) { - int x = j & 15; - int y = yStart + (j >> 8); - int z = (j >> 4) & 15; - mutableLoc.setX(bx + x); - mutableLoc.setY(y); - mutableLoc.setZ(bz + z); - setBlock(adapter, chunk, mutableLoc, combined, update); - } - continue; - } else { - boolean light = type.getMaterial().getLightValue() > 0; - if (light) { - if (place) { - continue; - } - light = light && getParent().getSettings().LIGHTING.MODE != 0; - if (light) { - parent.enableLighting(disableResult); - } - } else if (!place) { - continue; - } - int x = j & 15; - int y = yStart + (j >> 8); - int z = (j >> 4) & 15; - if (type.getMaterial().hasContainer() && adapter != null) { - CompoundTag tile = getTile(x, y, z); - if (tile != null) { - synchronized (BukkitChunk_All.this) { - BaseBlock state = BaseBlock.getFromInternalId(combined, tile); - adapter.setBlock(chunk, bx + x, y, bz + z, state, update); - } - continue; - } - } - if (type.getMaterial().isTicksRandomly()) { - synchronized (BukkitChunk_All.this) { - mutableLoc.setX(bx + x); - mutableLoc.setY(y); - mutableLoc.setZ(bz + z); - setBlock(adapter, chunk, mutableLoc, combined, update); - } - } else { - mutableLoc.setX(bx + x); - mutableLoc.setY(y); - mutableLoc.setZ(bz + z); - setBlock(adapter, chunk, mutableLoc, combined, update); - } - if (light) { - parent.disableLighting(disableResult); - } - } - if (System.currentTimeMillis() - start > recommended) { - index++; - break mainloop; - } - } - index = 0; - } - } catch (final Throwable e) { - e.printStackTrace(); - } - } while (System.currentTimeMillis() - start < recommended); - if (more || place) { - this.addToQueue(); - } - parent.resetLighting(disableResult); - return this; - } - - public void setBlock(BukkitImplAdapter adapter, Chunk chunk, Location location, int combinedId, boolean update) { - com.sk89q.worldedit.world.block.BaseBlock base = com.sk89q.worldedit.world.block.BlockState.getFromInternalId(combinedId).toBaseBlock(); - if (adapter != null) { - adapter.setBlock(chunk, (int) location.getX(), (int) location.getY(), (int) location.getZ(), base, update); - } else { - Block block = location.getWorld().getBlockAt(location); - block.setBlockData(BukkitAdapter.adapt(base), false); - } - } -} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All_ReadonlySnapshot.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All_ReadonlySnapshot.java deleted file mode 100644 index 4ed7a4e9a..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All_ReadonlySnapshot.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.boydti.fawe.bukkit.v0; - -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.util.MathMan; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; - -import java.util.*; - -import com.sk89q.worldedit.world.biome.BiomeType; -import org.bukkit.ChunkSnapshot; -import org.bukkit.block.Biome; -import org.bukkit.block.data.BlockData; - -import javax.annotation.Nullable; - -public class BukkitChunk_All_ReadonlySnapshot extends FaweChunk { - private final ChunkSnapshot snapshot; - private final boolean hasBiomes; - private final BukkitChunk_All next; - private Set entities = new HashSet<>(); - private Map tiles = new HashMap<>(); - - public BukkitChunk_All_ReadonlySnapshot(BukkitQueue_All parent, BukkitChunk_All next, ChunkSnapshot snapshot, boolean biomes) { - super(parent, snapshot.getX(), snapshot.getZ()); - this.next = next; - this.snapshot = snapshot; - this.hasBiomes = biomes; - } - - public void setTiles(Map tiles) { - this.tiles = tiles; - } - - public void setEntities(Set entities) { - this.entities = entities; - } - - @Override - public BukkitQueue_All getParent() { - return (BukkitQueue_All) super.getParent(); - } - - @Override - public int getBitMask() { - return Character.MAX_VALUE; - } - - @Override - public int getBlockCombinedId(int x, int y, int z) { - BlockData blockData = snapshot.getBlockData(x, y, z); - return BukkitAdapter.adapt(blockData).getInternalId(); - } - - @Override - public BiomeType[] getBiomeArray() { - if (!hasBiomes || next.biomes == null) return null; - BukkitImplAdapter adapter = getParent().getAdapter(); - BiomeType[] biomes = Arrays.copyOf(next.biomes, next.biomes.length); - int index = 0; - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++, index++) { - if (biomes[index] != null) { - Biome biome = snapshot.getBiome(x, z); - biomes[index] = adapter.adapt(biome); - } - } - } - return biomes; - } - - @Nullable - @Override - public int[] getIdArray(int layer) { - int[] nextLayer = next.setBlocks[layer]; - if (nextLayer == null) return null; - int[] ids = Arrays.copyOf(nextLayer, nextLayer.length); - int index = 0; - int by = layer << 4; - for (int y = 0; y < 16; y++) { - int yy = by + y; - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++, index++) { - if (ids[index] != 0) { - ids[index] = getBlockCombinedId(x, yy, z); - } - } - } - } - return ids; - } - - @Override - public Object getChunk() { - return snapshot; - } - - @Override - public void setTile(int x, int y, int z, CompoundTag tile) { - tiles.put(MathMan.tripleBlockCoord(x, y, z), tile); - } - - @Override - public void setEntity(CompoundTag entity) { - entities.add(entity); - } - - @Override - public void removeEntity(UUID uuid) { - throw new UnsupportedOperationException("Read only"); - } - - @Override - public void setBlock(int x, int y, int z, int combinedId) { - throw new UnsupportedOperationException("Read only"); - } - - @Override - public Set getEntities() { - return entities; - } - - @Override - public Set getEntityRemoves() { - throw new UnsupportedOperationException("Read only"); - } - - @Override - public Map getTiles() { - return tiles; - } - - @Override - public CompoundTag getTile(int x, int y, int z) { - if (tiles == null) return null; - short pair = MathMan.tripleBlockCoord(x, y, z); - return tiles.get(pair); - } - - @Override - public void setBiome(int x, int z, BiomeType biome) { - throw new UnsupportedOperationException("Read only"); - } - - @Override - public FaweChunk copy(boolean shallow) { - return null; - } - - @Override - public FaweChunk call() { - return null; - } -} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java deleted file mode 100644 index 325038d8e..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java +++ /dev/null @@ -1,368 +0,0 @@ -package com.boydti.fawe.bukkit.v0; - -import com.boydti.fawe.Fawe; -import com.boydti.fawe.bukkit.BukkitPlayer; -import com.boydti.fawe.bukkit.FaweBukkit; -import com.boydti.fawe.bukkit.util.BukkitReflectionUtils; -import com.boydti.fawe.example.NMSMappedFaweQueue; -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.FawePlayer; -import com.boydti.fawe.object.RunnableVal; -import com.boydti.fawe.object.queue.LazyFaweChunk; -import com.boydti.fawe.object.visitor.FaweChunkVisitor; -import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.ReflectionUtils; -import com.boydti.fawe.util.TaskManager; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.ProtocolManager; -import com.comphenix.protocol.injector.netty.WirePacket; -import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BlockState; -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.WorldCreator; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.world.ChunkLoadEvent; -import org.bukkit.event.world.ChunkUnloadEvent; -import org.bukkit.event.world.WorldInitEvent; -import org.bukkit.plugin.Plugin; - -import java.io.File; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.concurrent.ConcurrentHashMap; - -public abstract class BukkitQueue_0 extends NMSMappedFaweQueue implements Listener { - - protected static boolean PAPER = true; - private static BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); - private static Method methodGetHandle; - - static { - Class classCraftChunk = BukkitReflectionUtils.getCbClass("CraftChunk"); - try { - methodGetHandle = ReflectionUtils.setAccessible(classCraftChunk.getDeclaredMethod("getHandle")); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } - } - - public BukkitQueue_0(final com.sk89q.worldedit.world.World world) { - super(world); - if (!registered) { - registered = true; - Bukkit.getServer().getPluginManager().registerEvents(this, ((FaweBukkit) Fawe.imp()).getPlugin()); - } - } - - public BukkitQueue_0(String world) { - super(world); - if (!registered) { - registered = true; - Bukkit.getServer().getPluginManager().registerEvents(this, ((FaweBukkit) Fawe.imp()).getPlugin()); - } - } - - @Override - public boolean supports(Capability capability) { - switch (capability) { - case CHUNK_PACKETS: - Plugin plib = Bukkit.getPluginManager().getPlugin("ProtocolLib"); - return plib != null && plib.isEnabled(); - } - return super.supports(capability); - } - - @Override - public void sendChunk(FaweChunk fc) { - if (!Fawe.isMainThread()) { - startSet(true); - try { - super.sendChunk(fc); - } finally { - endSet(true); - } - } else super.sendChunk(fc); - } - - @Override - public void sendChunkUpdate(FaweChunk chunk, FawePlayer... players) { - if (supports(Capability.CHUNK_PACKETS)) { - sendChunkUpdatePLIB(chunk, players); - } else { - sendBlockUpdate(chunk, players); - } - } - - public void sendChunkUpdatePLIB(FaweChunk chunk, FawePlayer... players) { - ProtocolManager manager = ProtocolLibrary.getProtocolManager(); - WirePacket packet = null; - int viewDistance = Bukkit.getViewDistance(); - try { - for (FawePlayer fawePlayer : players) { - int cx = chunk.getX(); - int cz = chunk.getZ(); - - Player player = ((BukkitPlayer) fawePlayer).parent; - Location loc = player.getLocation(); - - if (Math.abs((loc.getBlockX() >> 4) - cx) <= viewDistance - && Math.abs((loc.getBlockZ() >> 4) - cz) <= viewDistance) { - if (packet == null) { - byte[] data; - byte[] buffer = new byte[8192]; - if (chunk instanceof LazyFaweChunk) { - chunk = (FaweChunk) chunk.getChunk(); - } - // TODO FIXME - // if (chunk instanceof MCAChunk) { - // data = new MCAChunkPacket((MCAChunk) chunk, true, true, hasSky()).apply(buffer); - // } else { - // data = new FaweChunkPacket(chunk, true, true, hasSky()).apply(buffer); - // } - // packet = new WirePacket(PacketType.Play.Server.MAP_CHUNK, data); - } - manager.sendWirePacket(player, packet); - } - } - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } - } - - @Override - public boolean queueChunkLoad(int cx, int cz, RunnableVal operation) { - if (PAPER) { - try { - new PaperChunkCallback(getImpWorld(), cx, cz) { - @Override - public void onLoad(Chunk bukkitChunk) { - try { - CHUNK chunk = (CHUNK) methodGetHandle.invoke(bukkitChunk); - try { - operation.run(chunk); - } catch (Throwable e) { - e.printStackTrace(); - } - } catch (Throwable e) { - PAPER = false; - } - } - }; - return true; - } catch (Throwable ignore) { - PAPER = false; - } - } - return super.queueChunkLoad(cx, cz); - } - - public static BukkitImplAdapter getAdapter() { - return adapter; - } - - public static Tag toNative(Object tag) { - BukkitImplAdapter adapter = getAdapter(); - return adapter.toNative(tag); - } - - public static Object fromNative(Tag tag) { - BukkitImplAdapter adapter = getAdapter(); - return adapter.fromNative(tag); - } - - @Override - public File getSaveFolder() { - return new File(Bukkit.getWorldContainer(), getWorldName() + File.separator + "region"); - } - - @Override - public void setFullbright(CHUNKSECTIONS sections) {} - - @Override - public void relight(int x, int y, int z) {} - - @Override - public void relightBlock(int x, int y, int z) {} - - @Override - public void relightSky(int x, int y, int z) {} - - @Override - public boolean removeSectionLighting(SECTION sections, int layer, boolean hasSky) { - return false; - } - - public static void checkVersion(String supported) { - String version = Bukkit.getServer().getClass().getPackage().getName(); - if (!version.contains(supported)) { - throw new IllegalStateException("Unsupported version: " + version + " (supports: " + supported + ")"); - } - } - - protected static boolean registered = false; - protected static boolean disableChunkLoad = false; - - @EventHandler - public static void onWorldLoad(WorldInitEvent event) { - if (disableChunkLoad) { - World world = event.getWorld(); - world.setKeepSpawnInMemory(false); - } - } - - @Override - public boolean queueChunkLoad(int cx, int cz) { - if (super.queueChunkLoad(cx, cz)) { - return true; - } - return false; - } - - public World createWorld(final WorldCreator creator) { - return TaskManager.IMP.sync(new RunnableVal() { - @Override - public void run(World value) { - disableChunkLoad = true; - this.value = creator.createWorld(); - disableChunkLoad = false; - } - }); - } - - @Override - public World getImpWorld() { - return getWorldName() != null ? Bukkit.getWorld(getWorldName()) : null; - } - - @Override - public void sendChunk(int x, int z, int bitMask) {} - - @Override - public void refreshChunk(FaweChunk fs) { - World world = getWorld(); - if(world != null) { - world.refreshChunk(fs.getX(), fs.getZ()); - } - } - - @Override - public boolean regenerateChunk(World world, int x, int z, BiomeType biome, Long seed) { - return world.regenerateChunk(x, z); - } - - @Override - public boolean hasSky() { - World world = getWorld(); - return world == null || world.getEnvironment() == World.Environment.NORMAL; - } - - private volatile boolean timingsEnabled; - private static boolean alertTimingsChange = true; - - private static Field fieldTimingsEnabled; - private static Field fieldAsyncCatcherEnabled; - private static Method methodCheck; - static { - try { - fieldAsyncCatcherEnabled = Class.forName("org.spigotmc.AsyncCatcher").getField("enabled"); - fieldAsyncCatcherEnabled.setAccessible(true); - } catch (Throwable ignore) {} - try { - fieldTimingsEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled"); - fieldTimingsEnabled.setAccessible(true); - methodCheck = Class.forName("co.aikar.timings.TimingsManager").getDeclaredMethod("recheckEnabled"); - methodCheck.setAccessible(true); - } catch (Throwable ignore){} - } - - @Override - public void startSet(boolean parallel) { - ChunkListener.physicsFreeze = true; - if (parallel) { - try { - if (fieldAsyncCatcherEnabled != null) { - fieldAsyncCatcherEnabled.set(null, false); - } - if (fieldTimingsEnabled != null) { - timingsEnabled = (boolean) fieldTimingsEnabled.get(null); - if (timingsEnabled) { - if (alertTimingsChange) { - alertTimingsChange = false; - Fawe.debug("Having `parallel-threads` > 1 interferes with the timings."); - } - fieldTimingsEnabled.set(null, false); - methodCheck.invoke(null); - } - } - } catch (Throwable e) { - e.printStackTrace(); - } - } - } - - @Override - public void endSet(boolean parallel) { - ChunkListener.physicsFreeze = false; - if (parallel) { - try { - if (fieldAsyncCatcherEnabled != null) { - fieldAsyncCatcherEnabled.set(null, true); - } - if (fieldTimingsEnabled != null && timingsEnabled) { - fieldTimingsEnabled.set(null, true); - methodCheck.invoke(null); - } - } catch (Throwable e) { - e.printStackTrace(); - } - } - } - - @Override - public void sendBlockUpdate(final FaweChunk chunk, FawePlayer... players) { - if (players.length == 0) { - return; - } - int cx = chunk.getX(); - int cz = chunk.getZ(); - int view = Bukkit.getServer().getViewDistance(); - boolean sendAny = false; - boolean[] send = new boolean[players.length]; - for (int i = 0; i < players.length; i++) { - FawePlayer player = players[i]; - Player bp = ((BukkitPlayer) player).parent; - Location loc = bp.getLocation(); - if (Math.abs((loc.getBlockX() >> 4) - cx) <= view && Math.abs((loc.getBlockZ() >> 4) - cz) <= view) { - sendAny = true; - send[i] = true; - } - } - if (!sendAny) { - return; - } - final World world = getWorld(); - final int bx = cx << 4; - final int bz = cz << 4; - chunk.forEachQueuedBlock(new FaweChunkVisitor() { - @Override - public void run(int localX, int y, int localZ, int combined) { - Location loc = new Location(world, bx + localX, y, bz + localZ); - for (int i = 0; i < players.length; i++) { - if (send[i]) { - ((BukkitPlayer) players[i]).parent.sendBlockChange(loc, BukkitAdapter.adapt(BlockState.getFromInternalId(combined))); - } - } - } - }); - } -} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java deleted file mode 100644 index 863345ec4..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java +++ /dev/null @@ -1,395 +0,0 @@ -package com.boydti.fawe.bukkit.v0; - -import com.boydti.fawe.bukkit.util.BukkitReflectionUtils; -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.example.NullRelighter; -import com.boydti.fawe.example.Relighter; -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.RegionWrapper; -import com.boydti.fawe.object.RunnableVal; -import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.ReflectionUtils; -import com.boydti.fawe.util.SetQueue; -import com.boydti.fawe.util.TaskManager; - -import com.google.common.collect.MapMaker; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockTypes; -import org.bukkit.Chunk; -import org.bukkit.ChunkSnapshot; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.block.Biome; -import org.bukkit.block.data.BlockData; - -import java.io.File; -import java.io.RandomAccessFile; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayDeque; -import java.util.Map; -import java.util.concurrent.ConcurrentMap; - -public class BukkitQueue_All extends BukkitQueue_0 { - - private ConcurrentMap chunkCache = new MapMaker() - .weakValues() - .makeMap(); - - public BukkitQueue_All(com.sk89q.worldedit.world.World world) { - super(world); - Settings.IMP.QUEUE.PARALLEL_THREADS = 1; - } - - public BukkitQueue_All(String world) { - super(world); - Settings.IMP.QUEUE.PARALLEL_THREADS = 1; - } - - @Override - public boolean queueChunkLoad(int cx, int cz, RunnableVal operation) { - if (PAPER) { - try { - new PaperChunkCallback(getImpWorld(), cx, cz) { - @Override - public void onLoad(Chunk chunk) { - try { - ChunkSnapshot snapshot = tryGetSnasphot(chunk); - operation.run(snapshot); - } catch (Throwable e) { - PAPER = false; - } - } - }; - return true; - } catch (Throwable ignore) { - PAPER = false; - } - } - return super.queueChunkLoad(cx, cz); - } - - @Override - public Relighter getRelighter() { - return NullRelighter.INSTANCE; - } - - private static Class classRegionFileCache; - private static Method methodGetHandleChunk; - private static Method methodGetHandleWorld; - private static Method methodFlush; - private static Method methodNeedsSaving; - private static Field fieldChunkProvider; - private static Field fieldChunkLoader; - private static Field fieldRegionMap; - private static Field fieldRegionRAF; - - static { - try { - BukkitReflectionUtils.init(); - classRegionFileCache = BukkitReflectionUtils.getNmsClass("RegionFileCache"); - Class classRegionFile = BukkitReflectionUtils.getNmsClass("RegionFile"); - Class classCraftChunk = BukkitReflectionUtils.getCbClass("CraftChunk"); - Class classNMSChunk = BukkitReflectionUtils.getNmsClass("Chunk"); - Class classCraftWorld = BukkitReflectionUtils.getCbClass("CraftWorld"); - Class classNMSWorld = BukkitReflectionUtils.getNmsClass("World"); - Class classChunkProviderServer = BukkitReflectionUtils.getNmsClass("ChunkProviderServer"); - Class classIChunkProvider = BukkitReflectionUtils.getNmsClass("IChunkProvider"); - Class classIChunkLoader = BukkitReflectionUtils.getNmsClass("IChunkLoader"); - Class classChunkRegionLoader = BukkitReflectionUtils.getNmsClass("ChunkRegionLoader"); - - methodGetHandleChunk = ReflectionUtils.setAccessible(classCraftChunk.getDeclaredMethod("getHandle")); - methodGetHandleWorld = ReflectionUtils.setAccessible(classCraftWorld.getDeclaredMethod("getHandle")); - methodFlush = ReflectionUtils.findMethod(classChunkRegionLoader, boolean.class); - methodNeedsSaving = ReflectionUtils.findMethod(classNMSChunk, boolean.class, boolean.class); - - fieldChunkProvider = ReflectionUtils.findField(classNMSWorld, classIChunkProvider); - fieldChunkLoader = ReflectionUtils.findField(classChunkProviderServer, classIChunkLoader); - - fieldRegionMap = ReflectionUtils.findField(classRegionFileCache, Map.class); - fieldRegionRAF = ReflectionUtils.findField(classRegionFile, RandomAccessFile.class); - } catch (Throwable throwable) { - throwable.printStackTrace(); - } - } - - @Override - public boolean setMCA(int mcaX, int mcaZ, RegionWrapper allowed, Runnable whileLocked, boolean saveChunks, boolean load) { - if (classRegionFileCache == null) { - return super.setMCA(mcaX, mcaZ, allowed, whileLocked, saveChunks, load); - } - TaskManager.IMP.sync(new RunnableVal() { - @Override - public void run(Boolean value) { - long start = System.currentTimeMillis(); - long last = start; - synchronized (classRegionFileCache) { - try { - World world = getWorld(); - boolean autoSave = world.isAutoSave(); - - if (world.getKeepSpawnInMemory()) world.setKeepSpawnInMemory(false); - - ArrayDeque unloaded = null; - if (load) { - int bcx = mcaX << 5; - int bcz = mcaZ << 5; - int tcx = bcx + 31; - int tcz = bcz + 31; - for (Chunk chunk : world.getLoadedChunks()) { - int cx = chunk.getX(); - int cz = chunk.getZ(); - if (cx >= bcx && cx <= tcx && cz >= bcz && cz <= tcz) { - Object nmsChunk = methodGetHandleChunk.invoke(chunk); - boolean mustSave = saveChunks && (boolean) methodNeedsSaving.invoke(nmsChunk, false); - chunk.unload(mustSave); - if (unloaded == null) unloaded = new ArrayDeque<>(); - unloaded.add(chunk); - } - } - } else { - world.save(); - } - - Object nmsWorld = methodGetHandleWorld.invoke(world); - Object chunkProviderServer = fieldChunkProvider.get(nmsWorld); - Object chunkRegionLoader = fieldChunkLoader.get(chunkProviderServer); - while ((boolean) methodFlush.invoke(chunkRegionLoader)); - - if (unloaded != null) { - Map regionMap = (Map) fieldRegionMap.get(null); - File file = new File(world.getWorldFolder(), "region" + File.separator + "r." + mcaX + "." + mcaZ + ".mca"); - Object regionFile = regionMap.remove(file); - if (regionFile != null) { - RandomAccessFile raf = (RandomAccessFile) fieldRegionRAF.get(regionFile); - raf.close(); - } - } - - whileLocked.run(); - - if (load && unloaded != null) { - final ArrayDeque finalUnloaded = unloaded; - TaskManager.IMP.async(() -> { - for (Chunk chunk : finalUnloaded) { - int cx = chunk.getX(); - int cz = chunk.getZ(); - if (world.isChunkLoaded(cx, cz)) continue; - SetQueue.IMP.addTask(() -> { - world.loadChunk(chunk.getX(), chunk.getZ(), false); - world.refreshChunk(chunk.getX(), chunk.getZ()); - }); - - } - }); - // load chunks - - } - } catch (Throwable e) { - e.printStackTrace(); - } - } - } - }); - return true; - } - - @Override - public void setSkyLight(ChunkSnapshot chunk, int x, int y, int z, int value) { - // Not supported - } - - @Override - public void setBlockLight(ChunkSnapshot chunk, int x, int y, int z, int value) { - // Not supported - } - - @Override - public int getCombinedId4Data(ChunkSnapshot chunk, int x, int y, int z) { - if (chunk.isSectionEmpty(y >> 4)) { - return BlockTypes.AIR.getInternalId(); - } - BlockData blockData = chunk.getBlockData(x & 15, y, z & 15); - return BukkitAdapter.adapt(blockData).getInternalId(); - } - - @Override - public BiomeType getBiome(ChunkSnapshot chunkSnapshot, int x, int z) { - Biome biome = chunkSnapshot.getBiome(x & 15, z & 15); - return getAdapter().adapt(biome); - } - - @Override - public ChunkSnapshot getSections(ChunkSnapshot chunkSnapshot) { - return chunkSnapshot; - } - - @Override - public ChunkSnapshot getCachedChunk(World world, int cx, int cz) { - long pair = MathMan.pairInt(cx, cz); - ChunkSnapshot cached = chunkCache.get(pair); - if (cached != null) return cached; - if (world.isChunkLoaded(cx, cz)) { - if (world.isChunkLoaded(cx, cz)) { - Chunk chunk = world.getChunkAt(cx, cz); - ChunkSnapshot snapshot = getAndCacheChunk(chunk); - return snapshot; - } else { - return null; - } - } else { - return null; - } - } - - @Override - public int getEmmittedLight(final ChunkSnapshot chunk, int x, int y, int z) { - return chunk.getBlockEmittedLight(x & 15, y, z & 15); - } - - @Override - public int getSkyLight(final ChunkSnapshot chunk, int x, int y, int z) { - return chunk.getBlockSkyLight(x & 15, y, z & 15); - } - - @Override - public int getLight(final ChunkSnapshot chunk, int x, int y, int z) { - x = x & 15; - z = z & 15; - return Math.max(chunk.getBlockEmittedLight(x, y, z), chunk.getBlockSkyLight(x, y, z)); - } - - @Override - public ChunkSnapshot loadChunk(World world, int x, int z, boolean generate) { - Chunk chunk = world.getChunkAt(x, z); - chunk.load(generate); - return chunk.isLoaded() ? getAndCacheChunk(chunk) : null; - } - - private ChunkSnapshot tryGetSnasphot(Chunk chunk) { - try { - return chunk.getChunkSnapshot(false, true, false); - } catch (Throwable throwable) { - Throwable cause = throwable; - while (cause.getCause() != null) { - cause = cause.getCause(); - } - if (cause instanceof IllegalStateException) { - return null; - } - throw throwable; - } - } - - private ChunkSnapshot getAndCacheChunk(Chunk chunk) { - ChunkSnapshot snapshot = tryGetSnasphot(chunk); - if (snapshot == null) { - snapshot = tryGetSnasphot(chunk); - if (snapshot == null) { - snapshot = TaskManager.IMP.sync(() -> tryGetSnasphot(chunk)); - if (snapshot == null) { - snapshot = chunk.getChunkSnapshot(false, true, false); - } - } - } - chunkCache.put(MathMan.pairInt(chunk.getX(), chunk.getZ()), snapshot); - return snapshot; - } - - @Override - public ChunkSnapshot getCachedSections(World impWorld, int cx, int cz) { - return getCachedChunk(impWorld, cx, cz); - } - - @Override - public CompoundTag getTileEntity(ChunkSnapshot chunk, int x, int y, int z) { - if (getAdapter() == null) { - return null; - } - Location loc = new Location(getWorld(), x, y, z); - BaseBlock block = getAdapter().getBlock(loc); - return block.getNbtData(); - } - - @Override - public FaweChunk getFaweChunk(int x, int z) { - return new BukkitChunk_All(this, x, z); - } - - @Override - public boolean supports(Capability capability) { - switch (capability) { - case CHANGE_TASKS: return getAdapter() != null; - } - return super.supports(capability); - } - - @Override - public void startSet(boolean parallel) { - super.startSet(true); - } - - private Field fieldNeighbors; - private Method chunkGetHandle; - - /** - * Exploiting a bug in the vanilla lighting algorithm for faster block placement - * - Could have been achieved without reflection by force unloading specific chunks - * - Much faster just setting the variable manually though - * @param chunk - * @return - */ - protected Object[] disableLighting(Chunk chunk) { - try { - if (chunkGetHandle == null) { - chunkGetHandle = chunk.getClass().getDeclaredMethod("getHandle"); - chunkGetHandle.setAccessible(true); - } - Object nmsChunk = chunkGetHandle.invoke(chunk); - if (fieldNeighbors == null) { - fieldNeighbors = nmsChunk.getClass().getDeclaredField("neighbors"); - fieldNeighbors.setAccessible(true); - } - Object value = fieldNeighbors.get(nmsChunk); - fieldNeighbors.set(nmsChunk, 0); - return new Object[] {nmsChunk, value}; - } catch (Throwable ignore) {} - return null; - } - - protected void disableLighting(Object[] disableResult) { - if (disableResult != null) { - try { - fieldNeighbors.set(disableResult[0], 0); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - } - - protected void resetLighting(Object[] disableResult) { - if (disableResult != null) { - try { - fieldNeighbors.set(disableResult[0], disableResult[1]); - } catch (Throwable throwable) { - throwable.printStackTrace(); - } - } - } - - protected void enableLighting(Object[] disableResult) { - if (disableResult != null) { - try { - fieldNeighbors.set(disableResult[0], 0x739C0); - } catch (Throwable ignore) {} - } - } - - @Override - public void endSet(boolean parallel) { - super.endSet(true); - } -} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/PaperChunkCallback.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/PaperChunkCallback.java deleted file mode 100644 index 4d22f8fa8..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/PaperChunkCallback.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.boydti.fawe.bukkit.v0; - -import org.bukkit.Chunk; -import org.bukkit.World; - -public abstract class PaperChunkCallback { - public PaperChunkCallback(World world, int x, int z) { -// world.getChunkAtAsync(x, z, PaperChunkCallback.this::onLoad); - throw new UnsupportedOperationException("Not implemented"); - } - - public abstract void onLoad(Chunk chunk); -} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/BukkitChunk_1_13.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/BukkitChunk_1_13.java deleted file mode 100644 index dcd00cbe6..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/BukkitChunk_1_13.java +++ /dev/null @@ -1,627 +0,0 @@ -package com.boydti.fawe.bukkit.v1_13; - -import com.boydti.fawe.Fawe; -import com.boydti.fawe.bukkit.adapter.v1_13_1.BlockMaterial_1_13; -import com.boydti.fawe.bukkit.adapter.v1_13_1.Spigot_v1_13_R2; -import com.boydti.fawe.bukkit.v0.BukkitQueue_0; -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.example.IntFaweChunk; -import com.boydti.fawe.jnbt.anvil.BitArray4096; -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.FaweQueue; -import com.boydti.fawe.util.MainUtil; -import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.ReflectionUtils; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.LongTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.internal.Constants; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BlockID; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockTypes; -import net.minecraft.server.v1_13_R2.BiomeBase; -import net.minecraft.server.v1_13_R2.Block; -import net.minecraft.server.v1_13_R2.BlockPosition; -import net.minecraft.server.v1_13_R2.Blocks; -import net.minecraft.server.v1_13_R2.ChunkSection; -import net.minecraft.server.v1_13_R2.DataBits; -import net.minecraft.server.v1_13_R2.DataPalette; -import net.minecraft.server.v1_13_R2.DataPaletteBlock; -import net.minecraft.server.v1_13_R2.DataPaletteHash; -import net.minecraft.server.v1_13_R2.DataPaletteLinear; -import net.minecraft.server.v1_13_R2.Entity; -import net.minecraft.server.v1_13_R2.EntityPlayer; -import net.minecraft.server.v1_13_R2.EntityTypes; -import net.minecraft.server.v1_13_R2.GameProfileSerializer; -import net.minecraft.server.v1_13_R2.IBlockData; -import net.minecraft.server.v1_13_R2.MinecraftKey; -import net.minecraft.server.v1_13_R2.NBTTagCompound; -import net.minecraft.server.v1_13_R2.NBTTagInt; -import net.minecraft.server.v1_13_R2.NibbleArray; -import net.minecraft.server.v1_13_R2.RegistryID; -import net.minecraft.server.v1_13_R2.TileEntity; -import org.bukkit.Chunk; -import org.bukkit.World; -import org.bukkit.block.Biome; -import org.bukkit.craftbukkit.v1_13_R2.CraftChunk; -import org.bukkit.craftbukkit.v1_13_R2.block.CraftBlock; -import org.bukkit.event.entity.CreatureSpawnEvent; - -import java.lang.reflect.InvocationTargetException; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -import static com.boydti.fawe.bukkit.v0.BukkitQueue_0.getAdapter; -import static com.boydti.fawe.bukkit.v1_13.BukkitQueue_1_13.fieldRegistryb; -import static com.boydti.fawe.bukkit.v1_13.BukkitQueue_1_13.fieldRegistryc; -import static com.boydti.fawe.bukkit.v1_13.BukkitQueue_1_13.fieldRegistryd; -import static com.boydti.fawe.bukkit.v1_13.BukkitQueue_1_13.fieldRegistrye; -import static com.boydti.fawe.bukkit.v1_13.BukkitQueue_1_13.fieldRegistryf; - -public class BukkitChunk_1_13 extends IntFaweChunk { - - public ChunkSection[] sectionPalettes; - - private static final IBlockData AIR = ((BlockMaterial_1_13) BlockTypes.AIR.getMaterial()).getState(); - - /** - * A FaweSections object represents a chunk and the blocks that you wish to change in it. - * - * @param parent - * @param x - * @param z - */ - public BukkitChunk_1_13(FaweQueue parent, int x, int z) { - super(parent, x, z); - } - - public BukkitChunk_1_13(FaweQueue parent, int x, int z, int[][] ids, short[] count, short[] air) { - super(parent, x, z, ids, count, air); - } - - public void storeBiomes(BiomeBase[] biomes) { - if (biomes != null) { - if (this.biomes == null) { - this.biomes = new BiomeType[256]; - } - for (int i = 0; i < 256; i++) { - this.biomes[i] = BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(biomes[i])); - } - } - } - - @Override - public int[][] getCombinedIdArrays() { - if (this.sectionPalettes != null) { - for (int i = 0; i < setBlocks.length; i++) { - getIdArray(i); - } - } - return this.setBlocks; - } - - @Override - public int[] getIdArray(int layer) { - if (this.setBlocks[layer] == null && this.sectionPalettes != null) { - ChunkSection section = this.sectionPalettes[layer]; - int[] idsArray = this.setBlocks[layer]; - if (section != null && idsArray == null) { - this.setBlocks[layer] = idsArray = new int[4096]; - if (!section.a()) { - try { - DataPaletteBlock blocks = section.getBlocks(); - DataBits bits = (DataBits) BukkitQueue_1_13.fieldBits.get(blocks); - DataPalette palette = (DataPalette) BukkitQueue_1_13.fieldPalette.get(blocks); - - long[] raw = bits.a(); - int bitsPerEntry = bits.c(); - - new BitArray4096(raw, bitsPerEntry).toRaw(idsArray); - IBlockData defaultBlock = (IBlockData) BukkitQueue_1_13.fieldDefaultBlock.get(blocks); - // TODO optimize away palette.a - for (int i = 0; i < 4096; i++) { - IBlockData ibd = palette.a(idsArray[i]); - if (ibd == null) { - ibd = defaultBlock; - } - int ordinal = ((Spigot_v1_13_R2) getAdapter()).adaptToInt(ibd); - idsArray[i] = BlockTypes.states[ordinal].getInternalId(); - } - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - } - } - return this.setBlocks[layer]; - } - - public boolean storeTile(TileEntity tile, BlockPosition pos) { - CompoundTag nativeTag = getParent().getTag(tile); - setTile(pos.getX() & 15, pos.getY(), pos.getZ() & 15, nativeTag); - return true; - } - - public boolean storeEntity(Entity ent) throws InvocationTargetException, IllegalAccessException { - if (ent instanceof EntityPlayer || BukkitQueue_0.getAdapter() == null) { - return false; - } - EntityTypes type = ent.P(); - MinecraftKey id = EntityTypes.getName(type); - if (id != null) { - NBTTagCompound tag = new NBTTagCompound(); - ent.save(tag); // readEntityIntoTag - CompoundTag nativeTag = (CompoundTag) BukkitQueue_0.toNative(tag); - Map map = ReflectionUtils.getMap(nativeTag.getValue()); - map.put("Id", new StringTag(id.toString())); - setEntity(nativeTag); - return true; - } else { - return false; - } - } - - public boolean storeSection(ChunkSection section, int layer) throws IllegalAccessException { - if (sectionPalettes == null) { - // TODO optimize don't copy light - sectionPalettes = new ChunkSection[16]; - } - sectionPalettes[layer] = section; - return true; - } - - public ChunkSection copy(ChunkSection current) throws IllegalAccessException, InvocationTargetException, NoSuchFieldException { - ChunkSection newSection = new ChunkSection(current.getYPosition(), current.getSkyLightArray() != null); - - // Copy light - NibbleArray skyLight = current.getSkyLightArray(); - NibbleArray blockLight = current.getEmittedLightArray(); - - NibbleArray newBlockLight = newSection.getEmittedLightArray(); - NibbleArray newSkyLight = newSection.getSkyLightArray(); - - byte[] newBlockBytes = newBlockLight.asBytes(); - byte[] blockLightBytes = blockLight.asBytes(); - for (int i = 0; i < 2048; i++) newBlockBytes[i] = blockLightBytes[i]; - if (skyLight != null) { - byte[] newSkyBytes = newSkyLight.asBytes(); - byte[] skyLightBytes = skyLight.asBytes(); - for (int i = 0; i < 2048; i++) newSkyBytes[i] = skyLightBytes[i]; - } - - // Copy counters - Object nonEmptyBlockCount = BukkitQueue_1_13.fieldNonEmptyBlockCount.get(current); - BukkitQueue_1_13.fieldNonEmptyBlockCount.set(newSection, nonEmptyBlockCount); - - Object tickingBlockCount = BukkitQueue_1_13.fieldTickingBlockCount.get(current); - BukkitQueue_1_13.fieldTickingBlockCount.set(newSection, tickingBlockCount); - - Object liquidCount = BukkitQueue_1_13.fieldLiquidCount.get(current); - BukkitQueue_1_13.fieldLiquidCount.set(newSection, liquidCount); - - // Copy blocks - DataPaletteBlock blocks = current.getBlocks(); - DataPaletteBlock blocksCopy = copy(blocks); - BukkitQueue_1_13.fieldSection.set(newSection, blocksCopy); - - return newSection; - } - - public DataPaletteBlock copy(DataPaletteBlock current) throws IllegalAccessException, InvocationTargetException, NoSuchFieldException { - // Clone palette - DataPalette currentPalette = (DataPalette) BukkitQueue_1_13.fieldPalette.get(current); - DataPaletteBlock paletteBlock = newDataPaletteBlock(); - int size = BukkitQueue_1_13.fieldSize.getInt(current); - - DataPalette newPalette = currentPalette; - if (currentPalette instanceof DataPaletteHash) { - // TODO optimize resize - newPalette = new DataPaletteHash<>(Block.REGISTRY_ID, size, paletteBlock, GameProfileSerializer::d, GameProfileSerializer::a); - RegistryID currReg = (RegistryID) BukkitQueue_1_13.fieldHashBlocks.get(currentPalette); - RegistryID newReg = (RegistryID) BukkitQueue_1_13.fieldHashBlocks.get(newPalette); - int arrLen = 1 << size; - System.arraycopy(fieldRegistryb.get(currReg), 0, fieldRegistryb.get(newReg), 0, arrLen); - System.arraycopy(fieldRegistryc.get(currReg), 0, fieldRegistryc.get(newReg), 0, arrLen); - System.arraycopy(fieldRegistryd.get(currReg), 0, fieldRegistryd.get(newReg), 0, arrLen); - fieldRegistrye.set(newReg, fieldRegistrye.get(currReg)); - fieldRegistryf.set(newReg, fieldRegistryf.get(currReg)); - } else if (currentPalette instanceof DataPaletteLinear) { - // TODO optimize resize - newPalette = new DataPaletteLinear<>(Block.REGISTRY_ID, size, paletteBlock, GameProfileSerializer::d); - Object[] currArray = ((Object[]) BukkitQueue_1_13.fieldLinearBlocks.get(currentPalette)); - Object[] newArray = ((Object[]) BukkitQueue_1_13.fieldLinearBlocks.get(newPalette)); - BukkitQueue_1_13.fieldLinearIndex.set(newPalette, BukkitQueue_1_13.fieldLinearIndex.get(currentPalette)); - for (int i = 0; i < newArray.length; i++) newArray[i] = currArray[i]; - } - - BukkitQueue_1_13.fieldPalette.set(paletteBlock, newPalette); - // Clone size - BukkitQueue_1_13.fieldSize.set(paletteBlock, size); - // Clone palette - DataBits currentBits = (DataBits) BukkitQueue_1_13.fieldBits.get(current); - DataBits newBits = new DataBits(currentBits.c(), currentBits.b(), currentBits.a().clone()); - BukkitQueue_1_13.fieldBits.set(paletteBlock, newBits); - - // TODO copy only if different - Object defaultBlock = BukkitQueue_1_13.fieldDefaultBlock.get(current); - if (defaultBlock != AIR) { - ReflectionUtils.setFailsafeFieldValue(BukkitQueue_1_13.fieldDefaultBlock, paletteBlock, BukkitQueue_1_13.fieldDefaultBlock.get(current)); - } - - return paletteBlock; - } - - @Override - public IntFaweChunk copy(boolean shallow) { - BukkitChunk_1_13 copy; - if (shallow) { - copy = new BukkitChunk_1_13(getParent(), getX(), getZ(), setBlocks, count, air); - copy.biomes = biomes; - copy.chunk = chunk; - } else { - copy = new BukkitChunk_1_13(getParent(), getX(), getZ(), (int[][]) MainUtil.copyNd(setBlocks), count.clone(), air.clone()); - copy.biomes = biomes != null ? biomes.clone() : null; - copy.chunk = chunk; - } - if (sectionPalettes != null) { - copy.sectionPalettes = new ChunkSection[16]; - try { - for (int i = 0; i < sectionPalettes.length; i++) { - ChunkSection current = sectionPalettes[i]; - if (current == null) { - continue; - } - copy.sectionPalettes[i] = copy(current); - } - } catch (Throwable e) { - e.printStackTrace(); - } - } - return copy; - } - - private DataPaletteBlock newDataPaletteBlock() { - return new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::d, GameProfileSerializer::a, Blocks.AIR.getBlockData()); - } - - @Override - public Chunk getNewChunk() { - return getParent().getWorld().getChunkAt(getX(), getZ()); - } - - public void optimize() { - if (sectionPalettes != null) { - return; - } - int[][] arrays = getCombinedIdArrays(); - for (int layer = 0; layer < 16; layer++) { - if (getCount(layer) > 0) { - if (sectionPalettes == null) { - sectionPalettes = new ChunkSection[16]; - } - int[] array = arrays[layer]; - sectionPalettes[layer] = BukkitQueue_1_13.newChunkSection(layer, getParent().hasSky(), array); - } - } - } - - @Override - public void start() { - getChunk().load(true); - } - - private void removeEntity(Entity entity) { - entity.b(false); - entity.die(); - entity.valid = false; - } - - @Override - public FaweChunk call() { - Spigot_v1_13_R2 adapter = (Spigot_v1_13_R2) BukkitQueue_0.getAdapter(); - try { - BukkitChunk_1_13 copy = getParent().getChangeTask() != null ? new BukkitChunk_1_13(getParent(), getX(), getZ()) : null; - final Chunk chunk = this.getChunk(); - final World world = chunk.getWorld(); - Settings settings = getParent().getSettings(); - int bx = this.getX() << 4; - int bz = this.getZ() << 4; - final boolean flag = world.getEnvironment() == World.Environment.NORMAL; - net.minecraft.server.v1_13_R2.Chunk nmsChunk = ((CraftChunk) chunk).getHandle(); - nmsChunk.f(true); // Set Modified - nmsChunk.mustSave = true; - nmsChunk.markDirty(); - net.minecraft.server.v1_13_R2.World nmsWorld = nmsChunk.world; - ChunkSection[] sections = nmsChunk.getSections(); - List[] entities = nmsChunk.getEntitySlices(); - Map tiles = nmsChunk.getTileEntities(); - // Remove entities - HashSet entsToRemove = this.getEntityRemoves(); - if (!entsToRemove.isEmpty()) { - for (Collection ents : entities) { - if (!ents.isEmpty()) { - Iterator iter = ents.iterator(); - while (iter.hasNext()) { - Entity entity = iter.next(); - if (entsToRemove.contains(entity.getUniqueID())) { - if (copy != null) { - copy.storeEntity(entity); - } - iter.remove(); - synchronized (BukkitQueue_0.class) { - removeEntity(entity); - } - } - } - } - } - } - for (int i = 0; i < entities.length; i++) { - int count = this.getCount(i); - if (count == 0 || settings.EXPERIMENTAL.KEEP_ENTITIES_IN_BLOCKS) { - continue; - } else if (count >= 4096) { - Collection ents = entities[i]; - if (!ents.isEmpty()) { - synchronized (BukkitQueue_0.class) { - Iterator iter = ents.iterator(); - while (iter.hasNext()) { - Entity entity = iter.next(); - if (entity instanceof EntityPlayer) { - continue; - } - iter.remove(); - if (copy != null) { - copy.storeEntity(entity); - } - removeEntity(entity); - } - } - } - } else { - Collection ents = entities[i]; - if (!ents.isEmpty()) { - int layerYStart = i << 4; - int layerYEnd = layerYStart + 15; - int[] array = this.getIdArray(i); - if (array == null) continue; - Iterator iter = ents.iterator(); - while (iter.hasNext()) { - Entity entity = iter.next(); - if (entity instanceof EntityPlayer) { - continue; - } - int y = MathMan.roundInt(entity.locY); - if (y > layerYEnd || y < layerYStart) continue; - int x = (MathMan.roundInt(entity.locX) & 15); - int z = (MathMan.roundInt(entity.locZ) & 15); - - int index = (((y & 0xF) << 8) | (z << 4) | x); - if (array[index] != 0) { - if (copy != null) { - copy.storeEntity(entity); - } - iter.remove(); - synchronized (BukkitQueue_0.class) { - removeEntity(entity); - } - } - } - } - } - } - // Set entities - Set entitiesToSpawn = this.getEntities(); - if (!entitiesToSpawn.isEmpty()) { - synchronized (BukkitQueue_0.class) { - for (CompoundTag nativeTag : entitiesToSpawn) { - Map entityTagMap = ReflectionUtils.getMap(nativeTag.getValue()); - StringTag idTag = (StringTag) entityTagMap.get("Id"); - ListTag posTag = (ListTag) entityTagMap.get("Pos"); - ListTag rotTag = (ListTag) entityTagMap.get("Rotation"); - if (idTag == null || posTag == null || rotTag == null) { - Fawe.debug("Unknown entity tag: " + nativeTag); - continue; - } - double x = posTag.getDouble(0); - double y = posTag.getDouble(1); - double z = posTag.getDouble(2); - float yaw = rotTag.getFloat(0); - float pitch = rotTag.getFloat(1); - String id = idTag.getValue(); - Entity entity = EntityTypes.a(nmsWorld, new MinecraftKey(id)); - if (entity != null) { - UUID uuid = entity.getUniqueID(); - entityTagMap.put("UUIDMost", new LongTag(uuid.getMostSignificantBits())); - entityTagMap.put("UUIDLeast", new LongTag(uuid.getLeastSignificantBits())); - NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_13.fromNative(nativeTag); - for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { - tag.remove(name); - } - entity.f(tag); - entity.setLocation(x, y, z, yaw, pitch); - synchronized (BukkitQueue_0.class) { - nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM); - } - } - } - } - } - // Set blocks - for (int j = 0; j < sections.length; j++) { - int count = this.getCount(j); - if (count == 0) { - continue; - } - int countAir = this.getAir(j); - final int[] array = this.getIdArray(j); - if (array == null) { - continue; - } - ChunkSection section = sections[j]; - if (copy != null) { - if (section != null) { - copy.storeSection(copy(section), j); - } - } - if (section == null) { - if (count == countAir) { - continue; - } - if (this.sectionPalettes != null && this.sectionPalettes[j] != null) { - section = sections[j] = this.sectionPalettes[j]; - continue; - } else { - section = sections[j] = getParent().newChunkSection(j, flag, array); - continue; - } - } else if (count >= 4096 && false) { - if (countAir >= 4096) { - sections[j] = null; - continue; - } - if (this.sectionPalettes != null && this.sectionPalettes[j] != null) { - section = sections[j] = this.sectionPalettes[j]; - continue; - } else { - section = sections[j] = getParent().newChunkSection(j, flag, array); - continue; - } - } - int by = j << 4; - DataPaletteBlock nibble = section.getBlocks(); - int nonEmptyBlockCount = 0; - IBlockData existing; - - for (int y = 0, i = 0; y < 16; y++) { - for (int z = 0; z < 16; z++) { - for (int x= 0; x < 16; x++, i++) { - int combinedId = array[i]; - switch (combinedId) { - case 0: - continue; - case BlockID.AIR: - case BlockID.CAVE_AIR: - case BlockID.VOID_AIR: - existing = nibble.a(x, y, z); - if (!existing.isAir()) { - if (existing.e() > 0) { - getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z); - } - nonEmptyBlockCount--; - nibble.setBlock(x, y, z, AIR); - } - continue; - default: - existing = nibble.a(x, y, z); - if (!existing.isAir()) { - if (existing.e() > 0) { - getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z); - } - } else { - nonEmptyBlockCount++; - } - BlockState state = BlockState.getFromInternalId(combinedId); - IBlockData ibd = ((BlockMaterial_1_13) state.getMaterial()).getState(); - nibble.setBlock(x, y, z, ibd); - } - } - } - } - getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section); - } - - // Trim tiles - HashMap toRemove = null; - if (!tiles.isEmpty()) { - for (Map.Entry tile : tiles.entrySet()) { - BlockPosition pos = tile.getKey(); - int lx = pos.getX() & 15; - int ly = pos.getY(); - int lz = pos.getZ() & 15; - int layer = ly >> 4; - int[] array = this.getIdArray(layer); - if (array == null) { - continue; - } - int index = (((ly & 0xF) << 8) | (lz << 4) | lx); - if (array[index] != 0) { - if (toRemove == null) { - toRemove = new HashMap<>(); - } - if (copy != null) { - copy.storeTile(tile.getValue(), tile.getKey()); - } - toRemove.put(tile.getKey(), tile.getValue()); - } - } - if (toRemove != null) { - synchronized (BukkitQueue_0.class) { - for (Map.Entry entry : toRemove.entrySet()) { - BlockPosition bp = entry.getKey(); - TileEntity tile = entry.getValue(); - nmsWorld.n(bp); - tiles.remove(bp); - tile.z(); - tile.invalidateBlockCache(); - } - } - } - } - - // Set biomes - if (this.biomes != null) { - BiomeBase[] currentBiomes = nmsChunk.getBiomeIndex(); - if (copy != null) { - copy.storeBiomes(currentBiomes); - } - for (int i = 0 ; i < this.biomes.length; i++) { - BiomeType biome = this.biomes[i]; - if (biome != null) { - Biome craftBiome = adapter.adapt(biome); - currentBiomes[i] = CraftBlock.biomeToBiomeBase(craftBiome); - } - } - } - // Set tiles - Map tilesToSpawn = this.getTiles(); - if (!tilesToSpawn.isEmpty()) { - for (Map.Entry entry : tilesToSpawn.entrySet()) { - CompoundTag nativeTag = entry.getValue(); - short blockHash = entry.getKey(); - int x = (blockHash >> 12 & 0xF) + bx; - int y = (blockHash & 0xFF); - int z = (blockHash >> 8 & 0xF) + bz; - BlockPosition pos = new BlockPosition(x, y, z); // Set pos - synchronized (BukkitQueue_0.class) { - TileEntity tileEntity = nmsWorld.getTileEntity(pos); - if (tileEntity != null) { - NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_13.fromNative(nativeTag); - tag.set("x", new NBTTagInt(x)); - tag.set("y", new NBTTagInt(y)); - tag.set("z", new NBTTagInt(z)); - tileEntity.load(tag); - } - } - } - } - // Change task - if (copy != null) { - getParent().getChangeTask().run(copy, this); - } - } catch (Throwable e) { - e.printStackTrace(); - } - return this; - } -} \ No newline at end of file diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/BukkitQueue_1_13.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/BukkitQueue_1_13.java deleted file mode 100644 index 05c0609e0..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/BukkitQueue_1_13.java +++ /dev/null @@ -1,721 +0,0 @@ -package com.boydti.fawe.bukkit.v1_13; - -import com.boydti.fawe.FaweCache; -import com.boydti.fawe.bukkit.BukkitPlayer; -import com.boydti.fawe.bukkit.adapter.v1_13_1.BlockMaterial_1_13; -import com.boydti.fawe.bukkit.adapter.v1_13_1.Spigot_v1_13_R2; -import com.boydti.fawe.bukkit.v0.BukkitQueue_0; -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.example.IntFaweChunk; -import com.boydti.fawe.jnbt.anvil.BitArray4096; -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.FawePlayer; -import com.boydti.fawe.object.RegionWrapper; -import com.boydti.fawe.object.brush.visualization.VisualChunk; -import com.boydti.fawe.object.visitor.FaweChunkVisitor; -import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.TaskManager; - -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BlockID; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockTypes; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import net.minecraft.server.v1_13_R2.*; -import org.bukkit.Chunk; -import org.bukkit.World; -import org.bukkit.craftbukkit.v1_13_R2.CraftChunk; -import org.bukkit.craftbukkit.v1_13_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_13_R2.block.CraftBlock; -import org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.atomic.LongAdder; - -public class BukkitQueue_1_13 extends BukkitQueue_0 { - - final static Field fieldBits; - final static Field fieldPalette; - final static Field fieldSize; - - final static Field fieldHashBlocks; - final static Field fieldLinearBlocks; - private final static Field fieldHashIndex; - final static Field fieldRegistryb; - final static Field fieldRegistryc; - final static Field fieldRegistryd; - final static Field fieldRegistrye; - final static Field fieldRegistryf; - - final static Field fieldLinearIndex; - final static Field fieldDefaultBlock; - - private final static Field fieldFluidCount; - final static Field fieldTickingBlockCount; - final static Field fieldNonEmptyBlockCount; - final static Field fieldSection; - final static Field fieldLiquidCount; - private final static ChunkSection emptySection; - - private final static Field fieldDirtyCount; - private final static Field fieldDirtyBits; - - static { - try { - emptySection = new ChunkSection(0, true); - Arrays.fill(emptySection.getSkyLightArray().asBytes(), (byte) 255); - fieldSection = ChunkSection.class.getDeclaredField("blockIds"); - fieldLiquidCount = ChunkSection.class.getDeclaredField("e"); - fieldSection.setAccessible(true); - fieldLiquidCount.setAccessible(true); - - fieldFluidCount = ChunkSection.class.getDeclaredField("e"); - fieldTickingBlockCount = ChunkSection.class.getDeclaredField("tickingBlockCount"); - fieldNonEmptyBlockCount = ChunkSection.class.getDeclaredField("nonEmptyBlockCount"); - fieldFluidCount.setAccessible(true); - fieldTickingBlockCount.setAccessible(true); - fieldNonEmptyBlockCount.setAccessible(true); - - fieldHashBlocks = DataPaletteHash.class.getDeclaredField("b"); - fieldHashBlocks.setAccessible(true); - fieldLinearBlocks = DataPaletteLinear.class.getDeclaredField("b"); - fieldLinearBlocks.setAccessible(true); - - fieldHashIndex = DataPaletteHash.class.getDeclaredField("f"); - fieldHashIndex.setAccessible(true); - - fieldRegistryb = RegistryID.class.getDeclaredField("b"); - fieldRegistryc = RegistryID.class.getDeclaredField("c"); - fieldRegistryd = RegistryID.class.getDeclaredField("d"); - fieldRegistrye = RegistryID.class.getDeclaredField("e"); - fieldRegistryf = RegistryID.class.getDeclaredField("f"); - fieldRegistryb.setAccessible(true); - fieldRegistryc.setAccessible(true); - fieldRegistryd.setAccessible(true); - fieldRegistrye.setAccessible(true); - fieldRegistryf.setAccessible(true); - - fieldLinearIndex = DataPaletteLinear.class.getDeclaredField("f"); - fieldLinearIndex.setAccessible(true); - - fieldDefaultBlock = DataPaletteBlock.class.getDeclaredField("g"); - fieldDefaultBlock.setAccessible(true); - - fieldSize = DataPaletteBlock.class.getDeclaredField("i"); - fieldSize.setAccessible(true); - - fieldBits = DataPaletteBlock.class.getDeclaredField("a"); - fieldBits.setAccessible(true); - - fieldPalette = DataPaletteBlock.class.getDeclaredField("h"); - fieldPalette.setAccessible(true); - - fieldDirtyCount = PlayerChunk.class.getDeclaredField("dirtyCount"); - fieldDirtyBits = PlayerChunk.class.getDeclaredField("h"); - fieldDirtyCount.setAccessible(true); - fieldDirtyBits.setAccessible(true); - - System.out.println("Using adapter: " + getAdapter()); - System.out.println("========================================="); - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - - public BukkitQueue_1_13(final com.sk89q.worldedit.world.World world) { - super(world); - getImpWorld(); - } - - public BukkitQueue_1_13(final String world) { - super(world); - getImpWorld(); - } - - private boolean save(net.minecraft.server.v1_13_R2.Chunk chunk, ChunkProviderServer cps) { - cps.saveChunk(chunk, false); - chunk.a(false); - return true; - } - - @Override - public ChunkSection[] getSections(net.minecraft.server.v1_13_R2.Chunk chunk) { - return chunk.getSections(); - } - - @Override - public net.minecraft.server.v1_13_R2.Chunk loadChunk(World world, int x, int z, boolean generate) { - ChunkProviderServer provider = ((CraftWorld) world).getHandle().getChunkProvider(); - if (generate) { - return provider.getChunkAt(x, z, true, true); - } else { - return provider.getChunkAt(x, z, true, false); - } - } - - @Override - public ChunkSection[] getCachedSections(World world, int cx, int cz) { - net.minecraft.server.v1_13_R2.Chunk chunk = ((CraftWorld) world).getHandle().getChunkProvider().getChunkAt(cx, cz, false, false); - if (chunk != null) { - return chunk.getSections(); - } - return null; - } - - @Override - public net.minecraft.server.v1_13_R2.Chunk getCachedChunk(World world, int cx, int cz) { - return ((CraftWorld) world).getHandle().getChunkProvider().getChunkAt(cx, cz, false, false); - } - - @Override - public ChunkSection getCachedSection(ChunkSection[] chunkSections, int cy) { - return chunkSections[cy]; - } - - @Override - public void saveChunk(net.minecraft.server.v1_13_R2.Chunk chunk) { - chunk.f(true); // Set Modified - chunk.mustSave = true; - } - - @Override - public boolean regenerateChunk(World world, int x, int z, BiomeType biome, Long seed) { - return super.regenerateChunk(world, x, z, biome, seed); - } - - @Override - public boolean setMCA(final int mcaX, final int mcaZ, final RegionWrapper allowed, final Runnable whileLocked, final boolean saveChunks, final boolean load) { - throw new UnsupportedOperationException("Anvil not implemented yet"); -// TaskManager.IMP.sync(new RunnableVal() { -// @Override -// public void run(Boolean value) { -// long start = System.currentTimeMillis(); -// long last = start; -// synchronized (RegionFileCache.class) { -// World world = getWorld(); -// if (world.getKeepSpawnInMemory()) world.setKeepSpawnInMemory(false); -// ChunkProviderServer provider = nmsWorld.getChunkProvider(); -// -// boolean mustSave = false; -// boolean[][] chunksUnloaded = null; -// { // Unload chunks -// Iterator iter = provider.a().iterator(); -// while (iter.hasNext()) { -// net.minecraft.server.v1_13_R2.Chunk chunk = iter.next(); -// if (chunk.locX >> 5 == mcaX && chunk.locZ >> 5 == mcaZ) { -// boolean isIn = allowed.isInChunk(chunk.locX, chunk.locZ); -// if (isIn) { -// if (!load) { -// mustSave |= saveChunks && save(chunk, provider); -// continue; -// } -// iter.remove(); -// boolean save = saveChunks && chunk.a(false); -// mustSave |= save; -// provider.unloadChunk(chunk, save); -// if (chunksUnloaded == null) { -// chunksUnloaded = new boolean[32][]; -// } -// int relX = chunk.locX & 31; -// boolean[] arr = chunksUnloaded[relX]; -// if (arr == null) { -// arr = chunksUnloaded[relX] = new boolean[32]; -// } -// arr[chunk.locZ & 31] = true; -// } -// } -// } -// } -// if (mustSave) { -// provider.c(); // TODO only the necessary chunks -// } -// -// File unloadedRegion = null; -// if (load && !RegionFileCache.a.isEmpty()) { -// Map map = RegionFileCache.a; -// Iterator> iter = map.entrySet().iterator(); -// String requiredPath = world.getName() + File.separator + "region"; -// while (iter.hasNext()) { -// Map.Entry entry = iter.next(); -// File file = entry.getKey(); -// int[] regPos = MainUtil.regionNameToCoords(file.getPath()); -// if (regPos[0] == mcaX && regPos[1] == mcaZ && file.getPath().contains(requiredPath)) { -// if (file.exists()) { -// unloadedRegion = file; -// RegionFile regionFile = entry.getValue(); -// iter.remove(); -// try { -// regionFile.c(); -// } catch (IOException e) { -// e.printStackTrace(); -// } -// } -// break; -// } -// } -// } -// -// long now = System.currentTimeMillis(); -// if (whileLocked != null) whileLocked.run(); -// if (!load) return; -// -// { // Load the region again -// if (unloadedRegion != null && chunksUnloaded != null && unloadedRegion.exists()) { -// final boolean[][] finalChunksUnloaded = chunksUnloaded; -// TaskManager.IMP.async(() -> { -// int bx = mcaX << 5; -// int bz = mcaZ << 5; -// for (int x = 0; x < finalChunksUnloaded.length; x++) { -// boolean[] arr = finalChunksUnloaded[x]; -// if (arr != null) { -// for (int z = 0; z < arr.length; z++) { -// if (arr[z]) { -// int cx = bx + x; -// int cz = bz + z; -// SetQueue.IMP.addTask(new Runnable() { -// @Override -// public void run() { -// net.minecraft.server.v1_13_R2.Chunk chunk = provider.getChunkAt(cx, cz, null, false); -// if (chunk != null) { -// PlayerChunk pc = getPlayerChunk(nmsWorld, cx, cz); -// if (pc != null) { -// sendChunk(pc, chunk, 0); -// } -// } -// } -// }); -// } -// } -// } -// } -// }); -// } -// } -// } -// } -// }); -// return true; - } - - @Override - public boolean next(int amount, long time) { - return super.next(amount, time); - } - - @Override - public void setSkyLight(ChunkSection section, int x, int y, int z, int value) { - section.getSkyLightArray().a(x & 15, y & 15, z & 15, value); - } - - @Override - public void setBlockLight(ChunkSection section, int x, int y, int z, int value) { - section.getEmittedLightArray().a(x & 15, y & 15, z & 15, value); - } - - @Override - public int getCombinedId4Data(ChunkSection lastSection, int x, int y, int z) { - DataPaletteBlock dataPalette = lastSection.getBlocks(); - IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); - int ordinal = ((Spigot_v1_13_R2) getAdapter()).adaptToInt(ibd); - return BlockTypes.states[ordinal].getInternalId(); - } - - @Override - public BiomeType getBiome(net.minecraft.server.v1_13_R2.Chunk chunk, int x, int z) { - BiomeBase base = chunk.getBiomeIndex()[((z & 15) << 4) + (x & 15)]; - return getAdapter().adapt(CraftBlock.biomeBaseToBiome(base)); - } - - @Override - public int getOpacity(ChunkSection section, int x, int y, int z) { - DataPaletteBlock dataPalette = section.getBlocks(); - IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); - pos.a(x, y, z); - return ibd.b(nmsWorld, pos); - } - - @Override - public int getBrightness(ChunkSection section, int x, int y, int z) { - DataPaletteBlock dataPalette = section.getBlocks(); - IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); - return ibd.e(); - } - - @Override - public int getOpacityBrightnessPair(ChunkSection section, int x, int y, int z) { - DataPaletteBlock dataPalette = section.getBlocks(); - IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); - pos.a(x, y, z); - int opacity = ibd.b(nmsWorld, pos); - int brightness = ibd.e(); - return MathMan.pair16(brightness, opacity); - } - - @Override - public void sendChunk(int x, int z, int bitMask) { - net.minecraft.server.v1_13_R2.Chunk chunk = getCachedChunk(getWorld(), x, z); - if (chunk != null) { - sendChunk(getPlayerChunk((WorldServer) chunk.getWorld(), chunk.locX, chunk.locZ), chunk, bitMask); - } - } - - @Override - public void sendChunkUpdatePLIB(FaweChunk chunk, FawePlayer... players) { -// PlayerChunkMap playerManager = ((CraftWorld) getWorld()).getHandle().getPlayerChunkMap(); -// ProtocolManager manager = ProtocolLibrary.getProtocolManager(); -// WirePacket packet = null; -// try { -// for (int i = 0; i < players.length; i++) { -// CraftPlayer bukkitPlayer = ((CraftPlayer) ((BukkitPlayer) players[i]).parent); -// EntityPlayer player = bukkitPlayer.getHandle(); -// -// if (playerManager.a(player, chunk.getX(), chunk.getZ())) { -// if (packet == null) { -// byte[] data; -// byte[] buffer = new byte[8192]; -// if (chunk instanceof LazyFaweChunk) { -// chunk = (FaweChunk) chunk.getChunk(); -// } -// if (chunk instanceof MCAChunk) { -// data = new MCAChunkPacket((MCAChunk) chunk, true, true, hasSky()).apply(buffer); -// } else { -// data = new FaweChunkPacket(chunk, true, true, hasSky()).apply(buffer); -// } -// packet = new WirePacket(PacketType.Play.Server.MAP_CHUNK, data); -// } -// manager.sendWirePacket(bukkitPlayer, packet); -// } -// } -// } catch (InvocationTargetException e) { -// throw new RuntimeException(e); -// } - super.sendChunkUpdatePLIB(chunk, players); // TODO remove - } - - @Override - public void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) { - try { - PlayerChunkMap playerManager = ((CraftWorld) getWorld()).getHandle().getPlayerChunkMap(); - boolean watching = false; - boolean[] watchingArr = new boolean[players.length]; - for (int i = 0; i < players.length; i++) { - EntityPlayer player = ((CraftPlayer) ((BukkitPlayer) players[i]).parent).getHandle(); - if (playerManager.a(player, chunk.getX(), chunk.getZ())) { - watchingArr[i] = true; - watching = true; - } - } - if (!watching) return; - final LongAdder size = new LongAdder(); - if (chunk instanceof VisualChunk) { - size.add(((VisualChunk) chunk).size()); - } else if (chunk instanceof IntFaweChunk) { - size.add(((IntFaweChunk) chunk).getTotalCount()); - } else { - chunk.forEachQueuedBlock(new FaweChunkVisitor() { - @Override - public void run(int localX, int y, int localZ, int combined) { - size.add(1); - } - }); - } - if (size.intValue() == 0) return; - PacketPlayOutMultiBlockChange packet = new PacketPlayOutMultiBlockChange(); - ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer(); - final PacketDataSerializer buffer = new PacketDataSerializer(byteBuf); - buffer.writeInt(chunk.getX()); - buffer.writeInt(chunk.getZ()); - buffer.d(size.intValue()); - chunk.forEachQueuedBlock(new FaweChunkVisitor() { - @Override - public void run(int localX, int y, int localZ, int combined) { - short index = (short) (localX << 12 | localZ << 8 | y); - if (combined < 16) combined = 0; - buffer.writeShort(index); - buffer.d(combined); - } - }); - packet.a(buffer); - for (int i = 0; i < players.length; i++) { - if (watchingArr[i]) ((CraftPlayer) ((BukkitPlayer) players[i]).parent).getHandle().playerConnection.sendPacket(packet); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void refreshChunk(FaweChunk fc) { - sendChunk(fc.getX(), fc.getZ(), fc.getBitMask()); - } - - public void sendPacket(int cx, int cz, Packet packet) { - PlayerChunk chunk = getPlayerChunk(nmsWorld, cx, cz); - if (chunk != null) { - for (EntityPlayer player : chunk.players) { - player.playerConnection.sendPacket(packet); - } - } - } - - private PlayerChunk getPlayerChunk(WorldServer w, int cx, int cz) { - PlayerChunkMap chunkMap = w.getPlayerChunkMap(); - PlayerChunk playerChunk = chunkMap.getChunk(cx, cz); - if (playerChunk == null) { - return null; - } - if (playerChunk.players.isEmpty()) { - return null; - } - return playerChunk; - } - - private boolean sendChunk(PlayerChunk playerChunk, net.minecraft.server.v1_13_R2.Chunk nmsChunk, int mask) { - if (playerChunk == null) { - return false; - } - if (playerChunk.e()) { - ChunkSection[] sections = nmsChunk.getSections(); - for (int layer = 0; layer < 16; layer++) { - if (sections[layer] == null && (mask & (1 << layer)) != 0) { - sections[layer] = new ChunkSection(layer << 4, nmsWorld.worldProvider.g()); - } - } - TaskManager.IMP.sync(() -> { - try { - int dirtyBits = fieldDirtyBits.getInt(playerChunk); - if (dirtyBits == 0) { - ((CraftWorld) getWorld()).getHandle().getPlayerChunkMap().a(playerChunk); - } - if (mask == 0) { - dirtyBits = 65535; - } else { - dirtyBits |= mask; - } - - fieldDirtyBits.set(playerChunk, dirtyBits); - fieldDirtyCount.set(playerChunk, 64); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - return null; - }); - } - return true; - } - - public boolean hasEntities(net.minecraft.server.v1_13_R2.Chunk nmsChunk) { - try { - final Collection[] entities = nmsChunk.entitySlices; - for (Collection slice : entities) { - if (slice != null && !slice.isEmpty()) { - return true; - } - } - } catch (Throwable ignore) {} - return false; - } - - @Override - public boolean removeSectionLighting(ChunkSection section, int layer, boolean sky) { - if (section != null) { - Arrays.fill(section.getEmittedLightArray().asBytes(), (byte) 0); - if (sky) { - byte[] light = section.getSkyLightArray().asBytes(); - if (light != null) { - Arrays.fill(light, (byte) 0); - } - } - return true; - } - return false; - } - - @Override - public void setFullbright(ChunkSection[] sections) { - for (ChunkSection section : sections) { - if (section != null) { - byte[] bytes = section.getSkyLightArray().asBytes(); - Arrays.fill(bytes, (byte) 255); - } - } - } - - @Override - public int getSkyLight(ChunkSection section, int x, int y, int z) { - return section.c(x & 15, y & 15, z & 15); - } - - @Override - public int getEmmittedLight(ChunkSection section, int x, int y, int z) { - return section.d(x & 15, y & 15, z & 15); - } - - @Override - public void relightBlock(int x, int y, int z) { - pos.c(x, y, z); - nmsWorld.c(EnumSkyBlock.BLOCK, pos); - } - - @Override - public void relightSky(int x, int y, int z) { - pos.c(x, y, z); - nmsWorld.c(EnumSkyBlock.SKY, pos); - } - - @Override - public void relight(int x, int y, int z) { - pos.c(x, y, z); - nmsWorld.r(pos); - } - - private WorldServer nmsWorld; - - @Override - public World getImpWorld() { - World world = super.getImpWorld(); - if (world != null) { - this.nmsWorld = ((CraftWorld) world).getHandle(); - return super.getImpWorld(); - } else { - return null; - } - } - - static void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException { - fieldFluidCount.set(section, 0); // TODO FIXME - fieldTickingBlockCount.set(section, tickingBlockCount); - fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount); - } - - int getNonEmptyBlockCount(ChunkSection section) throws IllegalAccessException { - return (int) fieldNonEmptyBlockCount.get(section); - } - - public void setPalette(ChunkSection section, DataPaletteBlock palette) throws NoSuchFieldException, IllegalAccessException { - fieldSection.set(section, palette); - Arrays.fill(section.getEmittedLightArray().asBytes(), (byte) 0); - } - - static ChunkSection newChunkSection(int y2, boolean flag, int[] blocks) { - ChunkSection section = new ChunkSection(y2 << 4, flag); - if (blocks == null) { - return section; - } - int[] blockToPalette = FaweCache.BLOCK_TO_PALETTE.get(); - int[] paletteToBlock = FaweCache.PALETTE_TO_BLOCK.get(); - long[] blockstates = FaweCache.BLOCK_STATES.get(); - int[] blocksCopy = FaweCache.SECTION_BLOCKS.get(); - try { - int num_palette = 0; - int air = 0; - for (int i = 0; i < 4096; i++) { - int stateId = blocks[i]; - switch (stateId) { - case 0: - case BlockID.AIR: - case BlockID.CAVE_AIR: - case BlockID.VOID_AIR: - stateId = BlockID.AIR; - air++; - } - int ordinal = BlockState.getFromInternalId(stateId).getOrdinal(); // TODO fixme Remove all use of BlockTypes.BIT_OFFSET so that this conversion isn't necessary - int palette = blockToPalette[ordinal]; - if (palette == Integer.MAX_VALUE) { - blockToPalette[ordinal] = palette = num_palette; - paletteToBlock[num_palette] = ordinal; - num_palette++; - } - blocksCopy[i] = palette; - } - - // BlockStates - int bitsPerEntry = MathMan.log2nlz(num_palette - 1); - if (Settings.IMP.PROTOCOL_SUPPORT_FIX || num_palette != 1) { - bitsPerEntry = Math.max(bitsPerEntry, 4); // Protocol support breaks <4 bits per entry - } else { - bitsPerEntry = Math.max(bitsPerEntry, 1); // For some reason minecraft needs 4096 bits to store 0 entries - } - - int blockBitArrayEnd = (bitsPerEntry * 4096) >> 6; - if (num_palette == 1) { - for (int i = 0; i < blockBitArrayEnd; i++) blockstates[i] = 0; - } else { - BitArray4096 bitArray = new BitArray4096(blockstates, bitsPerEntry); - bitArray.fromRaw(blocksCopy); - } - - // set palette & data bits - DataPaletteBlock dataPaletteBlocks = section.getBlocks(); - // private DataPalette h; - // protected DataBits a; - long[] bits = Arrays.copyOfRange(blockstates, 0, blockBitArrayEnd); - DataBits nmsBits = new DataBits(bitsPerEntry, 4096, bits); - DataPalette palette = new DataPaletteLinear<>(Block.REGISTRY_ID, bitsPerEntry, dataPaletteBlocks, GameProfileSerializer::d); - - // set palette - for (int i = 0; i < num_palette; i++) { - int ordinal = paletteToBlock[i]; - blockToPalette[ordinal] = Integer.MAX_VALUE; - BlockState state = BlockTypes.states[ordinal]; - IBlockData ibd = ((BlockMaterial_1_13) state.getMaterial()).getState(); - palette.a(ibd); - } - try { - fieldBits.set(dataPaletteBlocks, nmsBits); - fieldPalette.set(dataPaletteBlocks, palette); - fieldSize.set(dataPaletteBlocks, bitsPerEntry); - setCount(0, 4096 - air, section); - } catch (IllegalAccessException | NoSuchFieldException e) { - throw new RuntimeException(e); - } - - return section; - } catch (Throwable e){ - Arrays.fill(blockToPalette, Integer.MAX_VALUE); - throw e; - } - } - - protected BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0); - - @Override - public CompoundTag getTileEntity(net.minecraft.server.v1_13_R2.Chunk chunk, int x, int y, int z) { - Map tiles = chunk.getTileEntities(); - pos.c(x, y, z); - TileEntity tile = tiles.get(pos); - return tile != null ? getTag(tile) : null; - } - - CompoundTag getTag(TileEntity tile) { - try { - NBTTagCompound tag = new NBTTagCompound(); - tile.save(tag); // readTagIntoEntity - return (CompoundTag) toNative(tag); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - @Deprecated - public boolean unloadChunk(final String world, final Chunk chunk) { - net.minecraft.server.v1_13_R2.Chunk c = ((CraftChunk) chunk).getHandle(); - c.mustSave = false; - if (chunk.isLoaded()) { - chunk.unload(false); - } - return true; - } - - @Override - public BukkitChunk_1_13 getFaweChunk(int x, int z) { - return new BukkitChunk_1_13(this, x, z); - } -} \ No newline at end of file diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_14/BukkitChunk_1_14.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_14/BukkitChunk_1_14.java deleted file mode 100644 index ed2041bec..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_14/BukkitChunk_1_14.java +++ /dev/null @@ -1,617 +0,0 @@ -package com.boydti.fawe.bukkit.v1_14; - -import com.boydti.fawe.Fawe; -import com.boydti.fawe.bukkit.v0.BukkitQueue_0; -import com.boydti.fawe.bukkit.v1_14.adapter.BlockMaterial_1_14; -import com.boydti.fawe.bukkit.v1_14.adapter.Spigot_v1_14_R1; -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.example.IntFaweChunk; -import com.boydti.fawe.jnbt.anvil.BitArray4096; -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.FaweQueue; -import com.boydti.fawe.util.MainUtil; -import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.ReflectionUtils; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.LongTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.internal.Constants; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BlockID; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockTypes; -import net.minecraft.server.v1_14_R1.BiomeBase; -import net.minecraft.server.v1_14_R1.Block; -import net.minecraft.server.v1_14_R1.BlockPosition; -import net.minecraft.server.v1_14_R1.Blocks; -import net.minecraft.server.v1_14_R1.ChunkSection; -import net.minecraft.server.v1_14_R1.DataBits; -import net.minecraft.server.v1_14_R1.DataPalette; -import net.minecraft.server.v1_14_R1.DataPaletteBlock; -import net.minecraft.server.v1_14_R1.DataPaletteHash; -import net.minecraft.server.v1_14_R1.DataPaletteLinear; -import net.minecraft.server.v1_14_R1.Entity; -import net.minecraft.server.v1_14_R1.EntityPlayer; -import net.minecraft.server.v1_14_R1.EntityTypes; -import net.minecraft.server.v1_14_R1.GameProfileSerializer; -import net.minecraft.server.v1_14_R1.IBlockData; -import net.minecraft.server.v1_14_R1.MinecraftKey; -import net.minecraft.server.v1_14_R1.NBTTagCompound; -import net.minecraft.server.v1_14_R1.NBTTagInt; -import net.minecraft.server.v1_14_R1.RegistryID; -import net.minecraft.server.v1_14_R1.TileEntity; -import org.bukkit.Chunk; -import org.bukkit.World; -import org.bukkit.block.Biome; -import org.bukkit.craftbukkit.v1_14_R1.CraftChunk; -import org.bukkit.craftbukkit.v1_14_R1.block.CraftBlock; -import org.bukkit.event.entity.CreatureSpawnEvent; - -import java.lang.reflect.InvocationTargetException; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -import static com.boydti.fawe.bukkit.v0.BukkitQueue_0.getAdapter; -import static com.boydti.fawe.bukkit.v1_14.BukkitQueue_1_14.fieldRegistryb; -import static com.boydti.fawe.bukkit.v1_14.BukkitQueue_1_14.fieldRegistryc; -import static com.boydti.fawe.bukkit.v1_14.BukkitQueue_1_14.fieldRegistryd; -import static com.boydti.fawe.bukkit.v1_14.BukkitQueue_1_14.fieldRegistrye; -import static com.boydti.fawe.bukkit.v1_14.BukkitQueue_1_14.fieldRegistryf; - -public class BukkitChunk_1_14 extends IntFaweChunk { - - public ChunkSection[] sectionPalettes; - - private static final IBlockData AIR = ((BlockMaterial_1_14) BlockTypes.AIR.getMaterial()).getState(); - - /** - * A FaweSections object represents a chunk and the blocks that you wish to change in it. - * - * @param parent - * @param x - * @param z - */ - public BukkitChunk_1_14(FaweQueue parent, int x, int z) { - super(parent, x, z); - } - - public BukkitChunk_1_14(FaweQueue parent, int x, int z, int[][] ids, short[] count, short[] air) { - super(parent, x, z, ids, count, air); - } - - public void storeBiomes(BiomeBase[] biomes) { - if (biomes != null) { - if (this.biomes == null) { - this.biomes = new BiomeType[256]; - } - for (int i = 0; i < 256; i++) { - this.biomes[i] = BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(biomes[i])); - } - } - } - - @Override - public int[][] getCombinedIdArrays() { - if (this.sectionPalettes != null) { - for (int i = 0; i < setBlocks.length; i++) { - getIdArray(i); - } - } - return this.setBlocks; - } - - @Override - public int[] getIdArray(int layer) { - if (this.setBlocks[layer] == null && this.sectionPalettes != null) { - ChunkSection section = this.sectionPalettes[layer]; - int[] idsArray = this.setBlocks[layer]; - if (section != null && idsArray == null) { - this.setBlocks[layer] = idsArray = new int[4096]; - if (!section.c()) { - try { - DataPaletteBlock blocks = section.getBlocks(); - DataBits bits = (DataBits) BukkitQueue_1_14.fieldBits.get(blocks); - DataPalette palette = (DataPalette) BukkitQueue_1_14.fieldPalette.get(blocks); - - long[] raw = bits.a(); - int bitsPerEntry = bits.c(); - - new BitArray4096(raw, bitsPerEntry).toRaw(idsArray); - IBlockData defaultBlock = (IBlockData) BukkitQueue_1_14.fieldDefaultBlock.get(blocks); - // TODO optimize away palette.a - for (int i = 0; i < 4096; i++) { - IBlockData ibd = palette.a(idsArray[i]); - if (ibd == null) { - ibd = defaultBlock; - } - int ordinal = ((Spigot_v1_14_R1) getAdapter()).adaptToInt(ibd); - idsArray[i] = BlockTypes.states[ordinal].getInternalId(); - } - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - } - } - return this.setBlocks[layer]; - } - - public boolean storeTile(TileEntity tile, BlockPosition pos) { - CompoundTag nativeTag = getParent().getTag(tile); - setTile(pos.getX() & 15, pos.getY(), pos.getZ() & 15, nativeTag); - return true; - } - - public boolean storeEntity(Entity ent) throws InvocationTargetException, IllegalAccessException { - if (ent instanceof EntityPlayer || BukkitQueue_0.getAdapter() == null) { - return false; - } - EntityTypes type = ent.getEntityType(); - MinecraftKey id = EntityTypes.getName(type); - if (id != null) { - NBTTagCompound tag = new NBTTagCompound(); - ent.save(tag); // readEntityIntoTag - CompoundTag nativeTag = (CompoundTag) BukkitQueue_0.toNative(tag); - Map map = ReflectionUtils.getMap(nativeTag.getValue()); - map.put("Id", new StringTag(id.toString())); - setEntity(nativeTag); - return true; - } else { - return false; - } - } - - public boolean storeSection(ChunkSection section, int layer) throws IllegalAccessException { - if (sectionPalettes == null) { - // TODO optimize don't copy light - sectionPalettes = new ChunkSection[16]; - } - sectionPalettes[layer] = section; - return true; - } - - public ChunkSection copy(ChunkSection current) throws IllegalAccessException, InvocationTargetException, NoSuchFieldException { - ChunkSection newSection = new ChunkSection(current.getYPosition()); - - // Copy counters - short nonEmptyBlockCount = BukkitQueue_1_14.fieldNonEmptyBlockCount.getShort(current); - BukkitQueue_1_14.fieldNonEmptyBlockCount.setShort(newSection, nonEmptyBlockCount); - - short tickingBlockCount = BukkitQueue_1_14.fieldTickingBlockCount.getShort(current); - BukkitQueue_1_14.fieldTickingBlockCount.setShort(newSection, tickingBlockCount); - - short liquidCount = BukkitQueue_1_14.fieldFluidCount.getShort(current); - BukkitQueue_1_14.fieldFluidCount.setShort(newSection, liquidCount); - - // Copy blocks - DataPaletteBlock blocks = current.getBlocks(); - DataPaletteBlock blocksCopy = copy(blocks); - BukkitQueue_1_14.fieldSection.set(newSection, blocksCopy); - - return newSection; - } - - public DataPaletteBlock copy(DataPaletteBlock current) throws IllegalAccessException, InvocationTargetException, NoSuchFieldException { - // Clone palette - DataPalette currentPalette = (DataPalette) BukkitQueue_1_14.fieldPalette.get(current); - DataPaletteBlock paletteBlock = newDataPaletteBlock(); - int size = BukkitQueue_1_14.fieldSize.getInt(current); - - DataPalette newPalette = currentPalette; - if (currentPalette instanceof DataPaletteHash) { - // TODO optimize resize - newPalette = new DataPaletteHash<>(Block.REGISTRY_ID, size, paletteBlock, GameProfileSerializer::d, GameProfileSerializer::a); - RegistryID currReg = (RegistryID) BukkitQueue_1_14.fieldHashBlocks.get(currentPalette); - RegistryID newReg = (RegistryID) BukkitQueue_1_14.fieldHashBlocks.get(newPalette); - int arrLen = 1 << size; - System.arraycopy(fieldRegistryb.get(currReg), 0, fieldRegistryb.get(newReg), 0, arrLen); - System.arraycopy(fieldRegistryc.get(currReg), 0, fieldRegistryc.get(newReg), 0, arrLen); - System.arraycopy(fieldRegistryd.get(currReg), 0, fieldRegistryd.get(newReg), 0, arrLen); - fieldRegistrye.set(newReg, fieldRegistrye.get(currReg)); - fieldRegistryf.set(newReg, fieldRegistryf.get(currReg)); - } else if (currentPalette instanceof DataPaletteLinear) { - // TODO optimize resize - newPalette = new DataPaletteLinear<>(Block.REGISTRY_ID, size, paletteBlock, GameProfileSerializer::d); - Object[] currArray = ((Object[]) BukkitQueue_1_14.fieldLinearBlocks.get(currentPalette)); - Object[] newArray = ((Object[]) BukkitQueue_1_14.fieldLinearBlocks.get(newPalette)); - BukkitQueue_1_14.fieldLinearIndex.set(newPalette, BukkitQueue_1_14.fieldLinearIndex.get(currentPalette)); - for (int i = 0; i < newArray.length; i++) newArray[i] = currArray[i]; - } - - BukkitQueue_1_14.fieldPalette.set(paletteBlock, newPalette); - // Clone size - BukkitQueue_1_14.fieldSize.set(paletteBlock, size); - // Clone palette - DataBits currentBits = (DataBits) BukkitQueue_1_14.fieldBits.get(current); - DataBits newBits = new DataBits(currentBits.c(), currentBits.b(), currentBits.a().clone()); - BukkitQueue_1_14.fieldBits.set(paletteBlock, newBits); - - // TODO copy only if different - Object defaultBlock = BukkitQueue_1_14.fieldDefaultBlock.get(current); - if (defaultBlock != AIR) { - ReflectionUtils.setFailsafeFieldValue(BukkitQueue_1_14.fieldDefaultBlock, paletteBlock, BukkitQueue_1_14.fieldDefaultBlock.get(current)); - } - - return paletteBlock; - } - - @Override - public IntFaweChunk copy(boolean shallow) { - BukkitChunk_1_14 copy; - if (shallow) { - copy = new BukkitChunk_1_14(getParent(), getX(), getZ(), setBlocks, count, air); - copy.biomes = biomes; - copy.chunk = chunk; - } else { - copy = new BukkitChunk_1_14(getParent(), getX(), getZ(), (int[][]) MainUtil.copyNd(setBlocks), count.clone(), air.clone()); - copy.biomes = biomes != null ? biomes.clone() : null; - copy.chunk = chunk; - } - if (sectionPalettes != null) { - copy.sectionPalettes = new ChunkSection[16]; - try { - for (int i = 0; i < sectionPalettes.length; i++) { - ChunkSection current = sectionPalettes[i]; - if (current == null) { - continue; - } - copy.sectionPalettes[i] = copy(current); - } - } catch (Throwable e) { - e.printStackTrace(); - } - } - return copy; - } - - private DataPaletteBlock newDataPaletteBlock() { - return new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::d, GameProfileSerializer::a, Blocks.AIR.getBlockData()); - } - - @Override - public Chunk getNewChunk() { - return ((BukkitQueue_1_14) getParent()).getWorld().getChunkAt(getX(), getZ()); - } - - public void optimize() { - if (sectionPalettes != null) { - return; - } - int[][] arrays = getCombinedIdArrays(); - for (int layer = 0; layer < 16; layer++) { - if (getCount(layer) > 0) { - if (sectionPalettes == null) { - sectionPalettes = new ChunkSection[16]; - } - int[] array = arrays[layer]; - sectionPalettes[layer] = BukkitQueue_1_14.newChunkSection(layer, getParent().hasSky(), array); - } - } - } - - @Override - public void start() { - getChunk().load(true); - } - - private void removeEntity(Entity entity) { - entity.die(); - entity.valid = false; - } - - @Override - public FaweChunk call() { - Spigot_v1_14_R1 adapter = (Spigot_v1_14_R1) BukkitQueue_0.getAdapter(); - try { - BukkitChunk_1_14 copy = getParent().getChangeTask() != null ? new BukkitChunk_1_14(getParent(), getX(), getZ()) : null; - final Chunk chunk = this.getChunk(); - final World world = chunk.getWorld(); - Settings settings = getParent().getSettings(); - int bx = this.getX() << 4; - int bz = this.getZ() << 4; - final boolean flag = world.getEnvironment() == World.Environment.NORMAL; - net.minecraft.server.v1_14_R1.Chunk nmsChunk = ((CraftChunk) chunk).getHandle(); - nmsChunk.d(true); // Set Modified - nmsChunk.mustNotSave = false; - nmsChunk.markDirty(); - net.minecraft.server.v1_14_R1.World nmsWorld = nmsChunk.world; - ChunkSection[] sections = nmsChunk.getSections(); - List[] entities = nmsChunk.getEntitySlices(); - Map tiles = nmsChunk.getTileEntities(); - // Remove entities - HashSet entsToRemove = this.getEntityRemoves(); - if (!entsToRemove.isEmpty()) { - for (int i = 0; i < entities.length; i++) { - Collection ents = entities[i]; - if (!ents.isEmpty()) { - Iterator iter = ents.iterator(); - while (iter.hasNext()) { - Entity entity = iter.next(); - if (entsToRemove.contains(entity.getUniqueID())) { - if (copy != null) { - copy.storeEntity(entity); - } - iter.remove(); - synchronized (BukkitQueue_0.class) { - removeEntity(entity); - } - } - } - } - } - } - for (int i = 0; i < entities.length; i++) { - int count = this.getCount(i); - if (count == 0 || settings.EXPERIMENTAL.KEEP_ENTITIES_IN_BLOCKS) { - continue; - } else if (count >= 4096) { - Collection ents = entities[i]; - if (!ents.isEmpty()) { - synchronized (BukkitQueue_0.class) { - Iterator iter = ents.iterator(); - while (iter.hasNext()) { - Entity entity = iter.next(); - if (entity instanceof EntityPlayer) { - continue; - } - iter.remove(); - if (copy != null) { - copy.storeEntity(entity); - } - removeEntity(entity); - } - } - } - } else { - Collection ents = entities[i]; - if (!ents.isEmpty()) { - int layerYStart = i << 4; - int layerYEnd = layerYStart + 15; - int[] array = this.getIdArray(i); - if (array == null) continue; - Iterator iter = ents.iterator(); - while (iter.hasNext()) { - Entity entity = iter.next(); - if (entity instanceof EntityPlayer) { - continue; - } - int y = MathMan.roundInt(entity.locY); - if (y > layerYEnd || y < layerYStart) continue; - int x = (MathMan.roundInt(entity.locX) & 15); - int z = (MathMan.roundInt(entity.locZ) & 15); - - int index = (((y & 0xF) << 8) | (z << 4) | x); - if (array[index] != 0) { - if (copy != null) { - copy.storeEntity(entity); - } - iter.remove(); - synchronized (BukkitQueue_0.class) { - removeEntity(entity); - } - } - } - } - } - } - // Set entities - Set entitiesToSpawn = this.getEntities(); - if (!entitiesToSpawn.isEmpty()) { - synchronized (BukkitQueue_0.class) { - for (CompoundTag nativeTag : entitiesToSpawn) { - Map entityTagMap = ReflectionUtils.getMap(nativeTag.getValue()); - StringTag idTag = (StringTag) entityTagMap.get("Id"); - ListTag posTag = (ListTag) entityTagMap.get("Pos"); - ListTag rotTag = (ListTag) entityTagMap.get("Rotation"); - if (idTag == null || posTag == null || rotTag == null) { - Fawe.debug("Unknown entity tag: " + nativeTag); - continue; - } - double x = posTag.getDouble(0); - double y = posTag.getDouble(1); - double z = posTag.getDouble(2); - float yaw = rotTag.getFloat(0); - float pitch = rotTag.getFloat(1); - String id = idTag.getValue(); - EntityTypes type = EntityTypes.a(id).orElse(null); - if (type != null) { - Entity entity = type.a(nmsWorld); - if (entity != null) { - UUID uuid = entity.getUniqueID(); - entityTagMap.put("UUIDMost", new LongTag(uuid.getMostSignificantBits())); - entityTagMap.put("UUIDLeast", new LongTag(uuid.getLeastSignificantBits())); - if (nativeTag != null) { - NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_14.fromNative(nativeTag); - for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { - tag.remove(name); - } - entity.f(tag); - } - entity.setLocation(x, y, z, yaw, pitch); - synchronized (BukkitQueue_0.class) { - nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM); - } - } - } - } - } - } - // Set blocks - for (int j = 0; j < sections.length; j++) { - int count = this.getCount(j); - if (count == 0) { - continue; - } - int countAir = this.getAir(j); - final int[] array = this.getIdArray(j); - if (array == null) { - continue; - } - ChunkSection section = sections[j]; - if (copy != null) { - if (section != null) { - copy.storeSection(copy(section), j); - } - } - if (section == null) { - if (count == countAir) { - continue; - } - if (this.sectionPalettes != null && this.sectionPalettes[j] != null) { - section = sections[j] = this.sectionPalettes[j]; - continue; - } else { - section = sections[j] = getParent().newChunkSection(j, flag, array); - continue; - } - } else if (count >= 4096 && false) { - if (countAir >= 4096) { - sections[j] = null; - continue; - } - if (this.sectionPalettes != null && this.sectionPalettes[j] != null) { - section = sections[j] = this.sectionPalettes[j]; - continue; - } else { - section = sections[j] = getParent().newChunkSection(j, flag, array); - continue; - } - } - int by = j << 4; - DataPaletteBlock nibble = section.getBlocks(); - int nonEmptyBlockCount = 0; - IBlockData existing; - - for (int y = 0, i = 0; y < 16; y++) { - for (int z = 0; z < 16; z++) { - for (int x= 0; x < 16; x++, i++) { - int combinedId = array[i]; - switch (combinedId) { - case 0: - continue; - case BlockID.AIR: - case BlockID.CAVE_AIR: - case BlockID.VOID_AIR: - existing = nibble.a(x, y, z); - if (!existing.isAir()) { -// if (existing.e() > 0) { -// getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z); -// } - nonEmptyBlockCount--; - nibble.setBlock(x, y, z, AIR); - } - continue; - default: - existing = nibble.a(x, y, z); - if (!existing.isAir()) { -// if (existing.e() > 0) { -// getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z); -// } - } else { - nonEmptyBlockCount++; - } - BlockState state = BlockState.getFromInternalId(combinedId); - IBlockData ibd = ((BlockMaterial_1_14) state.getMaterial()).getState(); - nibble.setBlock(x, y, z, ibd); - } - } - } - } - getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section); - } - - // Trim tiles - HashMap toRemove = null; - if (!tiles.isEmpty()) { - Iterator> iterator = tiles.entrySet().iterator(); - while (iterator.hasNext()) { - Map.Entry tile = iterator.next(); - BlockPosition pos = tile.getKey(); - int lx = pos.getX() & 15; - int ly = pos.getY(); - int lz = pos.getZ() & 15; - int layer = ly >> 4; - int[] array = this.getIdArray(layer); - if (array == null) { - continue; - } - int index = (((ly & 0xF) << 8) | (lz << 4) | lx); - if (array[index] != 0) { - if (toRemove == null) { - toRemove = new HashMap<>(); - } - if (copy != null) { - copy.storeTile(tile.getValue(), tile.getKey()); - } - toRemove.put(tile.getKey(), tile.getValue()); - } - } - if (toRemove != null) { - synchronized (BukkitQueue_0.class) { - for (Map.Entry entry : toRemove.entrySet()) { - BlockPosition bp = entry.getKey(); - TileEntity tile = entry.getValue(); - nmsWorld.removeTileEntity(bp); - tiles.remove(bp); - tile.n(); - tile.invalidateBlockCache(); - } - } - } - } - - // Set biomes - if (this.biomes != null) { - BiomeBase[] currentBiomes = nmsChunk.getBiomeIndex(); - if (copy != null) { - copy.storeBiomes(currentBiomes); - } - for (int i = 0 ; i < this.biomes.length; i++) { - BiomeType biome = this.biomes[i]; - if (biome != null) { - Biome craftBiome = adapter.adapt(biome); - currentBiomes[i] = CraftBlock.biomeToBiomeBase(craftBiome); - } - } - } - // Set tiles - Map tilesToSpawn = this.getTiles(); - if (!tilesToSpawn.isEmpty()) { - for (Map.Entry entry : tilesToSpawn.entrySet()) { - CompoundTag nativeTag = entry.getValue(); - short blockHash = entry.getKey(); - int x = (blockHash >> 12 & 0xF) + bx; - int y = (blockHash & 0xFF); - int z = (blockHash >> 8 & 0xF) + bz; - BlockPosition pos = new BlockPosition(x, y, z); // Set pos - synchronized (BukkitQueue_0.class) { - TileEntity tileEntity = nmsWorld.getTileEntity(pos); - if (tileEntity != null) { - NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_14.fromNative(nativeTag); - tag.set("x", new NBTTagInt(x)); - tag.set("y", new NBTTagInt(y)); - tag.set("z", new NBTTagInt(z)); - tileEntity.load(tag); - } - } - } - } - // Change task - if (copy != null) { - getParent().getChangeTask().run(copy, this); - } - } catch (Throwable e) { - e.printStackTrace(); - } - return this; - } -} \ No newline at end of file diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_14/BukkitQueue_1_14.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_14/BukkitQueue_1_14.java deleted file mode 100644 index a8ad08768..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_14/BukkitQueue_1_14.java +++ /dev/null @@ -1,932 +0,0 @@ -package com.boydti.fawe.bukkit.v1_14; - -import com.boydti.fawe.Fawe; -import com.boydti.fawe.FaweCache; -import com.boydti.fawe.bukkit.BukkitPlayer; -import com.boydti.fawe.bukkit.v0.BukkitQueue_0; -import com.boydti.fawe.bukkit.v1_14.adapter.BlockMaterial_1_14; -import com.boydti.fawe.bukkit.v1_14.adapter.Spigot_v1_14_R1; -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.example.IntFaweChunk; -import com.boydti.fawe.jnbt.anvil.BitArray4096; -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.FawePlayer; -import com.boydti.fawe.object.RegionWrapper; -import com.boydti.fawe.object.brush.visualization.VisualChunk; -import com.boydti.fawe.object.visitor.FaweChunkVisitor; -import com.boydti.fawe.util.MainUtil; -import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.ReflectionUtils; -import com.boydti.fawe.util.TaskManager; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BlockID; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockTypes; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import net.minecraft.server.v1_14_R1.BiomeBase; -import net.minecraft.server.v1_14_R1.Block; -import net.minecraft.server.v1_14_R1.BlockPosition; -import net.minecraft.server.v1_14_R1.ChunkCoordIntPair; -import net.minecraft.server.v1_14_R1.ChunkProviderServer; -import net.minecraft.server.v1_14_R1.ChunkSection; -import net.minecraft.server.v1_14_R1.ChunkStatus; -import net.minecraft.server.v1_14_R1.DataBits; -import net.minecraft.server.v1_14_R1.DataPalette; -import net.minecraft.server.v1_14_R1.DataPaletteBlock; -import net.minecraft.server.v1_14_R1.DataPaletteHash; -import net.minecraft.server.v1_14_R1.DataPaletteLinear; -import net.minecraft.server.v1_14_R1.Entity; -import net.minecraft.server.v1_14_R1.EntityPlayer; -import net.minecraft.server.v1_14_R1.EnumSkyBlock; -import net.minecraft.server.v1_14_R1.GameProfileSerializer; -import net.minecraft.server.v1_14_R1.IBlockData; -import net.minecraft.server.v1_14_R1.IChunkAccess; -import net.minecraft.server.v1_14_R1.NBTTagCompound; -import net.minecraft.server.v1_14_R1.Packet; -import net.minecraft.server.v1_14_R1.PacketDataSerializer; -import net.minecraft.server.v1_14_R1.PacketPlayOutMultiBlockChange; -import net.minecraft.server.v1_14_R1.PlayerChunk; -import net.minecraft.server.v1_14_R1.PlayerChunkMap; -import net.minecraft.server.v1_14_R1.ProtoChunkExtension; -import net.minecraft.server.v1_14_R1.RegistryID; -import net.minecraft.server.v1_14_R1.TileEntity; -import net.minecraft.server.v1_14_R1.WorldChunkManager; -import net.minecraft.server.v1_14_R1.WorldData; -import net.minecraft.server.v1_14_R1.WorldServer; -import org.bukkit.Chunk; -import org.bukkit.World; -import org.bukkit.craftbukkit.v1_14_R1.CraftChunk; -import org.bukkit.craftbukkit.v1_14_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_14_R1.block.CraftBlock; -import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.atomic.LongAdder; -import java.util.function.Consumer; -import java.util.function.Supplier; - -public class BukkitQueue_1_14 extends BukkitQueue_0 { - - public final static Field fieldBits; - public final static Field fieldPalette; - protected final static Field fieldSize; - - protected final static Field fieldHashBlocks; - protected final static Field fieldLinearBlocks; - protected final static Field fieldHashIndex; - protected final static Field fieldRegistryb; - protected final static Field fieldRegistryc; - protected final static Field fieldRegistryd; - protected final static Field fieldRegistrye; - protected final static Field fieldRegistryf; - - protected final static Field fieldLinearIndex; - protected final static Field fieldDefaultBlock; - - protected final static Field fieldFluidCount; - protected final static Field fieldTickingBlockCount; - protected final static Field fieldNonEmptyBlockCount; - protected final static Field fieldSection; - -// protected final static Field fieldBiomes; - - protected final static Field fieldChunkGenerator; - protected final static Field fieldSeed; -// protected final static Field fieldBiomeCache; -// protected final static Field fieldBiomes2; - protected final static Field fieldGenLayer1; - protected final static Field fieldGenLayer2; - protected final static Field fieldSave; -// protected final static MutableGenLayer genLayer; - protected final static ChunkSection emptySection; - -// protected static final Method methodResize; - - protected final static Field fieldDirtyCount; - protected final static Field fieldDirtyBits; - - static { - try { - emptySection = new ChunkSection(0); - fieldSection = ChunkSection.class.getDeclaredField("blockIds"); - fieldSection.setAccessible(true); - - fieldFluidCount = ChunkSection.class.getDeclaredField("e"); - fieldTickingBlockCount = ChunkSection.class.getDeclaredField("tickingBlockCount"); - fieldNonEmptyBlockCount = ChunkSection.class.getDeclaredField("nonEmptyBlockCount"); - fieldFluidCount.setAccessible(true); - fieldTickingBlockCount.setAccessible(true); - fieldNonEmptyBlockCount.setAccessible(true); - - - -// fieldBiomes = ChunkProviderGenerate.class.getDeclaredField("D"); // * -// fieldBiomes.setAccessible(true); - - fieldChunkGenerator = ChunkProviderServer.class.getDeclaredField("chunkGenerator"); - fieldChunkGenerator.setAccessible(true); - fieldSeed = WorldData.class.getDeclaredField("e"); - fieldSeed.setAccessible(true); - -// fieldBiomeCache = WorldChunkManager.class.getDeclaredField("d"); // * -// fieldBiomeCache.setAccessible(true); -// fieldBiomes2 = WorldChunkManager.class.getDeclaredField("e"); // * -// fieldBiomes2.setAccessible(true); - fieldGenLayer1 = WorldChunkManager.class.getDeclaredField("b") ; - fieldGenLayer2 = WorldChunkManager.class.getDeclaredField("c") ; - fieldGenLayer1.setAccessible(true); - fieldGenLayer2.setAccessible(true); - - fieldSave = ReflectionUtils.setAccessible(net.minecraft.server.v1_14_R1.Chunk.class.getDeclaredField("s")); //* - - fieldHashBlocks = DataPaletteHash.class.getDeclaredField("b"); - fieldHashBlocks.setAccessible(true); - fieldLinearBlocks = DataPaletteLinear.class.getDeclaredField("b"); - fieldLinearBlocks.setAccessible(true); - - fieldHashIndex = DataPaletteHash.class.getDeclaredField("f"); - fieldHashIndex.setAccessible(true); - - fieldRegistryb = RegistryID.class.getDeclaredField("b"); - fieldRegistryc = RegistryID.class.getDeclaredField("c"); - fieldRegistryd = RegistryID.class.getDeclaredField("d"); - fieldRegistrye = RegistryID.class.getDeclaredField("e"); - fieldRegistryf = RegistryID.class.getDeclaredField("f"); - fieldRegistryb.setAccessible(true); - fieldRegistryc.setAccessible(true); - fieldRegistryd.setAccessible(true); - fieldRegistrye.setAccessible(true); - fieldRegistryf.setAccessible(true); - - fieldLinearIndex = DataPaletteLinear.class.getDeclaredField("f"); - fieldLinearIndex.setAccessible(true); - - fieldDefaultBlock = DataPaletteBlock.class.getDeclaredField("g"); - fieldDefaultBlock.setAccessible(true); - - fieldSize = DataPaletteBlock.class.getDeclaredField("i"); - fieldSize.setAccessible(true); - - fieldBits = DataPaletteBlock.class.getDeclaredField("a"); - fieldBits.setAccessible(true); - - fieldPalette = DataPaletteBlock.class.getDeclaredField("h"); - fieldPalette.setAccessible(true); - -// methodResize = DataPaletteBlock.class.getDeclaredMethod("b", int.class); -// methodResize.setAccessible(true); - - fieldDirtyCount = PlayerChunk.class.getDeclaredField("dirtyCount"); - fieldDirtyBits = PlayerChunk.class.getDeclaredField("r"); - fieldDirtyCount.setAccessible(true); - fieldDirtyBits.setAccessible(true); - - Fawe.debug("Using adapter: " + getAdapter()); - Fawe.debug("========================================="); - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - - public BukkitQueue_1_14(final com.sk89q.worldedit.world.World world) { - super(world); - getImpWorld(); - } - - public BukkitQueue_1_14(final String world) { - super(world); - getImpWorld(); - } - - @Override - public ChunkSection[] getSections(IChunkAccess chunk) { - return chunk.getSections(); - } - - @Override - public IChunkAccess loadChunk(World world, int x, int z, boolean generate) { - ChunkProviderServer provider = ((CraftWorld) world).getHandle().getChunkProvider(); - IChunkAccess chunk; - if (generate) { - chunk = provider.getChunkAt(x, z, ChunkStatus.FEATURES, true); - } else { - chunk = provider.getChunkAt(x, z, ChunkStatus.FEATURES, false); - } - return cast(chunk); - } - - private IChunkAccess cast(IChunkAccess chunkAccess) { - if (chunkAccess instanceof ProtoChunkExtension) { - ProtoChunkExtension proto = (ProtoChunkExtension) chunkAccess; - if (proto.u() != null) chunkAccess = proto.u(); - } - return chunkAccess; - } - - @Override - public ChunkSection[] getCachedSections(World world, int cx, int cz) { - IChunkAccess chunk = ((CraftWorld) world).getHandle().getChunkProvider().getChunkAt(cx, cz, ChunkStatus.FEATURES, false); - if (chunk != null) { - return chunk.getSections(); - } - return null; - } - - @Override - public IChunkAccess getCachedChunk(World world, int cx, int cz) { - return cast(((CraftWorld) world).getHandle().getChunkProvider().getChunkAt(cx, cz, ChunkStatus.FEATURES, false)); - } - - @Override - public ChunkSection getCachedSection(ChunkSection[] chunkSections, int cy) { - return chunkSections[cy]; - } - - @Override - public void saveChunk(IChunkAccess chunkAccess) { - chunkAccess = cast(chunkAccess); - if (chunkAccess instanceof Chunk) { - net.minecraft.server.v1_14_R1.Chunk nmsChunk = (net.minecraft.server.v1_14_R1.Chunk) chunkAccess; - nmsChunk.d(true); // Set Modified - nmsChunk.mustNotSave = false; - nmsChunk.markDirty(); - } else { - chunkAccess.setNeedsSaving(true); - } - } - - @Override - public boolean regenerateChunk(World world, int x, int z, BiomeType biome, Long seed) { -// if (biome != null) { -// try { -// if (seed == null) { -// seed = world.getSeed(); -// } -// nmsWorld.worldData.getSeed(); -// boolean result; -// ChunkProviderGenerate generator = new ChunkProviderGenerate(nmsWorld, seed, false, ""); -// Biome bukkitBiome = getAdapter().getBiome(biome.getId()); -// BiomeBase base = BiomeBase.getBiome(biome.getId()); -// fieldBiomes.set(generator, new BiomeBase[]{base}); -// boolean cold = base.getTemperature() <= 1; -// net.minecraft.server.v1_14_R1.ChunkGenerator existingGenerator = nmsWorld.getChunkProvider().chunkGenerator; -// long existingSeed = world.getSeed(); -// { -// if (genLayer == null) genLayer = new MutableGenLayer(seed); -// genLayer.set(biome.getId()); -// Object existingGenLayer1 = fieldGenLayer1.get(nmsWorld.getWorldChunkManager()); -// Object existingGenLayer2 = fieldGenLayer2.get(nmsWorld.getWorldChunkManager()); -// fieldGenLayer1.set(nmsWorld.getWorldChunkManager(), genLayer); -// fieldGenLayer2.set(nmsWorld.getWorldChunkManager(), genLayer); -// -// fieldSeed.set(nmsWorld.worldData, seed); -// -// ReflectionUtils.setFailsafeFieldValue(fieldBiomeCache, this.nmsWorld.getWorldChunkManager(), new BiomeCache(this.nmsWorld.getWorldChunkManager())); -// -// ReflectionUtils.setFailsafeFieldValue(fieldChunkGenerator, this.nmsWorld.getChunkProvider(), generator); -// -// keepLoaded.remove(MathMan.pairInt(x, z)); -// result = getWorld().regenerateChunk(x, z); -// net.minecraft.server.v1_14_R1.Chunk nmsChunk = getCachedChunk(world, x, z); -// if (nmsChunk != null) { -// nmsChunk.f(true); // Set Modified -// nmsChunk.mustSave = true; -// } -// -// ReflectionUtils.setFailsafeFieldValue(fieldChunkGenerator, this.nmsWorld.getChunkProvider(), existingGenerator); -// -// fieldSeed.set(nmsWorld.worldData, existingSeed); -// -// fieldGenLayer1.set(nmsWorld.getWorldChunkManager(), existingGenLayer1); -// fieldGenLayer2.set(nmsWorld.getWorldChunkManager(), existingGenLayer2); -// } -// return result; -// } catch (Throwable e) { -// e.printStackTrace(); -// } -// } - return super.regenerateChunk(world, x, z, biome, seed); - } - - @Override - public boolean setMCA(final int mcaX, final int mcaZ, final RegionWrapper allowed, final Runnable whileLocked, final boolean saveChunks, final boolean load) { - throw new UnsupportedOperationException("Anvil not implemented yet"); -// TaskManager.IMP.sync(new RunnableVal() { -// @Override -// public void run(Boolean value) { -// long start = System.currentTimeMillis(); -// long last = start; -// synchronized (RegionFileCache.class) { -// World world = getWorld(); -// if (world.getKeepSpawnInMemory()) world.setKeepSpawnInMemory(false); -// ChunkProviderServer provider = nmsWorld.getChunkProvider(); -// -// boolean mustSave = false; -// boolean[][] chunksUnloaded = null; -// { // Unload chunks -// Iterator iter = provider.a().iterator(); -// while (iter.hasNext()) { -// net.minecraft.server.v1_14_R1.Chunk chunk = iter.next(); -// if (chunk.locX >> 5 == mcaX && chunk.locZ >> 5 == mcaZ) { -// boolean isIn = allowed.isInChunk(chunk.locX, chunk.locZ); -// if (isIn) { -// if (!load) { -// mustSave |= saveChunks && save(chunk, provider); -// continue; -// } -// iter.remove(); -// boolean save = saveChunks && chunk.a(false); -// mustSave |= save; -// provider.unloadChunk(chunk, save); -// if (chunksUnloaded == null) { -// chunksUnloaded = new boolean[32][]; -// } -// int relX = chunk.locX & 31; -// boolean[] arr = chunksUnloaded[relX]; -// if (arr == null) { -// arr = chunksUnloaded[relX] = new boolean[32]; -// } -// arr[chunk.locZ & 31] = true; -// } -// } -// } -// } -// if (mustSave) { -// provider.c(); // TODO only the necessary chunks -// } -// -// File unloadedRegion = null; -// if (load && !RegionFileCache.a.isEmpty()) { -// Map map = RegionFileCache.a; -// Iterator> iter = map.entrySet().iterator(); -// String requiredPath = world.getName() + File.separator + "region"; -// while (iter.hasNext()) { -// Map.Entry entry = iter.next(); -// File file = entry.getKey(); -// int[] regPos = MainUtil.regionNameToCoords(file.getPath()); -// if (regPos[0] == mcaX && regPos[1] == mcaZ && file.getPath().contains(requiredPath)) { -// if (file.exists()) { -// unloadedRegion = file; -// RegionFile regionFile = entry.getValue(); -// iter.remove(); -// try { -// regionFile.c(); -// } catch (IOException e) { -// e.printStackTrace(); -// } -// } -// break; -// } -// } -// } -// -// long now = System.currentTimeMillis(); -// if (whileLocked != null) whileLocked.run(); -// if (!load) return; -// -// { // Load the region again -// if (unloadedRegion != null && chunksUnloaded != null && unloadedRegion.exists()) { -// final boolean[][] finalChunksUnloaded = chunksUnloaded; -// TaskManager.IMP.async(() -> { -// int bx = mcaX << 5; -// int bz = mcaZ << 5; -// for (int x = 0; x < finalChunksUnloaded.length; x++) { -// boolean[] arr = finalChunksUnloaded[x]; -// if (arr != null) { -// for (int z = 0; z < arr.length; z++) { -// if (arr[z]) { -// int cx = bx + x; -// int cz = bz + z; -// SetQueue.IMP.addTask(new Runnable() { -// @Override -// public void run() { -// net.minecraft.server.v1_14_R1.Chunk chunk = provider.getChunkAt(cx, cz, null, false); -// if (chunk != null) { -// PlayerChunk pc = getPlayerChunk(nmsWorld, cx, cz); -// if (pc != null) { -// sendChunk(pc, chunk, 0); -// } -// } -// } -// }); -// } -// } -// } -// } -// }); -// } -// } -// } -// } -// }); -// return true; - } - - @Override - public boolean next(int amount, long time) { - return super.next(amount, time); - } - - @Override - public void setSkyLight(ChunkSection section, int x, int y, int z, int value) { -// section.getSkyLightArray().a(x & 15, y & 15, z & 15, value); - } - - @Override - public void setBlockLight(ChunkSection section, int x, int y, int z, int value) { -// section.getEmittedLightArray().a(x & 15, y & 15, z & 15, value); - } - -// @Override -// public World createWorld(final WorldCreator creator) { -// final String name = creator.name(); -// ChunkGenerator generator = creator.generator(); -// final CraftServer server = (CraftServer) Bukkit.getServer(); -// final MinecraftServer console = server.getServer(); -// final File folder = new File(server.getWorldContainer(), name); -// final World world = server.getWorld(name); -// final WorldType type = WorldType.getType(creator.type().getName()); -// final boolean generateStructures = creator.generateStructures(); -// if (world != null) { -// return world; -// } -// if (folder.exists() && !folder.isDirectory()) { -// throw new IllegalArgumentException("File exists with the name '" + name + "' and isn't a folder"); -// } -// TaskManager.IMP.sync(new RunnableVal() { -// @Override -// public void run(Object value) { -// try { -// Field field = CraftServer.class.getDeclaredField("worlds"); -// field.setAccessible(true); -// Map existing = (Map) field.get(server); -// if (!existing.getClass().getName().contains("SynchronizedMap")) { -// field.set(server, Collections.synchronizedMap(existing)); -// } -// } catch (Throwable e) { -// e.printStackTrace(); -// } -// } -// }); -// if (generator == null) { -// generator = server.getGenerator(name); -// } -// int dimension = 10 + console.worlds.size(); -// boolean used = false; -// do { -// for (final WorldServer ws : console.worlds) { -// used = (ws.dimension == dimension); -// if (used) { -// ++dimension; -// break; -// } -// } -// } while (used); -// final boolean hardcore = false; -// final IDataManager sdm = new ServerNBTManager(server.getWorldContainer(), name, true, server.getHandle().getServer().dataConverterManager); -// WorldData worlddata = sdm.getWorldData(); -// final WorldSettings worldSettings; -// if (worlddata == null) { -// worldSettings = new WorldSettings(creator.seed(), EnumGamemode.getById(server.getDefaultGameMode().getValue()), generateStructures, hardcore, type); -// worldSettings.setGeneratorSettings(creator.generatorSettings()); -// worlddata = new WorldData(worldSettings, name); -// } else { -// worldSettings = null; -// } -// worlddata.checkName(name); -// final WorldServer internal = (WorldServer)new WorldServer(console, sdm, worlddata, dimension, console.methodProfiler, creator.environment(), generator).b(); -// startSet(true); // Temporarily allow async chunk load since the world isn't added yet -// if (worldSettings != null) { -// internal.a(worldSettings); -// } -// endSet(true); -// internal.scoreboard = server.getScoreboardManager().getMainScoreboard().getHandle(); -// internal.tracker = new EntityTracker(internal); -// internal.addIWorldAccess(new WorldManager(console, internal)); -// internal.worldData.setDifficulty(EnumDifficulty.EASY); -// internal.setSpawnFlags(true, true); -// if (generator != null) { -// internal.getWorld().getPopulators().addAll(generator.getDefaultPopulators(internal.getWorld())); -// } -// // Add the world -// return TaskManager.IMP.sync(new RunnableVal() { -// @Override -// public void run(World value) { -// console.worlds.add(internal); -// server.getPluginManager().callEvent(new WorldInitEvent(internal.getWorld())); -// server.getPluginManager().callEvent(new WorldLoadEvent(internal.getWorld())); -// this.value = internal.getWorld(); -// } -// }); -// } - - @Override - public int getCombinedId4Data(ChunkSection lastSection, int x, int y, int z) { - DataPaletteBlock dataPalette = lastSection.getBlocks(); - IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); - int ordinal = ((Spigot_v1_14_R1) getAdapter()).adaptToInt(ibd); - return BlockTypes.states[ordinal].getInternalId(); - } - - @Override - public BiomeType getBiome(IChunkAccess chunk, int x, int z) { - BiomeBase base = chunk.getBiomeIndex()[((z & 15) << 4) + (x & 15)]; - return getAdapter().adapt(CraftBlock.biomeBaseToBiome(base)); - } - - @Override - public int getOpacity(ChunkSection section, int x, int y, int z) { - return 0; - } - - @Override - public int getBrightness(ChunkSection section, int x, int y, int z) { - return 0; - } - - @Override - public int getOpacityBrightnessPair(ChunkSection section, int x, int y, int z) { - return 0; - } - - @Override - public void sendChunk(int x, int z, int bitMask) { - IChunkAccess chunk = getCachedChunk(getWorld(), x, z); - if (chunk != null) { - sendChunk(getPlayerChunk((WorldServer) nmsWorld, x, z), chunk, bitMask); - } - } - - @Override - public void sendChunkUpdatePLIB(FaweChunk chunk, FawePlayer... players) { -// PlayerChunkMap playerManager = ((CraftWorld) getWorld()).getHandle().getPlayerChunkMap(); -// ProtocolManager manager = ProtocolLibrary.getProtocolManager(); -// WirePacket packet = null; -// try { -// for (int i = 0; i < players.length; i++) { -// CraftPlayer bukkitPlayer = ((CraftPlayer) ((BukkitPlayer) players[i]).parent); -// EntityPlayer player = bukkitPlayer.getHandle(); -// -// if (playerManager.a(player, chunk.getX(), chunk.getZ())) { -// if (packet == null) { -// byte[] data; -// byte[] buffer = new byte[8192]; -// if (chunk instanceof LazyFaweChunk) { -// chunk = (FaweChunk) chunk.getChunk(); -// } -// if (chunk instanceof MCAChunk) { -// data = new MCAChunkPacket((MCAChunk) chunk, true, true, hasSky()).apply(buffer); -// } else { -// data = new FaweChunkPacket(chunk, true, true, hasSky()).apply(buffer); -// } -// packet = new WirePacket(PacketType.Play.Server.MAP_CHUNK, data); -// } -// manager.sendWirePacket(bukkitPlayer, packet); -// } -// } -// } catch (InvocationTargetException e) { -// throw new RuntimeException(e); -// } - super.sendChunkUpdatePLIB(chunk, players); // TODO remove - } - - @Override - public void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) { - try { - PlayerChunkMap playerManager = ((CraftWorld) getWorld()).getHandle().getChunkProvider().playerChunkMap; - boolean[] watching = new boolean[1]; - boolean[] watchingArr = new boolean[players.length]; - ChunkCoordIntPair pair = new ChunkCoordIntPair(chunk.getX(), chunk.getZ()); - PlayerChunk plrChunk = playerManager.visibleChunks.get(pair.pair()); - if (plrChunk != null) { - plrChunk.players.a(pair, false).forEach(new Consumer() { - @Override - public void accept(EntityPlayer entityPlayer) { - for (int i = 0; i < players.length; i++) { - EntityPlayer player = ((CraftPlayer) ((BukkitPlayer) players[i]).parent).getHandle(); - if (player == entityPlayer) { - watchingArr[i] = true; - watching[0] = true; - } - } - } - }); - } - if (!watching[0]) return; - final LongAdder size = new LongAdder(); - if (chunk instanceof VisualChunk) { - size.add(((VisualChunk) chunk).size()); - } else if (chunk instanceof IntFaweChunk) { - size.add(((IntFaweChunk) chunk).getTotalCount()); - } else { - chunk.forEachQueuedBlock(new FaweChunkVisitor() { - @Override - public void run(int localX, int y, int localZ, int combined) { - size.add(1); - } - }); - } - if (size.intValue() == 0) return; - PacketPlayOutMultiBlockChange packet = new PacketPlayOutMultiBlockChange(); - ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer(); - final PacketDataSerializer buffer = new PacketDataSerializer(byteBuf); - buffer.writeInt(chunk.getX()); - buffer.writeInt(chunk.getZ()); - buffer.d(size.intValue()); - chunk.forEachQueuedBlock(new FaweChunkVisitor() { - @Override - public void run(int localX, int y, int localZ, int combined) { - short index = (short) (localX << 12 | localZ << 8 | y); - if (combined < 16) combined = 0; - buffer.writeShort(index); - buffer.d(combined); - } - }); - packet.a(buffer); - for (int i = 0; i < players.length; i++) { - if (watchingArr[i]) ((CraftPlayer) ((BukkitPlayer) players[i]).parent).getHandle().playerConnection.sendPacket(packet); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void refreshChunk(FaweChunk fc) { - sendChunk(fc.getX(), fc.getZ(), fc.getBitMask()); - } - - private PlayerChunk getPlayerChunk(WorldServer w, int cx, int cz) { - PlayerChunkMap chunkMap = w.getChunkProvider().playerChunkMap; - PlayerChunk playerChunk = chunkMap.visibleChunks.get(ChunkCoordIntPair.pair(cx, cz)); - if (playerChunk == null) { - return null; - } - return playerChunk; - } - - public boolean sendChunk(PlayerChunk playerChunk, IChunkAccess nmsChunk, int mask) { - if (playerChunk == null) { - return false; - } - ChunkSection[] sections = nmsChunk.getSections(); - for (int layer = 0; layer < 16; layer++) { - if (sections[layer] == null && (mask & (1 << layer)) != 0) { - sections[layer] = new ChunkSection(layer << 4); - } - } - TaskManager.IMP.sync(new Supplier() { - @Override - public Object get() { - try { - int dirtyBits = fieldDirtyBits.getInt(playerChunk); - if (dirtyBits == 0) { - ((CraftWorld) getWorld()).getHandle().getChunkProvider().playerChunkMap.a(playerChunk); - } - if (mask == 0) { - dirtyBits = 65535; - } else { - dirtyBits |= mask; - } - - fieldDirtyBits.set(playerChunk, dirtyBits); - fieldDirtyCount.set(playerChunk, 64); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - return null; - } - }); -// if (mask == 0) { -// PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, 65535); -// for (EntityPlayer player : playerChunk.players) { -// player.playerConnection.sendPacket(packet); -// } -// return true; -// } -// // Send chunks -// boolean empty = false; -// ChunkSection[] sections = nmsChunk.getSections(); -// for (int i = 0; i < sections.length; i++) { -// if (sections[i] == null) { -// sections[i] = emptySection; -// empty = true; -// } -// } -// if (mask == 0 || mask == 65535 && hasEntities(nmsChunk)) { -// PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, 65280); -// for (EntityPlayer player : playerChunk.players) { -// player.playerConnection.sendPacket(packet); -// } -// mask = 255; -// } -// PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, mask); -// for (EntityPlayer player : playerChunk.players) { -// player.playerConnection.sendPacket(packet); -// } -// if (empty) { -// for (int i = 0; i < sections.length; i++) { -// if (sections[i] == emptySection) { -// sections[i] = null; -// } -// } -// } - return true; - } - - public boolean hasEntities(net.minecraft.server.v1_14_R1.Chunk nmsChunk) { - try { - final Collection[] entities = nmsChunk.entitySlices; - for (int i = 0; i < entities.length; i++) { - Collection slice = entities[i]; - if (slice != null && !slice.isEmpty()) { - return true; - } - } - } catch (Throwable ignore) {} - return false; - } - - @Override - public boolean removeSectionLighting(ChunkSection section, int layer, boolean sky) { - return false; - } - - @Override - public void setFullbright(ChunkSection[] sections) { - } - - @Override - public int getSkyLight(ChunkSection section, int x, int y, int z) { - return 15; - } - - @Override - public int getEmmittedLight(ChunkSection section, int x, int y, int z) { - return 15; - } - - @Override - public void relightBlock(int x, int y, int z) { - } - - @Override - public void relightSky(int x, int y, int z) { - } - - @Override - public void relight(int x, int y, int z) { - } - - protected WorldServer nmsWorld; - - @Override - public World getImpWorld() { - World world = super.getImpWorld(); - if (world != null) { - this.nmsWorld = ((CraftWorld) world).getHandle(); - return super.getImpWorld(); - } else { - return null; - } - } - - public static void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException { - fieldFluidCount.setShort(section, (short) 0); // TODO FIXME - fieldTickingBlockCount.setShort(section, (short) tickingBlockCount); - fieldNonEmptyBlockCount.setShort(section, (short) nonEmptyBlockCount); - } - - public int getNonEmptyBlockCount(ChunkSection section) throws IllegalAccessException { - return fieldNonEmptyBlockCount.getShort(section); - } - - public void setPalette(ChunkSection section, DataPaletteBlock palette) throws NoSuchFieldException, IllegalAccessException { - fieldSection.set(section, palette); - } - - public static ChunkSection newChunkSection(int y2, boolean flag, int[] blocks) { - if (blocks == null) { - return new ChunkSection(y2 << 4); - } else { - ChunkSection section = new ChunkSection(y2 << 4); - int[] blockToPalette = FaweCache.BLOCK_TO_PALETTE.get(); - int[] paletteToBlock = FaweCache.PALETTE_TO_BLOCK.get(); - long[] blockstates = FaweCache.BLOCK_STATES.get(); - int[] blocksCopy = FaweCache.SECTION_BLOCKS.get(); - try { - int num_palette = 0; - int air = 0; - for (int i = 0; i < 4096; i++) { - int stateId = blocks[i]; - switch (stateId) { - case 0: - case BlockID.AIR: - case BlockID.CAVE_AIR: - case BlockID.VOID_AIR: - stateId = BlockID.AIR; - air++; - } - int ordinal = BlockState.getFromInternalId(stateId).getOrdinal(); // TODO fixme Remove all use of BlockTypes.BIT_OFFSET so that this conversion isn't necessary - int palette = blockToPalette[ordinal]; - if (palette == Integer.MAX_VALUE) { - blockToPalette[ordinal] = palette = num_palette; - paletteToBlock[num_palette] = ordinal; - num_palette++; - } - blocksCopy[i] = palette; - } - - // BlockStates - int bitsPerEntry = MathMan.log2nlz(num_palette - 1); - if (Settings.IMP.PROTOCOL_SUPPORT_FIX || num_palette != 1) { - bitsPerEntry = Math.max(bitsPerEntry, 4); // Protocol support breaks <4 bits per entry - } else { - bitsPerEntry = Math.max(bitsPerEntry, 1); // For some reason minecraft needs 4096 bits to store 0 entries - } - - int blockBitArrayEnd = (bitsPerEntry * 4096) >> 6; - if (num_palette == 1) { - for (int i = 0; i < blockBitArrayEnd; i++) blockstates[i] = 0; - } else { - BitArray4096 bitArray = new BitArray4096(blockstates, bitsPerEntry); - bitArray.fromRaw(blocksCopy); - } - - // set palette & data bits - DataPaletteBlock dataPaletteBlocks = section.getBlocks(); - // private DataPalette h; - // protected DataBits a; - long[] bits = Arrays.copyOfRange(blockstates, 0, blockBitArrayEnd); - DataBits nmsBits = new DataBits(bitsPerEntry, 4096, bits); - DataPalette palette; -// palette = new DataPaletteHash<>(Block.REGISTRY_ID, bitsPerEntry, dataPaletteBlocks, GameProfileSerializer::d, GameProfileSerializer::a); - palette = new DataPaletteLinear<>(Block.REGISTRY_ID, bitsPerEntry, dataPaletteBlocks, GameProfileSerializer::d); - - // set palette - for (int i = 0; i < num_palette; i++) { - int ordinal = paletteToBlock[i]; - blockToPalette[ordinal] = Integer.MAX_VALUE; - BlockState state = BlockTypes.states[ordinal]; - IBlockData ibd = ((BlockMaterial_1_14) state.getMaterial()).getState(); - palette.a(ibd); - } - try { - fieldBits.set(dataPaletteBlocks, nmsBits); - fieldPalette.set(dataPaletteBlocks, palette); - fieldSize.set(dataPaletteBlocks, bitsPerEntry); - setCount(0, 4096 - air, section); - } catch (IllegalAccessException | NoSuchFieldException e) { - throw new RuntimeException(e); - } - - return section; - } catch (Throwable e){ - Arrays.fill(blockToPalette, Integer.MAX_VALUE); - throw e; - } - } - } - - protected BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0); - - @Override - public CompoundTag getTileEntity(IChunkAccess chunk, int x, int y, int z) { - Map tiles = ((net.minecraft.server.v1_14_R1.Chunk) cast(chunk)).getTileEntities(); - pos.c(x, y, z); - TileEntity tile = tiles.get(pos); - return tile != null ? getTag(tile) : null; - } - - public CompoundTag getTag(TileEntity tile) { - try { - NBTTagCompound tag = new NBTTagCompound(); - tile.save(tag); // readTagIntoEntity - return (CompoundTag) toNative(tag); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - @Deprecated - public boolean unloadChunk(final String world, final Chunk chunk) { - net.minecraft.server.v1_14_R1.Chunk c = ((CraftChunk) chunk).getHandle(); - c.mustNotSave = true; - if (chunk.isLoaded()) { - chunk.unload(false); - } - return true; - } - - @Override - public BukkitChunk_1_14 getFaweChunk(int x, int z) { - return new BukkitChunk_1_14(this, x, z); - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/DelegateFilter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/DelegateFilter.java index 5bc48aa80..bbbe85f61 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/DelegateFilter.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/DelegateFilter.java @@ -1,13 +1,18 @@ package com.boydti.fawe.beta; -public abstract class DelegateFilter implements IDelegateFilter { +public class DelegateFilter implements IDelegateFilter { private final Filter parent; - public DelegateFilter(Filter parent) { + public DelegateFilter(T parent) { this.parent = parent; } @Override - public Filter getParent() { - return parent; + public T getParent() { + return (T) parent; + } + + @Override + public Filter newInstance(Filter other) { + return new DelegateFilter(other); } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateFilter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateFilter.java index e85587e59..e39b1b703 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateFilter.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateFilter.java @@ -46,5 +46,7 @@ public interface IDelegateFilter extends Filter { return this; } - Filter newInstance(Filter other); + default Filter newInstance(Filter other) { + throw new UnsupportedOperationException("Not implemented"); + } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/filters/CountFilter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/filters/CountFilter.java index 988b60161..8dda75900 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/filters/CountFilter.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/filters/CountFilter.java @@ -1,18 +1,9 @@ package com.boydti.fawe.beta.filters; import com.boydti.fawe.beta.FilterBlock; -import com.boydti.fawe.config.BBC; -import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.util.Countable; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockTypes; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; public class CountFilter extends ForkedFilter { - private final int[] counter = new int[BlockTypes.states.length]; + private int total; public CountFilter() { super(null); @@ -29,9 +20,7 @@ public class CountFilter extends ForkedFilter { @Override public void join(CountFilter filter) { - for (int i = 0; i < filter.counter.length; i++) { - this.counter[i] += filter.counter[i]; - } + this.total += filter.getTotal(); } /* @@ -40,29 +29,10 @@ public class CountFilter extends ForkedFilter { @Override public final void applyBlock(final FilterBlock block) { - counter[block.getOrdinal()]++; + total++; } - public List> getDistribution() { - final List> distribution = new ArrayList<>(); - for (int i = 0; i < counter.length; i++) { - final int count = counter[i]; - if (count != 0) { - distribution.add(new Countable<>(BlockTypes.states[i], count)); - } - } - Collections.sort(distribution); - return distribution; - } - - public void print(final Actor actor, final long size) { - for (final Countable c : getDistribution()) { - final String name = c.getID().toString(); - final String str = String.format("%-7s (%.3f%%) %s", - String.valueOf(c.getAmount()), - c.getAmount() / (double) size * 100, - name); - actor.print(BBC.getPrefix() + str); - } + public int getTotal() { + return total; } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/filters/DistrFilter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/filters/DistrFilter.java new file mode 100644 index 000000000..bde69e284 --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/filters/DistrFilter.java @@ -0,0 +1,107 @@ +package com.boydti.fawe.beta.filters; + +import com.boydti.fawe.beta.FilterBlock; +import com.boydti.fawe.config.BBC; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.function.mask.ABlockMask; +import com.sk89q.worldedit.util.Countable; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.block.BlockTypes; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class DistrFilter extends ForkedFilter { + private final int[] counter = new int[BlockTypes.states.length]; + + public DistrFilter() { + super(null); + } + + private DistrFilter(DistrFilter root) { + super(root); + } + + @Override + public DistrFilter init() { + return new DistrFilter(this); + } + + @Override + public void join(DistrFilter filter) { + for (int i = 0; i < filter.counter.length; i++) { + this.counter[i] += filter.counter[i]; + } + } + + /* + Implementation + */ + + @Override + public final void applyBlock(final FilterBlock block) { + counter[block.getOrdinal()]++; + } + + public int getTotal(ABlockMask mask) { + int total = 0; + for (int i = 0; i < counter.length; i++) { + int value = counter[i]; + if (value != 0 && mask.test(BlockTypes.states[i])) { + total += value; + } + } + return total; + } + + public int getTotal() { + int total = 0; + for (int value : counter) total += value; + return total; + } + + public List> getDistribution() { + final List> distribution = new ArrayList<>(); + for (int i = 0; i < counter.length; i++) { + final int count = counter[i]; + if (count != 0) { + distribution.add(new Countable<>(BlockTypes.states[i], count)); + } + } + Collections.sort(distribution); + return distribution; + } + + public List> getTypeDistribution() { + final List> distribution = new ArrayList<>(); + int[] typeCounter = new int[BlockTypes.values.length]; + for (int i = 0; i < counter.length; i++) { + final int count = counter[i]; + if (count != 0) { + BlockState state = BlockTypes.states[i]; + typeCounter[state.getBlockType().getInternalId()] += count; + } + } + for (int i = 0; i < typeCounter.length; i++) { + final int count = typeCounter[i]; + if (count != 0) { + distribution.add(new Countable<>(BlockTypes.values[i], count)); + } + } + Collections.sort(distribution); + return distribution; + } + + public void print(final Actor actor, final long size) { + for (final Countable c : getDistribution()) { + final String name = c.getID().toString(); + final String str = String.format("%-7s (%.3f%%) %s", + String.valueOf(c.getAmount()), + c.getAmount() / (double) size * 100, + name); + actor.print(BBC.getPrefix() + str); + } + } +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/IQueueWrapper.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/IQueueWrapper.java new file mode 100644 index 000000000..8c4957ce2 --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/IQueueWrapper.java @@ -0,0 +1,9 @@ +package com.boydti.fawe.beta.implementation; + +import com.boydti.fawe.beta.IQueueExtent; + +public interface IQueueWrapper { + default IQueueExtent wrapQueue(IQueueExtent queue) { + return queue; + } +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/MultiThreadedQueue.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/MultiThreadedQueue.java new file mode 100644 index 000000000..3795c4dcf --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/MultiThreadedQueue.java @@ -0,0 +1,143 @@ +package com.boydti.fawe.beta.implementation; + +import com.boydti.fawe.beta.ChunkFilterBlock; +import com.boydti.fawe.beta.Filter; +import com.boydti.fawe.beta.IChunk; +import com.boydti.fawe.beta.IQueueExtent; +import com.boydti.fawe.beta.filters.CountFilter; +import com.boydti.fawe.beta.filters.DistrFilter; +import com.boydti.fawe.config.Settings; +import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.extent.AbstractDelegateExtent; +import com.sk89q.worldedit.function.mask.BlockMask; +import com.sk89q.worldedit.function.mask.BlockMaskBuilder; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.SingleBlockStateMask; +import com.sk89q.worldedit.function.operation.Operations; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.function.visitor.RegionVisitor; +import com.sk89q.worldedit.math.BlockVector2; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.Countable; +import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.block.BlockTypes; + +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ForkJoinTask; + +public class MultiThreadedQueue extends AbstractDelegateExtent implements IQueueWrapper { + private final World world; + private final QueueHandler handler; + + protected MultiThreadedQueue(QueueHandler handler, World world) { + super(handler.getQueue(world)); + this.world = world; + this.handler = handler; + } + + public IQueueExtent getQueue() { + return handler.getQueue(this.world); + } + + public T apply(final Region region, final T filter) { + // The chunks positions to iterate over + final Set chunks = region.getChunks(); + final Iterator chunksIter = chunks.iterator(); + + // Get a pool, to operate on the chunks in parallel + final int size = Math.min(chunks.size(), Settings.IMP.QUEUE.PARALLEL_THREADS); + final ForkJoinTask[] tasks = new ForkJoinTask[size]; + for (int i = 0; i < size; i++) { + tasks[i] = handler.submit(new Runnable() { + @Override + public void run() { + final Filter newFilter = filter.fork(); + // Create a chunk that we will reuse/reset for each operation + final IQueueExtent queue = wrapQueue(getQueue()); + synchronized (queue) { + ChunkFilterBlock block = null; + + while (true) { + // Get the next chunk posWeakChunk + final int X, Z; + synchronized (chunksIter) { + if (!chunksIter.hasNext()) break; + final BlockVector2 pos = chunksIter.next(); + X = pos.getX(); + Z = pos.getZ(); + } + if (!newFilter.appliesChunk(X, Z)) { + continue; + } + IChunk chunk = queue.getCachedChunk(X, Z); + // Initialize + chunk.init(queue, X, Z); + + IChunk newChunk = newFilter.applyChunk(chunk, region); + if (newChunk != null) { + chunk = newChunk; + if (block == null) block = queue.initFilterBlock(); + chunk.filterBlocks(newFilter, block, region); + } + queue.submit(chunk); + } + queue.flush(); + } + } + }); + } + // Join filters + for (int i = 0; i < tasks.length; i++) { + final ForkJoinTask task = tasks[i]; + if (task != null) { + task.quietlyJoin(); + } + } + filter.join(); + return filter; + } + + @Override + public int countBlocks(final Region region, final Mask searchMask) { + return + // Apply a filter over a region + apply(region, searchMask + .toFilter(new CountFilter())) // Adapt the mask to a filter which counts + .getParent() // Get the counter of this mask + .getTotal(); // Get the total from the counter + } + + @Override + public > int setBlocks(Region region, B block) throws MaxChangedBlocksException { + apply(region, block); + return 0; + } + + @Override + public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException { + apply(region, pattern); + return 0; + } + + @Override + public int replaceBlocks(Region region, Mask mask, Pattern pattern) throws MaxChangedBlocksException { + apply(region, mask.toFilter(pattern)); + return 0; + } + + @Override + public List> getBlockDistributionWithData(Region region) { + return apply(region, new DistrFilter()).getDistribution(); + } + + @Override + public List> getBlockDistribution(Region region) { + return apply(region, new DistrFilter()).getTypeDistribution(); + } +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java index 665f4043f..9a369fef5 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java @@ -70,6 +70,10 @@ public abstract class QueueHandler implements Trimable, Runnable { return forkJoinPoolSecondary.submit(call); } + public ForkJoinTask submit(final Runnable call) { + return forkJoinPoolPrimary.submit(call); + } + public Future sync(final Runnable run, final T value) { final FutureTask result = new FutureTask<>(run, value); syncTasks.add(result); @@ -143,61 +147,4 @@ public abstract class QueueHandler implements Trimable, Runnable { } return result; } - - public void apply(final World world, final Region region, final Filter filter) { - // The chunks positions to iterate over - final Set chunks = region.getChunks(); - final Iterator chunksIter = chunks.iterator(); - - // Get a pool, to operate on the chunks in parallel - final int size = Math.min(chunks.size(), Settings.IMP.QUEUE.PARALLEL_THREADS); - final ForkJoinTask[] tasks = new ForkJoinTask[size]; - for (int i = 0; i < size; i++) { - tasks[i] = forkJoinPoolPrimary.submit(new Runnable() { - @Override - public void run() { - final Filter newFilter = filter.fork(); - // Create a chunk that we will reuse/reset for each operation - final IQueueExtent queue = getQueue(world); - synchronized (queue) { - ChunkFilterBlock block = null; - - while (true) { - // Get the next chunk posWeakChunk - final int X, Z; - synchronized (chunksIter) { - if (!chunksIter.hasNext()) break; - final BlockVector2 pos = chunksIter.next(); - X = pos.getX(); - Z = pos.getZ(); - } - if (!newFilter.appliesChunk(X, Z)) { - continue; - } - IChunk chunk = queue.getCachedChunk(X, Z); - // Initialize - chunk.init(queue, X, Z); - - IChunk newChunk = newFilter.applyChunk(chunk, region); - if (newChunk != null) { - chunk = newChunk; - if (block == null) block = queue.initFilterBlock(); - chunk.filterBlocks(newFilter, block, region); - } - queue.submit(chunk); - } - queue.flush(); - } - } - }); - } - // Join filters - for (int i = 0; i < tasks.length; i++) { - final ForkJoinTask task = tasks[i]; - if (task != null) { - task.quietlyJoin(); - } - } - filter.join(); - } } \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/boydti/fawe/example/DefaultFaweQueueMap.java b/worldedit-core/src/main/java/com/boydti/fawe/example/DefaultFaweQueueMap.java deleted file mode 100644 index 08cb86e52..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/example/DefaultFaweQueueMap.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.boydti.fawe.example; - -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.FaweQueue; -import com.boydti.fawe.object.RunnableVal; -import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.SetQueue; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.ExecutorCompletionService; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -public class DefaultFaweQueueMap implements IFaweQueueMap { - - private final MappedFaweQueue parent; - - public DefaultFaweQueueMap(MappedFaweQueue parent) { - this.parent = parent; - } - - public final Long2ObjectOpenHashMap blocks = new Long2ObjectOpenHashMap() { - @Override - public FaweChunk put(Long key, FaweChunk value) { - return put((long) key, value); - } - - @Override - public FaweChunk put(long key, FaweChunk value) { - if (parent.getProgressTask() != null) { - try { - parent.getProgressTask().run(FaweQueue.ProgressType.QUEUE, size() + 1); - } catch (Throwable e) { - e.printStackTrace(); - } - } - synchronized (this) { - return super.put(key, value); - } - } - }; - - @Override - public Collection getFaweChunks() { - synchronized (blocks) { - return new HashSet<>(blocks.values()); - } - } - - @Override - public void forEachChunk(RunnableVal onEach) { - synchronized (blocks) { - for (Map.Entry entry : blocks.entrySet()) { - onEach.run(entry.getValue()); - } - } - } - - @Override - public FaweChunk getFaweChunk(int cx, int cz) { - if (cx == lastX && cz == lastZ) { - return lastWrappedChunk; - } - long pair = MathMan.pairInt(cx, cz); - FaweChunk chunk = this.blocks.get(pair); - if (chunk == null) { - chunk = this.getNewFaweChunk(cx, cz); - FaweChunk previous = this.blocks.put(pair, chunk); - if (previous != null) { - blocks.put(pair, previous); - return previous; - } - this.blocks.put(pair, chunk); - } - return chunk; - } - - @Override - public FaweChunk getCachedFaweChunk(int cx, int cz) { - if (cx == lastX && cz == lastZ) { - return lastWrappedChunk; - } - long pair = MathMan.pairInt(cx, cz); - FaweChunk chunk = this.blocks.get(pair); - lastWrappedChunk = chunk; - return chunk; - } - - @Override - public void add(FaweChunk chunk) { - long pair = MathMan.pairInt(chunk.getX(), chunk.getZ()); - FaweChunk previous = this.blocks.put(pair, chunk); - if (previous != null) { - blocks.put(pair, previous); - } - } - - - @Override - public void clear() { - blocks.clear(); - } - - @Override - public int size() { - return blocks.size(); - } - - private FaweChunk getNewFaweChunk(int cx, int cz) { - return parent.getFaweChunk(cx, cz); - } - - private volatile FaweChunk lastWrappedChunk; - private int lastX = Integer.MIN_VALUE; - private int lastZ = Integer.MIN_VALUE; - - @Override - public boolean next(int amount, long time) { - synchronized (blocks) { - try { - boolean skip = parent.getStage() == SetQueue.QueueStage.INACTIVE; - int added = 0; - Iterator> iter = blocks.entrySet().iterator(); - if (amount == 1) { - long start = System.currentTimeMillis(); - do { - if (iter.hasNext()) { - FaweChunk chunk = iter.next().getValue(); - if (skip && chunk == lastWrappedChunk) { - continue; - } - iter.remove(); - parent.start(chunk); - chunk.call(); - parent.end(chunk); - } else { - break; - } - } while (System.currentTimeMillis() - start < time); - } else { - ExecutorCompletionService service = SetQueue.IMP.getCompleterService(); - ForkJoinPool pool = SetQueue.IMP.getForkJoinPool(); - boolean result = true; - // amount = 8; - for (int i = 0; i < amount && (result = iter.hasNext()); i++) { - Map.Entry item = iter.next(); - FaweChunk chunk = item.getValue(); - if (skip && chunk == lastWrappedChunk) { - i--; - continue; - } - iter.remove(); - parent.start(chunk); - service.submit(chunk); - added++; - } - // if result, then submitted = amount - if (result) { - long start = System.currentTimeMillis(); - while (System.currentTimeMillis() - start < time && result) { - if (result = iter.hasNext()) { - Map.Entry item = iter.next(); - FaweChunk chunk = item.getValue(); - if (skip && chunk == lastWrappedChunk) { - continue; - } - iter.remove(); - parent.start(chunk); - service.submit(chunk); - Future future = service.poll(50, TimeUnit.MILLISECONDS); - if (future != null) { - FaweChunk fc = (FaweChunk) future.get(); - parent.end(fc); - } - } - } - } - pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS); - Future future; - while ((future = service.poll()) != null) { - FaweChunk fc = (FaweChunk) future.get(); - parent.end(fc); - } - } - } catch (Throwable e) { - e.printStackTrace(); - } - return !blocks.isEmpty(); - } - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/example/IFaweQueueMap.java b/worldedit-core/src/main/java/com/boydti/fawe/example/IFaweQueueMap.java deleted file mode 100644 index 2f2bbaa38..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/example/IFaweQueueMap.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.boydti.fawe.example; - -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.RunnableVal; -import java.util.Collection; - -public interface IFaweQueueMap { - - Collection getFaweChunks(); - - void forEachChunk(RunnableVal onEach); - - FaweChunk getFaweChunk(int cx, int cz); - - FaweChunk getCachedFaweChunk(int cx, int cz); - - void add(FaweChunk chunk); - - void clear(); - - int size(); - - boolean next(int size, long time); -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/example/IntFaweChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/example/IntFaweChunk.java deleted file mode 100644 index 9774c4786..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/example/IntFaweChunk.java +++ /dev/null @@ -1,244 +0,0 @@ -package com.boydti.fawe.example; - -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.FaweQueue; -import com.boydti.fawe.util.MathMan; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BlockID; - -import java.util.*; - -public abstract class IntFaweChunk extends FaweChunk { - - public final int[][] setBlocks; - public final short[] count; - public final short[] air; - - public BiomeType[] biomes; - public HashMap tiles; - public HashSet entities; - public HashSet entityRemoves; - - public T chunk; - - public IntFaweChunk(FaweQueue parent, int x, int z, int[][] setBlocks, short[] count, short[] air) { - super(parent, x, z); - this.setBlocks = setBlocks; - this.count = count; - this.air = air; - } - - /** - * A FaweSections object represents a chunk and the blocks that you wish to change in it. - * - * @param parent - * @param x - * @param z - */ - public IntFaweChunk(FaweQueue parent, int x, int z) { - super(parent, x, z); - this.setBlocks = new int[HEIGHT >> 4][]; - this.count = new short[HEIGHT >> 4]; - this.air = new short[HEIGHT >> 4]; - } - - @Override - public V getParent() { - return (V) super.getParent(); - } - - @Override - public T getChunk() { - if (this.chunk == null) { - this.chunk = getNewChunk(); - } - return this.chunk; - } - - public abstract T getNewChunk(); - - @Override - public void setLoc(final FaweQueue parent, int x, int z) { - super.setLoc(parent, x, z); - this.chunk = null; - } - - /** - * Get the number of block changes in a specified section - * - * @param i - * @return - */ - public int getCount(final int i) { - return this.count[i]; - } - - public int getAir(final int i) { - return this.air[i]; - } - - public void setCount(final int i, final short value) { - this.count[i] = value; - } - - public int getTotalCount() { - int total = 0; - for (short value : count) { - total += Math.min(4096, value); - } - return total; - } - - public int getTotalAir() { - int total = 0; - for (short value : air) { - total += Math.min(4096, value); - } - return total; - } - - @Override - public int getBitMask() { - int bitMask = 0; - for (int section = 0; section < setBlocks.length; section++) { - if (setBlocks[section] != null) { - bitMask += 1 << section; - } - } - return bitMask; - } - - /** - * Get the raw data for a section - * - * @param i - * @return - */ - @Override - public int[] getIdArray(final int i) { - return this.setBlocks[i]; - } - - @Override - public int[][] getCombinedIdArrays() { - return this.setBlocks; - } - - @Override - public BiomeType[] getBiomeArray() { - return this.biomes; - } - - @Override - public int getBlockCombinedId(int x, int y, int z) { - int[] array = getIdArray(y >> 4); - if (array == null) { - return 0; - } - return array[(((y & 0xF) << 8) | (z << 4) | x)]; - } - - @Override - public void setTile(int x, int y, int z, CompoundTag tile) { - if (tiles == null) { - tiles = new HashMap<>(); - } - short pair = MathMan.tripleBlockCoord(x, y, z); - tiles.put(pair, tile); - } - - @Override - public CompoundTag getTile(int x, int y, int z) { - if (tiles == null) { - return null; - } - short pair = MathMan.tripleBlockCoord(x, y, z); - return tiles.get(pair); - } - - @Override - public Map getTiles() { - return tiles == null ? new HashMap<>() : tiles; - } - - @Override - public Set getEntities() { - return entities == null ? Collections.emptySet() : entities; - } - - @Override - public void setEntity(CompoundTag tag) { - if (entities == null) { - entities = new HashSet<>(); - } - entities.add(tag); - } - - @Override - public void removeEntity(UUID uuid) { - if (entityRemoves == null) { - entityRemoves = new HashSet<>(); - } - entityRemoves.add(uuid); - } - - @Override - public HashSet getEntityRemoves() { - return entityRemoves == null ? new HashSet<>() : entityRemoves; - } - - @Override - public void setBlock(int x, int y, int z, int combinedId) { - final int i = y >> 4; - int[] vs = this.setBlocks[i]; - if (vs == null) { - vs = this.setBlocks[i] = new int[4096]; - } - int index = (((y & 15) << 8) | (z << 4) | x); - int existing = vs[index]; - vs[index] = combinedId; - switch (existing) { - case 0: - this.count[i]++; - switch (combinedId) { - case 0: - case BlockID.AIR: - case BlockID.CAVE_AIR: - case BlockID.VOID_AIR: - this.air[i]++; - } - break; - case BlockID.AIR: - case BlockID.CAVE_AIR: - case BlockID.VOID_AIR: - switch (combinedId) { - case 0: - case BlockID.AIR: - case BlockID.CAVE_AIR: - case BlockID.VOID_AIR: - break; - default: - this.air[i]--; - - } - } - return; - } - - @Deprecated - public void setBitMask(int ignore) { - // Remove - } - - @Override - public void setBiome(final int x, final int z, BiomeType biome) { - if (this.biomes == null) { - this.biomes = new BiomeType[256]; - } - biomes[((z & 15) << 4) + (x & 15)] = biome; - } - - @Override - public abstract IntFaweChunk copy(boolean shallow); -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java b/worldedit-core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java deleted file mode 100644 index fb988ab7a..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java +++ /dev/null @@ -1,789 +0,0 @@ -package com.boydti.fawe.example; - -import com.boydti.fawe.Fawe; -import com.boydti.fawe.FaweAPI; -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.FaweQueue; -import com.boydti.fawe.object.IntegerPair; -import com.boydti.fawe.object.RunnableVal; -import com.boydti.fawe.object.RunnableVal2; -import com.boydti.fawe.object.exception.FaweException; -import com.boydti.fawe.object.extent.LightingExtent; -import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.SetQueue; -import com.boydti.fawe.util.TaskManager; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.world.World; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BlockTypes; - -import java.util.ArrayDeque; -import java.util.Collection; -import java.util.HashSet; -import java.util.UUID; -import java.util.concurrent.ConcurrentLinkedDeque; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.TimeUnit; - -public abstract class MappedFaweQueue implements LightingExtent, FaweQueue { - - private WORLD impWorld; - - private IFaweQueueMap map; - - public int lastSectionX = Integer.MIN_VALUE; - public int lastSectionZ = Integer.MIN_VALUE; - public int lastSectionY = Integer.MIN_VALUE; - public CHUNK lastChunk; - public CHUNKSECTIONS lastChunkSections; - public SECTION lastSection; - - - private World weWorld; - private String world; - private ConcurrentLinkedDeque sessions; - private long modified = System.currentTimeMillis(); - private RunnableVal2 changeTask; - private RunnableVal2 progressTask; - private SetQueue.QueueStage stage; - private Settings settings = Settings.IMP; - public ConcurrentLinkedDeque tasks = new ConcurrentLinkedDeque<>(); - - private CHUNK cachedLoadChunk; - public final RunnableVal loadChunk = new RunnableVal() { - - { - this.value = new IntegerPair(0, 0); - } - - @Override - public void run(IntegerPair coord) { - cachedLoadChunk = loadChunk(getWorld(), coord.x, coord.z, true); - } - }; - - public MappedFaweQueue(final World world) { - this(world, null); - } - - public MappedFaweQueue(final String world) { - this.world = world; - map = getSettings().PREVENT_CRASHES ? new WeakFaweQueueMap(this) : new DefaultFaweQueueMap(this); - } - - public MappedFaweQueue(final String world, IFaweQueueMap map) { - this.world = world; - if (map == null) { - map = getSettings().PREVENT_CRASHES ? new WeakFaweQueueMap(this) : new DefaultFaweQueueMap(this); - } - this.map = map; - } - - public MappedFaweQueue(final World world, IFaweQueueMap map) { - this.weWorld = world; - if (world != null) this.world = world.getName(); - if (map == null) { - map = getSettings().PREVENT_CRASHES ? new WeakFaweQueueMap(this) : new DefaultFaweQueueMap(this); - } - this.map = map; - } - - @Override - public int getMaxY() { - return weWorld == null ? 255 : weWorld.getMaxY(); - } - - public IFaweQueueMap getFaweQueueMap() { - return map; - } - - @Override - public Collection getFaweChunks() { - return map.getFaweChunks(); - } - - @Override - public void optimize() { - final ForkJoinPool pool = TaskManager.IMP.getPublicForkJoinPool(); - map.forEachChunk(new RunnableVal() { - @Override - public void run(final FaweChunk chunk) { - pool.submit(chunk::optimize); - } - }); - pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS); - } - - public abstract WORLD getImpWorld(); - - public abstract boolean regenerateChunk(WORLD world, int x, int z, BiomeType biome, Long seed); - - @Override - public abstract FaweChunk getFaweChunk(int x, int z); - - public abstract CHUNK loadChunk(WORLD world, int x, int z, boolean generate); - - public abstract CHUNKSECTIONS getSections(CHUNK chunk); - - public abstract CHUNKSECTIONS getCachedSections(WORLD world, int cx, int cz); - - public abstract CHUNK getCachedChunk(WORLD world, int cx, int cz); - - public WORLD getWorld() { - if (impWorld != null) { - return impWorld; - } - return impWorld = getImpWorld(); - } - - @Override - public boolean regenerateChunk(int x, int z, BiomeType biome, Long seed) { - return regenerateChunk(getWorld(), x, z, biome, seed); - } - - @Override - public boolean setBlock(int x, int y, int z, int id) { - int cx = x >> 4; - int cz = z >> 4; - FaweChunk chunk = map.getFaweChunk(cx, cz); - chunk.setBlock(x & 15, y, z & 15, id); - return true; - } - - @Override - public void setTile(int x, int y, int z, CompoundTag tag) { - if ((y >= FaweChunk.HEIGHT) || (y < 0)) { - return; - } - int cx = x >> 4; - int cz = z >> 4; - FaweChunk chunk = map.getFaweChunk(cx, cz); - chunk.setTile(x & 15, y, z & 15, tag); - } - - @Override - public void setEntity(int x, int y, int z, CompoundTag tag) { - if ((y >= FaweChunk.HEIGHT) || (y < 0)) { - return; - } - int cx = x >> 4; - int cz = z >> 4; - FaweChunk chunk = map.getFaweChunk(cx, cz); - chunk.setEntity(tag); - } - - @Override - public void removeEntity(int x, int y, int z, UUID uuid) { - if ((y >= FaweChunk.HEIGHT) || (y < 0)) { - return; - } - int cx = x >> 4; - int cz = z >> 4; - FaweChunk chunk = map.getFaweChunk(cx, cz); - chunk.removeEntity(uuid); - } - - @Override - public boolean setBiome(int x, int z, BiomeType biome) { - int cx = x >> 4; - int cz = z >> 4; - FaweChunk chunk = map.getFaweChunk(cx, cz); - chunk.setBiome(x & 15, z & 15, biome); - return true; - } - - @Override - public boolean next(int amount, long time) { - return map.next(amount, time); - } - - public void start(FaweChunk chunk) { - chunk.start(); - } - - public void end(FaweChunk chunk) { - if (getProgressTask() != null) { - getProgressTask().run(ProgressType.DISPATCH, size() + 1); - } - chunk.end(); - } - - @Override - public void runTasks() { - synchronized (this) { - this.notifyAll(); - } - if (getProgressTask() != null) { - try { - getProgressTask().run(ProgressType.DONE, 1); - } catch (Throwable e) { - e.printStackTrace(); - } - } - while (!tasks.isEmpty()) { - Runnable task = tasks.poll(); - if (task != null) { - try { - task.run(); - } catch (Throwable e) { - e.printStackTrace(); - } - } - } - if (getProgressTask() != null) { - try { - getProgressTask().run(ProgressType.DONE, 1); - } catch (Throwable e) { - e.printStackTrace(); - } - } - ArrayDeque tmp = new ArrayDeque<>(tasks); - tasks.clear(); - for (Runnable run : tmp) { - try { - run.run(); - } catch (Throwable e) { - e.printStackTrace(); - } - } - } - - public Settings getSettings() { - return settings; - } - - public void setSettings(Settings settings) { - this.settings = settings == null ? Settings.IMP : settings; - } - - public void setWorld(String world) { - this.world = world; - this.weWorld = null; - } - - public World getWEWorld() { - return weWorld != null ? weWorld : (weWorld = FaweAPI.getWorld(world)); - } - - public String getWorldName() { - return world; - } - - @Override - public Collection getEditSessions() { - Collection tmp = sessions; - if (tmp == null) tmp = new HashSet<>(); - return tmp; - } - - @Override - public void addEditSession(EditSession session) { - ConcurrentLinkedDeque tmp = sessions; - if (tmp == null) tmp = new ConcurrentLinkedDeque<>(); - tmp.add(session); - this.sessions = tmp; - } - - @Override - public boolean supports(Capability capability) { - if (capability == Capability.CHANGE_TASKS) { - return true; - } - return false; - } - - public void setSessions(ConcurrentLinkedDeque sessions) { - this.sessions = sessions; - } - - public long getModified() { - return modified; - } - - public void setModified(long modified) { - this.modified = modified; - } - - public RunnableVal2 getProgressTask() { - return progressTask; - } - - public void setProgressTask(RunnableVal2 progressTask) { - this.progressTask = progressTask; - } - - public void setChangeTask(RunnableVal2 changeTask) { - this.changeTask = changeTask; - } - - public RunnableVal2 getChangeTask() { - return changeTask; - } - - public SetQueue.QueueStage getStage() { - return stage; - } - - public void setStage(SetQueue.QueueStage stage) { - this.stage = stage; - } - - public void addNotifyTask(Runnable runnable) { - this.tasks.add(runnable); - } - - public void addTask(Runnable whenFree) { - tasks.add(whenFree); - } - - @Override - public int size() { - int size = map.size(); - if (size == 0 && getStage() == SetQueue.QueueStage.NONE) { - runTasks(); - } - return size; - } - - @Override - public void clear() { - lastSectionX = Integer.MIN_VALUE; - lastSectionZ = Integer.MIN_VALUE; - lastSectionY = -1; - lastChunk = null; - lastChunkSections = null; - map.clear(); - runTasks(); - } - - @Override - public void setChunk(FaweChunk chunk) { - map.add(chunk); - } - - public SECTION getCachedSection(CHUNKSECTIONS chunk, int cy) { - return (SECTION) lastChunkSections; - } - - public abstract int getCombinedId4Data(SECTION section, int x, int y, int z); - - public int getLocalCombinedId4Data(CHUNK chunk, int x, int y, int z) { - CHUNKSECTIONS sections = getSections(lastChunk); - SECTION section = getCachedSection(sections, y >> 4); - if (section == null) { - return BlockTypes.AIR.getInternalId(); - } - return getCombinedId4Data(lastSection, x, y, z); - } - - public abstract BiomeType getBiome(CHUNK chunk, int x, int z); - - public abstract CompoundTag getTileEntity(CHUNK chunk, int x, int y, int z); - - public CHUNK ensureChunkLoaded(int cx, int cz) throws FaweException.FaweChunkLoadException { - CHUNK chunk = getCachedChunk(getWorld(), cx, cz); - if (chunk != null) { - return chunk; - } - boolean sync = Fawe.isMainThread(); - if (sync) { - return loadChunk(getWorld(), cx, cz, true); - } else if (getSettings().HISTORY.CHUNK_WAIT_MS > 0) { - cachedLoadChunk = null; - loadChunk.value.x = cx; - loadChunk.value.z = cz; - TaskManager.IMP.syncWhenFree(loadChunk, getSettings().HISTORY.CHUNK_WAIT_MS); - return cachedLoadChunk; - } else { - return null; - } - } - - public boolean queueChunkLoad(final int cx, final int cz) { - CHUNK chunk = getCachedChunk(getWorld(), cx, cz); - if (chunk == null) { - SetQueue.IMP.addTask(() -> loadChunk(getWorld(), cx, cz, true)); - return true; - } - return false; - } - - public boolean queueChunkLoad(final int cx, final int cz, RunnableVal operation) { - operation.value = getCachedChunk(getWorld(), cx, cz); - if (operation.value == null) { - SetQueue.IMP.addTask(() -> { - operation.value = loadChunk(getWorld(), cx, cz, true); - if (operation.value != null) TaskManager.IMP.async(operation); - }); - return true; - } else { - TaskManager.IMP.async(operation); - } - return false; - } - - @Override - public boolean hasBlock(int x, int y, int z) throws FaweException.FaweChunkLoadException { - int cx = x >> 4; - int cz = z >> 4; - int cy = y >> 4; - if (cx != lastSectionX || cz != lastSectionZ) { - lastSectionX = cx; - lastSectionZ = cz; - lastChunk = ensureChunkLoaded(cx, cz); - if (lastChunk != null) { - lastChunkSections = getSections(lastChunk); - lastSection = getCachedSection(lastChunkSections, cy); - } else { - lastChunkSections = null; - return false; - } - } else if (cy != lastSectionY) { - if (lastChunkSections != null) { - lastSection = getCachedSection(lastChunkSections, cy); - } else { - return false; - } - } - if (lastSection == null) { - return false; - } - return hasBlock(lastSection, x, y, z); - } - - public boolean hasBlock(SECTION section, int x, int y, int z) { - return getCombinedId4Data(lastSection, x, y, z) != 0; - } - - public int getOpacity(SECTION section, int x, int y, int z) { - int combined = getCombinedId4Data(section, x, y, z); - if (combined == 0) { - return 0; - } - return Math.min(15, BlockTypes.getFromStateId(combined).getMaterial().getLightOpacity()); - } - - public int getBrightness(SECTION section, int x, int y, int z) { - int combined = getCombinedId4Data(section, x, y, z); - if (combined == 0) { - return 0; - } - return Math.min(15, BlockTypes.getFromStateId(combined).getMaterial().getLightValue()); - } - - public int getOpacityBrightnessPair(SECTION section, int x, int y, int z) { - return MathMan.pair16(Math.min(15, getOpacity(section, x, y, z)), getBrightness(section, x, y, z)); - } - - public abstract int getSkyLight(SECTION sections, int x, int y, int z); - - public abstract int getEmmittedLight(SECTION sections, int x, int y, int z); - - public int getLight(SECTION sections, int x, int y, int z) { - if (!hasSky()) { - return getEmmittedLight(sections, x, y, z); - } - return Math.max(getSkyLight(sections, x, y, z), getEmmittedLight(sections, x, y, z)); - } - - @Override - public int getLight(int x, int y, int z) { - int cx = x >> 4; - int cz = z >> 4; - int cy = y >> 4; - if (cx != lastSectionX || cz != lastSectionZ) { - lastSectionX = cx; - lastSectionZ = cz; - lastChunk = ensureChunkLoaded(cx, cz); - if (lastChunk != null) { - lastChunkSections = getSections(lastChunk); - lastSection = getCachedSection(lastChunkSections, cy); - } else { - lastChunkSections = null; - return 0; - } - } else if (cy != lastSectionY) { - if (lastChunkSections != null) { - lastSection = getCachedSection(lastChunkSections, cy); - } else { - return 0; - } - } - if (lastSection == null) { - return 0; - } - return getLight(lastSection, x, y, z); - } - - @Override - public int getSkyLight(int x, int y, int z) { - int cx = x >> 4; - int cz = z >> 4; - int cy = y >> 4; - if (cx != lastSectionX || cz != lastSectionZ) { - lastSectionX = cx; - lastSectionZ = cz; - lastChunk = ensureChunkLoaded(cx, cz); - if (lastChunk != null) { - lastChunkSections = getSections(lastChunk); - lastSection = getCachedSection(lastChunkSections, cy); - } else { - lastChunkSections = null; - return 0; - } - } else if (cy != lastSectionY) { - if (lastChunkSections != null) { - lastSection = getCachedSection(lastChunkSections, cy); - } else { - return 0; - } - } - if (lastSection == null) { - if (lastChunkSections == null) { - return 0; - } - int max = FaweChunk.HEIGHT >> 4; - do { - if (++cy >= max) { - return 15; - } - lastSection = getCachedSection(lastChunkSections, cy); - } while (lastSection == null); - } - if (lastSection == null) { - - return getSkyLight(x, y + 16, z); - } - return getSkyLight(lastSection, x, y, z); - } - - @Override - public int getBlockLight(int x, int y, int z) { - return getEmmittedLight(x, y, z); - } - - @Override - public int getEmmittedLight(int x, int y, int z) { - int cx = x >> 4; - int cz = z >> 4; - int cy = y >> 4; - if (cx != lastSectionX || cz != lastSectionZ) { - lastSectionX = cx; - lastSectionZ = cz; - lastChunk = ensureChunkLoaded(cx, cz); - if (lastChunk != null) { - lastChunkSections = getSections(lastChunk); - lastSection = getCachedSection(lastChunkSections, cy); - } else { - lastChunkSections = null; - return 0; - } - } else if (cy != lastSectionY) { - if (lastChunkSections != null) { - lastSection = getCachedSection(lastChunkSections, cy); - } else { - return 0; - } - } - if (lastSection == null) { - return 0; - } - return getEmmittedLight(lastSection, x, y, z); - } - - @Override - public int getOpacity(int x, int y, int z) { - int cx = x >> 4; - int cz = z >> 4; - int cy = y >> 4; - if (cx != lastSectionX || cz != lastSectionZ) { - lastSectionX = cx; - lastSectionZ = cz; - lastChunk = ensureChunkLoaded(cx, cz); - if (lastChunk != null) { - lastChunkSections = getSections(lastChunk); - lastSection = getCachedSection(lastChunkSections, cy); - } else { - lastChunkSections = null; - return 0; - } - } else if (cy != lastSectionY) { - if (lastChunkSections != null) { - lastSection = getCachedSection(lastChunkSections, cy); - } else { - return 0; - } - } - if (lastSection == null) { - return 0; - } - return getOpacity(lastSection, x, y, z); - } - - @Override - public int getOpacityBrightnessPair(int x, int y, int z) { - int cx = x >> 4; - int cz = z >> 4; - int cy = y >> 4; - if (cx != lastSectionX || cz != lastSectionZ) { - lastSectionX = cx; - lastSectionZ = cz; - lastChunk = ensureChunkLoaded(cx, cz); - if (lastChunk != null) { - lastChunkSections = getSections(lastChunk); - lastSection = getCachedSection(lastChunkSections, cy); - } else { - lastChunkSections = null; - return 0; - } - } else if (cy != lastSectionY) { - if (lastChunkSections != null) { - lastSection = getCachedSection(lastChunkSections, cy); - } else { - return 0; - } - } - if (lastSection == null) { - return 0; - } - return getOpacityBrightnessPair(lastSection, x, y, z); - } - - @Override - public int getBrightness(int x, int y, int z) { - int cx = x >> 4; - int cz = z >> 4; - int cy = y >> 4; - if (cx != lastSectionX || cz != lastSectionZ) { - lastSectionX = cx; - lastSectionZ = cz; - lastChunk = ensureChunkLoaded(cx, cz); - if (lastChunk != null) { - lastChunkSections = getSections(lastChunk); - lastSection = getCachedSection(lastChunkSections, cy); - } else { - lastChunkSections = null; - return 0; - } - } else if (cy != lastSectionY) { - if (lastChunkSections != null) { - lastSection = getCachedSection(lastChunkSections, cy); - } else { - return 0; - } - } - if (lastSection == null) { - return 0; - } - return getBrightness(lastSection, x, y, z); - } - - @Override - public int getCachedCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException { - int cx = x >> 4; - int cz = z >> 4; - FaweChunk fc = map.getCachedFaweChunk(cx, cz); - if (fc != null) { - int combined = fc.getBlockCombinedId(x & 15, y, z & 15); - if (combined != 0) { - return combined; - } - } - int cy = y >> 4; - if (cx != lastSectionX || cz != lastSectionZ) { - lastSectionX = cx; - lastSectionZ = cz; - lastChunk = ensureChunkLoaded(cx, cz); - if (lastChunk != null) { - lastChunkSections = getSections(lastChunk); - lastSection = getCachedSection(lastChunkSections, cy); - } else { - lastChunkSections = null; - return BlockTypes.AIR.getInternalId(); - } - } else if (cy != lastSectionY) { - if (lastChunkSections != null) { - lastSection = getCachedSection(lastChunkSections, cy); - } else { - return BlockTypes.AIR.getInternalId(); - } - } - if (lastSection == null) { - return BlockTypes.AIR.getInternalId(); - } - return getCombinedId4Data(lastSection, x, y, z); - } - - @Override - public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException { - int cx = x >> 4; - int cz = z >> 4; - int cy = y >> 4; - if (cx != lastSectionX || cz != lastSectionZ) { - lastSectionX = cx; - lastSectionZ = cz; - lastChunk = ensureChunkLoaded(cx, cz); - if (lastChunk != null) { - lastChunkSections = getSections(lastChunk); - lastSection = getCachedSection(lastChunkSections, cy); - } else { - lastChunkSections = null; - return BlockTypes.AIR.getInternalId(); - } - } else if (cy != lastSectionY) { - if (lastChunkSections != null) { - lastSection = getCachedSection(lastChunkSections, cy); - } else { - return BlockTypes.AIR.getInternalId(); - } - } - if (lastSection == null) { - return BlockTypes.AIR.getInternalId(); - } - return getCombinedId4Data(lastSection, x, y, z); - } - - @Override - public BiomeType getBiomeType(int x, int z) throws FaweException.FaweChunkLoadException { - int cx = x >> 4; - int cz = z >> 4; - lastSectionY = -1; - if (cx != lastSectionX || cz != lastSectionZ) { - lastSectionX = cx; - lastSectionZ = cz; - lastChunk = ensureChunkLoaded(cx, cz); - if (lastChunk != null) { - lastChunkSections = getSections(lastChunk); - } else { - lastChunkSections = null; - return null; - } - } else if (lastChunk == null) { - return null; - } - return getBiome(lastChunk, x, z); - } - - @Override - public CompoundTag getTileEntity(int x, int y, int z) throws FaweException.FaweChunkLoadException { - int cx = x >> 4; - int cz = z >> 4; - lastSectionY = -1; - if (cx != lastSectionX || cz != lastSectionZ) { - lastSectionX = cx; - lastSectionZ = cz; - lastChunk = ensureChunkLoaded(cx, cz); - if (lastChunk != null) { - lastChunkSections = getSections(lastChunk); - } else { - lastChunkSections = null; - return null; - } - } else if (lastChunk == null) { - return null; - } - return getTileEntity(lastChunk, x, y, z); - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java b/worldedit-core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java deleted file mode 100644 index aa04b611f..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java +++ /dev/null @@ -1,216 +0,0 @@ -package com.boydti.fawe.example; - -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.util.TaskManager; -import com.sk89q.worldedit.world.World; -import com.sk89q.worldedit.world.block.BlockTypes; - -public abstract class NMSMappedFaweQueue extends MappedFaweQueue { - - private final int maxY; - - public NMSMappedFaweQueue(World world) { - super(world); - this.maxY = world.getMaxY(); - } - - public NMSMappedFaweQueue(String world) { - super(world); - this.maxY = 256; - } - - public NMSMappedFaweQueue(String world, IFaweQueueMap map) { - super(world, map); - this.maxY = 256; - } - - public NMSMappedFaweQueue(World world, IFaweQueueMap map) { - super(world, map); - this.maxY = world.getMaxY(); - } - - @Override - public void runTasks() { - super.runTasks(); - if (!getRelighter().isEmpty()) { - TaskManager.IMP.async(() -> { - if (getSettings().IMP.LIGHTING.REMOVE_FIRST) { - getRelighter().removeAndRelight(hasSky()); - } else { - getRelighter().fixLightingSafe(hasSky()); - } - }); - } - } - - private final Relighter relighter = getSettings().IMP.LIGHTING.MODE > 0 ? new NMSRelighter(this) : NullRelighter.INSTANCE; - - @Override - public Relighter getRelighter() { - return relighter; - } - - @Override - public void end(FaweChunk chunk) { - super.end(chunk); - if (getSettings().IMP.LIGHTING.MODE == 0) { - sendChunk(chunk); - return; - } - if (!getSettings().IMP.LIGHTING.DELAY_PACKET_SENDING) { - sendChunk(chunk); - } - if (getSettings().IMP.LIGHTING.MODE == 2) { - getRelighter().addChunk(chunk.getX(), chunk.getZ(), null, chunk.getBitMask()); - return; - } - IntFaweChunk cfc = (IntFaweChunk) chunk; - boolean relight = false; - byte[] fix = new byte[(maxY + 1) >> 4]; - boolean sky = hasSky(); - if (sky) { - int layers = FaweChunk.HEIGHT >> 4; - for (int i = layers - 1; i >= 0; i--) { - int air = cfc.getAir(i); - int solid = cfc.getCount(i); - if (air == 4096) { - fix[i] = Relighter.SkipReason.AIR; - } else if (air == 0 && solid == 4096) { - fix[i] = Relighter.SkipReason.SOLID; - } else if (solid == 0 && relight == false) { - fix[i] = Relighter.SkipReason.AIR; - } else { - fix[i] = Relighter.SkipReason.NONE; - relight = true; - } - } - } - if (relight) { - getRelighter().addChunk(chunk.getX(), chunk.getZ(), fix, chunk.getBitMask()); - } else if (getSettings().IMP.LIGHTING.DELAY_PACKET_SENDING) { - sendChunk(chunk); - } - } - - @Override - public void sendChunk(final FaweChunk fc) { - try { - refreshChunk(fc); - } catch (Throwable e) { - e.printStackTrace(); - } - } - - public abstract void setFullbright(CHUNKSECTION sections); - - public boolean removeLighting(CHUNKSECTION sections, RelightMode mode, boolean hasSky) { - boolean result = false; - for (int i = 0; i < 16; i++) { - SECTION section = getCachedSection(sections, i); - if (section != null) { - result |= removeSectionLighting(section, i, hasSky); - } - } - return result; - } - - public abstract boolean removeSectionLighting(SECTION sections, int layer, boolean hasSky); - - public boolean isSurrounded(final char[][] sections, final int x, final int y, final int z) { - return this.isSolid(this.getId(sections, x, y + 1, z)) - && this.isSolid(this.getId(sections, x + 1, y - 1, z)) - && this.isSolid(this.getId(sections, x - 1, y, z)) - && this.isSolid(this.getId(sections, x, y, z + 1)) - && this.isSolid(this.getId(sections, x, y, z - 1)); - } - - public boolean isSolid(final int id) { - return !BlockTypes.get(id).getMaterial().isTranslucent(); - } - - public int getId(final char[][] sections, final int x, final int y, final int z) { - if ((x < 0) || (x > 15) || (z < 0) || (z > 15)) { - return BlockTypes.AIR.getInternalId(); - } - if ((y < 0) || (y > maxY)) { - return BlockTypes.AIR.getInternalId(); - } - final int i = y >> 4; - final char[] section = sections[i]; - if (section == null) { - return 0; - } - return section[(((y & 0xF) << 8) | (z << 4) | x)] >> 4; - } - - public void saveChunk(CHUNK chunk) { - } - - public abstract void relight(int x, int y, int z); - - public abstract void relightBlock(int x, int y, int z); - - public abstract void relightSky(int x, int y, int z); - - public void setSkyLight(int x, int y, int z, int value) { - int cx = x >> 4; - int cz = z >> 4; - int cy = y >> 4; - if (cx != lastSectionX || cz != lastSectionZ) { - lastSectionX = cx; - lastSectionZ = cz; - lastChunk = ensureChunkLoaded(cx, cz); - if (lastChunk != null) { - lastChunkSections = getSections(lastChunk); - lastSection = getCachedSection(lastChunkSections, cy); - } else { - lastChunkSections = null; - return; - } - } else if (cy != lastSectionY) { - if (lastChunkSections != null) { - lastSection = getCachedSection(lastChunkSections, cy); - } else { - return; - } - } - if (lastSection == null) { - return; - } - setSkyLight(lastSection, x, y, z, value); - } - - public void setBlockLight(int x, int y, int z, int value) { - int cx = x >> 4; - int cz = z >> 4; - int cy = y >> 4; - if (cx != lastSectionX || cz != lastSectionZ) { - lastSectionX = cx; - lastSectionZ = cz; - lastChunk = ensureChunkLoaded(cx, cz); - if (lastChunk != null) { - lastChunkSections = getSections(lastChunk); - lastSection = getCachedSection(lastChunkSections, cy); - } else { - lastChunkSections = null; - return; - } - } else if (cy != lastSectionY) { - if (lastChunkSections != null) { - lastSection = getCachedSection(lastChunkSections, cy); - } else { - return; - } - } - if (lastSection == null) { - return; - } - setBlockLight(lastSection, x, y, z, value); - } - - public abstract void setSkyLight(SECTION section, int x, int y, int z, int value); - - public abstract void setBlockLight(SECTION section, int x, int y, int z, int value); - - public abstract void refreshChunk(FaweChunk fs); -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/example/NMSRelighter.java b/worldedit-core/src/main/java/com/boydti/fawe/example/NMSRelighter.java deleted file mode 100644 index 6e4a79629..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/example/NMSRelighter.java +++ /dev/null @@ -1,597 +0,0 @@ -package com.boydti.fawe.example; - -import com.boydti.fawe.FaweCache; -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.FaweQueue; -import com.boydti.fawe.object.IntegerTrio; -import com.boydti.fawe.object.RunnableVal; -import com.boydti.fawe.object.collection.BlockVectorSet; -import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.TaskManager; -import com.google.common.io.LineReader; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; - -import java.io.*; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.atomic.AtomicBoolean; - -public class NMSRelighter implements Relighter { - private final NMSMappedFaweQueue queue; - - private final Map skyToRelight; - private final Object present = new Object(); - private final Map chunksToSend; - private final ConcurrentLinkedQueue queuedSkyToRelight = new ConcurrentLinkedQueue<>(); - - private final Map lightQueue; - private final AtomicBoolean lightLock = new AtomicBoolean(false); - private final ConcurrentHashMap concurrentLightQueue; - - private final int maxY; - private volatile boolean relighting = false; - - public final IntegerTrio mutableBlockPos = new IntegerTrio(); - - private static final int DISPATCH_SIZE = 64; - private boolean removeFirst; - - public NMSRelighter(NMSMappedFaweQueue queue) { - this.queue = queue; - this.skyToRelight = new Long2ObjectOpenHashMap<>(); - this.lightQueue = new Long2ObjectOpenHashMap<>(); - this.chunksToSend = new Long2ObjectOpenHashMap<>(); - this.concurrentLightQueue = new ConcurrentHashMap<>(); - this.maxY = queue.getMaxY(); - } - - @Override - public boolean isEmpty() { - return skyToRelight.isEmpty() && lightQueue.isEmpty() && queuedSkyToRelight.isEmpty() && concurrentLightQueue.isEmpty(); - } - - @Override - public synchronized void removeAndRelight(boolean sky) { - removeFirst = true; - fixLightingSafe(sky); - removeFirst = false; - } - - private void set(int x, int y, int z, long[][][] map) { - long[][] m1 = map[z]; - if (m1 == null) { - m1 = map[z] = new long[16][]; - } - long[] m2 = m1[x]; - if (m2 == null) { - m2 = m1[x] = new long[4]; - } - long value = m2[y >> 6] |= 1l << y; - } - - public void addLightUpdate(int x, int y, int z) { - long index = MathMan.pairInt(x >> 4, z >> 4); - if (lightLock.compareAndSet(false, true)) { - synchronized (lightQueue) { - try { - long[][][] currentMap = lightQueue.get(index); - if (currentMap == null) { - currentMap = new long[16][][]; - this.lightQueue.put(index, currentMap); - } - set(x & 15, y, z & 15, currentMap); - } finally { - lightLock.set(false); - } - } - } else { - long[][][] currentMap = concurrentLightQueue.get(index); - if (currentMap == null) { - currentMap = new long[16][][]; - this.concurrentLightQueue.put(index, currentMap); - } - set(x & 15, y, z & 15, currentMap); - } - } - - public synchronized void clear() { - queuedSkyToRelight.clear(); - skyToRelight.clear(); - chunksToSend.clear(); - lightQueue.clear(); - concurrentLightQueue.clear(); - } - - public boolean addChunk(int cx, int cz, byte[] fix, int bitmask) { - RelightSkyEntry toPut = new RelightSkyEntry(cx, cz, fix, bitmask); - queuedSkyToRelight.add(toPut); - return true; - } - - private synchronized Map getSkyMap() { - RelightSkyEntry entry; - while ((entry = queuedSkyToRelight.poll()) != null) { - long pair = MathMan.pairInt(entry.x, entry.z); - RelightSkyEntry existing = skyToRelight.put(pair, entry); - if (existing != null) { - entry.bitmask |= existing.bitmask; - if (entry.fix != null) { - for (int i = 0; i < entry.fix.length; i++) { - entry.fix[i] &= existing.fix[i]; - } - } - } - } - return skyToRelight; - } - - public synchronized void removeLighting() { - Iterator> iter = getSkyMap().entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry entry = iter.next(); - RelightSkyEntry chunk = entry.getValue(); - long pair = entry.getKey(); - Integer existing = chunksToSend.get(pair); - chunksToSend.put(pair, chunk.bitmask | (existing != null ? existing : 0)); - queue.ensureChunkLoaded(chunk.x, chunk.z); - Object sections = queue.getCachedSections(queue.getWorld(), chunk.x, chunk.z); - queue.removeLighting(sections, FaweQueue.RelightMode.ALL, queue.hasSky()); - iter.remove(); - } - } - - public void updateBlockLight(Map map) { - int size = map.size(); - if (size == 0) { - return; - } - Queue lightPropagationQueue = new ArrayDeque<>(); - Queue lightRemovalQueue = new ArrayDeque<>(); - Map visited = new HashMap<>(); - Map removalVisited = new HashMap<>(); - - Iterator> iter = map.entrySet().iterator(); - while (iter.hasNext() && size-- > 0) { - Map.Entry entry = iter.next(); - long index = entry.getKey(); - long[][][] blocks = entry.getValue(); - int chunkX = MathMan.unpairIntX(index); - int chunkZ = MathMan.unpairIntY(index); - int bx = chunkX << 4; - int bz = chunkZ << 4; - for (int lz = 0; lz < blocks.length; lz++) { - long[][] m1 = blocks[lz]; - if (m1 == null) continue; - for (int lx = 0; lx < m1.length; lx++) { - long[] m2 = m1[lx]; - if (m2 == null) continue; - for (int i = 0; i < m2.length; i++) { - int yStart = i << 6; - long value = m2[i]; - if (value != 0) { - for (int j = 0; j < 64; j++) { - if (((value >> j) & 1) == 1) { - int x = lx + bx; - int y = yStart + j; - int z = lz + bz; - int oldLevel = queue.getEmmittedLight(x, y, z); - int newLevel = queue.getBrightness(x, y, z); - if (oldLevel != newLevel) { - queue.setBlockLight(x, y, z, newLevel); - IntegerTrio node = new IntegerTrio(x, y, z); - if (newLevel < oldLevel) { - removalVisited.put(node, present); - lightRemovalQueue.add(new Object[]{node, oldLevel}); - } else { - visited.put(node, present); - lightPropagationQueue.add(node); - } - } - } - } - } - } - } - } - iter.remove(); - } - - while (!lightRemovalQueue.isEmpty()) { - Object[] val = lightRemovalQueue.poll(); - IntegerTrio node = (IntegerTrio) val[0]; - int lightLevel = (int) val[1]; - - this.computeRemoveBlockLight(node.x - 1, node.y, node.z, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited); - this.computeRemoveBlockLight(node.x + 1, node.y, node.z, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited); - if (node.y > 0) { - this.computeRemoveBlockLight(node.x, node.y - 1, node.z, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited); - } - if (node.y < 255) { - this.computeRemoveBlockLight(node.x, node.y + 1, node.z, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited); - } - this.computeRemoveBlockLight(node.x, node.y, node.z - 1, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited); - this.computeRemoveBlockLight(node.x, node.y, node.z + 1, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited); - } - - while (!lightPropagationQueue.isEmpty()) { - IntegerTrio node = lightPropagationQueue.poll(); - int lightLevel = queue.getEmmittedLight(node.x, node.y, node.z); - if (lightLevel > 1) { - this.computeSpreadBlockLight(node.x - 1, node.y, node.z, lightLevel, lightPropagationQueue, visited); - this.computeSpreadBlockLight(node.x + 1, node.y, node.z, lightLevel, lightPropagationQueue, visited); - if (node.y > 0) { - this.computeSpreadBlockLight(node.x, node.y - 1, node.z, lightLevel, lightPropagationQueue, visited); - } - if (node.y < 255) { - this.computeSpreadBlockLight(node.x, node.y + 1, node.z, lightLevel, lightPropagationQueue, visited); - } - this.computeSpreadBlockLight(node.x, node.y, node.z - 1, lightLevel, lightPropagationQueue, visited); - this.computeSpreadBlockLight(node.x, node.y, node.z + 1, lightLevel, lightPropagationQueue, visited); - } - } - } - - private void computeRemoveBlockLight(int x, int y, int z, int currentLight, Queue queue, Queue spreadQueue, Map visited, - Map spreadVisited) { - int current = this.queue.getEmmittedLight(x, y, z); - if (current != 0 && current < currentLight) { - this.queue.setBlockLight(x, y, z, 0); - if (current > 1) { - if (!visited.containsKey(mutableBlockPos)) { - IntegerTrio index = new IntegerTrio(x, y, z); - visited.put(index, present); - queue.add(new Object[]{index, current}); - } - } - } else if (current >= currentLight) { - mutableBlockPos.set(x, y, z); - if (!spreadVisited.containsKey(mutableBlockPos)) { - IntegerTrio index = new IntegerTrio(x, y, z); - spreadVisited.put(index, present); - spreadQueue.add(index); - } - } - } - - private void computeSpreadBlockLight(int x, int y, int z, int currentLight, Queue queue, Map visited) { - currentLight = currentLight - Math.max(1, this.queue.getOpacity(x, y, z)); - if (currentLight > 0) { - int current = this.queue.getEmmittedLight(x, y, z); - if (current < currentLight) { - this.queue.setBlockLight(x, y, z, currentLight); - mutableBlockPos.set(x, y, z); - if (!visited.containsKey(mutableBlockPos)) { - visited.put(new IntegerTrio(x, y, z), present); - if (currentLight > 1) { - queue.add(new IntegerTrio(x, y, z)); - } - } - } - } - } - - public void fixLightingSafe(boolean sky) { - if (isEmpty()) return; - try { - if (sky) { - fixSkyLighting(); - } else { - synchronized (this) { - Map map = getSkyMap(); - Iterator> iter = map.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry entry = iter.next(); - chunksToSend.put(entry.getKey(), entry.getValue().bitmask); - iter.remove(); - } - } - } - fixBlockLighting(); - sendChunks(); - } catch (Throwable e) { - e.printStackTrace(); - } - } - - public void fixBlockLighting() { - synchronized (lightQueue) { - while (!lightLock.compareAndSet(false, true)); - try { - updateBlockLight(this.lightQueue); - } finally { - lightLock.set(false); - } - } - } - - public synchronized void sendChunks() { - RunnableVal runnable = new RunnableVal() { - @Override - public void run(Object value) { - Iterator> iter = chunksToSend.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry entry = iter.next(); - long pair = entry.getKey(); - int bitMask = entry.getValue(); - int x = MathMan.unpairIntX(pair); - int z = MathMan.unpairIntY(pair); - queue.sendChunk(x, z, bitMask); - iter.remove(); - } - } - }; - if (Settings.IMP.LIGHTING.ASYNC) { - runnable.run(); - } else { - TaskManager.IMP.sync(runnable); - } - } - - private boolean isTransparent(int x, int y, int z) { - return queue.getOpacity(x, y, z) < 15; - } - - public synchronized void fixSkyLighting() { - // Order chunks - Map map = getSkyMap(); - ArrayList chunksList = new ArrayList<>(map.size()); - Iterator> iter = map.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry entry = iter.next(); - chunksToSend.put(entry.getKey(), entry.getValue().bitmask); - chunksList.add(entry.getValue()); - iter.remove(); - } - Collections.sort(chunksList); - int size = chunksList.size(); - if (size > DISPATCH_SIZE) { - int amount = (size + DISPATCH_SIZE - 1) / DISPATCH_SIZE; - for (int i = 0; i < amount; i++) { - int start = i * DISPATCH_SIZE; - int end = Math.min(size, start + DISPATCH_SIZE); - List sub = chunksList.subList(start, end); - fixSkyLighting(sub); - } - } else { - fixSkyLighting(chunksList); - } - } - - public void fill(byte[] mask, int chunkX, int y, int chunkZ, byte reason) { - if (y >= FaweChunk.HEIGHT) { - Arrays.fill(mask, (byte) 15); - return; - } - switch (reason) { - case SkipReason.SOLID: { - Arrays.fill(mask, (byte) 0); - return; - } - case SkipReason.AIR: { - int bx = chunkX << 4; - int bz = chunkZ << 4; - int index = 0; - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++) { - mask[index++] = (byte) queue.getSkyLight(bx + x, y, bz + z); - } - } - } - } - } - - private void fixSkyLighting(List sorted) { - RelightSkyEntry[] chunks = sorted.toArray(new RelightSkyEntry[0]); - boolean remove = this.removeFirst; - BlockVectorSet chunkSet = null; - if (remove) { - chunkSet = new BlockVectorSet(); - BlockVectorSet tmpSet = new BlockVectorSet(); - for (RelightSkyEntry chunk : chunks) { - tmpSet.add(chunk.x, 0, chunk.z); - } - for (RelightSkyEntry chunk : chunks) { - int x = chunk.x; - int z = chunk.z; - if (tmpSet.contains(x + 1, 0, z) && tmpSet.contains(x - 1, 0, z) && tmpSet.contains(x, 0, z + 1) && tmpSet.contains(x, 0, z - 1)) { - chunkSet.add(x, 0, z); - } - } - } - -// byte[] cacheX = FaweCache.CACHE_X[0]; -// byte[] cacheZ = FaweCache.CACHE_Z[0]; - for (int y = FaweChunk.HEIGHT - 1; y > 0; y--) { - for (RelightSkyEntry chunk : chunks) { // Propogate skylight - int layer = y >> 4; - byte[] mask = chunk.mask; - if (chunk.fix[layer] != SkipReason.NONE) { - if ((y & 15) == 0 && layer != 0 && chunk.fix[layer - 1] == SkipReason.NONE) { - fill(mask, chunk.x, y, chunk.z, chunk.fix[layer]); - } - continue; - } - int bx = chunk.x << 4; - int bz = chunk.z << 4; - Object chunkObj = queue.ensureChunkLoaded(chunk.x, chunk.z); - Object sections = queue.getCachedSections(queue.getWorld(), chunk.x, chunk.z); - if (sections == null) continue; - Object section = queue.getCachedSection(sections, layer); - if (section == null) continue; - chunk.smooth = false; - - if (remove && (y & 15) == 15 && chunkSet.contains(chunk.x, 0, chunk.z)) { - queue.removeSectionLighting(section, y >> 4, true); - } - - for (int z = 0, j = 0; z < 16; z++) { - for (int x = 0; x < 16; x++, j++) { - byte value = mask[j]; - byte pair = (byte) queue.getOpacityBrightnessPair(section, x, y, z); - int opacity = MathMan.unpair16x(pair); - int brightness = MathMan.unpair16y(pair); - if (brightness > 1 && (brightness != 15 || opacity != 15)) { - addLightUpdate(bx + x, y, bz + z); - } - switch (value) { - case 0: - if (opacity > 1) { - queue.setSkyLight(section, x, y, z, 0); - continue; - } - break; - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - if (opacity >= value) { - mask[j] = 0; - queue.setSkyLight(section, x, y, z, 0); - continue; - } - if (opacity <= 1) { - mask[j] = --value; - } else { - mask[j] = value = (byte) Math.max(0, value - opacity); - } - break; - case 15: - if (opacity > 1) { - value -= opacity; - mask[j] = value; - } - queue.setSkyLight(section, x, y, z, value); - continue; - } - chunk.smooth = true; - queue.setSkyLight(section, x, y, z, value); - } - } - queue.saveChunk(chunkObj); - } - for (RelightSkyEntry chunk : chunks) { // Smooth forwards - if (chunk.smooth) { - smoothSkyLight(chunk, y, true); - } - } - for (int i = chunks.length - 1; i >= 0; i--) { // Smooth backwards - RelightSkyEntry chunk = chunks[i]; - if (chunk.smooth) { - smoothSkyLight(chunk, y, false); - } - } - } - } - - public void smoothSkyLight(RelightSkyEntry chunk, int y, boolean direction) { - byte[] mask = chunk.mask; - int bx = chunk.x << 4; - int bz = chunk.z << 4; - queue.ensureChunkLoaded(chunk.x, chunk.z); - Object sections = queue.getCachedSections(queue.getWorld(), chunk.x, chunk.z); - if (sections == null) return; - Object section = queue.getCachedSection(sections, y >> 4); - if (section == null) return; - if (direction) { - for (int j = 0; j < 256; j++) { - int x = j & 15; - int z = j >> 4; - if (mask[j] >= 14 || (mask[j] == 0 && queue.getOpacity(section, x, y, z) > 1)) { - continue; - } - byte value = mask[j]; - if ((value = (byte) Math.max(queue.getSkyLight(bx + x - 1, y, bz + z) - 1, value)) >= 14) ; - else if ((value = (byte) Math.max(queue.getSkyLight(bx + x, y, bz + z - 1) - 1, value)) >= 14) ; - if (value > mask[j]) queue.setSkyLight(section, x, y, z, mask[j] = value); - } - } else { - for (int j = 255; j >= 0; j--) { - int x = j & 15; - int z = j >> 4; - if (mask[j] >= 14 || (mask[j] == 0 && queue.getOpacity(section, x, y, z) > 1)) { - continue; - } - byte value = mask[j]; - if ((value = (byte) Math.max(queue.getSkyLight(bx + x + 1, y, bz + z) - 1, value)) >= 14) ; - else if ((value = (byte) Math.max(queue.getSkyLight(bx + x, y, bz + z + 1) - 1, value)) >= 14) ; - if (value > mask[j]) queue.setSkyLight(section, x, y, z, mask[j] = value); - } - } - } - - public boolean isUnlit(byte[] array) { - for (byte val : array) { - if (val != 0) { - return false; - } - } - return true; - } - - private class RelightSkyEntry implements Comparable { - public final int x; - public final int z; - public final byte[] mask; - public final byte[] fix; - public int bitmask; - public boolean smooth; - - public RelightSkyEntry(int x, int z, byte[] fix, int bitmask) { - this.x = x; - this.z = z; - byte[] array = new byte[256]; - Arrays.fill(array, (byte) 15); - this.mask = array; - this.bitmask = bitmask; - if (fix == null) { - this.fix = new byte[(maxY + 1) >> 4]; - Arrays.fill(this.fix, SkipReason.NONE); - } else { - this.fix = fix; - } - } - - @Override - public String toString() { - return x + "," + z; - } - - @Override - public int compareTo(Object o) { - RelightSkyEntry other = (RelightSkyEntry) o; - if (other.x < x) { - return 1; - } - if (other.x > x) { - return -1; - } - if (other.z < z) { - return 1; - } - if (other.z > z) { - return -1; - } - return 0; - } - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/example/NullFaweChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/example/NullFaweChunk.java deleted file mode 100644 index b3bba3396..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/example/NullFaweChunk.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.boydti.fawe.example; - -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.FaweQueue; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BlockTypes; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -public class NullFaweChunk extends FaweChunk { - public static final NullFaweChunk INSTANCE = new NullFaweChunk(null, 0, 0); - - /** - * A FaweSections object represents a chunk and the blocks that you wish to change in it. - * - * @param parent - * @param x - * @param z - */ - public NullFaweChunk(FaweQueue parent, int x, int z) { - super(parent, x, z); - } - - @Override - public int[][] getCombinedIdArrays() { - return new int[16][]; - } - - @Override - public int[] getIdArray(int layer) { - return null; - } - - @Override - public BiomeType[] getBiomeArray() { - return new BiomeType[256]; - } - - @Override - public int getBitMask() { - return 0; - } - - @Override - public int getBlockCombinedId(int x, int y, int z) { - return BlockTypes.AIR.getInternalId(); - } - - @Override - public Void getChunk() { - return null; - } - - @Override - public void setTile(int x, int y, int z, CompoundTag tile) { - - } - - @Override - public void setEntity(CompoundTag entity) { - - } - - @Override - public void removeEntity(UUID uuid) { - - } - - @Override - public void setBlock(int x, int y, int z, int combinedId) { - - } - - @Override - public Set getEntities() { - return new HashSet<>(); - } - - @Override - public Set getEntityRemoves() { - return new HashSet<>(); - } - - @Override - public Map getTiles() { - return new HashMap<>(); - } - - @Override - public CompoundTag getTile(int x, int y, int z) { - return null; - } - - @Override - public void setBiome(int x, int z, BiomeType biome) { - - } - - @Override - public FaweChunk copy(boolean shallow) { - return this; - } - - @Override - public FaweChunk call() { - return null; - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/example/NullQueueIntFaweChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/example/NullQueueIntFaweChunk.java deleted file mode 100644 index f1c31df3f..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/example/NullQueueIntFaweChunk.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.boydti.fawe.example; - -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.util.MainUtil; - -public class NullQueueIntFaweChunk extends IntFaweChunk { - - public NullQueueIntFaweChunk(int cx, int cz) { - super(null, cx, cz); - } - - public NullQueueIntFaweChunk(int x, int z, int[][] ids, short[] count, short[] air) { - super(null, x, z, ids, count, air); - } - - @Override - public Object getNewChunk() { - return null; - } - - @Override - public IntFaweChunk copy(boolean shallow) { - if (shallow) { - return new NullQueueIntFaweChunk(getX(), getZ(), setBlocks, count, air); - } else { - return new NullQueueIntFaweChunk(getX(), getZ(), (int[][]) MainUtil.copyNd(setBlocks), count.clone(), air.clone()); - } - } - - @Override - public FaweChunk call() { - return null; - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/example/NullRelighter.java b/worldedit-core/src/main/java/com/boydti/fawe/example/NullRelighter.java deleted file mode 100644 index 59ced0651..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/example/NullRelighter.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.boydti.fawe.example; - -public class NullRelighter implements Relighter { - - public static NullRelighter INSTANCE = new NullRelighter(); - - private NullRelighter() { - } - - @Override - public boolean addChunk(int cx, int cz, byte[] fix, int bitmask) { - return false; - } - - @Override - public void addLightUpdate(int x, int y, int z) { - - } - - @Override - public void fixLightingSafe(boolean sky) { - - } - - @Override - public void clear() { - - } - - @Override - public void removeLighting() { - - } - - @Override - public void fixBlockLighting() { - - } - - @Override - public void fixSkyLighting() { - - } - - @Override - public boolean isEmpty() { - return true; - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/example/Relighter.java b/worldedit-core/src/main/java/com/boydti/fawe/example/Relighter.java deleted file mode 100644 index 82f5ea0b1..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/example/Relighter.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.boydti.fawe.example; - -public interface Relighter { - boolean addChunk(int cx, int cz, byte[] skipReason, int bitmask); - - void addLightUpdate(int x, int y, int z); - - void fixLightingSafe(boolean sky); - - default void removeAndRelight(boolean sky) { - removeLighting(); - fixLightingSafe(sky); - } - - void clear(); - - void removeLighting(); - - void fixBlockLighting(); - - void fixSkyLighting(); - - boolean isEmpty(); - - public static class SkipReason { - public static final byte NONE = 0; - public static final byte AIR = 1; - public static final byte SOLID = 2; - } -} \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/boydti/fawe/example/SimpleIntFaweChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/example/SimpleIntFaweChunk.java deleted file mode 100644 index 6012e9782..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/example/SimpleIntFaweChunk.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.boydti.fawe.example; - -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.FaweQueue; -import com.boydti.fawe.util.MainUtil; - -public class SimpleIntFaweChunk extends IntFaweChunk { - - public SimpleIntFaweChunk(FaweQueue parent, int x, int z) { - super(parent, x, z); - } - - public SimpleIntFaweChunk(FaweQueue parent, int x, int z, int[][] ids, short[] count, short[] air) { - super(parent, x, z, ids, count, air); - } - - @Override - public Object getNewChunk() { - return this; - } - - @Override - public IntFaweChunk copy(boolean shallow) { - SimpleIntFaweChunk copy; - if (shallow) { - copy = new SimpleIntFaweChunk(getParent(), getX(), getZ(), setBlocks, count, air); - copy.biomes = biomes; - } else { - copy = new SimpleIntFaweChunk(getParent(), getX(), getZ(), (int[][]) MainUtil.copyNd(setBlocks), count.clone(), air.clone()); - copy.biomes = biomes != null ? biomes.clone() : null; - } - return copy; - } - - @Override - public FaweChunk call() { - getParent().setChunk(this); - return this; - } -} \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/boydti/fawe/example/WeakFaweQueueMap.java b/worldedit-core/src/main/java/com/boydti/fawe/example/WeakFaweQueueMap.java deleted file mode 100644 index 0f2b4f808..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/example/WeakFaweQueueMap.java +++ /dev/null @@ -1,242 +0,0 @@ -package com.boydti.fawe.example; - -import com.boydti.fawe.Fawe; -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.FaweQueue; -import com.boydti.fawe.object.RunnableVal; -import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.SetQueue; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import java.lang.ref.Reference; -import java.lang.ref.SoftReference; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.ExecutorCompletionService; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -public class WeakFaweQueueMap implements IFaweQueueMap { - - private final MappedFaweQueue parent; - - public WeakFaweQueueMap(MappedFaweQueue parent) { - this.parent = parent; - } - - public final Long2ObjectOpenHashMap> blocks = new Long2ObjectOpenHashMap>() { - @Override - public Reference put(Long key, Reference value) { - return put((long) key, value); - } - - @Override - public Reference put(long key, Reference value) { - if (parent.getProgressTask() != null) { - try { - parent.getProgressTask().run(FaweQueue.ProgressType.QUEUE, size()); - } catch (Throwable e) { - e.printStackTrace(); - } - } - synchronized (this) { - return super.put(key, value); - } - } - }; - - @Override - public Collection getFaweChunks() { - HashSet set = new HashSet<>(); - synchronized (blocks) { - Iterator>> iter = blocks.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry> entry = iter.next(); - FaweChunk value = entry.getValue().get(); - if (value != null) { - set.add(value); - } else { - Fawe.debug("Skipped modifying chunk due to low memory (1)"); - iter.remove(); - } - } - return set; - } - } - - @Override - public void forEachChunk(RunnableVal onEach) { - synchronized (blocks) { - Iterator>> iter = blocks.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry> entry = iter.next(); - FaweChunk value = entry.getValue().get(); - if (value != null) { - onEach.run(value); - } else { - Fawe.debug("Skipped modifying chunk due to low memory (2)"); - iter.remove(); - } - } - } - } - - @Override - public FaweChunk getFaweChunk(int cx, int cz) { - if (cx == lastX && cz == lastZ) { - return lastWrappedChunk; - } - long pair = MathMan.pairInt(cx, cz); - Reference chunkReference = this.blocks.get(pair); - FaweChunk chunk; - if (chunkReference == null || (chunk = chunkReference.get()) == null) { - chunk = this.getNewFaweChunk(cx, cz); - Reference previous = this.blocks.put(pair, new SoftReference(chunk)); - if (previous != null) { - FaweChunk tmp = previous.get(); - if (tmp != null) { - chunk = tmp; - this.blocks.put(pair, previous); - } - } - - } - return chunk; - } - - @Override - public FaweChunk getCachedFaweChunk(int cx, int cz) { - if (cx == lastX && cz == lastZ) { - return lastWrappedChunk; - } - long pair = MathMan.pairInt(cx, cz); - Reference reference = this.blocks.get(pair); - if (reference != null) { - return reference.get(); - } else { - return null; - } - } - - @Override - public void add(FaweChunk chunk) { - long pair = MathMan.pairInt(chunk.getX(), chunk.getZ()); - Reference previous = this.blocks.put(pair, new SoftReference<>(chunk)); - if (previous != null) { - FaweChunk previousChunk = previous.get(); - if (previousChunk != null) { - blocks.put(pair, previous); - } - } - } - - - @Override - public void clear() { - blocks.clear(); - } - - @Override - public int size() { - return blocks.size(); - } - - private FaweChunk getNewFaweChunk(int cx, int cz) { - return parent.getFaweChunk(cx, cz); - } - - private FaweChunk lastWrappedChunk; - private int lastX = Integer.MIN_VALUE; - private int lastZ = Integer.MIN_VALUE; - - @Override - public boolean next(int amount, long time) { - synchronized (blocks) { - try { - boolean skip = parent.getStage() == SetQueue.QueueStage.INACTIVE; - int added = 0; - Iterator>> iter = blocks.entrySet().iterator(); - if (amount == 1) { - long start = System.currentTimeMillis(); - do { - if (iter.hasNext()) { - Map.Entry> entry = iter.next(); - Reference chunkReference = entry.getValue(); - FaweChunk chunk = chunkReference.get(); - if (skip && chunk == lastWrappedChunk) { - continue; - } - iter.remove(); - if (chunk != null) { - parent.start(chunk); - chunk.call(); - parent.end(chunk); - } else { - Fawe.debug("Skipped modifying chunk due to low memory (3)"); - } - } else { - break; - } - } while (System.currentTimeMillis() - start < time); - return !blocks.isEmpty(); - } - ExecutorCompletionService service = SetQueue.IMP.getCompleterService(); - ForkJoinPool pool = SetQueue.IMP.getForkJoinPool(); - boolean result = true; - // amount = 8; - for (int i = 0; i < amount && (result = iter.hasNext()); ) { - Map.Entry> item = iter.next(); - Reference chunkReference = item.getValue(); - FaweChunk chunk = chunkReference.get(); - if (skip && chunk == lastWrappedChunk) { - continue; - } - iter.remove(); - if (chunk != null) { - parent.start(chunk); - service.submit(chunk); - added++; - i++; - } else { - Fawe.debug("Skipped modifying chunk due to low memory (4)"); - } - } - // if result, then submitted = amount - if (result) { - long start = System.currentTimeMillis(); - while (System.currentTimeMillis() - start < time && result) { - if (result = iter.hasNext()) { - Map.Entry> item = iter.next(); - Reference chunkReference = item.getValue(); - FaweChunk chunk = chunkReference.get(); - if (skip && chunk == lastWrappedChunk) { - continue; - } - iter.remove(); - if (chunk != null) { - parent.start(chunk); - service.submit(chunk); - Future future = service.poll(50, TimeUnit.MILLISECONDS); - if (future != null) { - FaweChunk fc = (FaweChunk) future.get(); - parent.end(fc); - } - } - } - } - } - pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS); - Future future; - while ((future = service.poll()) != null) { - FaweChunk fc = (FaweChunk) future.get(); - parent.end(fc); - } - } catch (Throwable e) { - e.printStackTrace(); - } - return !blocks.isEmpty(); - } - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/FaweChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/object/FaweChunk.java deleted file mode 100644 index 94471f67b..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/FaweChunk.java +++ /dev/null @@ -1,310 +0,0 @@ -package com.boydti.fawe.object; - -import com.boydti.fawe.object.visitor.FaweChunkVisitor; - -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BlockStateHolder; - -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.Callable; -import javax.annotation.Nullable; - -public abstract class FaweChunk implements Callable { - public static int HEIGHT = 256; - - private FaweQueue parent; - private int x, z; - - /** - * A FaweSections object represents a chunk and the blocks that you wish to change in it. - */ - public FaweChunk(FaweQueue parent, int x, int z) { - this.parent = parent; - this.x = x; - this.z = z; - } - - /** - * Change the chunk's location
- * - E.g. if you are cloning a chunk and want to set multiple - * - * @param parent - * @param x - * @param z - */ - public void setLoc(FaweQueue parent, int x, int z) { - this.parent = parent; - this.x = x; - this.z = z; - } - - /** - * Get the parent queue this chunk belongs to - * - * @return - */ - public FaweQueue getParent() { - return parent; - } - - public int getX() { - return x; - } - - public int getZ() { - return z; - } - - /** - * Get a unique hashcode for this chunk - * - * @return - */ - public long longHash() { - return (long) x << 32 | z & 0xFFFFFFFFL; - } - - /** - * Get a hashcode; unique below abs(x/z) < Short.MAX_VALUE - * - * @return - */ - @Override - public int hashCode() { - return x << 16 | z & 0xFFFF; - } - - /** - * Add the chunk to the queue - */ - public void addToQueue() { - parent.setChunk(this); - } - - /** - * The modified sections - * - * @return - */ - public abstract int getBitMask(); - - /** - * Get the combined block id at a location
- * combined = (id <<<< 4) + data - * - * @param x - * @param y - * @param z - * @return The combined id - */ - public abstract int getBlockCombinedId(int x, int y, int z); - - public > void setBlock(int x, int y, int z, B block) { - setBlock(x, y, z, block.getInternalId()); - if (block instanceof BaseBlock && ((BaseBlock)block).hasNbtData()) { - setTile(x & 15, y, z & 15, ((BaseBlock)block).getNbtData()); - } - } - - public BlockState getBlock(int x, int y, int z) { - int combined = getBlockCombinedId(x, y, z); - // TODO FIXME optimize get nbt - try { - CompoundTag tile = getTile(x & 15, y, z & 15); - if (tile != null) { - return BaseBlock.getFromInternalId(combined, tile).toImmutableState(); - } - } catch (Throwable e) { - e.printStackTrace(); - } - return BlockState.getFromInternalId(combined); - } - - public int[][] getCombinedIdArrays() { - int[][] ids = new int[HEIGHT >> 4][]; - for (int layer = 0; layer < HEIGHT >> 4; layer++) { - ids[layer] = getIdArray(layer); - } - return ids; - } - - /** - * Get the combined id array at a layer or null if it does not exist - * - * @param layer - * @return int[] or null - */ - public - @Nullable - int[] getIdArray(int layer) { - int[] ids = new int[4096]; - int by = layer << 4; - int index = 0; - for (int y = 0; y < 16; y++) { - int yy = by + y; - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++) { - ids[index++] = getBlockCombinedId(x, yy, z); - } - } - } - return ids; - } - - public byte[][] getBlockLightArray() { - return null; - } - - public byte[][] getSkyLightArray() { - return null; - } - - public abstract BiomeType[] getBiomeArray(); - - public BiomeType getBiomeType(int x, int z) { - return getBiomeArray()[(x & 15) + ((z & 15) << 4)]; - } - - public void forEachQueuedBlock(FaweChunkVisitor onEach) { - for (int y = 0; y < HEIGHT; y++) { - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++) { - int combined = getBlockCombinedId(x, y, z); - if (combined == 0) { - continue; - } - onEach.run(x, y, z, combined); - } - } - } - } - - /** - * Fill this chunk with a block - * - * @param combinedId - */ - public void fill(int combinedId) { - fillCuboid(0, 15, 0, HEIGHT - 1, 0, 15, combinedId); - } - - /** - * Fill a cuboid in this chunk with a block - * - * @param x1 - * @param x2 - * @param y1 - * @param y2 - * @param z1 - * @param z2 - * @param combinedId - */ - public void fillCuboid(int x1, int x2, int y1, int y2, int z1, int z2, int combinedId) { - for (int x = x1; x <= x2; x++) { - for (int y = y1; y <= y2; y++) { - for (int z = z1; z <= z2; z++) { - setBlock(x, y, z, combinedId); - } - } - } - } - - /** - * Get the underlying chunk object - * - * @return - */ - public abstract T getChunk(); - - /** - * Set a tile entity at a location
- * - May throw an error if an invalid block is at the location - * - * @param x - * @param y - * @param z - * @param tile - */ - public abstract void setTile(int x, int y, int z, CompoundTag tile); - - public abstract void setEntity(CompoundTag entity); - - public abstract void removeEntity(UUID uuid); - - public abstract void setBlock(int x, int y, int z, int combinedId); - - public abstract Set getEntities(); - - /** - * Get the UUID of entities being removed - * - * @return - */ - public abstract Set getEntityRemoves(); - - /** - * Get the map of location to tile entity
- * - The byte pair represents the location in the chunk
- * - * @return - * @see com.boydti.fawe.util.MathMan#unpair16x (get0) => x - * @see com.boydti.fawe.util.MathMan#unpair16y (get0) => z - * get1 => y - */ - public abstract Map getTiles(); - - /** - * Get the tile at a location - * - * @param x - * @param y - * @param z - * @return - */ - public abstract CompoundTag getTile(int x, int y, int z); - - public abstract void setBiome(final int x, final int z, final BiomeType biome); - - public void setBiome(final BiomeType biome) { - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++) { - setBiome(x, z, biome); - } - } - } - - /** - * Spend time now so that the chunk can be more efficiently dispatched later
- * - Modifications after this call will be ignored - */ - public void optimize() { - } - - @Override - public boolean equals(final Object obj) { - if ((obj == null) || obj.hashCode() != hashCode() || !(obj instanceof FaweChunk)) { - return false; - } - return longHash() != ((FaweChunk) obj).longHash(); - } - - public abstract FaweChunk copy(boolean shallow); - - public void start() { - } - - ; - - public void end() { - } - - ; - - @Override - public abstract FaweChunk call(); -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/FaweQueue.java b/worldedit-core/src/main/java/com/boydti/fawe/object/FaweQueue.java deleted file mode 100644 index 8b8c328ca..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/FaweQueue.java +++ /dev/null @@ -1,526 +0,0 @@ -package com.boydti.fawe.object; - -import com.boydti.fawe.Fawe; -import com.boydti.fawe.config.BBC; -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.example.NullRelighter; -import com.boydti.fawe.example.Relighter; -import com.boydti.fawe.object.exception.FaweException; -import com.boydti.fawe.util.MainUtil; -import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.MemUtil; -import com.boydti.fawe.util.SetQueue; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.math.BlockVector2; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.MutableBlockVector3; -import com.sk89q.worldedit.regions.CuboidRegion; -import com.sk89q.worldedit.world.World; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.block.BlockTypes; - -import java.io.File; -import java.util.Collection; -import java.util.Collections; -import java.util.UUID; -import javax.annotation.Nullable; - -/** - * A queue based Extent capable of queing chunk and region changes - */ -public interface FaweQueue extends HasFaweQueue, Extent { - - enum ProgressType { - QUEUE, - DISPATCH, - DONE, - } - - enum RelightMode { - NONE, - OPTIMAL, - ALL, - } - - enum Capability { - // If history can be recorded in an async task by the dispatcher - CHANGE_TASKS, - // If custom chunk packets can be sent - CHUNK_PACKETS - // - } - - default Relighter getRelighter() { - return NullRelighter.INSTANCE; - } - - @Override - default BlockVector3 getMinimumPoint() { - return BlockVector3.at(-30000000, 0, -30000000); - } - - @Override - default BlockVector3 getMaximumPoint() { - return BlockVector3.at(30000000, getMaxY(), 30000000); - } - - @Override - default BlockState getBlock(int x, int y, int z) { - int combinedId4Data = getCachedCombinedId4Data(x, y, z, BlockTypes.AIR.getInternalId()); - try { - return BlockState.getFromInternalId(combinedId4Data); - } catch (Throwable e) { - e.printStackTrace(); - return BlockTypes.AIR.getDefaultState(); - } - } - - @Override - default > boolean setBlock(int x, int y, int z, B block) throws WorldEditException { - return setBlock(x, y, z, block.getInternalId(), block instanceof BaseBlock ? block.getNbtData() : null); - } - - @Override - default BaseBlock getFullBlock(BlockVector3 position) { - int combinedId4Data = getCachedCombinedId4Data(position.getBlockX(), position.getBlockY(), position.getBlockZ(), BlockTypes.AIR.getInternalId()); - try { - BaseBlock block = BaseBlock.getFromInternalId(combinedId4Data, null); - if (block.getMaterial().hasContainer()) { - CompoundTag tile = getTileEntity(position.getBlockX(), position.getBlockY(), position.getBlockZ()); - if (tile != null) { - return BaseBlock.getFromInternalId(combinedId4Data, tile); - } - } - return block; - } catch (Throwable e) { - e.printStackTrace(); - return BlockTypes.AIR.getDefaultState().toBaseBlock(); - } - } - - @Override - default BiomeType getBiome(BlockVector2 position) { - return null; - } - - @Override - default > boolean setBlock(BlockVector3 position, B block) throws WorldEditException { - return setBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ(), block); - } - - boolean setBlock(final int x, final int y, final int z, int combinedId); - - default boolean setBlock(final int x, final int y, final int z, int combinedId, CompoundTag nbtData) { - if (setBlock(x, y, z, combinedId)) { - if (nbtData != null) setTile(x, y, z, nbtData); - return true; - } - return false; - } - - @Override - default boolean setBiome(BlockVector2 position, BiomeType biome) { - return setBiome(position.getBlockX(), position.getBlockZ(), biome); - } - - @Override - default FaweQueue getQueue() { - return this; - } - - - - default void addEditSession(EditSession session) { - if (session == null) { - return; - } - Collection sessions = getEditSessions(); - sessions.add(session); - } - - /** - * Add a progress task
- * - Progress type - * - Amount of type - * - * @param progressTask - */ - default void setProgressTracker(RunnableVal2 progressTask) { - this.setProgressTask(progressTask); - } - - default Collection getEditSessions() { - return Collections.emptySet(); - } - - default boolean supports(Capability capability) { - return false; - } - - default void optimize() {} - - default int setBlocks(CuboidRegion cuboid, int combinedId) { - RegionWrapper current = new RegionWrapper(cuboid.getMinimumPoint(), cuboid.getMaximumPoint()); - final int minY = cuboid.getMinimumY(); - final int maxY = cuboid.getMaximumY(); - - final FaweChunk fc = getFaweChunk(0, 0); - fc.fillCuboid(0, 15, minY, maxY, 0, 15, combinedId); - fc.optimize(); - - int bcx = (current.minX) >> 4; - int bcz = (current.minZ) >> 4; - - int tcx = (current.maxX) >> 4; - int tcz = (current.maxZ) >> 4; - // [chunkx, chunkz, pos1x, pos1z, pos2x, pos2z, isedge] - MainUtil.chunkTaskSync(current, new RunnableVal() { - @Override - public void run(int[] value) { - FaweChunk newChunk; - if (value[6] == 0) { - newChunk = fc.copy(true); - newChunk.setLoc(FaweQueue.this, value[0], value[1]); - } else { - int bx = value[2] & 15; - int tx = value[4] & 15; - int bz = value[3] & 15; - int tz = value[5] & 15; - if (bx == 0 && tx == 15 && bz == 0 && tz == 15) { - newChunk = fc.copy(true); - newChunk.setLoc(FaweQueue.this, value[0], value[1]); - } else { - newChunk = FaweQueue.this.getFaweChunk(value[0], value[1]); - newChunk.fillCuboid(value[2] & 15, value[4] & 15, minY, maxY, value[3] & 15, value[5] & 15, combinedId); - } - } - newChunk.addToQueue(); - } - }); - return cuboid.getArea(); - } - - void setTile(int x, int y, int z, CompoundTag tag); - - void setEntity(int x, int y, int z, CompoundTag tag); - - void removeEntity(int x, int y, int z, UUID uuid); - - boolean setBiome(final int x, final int z, final BiomeType biome); - - FaweChunk getFaweChunk(int x, int z); - - Collection getFaweChunks(); - - default boolean setMCA(int mcaX, int mcaZ, RegionWrapper region, Runnable whileLocked, boolean save, boolean load) { - if (whileLocked != null) whileLocked.run(); - return true; - } - - void setChunk(final FaweChunk chunk); - - File getSaveFolder(); - - default int getMaxY() { - World weWorld = getWEWorld(); - return weWorld == null ? 255 : weWorld.getMaxY(); - } - - default Settings getSettings() { - return Settings.IMP; - } - - default void setSettings(Settings settings) { - - } - - void setWorld(String world); - - World getWEWorld(); - - String getWorldName(); - - long getModified(); - - void setModified(long modified); - - RunnableVal2 getProgressTask(); - - void setProgressTask(RunnableVal2 progressTask); - - void setChangeTask(RunnableVal2 changeTask); - - RunnableVal2 getChangeTask(); - - SetQueue.QueueStage getStage(); - - void setStage(SetQueue.QueueStage stage); - - void addNotifyTask(Runnable runnable); - - void runTasks(); - - void addTask(Runnable whenFree); - - default void forEachBlockInChunk(int cx, int cz, RunnableVal2 onEach) { - int bx = cx << 4; - int bz = cz << 4; - MutableBlockVector3 mutable = new MutableBlockVector3(0, 0, 0); - for (int x = 0; x < 16; x++) { - int xx = x + bx; - mutable.mutX(xx); - for (int z = 0; z < 16; z++) { - int zz = z + bz; - mutable.mutZ(zz); - for (int y = 0; y <= getMaxY(); y++) { - int combined = getCombinedId4Data(xx, y, zz); - BaseBlock block = BlockState.getFromInternalId(combined).toBaseBlock(); - BlockType type = block.getBlockType(); - if (type.getMaterial().isAir()) { - continue; - } - mutable.mutY(y); - CompoundTag tile = getTileEntity(x, y, z); - if (tile != null) { - onEach.run(mutable, block.toBaseBlock(tile)); - } else { - onEach.run(mutable, block); - } - } - } - } - } - - default void forEachTileInChunk(int cx, int cz, RunnableVal2 onEach) { - int bx = cx << 4; - int bz = cz << 4; - MutableBlockVector3 mutable = new MutableBlockVector3(0, 0, 0); - for (int x = 0; x < 16; x++) { - int xx = x + bx; - for (int z = 0; z < 16; z++) { - int zz = z + bz; - for (int y = 0; y < getMaxY(); y++) { - int combined = getCombinedId4Data(xx, y, zz); - if (combined == 0) { - continue; - } - BlockType type = BlockTypes.getFromStateId(combined); - if (type.getMaterial().hasContainer()) { - CompoundTag tile = getTileEntity(x, y, z); - if (tile != null) { - mutable.mutX(xx); - mutable.mutZ(zz); - mutable.mutY(y); - BaseBlock block = BaseBlock.getFromInternalId(combined, tile); - onEach.run(mutable, block); - } - } - } - } - } - } - - @Deprecated - default boolean regenerateChunk(int x, int z) { - return regenerateChunk(x, z, null, null); - } - - boolean regenerateChunk(int x, int z, @Nullable BiomeType biome, @Nullable Long seed); - - default void startSet(boolean parallel) { - } - - default void endSet(boolean parallel) { - } - - default int cancel() { - clear(); - int count = 0; - for (EditSession session : getEditSessions()) { - if (session.cancel()) { - count++; - } - } - return count; - } - - void sendBlockUpdate(FaweChunk chunk, FawePlayer... players); - - default void sendChunkUpdate(FaweChunk chunk, FawePlayer... players) { - sendBlockUpdate(chunk, players); - } - - @Deprecated - default boolean next() { - int amount = Settings.IMP.QUEUE.PARALLEL_THREADS; - long time = 20; // 30ms - return next(amount, time); - } - - /** - * Gets the FaweChunk and sets the requested blocks - * - * @return - */ - boolean next(int amount, long time); - - default void saveMemory() { - MainUtil.sendAdmin(BBC.OOM.s()); - // Set memory limited - MemUtil.memoryLimitedTask(); - // Clear block placement - clear(); - Fawe.get().getWorldEdit().getSessionManager().clear(); - // GC - System.gc(); - System.gc(); - // Unload chunks - } - - void sendChunk(FaweChunk chunk); - - void sendChunk(int x, int z, int bitMask); - - /** - * This method is called when the server is < 1% available memory - */ - void clear(); - - default boolean hasBlock(int x, int y, int z) throws FaweException.FaweChunkLoadException { - return getCombinedId4Data(x, y, z) != 0; - } - - BiomeType getBiomeType(int x, int z) throws FaweException.FaweChunkLoadException; - - int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException; - - int getCachedCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException; - - default int getAdjacentLight(int x, int y, int z) { - int light = 0; - if ((light = Math.max(light, getSkyLight(x - 1, y, z))) == 15) { - return light; - } - if ((light = Math.max(light, getSkyLight(x + 1, y, z))) == 15) { - return light; - } - if ((light = Math.max(light, getSkyLight(x, y, z - 1))) == 15) { - return light; - } - return Math.max(light, getSkyLight(x, y, z + 1)); - } - - boolean hasSky(); - - int getSkyLight(int x, int y, int z); - - default int getLight(int x, int y, int z) { - if (!hasSky()) { - return getEmmittedLight(x, y, z); - } - return Math.max(getSkyLight(x, y, z), getEmmittedLight(x, y, z)); - } - - int getEmmittedLight(int x, int y, int z); - - CompoundTag getTileEntity(int x, int y, int z) throws FaweException.FaweChunkLoadException; - - default int getCombinedId4Data(int x, int y, int z, int def) { - try { - return getCombinedId4Data(x, y, z); - } catch (FaweException ignore) { - return def; - } - } - - default int getCachedCombinedId4Data(int x, int y, int z, int def) { - try { - return getCachedCombinedId4Data(x, y, z); - } catch (FaweException ignore) { - return def; - } - } - - default int getCombinedId4DataDebug(int x, int y, int z, int def, EditSession session) { - try { - return getCombinedId4Data(x, y, z); - } catch (FaweException ignore) { - session.debug(BBC.WORLDEDIT_FAILED_LOAD_CHUNK, x >> 4, z >> 4); - return def; - } catch (Throwable e) { - e.printStackTrace(); - return BlockTypes.AIR.getInternalId(); - } - } - - default int getBrightness(int x, int y, int z) { - int combined = getCombinedId4Data(x, y, z); - if (combined == 0) { - return 0; - } - return BlockTypes.getFromStateId(combined).getMaterial().getLightValue(); - } - - default int getOpacityBrightnessPair(int x, int y, int z) { - return MathMan.pair16(Math.min(15, getOpacity(x, y, z)), getBrightness(x, y, z)); - } - - default int getOpacity(int x, int y, int z) { - int combined = getCombinedId4Data(x, y, z); - if (combined == 0) { - return 0; - } - return BlockTypes.getFromStateId(combined).getMaterial().getLightOpacity(); - } - - int size(); - - default boolean isEmpty() { - return size() == 0; - } - - /** - * Lock the thread until the queue is empty - */ - default void flush() { - flush(10000); - } - - /** - * Lock the thread until the queue is empty - */ - default void flush(int time) { - if (size() > 0) { - if (Fawe.isMainThread()) { - SetQueue.IMP.flush(this); - } else { - if (enqueue()) { - while (!isEmpty() && getStage() == SetQueue.QueueStage.ACTIVE) { - synchronized (this) { - try { - this.wait(time); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } - } - } - } - - default boolean enqueue() { - return SetQueue.IMP.enqueue(this); - } - - default void dequeue() { - SetQueue.IMP.dequeue(this); - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/HasFaweQueue.java b/worldedit-core/src/main/java/com/boydti/fawe/object/HasFaweQueue.java deleted file mode 100644 index 8ad5b840f..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/HasFaweQueue.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.boydti.fawe.object; - -public interface HasFaweQueue { - FaweQueue getQueue(); -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/NullChangeSet.java b/worldedit-core/src/main/java/com/boydti/fawe/object/NullChangeSet.java index c7d5d931d..baecc2148 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/NullChangeSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/NullChangeSet.java @@ -53,11 +53,6 @@ public class NullChangeSet extends FaweChangeSet { } - @Override - public void addChangeTask(FaweQueue queue) { - - } - @Override public Iterator getIterator(BlockBag blockBag, int mode, boolean redo) { return getIterator(redo); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/schematic/Schematic.java b/worldedit-core/src/main/java/com/boydti/fawe/object/schematic/Schematic.java index 0b2ef0e2d..f7aebefd3 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/schematic/Schematic.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/schematic/Schematic.java @@ -122,7 +122,6 @@ public class Schematic { public EditSession paste(World world, BlockVector3 to, boolean allowUndo, boolean pasteAir, boolean copyEntities, @Nullable Transform transform) { checkNotNull(world); checkNotNull(to); - Region region = clipboard.getRegion(); EditSession editSession; if (world instanceof EditSession) { editSession = (EditSession) world; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java b/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java index 9d5d45036..45483aff0 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java @@ -45,7 +45,7 @@ import static com.google.common.base.Preconditions.checkNotNull; public class EditSessionBuilder { private World world; private String worldName; - private FaweQueue queue; + private Extent extent; private FawePlayer player; private FaweLimit limit; private FaweChangeSet changeSet; @@ -76,12 +76,14 @@ public class EditSessionBuilder { public EditSessionBuilder(@Nonnull World world) { checkNotNull(world); this.world = world; + this.extent = world; this.worldName = Fawe.imp().getWorldName(world); } public EditSessionBuilder(World world, String worldName) { if (world == null && worldName == null) throw new NullPointerException("Both world and worldname cannot be null"); this.world = world; + this.extent = world; this.worldName = worldName; } @@ -198,8 +200,8 @@ public class EditSessionBuilder { return this; } - public EditSessionBuilder queue(@Nullable FaweQueue queue) { - this.queue = queue; + public EditSessionBuilder extent(@Nullable Extent extent) { + this.extent = extent; return this; } @@ -260,7 +262,6 @@ public class EditSessionBuilder { } private FaweChangeSet changeTask; - private AbstractDelegateExtent extent; private int maxY; private HistoryExtent history; private AbstractDelegateExtent bypassHistory; @@ -270,18 +271,6 @@ public class EditSessionBuilder { if (extent != null) return this; wrapped = false; - // - if (worldName == null) { - if (world == null) { - if (queue == null) { - worldName = ""; - } else { - worldName = queue.getWorldName(); - } - } else { - worldName = Fawe.imp().getWorldName(world); - } - } if (world == null && !this.worldName.isEmpty()) { world = FaweAPI.getWorld(this.worldName); } @@ -326,106 +315,107 @@ public class EditSessionBuilder { this.blockBag = limit.INVENTORY_MODE != 0 ? blockBag : null; // this.limit = limit.copy(); - if (queue == null) { - boolean placeChunks = this.fastmode || this.limit.FAST_PLACEMENT; - World unwrapped = WorldWrapper.unwrap(world); - if (unwrapped instanceof FaweQueue) { - queue = (FaweQueue) unwrapped; - } else if (unwrapped instanceof MCAWorld) { - queue = ((MCAWorld) unwrapped).getQueue(); - } else if (player != null && world.equals(player.getWorld())) { - queue = player.getFaweQueue(placeChunks, autoQueue); - } else { - queue = SetQueue.IMP.getNewQueue(world, placeChunks, autoQueue); - } - } - if (combineStages == null) { - combineStages = - // If it's enabled in the settings - Settings.IMP.HISTORY.COMBINE_STAGES - // If fast placement is disabled, it's slower to perform a copy on each chunk - && this.limit.FAST_PLACEMENT - // If the specific queue doesn't support it - && queue.supports(FaweQueue.Capability.CHANGE_TASKS) - // If the edit uses items from the inventory we can't use a delayed task - && this.blockBag == null; - } - if (!Settings.IMP.QUEUE.PROGRESS.DISPLAY.equalsIgnoreCase("false") && player != null) { - switch (Settings.IMP.QUEUE.PROGRESS.DISPLAY.toLowerCase()) { - case "chat": - this.queue.setProgressTask(new ChatProgressTracker(player)); - break; - case "title": - case "true": - default: - this.queue.setProgressTask(new DefaultProgressTracker(player)); - } - } - this.bypassAll = wrapExtent(new FastWorldEditExtent(world, queue), eventBus, event, EditSession.Stage.BEFORE_CHANGE); - this.bypassHistory = (this.extent = wrapExtent(bypassAll, eventBus, event, EditSession.Stage.BEFORE_REORDER)); - if (!this.fastmode || changeSet != null) { - if (changeSet == null) { - if (Settings.IMP.HISTORY.USE_DISK) { - UUID uuid = player == null ? EditSession.CONSOLE : player.getUUID(); - if (Settings.IMP.HISTORY.USE_DATABASE) { - changeSet = new RollbackOptimizedHistory(world, uuid); - } else { - changeSet = new DiskStorageHistory(world, uuid); - } - } else if (combineStages && Settings.IMP.HISTORY.COMPRESSION_LEVEL == 0 && !(queue instanceof MCAQueue)) { - changeSet = new CPUOptimizedChangeSet(world); - } else { - changeSet = new MemoryOptimizedHistory(world); - } - } - if (this.limit.SPEED_REDUCTION > 0) { - this.bypassHistory = new SlowExtent(this.bypassHistory, this.limit.SPEED_REDUCTION); - } - if (changeSet instanceof NullChangeSet && Fawe.imp().getBlocksHubApi() != null && player != null) { - changeSet = LoggingChangeSet.wrap(player, changeSet); - } - if (!(changeSet instanceof NullChangeSet)) { - if (!(changeSet instanceof LoggingChangeSet) && player != null && Fawe.imp().getBlocksHubApi() != null) { - changeSet = LoggingChangeSet.wrap(player, changeSet); - } - if (this.blockBag != null) { - changeSet = new BlockBagChangeSet(changeSet, blockBag, limit.INVENTORY_MODE == 1); - } - if (combineStages) { - changeTask = changeSet; - changeSet.addChangeTask(queue); - } else { - this.extent = (history = new HistoryExtent(bypassHistory, changeSet, queue)); -// if (this.blockBag != null) { -// this.extent = new BlockBagExtent(this.extent, blockBag, limit.INVENTORY_MODE == 1); +// if (queue == null) { +// boolean placeChunks = this.fastmode || this.limit.FAST_PLACEMENT; +// World unwrapped = WorldWrapper.unwrap(world); +// if (unwrapped instanceof FaweQueue) { +// queue = (FaweQueue) unwrapped; +// } else if (unwrapped instanceof MCAWorld) { +// queue = ((MCAWorld) unwrapped).getQueue(); +// } else if (player != null && world.equals(player.getWorld())) { +// queue = player.getFaweQueue(placeChunks, autoQueue); +// } else { +// queue = SetQueue.IMP.getNewQueue(world, placeChunks, autoQueue); +// } +// } +// if (combineStages == null) { +// combineStages = +// // If it's enabled in the settings +// Settings.IMP.HISTORY.COMBINE_STAGES +// // If fast placement is disabled, it's slower to perform a copy on each chunk +// && this.limit.FAST_PLACEMENT +// // If the specific queue doesn't support it +// && queue.supports(FaweQueue.Capability.CHANGE_TASKS) +// // If the edit uses items from the inventory we can't use a delayed task +// && this.blockBag == null; +// } +// if (!Settings.IMP.QUEUE.PROGRESS.DISPLAY.equalsIgnoreCase("false") && player != null) { +// switch (Settings.IMP.QUEUE.PROGRESS.DISPLAY.toLowerCase()) { +// case "chat": +// this.queue.setProgressTask(new ChatProgressTracker(player)); +// break; +// case "title": +// case "true": +// default: +// this.queue.setProgressTask(new DefaultProgressTracker(player)); +// } +// } +// this.bypassAll = wrapExtent(new FastWorldEditExtent(world, queue), eventBus, event, EditSession.Stage.BEFORE_CHANGE); +// this.bypassHistory = (this.extent = wrapExtent(bypassAll, eventBus, event, EditSession.Stage.BEFORE_REORDER)); +// if (!this.fastmode || changeSet != null) { +// if (changeSet == null) { +// if (Settings.IMP.HISTORY.USE_DISK) { +// UUID uuid = player == null ? EditSession.CONSOLE : player.getUUID(); +// if (Settings.IMP.HISTORY.USE_DATABASE) { +// changeSet = new RollbackOptimizedHistory(world, uuid); +// } else { +// changeSet = new DiskStorageHistory(world, uuid); // } - } - } - } - if (allowedRegions == null) { - if (player != null && !player.hasPermission("fawe.bypass") && !player.hasPermission("fawe.bypass.regions") && !(queue instanceof VirtualWorld)) { - allowedRegions = player.getCurrentRegions(); - } - } - this.maxY = world == null ? 255 : world.getMaxY(); - if (allowedRegions != null) { - if (allowedRegions.length == 0) { - this.extent = new NullExtent(this.extent, FaweException.NO_REGION); - } else { - this.extent = new ProcessedWEExtent(this.extent, this.limit); - if (allowedRegions.length == 1) { - this.extent = new SingleRegionExtent(this.extent, this.limit, allowedRegions[0]); - } else { - this.extent = new MultiRegionExtent(this.extent, this.limit, allowedRegions); - } - } - } else { - this.extent = new HeightBoundExtent(this.extent, this.limit, 0, maxY); - } - if (this.limit.STRIP_NBT != null && !this.limit.STRIP_NBT.isEmpty()) { - this.extent = new StripNBTExtent(this.extent, this.limit.STRIP_NBT); - } - this.extent = wrapExtent(this.extent, eventBus, event, EditSession.Stage.BEFORE_HISTORY); +// } else if (combineStages && Settings.IMP.HISTORY.COMPRESSION_LEVEL == 0 && !(queue instanceof MCAQueue)) { +// changeSet = new CPUOptimizedChangeSet(world); +// } else { +// changeSet = new MemoryOptimizedHistory(world); +// } +// } +// if (this.limit.SPEED_REDUCTION > 0) { +// this.bypassHistory = new SlowExtent(this.bypassHistory, this.limit.SPEED_REDUCTION); +// } +// if (changeSet instanceof NullChangeSet && Fawe.imp().getBlocksHubApi() != null && player != null) { +// changeSet = LoggingChangeSet.wrap(player, changeSet); +// } +// if (!(changeSet instanceof NullChangeSet)) { +// if (!(changeSet instanceof LoggingChangeSet) && player != null && Fawe.imp().getBlocksHubApi() != null) { +// changeSet = LoggingChangeSet.wrap(player, changeSet); +// } +// if (this.blockBag != null) { +// changeSet = new BlockBagChangeSet(changeSet, blockBag, limit.INVENTORY_MODE == 1); +// } +// if (combineStages) { +// changeTask = changeSet; +// changeSet.addChangeTask(queue); +// } else { +// this.extent = (history = new HistoryExtent(bypassHistory, changeSet, queue)); +//// if (this.blockBag != null) { +//// this.extent = new BlockBagExtent(this.extent, blockBag, limit.INVENTORY_MODE == 1); +//// } +// } +// } +// } +// if (allowedRegions == null) { +// if (player != null && !player.hasPermission("fawe.bypass") && !player.hasPermission("fawe.bypass.regions") && !(queue instanceof VirtualWorld)) { +// allowedRegions = player.getCurrentRegions(); +// } +// } +// this.maxY = world == null ? 255 : world.getMaxY(); +// if (allowedRegions != null) { +// if (allowedRegions.length == 0) { +// this.extent = new NullExtent(this.extent, FaweException.NO_REGION); +// } else { +// this.extent = new ProcessedWEExtent(this.extent, this.limit); +// if (allowedRegions.length == 1) { +// this.extent = new SingleRegionExtent(this.extent, this.limit, allowedRegions[0]); +// } else { +// this.extent = new MultiRegionExtent(this.extent, this.limit, allowedRegions); +// } +// } +// } else { +// this.extent = new HeightBoundExtent(this.extent, this.limit, 0, maxY); +// } +// if (this.limit.STRIP_NBT != null && !this.limit.STRIP_NBT.isEmpty()) { +// this.extent = new StripNBTExtent(this.extent, this.limit.STRIP_NBT); +// } +// this.extent = wrapExtent(this.extent, eventBus, event, EditSession.Stage.BEFORE_HISTORY); +// return this; return this; } @@ -445,10 +435,6 @@ public class EditSessionBuilder { return worldName; } - public FaweQueue getQueue() { - return queue; - } - public boolean isWrapped() { return wrapped; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index ff7b44b35..ce92e7e65 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -20,48 +20,33 @@ package com.sk89q.worldedit; import com.boydti.fawe.Fawe; -import com.boydti.fawe.FaweAPI; import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.Settings; -import com.boydti.fawe.example.MappedFaweQueue; -import com.boydti.fawe.jnbt.anvil.MCAQueue; -import com.boydti.fawe.jnbt.anvil.MCAWorld; -import com.boydti.fawe.logging.LoggingChangeSet; -import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory; import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.HasFaweQueue; import com.boydti.fawe.object.HistoryExtent; -import com.boydti.fawe.object.NullChangeSet; import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.RunnableVal; -import com.boydti.fawe.object.brush.visualization.VirtualWorld; import com.boydti.fawe.object.changeset.BlockBagChangeSet; -import com.boydti.fawe.object.changeset.CPUOptimizedChangeSet; -import com.boydti.fawe.object.changeset.DiskStorageHistory; import com.boydti.fawe.object.changeset.FaweChangeSet; -import com.boydti.fawe.object.changeset.MemoryOptimizedHistory; import com.boydti.fawe.object.collection.LocalBlockVectorSet; import com.boydti.fawe.object.exception.FaweException; -import com.boydti.fawe.object.extent.*; +import com.boydti.fawe.object.extent.FaweRegionExtent; +import com.boydti.fawe.object.extent.NullExtent; +import com.boydti.fawe.object.extent.ProcessedWEExtent; +import com.boydti.fawe.object.extent.ResettableExtent; +import com.boydti.fawe.object.extent.SourceMaskExtent; import com.boydti.fawe.object.function.SurfaceRegionFunction; import com.boydti.fawe.object.mask.ResettableMask; import com.boydti.fawe.object.pattern.ExistingPattern; -import com.boydti.fawe.object.progress.ChatProgressTracker; -import com.boydti.fawe.object.progress.DefaultProgressTracker; import com.boydti.fawe.util.EditSessionBuilder; import com.boydti.fawe.util.ExtentTraverser; import com.boydti.fawe.util.MaskTraverser; import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.MemUtil; -import com.boydti.fawe.util.Perm; import com.boydti.fawe.util.SetQueue; import com.boydti.fawe.util.TaskManager; -import com.boydti.fawe.wrappers.WorldWrapper; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.base.Supplier; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.blocks.BaseItemStack; @@ -77,17 +62,25 @@ import com.sk89q.worldedit.extent.inventory.BlockBagExtent; import com.sk89q.worldedit.extent.world.SurvivalModeExtent; import com.sk89q.worldedit.function.GroundFunction; import com.sk89q.worldedit.function.RegionFunction; -import com.sk89q.worldedit.function.RegionMaskingFilter; import com.sk89q.worldedit.function.block.BlockReplace; import com.sk89q.worldedit.function.block.Naturalizer; import com.sk89q.worldedit.function.generator.ForestGenerator; import com.sk89q.worldedit.function.generator.GardenPatchGenerator; -import com.sk89q.worldedit.function.mask.*; +import com.sk89q.worldedit.function.mask.BlockTypeMask; +import com.sk89q.worldedit.function.mask.BoundedHeightMask; +import com.sk89q.worldedit.function.mask.ExistingBlockMask; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.MaskIntersection; +import com.sk89q.worldedit.function.mask.MaskUnion; +import com.sk89q.worldedit.function.mask.Masks; +import com.sk89q.worldedit.function.mask.NoiseFilter2D; +import com.sk89q.worldedit.function.mask.RegionMask; +import com.sk89q.worldedit.function.mask.SingleBlockTypeMask; +import com.sk89q.worldedit.function.mask.SolidBlockMask; import com.sk89q.worldedit.function.operation.ChangeSetExecutor; import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.Operations; -import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.WaterloggedRemover; import com.sk89q.worldedit.function.util.RegionOffset; @@ -108,7 +101,6 @@ import com.sk89q.worldedit.internal.expression.runtime.ExpressionTimeoutExceptio import com.sk89q.worldedit.internal.expression.runtime.RValue; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.MathUtils; import com.sk89q.worldedit.math.MutableBlockVector2; import com.sk89q.worldedit.math.MutableBlockVector3; import com.sk89q.worldedit.math.Vector2; @@ -123,16 +115,12 @@ import com.sk89q.worldedit.regions.EllipsoidRegion; import com.sk89q.worldedit.regions.FlatRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Regions; -import static com.sk89q.worldedit.regions.Regions.asFlatRegion; -import static com.sk89q.worldedit.regions.Regions.maximumBlockY; -import static com.sk89q.worldedit.regions.Regions.minimumBlockY; import com.sk89q.worldedit.regions.shape.ArbitraryBiomeShape; import com.sk89q.worldedit.regions.shape.ArbitraryShape; import com.sk89q.worldedit.regions.shape.RegionShape; import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment; import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.util.Direction; -import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.util.eventbus.EventBus; import com.sk89q.worldedit.world.SimpleWorld; @@ -151,7 +139,6 @@ import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -163,6 +150,12 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.regions.Regions.asFlatRegion; +import static com.sk89q.worldedit.regions.Regions.maximumBlockY; +import static com.sk89q.worldedit.regions.Regions.minimumBlockY; + /** * An {@link Extent} that handles history, {@link BlockBag}s, change limits, * block re-ordering, and much more. Most operations in WorldEdit use this class. @@ -211,7 +204,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, } private final World world; private final String worldName; - private final FaweQueue queue; private boolean wrapped; private boolean fastMode; private final HistoryExtent history; @@ -232,19 +224,18 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, public static final UUID CONSOLE = UUID.fromString("1-1-3-3-7"); @Deprecated - public EditSession(@Nonnull World world, @Nullable FaweQueue queue, @Nullable FawePlayer player, @Nullable FaweLimit limit, @Nullable FaweChangeSet changeSet, @Nullable RegionWrapper[] allowedRegions, @Nullable Boolean autoQueue, @Nullable Boolean fastmode, @Nullable Boolean checkMemory, @Nullable Boolean combineStages, @Nullable BlockBag blockBag, @Nullable EventBus bus, @Nullable EditSessionEvent event) { - this(null, world, queue, player, limit, changeSet, allowedRegions, autoQueue, fastmode, checkMemory, combineStages, blockBag, bus, event); + public EditSession(@Nonnull World world, @Nullable FawePlayer player, @Nullable FaweLimit limit, @Nullable FaweChangeSet changeSet, @Nullable RegionWrapper[] allowedRegions, @Nullable Boolean autoQueue, @Nullable Boolean fastmode, @Nullable Boolean checkMemory, @Nullable Boolean combineStages, @Nullable BlockBag blockBag, @Nullable EventBus bus, @Nullable EditSessionEvent event) { + this(null, world, player, limit, changeSet, allowedRegions, autoQueue, fastmode, checkMemory, combineStages, blockBag, bus, event); } - public EditSession(@Nullable String worldName, @Nullable World world, @Nullable FaweQueue queue, @Nullable FawePlayer player, @Nullable FaweLimit limit, @Nullable FaweChangeSet changeSet, @Nullable Region[] allowedRegions, @Nullable Boolean autoQueue, @Nullable Boolean fastmode, @Nullable Boolean checkMemory, @Nullable Boolean combineStages, @Nullable BlockBag blockBag, @Nullable EventBus bus, @Nullable EditSessionEvent event) { - this(new EditSessionBuilder(world, worldName).queue(queue).player(player).limit(limit).changeSet(changeSet).allowedRegions(allowedRegions).autoQueue(autoQueue).fastmode(fastmode).checkMemory(checkMemory).combineStages(combineStages).blockBag(blockBag).eventBus(bus).event(event)); + public EditSession(@Nullable String worldName, @Nullable World world, @Nullable FawePlayer player, @Nullable FaweLimit limit, @Nullable FaweChangeSet changeSet, @Nullable Region[] allowedRegions, @Nullable Boolean autoQueue, @Nullable Boolean fastmode, @Nullable Boolean checkMemory, @Nullable Boolean combineStages, @Nullable BlockBag blockBag, @Nullable EventBus bus, @Nullable EditSessionEvent event) { + this(new EditSessionBuilder(world, worldName).player(player).limit(limit).changeSet(changeSet).allowedRegions(allowedRegions).autoQueue(autoQueue).fastmode(fastmode).checkMemory(checkMemory).combineStages(combineStages).blockBag(blockBag).eventBus(bus).event(event)); } public EditSession(EditSessionBuilder builder) { super(builder.compile().getExtent()); this.world = builder.getWorld(); this.worldName = builder.getWorldName(); - this.queue = builder.getQueue(); this.wrapped = builder.isWrapped(); this.fastMode = builder.hasFastMode(); this.history = builder.getHistory(); @@ -268,7 +259,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, * @param event the event to call with the extent */ public EditSession(EventBus eventBus, World world, int maxBlocks, @Nullable BlockBag blockBag, EditSessionEvent event) { - this(world, null, null, null, null, null, true, null, null, null, blockBag, eventBus, event); + this(world, null, null, null, null, true, null, null, null, blockBag, eventBus, event); } public void setExtent(AbstractDelegateExtent extent) { @@ -360,36 +351,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, } bypassHistory = nullExtent; bypassAll = nullExtent; - dequeue(); - if (!queue.isEmpty()) { - if (Fawe.isMainThread()) { - queue.clear(); - } else { - SetQueue.IMP.addTask(() -> queue.clear()); - } - } - return true; - } - - /** - * Remove this EditSession from the queue
- * - This doesn't necessarily stop it from being queued again - */ - public void dequeue() { - if (queue != null) { - SetQueue.IMP.dequeue(queue); - } - } - - /** - * Add a task to run when this EditSession is done dispatching - * - * @param whenDone - */ - public void addNotifyTask(Runnable whenDone) { - if (queue != null) { - queue.addNotifyTask(whenDone); - } + return super.cancel(); } /** @@ -402,16 +364,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, message.send(player, args); } - /** - * Get the FaweQueue this EditSession uses to queue the changes
- * - Note: All implementation queues for FAWE are instances of NMSMappedFaweQueue - * - * @return - */ - public FaweQueue getQueue() { - return queue; - } - // pkg private for TracedEditSession only, may later become public API boolean commitRequired() { return false; @@ -481,26 +433,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, changes++; } - /** - * Change the ChangeSet being used for this EditSession - * - If history is disabled, no changeset can be set - * - * @param set (null = remove the changeset) - */ - public void setChangeSet(@Nullable FaweChangeSet set) { - if (set == null) { - disableHistory(true); - } else { - if (history != null) { - history.setChangeSet(set); - } else { - changeTask = set; - set.addChangeTask(queue); - } - } - changes++; - } - /** * Get the maximum number of blocks that can be changed. -1 will be returned * if it the limit disabled. @@ -847,31 +779,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, return this.getExtent().setBiome(x, y, z, biome); } - @Override - public int getLight(int x, int y, int z) { - return queue.getLight(x, y, z); - } - - @Override - public int getBlockLight(int x, int y, int z) { - return queue.getEmmittedLight(x, y, z); - } - - @Override - public int getSkyLight(int x, int y, int z) { - return queue.getSkyLight(x, y, z); - } - - @Override - public int getBrightness(int x, int y, int z) { - return queue.getBrightness(x, y, z); - } - - @Override - public int getOpacity(int x, int y, int z) { - return queue.getOpacity(x, y, z); - } - public BlockState getBlock(int x, int y, int z) { return getExtent().getBlock(x, y, z); } @@ -907,6 +814,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, * @param maxY maximal height * @return height of highest block found or 'minY' */ + @Override public int getHighestTerrainBlock(int x, int z, int minY, int maxY) { for (int y = maxY; y >= minY; --y) { if (getBlock(x, y, z).getBlockType().getMaterial().isMovementBlocker()) { @@ -926,22 +834,18 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, * @param filter a mask of blocks to consider, or null to consider any solid (movement-blocking) block * @return height of highest block found or 'minY' */ + @Override public int getHighestTerrainBlock(int x, int z, int minY, int maxY, Mask filter) { for (int y = maxY; y >= minY; --y) { if (filter.test(mutablebv.setComponents(x, y, z))) { return y; } } - return minY; } public BlockType getBlockType(int x, int y, int z) { - if (!limit.MAX_CHECKS()) { - throw FaweException.MAX_CHECKS; - } - int combinedId4Data = queue.getCombinedId4DataDebug(x, y, z, BlockTypes.AIR.getInternalId(), this); - return BlockTypes.getFromStateId(combinedId4Data); + return getBlock(x, y, z).getBlockType(); } /** @@ -1208,15 +1112,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, // Reset limit limit.set(originalLimit); // Enqueue it - if (queue == null || queue.isEmpty()) { - queue.dequeue(); - return; - } - if (Fawe.isMainThread()) { - SetQueue.IMP.flush(queue); - } else { - queue.flush(); - } + super.commit(); if (getChangeSet() != null) { if (Settings.IMP.HISTORY.COMBINE_STAGES) { ((FaweChangeSet) getChangeSet()).closeAsync(); @@ -1226,56 +1122,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, } } - /** - * Count the number of blocks of a given list of types in a region. - * - * @param region the region - * @param searchIDs a list of IDs to search - * @return the number of found blocks - */ - public int countBlock(final Region region, final Set searchIDs) { - if (searchIDs.isEmpty()) { - return 0; - } - if (searchIDs.size() == 1) { - final BlockType id = searchIDs.iterator().next(); - RegionVisitor visitor = new RegionVisitor(region, position -> getBlockType(position) == id, this); - Operations.completeBlindly(visitor); - return visitor.getAffected(); - } - final boolean[] ids = new boolean[BlockTypes.size()]; - for (final BlockType id : searchIDs) { - ids[id.getInternalId()] = true; - } - return this.countBlock(region, ids); - } - - public int countBlock(final Region region, final boolean[] ids) { - RegionVisitor visitor = new RegionVisitor(region, position -> ids[getBlockType(position).getInternalId()], this); - Operations.completeBlindly(visitor); - return visitor.getAffected(); - } - - public int countBlock(final Region region, final Mask mask) { - RegionVisitor visitor = new RegionVisitor(region, mask::test, this); - Operations.completeBlindly(visitor); - return visitor.getAffected(); - } - - /** - * Count the number of blocks of a list of types in a region. - * - * @param region the region - * @param searchBlocks the list of blocks to search - * @return the number of blocks that matched the pattern - */ - public int countBlocks(Region region, Set searchBlocks) { - Mask mask = new BlockMaskBuilder().addBlocks(searchBlocks).build(getExtent()); - RegionVisitor visitor = new RegionVisitor(region, mask::test, this); - Operations.completeBlindly(visitor); - return visitor.getAffected(); - } - public int fall(final Region region, boolean fullHeight, final BlockStateHolder replace) { FlatRegion flat = asFlatRegion(region); final int startPerformY = region.getMinimumPoint().getBlockY(); @@ -1520,137 +1366,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, return replaceBlocks(region, mask, pattern); } - /** - * Sets all the blocks inside a region to a given block type. - * - * @param region the region - * @param block the block - * @return number of blocks affected - * @throws MaxChangedBlocksException thrown if too many blocks are changed - */ - public > int setBlocks(Region region, B block) throws MaxChangedBlocksException { - checkNotNull(region); - checkNotNull(block); - boolean hasNbt = block instanceof BaseBlock && ((BaseBlock)block).hasNbtData(); - - if (canBypassAll(region, false, true) && !hasNbt) { - return changes = queue.setBlocks((CuboidRegion) region, block.getInternalId()); - } - try { - if (hasExtraExtents()) { - RegionVisitor visitor = new RegionVisitor(region, new BlockReplace(getExtent(), (block)), this); - Operations.completeBlindly(visitor); - this.changes += visitor.getAffected(); - } else { - for (BlockVector3 blockVector3 : region) { - if (getExtent().setBlock(blockVector3, block)) { - changes++; - } - } - } - } catch (final WorldEditException e) { - throw new RuntimeException("Unexpected exception", e); - } - return changes; - } - - /** - * Sets all the blocks inside a region to a given pattern. - * - * @param region the region - * @param pattern the pattern that provides the replacement block - * @return number of blocks affected - * @throws MaxChangedBlocksException thrown if too many blocks are changed - */ - public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException { - checkNotNull(region); - checkNotNull(pattern); - if (pattern instanceof BlockPattern) { - return setBlocks(region, ((BlockPattern) pattern).getBlock()); - } - if (pattern instanceof BlockStateHolder) { - return setBlocks(region, (BlockStateHolder) pattern); - } - BlockReplace replace = new BlockReplace(this, pattern); - RegionVisitor visitor = new RegionVisitor(region, replace, queue instanceof MappedFaweQueue ? (MappedFaweQueue) queue : null); - Operations.completeBlindly(visitor); - return this.changes = visitor.getAffected(); - } - - /** - * Replaces all the blocks matching a given filter, within a given region, to a block - * returned by a given pattern. - * - * @param region the region to replace the blocks within - * @param filter a list of block types to match, or null to use {@link ExistingBlockMask} - * @param replacement the replacement block - * @return number of blocks affected - * @throws MaxChangedBlocksException thrown if too many blocks are changed - */ - public > int replaceBlocks(Region region, Set filter, B replacement) throws MaxChangedBlocksException { - return replaceBlocks(region, filter, (replacement)); - } - - /** - * Replaces all the blocks matching a given filter, within a given region, to a block - * returned by a given pattern. - * - * @param region the region to replace the blocks within - * @param filter a list of block types to match, or null to use {@link ExistingBlockMask} - * @param pattern the pattern that provides the new blocks - * @return number of blocks affected - * @throws MaxChangedBlocksException thrown if too many blocks are changed - */ - public int replaceBlocks(Region region, Set filter, Pattern pattern) throws MaxChangedBlocksException { - Mask mask = filter == null ? new ExistingBlockMask(this) : new BlockMaskBuilder().addBlocks(filter).build(this); - return replaceBlocks(region, mask, pattern); - } - - /** - * Replaces all the blocks matching a given mask, within a given region, to a block - * returned by a given pattern. - * - * @param region the region to replace the blocks within - * @param mask the mask that blocks must match - * @param pattern the pattern that provides the new blocks - * @return number of blocks affected - * @throws MaxChangedBlocksException thrown if too many blocks are changed - */ - public int replaceBlocks(Region region, Mask mask, Pattern pattern) throws MaxChangedBlocksException { - checkNotNull(region); - checkNotNull(mask); - checkNotNull(pattern); - - BlockReplace replace = new BlockReplace(this, pattern); - RegionMaskingFilter filter = new RegionMaskingFilter(mask, replace); - RegionVisitor visitor = new RegionVisitor(region, filter, queue instanceof MappedFaweQueue ? (MappedFaweQueue) queue : null); - Operations.completeBlindly(visitor); - return this.changes = visitor.getAffected(); - } - - /** - * Sets the blocks at the center of the given region to the given pattern. - * If the center sits between two blocks on a certain axis, then two blocks - * will be placed to mark the center. - * - * @param region the region to find the center of - * @param pattern the replacement pattern - * @return the number of blocks placed - * @throws MaxChangedBlocksException thrown if too many blocks are changed - */ - public int center(Region region, Pattern pattern) throws MaxChangedBlocksException { - checkNotNull(region); - checkNotNull(pattern); - - Vector3 center = region.getCenter(); - Region centerRegion = new CuboidRegion( - getWorld(), // Causes clamping of Y range - BlockVector3.at(((int) center.getX()), ((int) center.getY()), ((int) center.getZ())), - BlockVector3.at(MathUtils.roundHalfUp(center.getX()), - center.getY(), MathUtils.roundHalfUp(center.getZ()))); - return setBlocks(centerRegion, pattern); - } - /** * Make the faces of the given region as if it was a {@link CuboidRegion}. * @@ -1750,14 +1465,18 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, if (region instanceof CuboidRegion) { return makeCuboidWalls(region, pattern); } else { - for (BlockVector3 position : region) { - int x = position.getBlockX(); - int y = position.getBlockY(); - int z = position.getBlockZ(); - if (!region.contains(x, z + 1) || !region.contains(x, z - 1) || !region.contains(x + 1, z) || !region.contains(x - 1, z)) { - setBlock(position, pattern); + replaceBlocks(region, new Mask() { + @Override + public boolean test(BlockVector3 position) { + int x = position.getBlockX(); + int y = position.getBlockY(); + int z = position.getBlockZ(); + if (!region.contains(x, z + 1) || !region.contains(x, z - 1) || !region.contains(x + 1, z) || !region.contains(x - 1, z)) { + return true; + } + return false; } - } + }, pattern); } return changes; } @@ -1773,7 +1492,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, */ public > int overlayCuboidBlocks(Region region, B block) throws MaxChangedBlocksException { checkNotNull(block); - return overlayCuboidBlocks(region, (block)); } @@ -3207,25 +2925,11 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, Direction.DOWN.toBlockVector(), }; - private static double lengthSq(double x, double y, double z) { - return (x * x) + (y * y) + (z * z); - } - - private static double lengthSq(double x, double z) { - return (x * x) + (z * z); - } - - @Override public String getName() { return worldName; } - @Override - public int getBlockLightLevel(BlockVector3 position) { - return queue.getEmmittedLight(position.getBlockX(), position.getBlockY(), position.getBlockZ()); - } - @Override public boolean clearContainerBlockContents(BlockVector3 pos) { BaseBlock block = getFullBlock(pos); @@ -3251,14 +2955,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, for (int x = pos1.getX(); x <= pos2.getX(); x++) { for (int z = pos1.getBlockZ(); z <= pos2.getBlockZ(); z++) { for (int y = pos1.getY(); y <= pos2.getY(); y++) { - int from = queue.getCombinedId4Data(x, y, z); - queue.setBlock(x, y, z, from); - if (BlockTypes.getFromStateId(from).getMaterial().hasContainer()) { - CompoundTag tile = queue.getTileEntity(x, y, z); - if (tile != null) { - queue.setTile(x, y, z, tile); - } - } + setBlock(x, y, z, getFullBlock(x, y, z)); } } } @@ -3363,8 +3060,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, if (changes != 0) { flushQueue(); return true; - } else { - this.queue.clear(); } return false; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index fd43d0064..f6fef19f3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -21,10 +21,9 @@ package com.sk89q.worldedit.command; import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweAPI; -import com.boydti.fawe.beta.IQueueExtent; import com.boydti.fawe.beta.filters.SetFilter; import com.boydti.fawe.beta.implementation.QueueHandler; -import com.boydti.fawe.beta.filters.CountFilter; +import com.boydti.fawe.beta.filters.DistrFilter; import com.boydti.fawe.config.BBC; import com.boydti.fawe.example.NMSMappedFaweQueue; import com.boydti.fawe.object.FaweLimit; @@ -77,8 +76,6 @@ import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.biome.Biomes; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.registry.BiomeRegistry; import java.util.ArrayList; @@ -125,7 +122,7 @@ public class RegionCommands extends MethodCommands { public void debugtest(Player player, @Selection Region region) throws WorldEditException { QueueHandler queueHandler = Fawe.get().getQueueHandler(); World world = player.getWorld(); - CountFilter filter = new CountFilter(); + DistrFilter filter = new DistrFilter(); long start = System.currentTimeMillis(); queueHandler.apply(world, region, filter); long diff = System.currentTimeMillis() - start; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java index b928acd2a..b3468158f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java @@ -66,7 +66,7 @@ public class AbstractDelegateExtent implements Extent, LightingExtent { * * @return the extent */ - public Extent getExtent() { + public final Extent getExtent() { return extent; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java index 9e8f3e944..a76be6020 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.extent; +import com.boydti.fawe.example.MappedFaweQueue; import com.boydti.fawe.jnbt.anvil.generator.CavesGen; import com.boydti.fawe.jnbt.anvil.generator.GenBase; import com.boydti.fawe.jnbt.anvil.generator.OreGen; @@ -26,22 +27,35 @@ import com.boydti.fawe.jnbt.anvil.generator.Resource; import com.boydti.fawe.jnbt.anvil.generator.SchemGen; import com.boydti.fawe.object.clipboard.WorldCopyClipboard; +import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; +import com.sk89q.worldedit.function.RegionMaskingFilter; +import com.sk89q.worldedit.function.block.BlockReplace; +import com.sk89q.worldedit.function.mask.BlockMask; +import com.sk89q.worldedit.function.mask.BlockMaskBuilder; +import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.operation.Operation; +import com.sk89q.worldedit.function.operation.Operations; +import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.function.visitor.RegionVisitor; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.math.MathUtils; import com.sk89q.worldedit.math.MutableBlockVector3; +import com.sk89q.worldedit.math.Vector3; +import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.registry.state.PropertyGroup; import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; @@ -51,8 +65,11 @@ import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Set; import java.util.concurrent.ThreadLocalRandom; +import static com.google.common.base.Preconditions.checkNotNull; + /** * A world, portion of a world, clipboard, or other object that can have blocks * set or entities placed. @@ -328,7 +345,7 @@ public interface Extent extends InputExtent, OutputExtent { int[] counter = new int[BlockTypes.size()]; for (final BlockVector3 pt : region) { - BlockType type = getBlockType(pt); + BlockType type = getBlock(pt).getBlockType(); counter[type.getInternalId()]++; } List> distribution = new ArrayList<>(); @@ -385,6 +402,10 @@ public interface Extent extends InputExtent, OutputExtent { return null; } + default boolean cancel() { + + } + default int getMaxY() { return 255; } @@ -401,4 +422,163 @@ public interface Extent extends InputExtent, OutputExtent { weClipboard.setOrigin(region.getMinimumPoint()); return weClipboard; } + + + /** + * Count the number of blocks of a list of types in a region. + * + * @param region the region + * @param searchBlocks the list of blocks to search + * @return the number of blocks that matched the block + */ + default int countBlocks(Region region, Set searchBlocks) { + BlockMask mask = new BlockMask(this, searchBlocks); + return countBlocks(region, mask); + } + + /** + * Count the number of blocks of a list of types in a region. + * + * @param region the region + * @param searchMask mask to match + * @return the number of blocks that matched the mask + */ + default int countBlocks(Region region, Mask searchMask) { + RegionVisitor visitor = new RegionVisitor(region, searchMask::test); + Operations.completeBlindly(visitor); + return visitor.getAffected(); + } + + /** + * Sets all the blocks inside a region to a given block type. + * + * @param region the region + * @param block the block + * @return number of blocks affected + * @throws MaxChangedBlocksException thrown if too many blocks are changed + */ + default > int setBlocks(Region region, B block) throws MaxChangedBlocksException { + checkNotNull(region); + checkNotNull(block); + boolean hasNbt = block instanceof BaseBlock && ((BaseBlock)block).hasNbtData(); + + if (canBypassAll(region, false, true) && !hasNbt) { + return changes = queue.setBlocks((CuboidRegion) region, block.getInternalId()); + } + try { + if (hasExtraExtents()) { + RegionVisitor visitor = new RegionVisitor(region, new BlockReplace(getExtent(), (block)), this); + Operations.completeBlindly(visitor); + this.changes += visitor.getAffected(); + } else { + for (BlockVector3 blockVector3 : region) { + if (getExtent().setBlock(blockVector3, block)) { + changes++; + } + } + } + } catch (final WorldEditException e) { + throw new RuntimeException("Unexpected exception", e); + } + return changes; + } + + /** + * Sets all the blocks inside a region to a given pattern. + * + * @param region the region + * @param pattern the pattern that provides the replacement block + * @return number of blocks affected + * @throws MaxChangedBlocksException thrown if too many blocks are changed + */ + default int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException { + checkNotNull(region); + checkNotNull(pattern); + if (pattern instanceof BlockPattern) { + return setBlocks(region, ((BlockPattern) pattern).getBlock()); + } + if (pattern instanceof BlockStateHolder) { + return setBlocks(region, (BlockStateHolder) pattern); + } + BlockReplace replace = new BlockReplace(this, pattern); + RegionVisitor visitor = new RegionVisitor(region, replace, queue instanceof MappedFaweQueue ? (MappedFaweQueue) queue : null); + Operations.completeBlindly(visitor); + return this.changes = visitor.getAffected(); + } + + /** + * Replaces all the blocks matching a given filter, within a given region, to a block + * returned by a given pattern. + * + * @param region the region to replace the blocks within + * @param filter a list of block types to match, or null to use {@link com.sk89q.worldedit.function.mask.ExistingBlockMask} + * @param replacement the replacement block + * @return number of blocks affected + * @throws MaxChangedBlocksException thrown if too many blocks are changed + */ + default > int replaceBlocks(Region region, Set filter, B replacement) throws MaxChangedBlocksException { + return replaceBlocks(region, filter, new BlockPattern(replacement)); + } + + /** + * Replaces all the blocks matching a given filter, within a given region, to a block + * returned by a given pattern. + * + * @param region the region to replace the blocks within + * @param filter a list of block types to match, or null to use {@link com.sk89q.worldedit.function.mask.ExistingBlockMask} + * @param pattern the pattern that provides the new blocks + * @return number of blocks affected + * @throws MaxChangedBlocksException thrown if too many blocks are changed + */ + default int replaceBlocks(Region region, Set filter, Pattern pattern) throws MaxChangedBlocksException { + Mask mask = filter == null ? new ExistingBlockMask(this) : new BlockMask(this, filter); + return replaceBlocks(region, mask, pattern); + } + + /** + * Replaces all the blocks matching a given mask, within a given region, to a block + * returned by a given pattern. + * + * @param region the region to replace the blocks within + * @param mask the mask that blocks must match + * @param pattern the pattern that provides the new blocks + * @return number of blocks affected + * @throws MaxChangedBlocksException thrown if too many blocks are changed + */ + default int replaceBlocks(Region region, Mask mask, Pattern pattern) throws MaxChangedBlocksException { + checkNotNull(region); + checkNotNull(mask); + checkNotNull(pattern); + + BlockReplace replace = new BlockReplace(this, pattern); + RegionMaskingFilter filter = new RegionMaskingFilter(mask, replace); + RegionVisitor visitor = new RegionVisitor(region, filter); + Operations.completeLegacy(visitor); + return visitor.getAffected(); + } + + + /** + * Sets the blocks at the center of the given region to the given pattern. + * If the center sits between two blocks on a certain axis, then two blocks + * will be placed to mark the center. + * + * @param region the region to find the center of + * @param pattern the replacement pattern + * @return the number of blocks placed + * @throws MaxChangedBlocksException thrown if too many blocks are changed + */ + default int center(Region region, Pattern pattern) throws MaxChangedBlocksException { + checkNotNull(region); + checkNotNull(pattern); + + Vector3 center = region.getCenter(); + Region centerRegion = new CuboidRegion( + getWorld(), // Causes clamping of Y range + BlockVector3.at(((int) center.getX()), ((int) center.getY()), ((int) center.getZ())), + BlockVector3.at(MathUtils.roundHalfUp(center.getX()), + center.getY(), MathUtils.roundHalfUp(center.getZ()))); + return setBlocks(centerRegion, pattern); + } + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/InputExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/InputExtent.java index d8f533407..10fc0cbe8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/InputExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/InputExtent.java @@ -56,10 +56,6 @@ public interface InputExtent { return getBlock(MutableBlockVector3.get(x, y, z)); } - default BlockType getBlockType(BlockVector3 position) { - return getBlock(position).getBlockType(); - } - /** * Get a immutable snapshot of the block at the given location. * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java index ae9f7bc79..cb4d91fba 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java @@ -20,6 +20,7 @@ package com.sk89q.worldedit.function.mask; import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.extent.NullExtent; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; @@ -34,12 +35,16 @@ import java.util.function.Predicate; public class BlockMask extends ABlockMask { private final boolean[] ordinals; + public BlockMask() { + this(new NullExtent()); + } + public BlockMask(Extent extent) { this(extent, new boolean[BlockTypes.states.length]); } public BlockMask(Extent extent, boolean[] ordinals) { - super(extent); + super(extent == null ? new NullExtent() : extent); this.ordinals = ordinals; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java index d23af2b16..359a38175 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java @@ -19,9 +19,12 @@ package com.sk89q.worldedit.function.mask; +import com.boydti.fawe.beta.DelegateFilter; +import com.boydti.fawe.beta.Filter; import com.boydti.fawe.beta.FilterBlock; import com.sk89q.minecraft.util.commands.Link; import com.sk89q.worldedit.command.UtilityCommands; +import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; import javax.annotation.Nullable; @@ -40,6 +43,28 @@ public interface Mask { */ boolean test(BlockVector3 vector); + default Filter toFilter(Runnable run) { + return new Filter() { + @Override + public void applyBlock(FilterBlock block) { + if (test(block)) { + run.run(); + } + } + }; + } + + default DelegateFilter toFilter(T filter) { + return new DelegateFilter(filter) { + @Override + public void applyBlock(FilterBlock block) { + if (test(block)) { + filter.applyBlock(block); + } + } + }; + } + /** * Get the 2D version of this mask if one exists. * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java index 3ed94f36d..9791bb8ce 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.function.pattern; +import com.boydti.fawe.beta.Filter; import com.boydti.fawe.beta.FilterBlock; import com.sk89q.minecraft.util.commands.Link; import com.sk89q.worldedit.WorldEditException; @@ -32,7 +33,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder; * Returns a {@link BlockStateHolder} for a given position. */ @Link(clazz = UtilityCommands.class, value = "patterns") -public interface Pattern { +public interface Pattern extends Filter { /** * Return a {@link BlockStateHolder} for the given position. @@ -45,4 +46,9 @@ public interface Pattern { default boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { return set.setFullBlock(extent, apply(get)); } + + @Override + default void applyBlock(final FilterBlock block) { + apply(block, block, block); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java index c6d7b82e5..e61d0a4d8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java @@ -25,6 +25,7 @@ import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.function.mask.ABlockMask; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.registry.state.PropertyKey; @@ -300,5 +301,4 @@ public class BaseBlock implements BlockStateHolder { return getAsString(); } } - } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java index 0ba5f1fb9..e1339747c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java @@ -23,6 +23,7 @@ import static com.google.common.base.Preconditions.checkArgument; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.function.mask.ABlockMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.SingleBlockTypeMask; import com.sk89q.worldedit.function.pattern.FawePattern; @@ -306,7 +307,11 @@ public class BlockType implements FawePattern, Keyed { return this.getDefaultState().toBaseBlock(); } - public Mask toMask(Extent extent) { + public SingleBlockTypeMask toMask() { + return toMask(null); + } + + public SingleBlockTypeMask toMask(Extent extent) { return new SingleBlockTypeMask(extent, this); }