mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-03 00:17:15 +00:00
Saving chunks still is a problem though
This commit is contained in:
parent
5d5c5ba9f4
commit
7c6df58c15
@ -171,6 +171,11 @@ public class CommandDeveloper implements DecreeExecutor {
|
||||
Iris.info("Done fixing biomes!");
|
||||
}
|
||||
|
||||
@Decree(description = "check", aliases = {"ck"} )
|
||||
public void check() {
|
||||
sender().sendMessage("Data Pack Biome: " + INMS.get().getTrueBiomeBaseKey(player().getLocation()) + " (ID: " + INMS.get().getTrueBiomeBaseId(INMS.get().getTrueBiomeBase(player().getLocation())) + ")");
|
||||
}
|
||||
|
||||
@Decree(description = "Upgrade to another Minecraft version")
|
||||
public void upgrade(
|
||||
@Param(description = "The version to upgrade to", defaultValue = "latest") DataVersion version) {
|
||||
|
@ -24,6 +24,7 @@ import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.hunk.Hunk;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.Vector3d;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
|
||||
@ -98,6 +99,10 @@ public interface INMSBinding {
|
||||
|
||||
int countCustomBiomes();
|
||||
|
||||
default void setBiomes(int cx, int cz, World world, Hunk<Object> biomes) {
|
||||
Iris.error("Unsupported version!");
|
||||
}
|
||||
|
||||
void forceBiomeInto(int x, int y, int z, Object somethingVeryDirty, ChunkGenerator.BiomeGrid chunk);
|
||||
|
||||
default boolean supportsDataPacks() {
|
||||
|
@ -4,62 +4,50 @@ import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.util.hunk.Hunk;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.math.RollingSequence;
|
||||
import com.volmit.iris.util.misc.E;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class IrisBiomeFixer {
|
||||
/**
|
||||
* Do a pregen style approach iterate across a certain region and set everything to the correct biome again.
|
||||
* Have 2 modes ( all, surface-only ) surface-only gets the underground caves from a different world
|
||||
*/
|
||||
|
||||
private World world;
|
||||
private Engine engine;
|
||||
private int radius;
|
||||
private ChronoLatch latch;
|
||||
|
||||
private RollingSequence chunksPerSecond;
|
||||
private RollingSequence chunksPerMinute;
|
||||
private AtomicLong startTime;
|
||||
private AtomicLong lastLogTime;
|
||||
|
||||
private AtomicInteger generated = new AtomicInteger(0);
|
||||
private AtomicInteger lastGenerated = new AtomicInteger(0);
|
||||
private AtomicInteger generatedLast = new AtomicInteger(0);
|
||||
private AtomicInteger generatedLastMinute = new AtomicInteger(0);
|
||||
private AtomicInteger totalChunks = new AtomicInteger(0);
|
||||
private ChronoLatch progressLatch = new ChronoLatch(5000); // Update every 5 seconds
|
||||
private ChronoLatch minuteLatch = new ChronoLatch(60000, false);
|
||||
|
||||
// File to store unregistered biome IDs
|
||||
private File unregisteredBiomesFile;
|
||||
|
||||
// Reference to your plugin instance (Assuming you have one)
|
||||
private Plugin plugin;
|
||||
|
||||
private ScheduledExecutorService progressUpdater;
|
||||
|
||||
public IrisBiomeFixer(World world) {
|
||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||
Iris.info("This is not an Iris world!");
|
||||
return;
|
||||
}
|
||||
|
||||
this.chunksPerSecond = new RollingSequence(32);
|
||||
this.chunksPerSecond = new RollingSequence(10);
|
||||
this.chunksPerMinute = new RollingSequence(10);
|
||||
this.startTime = new AtomicLong(M.ms());
|
||||
this.lastLogTime = new AtomicLong(M.ms());
|
||||
this.world = world;
|
||||
@ -69,6 +57,9 @@ public class IrisBiomeFixer {
|
||||
|
||||
// Initialize the file for storing unregistered biome IDs
|
||||
this.unregisteredBiomesFile = new File(world.getWorldFolder(), "unregistered_biomes.txt");
|
||||
|
||||
// Initialize the progress updater executor
|
||||
this.progressUpdater = Executors.newSingleThreadScheduledExecutor();
|
||||
}
|
||||
|
||||
public void fixBiomes() {
|
||||
@ -94,6 +85,9 @@ public class IrisBiomeFixer {
|
||||
totalChunks.addAndGet(1024);
|
||||
}
|
||||
|
||||
// Start the progress updater
|
||||
progressUpdater.scheduleAtFixedRate(this::updateProgress, 1, 1, TimeUnit.SECONDS);
|
||||
|
||||
for (File regionFile : regionFiles) {
|
||||
String filename = regionFile.getName(); // e.g., "r.0.0.mca"
|
||||
String[] parts = filename.split("\\.");
|
||||
@ -114,81 +108,105 @@ public class IrisBiomeFixer {
|
||||
continue;
|
||||
}
|
||||
|
||||
J.s(() -> {
|
||||
world.loadChunk(chunkX, chunkZ);
|
||||
});
|
||||
Chunk chunk = world.getChunkAt(chunkX, chunkZ);
|
||||
|
||||
int minY = world.getMinHeight();
|
||||
int maxY = world.getMaxHeight();
|
||||
int height = maxY - minY; // Correct height calculation
|
||||
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int y = minY; y < maxY; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
Block block = chunk.getBlock(x, y, z);
|
||||
IrisBiome irisBiome = engine.getBiome(x, y, z);
|
||||
IrisBiomeCustom custom;
|
||||
try {
|
||||
custom = irisBiome.getCustomBiome(rng, x, y, z);
|
||||
} catch (Exception e) {
|
||||
custom = null;
|
||||
}
|
||||
Hunk<Object> biomes = Hunk.newHunk(16, height, 16);
|
||||
|
||||
if (custom != null) {
|
||||
try {
|
||||
int id = INMS.get().getBiomeBaseIdForKey(engine.getDimension().getLoadKey() + ":" + custom.getId());
|
||||
Biome biome = (Biome) INMS.get().getBiomeBaseFromId(id);
|
||||
world.setBiome(block.getX(), block.getY(), block.getZ(), biome);
|
||||
} catch (Exception e) {
|
||||
Iris.warn("Fallback! IrisBiome ID: " + custom.getId() + " is invalid!");
|
||||
world.setBiome(block.getX(), block.getY(), block.getZ(), irisBiome.getDerivative());
|
||||
}
|
||||
for (int x = 0; x < 16; x += 4) {
|
||||
for (int z = 0; z < 16; z += 4) {
|
||||
for (int y = minY; y < maxY; y += 4) {
|
||||
// Calculate the biome once per 4x4x4 block
|
||||
int realX = chunkX * 16 + x;
|
||||
int realZ = chunkZ * 16 + z;
|
||||
int realY = y;
|
||||
|
||||
IrisBiome biome = engine.getBiome(realX, realY, realZ);
|
||||
Object biomeHolder = null;
|
||||
|
||||
if (biome.isCustom()) {
|
||||
biomeHolder = INMS.get().getCustomBiomeBaseHolderFor(
|
||||
engine.getDimension().getLoadKey() + ":" + biome.getCustomBiome(rng, realX, realY, realZ).getId());
|
||||
} else {
|
||||
// Use derivative biome if custom biome is null
|
||||
world.setBiome(block.getX(), block.getY(), block.getZ(), irisBiome.getDerivative());
|
||||
// Handle non-custom biome if necessary
|
||||
// biomeHolder = INMS.get().getCustomBiomeBaseHolderFor(biome.getDerivative().getKey().getKey());
|
||||
}
|
||||
|
||||
// Now fill the 4x4x4 block in the hunk
|
||||
for (int subX = x; subX < x + 4 && subX < 16; subX++) {
|
||||
for (int subZ = z; subZ < z + 4 && subZ < 16; subZ++) {
|
||||
for (int subY = y; subY < y + 4 && subY < maxY; subY++) {
|
||||
int relativeY = subY - minY; // Offset Y-coordinate
|
||||
|
||||
biomes.set(subX, relativeY, subZ, biomeHolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INMS.get().setBiomes(cx, cz, engine.getWorld().realWorld(), biomes);
|
||||
|
||||
generated.incrementAndGet();
|
||||
|
||||
// Progress Logging
|
||||
if (progressLatch.flip()) {
|
||||
long currentTime = M.ms();
|
||||
long elapsedTime = currentTime - lastLogTime.get();
|
||||
int currentGenerated = generated.get();
|
||||
int last = lastGenerated.getAndSet(currentGenerated);
|
||||
int chunksProcessed = currentGenerated - last;
|
||||
|
||||
double seconds = elapsedTime / 1000.0;
|
||||
int cps = seconds > 0 ? (int) (chunksProcessed / seconds) : 0;
|
||||
chunksPerSecond.put(cps);
|
||||
|
||||
long eta = computeETA(cps);
|
||||
double percentage = ((double) currentGenerated / totalChunks.get()) * 100;
|
||||
|
||||
Iris.info(String.format("Biome Fixer Progress: %d/%d chunks (%.2f%%) - %d chunks/s ETA: %s",
|
||||
currentGenerated, totalChunks.get(), percentage, cps, formatETA(eta)));
|
||||
|
||||
lastLogTime.set(currentTime);
|
||||
}
|
||||
|
||||
world.unloadChunk(chunkX, chunkZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shut down the progress updater
|
||||
progressUpdater.shutdown();
|
||||
|
||||
try {
|
||||
// Wait for the progress updater to finish
|
||||
if (!progressUpdater.awaitTermination(1, TimeUnit.MINUTES)) {
|
||||
Iris.warn("Progress updater did not terminate in time.");
|
||||
progressUpdater.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Iris.warn("Progress updater interrupted during shutdown.");
|
||||
progressUpdater.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
// Final Progress Update
|
||||
Iris.info(String.format("Biome Fixing Completed: %d/%d chunks processed.", generated.get(), totalChunks.get()));
|
||||
Iris.info("Biome Fixing Completed: " + generated.get() + "/" + totalChunks.get() + " chunks processed.");
|
||||
}
|
||||
|
||||
private long computeETA(int cps) {
|
||||
if (chunksPerSecond.size() < chunksPerSecond.getMax()) {
|
||||
if (cps == 0) return Long.MAX_VALUE;
|
||||
private void updateProgress() {
|
||||
long currentTime = M.ms();
|
||||
int currentGenerated = generated.get();
|
||||
int last = generatedLast.getAndSet(currentGenerated);
|
||||
int chunksProcessed = currentGenerated - last;
|
||||
|
||||
chunksPerSecond.put(chunksProcessed);
|
||||
|
||||
// Update chunks per minute
|
||||
if (minuteLatch.flip()) {
|
||||
int lastMinuteGenerated = generatedLastMinute.getAndSet(currentGenerated);
|
||||
int minuteProcessed = currentGenerated - lastMinuteGenerated;
|
||||
chunksPerMinute.put(minuteProcessed);
|
||||
}
|
||||
|
||||
long eta = computeETA();
|
||||
double percentage = ((double) currentGenerated / totalChunks.get()) * 100;
|
||||
|
||||
if (progressLatch.flip()) {
|
||||
Iris.info("Biome Fixer Progress: " + currentGenerated + "/" + totalChunks.get() +
|
||||
" chunks (" + percentage + "%%) - " +
|
||||
chunksPerSecond.getAverage() + " chunks/s ETA: " + formatETA(eta));
|
||||
}
|
||||
}
|
||||
|
||||
private long computeETA() {
|
||||
if (generated.get() > totalChunks.get() / 8) {
|
||||
// Use smooth function
|
||||
double elapsedTime = (double) (M.ms() - startTime.get());
|
||||
double rate = generated.get() / elapsedTime; // chunks per millisecond
|
||||
int remaining = totalChunks.get() - generated.get();
|
||||
return (long) ((double) remaining / cps) * 1000;
|
||||
return (long) (remaining / rate);
|
||||
} else {
|
||||
// Use quick function
|
||||
double averageCps = chunksPerSecond.getAverage();
|
||||
if (averageCps == 0) return Long.MAX_VALUE;
|
||||
int remaining = totalChunks.get() - generated.get();
|
||||
@ -205,6 +223,6 @@ public class IrisBiomeFixer {
|
||||
seconds %= 60;
|
||||
long hours = minutes / 60;
|
||||
minutes %= 60;
|
||||
return String.format("%02dh:%02dm:%02ds", hours, minutes, seconds);
|
||||
return hours + "h:" + minutes + "m:" + seconds + "s";
|
||||
}
|
||||
}
|
@ -1,10 +1,6 @@
|
||||
package com.volmit.iris.core.nms.v1_20_R3;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
@ -33,10 +29,8 @@ import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlockState;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlockStates;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftDolphin;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.util.CraftNamespacedKey;
|
||||
import org.bukkit.entity.Dolphin;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
@ -56,7 +50,6 @@ import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.Vector3d;
|
||||
import com.volmit.iris.util.matter.MatterBiomeInject;
|
||||
import com.volmit.iris.util.nbt.io.NBTUtil;
|
||||
import com.volmit.iris.util.nbt.mca.NBTWorld;
|
||||
import com.volmit.iris.util.nbt.mca.palette.*;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
@ -71,14 +64,12 @@ import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
public class NMSBinding implements INMSBinding {
|
||||
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
|
||||
@ -286,7 +277,11 @@ public class NMSBinding implements INMSBinding {
|
||||
|
||||
@Override
|
||||
public int getTrueBiomeBaseId(Object biomeBase) {
|
||||
return getCustomBiomeRegistry().getId(((Holder<net.minecraft.world.level.biome.Biome>) biomeBase).value());
|
||||
if (biomeBase instanceof net.minecraft.world.level.biome.Biome) {
|
||||
net.minecraft.world.level.biome.Biome biome = (net.minecraft.world.level.biome.Biome) biomeBase;
|
||||
return getCustomBiomeRegistry().getId(biome);
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid biomeBase type: " + biomeBase.getClass().getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -315,7 +310,15 @@ public class NMSBinding implements INMSBinding {
|
||||
|
||||
@Override
|
||||
public String getKeyForBiomeBase(Object biomeBase) {
|
||||
return getCustomBiomeRegistry().getKey((net.minecraft.world.level.biome.Biome) biomeBase).getPath(); // something, not something:something
|
||||
if (biomeBase instanceof net.minecraft.core.Holder<?>) {
|
||||
net.minecraft.core.Holder<?> holder = (net.minecraft.core.Holder<?>) biomeBase;
|
||||
|
||||
if (holder.value() instanceof net.minecraft.world.level.biome.Biome) {
|
||||
net.minecraft.world.level.biome.Biome biome = (net.minecraft.world.level.biome.Biome) holder.value();
|
||||
return getCustomBiomeRegistry().getKey(biome).getPath();
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid biomeBase type: " + biomeBase.getClass().getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -438,6 +441,7 @@ public class NMSBinding implements INMSBinding {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiomes(int cx, int cz, World world, Hunk<Object> biomes) {
|
||||
LevelChunk c = ((CraftWorld) world).getHandle().getChunk(cx, cz);
|
||||
biomes.iterateSync((x, y, z, b) -> c.setBiome(x, y, z, (Holder<net.minecraft.world.level.biome.Biome>) b));
|
||||
|
Loading…
x
Reference in New Issue
Block a user