diff --git a/gradle.properties b/gradle.properties index 052db24..436e5d9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ yarn_mappings=1.21.4+build.8 loader_version=0.16.10 # Mod Properties -mod_version=1.3.0 +mod_version=1.4.0 maven_group=dev.quickinfos archives_base_name=quickinfos diff --git a/src/client/java/dev/quickinfos/QuickInfosClient.java b/src/client/java/dev/quickinfos/QuickInfosClient.java index 65524db..e4bacd6 100644 --- a/src/client/java/dev/quickinfos/QuickInfosClient.java +++ b/src/client/java/dev/quickinfos/QuickInfosClient.java @@ -1,10 +1,14 @@ package dev.quickinfos; import dev.quickinfos.config.ConfigManager; +import dev.quickinfos.exceptions.CannotCheckTriggerConditionTrackerException; +import dev.quickinfos.exceptions.CannotRenderInfoException; +import dev.quickinfos.exceptions.CannotTriggerTrackerException; import dev.quickinfos.infos.*; -import dev.quickinfos.screen.QuickInfosScreen; import dev.quickinfos.trackers.DeathCoordinatesTracker; import dev.quickinfos.trackers.Tracker; +import dev.quickinfos.utils.ScreenUtils; +import dev.quickinfos.utils.StaticUtils; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; @@ -16,6 +20,7 @@ import net.minecraft.client.render.RenderTickCounter; import net.minecraft.text.Text; import net.minecraft.util.Colors; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -31,15 +36,15 @@ public void onInitializeClient() { private void onInitializeLoadStatic() { for (Tracker tracker : new Tracker[] {new DeathCoordinatesTracker()}) { try { - StaticVariables.TRACKERS.put(tracker.getClass().getName(), tracker); + Singleton.TRACKERS.put(tracker.getClass().getName(), tracker); } catch (Throwable e) { System.err.println("Failed to load a tracker at start: " + e.getMessage()); } } - for (Info info : new Info[] {new Coordinates(), new DeathCoordinates(), new TargetedBlock(), new CurrentBiome(), new FacingDirection()}) { + for (Info info : new Info[] {new Coordinates(), new DeathCoordinates(), new TargetedBlock(), new TargetedBlockCoordinates(), new CurrentBiome(), new FacingDirection()}) { try { - StaticVariables.INFOS_INSTANCES.put(info.getClass().getName(), info); + Singleton.INFOS_INSTANCES.put(info.getClass().getName(), info); } catch (Throwable e) { System.err.println("Failed to load info at start: " + e.getMessage()); } @@ -47,13 +52,13 @@ private void onInitializeLoadStatic() { } private void onInitializeLoadConfig() { - StaticVariables.config = ConfigManager.loadConfig(); - if(StaticVariables.config.isValid()){ - StaticVariables.useUserConfig(); + Singleton.config = ConfigManager.loadConfig(); + if(Singleton.config.isValid()){ + Singleton.useUserConfig(); } else { - StaticVariables.useDefaultConfig(); - StaticVariables.useDefaultOrderedInfos(); + Singleton.useDefaultConfig(); + Singleton.useDefaultOrderedInfos(); } } @@ -61,16 +66,18 @@ private void onInitializeRegisterEvents() { // #-----------------# // # Attach Trackers # // #-----------------# - ClientTickEvents.END_CLIENT_TICK.register((client) -> { - if(client == null){ - return; - } - - for(Tracker tracker : StaticVariables.TRACKERS.values()) { - if(tracker.shouldTrigger(client)) { - tracker.trigger(client); + ClientTickEvents.START_CLIENT_TICK.register((client) -> { + for(Tracker tracker : Singleton.TRACKERS.values()) { + try { + if (tracker.shouldTrigger(client)) { + tracker.trigger(client); + } } - } + catch (CannotCheckTriggerConditionTrackerException | CannotTriggerTrackerException e){ + // Cancel other trackers if one fails as they all depend on client + return; + } + } }); // #--------------------# @@ -79,19 +86,30 @@ private void onInitializeRegisterEvents() { HudLayerRegistrationCallback.EVENT.register( layeredDrawer -> layeredDrawer.attachLayerBefore( IdentifiedLayer.CROSSHAIR, - StaticVariables.QUICKINFOS_LAYER, + Singleton.QUICKINFOS_LAYER, QuickInfosClient::onCrosshairRender)); + // #-------------# + // # Keybindings # + // #-------------# + ClientTickEvents.END_CLIENT_TICK.register((client) -> { + while (Singleton.TOGGLE_INFO_KEY.wasPressed()){ + Singleton.SHOW = !Singleton.SHOW; + } + while (Singleton.SHOW_MENU_KEY.wasPressed()){ + ScreenUtils.openScreen(client); + } + }); + // #-------------# // # /quickinfos # // #-------------# ClientCommandRegistrationCallback.EVENT.register( ((commandDispatcher, registryAccess) -> - commandDispatcher.register(ClientCommandManager.literal("quickinfos").executes( + commandDispatcher.register(ClientCommandManager.literal(StaticUtils.COMMAND_LITERAL).executes( commandContext -> { try{ - MinecraftClient client = commandContext.getSource().getClient(); - client.send(() -> client.setScreen(new QuickInfosScreen(Text.empty()))); + ScreenUtils.openScreen(commandContext.getSource().getClient()); return 0; }catch (Throwable e){ commandContext.getSource().sendError(Text.of(e.toString())); @@ -110,26 +128,32 @@ private static void onCrosshairRender(DrawContext drawContext, RenderTickCounter client == null || client.options.hudHidden || client.getDebugHud().shouldShowDebugHud() || - StaticVariables.ORDERED_INFOS.isEmpty() || + Singleton.ORDERED_INFOS.isEmpty() || client.player == null || - client.world == null) { + client.world == null || + !Singleton.SHOW) { return; } // Split the selected infos into separate lines - String[] rawLines = StaticVariables.ORDERED_INFOS.stream().map(info -> { - try { - return info.isOn() ? info.toHUDScreen(client) : ""; - } catch (Throwable e){ - return ""; - } - }).toArray(String[]::new); + String[] rawLines; + try { + rawLines = Singleton.ORDERED_INFOS.stream().map(info -> info.isOn() ? info.render(client) : "").toArray(String[]::new); + } + catch (CannotRenderInfoException e){ + // Abort if one info cannot be rendered as they all depend on client + return; + } ArrayList lines = new ArrayList<>(); for(String line : rawLines) { if(line != null && !line.isEmpty()) lines.add(line) ; } + renderLines(client, lines, drawContext); + } + + private static void renderLines(@NotNull MinecraftClient client, @NotNull ArrayList lines, @NotNull DrawContext drawContext) { // Calculate the screen width and set a y_margin int screenWidth = client.getWindow().getScaledWidth(); int y_margin = 2; @@ -139,8 +163,8 @@ private static void onCrosshairRender(DrawContext drawContext, RenderTickCounter for (String line : lines) { int textWidth = client.textRenderer.getWidth(line); int bottom_top = lines.size() * (client.textRenderer.fontHeight + y_margin); - int x = y_margin; - switch (StaticVariables.POSITION){ + int x = 2; + switch (Singleton.POSITION){ case TOP_RIGHT: x = screenWidth - textWidth - y_margin; drawContext.drawText(client.textRenderer, line, x, y, Colors.WHITE, false); diff --git a/src/client/java/dev/quickinfos/StaticVariables.java b/src/client/java/dev/quickinfos/Singleton.java similarity index 61% rename from src/client/java/dev/quickinfos/StaticVariables.java rename to src/client/java/dev/quickinfos/Singleton.java index 0a4f7eb..cd77480 100644 --- a/src/client/java/dev/quickinfos/StaticVariables.java +++ b/src/client/java/dev/quickinfos/Singleton.java @@ -7,25 +7,28 @@ import dev.quickinfos.infos.FacingDirection; import dev.quickinfos.infos.Info; import dev.quickinfos.trackers.Tracker; +import dev.quickinfos.utils.DefaultConfigUtils; +import dev.quickinfos.utils.KeyUtils; +import dev.quickinfos.utils.StaticUtils; +import net.minecraft.client.option.KeyBinding; import net.minecraft.util.Identifier; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; -public class StaticVariables { - public static final Identifier QUICKINFOS_LAYER = Identifier.of("quickinfos"); +public class Singleton { + public static final Identifier QUICKINFOS_LAYER = Identifier.of(StaticUtils.LAYER_ID); public static final HashMap INFOS_INSTANCES = new HashMap<>(); public static final HashMap TRACKERS = new HashMap<>(); public static final ArrayList ORDERED_INFOS = new ArrayList<>(); public static Positions POSITION; + public static KeyBinding TOGGLE_INFO_KEY; + public static KeyBinding SHOW_MENU_KEY; + public static boolean SHOW; public static Config config; - private StaticVariables() {} - - public static void useDefaultOrderedInfos() { - ORDERED_INFOS.addAll(INFOS_INSTANCES.values()); - } + private Singleton() {} public static void useDefaultConfig(){ INFOS_INSTANCES.get(Coordinates.class.getName()).setOn(true); @@ -33,11 +36,17 @@ public static void useDefaultConfig(){ INFOS_INSTANCES.get(FacingDirection.class.getName()).setOn(true); POSITION = Positions.TOP_RIGHT; + SHOW = true; + + TOGGLE_INFO_KEY = KeyUtils.registerToggleInfo(DefaultConfigUtils.TOGGLE_INFO_KEYCODE); + SHOW_MENU_KEY = KeyUtils.registerShowMenu(DefaultConfigUtils.SHOW_MENU_KEYCODE); } - public static void useUserConfig(){ - POSITION = config.getPosition(); + public static void useDefaultOrderedInfos() { + ORDERED_INFOS.addAll(INFOS_INSTANCES.values()); + } + public static void useUserConfig(){ for (Map.Entry entry : config.getEnabledModules().entrySet()) { Info info = INFOS_INSTANCES.getOrDefault(entry.getKey(), null); if(info != null){ @@ -45,5 +54,19 @@ public static void useUserConfig(){ ORDERED_INFOS.add(info); } } + + // For new infos in mod updates + for (Info info : INFOS_INSTANCES.values()) { + if(!ORDERED_INFOS.contains(info)){ + ORDERED_INFOS.add(info); + info.setOn(false); + } + } + + POSITION = config.getPosition(); + SHOW = config.getShow(); + + TOGGLE_INFO_KEY = KeyUtils.registerToggleInfo(config.getToggleKeyCode()); + SHOW_MENU_KEY = KeyUtils.registerShowMenu(config.getShowMenuKeyCode()); } } diff --git a/src/client/java/dev/quickinfos/config/Config.java b/src/client/java/dev/quickinfos/config/Config.java index 546de6c..e2ff0b8 100644 --- a/src/client/java/dev/quickinfos/config/Config.java +++ b/src/client/java/dev/quickinfos/config/Config.java @@ -1,17 +1,24 @@ package dev.quickinfos.config; import dev.quickinfos.enums.Positions; +import org.lwjgl.glfw.GLFW; import java.util.LinkedHashMap; import java.util.Map; public class Config { + + //#region Fields + private final Map enabledModules = new LinkedHashMap<>(); private Positions position; + private int toggleKeyCode; + private int showMenuKeyCode; + private boolean show; - public boolean isValid(){ - return position != null && !enabledModules.isEmpty(); - } + //#endregion Fields + + //#region Getters and setters public Map getEnabledModules() { return enabledModules; @@ -21,19 +28,66 @@ public void addEnabledModule(String enabledModule, boolean isOn) { this.enabledModules.put(enabledModule, isOn); } - public void clearEnabledModules() { - this.enabledModules.clear(); - } - public Positions getPosition() { return this.position; } + public void setPosition(Positions position) { + this.position = position; + } + + public int getToggleKeyCode() { + return toggleKeyCode; + } + + public void setToggleKeyCode(int toggleKeyCode) { + this.toggleKeyCode = toggleKeyCode; + } + + public boolean getShow() { + return show; + } + + public void setShow(boolean show) { + this.show = show; + } + + public int getShowMenuKeyCode() { + return showMenuKeyCode; + } + + public void setShowMenuKeyCode(int showMenuKeyCode) { + this.showMenuKeyCode = showMenuKeyCode; + } + + //#endregion Getters and setters + + //#region Methods + + public boolean isValid() { + return position != null && !enabledModules.isEmpty(); + } + + public void clearEnabledModules() { + this.enabledModules.clear(); + } + public void clearPosition() { this.position = null; } - public void setPosition(Positions position) { - this.position = position; + public void clearToggleKeyCode() { + this.toggleKeyCode = GLFW.GLFW_KEY_K; + } + + public void clearShow() { + this.show = true; + } + + public void clearShowMenuKeyCode() { + this.showMenuKeyCode = GLFW.GLFW_KEY_M; } + + //#endregion Methods + } diff --git a/src/client/java/dev/quickinfos/config/ConfigManager.java b/src/client/java/dev/quickinfos/config/ConfigManager.java index 488de00..f3862bf 100644 --- a/src/client/java/dev/quickinfos/config/ConfigManager.java +++ b/src/client/java/dev/quickinfos/config/ConfigManager.java @@ -4,6 +4,7 @@ import com.google.gson.GsonBuilder; import dev.quickinfos.enums.Positions; import dev.quickinfos.infos.Info; +import dev.quickinfos.utils.StaticUtils; import net.fabricmc.loader.api.FabricLoader; import java.nio.file.Files; @@ -12,7 +13,7 @@ public class ConfigManager { private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); - private static final Path CONFIG_FILE = FabricLoader.getInstance().getConfigDir().resolve("quickinfos_mod.json"); + private static final Path CONFIG_FILE = FabricLoader.getInstance().getConfigDir().resolve(StaticUtils.CONFIG_FILE_PATH); public static Config loadConfig() { try { @@ -28,10 +29,19 @@ public static Config loadConfig() { } } - public static void saveConfig(Positions position, ArrayList infos, Config config) { + public static void saveConfig(boolean show, int showMenuKeyCode, int toggleKeyCode, Positions position, ArrayList infos, Config config) { config.clearPosition(); config.setPosition(position); + config.clearShow(); + config.setShow(show); + + config.clearToggleKeyCode(); + config.setToggleKeyCode(toggleKeyCode); + + config.clearShowMenuKeyCode(); + config.setShowMenuKeyCode(showMenuKeyCode); + config.clearEnabledModules(); for (Info info : infos) { config.addEnabledModule(info.getClass().getName(), info.isOn()); diff --git a/src/client/java/dev/quickinfos/exceptions/CannotCheckTriggerConditionTrackerException.java b/src/client/java/dev/quickinfos/exceptions/CannotCheckTriggerConditionTrackerException.java new file mode 100644 index 0000000..38122cc --- /dev/null +++ b/src/client/java/dev/quickinfos/exceptions/CannotCheckTriggerConditionTrackerException.java @@ -0,0 +1,13 @@ +package dev.quickinfos.exceptions; + +import dev.quickinfos.trackers.Tracker; + +public class CannotCheckTriggerConditionTrackerException extends RuntimeException { + public CannotCheckTriggerConditionTrackerException(Tracker tracker) { + this(tracker.getClass().getName() + " could not verify trigger condition"); + } + + public CannotCheckTriggerConditionTrackerException(String message) { + super(message); + } +} diff --git a/src/client/java/dev/quickinfos/exceptions/CannotRenderInfoException.java b/src/client/java/dev/quickinfos/exceptions/CannotRenderInfoException.java new file mode 100644 index 0000000..33b2923 --- /dev/null +++ b/src/client/java/dev/quickinfos/exceptions/CannotRenderInfoException.java @@ -0,0 +1,13 @@ +package dev.quickinfos.exceptions; + +import dev.quickinfos.infos.Info; + +public class CannotRenderInfoException extends RuntimeException { + public CannotRenderInfoException(Info info) { + this(info.getHumanReadableName() + " could not be rendered"); + } + + public CannotRenderInfoException(String message) { + super(message); + } +} diff --git a/src/client/java/dev/quickinfos/exceptions/CannotTriggerTrackerException.java b/src/client/java/dev/quickinfos/exceptions/CannotTriggerTrackerException.java new file mode 100644 index 0000000..1ef624b --- /dev/null +++ b/src/client/java/dev/quickinfos/exceptions/CannotTriggerTrackerException.java @@ -0,0 +1,13 @@ +package dev.quickinfos.exceptions; + +import dev.quickinfos.trackers.Tracker; + +public class CannotTriggerTrackerException extends RuntimeException { + public CannotTriggerTrackerException(Tracker tracker) { + this(tracker.getClass().getName() + " could not be triggered"); + } + + public CannotTriggerTrackerException(String message) { + super(message); + } +} diff --git a/src/client/java/dev/quickinfos/infos/Coordinates.java b/src/client/java/dev/quickinfos/infos/Coordinates.java index d8155d1..e3c7932 100644 --- a/src/client/java/dev/quickinfos/infos/Coordinates.java +++ b/src/client/java/dev/quickinfos/infos/Coordinates.java @@ -1,5 +1,6 @@ package dev.quickinfos.infos; +import dev.quickinfos.exceptions.CannotRenderInfoException; import net.minecraft.client.MinecraftClient; import net.minecraft.util.math.Vec3d; import org.jetbrains.annotations.NotNull; @@ -12,13 +13,11 @@ public String getHumanReadableName() { } @Override - public String toHUDScreen(@NotNull MinecraftClient client) { - if (client.player == null) { - return "Unknown player position"; - } + public String render(@NotNull MinecraftClient client) { + if (client.player == null) + throw new CannotRenderInfoException(this); Vec3d pos = client.player.getPos(); - return String.format("%.1f / %.1f / %.1f", pos.getX(), pos.getY(), pos.getZ()); } diff --git a/src/client/java/dev/quickinfos/infos/CurrentBiome.java b/src/client/java/dev/quickinfos/infos/CurrentBiome.java index 2cba5d9..36c1c5e 100644 --- a/src/client/java/dev/quickinfos/infos/CurrentBiome.java +++ b/src/client/java/dev/quickinfos/infos/CurrentBiome.java @@ -1,5 +1,7 @@ package dev.quickinfos.infos; +import dev.quickinfos.exceptions.CannotRenderInfoException; +import dev.quickinfos.utils.StaticUtils; import net.minecraft.client.MinecraftClient; import net.minecraft.registry.RegistryKey; import net.minecraft.util.math.BlockPos; @@ -15,15 +17,13 @@ public String getHumanReadableName() { } @Override - public String toHUDScreen(@NotNull MinecraftClient client) { - if (client.player == null || client.world == null) { - return "Unknown biome"; - } + public String render(@NotNull MinecraftClient client) { + if (client.player == null || client.world == null) + throw new CannotRenderInfoException(this); BlockPos playerPos = client.player.getBlockPos(); Optional> biome = client.world.getBiome(playerPos).getKey(); - return biome.map(biomeRegistryKey -> biomeRegistryKey.getValue().toString()) - .orElse("Unknown biome"); + .orElse(StaticUtils.NONE_INFO_CALCULATED); } } diff --git a/src/client/java/dev/quickinfos/infos/DeathCoordinates.java b/src/client/java/dev/quickinfos/infos/DeathCoordinates.java index b0a76fb..dee5bdc 100644 --- a/src/client/java/dev/quickinfos/infos/DeathCoordinates.java +++ b/src/client/java/dev/quickinfos/infos/DeathCoordinates.java @@ -1,7 +1,9 @@ package dev.quickinfos.infos; -import dev.quickinfos.StaticVariables; +import dev.quickinfos.Singleton; +import dev.quickinfos.exceptions.CannotRenderInfoException; import dev.quickinfos.trackers.DeathCoordinatesTracker; +import dev.quickinfos.utils.StaticUtils; import net.minecraft.client.MinecraftClient; import net.minecraft.util.math.BlockPos; import org.jetbrains.annotations.NotNull; @@ -14,14 +16,13 @@ public String getHumanReadableName() { } @Override - public String toHUDScreen(@NotNull MinecraftClient client) { - if (client.player == null) { - return "Unknown player position"; - } + public String render(@NotNull MinecraftClient client) { + if (client.player == null) + throw new CannotRenderInfoException(this); - BlockPos pos = ((DeathCoordinatesTracker)StaticVariables.TRACKERS.get(DeathCoordinatesTracker.class.getName())).getLastDeathPos(); - - return String.format("Died at %d / %d / %d", pos.getX(), pos.getY(), pos.getZ()); + BlockPos pos = ((DeathCoordinatesTracker) Singleton.TRACKERS.get(DeathCoordinatesTracker.class.getName())).getLastDeathPos(); + return pos != null ? String.format("Died at %d / %d / %d", pos.getX(), pos.getY(), pos.getZ()) : + StaticUtils.NONE_INFO_CALCULATED; } } diff --git a/src/client/java/dev/quickinfos/infos/FacingDirection.java b/src/client/java/dev/quickinfos/infos/FacingDirection.java index fe1b853..17dff92 100644 --- a/src/client/java/dev/quickinfos/infos/FacingDirection.java +++ b/src/client/java/dev/quickinfos/infos/FacingDirection.java @@ -1,5 +1,7 @@ package dev.quickinfos.infos; +import dev.quickinfos.exceptions.CannotRenderInfoException; +import dev.quickinfos.utils.StaticUtils; import net.minecraft.client.MinecraftClient; import org.jetbrains.annotations.NotNull; @@ -11,10 +13,9 @@ public String getHumanReadableName() { } @Override - public String toHUDScreen(@NotNull MinecraftClient client) { - if (client.player == null) { - return "Unknown player direction"; - } + public String render(@NotNull MinecraftClient client) { + if (client.player == null) + throw new CannotRenderInfoException(this); float yaw = client.player.getYaw(); @@ -22,25 +23,23 @@ public String toHUDScreen(@NotNull MinecraftClient client) { float normalizedYaw = (yaw % 360 + 360) % 360; // Determine the cardinal direction based on the yaw - if (normalizedYaw >= 337.5 || normalizedYaw < 22.5) { - return "South"; - } else if (normalizedYaw >= 22.5 && normalizedYaw < 67.5) { - return "South-West"; - } else if (normalizedYaw >= 67.5 && normalizedYaw < 112.5) { - return "West"; - } else if (normalizedYaw >= 112.5 && normalizedYaw < 157.5) { - return "North-West"; - } else if (normalizedYaw >= 157.5 && normalizedYaw < 202.5) { - return "North"; - } else if (normalizedYaw >= 202.5 && normalizedYaw < 247.5) { - return "North-East"; - } else if (normalizedYaw >= 247.5 && normalizedYaw < 292.5) { - return "East"; - } else if (normalizedYaw >= 292.5 && normalizedYaw < 337.5) { - return "South-East"; - } else { - return "Unknown"; - } + return getDirection(normalizedYaw); + } + + public static String getDirection(double normalizedYaw) { + int sector = (int) ((normalizedYaw + 22.5) / 45) % 8; + + return switch (sector) { + case 0 -> "South"; + case 1 -> "South-West"; + case 2 -> "West"; + case 3 -> "North-West"; + case 4 -> "North"; + case 5 -> "North-East"; + case 6 -> "East"; + case 7 -> "South-East"; + default -> StaticUtils.NONE_INFO_CALCULATED; + }; } } diff --git a/src/client/java/dev/quickinfos/infos/Info.java b/src/client/java/dev/quickinfos/infos/Info.java index b7053cd..598a5c4 100644 --- a/src/client/java/dev/quickinfos/infos/Info.java +++ b/src/client/java/dev/quickinfos/infos/Info.java @@ -1,5 +1,6 @@ package dev.quickinfos.infos; +import dev.quickinfos.exceptions.CannotRenderInfoException; import net.minecraft.client.MinecraftClient; import org.jetbrains.annotations.NotNull; @@ -10,5 +11,5 @@ public abstract class Info { public void setOn(boolean on) { isOn = on; } public abstract String getHumanReadableName(); - public abstract String toHUDScreen(@NotNull MinecraftClient client); + public abstract String render(@NotNull MinecraftClient client) throws CannotRenderInfoException; } diff --git a/src/client/java/dev/quickinfos/infos/TargetedBlock.java b/src/client/java/dev/quickinfos/infos/TargetedBlock.java index 10f577c..d6652e6 100644 --- a/src/client/java/dev/quickinfos/infos/TargetedBlock.java +++ b/src/client/java/dev/quickinfos/infos/TargetedBlock.java @@ -1,9 +1,11 @@ package dev.quickinfos.infos; +import dev.quickinfos.exceptions.CannotRenderInfoException; +import dev.quickinfos.utils.PlayerUtils; +import dev.quickinfos.utils.StaticUtils; import net.minecraft.client.MinecraftClient; import net.minecraft.registry.Registries; import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.hit.HitResult; import org.jetbrains.annotations.NotNull; public class TargetedBlock extends Info { @@ -14,20 +16,13 @@ public String getHumanReadableName() { } @Override - public String toHUDScreen(@NotNull MinecraftClient client) { - if (client.player == null || client.world == null) { - return "Unknown targeted entity"; - } + public String render(@NotNull MinecraftClient client) { + if (client.player == null || client.world == null) + throw new CannotRenderInfoException(this); - double range = client.player.getBlockInteractionRange(); - HitResult hitResult = client.player.raycast(range, 1, false); - if(hitResult.getType() == HitResult.Type.BLOCK) { - String blockName = Registries.BLOCK.getId(client.world.getBlockState(((BlockHitResult) hitResult).getBlockPos()).getBlock()).toString(); - return String.format("Target %s", blockName); - } - else { - return ""; - } + BlockHitResult targetedBlock = PlayerUtils.getTargetedBlockInRange(client.player, false); + return targetedBlock != null ? String.format("Target %s", Registries.BLOCK.getId(client.world.getBlockState(targetedBlock.getBlockPos()).getBlock())) : + StaticUtils.NONE_INFO_CALCULATED; } } diff --git a/src/client/java/dev/quickinfos/infos/TargetedBlockCoordinates.java b/src/client/java/dev/quickinfos/infos/TargetedBlockCoordinates.java new file mode 100644 index 0000000..5997222 --- /dev/null +++ b/src/client/java/dev/quickinfos/infos/TargetedBlockCoordinates.java @@ -0,0 +1,32 @@ +package dev.quickinfos.infos; + +import dev.quickinfos.exceptions.CannotRenderInfoException; +import dev.quickinfos.utils.PlayerUtils; +import dev.quickinfos.utils.StaticUtils; +import net.minecraft.client.MinecraftClient; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import org.jetbrains.annotations.NotNull; + +public class TargetedBlockCoordinates extends Info { + + @Override + public String getHumanReadableName() { + return "Targeted Block's Coordinates"; + } + + @Override + public String render(@NotNull MinecraftClient client) { + if (client.player == null || client.world == null) + throw new CannotRenderInfoException(this); + + BlockHitResult targetedBlock = PlayerUtils.getTargetedBlockInRange(client.player, false); + + if(targetedBlock == null) + return StaticUtils.NONE_INFO_CALCULATED; + + BlockPos pos = targetedBlock.getBlockPos(); + return String.format("Target at %d / %d / %d", pos.getX(), pos.getY(), pos.getZ()); + } + +} diff --git a/src/client/java/dev/quickinfos/screen/QuickInfosScreen.java b/src/client/java/dev/quickinfos/screen/QuickInfosScreen.java index fa87657..694ece6 100644 --- a/src/client/java/dev/quickinfos/screen/QuickInfosScreen.java +++ b/src/client/java/dev/quickinfos/screen/QuickInfosScreen.java @@ -1,6 +1,6 @@ package dev.quickinfos.screen; -import dev.quickinfos.StaticVariables; +import dev.quickinfos.Singleton; import dev.quickinfos.config.ConfigManager; import dev.quickinfos.enums.Positions; import dev.quickinfos.infos.Info; @@ -28,12 +28,13 @@ public void init() { public void render(DrawContext context, int mouseX, int mouseY, float delta) { super.render(context, mouseX, mouseY, delta); context.drawText(this.textRenderer, "Quick infos menu", 40, 40 - this.textRenderer.fontHeight - 10, 0xFFFFFFFF, true); + context.drawText(this.textRenderer, "Checkout Minecraft default controls menu for keybindings", 40, 60 - this.textRenderer.fontHeight - 10, 0xFFFFFFFF, true); } @Override public void close() { try { - ConfigManager.saveConfig(StaticVariables.POSITION, StaticVariables.ORDERED_INFOS, StaticVariables.config); + ConfigManager.saveConfig(Singleton.SHOW, Singleton.SHOW_MENU_KEY.getDefaultKey().getCode(), Singleton.TOGGLE_INFO_KEY.getDefaultKey().getCode(), Singleton.POSITION, Singleton.ORDERED_INFOS, Singleton.config); } finally { super.close(); } @@ -62,11 +63,11 @@ public void onMoveDown(UpDownWidget upDownWidget) { } private void move(UpDownWidget upDownWidget, boolean up) { - int index = StaticVariables.ORDERED_INFOS.indexOf(upDownWidget.getInfo()); + int index = Singleton.ORDERED_INFOS.indexOf(upDownWidget.getInfo()); if(up ? index > 0 : - index != -1 && index < StaticVariables.ORDERED_INFOS.size()-1) { - StaticVariables.ORDERED_INFOS.remove(index); - StaticVariables.ORDERED_INFOS.add(index + (up ? -1 : +1), upDownWidget.getInfo()); + index != -1 && index < Singleton.ORDERED_INFOS.size()-1) { + Singleton.ORDERED_INFOS.remove(index); + Singleton.ORDERED_INFOS.add(index + (up ? -1 : +1), upDownWidget.getInfo()); } refreshUpDownList(); } @@ -80,8 +81,8 @@ private void refreshUpDownList(){ } upDownWidgets.clear(); } - int y = 80; - for(Info orderedInfo : StaticVariables.ORDERED_INFOS){ + int y = 100; + for(Info orderedInfo : Singleton.ORDERED_INFOS){ upDownWidgets.add(new UpDownWidget(orderedInfo, 40, y, 320, 20, this)); y+= 22; } @@ -93,17 +94,18 @@ private void refreshUpDownList(){ } private void createPositionButton(){ - ButtonWidget posButton = ButtonWidget.builder(Text.of(buildMessage(StaticVariables.POSITION)), button -> { - switch (StaticVariables.POSITION){ - case TOP_RIGHT -> StaticVariables.POSITION = Positions.BOTTOM_RIGHT; - case BOTTOM_RIGHT -> StaticVariables.POSITION = Positions.BOTTOM_LEFT; - case BOTTOM_LEFT -> StaticVariables.POSITION = Positions.TOP_LEFT; - case TOP_LEFT -> StaticVariables.POSITION = Positions.TOP_RIGHT; + ButtonWidget posButton = ButtonWidget.builder(Text.of(buildMessage(Singleton.POSITION)), button -> { + switch (Singleton.POSITION){ + case TOP_RIGHT -> Singleton.POSITION = Positions.BOTTOM_RIGHT; + case BOTTOM_RIGHT -> Singleton.POSITION = Positions.BOTTOM_LEFT; + case BOTTOM_LEFT -> Singleton.POSITION = Positions.TOP_LEFT; + case TOP_LEFT -> Singleton.POSITION = Positions.TOP_RIGHT; } - button.setMessage(Text.of(buildMessage(StaticVariables.POSITION))); + button.setMessage(Text.of(buildMessage(Singleton.POSITION))); }) - .dimensions(40, 40, 160, 20) + .dimensions(40, 65, 160, 20) .build(); this.addDrawableChild(posButton); } + } diff --git a/src/client/java/dev/quickinfos/trackers/DeathCoordinatesTracker.java b/src/client/java/dev/quickinfos/trackers/DeathCoordinatesTracker.java index cc17787..5d6f929 100644 --- a/src/client/java/dev/quickinfos/trackers/DeathCoordinatesTracker.java +++ b/src/client/java/dev/quickinfos/trackers/DeathCoordinatesTracker.java @@ -1,5 +1,7 @@ package dev.quickinfos.trackers; +import dev.quickinfos.exceptions.CannotCheckTriggerConditionTrackerException; +import dev.quickinfos.exceptions.CannotTriggerTrackerException; import net.minecraft.client.MinecraftClient; import net.minecraft.util.math.BlockPos; import org.jetbrains.annotations.NotNull; @@ -14,13 +16,13 @@ public BlockPos getLastDeathPos() { @Override public boolean shouldTrigger(@NotNull MinecraftClient client) { - if (client.player == null) return false; + if (client.player == null) throw new CannotCheckTriggerConditionTrackerException(this); return client.player.getHealth() == 0; } @Override public void trigger(@NotNull MinecraftClient client) { - if (client.player == null) return; + if (client.player == null) throw new CannotTriggerTrackerException(this); lastDeathPos = new BlockPos(client.player.getBlockPos()); } } diff --git a/src/client/java/dev/quickinfos/trackers/Tracker.java b/src/client/java/dev/quickinfos/trackers/Tracker.java index e664e27..34ac540 100644 --- a/src/client/java/dev/quickinfos/trackers/Tracker.java +++ b/src/client/java/dev/quickinfos/trackers/Tracker.java @@ -1,9 +1,11 @@ package dev.quickinfos.trackers; +import dev.quickinfos.exceptions.CannotCheckTriggerConditionTrackerException; +import dev.quickinfos.exceptions.CannotTriggerTrackerException; import net.minecraft.client.MinecraftClient; import org.jetbrains.annotations.NotNull; public interface Tracker { - boolean shouldTrigger(@NotNull MinecraftClient client); - void trigger(@NotNull MinecraftClient client); + boolean shouldTrigger(@NotNull MinecraftClient client) throws CannotCheckTriggerConditionTrackerException; + void trigger(@NotNull MinecraftClient client) throws CannotTriggerTrackerException; } diff --git a/src/client/java/dev/quickinfos/utils/DefaultConfigUtils.java b/src/client/java/dev/quickinfos/utils/DefaultConfigUtils.java new file mode 100644 index 0000000..a45ba23 --- /dev/null +++ b/src/client/java/dev/quickinfos/utils/DefaultConfigUtils.java @@ -0,0 +1,8 @@ +package dev.quickinfos.utils; + +import org.lwjgl.glfw.GLFW; + +public class DefaultConfigUtils { + public static int SHOW_MENU_KEYCODE = GLFW.GLFW_KEY_M; + public static int TOGGLE_INFO_KEYCODE = GLFW.GLFW_KEY_K; +} diff --git a/src/client/java/dev/quickinfos/utils/KeyUtils.java b/src/client/java/dev/quickinfos/utils/KeyUtils.java new file mode 100644 index 0000000..6ee6312 --- /dev/null +++ b/src/client/java/dev/quickinfos/utils/KeyUtils.java @@ -0,0 +1,25 @@ +package dev.quickinfos.utils; + +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.util.InputUtil; + +public class KeyUtils { + + public static KeyBinding registerToggleInfo(int keyCode){ + return registerKeyBindingInMinecraftControls("Toggle Key", keyCode); + } + + public static KeyBinding registerShowMenu(int keyCode){ + return registerKeyBindingInMinecraftControls("Show Menu Key", keyCode); + } + + public static KeyBinding registerKeyBindingInMinecraftControls(String translationKey, int keyCode){ + return KeyBindingHelper.registerKeyBinding(new KeyBinding( + translationKey, + InputUtil.Type.KEYSYM, + keyCode, + StaticUtils.QUICKINFOS_CATEGORY_CONTROLS + )); + } +} diff --git a/src/client/java/dev/quickinfos/utils/PlayerUtils.java b/src/client/java/dev/quickinfos/utils/PlayerUtils.java new file mode 100644 index 0000000..de5fbc1 --- /dev/null +++ b/src/client/java/dev/quickinfos/utils/PlayerUtils.java @@ -0,0 +1,16 @@ +package dev.quickinfos.utils; + +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.hit.BlockHitResult; + +public class PlayerUtils { + public static HitResult getTargetedObjectInRange(ClientPlayerEntity player, boolean includeFluids){ + return player.raycast(player.getBlockInteractionRange(), 1, includeFluids); + } + + public static BlockHitResult getTargetedBlockInRange(ClientPlayerEntity player, boolean includeFluids){ + HitResult hitResult = getTargetedObjectInRange(player, includeFluids); + return hitResult.getType() == HitResult.Type.BLOCK ? (BlockHitResult) hitResult : null; + } +} diff --git a/src/client/java/dev/quickinfos/utils/ScreenUtils.java b/src/client/java/dev/quickinfos/utils/ScreenUtils.java new file mode 100644 index 0000000..6f5bff9 --- /dev/null +++ b/src/client/java/dev/quickinfos/utils/ScreenUtils.java @@ -0,0 +1,12 @@ +package dev.quickinfos.utils; + +import dev.quickinfos.screen.QuickInfosScreen; +import net.minecraft.client.MinecraftClient; +import net.minecraft.text.Text; +import org.jetbrains.annotations.NotNull; + +public class ScreenUtils { + public static void openScreen(@NotNull MinecraftClient client){ + client.send(() -> client.setScreen(new QuickInfosScreen(Text.empty()))); + } +} diff --git a/src/client/java/dev/quickinfos/utils/StaticUtils.java b/src/client/java/dev/quickinfos/utils/StaticUtils.java new file mode 100644 index 0000000..b4af6ee --- /dev/null +++ b/src/client/java/dev/quickinfos/utils/StaticUtils.java @@ -0,0 +1,9 @@ +package dev.quickinfos.utils; + +public class StaticUtils { + public static final String NONE_INFO_CALCULATED = ""; + public static final String CONFIG_FILE_PATH = "quickinfos_mod.json"; + public static final String LAYER_ID = "quickinfos"; + public static final String COMMAND_LITERAL = "quickinfos"; + public static final String QUICKINFOS_CATEGORY_CONTROLS = "Quickinfos"; +}