From 06275e8d3d208bc08ade414cf4a52dc43a831203 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Tue, 26 Jul 2016 10:04:19 +1000 Subject: [PATCH] [Bleeding] Lighting changes + broken --- .../boydti/fawe/bukkit/v0/BukkitQueue_0.java | 16 ++ .../fawe/bukkit/v0/BukkitQueue_All.java | 6 +- .../fawe/bukkit/v1_10/BukkitQueue_1_10.java | 209 ++++++++++++------ bukkit110/src/main/resources/plugin.yml | 5 - bukkit1710/src/main/resources/plugin.yml | 5 - bukkit18/src/main/resources/plugin.yml | 5 - core/src/main/java/com/boydti/fawe/Fawe.java | 2 - .../main/java/com/boydti/fawe/FaweAPI.java | 94 ++++---- .../com/boydti/fawe/command/FixLighting.java | 35 --- .../java/com/boydti/fawe/config/Config.java | 2 - .../boydti/fawe/example/MappedFaweQueue.java | 128 +++++++++++ .../fawe/example/NMSMappedFaweQueue.java | 137 ++++++++---- .../com/boydti/fawe/example/NMSRelighter.java | 194 ++++++++++++++++ .../com/boydti/fawe/object/FaweQueue.java | 104 +++++++++ .../boydti/fawe/util/DelegateFaweQueue.java | 22 ++ .../worldedit/command/NavigationCommands.java | 2 +- .../worldedit/command/RegionCommands.java | 25 +++ .../world/registry/BundledBlockData.java | 10 +- .../java/com/boydti/fawe/SpongeCommand.java | 4 +- 19 files changed, 778 insertions(+), 227 deletions(-) delete mode 100644 core/src/main/java/com/boydti/fawe/command/FixLighting.java create mode 100644 core/src/main/java/com/boydti/fawe/example/NMSRelighter.java 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 5fc76581..7035d334 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 @@ -12,6 +12,7 @@ import com.boydti.fawe.util.SetQueue; import com.boydti.fawe.util.TaskManager; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; +import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Collection; @@ -43,6 +44,21 @@ public abstract class BukkitQueue_0 extends NMSMa } } + @Override + public void forEachMCA(RunnableVal onEach) { + File folder = new File(Bukkit.getWorldContainer(), getWorldName() + File.separator + "region"); + File[] regionFiles = folder.listFiles(); + if (regionFiles == null) { + throw new RuntimeException("Could not find worlds folder: " + folder + " ? (no read access?)"); + } + for (File file : regionFiles) { + String name = file.getName(); + if (name.endsWith("mca")) { + onEach.run(file); + } + } + } + @Override public void setFullbright(CHUNKSECTIONS sections) {} 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 93150d62..83681559 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 @@ -25,13 +25,13 @@ public class BukkitQueue_All extends BukkitQueue_0 { } @Override - public void setSkyLight(int x, int y, int z, int value) { + public void setSkyLight(Chunk chunk, int x, int y, int z, int value) { } @Override - public void setBlockLight(int x, int y, int z, int value) { - + public void setBlockLight(Chunk chunk, int x, int y, int z, int value) { +// chunk.getBlock(x & 15, y, z & 15); } public int getCombinedId4Data(Chunk section, int x, int y, int z) { 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 d417f05e..be0a2358 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 @@ -6,6 +6,7 @@ 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.IntegerPair; import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MathMan; @@ -76,7 +77,7 @@ 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 { +public class BukkitQueue_1_10 extends BukkitQueue_0 { private static IBlockData air; private static Field fieldBits; @@ -103,32 +104,12 @@ public class BukkitQueue_1_10 extends BukkitQueue_0> 4; - int cz = z >> 4; - if (!ensureChunkLoaded(cx, cz)) { - return; - } - ChunkSection[] sections = getCachedSections(getWorld(), cx, cz); - ChunkSection section = sections[y >> 4]; - if (section == null) { - return; - } + public void setSkyLight(ChunkSection section, int x, int y, int z, int value) { section.getSkyLightArray().a(x & 15, y & 15, z & 15, value); } @Override - public void setBlockLight(int x, int y, int z, int value) { - int cx = x >> 4; - int cz = z >> 4; - if (!ensureChunkLoaded(cx, cz)) { - return; - } - ChunkSection[] sections = getCachedSections(getWorld(), cx, cz); - ChunkSection section = sections[y >> 4]; - if (section == null) { - return; - } + public void setBlockLight(ChunkSection section, int x, int y, int z, int value) { section.getEmittedLightArray().a(x & 15, y & 15, z & 15, value); } @@ -136,7 +117,8 @@ public class BukkitQueue_1_10 extends BukkitQueue_0 4) { for (int i = 0; i < sections.length; i++) { ChunkSection section = sections[i]; if (section != null) { section.a(new NibbleArray()); // Emitted if (sky) { + System.out.println("REMOVE SKY"); section.b(new NibbleArray()); // Skylight } } @@ -339,33 +322,134 @@ public class BukkitQueue_1_10 extends BukkitQueue_0 0) { - ChunkSection section = sections[y >> 4]; - if (section != null) { - section.a(x, y & 15, z, l); + // Optimizations + // If it's all air, use the above light values + // If it's all solid, use no light values + World world = getWorld(); + byte[] mask = new byte[256]; + byte[] smoothArray = new byte[256]; + Arrays.fill(mask, (byte) 15); + int bx = chunk.getX() << 4; + int bz = chunk.getZ() << 4; + section: + for (int y2 = 15; y2 >= 0; y2--) { + ChunkSection section = sections[y2]; + if (section == null) { + continue; + } + int y = 16 + (y2 << 4); + DataPaletteBlock dataPalette = section.getBlocks(); + layer: + for (int y1 = 15; y1 >= 0; y1--) { + y--; + boolean smooth = false; + index: + for (int j = 0; j < 256; j++) { + byte value = mask[j]; + smoothArray[j] = 0; + int x = FaweCache.CACHE_X[y1][j]; + int z = FaweCache.CACHE_Z[y1][j]; + IBlockData ibd = dataPalette.a(x, y1, z); + int opacity = ibd.c(); + if (x == 0 && z == 0) { + System.out.println(y + ": " + value + "," + opacity + " | " + getCombinedId4Data(bx + x, y, bz + z)); + } + if (opacity != 0 && opacity >= value) { + mask[j] = 0; + continue index; + } + switch (value) { + case 0: + if (opacity != 0) { + continue index; } + break; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + if (opacity == 0) { + mask[j] = --value; + if (x == 0 && z == 0) System.out.println(" - " + value); + } else { + mask[j] = value = (byte) Math.max(0, value - opacity); + if (x == 0 && z == 0) System.out.println(" - " + value); + } + break; + case 15: + if (opacity == 0) { + section.a(x, y1, z, value); + } else { + value -= opacity; + mask[j] = value; + section.a(x, y1, z, value); + if (x == 0 && z == 0) { + System.out.println(" - " + value); + } + } + continue index; + } + // Smooth + smooth = true; + smoothArray[j] = 1; + int adjacent = getAdjacentLight(bx + x, y, bz + z) - 1; + if (adjacent > value) { + if (x == 0 && z == 0) { + if (getSkyLight(bx + x - 1, y, bz + z) == 15) System.out.println("x-1"); + if (getSkyLight(bx + x + 1, y, bz + z) == 15) System.out.println("x+1"); + if (getSkyLight(bx + x, y, bz + z - 1) == 15) System.out.println("z-1"); + if (getSkyLight(bx + x, y, bz + z + 1) == 15) System.out.println("z+1"); + System.out.println("VALUE IS GREATER: " + getAdjacentLight(bx + x, y, bz + z)); } - --y; - } while (y > 0 && l > 0); + value = (byte) adjacent; + mask[j] = value; + } + section.a(x, y1, z, value); } +// if (smooth) { +// short[][] cache1 = FaweCache.CACHE_J[0]; +// for (int x = 0; x < 16; x++) { +// int xx = bx + x; +// short[] cache2 = cache1[x]; +// for (int z = 0; z < 16; z++) { +// int zz = bz + z; +// int j = cache2[z]; +// if (smoothArray[j] == 0) { +// continue; +// } +// byte value = mask[j]; +// int adjacent = getAdjacentLight(xx, y, zz) - 1; +// if (adjacent > value) { +// section.a(x, y1, z, mask[j] = (byte) adjacent); +// } +// } +// } +// for (int z = 15; z >=0; z--) { +// for (int x = 15; x >= 0; x--) { +// int xx = bx + x; +// int zz = bz + z; +// int j = cache1[x][z]; +// if (smoothArray[j] == 0) { +// continue; +// } +// byte value = mask[j]; +// int adjacent = getAdjacentLight(xx, y, zz) - 1; +// if (adjacent > value) { +// section.a(x, y1, z, mask[j] = (byte) adjacent); +// } +// } +// } +// } } } return true; @@ -383,21 +467,16 @@ public class BukkitQueue_1_10 extends BukkitQueue_0 * - First removes all lighting, then relights @@ -387,7 +391,7 @@ public class FaweAPI { * @param selection (assumes cuboid) * @return */ - public static int fixLighting(String world, Region selection) { + public static int fixLighting(String world, Region selection, final FaweQueue.RelightMode mode) { final Vector bot = selection.getMinimumPoint(); final Vector top = selection.getMaximumPoint(); @@ -402,59 +406,51 @@ public class FaweAPI { // Remove existing lighting first if (queue instanceof NMSMappedFaweQueue) { final NMSMappedFaweQueue nmsQueue = (NMSMappedFaweQueue) queue; - boolean sky = nmsQueue.hasSky(); + NMSRelighter relighter = new NMSRelighter(nmsQueue); for (int x = minX; x <= maxX; x++) { for (int z = minZ; z <= maxZ; z ++) { - if (!nmsQueue.isChunkLoaded(x, z)) { - final int xf = x; - final int zf = z; - if (!TaskManager.IMP.syncWhenFree(new RunnableVal() { - @Override - public void run(Boolean value) { - this.value = nmsQueue.loadChunk(nmsQueue.getWorld(), xf, zf, false); - } - })) { - continue; - } - } - Object sections = nmsQueue.getCachedSections(nmsQueue.getWorld(), x, z); - nmsQueue.removeLighting(sections, FaweQueue.RelightMode.ALL, sky); + relighter.addChunk(x, z); } } - } - ArrayList threads = new ArrayList<>(); - for (int X = 0; X < 2; X++) { - for (int Z = 0; Z < 2; Z++) { - for (int x = minX + X; x <= maxX; x += 2) { - for (int z = minZ + Z; z <= maxZ; z += 2) { - final FaweChunk chunk = queue.getFaweChunk(x, z); - if (Settings.LIGHTING.ASYNC) { - Thread thread = new Thread(new Runnable() { - @Override - public void run() { - queue.fixLightingSafe(chunk, FaweQueue.RelightMode.ALL); - queue.sendChunk(chunk, FaweQueue.RelightMode.NONE); - } - }); - thread.start(); - threads.add(thread); - } else { - queue.fixLightingSafe(chunk, FaweQueue.RelightMode.ALL); - queue.sendChunk(chunk, FaweQueue.RelightMode.NONE); - } - count++; - } - } - for (Thread thread : threads) { - try { - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - threads.clear(); + boolean sky = nmsQueue.hasSky(); + if (sky) { + relighter.fixSkyLighting(); } + relighter.fixBlockLighting(); } +// ArrayList threads = new ArrayList<>(); +// for (int X = 0; X < 2; X++) { +// for (int Z = 0; Z < 2; Z++) { +// for (int x = minX + X; x <= maxX; x += 2) { +// for (int z = minZ + Z; z <= maxZ; z += 2) { +// final FaweChunk chunk = queue.getFaweChunk(x, z); +// if (Settings.LIGHTING.ASYNC) { +// Thread thread = new Thread(new Runnable() { +// @Override +// public void run() { +// queue.fixLightingSafe(chunk, mode); +// queue.sendChunk(chunk, FaweQueue.RelightMode.NONE); +// } +// }); +// thread.start(); +// threads.add(thread); +// } else { +// queue.fixLightingSafe(chunk, mode); +// queue.sendChunk(chunk, FaweQueue.RelightMode.NONE); +// } +// count++; +// } +// } +// for (Thread thread : threads) { +// try { +// thread.join(); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// } +// threads.clear(); +// } +// } return count; } diff --git a/core/src/main/java/com/boydti/fawe/command/FixLighting.java b/core/src/main/java/com/boydti/fawe/command/FixLighting.java deleted file mode 100644 index 564db9cc..00000000 --- a/core/src/main/java/com/boydti/fawe/command/FixLighting.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.boydti.fawe.command; - -import com.boydti.fawe.FaweAPI; -import com.boydti.fawe.config.BBC; -import com.boydti.fawe.object.FaweCommand; -import com.boydti.fawe.object.FaweLocation; -import com.boydti.fawe.object.FawePlayer; -import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.regions.CuboidRegion; -import com.sk89q.worldedit.regions.Region; - -public class FixLighting extends FaweCommand { - - public FixLighting() { - super("fawe.fixlighting"); - } - - @Override - public boolean execute(final FawePlayer player, final String... args) { - if (player == null) { - return false; - } - final FaweLocation loc = player.getLocation(); - final int cx = loc.x >> 4; - final int cz = loc.z >> 4; - - Region selection = player.getSelection(); - if (selection == null) { - selection = new CuboidRegion(new Vector(cx - 8, 0, cz - 8).multiply(16), new Vector(cx + 8, 0, cz + 8).multiply(16)); - } - int count = FaweAPI.fixLighting(loc.world, selection); - BBC.FIX_LIGHTING_SELECTION.send(player, count); - return true; - } -} diff --git a/core/src/main/java/com/boydti/fawe/config/Config.java b/core/src/main/java/com/boydti/fawe/config/Config.java index eb45f632..8f2d76c6 100644 --- a/core/src/main/java/com/boydti/fawe/config/Config.java +++ b/core/src/main/java/com/boydti/fawe/config/Config.java @@ -21,8 +21,6 @@ import java.util.Map; public class Config { - // TODO - /** * Get the value for a node
* Probably throws some error if you try to get a non existent key 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 b43c15cc..e4bc2494 100644 --- a/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java @@ -1,6 +1,7 @@ package com.boydti.fawe.example; import com.boydti.fawe.Fawe; +import com.boydti.fawe.FaweCache; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FaweQueue; @@ -11,7 +12,9 @@ import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.SetQueue; import com.boydti.fawe.util.TaskManager; import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.blocks.BlockMaterial; import com.sk89q.worldedit.world.biome.BaseBiome; +import com.sk89q.worldedit.world.registry.BundledBlockData; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.UUID; @@ -434,6 +437,131 @@ public abstract class MappedFaweQueue extends FaweQueue { return getCombinedId4Data(lastSection, x, y, z) != 0; } + public int getOpacity(SECTION section, int x, int y, int z) { + int combined = getCombinedId4Data(section, x, y, z); + if (combined == 0) { + return 0; + } + BlockMaterial block = BundledBlockData.getInstance().getMaterialById(FaweCache.getId(combined)); + if (block == null) { + return 255; + } + return block.getLightOpacity(); + } + + public abstract int getSkyLight(SECTION sections, int x, int y, int z); + + public abstract int getEmmittedLight(SECTION sections, int x, int y, int z); + + public int getLight(SECTION sections, int x, int y, int z) { + if (!hasSky()) { + return getEmmittedLight(sections, x, y, z); + } + return Math.max(getSkyLight(sections, x, y, z), getEmmittedLight(sections, x, y, z)); + } + + @Override + public int getLight(int x, int y, int z) { + int cx = x >> 4; + int cz = z >> 4; + int cy = y >> 4; + if (cx != lastChunkX || cz != lastChunkZ) { + lastChunkX = cx; + lastChunkZ = cz; + if (!ensureChunkLoaded(cx, cz)) { + return 0; + } + lastChunkSections = getCachedSections(getWorld(), cx, cz); + lastSection = getCachedSection(lastChunkSections, cy); + } else if (cy != lastChunkY) { + if (lastChunkSections == null) { + return 0; + } + lastSection = getCachedSection(lastChunkSections, cy); + } + + if (lastSection == null) { + return 0; + } + return getLight(lastSection, x, y, z); + } + + @Override + public int getSkyLight(int x, int y, int z) { + int cx = x >> 4; + int cz = z >> 4; + int cy = y >> 4; + if (cx != lastChunkX || cz != lastChunkZ) { + lastChunkX = cx; + lastChunkZ = cz; + if (!ensureChunkLoaded(cx, cz)) { + return 0; + } + lastChunkSections = getCachedSections(getWorld(), cx, cz); + lastSection = getCachedSection(lastChunkSections, cy); + } else if (cy != lastChunkY) { + if (lastChunkSections == null) { + return 0; + } + lastSection = getCachedSection(lastChunkSections, cy); + } + if (lastSection == null) { + return 0; + } + return getSkyLight(lastSection, x, y, z); + } + + @Override + public int getEmmittedLight(int x, int y, int z) { + int cx = x >> 4; + int cz = z >> 4; + int cy = y >> 4; + if (cx != lastChunkX || cz != lastChunkZ) { + lastChunkX = cx; + lastChunkZ = cz; + if (!ensureChunkLoaded(cx, cz)) { + return 0; + } + lastChunkSections = getCachedSections(getWorld(), cx, cz); + lastSection = getCachedSection(lastChunkSections, cy); + } else if (cy != lastChunkY) { + if (lastChunkSections == null) { + return 0; + } + lastSection = getCachedSection(lastChunkSections, cy); + } + if (lastSection == null) { + return 0; + } + return getEmmittedLight(lastSection, x, y, z); + } + + @Override + public int getOpacity(int x, int y, int z) { + int cx = x >> 4; + int cz = z >> 4; + int cy = y >> 4; + if (cx != lastChunkX || cz != lastChunkZ) { + lastChunkX = cx; + lastChunkZ = cz; + if (!ensureChunkLoaded(cx, cz)) { + return 0; + } + lastChunkSections = getCachedSections(getWorld(), cx, cz); + lastSection = getCachedSection(lastChunkSections, cy); + } else if (cy != lastChunkY) { + if (lastChunkSections == null) { + return 0; + } + lastSection = getCachedSection(lastChunkSections, cy); + } + + if (lastSection == null) { + return 0; + } + return getOpacity(lastSection, x, y, z); + } + @Override public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException { int cx = x >> 4; 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 95a0b5d3..5437e4af 100644 --- a/core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java @@ -59,8 +59,6 @@ public abstract class NMSMappedFaweQueue ex }, Settings.LIGHTING.ASYNC); } - public abstract boolean hasSky(); - public abstract void setFullbright(CHUNKSECTION sections); public abstract boolean removeLighting(CHUNKSECTION sections, RelightMode mode, boolean hasSky); @@ -97,21 +95,58 @@ public abstract class NMSMappedFaweQueue ex public abstract void relight(int x, int y, int z); - public abstract void setSkyLight(int x, int y, int z, int value); - - public abstract void setBlockLight(int x, int y, int z, int value); - - public abstract int getSkyLight(CHUNKSECTION sections, int x, int y, int z); - - public abstract int getEmmittedLight(CHUNKSECTION sections, int x, int y, int z); - - public int getLight(CHUNKSECTION sections, int x, int y, int z) { - if (!hasSky()) { - return getEmmittedLight(sections, x, y, z); + public void setSkyLight(int x, int y, int z, int value) { + int cx = x >> 4; + int cz = z >> 4; + int cy = y >> 4; + if (cx != lastChunkX || cz != lastChunkZ) { + lastChunkX = cx; + lastChunkZ = cz; + if (!ensureChunkLoaded(cx, cz)) { + return; + } + lastChunkSections = getCachedSections(getWorld(), cx, cz); + lastSection = getCachedSection(lastChunkSections, cy); + } else if (cy != lastChunkY) { + if (lastChunkSections == null) { + return; + } + lastSection = getCachedSection(lastChunkSections, cy); } - return Math.max(getSkyLight(sections, x, y, z), getEmmittedLight(sections, x, y, z)); + if (lastSection == null) { + return; + } + setSkyLight(lastSection, x, y, z, value); } + public void setBlockLight(int x, int y, int z, int value) { + int cx = x >> 4; + int cz = z >> 4; + int cy = y >> 4; + if (cx != lastChunkX || cz != lastChunkZ) { + lastChunkX = cx; + lastChunkZ = cz; + if (!ensureChunkLoaded(cx, cz)) { + return; + } + lastChunkSections = getCachedSections(getWorld(), cx, cz); + lastSection = getCachedSection(lastChunkSections, cy); + } else if (cy != lastChunkY) { + if (lastChunkSections == null) { + return; + } + lastSection = getCachedSection(lastChunkSections, cy); + } + if (lastSection == null) { + return; + } + setBlockLight(lastSection, x, y, z, value); + } + + public abstract void setSkyLight(SECTION section, int x, int y, int z, int value); + + public abstract void setBlockLight(SECTION section, int x, int y, int z, int value); + @Override public boolean fixLighting(FaweChunk fc, RelightMode mode) { if (mode == RelightMode.NONE) { @@ -182,41 +217,43 @@ public abstract class NMSMappedFaweQueue ex } switch (mode) { case ALL: { - for (int k = 4095; k >= 0; k--) { - final int x = FaweCache.CACHE_X[j][k]; - final int y = FaweCache.CACHE_Y[j][k]; - if (y == 0) { - continue; - } - final int z = FaweCache.CACHE_Z[j][k]; - final int i = array[k]; - final short id = (short) (i >> 4); - switch (FaweCache.getLight(id)) { - case OCCLUDING: - if (y == 0 || !FaweCache.isTransparent(bc.getCombinedId(x, y - 1, z) >> 4)) { - continue; - } - break; - case TRANSPARENT_EMIT: - case SOLID_EMIT: - if (this.isSurrounded(bc.getCombinedIdArrays(), x, y, z)) { - continue; - } - break; - case TRANSPARENT: - if (y >= 255) { - continue; - } - int light = getSkyLight(sections, x, y, z); - if (light != 0) { - continue; - } - break; - } - relight(X + x, y, Z + z); - } - break; + } +// for (int k = 4095; k >= 0; k--) { +// final int x = FaweCache.CACHE_X[j][k]; +// final int y = FaweCache.CACHE_Y[j][k]; +// if (y == 0) { +// continue; +// } +// final int z = FaweCache.CACHE_Z[j][k]; +// final int i = array[k]; +// final short id = (short) (i >> 4); +// switch (FaweCache.getLight(id)) { +// case OCCLUDING: +// if (y == 0 || !FaweCache.isTransparent(bc.getCombinedId(x, y - 1, z) >> 4)) { +// continue; +// } +// break; +// case TRANSPARENT_EMIT: +// case SOLID_EMIT: +// if (this.isSurrounded(bc.getCombinedIdArrays(), x, y, z)) { +// continue; +// } +// break; +// case TRANSPARENT: +// if (y >= 255) { +// continue; +// } +// int light = getSkyLight(sections, x, y, z); +// if (light != 0) { +// continue; +// } +// break; +// } +// relight(X + x, y, Z + z); +// } +// break; +// } case OPTIMAL: { for (int k = 4095; k >= 0; k--) { final int x = FaweCache.CACHE_X[j][k]; @@ -272,7 +309,9 @@ public abstract class NMSMappedFaweQueue ex } } return true; - } catch (Throwable ignore) {} + } catch (Throwable ignore) { + ignore.printStackTrace(); + } return false; } diff --git a/core/src/main/java/com/boydti/fawe/example/NMSRelighter.java b/core/src/main/java/com/boydti/fawe/example/NMSRelighter.java new file mode 100644 index 00000000..3a46e81f --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/example/NMSRelighter.java @@ -0,0 +1,194 @@ +package com.boydti.fawe.example; + +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.util.MathMan; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; + +public class NMSRelighter { + private final NMSMappedFaweQueue queue; + private final HashMap toRelight; + + public NMSRelighter(NMSMappedFaweQueue queue) { + this.queue = queue; + toRelight = new HashMap<>(); + } + + public boolean addChunk(int cx, int cz) { + long pair = MathMan.pairInt(cx, cz); + if (toRelight.containsKey(pair)) { + return false; + } + toRelight.put(pair, new RelightChunk(cx, cz)); + return true; + } + + public void fixBlockLighting() { + + } + + public void fixSkyLighting() { + // Order chunks + ArrayList chunksList = new ArrayList<>(toRelight.values()); + Collections.sort(chunksList); + RelightChunk[] chunks = chunksList.toArray(new RelightChunk[chunksList.size()]); + + byte[] cacheX = FaweCache.CACHE_X[0]; + byte[] cacheZ = FaweCache.CACHE_Z[0]; + for (int y = 255; y >= 0; y--) { + for (RelightChunk chunk : chunks) { // Propogate skylight + byte[] mask = chunk.mask; + Object sections = queue.getCachedSections(queue.getWorld(), chunk.x, chunk.z); + if (sections == null) continue; + Object section = queue.getCachedSection(sections, y >> 4); + if (section == null) continue; + chunk.smooth = false; + for (int j = 0; j < 256; j++) { + int x = cacheX[j]; + int z = cacheZ[j]; + byte value = mask[j]; + int opacity = queue.getOpacity(section, x, y, z); + if (opacity != 0 && opacity >= value) { + mask[j] = 0; + continue; + } + switch (value) { + case 0: + if (opacity != 0) { + continue; + } + break; + case 2: + case 4: + case 6: + case 8: + case 10: + case 12: + case 14: + if (opacity == 0) { + mask[j] = --value; + } else { + mask[j] = (byte) Math.max(0, value - opacity); + } + queue.setSkyLight(section, x, y, z, value); + continue; + case 1: + case 3: + case 5: + case 7: + case 9: + case 11: + case 13: + if (opacity == 0) { + mask[j] = --value; + } else { + mask[j] = value = (byte) Math.max(0, value - opacity); + } + break; + case 15: + if (opacity != 0) { + value -= opacity; + mask[j] = value; + } + queue.setSkyLight(section, x, y, z, value); + continue; + } + chunk.smooth = true; + queue.setSkyLight(section, x, y, z, value); + } + } + for (RelightChunk chunk : chunks) { // Smooth forwards + if (chunk.smooth) { + smooth(chunk, y, true); + } + } + for (int i = chunks.length - 1; i>= 0; i--) { // Smooth backwards + RelightChunk chunk = chunks[i]; + if (chunk.smooth) { + smooth(chunk, y, false); + } + } + } + + } + + public void smooth(RelightChunk chunk, int y, boolean direction) { + byte[] mask = chunk.mask; + int bx = chunk.x << 4; + int bz = chunk.z << 4; + Object sections = queue.getCachedSections(queue.getWorld(), chunk.x, chunk.z); + if (sections == null) return; + Object section = queue.getCachedSection(sections, y >> 4); + if (section == null) return; + if (direction) { + for (int j = 0; j < 256; j++) { + int x = j & 15; + int z = j >> 4; + if (mask[j] >= 14 || (mask[j] == 0 && queue.getOpacity(section, x, y, z) > 0)) { + continue; + } + byte value = mask[j]; + if ((value = (byte) Math.max(queue.getSkyLight(bx + x - 1, y, bz + z) - 1, value)) >= 14); + else if ((value = (byte) Math.max(queue.getSkyLight(bx + x, y, bz + z - 1) - 1, value)) >= 14); + if (value > mask[j]) queue.setSkyLight(section, x, y, z, mask[j] = value); + } + } else { + for (int j = 255; j >= 0; j--) { + int x = j & 15; + int z = j >> 4; + if (mask[j] >= 14 || (mask[j] == 0 && queue.getOpacity(section, x, y, z) > 0)) { + continue; + } + byte value = mask[j]; + if ((value = (byte) Math.max(queue.getSkyLight(bx + x + 1, y, bz + z) - 1, value)) >= 14); + else if ((value = (byte) Math.max(queue.getSkyLight(bx + x, y, bz + z + 1) - 1, value)) >= 14); + if (value > mask[j]) queue.setSkyLight(section, x, y, z, mask[j] = value); + } + } + } + + public boolean isUnlit(byte[] array) { + for (byte val : array) { + if (val != 0) { + return false; + } + } + return true; + } + + private class RelightChunk implements Comparable { + public final int x; + public final int z; + public final byte[] mask; + public boolean smooth; + + public RelightChunk(int x, int z) { + this.x = x; + this.z = z; + byte[] array = new byte[256]; + Arrays.fill(array, (byte) 15); + this.mask = array; + } + + + @Override + public int compareTo(Object o) { + RelightChunk other = (RelightChunk) o; + if (other.x < x) { + return -1; + } + if (other.x > x) { + return 1; + } + if (other.z < z) { + return -1; + } + if (other.z > z) { + return 1; + } + return 0; + } + } +} diff --git a/core/src/main/java/com/boydti/fawe/object/FaweQueue.java b/core/src/main/java/com/boydti/fawe/object/FaweQueue.java index 5b7644cc..254b501e 100644 --- a/core/src/main/java/com/boydti/fawe/object/FaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/object/FaweQueue.java @@ -1,6 +1,7 @@ package com.boydti.fawe.object; import com.boydti.fawe.Fawe; +import com.boydti.fawe.FaweCache; import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.exception.FaweException; @@ -10,7 +11,12 @@ import com.boydti.fawe.util.SetQueue; import com.boydti.fawe.util.TaskManager; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.blocks.BlockMaterial; import com.sk89q.worldedit.world.biome.BaseBiome; +import com.sk89q.worldedit.world.registry.BundledBlockData; +import java.io.File; import java.util.HashSet; import java.util.Set; import java.util.UUID; @@ -41,6 +47,7 @@ public abstract class FaweQueue { MINIMAL, FULLBRIGHT, OPTIMAL, + FAST, ALL, } @@ -151,6 +158,64 @@ public abstract class FaweQueue { }); } + public abstract void forEachMCA(RunnableVal onEach); + + public void forEachBlockInChunk(int cx, int cz, RunnableVal2 onEach) { + int bx = cx << 4; + int bz = cz << 4; + Vector mutable = new Vector(0, 0, 0); + for (int x = 0; x < 16; x++) { + int xx = x + bx; + mutable.x = xx; + for (int z = 0; z < 16; z++) { + int zz = z + bz; + mutable.z = zz; + for (int y = 0; y < 256; y++) { + int combined = getCombinedId4Data(xx, y, zz); + if (combined == 0) { + continue; + } + int id = FaweCache.getId(combined); + mutable.y = y; + if (FaweCache.hasNBT(id)) { + CompoundTag tile = getTileEntity(x, y, z); + BaseBlock block = new BaseBlock(id, FaweCache.getData(combined), tile); + onEach.run(mutable, block); + } else { + onEach.run(mutable, FaweCache.CACHE_BLOCK[combined]); + } + } + } + } + } + + public void forEachTileInChunk(int cx, int cz, RunnableVal2 onEach) { + int bx = cx << 4; + int bz = cz << 4; + Vector mutable = new Vector(0, 0, 0); + for (int x = 0; x < 16; x++) { + int xx = x + bx; + for (int z = 0; z < 16; z++) { + int zz = z + bz; + for (int y = 0; y < 256; y++) { + int combined = getCombinedId4Data(xx, y, zz); + if (combined == 0) { + continue; + } + int id = FaweCache.getId(combined); + if (FaweCache.hasNBT(id)) { + mutable.x = xx; + mutable.z = zz; + mutable.y = y; + CompoundTag tile = getTileEntity(x, y, z); + BaseBlock block = new BaseBlock(id, FaweCache.getData(combined), tile); + onEach.run(mutable, block); + } + } + } + } + } + public abstract boolean fixLighting(final FaweChunk chunk, RelightMode mode); public abstract boolean isChunkLoaded(final int x, final int z); @@ -208,6 +273,33 @@ public abstract class FaweQueue { public abstract int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException; + public int getAdjacentLight(int x, int y, int z) { + int light = 0; + if ((light = Math.max(light, getSkyLight(x - 1, y, z))) == 15) { + return light; + } + if ((light = Math.max(light, getSkyLight(x + 1, y, z))) == 15) { + return light; + } + if ((light = Math.max(light, getSkyLight(x, y, z - 1))) == 15) { + return light; + } + return Math.max(light, getSkyLight(x, y, z + 1)); + } + + public abstract boolean hasSky(); + + public abstract int getSkyLight(int x, int y, int z); + + public int getLight(int x, int y, int z) { + if (!hasSky()) { + return getEmmittedLight(x, y, z); + } + return Math.max(getSkyLight(x, y, z), getEmmittedLight(x, y, z)); + } + + public abstract int getEmmittedLight(int x, int y, int z); + public abstract CompoundTag getTileEntity(int x, int y, int z) throws FaweException.FaweChunkLoadException; public int getCombinedId4Data(int x, int y, int z, int def) { @@ -227,6 +319,18 @@ public abstract class FaweQueue { } } + public int getOpacity(int x, int y, int z) { + int combined = getCombinedId4Data(x, y, z); + if (combined == 0) { + return 0; + } + BlockMaterial block = BundledBlockData.getInstance().getMaterialById(FaweCache.getId(combined)); + if (block == null) { + return 255; + } + return block.getLightOpacity(); + } + public abstract int size(); /** 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 04afc3a2..eed7bd43 100644 --- a/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java @@ -2,11 +2,13 @@ package com.boydti.fawe.util; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FaweQueue; +import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.RunnableVal2; import com.boydti.fawe.object.exception.FaweException; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.world.biome.BaseBiome; +import java.io.File; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentLinkedDeque; @@ -127,6 +129,11 @@ public class DelegateFaweQueue extends FaweQueue { parent.setChunk(chunk); } + @Override + public void forEachMCA(RunnableVal onEach) { + parent.forEachMCA(onEach); + } + @Override public boolean fixLighting(FaweChunk chunk, RelightMode mode) { return parent.fixLighting(chunk, mode); @@ -192,6 +199,21 @@ public class DelegateFaweQueue extends FaweQueue { return parent.getCombinedId4Data(x, y, z); } + @Override + public boolean hasSky() { + return parent.hasSky(); + } + + @Override + public int getSkyLight(int x, int y, int z) { + return parent.getSkyLight(x, y, z); + } + + @Override + public int getEmmittedLight(int x, int y, int z) { + return parent.getEmmittedLight(x, y, z); + } + @Override public CompoundTag getTileEntity(int x, int y, int z) throws FaweException.FaweChunkLoadException { return parent.getTileEntity(x, y, z); 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 8d6ba9a4..afaa5152 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java @@ -21,7 +21,7 @@ package com.sk89q.worldedit.command; import com.boydti.fawe.FaweAPI; import com.boydti.fawe.config.BBC; -import com.intellectualcrafters.plot.util.MathMan; +import com.boydti.fawe.util.MathMan; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandPermissions; diff --git a/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index abba0a44..b736ad87 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -19,7 +19,11 @@ package com.sk89q.worldedit.command; +import com.boydti.fawe.FaweAPI; import com.boydti.fawe.config.BBC; +import com.boydti.fawe.object.FaweLocation; +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.FaweQueue; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.Logging; @@ -86,6 +90,27 @@ public class RegionCommands { this.worldEdit = worldEdit; } + @Command( + aliases = { "/fixlighting" }, + desc = "Get the light at a position", + min = 0, + max = 0 + ) + @CommandPermissions("worldedit.light.get") + public void fixlighting(Player player, EditSession editSession) throws WorldEditException { + FawePlayer fp = FawePlayer.wrap(player); + final FaweLocation loc = fp.getLocation(); + final int cx = loc.x >> 4; + final int cz = loc.z >> 4; + + Region selection = fp.getSelection(); + if (selection == null) { + selection = new CuboidRegion(new Vector(cx - 8, 0, cz - 8).multiply(16), new Vector(cx + 8, 0, cz + 8).multiply(16)); + } + int count = FaweAPI.fixLighting(loc.world, selection, FaweQueue.RelightMode.ALL); + BBC.FIX_LIGHTING_SELECTION.send(fp, count); + } + @Command( aliases = { "/line" }, usage = " [thickness]", diff --git a/core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockData.java b/core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockData.java index 1b524188..36c7699d 100644 --- a/core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockData.java +++ b/core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockData.java @@ -60,7 +60,9 @@ public class BundledBlockData { private static final BundledBlockData INSTANCE = new BundledBlockData(); private final Map idMap = new HashMap(); - private final Map legacyMap = new HashMap(); // Trove usage removed temporarily + + private final BlockEntry[] legacyMap = new BlockEntry[4096]; + /** * Create a new instance. @@ -95,11 +97,11 @@ public class BundledBlockData { public boolean add(BlockEntry entry, boolean overwrite) { entry.postDeserialization(); - if (!overwrite && (idMap.containsKey(entry.id) || legacyMap.containsKey(entry.legacyId))) { + if (!overwrite && (idMap.containsKey(entry.id) || legacyMap[entry.legacyId] != null)) { return false; } idMap.put(entry.id, entry); - legacyMap.put(entry.legacyId, entry); + legacyMap[entry.legacyId] = entry; return true; } @@ -122,7 +124,7 @@ public class BundledBlockData { */ @Nullable public BlockEntry findById(int id) { - return legacyMap.get(id); + return legacyMap[id]; } /** diff --git a/sponge/src/main/java/com/boydti/fawe/SpongeCommand.java b/sponge/src/main/java/com/boydti/fawe/SpongeCommand.java index af14464c..b6e6d909 100644 --- a/sponge/src/main/java/com/boydti/fawe/SpongeCommand.java +++ b/sponge/src/main/java/com/boydti/fawe/SpongeCommand.java @@ -47,11 +47,11 @@ public class SpongeCommand implements CommandCallable { @Override public Optional getHelp(final CommandSource cmd) { - return Optional.of(Text.of("/")); + return Optional.of(Text.of("/")); } @Override public Text getUsage(final CommandSource cmd) { - return Text.of("/"); + return Text.of("/"); } }