mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-26 22:10:18 +00:00
Slices + Huge performance increase
This commit is contained in:
1 parent
6532715490
commit
7c725a9436
1 file changed
+93
-104
@@ -4,34 +4,24 @@ import com.volmit.iris.Iris;
|
|||||||
import com.volmit.iris.core.nms.IMemoryWorld;
|
import com.volmit.iris.core.nms.IMemoryWorld;
|
||||||
import com.volmit.iris.core.nms.INMS;
|
import com.volmit.iris.core.nms.INMS;
|
||||||
import com.volmit.iris.core.nms.container.Pair;
|
import com.volmit.iris.core.nms.container.Pair;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.object.annotations.Desc;
|
import com.volmit.iris.engine.object.annotations.Desc;
|
||||||
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.context.ChunkedDataCache;
|
import com.volmit.iris.util.context.ChunkedDataCache;
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.hunk.Hunk;
|
import com.volmit.iris.util.hunk.Hunk;
|
||||||
import com.volmit.iris.util.hunk.view.ChunkDataHunkView;
|
|
||||||
import com.volmit.iris.util.math.Position2;
|
import com.volmit.iris.util.math.Position2;
|
||||||
import com.volmit.iris.util.math.RollingSequence;
|
import com.volmit.iris.util.math.RollingSequence;
|
||||||
import com.volmit.iris.util.misc.E;
|
|
||||||
import com.volmit.iris.util.nbt.mca.MCAFile;
|
|
||||||
import com.volmit.iris.util.nbt.mca.MCAUtil;
|
|
||||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
|
||||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||||
import com.volmit.iris.util.parallel.MultiBurst;
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||||
import com.volmit.iris.util.scheduling.Queue;
|
import com.volmit.iris.util.scheduling.Queue;
|
||||||
import com.volmit.iris.util.scheduling.ShurikenQueue;
|
import com.volmit.iris.util.scheduling.ShurikenQueue;
|
||||||
import it.unimi.dsi.fastutil.Hash;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
@@ -43,8 +33,6 @@ import java.util.*;
|
|||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import static org.bukkit.Bukkit.createChunkData;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@Desc("Dimension Merging only supports 1 for now.")
|
@Desc("Dimension Merging only supports 1 for now.")
|
||||||
@@ -55,8 +43,6 @@ public class IrisMerger {
|
|||||||
private transient ReentrantLock lock = new ReentrantLock();
|
private transient ReentrantLock lock = new ReentrantLock();
|
||||||
private transient ChunkGenerator chunkGenerator;
|
private transient ChunkGenerator chunkGenerator;
|
||||||
private static final BlockData FILLER = Material.STONE.createBlockData();
|
private static final BlockData FILLER = Material.STONE.createBlockData();
|
||||||
private transient KMap<Pair<Position2, Hunk<BlockData>>, Boolean> chunks = new KMap<>();
|
|
||||||
private transient Queue<Pair<Position2, Hunk<BlockData>>> queue = new ShurikenQueue<>();
|
|
||||||
|
|
||||||
@Desc("Selected Generator")
|
@Desc("Selected Generator")
|
||||||
private String generator;
|
private String generator;
|
||||||
@@ -82,12 +68,11 @@ public class IrisMerger {
|
|||||||
@Desc("If it should translate iris deposits/ores to their deepslate variant")
|
@Desc("If it should translate iris deposits/ores to their deepslate variant")
|
||||||
private boolean deepslateTranslator = true;
|
private boolean deepslateTranslator = true;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges underground from a selected chunk into the corresponding chunk in the outcome world.
|
* Merges underground from a selected chunk into the corresponding chunk in the outcome world.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void generateVanillaUnderground(int x, int z, Engine engine) {
|
public void generateVanillaUnderground(int cx, int cz, Engine engine) {
|
||||||
if (engine.getMemoryWorld() == null)
|
if (engine.getMemoryWorld() == null)
|
||||||
throw new IllegalStateException("MemoryWorld is null. Ensure that it has been initialized.");
|
throw new IllegalStateException("MemoryWorld is null. Ensure that it has been initialized.");
|
||||||
if (engine.getWorld().realWorld() == null)
|
if (engine.getWorld().realWorld() == null)
|
||||||
@@ -107,32 +92,26 @@ public class IrisMerger {
|
|||||||
} else {
|
} else {
|
||||||
bukkit = Bukkit.getWorld(world);
|
bukkit = Bukkit.getWorld(world);
|
||||||
if (bukkit == null) {
|
if (bukkit == null) {
|
||||||
Iris.info("World " + world + " not loaded yet, cannot generate chunk at (" + x + ", " + z + ")");
|
Iris.info("World " + world + " not loaded yet, cannot generate chunk at (" + cx + ", " + cz + ")");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//chunkData = getChunkDataAt(bukkit, x, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
Hunk<BlockData> vh = Hunk.newHunk(16, Math.abs(bukkit.getMinHeight()) + bukkit.getMaxHeight(), 16);
|
|
||||||
getChunkDataHunkAt(bukkit, x, z, vh);
|
|
||||||
Hunk<BlockData> ih = null;
|
|
||||||
if (deepslateTranslator) {
|
|
||||||
ih = Hunk.newHunk(16, Math.abs(bukkit.getMinHeight()) + bukkit.getMaxHeight(), 16);
|
|
||||||
getChunkDataHunkAt(engine.getWorld().realWorld(), x, z, ih);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Chunk chunk = bukkit.getChunkAt(cx, cz);
|
||||||
|
Chunk ichunk = engine.getWorld().realWorld().getChunkAt(cx, cz);
|
||||||
|
|
||||||
int totalHeight = bukkit.getMaxHeight() - bukkit.getMinHeight();
|
int totalHeight = bukkit.getMaxHeight() - bukkit.getMinHeight();
|
||||||
int minHeight = Math.abs(bukkit.getMinHeight());
|
int minHeight = Math.abs(bukkit.getMinHeight());
|
||||||
|
|
||||||
var world = engine.getWorld().realWorld();
|
var world = engine.getWorld().realWorld();
|
||||||
int wX = x << 4;
|
int wX = cx << 4;
|
||||||
int wZ = z << 4;
|
int wZ = cz << 4;
|
||||||
|
|
||||||
BurstExecutor b = MultiBurst.burst.burst();
|
BurstExecutor b = MultiBurst.burst.burst();
|
||||||
var cache = new ChunkedDataCache<>(b, engine.getComplex().getHeightStream(), wX, wZ);
|
var cache = new ChunkedDataCache<>(b, engine.getComplex().getHeightStream(), wX, wZ);
|
||||||
b.complete();
|
b.complete();
|
||||||
|
|
||||||
|
|
||||||
Set<Biome> caveBiomes = new HashSet<>(Arrays.asList(
|
Set<Biome> caveBiomes = new HashSet<>(Arrays.asList(
|
||||||
Biome.DRIPSTONE_CAVES,
|
Biome.DRIPSTONE_CAVES,
|
||||||
Biome.LUSH_CAVES,
|
Biome.LUSH_CAVES,
|
||||||
@@ -142,55 +121,76 @@ public class IrisMerger {
|
|||||||
var nms = INMS.get();
|
var nms = INMS.get();
|
||||||
var flag = new Flags(false, false, true, false, false).value();
|
var flag = new Flags(false, false, true, false, false).value();
|
||||||
|
|
||||||
for (int xx = 0; xx < 16; xx++) {
|
for (int xx = 0; xx < 16; xx += 4) {
|
||||||
for (int zz = 0; zz < 16; zz++) {
|
for (int zz = 0; zz < 16; zz += 4) {
|
||||||
int height = (int) Math.ceil(cache.get(xx, zz) - depth);
|
int maxHeightInSection = 0;
|
||||||
|
|
||||||
for (int y = 0; y < totalHeight; y++) {
|
for (int x = 0; x < 4; x++) {
|
||||||
if (shouldSkip(y, height)) {
|
for (int z = 0; z < 4; z++) {
|
||||||
continue;
|
int globalX = xx + x;
|
||||||
|
int globalZ = zz + z;
|
||||||
|
int height = (int) Math.ceil(cache.get(globalX, globalZ) - depth);
|
||||||
|
if (height > maxHeightInSection) {
|
||||||
|
maxHeightInSection = height;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BlockData blockData = vh.get(xx, y, zz);
|
Hunk<BlockData> vh = getHunkSlice(chunk, xx, zz, maxHeightInSection);
|
||||||
if (!blockData.getMaterial().isAir() && deepslateTranslator) {
|
Hunk<BlockData> ih = getHunkSlice(ichunk, xx, zz, maxHeightInSection);
|
||||||
if (ih.get(xx, y, zz).getMaterial() != FILLER.getMaterial() && blockData.getMaterial().isOccluding()) {
|
|
||||||
try {
|
for (int x = 0; x < 4; x++) {
|
||||||
BlockData newBlockData = ih.get(xx, y, zz);
|
for (int z = 0; z < 4; z++) {
|
||||||
if (hasAround(vh, xx, y, zz, Material.DEEPSLATE)) {
|
int globalX = xx + x;
|
||||||
String id = newBlockData.getMaterial().getItemTranslationKey().replaceFirst("^block\\.[^.]+\\.", "").toUpperCase();
|
int globalZ = zz + z;
|
||||||
id = "DEEPSLATE_" + id;
|
int height = (int) Math.ceil(cache.get(globalX, globalZ) - depth);
|
||||||
Material dps = Material.getMaterial(id);
|
|
||||||
if (dps != null)
|
for (int y = 0; y < totalHeight; y++) {
|
||||||
blockData = dps.createBlockData();
|
if (shouldSkip(y, height))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BlockData blockData = vh.get(x, y, z);
|
||||||
|
if (!blockData.getMaterial().isAir() && deepslateTranslator) {
|
||||||
|
if (ih.get(x, y, z).getMaterial() != FILLER.getMaterial() && blockData.getMaterial().isOccluding()) {
|
||||||
|
try {
|
||||||
|
BlockData newBlockData = ih.get(x, y, z);
|
||||||
|
if (hasAround(vh, x, y, z, Material.DEEPSLATE)) {
|
||||||
|
String id = newBlockData.getMaterial().getItemTranslationKey().replaceFirst("^block\\.[^.]+\\.", "").toUpperCase();
|
||||||
|
id = "DEEPSLATE_" + id;
|
||||||
|
Material dps = Material.getMaterial(id);
|
||||||
|
if (dps != null)
|
||||||
|
blockData = dps.createBlockData();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Handle exception
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
//Iris.error(e.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nms.setBlock(
|
nms.setBlock(
|
||||||
world,
|
world,
|
||||||
wX + xx,
|
wX + globalX,
|
||||||
y - minHeight,
|
y - minHeight,
|
||||||
wZ + zz,
|
wZ + globalZ,
|
||||||
blockData,
|
blockData,
|
||||||
flag,
|
flag,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
if (nms.hasTile(blockData.getMaterial())) {
|
if (nms.hasTile(blockData.getMaterial())) {
|
||||||
var tile = nms.serializeTile(new Location(bukkit, wX + xx, y - minHeight, wZ + zz));
|
var tile = nms.serializeTile(new Location(bukkit, wX + globalX, y - minHeight, wZ + globalZ));
|
||||||
if (tile != null) {
|
if (tile != null) {
|
||||||
nms.deserializeTile(tile, new Location(world, wX + xx, y - minHeight, wZ + zz));
|
nms.deserializeTile(tile, new Location(world, wX + globalX, y - minHeight, wZ + globalZ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x % 4 == 0 && z % 4 == 0 && y % 4 == 0) {
|
if (globalX % 4 == 0 && globalZ % 4 == 0 && y % 4 == 0) {
|
||||||
Biome biome;
|
Biome biome;
|
||||||
biome = bukkit.getBiome(wX + xx, y, wZ + zz);
|
biome = bukkit.getBiome(wX + globalX, y, wZ + globalZ);
|
||||||
if (caveBiomes.contains(biome)) {
|
if (caveBiomes.contains(biome)) {
|
||||||
world.setBiome(wX + xx, y - minHeight, wZ + zz, biome);
|
world.setBiome(wX + globalX, y - minHeight, wZ + globalZ, biome);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,9 +241,16 @@ public class IrisMerger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getChunkDataHunkAt(World world, int chunkX, int chunkZ, Hunk<BlockData> h) {
|
/**
|
||||||
Chunk chunk = world.getChunkAt(chunkX, chunkZ);
|
* Retrieves a 4x4 hunk slice starting at (sx, sz) up to the specified height.
|
||||||
|
*
|
||||||
|
* @param chunk The Bukkit chunk
|
||||||
|
* @param sx Chunk Slice X (must be multiple of 4)
|
||||||
|
* @param sz Chunk Slice Z (must be multiple of 4)
|
||||||
|
* @param height The maximum height to process
|
||||||
|
* @return A hunk of size 4x(totalHeight)x4
|
||||||
|
*/
|
||||||
|
private Hunk<BlockData> getHunkSlice(Chunk chunk, int sx, int sz, int height) {
|
||||||
if (!chunk.isGenerated())
|
if (!chunk.isGenerated())
|
||||||
throw new IllegalStateException("Chunk is not generated!");
|
throw new IllegalStateException("Chunk is not generated!");
|
||||||
|
|
||||||
@@ -251,42 +258,24 @@ public class IrisMerger {
|
|||||||
chunk.load();
|
chunk.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
int height = Math.abs(world.getMinHeight()) + world.getMaxHeight();
|
int minHeight = chunk.getWorld().getMinHeight();
|
||||||
int minHeight = Math.abs(world.getMinHeight());
|
int maxHeight = chunk.getWorld().getMaxHeight();
|
||||||
|
int totalHeight = Math.abs(minHeight) + maxHeight;
|
||||||
|
|
||||||
for (int y = 0; y < height; y++) {
|
Hunk<BlockData> h = Hunk.newHunk(4, totalHeight, 4);
|
||||||
for (int x = 0; x < 16; x++) {
|
|
||||||
for (int z = 0; z < 16; z++) {
|
for (int x = 0; x < 4; x++) {
|
||||||
h.set(x, y, z, chunk.getBlock(x, y - minHeight, z).getBlockData());
|
for (int z = 0; z < 4; z++) {
|
||||||
|
for (int y = 0; y < totalHeight; y++) {
|
||||||
|
if (shouldSkip(y, height))
|
||||||
|
continue;
|
||||||
|
BlockData data = chunk.getBlock(sx + x, y + minHeight, sz + z).getBlockData();
|
||||||
|
h.set(x, y, z, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
return h;
|
||||||
private ChunkGenerator.ChunkData getChunkDataAt(World world, int chunkX, int chunkZ) {
|
|
||||||
ChunkGenerator.ChunkData chunkData = createChunkData(world);
|
|
||||||
Chunk chunk = world.getChunkAt(chunkX, chunkZ);
|
|
||||||
|
|
||||||
if (!chunk.isGenerated())
|
|
||||||
throw new IllegalStateException("Chunk is not generated!");
|
|
||||||
|
|
||||||
if (!chunk.isLoaded()) {
|
|
||||||
chunk.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
int minY = world.getMinHeight();
|
|
||||||
int maxY = world.getMaxHeight();
|
|
||||||
|
|
||||||
for (int y = minY; y < maxY; y++) {
|
|
||||||
for (int x = 0; x < 16; x++) {
|
|
||||||
for (int z = 0; z < 16; z++) {
|
|
||||||
BlockData blockData = chunk.getBlock(x, y, z).getBlockData();
|
|
||||||
chunkData.setBlock(x, y, z, blockData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return chunkData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasAround(Hunk<BlockData> hunk, int x, int y, int z, Material material) {
|
private boolean hasAround(Hunk<BlockData> hunk, int x, int y, int z, Material material) {
|
||||||
@@ -334,7 +323,7 @@ public class IrisMerger {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
World bukkitWorld = Bukkit.getWorld(world);
|
World bukkitWorld = Bukkit.getWorld(world);
|
||||||
if(!new File(Bukkit.getWorldContainer(), world).exists())
|
if (!new File(Bukkit.getWorldContainer(), world).exists())
|
||||||
throw new IllegalStateException("World does not exist!");
|
throw new IllegalStateException("World does not exist!");
|
||||||
if (bukkitWorld == null) {
|
if (bukkitWorld == null) {
|
||||||
Iris.info("World " + world + " is not loaded yet, creating it.");
|
Iris.info("World " + world + " is not loaded yet, creating it.");
|
||||||
|
|||||||
Reference in new issue
Block a user