From bd0869a570977dc4eb9b79aad2867c205a8dfc14 Mon Sep 17 00:00:00 2001 From: Benjamin-Norton Date: Wed, 17 May 2023 23:23:13 -0400 Subject: [PATCH] Add nearby block highlighting --- gradle.properties | 2 +- .../randoassistant/config/Config.java | 4 ++ .../randoassistant/config/ConfigManager.java | 1 + .../event/client/EventManager.java | 48 +++++++++++++++++++ .../randoassistant/render/overlay/Cuboid.java | 1 + .../render/overlay/RenderManager.java | 21 ++++++-- .../screen/LootBookSettingsWidget.java | 47 ++++++++++++++++-- .../randoassistant/tracking/Tracker.java | 9 +++- .../tracking/trackable/TrackableCrawler.java | 2 +- .../randoassistant.client.mixins.json | 6 +-- .../assets/randoassistant/lang/en_us.json | 4 +- 11 files changed, 129 insertions(+), 16 deletions(-) diff --git a/gradle.properties b/gradle.properties index 8e47cba..4329e05 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ yarn_mappings=1.19.4+build.2 loader_version=0.14.19 # Mod Properties -mod_version=1.2.1 +mod_version=1.2.2 maven_group=com.bawnorton.randoassistant archives_base_name=randoassistant diff --git a/src/client/java/com/bawnorton/randoassistant/config/Config.java b/src/client/java/com/bawnorton/randoassistant/config/Config.java index 9b1699c..175bd52 100644 --- a/src/client/java/com/bawnorton/randoassistant/config/Config.java +++ b/src/client/java/com/bawnorton/randoassistant/config/Config.java @@ -30,6 +30,10 @@ public class Config { @SerializedName("search_depth") public Integer searchDepth; + @Expose + @SerializedName("highlight_radius") + public Integer highlightRadius; + private Config() { } diff --git a/src/client/java/com/bawnorton/randoassistant/config/ConfigManager.java b/src/client/java/com/bawnorton/randoassistant/config/ConfigManager.java index 4dcae52..120cf15 100644 --- a/src/client/java/com/bawnorton/randoassistant/config/ConfigManager.java +++ b/src/client/java/com/bawnorton/randoassistant/config/ConfigManager.java @@ -23,6 +23,7 @@ public static void loadConfig() { if (config.enableOverride == null) config.enableOverride = false; if (config.randomizeColours == null) config.randomizeColours = false; if (config.searchDepth == null) config.searchDepth = 6; + if (config.highlightRadius == null) config.highlightRadius = 5; Config.update(config); save(); diff --git a/src/client/java/com/bawnorton/randoassistant/event/client/EventManager.java b/src/client/java/com/bawnorton/randoassistant/event/client/EventManager.java index 0a666e9..fc831f9 100644 --- a/src/client/java/com/bawnorton/randoassistant/event/client/EventManager.java +++ b/src/client/java/com/bawnorton/randoassistant/event/client/EventManager.java @@ -3,11 +3,33 @@ import com.bawnorton.randoassistant.RandoAssistantClient; import com.bawnorton.randoassistant.config.Config; import com.bawnorton.randoassistant.networking.client.Networking; +import com.bawnorton.randoassistant.render.overlay.Colour; +import com.bawnorton.randoassistant.render.overlay.Cube; +import com.bawnorton.randoassistant.render.overlay.Cuboid; +import com.bawnorton.randoassistant.render.overlay.RenderManager; import com.bawnorton.randoassistant.tracking.Tracker; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.registry.Registries; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.shape.VoxelShape; +import org.lwjgl.glfw.GLFW; public class EventManager { + public static KeyBinding highlight = KeyBindingHelper.registerKeyBinding(new KeyBinding( + "key.randoassistant.highlight", + GLFW.GLFW_KEY_V, + "key.categories.randoassistant" + )); + public static void init() { ClientPlayConnectionEvents.JOIN.register((handler, sender, server) -> { RandoAssistantClient.isInstalledOnServer = false; @@ -15,5 +37,31 @@ public static void init() { Tracker.getInstance().clear(); Networking.requestHandshakePacket(); }); + + ClientTickEvents.END_CLIENT_TICK.register(client -> { + RenderManager.clearRenderers(); + if(highlight.isPressed()) { + ClientPlayerEntity player = client.player; + if(player == null) return; + BlockPos pos = player.getBlockPos(); + int radius = Config.getInstance().highlightRadius; + for(int x = -radius; x < radius; x++) { + for(int y = -radius; y < radius; y++) { + for(int z = -radius; z < radius; z++) { + BlockPos blockPos = pos.add(x, y, z); + if(client.world == null) return; + + BlockState state = client.world.getBlockState(blockPos); + Block block = state.getBlock(); + Identifier id = Registries.BLOCK.getId(block); + if(Tracker.getInstance().isEnabled(id)) continue; + + Cube cube = new Cube(blockPos, Colour.fromHex(0xFF0000)); + RenderManager.addRenderer(blockPos, cube); + } + } + } + } + }); } } diff --git a/src/client/java/com/bawnorton/randoassistant/render/overlay/Cuboid.java b/src/client/java/com/bawnorton/randoassistant/render/overlay/Cuboid.java index 81f8150..dd50461 100644 --- a/src/client/java/com/bawnorton/randoassistant/render/overlay/Cuboid.java +++ b/src/client/java/com/bawnorton/randoassistant/render/overlay/Cuboid.java @@ -3,6 +3,7 @@ import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3i; diff --git a/src/client/java/com/bawnorton/randoassistant/render/overlay/RenderManager.java b/src/client/java/com/bawnorton/randoassistant/render/overlay/RenderManager.java index 47a7c2f..02b08bf 100644 --- a/src/client/java/com/bawnorton/randoassistant/render/overlay/RenderManager.java +++ b/src/client/java/com/bawnorton/randoassistant/render/overlay/RenderManager.java @@ -2,10 +2,14 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.*; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.registry.tag.FluidTags; +import net.minecraft.registry.tag.TagKey; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; @@ -33,7 +37,7 @@ public static void renderRenderers(MatrixStack matrixStack, Camera camera) { RenderSystem.setShader(GameRenderer::getPositionColorProgram); RenderSystem.enableBlend(); RenderSystem.blendFuncSeparate(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SrcFactor.ONE, GlStateManager.DstFactor.ZERO); - RenderSystem.lineWidth(2.0f); + RenderSystem.lineWidth(20.0f); buffer.begin(VertexFormat.DrawMode.DEBUG_LINES, VertexFormats.POSITION_COLOR); @@ -59,10 +63,17 @@ public static void renderRenderers(MatrixStack matrixStack, Camera camera) { } private static boolean isValidBlock(BlockPos pos) { - BlockEntity blockEntity = null; + Block block = null; if (client.world != null) { - blockEntity = client.world.getBlockEntity(pos); + BlockState state = client.world.getBlockState(pos); + if(state.getFluidState().isEmpty() && !state.isAir()) { + block = state.getBlock(); + } } - return blockEntity != null; + return block != null; + } + + public static void clearRenderers() { + renderers.clear(); } } diff --git a/src/client/java/com/bawnorton/randoassistant/screen/LootBookSettingsWidget.java b/src/client/java/com/bawnorton/randoassistant/screen/LootBookSettingsWidget.java index 452c57d..4e52de5 100644 --- a/src/client/java/com/bawnorton/randoassistant/screen/LootBookSettingsWidget.java +++ b/src/client/java/com/bawnorton/randoassistant/screen/LootBookSettingsWidget.java @@ -3,6 +3,7 @@ import com.bawnorton.randoassistant.RandoAssistantClient; import com.bawnorton.randoassistant.config.Config; import com.bawnorton.randoassistant.config.ConfigManager; +import com.bawnorton.randoassistant.event.client.EventManager; import com.bawnorton.randoassistant.tracking.Tracker; import com.bawnorton.randoassistant.tracking.trackable.TrackableCrawler; import net.minecraft.client.MinecraftClient; @@ -12,6 +13,8 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; +import java.util.function.Consumer; + import static com.bawnorton.randoassistant.screen.LootTableGraphWidget.HEIGHT; public class LootBookSettingsWidget { @@ -25,6 +28,7 @@ public class LootBookSettingsWidget { private final ToggleButtonWidget enableOverride; private final ToggleButtonWidget randomizeColours; private final TextFieldWidget searchDepth; + private final TextFieldWidget highlightRadius; public LootBookSettingsWidget(MinecraftClient client, int x, int y) { this.client = client; @@ -39,6 +43,7 @@ public LootBookSettingsWidget(MinecraftClient client, int x, int y) { silkTouchStarIcons = createButton(x, y + 20, "Display star icons on broken but not silk-touched blocks\n\nRequires §bUnbroken Stars", Config.getInstance().silktouchUnbrokenBlockIcon); enableOverride = createButton(x, y + 40, "Enable all undiscovered loot tables\n\n§7This is not permanent", Config.getInstance().enableOverride); randomizeColours = createButton(x, y + 60, "Randomize world and entity colours (Cosmetic)", Config.getInstance().randomizeColours); + searchDepth = new TextFieldWidget(client.textRenderer, x - 5, y + 80, 20, client.textRenderer.fontHeight + 3, Text.of("")); searchDepth.setChangedListener((text) -> { String filtered = text.replaceAll("[^0-9]", ""); @@ -49,7 +54,7 @@ public LootBookSettingsWidget(MinecraftClient client, int x, int y) { } else { searchDepth.setEditableColor(0xFFFFFF); } - if(!filtered.equals(text)) { + if (!filtered.equals(text)) { searchDepth.setText(filtered); } }); @@ -58,6 +63,26 @@ public LootBookSettingsWidget(MinecraftClient client, int x, int y) { searchDepth.setEditableColor(0xFFFFFF); searchDepth.setText(String.valueOf(Config.getInstance().searchDepth)); searchDepth.setTooltip(Tooltip.of(Text.of("The maximum number of steps to search for a path to the target item\n\n§6Warning: §rValues over §c15§r are not recommended!"))); + + highlightRadius = new TextFieldWidget(client.textRenderer, x - 5, y + 100, 20, client.textRenderer.fontHeight + 3, Text.of("")); + highlightRadius.setChangedListener((text) -> { + String filtered = text.replaceAll("[^0-9]", ""); + while (filtered.startsWith("0")) filtered = filtered.substring(1); + if (filtered.isEmpty()) { + filtered = "0"; + highlightRadius.setEditableColor(0xAAAAAA); + } else { + highlightRadius.setEditableColor(0xFFFFFF); + } + if (!filtered.equals(text)) { + highlightRadius.setText(filtered); + } + }); + highlightRadius.setMaxLength(2); + highlightRadius.setVisible(true); + highlightRadius.setEditableColor(0xFFFFFF); + highlightRadius.setText(String.valueOf(Config.getInstance().highlightRadius)); + highlightRadius.setTooltip(Tooltip.of(Text.of("The radius of the highlight effect when pressing \"" + EventManager.highlight.getBoundKeyLocalizedText().getString() + "\"\n\n§6Warning: §rValues over §c10§r are not recommended!"))); } private ToggleButtonWidget createButton(int x, int y, String tooltip, boolean toggled) { @@ -80,6 +105,8 @@ public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { client.textRenderer.draw(matrices, Text.of("Randomize Colours"), randomizeColours.getX() - 110, randomizeColours.getY() + 4, 0xFFFFFF); this.searchDepth.render(matrices, mouseX, mouseY, delta); client.textRenderer.draw(matrices, Text.of("Search Depth"), searchDepth.getX() - 105, searchDepth.getY() + 4, 0xFFFFFF); + this.highlightRadius.render(matrices, mouseX, mouseY, delta); + client.textRenderer.draw(matrices, Text.of("Highlight Radius"), highlightRadius.getX() - 105, highlightRadius.getY() + 4, 0xFFFFFF); } public boolean mouseClicked(double mouseX, double mouseY, int button) { @@ -93,6 +120,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { } Config.getInstance().randomizeColours = randomizeColours.isToggled(); Config.getInstance().searchDepth = Integer.parseInt(searchDepth.getText()); + Config.getInstance().highlightRadius = Integer.parseInt(highlightRadius.getText()); TrackableCrawler.clearCache(); Tracker.getInstance().clearCache(); ConfigManager.saveConfig(); @@ -121,15 +149,24 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { randomizeColours.setToggled(!randomizeColours.isToggled()); return true; } - return searchDepth.mouseClicked(mouseX, mouseY, button); + if(searchDepth.mouseClicked(mouseX, mouseY, button)) { + return true; + } + return highlightRadius.mouseClicked(mouseX, mouseY, button); } public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - return searchDepth.keyPressed(keyCode, scanCode, modifiers); + if(searchDepth.keyPressed(keyCode, scanCode, modifiers)) { + return true; + } + return highlightRadius.keyPressed(keyCode, scanCode, modifiers); } public boolean charTyped(char chr, int modifiers) { - return searchDepth.charTyped(chr, modifiers); + if(searchDepth.charTyped(chr, modifiers)) { + return true; + } + return highlightRadius.charTyped(chr, modifiers); } public void moveWidgets(boolean up) { @@ -141,6 +178,7 @@ public void moveWidgets(boolean up) { this.enableOverride.setY(this.enableOverride.getY() - HEIGHT / 2); this.randomizeColours.setY(this.randomizeColours.getY() - HEIGHT / 2); this.searchDepth.setY(this.searchDepth.getY() - HEIGHT / 2); + this.highlightRadius.setY(this.highlightRadius.getY() - HEIGHT / 2); } else { this.y += HEIGHT / 2; this.backButton.setY(this.backButton.getY() + HEIGHT / 2); @@ -149,6 +187,7 @@ public void moveWidgets(boolean up) { this.enableOverride.setY(this.enableOverride.getY() + HEIGHT / 2); this.randomizeColours.setY(this.randomizeColours.getY() + HEIGHT / 2); this.searchDepth.setY(this.searchDepth.getY() + HEIGHT / 2); + this.highlightRadius.setY(this.highlightRadius.getY() + HEIGHT / 2); } } } diff --git a/src/client/java/com/bawnorton/randoassistant/tracking/Tracker.java b/src/client/java/com/bawnorton/randoassistant/tracking/Tracker.java index 5baaea8..bef5ac9 100644 --- a/src/client/java/com/bawnorton/randoassistant/tracking/Tracker.java +++ b/src/client/java/com/bawnorton/randoassistant/tracking/Tracker.java @@ -38,12 +38,14 @@ public class Tracker { private final Map, Item> TRACKABLE_CRAFTED; private final Map>> TRACKED; + private final Map> ID_TO_TRACKABLE; public Tracker() { TRACKABLE_INTERACTED = new TrackableMap<>(); TRACKABLE_LOOTED = new TrackableMap<>(); TRACKABLE_CRAFTED = Maps.newHashMap(); TRACKED = Maps.newHashMap(); + ID_TO_TRACKABLE = Maps.newHashMap(); } public static Tracker getInstance() { @@ -56,6 +58,7 @@ public static Tracker getInstance() { public void track(SerializeableLootTable lootTable) { Stat stat = RandoAssistantStats.LOOTED.getOrCreateStat(lootTable.getLootTableId()); Trackable trackable = TRACKABLE_LOOTED.getOrCreate(stat, lootTable.getSourceId()); + ID_TO_TRACKABLE.put(lootTable.getSourceId(), trackable); for(Item target : lootTable.getItems()) { trackable.addOutput(Registries.ITEM.getId(target), lootTable.getCondition()); Set> tracked = TRACKED.getOrDefault(Registries.ITEM.getId(target), Sets.newHashSet()); @@ -80,7 +83,7 @@ public void track(SerializeableCrafting crafting) { } @Nullable - public Set> getTracked(Identifier id) { + public Set> getSources(Identifier id) { return TRACKED.get(id); } @@ -214,6 +217,10 @@ public void testAll() { } } + public boolean isEnabled(Identifier id) { + return ID_TO_TRACKABLE.containsKey(id) && ID_TO_TRACKABLE.get(id).isEnabled(); + } + private static class TrackableMap { private final HashMap, Trackable> trackables; diff --git a/src/client/java/com/bawnorton/randoassistant/tracking/trackable/TrackableCrawler.java b/src/client/java/com/bawnorton/randoassistant/tracking/trackable/TrackableCrawler.java index deb7fb3..ce6faf8 100644 --- a/src/client/java/com/bawnorton/randoassistant/tracking/trackable/TrackableCrawler.java +++ b/src/client/java/com/bawnorton/randoassistant/tracking/trackable/TrackableCrawler.java @@ -33,7 +33,7 @@ public static TrackingGraph crawl(Identifier target) { private static void crawl(Identifier original, Identifier target, TrackingGraph graph, int depth) { if(depth >= Config.getInstance().searchDepth) return; graph.add(target); - Set> sources = Tracker.getInstance().getTracked(target); + Set> sources = Tracker.getInstance().getSources(target); if(sources == null) sources = new HashSet<>(); List sourceIds = sources.stream().filter(Trackable::isEnabled).map(Trackable::getIdentifier).toList(); diff --git a/src/client/resources/randoassistant.client.mixins.json b/src/client/resources/randoassistant.client.mixins.json index e58b6d1..827ec54 100644 --- a/src/client/resources/randoassistant.client.mixins.json +++ b/src/client/resources/randoassistant.client.mixins.json @@ -8,6 +8,9 @@ "BiomeColorBlenderMixin", "BiomeMixin", "BlockColorsMixin", + "ClientPlayNetworkHandlerMixin", + "CraftingScreenMixin", + "GameRendererMixin", "HandledScreenMixin", "HoveredTooltipPositionerMixin", "InventoryScreenMixin", @@ -21,8 +24,5 @@ "defaultRequire": 1 }, "mixins": [ - "ClientPlayNetworkHandlerMixin", - "CraftingScreenMixin", - "GameRendererMixin" ] } \ No newline at end of file diff --git a/src/main/resources/assets/randoassistant/lang/en_us.json b/src/main/resources/assets/randoassistant/lang/en_us.json index 8749fe8..f7e3849 100644 --- a/src/main/resources/assets/randoassistant/lang/en_us.json +++ b/src/main/resources/assets/randoassistant/lang/en_us.json @@ -1,4 +1,6 @@ { "randoassistant.homepage": "My Website", - "item.randoassistant.wob": "Wob" + "item.randoassistant.wob": "Wob", + "key.randoassistant.highlight": "Highlight Unbroken Blocks", + "key.categories.randoassistant": "Rando Assistant" } \ No newline at end of file