More work
This commit is contained in:
@@ -3,6 +3,7 @@ package me.cortex.voxy.client;
|
|||||||
import me.cortex.voxy.client.core.VoxelCore;
|
import me.cortex.voxy.client.core.VoxelCore;
|
||||||
import me.cortex.voxy.client.saver.ContextSelectionSystem;
|
import me.cortex.voxy.client.saver.ContextSelectionSystem;
|
||||||
import me.cortex.voxy.client.terrain.WorldImportCommand;
|
import me.cortex.voxy.client.terrain.WorldImportCommand;
|
||||||
|
import me.cortex.voxy.commonImpl.VoxyCommon;
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
|
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientWorldEvents;
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientWorldEvents;
|
||||||
@@ -14,5 +15,6 @@ public class VoxyClient implements ClientModInitializer {
|
|||||||
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {
|
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {
|
||||||
dispatcher.register(WorldImportCommand.register());
|
dispatcher.register(WorldImportCommand.register());
|
||||||
});
|
});
|
||||||
|
VoxyCommon.setInstanceFactory(VoxyClientInstance::new);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
37
src/main/java/me/cortex/voxy/client/VoxyClientInstance.java
Normal file
37
src/main/java/me/cortex/voxy/client/VoxyClientInstance.java
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package me.cortex.voxy.client;
|
||||||
|
|
||||||
|
import me.cortex.voxy.client.core.WorldImportWrapper;
|
||||||
|
import me.cortex.voxy.client.saver.ContextSelectionSystem;
|
||||||
|
import me.cortex.voxy.common.world.WorldEngine;
|
||||||
|
import me.cortex.voxy.commonImpl.IVoxyWorldGetter;
|
||||||
|
import me.cortex.voxy.commonImpl.IVoxyWorldSetter;
|
||||||
|
import me.cortex.voxy.commonImpl.VoxyInstance;
|
||||||
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
|
||||||
|
public class VoxyClientInstance extends VoxyInstance {
|
||||||
|
private static final ContextSelectionSystem SELECTOR = new ContextSelectionSystem();
|
||||||
|
public WorldImportWrapper importWrapper;
|
||||||
|
|
||||||
|
public VoxyClientInstance() {
|
||||||
|
super(12);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopWorld(WorldEngine world) {
|
||||||
|
if (this.importWrapper != null) {
|
||||||
|
this.importWrapper.stopImporter();
|
||||||
|
this.importWrapper = null;
|
||||||
|
}
|
||||||
|
super.stopWorld(world);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorldEngine getOrMakeRenderWorld(ClientWorld world) {
|
||||||
|
var vworld = ((IVoxyWorldGetter)world).getWorldEngine();
|
||||||
|
if (vworld == null) {
|
||||||
|
vworld = this.createWorld(SELECTOR.getBestSelectionOrCreate(world).createSectionStorageBackend());
|
||||||
|
((IVoxyWorldSetter)world).setWorldEngine(vworld);
|
||||||
|
this.importWrapper = new WorldImportWrapper(this.threadPool, vworld);
|
||||||
|
}
|
||||||
|
return vworld;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package me.cortex.voxy.client.mixin.joml;
|
|
||||||
|
|
||||||
import org.joml.FrustumIntersection;
|
|
||||||
import org.joml.Vector4f;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
|
||||||
|
|
||||||
@Mixin(value = FrustumIntersection.class, remap = false)
|
|
||||||
public interface AccessFrustumIntersection {
|
|
||||||
@Accessor Vector4f[] getPlanes();
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,10 +23,11 @@ public class MixinMinecraftClient {
|
|||||||
VoxyCommon.shutdownInstance();
|
VoxyCommon.shutdownInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
@Inject(method = "joinWorld", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;setWorld(Lnet/minecraft/client/world/ClientWorld;)V", shift = At.Shift.BEFORE))
|
@Inject(method = "joinWorld", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;setWorld(Lnet/minecraft/client/world/ClientWorld;)V", shift = At.Shift.BEFORE))
|
||||||
private void voxy$injectInitialization(ClientWorld world, DownloadingTerrainScreen.WorldEntryReason worldEntryReason, CallbackInfo ci) {
|
private void voxy$injectInitialization(ClientWorld world, DownloadingTerrainScreen.WorldEntryReason worldEntryReason, CallbackInfo ci) {
|
||||||
if (VoxyConfig.CONFIG.enabled) {
|
if (VoxyConfig.CONFIG.enabled) {
|
||||||
VoxyCommon.createInstance();
|
VoxyCommon.createInstance();
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package me.cortex.voxy.client.mixin.minecraft;
|
package me.cortex.voxy.client.mixin.minecraft;
|
||||||
|
|
||||||
import me.cortex.voxy.client.VoxyClient;
|
import me.cortex.voxy.client.VoxyClientInstance;
|
||||||
import me.cortex.voxy.client.config.VoxyConfig;
|
import me.cortex.voxy.client.config.VoxyConfig;
|
||||||
import me.cortex.voxy.client.core.IGetVoxyRenderSystem;
|
import me.cortex.voxy.client.core.IGetVoxyRenderSystem;
|
||||||
import me.cortex.voxy.client.core.rendering.VoxyRenderSystem;
|
import me.cortex.voxy.client.core.rendering.VoxyRenderSystem;
|
||||||
import me.cortex.voxy.common.Logger;
|
import me.cortex.voxy.common.Logger;
|
||||||
import me.cortex.voxy.common.world.WorldEngine;
|
import me.cortex.voxy.common.world.WorldEngine;
|
||||||
|
import me.cortex.voxy.commonImpl.IVoxyWorldGetter;
|
||||||
import me.cortex.voxy.commonImpl.VoxyCommon;
|
import me.cortex.voxy.commonImpl.VoxyCommon;
|
||||||
import me.cortex.voxy.commonImpl.VoxyInstance;
|
import me.cortex.voxy.commonImpl.VoxyInstance;
|
||||||
import net.minecraft.client.render.*;
|
import net.minecraft.client.render.*;
|
||||||
@@ -46,11 +47,25 @@ public abstract class MixinWorldRenderer implements IGetVoxyRenderSystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "setWorld", at = @At("TAIL"))
|
@Unique private ClientWorld refCopy;
|
||||||
|
|
||||||
|
@Inject(method = "setWorld", at = @At("HEAD"))
|
||||||
private void initVoxelCore(ClientWorld world, CallbackInfo ci) {
|
private void initVoxelCore(ClientWorld world, CallbackInfo ci) {
|
||||||
|
this.refCopy = this.world;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "setWorld", at = @At("TAIL"))
|
||||||
|
private void voxy$setWorld(ClientWorld world, CallbackInfo ci) {
|
||||||
if (world == null) {
|
if (world == null) {
|
||||||
this.shutdownRenderer();
|
this.shutdownRenderer();
|
||||||
}
|
}
|
||||||
|
//Release the client world
|
||||||
|
if (this.refCopy != null) {
|
||||||
|
var engine = ((IVoxyWorldGetter)this.refCopy).getWorldEngine();
|
||||||
|
if (engine != null) {
|
||||||
|
VoxyCommon.getInstance().stopWorld(engine);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "close", at = @At("HEAD"))
|
@Inject(method = "close", at = @At("HEAD"))
|
||||||
@@ -73,12 +88,12 @@ public abstract class MixinWorldRenderer implements IGetVoxyRenderSystem {
|
|||||||
Logger.info("Not creating renderer due to disabled");
|
Logger.info("Not creating renderer due to disabled");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var instance = VoxyCommon.getInstance();
|
var instance = (VoxyClientInstance)VoxyCommon.getInstance();
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
Logger.error("Not creating renderer due to null instance");
|
Logger.error("Not creating renderer due to null instance");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
WorldEngine world = instance.getOrMakeWorld(this.world);
|
WorldEngine world = instance.getOrMakeRenderWorld(this.world);
|
||||||
if (world == null) {
|
if (world == null) {
|
||||||
Logger.error("Null world selected");
|
Logger.error("Null world selected");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
|||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
import com.mojang.brigadier.suggestion.Suggestions;
|
import com.mojang.brigadier.suggestion.Suggestions;
|
||||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||||
|
import me.cortex.voxy.client.VoxyClientInstance;
|
||||||
import me.cortex.voxy.commonImpl.VoxyCommon;
|
import me.cortex.voxy.commonImpl.VoxyCommon;
|
||||||
import me.cortex.voxy.commonImpl.VoxyInstance;
|
import me.cortex.voxy.commonImpl.VoxyInstance;
|
||||||
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
|
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
|
||||||
@@ -47,7 +48,7 @@ public class WorldImportCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean fileBasedImporter(File directory) {
|
private static boolean fileBasedImporter(File directory) {
|
||||||
var instance = VoxyCommon.getInstance();
|
var instance = (VoxyClientInstance)VoxyCommon.getInstance();
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -133,7 +134,7 @@ public class WorldImportCommand {
|
|||||||
innerDir = ctx.getArgument("innerPath", String.class);
|
innerDir = ctx.getArgument("innerPath", String.class);
|
||||||
} catch (Exception e) {}
|
} catch (Exception e) {}
|
||||||
|
|
||||||
var instance = VoxyCommon.getInstance();
|
var instance = (VoxyClientInstance)VoxyCommon.getInstance();
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -143,7 +144,7 @@ public class WorldImportCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static int cancelImport(CommandContext<FabricClientCommandSource> fabricClientCommandSourceCommandContext) {
|
private static int cancelImport(CommandContext<FabricClientCommandSource> fabricClientCommandSourceCommandContext) {
|
||||||
var instance = VoxyCommon.getInstance();
|
var instance = (VoxyClientInstance)VoxyCommon.getInstance();
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,4 +164,8 @@ public class ServiceSlice extends TrackedObject {
|
|||||||
this.threadPool.steal(this);
|
this.threadPool.steal(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAlive() {
|
||||||
|
return this.alive;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class VoxyCommon implements ModInitializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//This is hardcoded like this because people do not understand what they are doing
|
//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) {
|
public static boolean isVerificationFlagOn(String name) {
|
||||||
return (!GlobalVerificationDisableOverride) && System.getProperty("voxy."+name, "true").equals("true");
|
return (!GlobalVerificationDisableOverride) && System.getProperty("voxy."+name, "true").equals("true");
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,14 @@ public class VoxyCommon implements ModInitializer {
|
|||||||
|
|
||||||
public interface IInstanceFactory {VoxyInstance create();}
|
public interface IInstanceFactory {VoxyInstance create();}
|
||||||
private static VoxyInstance INSTANCE;
|
private static VoxyInstance INSTANCE;
|
||||||
private static IInstanceFactory FACTORY;
|
private static IInstanceFactory FACTORY = null;
|
||||||
|
|
||||||
|
public static void setInstanceFactory(IInstanceFactory factory) {
|
||||||
|
if (FACTORY != null) {
|
||||||
|
throw new IllegalStateException("Cannot set instance factory more than once");
|
||||||
|
}
|
||||||
|
FACTORY = factory;
|
||||||
|
}
|
||||||
|
|
||||||
public static VoxyInstance getInstance() {
|
public static VoxyInstance getInstance() {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public class VoxyInstance {
|
|||||||
protected final Set<WorldEngine> activeWorlds = new HashSet<>();
|
protected final Set<WorldEngine> activeWorlds = new HashSet<>();
|
||||||
|
|
||||||
public VoxyInstance(int threadCount) {
|
public VoxyInstance(int threadCount) {
|
||||||
|
Logger.info("Initializing voxy instance");
|
||||||
this.threadPool = new ServiceThreadPool(threadCount);
|
this.threadPool = new ServiceThreadPool(threadCount);
|
||||||
this.savingService = new SectionSavingService(this.threadPool);
|
this.savingService = new SectionSavingService(this.threadPool);
|
||||||
this.ingestService = new VoxelIngestService(this.threadPool);
|
this.ingestService = new VoxelIngestService(this.threadPool);
|
||||||
@@ -36,9 +37,22 @@ public class VoxyInstance {
|
|||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
Logger.info("Shutdown voxy instance");
|
Logger.info("Shutdown voxy instance");
|
||||||
|
|
||||||
try {this.ingestService.shutdown();} catch (Exception e) {Logger.error(e);}
|
try {this.ingestService.shutdown();} catch (Exception e) {Logger.error(e);}
|
||||||
try {this.savingService.shutdown();} catch (Exception e) {Logger.error(e);}
|
try {this.savingService.shutdown();} catch (Exception e) {Logger.error(e);}
|
||||||
|
|
||||||
|
if (!this.activeWorlds.isEmpty()) {
|
||||||
|
Logger.error("Not all worlds shutdown, force closing " + this.activeWorlds.size() + " worlds");
|
||||||
|
for (var world : new HashSet<>(this.activeWorlds)) {//Create a clone
|
||||||
|
this.stopWorld(world);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {this.threadPool.shutdown();} catch (Exception e) {Logger.error(e);}
|
try {this.threadPool.shutdown();} catch (Exception e) {Logger.error(e);}
|
||||||
|
|
||||||
|
if (!this.activeWorlds.isEmpty()) {
|
||||||
|
throw new IllegalStateException("Not all worlds shutdown");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServiceThreadPool getThreadPool() {
|
public ServiceThreadPool getThreadPool() {
|
||||||
@@ -94,29 +108,9 @@ public class VoxyInstance {
|
|||||||
throw new IllegalStateException("World cannot be in world set and not alive");
|
throw new IllegalStateException("World cannot be in world set and not alive");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (this.importWrapper != null) {
|
|
||||||
this.importWrapper.stopImporter();
|
|
||||||
this.importWrapper = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.flush();
|
this.flush();
|
||||||
|
|
||||||
|
|
||||||
world.free();
|
world.free();
|
||||||
this.activeWorlds.remove(world);
|
this.activeWorlds.remove(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final ContextSelectionSystem SELECTOR = new ContextSelectionSystem();
|
|
||||||
public WorldImportWrapper importWrapper;
|
|
||||||
public WorldEngine getOrMakeWorld(ClientWorld world) {
|
|
||||||
var vworld = ((IVoxyWorldGetter)world).getWorldEngine();
|
|
||||||
if (vworld == null) {
|
|
||||||
vworld = this.createWorld(SELECTOR.getBestSelectionOrCreate(world).createSectionStorageBackend());
|
|
||||||
((IVoxyWorldSetter)world).setWorldEngine(vworld);
|
|
||||||
this.importWrapper = new WorldImportWrapper(this.threadPool, vworld);
|
|
||||||
}
|
|
||||||
return vworld;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -16,17 +16,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
public class MixinWorld implements IVoxyWorldGetter, IVoxyWorldSetter {
|
public class MixinWorld implements IVoxyWorldGetter, IVoxyWorldSetter {
|
||||||
@Unique private WorldEngine voxyWorld;
|
@Unique private WorldEngine voxyWorld;
|
||||||
|
|
||||||
@Inject(method = "close", at = @At("HEAD"))
|
|
||||||
private void closeVoxyWorld(CallbackInfo ci) {
|
|
||||||
if (this.voxyWorld != null) {
|
|
||||||
//TODO: FIXME: DONT DO THIS, this is a hack to ensure everything is saved
|
|
||||||
var instance = VoxyCommon.getInstance();
|
|
||||||
try {instance.stopWorld(this.voxyWorld); this.voxyWorld = null;} catch (Exception e) {
|
|
||||||
Logger.error("Failed to shutdown voxy world engine.", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WorldEngine getWorldEngine() {
|
public WorldEngine getWorldEngine() {
|
||||||
return this.voxyWorld;
|
return this.voxyWorld;
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
"package": "me.cortex.voxy.client.mixin",
|
"package": "me.cortex.voxy.client.mixin",
|
||||||
"compatibilityLevel": "JAVA_17",
|
"compatibilityLevel": "JAVA_17",
|
||||||
"client": [
|
"client": [
|
||||||
"joml.AccessFrustumIntersection",
|
|
||||||
"minecraft.MixinClientCommonNetworkHandler",
|
"minecraft.MixinClientCommonNetworkHandler",
|
||||||
|
"minecraft.MixinClientPlayNetworkHandler",
|
||||||
"minecraft.MixinDebugHud",
|
"minecraft.MixinDebugHud",
|
||||||
"minecraft.MixinMinecraftClient",
|
"minecraft.MixinMinecraftClient",
|
||||||
"minecraft.MixinThreadExecutor",
|
"minecraft.MixinThreadExecutor",
|
||||||
|
|||||||
Reference in New Issue
Block a user