diff --git a/src/main/java/me/cortex/voxelmon/Test.java b/src/main/java/me/cortex/voxelmon/Test.java index e6cdbdc0..14223fa3 100644 --- a/src/main/java/me/cortex/voxelmon/Test.java +++ b/src/main/java/me/cortex/voxelmon/Test.java @@ -57,6 +57,6 @@ public class Test { //WorldEngine engine = new WorldEngine(new File("storagefile2.db"), 5); WorldImporter importer = new WorldImporter(null, null); //importer.importWorld(new File("run/saves/Drehmal 2.2 Apotheosis Beta - 1.0.0/region/")); - importer.importWorldAsyncStart(new File("D:\\PrismLauncher-Windows-MSVC-Portable-7.1\\instances\\1.20.1(3)\\.minecraft\\.bobby\\build.docm77.de\\-8149132374211427218\\minecraft\\overworld\\")); + importer.importWorldAsyncStart(new File("D:\\PrismLauncher-Windows-MSVC-Portable-7.1\\instances\\1.20.1(3)\\.minecraft\\.bobby\\build.docm77.de\\-8149132374211427218\\minecraft\\overworld\\"), 2,null, null); } } diff --git a/src/main/java/me/cortex/voxelmon/Voxelmon.java b/src/main/java/me/cortex/voxelmon/Voxelmon.java index 846a0ad2..c0f07545 100644 --- a/src/main/java/me/cortex/voxelmon/Voxelmon.java +++ b/src/main/java/me/cortex/voxelmon/Voxelmon.java @@ -1,6 +1,7 @@ package me.cortex.voxelmon; import me.cortex.voxelmon.terrain.TestSparseGenCommand; +//import me.cortex.voxelmon.terrain.WorldImportCommand; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; @@ -8,6 +9,6 @@ import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; public class Voxelmon implements ClientModInitializer { @Override public void onInitializeClient() { - //CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> TestSparseGenCommand.register(dispatcher)); + //CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> WorldImportCommand.register(dispatcher)); } } diff --git a/src/main/java/me/cortex/voxelmon/core/VoxelCore.java b/src/main/java/me/cortex/voxelmon/core/VoxelCore.java index 34d5f046..52bcc8a6 100644 --- a/src/main/java/me/cortex/voxelmon/core/VoxelCore.java +++ b/src/main/java/me/cortex/voxelmon/core/VoxelCore.java @@ -22,6 +22,7 @@ import net.minecraft.client.render.Frustum; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.Box; import net.minecraft.util.math.Direction; +import net.minecraft.world.World; import net.minecraft.world.chunk.WorldChunk; import org.lwjgl.system.MemoryUtil; @@ -72,7 +73,7 @@ public class VoxelCore { //Trigger the shared index buffer loading SharedIndexBuffer.INSTANCE.id(); this.renderer = new Gl46FarWorldRenderer(); - this.world = new WorldEngine(new File("storagefile2.db"), 20, 5);//"storagefile.db"//"ethoslab.db" + this.world = new WorldEngine(new File("storagefile.db"), 20, 5);//"storagefile.db"//"ethoslab.db" this.renderTracker = new RenderTracker(this.world, this.renderer); this.renderGen = new RenderGenerationService(this.world,4, this.renderTracker::processBuildResult); @@ -196,4 +197,12 @@ public class VoxelCore { try {this.renderer.shutdown();} catch (Exception e) {System.err.println(e);} try {this.postProcessing.shutdown();} catch (Exception e) {System.err.println(e);} } + + public WorldImporter createWorldImporter(World mcWorld, File worldPath) { + var importer = new WorldImporter(this.world, mcWorld); + importer.importWorldAsyncStart(worldPath, 10, null, ()->{ + System.err.println("DONE IMPORT"); + }); + return importer; + } } diff --git a/src/main/java/me/cortex/voxelmon/core/rendering/building/RenderDataFactory.java b/src/main/java/me/cortex/voxelmon/core/rendering/building/RenderDataFactory.java index b31f412c..569f7215 100644 --- a/src/main/java/me/cortex/voxelmon/core/rendering/building/RenderDataFactory.java +++ b/src/main/java/me/cortex/voxelmon/core/rendering/building/RenderDataFactory.java @@ -3,6 +3,7 @@ package me.cortex.voxelmon.core.rendering.building; import it.unimi.dsi.fastutil.longs.LongArrayList; import me.cortex.voxelmon.core.util.MemoryBuffer; import me.cortex.voxelmon.core.util.Mesher2D; +import me.cortex.voxelmon.core.util.Mesher2Dv2; import me.cortex.voxelmon.core.world.WorldEngine; import me.cortex.voxelmon.core.world.WorldSection; import me.cortex.voxelmon.core.world.other.Mapper; @@ -11,7 +12,7 @@ import org.lwjgl.system.MemoryUtil; public class RenderDataFactory { - private final Mesher2D mesher = new Mesher2D(5,15);//15 + private final Mesher2Dv2 mesher = new Mesher2Dv2(5,15);//15 private final LongArrayList outData = new LongArrayList(1000); private final WorldEngine world; public RenderDataFactory(WorldEngine world) { diff --git a/src/main/java/me/cortex/voxelmon/core/util/Mesher2Dv2.java b/src/main/java/me/cortex/voxelmon/core/util/Mesher2Dv2.java new file mode 100644 index 00000000..1e427df3 --- /dev/null +++ b/src/main/java/me/cortex/voxelmon/core/util/Mesher2Dv2.java @@ -0,0 +1,175 @@ +package me.cortex.voxelmon.core.util; + +import java.util.Arrays; +import java.util.BitSet; +import java.util.Random; + +public class Mesher2Dv2 { + private final int size; + private final int maxSize; + private final long[] data; + private final BitSet setset; + private int[] quadCache; + public Mesher2Dv2(int sizeBits, int maxSize) { + this.size = sizeBits; + this.maxSize = maxSize; + this.data = new long[1<<(sizeBits<<1)]; + this.setset = new BitSet(1<<(sizeBits<<1)); + this.quadCache = new int[128]; + } + + private int getIdx(int x, int z) { + int M = (1<M || z>M) { + throw new IllegalStateException(); + } + return ((z&M)<>24)&0xFF; + } + + public static int getZ(int data) { + return (data>>16)&0xFF; + } + + public static int getH(int data) { + return (data>>8)&0xFF; + } + + public static int getW(int data) { + return data&0xFF; + } + + // + private static int encodeQuad(int x, int z, int sx, int sz) { + return ((x&0xFF)<<24)|((z&0xFF)<<16)|((sx&0xFF)<<8)|((sz&0xFF)<<0); + } + + private boolean canMerge(int x, int z, long match) { + int id = this.getIdx(x, z); + return this.setset.get(id) && this.data[id] == match; + } + + public int[] process() { + int[] quads = this.quadCache; + int idxCount = 0; + + //TODO: add different strategies/ways to mesh + int posId = this.data[0] == 0?this.setset.nextSetBit(0):0; + while (posId < this.data.length && posId != -1) { + int idx = posId; + long data = this.data[idx]; + + int M = (1<>>this.size)&M; + + boolean ex = x != ((1< this.maxSize || endX+1 == (1 << this.size) - 1) { + ex = false; + } + } + if (ex) { + for (int tz = z; tz < endZ+1; tz++) { + if (!this.canMerge(endX + 1, tz, data)) { + ex = false; + } + } + } + if (ex) { + endX++; + } + if (ez) { + if (endZ + 1 > this.maxSize || endZ+1 == (1<{ - var file = child.toFile(); - if (!file.isFile()) { - return; - } - var name = file.getName(); - var sections = name.split("\\."); - if (sections.length != 4 || (!sections[0].equals("r")) || (!sections[3].equals("mca"))) { - throw new IllegalStateException(); - } - int rx = Integer.parseInt(sections[1]); - int rz = Integer.parseInt(sections[2]); - }); - } - - private void importRegionFile(Path file, int x, int z) throws IOException { - try (var fileStream = FileChannel.open(file, StandardOpenOption.READ)) { - var sectorsSavesBB = MemoryUtil.memAlloc(8192); - if (fileStream.read(sectorsSavesBB) != 8192) { - throw new IllegalStateException("Header of region file invalid"); - } - var sectorsSaves = sectorsSavesBB.asIntBuffer(); - - //Find and load all saved chunks - for (int idx = 0; idx < 1024; idx++) { - int sectorMeta = sectorsSaves.get(idx); - if (sectorMeta == 0) { - //Empty chunk - continue; - } - int sectorStart = sectorMeta>>>8; - int sectorCount = sectorMeta&((1<<8)-1); - - - } - } - } - - private void importChunkNBT(ChunkPos pos, NbtCompound chunk) { - - } -} diff --git a/src/main/java/me/cortex/voxelmon/importers/WorldImporter.java b/src/main/java/me/cortex/voxelmon/importers/WorldImporter.java index 9fdd1137..165fe321 100644 --- a/src/main/java/me/cortex/voxelmon/importers/WorldImporter.java +++ b/src/main/java/me/cortex/voxelmon/importers/WorldImporter.java @@ -30,8 +30,14 @@ import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.Arrays; import java.util.Objects; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.function.Function; public class WorldImporter { + public record ImportUpdate(){} + private final WorldEngine world; private final World mcWorld; private final Codec>> biomeCodec; @@ -45,27 +51,35 @@ public class WorldImporter { } private Thread worker; - public void importWorldAsyncStart(File directory) { + public void importWorldAsyncStart(File directory, int threads, Function updateCallback, Runnable onCompletion) { this.worker = new Thread(() -> { - Arrays.stream(directory.listFiles()).parallel().forEach(file -> { + var workers = new ForkJoinPool(threads); + for (var file : directory.listFiles()) { if (!file.isFile()) { - return; + continue; } var name = file.getName(); var sections = name.split("\\."); if (sections.length != 4 || (!sections[0].equals("r")) || (!sections[3].equals("mca"))) { System.err.println("Unknown file: " + name); - return; + continue; } int rx = Integer.parseInt(sections[1]); int rz = Integer.parseInt(sections[2]); - try { - this.importRegionFile(file.toPath(), rx, rz); - } catch (Exception e) { - e.printStackTrace(); - } - }); - System.err.println("Done"); + workers.submit(() -> { + try { + this.importRegionFile(file.toPath(), rx, rz); + } catch ( + Exception e) { + e.printStackTrace(); + } + }); + } + workers.shutdown(); + try { + workers.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); + } catch (InterruptedException e) {} + onCompletion.run(); }); this.worker.setName("World importer"); this.worker.start(); diff --git a/src/main/java/me/cortex/voxelmon/terrain/WorldImportCommand.java b/src/main/java/me/cortex/voxelmon/terrain/WorldImportCommand.java new file mode 100644 index 00000000..b34b2301 --- /dev/null +++ b/src/main/java/me/cortex/voxelmon/terrain/WorldImportCommand.java @@ -0,0 +1,29 @@ +package me.cortex.voxelmon.terrain; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.context.CommandContext; +import me.cortex.voxelmon.core.VoxelCore; +import me.cortex.voxelmon.importers.WorldImporter; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientCommandSource; +import net.minecraft.server.command.ServerCommandSource; + +import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal; +import static com.mojang.brigadier.builder.RequiredArgumentBuilder.argument; + + +/* +public class WorldImportCommand { + public static void register(CommandDispatcher dispatcher) { + dispatcher.register(literal("zenith") + .then(literal("import").then(literal("world").then(argument("world_name", StringArgumentType.string()).executes(WorldImportCommand::importWorld))))); + } + + + private static int importWorld(CommandContext ctx) { + VoxelCore.INSTANCE.createWorldImporter(MinecraftClient.getInstance().world, ctx.getArgument("world_name", String.class)); + return 0; + } +} +*/ \ No newline at end of file