Made it reloadable, added import command, fixed race conditions and many other things
This commit is contained in:
7
src/main/java/me/cortex/voxelmon/IGetVoxelCore.java
Normal file
7
src/main/java/me/cortex/voxelmon/IGetVoxelCore.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package me.cortex.voxelmon;
|
||||
|
||||
import me.cortex.voxelmon.core.VoxelCore;
|
||||
|
||||
public interface IGetVoxelCore {
|
||||
VoxelCore getVoxelCore();
|
||||
}
|
||||
@@ -2,13 +2,17 @@ package me.cortex.voxelmon;
|
||||
|
||||
import me.cortex.voxelmon.terrain.TestSparseGenCommand;
|
||||
//import me.cortex.voxelmon.terrain.WorldImportCommand;
|
||||
import me.cortex.voxelmon.terrain.WorldImportCommand;
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
|
||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||
|
||||
public class Voxelmon implements ClientModInitializer {
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
//CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> WorldImportCommand.register(dispatcher));
|
||||
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {
|
||||
dispatcher.register(WorldImportCommand.register());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public class DistanceTracker {
|
||||
this.tracker = tracker;
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ import static org.lwjgl.opengl.ARBFramebufferObject.glBindFramebuffer;
|
||||
//Ingest -> world engine -> raw render data -> render data
|
||||
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,
|
||||
Blocks.TALL_GRASS, Blocks.LARGE_FERN,
|
||||
Blocks.TALL_GRASS, Blocks.LARGE_FERN, Blocks.SHORT_GRASS,
|
||||
|
||||
Blocks.SPRUCE_LEAVES,
|
||||
Blocks.BIRCH_LEAVES,
|
||||
@@ -58,9 +58,6 @@ public class VoxelCore {
|
||||
private static final Set<Block> waterTint = new HashSet<>(List.of(Blocks.WATER));
|
||||
|
||||
|
||||
|
||||
public static VoxelCore INSTANCE = new VoxelCore();
|
||||
|
||||
private final WorldEngine world;
|
||||
private final DistanceTracker distanceTracker;
|
||||
private final RenderGenerationService renderGen;
|
||||
@@ -69,6 +66,8 @@ public class VoxelCore {
|
||||
private final AbstractFarWorldRenderer renderer;
|
||||
private final PostProcessing postProcessing;
|
||||
|
||||
//private final Thread shutdownThread = new Thread(this::shutdown);
|
||||
|
||||
public VoxelCore() {
|
||||
//Trigger the shared index buffer loading
|
||||
SharedIndexBuffer.INSTANCE.id();
|
||||
@@ -81,33 +80,13 @@ public class VoxelCore {
|
||||
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
|
||||
this.distanceTracker = new DistanceTracker(this.renderTracker, 5, 16);
|
||||
this.distanceTracker = new DistanceTracker(this.renderTracker, 5, 16);//20
|
||||
|
||||
this.postProcessing = new PostProcessing();
|
||||
|
||||
this.world.getMapper().setCallbacks(this::stateUpdate, this::biomeUpdate);
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown));
|
||||
|
||||
|
||||
|
||||
/*
|
||||
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));
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
//Runtime.getRuntime().addShutdownHook(this.shutdownThread);
|
||||
|
||||
|
||||
//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
|
||||
|
||||
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.world.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);}
|
||||
}
|
||||
|
||||
public WorldImporter createWorldImporter(World mcWorld, File worldPath) {
|
||||
var importer = new WorldImporter(this.world, mcWorld);
|
||||
importer.importWorldAsyncStart(worldPath, 10, null, ()->{
|
||||
importer.importWorldAsyncStart(worldPath, 5, null, ()->{
|
||||
System.err.println("DONE IMPORT");
|
||||
});
|
||||
return importer;
|
||||
|
||||
@@ -32,47 +32,6 @@ public class RenderTracker {
|
||||
public RenderTracker(WorldEngine world, AbstractFarWorldRenderer renderer) {
|
||||
this.world = world;
|
||||
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
|
||||
|
||||
@@ -38,7 +38,8 @@ public abstract class TrackedObject {
|
||||
boolean[] freed = new boolean[1];
|
||||
var clean = cleaner.register(obj, ()->{
|
||||
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();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -131,6 +131,10 @@ public class ColourResolver {
|
||||
|
||||
public static long resolveBiomeColour(String 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 ARGBWater = biome.getWaterColor();
|
||||
return Integer.toUnsignedLong(((ARGBFoliage&0xFFFFFF)<<8)|(ARGBFoliage>>>24)) | (Integer.toUnsignedLong(((ARGBWater&0xFFFFFF)<<8)|(ARGBWater>>>24))<<32);
|
||||
|
||||
@@ -79,6 +79,7 @@ public class Mapper {
|
||||
List<BiomeEntry> bentries = new ArrayList<>();
|
||||
List<Pair<byte[], Integer>> sentryErrors = new ArrayList<>();
|
||||
|
||||
|
||||
for (var entry : mappings.int2ObjectEntrySet()) {
|
||||
int entryType = entry.getIntKey()>>>30;
|
||||
int id = entry.getIntKey() & ((1<<30)-1);
|
||||
@@ -126,6 +127,7 @@ public class Mapper {
|
||||
}
|
||||
this.blockId2stateEntry.add(entry);
|
||||
});
|
||||
|
||||
bentries.stream().sorted(Comparator.comparing(a->a.id)).forEach(entry -> {
|
||||
if (this.biomeId2biomeEntry.size() != entry.id) {
|
||||
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);
|
||||
//this.block2stateEntry.put(state, entry);
|
||||
this.blockId2stateEntry.add(entry);
|
||||
@@ -151,7 +153,7 @@ public class Mapper {
|
||||
return entry;
|
||||
}
|
||||
|
||||
private BiomeEntry registerNewBiome(String biome) {
|
||||
private synchronized BiomeEntry registerNewBiome(String biome) {
|
||||
BiomeEntry entry = new BiomeEntry(this.biome2biomeEntry.size(), biome);
|
||||
//this.biome2biomeEntry.put(biome, entry);
|
||||
this.biomeId2biomeEntry.add(entry);
|
||||
@@ -207,6 +209,42 @@ public class Mapper {
|
||||
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 final int id;
|
||||
public final BlockState state;
|
||||
|
||||
@@ -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->{
|
||||
var keyBuff = transaction.stack.malloc(4);
|
||||
keyBuff.putInt(0, id);
|
||||
@@ -135,7 +135,9 @@ public class StorageBackend {
|
||||
int keyVal = keyPtr.mv_data().getInt(0);
|
||||
byte[] data = new byte[(int) valPtr.mv_size()];
|
||||
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;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
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.util.math.ChunkPos;
|
||||
import net.minecraft.world.chunk.WorldChunk;
|
||||
@@ -14,6 +15,9 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
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)
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package me.cortex.voxelmon.mixin.minecraft;
|
||||
|
||||
import me.cortex.voxelmon.IGetVoxelCore;
|
||||
import me.cortex.voxelmon.core.VoxelCore;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.hud.DebugHud;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -14,6 +16,9 @@ public class MixinDebugHud {
|
||||
@Inject(method = "getRightText", at = @At("TAIL"))
|
||||
private void injectDebug(CallbackInfoReturnable<List<String>> cir) {
|
||||
var ret = cir.getReturnValue();
|
||||
VoxelCore.INSTANCE.addDebugInfo(ret);
|
||||
var core = ((IGetVoxelCore) MinecraftClient.getInstance().worldRenderer).getVoxelCore();
|
||||
if (core != null) {
|
||||
core.addDebugInfo(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +1,80 @@
|
||||
package me.cortex.voxelmon.mixin.minecraft;
|
||||
|
||||
import me.cortex.voxelmon.IGetVoxelCore;
|
||||
import me.cortex.voxelmon.Voxelmon;
|
||||
import me.cortex.voxelmon.core.VoxelCore;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
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.world.ClientWorld;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix4f;
|
||||
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.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@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 setupTerrain(Camera camera, Frustum frustum, boolean hasForcedFrustum, boolean spectator);
|
||||
|
||||
@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))
|
||||
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
|
||||
VoxelCore.INSTANCE.renderSetup(this.frustum, camera);
|
||||
this.core.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))
|
||||
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();
|
||||
//Call the actual render method
|
||||
VoxelCore.INSTANCE.renderOpaque(matrices, cam.x, cam.y, cam.z);
|
||||
this.core.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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,29 +1,31 @@
|
||||
package me.cortex.voxelmon.terrain;
|
||||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import me.cortex.voxelmon.core.VoxelCore;
|
||||
import me.cortex.voxelmon.IGetVoxelCore;
|
||||
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.network.ClientCommandSource;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.text.Text;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal;
|
||||
import static com.mojang.brigadier.builder.RequiredArgumentBuilder.argument;
|
||||
import java.io.File;
|
||||
|
||||
|
||||
/*
|
||||
public class WorldImportCommand {
|
||||
public static void register(CommandDispatcher<ClientCommandSource> dispatcher) {
|
||||
dispatcher.register(literal("zenith")
|
||||
.then(literal("import").then(literal("world").then(argument("world_name", StringArgumentType.string()).executes(WorldImportCommand::importWorld)))));
|
||||
public static LiteralArgumentBuilder<FabricClientCommandSource> register() {
|
||||
return ClientCommandManager.literal("zenith").then(ClientCommandManager.literal("import").then(ClientCommandManager.literal("world").then(ClientCommandManager.argument("world_name", StringArgumentType.string()).executes(WorldImportCommand::importWorld))));
|
||||
}
|
||||
|
||||
public static WorldImporter importerInstance;
|
||||
|
||||
private static int importWorld(CommandContext<ClientCommandSource> ctx) {
|
||||
VoxelCore.INSTANCE.createWorldImporter(MinecraftClient.getInstance().world, ctx.getArgument("world_name", String.class));
|
||||
private static int importWorld(CommandContext<FabricClientCommandSource> ctx) {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
@@ -81,7 +81,7 @@ void main() {
|
||||
if (face == 0) {
|
||||
colour.xyz *= vec3(0.75, 0.75, 0.75);
|
||||
} 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user