From 14dddfb1de8db948effa913492b0022b943d1d9f Mon Sep 17 00:00:00 2001 From: Leijurv Date: Tue, 21 Aug 2018 15:18:35 -0700 Subject: [PATCH] chunk packing linkedblockingqueue --- .../java/baritone/bot/chunk/CachedRegion.java | 20 +++++---- .../java/baritone/bot/chunk/CachedWorld.java | 42 +++++++++++++++++-- .../bot/chunk/CachedWorldProvider.java | 10 +++++ .../java/baritone/bot/chunk/ChunkPacker.java | 11 ++--- .../bot/chunk/ICachedChunkAccess.java | 31 -------------- .../baritone/bot/event/GameEventHandler.java | 12 +++--- 6 files changed, 74 insertions(+), 52 deletions(-) delete mode 100644 src/main/java/baritone/bot/chunk/ICachedChunkAccess.java diff --git a/src/main/java/baritone/bot/chunk/CachedRegion.java b/src/main/java/baritone/bot/chunk/CachedRegion.java index 05d6ee9d..8f2dfc9b 100644 --- a/src/main/java/baritone/bot/chunk/CachedRegion.java +++ b/src/main/java/baritone/bot/chunk/CachedRegion.java @@ -17,6 +17,7 @@ package baritone.bot.chunk; +import baritone.bot.utils.pathing.IBlockTypeAccess; import baritone.bot.utils.pathing.PathingBlockType; import java.io.*; @@ -32,7 +33,7 @@ import java.util.zip.GZIPOutputStream; * @author Brady * @since 8/3/2018 9:35 PM */ -public final class CachedRegion implements ICachedChunkAccess { +public final class CachedRegion implements IBlockTypeAccess { private static final byte CHUNK_NOT_PRESENT = 0; private static final byte CHUNK_PRESENT = 1; @@ -76,8 +77,7 @@ public final class CachedRegion implements ICachedChunkAccess { return null; } - @Override - public final void updateCachedChunk(int chunkX, int chunkZ, BitSet data) { + final void updateCachedChunk(int chunkX, int chunkZ, BitSet data) { CachedChunk chunk = this.getChunk(chunkX, chunkZ); if (chunk == null) { this.chunks[chunkX][chunkZ] = new CachedChunk(chunkX, chunkZ, data); @@ -111,7 +111,7 @@ public final class CachedRegion implements ICachedChunkAccess { if (!Files.exists(path)) Files.createDirectories(path); - System.out.println("Saving region " + x + "," + z + " to disk"); + System.out.println("Saving region " + x + "," + z + " to disk " + path); Path regionFile = getRegionFile(path, this.x, this.z); if (!Files.exists(regionFile)) Files.createFile(regionFile); @@ -138,7 +138,10 @@ public final class CachedRegion implements ICachedChunkAccess { out.writeInt(~CACHED_REGION_MAGIC); } hasUnsavedChanges = false; - } catch (IOException ignored) {} + System.out.println("Saved region successfully"); + } catch (IOException ex) { + ex.printStackTrace(); + } } public void load(String directory) { @@ -151,7 +154,7 @@ public final class CachedRegion implements ICachedChunkAccess { if (!Files.exists(regionFile)) return; - System.out.println("Loading region " + x + "," + z + " from disk"); + System.out.println("Loading region " + x + "," + z + " from disk " + path); try ( FileInputStream fileIn = new FileInputStream(regionFile.toFile()); @@ -189,7 +192,10 @@ public final class CachedRegion implements ICachedChunkAccess { } } hasUnsavedChanges = false; - } catch (IOException ignored) {} + System.out.println("Loaded region successfully"); + } catch (IOException ex) { + ex.printStackTrace(); + } } private static boolean isAllZeros(final byte[] array) { diff --git a/src/main/java/baritone/bot/chunk/CachedWorld.java b/src/main/java/baritone/bot/chunk/CachedWorld.java index eb7513a3..d3900f6f 100644 --- a/src/main/java/baritone/bot/chunk/CachedWorld.java +++ b/src/main/java/baritone/bot/chunk/CachedWorld.java @@ -17,18 +17,21 @@ package baritone.bot.chunk; +import baritone.bot.utils.pathing.IBlockTypeAccess; import baritone.bot.utils.pathing.PathingBlockType; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.minecraft.world.chunk.Chunk; import java.util.BitSet; +import java.util.concurrent.LinkedBlockingQueue; import java.util.function.Consumer; /** * @author Brady * @since 8/4/2018 12:02 AM */ -public final class CachedWorld implements ICachedChunkAccess { +public final class CachedWorld implements IBlockTypeAccess { /** * The maximum number of regions in any direction from (0,0) @@ -45,10 +48,21 @@ public final class CachedWorld implements ICachedChunkAccess { */ private final String directory; + private final LinkedBlockingQueue toPack = new LinkedBlockingQueue<>(); + public CachedWorld(String directory) { this.directory = directory; // Insert an invalid region element cachedRegions.put(0, null); + new PackerThread().start(); + } + + public final void queueForPacking(Chunk chunk) { + try { + toPack.put(chunk); + } catch (InterruptedException e) { + e.printStackTrace(); + } } @Override @@ -57,17 +71,19 @@ public final class CachedWorld implements ICachedChunkAccess { return region.getBlockType(x & 511, y, z & 511); } - @Override - public final void updateCachedChunk(int chunkX, int chunkZ, BitSet data) { + private void updateCachedChunk(int chunkX, int chunkZ, BitSet data) { CachedRegion region = getOrCreateRegion(chunkX >> 5, chunkZ >> 5); region.updateCachedChunk(chunkX & 31, chunkZ & 31, data); } public final void save() { + long start = System.currentTimeMillis(); this.cachedRegions.values().forEach(region -> { if (region != null) region.save(this.directory); }); + long now = System.currentTimeMillis(); + System.out.println("World save took " + (now - start) + "ms"); } /** @@ -129,4 +145,24 @@ public final class CachedWorld implements ICachedChunkAccess { private boolean isRegionInWorld(int regionX, int regionZ) { return regionX <= REGION_MAX && regionX >= -REGION_MAX && regionZ <= REGION_MAX && regionZ >= -REGION_MAX; } + + private class PackerThread extends Thread { + public void run() { + while (true) { + LinkedBlockingQueue queue = toPack; + if (queue == null) { + break; + } + try { + Chunk chunk = queue.take(); + BitSet packed = ChunkPacker.createPackedChunk(chunk); + CachedWorld.this.updateCachedChunk(chunk.x, chunk.z, packed); + //System.out.println("Processed chunk at " + chunk.x + "," + chunk.z); + } catch (InterruptedException e) { + e.printStackTrace(); + break; + } + } + } + } } diff --git a/src/main/java/baritone/bot/chunk/CachedWorldProvider.java b/src/main/java/baritone/bot/chunk/CachedWorldProvider.java index e6062d6d..b59c3a52 100644 --- a/src/main/java/baritone/bot/chunk/CachedWorldProvider.java +++ b/src/main/java/baritone/bot/chunk/CachedWorldProvider.java @@ -69,7 +69,17 @@ public enum CachedWorldProvider implements Helper { } public final void closeWorld() { + CachedWorld world = this.currentWorld; this.currentWorld = null; + if (world == null) { + return; + } + new Thread() { + public void run() { + System.out.println("Started saving the world in a new thread"); + world.save(); + } + }.start(); } public final void ifWorldLoaded(Consumer currentWorldConsumer) { diff --git a/src/main/java/baritone/bot/chunk/ChunkPacker.java b/src/main/java/baritone/bot/chunk/ChunkPacker.java index 7b8fbbe4..25ef3b39 100644 --- a/src/main/java/baritone/bot/chunk/ChunkPacker.java +++ b/src/main/java/baritone/bot/chunk/ChunkPacker.java @@ -18,9 +18,9 @@ package baritone.bot.chunk; import baritone.bot.pathing.movement.MovementHelper; -import baritone.bot.utils.pathing.PathingBlockType; import baritone.bot.utils.BlockStateInterface; import baritone.bot.utils.Helper; +import baritone.bot.utils.pathing.PathingBlockType; import net.minecraft.block.Block; import net.minecraft.block.BlockAir; import net.minecraft.block.state.IBlockState; @@ -29,8 +29,6 @@ import net.minecraft.world.chunk.Chunk; import java.util.BitSet; -import static net.minecraft.block.Block.NULL_AABB; - /** * @author Brady * @since 8/3/2018 1:09 AM @@ -39,7 +37,8 @@ public final class ChunkPacker implements Helper { private ChunkPacker() {} - public static BitSet createPackedChunk(Chunk chunk) { + public static synchronized BitSet createPackedChunk(Chunk chunk) { + long start = System.currentTimeMillis(); BitSet bitSet = new BitSet(CachedChunk.SIZE); try { for (int y = 0; y < 256; y++) { @@ -55,6 +54,8 @@ public final class ChunkPacker implements Helper { } catch (Exception e) { e.printStackTrace(); } + long end = System.currentTimeMillis(); + //System.out.println("Chunk packing took " + (end - start) + "ms for " + chunk.x + "," + chunk.z); return bitSet; } @@ -69,7 +70,7 @@ public final class ChunkPacker implements Helper { return PathingBlockType.AVOID; } - if (block instanceof BlockAir || state.getCollisionBoundingBox(mc.world, pos) == NULL_AABB) { + if (block instanceof BlockAir) { return PathingBlockType.AIR; } diff --git a/src/main/java/baritone/bot/chunk/ICachedChunkAccess.java b/src/main/java/baritone/bot/chunk/ICachedChunkAccess.java deleted file mode 100644 index 9cb4e649..00000000 --- a/src/main/java/baritone/bot/chunk/ICachedChunkAccess.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.bot.chunk; - -import baritone.bot.utils.pathing.IBlockTypeAccess; - -import java.util.BitSet; - -/** - * @author Brady - * @since 8/4/2018 1:10 AM - */ -public interface ICachedChunkAccess extends IBlockTypeAccess { - - void updateCachedChunk(int chunkX, int chunkZ, BitSet data); -} diff --git a/src/main/java/baritone/bot/event/GameEventHandler.java b/src/main/java/baritone/bot/event/GameEventHandler.java index 4221d3bc..c83f6815 100644 --- a/src/main/java/baritone/bot/event/GameEventHandler.java +++ b/src/main/java/baritone/bot/event/GameEventHandler.java @@ -36,9 +36,7 @@ package baritone.bot.event; import baritone.bot.Baritone; import baritone.bot.behavior.Behavior; -import baritone.bot.chunk.CachedWorld; import baritone.bot.chunk.CachedWorldProvider; -import baritone.bot.chunk.ChunkPacker; import baritone.bot.event.events.*; import baritone.bot.event.events.type.EventState; import baritone.bot.event.listener.IGameEventListener; @@ -49,6 +47,7 @@ import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.settings.KeyBinding; +import net.minecraft.world.chunk.Chunk; import org.lwjgl.input.Keyboard; import java.util.function.Consumer; @@ -110,9 +109,10 @@ public final class GameEventHandler implements IGameEventListener, Helper { if (Baritone.settings().chunkCaching.get()) { if (isPostPopulate || isPreUnload) { - CachedWorldProvider.INSTANCE.ifWorldLoaded(world -> - world.updateCachedChunk(event.getX(), event.getZ(), - ChunkPacker.createPackedChunk(mc.world.getChunk(event.getX(), event.getZ())))); + CachedWorldProvider.INSTANCE.ifWorldLoaded(world -> { + Chunk chunk = mc.world.getChunk(event.getX(), event.getZ()); + world.queueForPacking(chunk); + }); } } @@ -137,7 +137,7 @@ public final class GameEventHandler implements IGameEventListener, Helper { switch (event.getState()) { case PRE: - cache.ifWorldLoaded(CachedWorld::save); + cache.closeWorld(); break; case POST: cache.closeWorld();