This commit is contained in:
RePixelatedMC
2024-09-27 17:07:01 +02:00
parent 7583b91d46
commit 9a24627ceb
3 changed files with 168 additions and 153 deletions

View File

@@ -1,134 +0,0 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2022 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.core.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.pregenerator.DeepSearchPregenerator;
import com.volmit.iris.core.pregenerator.PregenTask;
import com.volmit.iris.core.pregenerator.TurboPregenerator;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.util.data.Dimension;
import com.volmit.iris.util.decree.DecreeExecutor;
import com.volmit.iris.util.decree.annotations.Decree;
import com.volmit.iris.util.decree.annotations.Param;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.Position2;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.util.Vector;
import java.io.File;
import java.io.IOException;
@Decree(name = "DeepSearch", aliases = "search", description = "Pregenerate your Iris worlds!")
public class CommandDeepSearch implements DecreeExecutor {
public String worldName;
@Decree(description = "DeepSearch a world")
public void start(
@Param(description = "The radius of the pregen in blocks", aliases = "size")
int radius,
@Param(description = "The world to pregen", contextual = true)
World world,
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
Vector center
) {
worldName = world.getName();
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
File TurboFile = new File(worldDirectory, "DeepSearch.json");
if (TurboFile.exists()) {
if (DeepSearchPregenerator.getInstance() != null) {
sender().sendMessage(C.BLUE + "DeepSearch is already in progress");
Iris.info(C.YELLOW + "DeepSearch is already in progress");
return;
} else {
try {
TurboFile.delete();
} catch (Exception e){
Iris.error("Failed to delete the old instance file of DeepSearch!");
return;
}
}
}
try {
if (sender().isPlayer() && access() == null) {
sender().sendMessage(C.RED + "The engine access for this world is null!");
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
}
DeepSearchPregenerator.DeepSearchJob DeepSearchJob = DeepSearchPregenerator.DeepSearchJob.builder()
.world(world)
.radiusBlocks(radius)
.position(0)
.build();
File SearchGenFile = new File(worldDirectory, "DeepSearch.json");
DeepSearchPregenerator pregenerator = new DeepSearchPregenerator(DeepSearchJob, SearchGenFile);
pregenerator.start();
String msg = C.GREEN + "DeepSearch started in " + C.GOLD + worldName + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
sender().sendMessage(msg);
Iris.info(msg);
} catch (Throwable e) {
sender().sendMessage(C.RED + "Epic fail. See console.");
Iris.reportError(e);
e.printStackTrace();
}
}
@Decree(description = "Stop the active DeepSearch task", aliases = "x")
public void stop(@Param(aliases = "world", description = "The world to pause") World world) throws IOException {
DeepSearchPregenerator DeepSearchInstance = DeepSearchPregenerator.getInstance();
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
File turboFile = new File(worldDirectory, "DeepSearch.json");
if (DeepSearchInstance != null) {
DeepSearchInstance.shutdownInstance(world);
sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName());
} else if (turboFile.exists() && turboFile.delete()) {
sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName());
} else if (turboFile.exists()) {
Iris.error("Failed to delete the old instance file of Turbo Pregen!");
} else {
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
}
}
@Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
public void pause(
@Param(aliases = "world", description = "The world to pause")
World world
) {
if (TurboPregenerator.getInstance() != null) {
TurboPregenerator.setPausedTurbo(world);
sender().sendMessage(C.GREEN + "Paused/unpaused Turbo Pregen, now: " + (TurboPregenerator.isPausedTurbo(world) ? "Paused" : "Running") + ".");
} else {
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
File TurboFile = new File(worldDirectory, "DeepSearch.json");
if (TurboFile.exists()){
TurboPregenerator.loadTurboGenerator(world.getName());
sender().sendMessage(C.YELLOW + "Started DeepSearch back up!");
} else {
sender().sendMessage(C.YELLOW + "No active DeepSearch tasks to pause/unpause.");
}
}
}
}

View File

@@ -26,6 +26,7 @@ import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
import com.volmit.iris.core.pregenerator.ChunkUpdater;
import com.volmit.iris.core.service.IrisEngineSVC;
import com.volmit.iris.core.tools.IrisBiomeFixer;
import com.volmit.iris.core.tools.IrisConverter;
import com.volmit.iris.core.tools.IrisPackBenchmarking;
import com.volmit.iris.core.tools.IrisToolbelt;
@@ -160,6 +161,16 @@ public class CommandDeveloper implements DecreeExecutor {
}
@Decree(description = "Fix biomes in a iris world")
public void fixBiomes(
@Param(description = "The IrisWorld to fix biomes at") World world) {
IrisBiomeFixer biomeFixer = new IrisBiomeFixer(world);
Iris.info("Fixing biomes.");
biomeFixer.fixBiomes();
Iris.info("Done fixing biomes!");
}
@Decree(description = "Upgrade to another Minecraft version")
public void upgrade(
@Param(description = "The version to upgrade to", defaultValue = "latest") DataVersion version) {

View File

@@ -1,46 +1,184 @@
package com.volmit.iris.core.tools;
import com.volmit.iris.Iris;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
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.math.M;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.Spiraler;
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.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.scheduling.ChronoLatch;
import org.bukkit.Chunk;
import com.volmit.iris.util.scheduling.J;
import org.bukkit.World;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import org.bukkit.Chunk;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.concurrent.atomic.AtomicLong;
public class IrisBiomeFixer {
/**
* Do a pregen style approach irritate across a certain region and set everything to the correct biome again.
* 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 AtomicLong startTime;
private AtomicLong lastLogTime;
public IrisBiomeFixer(World world, int radius) {
private AtomicInteger generated = new AtomicInteger(0);
private AtomicInteger lastGenerated = new AtomicInteger(0);
private AtomicInteger totalChunks = new AtomicInteger(0);
private ChronoLatch progressLatch = new ChronoLatch(5000); // Update every 5 seconds
public IrisBiomeFixer(World world) {
if (!IrisToolbelt.isIrisWorld(world)) {
Iris.info("This is not an Iris world!");
return;
}
this.chunksPerSecond = new RollingSequence(32);
this.startTime = new AtomicLong(M.ms());
this.lastLogTime = new AtomicLong(M.ms());
this.world = world;
this.radius = radius;
this.latch = new ChronoLatch(3000);
this.engine = IrisToolbelt.access(world).getEngine();
}
public void fixBiomes() {
File regionFolder = new File(world.getWorldFolder(), "region");
File[] regionFiles = regionFolder.listFiles((dir, name) -> name.endsWith(".mca"));
if (regionFiles == null || regionFiles.length == 0) {
Iris.info("No region files found in " + regionFolder.getAbsolutePath());
return;
}
RNG rng = new RNG(engine.getSeedManager().getBiome());
// Calculate total chunks
for (File regionFile : regionFiles) {
String filename = regionFile.getName(); // e.g., "r.0.0.mca"
String[] parts = filename.split("\\.");
if (parts.length != 4) {
continue;
}
totalChunks.addAndGet(1024); // Each region has 32x32 chunks = 1024
}
for (File regionFile : regionFiles) {
String filename = regionFile.getName(); // e.g., "r.0.0.mca"
String[] parts = filename.split("\\.");
if (parts.length != 4) {
continue;
}
int regionX = Integer.parseInt(parts[1]);
int regionZ = Integer.parseInt(parts[2]);
for (int cx = 0; cx < 32; cx++) {
for (int cz = 0; cz < 32; cz++) {
int chunkX = regionX * 32 + cx;
int chunkZ = regionZ * 32 + cz;
if (!world.isChunkGenerated(chunkX, chunkZ)) {
continue;
}
J.s(() -> {
world.loadChunk(chunkX, chunkZ);
});
Chunk chunk = world.getChunkAt(chunkX, chunkZ);
int minY = world.getMinHeight();
int maxY = world.getMaxHeight();
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);
Biome bukkitBiome = null;
IrisBiome irisBiome = engine.getBiome(x, y, z);
IrisBiomeCustom custom = irisBiome.getCustomBiome(rng, x, y, z);
if (custom != null) {
bukkitBiome = Biome.valueOf(custom.getId().toUpperCase());
} else {
}
world.setBiome(block.getX(), block.getY(), block.getZ(), bukkitBiome);
}
}
}
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);
}
}
}
// Final Progress Update
Iris.info(String.format("Biome Fixing Completed: %d/%d chunks processed.", generated.get(), totalChunks.get()));
}
private long computeETA(int cps) {
if (chunksPerSecond.size() < chunksPerSecond.getMax()) {
if (cps == 0) return Long.MAX_VALUE;
int remaining = totalChunks.get() - generated.get();
return (long) ((double) remaining / cps) * 1000;
} else {
double averageCps = chunksPerSecond.getAverage();
if (averageCps == 0) return Long.MAX_VALUE;
int remaining = totalChunks.get() - generated.get();
return (long) ((double) remaining / averageCps) * 1000;
}
}
private String formatETA(long millis) {
if (millis == Long.MAX_VALUE) {
return "Unknown";
}
long seconds = millis / 1000;
long minutes = seconds / 60;
seconds %= 60;
long hours = minutes / 60;
minutes %= 60;
return String.format("%02dh:%02dm:%02ds", hours, minutes, seconds);
}
}