This commit is contained in:
cyberpwn 2021-08-24 08:24:36 -04:00
parent 6dc3e74607
commit 7b6405fba7
11 changed files with 189 additions and 139 deletions

View File

@ -167,6 +167,7 @@ shadowJar
include(dependency('io.papermc:paperlib')) include(dependency('io.papermc:paperlib'))
include(dependency('com.dfsek:Paralithic')) include(dependency('com.dfsek:Paralithic'))
include(dependency('net.kyori:')) include(dependency('net.kyori:'))
include(dependency('com.github.Querz:NBT'))
} }
} }
@ -185,6 +186,7 @@ dependencies {
implementation "net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT" implementation "net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT"
implementation "net.kyori:adventure-platform-bukkit:4.0.0-SNAPSHOT" implementation "net.kyori:adventure-platform-bukkit:4.0.0-SNAPSHOT"
implementation 'net.kyori:adventure-api:4.8.1' implementation 'net.kyori:adventure-api:4.8.1'
implementation 'com.github.Querz:NBT:6.1'
// Dynamically Loaded // Dynamically Loaded
implementation 'io.timeandspace:smoothie-map:2.0.2' implementation 'io.timeandspace:smoothie-map:2.0.2'

View File

@ -128,7 +128,8 @@ public class IrisToolbelt {
return pregenerate(task, new HeadlessPregenMethod(((HeadlessGenerator) gen).getWorld(), (HeadlessGenerator) gen)); return pregenerate(task, new HeadlessPregenMethod(((HeadlessGenerator) gen).getWorld(), (HeadlessGenerator) gen));
} }
return pregenerate(task, new HybridPregenMethod(gen.getEngine().getWorld().realWorld(), IrisSettings.getThreadCount((int) IrisSettings.get().getConcurrency().getParallelism()))); return pregenerate(task, new HybridPregenMethod(gen.getEngine().getWorld().realWorld(),
IrisSettings.getThreadCount((int) IrisSettings.get().getConcurrency().getParallelism())));
} }
/** /**

View File

@ -54,7 +54,10 @@ import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.PrecisionStopwatch; import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import net.minecraft.world.level.block.state.IBlockData;
import org.bukkit.Bukkit;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
@ -405,26 +408,42 @@ public class IrisEngine implements Engine {
context.touch(); context.touch();
getEngineData().getStatistics().generatedChunk(); getEngineData().getStatistics().generatedChunk();
try { try {
PrecisionStopwatch p = PrecisionStopwatch.start(); PrecisionStopwatch p = PrecisionStopwatch.start();
Hunk<BlockData> blocks = vblocks.listen((xx, y, zz, t) -> catchBlockUpdates(x + xx, y + getMinHeight(), z + zz, t)); Hunk<BlockData> blocks = vblocks.listen((xx, y, zz, t) -> catchBlockUpdates(x + xx, y + getMinHeight(), z + zz, t));
getMantle().generateMatter(x >> 4, z >> 4, multicore);
burst().burst(multicore, if(multicore)
() -> getTerrainActuator().actuate(x, z, vblocks, multicore), {
() -> getBiomeActuator().actuate(x, z, vbiomes, multicore) for (int i = 0; i < 16; i++) {
); for (int j = 0; j < 16; j++) {
burst().burst(multicore, blocks.set(i, 0, j, Material.RED_GLAZED_TERRACOTTA.createBlockData());
() -> getCaveModifier().modify(x, z, vblocks, multicore), }
() -> getDecorantActuator().actuate(x, z, blocks, multicore), }
() -> getRavineModifier().modify(x, z, vblocks, multicore) }
);
else
{
getMantle().generateMatter(x >> 4, z >> 4, multicore);
burst().burst(multicore,
() -> getTerrainActuator().actuate(x, z, vblocks, multicore),
() -> getBiomeActuator().actuate(x, z, vbiomes, multicore)
);
burst().burst(multicore,
() -> getCaveModifier().modify(x, z, vblocks, multicore),
() -> getDecorantActuator().actuate(x, z, blocks, multicore),
() -> getRavineModifier().modify(x, z, vblocks, multicore)
);
getPostModifier().modify(x, z, vblocks, multicore);
burst().burst(multicore,
() -> getMantle().insertMatter(x >> 4, z >> 4, BlockData.class, blocks, multicore),
() -> getDepositModifier().modify(x, z, vblocks, multicore)
);
}
getPostModifier().modify(x, z, vblocks, multicore);
burst().burst(multicore,
() -> getMantle().insertMatter(x >> 4, z >> 4, BlockData.class, blocks, multicore),
() -> getDepositModifier().modify(x, z, vblocks, multicore)
);
getMetrics().getTotal().put(p.getMilliseconds()); getMetrics().getTotal().put(p.getMilliseconds());
generated.incrementAndGet(); generated.incrementAndGet();

View File

@ -18,107 +18,82 @@
package com.volmit.iris.engine.data.cache; package com.volmit.iris.engine.data.cache;
import com.volmit.iris.util.math.M; import com.volmit.iris.Iris;
import com.volmit.iris.util.scheduling.IrisLock;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier; import java.util.function.Supplier;
public class AtomicCache<T> { public class AtomicCache<T> {
private transient volatile T t; private transient final AtomicReference<T> t;
private transient volatile long a; private transient final AtomicBoolean set;
private transient volatile int validations; private transient final ReentrantLock lock;
private final IrisLock check; private transient final boolean nullSupport;
private final IrisLock time;
private final IrisLock write;
private final boolean nullSupport;
public AtomicCache() { public AtomicCache() {
this(false); this(false);
} }
public AtomicCache(boolean nullSupport) { public AtomicCache(boolean nullSupport) {
set = nullSupport ? new AtomicBoolean() : null;
t = new AtomicReference<>();
lock = new ReentrantLock();
this.nullSupport = nullSupport; this.nullSupport = nullSupport;
check = new IrisLock("Check");
write = new IrisLock("Write");
time = new IrisLock("Time");
validations = 0;
a = -1;
t = null;
} }
public void reset() { public void reset() {
check.lock(); t.set(null);
write.lock();
time.lock(); if(nullSupport)
a = -1; {
t = null; set.set(false);
time.unlock(); }
write.unlock();
check.unlock();
} }
public T aquire(Supplier<T> t) { public T aquire(Supplier<T> t) {
if (nullSupport) { if(this.t.get() != null)
return aquireNull(t); {
return this.t.get();
} }
if (this.t != null && validations > 1000) { else if(nullSupport && set.get())
return this.t; {
return null;
} }
if (this.t != null && M.ms() - a > 1000) { lock.lock();
if (this.t != null) {
//noinspection NonAtomicOperationOnVolatileField if(this.t.get() != null)
validations++; {
lock.unlock();
return this.t.get();
}
else if(nullSupport && set.get())
{
lock.unlock();
return null;
}
try
{
this.t.set(t.get());
if(nullSupport)
{
set.set(true);
} }
return this.t;
} }
check.lock(); catch(Throwable e)
{
if (this.t == null) { Iris.error("Atomic cache failure!");
write.lock(); e.printStackTrace();
this.t = t.get();
time.lock();
if (a == -1) {
a = M.ms();
}
time.unlock();
write.unlock();
} }
check.unlock(); lock.unlock();
return this.t;
}
public T aquireNull(Supplier<T> t) { return t.get();
if (validations > 1000) {
return this.t;
}
if (M.ms() - a > 1000) {
//noinspection NonAtomicOperationOnVolatileField
validations++;
return this.t;
}
check.lock();
write.lock();
this.t = t.get();
time.lock();
if (a == -1) {
a = M.ms();
}
time.unlock();
write.unlock();
check.unlock();
return this.t;
} }
} }

View File

@ -198,8 +198,8 @@ public class IrisBiome extends IrisRegistrant implements IRare {
private final transient AtomicCache<KMap<String, IrisBiomeGeneratorLink>> genCache = new AtomicCache<>(); private final transient AtomicCache<KMap<String, IrisBiomeGeneratorLink>> genCache = new AtomicCache<>();
private final transient AtomicCache<KMap<String, Integer>> genCacheMax = new AtomicCache<>(); private final transient AtomicCache<KMap<String, Integer>> genCacheMax = new AtomicCache<>();
private final transient AtomicCache<KMap<String, Integer>> genCacheMin = new AtomicCache<>(); private final transient AtomicCache<KMap<String, Integer>> genCacheMin = new AtomicCache<>();
private final transient AtomicCache<KList<IrisObjectPlacement>> surfaceObjectsCache = new AtomicCache<>(false); private final transient AtomicCache<KList<IrisObjectPlacement>> surfaceObjectsCache = new AtomicCache<>();
private final transient AtomicCache<KList<IrisObjectPlacement>> carveObjectsCache = new AtomicCache<>(false); private final transient AtomicCache<KList<IrisObjectPlacement>> carveObjectsCache = new AtomicCache<>();
private final transient AtomicCache<Color> cacheColor = new AtomicCache<>(); private final transient AtomicCache<Color> cacheColor = new AtomicCache<>();
private final transient AtomicCache<Color> cacheColorObjectDensity = new AtomicCache<>(); private final transient AtomicCache<Color> cacheColorObjectDensity = new AtomicCache<>();
private final transient AtomicCache<Color> cacheColorDecoratorLoad = new AtomicCache<>(); private final transient AtomicCache<Color> cacheColorDecoratorLoad = new AtomicCache<>();

View File

@ -22,6 +22,7 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.project.loader.IrisData; import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.core.service.StudioSVC; import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.dimensional.IrisDimension; import com.volmit.iris.engine.object.dimensional.IrisDimension;
import com.volmit.iris.engine.platform.BukkitChunkGenerator; import com.volmit.iris.engine.platform.BukkitChunkGenerator;
import com.volmit.iris.engine.platform.HeadlessGenerator; import com.volmit.iris.engine.platform.HeadlessGenerator;
@ -65,8 +66,24 @@ public class HeadlessWorld {
} }
} }
@SuppressWarnings("ConstantConditions")
public HeadlessGenerator generate() { public HeadlessGenerator generate() {
return new HeadlessGenerator(this); Engine e = null;
if(getWorld().tryGetRealWorld())
{
if(IrisToolbelt.isIrisWorld(getWorld().realWorld()))
{
e = IrisToolbelt.access(getWorld().realWorld()).getEngine();
}
}
if(e != null)
{
Iris.info("Using Existing Engine " + getWorld().name() + " for Headless Pregeneration.");
}
return e != null ? new HeadlessGenerator(this, e) : new HeadlessGenerator(this);
} }
public World load() { public World load() {
@ -81,7 +98,8 @@ public class HeadlessWorld {
} }
public static HeadlessWorld from(World world) { public static HeadlessWorld from(World world) {
return new HeadlessWorld(world.getName(), IrisToolbelt.access(world).getEngine().getTarget().getDimension(), world.getSeed()); return new HeadlessWorld(world.getName(), IrisToolbelt.access(world)
.getEngine().getTarget().getDimension(), world.getSeed());
} }
public static HeadlessWorld from(String name, String dimension, long seed) { public static HeadlessWorld from(String name, String dimension, long seed) {

View File

@ -24,6 +24,7 @@ import com.volmit.iris.util.collection.KList;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@ -61,6 +62,24 @@ public class IrisWorld {
.environment(world.getEnvironment()); .environment(world.getEnvironment());
} }
public boolean tryGetRealWorld()
{
if(hasRealWorld())
{
return true;
}
World w = Bukkit.getWorld(name);
if(w != null)
{
realWorld = w;
return true;
}
return false;
}
public boolean hasRealWorld() { public boolean hasRealWorld() {
return realWorld != null; return realWorld != null;
} }

View File

@ -176,6 +176,8 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
@Override @Override
public @NotNull ChunkData generateChunkData(@NotNull World world, @NotNull Random ignored, int x, int z, @NotNull BiomeGrid biome) { public @NotNull ChunkData generateChunkData(@NotNull World world, @NotNull Random ignored, int x, int z, @NotNull BiomeGrid biome) {
try { try {
if(lastSeed != world.getSeed()) if(lastSeed != world.getSeed())
{ {

View File

@ -24,16 +24,20 @@ import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.pregenerator.PregenListener; import com.volmit.iris.core.pregenerator.PregenListener;
import com.volmit.iris.core.pregenerator.PregenTask; import com.volmit.iris.core.pregenerator.PregenTask;
import com.volmit.iris.engine.IrisEngine; import com.volmit.iris.engine.IrisEngine;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.data.chunk.MCATerrainChunk; import com.volmit.iris.engine.data.chunk.MCATerrainChunk;
import com.volmit.iris.engine.data.chunk.TerrainChunk; import com.volmit.iris.engine.data.chunk.TerrainChunk;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineTarget; import com.volmit.iris.engine.framework.EngineTarget;
import com.volmit.iris.engine.framework.WrongEngineBroException;
import com.volmit.iris.engine.object.common.HeadlessWorld; import com.volmit.iris.engine.object.common.HeadlessWorld;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.documentation.RegionCoordinates; import com.volmit.iris.util.documentation.RegionCoordinates;
import com.volmit.iris.util.hunk.Hunk; import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.math.Position2; import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.nbt.mca.MCAFile; import com.volmit.iris.util.nbt.mca.MCAFile;
import com.volmit.iris.util.nbt.mca.MCAUtil; import com.volmit.iris.util.nbt.mca.MCAUtil;
import com.volmit.iris.util.nbt.mca.NBTWorld; import com.volmit.iris.util.nbt.mca.NBTWorld;
@ -56,12 +60,17 @@ public class HeadlessGenerator implements PlatformChunkGenerator {
private final NBTWorld writer; private final NBTWorld writer;
private final MultiBurst burst; private final MultiBurst burst;
private final Engine engine; private final Engine engine;
private final long rkey = RNG.r.lmax();
public HeadlessGenerator(HeadlessWorld world) { public HeadlessGenerator(HeadlessWorld world) {
this(world, new IrisEngine(new EngineTarget(world.getWorld(), world.getDimension(), world.getDimension().getLoader()), world.isStudio()));
}
public HeadlessGenerator(HeadlessWorld world, Engine engine) {
this.engine = engine;
this.world = world; this.world = world;
burst = MultiBurst.burst; burst = MultiBurst.burst;
writer = new NBTWorld(world.getWorld().worldFolder()); writer = new NBTWorld(world.getWorld().worldFolder());
engine = new IrisEngine(new EngineTarget(world.getWorld(), world.getDimension(), world.getDimension().getLoader()), isStudio());
} }
@ChunkCoordinates @ChunkCoordinates
@ -79,6 +88,7 @@ public class HeadlessGenerator implements PlatformChunkGenerator {
getEngine().generate(x * 16, z * 16, getEngine().generate(x * 16, z * 16,
Hunk.view((ChunkGenerator.ChunkData) tc), Hunk.view((ChunkGenerator.BiomeGrid) tc), Hunk.view((ChunkGenerator.ChunkData) tc), Hunk.view((ChunkGenerator.BiomeGrid) tc),
false); false);
chunk.cleanupPalettesAndBlockStates();
} catch (Throwable e) { } catch (Throwable e) {
Iris.error("======================================"); Iris.error("======================================");
e.printStackTrace(); e.printStackTrace();
@ -102,7 +112,7 @@ public class HeadlessGenerator implements PlatformChunkGenerator {
@RegionCoordinates @RegionCoordinates
public void generateRegion(int x, int z, PregenListener listener) { public void generateRegion(int x, int z, PregenListener listener) {
BurstExecutor e = burst.burst(1024); BurstExecutor e = burst.burst(1024);
MCAFile f = writer.getMCA(x, x); MCAFile f = writer.getMCA(x, z);
PregenTask.iterateRegion(x, z, (ii, jj) -> e.queue(() -> { PregenTask.iterateRegion(x, z, (ii, jj) -> e.queue(() -> {
if (listener != null) { if (listener != null) {
listener.onChunkGenerating(ii, jj); listener.onChunkGenerating(ii, jj);
@ -132,7 +142,6 @@ public class HeadlessGenerator implements PlatformChunkGenerator {
} }
public void close() { public void close() {
getEngine().close();
writer.close(); writer.close();
} }

View File

@ -28,21 +28,49 @@ import com.volmit.iris.util.math.M;
import com.volmit.iris.util.nbt.tag.CompoundTag; import com.volmit.iris.util.nbt.tag.CompoundTag;
import com.volmit.iris.util.nbt.tag.StringTag; import com.volmit.iris.util.nbt.tag.StringTag;
import com.volmit.iris.util.parallel.HyperLock; import com.volmit.iris.util.parallel.HyperLock;
import com.volmit.iris.util.scheduling.IrisLock;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import javax.management.RuntimeErrorException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Function;
public class NBTWorld { public class NBTWorld {
private static final BlockData AIR = B.get("AIR"); private static final BlockData AIR = B.get("AIR");
private static final Map<String, CompoundTag> blockDataCache = new KMap<>(); private static final Map<BlockData, CompoundTag> blockDataCache = new KMap<>();
private static final Function<BlockData, CompoundTag> BLOCK_DATA_COMPUTE = (blockData) -> {
CompoundTag s = new CompoundTag();
String data = blockData.getAsString(true);
NamespacedKey key = blockData.getMaterial().getKey();
s.putString("Name", key.getNamespace() + ":" + key.getKey());
if (data.contains("[")) {
String raw = data.split("\\Q[\\E")[1].replaceAll("\\Q]\\E", "");
CompoundTag props = new CompoundTag();
if (raw.contains(",")) {
for (String i : raw.split("\\Q,\\E")) {
String[] m = i.split("\\Q=\\E");
String k = m[0];
String v = m[1];
props.put(k, new StringTag(v));
}
} else {
String[] m = raw.split("\\Q=\\E");
String k = m[0];
String v = m[1];
props.put(k, new StringTag(v));
}
s.put("Properties", props);
}
return s;
};
private static final Map<Biome, Integer> biomeIds = computeBiomeIDs(); private static final Map<Biome, Integer> biomeIds = computeBiomeIDs();
private final KMap<Long, MCAFile> loadedRegions; private final KMap<Long, MCAFile> loadedRegions;
private final HyperLock hyperLock = new HyperLock(); private final HyperLock hyperLock = new HyperLock();
@ -184,38 +212,8 @@ public class NBTWorld {
return b; return b;
} }
public static CompoundTag getCompound(BlockData blockData) { public static CompoundTag getCompound(BlockData bd) {
String data = blockData.getAsString(true); return blockDataCache.computeIfAbsent(bd, BLOCK_DATA_COMPUTE).clone();
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());
if (data.contains("[")) {
String raw = data.split("\\Q[\\E")[1].replaceAll("\\Q]\\E", "");
CompoundTag props = new CompoundTag();
if (raw.contains(",")) {
for (String i : raw.split("\\Q,\\E")) {
String[] m = i.split("\\Q=\\E");
String k = m[0];
String v = m[1];
props.put(k, new StringTag(v));
}
} else {
String[] m = raw.split("\\Q=\\E");
String k = m[0];
String v = m[1];
props.put(k, new StringTag(v));
}
s.put("Properties", props);
}
blockDataCache.put(data, s.clone());
return s;
} }
public BlockData getBlockData(int x, int y, int z) { public BlockData getBlockData(int x, int y, int z) {
@ -275,6 +273,13 @@ public class NBTWorld {
return c; return c;
} }
public Chunk getNewChunk(MCAFile mca, int x, int z) {
Chunk c = Chunk.newChunk();
mca.setChunk(x & 31, z & 31, c);
return c;
}
public long getIdleDuration(int x, int z) { public long getIdleDuration(int x, int z) {
return hyperLock.withResult(x, z, () -> { return hyperLock.withResult(x, z, () -> {
Long l = lastUse.get(Cache.key(x, z)); Long l = lastUse.get(Cache.key(x, z));

View File

@ -25,6 +25,7 @@ import com.volmit.iris.util.nbt.tag.CompoundTag;
import com.volmit.iris.util.nbt.tag.ListTag; import com.volmit.iris.util.nbt.tag.ListTag;
import com.volmit.iris.util.nbt.tag.LongArrayTag; import com.volmit.iris.util.nbt.tag.LongArrayTag;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import net.minecraft.world.level.chunk.DataPaletteGlobal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -148,7 +149,7 @@ public class Section {
* @param blockZ The z-coordinate of the block in this Section * @param blockZ The z-coordinate of the block in this Section
* @return The block state data of this block. * @return The block state data of this block.
*/ */
public CompoundTag getBlockStateAt(int blockX, int blockY, int blockZ) { public synchronized CompoundTag getBlockStateAt(int blockX, int blockY, int blockZ) {
try { try {
int index = getBlockIndex(blockX, blockY, blockZ); int index = getBlockIndex(blockX, blockY, blockZ);
int paletteIndex = getPaletteIndex(index); int paletteIndex = getPaletteIndex(index);
@ -172,7 +173,7 @@ public class Section {
* This option should only be used moderately to avoid unnecessary recalculation of the palette indices. * This option should only be used moderately to avoid unnecessary recalculation of the palette indices.
* Recalculating the Palette should only be executed once right before saving the Section to file. * Recalculating the Palette should only be executed once right before saving the Section to file.
*/ */
public void setBlockStateAt(int blockX, int blockY, int blockZ, CompoundTag state, boolean cleanup) { public synchronized void setBlockStateAt(int blockX, int blockY, int blockZ, CompoundTag state, boolean cleanup) {
int paletteIndex = addToPalette(state); int paletteIndex = addToPalette(state);
int paletteSizeBefore = palette.size(); int paletteSizeBefore = palette.size();
//power of 2 --> bits must increase, but only if the palette size changed //power of 2 --> bits must increase, but only if the palette size changed
@ -184,7 +185,6 @@ public class Section {
} }
setPaletteIndex(getBlockIndex(blockX, blockY, blockZ), paletteIndex, blockStates); setPaletteIndex(getBlockIndex(blockX, blockY, blockZ), paletteIndex, blockStates);
if (cleanup) { if (cleanup) {
cleanupPaletteAndBlockStates(); cleanupPaletteAndBlockStates();
} }
@ -196,7 +196,7 @@ public class Section {
* @param blockStateIndex The index of the block in this section, ranging from 0-4095. * @param blockStateIndex The index of the block in this section, ranging from 0-4095.
* @return The index of the block data in the palette. * @return The index of the block data in the palette.
*/ */
public int getPaletteIndex(int blockStateIndex) { public synchronized int getPaletteIndex(int blockStateIndex) {
int bits = blockStates.length() >> 6; int bits = blockStates.length() >> 6;
if (dataVersion < 2527) { if (dataVersion < 2527) {
@ -251,7 +251,7 @@ public class Section {
* *
* @return The palette of this Section. * @return The palette of this Section.
*/ */
public ListTag<CompoundTag> getPalette() { public synchronized ListTag<CompoundTag> getPalette() {
return palette; return palette;
} }
@ -367,7 +367,7 @@ public class Section {
/** /**
* @return The indices of the block states of this Section. * @return The indices of the block states of this Section.
*/ */
public AtomicLongArray getBlockStates() { public synchronized AtomicLongArray getBlockStates() {
return blockStates; return blockStates;
} }
@ -431,7 +431,7 @@ public class Section {
* @param y The Y-value of this Section * @param y The Y-value of this Section
* @return A reference to the raw CompoundTag this Section is based on * @return A reference to the raw CompoundTag this Section is based on
*/ */
public CompoundTag updateHandle(int y) { public synchronized CompoundTag updateHandle(int y) {
data.putByte("Y", (byte) y); data.putByte("Y", (byte) y);
if (palette != null) { if (palette != null) {
data.put("Palette", palette); data.put("Palette", palette);