From 4f7e1a6b315a509bb8e56ed26537c5dd79bae23a Mon Sep 17 00:00:00 2001 From: TomyLobo Date: Mon, 17 Oct 2011 06:07:58 +0200 Subject: [PATCH] Improved speed greatly by deferring lighting until after all blocks are in place. This needs CraftBukkit to work. --- .../java/com/sk89q/worldedit/EditSession.java | 10 +++++ .../sk89q/worldedit/bukkit/BukkitWorld.java | 44 ++++++++++++++----- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/sk89q/worldedit/EditSession.java b/src/main/java/com/sk89q/worldedit/EditSession.java index 5b8207913..9152f0a5b 100644 --- a/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/src/main/java/com/sk89q/worldedit/EditSession.java @@ -554,9 +554,14 @@ public class EditSession { return; } + final Set dirtyChunks = new HashSet(); + for (Map.Entry entry : queueAfter) { BlockVector pt = (BlockVector) entry.getKey(); rawSetBlock(pt, (BaseBlock) entry.getValue()); + + // TODO: use ChunkStore.toChunk(pt) after optimizing it. + if (fastMode) dirtyChunks.add(new BlockVector2D(pt.getBlockX() >> 4, pt.getBlockZ() >> 4)); } // We don't want to place these blocks if other blocks were missing @@ -622,10 +627,15 @@ public class EditSession { for (BlockVector pt : walked) { rawSetBlock(pt, blockTypes.get(pt)); blocks.remove(pt); + + // TODO: use ChunkStore.toChunk(pt) after optimizing it. + if (fastMode) dirtyChunks.add(new BlockVector2D(pt.getBlockX() >> 4, pt.getBlockZ() >> 4)); } } } + if (!dirtyChunks.isEmpty()) world.fixLighting(dirtyChunks); + queueAfter.clear(); queueLast.clear(); } diff --git a/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index be9f46e9a..10c51ac6d 100644 --- a/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -107,7 +107,17 @@ public class BukkitWorld extends LocalWorld { */ @Override public boolean setBlockTypeFast(Vector pt, int type) { - return world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).setTypeId(type, false); + final Block block = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + if (fastLighting) { + type = type & 255; + final int previousOpacity = Block_lightOpacity[type]; + Block_lightOpacity[type] = 0; + final boolean ret = block.setTypeId(type); + Block_lightOpacity[type] = previousOpacity; + return ret; + } + + return block.setTypeId(type, false); } /** @@ -131,7 +141,17 @@ public class BukkitWorld extends LocalWorld { */ @Override public boolean setTypeIdAndDataFast(Vector pt, int type, int data){ - return world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).setTypeIdAndData(type, (byte) data, false); + final Block block = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + if (fastLighting) { + type = type & 255; + final int previousOpacity = Block_lightOpacity[type]; + Block_lightOpacity[type] = 0; + final boolean ret = block.setTypeIdAndData(type, (byte) data, true); + Block_lightOpacity[type] = previousOpacity; + return ret; + } + + return block.setTypeIdAndData(type, (byte) data, false); } /** @@ -726,8 +746,8 @@ public class BukkitWorld extends LocalWorld { Object chunk = World_getChunkFromChunkCoords.invoke(notchWorld, x, z); - int length = ((byte[])Chunk_b.get(chunk)).length; - Chunk_h.set(chunk, NibbleArray_ctor.newInstance(length, 7)); + int length = ((byte[])Chunk_blocks.get(chunk)).length; + Chunk_skylightMap.set(chunk, NibbleArray_ctor.newInstance(length, 7)); //Chunk_i.set(chunk, NibbleArray_ctor.newInstance(length, 7)); Chunk_generateSkylightMap.invoke(chunk); @@ -740,25 +760,29 @@ public class BukkitWorld extends LocalWorld { } private static boolean fastLighting = false; + private static int[] Block_lightOpacity; private static Method CraftWorld_getHandle; private static Method World_getChunkFromChunkCoords; private static Method Chunk_generateSkylightMap; - private static Field Chunk_b; - private static Field Chunk_h; - //private static Field Chunk_i; + private static Field Chunk_blocks; + private static Field Chunk_skylightMap; + //private static Field Chunk_blocklightMap; private static Constructor NibbleArray_ctor; static { if (Bukkit.getServer().getName().equalsIgnoreCase("CraftBukkit")) { try { + Block_lightOpacity = (int[]) Class.forName("net.minecraft.server.Block").getDeclaredField("q").get(null); + CraftWorld_getHandle = Class.forName("org.bukkit.craftbukkit.CraftWorld").getMethod("getHandle"); World_getChunkFromChunkCoords = Class.forName("net.minecraft.server.World").getMethod("getChunkAt", int.class, int.class); Chunk_generateSkylightMap = Class.forName("net.minecraft.server.Chunk").getMethod("initLighting"); - Chunk_b = Class.forName("net.minecraft.server.Chunk").getField("b"); - Chunk_h = Class.forName("net.minecraft.server.Chunk").getField("h"); - //Chunk_i = Class.forName("net.minecraft.server.Chunk").getField("i"); + Chunk_blocks = Class.forName("net.minecraft.server.Chunk").getField("b"); + Chunk_skylightMap = Class.forName("net.minecraft.server.Chunk").getField("h"); + //Chunk_blocklightMap = Class.forName("net.minecraft.server.Chunk").getField("i"); NibbleArray_ctor = Class.forName("net.minecraft.server.NibbleArray").getConstructor(int.class, int.class); + fastLighting = true; } catch (Throwable e) {