Added progress bar to world importer, world name suggestions for when import a world (not bobby), fixed the entire thing segfaulting if voxy core shuts down while importing
This commit is contained in:
@@ -16,7 +16,10 @@ import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.Camera;
|
||||
import net.minecraft.client.render.Frustum;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.boss.BossBar;
|
||||
import net.minecraft.entity.boss.ServerBossBar;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.WorldChunk;
|
||||
import org.joml.Matrix4f;
|
||||
@@ -54,7 +57,7 @@ public class VoxelCore {
|
||||
|
||||
//private final Thread shutdownThread = new Thread(this::shutdown);
|
||||
|
||||
|
||||
private WorldImporter importer;
|
||||
public VoxelCore(ContextSelectionSystem.Selection worldSelection) {
|
||||
this.world = worldSelection.createEngine();
|
||||
var cfg = worldSelection.getConfig();
|
||||
@@ -216,6 +219,10 @@ public class VoxelCore {
|
||||
//}
|
||||
|
||||
//this.world.getMapper().forceResaveStates();
|
||||
if (this.importer != null) {
|
||||
System.out.println("Shutting down importer");
|
||||
try {this.importer.shutdown();this.importer = null;} catch (Exception e) {System.err.println(e);}
|
||||
}
|
||||
System.out.println("Shutting down voxel core");
|
||||
try {this.renderGen.shutdown();} catch (Exception e) {System.err.println(e);}
|
||||
System.out.println("Render gen shut down");
|
||||
@@ -227,12 +234,24 @@ public class VoxelCore {
|
||||
System.out.println("Voxel core shut down");
|
||||
}
|
||||
|
||||
public WorldImporter createWorldImporter(World mcWorld, File worldPath) {
|
||||
public boolean createWorldImporter(World mcWorld, File worldPath) {
|
||||
if (this.importer != null) {
|
||||
return false;
|
||||
}
|
||||
var importer = new WorldImporter(this.world, mcWorld);
|
||||
importer.importWorldAsyncStart(worldPath, 4, null, ()->{
|
||||
System.err.println("DONE IMPORT");
|
||||
});
|
||||
return importer;
|
||||
var bossBar = new ServerBossBar(Text.of("Voxy world importer"), BossBar.Color.GREEN, BossBar.Style.PROGRESS);
|
||||
bossBar.addPlayer(MinecraftClient.getInstance().getServer().getPlayerManager().getPlayer(MinecraftClient.getInstance().player.getUuid()));
|
||||
importer.importWorldAsyncStart(worldPath, 4, (a,b)->
|
||||
MinecraftClient.getInstance().executeSync(()-> {
|
||||
bossBar.setPercent(((float) a)/((float) b));
|
||||
bossBar.setName(Text.of("Voxy import: "+ a+"/"+b + " region files"));
|
||||
}),
|
||||
()-> {
|
||||
MinecraftClient.getInstance().executeSync(bossBar::clearPlayers);
|
||||
this.importer = null;
|
||||
});
|
||||
this.importer = importer;
|
||||
return true;
|
||||
}
|
||||
|
||||
public WorldEngine getWorldEngine() {
|
||||
|
||||
@@ -36,19 +36,19 @@ import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class WorldImporter {
|
||||
public record ImportUpdate(){}
|
||||
public interface UpdateCallback {
|
||||
void update(int finished, int outof);
|
||||
}
|
||||
|
||||
private final WorldEngine world;
|
||||
private final World mcWorld;
|
||||
private final ReadableContainer<RegistryEntry<Biome>> defaultBiomeProvider;
|
||||
private final Codec<ReadableContainer<RegistryEntry<Biome>>> biomeCodec;
|
||||
private final AtomicInteger totalRegions = new AtomicInteger();
|
||||
private final AtomicInteger regionsProcessed = new AtomicInteger();
|
||||
private final AtomicInteger percentMarker = new AtomicInteger();
|
||||
|
||||
private volatile boolean isRunning;
|
||||
public WorldImporter(WorldEngine worldEngine, World mcWorld) {
|
||||
this.world = worldEngine;
|
||||
this.mcWorld = mcWorld;
|
||||
|
||||
var biomeRegistry = mcWorld.getRegistryManager().get(RegistryKeys.BIOME);
|
||||
var defaultBiome = biomeRegistry.entryOf(BiomeKeys.PLAINS);
|
||||
@@ -97,9 +97,16 @@ public class WorldImporter {
|
||||
this.biomeCodec = PalettedContainer.createReadableContainerCodec(biomeRegistry.getIndexedEntries(), biomeRegistry.createEntryCodec(), PalettedContainer.PaletteProvider.BIOME, biomeRegistry.entryOf(BiomeKeys.PLAINS));
|
||||
}
|
||||
|
||||
|
||||
public void shutdown() {
|
||||
this.isRunning = false;
|
||||
try {this.worker.join();} catch (InterruptedException e) {throw new RuntimeException(e);}
|
||||
}
|
||||
|
||||
private Thread worker;
|
||||
public void importWorldAsyncStart(File directory, int threads, Function<ImportUpdate, Boolean> updateCallback, Runnable onCompletion) {
|
||||
public void importWorldAsyncStart(File directory, int threads, UpdateCallback updateCallback, Runnable onCompletion) {
|
||||
this.worker = new Thread(() -> {
|
||||
this.isRunning = true;
|
||||
var workers = new ForkJoinPool(threads);
|
||||
var files = directory.listFiles();
|
||||
for (var file : files) {
|
||||
@@ -117,16 +124,12 @@ public class WorldImporter {
|
||||
this.totalRegions.addAndGet(1);
|
||||
workers.submit(() -> {
|
||||
try {
|
||||
if (!isRunning) {
|
||||
return;
|
||||
}
|
||||
this.importRegionFile(file.toPath(), rx, rz);
|
||||
int regionsProcessedCount = this.regionsProcessed.addAndGet(1);
|
||||
synchronized (this.world) {
|
||||
int percentMark = this.percentMarker.get();
|
||||
int percent = (regionsProcessedCount*100)/this.totalRegions.get();
|
||||
if (percent > percentMark) {
|
||||
System.out.println(regionsProcessedCount + "/" + this.totalRegions.get());
|
||||
this.percentMarker.addAndGet(1);
|
||||
}
|
||||
}
|
||||
updateCallback.update(regionsProcessedCount, this.totalRegions.get());
|
||||
} catch (
|
||||
Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -3,13 +3,19 @@ package me.cortex.voxy.client.terrain;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.suggestion.Suggestions;
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||
import me.cortex.voxy.client.core.IGetVoxelCore;
|
||||
import me.cortex.voxy.client.importers.WorldImporter;
|
||||
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
|
||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.command.CommandSource;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
|
||||
public class WorldImportCommand {
|
||||
@@ -17,33 +23,55 @@ public class WorldImportCommand {
|
||||
return ClientCommandManager.literal("voxy").then(
|
||||
ClientCommandManager.literal("import")
|
||||
.then(ClientCommandManager.literal("world")
|
||||
.then(ClientCommandManager.argument("world_name", StringArgumentType.string()).executes(WorldImportCommand::importWorld)))
|
||||
.then(ClientCommandManager.argument("world_name", StringArgumentType.string())
|
||||
.suggests(WorldImportCommand::importWorldSuggester)
|
||||
.executes(WorldImportCommand::importWorld)))
|
||||
.then(ClientCommandManager.literal("bobby")
|
||||
.then(ClientCommandManager.argument("world_name", StringArgumentType.string()).executes(WorldImportCommand::importBobby)))
|
||||
.then(ClientCommandManager.argument("world_name", StringArgumentType.string())
|
||||
.executes(WorldImportCommand::importBobby)))
|
||||
.then(ClientCommandManager.literal("raw")
|
||||
.then(ClientCommandManager.argument("path", StringArgumentType.string()).executes(WorldImportCommand::importRaw))));
|
||||
.then(ClientCommandManager.argument("path", StringArgumentType.string())
|
||||
.executes(WorldImportCommand::importRaw))));
|
||||
}
|
||||
|
||||
public static WorldImporter importerInstance;
|
||||
|
||||
private static int importRaw(CommandContext<FabricClientCommandSource> ctx) {
|
||||
var instance = MinecraftClient.getInstance();
|
||||
var file = new File(ctx.getArgument("path", String.class));
|
||||
importerInstance = ((IGetVoxelCore)instance.worldRenderer).getVoxelCore().createWorldImporter(MinecraftClient.getInstance().player.clientWorld, file);
|
||||
((IGetVoxelCore)instance.worldRenderer).getVoxelCore().createWorldImporter(MinecraftClient.getInstance().player.clientWorld, file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int importBobby(CommandContext<FabricClientCommandSource> ctx) {
|
||||
var instance = MinecraftClient.getInstance();
|
||||
var file = new File(".bobby").toPath().resolve(ctx.getArgument("world_name", String.class)).toFile();
|
||||
importerInstance = ((IGetVoxelCore)instance.worldRenderer).getVoxelCore().createWorldImporter(MinecraftClient.getInstance().player.clientWorld, file);
|
||||
((IGetVoxelCore)instance.worldRenderer).getVoxelCore().createWorldImporter(MinecraftClient.getInstance().player.clientWorld, file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static CompletableFuture<Suggestions> importWorldSuggester(CommandContext<FabricClientCommandSource> ctx, SuggestionsBuilder sb) {
|
||||
try {
|
||||
var worlds = Files.list(MinecraftClient.getInstance().runDirectory.toPath().resolve("saves")).toList();
|
||||
for (var world : worlds) {
|
||||
if (!world.toFile().isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
var wn = world.getFileName().toString();
|
||||
if (CommandSource.shouldSuggest(sb.getRemaining(), wn)) {
|
||||
sb.suggest(wn);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return sb.buildFuture();
|
||||
}
|
||||
|
||||
private static int importWorld(CommandContext<FabricClientCommandSource> ctx) {
|
||||
var instance = MinecraftClient.getInstance();
|
||||
var file = new File("saves").toPath().resolve(ctx.getArgument("world_name", String.class)).resolve("region").toFile();
|
||||
importerInstance = ((IGetVoxelCore)instance.worldRenderer).getVoxelCore().createWorldImporter(MinecraftClient.getInstance().player.clientWorld, file);
|
||||
((IGetVoxelCore)instance.worldRenderer).getVoxelCore().createWorldImporter(MinecraftClient.getInstance().player.clientWorld, file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user