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.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;
|
||||
@@ -14,5 +15,6 @@ public class VoxyClient implements ClientModInitializer {
|
||||
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {
|
||||
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();
|
||||
}
|
||||
|
||||
/*
|
||||
@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) {
|
||||
if (VoxyConfig.CONFIG.enabled) {
|
||||
VoxyCommon.createInstance();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
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.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.VoxyCommon;
|
||||
import me.cortex.voxy.commonImpl.VoxyInstance;
|
||||
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) {
|
||||
this.refCopy = this.world;
|
||||
}
|
||||
|
||||
@Inject(method = "setWorld", at = @At("TAIL"))
|
||||
private void voxy$setWorld(ClientWorld world, CallbackInfo ci) {
|
||||
if (world == null) {
|
||||
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"))
|
||||
@@ -73,12 +88,12 @@ public abstract class MixinWorldRenderer implements IGetVoxyRenderSystem {
|
||||
Logger.info("Not creating renderer due to disabled");
|
||||
return;
|
||||
}
|
||||
var instance = VoxyCommon.getInstance();
|
||||
var instance = (VoxyClientInstance)VoxyCommon.getInstance();
|
||||
if (instance == null) {
|
||||
Logger.error("Not creating renderer due to null instance");
|
||||
return;
|
||||
}
|
||||
WorldEngine world = instance.getOrMakeWorld(this.world);
|
||||
WorldEngine world = instance.getOrMakeRenderWorld(this.world);
|
||||
if (world == null) {
|
||||
Logger.error("Null world selected");
|
||||
return;
|
||||
|
||||
@@ -5,6 +5,7 @@ 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.commonImpl.VoxyCommon;
|
||||
import me.cortex.voxy.commonImpl.VoxyInstance;
|
||||
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
|
||||
@@ -47,7 +48,7 @@ public class WorldImportCommand {
|
||||
}
|
||||
|
||||
private static boolean fileBasedImporter(File directory) {
|
||||
var instance = VoxyCommon.getInstance();
|
||||
var instance = (VoxyClientInstance)VoxyCommon.getInstance();
|
||||
if (instance == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -133,7 +134,7 @@ public class WorldImportCommand {
|
||||
innerDir = ctx.getArgument("innerPath", String.class);
|
||||
} catch (Exception e) {}
|
||||
|
||||
var instance = VoxyCommon.getInstance();
|
||||
var instance = (VoxyClientInstance)VoxyCommon.getInstance();
|
||||
if (instance == null) {
|
||||
return 1;
|
||||
}
|
||||
@@ -143,7 +144,7 @@ public class WorldImportCommand {
|
||||
}
|
||||
|
||||
private static int cancelImport(CommandContext<FabricClientCommandSource> fabricClientCommandSourceCommandContext) {
|
||||
var instance = VoxyCommon.getInstance();
|
||||
var instance = (VoxyClientInstance)VoxyCommon.getInstance();
|
||||
if (instance == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -164,4 +164,8 @@ public class ServiceSlice extends TrackedObject {
|
||||
this.threadPool.steal(this);
|
||||
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
|
||||
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");
|
||||
}
|
||||
@@ -41,7 +41,14 @@ public class VoxyCommon implements ModInitializer {
|
||||
|
||||
public interface IInstanceFactory {VoxyInstance create();}
|
||||
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() {
|
||||
return INSTANCE;
|
||||
|
||||
@@ -23,6 +23,7 @@ public class VoxyInstance {
|
||||
protected final Set<WorldEngine> activeWorlds = new HashSet<>();
|
||||
|
||||
public VoxyInstance(int threadCount) {
|
||||
Logger.info("Initializing voxy instance");
|
||||
this.threadPool = new ServiceThreadPool(threadCount);
|
||||
this.savingService = new SectionSavingService(this.threadPool);
|
||||
this.ingestService = new VoxelIngestService(this.threadPool);
|
||||
@@ -36,9 +37,22 @@ public class VoxyInstance {
|
||||
|
||||
public void shutdown() {
|
||||
Logger.info("Shutdown voxy instance");
|
||||
|
||||
try {this.ingestService.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);}
|
||||
|
||||
if (!this.activeWorlds.isEmpty()) {
|
||||
throw new IllegalStateException("Not all worlds shutdown");
|
||||
}
|
||||
}
|
||||
|
||||
public ServiceThreadPool getThreadPool() {
|
||||
@@ -94,29 +108,9 @@ public class VoxyInstance {
|
||||
throw new IllegalStateException("World cannot be in world set and not alive");
|
||||
}
|
||||
|
||||
|
||||
if (this.importWrapper != null) {
|
||||
this.importWrapper.stopImporter();
|
||||
this.importWrapper = null;
|
||||
}
|
||||
|
||||
this.flush();
|
||||
|
||||
|
||||
world.free();
|
||||
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 {
|
||||
@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
|
||||
public WorldEngine getWorldEngine() {
|
||||
return this.voxyWorld;
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
"package": "me.cortex.voxy.client.mixin",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"client": [
|
||||
"joml.AccessFrustumIntersection",
|
||||
"minecraft.MixinClientCommonNetworkHandler",
|
||||
"minecraft.MixinClientPlayNetworkHandler",
|
||||
"minecraft.MixinDebugHud",
|
||||
"minecraft.MixinMinecraftClient",
|
||||
"minecraft.MixinThreadExecutor",
|
||||
|
||||
Reference in New Issue
Block a user