diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/ABukkitMain.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/ABukkitMain.java index 8db62b31..e9cccb5b 100644 --- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/ABukkitMain.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/ABukkitMain.java @@ -55,4 +55,6 @@ public abstract class ABukkitMain extends JavaPlugin { } public abstract FaweQueue getQueue(World world); + + public abstract FaweQueue getQueue(String world); } \ No newline at end of file diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java index 4ccb41ee..10ac9db0 100644 --- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java @@ -150,6 +150,47 @@ public class FaweBukkit implements IFawe, Listener { private boolean hasNMS = true; private boolean playerChunk = false; + @Override + public FaweQueue getNewQueue(String world, boolean fast) { + if (playerChunk != (playerChunk = true)) { + try { + Field fieldDirtyCount = ReflectionUtils.getRefClass("{nms}.PlayerChunk").getField("dirtyCount").getRealField(); + fieldDirtyCount.setAccessible(true); + int mod = fieldDirtyCount.getModifiers(); + if ((mod & Modifier.VOLATILE) == 0) { + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(fieldDirtyCount, mod + Modifier.VOLATILE); + } + } catch (Throwable ignore) {} + } + try { + return plugin.getQueue(world); + } catch (Throwable ignore) {} + // Disable incompatible settings + Settings.QUEUE.PARALLEL_THREADS = 1; // BukkitAPI placer is too slow to parallel thread at the chunk level + Settings.HISTORY.COMBINE_STAGES = false; // Performing a chunk copy (if possible) wouldn't be faster using the BukkitAPI + if (hasNMS) { + debug("====== NO NMS BLOCK PLACER FOUND ======"); + debug("FAWE couldn't find a fast block placer"); + debug("Bukkit version: " + Bukkit.getVersion()); + debug("NMS label: " + plugin.getClass().getSimpleName().split("_")[1]); + debug("Fallback placer: " + BukkitQueue_All.class); + debug("======================================="); + debug("Download the version of FAWE for your platform"); + debug(" - http://ci.athion.net/job/FastAsyncWorldEdit/lastSuccessfulBuild/artifact/target"); + debug("======================================="); + TaskManager.IMP.laterAsync(new Runnable() { + @Override + public void run() { + MainUtil.sendAdmin("&cNo NMS placer found, see console!"); + } + }, 1); + hasNMS = false; + } + return new BukkitQueue_All(world); + } + /** * The FaweQueue is a core part of block placement
* - The queue returned here is used in the SetQueue class (SetQueue handles the implementation specific queue)
diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All.java index 25957507..08ff48b5 100644 --- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All.java @@ -3,6 +3,7 @@ package com.boydti.fawe.bukkit.v0; import com.boydti.fawe.FaweCache; import com.boydti.fawe.config.Settings; import com.boydti.fawe.example.CharFaweChunk; +import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.util.MainUtil; import com.sk89q.jnbt.CompoundTag; @@ -17,7 +18,7 @@ import org.bukkit.Chunk; import org.bukkit.World; import org.bukkit.block.Block; -public class BukkitChunk_All extends CharFaweChunk { +public class BukkitChunk_All extends CharFaweChunk { /** * A FaweSections object represents a chunk and the blocks that you wish to change in it. @@ -39,17 +40,23 @@ public class BukkitChunk_All extends CharFaweChunk { private int index; private boolean place = true; + @Override + public void start() { + getChunk().load(true); + } + /** * * @return */ - public void execute(long start) { + @Override + public FaweChunk call() { + long start = System.currentTimeMillis(); int recommended = 25 + BukkitQueue_All.ALLOCATE; boolean more = true; BukkitQueue_All parent = (BukkitQueue_All) getParent(); final Chunk chunk = getChunk(); Object[] disableResult = parent.disableLighting(chunk); - chunk.load(true); final World world = chunk.getWorld(); char[][] sections = getCombinedIdArrays(); if (layer == -1) { @@ -220,6 +227,7 @@ public class BukkitChunk_All extends CharFaweChunk { this.addToQueue(); } parent.resetLighting(disableResult); + return this; } public void setBlock(Block block, int id, byte data) { diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java index 6a5e97fc..79a5eb68 100644 --- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java @@ -42,6 +42,15 @@ public abstract class BukkitQueue_0 extends NMSMa } } + public BukkitQueue_0(String world) { + super(world); + setupAdapter(null); + if (!registered) { + registered = true; + Bukkit.getServer().getPluginManager().registerEvents(this, ((FaweBukkit) Fawe.imp()).getPlugin()); + } + } + @Override public File getSaveFolder() { return new File(Bukkit.getWorldContainer(), getWorldName() + File.separator + "region"); @@ -210,14 +219,4 @@ public abstract class BukkitQueue_0 extends NMSMa try { Class.forName("org.spigotmc.AsyncCatcher").getField("enabled").set(null, true); } catch (Throwable ignore) {} } } - - @Override - public FaweChunk getFaweChunk(int x, int z) { - return new CharFaweChunk(this, x, z) { - @Override - public Chunk getNewChunk() { - return BukkitQueue_0.this.getWorld().getChunkAt(getX(), getZ()); - } - }; - } } diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java index 8edbbebe..44c69866 100644 --- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java @@ -1,6 +1,5 @@ package com.boydti.fawe.bukkit.v0; -import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.FaweChunk; @@ -26,6 +25,16 @@ public class BukkitQueue_All extends BukkitQueue_0 { if (Settings.QUEUE.EXTRA_TIME_MS != Integer.MIN_VALUE) { ALLOCATE = Settings.QUEUE.EXTRA_TIME_MS; Settings.QUEUE.EXTRA_TIME_MS = Integer.MIN_VALUE; + Settings.QUEUE.PARALLEL_THREADS = 1; + } + } + + public BukkitQueue_All(String world) { + super(world); + if (Settings.QUEUE.EXTRA_TIME_MS != Integer.MIN_VALUE) { + ALLOCATE = Settings.QUEUE.EXTRA_TIME_MS; + Settings.QUEUE.EXTRA_TIME_MS = Integer.MIN_VALUE; + Settings.QUEUE.PARALLEL_THREADS = 1; } } @@ -114,21 +123,6 @@ public class BukkitQueue_All extends BukkitQueue_0 { private int skip; - @Override - public boolean setComponents(FaweChunk fc, RunnableVal changeTask) { - if (skip > 0) { - skip--; - fc.addToQueue(); - return true; - } - long start = System.currentTimeMillis(); - ((BukkitChunk_All) fc).execute(start); - if (System.currentTimeMillis() - start > 50 || Fawe.get().getTPS() < TPS_TARGET) { - skip = 10; - } - return true; - } - @Override public void startSet(boolean parallel) { super.startSet(true); diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java index 3a6e0a55..3754cbbb 100644 --- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java @@ -129,7 +129,7 @@ public class AsyncWorld implements World { * @return */ public synchronized static AsyncWorld create(final WorldCreator creator) { - BukkitQueue_0 queue = (BukkitQueue_0) SetQueue.IMP.getNewQueue(FaweAPI.getWorld(creator.name()), true, false); + BukkitQueue_0 queue = (BukkitQueue_0) SetQueue.IMP.getNewQueue(creator.name(), true, false); World world = queue.createWorld(creator); return wrap(world); } diff --git a/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitChunk_1_10.java b/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitChunk_1_10.java index 999c3468..0fc62c25 100644 --- a/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitChunk_1_10.java +++ b/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitChunk_1_10.java @@ -1,20 +1,49 @@ package com.boydti.fawe.bukkit.v1_10; +import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.example.CharFaweChunk; +import com.boydti.fawe.object.BytePair; +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.internal.Constants; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.UUID; import net.minecraft.server.v1_10_R1.Block; +import net.minecraft.server.v1_10_R1.BlockPosition; +import net.minecraft.server.v1_10_R1.ChunkSection; import net.minecraft.server.v1_10_R1.DataBits; import net.minecraft.server.v1_10_R1.DataPalette; import net.minecraft.server.v1_10_R1.DataPaletteBlock; import net.minecraft.server.v1_10_R1.DataPaletteGlobal; +import net.minecraft.server.v1_10_R1.Entity; +import net.minecraft.server.v1_10_R1.EntityPlayer; +import net.minecraft.server.v1_10_R1.EntityTypes; import net.minecraft.server.v1_10_R1.IBlockData; +import net.minecraft.server.v1_10_R1.NBTTagCompound; +import net.minecraft.server.v1_10_R1.TileEntity; import org.bukkit.Chunk; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_10_R1.CraftChunk; +import org.bukkit.event.entity.CreatureSpawnEvent; -public class BukkitChunk_1_10 extends CharFaweChunk { +public class BukkitChunk_1_10 extends CharFaweChunk { public DataPaletteBlock[] sectionPalettes; @@ -35,7 +64,7 @@ public class BukkitChunk_1_10 extends CharFaweChunk { } @Override - public CharFaweChunk copy(boolean shallow) { + public CharFaweChunk copy(boolean shallow) { BukkitChunk_1_10 value = (BukkitChunk_1_10) super.copy(shallow); if (sectionPalettes != null) { value.sectionPalettes = new DataPaletteBlock[16]; @@ -125,4 +154,229 @@ public class BukkitChunk_1_10 extends CharFaweChunk { } } } + + @Override + public void start() { + getChunk().load(true); + } + + @Override + public FaweChunk call() { + try { + final Chunk chunk = this.getChunk(); + final World world = chunk.getWorld(); + final boolean flag = world.getEnvironment() == World.Environment.NORMAL; + net.minecraft.server.v1_10_R1.Chunk nmsChunk = ((CraftChunk) chunk).getHandle(); + nmsChunk.f(true); // Set Modified + nmsChunk.mustSave = true; + net.minecraft.server.v1_10_R1.World nmsWorld = nmsChunk.world; + ChunkSection[] sections = nmsChunk.getSections(); + Class clazzChunk = nmsChunk.getClass(); + final Collection[] entities = (Collection[]) getParent().getEntitySlices.invoke(nmsChunk); + Map tiles = nmsChunk.getTileEntities(); + // Remove entities + for (int i = 0; i < entities.length; i++) { + int count = this.getCount(i); + if (count == 0) { + continue; + } else if (count >= 4096) { + entities[i].clear(); + } else { + char[] array = this.getIdArray(i); + Collection ents = new ArrayList<>(entities[i]); + for (Entity entity : ents) { + if (entity instanceof EntityPlayer) { + continue; + } + int x = ((int) Math.round(entity.locX) & 15); + int z = ((int) Math.round(entity.locZ) & 15); + int y = (int) Math.round(entity.locY); + if (array == null || y < 0 || y > 255) { + continue; + } + if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) { + nmsWorld.removeEntity(entity); + } + } + } + } + HashSet entsToRemove = this.getEntityRemoves(); + if (entsToRemove.size() > 0) { + for (int i = 0; i < entities.length; i++) { + Collection ents = new ArrayList<>(entities[i]); + for (Entity entity : ents) { + if (entsToRemove.contains(entity.getUniqueID())) { + nmsWorld.removeEntity(entity); + } + } + } + } + // Set entities + Set createdEntities = new HashSet<>(); + Set entitiesToSpawn = this.getEntities(); + 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.createEntityByName(id, 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_10.methodFromNative.invoke(BukkitQueue_1_10.adapter, nativeTag); + for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { + tag.remove(name); + } + entity.f(tag); + } + entity.setLocation(x, y, z, yaw, pitch); + nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM); + createdEntities.add(entity.getUniqueID()); + } + } + // Change task? + if (getParent().getChangeTask() != null) { + BukkitChunk_1_10 previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false); + getParent().getChangeTask().run(previous, this); + } + // Trim tiles + Iterator> iterator = tiles.entrySet().iterator(); + HashMap toRemove = null; + 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 j = FaweCache.CACHE_I[ly][lz][lx]; + char[] array = this.getIdArray(j); + if (array == null) { + continue; + } + int k = FaweCache.CACHE_J[ly][lz][lx]; + if (array[k] != 0) { + if (toRemove == null) { + toRemove = new HashMap<>(); + } + toRemove.put(tile.getKey(), tile.getValue()); + } + } + if (toRemove != null) { + for (Map.Entry entry : toRemove.entrySet()) { + BlockPosition bp = entry.getKey(); + TileEntity tile = entry.getValue(); + tiles.remove(bp); + tile.y(); + nmsWorld.s(bp); + tile.invalidateBlockCache(); + } + + } + // Set blocks + for (int j = 0; j < sections.length; j++) { + int count = this.getCount(j); + if (count == 0) { + continue; + } + final char[] array = this.getIdArray(j); + if (array == null) { + continue; + } + ChunkSection section = sections[j]; + if (section == null) { + if (this.sectionPalettes != null && this.sectionPalettes[j] != null) { + section = sections[j] = getParent().newChunkSection(j << 4, flag, null); + getParent().setPalette(section, this.sectionPalettes[j]); + getParent().setCount(0, count - this.getAir(j), section); + continue; + } else { + sections[j] = getParent().newChunkSection(j << 4, flag, array); + } + continue; + } else if (count >= 4096) { + if (this.sectionPalettes != null && this.sectionPalettes[j] != null) { + getParent().setPalette(section, this.sectionPalettes[j]); + getParent().setCount(0, count - this.getAir(j), section); + continue; + } else { + sections[j] = getParent().newChunkSection(j << 4, flag, array); + } + continue; + } + DataPaletteBlock nibble = section.getBlocks(); + int nonEmptyBlockCount = 0; + for (int y = 0; y < 16; y++) { + short[][] i1 = FaweCache.CACHE_J[y]; + for (int z = 0; z < 16; z++) { + short[] i2 = i1[z]; + for (int x= 0; x < 16; x++) { + char combinedId = array[i2[x]]; + switch (combinedId) { + case 0: + IBlockData existing = nibble.a(x, y, z); + if (existing != BukkitQueue_1_10.air) { + nonEmptyBlockCount++; + } + continue; + case 1: + nibble.setBlock(x, y, z, BukkitQueue_1_10.air); + continue; + default: + nonEmptyBlockCount++; + nibble.setBlock(x, y, z, getParent().IBD_CACHE[(int) combinedId]); + } + } + } + } + getParent().setCount(0, nonEmptyBlockCount, section); + } + // Set biomes + int[][] biomes = this.biomes; + if (biomes != null) { + for (int x = 0; x < 16; x++) { + int[] array = biomes[x]; + if (array == null) { + continue; + } + for (int z = 0; z < 16; z++) { + int biome = array[z]; + if (biome == 0) { + continue; + } + nmsChunk.getBiomeIndex()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; + } + } + } + // Set tiles + Map tilesToSpawn = this.getTiles(); + int bx = this.getX() << 4; + int bz = this.getZ() << 4; + + for (Map.Entry entry : tilesToSpawn.entrySet()) { + CompoundTag nativeTag = entry.getValue(); + BytePair pair = entry.getKey(); + BlockPosition pos = new BlockPosition(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos + TileEntity tileEntity = nmsWorld.getTileEntity(pos); + if (tileEntity != null) { + NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_10.methodFromNative.invoke(BukkitQueue_1_10.adapter, nativeTag); + tileEntity.a(tag); // ReadTagIntoTile + } + } + } catch (Throwable e) { + MainUtil.handleError(e); + } + return this; + } } diff --git a/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitMain_110.java b/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitMain_110.java index 5dd09b73..a062d1cd 100644 --- a/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitMain_110.java +++ b/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitMain_110.java @@ -3,6 +3,7 @@ package com.boydti.fawe.bukkit.v1_10; import com.boydti.fawe.bukkit.ABukkitMain; import com.boydti.fawe.bukkit.v0.BukkitQueue_0; import com.boydti.fawe.config.Settings; +import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.io.BufferedRandomAccessFile; import com.boydti.fawe.object.io.FastByteArrayInputStream; import com.boydti.fawe.object.io.FastByteArrayOutputStream; @@ -31,6 +32,11 @@ public class BukkitMain_110 extends ABukkitMain { return new BukkitQueue_1_10(world); } + @Override + public FaweQueue getQueue(String world) { + return new BukkitQueue_1_10(world); + } + @Override public void onEnable() { super.onEnable(); diff --git a/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitQueue_1_10.java b/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitQueue_1_10.java index 23d364bf..d882f39d 100644 --- a/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitQueue_1_10.java +++ b/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitQueue_1_10.java @@ -4,7 +4,6 @@ import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.bukkit.v0.BukkitQueue_0; import com.boydti.fawe.example.CharFaweChunk; -import com.boydti.fawe.object.BytePair; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.util.MainUtil; @@ -12,26 +11,19 @@ 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.jnbt.ListTag; -import com.sk89q.jnbt.LongTag; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.internal.Constants; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import java.util.UUID; +import java.util.concurrent.ExecutorCompletionService; import net.minecraft.server.v1_10_R1.Block; import net.minecraft.server.v1_10_R1.BlockPosition; import net.minecraft.server.v1_10_R1.ChunkSection; @@ -62,26 +54,33 @@ import net.minecraft.server.v1_10_R1.WorldType; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.World; -import org.bukkit.World.Environment; import org.bukkit.WorldCreator; import org.bukkit.craftbukkit.v1_10_R1.CraftChunk; import org.bukkit.craftbukkit.v1_10_R1.CraftServer; import org.bukkit.craftbukkit.v1_10_R1.CraftWorld; -import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.world.WorldInitEvent; import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.generator.ChunkGenerator; public class BukkitQueue_1_10 extends BukkitQueue_0 { - private static IBlockData air; - private static Field fieldBits; - private static Method getEntitySlices; + protected static IBlockData air; + protected static Field fieldBits; + protected static Method getEntitySlices; public static final IBlockData[] IBD_CACHE = new IBlockData[Character.MAX_VALUE]; public BukkitQueue_1_10(final com.sk89q.worldedit.world.World world) { super(world); + init(); + } + + public BukkitQueue_1_10(final String world) { + super(world); + init(); + } + + private void init() { checkVersion("v1_10_R1"); if (air == null) { try { @@ -108,6 +107,11 @@ public class BukkitQueue_1_10 extends BukkitQueue_0 tilesGeneric, Collection[] entitiesGeneric, Set createdEntities, boolean all) throws Exception { + public BukkitChunk_1_10 getPrevious(CharFaweChunk fs, ChunkSection[] sections, Map tilesGeneric, Collection[] entitiesGeneric, Set createdEntities, boolean all) throws Exception { Map tiles = (Map) tilesGeneric; Collection[] entities = (Collection[]) entitiesGeneric; - CharFaweChunk previous = (CharFaweChunk) getFaweChunk(fs.getX(), fs.getZ()); + BukkitChunk_1_10 previous = getFaweChunk(fs.getX(), fs.getZ()); // Copy blocks char[][] idPrevious = new char[16][]; for (int layer = 0; layer < sections.length; layer++) { @@ -481,7 +485,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0 changeTask) { - final com.boydti.fawe.bukkit.v1_10.BukkitChunk_1_10 fs = (com.boydti.fawe.bukkit.v1_10.BukkitChunk_1_10) fc; - final Chunk chunk = (Chunk) fs.getChunk(); - final World world = chunk.getWorld(); - chunk.load(true); - try { - final boolean flag = world.getEnvironment() == Environment.NORMAL; - net.minecraft.server.v1_10_R1.Chunk nmsChunk = ((CraftChunk) chunk).getHandle(); - nmsChunk.f(true); // Set Modified - nmsChunk.mustSave = true; - net.minecraft.server.v1_10_R1.World nmsWorld = nmsChunk.world; - ChunkSection[] sections = nmsChunk.getSections(); - Class clazzChunk = nmsChunk.getClass(); - final Collection[] entities = (Collection[]) getEntitySlices.invoke(nmsChunk); - Map tiles = nmsChunk.getTileEntities(); - // Remove entities - for (int i = 0; i < entities.length; i++) { - int count = fs.getCount(i); - if (count == 0) { - continue; - } else if (count >= 4096) { - entities[i].clear(); - } else { - char[] array = fs.getIdArray(i); - Collection ents = new ArrayList<>(entities[i]); - for (Entity entity : ents) { - if (entity instanceof EntityPlayer) { - continue; - } - int x = ((int) Math.round(entity.locX) & 15); - int z = ((int) Math.round(entity.locZ) & 15); - int y = (int) Math.round(entity.locY); - if (array == null || y < 0 || y > 255) { - continue; - } - if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) { - nmsWorld.removeEntity(entity); - } - } - } - } - HashSet entsToRemove = fs.getEntityRemoves(); - if (entsToRemove.size() > 0) { - for (int i = 0; i < entities.length; i++) { - Collection ents = new ArrayList<>(entities[i]); - for (Entity entity : ents) { - if (entsToRemove.contains(entity.getUniqueID())) { - nmsWorld.removeEntity(entity); - } - } - } - } - // Set entities - Set createdEntities = new HashSet<>(); - Set entitiesToSpawn = fs.getEntities(); - 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.createEntityByName(id, 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) methodFromNative.invoke(adapter, nativeTag); - for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { - tag.remove(name); - } - entity.f(tag); - } - entity.setLocation(x, y, z, yaw, pitch); - nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM); - createdEntities.add(entity.getUniqueID()); - } - } - // Change task? - if (changeTask != null) { - CharFaweChunk previous = getPrevious(fs, sections, tiles, entities, createdEntities, false); - changeTask.run(previous); - } - // Trim tiles - Iterator> iterator = tiles.entrySet().iterator(); - HashMap toRemove = null; - 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 j = FaweCache.CACHE_I[ly][lz][lx]; - char[] array = fs.getIdArray(j); - if (array == null) { - continue; - } - int k = FaweCache.CACHE_J[ly][lz][lx]; - if (array[k] != 0) { - if (toRemove == null) { - toRemove = new HashMap<>(); - } - toRemove.put(tile.getKey(), tile.getValue()); - } - } - if (toRemove != null) { - for (Entry entry : toRemove.entrySet()) { - BlockPosition bp = entry.getKey(); - TileEntity tile = entry.getValue(); - tiles.remove(bp); - tile.y(); - nmsWorld.s(bp); - tile.invalidateBlockCache(); - } - - } - // Set blocks - for (int j = 0; j < sections.length; j++) { - int count = fs.getCount(j); - if (count == 0) { - continue; - } - final char[] array = fs.getIdArray(j); - if (array == null) { - continue; - } - ChunkSection section = sections[j]; - if (section == null) { - if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) { - section = sections[j] = newChunkSection(j << 4, flag, null); - setPalette(section, fs.sectionPalettes[j]); - setCount(0, count - fs.getAir(j), section); - continue; - } else { - sections[j] = newChunkSection(j << 4, flag, array); - } - continue; - } else if (count >= 4096) { - if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) { - setPalette(section, fs.sectionPalettes[j]); - setCount(0, count - fs.getAir(j), section); - continue; - } else { - sections[j] = newChunkSection(j << 4, flag, array); - } - continue; - } - DataPaletteBlock nibble = section.getBlocks(); - int nonEmptyBlockCount = 0; - for (int y = 0; y < 16; y++) { - short[][] i1 = FaweCache.CACHE_J[y]; - for (int z = 0; z < 16; z++) { - short[] i2 = i1[z]; - for (int x= 0; x < 16; x++) { - char combinedId = array[i2[x]]; - switch (combinedId) { - case 0: - IBlockData existing = nibble.a(x, y, z); - if (existing != air) { - nonEmptyBlockCount++; - } - continue; - case 1: - nibble.setBlock(x, y, z, air); - continue; - default: - nonEmptyBlockCount++; - nibble.setBlock(x, y, z, IBD_CACHE[(int) combinedId]); - } - } - } - } - setCount(0, nonEmptyBlockCount, section); - } - // Set biomes - int[][] biomes = fs.biomes; - if (biomes != null) { - for (int x = 0; x < 16; x++) { - int[] array = biomes[x]; - if (array == null) { - continue; - } - for (int z = 0; z < 16; z++) { - int biome = array[z]; - if (biome == 0) { - continue; - } - nmsChunk.getBiomeIndex()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; - } - } - } - // Set tiles - Map tilesToSpawn = fs.getTiles(); - int bx = fs.getX() << 4; - int bz = fs.getZ() << 4; - - for (Map.Entry entry : tilesToSpawn.entrySet()) { - CompoundTag nativeTag = entry.getValue(); - BytePair pair = entry.getKey(); - BlockPosition pos = new BlockPosition(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos - TileEntity tileEntity = nmsWorld.getTileEntity(pos); - if (tileEntity != null) { - NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(adapter, nativeTag); - tileEntity.a(tag); // ReadTagIntoTile - } - } - } catch (Throwable e) { - MainUtil.handleError(e); - } - return true; - } - @Deprecated public boolean unloadChunk(final String world, final Chunk chunk) { net.minecraft.server.v1_10_R1.Chunk c = ((CraftChunk) chunk).getHandle(); @@ -740,7 +522,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0 { +public class BukkitChunk_1_7 extends CharFaweChunk { @Override public Chunk getNewChunk() { @@ -87,7 +114,7 @@ public class BukkitChunk_1_7 extends CharFaweChunk { } @Override - public CharFaweChunk copy(boolean shallow) { + public BukkitChunk_1_7 copy(boolean shallow) { BukkitChunk_1_7 copy = new BukkitChunk_1_7(getParent(), getX(), getZ()); if (shallow) { copy.byteIds = byteIds; @@ -108,4 +135,232 @@ public class BukkitChunk_1_7 extends CharFaweChunk { } return copy; } + + @Override + public void start() { + getChunk().load(true); + } + + @Override + public FaweChunk call() { + CraftChunk chunk = (CraftChunk) this.getChunk(); + net.minecraft.server.v1_7_R4.Chunk nmsChunk = chunk.getHandle(); + nmsChunk.e(); // Modified + nmsChunk.mustSave = true; + net.minecraft.server.v1_7_R4.World nmsWorld = nmsChunk.world; + try { + final boolean flag = getParent().getWorld().getEnvironment() == World.Environment.NORMAL; + // Sections + ChunkSection[] sections = nmsChunk.getSections(); + Map tiles = nmsChunk.tileEntities; + Collection[] entities = nmsChunk.entitySlices; + + // Remove entities + for (int i = 0; i < 16; i++) { + int count = this.getCount(i); + if (count == 0) { + continue; + } else if (count >= 4096) { + entities[i].clear(); + } else { + char[] array = this.getIdArray(i); + Collection ents = new ArrayList<>(entities[i]); + for (Entity entity : ents) { + if (entity instanceof EntityPlayer) { + continue; + } + int x = ((int) Math.round(entity.locX) & 15); + int z = ((int) Math.round(entity.locZ) & 15); + int y = (int) Math.round(entity.locY); + if (array == null) { + continue; + } + if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) { + nmsWorld.removeEntity(entity); + } + } + } + } + // Set entities + Set createdEntities = new HashSet<>(); + Set entitiesToSpawn = this.getEntities(); + for (CompoundTag nativeTag : entitiesToSpawn) { + Map entityTagMap = 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.createEntityByName(id, nmsWorld); + if (entity != null) { + if (nativeTag != null) { + NBTTagCompound tag = (NBTTagCompound) BukkitQueue17.methodFromNative.invoke(BukkitQueue17.adapter, nativeTag); + for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { + tag.remove(name); + } + entity.f(tag); + } + entity.setLocation(x, y, z, yaw, pitch); + nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM); + createdEntities.add(entity.getUniqueID()); + } + } + // Run change task if applicable + if (getParent().getChangeTask() != null) { + CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false); + getParent().getChangeTask().run(previous, this); + } + // Trim tiles + Iterator> iterator = tiles.entrySet().iterator(); + HashMap toRemove = null; + while (iterator.hasNext()) { + Map.Entry tile = iterator.next(); + ChunkPosition pos = tile.getKey(); + int lx = pos.x & 15; + int ly = pos.y; + int lz = pos.z & 15; + int j = FaweCache.CACHE_I[ly][lz][lx]; + char[] array = this.getIdArray(j); + if (array == null) { + continue; + } + int k = FaweCache.CACHE_J[ly][lz][lx]; + if (array[k] != 0) { + if (toRemove == null) { + toRemove = new HashMap<>(); + } + toRemove.put(tile.getKey(), tile.getValue()); + } + } + if (toRemove != null) { + for (Map.Entry entry : toRemove.entrySet()) { + ChunkPosition bp = entry.getKey(); + TileEntity tile = entry.getValue(); + tiles.remove(bp); + tile.s(); + nmsWorld.p(bp.x, bp.y, bp.z); + tile.u(); + } + + } + HashSet entsToRemove = this.getEntityRemoves(); + if (entsToRemove.size() > 0) { + for (int i = 0; i < entities.length; i++) { + Collection ents = new ArrayList<>(entities[i]); + for (Entity entity : ents) { + if (entsToRemove.contains(entity.getUniqueID())) { + nmsWorld.removeEntity(entity); + } + } + } + } + // Set blocks + for (int j = 0; j < sections.length; j++) { + if (this.getCount(j) == 0) { + continue; + } + byte[] newIdArray = this.getByteIdArray(j); + if (newIdArray == null) { + continue; + } + NibbleArray newDataArray = this.getDataArray(j); + ChunkSection section = sections[j]; + if ((section == null) || (this.getCount(j) >= 4096)) { + sections[j] = section = new ChunkSection(j << 4, flag); + section.setIdArray(newIdArray); + if (newDataArray != null) { + section.setDataArray(newDataArray); + } + continue; + } + byte[] currentIdArray = (byte[]) BukkitQueue17.fieldIds.get(section); + NibbleArray currentDataArray = (NibbleArray) BukkitQueue17.fieldData.get(section); + boolean data = currentDataArray != null && newDataArray != null; + if (!data) { + section.setDataArray(newDataArray); + } + if (currentIdArray == null) { + section.setIdArray(newIdArray); + continue; + } + boolean fill = true; + int solid = 0; + char[] charArray = this.getIdArray(j); + for (int k = 0; k < newIdArray.length; k++) { + char combined = charArray[k]; + switch (combined) { + case 0: + fill = false; + continue; + case 1: + fill = false; + if (currentIdArray[k] != 0) { + solid++; + } + currentIdArray[k] = 0; + continue; + default: + solid++; + currentIdArray[k] = newIdArray[k]; + if (data) { + int dataByte = FaweCache.getData(combined); + int x = FaweCache.CACHE_X[0][k]; + int y = FaweCache.CACHE_Y[0][k]; + int z = FaweCache.CACHE_Z[0][k]; + int newData = newDataArray.a(x, y, z); + currentDataArray.a(x, y, z, newData); + } + continue; + } + } + getParent().setCount(0, solid, section); + if (fill) { + this.setCount(j, Short.MAX_VALUE); + } + } + + // Set biomes + int[][] biomes = this.biomes; + if (biomes != null) { + for (int x = 0; x < 16; x++) { + int[] array = biomes[x]; + if (array == null) { + continue; + } + for (int z = 0; z < 16; z++) { + int biome = array[z]; + if (biome == 0) { + continue; + } + nmsChunk.m()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; // Biome array + } + } + } + // Set tiles + Map tilesToSpawn = this.getTiles(); + int bx = this.getX() << 4; + int bz = this.getZ() << 4; + + for (Map.Entry entry : tilesToSpawn.entrySet()) { + CompoundTag nativeTag = entry.getValue(); + BytePair pair = entry.getKey(); + TileEntity tileEntity = nmsWorld.getTileEntity(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); + if (tileEntity != null) { + NBTTagCompound tag = (NBTTagCompound) BukkitQueue17.methodFromNative.invoke(BukkitQueue17.adapter, nativeTag); + tileEntity.a(tag); // ReadTagIntoTile + } + } + } catch (Throwable e) { + MainUtil.handleError(e); + } + return this; + } } diff --git a/bukkit1710/src/main/java/com/boydti/fawe/bukkit/v1_7/BukkitMain_17.java b/bukkit1710/src/main/java/com/boydti/fawe/bukkit/v1_7/BukkitMain_17.java index d6dc0dc0..ef93dd81 100644 --- a/bukkit1710/src/main/java/com/boydti/fawe/bukkit/v1_7/BukkitMain_17.java +++ b/bukkit1710/src/main/java/com/boydti/fawe/bukkit/v1_7/BukkitMain_17.java @@ -2,6 +2,7 @@ package com.boydti.fawe.bukkit.v1_7; import com.boydti.fawe.bukkit.ABukkitMain; import com.boydti.fawe.bukkit.v0.BukkitQueue_0; +import com.boydti.fawe.object.FaweQueue; import com.sk89q.worldedit.world.World; public class BukkitMain_17 extends ABukkitMain { @@ -10,4 +11,9 @@ public class BukkitMain_17 extends ABukkitMain { public BukkitQueue_0 getQueue(World world) { return new BukkitQueue17(world); } + + @Override + public FaweQueue getQueue(String world) { + return new BukkitQueue17(world); + } } diff --git a/bukkit1710/src/main/java/com/boydti/fawe/bukkit/v1_7/BukkitQueue17.java b/bukkit1710/src/main/java/com/boydti/fawe/bukkit/v1_7/BukkitQueue17.java index 7083a128..3f384ad2 100644 --- a/bukkit1710/src/main/java/com/boydti/fawe/bukkit/v1_7/BukkitQueue17.java +++ b/bukkit1710/src/main/java/com/boydti/fawe/bukkit/v1_7/BukkitQueue17.java @@ -1,10 +1,8 @@ package com.boydti.fawe.bukkit.v1_7; -import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.bukkit.v0.BukkitQueue_0; import com.boydti.fawe.example.CharFaweChunk; -import com.boydti.fawe.object.BytePair; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.util.MainUtil; @@ -12,19 +10,14 @@ 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.jnbt.ListTag; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.internal.Constants; import java.io.File; import java.lang.reflect.Field; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -59,18 +52,26 @@ import org.bukkit.WorldCreator; import org.bukkit.craftbukkit.v1_7_R4.CraftChunk; import org.bukkit.craftbukkit.v1_7_R4.CraftServer; import org.bukkit.craftbukkit.v1_7_R4.CraftWorld; -import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.world.WorldInitEvent; import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.generator.ChunkGenerator; public class BukkitQueue17 extends BukkitQueue_0 { - private static Field fieldData; - private static Field fieldIds; + protected static Field fieldData; + protected static Field fieldIds; public BukkitQueue17(final com.sk89q.worldedit.world.World world) { super(world); + init(); + } + + public BukkitQueue17(final String world) { + super(world); + init(); + } + + private void init() { checkVersion("v1_7_R4"); if (fieldData == null) { try { @@ -236,230 +237,6 @@ public class BukkitQueue17 extends BukkitQueue_0 changeTask) { - BukkitChunk_1_7 fs = (BukkitChunk_1_7) fc; - CraftChunk chunk = (CraftChunk) fs.getChunk(); - net.minecraft.server.v1_7_R4.Chunk nmsChunk = chunk.getHandle(); - nmsChunk.e(); // Modified - nmsChunk.mustSave = true; - net.minecraft.server.v1_7_R4.World nmsWorld = nmsChunk.world; - try { - final boolean flag = getWorld().getEnvironment() == World.Environment.NORMAL; - // Sections - ChunkSection[] sections = nmsChunk.getSections(); - Map tiles = nmsChunk.tileEntities; - Collection[] entities = nmsChunk.entitySlices; - - // Remove entities - for (int i = 0; i < 16; i++) { - int count = fs.getCount(i); - if (count == 0) { - continue; - } else if (count >= 4096) { - entities[i].clear(); - } else { - char[] array = fs.getIdArray(i); - Collection ents = new ArrayList<>(entities[i]); - for (Entity entity : ents) { - if (entity instanceof EntityPlayer) { - continue; - } - int x = ((int) Math.round(entity.locX) & 15); - int z = ((int) Math.round(entity.locZ) & 15); - int y = (int) Math.round(entity.locY); - if (array == null) { - continue; - } - if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) { - nmsWorld.removeEntity(entity); - } - } - } - } - // Set entities - Set createdEntities = new HashSet<>(); - Set entitiesToSpawn = fs.getEntities(); - for (CompoundTag nativeTag : entitiesToSpawn) { - Map entityTagMap = 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.createEntityByName(id, nmsWorld); - if (entity != null) { - if (nativeTag != null) { - NBTTagCompound tag = (NBTTagCompound)methodFromNative.invoke(adapter, nativeTag); - for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { - tag.remove(name); - } - entity.f(tag); - } - entity.setLocation(x, y, z, yaw, pitch); - nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM); - createdEntities.add(entity.getUniqueID()); - } - } - // Run change task if applicable - if (changeTask != null) { - CharFaweChunk previous = getPrevious(fs, sections, tiles, entities, createdEntities, false); - changeTask.run(previous); - } - // Trim tiles - Iterator> iterator = tiles.entrySet().iterator(); - HashMap toRemove = null; - while (iterator.hasNext()) { - Map.Entry tile = iterator.next(); - ChunkPosition pos = tile.getKey(); - int lx = pos.x & 15; - int ly = pos.y; - int lz = pos.z & 15; - int j = FaweCache.CACHE_I[ly][lz][lx]; - char[] array = fs.getIdArray(j); - if (array == null) { - continue; - } - int k = FaweCache.CACHE_J[ly][lz][lx]; - if (array[k] != 0) { - if (toRemove == null) { - toRemove = new HashMap<>(); - } - toRemove.put(tile.getKey(), tile.getValue()); - } - } - if (toRemove != null) { - for (Map.Entry entry : toRemove.entrySet()) { - ChunkPosition bp = entry.getKey(); - TileEntity tile = entry.getValue(); - tiles.remove(bp); - tile.s(); - nmsWorld.p(bp.x, bp.y, bp.z); - tile.u(); - } - - } - HashSet entsToRemove = fs.getEntityRemoves(); - if (entsToRemove.size() > 0) { - for (int i = 0; i < entities.length; i++) { - Collection ents = new ArrayList<>(entities[i]); - for (Entity entity : ents) { - if (entsToRemove.contains(entity.getUniqueID())) { - nmsWorld.removeEntity(entity); - } - } - } - } - // Set blocks - for (int j = 0; j < sections.length; j++) { - if (fs.getCount(j) == 0) { - continue; - } - byte[] newIdArray = fs.getByteIdArray(j); - if (newIdArray == null) { - continue; - } - NibbleArray newDataArray = fs.getDataArray(j); - ChunkSection section = sections[j]; - if ((section == null) || (fs.getCount(j) >= 4096)) { - sections[j] = section = new ChunkSection(j << 4, flag); - section.setIdArray(newIdArray); - if (newDataArray != null) { - section.setDataArray(newDataArray); - } - continue; - } - byte[] currentIdArray = (byte[]) fieldIds.get(section); - NibbleArray currentDataArray = (NibbleArray) fieldData.get(section); - boolean data = currentDataArray != null && newDataArray != null; - if (!data) { - section.setDataArray(newDataArray); - } - if (currentIdArray == null) { - section.setIdArray(newIdArray); - continue; - } - boolean fill = true; - int solid = 0; - char[] charArray = fs.getIdArray(j); - for (int k = 0; k < newIdArray.length; k++) { - char combined = charArray[k]; - switch (combined) { - case 0: - fill = false; - continue; - case 1: - fill = false; - if (currentIdArray[k] != 0) { - solid++; - } - currentIdArray[k] = 0; - continue; - default: - solid++; - currentIdArray[k] = newIdArray[k]; - if (data) { - int dataByte = FaweCache.getData(combined); - int x = FaweCache.CACHE_X[0][k]; - int y = FaweCache.CACHE_Y[0][k]; - int z = FaweCache.CACHE_Z[0][k]; - int newData = newDataArray.a(x, y, z); - currentDataArray.a(x, y, z, newData); - } - continue; - } - } - setCount(0, solid, section); - if (fill) { - fs.setCount(j, Short.MAX_VALUE); - } - } - - // Set biomes - int[][] biomes = fs.biomes; - if (biomes != null) { - for (int x = 0; x < 16; x++) { - int[] array = biomes[x]; - if (array == null) { - continue; - } - for (int z = 0; z < 16; z++) { - int biome = array[z]; - if (biome == 0) { - continue; - } - nmsChunk.m()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; // Biome array - } - } - } - // Set tiles - Map tilesToSpawn = fs.getTiles(); - int bx = fs.getX() << 4; - int bz = fs.getZ() << 4; - - for (Map.Entry entry : tilesToSpawn.entrySet()) { - CompoundTag nativeTag = entry.getValue(); - BytePair pair = entry.getKey(); - TileEntity tileEntity = nmsWorld.getTileEntity(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); - if (tileEntity != null) { - NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(adapter, nativeTag); - tileEntity.a(tag); // ReadTagIntoTile - } - } - } catch (Throwable e) { - MainUtil.handleError(e); - } - return true; - } - public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException { Class clazz = section.getClass(); Field fieldTickingBlockCount = clazz.getDeclaredField("tickingBlockCount"); @@ -625,7 +402,7 @@ public class BukkitQueue17 extends BukkitQueue_0 { +public class BukkitChunk_1_8 extends CharFaweChunk { /** * A FaweSections object represents a chunk and the blocks that you wish to change in it. * @@ -21,4 +49,208 @@ public class BukkitChunk_1_8 extends CharFaweChunk { public Chunk getNewChunk() { return Bukkit.getWorld(getParent().getWorldName()).getChunkAt(getX(), getZ()); } + + @Override + public void start() { + getChunk().load(true); + } + + @Override + public FaweChunk call() { + CraftChunk chunk = (CraftChunk) this.getChunk(); + net.minecraft.server.v1_8_R3.Chunk nmsChunk = chunk.getHandle(); + nmsChunk.f(true); // Modified + nmsChunk.mustSave = true; + net.minecraft.server.v1_8_R3.World nmsWorld = nmsChunk.getWorld(); + try { + final boolean flag = getParent().getWorld().getEnvironment() == World.Environment.NORMAL; + // Sections + ChunkSection[] sections = nmsChunk.getSections(); + Map tiles = nmsChunk.getTileEntities(); + Collection[] entities = nmsChunk.getEntitySlices(); + + // Remove entities + for (int i = 0; i < 16; i++) { + int count = this.getCount(i); + if (count == 0) { + continue; + } else if (count >= 4096) { + entities[i].clear(); + } else { + char[] array = this.getIdArray(i); + Collection ents = new ArrayList<>(entities[i]); + for (Entity entity : ents) { + if (entity instanceof EntityPlayer) { + continue; + } + int x = ((int) Math.round(entity.locX) & 15); + int z = ((int) Math.round(entity.locZ) & 15); + int y = (int) Math.round(entity.locY); + if (array == null) { + continue; + } + if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) { + nmsWorld.removeEntity(entity); + } + } + } + } + // Set entities + Set createdEntities = new HashSet<>(); + Set entitiesToSpawn = this.getEntities(); + for (CompoundTag nativeTag : entitiesToSpawn) { + Map entityTagMap = 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.createEntityByName(id, nmsWorld); + if (entity != null) { + if (nativeTag != null) { + NBTTagCompound tag = (NBTTagCompound)BukkitQueue18R3.methodFromNative.invoke(BukkitQueue18R3.adapter, nativeTag); + for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { + tag.remove(name); + } + entity.f(tag); + } + entity.setLocation(x, y, z, yaw, pitch); + nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM); + createdEntities.add(entity.getUniqueID()); + } + } + // Run change task if applicable + if (getParent().getChangeTask() != null) { + CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false); + getParent().getChangeTask().run(previous, this); + } + // Trim tiles + Iterator> iterator = tiles.entrySet().iterator(); + HashMap toRemove = null; + 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 j = FaweCache.CACHE_I[ly][lz][lx]; + char[] array = this.getIdArray(j); + if (array == null) { + continue; + } + int k = FaweCache.CACHE_J[ly][lz][lx]; + if (array[k] != 0) { + if (toRemove == null) { + toRemove = new HashMap<>(); + } + toRemove.put(tile.getKey(), tile.getValue()); + } + } + if (toRemove != null) { + for (Map.Entry entry : toRemove.entrySet()) { + BlockPosition bp = entry.getKey(); + TileEntity tile = entry.getValue(); + tiles.remove(bp); + tile.y(); + nmsWorld.t(bp); + tile.E(); + } + + } + HashSet entsToRemove = this.getEntityRemoves(); + if (entsToRemove.size() > 0) { + for (int i = 0; i < entities.length; i++) { + Collection ents = new ArrayList<>(entities[i]); + for (Entity entity : ents) { + if (entsToRemove.contains(entity.getUniqueID())) { + nmsWorld.removeEntity(entity); + } + } + } + } + // Set blocks + for (int j = 0; j < sections.length; j++) { + if (this.getCount(j) == 0) { + continue; + } + char[] newArray = this.getIdArray(j); + if (newArray == null) { + continue; + } + ChunkSection section = sections[j]; + if (section != null && BukkitQueue18R3.isDirty != null) { + BukkitQueue18R3.isDirty.set(section, true); + } + if ((section == null) || (this.getCount(j) >= 4096)) { + section = new ChunkSection(j << 4, flag, newArray); + sections[j] = section; + continue; + } + char[] currentArray = section.getIdArray(); + int solid = 0; + for (int k = 0; k < newArray.length; k++) { + char n = newArray[k]; + switch (n) { + case 0: + continue; + case 1: + if (currentArray[k] > 1) { + solid++; + currentArray[k] = 0; + } + continue; + default: + solid++; + currentArray[k] = n; + continue; + } + } + getParent().setCount(0, solid, section); + } + + // Set biomes + int[][] biomes = this.biomes; + if (biomes != null) { + for (int x = 0; x < 16; x++) { + int[] array = biomes[x]; + if (array == null) { + continue; + } + for (int z = 0; z < 16; z++) { + int biome = array[z]; + if (biome == 0) { + continue; + } + nmsChunk.getBiomeIndex()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; + } + } + } + // Set tiles + Map tilesToSpawn = this.getTiles(); + int bx = this.getX() << 4; + int bz = this.getZ() << 4; + + for (Map.Entry entry : tilesToSpawn.entrySet()) { + CompoundTag nativeTag = entry.getValue(); + BytePair pair = entry.getKey(); + BlockPosition pos = new BlockPosition(pair.get0x() + bx, pair.get1() & 0xFF, pair.get0y() + bz); // Set pos + TileEntity tileEntity = nmsWorld.getTileEntity(pos); + if (tileEntity != null) { + NBTTagCompound tag = (NBTTagCompound) BukkitQueue18R3.methodFromNative.invoke(BukkitQueue18R3.adapter, nativeTag); + tileEntity.a(tag); // ReadTagIntoTile + } + } + } catch (Throwable e) { + MainUtil.handleError(e); + } + return this; + } } diff --git a/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitMain_18.java b/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitMain_18.java index 5ad82ddd..d6bda43a 100644 --- a/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitMain_18.java +++ b/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitMain_18.java @@ -2,6 +2,7 @@ package com.boydti.fawe.bukkit.v1_8; import com.boydti.fawe.bukkit.ABukkitMain; import com.boydti.fawe.bukkit.v0.BukkitQueue_0; +import com.boydti.fawe.object.FaweQueue; import com.sk89q.worldedit.world.World; public class BukkitMain_18 extends ABukkitMain { @@ -10,4 +11,9 @@ public class BukkitMain_18 extends ABukkitMain { public BukkitQueue_0 getQueue(World world) { return new BukkitQueue18R3(world); } + + @Override + public FaweQueue getQueue(String world) { + return new BukkitQueue18R3(world); + } } diff --git a/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java b/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java index e8af4d8d..1d45c291 100644 --- a/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java +++ b/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java @@ -4,7 +4,6 @@ import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.bukkit.v0.BukkitQueue_0; import com.boydti.fawe.example.CharFaweChunk; -import com.boydti.fawe.object.BytePair; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.util.MainUtil; @@ -12,20 +11,14 @@ 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.jnbt.ListTag; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.internal.Constants; import java.io.File; import java.lang.reflect.Field; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -60,7 +53,6 @@ import org.bukkit.WorldCreator; import org.bukkit.craftbukkit.v1_8_R3.CraftChunk; import org.bukkit.craftbukkit.v1_8_R3.CraftServer; import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; -import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.world.WorldInitEvent; import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.generator.ChunkGenerator; @@ -74,6 +66,11 @@ public class BukkitQueue18R3 extends BukkitQueue_0 changeTask) { - CharFaweChunk fs = (CharFaweChunk) fc; - CraftChunk chunk = (CraftChunk) fs.getChunk(); - net.minecraft.server.v1_8_R3.Chunk nmsChunk = chunk.getHandle(); - nmsChunk.f(true); // Modified - nmsChunk.mustSave = true; - net.minecraft.server.v1_8_R3.World nmsWorld = nmsChunk.getWorld(); - try { - final boolean flag = getWorld().getEnvironment() == World.Environment.NORMAL; - // Sections - ChunkSection[] sections = nmsChunk.getSections(); - Map tiles = nmsChunk.getTileEntities(); - Collection[] entities = nmsChunk.getEntitySlices(); - - // Remove entities - for (int i = 0; i < 16; i++) { - int count = fs.getCount(i); - if (count == 0) { - continue; - } else if (count >= 4096) { - entities[i].clear(); - } else { - char[] array = fs.getIdArray(i); - Collection ents = new ArrayList<>(entities[i]); - for (Entity entity : ents) { - if (entity instanceof EntityPlayer) { - continue; - } - int x = ((int) Math.round(entity.locX) & 15); - int z = ((int) Math.round(entity.locZ) & 15); - int y = (int) Math.round(entity.locY); - if (array == null) { - continue; - } - if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) { - nmsWorld.removeEntity(entity); - } - } - } - } - // Set entities - Set createdEntities = new HashSet<>(); - Set entitiesToSpawn = fs.getEntities(); - for (CompoundTag nativeTag : entitiesToSpawn) { - Map entityTagMap = 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.createEntityByName(id, nmsWorld); - if (entity != null) { - if (nativeTag != null) { - NBTTagCompound tag = (NBTTagCompound)methodFromNative.invoke(adapter, nativeTag); - for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { - tag.remove(name); - } - entity.f(tag); - } - entity.setLocation(x, y, z, yaw, pitch); - nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM); - createdEntities.add(entity.getUniqueID()); - } - } - // Run change task if applicable - if (changeTask != null) { - CharFaweChunk previous = getPrevious(fs, sections, tiles, entities, createdEntities, false); - changeTask.run(previous); - } - // Trim tiles - Iterator> iterator = tiles.entrySet().iterator(); - HashMap toRemove = null; - 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 j = FaweCache.CACHE_I[ly][lz][lx]; - char[] array = fs.getIdArray(j); - if (array == null) { - continue; - } - int k = FaweCache.CACHE_J[ly][lz][lx]; - if (array[k] != 0) { - if (toRemove == null) { - toRemove = new HashMap<>(); - } - toRemove.put(tile.getKey(), tile.getValue()); - } - } - if (toRemove != null) { - for (Map.Entry entry : toRemove.entrySet()) { - BlockPosition bp = entry.getKey(); - TileEntity tile = entry.getValue(); - tiles.remove(bp); - tile.y(); - nmsWorld.t(bp); - tile.E(); - } - - } - HashSet entsToRemove = fs.getEntityRemoves(); - if (entsToRemove.size() > 0) { - for (int i = 0; i < entities.length; i++) { - Collection ents = new ArrayList<>(entities[i]); - for (Entity entity : ents) { - if (entsToRemove.contains(entity.getUniqueID())) { - nmsWorld.removeEntity(entity); - } - } - } - } - // Set blocks - for (int j = 0; j < sections.length; j++) { - if (fs.getCount(j) == 0) { - continue; - } - char[] newArray = fs.getIdArray(j); - if (newArray == null) { - continue; - } - ChunkSection section = sections[j]; - if (section != null && isDirty != null) { - isDirty.set(section, true); - } - if ((section == null) || (fs.getCount(j) >= 4096)) { - section = new ChunkSection(j << 4, flag, newArray); - sections[j] = section; - continue; - } - char[] currentArray = section.getIdArray(); - int solid = 0; - for (int k = 0; k < newArray.length; k++) { - char n = newArray[k]; - switch (n) { - case 0: - continue; - case 1: - if (currentArray[k] > 1) { - solid++; - currentArray[k] = 0; - } - continue; - default: - solid++; - currentArray[k] = n; - continue; - } - } - setCount(0, solid, section); - } - - // Set biomes - int[][] biomes = fs.biomes; - if (biomes != null) { - for (int x = 0; x < 16; x++) { - int[] array = biomes[x]; - if (array == null) { - continue; - } - for (int z = 0; z < 16; z++) { - int biome = array[z]; - if (biome == 0) { - continue; - } - nmsChunk.getBiomeIndex()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; - } - } - } - // Set tiles - Map tilesToSpawn = fs.getTiles(); - int bx = fs.getX() << 4; - int bz = fs.getZ() << 4; - - for (Map.Entry entry : tilesToSpawn.entrySet()) { - CompoundTag nativeTag = entry.getValue(); - BytePair pair = entry.getKey(); - BlockPosition pos = new BlockPosition(pair.get0x() + bx, pair.get1() & 0xFF, pair.get0y() + bz); // Set pos - TileEntity tileEntity = nmsWorld.getTileEntity(pos); - if (tileEntity != null) { - NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(adapter, nativeTag); - tileEntity.a(tag); // ReadTagIntoTile - } - } - } catch (Throwable e) { - MainUtil.handleError(e); - } - return true; - } - public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException { Class clazz = section.getClass(); Field fieldTickingBlockCount = clazz.getDeclaredField("tickingBlockCount"); diff --git a/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java index ffcfd6a2..57192c2b 100644 --- a/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java +++ b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java @@ -1,20 +1,51 @@ package com.boydti.fawe.bukkit.v1_9; +import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.example.CharFaweChunk; +import com.boydti.fawe.object.BytePair; +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.internal.Constants; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.UUID; import net.minecraft.server.v1_9_R2.Block; +import net.minecraft.server.v1_9_R2.BlockPosition; +import net.minecraft.server.v1_9_R2.Blocks; +import net.minecraft.server.v1_9_R2.ChunkSection; import net.minecraft.server.v1_9_R2.DataBits; import net.minecraft.server.v1_9_R2.DataPalette; import net.minecraft.server.v1_9_R2.DataPaletteBlock; import net.minecraft.server.v1_9_R2.DataPaletteGlobal; +import net.minecraft.server.v1_9_R2.Entity; +import net.minecraft.server.v1_9_R2.EntityPlayer; +import net.minecraft.server.v1_9_R2.EntityTypes; import net.minecraft.server.v1_9_R2.IBlockData; +import net.minecraft.server.v1_9_R2.NBTTagCompound; +import net.minecraft.server.v1_9_R2.TileEntity; import org.bukkit.Chunk; +import org.bukkit.World; +import org.bukkit.block.Biome; +import org.bukkit.craftbukkit.v1_9_R2.CraftChunk; +import org.bukkit.event.entity.CreatureSpawnEvent; -public class BukkitChunk_1_9 extends CharFaweChunk { +public class BukkitChunk_1_9 extends CharFaweChunk { public DataPaletteBlock[] sectionPalettes; @@ -35,7 +66,7 @@ public class BukkitChunk_1_9 extends CharFaweChunk { } @Override - public CharFaweChunk copy(boolean shallow) { + public BukkitChunk_1_9 copy(boolean shallow) { BukkitChunk_1_9 value = (BukkitChunk_1_9) super.copy(shallow); if (sectionPalettes != null) { value.sectionPalettes = new DataPaletteBlock[16]; @@ -125,4 +156,252 @@ public class BukkitChunk_1_9 extends CharFaweChunk { } } } + + @Override + public void start() { + getChunk().load(true); + } + + @Override + public FaweChunk call() { + final Chunk chunk = (Chunk) this.getChunk(); + final World world = chunk.getWorld(); + try { + final boolean flag = world.getEnvironment() == World.Environment.NORMAL; + net.minecraft.server.v1_9_R2.Chunk nmsChunk = ((CraftChunk) chunk).getHandle(); + nmsChunk.f(true); // Modified + nmsChunk.mustSave = true; + net.minecraft.server.v1_9_R2.World nmsWorld = nmsChunk.world; + ChunkSection[] sections = nmsChunk.getSections(); + Class clazzChunk = nmsChunk.getClass(); + final Field ef = clazzChunk.getDeclaredField("entitySlices"); + final Collection[] entities = (Collection[]) ef.get(nmsChunk); + Map tiles = nmsChunk.getTileEntities(); + // Remove entities + for (int i = 0; i < entities.length; i++) { + int count = this.getCount(i); + if (count == 0) { + continue; + } else if (count >= 4096) { + entities[i].clear(); + } else { + char[] array = this.getIdArray(i); + Collection ents = new ArrayList<>(entities[i]); + for (Entity entity : ents) { + if (entity instanceof EntityPlayer) { + continue; + } + int x = ((int) Math.round(entity.locX) & 15); + int z = ((int) Math.round(entity.locZ) & 15); + int y = (int) Math.round(entity.locY); + if (array == null || y < 0 || y > 255) { + continue; + } + if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) { + nmsWorld.removeEntity(entity); + } + } + } + } + HashSet entsToRemove = this.getEntityRemoves(); + if (entsToRemove.size() > 0) { + for (int i = 0; i < entities.length; i++) { + Collection ents = new ArrayList<>(entities[i]); + for (Entity entity : ents) { + if (entsToRemove.contains(entity.getUniqueID())) { + nmsWorld.removeEntity(entity); + } + } + } + } + // Set entities + Set createdEntities = new HashSet<>(); + Set entitiesToSpawn = this.getEntities(); + 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.createEntityByName(id, 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_9_R1.methodFromNative.invoke(BukkitQueue_1_9_R1.adapter, nativeTag); + for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { + tag.remove(name); + } + entity.f(tag); + } + entity.setLocation(x, y, z, yaw, pitch); + nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM); + createdEntities.add(entity.getUniqueID()); + } + } + // Change task? + if (getParent().getChangeTask() != null) { + CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false); + getParent().getChangeTask().run(previous, this); + } + // Trim tiles + Iterator> iterator = tiles.entrySet().iterator(); + HashMap toRemove = null; + 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 j = FaweCache.CACHE_I[ly][lz][lx]; + char[] array = this.getIdArray(j); + if (array == null) { + continue; + } + int k = FaweCache.CACHE_J[ly][lz][lx]; + if (array[k] != 0) { + if (toRemove == null) { + toRemove = new HashMap<>(); + } + toRemove.put(tile.getKey(), tile.getValue()); + } + } + if (toRemove != null) { + for (Map.Entry entry : toRemove.entrySet()) { + BlockPosition bp = entry.getKey(); + TileEntity tile = entry.getValue(); + tiles.remove(bp); + tile.y(); + nmsWorld.s(bp); + tile.invalidateBlockCache(); + } + + } + // Set blocks + for (int j = 0; j < sections.length; j++) { + int count = this.getCount(j); + if (count == 0) { + continue; + } + final char[] array = this.getIdArray(j); + if (array == null) { + continue; + } + ChunkSection section = sections[j]; + if (section == null) { + if (this.sectionPalettes != null && this.sectionPalettes[j] != null) { + section = sections[j] = getParent().newChunkSection(j << 4, flag, null); + getParent().setPalette(section, this.sectionPalettes[j]); + getParent().setCount(0, count - this.getAir(j), section); + continue; + } else { + sections[j] = getParent().newChunkSection(j << 4, flag, array); + } + continue; + } else if (count >= 4096) { + if (this.sectionPalettes != null && this.sectionPalettes[j] != null) { + getParent().setPalette(section, this.sectionPalettes[j]); + getParent().setCount(0, count - this.getAir(j), section); + continue; + } else { + sections[j] = getParent().newChunkSection(j << 4, flag, array); + } + continue; + } + DataPaletteBlock nibble = section.getBlocks(); + Field fieldBits = nibble.getClass().getDeclaredField("b"); + fieldBits.setAccessible(true); + DataBits bits = (DataBits) fieldBits.get(nibble); + + Field fieldPalette = nibble.getClass().getDeclaredField("c"); + fieldPalette.setAccessible(true); + DataPalette palette = (DataPalette) fieldPalette.get(nibble); + int nonEmptyBlockCount = 0; + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + char combinedId = array[FaweCache.CACHE_J[y][z][x]]; + switch (combinedId) { + case 0: + IBlockData existing = nibble.a(x, y, z); + if (existing != BukkitQueue_1_9_R1.air) { + nonEmptyBlockCount++; + } + continue; + case 1: + nibble.setBlock(x, y, z, Blocks.AIR.getBlockData()); + continue; + default: + nonEmptyBlockCount++; + nibble.setBlock(x, y, z, Block.getById(combinedId >> 4).fromLegacyData(combinedId & 0xF)); + } + } + } + } + getParent().setCount(0, nonEmptyBlockCount, section); + } + // Set biomes + int[][] biomes = this.biomes; + if (biomes != null) { + for (int x = 0; x < 16; x++) { + int[] array = biomes[x]; + if (array == null) { + continue; + } + for (int z = 0; z < 16; z++) { + int biome = array[z]; + if (biome == 0) { + continue; + } + nmsChunk.getBiomeIndex()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; + } + } + } + // Set tiles + Map tilesToSpawn = this.getTiles(); + int bx = this.getX() << 4; + int bz = this.getZ() << 4; + + for (Map.Entry entry : tilesToSpawn.entrySet()) { + CompoundTag nativeTag = entry.getValue(); + BytePair pair = entry.getKey(); + BlockPosition pos = new BlockPosition(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos + TileEntity tileEntity = nmsWorld.getTileEntity(pos); + if (tileEntity != null) { + NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_9_R1.methodFromNative.invoke(BukkitQueue_1_9_R1.adapter, nativeTag); + tileEntity.a(tag); // ReadTagIntoTile + } + } + } catch (Throwable e) { + MainUtil.handleError(e); + } + final int[][] biomes = this.getBiomeArray(); + final Biome[] values = Biome.values(); + if (biomes != null) { + for (int x = 0; x < 16; x++) { + final int[] array = biomes[x]; + if (array == null) { + continue; + } + for (int z = 0; z < 16; z++) { + final int biome = array[z]; + if (biome == 0) { + continue; + } + chunk.getBlock(x, 0, z).setBiome(values[biome]); + } + } + } + return this; + } } diff --git a/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitMain_19.java b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitMain_19.java index 7c9237ce..031832d3 100644 --- a/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitMain_19.java +++ b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitMain_19.java @@ -2,6 +2,7 @@ package com.boydti.fawe.bukkit.v1_9; import com.boydti.fawe.bukkit.ABukkitMain; import com.boydti.fawe.bukkit.v0.BukkitQueue_0; +import com.boydti.fawe.object.FaweQueue; import com.sk89q.worldedit.world.World; public class BukkitMain_19 extends ABukkitMain { @@ -9,4 +10,9 @@ public class BukkitMain_19 extends ABukkitMain { public BukkitQueue_0 getQueue(World world) { return new BukkitQueue_1_9_R1(world); } + + @Override + public FaweQueue getQueue(String world) { + return new BukkitQueue_1_9_R1(world); + } } diff --git a/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java index 2329ce3f..baea56a0 100644 --- a/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java +++ b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java @@ -4,7 +4,6 @@ import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.bukkit.v0.BukkitQueue_0; import com.boydti.fawe.example.CharFaweChunk; -import com.boydti.fawe.object.BytePair; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.util.MainUtil; @@ -12,32 +11,22 @@ 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.jnbt.ListTag; -import com.sk89q.jnbt.LongTag; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.internal.Constants; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Field; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import java.util.UUID; import net.minecraft.server.v1_9_R2.Block; import net.minecraft.server.v1_9_R2.BlockPosition; -import net.minecraft.server.v1_9_R2.Blocks; import net.minecraft.server.v1_9_R2.ChunkSection; import net.minecraft.server.v1_9_R2.DataBits; -import net.minecraft.server.v1_9_R2.DataPalette; import net.minecraft.server.v1_9_R2.DataPaletteBlock; import net.minecraft.server.v1_9_R2.Entity; import net.minecraft.server.v1_9_R2.EntityPlayer; @@ -63,24 +52,30 @@ import net.minecraft.server.v1_9_R2.WorldType; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.World; -import org.bukkit.World.Environment; import org.bukkit.WorldCreator; -import org.bukkit.block.Biome; import org.bukkit.craftbukkit.v1_9_R2.CraftChunk; import org.bukkit.craftbukkit.v1_9_R2.CraftServer; import org.bukkit.craftbukkit.v1_9_R2.CraftWorld; -import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.world.WorldInitEvent; import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.generator.ChunkGenerator; public class BukkitQueue_1_9_R1 extends BukkitQueue_0 { - private static IBlockData air; - private static Field fieldBits; + protected static IBlockData air; + protected static Field fieldBits; public BukkitQueue_1_9_R1(final com.sk89q.worldedit.world.World world) { super(world); + init(); + } + + public BukkitQueue_1_9_R1(final String world) { + super(world); + init(); + } + + private void init() { checkVersion("v1_9_R2"); if (air == null) { try { @@ -287,7 +282,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0 changeTask) { - final BukkitChunk_1_9 fs = (BukkitChunk_1_9) fc; - final Chunk chunk = (Chunk) fs.getChunk(); - final World world = chunk.getWorld(); - chunk.load(true); - try { - final boolean flag = world.getEnvironment() == Environment.NORMAL; - net.minecraft.server.v1_9_R2.Chunk nmsChunk = ((CraftChunk) chunk).getHandle(); - nmsChunk.f(true); // Modified - nmsChunk.mustSave = true; - net.minecraft.server.v1_9_R2.World nmsWorld = nmsChunk.world; - ChunkSection[] sections = nmsChunk.getSections(); - Class clazzChunk = nmsChunk.getClass(); - final Field ef = clazzChunk.getDeclaredField("entitySlices"); - final Collection[] entities = (Collection[]) ef.get(nmsChunk); - Map tiles = nmsChunk.getTileEntities(); - // Remove entities - for (int i = 0; i < entities.length; i++) { - int count = fs.getCount(i); - if (count == 0) { - continue; - } else if (count >= 4096) { - entities[i].clear(); - } else { - char[] array = fs.getIdArray(i); - Collection ents = new ArrayList<>(entities[i]); - for (Entity entity : ents) { - if (entity instanceof EntityPlayer) { - continue; - } - int x = ((int) Math.round(entity.locX) & 15); - int z = ((int) Math.round(entity.locZ) & 15); - int y = (int) Math.round(entity.locY); - if (array == null || y < 0 || y > 255) { - continue; - } - if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) { - nmsWorld.removeEntity(entity); - } - } - } - } - HashSet entsToRemove = fs.getEntityRemoves(); - if (entsToRemove.size() > 0) { - for (int i = 0; i < entities.length; i++) { - Collection ents = new ArrayList<>(entities[i]); - for (Entity entity : ents) { - if (entsToRemove.contains(entity.getUniqueID())) { - nmsWorld.removeEntity(entity); - } - } - } - } - // Set entities - Set createdEntities = new HashSet<>(); - Set entitiesToSpawn = fs.getEntities(); - 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.createEntityByName(id, 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) methodFromNative.invoke(adapter, nativeTag); - for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { - tag.remove(name); - } - entity.f(tag); - } - entity.setLocation(x, y, z, yaw, pitch); - nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM); - createdEntities.add(entity.getUniqueID()); - } - } - // Change task? - if (changeTask != null) { - CharFaweChunk previous = getPrevious(fs, sections, tiles, entities, createdEntities, false); - changeTask.run(previous); - } - // Trim tiles - Iterator> iterator = tiles.entrySet().iterator(); - HashMap toRemove = null; - 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 j = FaweCache.CACHE_I[ly][lz][lx]; - char[] array = fs.getIdArray(j); - if (array == null) { - continue; - } - int k = FaweCache.CACHE_J[ly][lz][lx]; - if (array[k] != 0) { - if (toRemove == null) { - toRemove = new HashMap<>(); - } - toRemove.put(tile.getKey(), tile.getValue()); - } - } - if (toRemove != null) { - for (Entry entry : toRemove.entrySet()) { - BlockPosition bp = entry.getKey(); - TileEntity tile = entry.getValue(); - tiles.remove(bp); - tile.y(); - nmsWorld.s(bp); - tile.invalidateBlockCache(); - } - - } - // Set blocks - for (int j = 0; j < sections.length; j++) { - int count = fs.getCount(j); - if (count == 0) { - continue; - } - final char[] array = fs.getIdArray(j); - if (array == null) { - continue; - } - ChunkSection section = sections[j]; - if (section == null) { - if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) { - section = sections[j] = newChunkSection(j << 4, flag, null); - setPalette(section, fs.sectionPalettes[j]); - setCount(0, count - fs.getAir(j), section); - continue; - } else { - sections[j] = newChunkSection(j << 4, flag, array); - } - continue; - } else if (count >= 4096) { - if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) { - setPalette(section, fs.sectionPalettes[j]); - setCount(0, count - fs.getAir(j), section); - continue; - } else { - sections[j] = newChunkSection(j << 4, flag, array); - } - continue; - } - DataPaletteBlock nibble = section.getBlocks(); - Field fieldBits = nibble.getClass().getDeclaredField("b"); - fieldBits.setAccessible(true); - DataBits bits = (DataBits) fieldBits.get(nibble); - - Field fieldPalette = nibble.getClass().getDeclaredField("c"); - fieldPalette.setAccessible(true); - DataPalette palette = (DataPalette) fieldPalette.get(nibble); - int nonEmptyBlockCount = 0; - for (int y = 0; y < 16; y++) { - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++) { - char combinedId = array[FaweCache.CACHE_J[y][z][x]]; - switch (combinedId) { - case 0: - IBlockData existing = nibble.a(x, y, z); - if (existing != air) { - nonEmptyBlockCount++; - } - continue; - case 1: - nibble.setBlock(x, y, z, Blocks.AIR.getBlockData()); - continue; - default: - nonEmptyBlockCount++; - nibble.setBlock(x, y, z, Block.getById(combinedId >> 4).fromLegacyData(combinedId & 0xF)); - } - } - } - } - setCount(0, nonEmptyBlockCount, section); - } - // Set biomes - int[][] biomes = fs.biomes; - if (biomes != null) { - for (int x = 0; x < 16; x++) { - int[] array = biomes[x]; - if (array == null) { - continue; - } - for (int z = 0; z < 16; z++) { - int biome = array[z]; - if (biome == 0) { - continue; - } - nmsChunk.getBiomeIndex()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; - } - } - } - // Set tiles - Map tilesToSpawn = fs.getTiles(); - int bx = fs.getX() << 4; - int bz = fs.getZ() << 4; - - for (Map.Entry entry : tilesToSpawn.entrySet()) { - CompoundTag nativeTag = entry.getValue(); - BytePair pair = entry.getKey(); - BlockPosition pos = new BlockPosition(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos - TileEntity tileEntity = nmsWorld.getTileEntity(pos); - if (tileEntity != null) { - NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(adapter, nativeTag); - tileEntity.a(tag); // ReadTagIntoTile - } - } - } catch (Throwable e) { - MainUtil.handleError(e); - } - final int[][] biomes = fs.getBiomeArray(); - final Biome[] values = Biome.values(); - if (biomes != null) { - for (int x = 0; x < 16; x++) { - final int[] array = biomes[x]; - if (array == null) { - continue; - } - for (int z = 0; z < 16; z++) { - final int biome = array[z]; - if (biome == 0) { - continue; - } - chunk.getBlock(x, 0, z).setBiome(values[biome]); - } - } - } - return true; - } - @Deprecated public boolean unloadChunk(final String world, final Chunk chunk) { net.minecraft.server.v1_9_R2.Chunk c = ((CraftChunk) chunk).getHandle(); @@ -769,8 +519,8 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0 99) { return; } try { diff --git a/core/src/main/java/com/boydti/fawe/FaweAPI.java b/core/src/main/java/com/boydti/fawe/FaweAPI.java index a0dab3c8..8271923e 100644 --- a/core/src/main/java/com/boydti/fawe/FaweAPI.java +++ b/core/src/main/java/com/boydti/fawe/FaweAPI.java @@ -98,9 +98,8 @@ public class FaweAPI { return FawePlayer.wrap(obj); } - @Deprecated public static FaweQueue createQueue(String worldName, boolean autoqueue) { - return SetQueue.IMP.getNewQueue(getWorld(worldName), true, autoqueue); + return SetQueue.IMP.getNewQueue(worldName, true, autoqueue); } /** diff --git a/core/src/main/java/com/boydti/fawe/IFawe.java b/core/src/main/java/com/boydti/fawe/IFawe.java index 2f4d9ccd..6a85a55e 100644 --- a/core/src/main/java/com/boydti/fawe/IFawe.java +++ b/core/src/main/java/com/boydti/fawe/IFawe.java @@ -25,6 +25,8 @@ public interface IFawe { public FaweQueue getNewQueue(World world, boolean fast); + public FaweQueue getNewQueue(String world, boolean fast); + public String getWorldName(World world); public Collection getMaskManagers(); diff --git a/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java b/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java index 65c35b92..50ed82e3 100644 --- a/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java +++ b/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java @@ -15,7 +15,7 @@ import java.util.Map; import java.util.Set; import java.util.UUID; -public abstract class CharFaweChunk extends FaweChunk { +public abstract class CharFaweChunk extends FaweChunk { public char[][] ids; public short[] count; @@ -47,6 +47,11 @@ public abstract class CharFaweChunk extends FaweChunk { this.relight = new short[HEIGHT >> 4]; } + @Override + public V getParent() { + return (V) super.getParent(); + } + @Override public T getChunk() { if (this.chunk == null) { @@ -358,8 +363,8 @@ public abstract class CharFaweChunk extends FaweChunk { } @Override - public CharFaweChunk copy(boolean shallow) { - CharFaweChunk copy = (CharFaweChunk) getParent().getFaweChunk(getX(), getZ()); + public CharFaweChunk copy(boolean shallow) { + CharFaweChunk copy = (CharFaweChunk) getParent().getFaweChunk(getX(), getZ()); if (shallow) { copy.ids = ids; copy.air = air; diff --git a/core/src/main/java/com/boydti/fawe/example/DefaultFaweQueueMap.java b/core/src/main/java/com/boydti/fawe/example/DefaultFaweQueueMap.java index 8763f6d8..19ccbdf5 100644 --- a/core/src/main/java/com/boydti/fawe/example/DefaultFaweQueueMap.java +++ b/core/src/main/java/com/boydti/fawe/example/DefaultFaweQueueMap.java @@ -3,12 +3,13 @@ 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.MainUtil; import com.boydti.fawe.util.MathMan; import java.util.Collection; import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.concurrent.ExecutorCompletionService; public class DefaultFaweQueueMap implements IFaweQueueMap { @@ -21,26 +22,25 @@ public class DefaultFaweQueueMap implements IFaweQueueMap { /** * Map of chunks in the queue */ - public ConcurrentHashMap blocks = new ConcurrentHashMap<>(8, 0.9f, 1); - public ConcurrentLinkedDeque chunks = new ConcurrentLinkedDeque() { + public ConcurrentHashMap blocks = new ConcurrentHashMap(8, 0.9f, 1) { @Override - public boolean add(FaweChunk o) { + public FaweChunk put(Long key, FaweChunk value) { if (parent.getProgressTask() != null) { parent.getProgressTask().run(FaweQueue.ProgressType.QUEUE, size() + 1); } - return super.add(o); + return super.put(key, value); } }; @Override public Collection getFaweCunks() { - return new HashSet<>(chunks); + return new HashSet<>(blocks.values()); } @Override public void forEachChunk(RunnableVal onEach) { - for (FaweChunk chunk : chunks) { - onEach.run(chunk); + for (Map.Entry entry : blocks.entrySet()) { + onEach.run(entry.getValue()); } } @@ -59,7 +59,6 @@ public class DefaultFaweQueueMap implements IFaweQueueMap { return previous; } this.blocks.put(pair, chunk); - chunks.add(chunk); } return chunk; } @@ -77,9 +76,7 @@ public class DefaultFaweQueueMap implements IFaweQueueMap { public void add(FaweChunk chunk) { long pair = MathMan.pairInt(chunk.getX(), chunk.getZ()); FaweChunk previous = this.blocks.put(pair, chunk); - if (previous == null) { - chunks.add(chunk); - } else { + if (previous != null) { blocks.put(pair, previous); } } @@ -88,12 +85,11 @@ public class DefaultFaweQueueMap implements IFaweQueueMap { @Override public void clear() { blocks.clear(); - chunks.clear(); } @Override public int size() { - return chunks.size(); + return blocks.size(); } private FaweChunk getNewFaweChunk(int cx, int cz) { @@ -105,24 +101,59 @@ public class DefaultFaweQueueMap implements IFaweQueueMap { private int lastZ = Integer.MIN_VALUE; @Override - public boolean next() { + public boolean next(int amount, ExecutorCompletionService pool, long time) { + lastWrappedChunk = null; lastX = Integer.MIN_VALUE; lastZ = Integer.MIN_VALUE; try { - if (this.blocks.isEmpty()) { - return false; + int added = 0; + Iterator> iter = blocks.entrySet().iterator(); + if (amount == 1) { + long start = System.currentTimeMillis(); + do { + if (iter.hasNext()) { + FaweChunk chunk = iter.next().getValue(); + iter.remove(); + parent.start(chunk); + chunk.call(); + parent.end(chunk); + } else { + break; + } + } while (System.currentTimeMillis() - start < time); + return !blocks.isEmpty(); } - synchronized (blocks) { - FaweChunk chunk = chunks.poll(); - if (chunk != null) { - blocks.remove(chunk.longHash()); - parent.execute(chunk); - return true; + boolean result = true; + for (int i = 0; i < amount && (result = iter.hasNext()); i++, added++) { + Map.Entry item = iter.next(); + FaweChunk chunk = item.getValue(); + parent.start(chunk); + pool.submit(chunk); + iter.remove(); + } + if (result) { + long start = System.currentTimeMillis(); + while (System.currentTimeMillis() - start < time) { + for (int i = 0; i < amount && (iter.hasNext()); i++, added++) { + Map.Entry item = iter.next(); + FaweChunk chunk = item.getValue(); + parent.start(chunk); + pool.submit(chunk); + iter.remove(); + } + for (int i = 0; i < amount; i++, added--) { + FaweChunk fc = ((FaweChunk) pool.take().get()); + parent.end(fc); + } } } + for (int i = 0; i < added; i++) { + FaweChunk fc = ((FaweChunk) pool.take().get()); + parent.end(fc); + } } catch (Throwable e) { - MainUtil.handleError(e); + e.printStackTrace(); } - return false; + return !blocks.isEmpty(); } } diff --git a/core/src/main/java/com/boydti/fawe/example/IFaweQueueMap.java b/core/src/main/java/com/boydti/fawe/example/IFaweQueueMap.java index a3e1b5be..e20d1b41 100644 --- a/core/src/main/java/com/boydti/fawe/example/IFaweQueueMap.java +++ b/core/src/main/java/com/boydti/fawe/example/IFaweQueueMap.java @@ -3,6 +3,7 @@ package com.boydti.fawe.example; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.RunnableVal; import java.util.Collection; +import java.util.concurrent.ExecutorCompletionService; public interface IFaweQueueMap { @@ -20,5 +21,5 @@ public interface IFaweQueueMap { int size(); - boolean next(); + boolean next(int size, ExecutorCompletionService dispatcher, long time); } diff --git a/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java b/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java index 52ea52fc..356b6761 100644 --- a/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.UUID; import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.TimeUnit; @@ -36,6 +37,11 @@ public abstract class MappedFaweQueue extends FaweQueue { this(world, null); } + public MappedFaweQueue(final String world) { + super(world); + map = new DefaultFaweQueueMap(this); + } + public MappedFaweQueue(final World world, IFaweQueueMap map) { super(world); if (map == null) { @@ -99,8 +105,6 @@ public abstract class MappedFaweQueue extends FaweQueue { public abstract boolean regenerateChunk(WORLD world, int x, int z); - public abstract boolean setComponents(FaweChunk fc, RunnableVal changeTask); - @Override public abstract FaweChunk getFaweChunk(int x, int z); @@ -192,10 +196,19 @@ public abstract class MappedFaweQueue extends FaweQueue { } @Override - public boolean next() { - return map.next(); + public boolean next(int amount, ExecutorCompletionService pool, long time) { + return map.next(amount, pool, time); } + public void start(FaweChunk chunk) { + chunk.start(); + } + + public void end(FaweChunk chunk) { + chunk.end(); + } + + @Override public void runTasks() { if (getProgressTask() != null) { getProgressTask().run(ProgressType.DONE, 1); @@ -224,31 +237,6 @@ public abstract class MappedFaweQueue extends FaweQueue { private int dispatched = 0; - public boolean execute(final FaweChunk fc) { - if (fc == null) { - return false; - } - // Set blocks / entities / biome - if (getProgressTask() != null) { - getProgressTask().run(ProgressType.QUEUE, map.size()); - getProgressTask().run(ProgressType.DISPATCH, ++dispatched); - } - if (getChangeTask() != null) { - if (!this.setComponents(fc, new RunnableVal() { - @Override - public void run(FaweChunk before) { - getChangeTask().run(before, fc); - } - })) { - return false; - } - } else if (!this.setComponents(fc, null)) { - return false; - } - fc.executeNotifyTasks(); - return true; - } - @Override public void clear() { map.clear(); diff --git a/core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java b/core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java index dd76da3d..98e88b2a 100644 --- a/core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java @@ -22,6 +22,12 @@ public abstract class NMSMappedFaweQueue ex addRelightTask(); } + public NMSMappedFaweQueue(String world) { + super(world); + this.maxY = 256; + addRelightTask(); + } + public NMSMappedFaweQueue(World world, IFaweQueueMap map) { super(world, map); this.maxY = world.getMaxY(); @@ -47,35 +53,32 @@ public abstract class NMSMappedFaweQueue ex private NMSRelighter relighter; @Override - public boolean execute(FaweChunk fc) { - if (super.execute(fc)) { - sendChunk(fc); - if (Settings.LIGHTING.MODE == 0) { - return true; + public void end(FaweChunk chunk) { + super.end(chunk); + if (Settings.LIGHTING.MODE == 0) { + return; + } + if (relighter == null) { + relighter = new NMSRelighter(this); + } + if (Settings.LIGHTING.MODE == 2) { + relighter.addChunk(chunk.getX(), chunk.getZ(), null); + return; + } + CharFaweChunk cfc = (CharFaweChunk) chunk; + boolean relight = false; + boolean[] fix = new boolean[(maxY + 1) >> 4]; + boolean sky = hasSky(); + for (int i = 0; i < cfc.ids.length; i++) { + if ((sky && ((cfc.getAir(i) & 4095) != 0 || (cfc.getCount(i) & 4095) != 0)) || cfc.getRelight(i) != 0) { + relight = true; + fix[i] = true; } - if (relighter == null) { - relighter = new NMSRelighter(this); - } - if (Settings.LIGHTING.MODE == 2) { - relighter.addChunk(fc.getX(), fc.getZ(), null); - return true; - } - CharFaweChunk chunk = (CharFaweChunk) fc; - boolean relight = false; - boolean[] fix = new boolean[(maxY + 1) >> 4]; - boolean sky = hasSky(); - for (int i = 0; i < chunk.ids.length; i++) { - if ((sky && ((chunk.getAir(i) & 4095) != 0 || (chunk.getCount(i) & 4095) != 0)) || chunk.getRelight(i) != 0) { - relight = true; - fix[i] = true; - } - } - if (relight) { - relighter.addChunk(chunk.getX(), chunk.getZ(), fix); - } - return true; + } + if (relight) { + relighter.addChunk(chunk.getX(), chunk.getZ(), fix); } else { - return false; + refreshChunk(chunk); } } diff --git a/core/src/main/java/com/boydti/fawe/example/NullFaweChunk.java b/core/src/main/java/com/boydti/fawe/example/NullFaweChunk.java index 8f462803..e48f391f 100644 --- a/core/src/main/java/com/boydti/fawe/example/NullFaweChunk.java +++ b/core/src/main/java/com/boydti/fawe/example/NullFaweChunk.java @@ -92,4 +92,9 @@ public class NullFaweChunk extends FaweChunk { public FaweChunk copy(boolean shallow) { return this; } + + @Override + public FaweChunk call() { + return null; + } } diff --git a/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java b/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java index 8ac538d9..c3ec6405 100644 --- a/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java +++ b/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java @@ -402,4 +402,9 @@ public class MCAChunk extends FaweChunk { public Void getChunk() { throw new UnsupportedOperationException("Not applicable for this"); } + + @Override + public FaweChunk call() { + throw new UnsupportedOperationException("Not supported"); + } } diff --git a/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java b/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java index 217a7c06..41f5c958 100644 --- a/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java +++ b/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java @@ -5,7 +5,6 @@ import com.boydti.fawe.example.CharFaweChunk; import com.boydti.fawe.example.NMSMappedFaweQueue; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FaweQueue; -import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.RunnableVal4; import com.boydti.fawe.util.TaskManager; import com.sk89q.jnbt.CompoundTag; @@ -141,11 +140,6 @@ public class MCAQueue extends NMSMappedFaweQueue changeTask) { - throw new UnsupportedOperationException("Not supported"); - } - @Override public CharFaweChunk getPrevious(CharFaweChunk fs, FaweChunk sections, Map tiles, Collection[] entities, Set createdEntities, boolean all) throws Exception { throw new UnsupportedOperationException("Not supported"); diff --git a/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueueMap.java b/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueueMap.java index 3ae3b92a..88ed4fa1 100644 --- a/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueueMap.java +++ b/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueueMap.java @@ -14,6 +14,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorCompletionService; public class MCAQueueMap implements IFaweQueueMap { @@ -150,20 +151,26 @@ public class MCAQueueMap implements IFaweQueueMap { } @Override - public boolean next() { + public boolean next(int size, ExecutorCompletionService dispatcher, long time) { lastX = Integer.MIN_VALUE; lastZ = Integer.MIN_VALUE; lastFileX = Integer.MIN_VALUE; lastFileZ = Integer.MIN_VALUE; if (!mcaFileMap.isEmpty()) { Iterator> iter = mcaFileMap.entrySet().iterator(); - if (iter.hasNext()) { - MCAFile file = iter.next().getValue(); - iter.remove(); - file.flush(); - file.close(); - return true; - } + boolean result; + long start = System.currentTimeMillis(); + do { + if (result = iter.hasNext()) { + MCAFile file = iter.next().getValue(); + iter.remove(); + file.flush(); + file.close(); + } else { + break; + } + } while (System.currentTimeMillis() - start < time); + return result; } if (isHybridQueue) { boolean value = queue.next(); diff --git a/core/src/main/java/com/boydti/fawe/object/FaweChunk.java b/core/src/main/java/com/boydti/fawe/object/FaweChunk.java index f9d4b628..df4d0df3 100644 --- a/core/src/main/java/com/boydti/fawe/object/FaweChunk.java +++ b/core/src/main/java/com/boydti/fawe/object/FaweChunk.java @@ -9,8 +9,9 @@ import java.util.ArrayDeque; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.concurrent.Callable; -public abstract class FaweChunk { +public abstract class FaweChunk implements Callable { private FaweQueue parent; private int x,z; @@ -267,4 +268,11 @@ public abstract class FaweChunk { } public abstract FaweChunk copy(boolean shallow); + + public void start() {}; + + public void end() {}; + + @Override + public abstract FaweChunk call(); } diff --git a/core/src/main/java/com/boydti/fawe/object/FawePlayer.java b/core/src/main/java/com/boydti/fawe/object/FawePlayer.java index 44835203..1444b370 100644 --- a/core/src/main/java/com/boydti/fawe/object/FawePlayer.java +++ b/core/src/main/java/com/boydti/fawe/object/FawePlayer.java @@ -82,10 +82,7 @@ public abstract class FawePlayer { Field fieldPlayer = actor.getClass().getDeclaredField("player"); fieldPlayer.setAccessible(true); return wrap(fieldPlayer.get(actor)); - } catch (Throwable e) { - MainUtil.handleError(e); - return Fawe.imp().wrap(actor.getName()); - } + } catch (Throwable ignore) {} } } if (obj instanceof Actor) { diff --git a/core/src/main/java/com/boydti/fawe/object/FaweQueue.java b/core/src/main/java/com/boydti/fawe/object/FaweQueue.java index 9d610d43..fc79512c 100644 --- a/core/src/main/java/com/boydti/fawe/object/FaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/object/FaweQueue.java @@ -1,8 +1,10 @@ package com.boydti.fawe.object; import com.boydti.fawe.Fawe; +import com.boydti.fawe.FaweAPI; import com.boydti.fawe.FaweCache; import com.boydti.fawe.config.BBC; +import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MathMan; @@ -23,6 +25,7 @@ import java.util.HashSet; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.atomic.AtomicBoolean; public abstract class FaweQueue { @@ -34,6 +37,10 @@ public abstract class FaweQueue { private RunnableVal2 changeTask; private RunnableVal2 progressTask; + public FaweQueue(String world) { + this.world = world; + } + public FaweQueue(World world) { this.weWorld = world; this.world = Fawe.imp().getWorldName(world); @@ -62,7 +69,7 @@ public abstract class FaweQueue { } public World getWEWorld() { - return weWorld; + return weWorld != null ? weWorld : (weWorld = FaweAPI.getWorld(world)); } public String getWorldName() { @@ -226,11 +233,19 @@ public abstract class FaweQueue { return count; } + @Deprecated + public boolean next() { + int amount = Settings.QUEUE.PARALLEL_THREADS; + ExecutorCompletionService service = SetQueue.IMP.getCompleterService(); + long time = 20; // 30ms + return next(amount, service, time); + } + /** * Gets the FaweChunk and sets the requested blocks * @return */ - public abstract boolean next(); + public abstract boolean next(int amount, ExecutorCompletionService pool, long time); public void saveMemory() { MainUtil.sendAdmin(BBC.OOM.s()); @@ -369,6 +384,8 @@ public abstract class FaweQueue { } } + public abstract void runTasks(); + public boolean enqueue() { return SetQueue.IMP.enqueue(this); } diff --git a/core/src/main/java/com/boydti/fawe/object/player/DefaultFawePlayer.java b/core/src/main/java/com/boydti/fawe/object/player/DefaultFawePlayer.java new file mode 100644 index 00000000..b8c75714 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/player/DefaultFawePlayer.java @@ -0,0 +1,4 @@ +package com.boydti.fawe.object.player; + +public class DefaultFawePlayer { +} diff --git a/core/src/main/java/com/boydti/fawe/regions/general/plot/PlotSquaredFeature.java b/core/src/main/java/com/boydti/fawe/regions/general/plot/PlotSquaredFeature.java index 4185e6fc..1b2aa981 100644 --- a/core/src/main/java/com/boydti/fawe/regions/general/plot/PlotSquaredFeature.java +++ b/core/src/main/java/com/boydti/fawe/regions/general/plot/PlotSquaredFeature.java @@ -31,7 +31,7 @@ public class PlotSquaredFeature extends FaweMaskManager { try { // If it's going to fail, throw an error now rather than later QueueProvider provider = QueueProvider.of(FaweLocalBlockQueue.class, null); - GlobalBlockQueue.IMP.setProvider(provider); + GlobalBlockQueue.IMP = new GlobalBlockQueue(provider, 1); HybridPlotManager.REGENERATIVE_CLEAR = false; Fawe.debug(" - QueueProvider: " + FaweLocalBlockQueue.class); Fawe.debug(" - HybridPlotManager.REGENERATIVE_CLEAR: " + HybridPlotManager.REGENERATIVE_CLEAR); diff --git a/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java b/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java index 1b1aa7b4..70e96649 100644 --- a/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java @@ -12,6 +12,7 @@ import java.util.Collection; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.concurrent.ExecutorCompletionService; public class DelegateFaweQueue extends FaweQueue { private FaweQueue parent; @@ -169,6 +170,11 @@ public class DelegateFaweQueue extends FaweQueue { return parent.next(); } + @Override + public boolean next(int amount, ExecutorCompletionService pool, long time) { + return parent.next(amount, pool, time); + } + @Override public void saveMemory() { parent.saveMemory(); @@ -234,6 +240,11 @@ public class DelegateFaweQueue extends FaweQueue { return parent.size(); } + @Override + public void runTasks() { + parent.runTasks(); + } + @Override public boolean enqueue() { return parent.enqueue(); diff --git a/core/src/main/java/com/boydti/fawe/util/SetQueue.java b/core/src/main/java/com/boydti/fawe/util/SetQueue.java index be02f7b7..7f052a9e 100644 --- a/core/src/main/java/com/boydti/fawe/util/SetQueue.java +++ b/core/src/main/java/com/boydti/fawe/util/SetQueue.java @@ -3,13 +3,13 @@ package com.boydti.fawe.util; import com.boydti.fawe.Fawe; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.FaweQueue; -import com.boydti.fawe.object.RunnableVal2; import com.sk89q.worldedit.world.World; import java.util.ArrayList; import java.util.Collection; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.TimeUnit; @@ -40,23 +40,17 @@ public class SetQueue { */ private final ConcurrentLinkedDeque emptyTasks = new ConcurrentLinkedDeque<>(); - private final RunnableVal2 SET_TASK = new RunnableVal2() { - @Override - public void run(Long free, FaweQueue queue) { - do { - final boolean current = queue.next(); - if (current == false) { - lastSuccess = last; - if (inactiveQueues.size() == 0 && activeQueues.size() == 0) { - runEmptyTasks(); - } - return; - } - } while (((SetQueue.this.secondLast = System.currentTimeMillis()) - SetQueue.this.last) < free); - } - }; - private ForkJoinPool pool = new ForkJoinPool(); + private ExecutorCompletionService completer = new ExecutorCompletionService(pool); + + /** + * @see TaskManager#getPublicForkJoinPool() + * @return ForkJoinPool + */ + @Deprecated + public ExecutorCompletionService getCompleterService() { + return completer; + } public SetQueue() { tasks = new ConcurrentLinkedDeque<>(); @@ -65,56 +59,55 @@ public class SetQueue { TaskManager.IMP.repeat(new Runnable() { @Override public void run() { - while (!tasks.isEmpty() && Fawe.get().getTimer().isAbove(18.5)) { - tasks.poll().run(); - } - if (inactiveQueues.isEmpty() && activeQueues.isEmpty()) { - lastSuccess = System.currentTimeMillis(); - runEmptyTasks(); - return; - } - if (!MemUtil.isMemoryFree()) { - final int mem = MemUtil.calculateMemory(); - if (mem != Integer.MAX_VALUE) { - if ((mem <= 1) && Settings.CRASH_MITIGATION) { - for (FaweQueue queue : getAllQueues()) { - queue.saveMemory(); + try { + while (!tasks.isEmpty() && Fawe.get().getTimer().isAbove(18.5)) { + tasks.poll().run(); + } + if (inactiveQueues.isEmpty() && activeQueues.isEmpty()) { + lastSuccess = System.currentTimeMillis(); + runEmptyTasks(); + return; + } + if (!MemUtil.isMemoryFree()) { + final int mem = MemUtil.calculateMemory(); + if (mem != Integer.MAX_VALUE) { + if ((mem <= 1) && Settings.CRASH_MITIGATION) { + for (FaweQueue queue : getAllQueues()) { + queue.saveMemory(); + } + return; + } + if (SetQueue.this.forceChunkSet()) { + System.gc(); + } else { + SetQueue.this.runEmptyTasks(); } return; } - if (SetQueue.this.forceChunkSet()) { - System.gc(); - } else { - SetQueue.this.runEmptyTasks(); - } + } + FaweQueue queue = getNextQueue(); + if (queue == null || !Fawe.get().getTimer().isAbove(18.5)) { return; } - } - SET_TASK.value1 = Settings.QUEUE.EXTRA_TIME_MS + 50 + Math.min((50 + SetQueue.this.last) - (SetQueue.this.last = System.currentTimeMillis()), SetQueue.this.secondLast - System.currentTimeMillis()); - SET_TASK.value2 = getNextQueue(); - if (SET_TASK.value2 == null) { - return; - } - if (Thread.currentThread() != Fawe.get().getMainThread()) { - throw new IllegalStateException("This shouldn't be possible for placement to occur off the main thread"); - } - // Disable the async catcher as it can't discern async vs parallel - boolean parallel = Settings.QUEUE.PARALLEL_THREADS > 1; - SET_TASK.value2.startSet(parallel); - try { - if (Settings.QUEUE.PARALLEL_THREADS <= 1 || !Fawe.get().isJava8()) { - SET_TASK.run(); - } else { - for (int i = 0; i < Settings.QUEUE.PARALLEL_THREADS; i++) { - pool.submit(SET_TASK); - } - pool.awaitQuiescence(Settings.QUEUE.DISCARD_AFTER_MS, TimeUnit.MILLISECONDS); + if (Thread.currentThread() != Fawe.get().getMainThread()) { + throw new IllegalStateException("This shouldn't be possible for placement to occur off the main thread"); } + long time = Settings.QUEUE.EXTRA_TIME_MS + 50 + Math.min((50 + SetQueue.this.last) - (SetQueue.this.last = System.currentTimeMillis()), SetQueue.this.secondLast - System.currentTimeMillis()); + // Disable the async catcher as it can't discern async vs parallel + boolean parallel = Settings.QUEUE.PARALLEL_THREADS > 1; + queue.startSet(parallel); + try { + if (!queue.next(Settings.QUEUE.PARALLEL_THREADS, getCompleterService(), time)) { + queue.runTasks(); + } + } catch (Throwable e) { + pool.awaitQuiescence(Settings.QUEUE.DISCARD_AFTER_MS, TimeUnit.MILLISECONDS); + completer = new ExecutorCompletionService(pool); + e.printStackTrace(); + } + secondLast = System.currentTimeMillis(); } catch (Throwable e) { - MainUtil.handleError(e); - } finally { - // Enable it again (note that we are still on the main thread) - SET_TASK.value2.endSet(parallel); + e.printStackTrace(); } } }, 1); @@ -156,6 +149,7 @@ public class SetQueue { public void dequeue(FaweQueue queue) { inactiveQueues.remove(queue); activeQueues.remove(queue); + queue.runTasks(); } public Collection getAllQueues() { @@ -181,44 +175,34 @@ public class SetQueue { return queue; } + public FaweQueue getNewQueue(String world, boolean fast, boolean autoqueue) { + FaweQueue queue = Fawe.imp().getNewQueue(world, fast); + if (autoqueue) { + inactiveQueues.add(queue); + } + return queue; + } + public void flush(FaweQueue queue) { - SET_TASK.value1 = Long.MAX_VALUE; - SET_TASK.value2 = queue; - if (SET_TASK.value2 == null) { - return; - } - if (Thread.currentThread() != Fawe.get().getMainThread()) { - throw new IllegalStateException("Must be flushed on the main thread!"); - } - // Disable the async catcher as it can't discern async vs parallel - boolean parallel = Settings.QUEUE.PARALLEL_THREADS > 1; - SET_TASK.value2.startSet(parallel); + queue.startSet(Settings.QUEUE.PARALLEL_THREADS > 1); try { - if (!parallel || !Fawe.get().isJava8()) { - SET_TASK.run(); - } else { - for (int i = 0; i < Settings.QUEUE.PARALLEL_THREADS; i++) { - pool.submit(SET_TASK); - } - pool.awaitQuiescence(Settings.QUEUE.DISCARD_AFTER_MS, TimeUnit.MILLISECONDS); - } + queue.next(Settings.QUEUE.PARALLEL_THREADS, getCompleterService(), Long.MAX_VALUE); } catch (Throwable e) { + pool.awaitQuiescence(Settings.QUEUE.DISCARD_AFTER_MS, TimeUnit.MILLISECONDS); + completer = new ExecutorCompletionService(pool); MainUtil.handleError(e); - } finally { - // Enable it again (note that we are still on the main thread) - SET_TASK.value2.endSet(parallel); - dequeue(queue); } } public FaweQueue getNextQueue() { long now = System.currentTimeMillis(); - while (activeQueues.size() > 0) { + while (!activeQueues.isEmpty()) { FaweQueue queue = activeQueues.peek(); if (queue != null && queue.size() > 0) { queue.setModified(now); return queue; } else { + queue.runTasks(); activeQueues.poll(); } } @@ -234,6 +218,7 @@ public class SetQueue { total += queue.size(); if (queue.size() == 0) { if (age > Settings.QUEUE.DISCARD_AFTER_MS) { + queue.runTasks(); iter.remove(); } continue; @@ -265,6 +250,8 @@ public class SetQueue { if (set) { activeQueues.add(queue); return set; + } else { + queue.runTasks(); } } } @@ -285,6 +272,9 @@ public class SetQueue { } if (diff > Settings.QUEUE.DISCARD_AFTER_MS) { // These edits never finished + for (FaweQueue queue : tmp) { + queue.runTasks(); + } inactiveQueues.clear(); } return false; diff --git a/core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java b/core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java index 9c1dc454..20d43776 100644 --- a/core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java +++ b/core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java @@ -214,7 +214,7 @@ public class PlayerWrapper implements Player { TaskManager.IMP.sync(new RunnableVal() { @Override public void run(Object value) { - edit.getQueue().next(); + edit.getQueue().flush(); setPosition(new Vector(x + 0.5, y, z + 0.5)); } }); diff --git a/core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java b/core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java index 1f266813..30071fc2 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java @@ -162,7 +162,7 @@ public class NavigationCommands { @Command( aliases = { "jumpto", "j" }, - usage = "jumpto [world,x,y,z]", + usage = "[world,x,y,z]", desc = "Teleport to a location", min = 0, max = 1 diff --git a/core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java b/core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java index 1bae4aff..01473efe 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java +++ b/core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java @@ -151,7 +151,7 @@ public class SelectionCommand extends SimpleCommand { long start = System.currentTimeMillis(); BBC.OPERATION.send(actor, BBC.VISITOR_BLOCK.format(cuboid.getArea())); queue.flush(); - BBC.ACTION_COMPLETE.send(actor, start); + BBC.ACTION_COMPLETE.send(actor, (System.currentTimeMillis() - start) / 1000); return null; } } catch (Throwable e) { diff --git a/forge110/src/main/java/com/boydti/fawe/forge/FaweForge.java b/forge110/src/main/java/com/boydti/fawe/forge/FaweForge.java index 0e9c081a..8c698e84 100644 --- a/forge110/src/main/java/com/boydti/fawe/forge/FaweForge.java +++ b/forge110/src/main/java/com/boydti/fawe/forge/FaweForge.java @@ -118,6 +118,11 @@ public class FaweForge implements IFawe { return new ForgeQueue_All(world); } + @Override + public FaweQueue getNewQueue(String world, boolean dontCareIfFast) { + return new ForgeQueue_All(world); + } + @Override public Collection getMaskManagers() { return new ArrayList<>(); diff --git a/forge110/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java b/forge110/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java index e4a28530..780fcfa3 100644 --- a/forge110/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java +++ b/forge110/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java @@ -1,19 +1,42 @@ package com.boydti.fawe.forge.v0; +import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.example.CharFaweChunk; +import com.boydti.fawe.object.BytePair; import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.util.MainUtil; +import com.boydti.fawe.util.MathMan; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.ListTag; +import com.sk89q.jnbt.StringTag; +import com.sk89q.jnbt.Tag; import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.UUID; import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityList; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.BitArray; +import net.minecraft.util.ClassInheritanceMultiMap; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.chunk.BlockStateContainer; import net.minecraft.world.chunk.BlockStatePaletteRegistry; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.IBlockStatePalette; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; -public class ForgeChunk_All extends CharFaweChunk { +public class ForgeChunk_All extends CharFaweChunk { public BlockStateContainer[] sectionPalettes; @@ -35,7 +58,7 @@ public class ForgeChunk_All extends CharFaweChunk { } @Override - public CharFaweChunk copy(boolean shallow) { + public ForgeChunk_All copy(boolean shallow) { ForgeChunk_All value = (ForgeChunk_All) super.copy(shallow); if (sectionPalettes != null) { value.sectionPalettes = new BlockStateContainer[16]; @@ -111,4 +134,210 @@ public class ForgeChunk_All extends CharFaweChunk { } } } + + @Override + public ForgeChunk_All call() { + net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk(); + nmsChunk.setModified(true); + net.minecraft.world.World nmsWorld = getParent().getWorld(); + try { + boolean flag = !nmsWorld.provider.getHasNoSky(); + // Sections + ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray(); + Map tiles = nmsChunk.getTileEntityMap(); + ClassInheritanceMultiMap[] entities = nmsChunk.getEntityLists(); + // Remove entities + for (int i = 0; i < 16; i++) { + int count = this.getCount(i); + if (count == 0) { + continue; + } else if (count >= 4096) { + entities[i] = new ClassInheritanceMultiMap<>(Entity.class); + } else { + char[] array = this.getIdArray(i); + Collection ents = new ArrayList<>(entities[i]); + for (Entity entity : ents) { + if (entity instanceof EntityPlayer) { + continue; + } + int x = ((int) Math.round(entity.posX) & 15); + int z = ((int) Math.round(entity.posZ) & 15); + int y = (int) Math.round(entity.posY); + if (array == null) { + continue; + } + if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) { + nmsWorld.removeEntity(entity); + } + } + } + } + // Set entities + Set createdEntities = new HashSet<>(); + Set entitiesToSpawn = this.getEntities(); + for (CompoundTag nativeTag : entitiesToSpawn) { + Map entityTagMap = 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(); + NBTTagCompound tag = (NBTTagCompound)ForgeQueue_All.methodFromNative.invoke(null, nativeTag); + Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld); + if (entity != null) { + entity.setPositionAndRotation(x, y, z, yaw, pitch); + nmsWorld.spawnEntityInWorld(entity); + } + } + // Run change task if applicable + if (getParent().getChangeTask() != null) { + CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false); + getParent().getChangeTask().run(previous, this); + } + // Trim tiles + Set> entryset = tiles.entrySet(); + Iterator> iterator = entryset.iterator(); + while (iterator.hasNext()) { + Map.Entry tile = iterator.next(); + BlockPos pos = tile.getKey(); + int lx = pos.getX() & 15; + int ly = pos.getY(); + int lz = pos.getZ() & 15; + int j = FaweCache.CACHE_I[ly][lz][lx]; + char[] array = this.getIdArray(j); + if (array == null) { + continue; + } + int k = FaweCache.CACHE_J[ly][lz][lx]; + if (array[k] != 0) { + tile.getValue().invalidate();; + iterator.remove(); + } + } + HashSet entsToRemove = this.getEntityRemoves(); + if (entsToRemove.size() > 0) { + for (int i = 0; i < entities.length; i++) { + Collection ents = new ArrayList<>(entities[i]); + for (Entity entity : ents) { + if (entsToRemove.contains(entity.getUniqueID())) { + nmsWorld.removeEntity(entity); + } + } + } + } + // Efficiently merge sections + for (int j = 0; j < sections.length; j++) { + int count = this.getCount(j); + if (count == 0) { + continue; + } + final char[] array = this.getIdArray(j); + if (array == null) { + continue; + } + ExtendedBlockStorage section = sections[j]; + if (section == null) { + if (this.sectionPalettes != null && this.sectionPalettes[j] != null) { + section = sections[j] = new ExtendedBlockStorage(j << 4, flag); + getParent().setPalette(section, this.sectionPalettes[j]); + getParent().setCount(0, count - this.getAir(j), section); + continue; + } else { + sections[j] = section = new ExtendedBlockStorage(j << 4, flag); + } + } else if (count >= 4096) { + if (this.sectionPalettes != null && this.sectionPalettes[j] != null) { + getParent().setPalette(section, this.sectionPalettes[j]); + getParent().setCount(0, count - this.getAir(j), section); + continue; + } else { + sections[j] = section = new ExtendedBlockStorage(j << 4, flag); + } + } + BlockStateContainer nibble = section.getData(); + int nonEmptyBlockCount = 0; + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + char combinedId = array[FaweCache.CACHE_J[y][z][x]]; + switch (combinedId) { + case 0: + IBlockState existing = nibble.get(x, y, z); + if (existing != ForgeQueue_All.air) { + nonEmptyBlockCount++; + } + continue; + case 1: + nibble.set(x, y, z, ForgeQueue_All.air); + continue; + default: + nonEmptyBlockCount++; + nibble.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF)); + } + } + } + } + getParent().setCount(0, nonEmptyBlockCount, section); + } + // Set biomes + int[][] biomes = this.biomes; + if (biomes != null) { + for (int x = 0; x < 16; x++) { + int[] array = biomes[x]; + if (array == null) { + continue; + } + for (int z = 0; z < 16; z++) { + int biome = array[z]; + if (biome == 0) { + continue; + } + nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; + } + } + } + // Set tiles + Map tilesToSpawn = this.getTiles(); + int bx = this.getX() << 4; + int bz = this.getZ() << 4; + + for (Map.Entry entry : tilesToSpawn.entrySet()) { + CompoundTag nativeTag = entry.getValue(); + BytePair pair = entry.getKey(); + BlockPos pos = new BlockPos(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos + TileEntity tileEntity = nmsWorld.getTileEntity(pos); + if (tileEntity != null) { + NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag); + tileEntity.readFromNBT(tag); // ReadTagIntoTile + } + } + } catch (Throwable e) { + MainUtil.handleError(e); + } + int[][] biomes = this.biomes; + if (biomes != null) { + for (int x = 0; x < 16; x++) { + int[] array = biomes[x]; + if (array == null) { + continue; + } + for (int z = 0; z < 16; z++) { + int biome = array[z]; + if (biome == 0) { + continue; + } + nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; + } + } + } + return this; + } } diff --git a/forge110/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java b/forge110/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java index 589d6626..7385874a 100644 --- a/forge110/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java +++ b/forge110/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java @@ -1,28 +1,21 @@ package com.boydti.fawe.forge.v0; -import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.example.CharFaweChunk; import com.boydti.fawe.example.NMSMappedFaweQueue; -import com.boydti.fawe.object.BytePair; import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.RunnableVal; 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.StringTag; import com.sk89q.jnbt.Tag; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayDeque; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -57,11 +50,20 @@ import net.minecraftforge.common.DimensionManager; public class ForgeQueue_All extends NMSMappedFaweQueue { - private static Method methodFromNative; - private static Method methodToNative; + protected static Method methodFromNative; + protected static Method methodToNative; public ForgeQueue_All(com.sk89q.worldedit.world.World world) { super(world); + init(); + } + + public ForgeQueue_All(String world) { + super(world); + init(); + } + + private void init() { if (methodFromNative == null) { try { Class converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter"); @@ -76,7 +78,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue changeTask) { - ForgeChunk_All fs = (ForgeChunk_All) fc; - net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk(); - nmsChunk.setModified(true); - net.minecraft.world.World nmsWorld = getWorld(); - try { - boolean flag = !nmsWorld.provider.getHasNoSky(); - // Sections - ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray(); - Map tiles = nmsChunk.getTileEntityMap(); - ClassInheritanceMultiMap[] entities = nmsChunk.getEntityLists(); - - - // Remove entities - for (int i = 0; i < 16; i++) { - int count = fs.getCount(i); - if (count == 0) { - continue; - } else if (count >= 4096) { - entities[i] = new ClassInheritanceMultiMap<>(Entity.class); - } else { - char[] array = fs.getIdArray(i); - Collection ents = new ArrayList<>(entities[i]); - for (Entity entity : ents) { - if (entity instanceof EntityPlayer) { - continue; - } - int x = ((int) Math.round(entity.posX) & 15); - int z = ((int) Math.round(entity.posZ) & 15); - int y = (int) Math.round(entity.posY); - if (array == null) { - continue; - } - if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) { - nmsWorld.removeEntity(entity); - } - } - } - } - // Set entities - Set createdEntities = new HashSet<>(); - Set entitiesToSpawn = fs.getEntities(); - for (CompoundTag nativeTag : entitiesToSpawn) { - Map entityTagMap = 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(); - NBTTagCompound tag = (NBTTagCompound)methodFromNative.invoke(null, nativeTag); - Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld); - if (entity != null) { - entity.setPositionAndRotation(x, y, z, yaw, pitch); - nmsWorld.spawnEntityInWorld(entity); - } - } - // Run change task if applicable - if (changeTask != null) { - CharFaweChunk previous = getPrevious(fs, sections, tiles, entities, createdEntities, false); - changeTask.run(previous); - } - // Trim tiles - Set> entryset = tiles.entrySet(); - Iterator> iterator = entryset.iterator(); - while (iterator.hasNext()) { - Map.Entry tile = iterator.next(); - BlockPos pos = tile.getKey(); - int lx = pos.getX() & 15; - int ly = pos.getY(); - int lz = pos.getZ() & 15; - int j = FaweCache.CACHE_I[ly][lz][lx]; - char[] array = fs.getIdArray(j); - if (array == null) { - continue; - } - int k = FaweCache.CACHE_J[ly][lz][lx]; - if (array[k] != 0) { - tile.getValue().invalidate();; - iterator.remove(); - } - } - HashSet entsToRemove = fs.getEntityRemoves(); - if (entsToRemove.size() > 0) { - for (int i = 0; i < entities.length; i++) { - Collection ents = new ArrayList<>(entities[i]); - for (Entity entity : ents) { - if (entsToRemove.contains(entity.getUniqueID())) { - nmsWorld.removeEntity(entity); - } - } - } - } - // Efficiently merge sections - for (int j = 0; j < sections.length; j++) { - int count = fs.getCount(j); - if (count == 0) { - continue; - } - final char[] array = fs.getIdArray(j); - if (array == null) { - continue; - } - ExtendedBlockStorage section = sections[j]; - if (section == null) { - if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) { - section = sections[j] = new ExtendedBlockStorage(j << 4, flag); - setPalette(section, fs.sectionPalettes[j]); - setCount(0, count - fs.getAir(j), section); - continue; - } else { - sections[j] = section = new ExtendedBlockStorage(j << 4, flag); - } - } else if (count >= 4096) { - if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) { - setPalette(section, fs.sectionPalettes[j]); - setCount(0, count - fs.getAir(j), section); - continue; - } else { - sections[j] = section = new ExtendedBlockStorage(j << 4, flag); - } - } - BlockStateContainer nibble = section.getData(); - int nonEmptyBlockCount = 0; - for (int y = 0; y < 16; y++) { - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++) { - char combinedId = array[FaweCache.CACHE_J[y][z][x]]; - switch (combinedId) { - case 0: - IBlockState existing = nibble.get(x, y, z); - if (existing != air) { - nonEmptyBlockCount++; - } - continue; - case 1: - nibble.set(x, y, z, air); - continue; - default: - nonEmptyBlockCount++; - nibble.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF)); - } - } - } - } - setCount(0, nonEmptyBlockCount, section); - } - // Set biomes - int[][] biomes = fs.biomes; - if (biomes != null) { - for (int x = 0; x < 16; x++) { - int[] array = biomes[x]; - if (array == null) { - continue; - } - for (int z = 0; z < 16; z++) { - int biome = array[z]; - if (biome == 0) { - continue; - } - nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; - } - } - } - // Set tiles - Map tilesToSpawn = fs.getTiles(); - int bx = fs.getX() << 4; - int bz = fs.getZ() << 4; - - for (Map.Entry entry : tilesToSpawn.entrySet()) { - CompoundTag nativeTag = entry.getValue(); - BytePair pair = entry.getKey(); - BlockPos pos = new BlockPos(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos - TileEntity tileEntity = nmsWorld.getTileEntity(pos); - if (tileEntity != null) { - NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(null, nativeTag); - tileEntity.readFromNBT(tag); // ReadTagIntoTile - } - } - } catch (Throwable e) { - MainUtil.handleError(e); - } - int[][] biomes = fs.biomes; - if (biomes != null) { - for (int x = 0; x < 16; x++) { - int[] array = biomes[x]; - if (array == null) { - continue; - } - for (int z = 0; z < 16; z++) { - int biome = array[z]; - if (biome == 0) { - continue; - } - nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; - } - } - } - return true; - } + protected final static IBlockState air = Blocks.AIR.getDefaultState(); public void setPalette(ExtendedBlockStorage section, BlockStateContainer palette) throws NoSuchFieldException, IllegalAccessException { Field fieldSection = ExtendedBlockStorage.class.getDeclaredField("data"); @@ -604,7 +397,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue getMaskManagers() { return new ArrayList<>(); diff --git a/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java b/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java index 30b28844..187034a9 100644 --- a/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java +++ b/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java @@ -1,14 +1,36 @@ package com.boydti.fawe.forge.v0; +import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.example.CharFaweChunk; +import com.boydti.fawe.object.BytePair; import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.util.MainUtil; +import com.boydti.fawe.util.MathMan; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.ListTag; +import com.sk89q.jnbt.StringTag; +import com.sk89q.jnbt.Tag; +import java.util.ArrayList; +import java.util.Collection; +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 net.minecraft.entity.Entity; +import net.minecraft.entity.EntityList; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.ChunkPosition; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.NibbleArray; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; -public class ForgeChunk_All extends CharFaweChunk { +public class ForgeChunk_All extends CharFaweChunk { public byte[][] byteIds; public NibbleArray[] datas; @@ -83,7 +105,7 @@ public class ForgeChunk_All extends CharFaweChunk { } @Override - public CharFaweChunk copy(boolean shallow) { + public ForgeChunk_All copy(boolean shallow) { ForgeChunk_All copy = new ForgeChunk_All(getParent(), getX(), getZ()); if (shallow) { copy.byteIds = byteIds; @@ -104,4 +126,229 @@ public class ForgeChunk_All extends CharFaweChunk { } return copy; } + + @Override + public ForgeChunk_All call() { + net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk(); + net.minecraft.world.World nmsWorld = nmsChunk.worldObj; + nmsChunk.setChunkModified(); + nmsChunk.sendUpdates = true; + try { + boolean flag = !nmsWorld.provider.hasNoSky; + // Sections + ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray(); + Map tiles = nmsChunk.chunkTileEntityMap; + List[] entities = nmsChunk.entityLists; + + // Remove entities + for (int i = 0; i < 16; i++) { + int count = this.getCount(i); + if (count == 0) { + continue; + } else if (count >= 4096) { + entities[i].clear(); + } else { + char[] array = this.getIdArray(i); + Collection ents = new ArrayList<>(entities[i]); + for (Entity entity : ents) { + if (entity instanceof EntityPlayer) { + continue; + } + int x = ((int) Math.round(entity.posX) & 15); + int z = ((int) Math.round(entity.posZ) & 15); + int y = (int) Math.round(entity.posY); + if (array == null) { + continue; + } + if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) { + nmsWorld.removeEntity(entity); + } + } + } + } + // Set entities + Set createdEntities = new HashSet<>(); + Set entitiesToSpawn = this.getEntities(); + for (CompoundTag nativeTag : entitiesToSpawn) { + Map entityTagMap = 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(); + NBTTagCompound tag = (NBTTagCompound)ForgeQueue_All.methodFromNative.invoke(null, nativeTag); + Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld); + if (entity != null) { + entity.setPositionAndRotation(x, y, z, yaw, pitch); + nmsWorld.spawnEntityInWorld(entity); + } + } + // Run change task if applicable + if (getParent().getChangeTask() != null) { + CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false); + getParent().getChangeTask().run(previous, this); + } + // Trim tiles + Set> entryset = tiles.entrySet(); + Iterator> iterator = entryset.iterator(); + while (iterator.hasNext()) { + Map.Entry tile = iterator.next(); + ChunkPosition pos = tile.getKey(); + int lx = pos.chunkPosX & 15; + int ly = pos.chunkPosY; + int lz = pos.chunkPosZ & 15; + int j = FaweCache.CACHE_I[ly][lz][lx]; + char[] array = this.getIdArray(j); + if (array == null) { + continue; + } + int k = FaweCache.CACHE_J[ly][lz][lx]; + if (array[k] != 0) { + tile.getValue().invalidate();; + iterator.remove(); + } + } + HashSet entsToRemove = this.getEntityRemoves(); + if (entsToRemove.size() > 0) { + for (int i = 0; i < entities.length; i++) { + Collection ents = new ArrayList<>(entities[i]); + for (Entity entity : ents) { + if (entsToRemove.contains(entity.getUniqueID())) { + nmsWorld.removeEntity(entity); + } + } + } + } + // Efficiently merge sections + for (int j = 0; j < sections.length; j++) { + if (this.getCount(j) == 0) { + continue; + } + byte[] newIdArray = this.getByteIdArray(j); + if (newIdArray == null) { + continue; + } + NibbleArray newDataArray = this.getDataArray(j); + ExtendedBlockStorage section = sections[j]; + if ((section == null) || (this.getCount(j) >= 4096)) { + sections[j] = section = new ExtendedBlockStorage(j << 4, !getParent().getWorld().provider.hasNoSky); + section.setBlockLSBArray(newIdArray); + section.setBlockMetadataArray(newDataArray); + continue; + } + byte[] currentIdArray = section.getBlockLSBArray(); + NibbleArray currentDataArray = section.getMetadataArray(); + boolean data = currentDataArray != null; + if (!data) { + section.setBlockMetadataArray(newDataArray); + } + boolean fill = true; + int solid = 0; + char[] charArray = this.getIdArray(j); + for (int k = 0; k < newIdArray.length; k++) { + char combined = charArray[k]; + switch (combined) { + case 0: + fill = false; + continue; + case 1: + fill = false; + if (currentIdArray[k] != 0) { + solid++; + } + currentIdArray[k] = 0; + continue; + default: + solid++; + currentIdArray[k] = newIdArray[k]; + if (data) { + int dataByte = FaweCache.getData(combined); + int x = FaweCache.CACHE_X[0][k]; + int y = FaweCache.CACHE_Y[0][k]; + int z = FaweCache.CACHE_Z[0][k]; + int newData = newDataArray.get(x, y, z); + currentDataArray.set(x, y, z, newData); + } + continue; + } + } + getParent().setCount(0, solid, section); + if (fill) { + this.setCount(j, Short.MAX_VALUE); + } + } + + // Set biomes + int[][] biomes = this.biomes; + if (biomes != null) { + for (int x = 0; x < 16; x++) { + int[] array = biomes[x]; + if (array == null) { + continue; + } + for (int z = 0; z < 16; z++) { + int biome = array[z]; + if (biome == 0) { + continue; + } + nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; + } + } + } + // Set tiles + Map tilesToSpawn = this.getTiles(); + int bx = this.getX() << 4; + int bz = this.getZ() << 4; + + for (Map.Entry entry : tilesToSpawn.entrySet()) { + CompoundTag nativeTag = entry.getValue(); + BytePair pair = entry.getKey(); + int x = MathMan.unpair16x((byte) pair.get0()) + bx; + int y = pair.get1() & 0xFF; + int z = MathMan.unpair16y((byte) pair.get0()) + bz; + TileEntity tileEntity = nmsWorld.getTileEntity(x, y, z); + if (tileEntity != null) { + NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag); + tileEntity.readFromNBT(tag); // ReadTagIntoTile + } + } + } catch (Throwable e) { + MainUtil.handleError(e); + } + int[][] biomes = this.biomes; + if (biomes != null) { + for (int x = 0; x < 16; x++) { + int[] array = biomes[x]; + if (array == null) { + continue; + } + for (int z = 0; z < 16; z++) { + int biome = array[z]; + if (biome == 0) { + continue; + } + nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; + } + } + } + return this; + } + + public boolean hasEntities(Chunk nmsChunk) { + for (int i = 0; i < nmsChunk.entityLists.length; i++) { + List slice = nmsChunk.entityLists[i]; + if (slice != null && !slice.isEmpty()) { + return true; + } + } + return false; + } } diff --git a/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java b/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java index 7a33470c..c2a783ec 100644 --- a/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java +++ b/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java @@ -1,10 +1,8 @@ package com.boydti.fawe.forge.v0; -import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.example.CharFaweChunk; import com.boydti.fawe.example.NMSMappedFaweQueue; -import com.boydti.fawe.object.BytePair; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.IntegerPair; import com.boydti.fawe.object.RunnableVal; @@ -12,17 +10,14 @@ 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.StringTag; import com.sk89q.jnbt.Tag; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -52,11 +47,20 @@ import net.minecraftforge.common.DimensionManager; public class ForgeQueue_All extends NMSMappedFaweQueue { - private static Method methodFromNative; - private static Method methodToNative; + protected static Method methodFromNative; + protected static Method methodToNative; public ForgeQueue_All(com.sk89q.worldedit.world.World world) { super(world); + init(); + } + + public ForgeQueue_All(String world) { + super(world); + init(); + } + + private void init() { if (methodFromNative == null) { try { Class converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter"); @@ -199,7 +203,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue loadChunk = new RunnableVal() { + protected final RunnableVal loadChunk = new RunnableVal() { @Override public void run(IntegerPair loc) { Chunk chunk = getWorld().getChunkProvider().provideChunk(loc.x, loc.z); @@ -264,223 +268,6 @@ public class ForgeQueue_All extends NMSMappedFaweQueue changeTask) { - ForgeChunk_All fs = (ForgeChunk_All) fc; - net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk(); - net.minecraft.world.World nmsWorld = nmsChunk.worldObj; - nmsChunk.setChunkModified(); - nmsChunk.sendUpdates = true; - try { - boolean flag = !nmsWorld.provider.hasNoSky; - // Sections - ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray(); - Map tiles = nmsChunk.chunkTileEntityMap; - List[] entities = nmsChunk.entityLists; - - // Remove entities - for (int i = 0; i < 16; i++) { - int count = fs.getCount(i); - if (count == 0) { - continue; - } else if (count >= 4096) { - entities[i].clear(); - } else { - char[] array = fs.getIdArray(i); - Collection ents = new ArrayList<>(entities[i]); - for (Entity entity : ents) { - if (entity instanceof EntityPlayer) { - continue; - } - int x = ((int) Math.round(entity.posX) & 15); - int z = ((int) Math.round(entity.posZ) & 15); - int y = (int) Math.round(entity.posY); - if (array == null) { - continue; - } - if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) { - nmsWorld.removeEntity(entity); - } - } - } - } - // Set entities - Set createdEntities = new HashSet<>(); - Set entitiesToSpawn = fs.getEntities(); - for (CompoundTag nativeTag : entitiesToSpawn) { - Map entityTagMap = 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(); - NBTTagCompound tag = (NBTTagCompound)methodFromNative.invoke(null, nativeTag); - Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld); - if (entity != null) { - entity.setPositionAndRotation(x, y, z, yaw, pitch); - nmsWorld.spawnEntityInWorld(entity); - } - } - // Run change task if applicable - if (changeTask != null) { - CharFaweChunk previous = getPrevious(fs, sections, tiles, entities, createdEntities, false); - changeTask.run(previous); - } - // Trim tiles - Set> entryset = tiles.entrySet(); - Iterator> iterator = entryset.iterator(); - while (iterator.hasNext()) { - Map.Entry tile = iterator.next(); - ChunkPosition pos = tile.getKey(); - int lx = pos.chunkPosX & 15; - int ly = pos.chunkPosY; - int lz = pos.chunkPosZ & 15; - int j = FaweCache.CACHE_I[ly][lz][lx]; - char[] array = fs.getIdArray(j); - if (array == null) { - continue; - } - int k = FaweCache.CACHE_J[ly][lz][lx]; - if (array[k] != 0) { - tile.getValue().invalidate();; - iterator.remove(); - } - } - HashSet entsToRemove = fs.getEntityRemoves(); - if (entsToRemove.size() > 0) { - for (int i = 0; i < entities.length; i++) { - Collection ents = new ArrayList<>(entities[i]); - for (Entity entity : ents) { - if (entsToRemove.contains(entity.getUniqueID())) { - nmsWorld.removeEntity(entity); - } - } - } - } - // Efficiently merge sections - for (int j = 0; j < sections.length; j++) { - if (fs.getCount(j) == 0) { - continue; - } - byte[] newIdArray = fs.getByteIdArray(j); - if (newIdArray == null) { - continue; - } - NibbleArray newDataArray = fs.getDataArray(j); - ExtendedBlockStorage section = sections[j]; - if ((section == null) || (fs.getCount(j) >= 4096)) { - sections[j] = section = new ExtendedBlockStorage(j << 4, !getWorld().provider.hasNoSky); - section.setBlockLSBArray(newIdArray); - section.setBlockMetadataArray(newDataArray); - continue; - } - byte[] currentIdArray = section.getBlockLSBArray(); - NibbleArray currentDataArray = section.getMetadataArray(); - boolean data = currentDataArray != null; - if (!data) { - section.setBlockMetadataArray(newDataArray); - } - boolean fill = true; - int solid = 0; - char[] charArray = fs.getIdArray(j); - for (int k = 0; k < newIdArray.length; k++) { - char combined = charArray[k]; - switch (combined) { - case 0: - fill = false; - continue; - case 1: - fill = false; - if (currentIdArray[k] != 0) { - solid++; - } - currentIdArray[k] = 0; - continue; - default: - solid++; - currentIdArray[k] = newIdArray[k]; - if (data) { - int dataByte = FaweCache.getData(combined); - int x = FaweCache.CACHE_X[0][k]; - int y = FaweCache.CACHE_Y[0][k]; - int z = FaweCache.CACHE_Z[0][k]; - int newData = newDataArray.get(x, y, z); - currentDataArray.set(x, y, z, newData); - } - continue; - } - } - setCount(0, solid, section); - if (fill) { - fs.setCount(j, Short.MAX_VALUE); - } - } - - // Set biomes - int[][] biomes = fs.biomes; - if (biomes != null) { - for (int x = 0; x < 16; x++) { - int[] array = biomes[x]; - if (array == null) { - continue; - } - for (int z = 0; z < 16; z++) { - int biome = array[z]; - if (biome == 0) { - continue; - } - nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; - } - } - } - // Set tiles - Map tilesToSpawn = fs.getTiles(); - int bx = fs.getX() << 4; - int bz = fs.getZ() << 4; - - for (Map.Entry entry : tilesToSpawn.entrySet()) { - CompoundTag nativeTag = entry.getValue(); - BytePair pair = entry.getKey(); - int x = MathMan.unpair16x((byte) pair.get0()) + bx; - int y = pair.get1() & 0xFF; - int z = MathMan.unpair16y((byte) pair.get0()) + bz; - TileEntity tileEntity = nmsWorld.getTileEntity(x, y, z); - if (tileEntity != null) { - NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(null, nativeTag); - tileEntity.readFromNBT(tag); // ReadTagIntoTile - } - } - } catch (Throwable e) { - MainUtil.handleError(e); - } - int[][] biomes = fs.biomes; - if (biomes != null) { - for (int x = 0; x < 16; x++) { - int[] array = biomes[x]; - if (array == null) { - continue; - } - for (int z = 0; z < 16; z++) { - int biome = array[z]; - if (biome == 0) { - continue; - } - nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; - } - } - } - return true; - } - public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException { Class clazz = section.getClass(); Field fieldTickingBlockCount = clazz.getDeclaredField("field_76683_c"); // tickRefCount @@ -599,7 +386,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue getMaskManagers() { return new ArrayList<>(); diff --git a/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java b/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java index c80186b6..0c76e114 100644 --- a/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java +++ b/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java @@ -1,11 +1,35 @@ package com.boydti.fawe.forge.v0; +import com.boydti.fawe.Fawe; +import com.boydti.fawe.FaweCache; import com.boydti.fawe.example.CharFaweChunk; +import com.boydti.fawe.object.BytePair; import com.boydti.fawe.object.FaweQueue; +import com.boydti.fawe.util.MainUtil; +import com.boydti.fawe.util.MathMan; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.ListTag; +import com.sk89q.jnbt.StringTag; +import com.sk89q.jnbt.Tag; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityList; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ClassInheritanceMultiMap; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; -public class ForgeChunk_All extends CharFaweChunk { +public class ForgeChunk_All extends CharFaweChunk { /** * A FaweSections object represents a chunk and the blocks that you wish to change in it. * @@ -22,4 +46,209 @@ public class ForgeChunk_All extends CharFaweChunk { World world = ((ForgeQueue_All) getParent()).getWorld(); return world.getChunkProvider().provideChunk(getX(), getZ()); } + + @Override + public ForgeChunk_All call() { + net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk(); + nmsChunk.setModified(true); + nmsChunk.setHasEntities(true); + net.minecraft.world.World nmsWorld = nmsChunk.getWorld(); + try { + boolean flag = !nmsWorld.provider.getHasNoSky(); + // Sections + ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray(); + Map tiles = nmsChunk.getTileEntityMap(); + ClassInheritanceMultiMap[] entities = nmsChunk.getEntityLists(); + + + // Remove entities + for (int i = 0; i < 16; i++) { + int count = this.getCount(i); + if (count == 0) { + continue; + } else if (count >= 4096) { + entities[i] = new ClassInheritanceMultiMap<>(Entity.class); + } else { + char[] array = this.getIdArray(i); + Collection ents = new ArrayList<>(entities[i]); + for (Entity entity : ents) { + if (entity instanceof EntityPlayer) { + continue; + } + int x = ((int) Math.round(entity.posX) & 15); + int z = ((int) Math.round(entity.posZ) & 15); + int y = (int) Math.round(entity.posY); + if (array == null) { + continue; + } + if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) { + nmsWorld.removeEntity(entity); + } + } + } + } + // Set entities + Set createdEntities = new HashSet<>(); + Set entitiesToSpawn = this.getEntities(); + for (CompoundTag nativeTag : entitiesToSpawn) { + Map entityTagMap = 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(); + NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag); + Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld); + if (entity != null) { + entity.setPositionAndRotation(x, y, z, yaw, pitch); + nmsWorld.spawnEntityInWorld(entity); + } + } + // Run change task if applicable + if (getParent().getChangeTask() != null) { + CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false); + getParent().getChangeTask().run(previous, this); + } + // Trim tiles + Set> entryset = tiles.entrySet(); + Iterator> iterator = entryset.iterator(); + while (iterator.hasNext()) { + Map.Entry tile = iterator.next(); + BlockPos pos = tile.getKey(); + int lx = pos.getX() & 15; + int ly = pos.getY(); + int lz = pos.getZ() & 15; + int j = FaweCache.CACHE_I[ly][lz][lx]; + char[] array = this.getIdArray(j); + if (array == null) { + continue; + } + int k = FaweCache.CACHE_J[ly][lz][lx]; + if (array[k] != 0) { + tile.getValue().invalidate();; + iterator.remove(); + } + } + HashSet entsToRemove = this.getEntityRemoves(); + if (entsToRemove.size() > 0) { + for (int i = 0; i < entities.length; i++) { + Collection ents = new ArrayList<>(entities[i]); + for (Entity entity : ents) { + if (entsToRemove.contains(entity.getUniqueID())) { + nmsWorld.removeEntity(entity); + } + } + } + } + // Efficiently merge sections + for (int j = 0; j < sections.length; j++) { + int count = this.getCount(j); + if (count == 0) { + continue; + } + char[] newArray = this.getIdArray(j); + if (newArray == null) { + continue; + } + ExtendedBlockStorage section = sections[j]; + + if ((section == null)) { + section = new ExtendedBlockStorage(j << 4, flag); + section.setData(newArray); + sections[j] = section; + continue; + } else if (count >= 4096){ + section.setData(newArray); + getParent().setCount(0, count - this.getAir(j), section); + continue; + } + char[] currentArray = section.getData(); + boolean fill = true; + int solid = 0; + for (int k = 0; k < newArray.length; k++) { + char n = newArray[k]; + switch (n) { + case 0: + fill = false; + continue; + case 1: + fill = false; + if (currentArray[k] > 1) { + solid++; + } + currentArray[k] = 0; + continue; + default: + solid++; + currentArray[k] = n; + continue; + } + } + getParent().setCount(0, solid, section); + if (fill) { + this.setCount(j, Short.MAX_VALUE); + } + } + + // Set biomes + int[][] biomes = this.biomes; + if (biomes != null) { + for (int x = 0; x < 16; x++) { + int[] array = biomes[x]; + if (array == null) { + continue; + } + for (int z = 0; z < 16; z++) { + int biome = array[z]; + if (biome == 0) { + continue; + } + nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; + } + } + } + // Set tiles + Map tilesToSpawn = this.getTiles(); + int bx = this.getX() << 4; + int bz = this.getZ() << 4; + + for (Map.Entry entry : tilesToSpawn.entrySet()) { + CompoundTag nativeTag = entry.getValue(); + BytePair pair = entry.getKey(); + BlockPos pos = new BlockPos(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos + TileEntity tileEntity = nmsWorld.getTileEntity(pos); + if (tileEntity != null) { + NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag); + tileEntity.readFromNBT(tag); // ReadTagIntoTile + } + } + } catch (Throwable e) { + MainUtil.handleError(e); + } + int[][] biomes = this.biomes; + if (biomes != null) { + for (int x = 0; x < 16; x++) { + int[] array = biomes[x]; + if (array == null) { + continue; + } + for (int z = 0; z < 16; z++) { + int biome = array[z]; + if (biome == 0) { + continue; + } + nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; + } + } + } + return this; + } } diff --git a/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java b/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java index 4837ba52..0b6a50f2 100644 --- a/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java +++ b/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java @@ -1,27 +1,21 @@ package com.boydti.fawe.forge.v0; -import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.example.CharFaweChunk; import com.boydti.fawe.example.NMSMappedFaweQueue; -import com.boydti.fawe.object.BytePair; import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.RunnableVal; 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.StringTag; import com.sk89q.jnbt.Tag; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; -import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -50,11 +44,20 @@ import net.minecraftforge.common.DimensionManager; public class ForgeQueue_All extends NMSMappedFaweQueue { - private static Method methodFromNative; - private static Method methodToNative; + protected static Method methodFromNative; + protected static Method methodToNative; public ForgeQueue_All(com.sk89q.worldedit.world.World world) { super(world); + init(); + } + + public ForgeQueue_All(String world) { + super(world); + init(); + } + + private void init() { if (methodFromNative == null) { try { Class converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter"); @@ -69,7 +72,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue changeTask) { - CharFaweChunk fs = (CharFaweChunk) fc; - net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk(); - nmsChunk.setModified(true); - nmsChunk.setHasEntities(true); - net.minecraft.world.World nmsWorld = nmsChunk.getWorld(); - try { - boolean flag = !nmsWorld.provider.getHasNoSky(); - // Sections - ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray(); - Map tiles = nmsChunk.getTileEntityMap(); - ClassInheritanceMultiMap[] entities = nmsChunk.getEntityLists(); - - - // Remove entities - for (int i = 0; i < 16; i++) { - int count = fs.getCount(i); - if (count == 0) { - continue; - } else if (count >= 4096) { - entities[i] = new ClassInheritanceMultiMap<>(Entity.class); - } else { - char[] array = fs.getIdArray(i); - Collection ents = new ArrayList<>(entities[i]); - for (Entity entity : ents) { - if (entity instanceof EntityPlayer) { - continue; - } - int x = ((int) Math.round(entity.posX) & 15); - int z = ((int) Math.round(entity.posZ) & 15); - int y = (int) Math.round(entity.posY); - if (array == null) { - continue; - } - if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) { - nmsWorld.removeEntity(entity); - } - } - } - } - // Set entities - Set createdEntities = new HashSet<>(); - Set entitiesToSpawn = fs.getEntities(); - for (CompoundTag nativeTag : entitiesToSpawn) { - Map entityTagMap = 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(); - NBTTagCompound tag = (NBTTagCompound)methodFromNative.invoke(null, nativeTag); - Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld); - if (entity != null) { - entity.setPositionAndRotation(x, y, z, yaw, pitch); - nmsWorld.spawnEntityInWorld(entity); - } - } - // Run change task if applicable - if (changeTask != null) { - CharFaweChunk previous = getPrevious(fs, sections, tiles, entities, createdEntities, false); - changeTask.run(previous); - } - // Trim tiles - Set> entryset = tiles.entrySet(); - Iterator> iterator = entryset.iterator(); - while (iterator.hasNext()) { - Map.Entry tile = iterator.next(); - BlockPos pos = tile.getKey(); - int lx = pos.getX() & 15; - int ly = pos.getY(); - int lz = pos.getZ() & 15; - int j = FaweCache.CACHE_I[ly][lz][lx]; - char[] array = fs.getIdArray(j); - if (array == null) { - continue; - } - int k = FaweCache.CACHE_J[ly][lz][lx]; - if (array[k] != 0) { - tile.getValue().invalidate();; - iterator.remove(); - } - } - HashSet entsToRemove = fs.getEntityRemoves(); - if (entsToRemove.size() > 0) { - for (int i = 0; i < entities.length; i++) { - Collection ents = new ArrayList<>(entities[i]); - for (Entity entity : ents) { - if (entsToRemove.contains(entity.getUniqueID())) { - nmsWorld.removeEntity(entity); - } - } - } - } - // Efficiently merge sections - for (int j = 0; j < sections.length; j++) { - int count = fs.getCount(j); - if (count == 0) { - continue; - } - char[] newArray = fs.getIdArray(j); - if (newArray == null) { - continue; - } - ExtendedBlockStorage section = sections[j]; - - if ((section == null)) { - section = new ExtendedBlockStorage(j << 4, flag); - section.setData(newArray); - sections[j] = section; - continue; - } else if (count >= 4096){ - section.setData(newArray); - setCount(0, count - fs.getAir(j), section); - continue; - } - char[] currentArray = section.getData(); - boolean fill = true; - int solid = 0; - for (int k = 0; k < newArray.length; k++) { - char n = newArray[k]; - switch (n) { - case 0: - fill = false; - continue; - case 1: - fill = false; - if (currentArray[k] > 1) { - solid++; - } - currentArray[k] = 0; - continue; - default: - solid++; - currentArray[k] = n; - continue; - } - } - setCount(0, solid, section); - if (fill) { - fs.setCount(j, Short.MAX_VALUE); - } - } - - // Set biomes - int[][] biomes = fs.biomes; - if (biomes != null) { - for (int x = 0; x < 16; x++) { - int[] array = biomes[x]; - if (array == null) { - continue; - } - for (int z = 0; z < 16; z++) { - int biome = array[z]; - if (biome == 0) { - continue; - } - nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; - } - } - } - // Set tiles - Map tilesToSpawn = fs.getTiles(); - int bx = fs.getX() << 4; - int bz = fs.getZ() << 4; - - for (Map.Entry entry : tilesToSpawn.entrySet()) { - CompoundTag nativeTag = entry.getValue(); - BytePair pair = entry.getKey(); - BlockPos pos = new BlockPos(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos - TileEntity tileEntity = nmsWorld.getTileEntity(pos); - if (tileEntity != null) { - NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(null, nativeTag); - tileEntity.readFromNBT(tag); // ReadTagIntoTile - } - } - } catch (Throwable e) { - MainUtil.handleError(e); - } - int[][] biomes = fs.biomes; - if (biomes != null) { - for (int x = 0; x < 16; x++) { - int[] array = biomes[x]; - if (array == null) { - continue; - } - for (int z = 0; z < 16; z++) { - int biome = array[z]; - if (biome == 0) { - continue; - } - nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; - } - } - } - return true; - } - @Override public void refreshChunk(FaweChunk fc) { ForgeChunk_All fs = (ForgeChunk_All) fc; @@ -563,7 +360,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue getMaskManagers() { return new ArrayList<>(); diff --git a/forge194/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java b/forge194/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java index e4a28530..ff3daf0f 100644 --- a/forge194/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java +++ b/forge194/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java @@ -1,19 +1,42 @@ package com.boydti.fawe.forge.v0; +import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.example.CharFaweChunk; +import com.boydti.fawe.object.BytePair; import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.util.MainUtil; +import com.boydti.fawe.util.MathMan; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.ListTag; +import com.sk89q.jnbt.StringTag; +import com.sk89q.jnbt.Tag; import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.UUID; import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityList; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.BitArray; +import net.minecraft.util.ClassInheritanceMultiMap; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.chunk.BlockStateContainer; import net.minecraft.world.chunk.BlockStatePaletteRegistry; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.IBlockStatePalette; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; -public class ForgeChunk_All extends CharFaweChunk { +public class ForgeChunk_All extends CharFaweChunk { public BlockStateContainer[] sectionPalettes; @@ -35,7 +58,7 @@ public class ForgeChunk_All extends CharFaweChunk { } @Override - public CharFaweChunk copy(boolean shallow) { + public ForgeChunk_All copy(boolean shallow) { ForgeChunk_All value = (ForgeChunk_All) super.copy(shallow); if (sectionPalettes != null) { value.sectionPalettes = new BlockStateContainer[16]; @@ -111,4 +134,212 @@ public class ForgeChunk_All extends CharFaweChunk { } } } + + @Override + public ForgeChunk_All call() { + net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk(); + nmsChunk.setModified(true); + net.minecraft.world.World nmsWorld = nmsChunk.getWorld(); + try { + boolean flag = !nmsWorld.provider.getHasNoSky(); + // Sections + ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray(); + Map tiles = nmsChunk.getTileEntityMap(); + ClassInheritanceMultiMap[] entities = nmsChunk.getEntityLists(); + + + // Remove entities + for (int i = 0; i < 16; i++) { + int count = this.getCount(i); + if (count == 0) { + continue; + } else if (count >= 4096) { + entities[i] = new ClassInheritanceMultiMap<>(Entity.class); + } else { + char[] array = this.getIdArray(i); + Collection ents = new ArrayList<>(entities[i]); + for (Entity entity : ents) { + if (entity instanceof EntityPlayer) { + continue; + } + int x = ((int) Math.round(entity.posX) & 15); + int z = ((int) Math.round(entity.posZ) & 15); + int y = (int) Math.round(entity.posY); + if (array == null) { + continue; + } + if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) { + nmsWorld.removeEntity(entity); + } + } + } + } + // Set entities + Set createdEntities = new HashSet<>(); + Set entitiesToSpawn = this.getEntities(); + for (CompoundTag nativeTag : entitiesToSpawn) { + Map entityTagMap = 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(); + NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag); + Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld); + if (entity != null) { + entity.setPositionAndRotation(x, y, z, yaw, pitch); + nmsWorld.spawnEntityInWorld(entity); + } + } + // Run change task if applicable + if (getParent().getChangeTask() != null) { + CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false); + getParent().getChangeTask().run(previous, this); + } + // Trim tiles + Set> entryset = tiles.entrySet(); + Iterator> iterator = entryset.iterator(); + while (iterator.hasNext()) { + Map.Entry tile = iterator.next(); + BlockPos pos = tile.getKey(); + int lx = pos.getX() & 15; + int ly = pos.getY(); + int lz = pos.getZ() & 15; + int j = FaweCache.CACHE_I[ly][lz][lx]; + char[] array = this.getIdArray(j); + if (array == null) { + continue; + } + int k = FaweCache.CACHE_J[ly][lz][lx]; + if (array[k] != 0) { + tile.getValue().invalidate();; + iterator.remove(); + } + } + HashSet entsToRemove = this.getEntityRemoves(); + if (entsToRemove.size() > 0) { + for (int i = 0; i < entities.length; i++) { + Collection ents = new ArrayList<>(entities[i]); + for (Entity entity : ents) { + if (entsToRemove.contains(entity.getUniqueID())) { + nmsWorld.removeEntity(entity); + } + } + } + } + // Efficiently merge sections + for (int j = 0; j < sections.length; j++) { + int count = this.getCount(j); + if (count == 0) { + continue; + } + final char[] array = this.getIdArray(j); + if (array == null) { + continue; + } + ExtendedBlockStorage section = sections[j]; + if (section == null) { + if (this.sectionPalettes != null && this.sectionPalettes[j] != null) { + section = sections[j] = new ExtendedBlockStorage(j << 4, flag); + getParent().setPalette(section, this.sectionPalettes[j]); + getParent().setCount(0, count - this.getAir(j), section); + continue; + } else { + sections[j] = section = new ExtendedBlockStorage(j << 4, flag); + } + } else if (count >= 4096) { + if (this.sectionPalettes != null && this.sectionPalettes[j] != null) { + getParent().setPalette(section, this.sectionPalettes[j]); + getParent().setCount(0, count - this.getAir(j), section); + continue; + } else { + sections[j] = section = new ExtendedBlockStorage(j << 4, flag); + } + } + BlockStateContainer nibble = section.getData(); + int nonEmptyBlockCount = 0; + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + char combinedId = array[FaweCache.CACHE_J[y][z][x]]; + switch (combinedId) { + case 0: + IBlockState existing = nibble.get(x, y, z); + if (existing != ForgeQueue_All.air) { + nonEmptyBlockCount++; + } + continue; + case 1: + nibble.set(x, y, z, ForgeQueue_All.air); + continue; + default: + nonEmptyBlockCount++; + nibble.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF)); + } + } + } + } + getParent().setCount(0, nonEmptyBlockCount, section); + } + // Set biomes + int[][] biomes = this.biomes; + if (biomes != null) { + for (int x = 0; x < 16; x++) { + int[] array = biomes[x]; + if (array == null) { + continue; + } + for (int z = 0; z < 16; z++) { + int biome = array[z]; + if (biome == 0) { + continue; + } + nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; + } + } + } + // Set tiles + Map tilesToSpawn = this.getTiles(); + int bx = this.getX() << 4; + int bz = this.getZ() << 4; + + for (Map.Entry entry : tilesToSpawn.entrySet()) { + CompoundTag nativeTag = entry.getValue(); + BytePair pair = entry.getKey(); + BlockPos pos = new BlockPos(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos + TileEntity tileEntity = nmsWorld.getTileEntity(pos); + if (tileEntity != null) { + NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag); + tileEntity.readFromNBT(tag); // ReadTagIntoTile + } + } + } catch (Throwable e) { + MainUtil.handleError(e); + } + int[][] biomes = this.biomes; + if (biomes != null) { + for (int x = 0; x < 16; x++) { + int[] array = biomes[x]; + if (array == null) { + continue; + } + for (int z = 0; z < 16; z++) { + int biome = array[z]; + if (biome == 0) { + continue; + } + nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; + } + } + } + return this; + } } diff --git a/forge194/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java b/forge194/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java index 692d877e..a9ffec35 100644 --- a/forge194/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java +++ b/forge194/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java @@ -1,28 +1,21 @@ package com.boydti.fawe.forge.v0; -import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.example.CharFaweChunk; import com.boydti.fawe.example.NMSMappedFaweQueue; -import com.boydti.fawe.object.BytePair; import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.RunnableVal; 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.StringTag; import com.sk89q.jnbt.Tag; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayDeque; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -57,11 +50,20 @@ import net.minecraftforge.common.DimensionManager; public class ForgeQueue_All extends NMSMappedFaweQueue { - private static Method methodFromNative; - private static Method methodToNative; + protected static Method methodFromNative; + protected static Method methodToNative; public ForgeQueue_All(com.sk89q.worldedit.world.World world) { super(world); + init(); + } + + public ForgeQueue_All(String world) { + super(world); + init(); + } + + private void init() { if (methodFromNative == null) { try { Class converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter"); @@ -76,7 +78,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue changeTask) { - ForgeChunk_All fs = (ForgeChunk_All) fc; - net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk(); - nmsChunk.setModified(true); - net.minecraft.world.World nmsWorld = nmsChunk.getWorld(); - try { - boolean flag = !nmsWorld.provider.getHasNoSky(); - // Sections - ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray(); - Map tiles = nmsChunk.getTileEntityMap(); - ClassInheritanceMultiMap[] entities = nmsChunk.getEntityLists(); - - - // Remove entities - for (int i = 0; i < 16; i++) { - int count = fs.getCount(i); - if (count == 0) { - continue; - } else if (count >= 4096) { - entities[i] = new ClassInheritanceMultiMap<>(Entity.class); - } else { - char[] array = fs.getIdArray(i); - Collection ents = new ArrayList<>(entities[i]); - for (Entity entity : ents) { - if (entity instanceof EntityPlayer) { - continue; - } - int x = ((int) Math.round(entity.posX) & 15); - int z = ((int) Math.round(entity.posZ) & 15); - int y = (int) Math.round(entity.posY); - if (array == null) { - continue; - } - if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) { - nmsWorld.removeEntity(entity); - } - } - } - } - // Set entities - Set createdEntities = new HashSet<>(); - Set entitiesToSpawn = fs.getEntities(); - for (CompoundTag nativeTag : entitiesToSpawn) { - Map entityTagMap = 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(); - NBTTagCompound tag = (NBTTagCompound)methodFromNative.invoke(null, nativeTag); - Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld); - if (entity != null) { - entity.setPositionAndRotation(x, y, z, yaw, pitch); - nmsWorld.spawnEntityInWorld(entity); - } - } - // Run change task if applicable - if (changeTask != null) { - CharFaweChunk previous = getPrevious(fs, sections, tiles, entities, createdEntities, false); - changeTask.run(previous); - } - // Trim tiles - Set> entryset = tiles.entrySet(); - Iterator> iterator = entryset.iterator(); - while (iterator.hasNext()) { - Map.Entry tile = iterator.next(); - BlockPos pos = tile.getKey(); - int lx = pos.getX() & 15; - int ly = pos.getY(); - int lz = pos.getZ() & 15; - int j = FaweCache.CACHE_I[ly][lz][lx]; - char[] array = fs.getIdArray(j); - if (array == null) { - continue; - } - int k = FaweCache.CACHE_J[ly][lz][lx]; - if (array[k] != 0) { - tile.getValue().invalidate();; - iterator.remove(); - } - } - HashSet entsToRemove = fs.getEntityRemoves(); - if (entsToRemove.size() > 0) { - for (int i = 0; i < entities.length; i++) { - Collection ents = new ArrayList<>(entities[i]); - for (Entity entity : ents) { - if (entsToRemove.contains(entity.getUniqueID())) { - nmsWorld.removeEntity(entity); - } - } - } - } - // Efficiently merge sections - for (int j = 0; j < sections.length; j++) { - int count = fs.getCount(j); - if (count == 0) { - continue; - } - final char[] array = fs.getIdArray(j); - if (array == null) { - continue; - } - ExtendedBlockStorage section = sections[j]; - if (section == null) { - if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) { - section = sections[j] = new ExtendedBlockStorage(j << 4, flag); - setPalette(section, fs.sectionPalettes[j]); - setCount(0, count - fs.getAir(j), section); - continue; - } else { - sections[j] = section = new ExtendedBlockStorage(j << 4, flag); - } - } else if (count >= 4096) { - if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) { - setPalette(section, fs.sectionPalettes[j]); - setCount(0, count - fs.getAir(j), section); - continue; - } else { - sections[j] = section = new ExtendedBlockStorage(j << 4, flag); - } - } - BlockStateContainer nibble = section.getData(); - int nonEmptyBlockCount = 0; - for (int y = 0; y < 16; y++) { - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++) { - char combinedId = array[FaweCache.CACHE_J[y][z][x]]; - switch (combinedId) { - case 0: - IBlockState existing = nibble.get(x, y, z); - if (existing != air) { - nonEmptyBlockCount++; - } - continue; - case 1: - nibble.set(x, y, z, air); - continue; - default: - nonEmptyBlockCount++; - nibble.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF)); - } - } - } - } - setCount(0, nonEmptyBlockCount, section); - } - // Set biomes - int[][] biomes = fs.biomes; - if (biomes != null) { - for (int x = 0; x < 16; x++) { - int[] array = biomes[x]; - if (array == null) { - continue; - } - for (int z = 0; z < 16; z++) { - int biome = array[z]; - if (biome == 0) { - continue; - } - nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; - } - } - } - // Set tiles - Map tilesToSpawn = fs.getTiles(); - int bx = fs.getX() << 4; - int bz = fs.getZ() << 4; - - for (Map.Entry entry : tilesToSpawn.entrySet()) { - CompoundTag nativeTag = entry.getValue(); - BytePair pair = entry.getKey(); - BlockPos pos = new BlockPos(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos - TileEntity tileEntity = nmsWorld.getTileEntity(pos); - if (tileEntity != null) { - NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(null, nativeTag); - tileEntity.readFromNBT(tag); // ReadTagIntoTile - } - } - } catch (Throwable e) { - MainUtil.handleError(e); - } - int[][] biomes = fs.biomes; - if (biomes != null) { - for (int x = 0; x < 16; x++) { - int[] array = biomes[x]; - if (array == null) { - continue; - } - for (int z = 0; z < 16; z++) { - int biome = array[z]; - if (biome == 0) { - continue; - } - nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; - } - } - } - return true; - } + protected final static IBlockState air = Blocks.AIR.getDefaultState(); public void setPalette(ExtendedBlockStorage section, BlockStateContainer palette) throws NoSuchFieldException, IllegalAccessException { Field fieldSection = ExtendedBlockStorage.class.getDeclaredField("data"); @@ -602,7 +395,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue { +public class NukkitChunk extends CharFaweChunk { /** @@ -39,7 +39,8 @@ public class NukkitChunk extends CharFaweChunk { private int index; private boolean place = true; - public void execute() { + @Override + public NukkitChunk call() { NukkitQueue parent = (NukkitQueue) getParent(); Level world = ((NukkitQueue) getParent()).getWorld(); world.clearCache(true); @@ -113,5 +114,6 @@ public class NukkitChunk extends CharFaweChunk { } } } + return this; } } \ No newline at end of file diff --git a/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/queue/NukkitQueue.java b/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/queue/NukkitQueue.java index 859e8a29..95b29707 100644 --- a/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/queue/NukkitQueue.java +++ b/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/queue/NukkitQueue.java @@ -14,7 +14,6 @@ import com.boydti.fawe.example.NMSMappedFaweQueue; import com.boydti.fawe.nukkit.core.NBTConverter; import com.boydti.fawe.nukkit.optimization.FaweNukkit; import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.util.MathMan; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.world.World; @@ -25,8 +24,8 @@ import java.util.Set; import java.util.UUID; public class NukkitQueue extends NMSMappedFaweQueue { - private final FaweNukkit faweNukkit; - private final Level world; + private FaweNukkit faweNukkit; + private Level world; public static int ALLOCATE; public static double TPS_TARGET = 18.5; @@ -34,6 +33,15 @@ public class NukkitQueue extends NMSMappedFaweQueue changeTask) { - ((NukkitChunk) fc).execute(); - return true; - } - @Override public File getSaveFolder() { return new File("worlds" + File.separator + world.getFolderName() + File.separator + "region");