Made it reloadable, added import command, fixed race conditions and many other things

This commit is contained in:
mcrcortex
2024-01-14 10:14:01 +10:00
parent cf44c2e5b1
commit 10a0db8e04
14 changed files with 150 additions and 99 deletions

View File

@@ -0,0 +1,7 @@
package me.cortex.voxelmon;
import me.cortex.voxelmon.core.VoxelCore;
public interface IGetVoxelCore {
VoxelCore getVoxelCore();
}

View File

@@ -2,13 +2,17 @@ package me.cortex.voxelmon;
import me.cortex.voxelmon.terrain.TestSparseGenCommand; import me.cortex.voxelmon.terrain.TestSparseGenCommand;
//import me.cortex.voxelmon.terrain.WorldImportCommand; //import me.cortex.voxelmon.terrain.WorldImportCommand;
import me.cortex.voxelmon.terrain.WorldImportCommand;
import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
public class Voxelmon implements ClientModInitializer { public class Voxelmon implements ClientModInitializer {
@Override @Override
public void onInitializeClient() { public void onInitializeClient() {
//CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> WorldImportCommand.register(dispatcher)); ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {
dispatcher.register(WorldImportCommand.register());
});
} }
} }

View File

@@ -29,7 +29,7 @@ public class DistanceTracker {
this.tracker = tracker; this.tracker = tracker;
this.scale = scale; this.scale = scale;
this.rings[0] = new TransitionRing2D(5, (int) Math.ceil(MinecraftClient.getInstance().gameRenderer.getViewDistance()/16)/2, (x, z)->{ this.rings[0] = new TransitionRing2D(5, (int) MinecraftClient.getInstance().options.getClampedViewDistance()/2, (x, z)->{
if (false) { if (false) {
return; return;
} }

View File

@@ -48,7 +48,7 @@ import static org.lwjgl.opengl.ARBFramebufferObject.glBindFramebuffer;
//Ingest -> world engine -> raw render data -> render data //Ingest -> world engine -> raw render data -> render data
public class VoxelCore { public class VoxelCore {
private static final Set<Block> biomeTintableAllFaces = new HashSet<>(List.of(Blocks.OAK_LEAVES, Blocks.JUNGLE_LEAVES, Blocks.ACACIA_LEAVES, Blocks.DARK_OAK_LEAVES, Blocks.VINE, Blocks.MANGROVE_LEAVES, private static final Set<Block> biomeTintableAllFaces = new HashSet<>(List.of(Blocks.OAK_LEAVES, Blocks.JUNGLE_LEAVES, Blocks.ACACIA_LEAVES, Blocks.DARK_OAK_LEAVES, Blocks.VINE, Blocks.MANGROVE_LEAVES,
Blocks.TALL_GRASS, Blocks.LARGE_FERN, Blocks.TALL_GRASS, Blocks.LARGE_FERN, Blocks.SHORT_GRASS,
Blocks.SPRUCE_LEAVES, Blocks.SPRUCE_LEAVES,
Blocks.BIRCH_LEAVES, Blocks.BIRCH_LEAVES,
@@ -58,9 +58,6 @@ public class VoxelCore {
private static final Set<Block> waterTint = new HashSet<>(List.of(Blocks.WATER)); private static final Set<Block> waterTint = new HashSet<>(List.of(Blocks.WATER));
public static VoxelCore INSTANCE = new VoxelCore();
private final WorldEngine world; private final WorldEngine world;
private final DistanceTracker distanceTracker; private final DistanceTracker distanceTracker;
private final RenderGenerationService renderGen; private final RenderGenerationService renderGen;
@@ -69,6 +66,8 @@ public class VoxelCore {
private final AbstractFarWorldRenderer renderer; private final AbstractFarWorldRenderer renderer;
private final PostProcessing postProcessing; private final PostProcessing postProcessing;
//private final Thread shutdownThread = new Thread(this::shutdown);
public VoxelCore() { public VoxelCore() {
//Trigger the shared index buffer loading //Trigger the shared index buffer loading
SharedIndexBuffer.INSTANCE.id(); SharedIndexBuffer.INSTANCE.id();
@@ -81,33 +80,13 @@ public class VoxelCore {
this.renderTracker.setRenderGen(this.renderGen); this.renderTracker.setRenderGen(this.renderGen);
//To get to chunk scale multiply the scale by 2, the scale is after how many chunks does the lods halve //To get to chunk scale multiply the scale by 2, the scale is after how many chunks does the lods halve
this.distanceTracker = new DistanceTracker(this.renderTracker, 5, 16); this.distanceTracker = new DistanceTracker(this.renderTracker, 5, 16);//20
this.postProcessing = new PostProcessing(); this.postProcessing = new PostProcessing();
this.world.getMapper().setCallbacks(this::stateUpdate, this::biomeUpdate); this.world.getMapper().setCallbacks(this::stateUpdate, this::biomeUpdate);
Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown)); //Runtime.getRuntime().addShutdownHook(this.shutdownThread);
/*
Random r = new Random();
for (int ring = 0; ring < 5; ring++) {
for (int x = -32; x < 32; x++) {
for (int z = -32; z < 32; z++) {
if ((-16 < x && x < 16) && (-16 < z && z < 16)) {
continue;
}
var b = new MemoryBuffer(1000 * 8);
for (long j = 0; j < b.size; j += 8) {
MemoryUtil.memPutLong(b.address + j, r.nextLong());
}
this.renderer.enqueueResult(new BuiltSectionGeometry(WorldEngine.getWorldSectionId(ring, x, 2>>ring, z), b, null));
}
}
}*/
//WorldImporter importer = new WorldImporter(this.world, MinecraftClient.getInstance().world); //WorldImporter importer = new WorldImporter(this.world, MinecraftClient.getInstance().world);
@@ -200,15 +179,21 @@ public class VoxelCore {
// since they are AABBS crossing the normal is impossible without one of the axis being equal // since they are AABBS crossing the normal is impossible without one of the axis being equal
public void shutdown() { public void shutdown() {
try {this.world.shutdown();} catch (Exception e) {System.err.println(e);} //if (Thread.currentThread() != this.shutdownThread) {
// Runtime.getRuntime().removeShutdownHook(this.shutdownThread);
//}
//this.world.getMapper().forceResaveStates();
System.out.println("Shutting down voxel core");
try {this.renderGen.shutdown();} catch (Exception e) {System.err.println(e);} try {this.renderGen.shutdown();} catch (Exception e) {System.err.println(e);}
try {this.world.shutdown();} catch (Exception e) {System.err.println(e);}
try {this.renderer.shutdown();} catch (Exception e) {System.err.println(e);} try {this.renderer.shutdown();} catch (Exception e) {System.err.println(e);}
try {this.postProcessing.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) { public WorldImporter createWorldImporter(World mcWorld, File worldPath) {
var importer = new WorldImporter(this.world, mcWorld); var importer = new WorldImporter(this.world, mcWorld);
importer.importWorldAsyncStart(worldPath, 10, null, ()->{ importer.importWorldAsyncStart(worldPath, 5, null, ()->{
System.err.println("DONE IMPORT"); System.err.println("DONE IMPORT");
}); });
return importer; return importer;

View File

@@ -32,47 +32,6 @@ public class RenderTracker {
public RenderTracker(WorldEngine world, AbstractFarWorldRenderer renderer) { public RenderTracker(WorldEngine world, AbstractFarWorldRenderer renderer) {
this.world = world; this.world = world;
this.renderer = renderer; this.renderer = renderer;
var loader = new Thread(()->{
try {
Thread.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
int OX = 0;//-27;
int OZ = 0;//276;
int DROP = 48;
//Do ring rendering
for (int i = 0; i < 5; i++) {
for (int x = -DROP; x <= DROP; x++) {
for (int z = -DROP; z <= DROP; z++) {
int d = x*x+z*z;
if (d<(DROP/2-1)*(DROP/2) || d>DROP*DROP)
continue;
for (int y = -3>>i; y < Math.max(1, 10 >> i); y++) {
var sec = this.world.acquire(i, x + (OX>>(1+i)), y, z + (OZ>>(1+i)));
//this.renderGen.enqueueTask(sec);
sec.release();
}
try {
while (this.renderGen.getTaskCount() > 1000) {
Thread.sleep(50);
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
});
loader.setDaemon(true);
//loader.start();
} }
//Adds a lvl 0 section into the world renderer //Adds a lvl 0 section into the world renderer

View File

@@ -38,7 +38,8 @@ public abstract class TrackedObject {
boolean[] freed = new boolean[1]; boolean[] freed = new boolean[1];
var clean = cleaner.register(obj, ()->{ var clean = cleaner.register(obj, ()->{
if (!freed[0]) { if (!freed[0]) {
System.err.println("Object named: "+ clazz+" was not freed, location at:\n" + trace); System.err.println("Object named: "+ clazz+" was not freed, location at:\n");
trace.printStackTrace();
System.err.flush(); System.err.flush();
} }
}); });

View File

@@ -131,6 +131,10 @@ public class ColourResolver {
public static long resolveBiomeColour(String biomeId) { public static long resolveBiomeColour(String biomeId) {
var biome = MinecraftClient.getInstance().world.getRegistryManager().get(RegistryKeys.BIOME).get(new Identifier(biomeId)); var biome = MinecraftClient.getInstance().world.getRegistryManager().get(RegistryKeys.BIOME).get(new Identifier(biomeId));
if (biome == null) {
System.err.println("Biome: " + biomeId + " doesnt exist in registry!");
return 0;
}
int ARGBFoliage = biome.getFoliageColor(); int ARGBFoliage = biome.getFoliageColor();
int ARGBWater = biome.getWaterColor(); int ARGBWater = biome.getWaterColor();
return Integer.toUnsignedLong(((ARGBFoliage&0xFFFFFF)<<8)|(ARGBFoliage>>>24)) | (Integer.toUnsignedLong(((ARGBWater&0xFFFFFF)<<8)|(ARGBWater>>>24))<<32); return Integer.toUnsignedLong(((ARGBFoliage&0xFFFFFF)<<8)|(ARGBFoliage>>>24)) | (Integer.toUnsignedLong(((ARGBWater&0xFFFFFF)<<8)|(ARGBWater>>>24))<<32);

View File

@@ -79,6 +79,7 @@ public class Mapper {
List<BiomeEntry> bentries = new ArrayList<>(); List<BiomeEntry> bentries = new ArrayList<>();
List<Pair<byte[], Integer>> sentryErrors = new ArrayList<>(); List<Pair<byte[], Integer>> sentryErrors = new ArrayList<>();
for (var entry : mappings.int2ObjectEntrySet()) { for (var entry : mappings.int2ObjectEntrySet()) {
int entryType = entry.getIntKey()>>>30; int entryType = entry.getIntKey()>>>30;
int id = entry.getIntKey() & ((1<<30)-1); int id = entry.getIntKey() & ((1<<30)-1);
@@ -126,6 +127,7 @@ public class Mapper {
} }
this.blockId2stateEntry.add(entry); this.blockId2stateEntry.add(entry);
}); });
bentries.stream().sorted(Comparator.comparing(a->a.id)).forEach(entry -> { bentries.stream().sorted(Comparator.comparing(a->a.id)).forEach(entry -> {
if (this.biomeId2biomeEntry.size() != entry.id) { if (this.biomeId2biomeEntry.size() != entry.id) {
throw new IllegalStateException("Biome entry not ordered"); throw new IllegalStateException("Biome entry not ordered");
@@ -135,7 +137,7 @@ public class Mapper {
} }
private StateEntry registerNewBlockState(BlockState state) { private synchronized StateEntry registerNewBlockState(BlockState state) {
StateEntry entry = new StateEntry(this.blockId2stateEntry.size(), state); StateEntry entry = new StateEntry(this.blockId2stateEntry.size(), state);
//this.block2stateEntry.put(state, entry); //this.block2stateEntry.put(state, entry);
this.blockId2stateEntry.add(entry); this.blockId2stateEntry.add(entry);
@@ -151,7 +153,7 @@ public class Mapper {
return entry; return entry;
} }
private BiomeEntry registerNewBiome(String biome) { private synchronized BiomeEntry registerNewBiome(String biome) {
BiomeEntry entry = new BiomeEntry(this.biome2biomeEntry.size(), biome); BiomeEntry entry = new BiomeEntry(this.biome2biomeEntry.size(), biome);
//this.biome2biomeEntry.put(biome, entry); //this.biome2biomeEntry.put(biome, entry);
this.biomeId2biomeEntry.add(entry); this.biomeId2biomeEntry.add(entry);
@@ -207,6 +209,42 @@ public class Mapper {
return out; return out;
} }
public void forceResaveStates() {
var blocks = new ArrayList<>(this.block2stateEntry.values());
var biomes = new ArrayList<>(this.biome2biomeEntry.values());
for (var entry : blocks) {
if (entry.state.isAir() && entry.id == 0) {
continue;
}
if (this.blockId2stateEntry.indexOf(entry) != entry.id) {
throw new IllegalStateException("State Id NOT THE SAME, very critically bad");
}
byte[] serialized = entry.serialize();
ByteBuffer buffer = MemoryUtil.memAlloc(serialized.length);
buffer.put(serialized);
buffer.rewind();
this.storage.putIdMapping(entry.id | (BLOCK_STATE_TYPE<<30), buffer);
MemoryUtil.memFree(buffer);
}
for (var entry : biomes) {
if (this.biomeId2biomeEntry.indexOf(entry) != entry.id) {
throw new IllegalStateException("Biome Id NOT THE SAME, very critically bad");
}
byte[] serialized = entry.serialize();
ByteBuffer buffer = MemoryUtil.memAlloc(serialized.length);
buffer.put(serialized);
buffer.rewind();
this.storage.putIdMapping(entry.id | (BIOME_TYPE<<30), buffer);
MemoryUtil.memFree(buffer);
}
this.storage.flush();
}
public static final class StateEntry { public static final class StateEntry {
public final int id; public final int id;
public final BlockState state; public final BlockState state;

View File

@@ -115,7 +115,7 @@ public class StorageBackend {
})); }));
} }
public void putIdMapping(int id, ByteBuffer data) { public synchronized void putIdMapping(int id, ByteBuffer data) {
this.resizingTransaction(()->this.idMappingDatabase.transaction(transaction->{ this.resizingTransaction(()->this.idMappingDatabase.transaction(transaction->{
var keyBuff = transaction.stack.malloc(4); var keyBuff = transaction.stack.malloc(4);
keyBuff.putInt(0, id); keyBuff.putInt(0, id);
@@ -135,7 +135,9 @@ public class StorageBackend {
int keyVal = keyPtr.mv_data().getInt(0); int keyVal = keyPtr.mv_data().getInt(0);
byte[] data = new byte[(int) valPtr.mv_size()]; byte[] data = new byte[(int) valPtr.mv_size()];
Objects.requireNonNull(valPtr.mv_data()).get(data); Objects.requireNonNull(valPtr.mv_data()).get(data);
mapping.put(keyVal, data); if (mapping.put(keyVal, data) != null) {
throw new IllegalStateException("Multiple mappings to same id");
}
} }
} }
return null; return null;

View File

@@ -1,6 +1,7 @@
package me.cortex.voxelmon.mixin.minecraft; package me.cortex.voxelmon.mixin.minecraft;
import me.cortex.voxelmon.core.VoxelCore; import me.cortex.voxelmon.IGetVoxelCore;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.world.ClientChunkManager; import net.minecraft.client.world.ClientChunkManager;
import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.chunk.WorldChunk; import net.minecraft.world.chunk.WorldChunk;
@@ -14,6 +15,9 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
public class MixinClientChunkManager { public class MixinClientChunkManager {
@Inject(method = "unload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientChunkManager$ClientChunkMap;compareAndSet(ILnet/minecraft/world/chunk/WorldChunk;Lnet/minecraft/world/chunk/WorldChunk;)Lnet/minecraft/world/chunk/WorldChunk;", shift = At.Shift.BEFORE), locals = LocalCapture.CAPTURE_FAILHARD) @Inject(method = "unload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientChunkManager$ClientChunkMap;compareAndSet(ILnet/minecraft/world/chunk/WorldChunk;Lnet/minecraft/world/chunk/WorldChunk;)Lnet/minecraft/world/chunk/WorldChunk;", shift = At.Shift.BEFORE), locals = LocalCapture.CAPTURE_FAILHARD)
private void injectUnload(ChunkPos pos, CallbackInfo ci, int index, WorldChunk worldChunk) { private void injectUnload(ChunkPos pos, CallbackInfo ci, int index, WorldChunk worldChunk) {
VoxelCore.INSTANCE.enqueueIngest(worldChunk); var core = ((IGetVoxelCore)MinecraftClient.getInstance().worldRenderer).getVoxelCore();
if (core != null) {
core.enqueueIngest(worldChunk);
}
} }
} }

View File

@@ -1,6 +1,8 @@
package me.cortex.voxelmon.mixin.minecraft; package me.cortex.voxelmon.mixin.minecraft;
import me.cortex.voxelmon.IGetVoxelCore;
import me.cortex.voxelmon.core.VoxelCore; import me.cortex.voxelmon.core.VoxelCore;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.hud.DebugHud; import net.minecraft.client.gui.hud.DebugHud;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -14,6 +16,9 @@ public class MixinDebugHud {
@Inject(method = "getRightText", at = @At("TAIL")) @Inject(method = "getRightText", at = @At("TAIL"))
private void injectDebug(CallbackInfoReturnable<List<String>> cir) { private void injectDebug(CallbackInfoReturnable<List<String>> cir) {
var ret = cir.getReturnValue(); var ret = cir.getReturnValue();
VoxelCore.INSTANCE.addDebugInfo(ret); var core = ((IGetVoxelCore) MinecraftClient.getInstance().worldRenderer).getVoxelCore();
if (core != null) {
core.addDebugInfo(ret);
}
} }
} }

View File

@@ -1,40 +1,80 @@
package me.cortex.voxelmon.mixin.minecraft; package me.cortex.voxelmon.mixin.minecraft;
import me.cortex.voxelmon.IGetVoxelCore;
import me.cortex.voxelmon.Voxelmon; import me.cortex.voxelmon.Voxelmon;
import me.cortex.voxelmon.core.VoxelCore; import me.cortex.voxelmon.core.VoxelCore;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.*; import net.minecraft.client.render.*;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import net.minecraft.client.render.entity.EntityRenderDispatcher;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.world.ClientWorld;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; 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.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(WorldRenderer.class) @Mixin(WorldRenderer.class)
public abstract class MixinWorldRenderer { public abstract class MixinWorldRenderer implements IGetVoxelCore {
@Shadow protected abstract void renderLayer(RenderLayer renderLayer, MatrixStack matrices, double cameraX, double cameraY, double cameraZ, Matrix4f positionMatrix); @Shadow protected abstract void renderLayer(RenderLayer renderLayer, MatrixStack matrices, double cameraX, double cameraY, double cameraZ, Matrix4f positionMatrix);
@Shadow protected abstract void setupTerrain(Camera camera, Frustum frustum, boolean hasForcedFrustum, boolean spectator); @Shadow protected abstract void setupTerrain(Camera camera, Frustum frustum, boolean hasForcedFrustum, boolean spectator);
@Shadow private Frustum frustum; @Shadow private Frustum frustum;
@Shadow private @Nullable ClientWorld world;
@Unique private VoxelCore core;
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;setupTerrain(Lnet/minecraft/client/render/Camera;Lnet/minecraft/client/render/Frustum;ZZ)V", shift = At.Shift.AFTER)) @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;setupTerrain(Lnet/minecraft/client/render/Camera;Lnet/minecraft/client/render/Frustum;ZZ)V", shift = At.Shift.AFTER))
private void injectSetup(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f projectionMatrix, CallbackInfo ci) { private void injectSetup(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f projectionMatrix, CallbackInfo ci) {
//Call our setup method this.core.renderSetup(this.frustum, camera);
VoxelCore.INSTANCE.renderSetup(this.frustum, camera);
} }
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;renderLayer(Lnet/minecraft/client/render/RenderLayer;Lnet/minecraft/client/util/math/MatrixStack;DDDLorg/joml/Matrix4f;)V", ordinal = 2, shift = At.Shift.AFTER)) @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;renderLayer(Lnet/minecraft/client/render/RenderLayer;Lnet/minecraft/client/util/math/MatrixStack;DDDLorg/joml/Matrix4f;)V", ordinal = 2, shift = At.Shift.AFTER))
private void injectOpaqueRender(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f projectionMatrix, CallbackInfo ci) { private void injectOpaqueRender(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f projectionMatrix, CallbackInfo ci) {
var cam = camera.getPos(); var cam = camera.getPos();
//Call the actual render method this.core.renderOpaque(matrices, cam.x, cam.y, cam.z);
VoxelCore.INSTANCE.renderOpaque(matrices, cam.x, cam.y, cam.z);
} }
public VoxelCore getVoxelCore() {
return this.core;
}
@Inject(method = "reload()V", at = @At("TAIL"))
private void resetVoxelCore(CallbackInfo ci) {
if (this.world != null && this.core != null) {
this.core.shutdown();
this.core = new VoxelCore();
}
}
@Inject(method = "setWorld", at = @At("TAIL"))
private void initVoxelCore(ClientWorld world, CallbackInfo ci) {
if (world == null) {
if (this.core != null) {
this.core.shutdown();
this.core = null;
}
return;
}
if (this.core != null) {
throw new IllegalStateException("Core is not null");
}
this.core = new VoxelCore();
}
@Inject(method = "close", at = @At("HEAD"))
private void injectClose(CallbackInfo ci) {
if (this.core != null) {
this.core.shutdown();
this.core = null;
}
}

View File

@@ -1,29 +1,31 @@
package me.cortex.voxelmon.terrain; package me.cortex.voxelmon.terrain;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import me.cortex.voxelmon.core.VoxelCore; import me.cortex.voxelmon.IGetVoxelCore;
import me.cortex.voxelmon.importers.WorldImporter; import me.cortex.voxelmon.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.client.MinecraftClient;
import net.minecraft.client.network.ClientCommandSource; import net.minecraft.text.Text;
import net.minecraft.server.command.ServerCommandSource; import org.jetbrains.annotations.NotNull;
import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal; import java.io.File;
import static com.mojang.brigadier.builder.RequiredArgumentBuilder.argument;
/*
public class WorldImportCommand { public class WorldImportCommand {
public static void register(CommandDispatcher<ClientCommandSource> dispatcher) { public static LiteralArgumentBuilder<FabricClientCommandSource> register() {
dispatcher.register(literal("zenith") return ClientCommandManager.literal("zenith").then(ClientCommandManager.literal("import").then(ClientCommandManager.literal("world").then(ClientCommandManager.argument("world_name", StringArgumentType.string()).executes(WorldImportCommand::importWorld))));
.then(literal("import").then(literal("world").then(argument("world_name", StringArgumentType.string()).executes(WorldImportCommand::importWorld)))));
} }
public static WorldImporter importerInstance;
private static int importWorld(CommandContext<ClientCommandSource> ctx) { private static int importWorld(CommandContext<FabricClientCommandSource> ctx) {
VoxelCore.INSTANCE.createWorldImporter(MinecraftClient.getInstance().world, ctx.getArgument("world_name", String.class)); var instance = MinecraftClient.getInstance();
var file = new File(ctx.getArgument("world_name", String.class));
importerInstance = ((IGetVoxelCore)instance.worldRenderer).getVoxelCore().createWorldImporter(MinecraftClient.getInstance().player.clientWorld, file);
return 0; return 0;
} }
} }
*/

View File

@@ -81,7 +81,7 @@ void main() {
if (face == 0) { if (face == 0) {
colour.xyz *= vec3(0.75, 0.75, 0.75); colour.xyz *= vec3(0.75, 0.75, 0.75);
} else if (face != 1) { } else if (face != 1) {
colour.xyz *= vec3((float(face-2)/4)*0.25 + 0.75); colour.xyz *= vec3((float(face-2)/4)*0.5 + 0.5);
} }