From b84f670a481ff01dd0076b938fa7515d038eefa3 Mon Sep 17 00:00:00 2001 From: MartinLaptop Date: Sun, 15 Jan 2023 05:50:40 +0100 Subject: [PATCH 01/14] Complete internal rewrite to remove stuttering and heavily improve performance -replaces scanntast with a asyncrounus ChunkCache -split bufferupload on a per chunk basis to remove stuttering --- .../pro/mikey/fabric/xray/ScanController.java | 130 ++++++++++------- .../java/pro/mikey/fabric/xray/ScanTask.java | 131 ------------------ src/main/java/pro/mikey/fabric/xray/XRay.java | 75 ++++++++-- .../fabric/xray/mixins/MixinBlockItem.java | 3 +- .../fabric/xray/render/RenderOutlines.java | 126 +++++++++++++---- .../screens/forge/GuiSelectionScreen.java | 5 +- .../mikey/fabric/xray/tasks/AddChunkTask.java | 84 +++++++++++ .../mikey/fabric/xray/tasks/ReBuildCache.java | 75 ++++++++++ .../fabric/xray/tasks/RemoveChunkTask.java | 22 +++ .../fabric/xray/tasks/UpdateChunkTask.java | 34 +++++ .../advanced-xray-fabric/lang/en_us.json | 4 +- 11 files changed, 461 insertions(+), 228 deletions(-) delete mode 100644 src/main/java/pro/mikey/fabric/xray/ScanTask.java create mode 100644 src/main/java/pro/mikey/fabric/xray/tasks/AddChunkTask.java create mode 100644 src/main/java/pro/mikey/fabric/xray/tasks/ReBuildCache.java create mode 100644 src/main/java/pro/mikey/fabric/xray/tasks/RemoveChunkTask.java create mode 100644 src/main/java/pro/mikey/fabric/xray/tasks/UpdateChunkTask.java diff --git a/src/main/java/pro/mikey/fabric/xray/ScanController.java b/src/main/java/pro/mikey/fabric/xray/ScanController.java index 6125bd4..4e4beb9 100644 --- a/src/main/java/pro/mikey/fabric/xray/ScanController.java +++ b/src/main/java/pro/mikey/fabric/xray/ScanController.java @@ -1,78 +1,104 @@ package pro.mikey.fabric.xray; -import net.minecraft.Util; -import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.core.SectionPos; import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import pro.mikey.fabric.xray.records.BlockPosWithColor; -import pro.mikey.fabric.xray.storage.BlockStore; +import pro.mikey.fabric.xray.render.RenderOutlines; import pro.mikey.fabric.xray.storage.SettingsStore; +import pro.mikey.fabric.xray.tasks.*; + +import java.util.concurrent.*; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; public class ScanController { - public static Set renderQueue = Collections.synchronizedSet(new HashSet<>()); - private static ChunkPos playerLastChunk; + static ThreadPoolExecutor executor = new ThreadPoolExecutor( + StateSettings.getRadius(), StateSettings.getRadius(), + 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue() + ); /** - * No point even running if the player is still in the same chunk. + * This function sets the Threadpool up properly. + * Technically the threads set their own Priority to one anyways, so a normal Threapool would be sufficient */ - private static boolean playerLocationChanged() { - if (Minecraft.getInstance().player == null) - return false; - - ChunkPos plyChunkPos = Minecraft.getInstance().player.chunkPosition(); - int range = StateSettings.getHalfRange(); + public static void setup(){ + executor.setThreadFactory(r -> { + Thread thread = new Thread(r); + thread.setPriority(Thread.MIN_PRIORITY); + return thread; + }); + } - return playerLastChunk == null || - plyChunkPos.x > playerLastChunk.x + range || plyChunkPos.x < playerLastChunk.x - range || - plyChunkPos.z > playerLastChunk.z + range || plyChunkPos.z < playerLastChunk.z - range; + private static void submitTask(Runnable worker){ + if(!executor.isShutdown()){ + executor.execute(worker); + } } /** - * Runs the scan task by checking if the thread is ready but first attempting to provide the cache - * if the cache is still valid. - * - * @param forceRerun if the task is required to re-run for instance, a block is broken in the - * world. + * Just a security measure to forceclose the threadpool to make sure it doesnt linger in the background */ - public static synchronized void runTask(boolean forceRerun) { - Minecraft client = Minecraft.getInstance(); - if (client.player == null && client.level == null) { - return; - } + public static void CloseGame(){ + executor.shutdownNow(); + } - if (!SettingsStore.getInstance().get().isActive() || (!forceRerun && !playerLocationChanged())) { - return; - } - // Update the players last chunk to eval against above. - playerLastChunk = client.player.chunkPosition(); - Util.backgroundExecutor().execute(new ScanTask()); + /** + * This function rebuilds the ChunkCache completly and reloads all Chunks + * without flashing the already rendered Chunks instantly away + */ + public static void RebuildCache(){ + class RebuildThread extends Thread{ + @Override + public synchronized void run() { + RenderOutlines.clearChunks(false); + executor.shutdownNow(); + while(!executor.isTerminated()){ + try { + currentThread().wait(5); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + executor = new ThreadPoolExecutor( + StateSettings.getRadius(), StateSettings.getRadius(), + 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue() + ); + setup(); + Runnable worker = new ReBuildCache(); + executor.execute(worker); + } + } + Thread r = new RebuildThread(); + r.start(); } - public static void blockBroken(Level world, Player playerEntity, BlockPos blockPos, BlockState blockState, BlockEntity blockEntity) { - if (!SettingsStore.getInstance().get().isActive()) return; - - if (renderQueue.stream().anyMatch(e -> e.pos().equals(blockPos))) { - runTask(true); + /** + * This function updates a Chunk based on Pos + */ + public static void updateChunk(ChunkPos pos){ + if(SettingsStore.getInstance().get().isActive()){ + Runnable worker = new UpdateChunkTask(pos); + submitTask(worker); } } - public static void blockPlaced(BlockPlaceContext context) { - if (!SettingsStore.getInstance().get().isActive()) return; + /** + * This function updates a Chunk based on Pos + */ + public static void updateChunk(BlockPos pos){ + int chunkx = SectionPos.blockToSectionCoord(pos.getX()); + int chunkz = SectionPos.blockToSectionCoord(pos.getZ()); + ChunkPos chunkPos = new ChunkPos(chunkx,chunkz); + updateChunk(chunkPos); + } - BlockState defaultState = Block.byItem(context.getItemInHand().getItem()).defaultBlockState(); - if (BlockStore.getInstance().getCache().get().stream().anyMatch(e -> e.getState() == defaultState)) { - runTask(true); - } + /** + * This function removes a chunk from the Rendering + */ + public static void removeChunk(ChunkPos pos){ + Runnable worker = new RemoveChunkTask(pos); + submitTask(worker); } } diff --git a/src/main/java/pro/mikey/fabric/xray/ScanTask.java b/src/main/java/pro/mikey/fabric/xray/ScanTask.java deleted file mode 100644 index fa0119c..0000000 --- a/src/main/java/pro/mikey/fabric/xray/ScanTask.java +++ /dev/null @@ -1,131 +0,0 @@ -package pro.mikey.fabric.xray; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.LevelChunkSection; -import net.minecraft.world.level.material.LavaFluid; -import org.jetbrains.annotations.Nullable; -import pro.mikey.fabric.xray.cache.BlockSearchEntry; -import pro.mikey.fabric.xray.records.BasicColor; -import pro.mikey.fabric.xray.records.BlockPosWithColor; -import pro.mikey.fabric.xray.render.RenderOutlines; -import pro.mikey.fabric.xray.storage.BlockStore; -import pro.mikey.fabric.xray.storage.SettingsStore; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; - -public class ScanTask implements Runnable { - private static AtomicBoolean isScanning = new AtomicBoolean(false); - - ScanTask() { - } - - /** - * Check if we're valid and push back the blocks color for the render queue - */ - @Nullable - public static BasicColor isValidBlock(BlockPos pos, Level world, Set blocks) { - BlockState state = world.getBlockState(pos); - if (state.isAir()) { - return null; - } - - if (SettingsStore.getInstance().get().isShowLava() && state.getFluidState().getType() instanceof LavaFluid) { - return new BasicColor(210, 10, 10); - } - - BlockState defaultState = state.getBlock().defaultBlockState(); - - return blocks.stream() - .filter(localState -> localState.isDefault() && defaultState == localState.getState() || !localState.isDefault() && state == localState.getState()) - .findFirst() - .map(BlockSearchEntry::getColor) - .orElse(null); - } - - @Override - public void run() { - if (isScanning.get()) { - return; - } - - isScanning.set(true); - Set c = this.collectBlocks(); - ScanController.renderQueue.clear(); - ScanController.renderQueue.addAll(c); - isScanning.set(false); - RenderOutlines.requestedRefresh.set(true); - } - - /** - * This is an "exact" copy from the forge version of the mod but with the optimisations that the - * rewrite (Fabric) version has brought like chunk location based cache, etc. - * - *

This is only run if the cache is invalidated. - * - * @implNote Using the {@link BlockPos#betweenClosed(BlockPos, BlockPos)} may be a better system for the - * scanning. - */ - private Set collectBlocks() { - Set blocks = BlockStore.getInstance().getCache().get(); - - // If we're not looking for blocks, don't run. - if (blocks.isEmpty() && !SettingsStore.getInstance().get().isShowLava()) { - if (!ScanController.renderQueue.isEmpty()) { - ScanController.renderQueue.clear(); - } - return new HashSet<>(); - } - - Minecraft instance = Minecraft.getInstance(); - - final Level world = instance.level; - final Player player = instance.player; - - // Just stop if we can't get the player or world. - if (world == null || player == null) { - return new HashSet<>(); - } - - final Set renderQueue = new HashSet<>(); - - int cX = player.chunkPosition().x; - int cZ = player.chunkPosition().z; - - int range = StateSettings.getHalfRange(); - - for (int i = cX - range; i <= cX + range; i++) { - int chunkStartX = i << 4; - for (int j = cZ - range; j <= cZ + range; j++) { - int chunkStartZ = j << 4; - - int height = Arrays.stream(world.getChunk(i, j).getSections()) - .filter(Objects::nonNull) - .mapToInt(LevelChunkSection::bottomBlockY) - .max() - .orElse(0); - - for (int k = chunkStartX; k < chunkStartX + 16; k++) { - for (int l = chunkStartZ; l < chunkStartZ + 16; l++) { - for (int m = world.getMinBuildHeight(); m < height + (1 << 4); m++) { - BlockPos pos = new BlockPos(k, m, l); - BasicColor validBlock = isValidBlock(pos, world, blocks); - if (validBlock != null) { - renderQueue.add(new BlockPosWithColor(pos, validBlock)); - } - } - } - } - } - } - - return renderQueue; - } -} diff --git a/src/main/java/pro/mikey/fabric/xray/XRay.java b/src/main/java/pro/mikey/fabric/xray/XRay.java index fffd951..d11633f 100644 --- a/src/main/java/pro/mikey/fabric/xray/XRay.java +++ b/src/main/java/pro/mikey/fabric/xray/XRay.java @@ -1,7 +1,7 @@ package pro.mikey.fabric.xray; import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientChunkEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; @@ -11,8 +11,15 @@ import net.minecraft.ChatFormatting; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; -import net.minecraft.world.level.block.LevelEvent; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.LevelChunk; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.lwjgl.glfw.GLFW; @@ -22,6 +29,9 @@ import pro.mikey.fabric.xray.storage.BlockStore; import pro.mikey.fabric.xray.storage.SettingsStore; +import java.util.HashSet; +import java.util.Set; + public class XRay implements ModInitializer { public static final String MOD_ID = "advanced-xray-fabric"; @@ -32,24 +42,59 @@ public class XRay implements ModInitializer { private final KeyMapping guiButton = new KeyMapping("keybinding.open_gui", GLFW.GLFW_KEY_G, "category.xray"); + public static volatile Set chunks = new HashSet<>(); + @Override public void onInitialize() { LOGGER.info("XRay mod has been initialized"); ClientTickEvents.END_CLIENT_TICK.register(this::clientTickEvent); ClientLifecycleEvents.CLIENT_STOPPING.register(this::gameClosing); - ClientLifecycleEvents.CLIENT_STARTED.register(this::started); + ClientChunkEvents.CHUNK_LOAD.register(this::ChunkLoad); + ClientChunkEvents.CHUNK_UNLOAD.register(this::ChunkUnload); HudRenderCallback.EVENT.register(GuiOverlay::RenderGameOverlayEvent); WorldRenderEvents.LAST.register(RenderOutlines::render); - PlayerBlockBreakEvents.AFTER.register(ScanController::blockBroken); + PlayerBlockBreakEvents.AFTER.register(this::blockBroken); KeyBindingHelper.registerKeyBinding(this.xrayButton); KeyBindingHelper.registerKeyBinding(this.guiButton); + ScanController.setup(); + } + + /** + * Upon unloading a chunk the chunk can be removed from the rendering + */ + private void ChunkUnload(ClientLevel clientLevel, LevelChunk levelChunk) { + if (!SettingsStore.getInstance().get().isActive()) return; + chunks.remove(levelChunk); + ScanController.removeChunk(levelChunk.getPos()); } - private void started(Minecraft minecraft) { - LOGGER.info("Client started, setting up xray store"); + /** + * Upon loading a chunk the chunk needs to be queued for scanning and rendering + */ + private void ChunkLoad(ClientLevel clientLevel, LevelChunk levelChunk) { + if (!SettingsStore.getInstance().get().isActive()) return; + chunks.add(levelChunk); + ScanController.updateChunk(levelChunk.getPos()); + } + + /** + * Upon breaking a block the Chunk of the Block should be updated immediately + */ + private void blockBroken(Level world, Player playerEntity, BlockPos pos, BlockState blockState, BlockEntity blockEntity) { + if (!SettingsStore.getInstance().get().isActive()) return; + ScanController.updateChunk(pos); + } + + /** + * Upon placing a block the Chunk of the Block should be updated immediately + */ + public static void blockPlaced(BlockPlaceContext context) { + if (!SettingsStore.getInstance().get().isActive()) return; + BlockPos pos = context.getClickedPos(); + ScanController.updateChunk(pos); } /** @@ -57,6 +102,7 @@ private void started(Minecraft minecraft) { * we go about saving throughout the rest of the mod */ private void gameClosing(Minecraft client) { + ScanController.CloseGame(); SettingsStore.getInstance().write(); BlockStore.getInstance().write(); } @@ -68,9 +114,12 @@ private void clientTickEvent(Minecraft mc) { if (mc.player == null || mc.level == null || mc.screen != null) { return; } - - // Try and run the task :D - ScanController.runTask(false); + int counter = 0; + if (counter % 200 == 0) { + RenderOutlines.clearChunks(false); + counter=0; + } + counter++; while (this.guiButton.consumeClick()) { mc.setScreen(new GuiSelectionScreen()); @@ -81,8 +130,12 @@ private void clientTickEvent(Minecraft mc) { StateSettings stateSettings = SettingsStore.getInstance().get(); stateSettings.setActive(!stateSettings.isActive()); - - ScanController.runTask(true); + if(stateSettings.isActive()){ + ScanController.RebuildCache(); + } + else{ + RenderOutlines.clearChunks(true); + } mc.player.displayClientMessage(Component.translatable("message.xray_" + (!stateSettings.isActive() ? "deactivate" : "active")).withStyle(stateSettings.isActive() ? ChatFormatting.GREEN : ChatFormatting.RED), true); } diff --git a/src/main/java/pro/mikey/fabric/xray/mixins/MixinBlockItem.java b/src/main/java/pro/mikey/fabric/xray/mixins/MixinBlockItem.java index a54f4ae..3399e10 100644 --- a/src/main/java/pro/mikey/fabric/xray/mixins/MixinBlockItem.java +++ b/src/main/java/pro/mikey/fabric/xray/mixins/MixinBlockItem.java @@ -8,6 +8,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import pro.mikey.fabric.xray.ScanController; +import pro.mikey.fabric.xray.XRay; // Thanks to architectury @Mixin(BlockItem.class) @@ -15,7 +16,7 @@ public abstract class MixinBlockItem { @Inject(method = "place", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/InteractionResult;sidedSuccess(Z)Lnet/minecraft/world/InteractionResult;")) private void place(BlockPlaceContext context, CallbackInfoReturnable cir) { if (context.getLevel().isClientSide) { - ScanController.blockPlaced(context); + XRay.blockPlaced(context); } } } diff --git a/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java b/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java index 1feaded..3d2c601 100644 --- a/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java +++ b/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java @@ -5,58 +5,128 @@ import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.Camera; +import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.world.level.ChunkPos; import net.minecraft.world.phys.Vec3; import org.joml.Matrix4f; import org.joml.Quaternionf; -import org.joml.Vector3f; import org.lwjgl.opengl.GL11; -import pro.mikey.fabric.xray.ScanController; import pro.mikey.fabric.xray.records.BlockPosWithColor; import pro.mikey.fabric.xray.storage.SettingsStore; +import java.util.*; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicBoolean; -import static net.minecraft.util.Mth.cos; -import static net.minecraft.util.Mth.sin; +import static java.lang.Math.cos; +import static java.lang.Math.sin; public class RenderOutlines { - private static VertexBuffer vertexBuffer; - public static AtomicBoolean requestedRefresh = new AtomicBoolean(false); + /** + * This queue holds the by the threadpool queued workloads for the Renderthread. + * To keep performancy high the renderthreads only uploads one Chunk per frame + */ + private static ConcurrentLinkedQueue workQueue = new ConcurrentLinkedQueue<>(); + /** + * This is the internal Vertexbuffers mapped by chunk so the removal is simple + */ + private static Map chunkCache = new HashMap(); + /** + * This queue holds the by the threadpool queued removal workloads for the Renderthread. + * To keep performancy high the renderthreads removes up to 100 per frame. + */ + private static ConcurrentLinkedQueue deleteQueue = new ConcurrentLinkedQueue<>(); + /** + * If this boolen is set to true it force clears all the buffers immediately + */ + private static AtomicBoolean forceclear = new AtomicBoolean(false); private static int canvasLoaded = -1; + private static class WorkLoad{ + public Long chunk; + public Collection pos; + public WorkLoad(Long chunk,Collection pos){ + this.chunk = chunk; + this.pos = pos; + } + } + + /** + * This function adds a Chunk into the queue to be rendered + */ + public static void addChunk(Long chunk,Collection pos){ + workQueue.add(new WorkLoad(chunk,pos)); + } + + /** + * This function removes a chunk from the already rendered cache + */ + public static void removeChunk(Long number){ + deleteQueue.add(number); + } + + /** + * This function can be called to initiate a clear, + * if force is set to true if completly whipes all Buffers and queues, + * if force is set to false it only removes onloaded chunks from the active rendered queue + */ + public static void clearChunks(boolean force){ + if(force){ + forceclear.set(true); + } + else{ + Set keys = new HashSet<>(chunkCache.keySet()); + keys.forEach(chunkPos->{ + if((Minecraft.getInstance().player.clientLevel.getChunkSource().getChunk(ChunkPos.getX(chunkPos),ChunkPos.getZ(chunkPos),false)==null)){ + deleteQueue.add(chunkPos); + } + }); + } + } public static synchronized void render(WorldRenderContext context) { if (canvasLoaded == -1) { canvasLoaded = FabricLoader.getInstance().isModLoaded("canvas") ? 1 : 0; } + if(forceclear.get()){ + workQueue.clear(); + deleteQueue.clear(); + chunkCache.clear(); + forceclear.set(false); + } - if (ScanController.renderQueue.isEmpty() || !SettingsStore.getInstance().get().isActive()) { + if (!SettingsStore.getInstance().get().isActive()) { return; } - - if (vertexBuffer == null || requestedRefresh.get()) { - requestedRefresh.set(false); - vertexBuffer = new VertexBuffer(); - - Tesselator tessellator = Tesselator.getInstance(); - BufferBuilder buffer = tessellator.getBuilder(); - - buffer.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR); - ScanController.renderQueue.forEach(blockProps -> { - if (blockProps == null) { - return; - } - - renderBlock(buffer, blockProps, 1); + WorkLoad work = workQueue.poll(); + if(work!=null){ + BufferBuilder bufferBuilder = Tesselator.getInstance().getBuilder(); + bufferBuilder.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR); + work.pos.stream().forEach(posWithColor -> { + renderBlock(bufferBuilder, posWithColor, 1); }); - + bufferBuilder.clear(); + VertexBuffer vertexBuffer = new VertexBuffer(); vertexBuffer.bind(); - vertexBuffer.upload(buffer.end()); + BufferBuilder.RenderedBuffer buffer = bufferBuilder.end(); + vertexBuffer.upload(buffer); VertexBuffer.unbind(); + chunkCache.put(work.chunk,vertexBuffer); + bufferBuilder.discard(); + } + int removed = 0; + Long toRemove; + while ((toRemove = deleteQueue.poll()) != null && removed < 100) { + VertexBuffer vertexBuffer = chunkCache.get(toRemove); + if(vertexBuffer!=null){ + vertexBuffer.close(); + } + chunkCache.remove(toRemove); + removed++; } - if (vertexBuffer != null) { + if (chunkCache.size()>0) { Camera camera = context.camera(); Vec3 cameraPos = camera.getPosition(); @@ -79,8 +149,10 @@ public static synchronized void render(WorldRenderContext context) { RenderSystem.setShader(GameRenderer::getPositionColorShader); RenderSystem.applyModelViewMatrix(); RenderSystem.depthFunc(GL11.GL_ALWAYS); - vertexBuffer.bind(); - vertexBuffer.drawWithShader(poseStack.last().pose(), new Matrix4f(context.projectionMatrix()), RenderSystem.getShader()); + chunkCache.values().stream().forEach(buf -> { + buf.bind(); + buf.drawWithShader(poseStack.last().pose(), new Matrix4f(context.projectionMatrix()), RenderSystem.getShader()); + }); VertexBuffer.unbind(); RenderSystem.depthFunc(GL11.GL_LEQUAL); diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java index dc18369..1a4b27b 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java @@ -146,7 +146,6 @@ public void init() { this.addRenderableWidget(this.distButtons = Button.builder(Component.translatable("xray.input.show-lava", SettingsStore.getInstance().get().isShowLava()), button -> { SettingsStore.getInstance().get().setShowLava(!SettingsStore.getInstance().get().isShowLava()); - ScanController.runTask(true); button.setMessage(Component.translatable("xray.input.show-lava", SettingsStore.getInstance().get().isShowLava())); }) .pos((this.getWidth() / 2) + 79, this.getHeight() / 2 + 6) @@ -229,9 +228,7 @@ public void onClose() { SettingsStore.getInstance().write(); BlockStore.getInstance().write(); BlockStore.getInstance().updateCache(); - - ScanController.runTask(true); - + ScanController.RebuildCache(); super.onClose(); } diff --git a/src/main/java/pro/mikey/fabric/xray/tasks/AddChunkTask.java b/src/main/java/pro/mikey/fabric/xray/tasks/AddChunkTask.java new file mode 100644 index 0000000..c95ce68 --- /dev/null +++ b/src/main/java/pro/mikey/fabric/xray/tasks/AddChunkTask.java @@ -0,0 +1,84 @@ +package pro.mikey.fabric.xray.tasks; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.LavaFluid; +import org.jetbrains.annotations.Nullable; +import pro.mikey.fabric.xray.cache.BlockSearchEntry; +import pro.mikey.fabric.xray.records.BasicColor; +import pro.mikey.fabric.xray.records.BlockPosWithColor; +import pro.mikey.fabric.xray.render.RenderOutlines; +import pro.mikey.fabric.xray.storage.BlockStore; +import pro.mikey.fabric.xray.storage.SettingsStore; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * This task is responsible for taking a chunk and adding the blocks to the RenderOutlines to be rendered. + * This task is added to the threadpool and executed by a thread via the Scancontroller class. + */ +public class AddChunkTask implements Runnable { + + private ChunkPos chunkPos; + + public AddChunkTask(ChunkPos chunkPos){ + this.chunkPos = chunkPos; + } + @Override + public void run() { + Thread.currentThread().setPriority(1); + List toAdd = AddChunk(chunkPos); + if(Minecraft.getInstance().player.clientLevel.getChunkSource().getChunk(chunkPos.x,chunkPos.z,false)!=null) { + RenderOutlines.addChunk(chunkPos.toLong(),toAdd); + } + else{ + RenderOutlines.removeChunk(chunkPos.toLong()); + } + } + + public static List AddChunk(ChunkPos chunkPos){ + int chunkStartX = chunkPos.x*16; + int chunkStartZ = chunkPos.z*16; + final Level world = Minecraft.getInstance().level; + Set blocks = BlockStore.getInstance().getCache().get(); + int height = world.getHeight(); + List toAdd = new ArrayList<>(); + for (int k = chunkStartX; k < chunkStartX + 16; k++) { + for (int l = chunkStartZ; l < chunkStartZ + 16; l++) { + for (int m = world.getMinBuildHeight(); m < height + (1 << 4); m++) { + BlockPos pos = new BlockPos(k, m, l); + BasicColor validBlock = isValidBlock(pos, world, blocks); + if (validBlock != null) { + toAdd.add(new BlockPosWithColor(pos, validBlock)); + } + } + } + } + return toAdd; + } + + @Nullable + public static BasicColor isValidBlock(BlockPos pos, Level world, Set blocks) { + BlockState state = world.getBlockState(pos); + if (state.isAir()) { + return null; + } + + if (SettingsStore.getInstance().get().isShowLava() && state.getFluidState().getType() instanceof LavaFluid) { + return new BasicColor(210, 10, 10); + } + + BlockState defaultState = state.getBlock().defaultBlockState(); + + return blocks.stream() + .filter(localState -> localState.isDefault() && defaultState == localState.getState() || !localState.isDefault() && state == localState.getState()) + .findFirst() + .map(BlockSearchEntry::getColor) + .orElse(null); + } +} diff --git a/src/main/java/pro/mikey/fabric/xray/tasks/ReBuildCache.java b/src/main/java/pro/mikey/fabric/xray/tasks/ReBuildCache.java new file mode 100644 index 0000000..8da5011 --- /dev/null +++ b/src/main/java/pro/mikey/fabric/xray/tasks/ReBuildCache.java @@ -0,0 +1,75 @@ +package pro.mikey.fabric.xray.tasks; + + +import net.minecraft.client.Minecraft; +import net.minecraft.core.Direction; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.phys.Vec3; +import pro.mikey.fabric.xray.ScanController; + +import java.util.ArrayList; +import java.util.List; + +/** + * This task is responsible for completely rebuilding all loaded chunks arround the player + * This task is added to the threadpool and executed by a thread via the Scancontroller class. + */ +public class ReBuildCache implements Runnable{ + public ReBuildCache(){ + } + private class ChunkObject{ + ChunkObject(ChunkPos pos,Direction direction){ + this.direction=direction; + this.pos=pos; + } + public ChunkPos pos; + public Direction direction; + } + + @Override + public void run() { + List toScan = new ArrayList<>(); + Vec3 position = Minecraft.getInstance().player.position(); + toScan.add(new ChunkObject(new ChunkPos((int)position.x/16,(int)position.z/16),Direction.UP)); + toScan.add(new ChunkObject(new ChunkPos((int)position.x/16,(int)position.z/16+1),Direction.EAST)); + toScan.add(new ChunkObject(new ChunkPos((int)position.x/16,(int)position.z/16-1),Direction.WEST)); + toScan.add(new ChunkObject(new ChunkPos((int)position.x/16+1,(int)position.z/16),Direction.NORTH)); + toScan.add(new ChunkObject(new ChunkPos((int)position.x/16-1,(int)position.z/16),Direction.SOUTH)); + while (toScan.size()>0){ + ChunkObject chunkObject = toScan.remove(0); + if(Minecraft.getInstance().player.clientLevel.getChunkSource().getChunk(chunkObject.pos.x,chunkObject.pos.z,false)!=null){ + ScanController.updateChunk(chunkObject.pos); + switch (chunkObject.direction){ + case EAST -> { + if(chunkObject.pos.x==(int)position.x/16){ + toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x,chunkObject.pos.z+1),chunkObject.direction)); + } + toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x+1,chunkObject.pos.z),chunkObject.direction)); + break; + } + case WEST -> { + if(chunkObject.pos.x==(int)position.x/16){ + toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x,chunkObject.pos.z-1),chunkObject.direction)); + } + toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x-1,chunkObject.pos.z),chunkObject.direction)); + break; + } + case NORTH -> { + if(chunkObject.pos.z==(int)position.z/16){ + toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x+1,chunkObject.pos.z),chunkObject.direction)); + } + toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x,chunkObject.pos.z-1),chunkObject.direction)); + break; + } + case SOUTH -> { + toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x,chunkObject.pos.z+1),chunkObject.direction)); + if(chunkObject.pos.z==(int)position.z/16){ + toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x-1,chunkObject.pos.z),chunkObject.direction)); + } + break; + } + } + } + } + } +} diff --git a/src/main/java/pro/mikey/fabric/xray/tasks/RemoveChunkTask.java b/src/main/java/pro/mikey/fabric/xray/tasks/RemoveChunkTask.java new file mode 100644 index 0000000..519a2e5 --- /dev/null +++ b/src/main/java/pro/mikey/fabric/xray/tasks/RemoveChunkTask.java @@ -0,0 +1,22 @@ +package pro.mikey.fabric.xray.tasks; + +import net.minecraft.world.level.ChunkPos; +import pro.mikey.fabric.xray.render.RenderOutlines; + +/** + * This task is responsible for completely removing a chunk + * This task is added to the threadpool and executed by a thread via the Scancontroller class. + */ +public class RemoveChunkTask implements Runnable { + private ChunkPos chunkPos; + + public RemoveChunkTask(ChunkPos chunkPos){ + this.chunkPos = chunkPos; + } + + @Override + public void run() { + Thread.currentThread().setPriority(1); + RenderOutlines.removeChunk(chunkPos.toLong()); + } +} diff --git a/src/main/java/pro/mikey/fabric/xray/tasks/UpdateChunkTask.java b/src/main/java/pro/mikey/fabric/xray/tasks/UpdateChunkTask.java new file mode 100644 index 0000000..eda99a8 --- /dev/null +++ b/src/main/java/pro/mikey/fabric/xray/tasks/UpdateChunkTask.java @@ -0,0 +1,34 @@ +package pro.mikey.fabric.xray.tasks; + +import net.minecraft.client.Minecraft; +import net.minecraft.world.level.ChunkPos; +import pro.mikey.fabric.xray.records.BlockPosWithColor; +import pro.mikey.fabric.xray.render.RenderOutlines; + +import java.util.List; + +/** + * This task is responsible for taking a chunk and updating the blocks to the RenderOutlines to be rendered. + * In its current implementation in the RenderOutlines class this does virtually the same as AddChunk + * This task is added to the threadpool and executed by a thread via the Scancontroller class. + */ +public class UpdateChunkTask implements Runnable{ + private ChunkPos chunkPos; + + public UpdateChunkTask(ChunkPos chunkPos){ + this.chunkPos = chunkPos; + } + + @Override + public void run() { + Thread.currentThread().setPriority(1); + List toAdd = AddChunkTask.AddChunk(chunkPos); + if(Minecraft.getInstance().player.clientLevel.getChunkSource().getChunk(chunkPos.x,chunkPos.z,false)!=null) { + RenderOutlines.addChunk(chunkPos.toLong(),toAdd); + } + else{ + RenderOutlines.removeChunk(chunkPos.toLong()); + } + } + +} diff --git a/src/main/resources/assets/advanced-xray-fabric/lang/en_us.json b/src/main/resources/assets/advanced-xray-fabric/lang/en_us.json index b3ecb63..679d93f 100644 --- a/src/main/resources/assets/advanced-xray-fabric/lang/en_us.json +++ b/src/main/resources/assets/advanced-xray-fabric/lang/en_us.json @@ -22,7 +22,7 @@ "xray.input.add": "Add Block", "xray.input.add_hand": "Add Block in hand", "xray.input.add_look": "Add Looking at", - "xray.input.distance": "Distance: %s", + "xray.input.distance": "Threads: %s", "xray.input.show-lava": "Show Lava: %s", "xray.input.toggle_oredict": "Use Dictionary", "xray.title.config": "Configure Block", @@ -47,7 +47,7 @@ "xray.tooltips.add_block_in_hand": "Automatically selects the block you've\ngot in your hand to add to the list.", "xray.tooltips.add_block_looking_at": "Automatically selects the block you're\nlooking at to add to the list.", "xray.tooltips.show_lava": "Displays lava in RED like a normal block.\nWatch out! It's hot.", - "xray.tooltips.distance": "Warning: Lag if you go over 128.", + "xray.tooltips.andistce": "Warning: Lag if you use too many threads.", "xray.tooltips.edit1": "Click to enable / disable", "xray.tooltips.edit2": "Hold shift and click to edit.", "xray.message.help.gui": "To edit a block simply shift click on the block you wish to edit.\nIf you want to enable / disable a block then click on a block\n and it'll toggle on and off.", From b2e0eda94d19c5c14457f46fe8f8c744cc565c68 Mon Sep 17 00:00:00 2001 From: MartinLaptop Date: Sun, 15 Jan 2023 20:31:14 +0100 Subject: [PATCH 02/14] crude basic Category Support --- .../fabric/xray/cache/BlockSearchCache.java | 2 +- .../mikey/fabric/xray/records/BlockEntry.java | 7 + .../forge/GuiBlockSelectionScreen.java | 282 ++++++++++++++++++ .../screens/forge/GuiSelectionScreen.java | 143 ++++----- .../mikey/fabric/xray/storage/BlockStore.java | 7 + .../mikey/fabric/xray/tasks/AddChunkTask.java | 4 - 6 files changed, 348 insertions(+), 97 deletions(-) create mode 100644 src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java diff --git a/src/main/java/pro/mikey/fabric/xray/cache/BlockSearchCache.java b/src/main/java/pro/mikey/fabric/xray/cache/BlockSearchCache.java index cba317a..765307b 100644 --- a/src/main/java/pro/mikey/fabric/xray/cache/BlockSearchCache.java +++ b/src/main/java/pro/mikey/fabric/xray/cache/BlockSearchCache.java @@ -24,7 +24,7 @@ public void processGroupedList(List blockEntries) { // Flatten the grouped list down to a single cacheable list this.cache = - blockEntries.stream() + blockEntries.stream().filter(group -> group.active()) .flatMap( e -> e.entries().stream() diff --git a/src/main/java/pro/mikey/fabric/xray/records/BlockEntry.java b/src/main/java/pro/mikey/fabric/xray/records/BlockEntry.java index deb3099..bf106d7 100644 --- a/src/main/java/pro/mikey/fabric/xray/records/BlockEntry.java +++ b/src/main/java/pro/mikey/fabric/xray/records/BlockEntry.java @@ -3,6 +3,9 @@ import com.google.gson.*; import net.minecraft.nbt.NbtUtils; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.AirBlock; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import pro.mikey.fabric.xray.cache.BlockSearchEntry; @@ -27,6 +30,10 @@ public BlockEntry(BlockState state, String name, BasicColor color, int order, bo this.active = active; } + public static BlockEntry getAir(){ + return new BlockEntry(Blocks.AIR.defaultBlockState(), "air",new BasicColor(0,0,0),0,true,false); + } + public BlockState getState() { return this.state; } diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java new file mode 100644 index 0000000..6510f1d --- /dev/null +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java @@ -0,0 +1,282 @@ +package pro.mikey.fabric.xray.screens.forge; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.platform.Lighting; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import pro.mikey.fabric.xray.ScanController; +import pro.mikey.fabric.xray.StateSettings; +import pro.mikey.fabric.xray.XRay; +import pro.mikey.fabric.xray.records.BasicColor; +import pro.mikey.fabric.xray.records.BlockEntry; +import pro.mikey.fabric.xray.records.BlockGroup; +import pro.mikey.fabric.xray.storage.BlockStore; +import pro.mikey.fabric.xray.storage.SettingsStore; + +import java.awt.*; +import java.util.List; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +public class GuiBlockSelectionScreen extends GuiBase { + private static final List ORE_TAGS = List.of(Blocks.GOLD_ORE, Blocks.IRON_ORE, Blocks.DIAMOND_ORE, Blocks.REDSTONE_ORE, Blocks.LAPIS_ORE, Blocks.COAL_ORE, Blocks.EMERALD_ORE, Blocks.COPPER_ORE, Blocks.DEEPSLATE_GOLD_ORE, Blocks.DEEPSLATE_IRON_ORE, Blocks.DEEPSLATE_DIAMOND_ORE, Blocks.DEEPSLATE_REDSTONE_ORE, Blocks.DEEPSLATE_LAPIS_ORE, Blocks.DEEPSLATE_COAL_ORE, Blocks.DEEPSLATE_EMERALD_ORE, Blocks.DEEPSLATE_COPPER_ORE, Blocks.NETHER_GOLD_ORE, Blocks.ANCIENT_DEBRIS); + + private static final ResourceLocation CIRCLE = new ResourceLocation(XRay.PREFIX_GUI + "circle.png"); + public ItemRenderer render; + private Button distButtons; + private EditBox search; + private String lastSearch = ""; + private List itemList; + private BlockGroup group; + private ScrollingBlockList scrollList; + + public GuiBlockSelectionScreen(BlockGroup group) { + super(true); + this.setSideTitle(I18n.get("xray.single.tools")); + + this.itemList = group.entries(); + } + + @Override + public void init() { + if (this.minecraft.player == null) { + return; + } + + this.render = this.itemRenderer; +// this.buttons.clear(); + + this.scrollList = new ScrollingBlockList((this.getWidth() / 2) - 37, this.getHeight() / 2 + 10, 203, 185, this.itemList, this); + this.addRenderableWidget(this.scrollList); + + this.search = new EditBox(this.getFontRender(), this.getWidth() / 2 - 137, this.getHeight() / 2 - 105, 202, 18, Component.empty()); + this.search.setCanLoseFocus(true); + + // sidebar buttons + this.addRenderableWidget(Button.builder( Component.translatable("xray.input.add"), button -> { + this.minecraft.player.clientSideCloseContainer(); + this.minecraft.setScreen(new GuiBlockList()); + }) + .pos((this.getWidth() / 2) + 79, this.getHeight() / 2 - 60) + .size( 120, 20) + .tooltip(Tooltip.create(Component.translatable("xray.tooltips.add_block"))) + .build()); + + this.addRenderableWidget(Button.builder(Component.translatable("xray.input.add_hand"), button -> { + this.minecraft.player.clientSideCloseContainer(); + ItemStack handItem = this.minecraft.player.getItemInHand(InteractionHand.MAIN_HAND); + + // Check if the hand item is a block or not + if (!(handItem.getItem() instanceof BlockItem)) { + this.minecraft.player.displayClientMessage(Component.literal("[XRay] " + I18n.get("xray.message.invalid_hand", handItem.getHoverName().getString())), false); + return; + } + + this.minecraft.setScreen(new GuiAddBlock(((BlockItem) handItem.getItem()).getBlock().defaultBlockState(), () -> new GuiBlockSelectionScreen(this.group))); + }) + .pos(this.getWidth() / 2 + 79, this.getHeight() / 2 - 38) + .size( 120, 20) + .tooltip(Tooltip.create(Component.translatable("xray.tooltips.add_block_in_hand"))) + .build()); + + this.addRenderableWidget(Button.builder(Component.translatable("xray.input.add_look"), button -> { + LocalPlayer player = this.minecraft.player; + if (this.minecraft.level == null || player == null) { + return; + } + + this.onClose(); + try { + HitResult look = player.pick(100, 1f, false); + + if (look.getType() == BlockHitResult.Type.BLOCK) { + BlockState state = this.minecraft.level.getBlockState(((BlockHitResult) look).getBlockPos()); + + player.clientSideCloseContainer(); + this.minecraft.setScreen(new GuiAddBlock(state, () -> new GuiBlockSelectionScreen(this.group))); + } else { + player.displayClientMessage(Component.literal("[XRay] " + I18n.get("xray.message.nothing_infront")), false); + } + } catch (NullPointerException ex) { + player.displayClientMessage(Component.literal("[XRay] " + I18n.get("xray.message.thats_odd")), false); + } + }) + .pos(this.getWidth() / 2 + 79, this.getHeight() / 2 - 16) + .size(120, 20) + .tooltip(Tooltip.create(Component.translatable("xray.tooltips.add_block_looking_at"))) + .build()); + + this.addRenderableWidget(new Button.Builder( Component.translatable("xray.single.help"), button -> { + this.minecraft.player.clientSideCloseContainer(); + this.minecraft.setScreen(new GuiHelp()); + }).pos(this.getWidth() / 2 + 79, this.getHeight() / 2 + 58).size(60,20).build()); + this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.close"), button -> this.onClose()).pos((this.getWidth() / 2 + 79) + 62, this.getHeight() / 2 + 58).size(59,20).build()); + } + + private void updateSearch() { + if (this.lastSearch.equals(this.search.getValue())) { + return; + } + + if (this.search.getValue().equals("")) { + this.itemList = group.entries(); + this.scrollList.updateEntries(this.itemList); + this.lastSearch = ""; + return; + } + + this.itemList = this.group.entries().stream().filter(b -> b.getName().toLowerCase().contains(this.search.getValue().toLowerCase())).collect(Collectors.toCollection(ArrayList::new)); + + this.itemList.sort(Comparator.comparingInt(BlockEntry::getOrder)); + + this.scrollList.updateEntries(this.itemList); + this.lastSearch = this.search.getValue(); + } + + @Override + public void tick() { + super.tick(); + this.search.tick(); + + this.updateSearch(); + } + + @Override + public boolean mouseClicked(double x, double y, int mouse) { + if (this.search.mouseClicked(x, y, mouse)) { + this.setFocused(this.search); + } + + return super.mouseClicked(x, y, mouse); + } + + @Override + public void renderExtra(PoseStack stack, int x, int y, float partialTicks) { + this.search.render(stack, x, y, partialTicks); + this.scrollList.render(stack, x, y, partialTicks); + + if (!this.search.isFocused() && this.search.getValue().equals("")) { + this.minecraft.font.drawShadow(stack, I18n.get("xray.single.search"), (float) this.getWidth() / 2 - 130, (float) this.getHeight() / 2 - 101, Color.GRAY.getRGB()); + } + } + + @Override + public void onClose() { + SettingsStore.getInstance().write(); + BlockStore.getInstance().write(); + BlockStore.getInstance().updateCache(); + ScanController.RebuildCache(); + super.onClose(); + } + + public static class ScrollingBlockList extends ScrollingList { + static final int SLOT_HEIGHT = 35; + GuiBlockSelectionScreen parent; + + ScrollingBlockList(int x, int y, int width, int height, List blocks, GuiBlockSelectionScreen parent) { + super(x, y, width, height, SLOT_HEIGHT); + this.updateEntries(blocks); + this.parent = parent; + } + + void setSelected(BlockSlot entry, int mouse) { + if (entry == null) { + return; + } + + if (GuiBlockSelectionScreen.hasShiftDown()) { + this.minecraft.player.clientSideCloseContainer(); + this.minecraft.setScreen(new GuiEdit(entry.block)); + return; + } + + try { + BlockGroup group = BlockStore.getInstance().getByName(this.parent.group.name()); + int index = group.entries().indexOf(entry.getBlock()); + BlockEntry blockEntry = group.entries().get(index); + blockEntry.setActive(!blockEntry.isActive()); + group.entries().set(index, blockEntry); + BlockStore.getInstance().write(); + BlockStore.getInstance().updateCache(); + } catch (Exception ignored) { + } + } + + void updateEntries(List blocks) { + this.clearEntries(); + blocks.forEach(block -> this.addEntry(new BlockSlot(block, this))); // @mcp: func_230513_b_ = addEntry + } + + @Override + public Optional getChildAt(double mouseX, double mouseY) { + return Optional.empty(); + } + + public class BlockSlot extends Entry { + BlockEntry block; + ScrollingBlockList parent; + + BlockSlot(BlockEntry block, ScrollingBlockList parent) { + this.block = block; + this.parent = parent; + } + + public BlockEntry getBlock() { + return this.block; + } + + @Override + public void render(PoseStack stack, int entryIdx, int top, int left, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean p_194999_5_, float partialTicks) { + BlockEntry blockData = this.block; + + Font font = this.parent.minecraft.font; + + font.drawShadow(stack, blockData.getName(), left + 35, top + 7, 0xFFFFFF); + font.drawShadow(stack, blockData.isActive() ? "Enabled" : "Disabled", left + 35, top + 17, blockData.isActive() ? Color.GREEN.getRGB() : Color.RED.getRGB()); + + Lighting.setupFor3DItems(); + this.parent.minecraft.getItemRenderer().renderAndDecorateItem(blockData.getStack(), left + 10, top + 7); + Lighting.setupForFlatItems(); + + if (mouseX > left && mouseX < (left + entryWidth) && mouseY > top && mouseY < (top + entryHeight) && mouseY < (this.parent.y0 + this.parent.height) && mouseY > this.parent.y0) { + this.parent.parent.renderTooltip(stack, Arrays.asList(Component.translatable("xray.tooltips.edit1").getVisualOrderText(), Component.translatable("xray.tooltips.edit2").getVisualOrderText()), left + 15, (entryIdx == this.parent.children().size() - 1 && entryIdx != 0 ? (top - (entryHeight - 20)) : (top + (entryHeight + 15)))); + } + + RenderSystem.enableBlend(); + RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + RenderSystem.setShaderTexture(0, GuiBlockSelectionScreen.CIRCLE); + RenderSystem.setShaderColor(0, 0, 0, .5f); + blit(stack, (left + entryWidth) - 32, (int) (top + (entryHeight / 2f) - 9), 0, 0, 14, 14, 14, 14); + RenderSystem.setShaderColor(blockData.getHex().red() / 255f, blockData.getHex().green() / 255f, blockData.getHex().blue() / 255f, 1); + blit(stack, (left + entryWidth) - 30, (int) (top + (entryHeight / 2f) - 7), 0, 0, 10, 10, 10, 10); + RenderSystem.disableBlend(); + RenderSystem.setShaderColor(1f, 1f, 1f, 1f); + } + + @Override + public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int mouse) { + this.parent.setSelected(this, mouse); + return false; + } + } + } +} diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java index 1a4b27b..055811b 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java @@ -40,15 +40,18 @@ public class GuiSelectionScreen extends GuiBase { private static final List ORE_TAGS = List.of(Blocks.GOLD_ORE, Blocks.IRON_ORE, Blocks.DIAMOND_ORE, Blocks.REDSTONE_ORE, Blocks.LAPIS_ORE, Blocks.COAL_ORE, Blocks.EMERALD_ORE, Blocks.COPPER_ORE, Blocks.DEEPSLATE_GOLD_ORE, Blocks.DEEPSLATE_IRON_ORE, Blocks.DEEPSLATE_DIAMOND_ORE, Blocks.DEEPSLATE_REDSTONE_ORE, Blocks.DEEPSLATE_LAPIS_ORE, Blocks.DEEPSLATE_COAL_ORE, Blocks.DEEPSLATE_EMERALD_ORE, Blocks.DEEPSLATE_COPPER_ORE, Blocks.NETHER_GOLD_ORE, Blocks.ANCIENT_DEBRIS); + private static final List TAGS_STORAGE = List.of(Blocks.CHEST, Blocks.TRAPPED_CHEST, Blocks.ENDER_CHEST); + private static final List PLAYER_TAGS_INTEREST = List.of(Blocks.CRAFTING_TABLE, Blocks.ANVIL, Blocks.CHIPPED_ANVIL, Blocks.DAMAGED_ANVIL); + private static final List LAVA_TAGS = List.of(Blocks.LAVA); private static final ResourceLocation CIRCLE = new ResourceLocation(XRay.PREFIX_GUI + "circle.png"); - private final List originalList; + private final List originalList; public ItemRenderer render; private Button distButtons; private EditBox search; private String lastSearch = ""; - private List itemList; - private ScrollingBlockList scrollList; + private List itemList; + private ScrollingCategoryList scrollList; public GuiSelectionScreen() { super(true); @@ -56,8 +59,7 @@ public GuiSelectionScreen() { populateDefault(); - this.itemList = BlockStore.getInstance().get().size() >= 1 ? BlockStore.getInstance().get().get(0).entries() : new ArrayList<>(); - this.itemList.sort(Comparator.comparingInt(BlockEntry::getOrder)); + this.itemList = BlockStore.getInstance().get().size() >= 1 ? BlockStore.getInstance().get() : new ArrayList<>(); this.originalList = this.itemList; } @@ -67,8 +69,28 @@ private void populateDefault() { AtomicInteger order = new AtomicInteger(); Random random = new Random(); - BlockStore.getInstance().get().add(new BlockGroup("default", ORE_TAGS.stream().map(e -> - new BlockEntry(e.defaultBlockState(), e.asItem().getDescription().getString(), new BasicColor(random.nextInt(255), random.nextInt(255), random.nextInt(255)), order.getAndIncrement(), true, true)).collect(Collectors.toList()), 0, true) + + //Ores + BlockGroup ores = new BlockGroup("Ores", ORE_TAGS.stream().map(e -> + new BlockEntry(e.defaultBlockState(), e.asItem().getDescription().getString(), new BasicColor(random.nextInt(255), random.nextInt(255), random.nextInt(255)), order.getAndIncrement(), true, true)).collect(Collectors.toList()), 0, true); + BlockStore.getInstance().get().add(ores); + + //Storage + order.set(0); + BlockGroup storage = new BlockGroup("Storage", TAGS_STORAGE.stream().map(e -> + new BlockEntry(e.defaultBlockState(), e.asItem().getDescription().getString(), new BasicColor(random.nextInt(255), random.nextInt(255), random.nextInt(255)), order.getAndIncrement(), true, true)).collect(Collectors.toList()), 0, true); + Block echest = Blocks.ENDER_CHEST; + storage.entries().add(new BlockEntry(echest.defaultBlockState(), echest.asItem().getDescription().getString(), new BasicColor(200,30,200), order.getAndIncrement(), true, true)); + BlockStore.getInstance().get().add(storage); + + //Lava + BlockStore.getInstance().get().add(new BlockGroup("Lava", LAVA_TAGS.stream().map(e -> + new BlockEntry(e.defaultBlockState(), e.asItem().getDescription().getString(), new BasicColor(210,30,30), order.getAndIncrement(), true, true)).collect(Collectors.toList()), 0, false) + ); + //Player / Interest + order.set(0); + BlockStore.getInstance().get().add(new BlockGroup("Player / Interest", PLAYER_TAGS_INTEREST.stream().map(e -> + new BlockEntry(e.defaultBlockState(), e.asItem().getDescription().getString(), new BasicColor(30,30,210), order.getAndIncrement(), true, true)).collect(Collectors.toList()), 0, false) ); BlockStore.getInstance().updateCache(); @@ -84,75 +106,12 @@ public void init() { this.render = this.itemRenderer; // this.buttons.clear(); - this.scrollList = new ScrollingBlockList((this.getWidth() / 2) - 37, this.getHeight() / 2 + 10, 203, 185, this.itemList, this); + this.scrollList = new ScrollingCategoryList((this.getWidth() / 2) - 37, this.getHeight() / 2 + 10, 203, 185, this.itemList, this); this.addRenderableWidget(this.scrollList); this.search = new EditBox(this.getFontRender(), this.getWidth() / 2 - 137, this.getHeight() / 2 - 105, 202, 18, Component.empty()); this.search.setCanLoseFocus(true); - // sidebar buttons - this.addRenderableWidget(Button.builder( Component.translatable("xray.input.add"), button -> { - this.minecraft.player.clientSideCloseContainer(); - this.minecraft.setScreen(new GuiBlockList()); - }) - .pos((this.getWidth() / 2) + 79, this.getHeight() / 2 - 60) - .size( 120, 20) - .tooltip(Tooltip.create(Component.translatable("xray.tooltips.add_block"))) - .build()); - - this.addRenderableWidget(Button.builder(Component.translatable("xray.input.add_hand"), button -> { - this.minecraft.player.clientSideCloseContainer(); - ItemStack handItem = this.minecraft.player.getItemInHand(InteractionHand.MAIN_HAND); - - // Check if the hand item is a block or not - if (!(handItem.getItem() instanceof BlockItem)) { - this.minecraft.player.displayClientMessage(Component.literal("[XRay] " + I18n.get("xray.message.invalid_hand", handItem.getHoverName().getString())), false); - return; - } - - this.minecraft.setScreen(new GuiAddBlock(((BlockItem) handItem.getItem()).getBlock().defaultBlockState(), GuiSelectionScreen::new)); - }) - .pos(this.getWidth() / 2 + 79, this.getHeight() / 2 - 38) - .size( 120, 20) - .tooltip(Tooltip.create(Component.translatable("xray.tooltips.add_block_in_hand"))) - .build()); - - this.addRenderableWidget(Button.builder(Component.translatable("xray.input.add_look"), button -> { - LocalPlayer player = this.minecraft.player; - if (this.minecraft.level == null || player == null) { - return; - } - - this.onClose(); - try { - HitResult look = player.pick(100, 1f, false); - - if (look.getType() == BlockHitResult.Type.BLOCK) { - BlockState state = this.minecraft.level.getBlockState(((BlockHitResult) look).getBlockPos()); - - player.clientSideCloseContainer(); - this.minecraft.setScreen(new GuiAddBlock(state, GuiSelectionScreen::new)); - } else { - player.displayClientMessage(Component.literal("[XRay] " + I18n.get("xray.message.nothing_infront")), false); - } - } catch (NullPointerException ex) { - player.displayClientMessage(Component.literal("[XRay] " + I18n.get("xray.message.thats_odd")), false); - } - }) - .pos(this.getWidth() / 2 + 79, this.getHeight() / 2 - 16) - .size(120, 20) - .tooltip(Tooltip.create(Component.translatable("xray.tooltips.add_block_looking_at"))) - .build()); - - this.addRenderableWidget(this.distButtons = Button.builder(Component.translatable("xray.input.show-lava", SettingsStore.getInstance().get().isShowLava()), button -> { - SettingsStore.getInstance().get().setShowLava(!SettingsStore.getInstance().get().isShowLava()); - button.setMessage(Component.translatable("xray.input.show-lava", SettingsStore.getInstance().get().isShowLava())); - }) - .pos((this.getWidth() / 2) + 79, this.getHeight() / 2 + 6) - .size(120, 20) - .tooltip(Tooltip.create(Component.translatable("xray.tooltips.show_lava"))) - .build()); - this.addRenderableWidget(this.distButtons = Button.builder(Component.translatable("xray.input.distance", StateSettings.getVisualRadius()), button -> { SettingsStore.getInstance().get().increaseRange(); button.setMessage(Component.translatable("xray.input.distance", StateSettings.getVisualRadius())); @@ -183,7 +142,7 @@ private void updateSearch() { this.itemList = this.originalList.stream().filter(b -> b.getName().toLowerCase().contains(this.search.getValue().toLowerCase())).collect(Collectors.toCollection(ArrayList::new)); - this.itemList.sort(Comparator.comparingInt(BlockEntry::getOrder)); + this.itemList.sort(Comparator.comparingInt(BlockGroup::getOrder)); this.scrollList.updateEntries(this.itemList); this.lastSearch = this.search.getValue(); @@ -232,41 +191,40 @@ public void onClose() { super.onClose(); } - public static class ScrollingBlockList extends ScrollingList { + public static class ScrollingCategoryList extends ScrollingList { static final int SLOT_HEIGHT = 35; GuiSelectionScreen parent; - ScrollingBlockList(int x, int y, int width, int height, List blocks, GuiSelectionScreen parent) { + ScrollingCategoryList(int x, int y, int width, int height, List blocks, GuiSelectionScreen parent) { super(x, y, width, height, SLOT_HEIGHT); this.updateEntries(blocks); this.parent = parent; } - void setSelected(BlockSlot entry, int mouse) { + void setSelected(CategoryEntry entry, int mouse) { if (entry == null) { return; } if (GuiSelectionScreen.hasShiftDown()) { this.minecraft.player.clientSideCloseContainer(); - this.minecraft.setScreen(new GuiEdit(entry.block)); + this.minecraft.setScreen(new GuiBlockSelectionScreen(entry.getGroup())); return; } try { - int index = BlockStore.getInstance().get().get(0).entries().indexOf(entry.getBlock()); - BlockEntry blockEntry = BlockStore.getInstance().get().get(0).entries().get(index); - blockEntry.setActive(!blockEntry.isActive()); - BlockStore.getInstance().get().get(0).entries().set(index, blockEntry); + BlockStore.getInstance().get().stream().filter(group -> (group.getName().equals(entry.block.name()))).findFirst().ifPresent(group -> { + group.setActive(!group.active()); + }); BlockStore.getInstance().write(); BlockStore.getInstance().updateCache(); } catch (Exception ignored) { } } - void updateEntries(List blocks) { + void updateEntries(List blocks) { this.clearEntries(); - blocks.forEach(block -> this.addEntry(new BlockSlot(block, this))); // @mcp: func_230513_b_ = addEntry + blocks.forEach(group -> this.addEntry(new CategoryEntry(group, this))); // @mcp: func_230513_b_ = addEntry } @Override @@ -274,30 +232,31 @@ public Optional getChildAt(double mouseX, double mouseY) { return Optional.empty(); } - public class BlockSlot extends AbstractSelectionList.Entry { - BlockEntry block; - ScrollingBlockList parent; + public class CategoryEntry extends AbstractSelectionList.Entry { + BlockGroup block; + ScrollingCategoryList parent; - BlockSlot(BlockEntry block, ScrollingBlockList parent) { + CategoryEntry(BlockGroup block, ScrollingCategoryList parent) { this.block = block; this.parent = parent; } - public BlockEntry getBlock() { + public BlockGroup getGroup() { return this.block; } @Override public void render(PoseStack stack, int entryIdx, int top, int left, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean p_194999_5_, float partialTicks) { - BlockEntry blockData = this.block; + BlockGroup group = this.block; + BlockEntry display = group.entries().stream().findFirst().orElse(BlockEntry.getAir()); Font font = this.parent.minecraft.font; - font.drawShadow(stack, blockData.getName(), left + 35, top + 7, 0xFFFFFF); - font.drawShadow(stack, blockData.isActive() ? "Enabled" : "Disabled", left + 35, top + 17, blockData.isActive() ? Color.GREEN.getRGB() : Color.RED.getRGB()); + font.drawShadow(stack, group.getName(), left + 35, top + 7, 0xFFFFFF); + font.drawShadow(stack, group.isActive() ? "Enabled" : "Disabled", left + 35, top + 17, group.isActive() ? Color.GREEN.getRGB() : Color.RED.getRGB()); Lighting.setupFor3DItems(); - this.parent.minecraft.getItemRenderer().renderAndDecorateItem(blockData.getStack(), left + 10, top + 7); + this.parent.minecraft.getItemRenderer().renderAndDecorateItem(display.getStack(), left + 10, top + 7); Lighting.setupForFlatItems(); if (mouseX > left && mouseX < (left + entryWidth) && mouseY > top && mouseY < (top + entryHeight) && mouseY < (this.parent.y0 + this.parent.height) && mouseY > this.parent.y0) { @@ -309,7 +268,7 @@ public void render(PoseStack stack, int entryIdx, int top, int left, int entryWi RenderSystem.setShaderTexture(0, GuiSelectionScreen.CIRCLE); RenderSystem.setShaderColor(0, 0, 0, .5f); blit(stack, (left + entryWidth) - 32, (int) (top + (entryHeight / 2f) - 9), 0, 0, 14, 14, 14, 14); - RenderSystem.setShaderColor(blockData.getHex().red() / 255f, blockData.getHex().green() / 255f, blockData.getHex().blue() / 255f, 1); + RenderSystem.setShaderColor(display.getHex().red() / 255f, display.getHex().green() / 255f, display.getHex().blue() / 255f, 1); blit(stack, (left + entryWidth) - 30, (int) (top + (entryHeight / 2f) - 7), 0, 0, 10, 10, 10, 10); RenderSystem.disableBlend(); RenderSystem.setShaderColor(1f, 1f, 1f, 1f); diff --git a/src/main/java/pro/mikey/fabric/xray/storage/BlockStore.java b/src/main/java/pro/mikey/fabric/xray/storage/BlockStore.java index febfadc..76d627e 100644 --- a/src/main/java/pro/mikey/fabric/xray/storage/BlockStore.java +++ b/src/main/java/pro/mikey/fabric/xray/storage/BlockStore.java @@ -3,6 +3,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; +import org.jetbrains.annotations.Nullable; import pro.mikey.fabric.xray.cache.BlockSearchCache; import pro.mikey.fabric.xray.records.BlockEntry; import pro.mikey.fabric.xray.records.BlockGroup; @@ -31,6 +32,7 @@ public static BlockStore getInstance() { return instance; } + public void updateCache() { this.updateCache(this.get()); } @@ -48,6 +50,11 @@ public List get() { return this.blockEntries; } + @Nullable + public BlockGroup getByName(String name) { + return BlockStore.getInstance().get().stream().filter(group -> (group.getName().equals(name))).findFirst().orElse(null); + } + @Override public Gson getGson() { return new GsonBuilder() diff --git a/src/main/java/pro/mikey/fabric/xray/tasks/AddChunkTask.java b/src/main/java/pro/mikey/fabric/xray/tasks/AddChunkTask.java index c95ce68..2f9c6f9 100644 --- a/src/main/java/pro/mikey/fabric/xray/tasks/AddChunkTask.java +++ b/src/main/java/pro/mikey/fabric/xray/tasks/AddChunkTask.java @@ -69,10 +69,6 @@ public static BasicColor isValidBlock(BlockPos pos, Level world, Set Date: Mon, 16 Jan 2023 02:24:38 +0100 Subject: [PATCH 03/14] Add and edit Buttons for Groups --- .../mikey/fabric/xray/records/BlockGroup.java | 53 ++++++-- .../fabric/xray/screens/forge/GuiBase.java | 1 - .../forge/GuiBlockSelectionScreen.java | 32 ++--- .../xray/screens/forge/GuiCategoryEdit.java | 114 ++++++++++++++++++ .../screens/forge/GuiSelectionScreen.java | 22 +++- .../advanced-xray-fabric/lang/en_us.json | 2 + 6 files changed, 185 insertions(+), 39 deletions(-) create mode 100644 src/main/java/pro/mikey/fabric/xray/screens/forge/GuiCategoryEdit.java diff --git a/src/main/java/pro/mikey/fabric/xray/records/BlockGroup.java b/src/main/java/pro/mikey/fabric/xray/records/BlockGroup.java index b2496a8..2b0bc36 100644 --- a/src/main/java/pro/mikey/fabric/xray/records/BlockGroup.java +++ b/src/main/java/pro/mikey/fabric/xray/records/BlockGroup.java @@ -1,5 +1,9 @@ package pro.mikey.fabric.xray.records; +import net.minecraft.world.level.block.Block; +import pro.mikey.fabric.xray.storage.BlockStore; + +import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -8,20 +12,52 @@ public final class BlockGroup { private List entries; private int order; private boolean active; + private BasicColor color; + + public BlockGroup(String name, List entries, int order, boolean active) { + this.name = name; + this.entries = entries; + this.order = order; + this.active = active; + this.color = new BasicColor(0,0,0); + } - public BlockGroup( - String name, - List entries, - int order, - boolean active - ) { + public BlockGroup(String name, List entries, int order, boolean active, BasicColor color) { this.name = name; this.entries = entries; this.order = order; this.active = active; + this.color=color; + } + + public BasicColor getColor(){ + if(color==null){ + color=new BasicColor(0,0,0); + } + return color; + } + + public void setColor(BasicColor color){ + this.color = color; + } + + public void save(){ + if(!BlockStore.getInstance().get().contains(this)){ + BlockStore.getInstance().get().add(this); + } + BlockStore.getInstance().write(); + BlockStore.getInstance().updateCache(); + } + + public BlockEntry getFirst(){ + if(entries==null){ + entries = new ArrayList<>(); + } + return entries.stream().findFirst().orElse(BlockEntry.getAir()); } public String name() { + if(name==null) return ""; return name; } @@ -91,7 +127,10 @@ public String toString() { "name=" + name + ", " + "entries=" + entries + ", " + "order=" + order + ", " + - "active=" + active + ']'; + "active=" + active + ", "+ + "color="+color+ + ']'; + } } diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBase.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBase.java index 280c4fa..5ef1bba 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBase.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBase.java @@ -106,7 +106,6 @@ public void render(PoseStack stack, int x, int y, float partialTicks) { ); } } - this.renderExtra(stack, x, y, partialTicks); super.render(stack, x, y, partialTicks); } diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java index 6510f1d..8b476c1 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java @@ -52,7 +52,7 @@ public class GuiBlockSelectionScreen extends GuiBase { public GuiBlockSelectionScreen(BlockGroup group) { super(true); this.setSideTitle(I18n.get("xray.single.tools")); - + this.group=group; this.itemList = group.entries(); } @@ -98,31 +98,13 @@ public void init() { .tooltip(Tooltip.create(Component.translatable("xray.tooltips.add_block_in_hand"))) .build()); - this.addRenderableWidget(Button.builder(Component.translatable("xray.input.add_look"), button -> { - LocalPlayer player = this.minecraft.player; - if (this.minecraft.level == null || player == null) { - return; - } - - this.onClose(); - try { - HitResult look = player.pick(100, 1f, false); - - if (look.getType() == BlockHitResult.Type.BLOCK) { - BlockState state = this.minecraft.level.getBlockState(((BlockHitResult) look).getBlockPos()); - - player.clientSideCloseContainer(); - this.minecraft.setScreen(new GuiAddBlock(state, () -> new GuiBlockSelectionScreen(this.group))); - } else { - player.displayClientMessage(Component.literal("[XRay] " + I18n.get("xray.message.nothing_infront")), false); - } - } catch (NullPointerException ex) { - player.displayClientMessage(Component.literal("[XRay] " + I18n.get("xray.message.thats_odd")), false); - } + this.addRenderableWidget(Button.builder( Component.translatable("xray.single.group.edit"), button -> { + this.minecraft.player.clientSideCloseContainer(); + this.minecraft.setScreen(new GuiCategoryEdit(this.group)); }) - .pos(this.getWidth() / 2 + 79, this.getHeight() / 2 - 16) - .size(120, 20) - .tooltip(Tooltip.create(Component.translatable("xray.tooltips.add_block_looking_at"))) + .pos((this.getWidth() / 2) + 79, this.getHeight() / 2 + 36) + .size( 120, 20) + .tooltip(Tooltip.create(Component.translatable("xray.tooltips.add_block"))) .build()); this.addRenderableWidget(new Button.Builder( Component.translatable("xray.single.help"), button -> { diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiCategoryEdit.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiCategoryEdit.java new file mode 100644 index 0000000..29631be --- /dev/null +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiCategoryEdit.java @@ -0,0 +1,114 @@ +package pro.mikey.fabric.xray.screens.forge; + +import com.mojang.blaze3d.platform.Lighting; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.network.chat.Component; +import pro.mikey.fabric.xray.records.BasicColor; +import pro.mikey.fabric.xray.records.BlockEntry; +import pro.mikey.fabric.xray.records.BlockGroup; +import pro.mikey.fabric.xray.storage.BlockStore; + +public class GuiCategoryEdit extends GuiBase { + private final BlockGroup group; + private RatioSliderWidget redSlider; + private RatioSliderWidget greenSlider; + private RatioSliderWidget blueSlider; + private EditBox groupName; + + GuiCategoryEdit(BlockGroup block) { + super(true); // Has a sidebar + this.setSideTitle(I18n.get("xray.single.tools")); + + this.group = block; + } + + @Override + public void init() { + + this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.delete"), b -> { + try { + BlockStore.getInstance().get().remove(group); + BlockStore.getInstance().write(); + BlockStore.getInstance().updateCache(); + } catch (Exception e) { + } + this.getMinecraft().setScreen(new GuiSelectionScreen()); + }).pos((this.getWidth() / 2) + 78, this.getHeight() / 2 - 60).size(120, 20).build()); + + this.addRenderableWidget(new Button.Builder( Component.translatable("xray.single.cancel"), b -> { + this.getMinecraft().setScreen(new GuiSelectionScreen()); + }).pos((this.getWidth() / 2) + 78, this.getHeight() / 2 + 58).size(120, 20).build()); + + this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.save"), b -> { + group.setName(groupName.getValue()); + BasicColor color = new BasicColor((int) (this.redSlider.getValue() * 255), (int) (this.greenSlider.getValue() * 255), (int) (this.blueSlider.getValue() * 255)); + group.setColor(color); + group.save(); + + this.getMinecraft().setScreen(new GuiSelectionScreen()); + }).pos(this.getWidth() / 2 - 138, this.getHeight() / 2 + 83).size(202, 20).build()); + + this.addRenderableWidget(this.redSlider = new RatioSliderWidget(this.getWidth() / 2 - 138, this.getHeight() / 2 - 40, 100, 20, Component.translatable("xray.color.red"), 0)); + this.addRenderableWidget(this.greenSlider = new RatioSliderWidget(this.getWidth() / 2 - 138, this.getHeight() / 2 - 18, 100, 20, Component.translatable("xray.color.green"), 0)); + this.addRenderableWidget(this.blueSlider = new RatioSliderWidget(this.getWidth() / 2 - 138, this.getHeight() / 2 + 4, 100, 20, Component.translatable("xray.color.blue"), 0)); + + + this.groupName = new EditBox(this.getMinecraft().font, this.getWidth() / 2 - 138, this.getHeight() / 2 - 63, 202, 20, Component.empty()); + this.groupName.setValue(this.group.getName()); + this.addRenderableWidget(this.groupName); + this.redSlider.setValue(this.group.getColor().red() / 255f); + this.greenSlider.setValue(this.group.getColor().green() / 255f); + this.blueSlider.setValue(this.group.getColor().blue() / 255f); + } + + @Override + public void tick() { + super.tick(); + this.groupName.tick(); + } + + @Override + public void renderExtra(PoseStack stack, int x, int y, float partialTicks) { + this.getFontRender().drawShadow(stack, this.group.getName(), this.getWidth() / 2f - 138, this.getHeight() / 2f - 90, 0xffffff); + + this.groupName.render(stack, x, y, partialTicks); + + int color = (255 << 24) | ((int) (this.redSlider.getValue() * 255) << 16) | ((int) (this.greenSlider.getValue() * 255) << 8) | (int) (this.blueSlider.getValue() * 255); + + fill(stack, this.getWidth() / 2 - 35, this.getHeight() / 2 - 40, (this.getWidth() / 2 - 35) + 100, (this.getHeight() / 2 - 40) + 64, color); + + this.getFontRender().drawShadow(stack, "Color", this.getWidth() / 2f - 30, this.getHeight() / 2f - 35, 0xffffff); + Lighting.setupFor3DItems(); + if(!this.group.getFirst().getStack().getItem().equals(BlockEntry.getAir().getStack().getItem())){ + this.itemRenderer.renderAndDecorateItem(this.group.getFirst().getStack(), this.getWidth() / 2 + 50, this.getHeight() / 2 - 105); + } + Lighting.setupForFlatItems(); + } + + @Override + public boolean mouseClicked(double x, double y, int mouse) { + if (this.groupName.mouseClicked(x, y, mouse)) { + this.setFocused(this.groupName); + } + + return super.mouseClicked(x, y, mouse); + } + + @Override + public boolean mouseReleased(double x, double y, int mouse) { + return super.mouseReleased(x, y, mouse); + } + + @Override + public boolean hasTitle() { + return true; + } + + @Override + public String title() { + return I18n.get("xray.single.group.edit"); + } +} diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java index 055811b..4af412c 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java @@ -41,7 +41,7 @@ public class GuiSelectionScreen extends GuiBase { private static final List ORE_TAGS = List.of(Blocks.GOLD_ORE, Blocks.IRON_ORE, Blocks.DIAMOND_ORE, Blocks.REDSTONE_ORE, Blocks.LAPIS_ORE, Blocks.COAL_ORE, Blocks.EMERALD_ORE, Blocks.COPPER_ORE, Blocks.DEEPSLATE_GOLD_ORE, Blocks.DEEPSLATE_IRON_ORE, Blocks.DEEPSLATE_DIAMOND_ORE, Blocks.DEEPSLATE_REDSTONE_ORE, Blocks.DEEPSLATE_LAPIS_ORE, Blocks.DEEPSLATE_COAL_ORE, Blocks.DEEPSLATE_EMERALD_ORE, Blocks.DEEPSLATE_COPPER_ORE, Blocks.NETHER_GOLD_ORE, Blocks.ANCIENT_DEBRIS); private static final List TAGS_STORAGE = List.of(Blocks.CHEST, Blocks.TRAPPED_CHEST, Blocks.ENDER_CHEST); - private static final List PLAYER_TAGS_INTEREST = List.of(Blocks.CRAFTING_TABLE, Blocks.ANVIL, Blocks.CHIPPED_ANVIL, Blocks.DAMAGED_ANVIL); + private static final List PLAYER_TAGS_INTEREST = List.of(Blocks.CRAFTING_TABLE, Blocks.ANVIL, Blocks.CHIPPED_ANVIL, Blocks.DAMAGED_ANVIL,Blocks.BREWING_STAND,Blocks.BLAST_FURNACE, Blocks.FURNACE,Blocks.ENCHANTING_TABLE,Blocks.CARTOGRAPHY_TABLE,Blocks.FLETCHING_TABLE,Blocks.COMPOSTER,Blocks.LOOM,Blocks.SMOKER); private static final List LAVA_TAGS = List.of(Blocks.LAVA); private static final ResourceLocation CIRCLE = new ResourceLocation(XRay.PREFIX_GUI + "circle.png"); @@ -78,15 +78,15 @@ private void populateDefault() { //Storage order.set(0); BlockGroup storage = new BlockGroup("Storage", TAGS_STORAGE.stream().map(e -> - new BlockEntry(e.defaultBlockState(), e.asItem().getDescription().getString(), new BasicColor(random.nextInt(255), random.nextInt(255), random.nextInt(255)), order.getAndIncrement(), true, true)).collect(Collectors.toList()), 0, true); + new BlockEntry(e.defaultBlockState(), e.asItem().getDescription().getString(), new BasicColor(20,30,200), order.getAndIncrement(), true, true)).collect(Collectors.toList()), 0, true); Block echest = Blocks.ENDER_CHEST; storage.entries().add(new BlockEntry(echest.defaultBlockState(), echest.asItem().getDescription().getString(), new BasicColor(200,30,200), order.getAndIncrement(), true, true)); BlockStore.getInstance().get().add(storage); //Lava - BlockStore.getInstance().get().add(new BlockGroup("Lava", LAVA_TAGS.stream().map(e -> - new BlockEntry(e.defaultBlockState(), e.asItem().getDescription().getString(), new BasicColor(210,30,30), order.getAndIncrement(), true, true)).collect(Collectors.toList()), 0, false) - ); + BlockGroup lava = new BlockGroup("Lava", LAVA_TAGS.stream().map(e -> + new BlockEntry(e.defaultBlockState(), e.asItem().getDescription().getString(), new BasicColor(210,30,30), order.getAndIncrement(), true, true)).collect(Collectors.toList()), 0, false,new BasicColor(210,20,20)); + BlockStore.getInstance().get().add(lava); //Player / Interest order.set(0); BlockStore.getInstance().get().add(new BlockGroup("Player / Interest", PLAYER_TAGS_INTEREST.stream().map(e -> @@ -112,6 +112,16 @@ public void init() { this.search = new EditBox(this.getFontRender(), this.getWidth() / 2 - 137, this.getHeight() / 2 - 105, 202, 18, Component.empty()); this.search.setCanLoseFocus(true); + this.addRenderableWidget(Button.builder( Component.translatable("xray.single.group.add"), button -> { + this.minecraft.player.clientSideCloseContainer(); + BlockGroup group = new BlockGroup("New Group",new ArrayList<>(),10,true); + this.minecraft.setScreen(new GuiCategoryEdit(group)); + }) + .pos((this.getWidth() / 2) + 79, this.getHeight() / 2 - 60) + .size( 120, 20) + .tooltip(Tooltip.create(Component.translatable("xray.tooltips.add_block"))) + .build()); + this.addRenderableWidget(this.distButtons = Button.builder(Component.translatable("xray.input.distance", StateSettings.getVisualRadius()), button -> { SettingsStore.getInstance().get().increaseRange(); button.setMessage(Component.translatable("xray.input.distance", StateSettings.getVisualRadius())); @@ -268,7 +278,7 @@ public void render(PoseStack stack, int entryIdx, int top, int left, int entryWi RenderSystem.setShaderTexture(0, GuiSelectionScreen.CIRCLE); RenderSystem.setShaderColor(0, 0, 0, .5f); blit(stack, (left + entryWidth) - 32, (int) (top + (entryHeight / 2f) - 9), 0, 0, 14, 14, 14, 14); - RenderSystem.setShaderColor(display.getHex().red() / 255f, display.getHex().green() / 255f, display.getHex().blue() / 255f, 1); + RenderSystem.setShaderColor(group.getColor().red() / 255f, group.getColor().green() / 255f, group.getColor().blue() / 255f, 1); blit(stack, (left + entryWidth) - 30, (int) (top + (entryHeight / 2f) - 7), 0, 0, 10, 10, 10, 10); RenderSystem.disableBlend(); RenderSystem.setShaderColor(1f, 1f, 1f, 1f); diff --git a/src/main/resources/assets/advanced-xray-fabric/lang/en_us.json b/src/main/resources/assets/advanced-xray-fabric/lang/en_us.json index 679d93f..07df9db 100644 --- a/src/main/resources/assets/advanced-xray-fabric/lang/en_us.json +++ b/src/main/resources/assets/advanced-xray-fabric/lang/en_us.json @@ -14,6 +14,8 @@ "xray.single.close": "Close", "xray.single.search": "Search", "xray.single.help": "Help", + "xray.single.group.edit": "Edit Group", + "xray.single.group.add": "Add Group", "xray.overlay": "XRay Active", "xray.color.red": "Red: ", "xray.color.green": "Green: ", From 9e8ae7f78c0979055fd84eb7bdae5782c3c50a23 Mon Sep 17 00:00:00 2001 From: MartinLaptop Date: Mon, 16 Jan 2023 02:38:19 +0100 Subject: [PATCH 04/14] minor fixes -added barrle to group storate -made entries outside of the first Group editable --- .../screens/forge/GuiBlockSelectionScreen.java | 2 +- .../fabric/xray/screens/forge/GuiEdit.java | 18 ++++++++---------- .../xray/screens/forge/GuiSelectionScreen.java | 4 ++-- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java index 8b476c1..2dea7ff 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java @@ -187,7 +187,7 @@ void setSelected(BlockSlot entry, int mouse) { if (GuiBlockSelectionScreen.hasShiftDown()) { this.minecraft.player.clientSideCloseContainer(); - this.minecraft.setScreen(new GuiEdit(entry.block)); + this.minecraft.setScreen(new GuiEdit(entry.block,this.parent.group)); return; } diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java index f65fc86..63f8524 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java @@ -9,6 +9,7 @@ import net.minecraft.world.level.block.state.BlockState; import pro.mikey.fabric.xray.records.BasicColor; import pro.mikey.fabric.xray.records.BlockEntry; +import pro.mikey.fabric.xray.records.BlockGroup; import pro.mikey.fabric.xray.storage.BlockStore; public class GuiEdit extends GuiBase { @@ -18,12 +19,13 @@ public class GuiEdit extends GuiBase { private RatioSliderWidget greenSlider; private RatioSliderWidget blueSlider; private Button changeDefaultState; + private BlockGroup group; private BlockState lastState; - GuiEdit(BlockEntry block) { + GuiEdit(BlockEntry block, BlockGroup group) { super(true); // Has a sidebar this.setSideTitle(I18n.get("xray.single.tools")); - + this.group = group; this.block = block; } @@ -41,9 +43,8 @@ public void init() { this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.delete"), b -> { try { - BlockStore.getInstance().get().get(0).entries().remove(this.block); - BlockStore.getInstance().write(); - BlockStore.getInstance().updateCache(); + group.entries().remove(block); + group.save(); } catch (Exception e) { } this.getMinecraft().setScreen(new GuiSelectionScreen()); @@ -54,15 +55,12 @@ public void init() { }).pos((this.getWidth() / 2) + 78, this.getHeight() / 2 + 58).size(120, 20).build()); this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.save"), b -> { try { - int index = BlockStore.getInstance().get().get(0).entries().indexOf(this.block); - BlockEntry entry = BlockStore.getInstance().get().get(0).entries().get(index); + BlockEntry entry = block; entry.setName(this.oreName.getValue()); entry.setColor(new BasicColor((int) (this.redSlider.getValue() * 255), (int) (this.greenSlider.getValue() * 255), (int) (this.blueSlider.getValue() * 255))); entry.setState(this.block.getState()); entry.setDefault(this.lastState != null); - BlockStore.getInstance().get().get(0).entries().set(index, entry); - BlockStore.getInstance().write(); - BlockStore.getInstance().updateCache(); + this.group.save(); } catch (Exception ignored) { } // lazy catching for basic failures diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java index 4af412c..f5c72cd 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java @@ -40,7 +40,7 @@ public class GuiSelectionScreen extends GuiBase { private static final List ORE_TAGS = List.of(Blocks.GOLD_ORE, Blocks.IRON_ORE, Blocks.DIAMOND_ORE, Blocks.REDSTONE_ORE, Blocks.LAPIS_ORE, Blocks.COAL_ORE, Blocks.EMERALD_ORE, Blocks.COPPER_ORE, Blocks.DEEPSLATE_GOLD_ORE, Blocks.DEEPSLATE_IRON_ORE, Blocks.DEEPSLATE_DIAMOND_ORE, Blocks.DEEPSLATE_REDSTONE_ORE, Blocks.DEEPSLATE_LAPIS_ORE, Blocks.DEEPSLATE_COAL_ORE, Blocks.DEEPSLATE_EMERALD_ORE, Blocks.DEEPSLATE_COPPER_ORE, Blocks.NETHER_GOLD_ORE, Blocks.ANCIENT_DEBRIS); - private static final List TAGS_STORAGE = List.of(Blocks.CHEST, Blocks.TRAPPED_CHEST, Blocks.ENDER_CHEST); + private static final List TAGS_STORAGE = List.of(Blocks.CHEST, Blocks.TRAPPED_CHEST, Blocks.BARREL); private static final List PLAYER_TAGS_INTEREST = List.of(Blocks.CRAFTING_TABLE, Blocks.ANVIL, Blocks.CHIPPED_ANVIL, Blocks.DAMAGED_ANVIL,Blocks.BREWING_STAND,Blocks.BLAST_FURNACE, Blocks.FURNACE,Blocks.ENCHANTING_TABLE,Blocks.CARTOGRAPHY_TABLE,Blocks.FLETCHING_TABLE,Blocks.COMPOSTER,Blocks.LOOM,Blocks.SMOKER); private static final List LAVA_TAGS = List.of(Blocks.LAVA); @@ -90,7 +90,7 @@ private void populateDefault() { //Player / Interest order.set(0); BlockStore.getInstance().get().add(new BlockGroup("Player / Interest", PLAYER_TAGS_INTEREST.stream().map(e -> - new BlockEntry(e.defaultBlockState(), e.asItem().getDescription().getString(), new BasicColor(30,30,210), order.getAndIncrement(), true, true)).collect(Collectors.toList()), 0, false) + new BlockEntry(e.defaultBlockState(), e.asItem().getDescription().getString(), new BasicColor(30,210,30), order.getAndIncrement(), true, true)).collect(Collectors.toList()), 0, false) ); BlockStore.getInstance().updateCache(); From cc9b61927f8bc6da127f262ff330b1512108e2f2 Mon Sep 17 00:00:00 2001 From: MartinLaptop Date: Mon, 16 Jan 2023 18:18:30 +0100 Subject: [PATCH 05/14] Right Click to Edit --- .../fabric/xray/screens/forge/GuiBlockSelectionScreen.java | 2 +- .../pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java index 2dea7ff..728404a 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java @@ -185,7 +185,7 @@ void setSelected(BlockSlot entry, int mouse) { return; } - if (GuiBlockSelectionScreen.hasShiftDown()) { + if (GuiBlockSelectionScreen.hasShiftDown() || mouse==1) { this.minecraft.player.clientSideCloseContainer(); this.minecraft.setScreen(new GuiEdit(entry.block,this.parent.group)); return; diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java index f5c72cd..c325529 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java @@ -216,7 +216,7 @@ void setSelected(CategoryEntry entry, int mouse) { return; } - if (GuiSelectionScreen.hasShiftDown()) { + if (GuiSelectionScreen.hasShiftDown() || mouse == 1 ) { this.minecraft.player.clientSideCloseContainer(); this.minecraft.setScreen(new GuiBlockSelectionScreen(entry.getGroup())); return; From 101defe3e7e8ec8e943b9741bb5cf29a294480a2 Mon Sep 17 00:00:00 2001 From: MartinLaptop Date: Mon, 16 Jan 2023 23:34:26 +0100 Subject: [PATCH 06/14] BugFix AddBlock --- src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java index 63f8524..3210719 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java @@ -60,6 +60,7 @@ public void init() { entry.setColor(new BasicColor((int) (this.redSlider.getValue() * 255), (int) (this.greenSlider.getValue() * 255), (int) (this.blueSlider.getValue() * 255))); entry.setState(this.block.getState()); entry.setDefault(this.lastState != null); + if(!group.entries().contains(entry)) group.entries().add(entry); this.group.save(); } catch (Exception ignored) { } // lazy catching for basic failures From bbd3b093b3a731c0c233ccb5eb04c9cf48ffc6cc Mon Sep 17 00:00:00 2001 From: MartinLaptop Date: Sat, 21 Jan 2023 18:10:42 +0100 Subject: [PATCH 07/14] Fixing multiple bugs with adding Blocks to the wrong group/overwriting group(0) --- .../mikey/fabric/xray/records/BlockGroup.java | 1 - .../xray/screens/forge/GuiAddBlock.java | 14 +++------ .../xray/screens/forge/GuiBlockList.java | 13 +++++--- .../forge/GuiBlockSelectionScreen.java | 31 +++++++++++++++++-- 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/main/java/pro/mikey/fabric/xray/records/BlockGroup.java b/src/main/java/pro/mikey/fabric/xray/records/BlockGroup.java index 2b0bc36..d7b2ac4 100644 --- a/src/main/java/pro/mikey/fabric/xray/records/BlockGroup.java +++ b/src/main/java/pro/mikey/fabric/xray/records/BlockGroup.java @@ -1,6 +1,5 @@ package pro.mikey.fabric.xray.records; -import net.minecraft.world.level.block.Block; import pro.mikey.fabric.xray.storage.BlockStore; import java.util.ArrayList; diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiAddBlock.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiAddBlock.java index 860d8c0..064de28 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiAddBlock.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiAddBlock.java @@ -7,6 +7,7 @@ import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import pro.mikey.fabric.xray.records.BasicColor; import pro.mikey.fabric.xray.records.BlockEntry; @@ -28,10 +29,12 @@ public class GuiAddBlock extends GuiBase { private RatioSliderWidget blueSlider; private Button changeDefaultState; private BlockState lastState; + private BlockGroup group; private boolean oreNameCleared = false; - GuiAddBlock(BlockState selectedBlock, Supplier previousScreenCallback) { + GuiAddBlock(BlockState selectedBlock, BlockGroup group, Supplier previousScreenCallback) { super(false); + this.group = group; this.selectBlock = selectedBlock; this.lastState = null; this.previousScreenCallback = previousScreenCallback; @@ -54,15 +57,8 @@ public void init() { this.addRenderableWidget(this.addBtn = new Button.Builder(Component.translatable("xray.single.add"), button -> { this.onClose(); - - BlockGroup group = BlockStore.getInstance().get().size() >= 1 ? BlockStore.getInstance().get().get(0) : new BlockGroup("default", new ArrayList<>(), 1, true); + group = group != null ? group : new BlockGroup("default", new ArrayList<>(), 1, true); group.entries().add(new BlockEntry(this.selectBlock, this.oreName.getValue(), new BasicColor((int) (this.redSlider.getValue() * 255), (int) (this.greenSlider.getValue() * 255), (int) (this.blueSlider.getValue() * 255)), group.entries().size() + 1, this.selectBlock == this.selectBlock.getBlock().defaultBlockState(), true)); - - if (BlockStore.getInstance().get().size() > 0) { - BlockStore.getInstance().get().set(0, group); - } else { - BlockStore.getInstance().get().add(group); - } BlockStore.getInstance().write(); BlockStore.getInstance().updateCache(); diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockList.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockList.java index 7153f5a..b98928e 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockList.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockList.java @@ -13,6 +13,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.block.Block; +import pro.mikey.fabric.xray.records.BlockGroup; import pro.mikey.fabric.xray.records.BlockWithStack; import java.awt.*; @@ -24,15 +25,17 @@ public class GuiBlockList extends GuiBase { private ScrollingBlockList blockList; private EditBox search; private String lastSearched = ""; + private BlockGroup group; - GuiBlockList() { + GuiBlockList(BlockGroup group) { super(false); + this.group = group; this.blocks = BuiltInRegistries.ITEM.stream().filter(item -> item instanceof BlockItem && item != Items.AIR).map(item -> new BlockWithStack(Block.byItem(item), new ItemStack(item))).toList(); } @Override public void init() { - this.blockList = new ScrollingBlockList((this.getWidth() / 2) + 1, this.getHeight() / 2 - 12, 202, 185, this.blocks); + this.blockList = new ScrollingBlockList((this.getWidth() / 2) + 1, this.getHeight() / 2 - 12, 202, 185, this.blocks,group); this.addRenderableWidget(this.blockList); this.search = new EditBox(this.getFontRender(), this.getWidth() / 2 - 100, this.getHeight() / 2 + 85, 140, 18, Component.empty()); @@ -89,9 +92,11 @@ public boolean mouseScrolled(double p_mouseScrolled_1_, double p_mouseScrolled_3 static class ScrollingBlockList extends ScrollingList { static final int SLOT_HEIGHT = 35; + private BlockGroup group; - ScrollingBlockList(int x, int y, int width, int height, List blocks) { + ScrollingBlockList(int x, int y, int width, int height, List blocks,BlockGroup group) { super(x, y, width, height, SLOT_HEIGHT); + this.group=group; this.updateEntries(blocks); } @@ -103,7 +108,7 @@ public void setSelected(BlockSlot entry) { assert this.minecraft.player != null; this.minecraft.player.clientSideCloseContainer(); - this.minecraft.setScreen(new GuiAddBlock(entry.getBlock().block().defaultBlockState(), GuiBlockList::new)); + this.minecraft.setScreen(new GuiAddBlock(entry.getBlock().block().defaultBlockState(),group, () -> new GuiBlockList(group))); } void updateEntries(List blocks) { diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java index 728404a..d1a4188 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java @@ -74,7 +74,7 @@ public void init() { // sidebar buttons this.addRenderableWidget(Button.builder( Component.translatable("xray.input.add"), button -> { this.minecraft.player.clientSideCloseContainer(); - this.minecraft.setScreen(new GuiBlockList()); + this.minecraft.setScreen(new GuiBlockList(group)); }) .pos((this.getWidth() / 2) + 79, this.getHeight() / 2 - 60) .size( 120, 20) @@ -91,13 +91,40 @@ public void init() { return; } - this.minecraft.setScreen(new GuiAddBlock(((BlockItem) handItem.getItem()).getBlock().defaultBlockState(), () -> new GuiBlockSelectionScreen(this.group))); + this.minecraft.setScreen(new GuiAddBlock(((BlockItem) handItem.getItem()).getBlock().defaultBlockState(),group, () -> new GuiBlockSelectionScreen(this.group))); }) .pos(this.getWidth() / 2 + 79, this.getHeight() / 2 - 38) .size( 120, 20) .tooltip(Tooltip.create(Component.translatable("xray.tooltips.add_block_in_hand"))) .build()); + this.addRenderableWidget(Button.builder(Component.translatable("xray.input.add_look"), button -> { + LocalPlayer player = this.minecraft.player; + if (this.minecraft.level == null || player == null) { + return; + } + + this.onClose(); + try { + HitResult look = player.pick(100, 1f, false); + + if (look.getType() == BlockHitResult.Type.BLOCK) { + BlockState state = this.minecraft.level.getBlockState(((BlockHitResult) look).getBlockPos()); + + player.clientSideCloseContainer(); + this.minecraft.setScreen(new GuiAddBlock(state,group, () -> new GuiBlockSelectionScreen(group))); + } else { + player.displayClientMessage(Component.literal("[XRay] " + I18n.get("xray.message.nothing_infront")), false); + } + } catch (NullPointerException ex) { + player.displayClientMessage(Component.literal("[XRay] " + I18n.get("xray.message.thats_odd")), false); + } + }) + .pos(this.getWidth() / 2 + 79, this.getHeight() / 2 - 16) + .size(120, 20) + .tooltip(Tooltip.create(Component.translatable("xray.tooltips.add_block_looking_at"))) + .build()); + this.addRenderableWidget(Button.builder( Component.translatable("xray.single.group.edit"), button -> { this.minecraft.player.clientSideCloseContainer(); this.minecraft.setScreen(new GuiCategoryEdit(this.group)); From 4e8a79ff099782d97e9aaf20f1ec7d8abb1f9e7d Mon Sep 17 00:00:00 2001 From: MartinLaptop Date: Thu, 26 Jan 2023 00:35:37 +0100 Subject: [PATCH 08/14] proper back and cancel behaviour in UIs --- .../fabric/xray/screens/forge/GuiBlockSelectionScreen.java | 4 +++- .../java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java | 3 +-- .../resources/assets/advanced-xray-fabric/lang/en_us.json | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java index d1a4188..15c76aa 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java @@ -138,7 +138,9 @@ public void init() { this.minecraft.player.clientSideCloseContainer(); this.minecraft.setScreen(new GuiHelp()); }).pos(this.getWidth() / 2 + 79, this.getHeight() / 2 + 58).size(60,20).build()); - this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.close"), button -> this.onClose()).pos((this.getWidth() / 2 + 79) + 62, this.getHeight() / 2 + 58).size(59,20).build()); + this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.back"), b -> { + this.getMinecraft().setScreen(new GuiSelectionScreen()); + }).pos((this.getWidth() / 2 + 79) + 62, this.getHeight() / 2 + 58).size(59,20).build()); } private void updateSearch() { diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java index 3210719..8e8ace3 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java @@ -10,7 +10,6 @@ import pro.mikey.fabric.xray.records.BasicColor; import pro.mikey.fabric.xray.records.BlockEntry; import pro.mikey.fabric.xray.records.BlockGroup; -import pro.mikey.fabric.xray.storage.BlockStore; public class GuiEdit extends GuiBase { private final BlockEntry block; @@ -51,7 +50,7 @@ public void init() { }).pos((this.getWidth() / 2) + 78, this.getHeight() / 2 - 60).size(120, 20).build()); this.addRenderableWidget(new Button.Builder( Component.translatable("xray.single.cancel"), b -> { - this.getMinecraft().setScreen(new GuiSelectionScreen()); + this.getMinecraft().setScreen(new GuiBlockSelectionScreen(group)); }).pos((this.getWidth() / 2) + 78, this.getHeight() / 2 + 58).size(120, 20).build()); this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.save"), b -> { try { diff --git a/src/main/resources/assets/advanced-xray-fabric/lang/en_us.json b/src/main/resources/assets/advanced-xray-fabric/lang/en_us.json index 07df9db..fc3bde4 100644 --- a/src/main/resources/assets/advanced-xray-fabric/lang/en_us.json +++ b/src/main/resources/assets/advanced-xray-fabric/lang/en_us.json @@ -7,6 +7,7 @@ "spacer": "-------------------------------------------------------", "comment_forge": "Forge mod old lang stuff, please never translate", "xray.single.cancel": "Cancel", + "xray.single.back": "Back", "xray.single.add": "Add", "xray.single.delete": "Delete", "xray.single.save": "Save", From 38731ea19665033acb4370cf26eb413ea12dbe91 Mon Sep 17 00:00:00 2001 From: MartinLaptop Date: Thu, 26 Jan 2023 00:45:14 +0100 Subject: [PATCH 09/14] fixing up rest of UI navigation --- .../java/pro/mikey/fabric/xray/screens/forge/GuiAddBlock.java | 2 +- .../pro/mikey/fabric/xray/screens/forge/GuiBlockList.java | 2 +- .../java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiAddBlock.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiAddBlock.java index 064de28..3680bbc 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiAddBlock.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiAddBlock.java @@ -62,7 +62,7 @@ public void init() { BlockStore.getInstance().write(); BlockStore.getInstance().updateCache(); - this.getMinecraft().setScreen(new GuiSelectionScreen()); + this.getMinecraft().setScreen(new GuiBlockSelectionScreen(group)); }).pos(this.getWidth() / 2 - 100, this.getHeight() / 2 + 85).size(128, 20).build()); this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.cancel"), b -> { this.onClose(); diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockList.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockList.java index b98928e..184fbba 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockList.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockList.java @@ -44,7 +44,7 @@ public void init() { this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.cancel"), b -> { assert this.getMinecraft() != null; - this.getMinecraft().setScreen(new GuiSelectionScreen()); + this.getMinecraft().setScreen(new GuiBlockSelectionScreen(group)); }).pos(this.getWidth() / 2 + 43, this.getHeight() / 2 + 84).size(60, 20).build()); } diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java index 8e8ace3..467153b 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java @@ -46,7 +46,7 @@ public void init() { group.save(); } catch (Exception e) { } - this.getMinecraft().setScreen(new GuiSelectionScreen()); + this.getMinecraft().setScreen(new GuiBlockSelectionScreen(group)); }).pos((this.getWidth() / 2) + 78, this.getHeight() / 2 - 60).size(120, 20).build()); this.addRenderableWidget(new Button.Builder( Component.translatable("xray.single.cancel"), b -> { @@ -64,7 +64,7 @@ public void init() { } catch (Exception ignored) { } // lazy catching for basic failures - this.getMinecraft().setScreen(new GuiSelectionScreen()); + this.getMinecraft().setScreen(new GuiBlockSelectionScreen(group)); }).pos(this.getWidth() / 2 - 138, this.getHeight() / 2 + 83).size(202, 20).build()); this.addRenderableWidget(this.redSlider = new RatioSliderWidget(this.getWidth() / 2 - 138, this.getHeight() / 2 - 40, 100, 20, Component.translatable("xray.color.red"), 0)); From 52dea6353762ec3818bf95ccd6ee924800fd1877 Mon Sep 17 00:00:00 2001 From: MartinLaptop Date: Thu, 26 Jan 2023 00:52:07 +0100 Subject: [PATCH 10/14] -forceClear cache on close UI --- src/main/java/pro/mikey/fabric/xray/ScanController.java | 8 ++++++-- .../fabric/xray/screens/forge/GuiSelectionScreen.java | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/pro/mikey/fabric/xray/ScanController.java b/src/main/java/pro/mikey/fabric/xray/ScanController.java index 4e4beb9..b1d69eb 100644 --- a/src/main/java/pro/mikey/fabric/xray/ScanController.java +++ b/src/main/java/pro/mikey/fabric/xray/ScanController.java @@ -47,11 +47,11 @@ public static void CloseGame(){ * This function rebuilds the ChunkCache completly and reloads all Chunks * without flashing the already rendered Chunks instantly away */ - public static void RebuildCache(){ + public static void RebuildCache(boolean force){ class RebuildThread extends Thread{ @Override public synchronized void run() { - RenderOutlines.clearChunks(false); + RenderOutlines.clearChunks(force); executor.shutdownNow(); while(!executor.isTerminated()){ try { @@ -74,6 +74,10 @@ public synchronized void run() { r.start(); } + public static void RebuildCache(){ + RebuildCache(false); + } + /** * This function updates a Chunk based on Pos */ diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java index c325529..ccbd845 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java @@ -197,7 +197,7 @@ public void onClose() { SettingsStore.getInstance().write(); BlockStore.getInstance().write(); BlockStore.getInstance().updateCache(); - ScanController.RebuildCache(); + ScanController.RebuildCache(true); super.onClose(); } From 246003343f5fecce4d839c399229f2e721987b28 Mon Sep 17 00:00:00 2001 From: MartinLaptop Date: Thu, 26 Jan 2023 03:23:34 +0100 Subject: [PATCH 11/14] -complete cleanup -sorting of the VertexBuffer to fix a bug where further away stuff would render over closer stuff. --- .../pro/mikey/fabric/xray/ScanController.java | 42 ++++++---- .../pro/mikey/fabric/xray/StateSettings.java | 8 +- src/main/java/pro/mikey/fabric/xray/XRay.java | 33 ++++---- .../fabric/xray/cache/BlockSearchCache.java | 2 +- .../fabric/xray/cache/BlockSearchEntry.java | 4 - .../fabric/xray/mixins/MixinBlockItem.java | 1 - .../mikey/fabric/xray/records/BlockEntry.java | 2 - .../fabric/xray/render/RenderOutlines.java | 72 +++++++++++++---- .../fabric/xray/screens/AbstractScreen.java | 3 - .../mikey/fabric/xray/screens/MainScreen.java | 5 -- .../xray/screens/forge/GuiAddBlock.java | 17 ++-- .../fabric/xray/screens/forge/GuiBase.java | 5 +- .../xray/screens/forge/GuiBlockList.java | 10 +-- .../forge/GuiBlockSelectionScreen.java | 46 ++++------- .../xray/screens/forge/GuiCategoryEdit.java | 9 +-- .../fabric/xray/screens/forge/GuiEdit.java | 32 +++----- .../fabric/xray/screens/forge/GuiOverlay.java | 8 +- .../screens/forge/GuiSelectionScreen.java | 35 +++----- .../xray/screens/forge/RatioSliderWidget.java | 1 - .../xray/screens/forge/ScrollingList.java | 2 +- .../mikey/fabric/xray/storage/BlockStore.java | 2 +- .../pro/mikey/fabric/xray/storage/Store.java | 17 ++-- .../mikey/fabric/xray/tasks/AddChunkTask.java | 80 ------------------- .../mikey/fabric/xray/tasks/ReBuildCache.java | 50 ++++++------ .../fabric/xray/tasks/RemoveChunkTask.java | 2 +- .../fabric/xray/tasks/UpdateChunkTask.java | 62 ++++++++++++-- 26 files changed, 250 insertions(+), 300 deletions(-) delete mode 100644 src/main/java/pro/mikey/fabric/xray/tasks/AddChunkTask.java diff --git a/src/main/java/pro/mikey/fabric/xray/ScanController.java b/src/main/java/pro/mikey/fabric/xray/ScanController.java index b1d69eb..a5713d5 100644 --- a/src/main/java/pro/mikey/fabric/xray/ScanController.java +++ b/src/main/java/pro/mikey/fabric/xray/ScanController.java @@ -14,11 +14,11 @@ public class ScanController { static ThreadPoolExecutor executor = new ThreadPoolExecutor( StateSettings.getRadius(), StateSettings.getRadius(), 0L, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue() + new LinkedBlockingQueue<>() ); /** - * This function sets the Threadpool up properly. + * This function sets the ThreadPool up properly. * Technically the threads set their own Priority to one anyways, so a normal Threapool would be sufficient */ public static void setup(){ @@ -36,9 +36,9 @@ private static void submitTask(Runnable worker){ } /** - * Just a security measure to forceclose the threadpool to make sure it doesnt linger in the background + * Just a security measure to force-close the ThreadPool to make sure it doesn't linger in the background */ - public static void CloseGame(){ + public static void closeGame() { executor.shutdownNow(); } @@ -47,13 +47,13 @@ public static void CloseGame(){ * This function rebuilds the ChunkCache completly and reloads all Chunks * without flashing the already rendered Chunks instantly away */ - public static void RebuildCache(boolean force){ - class RebuildThread extends Thread{ + public static void reBuildCache(boolean force) { + class RebuildThread extends Thread { @Override public synchronized void run() { RenderOutlines.clearChunks(force); executor.shutdownNow(); - while(!executor.isTerminated()){ + while (!executor.isTerminated()) { try { currentThread().wait(5); } catch (InterruptedException e) { @@ -63,10 +63,10 @@ public synchronized void run() { executor = new ThreadPoolExecutor( StateSettings.getRadius(), StateSettings.getRadius(), 0L, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue() + new LinkedBlockingQueue<>() ); setup(); - Runnable worker = new ReBuildCache(); + Runnable worker = new ReBuildCache(); executor.execute(worker); } } @@ -74,16 +74,30 @@ public synchronized void run() { r.start(); } - public static void RebuildCache(){ - RebuildCache(false); + /** + * This function clears the Cache on a seperate Thread + */ + public static void clearCache(boolean force) { + class ClearThread extends Thread { + @Override + public synchronized void run() { + RenderOutlines.clearChunks(force); + } + } + Thread r = new ClearThread(); + r.start(); + } + + public static void reBuildCache() { + reBuildCache(false); } /** * This function updates a Chunk based on Pos */ - public static void updateChunk(ChunkPos pos){ - if(SettingsStore.getInstance().get().isActive()){ - Runnable worker = new UpdateChunkTask(pos); + public static void updateChunk(ChunkPos pos) { + if (SettingsStore.getInstance().get().isActive()) { + Runnable worker = new UpdateChunkTask(pos); submitTask(worker); } } diff --git a/src/main/java/pro/mikey/fabric/xray/StateSettings.java b/src/main/java/pro/mikey/fabric/xray/StateSettings.java index e43e600..baf4cfb 100644 --- a/src/main/java/pro/mikey/fabric/xray/StateSettings.java +++ b/src/main/java/pro/mikey/fabric/xray/StateSettings.java @@ -4,7 +4,7 @@ import pro.mikey.fabric.xray.storage.SettingsStore; public class StateSettings { - private static final int maxStepsToScan = 5; + private static final int MAX_STEPS_TO_SCAN = 5; private transient boolean isActive; private boolean showLava; @@ -35,7 +35,7 @@ public void setShowLava(boolean showLava) { } public static int getRadius() { - return Mth.clamp(SettingsStore.getInstance().get().range, 0, maxStepsToScan) * 3; + return Mth.clamp(SettingsStore.getInstance().get().range, 0, MAX_STEPS_TO_SCAN) * 3; } public static int getHalfRange() { @@ -47,7 +47,7 @@ public static int getVisualRadius() { } public void increaseRange() { - if (SettingsStore.getInstance().get().range < maxStepsToScan) + if (SettingsStore.getInstance().get().range < MAX_STEPS_TO_SCAN) SettingsStore.getInstance().get().range = SettingsStore.getInstance().get().range + 1; else SettingsStore.getInstance().get().range = 0; @@ -57,7 +57,7 @@ public void decreaseRange() { if (SettingsStore.getInstance().get().range > 0) SettingsStore.getInstance().get().range = SettingsStore.getInstance().get().range - 1; else - SettingsStore.getInstance().get().range = maxStepsToScan; + SettingsStore.getInstance().get().range = MAX_STEPS_TO_SCAN; } public boolean showOverlay() { diff --git a/src/main/java/pro/mikey/fabric/xray/XRay.java b/src/main/java/pro/mikey/fabric/xray/XRay.java index d11633f..99093a2 100644 --- a/src/main/java/pro/mikey/fabric/xray/XRay.java +++ b/src/main/java/pro/mikey/fabric/xray/XRay.java @@ -29,9 +29,6 @@ import pro.mikey.fabric.xray.storage.BlockStore; import pro.mikey.fabric.xray.storage.SettingsStore; -import java.util.HashSet; -import java.util.Set; - public class XRay implements ModInitializer { public static final String MOD_ID = "advanced-xray-fabric"; @@ -41,8 +38,7 @@ public class XRay implements ModInitializer { private final KeyMapping xrayButton = new KeyMapping("keybinding.enable_xray", GLFW.GLFW_KEY_BACKSLASH, "category.xray"); private final KeyMapping guiButton = new KeyMapping("keybinding.open_gui", GLFW.GLFW_KEY_G, "category.xray"); - - public static volatile Set chunks = new HashSet<>(); + private int counter = 0; @Override public void onInitialize() { @@ -50,9 +46,9 @@ public void onInitialize() { ClientTickEvents.END_CLIENT_TICK.register(this::clientTickEvent); ClientLifecycleEvents.CLIENT_STOPPING.register(this::gameClosing); - ClientChunkEvents.CHUNK_LOAD.register(this::ChunkLoad); - ClientChunkEvents.CHUNK_UNLOAD.register(this::ChunkUnload); - HudRenderCallback.EVENT.register(GuiOverlay::RenderGameOverlayEvent); + ClientChunkEvents.CHUNK_LOAD.register(this::chunkLoad); + ClientChunkEvents.CHUNK_UNLOAD.register(this::chunkUnload); + HudRenderCallback.EVENT.register(GuiOverlay::renderGameOverlayEvent); WorldRenderEvents.LAST.register(RenderOutlines::render); PlayerBlockBreakEvents.AFTER.register(this::blockBroken); @@ -65,18 +61,16 @@ public void onInitialize() { /** * Upon unloading a chunk the chunk can be removed from the rendering */ - private void ChunkUnload(ClientLevel clientLevel, LevelChunk levelChunk) { + private void chunkUnload(ClientLevel clientLevel, LevelChunk levelChunk) { if (!SettingsStore.getInstance().get().isActive()) return; - chunks.remove(levelChunk); ScanController.removeChunk(levelChunk.getPos()); } /** * Upon loading a chunk the chunk needs to be queued for scanning and rendering */ - private void ChunkLoad(ClientLevel clientLevel, LevelChunk levelChunk) { + private void chunkLoad(ClientLevel clientLevel, LevelChunk levelChunk) { if (!SettingsStore.getInstance().get().isActive()) return; - chunks.add(levelChunk); ScanController.updateChunk(levelChunk.getPos()); } @@ -102,7 +96,7 @@ public static void blockPlaced(BlockPlaceContext context) { * we go about saving throughout the rest of the mod */ private void gameClosing(Minecraft client) { - ScanController.CloseGame(); + ScanController.closeGame(); SettingsStore.getInstance().write(); BlockStore.getInstance().write(); } @@ -114,10 +108,13 @@ private void clientTickEvent(Minecraft mc) { if (mc.player == null || mc.level == null || mc.screen != null) { return; } - int counter = 0; + /* + this part only executes every 200 ticks, so every 10 seconds. + its making sure all unloaded Chunks are removed, because for some reason the Chunk unload event is not reliable at this + */ if (counter % 200 == 0) { - RenderOutlines.clearChunks(false); - counter=0; + ScanController.clearCache(false); + counter = 0; } counter++; @@ -131,10 +128,10 @@ private void clientTickEvent(Minecraft mc) { StateSettings stateSettings = SettingsStore.getInstance().get(); stateSettings.setActive(!stateSettings.isActive()); if(stateSettings.isActive()){ - ScanController.RebuildCache(); + ScanController.reBuildCache(); } else{ - RenderOutlines.clearChunks(true); + ScanController.clearCache(true); } mc.player.displayClientMessage(Component.translatable("message.xray_" + (!stateSettings.isActive() ? "deactivate" : "active")).withStyle(stateSettings.isActive() ? ChatFormatting.GREEN : ChatFormatting.RED), true); diff --git a/src/main/java/pro/mikey/fabric/xray/cache/BlockSearchCache.java b/src/main/java/pro/mikey/fabric/xray/cache/BlockSearchCache.java index 765307b..e3c720d 100644 --- a/src/main/java/pro/mikey/fabric/xray/cache/BlockSearchCache.java +++ b/src/main/java/pro/mikey/fabric/xray/cache/BlockSearchCache.java @@ -24,7 +24,7 @@ public void processGroupedList(List blockEntries) { // Flatten the grouped list down to a single cacheable list this.cache = - blockEntries.stream().filter(group -> group.active()) + blockEntries.stream().filter(BlockGroup::active) .flatMap( e -> e.entries().stream() diff --git a/src/main/java/pro/mikey/fabric/xray/cache/BlockSearchEntry.java b/src/main/java/pro/mikey/fabric/xray/cache/BlockSearchEntry.java index 039c65a..752d957 100644 --- a/src/main/java/pro/mikey/fabric/xray/cache/BlockSearchEntry.java +++ b/src/main/java/pro/mikey/fabric/xray/cache/BlockSearchEntry.java @@ -34,10 +34,6 @@ public static BlockState blockStateFromStringNBT(String nbt) { return NbtUtils.readBlockState(BuiltInRegistries.BLOCK.asLookup(), tag); } - public static String blockStateToStringNBT(BlockState state) { - return NbtUtils.writeBlockState(state).toString(); - } - public BlockState getState() { return this.state; } diff --git a/src/main/java/pro/mikey/fabric/xray/mixins/MixinBlockItem.java b/src/main/java/pro/mikey/fabric/xray/mixins/MixinBlockItem.java index 3399e10..38e69d8 100644 --- a/src/main/java/pro/mikey/fabric/xray/mixins/MixinBlockItem.java +++ b/src/main/java/pro/mikey/fabric/xray/mixins/MixinBlockItem.java @@ -7,7 +7,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import pro.mikey.fabric.xray.ScanController; import pro.mikey.fabric.xray.XRay; // Thanks to architectury diff --git a/src/main/java/pro/mikey/fabric/xray/records/BlockEntry.java b/src/main/java/pro/mikey/fabric/xray/records/BlockEntry.java index bf106d7..9e7e413 100644 --- a/src/main/java/pro/mikey/fabric/xray/records/BlockEntry.java +++ b/src/main/java/pro/mikey/fabric/xray/records/BlockEntry.java @@ -3,9 +3,7 @@ import com.google.gson.*; import net.minecraft.nbt.NbtUtils; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.AirBlock; import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import pro.mikey.fabric.xray.cache.BlockSearchEntry; diff --git a/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java b/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java index 3d2c601..2c81451 100644 --- a/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java +++ b/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java @@ -7,6 +7,7 @@ import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.RenderBuffers; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.phys.Vec3; import org.joml.Matrix4f; @@ -27,36 +28,47 @@ public class RenderOutlines { * This queue holds the by the threadpool queued workloads for the Renderthread. * To keep performancy high the renderthreads only uploads one Chunk per frame */ - private static ConcurrentLinkedQueue workQueue = new ConcurrentLinkedQueue<>(); + private static final ConcurrentLinkedQueue workQueue = new ConcurrentLinkedQueue<>(); /** * This is the internal Vertexbuffers mapped by chunk so the removal is simple */ - private static Map chunkCache = new HashMap(); + private static final Map chunkCache = new HashMap<>(); + /** + * This List provides the sorting for the rendering. + * I'm not aware of a way to make this faster, as this way im avoiding unnecessarily looping through the list + */ + private static final List sortedCache = new ArrayList<>(); /** * This queue holds the by the threadpool queued removal workloads for the Renderthread. * To keep performancy high the renderthreads removes up to 100 per frame. */ - private static ConcurrentLinkedQueue deleteQueue = new ConcurrentLinkedQueue<>(); + private static final ConcurrentLinkedQueue deleteQueue = new ConcurrentLinkedQueue<>(); /** * If this boolen is set to true it force clears all the buffers immediately */ - private static AtomicBoolean forceclear = new AtomicBoolean(false); + private static final AtomicBoolean forceclear = new AtomicBoolean(false); private static int canvasLoaded = -1; - private static class WorkLoad{ + + private static class WorkLoad { public Long chunk; public Collection pos; - public WorkLoad(Long chunk,Collection pos){ + + public WorkLoad(Long chunk, Collection pos) { this.chunk = chunk; this.pos = pos; } } + private RenderOutlines() { + //hide the constructor so nobody becomes bad ideas + } + /** * This function adds a Chunk into the queue to be rendered */ - public static void addChunk(Long chunk,Collection pos){ - workQueue.add(new WorkLoad(chunk,pos)); + public static void addChunk(Long chunk, Collection pos) { + workQueue.add(new WorkLoad(chunk, pos)); } /** @@ -93,6 +105,7 @@ public static synchronized void render(WorldRenderContext context) { workQueue.clear(); deleteQueue.clear(); chunkCache.clear(); + sortedCache.clear(); forceclear.set(false); } @@ -103,7 +116,7 @@ public static synchronized void render(WorldRenderContext context) { if(work!=null){ BufferBuilder bufferBuilder = Tesselator.getInstance().getBuilder(); bufferBuilder.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR); - work.pos.stream().forEach(posWithColor -> { + work.pos.forEach(posWithColor -> { renderBlock(bufferBuilder, posWithColor, 1); }); bufferBuilder.clear(); @@ -112,7 +125,8 @@ public static synchronized void render(WorldRenderContext context) { BufferBuilder.RenderedBuffer buffer = bufferBuilder.end(); vertexBuffer.upload(buffer); VertexBuffer.unbind(); - chunkCache.put(work.chunk,vertexBuffer); + chunkCache.put(work.chunk, vertexBuffer); + sortedCache.add(0, work.chunk); bufferBuilder.discard(); } int removed = 0; @@ -122,6 +136,7 @@ public static synchronized void render(WorldRenderContext context) { if(vertexBuffer!=null){ vertexBuffer.close(); } + sortedCache.remove(toRemove); chunkCache.remove(toRemove); removed++; } @@ -141,18 +156,36 @@ public static synchronized void render(WorldRenderContext context) { if (canvasLoaded == 1) { // canvas compat float f = camera.getXRot() * 0.017453292F; - poseStack.mulPose(new Quaternionf(1.0 * sin(f/2.0f), 0.0, 0.0, cos(f/2.0f))); + poseStack.mulPose(new Quaternionf(1.0 * sin(f / 2.0f), 0.0, 0.0, cos(f / 2.0f))); f = (camera.getYRot() + 180f) * 0.017453292F; - poseStack.mulPose(new Quaternionf(0.0, 1.0 * sin(f/2.0f), 0.0, cos(f/2.0f))); + poseStack.mulPose(new Quaternionf(0.0, 1.0 * sin(f / 2.0f), 0.0, cos(f / 2.0f))); } RenderSystem.setShader(GameRenderer::getPositionColorShader); RenderSystem.applyModelViewMatrix(); RenderSystem.depthFunc(GL11.GL_ALWAYS); - chunkCache.values().stream().forEach(buf -> { - buf.bind(); - buf.drawWithShader(poseStack.last().pose(), new Matrix4f(context.projectionMatrix()), RenderSystem.getShader()); - }); + int x = (int) context.camera().getPosition().x / 16; + int z = (int) context.camera().getPosition().z / 16; + double distance; + double lastDistance = Double.MAX_VALUE; + for (int i = 0; i < sortedCache.size(); i++) { + VertexBuffer buf = chunkCache.get(sortedCache.get(i)); + if (buf != null) { + buf.bind(); + buf.drawWithShader(poseStack.last().pose(), new Matrix4f(context.projectionMatrix()), RenderSystem.getShader()); + } + //this is a semi-bubble-sort algorithm + //it only loops through the array once per frame + //this might take a couple frames to reach a sorted array but lower frame-times are more important that a perfectly sorted array + //why sorting at all? because the depth buffer does not seem to do its job properly with debug lines, so closer chunks should be rendered later + distance = distance(sortedCache.get(i), x, z); + if (distance > lastDistance) { + Long temp = sortedCache.get(i - 1); + sortedCache.set(i - 1, sortedCache.get(i)); + sortedCache.set(i, temp); + } + lastDistance = distance; + } VertexBuffer.unbind(); RenderSystem.depthFunc(GL11.GL_LEQUAL); @@ -161,6 +194,13 @@ public static synchronized void render(WorldRenderContext context) { } } + private static double distance(long l1, int x1, int z1) { + int x2 = (int) l1; + int z2 = (int) (l1 >> 32); + //technically the sqrt is required for the distance, but it does not change the ordering so i can just skip it + return (x2 - x1) * (x2 - x1) + (z2 - z1) * (z2 - z1); + } + private static void renderBlock(BufferBuilder buffer, BlockPosWithColor blockProps, float opacity) { final float size = 1.0f; final double x = blockProps.pos().getX(), y = blockProps.pos().getY(), z = blockProps.pos().getZ(); diff --git a/src/main/java/pro/mikey/fabric/xray/screens/AbstractScreen.java b/src/main/java/pro/mikey/fabric/xray/screens/AbstractScreen.java index 5e98bec..de97043 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/AbstractScreen.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/AbstractScreen.java @@ -18,14 +18,11 @@ public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { this.renderBackground(matrices); super.render(matrices, mouseX, mouseY, delta); - // RenderSystem.pushMatrix(); - // RenderSystem.translatef(0.0F, 0.0F, 100.0F); RenderSystem.setShaderTexture(0, TEXTURE); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); int i = (this.width - 147) / 2; int j = (this.height - 166) / 2; this.blit(matrices, i, j, 1, 1, 147, 166); - // RenderSystem.popMatrix(); } } diff --git a/src/main/java/pro/mikey/fabric/xray/screens/MainScreen.java b/src/main/java/pro/mikey/fabric/xray/screens/MainScreen.java index 0825ae8..07e354f 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/MainScreen.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/MainScreen.java @@ -23,11 +23,6 @@ public MainScreen() { } } -// @Override -// public void init(MinecraftClient client, int width, int height) { -// super.init(client, width, height); -// } - @Override public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { super.render(matrices, mouseX, mouseY, delta); diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiAddBlock.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiAddBlock.java index 3680bbc..580aa19 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiAddBlock.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiAddBlock.java @@ -7,7 +7,6 @@ import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import pro.mikey.fabric.xray.records.BasicColor; import pro.mikey.fabric.xray.records.BlockEntry; @@ -23,12 +22,9 @@ public class GuiAddBlock extends GuiBase { private final Supplier previousScreenCallback; private BlockState selectBlock; private EditBox oreName; - private Button addBtn; private RatioSliderWidget redSlider; private RatioSliderWidget greenSlider; private RatioSliderWidget blueSlider; - private Button changeDefaultState; - private BlockState lastState; private BlockGroup group; private boolean oreNameCleared = false; @@ -36,7 +32,6 @@ public class GuiAddBlock extends GuiBase { super(false); this.group = group; this.selectBlock = selectedBlock; - this.lastState = null; this.previousScreenCallback = previousScreenCallback; this.itemStack = new ItemStack(this.selectBlock.getBlock(), 1); } @@ -45,17 +40,17 @@ public class GuiAddBlock extends GuiBase { public void init() { // Called when the gui should be (re)created boolean isDefaultState = this.selectBlock == this.selectBlock.getBlock().defaultBlockState(); - this.addRenderableWidget(this.changeDefaultState = new Button.Builder(Component.literal(isDefaultState ? "Already scanning for all states" : "Scan for all block states"), button -> { - this.lastState = this.selectBlock; + Button changeDefaultState; + this.addRenderableWidget(changeDefaultState = new Button.Builder(Component.literal(isDefaultState ? "Already scanning for all states" : "Scan for all block states"), button -> { this.selectBlock = this.selectBlock.getBlock().defaultBlockState(); button.active = false; - }).pos(this.getWidth() / 2 - 100, this.getHeight() / 2 + 60).size(202,20).build()); + }).pos(this.getWidth() / 2 - 100, this.getHeight() / 2 + 60).size(202, 20).build()); if (isDefaultState) { - this.changeDefaultState.active = false; + changeDefaultState.active = false; } - this.addRenderableWidget(this.addBtn = new Button.Builder(Component.translatable("xray.single.add"), button -> { + this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.add"), button -> { this.onClose(); group = group != null ? group : new BlockGroup("default", new ArrayList<>(), 1, true); group.entries().add(new BlockEntry(this.selectBlock, this.oreName.getValue(), new BasicColor((int) (this.redSlider.getValue() * 255), (int) (this.greenSlider.getValue() * 255), (int) (this.blueSlider.getValue() * 255)), group.entries().size() + 1, this.selectBlock == this.selectBlock.getBlock().defaultBlockState(), true)); @@ -81,7 +76,7 @@ public void init() { this.addRenderableWidget(this.redSlider); this.addRenderableWidget(this.greenSlider); this.addRenderableWidget(this.blueSlider); - this.addRenderableWidget(this.changeDefaultState); + this.addRenderableWidget(changeDefaultState); } @Override diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBase.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBase.java index 5ef1bba..94df577 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBase.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBase.java @@ -4,7 +4,6 @@ import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; @@ -29,8 +28,8 @@ public abstract class GuiBase extends Screen { abstract void renderExtra(PoseStack stack, int x, int y, float partialTicks); @Override - public boolean charTyped(char keyTyped, int __unknown) { - super.charTyped(keyTyped, __unknown); + public boolean charTyped(char keyTyped, int unknown) { + super.charTyped(keyTyped, unknown); if (keyTyped == 1 && this.getMinecraft().player != null) { this.getMinecraft().player.clientSideCloseContainer(); diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockList.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockList.java index 184fbba..eff30bd 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockList.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockList.java @@ -85,9 +85,9 @@ public boolean mouseClicked(double x, double y, int button) { } @Override - public boolean mouseScrolled(double p_mouseScrolled_1_, double p_mouseScrolled_3_, double p_mouseScrolled_5_) { - this.blockList.mouseScrolled(p_mouseScrolled_1_, p_mouseScrolled_3_, p_mouseScrolled_5_); - return super.mouseScrolled(p_mouseScrolled_1_, p_mouseScrolled_3_, p_mouseScrolled_5_); + public boolean mouseScrolled(double pMouseScrolled1, double pMouseScrolled2, double pMouseScrolled3) { + this.blockList.mouseScrolled(pMouseScrolled1, pMouseScrolled2, pMouseScrolled3); + return super.mouseScrolled(pMouseScrolled1, pMouseScrolled2, pMouseScrolled3); } static class ScrollingBlockList extends ScrollingList { @@ -130,7 +130,7 @@ BlockWithStack getBlock() { } @Override - public void render(PoseStack stack, int entryIdx, int top, int left, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean p_194999_5_, float partialTicks) { + public void render(PoseStack stack, int entryIdx, int top, int left, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean boolean5, float partialTicks) { Font font = this.parent.minecraft.font; ResourceLocation resource = BuiltInRegistries.BLOCK.getKey(this.block.block()); @@ -143,7 +143,7 @@ public void render(PoseStack stack, int entryIdx, int top, int left, int entryWi } @Override - public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int p_mouseClicked_5_) { + public boolean mouseClicked(double pMouseClicked1, double pMouseClicked3, int pMouseClicked5) { this.parent.setSelected(this); return false; } diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java index 15c76aa..0552161 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiBlockSelectionScreen.java @@ -10,22 +10,17 @@ import net.minecraft.client.gui.components.Tooltip; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.player.LocalPlayer; -import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.InteractionHand; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import pro.mikey.fabric.xray.ScanController; -import pro.mikey.fabric.xray.StateSettings; import pro.mikey.fabric.xray.XRay; -import pro.mikey.fabric.xray.records.BasicColor; import pro.mikey.fabric.xray.records.BlockEntry; import pro.mikey.fabric.xray.records.BlockGroup; import pro.mikey.fabric.xray.storage.BlockStore; @@ -34,15 +29,10 @@ import java.awt.*; import java.util.List; import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; public class GuiBlockSelectionScreen extends GuiBase { - private static final List ORE_TAGS = List.of(Blocks.GOLD_ORE, Blocks.IRON_ORE, Blocks.DIAMOND_ORE, Blocks.REDSTONE_ORE, Blocks.LAPIS_ORE, Blocks.COAL_ORE, Blocks.EMERALD_ORE, Blocks.COPPER_ORE, Blocks.DEEPSLATE_GOLD_ORE, Blocks.DEEPSLATE_IRON_ORE, Blocks.DEEPSLATE_DIAMOND_ORE, Blocks.DEEPSLATE_REDSTONE_ORE, Blocks.DEEPSLATE_LAPIS_ORE, Blocks.DEEPSLATE_COAL_ORE, Blocks.DEEPSLATE_EMERALD_ORE, Blocks.DEEPSLATE_COPPER_ORE, Blocks.NETHER_GOLD_ORE, Blocks.ANCIENT_DEBRIS); - private static final ResourceLocation CIRCLE = new ResourceLocation(XRay.PREFIX_GUI + "circle.png"); - public ItemRenderer render; - private Button distButtons; private EditBox search; private String lastSearch = ""; private List itemList; @@ -62,9 +52,6 @@ public void init() { return; } - this.render = this.itemRenderer; -// this.buttons.clear(); - this.scrollList = new ScrollingBlockList((this.getWidth() / 2) - 37, this.getHeight() / 2 + 10, 203, 185, this.itemList, this); this.addRenderableWidget(this.scrollList); @@ -108,11 +95,11 @@ public void init() { try { HitResult look = player.pick(100, 1f, false); - if (look.getType() == BlockHitResult.Type.BLOCK) { + if (look.getType() == HitResult.Type.BLOCK) { BlockState state = this.minecraft.level.getBlockState(((BlockHitResult) look).getBlockPos()); player.clientSideCloseContainer(); - this.minecraft.setScreen(new GuiAddBlock(state,group, () -> new GuiBlockSelectionScreen(group))); + this.minecraft.setScreen(new GuiAddBlock(state, group, () -> new GuiBlockSelectionScreen(group))); } else { player.displayClientMessage(Component.literal("[XRay] " + I18n.get("xray.message.nothing_infront")), false); } @@ -195,7 +182,7 @@ public void onClose() { SettingsStore.getInstance().write(); BlockStore.getInstance().write(); BlockStore.getInstance().updateCache(); - ScanController.RebuildCache(); + ScanController.reBuildCache(); super.onClose(); } @@ -214,22 +201,19 @@ void setSelected(BlockSlot entry, int mouse) { return; } - if (GuiBlockSelectionScreen.hasShiftDown() || mouse==1) { + if (GuiBlockSelectionScreen.hasShiftDown() || mouse == 1) { this.minecraft.player.clientSideCloseContainer(); - this.minecraft.setScreen(new GuiEdit(entry.block,this.parent.group)); + this.minecraft.setScreen(new GuiEdit(entry.block, this.parent.group)); return; } - try { - BlockGroup group = BlockStore.getInstance().getByName(this.parent.group.name()); - int index = group.entries().indexOf(entry.getBlock()); - BlockEntry blockEntry = group.entries().get(index); - blockEntry.setActive(!blockEntry.isActive()); - group.entries().set(index, blockEntry); - BlockStore.getInstance().write(); - BlockStore.getInstance().updateCache(); - } catch (Exception ignored) { - } + BlockGroup group = BlockStore.getInstance().getByName(this.parent.group.name()); + int index = group.entries().indexOf(entry.getBlock()); + BlockEntry blockEntry = group.entries().get(index); + blockEntry.setActive(!blockEntry.isActive()); + group.entries().set(index, blockEntry); + BlockStore.getInstance().write(); + BlockStore.getInstance().updateCache(); } void updateEntries(List blocks) { @@ -242,7 +226,7 @@ public Optional getChildAt(double mouseX, double mouseY) { return Optional.empty(); } - public class BlockSlot extends Entry { + public static class BlockSlot extends Entry { BlockEntry block; ScrollingBlockList parent; @@ -256,7 +240,7 @@ public BlockEntry getBlock() { } @Override - public void render(PoseStack stack, int entryIdx, int top, int left, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean p_194999_5_, float partialTicks) { + public void render(PoseStack stack, int entryIdx, int top, int left, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean boolean5, float partialTicks) { BlockEntry blockData = this.block; Font font = this.parent.minecraft.font; @@ -284,7 +268,7 @@ public void render(PoseStack stack, int entryIdx, int top, int left, int entryWi } @Override - public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int mouse) { + public boolean mouseClicked(double pMouseClicked1, double pMouseClicked3, int mouse) { this.parent.setSelected(this, mouse); return false; } diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiCategoryEdit.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiCategoryEdit.java index 29631be..182df23 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiCategoryEdit.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiCategoryEdit.java @@ -29,12 +29,9 @@ public class GuiCategoryEdit extends GuiBase { public void init() { this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.delete"), b -> { - try { - BlockStore.getInstance().get().remove(group); - BlockStore.getInstance().write(); - BlockStore.getInstance().updateCache(); - } catch (Exception e) { - } + BlockStore.getInstance().get().remove(group); + BlockStore.getInstance().write(); + BlockStore.getInstance().updateCache(); this.getMinecraft().setScreen(new GuiSelectionScreen()); }).pos((this.getWidth() / 2) + 78, this.getHeight() / 2 - 60).size(120, 20).build()); diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java index 467153b..14130c7 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java @@ -13,12 +13,11 @@ public class GuiEdit extends GuiBase { private final BlockEntry block; + private final BlockGroup group; private EditBox oreName; private RatioSliderWidget redSlider; private RatioSliderWidget greenSlider; private RatioSliderWidget blueSlider; - private Button changeDefaultState; - private BlockGroup group; private BlockState lastState; GuiEdit(BlockEntry block, BlockGroup group) { @@ -30,22 +29,20 @@ public class GuiEdit extends GuiBase { @Override public void init() { - this.addRenderableWidget(this.changeDefaultState = new Button.Builder( Component.literal(this.block.isDefault() ? "Already scanning for all states" : "Scan for all block states"), button -> { + Button changeDefaultState; + this.addRenderableWidget(changeDefaultState = new Button.Builder(Component.literal(this.block.isDefault() ? "Already scanning for all states" : "Scan for all block states"), button -> { this.lastState = this.block.getState(); this.block.setState(this.block.getState().getBlock().defaultBlockState()); button.active = false; }).pos(this.getWidth() / 2 - 138, this.getHeight() / 2 + 60).size(202, 20).build()); if (this.block.isDefault()) { - this.changeDefaultState.active = false; + changeDefaultState.active = false; } this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.delete"), b -> { - try { - group.entries().remove(block); - group.save(); - } catch (Exception e) { - } + group.entries().remove(block); + group.save(); this.getMinecraft().setScreen(new GuiBlockSelectionScreen(group)); }).pos((this.getWidth() / 2) + 78, this.getHeight() / 2 - 60).size(120, 20).build()); @@ -53,16 +50,13 @@ public void init() { this.getMinecraft().setScreen(new GuiBlockSelectionScreen(group)); }).pos((this.getWidth() / 2) + 78, this.getHeight() / 2 + 58).size(120, 20).build()); this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.save"), b -> { - try { - BlockEntry entry = block; - entry.setName(this.oreName.getValue()); - entry.setColor(new BasicColor((int) (this.redSlider.getValue() * 255), (int) (this.greenSlider.getValue() * 255), (int) (this.blueSlider.getValue() * 255))); - entry.setState(this.block.getState()); - entry.setDefault(this.lastState != null); - if(!group.entries().contains(entry)) group.entries().add(entry); - this.group.save(); - } catch (Exception ignored) { - } // lazy catching for basic failures + BlockEntry entry = block; + entry.setName(this.oreName.getValue()); + entry.setColor(new BasicColor((int) (this.redSlider.getValue() * 255), (int) (this.greenSlider.getValue() * 255), (int) (this.blueSlider.getValue() * 255))); + entry.setState(this.block.getState()); + entry.setDefault(this.lastState != null); + if (!group.entries().contains(entry)) group.entries().add(entry); + this.group.save(); this.getMinecraft().setScreen(new GuiBlockSelectionScreen(group)); }).pos(this.getWidth() / 2 - 138, this.getHeight() / 2 + 83).size(202, 20).build()); diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiOverlay.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiOverlay.java index d3ce5b0..271cd64 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiOverlay.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiOverlay.java @@ -3,6 +3,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiComponent; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.resources.language.I18n; import net.minecraft.resources.ResourceLocation; @@ -12,7 +13,7 @@ public class GuiOverlay { private static final ResourceLocation circle = new ResourceLocation(XRay.PREFIX_GUI + "circle.png"); - public static void RenderGameOverlayEvent(PoseStack matrixStack, float delta) { + public static void renderGameOverlayEvent(PoseStack matrixStack, float delta) { // Draw Indicator if (!SettingsStore.getInstance().get().isActive() || !SettingsStore.getInstance().get().showOverlay()) { return; @@ -20,7 +21,8 @@ public static void RenderGameOverlayEvent(PoseStack matrixStack, float delta) { boolean renderDebug = Minecraft.getInstance().options.renderDebug; - int x = 5, y = 5; + int x = 5; + int y = 5; if (renderDebug) { x = Minecraft.getInstance().getWindow().getGuiScaledWidth() - 10; y = Minecraft.getInstance().getWindow().getGuiScaledHeight() - 10; @@ -28,7 +30,7 @@ public static void RenderGameOverlayEvent(PoseStack matrixStack, float delta) { RenderSystem.setShaderColor(0, 1f, 0, 1f); RenderSystem.setShaderTexture(0, circle); - Screen.blit(matrixStack, x, y, 0f, 0f, 5, 5, 5, 5); + GuiComponent.blit(matrixStack, x, y, 0f, 0f, 5, 5, 5, 5); int width = Minecraft.getInstance().font.width(I18n.get("xray.overlay")); Minecraft.getInstance() diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java index ccbd845..a314c96 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java @@ -10,19 +10,11 @@ import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.components.Tooltip; import net.minecraft.client.gui.components.events.GuiEventListener; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.HitResult; import pro.mikey.fabric.xray.ScanController; import pro.mikey.fabric.xray.StateSettings; import pro.mikey.fabric.xray.XRay; @@ -46,7 +38,6 @@ public class GuiSelectionScreen extends GuiBase { private static final ResourceLocation CIRCLE = new ResourceLocation(XRay.PREFIX_GUI + "circle.png"); private final List originalList; - public ItemRenderer render; private Button distButtons; private EditBox search; private String lastSearch = ""; @@ -103,9 +94,6 @@ public void init() { return; } - this.render = this.itemRenderer; -// this.buttons.clear(); - this.scrollList = new ScrollingCategoryList((this.getWidth() / 2) - 37, this.getHeight() / 2 + 10, 203, 185, this.itemList, this); this.addRenderableWidget(this.scrollList); @@ -197,7 +185,7 @@ public void onClose() { SettingsStore.getInstance().write(); BlockStore.getInstance().write(); BlockStore.getInstance().updateCache(); - ScanController.RebuildCache(true); + ScanController.reBuildCache(true); super.onClose(); } @@ -216,20 +204,17 @@ void setSelected(CategoryEntry entry, int mouse) { return; } - if (GuiSelectionScreen.hasShiftDown() || mouse == 1 ) { + if (GuiSelectionScreen.hasShiftDown() || mouse == 1) { this.minecraft.player.clientSideCloseContainer(); this.minecraft.setScreen(new GuiBlockSelectionScreen(entry.getGroup())); return; } - try { - BlockStore.getInstance().get().stream().filter(group -> (group.getName().equals(entry.block.name()))).findFirst().ifPresent(group -> { - group.setActive(!group.active()); - }); - BlockStore.getInstance().write(); - BlockStore.getInstance().updateCache(); - } catch (Exception ignored) { - } + BlockStore.getInstance().get().stream().filter(group -> (group.getName().equals(entry.block.name()))).findFirst().ifPresent(group -> { + group.setActive(!group.active()); + }); + BlockStore.getInstance().write(); + BlockStore.getInstance().updateCache(); } void updateEntries(List blocks) { @@ -242,7 +227,7 @@ public Optional getChildAt(double mouseX, double mouseY) { return Optional.empty(); } - public class CategoryEntry extends AbstractSelectionList.Entry { + public static class CategoryEntry extends AbstractSelectionList.Entry { BlockGroup block; ScrollingCategoryList parent; @@ -256,7 +241,7 @@ public BlockGroup getGroup() { } @Override - public void render(PoseStack stack, int entryIdx, int top, int left, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean p_194999_5_, float partialTicks) { + public void render(PoseStack stack, int entryIdx, int top, int left, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean unknown, float partialTicks) { BlockGroup group = this.block; BlockEntry display = group.entries().stream().findFirst().orElse(BlockEntry.getAir()); @@ -285,7 +270,7 @@ public void render(PoseStack stack, int entryIdx, int top, int left, int entryWi } @Override - public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int mouse) { + public boolean mouseClicked(double pMouseClicked1, double pMouseClicked3, int mouse) { this.parent.setSelected(this, mouse); return false; } diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/RatioSliderWidget.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/RatioSliderWidget.java index 9a19298..d46d341 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/RatioSliderWidget.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/RatioSliderWidget.java @@ -2,7 +2,6 @@ import net.minecraft.client.gui.components.AbstractSliderButton; import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.contents.LiteralContents; public class RatioSliderWidget extends AbstractSliderButton { private final Component message; diff --git a/src/main/java/pro/mikey/fabric/xray/screens/forge/ScrollingList.java b/src/main/java/pro/mikey/fabric/xray/screens/forge/ScrollingList.java index bfce5fb..3e88ea6 100644 --- a/src/main/java/pro/mikey/fabric/xray/screens/forge/ScrollingList.java +++ b/src/main/java/pro/mikey/fabric/xray/screens/forge/ScrollingList.java @@ -7,7 +7,7 @@ import org.lwjgl.opengl.GL11; /** - * A bare bones implementation of the without the background or borders. With GL_SCISSOR to crop out + * A bare-bones implementation of the without the background or borders. With GL_SCISSOR to crop out * the overflow * *

This is how an abstract implementation should look... :cry: diff --git a/src/main/java/pro/mikey/fabric/xray/storage/BlockStore.java b/src/main/java/pro/mikey/fabric/xray/storage/BlockStore.java index 76d627e..bcdde19 100644 --- a/src/main/java/pro/mikey/fabric/xray/storage/BlockStore.java +++ b/src/main/java/pro/mikey/fabric/xray/storage/BlockStore.java @@ -21,7 +21,7 @@ private BlockStore() { super("blocks"); this.blockEntries = this.read(); - this.updateCache(this.blockEntries); // ensure the cache is up to date + this.updateCache(this.blockEntries); // ensure the cache is up-to-date } public static BlockStore getInstance() { diff --git a/src/main/java/pro/mikey/fabric/xray/storage/Store.java b/src/main/java/pro/mikey/fabric/xray/storage/Store.java index 3e6ba81..27849e8 100644 --- a/src/main/java/pro/mikey/fabric/xray/storage/Store.java +++ b/src/main/java/pro/mikey/fabric/xray/storage/Store.java @@ -32,16 +32,13 @@ public Gson getGson() { public T read() { Gson gson = this.getGson(); - try { - try { - return gson.fromJson(new FileReader(this.file), this.getType()); - } catch (JsonIOException | JsonSyntaxException e) { - XRay.LOGGER.fatal("Fatal error with json loading on {}.json", this.name, e); - } - } catch (FileNotFoundException ignored) { - this.justCreated = true; - + try (FileReader reader = new FileReader(this.file)) { + return gson.fromJson(reader, this.getType()); + } catch (JsonIOException | JsonSyntaxException e) { + XRay.LOGGER.fatal("Fatal error with json loading on {}.json", this.name, e); + } catch (IOException ignored) { // Write a blank version of the file + this.justCreated = true; if (new File(CONFIG_PATH).mkdirs()) { this.write(true); } @@ -54,7 +51,7 @@ public void write() { this.write(false); } - private void write(Boolean firstWrite) { + private void write(boolean firstWrite) { Gson gson = this.getGson(); try { diff --git a/src/main/java/pro/mikey/fabric/xray/tasks/AddChunkTask.java b/src/main/java/pro/mikey/fabric/xray/tasks/AddChunkTask.java deleted file mode 100644 index 2f9c6f9..0000000 --- a/src/main/java/pro/mikey/fabric/xray/tasks/AddChunkTask.java +++ /dev/null @@ -1,80 +0,0 @@ -package pro.mikey.fabric.xray.tasks; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.LavaFluid; -import org.jetbrains.annotations.Nullable; -import pro.mikey.fabric.xray.cache.BlockSearchEntry; -import pro.mikey.fabric.xray.records.BasicColor; -import pro.mikey.fabric.xray.records.BlockPosWithColor; -import pro.mikey.fabric.xray.render.RenderOutlines; -import pro.mikey.fabric.xray.storage.BlockStore; -import pro.mikey.fabric.xray.storage.SettingsStore; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -/** - * This task is responsible for taking a chunk and adding the blocks to the RenderOutlines to be rendered. - * This task is added to the threadpool and executed by a thread via the Scancontroller class. - */ -public class AddChunkTask implements Runnable { - - private ChunkPos chunkPos; - - public AddChunkTask(ChunkPos chunkPos){ - this.chunkPos = chunkPos; - } - @Override - public void run() { - Thread.currentThread().setPriority(1); - List toAdd = AddChunk(chunkPos); - if(Minecraft.getInstance().player.clientLevel.getChunkSource().getChunk(chunkPos.x,chunkPos.z,false)!=null) { - RenderOutlines.addChunk(chunkPos.toLong(),toAdd); - } - else{ - RenderOutlines.removeChunk(chunkPos.toLong()); - } - } - - public static List AddChunk(ChunkPos chunkPos){ - int chunkStartX = chunkPos.x*16; - int chunkStartZ = chunkPos.z*16; - final Level world = Minecraft.getInstance().level; - Set blocks = BlockStore.getInstance().getCache().get(); - int height = world.getHeight(); - List toAdd = new ArrayList<>(); - for (int k = chunkStartX; k < chunkStartX + 16; k++) { - for (int l = chunkStartZ; l < chunkStartZ + 16; l++) { - for (int m = world.getMinBuildHeight(); m < height + (1 << 4); m++) { - BlockPos pos = new BlockPos(k, m, l); - BasicColor validBlock = isValidBlock(pos, world, blocks); - if (validBlock != null) { - toAdd.add(new BlockPosWithColor(pos, validBlock)); - } - } - } - } - return toAdd; - } - - @Nullable - public static BasicColor isValidBlock(BlockPos pos, Level world, Set blocks) { - BlockState state = world.getBlockState(pos); - if (state.isAir()) { - return null; - } - - BlockState defaultState = state.getBlock().defaultBlockState(); - - return blocks.stream() - .filter(localState -> localState.isDefault() && defaultState == localState.getState() || !localState.isDefault() && state == localState.getState()) - .findFirst() - .map(BlockSearchEntry::getColor) - .orElse(null); - } -} diff --git a/src/main/java/pro/mikey/fabric/xray/tasks/ReBuildCache.java b/src/main/java/pro/mikey/fabric/xray/tasks/ReBuildCache.java index 8da5011..e06a0ea 100644 --- a/src/main/java/pro/mikey/fabric/xray/tasks/ReBuildCache.java +++ b/src/main/java/pro/mikey/fabric/xray/tasks/ReBuildCache.java @@ -15,13 +15,12 @@ * This task is added to the threadpool and executed by a thread via the Scancontroller class. */ public class ReBuildCache implements Runnable{ - public ReBuildCache(){ - } - private class ChunkObject{ - ChunkObject(ChunkPos pos,Direction direction){ - this.direction=direction; - this.pos=pos; + private static class ChunkObject { + ChunkObject(ChunkPos pos, Direction direction) { + this.direction = direction; + this.pos = pos; } + public ChunkPos pos; public Direction direction; } @@ -29,44 +28,41 @@ private class ChunkObject{ @Override public void run() { List toScan = new ArrayList<>(); + assert Minecraft.getInstance().player != null; Vec3 position = Minecraft.getInstance().player.position(); - toScan.add(new ChunkObject(new ChunkPos((int)position.x/16,(int)position.z/16),Direction.UP)); - toScan.add(new ChunkObject(new ChunkPos((int)position.x/16,(int)position.z/16+1),Direction.EAST)); - toScan.add(new ChunkObject(new ChunkPos((int)position.x/16,(int)position.z/16-1),Direction.WEST)); - toScan.add(new ChunkObject(new ChunkPos((int)position.x/16+1,(int)position.z/16),Direction.NORTH)); - toScan.add(new ChunkObject(new ChunkPos((int)position.x/16-1,(int)position.z/16),Direction.SOUTH)); - while (toScan.size()>0){ + toScan.add(new ChunkObject(new ChunkPos((int) position.x / 16, (int) position.z / 16), Direction.UP)); + toScan.add(new ChunkObject(new ChunkPos((int) position.x / 16, (int) position.z / 16 + 1), Direction.EAST)); + toScan.add(new ChunkObject(new ChunkPos((int) position.x / 16, (int) position.z / 16 - 1), Direction.WEST)); + toScan.add(new ChunkObject(new ChunkPos((int) position.x / 16 + 1, (int) position.z / 16), Direction.NORTH)); + toScan.add(new ChunkObject(new ChunkPos((int) position.x / 16 - 1, (int) position.z / 16), Direction.SOUTH)); + while (!toScan.isEmpty()) { ChunkObject chunkObject = toScan.remove(0); - if(Minecraft.getInstance().player.clientLevel.getChunkSource().getChunk(chunkObject.pos.x,chunkObject.pos.z,false)!=null){ + if (Minecraft.getInstance().player.clientLevel.getChunkSource().getChunk(chunkObject.pos.x, chunkObject.pos.z, false) != null) { ScanController.updateChunk(chunkObject.pos); - switch (chunkObject.direction){ + switch (chunkObject.direction) { case EAST -> { - if(chunkObject.pos.x==(int)position.x/16){ - toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x,chunkObject.pos.z+1),chunkObject.direction)); + if (chunkObject.pos.x == (int) position.x / 16) { + toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x, chunkObject.pos.z + 1), chunkObject.direction)); } - toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x+1,chunkObject.pos.z),chunkObject.direction)); - break; + toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x + 1, chunkObject.pos.z), chunkObject.direction)); } case WEST -> { if(chunkObject.pos.x==(int)position.x/16){ - toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x,chunkObject.pos.z-1),chunkObject.direction)); + toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x, chunkObject.pos.z - 1), chunkObject.direction)); } - toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x-1,chunkObject.pos.z),chunkObject.direction)); - break; + toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x - 1, chunkObject.pos.z), chunkObject.direction)); } case NORTH -> { if(chunkObject.pos.z==(int)position.z/16){ - toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x+1,chunkObject.pos.z),chunkObject.direction)); + toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x + 1, chunkObject.pos.z), chunkObject.direction)); } - toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x,chunkObject.pos.z-1),chunkObject.direction)); - break; + toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x, chunkObject.pos.z - 1), chunkObject.direction)); } case SOUTH -> { - toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x,chunkObject.pos.z+1),chunkObject.direction)); + toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x, chunkObject.pos.z + 1), chunkObject.direction)); if(chunkObject.pos.z==(int)position.z/16){ - toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x-1,chunkObject.pos.z),chunkObject.direction)); + toScan.add(new ChunkObject(new ChunkPos(chunkObject.pos.x - 1, chunkObject.pos.z), chunkObject.direction)); } - break; } } } diff --git a/src/main/java/pro/mikey/fabric/xray/tasks/RemoveChunkTask.java b/src/main/java/pro/mikey/fabric/xray/tasks/RemoveChunkTask.java index 519a2e5..c0373d1 100644 --- a/src/main/java/pro/mikey/fabric/xray/tasks/RemoveChunkTask.java +++ b/src/main/java/pro/mikey/fabric/xray/tasks/RemoveChunkTask.java @@ -8,7 +8,7 @@ * This task is added to the threadpool and executed by a thread via the Scancontroller class. */ public class RemoveChunkTask implements Runnable { - private ChunkPos chunkPos; + private final ChunkPos chunkPos; public RemoveChunkTask(ChunkPos chunkPos){ this.chunkPos = chunkPos; diff --git a/src/main/java/pro/mikey/fabric/xray/tasks/UpdateChunkTask.java b/src/main/java/pro/mikey/fabric/xray/tasks/UpdateChunkTask.java index eda99a8..c00930b 100644 --- a/src/main/java/pro/mikey/fabric/xray/tasks/UpdateChunkTask.java +++ b/src/main/java/pro/mikey/fabric/xray/tasks/UpdateChunkTask.java @@ -1,19 +1,28 @@ package pro.mikey.fabric.xray.tasks; import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; +import pro.mikey.fabric.xray.cache.BlockSearchEntry; +import pro.mikey.fabric.xray.records.BasicColor; import pro.mikey.fabric.xray.records.BlockPosWithColor; import pro.mikey.fabric.xray.render.RenderOutlines; +import pro.mikey.fabric.xray.storage.BlockStore; +import java.util.ArrayList; import java.util.List; +import java.util.Set; /** * This task is responsible for taking a chunk and updating the blocks to the RenderOutlines to be rendered. - * In its current implementation in the RenderOutlines class this does virtually the same as AddChunk - * This task is added to the threadpool and executed by a thread via the Scancontroller class. + * In its current implementation in the RenderOutlines class this does virtually the same as addChunk + * This task is added to the thread pool and executed by a thread via the ScanController class. */ public class UpdateChunkTask implements Runnable{ - private ChunkPos chunkPos; + private final ChunkPos chunkPos; public UpdateChunkTask(ChunkPos chunkPos){ this.chunkPos = chunkPos; @@ -22,13 +31,50 @@ public UpdateChunkTask(ChunkPos chunkPos){ @Override public void run() { Thread.currentThread().setPriority(1); - List toAdd = AddChunkTask.AddChunk(chunkPos); - if(Minecraft.getInstance().player.clientLevel.getChunkSource().getChunk(chunkPos.x,chunkPos.z,false)!=null) { - RenderOutlines.addChunk(chunkPos.toLong(),toAdd); - } - else{ + List toAdd = addChunk(chunkPos); + assert Minecraft.getInstance().player != null; + if (Minecraft.getInstance().player.clientLevel.getChunkSource().getChunk(chunkPos.x, chunkPos.z, false) != null) { + RenderOutlines.addChunk(chunkPos.toLong(), toAdd); + } else { RenderOutlines.removeChunk(chunkPos.toLong()); } } + public static List addChunk(ChunkPos chunkPos) { + int chunkStartX = chunkPos.x * 16; + int chunkStartZ = chunkPos.z * 16; + final Level world = Minecraft.getInstance().level; + Set blocks = BlockStore.getInstance().getCache().get(); + assert world != null; + int height = world.getHeight(); + List toAdd = new ArrayList<>(); + for (int k = chunkStartX; k < chunkStartX + 16; k++) { + for (int l = chunkStartZ; l < chunkStartZ + 16; l++) { + for (int m = world.getMinBuildHeight(); m < height + (1 << 4); m++) { + BlockPos pos = new BlockPos(k, m, l); + BasicColor validBlock = isValidBlock(pos, world, blocks); + if (validBlock != null) { + toAdd.add(new BlockPosWithColor(pos, validBlock)); + } + } + } + } + return toAdd; + } + + @Nullable + public static BasicColor isValidBlock(BlockPos pos, Level world, Set blocks) { + BlockState state = world.getBlockState(pos); + if (state.isAir()) { + return null; + } + + BlockState defaultState = state.getBlock().defaultBlockState(); + + return blocks.stream() + .filter(localState -> localState.isDefault() && defaultState == localState.getState() || !localState.isDefault() && state == localState.getState()) + .findFirst() + .map(BlockSearchEntry::getColor) + .orElse(null); + } } From 5b1237f8b90c393f621d79f39c9dfcdaf1f7a813 Mon Sep 17 00:00:00 2001 From: MartinLaptop Date: Fri, 24 Mar 2023 21:33:20 +0100 Subject: [PATCH 12/14] Fade in and theoretical Renderdistnace Support --- .../fabric/xray/render/RenderOutlines.java | 38 +++++++++++++++++-- .../fabric/xray/tasks/UpdateChunkTask.java | 4 +- .../lang/en_us.json | 2 +- 3 files changed, 38 insertions(+), 6 deletions(-) rename src/main/resources/assets/{advanced-xray-fabric => line-renderer}/lang/en_us.json (95%) diff --git a/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java b/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java index 2c81451..0e03760 100644 --- a/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java +++ b/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java @@ -12,7 +12,9 @@ import net.minecraft.world.phys.Vec3; import org.joml.Matrix4f; import org.joml.Quaternionf; +import org.joml.Vector3f; import org.lwjgl.opengl.GL11; +import pro.mikey.fabric.xray.XRay; import pro.mikey.fabric.xray.records.BlockPosWithColor; import pro.mikey.fabric.xray.storage.SettingsStore; @@ -33,6 +35,10 @@ public class RenderOutlines { * This is the internal Vertexbuffers mapped by chunk so the removal is simple */ private static final Map chunkCache = new HashMap<>(); + /** + * This Map holds the current Alpa value per Chunk for fadeIns + */ + public static Map fadeInMap = new HashMap<>(); /** * This List provides the sorting for the rendering. * I'm not aware of a way to make this faster, as this way im avoiding unnecessarily looping through the list @@ -48,6 +54,16 @@ public class RenderOutlines { */ private static final AtomicBoolean forceclear = new AtomicBoolean(false); + /** + * Render Distance in Chunks + */ + public static int maxRenderDistance = 4; + + /** + * Fade in time for new Chunks in seconds + */ + public static float fadeInSeconds = 1; + private static int canvasLoaded = -1; private static class WorkLoad { @@ -112,6 +128,13 @@ public static synchronized void render(WorldRenderContext context) { if (!SettingsStore.getInstance().get().isActive()) { return; } + double increment = (1.0 / fadeInSeconds) * (Minecraft.getInstance().getDeltaFrameTime()/20); + fadeInMap.forEach((pos,value)->{ + if(value<1){ + fadeInMap.put(pos, (float) Math.min(value + increment, 1.0)); + } + }); + WorkLoad work = workQueue.poll(); if(work!=null){ BufferBuilder bufferBuilder = Tesselator.getInstance().getBuilder(); @@ -128,6 +151,7 @@ public static synchronized void render(WorldRenderContext context) { chunkCache.put(work.chunk, vertexBuffer); sortedCache.add(0, work.chunk); bufferBuilder.discard(); + fadeInMap.put(work.chunk,0f); } int removed = 0; Long toRemove; @@ -168,17 +192,25 @@ public static synchronized void render(WorldRenderContext context) { int z = (int) context.camera().getPosition().z / 16; double distance; double lastDistance = Double.MAX_VALUE; + Matrix4f projectionMatrix = new Matrix4f(context.projectionMatrix()); + Vector3f pos = new Vector3f((float) cameraPos.x,(float)cameraPos.y,(float)cameraPos.z); + Vector3f lookAt = new Vector3f(pos.x+camera.getLookVector().x,pos.y+camera.getLookVector().y,pos.z+camera.getLookVector().z); + + projectionMatrix.lookAt(pos,lookAt,camera.getUpVector()); for (int i = 0; i < sortedCache.size(); i++) { VertexBuffer buf = chunkCache.get(sortedCache.get(i)); - if (buf != null) { + distance = distance(sortedCache.get(i), x, z); + if (buf != null && distance lastDistance) { Long temp = sortedCache.get(i - 1); sortedCache.set(i - 1, sortedCache.get(i)); @@ -198,7 +230,7 @@ private static double distance(long l1, int x1, int z1) { int x2 = (int) l1; int z2 = (int) (l1 >> 32); //technically the sqrt is required for the distance, but it does not change the ordering so i can just skip it - return (x2 - x1) * (x2 - x1) + (z2 - z1) * (z2 - z1); + return Math.sqrt((x2 - x1) * (x2 - x1) + (z2 - z1) * (z2 - z1)); } private static void renderBlock(BufferBuilder buffer, BlockPosWithColor blockProps, float opacity) { diff --git a/src/main/java/pro/mikey/fabric/xray/tasks/UpdateChunkTask.java b/src/main/java/pro/mikey/fabric/xray/tasks/UpdateChunkTask.java index c00930b..9d745c5 100644 --- a/src/main/java/pro/mikey/fabric/xray/tasks/UpdateChunkTask.java +++ b/src/main/java/pro/mikey/fabric/xray/tasks/UpdateChunkTask.java @@ -48,9 +48,9 @@ public static List addChunk(ChunkPos chunkPos) { assert world != null; int height = world.getHeight(); List toAdd = new ArrayList<>(); - for (int k = chunkStartX; k < chunkStartX + 16; k++) { + for (int m = world.getMinBuildHeight(); m < height + (1 << 4); m++) { for (int l = chunkStartZ; l < chunkStartZ + 16; l++) { - for (int m = world.getMinBuildHeight(); m < height + (1 << 4); m++) { + for (int k = chunkStartX; k < chunkStartX + 16; k++) { BlockPos pos = new BlockPos(k, m, l); BasicColor validBlock = isValidBlock(pos, world, blocks); if (validBlock != null) { diff --git a/src/main/resources/assets/advanced-xray-fabric/lang/en_us.json b/src/main/resources/assets/line-renderer/lang/en_us.json similarity index 95% rename from src/main/resources/assets/advanced-xray-fabric/lang/en_us.json rename to src/main/resources/assets/line-renderer/lang/en_us.json index fc3bde4..b50b9de 100644 --- a/src/main/resources/assets/advanced-xray-fabric/lang/en_us.json +++ b/src/main/resources/assets/line-renderer/lang/en_us.json @@ -54,5 +54,5 @@ "xray.tooltips.edit1": "Click to enable / disable", "xray.tooltips.edit2": "Hold shift and click to edit.", "xray.message.help.gui": "To edit a block simply shift click on the block you wish to edit.\nIf you want to enable / disable a block then click on a block\n and it'll toggle on and off.", - "xray.message.help.warning": "As a warning, using any distance over 64 will cause FPS drops due\nto the vast amount of blocks that we have to scan. (It's like 256^3)" + "xray.message.help.warning": "Setting the Threads to high might cause performance issues" } From 56410b350acb30e37cf8bc35661b7d26bde38513 Mon Sep 17 00:00:00 2001 From: MartinLaptop Date: Fri, 24 Mar 2023 21:39:19 +0100 Subject: [PATCH 13/14] BugFix --- .../java/pro/mikey/fabric/xray/render/RenderOutlines.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java b/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java index 0e03760..03c2f68 100644 --- a/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java +++ b/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java @@ -7,14 +7,12 @@ import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.RenderBuffers; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.phys.Vec3; import org.joml.Matrix4f; import org.joml.Quaternionf; import org.joml.Vector3f; import org.lwjgl.opengl.GL11; -import pro.mikey.fabric.xray.XRay; import pro.mikey.fabric.xray.records.BlockPosWithColor; import pro.mikey.fabric.xray.storage.SettingsStore; @@ -207,6 +205,9 @@ public static synchronized void render(WorldRenderContext context) { buf.drawWithShader(poseStack.last().pose(), new Matrix4f(context.projectionMatrix()), RenderSystem.getShader()); RenderSystem.setShaderColor(color[0],color[1],color[2],color[3]); } + else{ + fadeInMap.put(sortedCache.get(i),0f); + } //this is a semi-bubble-sort algorithm //it only loops through the array once per frame //this might take a couple frames to reach a sorted array but lower frame-times are more important that a perfectly sorted array From 06f9bec7c1d5880d8989a217db91b1210fc3c1b6 Mon Sep 17 00:00:00 2001 From: MartinLaptop Date: Fri, 24 Mar 2023 22:06:24 +0100 Subject: [PATCH 14/14] betterFade --- .../java/pro/mikey/fabric/xray/render/RenderOutlines.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java b/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java index 03c2f68..4b56d3e 100644 --- a/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java +++ b/src/main/java/pro/mikey/fabric/xray/render/RenderOutlines.java @@ -13,6 +13,7 @@ import org.joml.Quaternionf; import org.joml.Vector3f; import org.lwjgl.opengl.GL11; +import pro.mikey.fabric.xray.XRay; import pro.mikey.fabric.xray.records.BlockPosWithColor; import pro.mikey.fabric.xray.storage.SettingsStore; @@ -201,7 +202,9 @@ public static synchronized void render(WorldRenderContext context) { if (buf != null && distance