mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-19 10:43:14 +00:00
Merge remote-tracking branch 'upstream/master' into saplingOverrides
This commit is contained in:
commit
20b3e95b4f
@ -5,7 +5,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group 'com.volmit.iris'
|
group 'com.volmit.iris'
|
||||||
version '1.5.1'
|
version '1.5.2'
|
||||||
def apiVersion = '1.17'
|
def apiVersion = '1.17'
|
||||||
def name = 'Iris'
|
def name = 'Iris'
|
||||||
def main = 'com.volmit.iris.Iris'
|
def main = 'com.volmit.iris.Iris'
|
||||||
|
@ -20,7 +20,7 @@ package com.volmit.iris.core;
|
|||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.engine.data.DirectWorldWriter;
|
import com.volmit.iris.engine.data.mca.NBTWorld;
|
||||||
import com.volmit.iris.engine.data.nbt.io.NBTUtil;
|
import com.volmit.iris.engine.data.nbt.io.NBTUtil;
|
||||||
import com.volmit.iris.engine.data.nbt.io.NamedTag;
|
import com.volmit.iris.engine.data.nbt.io.NamedTag;
|
||||||
import com.volmit.iris.engine.data.nbt.tag.CompoundTag;
|
import com.volmit.iris.engine.data.nbt.tag.CompoundTag;
|
||||||
@ -151,7 +151,7 @@ public class ConversionManager {
|
|||||||
@SuppressWarnings("unchecked") ListTag<CompoundTag> paletteList = (ListTag<CompoundTag>) compound.getListTag("palette");
|
@SuppressWarnings("unchecked") ListTag<CompoundTag> paletteList = (ListTag<CompoundTag>) compound.getListTag("palette");
|
||||||
for (int i = 0; i < paletteList.size(); i++) {
|
for (int i = 0; i < paletteList.size(); i++) {
|
||||||
CompoundTag cp = paletteList.get(i);
|
CompoundTag cp = paletteList.get(i);
|
||||||
palette.add(DirectWorldWriter.getBlockData(cp));
|
palette.add(NBTWorld.getBlockData(cp));
|
||||||
}
|
}
|
||||||
IrisJigsawPiece piece = new IrisJigsawPiece();
|
IrisJigsawPiece piece = new IrisJigsawPiece();
|
||||||
IrisObject object = new IrisObject(w, h, d);
|
IrisObject object = new IrisObject(w, h, d);
|
||||||
@ -171,7 +171,7 @@ public class ConversionManager {
|
|||||||
CompoundTag finalState = new CompoundTag();
|
CompoundTag finalState = new CompoundTag();
|
||||||
finalState.putString("Name", nbt.getString("final_state"));
|
finalState.putString("Name", nbt.getString("final_state"));
|
||||||
BlockData jd = bd.clone();
|
BlockData jd = bd.clone();
|
||||||
bd = DirectWorldWriter.getBlockData(finalState);
|
bd = NBTWorld.getBlockData(finalState);
|
||||||
String joint = nbt.getString("joint");
|
String joint = nbt.getString("joint");
|
||||||
String pool = nbt.getString("pool");
|
String pool = nbt.getString("pool");
|
||||||
String poolId = toPoolName(pool);
|
String poolId = toPoolName(pool);
|
||||||
|
@ -21,8 +21,8 @@ package com.volmit.iris.core.gui;
|
|||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.IrisSettings;
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.engine.IrisWorlds;
|
import com.volmit.iris.engine.IrisWorlds;
|
||||||
import com.volmit.iris.engine.data.DirectWorldWriter;
|
|
||||||
import com.volmit.iris.engine.data.mca.MCAFile;
|
import com.volmit.iris.engine.data.mca.MCAFile;
|
||||||
|
import com.volmit.iris.engine.data.mca.NBTWorld;
|
||||||
import com.volmit.iris.engine.framework.IrisAccess;
|
import com.volmit.iris.engine.framework.IrisAccess;
|
||||||
import com.volmit.iris.engine.parallel.BurstExecutor;
|
import com.volmit.iris.engine.parallel.BurstExecutor;
|
||||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
import com.volmit.iris.engine.parallel.MultiBurst;
|
||||||
@ -77,7 +77,7 @@ public class Pregenerator implements Listener {
|
|||||||
private static final Color COLOR_MCA_DEFERRED = Color.decode("#3CB57A");
|
private static final Color COLOR_MCA_DEFERRED = Color.decode("#3CB57A");
|
||||||
private final World world;
|
private final World world;
|
||||||
private int lowestBedrock;
|
private int lowestBedrock;
|
||||||
private final DirectWorldWriter directWriter;
|
private final NBTWorld directWriter;
|
||||||
private final AtomicBoolean active;
|
private final AtomicBoolean active;
|
||||||
private final AtomicBoolean running;
|
private final AtomicBoolean running;
|
||||||
private final KList<ChunkPosition> errors;
|
private final KList<ChunkPosition> errors;
|
||||||
@ -89,6 +89,7 @@ public class Pregenerator implements Listener {
|
|||||||
private final AtomicInteger generated;
|
private final AtomicInteger generated;
|
||||||
private final AtomicInteger generatedLast;
|
private final AtomicInteger generatedLast;
|
||||||
private final RollingSequence perSecond;
|
private final RollingSequence perSecond;
|
||||||
|
private final RollingSequence perMinute;
|
||||||
private final AtomicInteger totalChunks;
|
private final AtomicInteger totalChunks;
|
||||||
private final AtomicLong memory;
|
private final AtomicLong memory;
|
||||||
private final AtomicReference<String> memoryMetric;
|
private final AtomicReference<String> memoryMetric;
|
||||||
@ -125,16 +126,17 @@ public class Pregenerator implements Listener {
|
|||||||
vmcaz = new AtomicInteger();
|
vmcaz = new AtomicInteger();
|
||||||
vcax = new AtomicInteger();
|
vcax = new AtomicInteger();
|
||||||
vcaz = new AtomicInteger();
|
vcaz = new AtomicInteger();
|
||||||
|
perMinute = new RollingSequence(200);
|
||||||
perSecond = new RollingSequence(20);
|
perSecond = new RollingSequence(20);
|
||||||
generatedLast = new AtomicInteger(0);
|
generatedLast = new AtomicInteger(0);
|
||||||
totalChunks = new AtomicInteger(0);
|
totalChunks = new AtomicInteger(0);
|
||||||
generated = new AtomicInteger(0);
|
generated = new AtomicInteger(0);
|
||||||
mcaDefer = new KList<>();
|
mcaDefer = new KList<>();
|
||||||
access = IrisWorlds.access(world);
|
access = IrisWorlds.access(world);
|
||||||
this.directWriter = new DirectWorldWriter(world.getWorldFolder());
|
this.directWriter = new NBTWorld(world.getWorldFolder());
|
||||||
this.running = new AtomicBoolean(true);
|
this.running = new AtomicBoolean(true);
|
||||||
this.active = new AtomicBoolean(true);
|
this.active = new AtomicBoolean(true);
|
||||||
MultiBurst burst = new MultiBurst("Iris Pregenerator", 9, Runtime.getRuntime().availableProcessors() + 4);
|
MultiBurst burst = new MultiBurst("Iris Pregenerator", 9, Runtime.getRuntime().availableProcessors());
|
||||||
int mcaSize = (((blockSize >> 4) + 2) >> 5) + 1;
|
int mcaSize = (((blockSize >> 4) + 2) >> 5) + 1;
|
||||||
onComplete = new KList<>();
|
onComplete = new KList<>();
|
||||||
max = new ChunkPosition(0, 0);
|
max = new ChunkPosition(0, 0);
|
||||||
@ -196,7 +198,7 @@ public class Pregenerator implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
burst.shutdownNow();
|
burst.shutdownNow();
|
||||||
directWriter.flush();
|
directWriter.close();
|
||||||
flushWorld();
|
flushWorld();
|
||||||
onComplete.forEach(Runnable::run);
|
onComplete.forEach(Runnable::run);
|
||||||
running.set(false);
|
running.set(false);
|
||||||
@ -214,6 +216,7 @@ public class Pregenerator implements Listener {
|
|||||||
int up = m - w;
|
int up = m - w;
|
||||||
double dur = p.getMilliseconds();
|
double dur = p.getMilliseconds();
|
||||||
perSecond.put((int) (up / (dur / 1000D)));
|
perSecond.put((int) (up / (dur / 1000D)));
|
||||||
|
perSecond.put((int) (up / (dur / 60000D)));
|
||||||
p.reset();
|
p.reset();
|
||||||
p.begin();
|
p.begin();
|
||||||
updateProgress();
|
updateProgress();
|
||||||
@ -239,8 +242,7 @@ public class Pregenerator implements Listener {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
File mca = new File(world.getWorldFolder(), "region/r." + x + "." + z + ".mca");
|
File mca = directWriter.getRegionFile(x, z);
|
||||||
File mcg = directWriter.getMCAFile(x, z);
|
|
||||||
BurstExecutor e = burst.burst(1024);
|
BurstExecutor e = burst.burst(1024);
|
||||||
int mcaox = x << 5;
|
int mcaox = x << 5;
|
||||||
int mcaoz = z << 5;
|
int mcaoz = z << 5;
|
||||||
@ -255,9 +257,8 @@ public class Pregenerator implements Listener {
|
|||||||
vcaz.set(jj);
|
vcaz.set(jj);
|
||||||
}));
|
}));
|
||||||
e.complete();
|
e.complete();
|
||||||
verifyMCA(x, z, burst);
|
//verifyMCA(x, z, burst);
|
||||||
directWriter.flush();
|
directWriter.save();
|
||||||
install(mcg, mca);
|
|
||||||
} else {
|
} else {
|
||||||
totalChunks.getAndAdd(1024);
|
totalChunks.getAndAdd(1024);
|
||||||
mcaDefer.add(new ChunkPosition(x, z));
|
mcaDefer.add(new ChunkPosition(x, z));
|
||||||
@ -299,27 +300,6 @@ public class Pregenerator implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean install(File from, File to) {
|
|
||||||
try {
|
|
||||||
Files.move(from.toPath(), to.toPath());
|
|
||||||
return true;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Iris.reportError(e);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
IO.copyFile(from, to);
|
|
||||||
from.delete();
|
|
||||||
return true;
|
|
||||||
} catch (IOException e) {
|
|
||||||
Iris.reportError(e);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateProgress() {
|
public void updateProgress() {
|
||||||
if (!latch.flip()) {
|
if (!latch.flip()) {
|
||||||
return;
|
return;
|
||||||
@ -335,7 +315,7 @@ public class Pregenerator implements Listener {
|
|||||||
if (PaperLib.isPaper()) {
|
if (PaperLib.isPaper()) {
|
||||||
method.set("PaperAsync (Slow)");
|
method.set("PaperAsync (Slow)");
|
||||||
|
|
||||||
while (wait.size() > 32) {
|
while (wait.size() > 16) {
|
||||||
J.sleep(5);
|
J.sleep(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -509,7 +489,8 @@ public class Pregenerator implements Listener {
|
|||||||
return new String[]{
|
return new String[]{
|
||||||
"Progress: " + Form.f(generated.get()) + " of " + Form.f(totalChunks.get()) + " (" + Form.pc((double) generated.get() / (double) totalChunks.get(), 0) + ")",
|
"Progress: " + Form.f(generated.get()) + " of " + Form.f(totalChunks.get()) + " (" + Form.pc((double) generated.get() / (double) totalChunks.get(), 0) + ")",
|
||||||
"ETA: " + Form.duration(eta, 0),
|
"ETA: " + Form.duration(eta, 0),
|
||||||
"Chunks/s: " + Form.f((int) perSecond.getAverage()),
|
"Chunks/s: " + Form.f((int) perSecond.getAverage()) + " (" + Form.f((int)perSecond.getMax()) + " Peak)",
|
||||||
|
"Chunks/min: " + Form.f((int) perMinute.getAverage())+ " (" + Form.f((int)perMinute.getMax()) + " Peak)",
|
||||||
"Memory: " + memoryMetric.get(),
|
"Memory: " + memoryMetric.get(),
|
||||||
"Cursor: " + "MCA(" + vmcax.get() + ", " + vmcaz.get() + ") @ (" + vcax.get() + ", " + vcaz.get() + ")",
|
"Cursor: " + "MCA(" + vmcax.get() + ", " + vmcaz.get() + ") @ (" + vcax.get() + ", " + vcaz.get() + ")",
|
||||||
"Gen Mode: " + method.get(),
|
"Gen Mode: " + method.get(),
|
||||||
|
@ -197,10 +197,15 @@ public class IrisComplex implements DataProvider {
|
|||||||
}, Interpolated.DOUBLE).cache2D(cacheSize);
|
}, Interpolated.DOUBLE).cache2D(cacheSize);
|
||||||
slopeStream = heightStream.slope(3).interpolate().bilinear(3, 3).cache2D(cacheSize);
|
slopeStream = heightStream.slope(3).interpolate().bilinear(3, 3).cache2D(cacheSize);
|
||||||
objectChanceStream = ProceduralStream.ofDouble((x, z) -> {
|
objectChanceStream = ProceduralStream.ofDouble((x, z) -> {
|
||||||
AtomicDouble str = new AtomicDouble(1D);
|
if(engine.getDimension().hasFeatures(engine))
|
||||||
engine.getFramework().getEngineParallax().forEachFeature(x, z, (i)
|
{
|
||||||
-> str.set(Math.min(str.get(), i.getObjectChanceModifier(x, z))));
|
AtomicDouble str = new AtomicDouble(1D);
|
||||||
return str.get();
|
engine.getFramework().getEngineParallax().forEachFeature(x, z, (i)
|
||||||
|
-> str.set(Math.min(str.get(), i.getObjectChanceModifier(x, z))));
|
||||||
|
return str.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1D;
|
||||||
});
|
});
|
||||||
|
|
||||||
trueBiomeStream = focus != null ? ProceduralStream.of((x, y) -> focus, Interpolated.of(a -> 0D,
|
trueBiomeStream = focus != null ? ProceduralStream.of((x, y) -> focus, Interpolated.of(a -> 0D,
|
||||||
|
@ -162,22 +162,21 @@ public class IrisEngine extends BlockPopulator implements Engine {
|
|||||||
public void generate(int x, int z, Hunk<BlockData> vblocks, Hunk<Biome> vbiomes) {
|
public void generate(int x, int z, Hunk<BlockData> vblocks, Hunk<Biome> vbiomes) {
|
||||||
try {
|
try {
|
||||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||||
Hunk<BlockData> blocks = vblocks;
|
|
||||||
|
|
||||||
switch (getDimension().getTerrainMode()) {
|
switch (getDimension().getTerrainMode()) {
|
||||||
case NORMAL -> {
|
case NORMAL -> {
|
||||||
getFramework().getEngineParallax().generateParallaxArea(x >> 4, z >> 4);
|
getFramework().getEngineParallax().generateParallaxArea(x >> 4, z >> 4);
|
||||||
getFramework().getBiomeActuator().actuate(x, z, vbiomes);
|
getFramework().getBiomeActuator().actuate(x, z, vbiomes);
|
||||||
getFramework().getTerrainActuator().actuate(x, z, blocks);
|
getFramework().getTerrainActuator().actuate(x, z, vblocks);
|
||||||
getFramework().getCaveModifier().modify(x, z, blocks);
|
getFramework().getCaveModifier().modify(x, z, vblocks);
|
||||||
getFramework().getRavineModifier().modify(x, z, blocks);
|
getFramework().getRavineModifier().modify(x, z, vblocks);
|
||||||
getFramework().getPostModifier().modify(x, z, blocks);
|
getFramework().getPostModifier().modify(x, z, vblocks);
|
||||||
getFramework().getDecorantActuator().actuate(x, z, blocks);
|
getFramework().getDecorantActuator().actuate(x, z, vblocks);
|
||||||
getFramework().getEngineParallax().insertParallax(x, z, blocks);
|
getFramework().getEngineParallax().insertParallax(x, z, vblocks);
|
||||||
getFramework().getDepositModifier().modify(x, z, blocks);
|
getFramework().getDepositModifier().modify(x, z, vblocks);
|
||||||
}
|
}
|
||||||
case ISLANDS -> {
|
case ISLANDS -> {
|
||||||
getFramework().getTerrainActuator().actuate(x, z, blocks);
|
getFramework().getTerrainActuator().actuate(x, z, vblocks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getMetrics().getTotal().put(p.getMilliseconds());
|
getMetrics().getTotal().put(p.getMilliseconds());
|
||||||
|
@ -22,6 +22,7 @@ import com.volmit.iris.engine.data.nbt.tag.CompoundTag;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
|
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||||||
|
|
||||||
@SuppressWarnings("ALL")
|
@SuppressWarnings("ALL")
|
||||||
public class MCAFile {
|
public class MCAFile {
|
||||||
@ -33,7 +34,7 @@ public class MCAFile {
|
|||||||
|
|
||||||
private final int regionX;
|
private final int regionX;
|
||||||
private final int regionZ;
|
private final int regionZ;
|
||||||
private Chunk[] chunks;
|
private AtomicReferenceArray<Chunk> chunks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MCAFile represents a world save file used by Minecraft to store world
|
* MCAFile represents a world save file used by Minecraft to store world
|
||||||
@ -69,7 +70,7 @@ public class MCAFile {
|
|||||||
* @throws IOException If something went wrong during deserialization.
|
* @throws IOException If something went wrong during deserialization.
|
||||||
*/
|
*/
|
||||||
public void deserialize(RandomAccessFile raf, long loadFlags) throws IOException {
|
public void deserialize(RandomAccessFile raf, long loadFlags) throws IOException {
|
||||||
chunks = new Chunk[1024];
|
chunks = new AtomicReferenceArray<>(1024);
|
||||||
for (int i = 0; i < 1024; i++) {
|
for (int i = 0; i < 1024; i++) {
|
||||||
raf.seek(i * 4);
|
raf.seek(i * 4);
|
||||||
int offset = raf.read() << 16;
|
int offset = raf.read() << 16;
|
||||||
@ -83,11 +84,11 @@ public class MCAFile {
|
|||||||
Chunk chunk = new Chunk(timestamp);
|
Chunk chunk = new Chunk(timestamp);
|
||||||
raf.seek(4096L * offset + 4); //+4: skip data size
|
raf.seek(4096L * offset + 4); //+4: skip data size
|
||||||
chunk.deserialize(raf, loadFlags);
|
chunk.deserialize(raf, loadFlags);
|
||||||
chunks[i] = chunk;
|
chunks.set(i, chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Chunk[] getChunks() {
|
public AtomicReferenceArray<Chunk> getChunks() {
|
||||||
return chunks;
|
return chunks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +129,7 @@ public class MCAFile {
|
|||||||
for (int cx = 0; cx < 32; cx++) {
|
for (int cx = 0; cx < 32; cx++) {
|
||||||
for (int cz = 0; cz < 32; cz++) {
|
for (int cz = 0; cz < 32; cz++) {
|
||||||
int index = getChunkIndex(cx, cz);
|
int index = getChunkIndex(cx, cz);
|
||||||
Chunk chunk = chunks[index];
|
Chunk chunk = chunks.get(index);
|
||||||
if (chunk == null) {
|
if (chunk == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -175,9 +176,9 @@ public class MCAFile {
|
|||||||
public void setChunk(int index, Chunk chunk) {
|
public void setChunk(int index, Chunk chunk) {
|
||||||
checkIndex(index);
|
checkIndex(index);
|
||||||
if (chunks == null) {
|
if (chunks == null) {
|
||||||
chunks = new Chunk[1024];
|
chunks = new AtomicReferenceArray<>(1024);
|
||||||
}
|
}
|
||||||
chunks[index] = chunk;
|
chunks.set(index, chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -203,7 +204,7 @@ public class MCAFile {
|
|||||||
if (chunks == null) {
|
if (chunks == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return chunks[index];
|
return chunks.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -217,6 +218,11 @@ public class MCAFile {
|
|||||||
return getChunk(getChunkIndex(chunkX, chunkZ));
|
return getChunk(getChunkIndex(chunkX, chunkZ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasChunk(int chunkX, int chunkZ)
|
||||||
|
{
|
||||||
|
return getChunk(chunkX, chunkZ) != null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the index of a chunk from its x- and z-coordinates in this region.
|
* Calculates the index of a chunk from its x- and z-coordinates in this region.
|
||||||
* This works with absolute and relative coordinates.
|
* This works with absolute and relative coordinates.
|
||||||
@ -319,15 +325,4 @@ public class MCAFile {
|
|||||||
}
|
}
|
||||||
return chunk.getBlockStateAt(blockX, blockY, blockZ);
|
return chunk.getBlockStateAt(blockX, blockY, blockZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Recalculates the Palette and the BlockStates of all chunks and sections of this region.
|
|
||||||
*/
|
|
||||||
public void cleanupPalettesAndBlockStates() {
|
|
||||||
for (Chunk chunk : chunks) {
|
|
||||||
if (chunk != null) {
|
|
||||||
chunk.cleanupPalettesAndBlockStates();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -16,75 +16,160 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.volmit.iris.engine.data;
|
package com.volmit.iris.engine.data.mca;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.nms.INMS;
|
import com.volmit.iris.core.nms.INMS;
|
||||||
import com.volmit.iris.engine.cache.Cache;
|
import com.volmit.iris.engine.cache.Cache;
|
||||||
import com.volmit.iris.engine.data.mca.Chunk;
|
import com.volmit.iris.engine.data.B;
|
||||||
import com.volmit.iris.engine.data.mca.MCAFile;
|
|
||||||
import com.volmit.iris.engine.data.mca.MCAUtil;
|
|
||||||
import com.volmit.iris.engine.data.mca.Section;
|
|
||||||
import com.volmit.iris.engine.data.nbt.tag.CompoundTag;
|
import com.volmit.iris.engine.data.nbt.tag.CompoundTag;
|
||||||
import com.volmit.iris.engine.data.nbt.tag.StringTag;
|
import com.volmit.iris.engine.data.nbt.tag.StringTag;
|
||||||
import com.volmit.iris.engine.parallel.BurstExecutor;
|
|
||||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.collection.KSet;
|
||||||
|
import com.volmit.iris.util.format.C;
|
||||||
|
import com.volmit.iris.util.math.M;
|
||||||
|
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 org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
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.*;
|
||||||
|
|
||||||
@SuppressWarnings("EmptyMethod")
|
public class NBTWorld {
|
||||||
public class DirectWorldWriter {
|
private static final BlockData AIR = B.get("AIR");
|
||||||
private final File worldFolder;
|
|
||||||
private final Map<Long, MCAFile> writeBuffer;
|
|
||||||
private static final Map<String, CompoundTag> blockDataCache = new KMap<>();
|
private static final Map<String, CompoundTag> blockDataCache = new KMap<>();
|
||||||
private static final Map<Biome, Integer> biomeIds = computeBiomeIDs();
|
private static final Map<Biome, Integer> biomeIds = computeBiomeIDs();
|
||||||
|
private final IrisLock regionLock = new IrisLock("Region");
|
||||||
|
private final KMap<Long, MCAFile> loadedRegions;
|
||||||
|
private final KMap<Long, Long> lastUse;
|
||||||
|
private final File worldFolder;
|
||||||
|
private final ExecutorService saveQueue;
|
||||||
|
|
||||||
public DirectWorldWriter(File worldFolder) {
|
public NBTWorld(File worldFolder)
|
||||||
|
{
|
||||||
this.worldFolder = worldFolder;
|
this.worldFolder = worldFolder;
|
||||||
writeBuffer = new KMap<>();
|
this.loadedRegions = new KMap<>();
|
||||||
new File(worldFolder, "iris/mca-region").mkdirs();
|
this.lastUse = new KMap<>();
|
||||||
|
saveQueue = Executors.newSingleThreadExecutor(r -> {
|
||||||
|
Thread t = new Thread(r);
|
||||||
|
t.setName("Iris MCA Writer");
|
||||||
|
t.setPriority(Thread.MIN_PRIORITY);
|
||||||
|
return t;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flush() {
|
public void close()
|
||||||
BurstExecutor ex2 = MultiBurst.burst.burst(writeBuffer.size());
|
{
|
||||||
|
regionLock.lock();
|
||||||
|
|
||||||
for (Long i : new KList<>(writeBuffer.keySet())) {
|
for(Long i : loadedRegions.k())
|
||||||
ex2.queue(() -> {
|
{
|
||||||
int x = Cache.keyX(i);
|
queueSaveUnload(Cache.keyX(i), Cache.keyZ(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);
|
|
||||||
writeBuffer.remove(i);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Iris.reportError(e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ex2.complete();
|
regionLock.unlock();
|
||||||
|
saveQueue.shutdown();
|
||||||
|
try {
|
||||||
|
while(!saveQueue.awaitTermination(3, TimeUnit.SECONDS))
|
||||||
|
{
|
||||||
|
Iris.info("Still Waiting to save MCA Files...");
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void optimizeChunk(int x, int z) {
|
public void queueSaveUnload(int x, int z)
|
||||||
getChunk(x, z).cleanupPalettesAndBlockStates();
|
{
|
||||||
|
saveQueue.submit(() -> {
|
||||||
|
MCAFile f = getMCAOrNull(x, z);
|
||||||
|
if(f != null)
|
||||||
|
{
|
||||||
|
unloadRegion(x, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
saveRegion(x, z, f);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getMCAFile(int x, int z) {
|
public void save()
|
||||||
return new File(worldFolder, "iris/mca-region/r." + x + "." + z + ".mca");
|
{
|
||||||
|
regionLock.lock();
|
||||||
|
|
||||||
|
boolean saving = true;
|
||||||
|
|
||||||
|
for(Long i : loadedRegions.k())
|
||||||
|
{
|
||||||
|
int x = Cache.keyX(i);
|
||||||
|
int z = Cache.keyZ(i);
|
||||||
|
|
||||||
|
if(!lastUse.containsKey(i))
|
||||||
|
{
|
||||||
|
lastUse.put(i, M.ms());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(shouldUnload(x, z))
|
||||||
|
{
|
||||||
|
queueSaveUnload(x, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Iris.debug("Regions: " + C.GOLD + loadedRegions.size() + C.LIGHT_PURPLE);
|
||||||
|
|
||||||
|
regionLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void queueSave()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void unloadRegion(int x, int z)
|
||||||
|
{
|
||||||
|
long key = Cache.key(x, z);
|
||||||
|
regionLock.lock();
|
||||||
|
loadedRegions.remove(key);
|
||||||
|
lastUse.remove(key);
|
||||||
|
regionLock.unlock();
|
||||||
|
Iris.debug("Unloaded Region " + C.GOLD + x + " " + z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveRegion(int x, int z)
|
||||||
|
{
|
||||||
|
long k = Cache.key(x, z);
|
||||||
|
MCAFile mca = getMCAOrNull(x, z);
|
||||||
|
try {
|
||||||
|
MCAUtil.write(mca, getRegionFile(x, z), true);
|
||||||
|
Iris.debug("Saved Region " + C.GOLD + x + " " + z);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Iris.error("Failed to save region " + getRegionFile(x, z).getPath());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveRegion(int x, int z, MCAFile mca)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
MCAUtil.write(mca, getRegionFile(x, z), true);
|
||||||
|
Iris.debug("Saved Region " + C.GOLD + x + " " + z);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Iris.error("Failed to save region " + getRegionFile(x, z).getPath());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldUnload(int x, int z)
|
||||||
|
{
|
||||||
|
return getIdleDuration(x, z) > 60000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getRegionFile(int x, int z) {
|
||||||
|
return new File(worldFolder, "region/r." + x + "." + z + ".mca");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BlockData getBlockData(CompoundTag tag) {
|
public static BlockData getBlockData(CompoundTag tag) {
|
||||||
@ -125,7 +210,6 @@ public class DirectWorldWriter {
|
|||||||
NamespacedKey key = blockData.getMaterial().getKey();
|
NamespacedKey key = blockData.getMaterial().getKey();
|
||||||
s.putString("Name", key.getNamespace() + ":" + key.getKey());
|
s.putString("Name", key.getNamespace() + ":" + key.getKey());
|
||||||
|
|
||||||
|
|
||||||
if (data.contains("[")) {
|
if (data.contains("[")) {
|
||||||
String raw = data.split("\\Q[\\E")[1].replaceAll("\\Q]\\E", "");
|
String raw = data.split("\\Q[\\E")[1].replaceAll("\\Q]\\E", "");
|
||||||
CompoundTag props = new CompoundTag();
|
CompoundTag props = new CompoundTag();
|
||||||
@ -154,7 +238,7 @@ public class DirectWorldWriter {
|
|||||||
CompoundTag tag = getChunkSection(x >> 4, y >> 4, z >> 4).getBlockStateAt(x & 15, y & 15, z & 15);
|
CompoundTag tag = getChunkSection(x >> 4, y >> 4, z >> 4).getBlockStateAt(x & 15, y & 15, z & 15);
|
||||||
|
|
||||||
if (tag == null) {
|
if (tag == null) {
|
||||||
return B.get("AIR");
|
return AIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return getBlockData(tag);
|
return getBlockData(tag);
|
||||||
@ -162,7 +246,7 @@ public class DirectWorldWriter {
|
|||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
|
|
||||||
}
|
}
|
||||||
return B.get("AIR");
|
return AIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBlockData(int x, int y, int z, BlockData data) {
|
public void setBlockData(int x, int y, int z, BlockData data) {
|
||||||
@ -185,10 +269,6 @@ public class DirectWorldWriter {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteChunk(int x, int z) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public Chunk getChunk(int x, int z) {
|
public Chunk getChunk(int x, int z) {
|
||||||
MCAFile mca = getMCA(x >> 5, z >> 5);
|
MCAFile mca = getMCA(x >> 5, z >> 5);
|
||||||
Chunk c = mca.getChunk(x & 31, z & 31);
|
Chunk c = mca.getChunk(x & 31, z & 31);
|
||||||
@ -201,28 +281,57 @@ public class DirectWorldWriter {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getIdleDuration(int x, int z)
|
||||||
|
{
|
||||||
|
Long l = lastUse.get(Cache.key(x, z));
|
||||||
|
|
||||||
|
return l == null ? 0 : (M.ms() - l);
|
||||||
|
}
|
||||||
|
|
||||||
public MCAFile getMCA(int x, int z) {
|
public MCAFile getMCA(int x, int z) {
|
||||||
long key = Cache.key(x, z);
|
long key = Cache.key(x, z);
|
||||||
MCAFile mca = writeBuffer.get(key);
|
|
||||||
|
|
||||||
if (mca != null) {
|
regionLock.lock();
|
||||||
return mca;
|
lastUse.put(key, M.ms());
|
||||||
|
MCAFile mcaf = loadedRegions.get(key);
|
||||||
|
regionLock.unlock();
|
||||||
|
|
||||||
|
if(mcaf == null)
|
||||||
|
{
|
||||||
|
File f = getRegionFile(x, z);
|
||||||
|
try {
|
||||||
|
mcaf = f.exists() ? MCAUtil.read(f) : new MCAFile(x, z);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Iris.error("Failed to properly read MCA File " + f.getPath() + " Using a blank one.");
|
||||||
|
e.printStackTrace();
|
||||||
|
mcaf = new MCAFile(x, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
regionLock.lock();
|
||||||
|
loadedRegions.put(key, mcaf);
|
||||||
|
regionLock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
File f = getMCAFile(x, z);
|
return mcaf;
|
||||||
try {
|
}
|
||||||
mca = f.exists() ? MCAUtil.read(f) : new MCAFile(x, z);
|
|
||||||
} catch (IOException e) {
|
public MCAFile getMCAOrNull(int x, int z) {
|
||||||
e.printStackTrace();
|
long key = Cache.key(x, z);
|
||||||
mca = new MCAFile(x, z);
|
MCAFile ff = null;
|
||||||
|
regionLock.lock();
|
||||||
|
|
||||||
|
if(loadedRegions.containsKey(key))
|
||||||
|
{
|
||||||
|
lastUse.put(key, M.ms());
|
||||||
|
ff = loadedRegions.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeBuffer.put(key, mca);
|
regionLock.unlock();
|
||||||
return mca;
|
return ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
return writeBuffer.size();
|
return loadedRegions.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<Biome, Integer> computeBiomeIDs() {
|
private static Map<Biome, Integer> computeBiomeIDs() {
|
||||||
@ -236,18 +345,4 @@ public class DirectWorldWriter {
|
|||||||
|
|
||||||
return biomeIds;
|
return biomeIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void verify(int mcaox, int mcaoz) {
|
|
||||||
MCAFile file = getMCA(mcaox, mcaoz);
|
|
||||||
|
|
||||||
for (int i = 0; i < 32; i++) {
|
|
||||||
for (int j = 0; j < 32; j++) {
|
|
||||||
Chunk c = file.getChunk(i, j);
|
|
||||||
|
|
||||||
if (c == null) {
|
|
||||||
Iris.warn("Chunk " + ((mcaox << 5) + i) + ", " + ((mcaoz << 5) + j) + " is null in MCA File " + mcaox + ", " + mcaoz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -27,8 +27,8 @@ import com.volmit.iris.engine.IrisEngineCompound;
|
|||||||
import com.volmit.iris.engine.IrisWorlds;
|
import com.volmit.iris.engine.IrisWorlds;
|
||||||
import com.volmit.iris.engine.cache.Cache;
|
import com.volmit.iris.engine.cache.Cache;
|
||||||
import com.volmit.iris.engine.data.B;
|
import com.volmit.iris.engine.data.B;
|
||||||
import com.volmit.iris.engine.data.DirectWorldWriter;
|
|
||||||
import com.volmit.iris.engine.data.chunk.TerrainChunk;
|
import com.volmit.iris.engine.data.chunk.TerrainChunk;
|
||||||
|
import com.volmit.iris.engine.data.mca.NBTWorld;
|
||||||
import com.volmit.iris.engine.hunk.Hunk;
|
import com.volmit.iris.engine.hunk.Hunk;
|
||||||
import com.volmit.iris.engine.object.IrisBiome;
|
import com.volmit.iris.engine.object.IrisBiome;
|
||||||
import com.volmit.iris.engine.object.IrisDimension;
|
import com.volmit.iris.engine.object.IrisDimension;
|
||||||
@ -104,7 +104,7 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
|||||||
populators = new KList<BlockPopulator>().qadd(new BlockPopulator() {
|
populators = new KList<BlockPopulator>().qadd(new BlockPopulator() {
|
||||||
@Override
|
@Override
|
||||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
||||||
if (compound != null) {
|
if (compound.get() != null) {
|
||||||
for (BlockPopulator i : compound.get().getPopulators()) {
|
for (BlockPopulator i : compound.get().getPopulators()) {
|
||||||
i.populate(world, random, chunk);
|
i.populate(world, random, chunk);
|
||||||
}
|
}
|
||||||
@ -295,7 +295,7 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void initialize(World world) {
|
public synchronized void initialize(World world) {
|
||||||
if (!(world instanceof FakeWorld) && fake.get() && this.compound != null) {
|
if (!(world instanceof FakeWorld) && fake.get() && this.compound.get() != null) {
|
||||||
fake.set(false);
|
fake.set(false);
|
||||||
this.compound.get().updateWorld(world);
|
this.compound.get().updateWorld(world);
|
||||||
getTarget().updateWorld(world);
|
getTarget().updateWorld(world);
|
||||||
@ -469,7 +469,7 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
|||||||
return tc.getRaw();
|
return tc.getRaw();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void directWriteMCA(World w, int x, int z, DirectWorldWriter writer, MultiBurst burst) {
|
public void directWriteMCA(World w, int x, int z, NBTWorld writer, MultiBurst burst) {
|
||||||
BurstExecutor e = burst.burst(1024);
|
BurstExecutor e = burst.burst(1024);
|
||||||
int mcaox = x << 5;
|
int mcaox = x << 5;
|
||||||
int mcaoz = z << 5;
|
int mcaoz = z << 5;
|
||||||
@ -485,7 +485,7 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
|||||||
e.complete();
|
e.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void directWriteChunk(World w, int x, int z, DirectWorldWriter writer) {
|
public void directWriteChunk(World w, int x, int z, NBTWorld writer) {
|
||||||
int ox = x << 4;
|
int ox = x << 4;
|
||||||
int oz = z << 4;
|
int oz = z << 4;
|
||||||
com.volmit.iris.engine.data.mca.Chunk cc = writer.getChunk(x, z);
|
com.volmit.iris.engine.data.mca.Chunk cc = writer.getChunk(x, z);
|
||||||
@ -543,7 +543,7 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cc.setBlockStateAt(xx, y, zz, DirectWorldWriter.getCompound(blockData), false);
|
cc.setBlockStateAt(xx, y, zz, NBTWorld.getCompound(blockData), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@ -557,7 +557,7 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
|||||||
y = 0;
|
y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DirectWorldWriter.getBlockData(cc.getBlockStateAt((x + ox) & 15, y, (z + oz) & 15));
|
return NBTWorld.getBlockData(cc.getBlockStateAt((x + ox) & 15, y, (z + oz) & 15));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -199,6 +199,11 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer {
|
|||||||
IrisLock getFeatureLock();
|
IrisLock getFeatureLock();
|
||||||
|
|
||||||
default void forEachFeature(double x, double z, Consumer<IrisFeaturePositional> f) {
|
default void forEachFeature(double x, double z, Consumer<IrisFeaturePositional> f) {
|
||||||
|
if(!getEngine().getDimension().hasFeatures(getEngine()))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
long key = Cache.key(((int) x) >> 4, ((int) z) >> 4);
|
long key = Cache.key(((int) x) >> 4, ((int) z) >> 4);
|
||||||
|
|
||||||
for (IrisFeaturePositional ipf : getFeatureCache().compute(key, (ke, v) -> {
|
for (IrisFeaturePositional ipf : getFeatureCache().compute(key, (ke, v) -> {
|
||||||
@ -225,17 +230,13 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer {
|
|||||||
ParallaxChunkMeta m = getParallaxAccess().getMetaR(i + cx, j + cz);
|
ParallaxChunkMeta m = getParallaxAccess().getMetaR(i + cx, j + cz);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
synchronized (m.getFeatures()) {
|
for (IrisFeaturePositional k : m.getFeatures()) {
|
||||||
for (IrisFeaturePositional k : m.getFeatures()) {
|
if (k.shouldFilter(x, z)) {
|
||||||
if (k.shouldFilter(x, z)) {
|
pos.add(k);
|
||||||
pos.add(k);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
|
||||||
Iris.warn("Failed to read positional features in chunk " + (i + cx) + " " + (j + cz) + "(" + e.getClass().getSimpleName() + ")");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ import com.volmit.iris.Iris;
|
|||||||
import com.volmit.iris.core.IrisDataManager;
|
import com.volmit.iris.core.IrisDataManager;
|
||||||
import com.volmit.iris.engine.IrisComplex;
|
import com.volmit.iris.engine.IrisComplex;
|
||||||
import com.volmit.iris.engine.data.DataProvider;
|
import com.volmit.iris.engine.data.DataProvider;
|
||||||
import com.volmit.iris.engine.data.DirectWorldWriter;
|
import com.volmit.iris.engine.data.mca.NBTWorld;
|
||||||
import com.volmit.iris.engine.object.IrisBiome;
|
import com.volmit.iris.engine.object.IrisBiome;
|
||||||
import com.volmit.iris.engine.object.IrisRegion;
|
import com.volmit.iris.engine.object.IrisRegion;
|
||||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
import com.volmit.iris.engine.parallel.MultiBurst;
|
||||||
@ -44,9 +44,9 @@ import java.util.function.Consumer;
|
|||||||
@SuppressWarnings("EmptyMethod")
|
@SuppressWarnings("EmptyMethod")
|
||||||
public interface IrisAccess extends Hotloadable, DataProvider {
|
public interface IrisAccess extends Hotloadable, DataProvider {
|
||||||
|
|
||||||
void directWriteMCA(World w, int x, int z, DirectWorldWriter writer, MultiBurst burst);
|
void directWriteMCA(World w, int x, int z, NBTWorld writer, MultiBurst burst);
|
||||||
|
|
||||||
void directWriteChunk(World w, int x, int z, DirectWorldWriter writer);
|
void directWriteChunk(World w, int x, int z, NBTWorld writer);
|
||||||
|
|
||||||
int getGenerated();
|
int getGenerated();
|
||||||
|
|
||||||
|
@ -349,6 +349,7 @@ public class IrisDimension extends IrisRegistrant {
|
|||||||
private final transient AtomicCache<Double> sinr = new AtomicCache<>();
|
private final transient AtomicCache<Double> sinr = new AtomicCache<>();
|
||||||
private final transient AtomicCache<Double> cosr = new AtomicCache<>();
|
private final transient AtomicCache<Double> cosr = new AtomicCache<>();
|
||||||
private final transient AtomicCache<Double> rad = new AtomicCache<>();
|
private final transient AtomicCache<Double> rad = new AtomicCache<>();
|
||||||
|
private final transient AtomicCache<Boolean> featuresUsed = new AtomicCache<>();
|
||||||
|
|
||||||
public boolean hasSky() {
|
public boolean hasSky() {
|
||||||
return getSky() != null;
|
return getSky() != null;
|
||||||
@ -517,4 +518,48 @@ public class IrisDimension extends IrisRegistrant {
|
|||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasFeatures(DataProvider data) {
|
||||||
|
return featuresUsed.aquire(() -> {
|
||||||
|
if(getFeatures().isNotEmpty() || getSpecificFeatures().isNotEmpty())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(IrisRegion i : getAllRegions(data))
|
||||||
|
{
|
||||||
|
if(i.getFeatures().isNotEmpty())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(IrisObjectPlacement j : i.getObjects())
|
||||||
|
{
|
||||||
|
if(j.isVacuum())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(IrisBiome j : i.getAllBiomes(data))
|
||||||
|
{
|
||||||
|
if(j.getFeatures().isNotEmpty())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(IrisObjectPlacement k : i.getObjects())
|
||||||
|
{
|
||||||
|
if(k.isVacuum())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Iris.verbose("Not using parallax noise features (they arent used in this dimension)");
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ import lombok.Data;
|
|||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@ -56,9 +57,9 @@ public class ParallaxChunkMeta {
|
|||||||
private int maxObject = -1;
|
private int maxObject = -1;
|
||||||
private int minObject = -1;
|
private int minObject = -1;
|
||||||
private int count;
|
private int count;
|
||||||
private KList<IrisFeaturePositional> features;
|
private CopyOnWriteArrayList<IrisFeaturePositional> features;
|
||||||
|
|
||||||
public ParallaxChunkMeta() {
|
public ParallaxChunkMeta() {
|
||||||
this(false, false, false, false, false, false, -1, -1, 0, new KList<>());
|
this(false, false, false, false, false, false, -1, -1, 0, new CopyOnWriteArrayList<>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,6 @@ public class ParallaxRegion extends HunkRegion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void save() throws IOException {
|
public synchronized void save() throws IOException {
|
||||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
|
||||||
blockSlice.save();
|
blockSlice.save();
|
||||||
objectSlice.save();
|
objectSlice.save();
|
||||||
entitySlice.save();
|
entitySlice.save();
|
||||||
@ -164,7 +163,6 @@ public class ParallaxRegion extends HunkRegion {
|
|||||||
updateSlice.save();
|
updateSlice.save();
|
||||||
saveMetaHunk();
|
saveMetaHunk();
|
||||||
super.save();
|
super.save();
|
||||||
Iris.debug("Saved Parallax Region " + C.AQUA + getX() + "," + getZ() + C.LIGHT_PURPLE + " in " + C.RED + Form.duration(p.getMilliseconds(), 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int unload() {
|
public int unload() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user