diff --git a/pom.xml b/pom.xml index a53f06917..4c86a507e 100644 --- a/pom.xml +++ b/pom.xml @@ -155,9 +155,9 @@ - com.github.Querz - NBT - 5.5 + io.timeandspace + smoothie-map + 2.0.2 diff --git a/src/main/java/com/volmit/iris/scaffold/engine/DirectWorldWriter.java b/src/main/java/com/volmit/iris/scaffold/engine/DirectWorldWriter.java index c0e7cb2d9..7e1d16ff7 100644 --- a/src/main/java/com/volmit/iris/scaffold/engine/DirectWorldWriter.java +++ b/src/main/java/com/volmit/iris/scaffold/engine/DirectWorldWriter.java @@ -5,9 +5,7 @@ import com.volmit.iris.nms.INMS; import com.volmit.iris.scaffold.cache.Cache; import com.volmit.iris.scaffold.parallel.BurstExecutor; import com.volmit.iris.scaffold.parallel.MultiBurst; -import com.volmit.iris.util.B; -import com.volmit.iris.util.KList; -import com.volmit.iris.util.KMap; +import com.volmit.iris.util.*; import net.querz.mca.Chunk; import net.querz.mca.MCAFile; import net.querz.mca.MCAUtil; @@ -24,41 +22,64 @@ import java.io.IOException; public class DirectWorldWriter { private final File worldFolder; private final KMap writeBuffer; + private final KMap lastUse; + private static final KMap blockDataCache = new KMap<>(); + private static final KMap biomeIds = computeBiomeIDs(); public DirectWorldWriter(File worldFolder) { this.worldFolder = worldFolder; + lastUse = new KMap<>(); writeBuffer = new KMap<>(); new File(worldFolder, "region").mkdirs(); } public void flush() { - BurstExecutor ex = MultiBurst.burst.burst(writeBuffer.size()); - writeBuffer.v().forEach((i) -> ex.queue(i::cleanupPalettesAndBlockStates)); - ex.complete(); BurstExecutor ex2 = MultiBurst.burst.burst(writeBuffer.size()); for(Long i : writeBuffer.k()) { - int x = Cache.keyX(i); - int z = Cache.keyZ(i); - try { - File f = getMCAFile(x, z); - - if(!f.exists()) - { - f.getParentFile().mkdirs(); - f.createNewFile(); - } - - MCAUtil.write(writeBuffer.get(i), f, true); - } catch (Throwable e) { - e.printStackTrace(); + if(M.ms() - lastUse.get(i) < 15000) + { + continue; } - } - writeBuffer.clear(); + ex2.queue(() -> { + int x = Cache.keyX(i); + int z = Cache.keyZ(i); + try { + File f = getMCAFile(x, z); + + if(!f.exists()) + { + f.getParentFile().mkdirs(); + f.createNewFile(); + } + + try + { + writeBuffer.get(i).cleanupPalettesAndBlockStates(); + } + + catch(Throwable e) + { + + } + + lastUse.remove(i); + MCAUtil.write(writeBuffer.get(i), f, true); + writeBuffer.remove(i); + } catch (Throwable e) { + e.printStackTrace(); + } + }); + } + } + + public void optimizeChunk(int x, int z) + { + getChunk(x, z).cleanupPalettesAndBlockStates(); } public File getMCAFile(int x, int z) @@ -66,8 +87,12 @@ public class DirectWorldWriter { return new File(worldFolder, "region/r." + x + "." + z + ".mca"); } - public BlockData getBlockData(CompoundTag tag) - { + public BlockData getBlockData(CompoundTag tag) { + if (tag == null) + { + return B.getAir(); + } + String p = tag.getString("Name"); if(tag.containsKey("Properties")) @@ -84,16 +109,29 @@ public class DirectWorldWriter { p += m.toString(",") + "]"; } - return B.get(p); + BlockData b = B.getOrNull(p); + + if(b == null) + { + return B.getAir(); + } + + return b; } public CompoundTag getCompound(BlockData blockData) { + String data = blockData.getAsString(true); + + if(blockDataCache.containsKey(data)) + { + return blockDataCache.get(data).clone(); + } + CompoundTag s = new CompoundTag(); NamespacedKey key = blockData.getMaterial().getKey(); s.putString("Name", key.getNamespace() + ":" + key.getKey()); - String data = blockData.getAsString(true); if(data.contains("[")) { @@ -120,6 +158,7 @@ public class DirectWorldWriter { s.put("Properties", props); } + blockDataCache.put(data, s.clone()); return s; } @@ -151,7 +190,7 @@ public class DirectWorldWriter { public void setBiome(int x, int y, int z, Biome biome) { - getChunk(x>>4, z>>4).setBiomeAt(x&15, y, z &15, INMS.get().getBiomeId(biome)); + getChunk(x>>4, z>>4).setBiomeAt(x&15, y, z &15, biomeIds.get(biome)); } public Section getChunkSection(int x, int y, int z) @@ -176,6 +215,7 @@ public class DirectWorldWriter { if(c == null) { c = Chunk.newChunk(); + lastUse.put(Cache.key(x >> 5, z >> 5), M.ms()); mca.setChunk(x&31, z&31, c); } @@ -204,7 +244,23 @@ public class DirectWorldWriter { } } + lastUse.put(key, M.ms()); writeBuffer.put(key, mca); return mca; } + + public int size() { + return writeBuffer.size(); + } + + private static KMap computeBiomeIDs() { + KMap biomeIds = new KMap<>(); + + for(Biome i : Biome.values()) + { + biomeIds.put(i, INMS.get().getBiomeId(i)); + } + + return biomeIds; + } } diff --git a/src/main/java/com/volmit/iris/scaffold/engine/EngineCompositeGenerator.java b/src/main/java/com/volmit/iris/scaffold/engine/EngineCompositeGenerator.java index 1b7bd5fb8..0185b5b4d 100644 --- a/src/main/java/com/volmit/iris/scaffold/engine/EngineCompositeGenerator.java +++ b/src/main/java/com/volmit/iris/scaffold/engine/EngineCompositeGenerator.java @@ -338,6 +338,7 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce { int ox = x << 4; int oz = z << 4; + net.querz.mca.Chunk cc = writer.getChunk(x, z); generateChunkRawData(w, x, z, new TerrainChunk() { @Override public void setRaw(ChunkData data) { @@ -356,12 +357,12 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce @Override public void setBiome(int x, int z, Biome bio) { - writer.setBiome(ox + x, 0, oz + z, bio); + setBiome(ox + x, 0, oz + z, bio); } @Override public void setBiome(int x, int y, int z, Biome bio) { - writer.setBiome(ox + x, y, oz + z, bio); + writer.setBiome((ox + x), y, oz + z, bio); } @Override @@ -371,12 +372,22 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce @Override public void setBlock(int x, int y, int z, BlockData blockData) { - writer.setBlockData(x+ox, y, z+oz, blockData); + cc.setBlockStateAt((x+ox)&15, y, (z+oz)&15, writer.getCompound(blockData), false); } @Override public BlockData getBlockData(int x, int y, int z) { - return writer.getBlockData(x + ox, y, z + oz); + if(y > getMaxHeight()) + { + y = getMaxHeight(); + } + + if(y < 0) + { + y = 0; + } + + return writer.getBlockData(cc.getBlockStateAt((x+ox)&15, y, (z+oz)&15)); } @Override @@ -431,6 +442,7 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce return 0; } }).run(); + writer.optimizeChunk(x, z); } public Chunk generatePaper(World world, int x, int z) diff --git a/src/main/java/com/volmit/iris/util/PregenJob.java b/src/main/java/com/volmit/iris/util/PregenJob.java index e7db8f98e..abe876c8e 100644 --- a/src/main/java/com/volmit/iris/util/PregenJob.java +++ b/src/main/java/com/volmit/iris/util/PregenJob.java @@ -147,6 +147,7 @@ public class PregenJob implements Listener { try { + instance.writer.flush(); Bukkit.getScheduler().cancelTask(task); if(consumer != null) @@ -172,6 +173,7 @@ public class PregenJob implements Listener instance.pms = instance.s.getMilliseconds(); instance.paused = true; instance.pausedAt = M.ms(); + instance.writer.flush(); } public static void resume() @@ -207,6 +209,8 @@ public class PregenJob implements Listener tick(skip); } + Iris.warn("Size: " + writer.size()); + PrecisionStopwatch p = PrecisionStopwatch.start(); if(PaperLib.isPaper()) diff --git a/src/main/java/net/querz/mca/Chunk.java b/src/main/java/net/querz/mca/Chunk.java index d305df04d..0236717f2 100644 --- a/src/main/java/net/querz/mca/Chunk.java +++ b/src/main/java/net/querz/mca/Chunk.java @@ -30,7 +30,7 @@ public class Chunk { private int[] biomes; private CompoundTag heightMaps; private CompoundTag carvingMasks; - private Section[] sections = new Section[16]; //always initialized with size = 16 for fast access + private final Section[] sections = new Section[16]; private ListTag entities; private ListTag tileEntities; private ListTag tileTicks; diff --git a/src/main/java/net/querz/mca/MCAFile.java b/src/main/java/net/querz/mca/MCAFile.java index 920372244..73eda6075 100644 --- a/src/main/java/net/querz/mca/MCAFile.java +++ b/src/main/java/net/querz/mca/MCAFile.java @@ -63,6 +63,11 @@ public class MCAFile { } } + public Chunk[] getChunks() + { + return chunks; + } + /** * Calls {@link MCAFile#serialize(RandomAccessFile, boolean)} without updating any timestamps. * @see MCAFile#serialize(RandomAccessFile, boolean) diff --git a/src/main/java/net/querz/mca/Section.java b/src/main/java/net/querz/mca/Section.java index 312035a39..51851d4de 100644 --- a/src/main/java/net/querz/mca/Section.java +++ b/src/main/java/net/querz/mca/Section.java @@ -1,19 +1,24 @@ package net.querz.mca; -import static net.querz.mca.LoadFlags.*; +import io.timeandspace.smoothie.OptimizationObjective; +import io.timeandspace.smoothie.SmoothieMap; import net.querz.nbt.tag.ByteArrayTag; import net.querz.nbt.tag.CompoundTag; import net.querz.nbt.tag.ListTag; import net.querz.nbt.tag.LongArrayTag; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import static net.querz.mca.LoadFlags.*; + public class Section { private CompoundTag data; - private Map> valueIndexedPalette = new HashMap<>(); + private Map> valueIndexedPalette = SmoothieMap.>newBuilder() + .optimizeFor(OptimizationObjective.FOOTPRINT).build(); private ListTag palette; private byte[] blockLight; private long[] blockStates; diff --git a/src/main/java/net/querz/nbt/tag/CompoundTag.java b/src/main/java/net/querz/nbt/tag/CompoundTag.java index 3909a72c1..eb8d35217 100644 --- a/src/main/java/net/querz/nbt/tag/CompoundTag.java +++ b/src/main/java/net/querz/nbt/tag/CompoundTag.java @@ -1,13 +1,9 @@ package net.querz.nbt.tag; +import com.volmit.iris.util.KMap; import net.querz.io.MaxDepthIO; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Objects; -import java.util.Set; +import java.util.*; import java.util.function.BiConsumer; public class CompoundTag extends Tag>> implements Iterable>>, Comparable, MaxDepthIO { @@ -24,7 +20,7 @@ public class CompoundTag extends Tag>> implements Iterable> createEmptyValue() { - return new HashMap<>(8); + return new KMap<>(); } public int size() { diff --git a/src/main/java/net/querz/nbt/tag/ListTag.java b/src/main/java/net/querz/nbt/tag/ListTag.java index 008e3aaa3..a72b94b51 100644 --- a/src/main/java/net/querz/nbt/tag/ListTag.java +++ b/src/main/java/net/querz/nbt/tag/ListTag.java @@ -1,13 +1,9 @@ package net.querz.nbt.tag; +import com.volmit.iris.util.KList; import net.querz.io.MaxDepthIO; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; +import java.util.*; import java.util.function.Consumer; /** @@ -52,10 +48,10 @@ public class ListTag> extends Tag> implements Iterable< * * @param Type of the list elements * @param initialCapacity The initial capacity of the returned List - * @return An instance of {@link java.util.List} with an initial capacity of 3 + * @return An instance of {@link List} with an initial capacity of 3 * */ private static List createEmptyValue(int initialCapacity) { - return new ArrayList<>(initialCapacity); + return new KList<>(initialCapacity); } /**