mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-19 10:43:14 +00:00
Optimizations
This commit is contained in:
parent
4f3b6e4029
commit
540656870a
6
pom.xml
6
pom.xml
@ -155,9 +155,9 @@
|
|||||||
</repositories>
|
</repositories>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.Querz</groupId>
|
<groupId>io.timeandspace</groupId>
|
||||||
<artifactId>NBT</artifactId>
|
<artifactId>smoothie-map</artifactId>
|
||||||
<version>5.5</version>
|
<version>2.0.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- Spigot API -->
|
<!-- Spigot API -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -5,9 +5,7 @@ import com.volmit.iris.nms.INMS;
|
|||||||
import com.volmit.iris.scaffold.cache.Cache;
|
import com.volmit.iris.scaffold.cache.Cache;
|
||||||
import com.volmit.iris.scaffold.parallel.BurstExecutor;
|
import com.volmit.iris.scaffold.parallel.BurstExecutor;
|
||||||
import com.volmit.iris.scaffold.parallel.MultiBurst;
|
import com.volmit.iris.scaffold.parallel.MultiBurst;
|
||||||
import com.volmit.iris.util.B;
|
import com.volmit.iris.util.*;
|
||||||
import com.volmit.iris.util.KList;
|
|
||||||
import com.volmit.iris.util.KMap;
|
|
||||||
import net.querz.mca.Chunk;
|
import net.querz.mca.Chunk;
|
||||||
import net.querz.mca.MCAFile;
|
import net.querz.mca.MCAFile;
|
||||||
import net.querz.mca.MCAUtil;
|
import net.querz.mca.MCAUtil;
|
||||||
@ -24,23 +22,30 @@ import java.io.IOException;
|
|||||||
public class DirectWorldWriter {
|
public class DirectWorldWriter {
|
||||||
private final File worldFolder;
|
private final File worldFolder;
|
||||||
private final KMap<Long, MCAFile> writeBuffer;
|
private final KMap<Long, MCAFile> writeBuffer;
|
||||||
|
private final KMap<Long, Long> lastUse;
|
||||||
|
private static final KMap<String, CompoundTag> blockDataCache = new KMap<>();
|
||||||
|
private static final KMap<Biome, Integer> biomeIds = computeBiomeIDs();
|
||||||
|
|
||||||
public DirectWorldWriter(File worldFolder)
|
public DirectWorldWriter(File worldFolder)
|
||||||
{
|
{
|
||||||
this.worldFolder = worldFolder;
|
this.worldFolder = worldFolder;
|
||||||
|
lastUse = new KMap<>();
|
||||||
writeBuffer = new KMap<>();
|
writeBuffer = new KMap<>();
|
||||||
new File(worldFolder, "region").mkdirs();
|
new File(worldFolder, "region").mkdirs();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flush()
|
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());
|
BurstExecutor ex2 = MultiBurst.burst.burst(writeBuffer.size());
|
||||||
|
|
||||||
for(Long i : writeBuffer.k())
|
for(Long i : writeBuffer.k())
|
||||||
{
|
{
|
||||||
|
if(M.ms() - lastUse.get(i) < 15000)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ex2.queue(() -> {
|
||||||
int x = Cache.keyX(i);
|
int x = Cache.keyX(i);
|
||||||
int z = Cache.keyZ(i);
|
int z = Cache.keyZ(i);
|
||||||
try {
|
try {
|
||||||
@ -52,13 +57,29 @@ public class DirectWorldWriter {
|
|||||||
f.createNewFile();
|
f.createNewFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
writeBuffer.get(i).cleanupPalettesAndBlockStates();
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(Throwable e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
lastUse.remove(i);
|
||||||
MCAUtil.write(writeBuffer.get(i), f, true);
|
MCAUtil.write(writeBuffer.get(i), f, true);
|
||||||
|
writeBuffer.remove(i);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writeBuffer.clear();
|
public void optimizeChunk(int x, int z)
|
||||||
|
{
|
||||||
|
getChunk(x, z).cleanupPalettesAndBlockStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getMCAFile(int x, int z)
|
public File getMCAFile(int x, int z)
|
||||||
@ -66,8 +87,12 @@ public class DirectWorldWriter {
|
|||||||
return new File(worldFolder, "region/r." + x + "." + z + ".mca");
|
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");
|
String p = tag.getString("Name");
|
||||||
|
|
||||||
if(tag.containsKey("Properties"))
|
if(tag.containsKey("Properties"))
|
||||||
@ -84,16 +109,29 @@ public class DirectWorldWriter {
|
|||||||
p += m.toString(",") + "]";
|
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)
|
public CompoundTag getCompound(BlockData blockData)
|
||||||
{
|
{
|
||||||
|
String data = blockData.getAsString(true);
|
||||||
|
|
||||||
|
if(blockDataCache.containsKey(data))
|
||||||
|
{
|
||||||
|
return blockDataCache.get(data).clone();
|
||||||
|
}
|
||||||
|
|
||||||
CompoundTag s = new CompoundTag();
|
CompoundTag s = new CompoundTag();
|
||||||
NamespacedKey key = blockData.getMaterial().getKey();
|
NamespacedKey key = blockData.getMaterial().getKey();
|
||||||
s.putString("Name", key.getNamespace() + ":" + key.getKey());
|
s.putString("Name", key.getNamespace() + ":" + key.getKey());
|
||||||
|
|
||||||
String data = blockData.getAsString(true);
|
|
||||||
|
|
||||||
if(data.contains("["))
|
if(data.contains("["))
|
||||||
{
|
{
|
||||||
@ -120,6 +158,7 @@ public class DirectWorldWriter {
|
|||||||
s.put("Properties", props);
|
s.put("Properties", props);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
blockDataCache.put(data, s.clone());
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +190,7 @@ public class DirectWorldWriter {
|
|||||||
|
|
||||||
public void setBiome(int x, int y, int z, Biome biome)
|
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)
|
public Section getChunkSection(int x, int y, int z)
|
||||||
@ -176,6 +215,7 @@ public class DirectWorldWriter {
|
|||||||
if(c == null)
|
if(c == null)
|
||||||
{
|
{
|
||||||
c = Chunk.newChunk();
|
c = Chunk.newChunk();
|
||||||
|
lastUse.put(Cache.key(x >> 5, z >> 5), M.ms());
|
||||||
mca.setChunk(x&31, z&31, c);
|
mca.setChunk(x&31, z&31, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +244,23 @@ public class DirectWorldWriter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastUse.put(key, M.ms());
|
||||||
writeBuffer.put(key, mca);
|
writeBuffer.put(key, mca);
|
||||||
return mca;
|
return mca;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return writeBuffer.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static KMap<Biome, Integer> computeBiomeIDs() {
|
||||||
|
KMap<Biome, Integer> biomeIds = new KMap<>();
|
||||||
|
|
||||||
|
for(Biome i : Biome.values())
|
||||||
|
{
|
||||||
|
biomeIds.put(i, INMS.get().getBiomeId(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return biomeIds;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,6 +338,7 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
|||||||
{
|
{
|
||||||
int ox = x << 4;
|
int ox = x << 4;
|
||||||
int oz = z << 4;
|
int oz = z << 4;
|
||||||
|
net.querz.mca.Chunk cc = writer.getChunk(x, z);
|
||||||
generateChunkRawData(w, x, z, new TerrainChunk() {
|
generateChunkRawData(w, x, z, new TerrainChunk() {
|
||||||
@Override
|
@Override
|
||||||
public void setRaw(ChunkData data) {
|
public void setRaw(ChunkData data) {
|
||||||
@ -356,12 +357,12 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBiome(int x, int z, Biome bio) {
|
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
|
@Override
|
||||||
public void setBiome(int x, int y, int z, Biome bio) {
|
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
|
@Override
|
||||||
@ -371,12 +372,22 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBlock(int x, int y, int z, BlockData blockData) {
|
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
|
@Override
|
||||||
public BlockData getBlockData(int x, int y, int z) {
|
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
|
@Override
|
||||||
@ -431,6 +442,7 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}).run();
|
}).run();
|
||||||
|
writer.optimizeChunk(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Chunk generatePaper(World world, int x, int z)
|
public Chunk generatePaper(World world, int x, int z)
|
||||||
|
@ -147,6 +147,7 @@ public class PregenJob implements Listener
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
instance.writer.flush();
|
||||||
Bukkit.getScheduler().cancelTask(task);
|
Bukkit.getScheduler().cancelTask(task);
|
||||||
|
|
||||||
if(consumer != null)
|
if(consumer != null)
|
||||||
@ -172,6 +173,7 @@ public class PregenJob implements Listener
|
|||||||
instance.pms = instance.s.getMilliseconds();
|
instance.pms = instance.s.getMilliseconds();
|
||||||
instance.paused = true;
|
instance.paused = true;
|
||||||
instance.pausedAt = M.ms();
|
instance.pausedAt = M.ms();
|
||||||
|
instance.writer.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void resume()
|
public static void resume()
|
||||||
@ -207,6 +209,8 @@ public class PregenJob implements Listener
|
|||||||
tick(skip);
|
tick(skip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Iris.warn("Size: " + writer.size());
|
||||||
|
|
||||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||||
|
|
||||||
if(PaperLib.isPaper())
|
if(PaperLib.isPaper())
|
||||||
|
@ -30,7 +30,7 @@ public class Chunk {
|
|||||||
private int[] biomes;
|
private int[] biomes;
|
||||||
private CompoundTag heightMaps;
|
private CompoundTag heightMaps;
|
||||||
private CompoundTag carvingMasks;
|
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<CompoundTag> entities;
|
private ListTag<CompoundTag> entities;
|
||||||
private ListTag<CompoundTag> tileEntities;
|
private ListTag<CompoundTag> tileEntities;
|
||||||
private ListTag<CompoundTag> tileTicks;
|
private ListTag<CompoundTag> tileTicks;
|
||||||
|
@ -63,6 +63,11 @@ public class MCAFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Chunk[] getChunks()
|
||||||
|
{
|
||||||
|
return chunks;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls {@link MCAFile#serialize(RandomAccessFile, boolean)} without updating any timestamps.
|
* Calls {@link MCAFile#serialize(RandomAccessFile, boolean)} without updating any timestamps.
|
||||||
* @see MCAFile#serialize(RandomAccessFile, boolean)
|
* @see MCAFile#serialize(RandomAccessFile, boolean)
|
||||||
|
@ -1,19 +1,24 @@
|
|||||||
package net.querz.mca;
|
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.ByteArrayTag;
|
||||||
import net.querz.nbt.tag.CompoundTag;
|
import net.querz.nbt.tag.CompoundTag;
|
||||||
import net.querz.nbt.tag.ListTag;
|
import net.querz.nbt.tag.ListTag;
|
||||||
import net.querz.nbt.tag.LongArrayTag;
|
import net.querz.nbt.tag.LongArrayTag;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static net.querz.mca.LoadFlags.*;
|
||||||
|
|
||||||
public class Section {
|
public class Section {
|
||||||
|
|
||||||
private CompoundTag data;
|
private CompoundTag data;
|
||||||
private Map<String, List<PaletteIndex>> valueIndexedPalette = new HashMap<>();
|
private Map<String, List<PaletteIndex>> valueIndexedPalette = SmoothieMap.<String, List<PaletteIndex>>newBuilder()
|
||||||
|
.optimizeFor(OptimizationObjective.FOOTPRINT).build();
|
||||||
private ListTag<CompoundTag> palette;
|
private ListTag<CompoundTag> palette;
|
||||||
private byte[] blockLight;
|
private byte[] blockLight;
|
||||||
private long[] blockStates;
|
private long[] blockStates;
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
package net.querz.nbt.tag;
|
package net.querz.nbt.tag;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.KMap;
|
||||||
import net.querz.io.MaxDepthIO;
|
import net.querz.io.MaxDepthIO;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
public class CompoundTag extends Tag<Map<String, Tag<?>>> implements Iterable<Map.Entry<String, Tag<?>>>, Comparable<CompoundTag>, MaxDepthIO {
|
public class CompoundTag extends Tag<Map<String, Tag<?>>> implements Iterable<Map.Entry<String, Tag<?>>>, Comparable<CompoundTag>, MaxDepthIO {
|
||||||
@ -24,7 +20,7 @@ public class CompoundTag extends Tag<Map<String, Tag<?>>> implements Iterable<Ma
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Map<String, Tag<?>> createEmptyValue() {
|
private static Map<String, Tag<?>> createEmptyValue() {
|
||||||
return new HashMap<>(8);
|
return new KMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
package net.querz.nbt.tag;
|
package net.querz.nbt.tag;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.KList;
|
||||||
import net.querz.io.MaxDepthIO;
|
import net.querz.io.MaxDepthIO;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,10 +48,10 @@ public class ListTag<T extends Tag<?>> extends Tag<List<T>> implements Iterable<
|
|||||||
*
|
*
|
||||||
* @param <T> Type of the list elements
|
* @param <T> Type of the list elements
|
||||||
* @param initialCapacity The initial capacity of the returned List
|
* @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 <T> List<T> createEmptyValue(int initialCapacity) {
|
private static <T> List<T> createEmptyValue(int initialCapacity) {
|
||||||
return new ArrayList<>(initialCapacity);
|
return new KList<>(initialCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user