This commit is contained in:
mcrcortex
2025-03-26 16:03:17 +10:00
parent d73f844b10
commit e812b13ef7
17 changed files with 113 additions and 88 deletions

View File

@@ -1,19 +1,14 @@
package me.cortex.voxy.client;
import me.cortex.voxy.client.core.VoxelCore;
import me.cortex.voxy.client.saver.ContextSelectionSystem;
import me.cortex.voxy.client.terrain.WorldImportCommand;
import me.cortex.voxy.commonImpl.VoxyCommon;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientWorldEvents;
import net.minecraft.client.world.ClientWorld;
public class VoxyClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {
dispatcher.register(WorldImportCommand.register());
dispatcher.register(VoxyCommands.register());
});
VoxyCommon.setInstanceFactory(VoxyClientInstance::new);
}

View File

@@ -1,19 +1,13 @@
package me.cortex.voxy.client;
import me.cortex.voxy.client.config.VoxyConfig;
import me.cortex.voxy.client.core.WorldImportWrapper;
import me.cortex.voxy.client.saver.ContextSelectionSystem;
import me.cortex.voxy.common.Logger;
import me.cortex.voxy.common.world.WorldEngine;
import me.cortex.voxy.commonImpl.IVoxyWorldGetter;
import me.cortex.voxy.commonImpl.IVoxyWorldSetter;
import me.cortex.voxy.commonImpl.IVoxyWorld;
import me.cortex.voxy.commonImpl.ImportManager;
import me.cortex.voxy.commonImpl.VoxyInstance;
import me.cortex.voxy.commonImpl.importers.DHImporter;
import net.minecraft.client.world.ClientWorld;
import java.io.File;
public class VoxyClientInstance extends VoxyInstance {
private static final ContextSelectionSystem SELECTOR = new ContextSelectionSystem();
@@ -27,10 +21,10 @@ public class VoxyClientInstance extends VoxyInstance {
}
public WorldEngine getOrMakeRenderWorld(ClientWorld world) {
var vworld = ((IVoxyWorldGetter)world).getWorldEngine();
var vworld = ((IVoxyWorld)world).getWorldEngine();
if (vworld == null) {
vworld = this.createWorld(SELECTOR.getBestSelectionOrCreate(world).createSectionStorageBackend());
((IVoxyWorldSetter)world).setWorldEngine(vworld);
((IVoxyWorld)world).setWorldEngine(vworld);
} else {
if (!this.activeWorlds.contains(vworld)) {
throw new IllegalStateException("World referenced does not exist in instance");

View File

@@ -1,13 +1,13 @@
package me.cortex.voxy.client.terrain;
package me.cortex.voxy.client;
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.VoxyClientInstance;
import me.cortex.voxy.client.core.IGetVoxyRenderSystem;
import me.cortex.voxy.commonImpl.IVoxyWorld;
import me.cortex.voxy.commonImpl.VoxyCommon;
import me.cortex.voxy.commonImpl.VoxyInstance;
import me.cortex.voxy.commonImpl.importers.DHImporter;
import me.cortex.voxy.commonImpl.importers.WorldImporter;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
@@ -22,35 +22,64 @@ import java.nio.file.Path;
import java.util.concurrent.CompletableFuture;
public class WorldImportCommand {
public class VoxyCommands {
public static LiteralArgumentBuilder<FabricClientCommandSource> register() {
return ClientCommandManager.literal("voxy").requires((ctx)-> VoxyCommon.getInstance() != null)
.then(ClientCommandManager.literal("reload")
.executes(VoxyCommands::reloadInstance))
.then(ClientCommandManager.literal("import")
.then(ClientCommandManager.literal("world")
.then(ClientCommandManager.argument("world_name", StringArgumentType.string())
.suggests(WorldImportCommand::importWorldSuggester)
.executes(WorldImportCommand::importWorld)))
.suggests(VoxyCommands::importWorldSuggester)
.executes(VoxyCommands::importWorld)))
.then(ClientCommandManager.literal("bobby")
.then(ClientCommandManager.argument("world_name", StringArgumentType.string())
.suggests(WorldImportCommand::importBobbySuggester)
.executes(WorldImportCommand::importBobby)))
.suggests(VoxyCommands::importBobbySuggester)
.executes(VoxyCommands::importBobby)))
.then(ClientCommandManager.literal("raw")
.then(ClientCommandManager.argument("path", StringArgumentType.string())
.executes(WorldImportCommand::importRaw)))
.executes(VoxyCommands::importRaw)))
.then(ClientCommandManager.literal("zip")
.then(ClientCommandManager.argument("zipPath", StringArgumentType.string())
.executes(WorldImportCommand::importZip)
.executes(VoxyCommands::importZip)
.then(ClientCommandManager.argument("innerPath", StringArgumentType.string())
.executes(WorldImportCommand::importZip))))
.executes(VoxyCommands::importZip))))
.then(ClientCommandManager.literal("distant_horizons")
.then(ClientCommandManager.argument("sqlDbPath", StringArgumentType.string())
.executes(WorldImportCommand::importDistantHorizons)))
.executes(VoxyCommands::importDistantHorizons)))
.then(ClientCommandManager.literal("cancel")
.executes(WorldImportCommand::cancelImport))
.executes(VoxyCommands::cancelImport))
);
}
private static int reloadInstance(CommandContext<FabricClientCommandSource> ctx) {
var instance = (VoxyClientInstance)VoxyCommon.getInstance();
if (instance == null) {
return 1;
}
var wr = MinecraftClient.getInstance().worldRenderer;
if (wr!=null) {
((IGetVoxyRenderSystem)wr).shutdownRenderer();
}
var w = ((IVoxyWorld)MinecraftClient.getInstance().world);
if (w != null) {
if (w.getWorldEngine() != null) {
instance.stopWorld(w.getWorldEngine());
}
w.setWorldEngine(null);
}
VoxyCommon.shutdownInstance();
VoxyCommon.createInstance();
if (wr!=null) {
((IGetVoxyRenderSystem)wr).createRenderer();
}
return 0;
}
private static int importDistantHorizons(CommandContext<FabricClientCommandSource> ctx) {
var instance = (VoxyClientInstance)VoxyCommon.getInstance();
if (instance == null) {

View File

@@ -3,8 +3,7 @@ package me.cortex.voxy.client.config;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import me.cortex.voxy.client.core.IGetVoxyRenderSystem;
import me.cortex.voxy.commonImpl.IVoxyWorldGetter;
import me.cortex.voxy.commonImpl.IVoxyWorldSetter;
import me.cortex.voxy.commonImpl.IVoxyWorld;
import me.cortex.voxy.commonImpl.VoxyCommon;
import me.shedaniel.clothconfig2.api.ConfigBuilder;
import me.shedaniel.clothconfig2.api.ConfigCategory;
@@ -40,7 +39,7 @@ public class VoxyConfigScreenFactory implements ModMenuApi {
builder.setSavingRunnable(() -> {
//After saving the core should be reloaded/reset
var worldRenderer = MinecraftClient.getInstance().worldRenderer;
var world = MinecraftClient.getInstance().world;
var world = ((IVoxyWorld) MinecraftClient.getInstance().world);
if (worldRenderer != null && (ON_SAVE_RELOAD_ALL||ON_SAVE_RELOAD_RENDERER)) {
//Shudown renderer
((IGetVoxyRenderSystem) worldRenderer).shutdownRenderer();
@@ -49,11 +48,11 @@ public class VoxyConfigScreenFactory implements ModMenuApi {
if (world != null && ON_SAVE_RELOAD_ALL) {
//This is a hack inserted for the client world thing
//TODO: FIXME: MAKE BETTER
var engine = ((IVoxyWorldGetter) world).getWorldEngine();
var engine = world.getWorldEngine();
if (engine != null) {
VoxyCommon.getInstance().stopWorld(engine);
}
((IVoxyWorldSetter) world).setWorldEngine(null);
world.setWorldEngine(null);
}
//Shutdown instance
if (ON_SAVE_RELOAD_ALL) {

View File

@@ -421,7 +421,11 @@ public class RenderDataFactory45 {
//TODO: swap this out for something not getting the next entry
long A = this.sectionData[idx * 2];
long B = this.sectionData[idx * 2+1];
if (ModelQueries.isFluid(B)) {
this.blockMesher.putNext(0);
continue;
}
//Example thing thats just wrong but as example
this.blockMesher.putNext((long) (false ? 0L : 1L) |
((A & 0xFFFFL) << 26) |

View File

@@ -0,0 +1,28 @@
package me.cortex.voxy.client.mixin.minecraft;
import me.cortex.voxy.client.LoadException;
import me.cortex.voxy.client.config.VoxyConfig;
import me.cortex.voxy.commonImpl.VoxyCommon;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.network.*;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.time.Duration;
import java.util.function.Consumer;
@Mixin(ClientLoginNetworkHandler.class)
public class MixinClientLoginNetworkHandler {
@Inject(method = "<init>", at = @At(value = "TAIL"))
private void voxy$init(ClientConnection connection, MinecraftClient client, ServerInfo serverInfo, Screen parentScreen, boolean newWorld, Duration worldLoadTime, Consumer statusConsumer, CookieStorage cookieStorage, CallbackInfo ci) {
if (VoxyConfig.CONFIG.enabled) {
VoxyCommon.createInstance();
}
}
}

View File

@@ -1,23 +0,0 @@
package me.cortex.voxy.client.mixin.minecraft;
import me.cortex.voxy.client.LoadException;
import me.cortex.voxy.client.config.VoxyConfig;
import me.cortex.voxy.commonImpl.VoxyCommon;
import net.minecraft.client.network.ClientCommonNetworkHandler;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ClientPlayNetworkHandler.class)
public class MixinClientPlayNetworkHandler {
@Inject(method = "onGameJoin", at = @At(value = "NEW", target = "(Lnet/minecraft/client/network/ClientPlayNetworkHandler;Lnet/minecraft/client/world/ClientWorld$Properties;Lnet/minecraft/registry/RegistryKey;Lnet/minecraft/registry/entry/RegistryEntry;IILnet/minecraft/client/render/WorldRenderer;ZJI)Lnet/minecraft/client/world/ClientWorld;", shift = At.Shift.BEFORE))
private void voxy$init(GameJoinS2CPacket packet, CallbackInfo ci) {
if (VoxyConfig.CONFIG.enabled) {
VoxyCommon.createInstance();
}
}
}

View File

@@ -6,10 +6,8 @@ import me.cortex.voxy.client.core.IGetVoxyRenderSystem;
import me.cortex.voxy.client.core.rendering.VoxyRenderSystem;
import me.cortex.voxy.common.Logger;
import me.cortex.voxy.common.world.WorldEngine;
import me.cortex.voxy.commonImpl.IVoxyWorldGetter;
import me.cortex.voxy.commonImpl.IVoxyWorldSetter;
import me.cortex.voxy.commonImpl.IVoxyWorld;
import me.cortex.voxy.commonImpl.VoxyCommon;
import me.cortex.voxy.commonImpl.VoxyInstance;
import net.minecraft.client.render.*;
import net.minecraft.client.util.ObjectAllocator;
import net.minecraft.client.world.ClientWorld;
@@ -54,11 +52,11 @@ public abstract class MixinWorldRenderer implements IGetVoxyRenderSystem {
this.shutdownRenderer();
if (this.world != null) {
var engine = ((IVoxyWorldGetter)this.world).getWorldEngine();
var engine = ((IVoxyWorld)this.world).getWorldEngine();
if (engine != null) {
VoxyCommon.getInstance().stopWorld(engine);
}
((IVoxyWorldSetter)this.world).setWorldEngine(null);
((IVoxyWorld)this.world).setWorldEngine(null);
}
}
}

View File

@@ -202,6 +202,11 @@ public class WorldEngine {
public void free() {
//Cannot free while there are loaded sections
if (this.sectionTracker.getLoadedCacheCount() != 0) {
throw new IllegalStateException();
}
this.thisTracker.free();
this.isLive = false;
try {this.mapper.close();} catch (Exception e) {Logger.error(e);}

View File

@@ -1,6 +1,5 @@
package me.cortex.voxy.common.world.service;
import it.unimi.dsi.fastutil.Pair;
import me.cortex.voxy.common.Logger;
import me.cortex.voxy.common.voxelization.ILightingSupplier;
import me.cortex.voxy.common.voxelization.VoxelizedSection;
@@ -8,15 +7,13 @@ import me.cortex.voxy.common.voxelization.WorldConversionFactory;
import me.cortex.voxy.common.world.WorldEngine;
import me.cortex.voxy.common.thread.ServiceSlice;
import me.cortex.voxy.common.thread.ServiceThreadPool;
import me.cortex.voxy.commonImpl.IVoxyWorldGetter;
import me.cortex.voxy.commonImpl.IVoxyWorld;
import net.minecraft.util.math.ChunkSectionPos;
import net.minecraft.world.LightType;
import net.minecraft.world.chunk.ChunkNibbleArray;
import net.minecraft.world.chunk.ChunkSection;
import net.minecraft.world.chunk.WorldChunk;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
public class VoxelIngestService {
@@ -80,7 +77,7 @@ public class VoxelIngestService {
}
public void enqueueIngest(WorldChunk chunk, boolean ignoreOnNullWorld) {
var engine = ((IVoxyWorldGetter)chunk.getWorld()).getWorldEngine();
var engine = ((IVoxyWorld)chunk.getWorld()).getWorldEngine();
if (engine == null) {
if (!ignoreOnNullWorld) {
Logger.error("Could not ingest chunk as does not have world engine");

View File

@@ -2,6 +2,7 @@ package me.cortex.voxy.commonImpl;
import me.cortex.voxy.common.world.WorldEngine;
public interface IVoxyWorldSetter {
public interface IVoxyWorld {
WorldEngine getWorldEngine();
void setWorldEngine(WorldEngine engine);
}

View File

@@ -1,7 +0,0 @@
package me.cortex.voxy.commonImpl;
import me.cortex.voxy.common.world.WorldEngine;
public interface IVoxyWorldGetter {
WorldEngine getWorldEngine();
}

View File

@@ -30,7 +30,7 @@ public class VoxyCommon implements ModInitializer {
}
//This is hardcoded like this because people do not understand what they are doing
private static final boolean GlobalVerificationDisableOverride = false;//System.getProperty("voxy.verificationDisableOverride", "false").equals("true");
private static final boolean GlobalVerificationDisableOverride = true;//System.getProperty("voxy.verificationDisableOverride", "false").equals("true");
public static boolean isVerificationFlagOn(String name) {
return (!GlobalVerificationDisableOverride) && System.getProperty("voxy."+name, "true").equals("true");
}

View File

@@ -128,6 +128,18 @@ public class VoxyInstance {
this.importManager.cancelImport(world);
if (world.getActiveSectionCount() != 0) {
Logger.warn("Waiting for world to finish use");
while (world.getActiveSectionCount() != 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
//TODO: maybe replace the flush with an atomic "in queue" counter that is per world
this.flush();
world.free();

View File

@@ -1,23 +1,16 @@
package me.cortex.voxy.commonImpl.mixin.minecraft;
import me.cortex.voxy.common.Logger;
import me.cortex.voxy.common.world.WorldEngine;
import me.cortex.voxy.commonImpl.IVoxyWorldGetter;
import me.cortex.voxy.commonImpl.IVoxyWorldSetter;
import me.cortex.voxy.commonImpl.VoxyCommon;
import me.cortex.voxy.commonImpl.IVoxyWorld;
import net.minecraft.world.World;
import net.minecraft.world.block.NeighborUpdater;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(World.class)
public class MixinWorld implements IVoxyWorldGetter, IVoxyWorldSetter {
@Shadow @Final protected NeighborUpdater neighborUpdater;
public class MixinWorld implements IVoxyWorld {
@Unique private WorldEngine voxyWorld;
@Override

View File

@@ -54,8 +54,8 @@ void setupScreenspace(in UnpackedNode node) {
//NOTE!: cant this be precomputed and put in an array?? in the scene uniform??
vec4 pPoint = (VP*vec4(vec3((i&1)!=0,(i&2)!=0,(i&4)!=0)*(32<<node.lodLevel),1));//Size of section is 32x32x32 (need to change it to a bounding box in the future)
pPoint += base;
zThing = max(pPoint.z, zThing);
vec3 point = pPoint.xyz/pPoint.w;
zThing = max(point.z, zThing);
//TODO: CLIP TO VIEWPORT
minBB = min(minBB, point);
maxBB = max(maxBB, point);
@@ -80,7 +80,7 @@ void setupScreenspace(in UnpackedNode node) {
//Checks if the node is implicitly culled (outside frustum)
bool outsideFrustum() {
return any(lessThanEqual(maxBB, vec3(0.0f))) || any(lessThanEqual(vec3(1.0f), minBB)) || zThing < 0;
return any(lessThanEqual(maxBB, vec3(0.0f))) || any(lessThanEqual(vec3(1.0f), minBB)) || zThing < 0;//
//|| any(lessThanEqual(minBB, vec3(0.0f, 0.0f, 0.0f))) || any(lessThanEqual(vec3(1.0f, 1.0f, 1.0f), maxBB));
}

View File

@@ -4,7 +4,7 @@
"compatibilityLevel": "JAVA_17",
"client": [
"minecraft.MixinClientCommonNetworkHandler",
"minecraft.MixinClientPlayNetworkHandler",
"minecraft.MixinClientLoginNetworkHandler",
"minecraft.MixinDebugHud",
"minecraft.MixinMinecraftClient",
"minecraft.MixinThreadExecutor",