From 347ec658bb89103630ac13d4103f56dcf7880d20 Mon Sep 17 00:00:00 2001 From: retuci0 Date: Wed, 31 Dec 2025 00:44:36 +0100 Subject: [PATCH] v2.0 --- .gitignore | 4 +- cambios.md | 19 +- gradle.properties | 2 +- .../me/retucio/camtweaks/CameraTweaks.java | 47 ++- .../command/args/EntityArgumentType.java | 4 +- .../command/commands/EnderChestCommand.java | 20 +- .../command/commands/SpectateCommand.java | 3 +- .../camtweaks/config/ClientConfig.java | 3 +- .../camtweaks/config/ConfigManager.java | 294 ++++++++++++------ .../camtweaks/event/JoinWorldEvent.java | 21 ++ .../camtweaks/event/events/PacketEvent.java | 4 +- .../events/camtweaks/UpdateSettingEvent.java | 8 +- .../camtweaks/mixin/InGameHudMixin.java | 2 +- .../camtweaks/mixin/MinecraftClientMixin.java | 8 + .../mixin/accessor/HandledScreenAccessor.java | 3 + .../me/retucio/camtweaks/module/Module.java | 19 +- .../camtweaks/module/ModuleManager.java | 14 +- .../camtweaks/module/modules/BlockESP.java | 96 ++++++ .../module/modules/BreakingProgress.java | 80 +++++ .../camtweaks/module/modules/ChatPlus.java | 6 +- .../retucio/camtweaks/module/modules/HUD.java | 20 +- .../module/modules/InventoryPlus.java | 70 +++++ .../module/modules/LightOverlay.java | 1 + .../camtweaks/module/modules/LogoutSpots.java | 35 +-- .../camtweaks/module/modules/Nametags.java | 22 +- .../camtweaks/module/modules/Offhand.java | 83 +++++ .../camtweaks/module/modules/PacketDelay.java | 148 +++++++++ .../camtweaks/module/modules/Racist.java | 59 ++++ .../camtweaks/module/modules/ShulkerPeek.java | 5 +- .../camtweaks/module/modules/UIMove.java | 88 ++++++ .../module/modules/WarnLowDurability.java | 38 ++- .../module/settings/BooleanSetting.java | 5 +- .../module/settings/ColorSetting.java | 3 +- .../module/settings/EnumSetting.java | 5 +- .../camtweaks/module/settings/KeySetting.java | 2 +- .../module/settings/ListSetting.java | 29 +- .../module/settings/NumberSetting.java | 5 +- .../module/settings/OptionSetting.java | 98 ++++++ .../{AbstractSetting.java => Setting.java} | 4 +- .../module/settings/StringSetting.java | 5 +- .../me/retucio/camtweaks/ui/HudRenderer.java | 241 -------------- .../camtweaks/ui/buttons/ChooseButton.java | 134 ++++++++ .../camtweaks/ui/buttons/SettingButton.java | 8 +- .../camtweaks/ui/frames/ColorPickerFrame.java | 9 +- .../camtweaks/ui/frames/SettingsFrame.java | 5 +- .../ui/{screen => hud}/HudEditorScreen.java | 123 +++----- .../retucio/camtweaks/ui/hud/HudElement.java | 91 ++++++ .../retucio/camtweaks/ui/hud/HudRenderer.java | 111 +++++++ .../ui/hud/elements/CoordsElement.java | 51 +++ .../ui/hud/elements/CustomTextElement.java | 49 +++ .../camtweaks/ui/hud/elements/FpsElement.java | 32 ++ .../ui/hud/elements/PingElement.java | 37 +++ .../ui/hud/elements/TimeElement.java | 33 ++ .../camtweaks/ui/hud/elements/TpsElement.java | 33 ++ .../retucio/camtweaks/ui/screen/ClickGUI.java | 7 +- .../retucio/camtweaks/ui/widgets/Button.java | 36 +++ .../retucio/camtweaks/ui/widgets/Frame.java | 63 ++++ .../camtweaks/ui/widgets/HudElement.java | 145 --------- .../me/retucio/camtweaks/util/ChatUtil.java | 2 +- .../me/retucio/camtweaks/util/EntityUtil.java | 103 ++++++ .../retucio/camtweaks/util/InventoryUtil.java | 264 ++++++++++++++++ .../me/retucio/camtweaks/util/KeyUtil.java | 5 + .../java/me/retucio/camtweaks/util/Lists.java | 49 ++- .../me/retucio/camtweaks/util/MiscUtil.java | 77 ++--- .../retucio/camtweaks/util/NetworkUtil.java | 74 +++++ .../camtweaks/util/render/RenderUtil.java | 195 +++++++----- src/main/resources/camtweaks.accesswidener | 12 +- 67 files changed, 2522 insertions(+), 849 deletions(-) create mode 100644 src/main/java/me/retucio/camtweaks/event/JoinWorldEvent.java create mode 100644 src/main/java/me/retucio/camtweaks/module/modules/BlockESP.java create mode 100644 src/main/java/me/retucio/camtweaks/module/modules/BreakingProgress.java create mode 100644 src/main/java/me/retucio/camtweaks/module/modules/InventoryPlus.java create mode 100644 src/main/java/me/retucio/camtweaks/module/modules/Offhand.java create mode 100644 src/main/java/me/retucio/camtweaks/module/modules/PacketDelay.java create mode 100644 src/main/java/me/retucio/camtweaks/module/modules/Racist.java create mode 100644 src/main/java/me/retucio/camtweaks/module/modules/UIMove.java create mode 100644 src/main/java/me/retucio/camtweaks/module/settings/OptionSetting.java rename src/main/java/me/retucio/camtweaks/module/settings/{AbstractSetting.java => Setting.java} (92%) delete mode 100644 src/main/java/me/retucio/camtweaks/ui/HudRenderer.java create mode 100644 src/main/java/me/retucio/camtweaks/ui/buttons/ChooseButton.java rename src/main/java/me/retucio/camtweaks/ui/{screen => hud}/HudEditorScreen.java (52%) create mode 100644 src/main/java/me/retucio/camtweaks/ui/hud/HudElement.java create mode 100644 src/main/java/me/retucio/camtweaks/ui/hud/HudRenderer.java create mode 100644 src/main/java/me/retucio/camtweaks/ui/hud/elements/CoordsElement.java create mode 100644 src/main/java/me/retucio/camtweaks/ui/hud/elements/CustomTextElement.java create mode 100644 src/main/java/me/retucio/camtweaks/ui/hud/elements/FpsElement.java create mode 100644 src/main/java/me/retucio/camtweaks/ui/hud/elements/PingElement.java create mode 100644 src/main/java/me/retucio/camtweaks/ui/hud/elements/TimeElement.java create mode 100644 src/main/java/me/retucio/camtweaks/ui/hud/elements/TpsElement.java create mode 100644 src/main/java/me/retucio/camtweaks/ui/widgets/Button.java create mode 100644 src/main/java/me/retucio/camtweaks/ui/widgets/Frame.java delete mode 100644 src/main/java/me/retucio/camtweaks/ui/widgets/HudElement.java create mode 100644 src/main/java/me/retucio/camtweaks/util/EntityUtil.java create mode 100644 src/main/java/me/retucio/camtweaks/util/InventoryUtil.java create mode 100644 src/main/java/me/retucio/camtweaks/util/NetworkUtil.java diff --git a/.gitignore b/.gitignore index decfc82..bbd79d1 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,6 @@ replay_*.log todo.txt cambios.md -remappedSrc/ \ No newline at end of file +remappedSrc/ +src/main/java/me/retucio/camtweaks/ui/widgets/Frame.java +src/main/java/me/retucio/camtweaks/ui/widgets/Button.java \ No newline at end of file diff --git a/cambios.md b/cambios.md index b0643f1..22d8216 100644 --- a/cambios.md +++ b/cambios.md @@ -1,15 +1,28 @@ -# v1.9.1 +# v2.0 ## novedades -- ARREGLADO EL SELECTOR DE COLORES - ### adiciones +- ajuste de opción: similar a enumsetting, pero abre un marco de selección, igual que listsetting. + #### módulos nuevos: +- resaltado de bloques: resalta bloques de cierto tipo renderizando una caja con su forma, visible a través de paredes +- delay de paquetes: simula un ping alto añadiendo delay a los paquetes +- inventario plus: te permite mover items a cualquier slot del inventario mediante teclas (ej.: d + tecla para slot 4); +- progreso de minado: muestra el progreso de minado de un bloque de una manera más visual, mediante cajas de color +- mano secundaria: equipa de manera automática un ítem en tu mano secundaria +- moverse en interfaz: te permite utilizar las teclas de movimiento con ciertas interfaces abiertas (configurable) + ### arreglos / mejoras +- ahora se pueden mostrar también las coordenadas del nether en el elemento del hud para coordenadas +- ahora ChatPlus utilizará los corchetes [] para mostrar la hora (antes era <>), además de también detectar cuando un jugador se une a la hora de dibujar las cabezas +- ahora puedes elegir el sonido en aviso de baja dur., junto a la altura y volumen de este +- ya no se pueden abrir interfaces del mod estando en pantallas donde se suele escribir (chat, carteles, etc.) +- arreglado algunos problemas con las configuraciones + ## problemas reconocidos - muchos, pero repórtalos en la página de problemas si quieres para que queden bien registrados \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index b5d7c0a..227a1f5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.21.10+build.2 loader_version=0.17.3 loom_version=1.11-SNAPSHOT -mod_version=1.9 +mod_version=2.0 maven_group=me.retucio archives_base_name=camtweaks diff --git a/src/main/java/me/retucio/camtweaks/CameraTweaks.java b/src/main/java/me/retucio/camtweaks/CameraTweaks.java index 6b00a59..5fee35c 100644 --- a/src/main/java/me/retucio/camtweaks/CameraTweaks.java +++ b/src/main/java/me/retucio/camtweaks/CameraTweaks.java @@ -18,27 +18,30 @@ import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.modules.HUD; import me.retucio.camtweaks.ui.screen.ClickGUI; -import me.retucio.camtweaks.ui.screen.HudEditorScreen; -import me.retucio.camtweaks.ui.HudRenderer; +import me.retucio.camtweaks.ui.hud.HudEditorScreen; +import me.retucio.camtweaks.ui.hud.HudRenderer; import me.retucio.camtweaks.ui.buttons.BindButton; import me.retucio.camtweaks.ui.buttons.SettingButton; import me.retucio.camtweaks.ui.buttons.TextButton; import me.retucio.camtweaks.ui.frames.ClientSettingsFrame; import me.retucio.camtweaks.ui.frames.SettingsFrame; -import me.retucio.camtweaks.util.ChatUtil; -import me.retucio.camtweaks.util.KeyUtil; -import me.retucio.camtweaks.util.Lists; -import me.retucio.camtweaks.util.MiscUtil; +import me.retucio.camtweaks.util.*; +import me.retucio.camtweaks.util.render.DrawUtil; +import me.retucio.camtweaks.util.render.RenderUtil; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.SharedConstants; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.ChatScreen; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ingame.AbstractCommandBlockScreen; +import net.minecraft.client.gui.screen.ingame.AbstractSignEditScreen; +import net.minecraft.client.gui.screen.ingame.AnvilScreen; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -68,7 +71,7 @@ public class CameraTweaks implements ClientModInitializer { private Screen prevScreen; - public boolean settingsApplied = false; + public static boolean settingsApplied = false; @Override @@ -80,14 +83,20 @@ public class CameraTweaks implements ClientModInitializer { ConfigManager.load(); EVENT_BUS.register(this); + EVENT_BUS.register(new HudRenderer()); - EVENT_BUS.register(MiscUtil.class); EVENT_BUS.register(ChatUtil.class); + EVENT_BUS.register(DrawUtil.class); + EVENT_BUS.register(EntityUtil.class); + EVENT_BUS.register(InventoryUtil.class); + EVENT_BUS.register(MiscUtil.class); + EVENT_BUS.register(NetworkUtil.class); + EVENT_BUS.register(RenderUtil.class); Lists.init(); - ModuleManager.INSTANCE = new ModuleManager(EVENT_BUS); + ModuleManager.INSTANCE = new ModuleManager(); EVENT_BUS.post(new LoadModuleManagerEvent()); CommandManager.INSTANCE = new CommandManager(); @@ -172,7 +181,8 @@ public class CameraTweaks implements ClientModInitializer { // maneja la lógica de apertura de la interfaz private void handleClickGUIKey(int key, boolean anyFocused) { - if (key != ClientSettingsFrame.guiSettings.getKey() || anyFocused) return; + if (key != ClientSettingsFrame.guiSettings.getKey() || anyFocused || isOnTypingScreen()) + return; // al parecer esto hace que con la tecla de la interfaz puedas ir cambiando de splash text en la pantalla del título // pero me ha hecho gracia así que así se queda @@ -188,13 +198,13 @@ public class CameraTweaks implements ClientModInitializer { // manejar la lógica de apertura del editor de elementos del hud, con la misma lógica que handleClickGUIKey() private void handleHudEditorKey(int key, boolean anyFocused) { HUD hud = ModuleManager.INSTANCE.getModuleByClass(HUD.class); - if (key != hud.editorKey.getKey() || anyFocused) return; - if (!hud.isEnabled()) { - ChatUtil.warn("HUD está desactivado, lumbreras"); - return; - } + if (key != hud.editorKey.getKey() || anyFocused || isOnTypingScreen()) return; if (mc.currentScreen != HudEditorScreen.INSTANCE) { + if (!hud.isEnabled()) { + ChatUtil.warn("HUD está desactivado, lumbreras"); + return; + } prevScreen = mc.currentScreen; mc.setScreen(HudEditorScreen.INSTANCE); } else { @@ -212,6 +222,13 @@ public class CameraTweaks implements ClientModInitializer { module.setEnabled(false); } + private boolean isOnTypingScreen() { + return mc.currentScreen instanceof ChatScreen + || mc.currentScreen instanceof AnvilScreen + || mc.currentScreen instanceof AbstractSignEditScreen + || mc.currentScreen instanceof AbstractCommandBlockScreen; + } + @SubscribeEvent public void onStop(ShutdownEvent event) { ConfigManager.save(); diff --git a/src/main/java/me/retucio/camtweaks/command/args/EntityArgumentType.java b/src/main/java/me/retucio/camtweaks/command/args/EntityArgumentType.java index 348bd42..dbacea3 100644 --- a/src/main/java/me/retucio/camtweaks/command/args/EntityArgumentType.java +++ b/src/main/java/me/retucio/camtweaks/command/args/EntityArgumentType.java @@ -8,7 +8,7 @@ import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import me.retucio.camtweaks.util.MiscUtil; +import me.retucio.camtweaks.util.EntityUtil; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.text.Text; @@ -190,7 +190,7 @@ public class EntityArgumentType implements ArgumentType { builder.suggest("@r"); builder.suggest("@s"); - Entity lookingAt = MiscUtil.getEntityPlayerIsLookingAt(); + Entity lookingAt = EntityUtil.getEntityPlayerIsLookingAt(); if (lookingAt != null) builder.suggest(lookingAt.getUuid().toString()); diff --git a/src/main/java/me/retucio/camtweaks/command/commands/EnderChestCommand.java b/src/main/java/me/retucio/camtweaks/command/commands/EnderChestCommand.java index 66789aa..3379c92 100644 --- a/src/main/java/me/retucio/camtweaks/command/commands/EnderChestCommand.java +++ b/src/main/java/me/retucio/camtweaks/command/commands/EnderChestCommand.java @@ -4,23 +4,11 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder; import me.retucio.camtweaks.CameraTweaks; import me.retucio.camtweaks.command.Command; import me.retucio.camtweaks.event.SubscribeEvent; -import me.retucio.camtweaks.event.events.DisconnectEvent; -import me.retucio.camtweaks.event.events.OpenScreenEvent; -import me.retucio.camtweaks.event.events.PacketEvent; import me.retucio.camtweaks.event.events.TickEvent; import me.retucio.camtweaks.ui.screen.PreviewScreen; import me.retucio.camtweaks.util.ChatUtil; -import me.retucio.camtweaks.util.MiscUtil; -import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; +import me.retucio.camtweaks.util.InventoryUtil; import net.minecraft.command.CommandSource; -import net.minecraft.inventory.EnderChestInventory; -import net.minecraft.inventory.Inventories; -import net.minecraft.inventory.Inventory; -import net.minecraft.inventory.SimpleInventory; -import net.minecraft.network.packet.s2c.play.CloseScreenS2CPacket; -import net.minecraft.screen.GenericContainerScreenHandler; -import net.minecraft.text.Text; -import net.minecraft.util.ActionResult; // accede a los contenidos de tu enderchest public class EnderChestCommand extends Command { @@ -36,7 +24,7 @@ public class EnderChestCommand extends Command { builder.executes(ctx -> { mc.execute(() -> { if (mc.player == null) return; - if (MiscUtil.getEchestInv() == null) { + if (InventoryUtil.getEchestInv() == null) { ChatUtil.warn("necesitas abrir un enderchest una vez primero"); return; } @@ -52,8 +40,8 @@ public class EnderChestCommand extends Command { public void onTick(TickEvent.Post event) { if (shouldOpenEchest) { shouldOpenEchest = false; - if (MiscUtil.getEchestInv() != null) - mc.setScreen(new PreviewScreen(MiscUtil.getEchestInv(), null)); + if (InventoryUtil.getEchestInv() != null) + mc.setScreen(new PreviewScreen(InventoryUtil.getEchestInv(), null)); } } } \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/command/commands/SpectateCommand.java b/src/main/java/me/retucio/camtweaks/command/commands/SpectateCommand.java index 445ae3a..54c3166 100644 --- a/src/main/java/me/retucio/camtweaks/command/commands/SpectateCommand.java +++ b/src/main/java/me/retucio/camtweaks/command/commands/SpectateCommand.java @@ -5,6 +5,7 @@ import me.retucio.camtweaks.command.Command; import me.retucio.camtweaks.command.args.EntityArgumentType; import me.retucio.camtweaks.event.SubscribeEvent; import me.retucio.camtweaks.event.events.KeyEvent; +import me.retucio.camtweaks.util.EntityUtil; import me.retucio.camtweaks.util.MiscUtil; import net.minecraft.command.CommandSource; import net.minecraft.entity.Entity; @@ -21,7 +22,7 @@ public class SpectateCommand extends Command { builder .executes(ctx -> { // If no argument, use the entity player is looking at mc.execute(() -> { - Entity target = MiscUtil.getEntityPlayerIsLookingAt(); + Entity target = EntityUtil.getEntityPlayerIsLookingAt(); if (target != null) mc.setCameraEntity(target); }); diff --git a/src/main/java/me/retucio/camtweaks/config/ClientConfig.java b/src/main/java/me/retucio/camtweaks/config/ClientConfig.java index c1f8419..79a7d14 100644 --- a/src/main/java/me/retucio/camtweaks/config/ClientConfig.java +++ b/src/main/java/me/retucio/camtweaks/config/ClientConfig.java @@ -57,8 +57,9 @@ public class ClientConfig { case KeySetting k: value = k.getKey(); break; case NumberSetting n: value = n.getValue(); break; case StringSetting s: value = s.getValue(); break; - case ListSetting l: value = l.getValues(); break; + case ListSetting l: value = l.getConfigValues(); break; case ColorSetting c: value = c.getConfigValue(); break; + case OptionSetting o: value = o.getIndex(); break; default: break; } diff --git a/src/main/java/me/retucio/camtweaks/config/ConfigManager.java b/src/main/java/me/retucio/camtweaks/config/ConfigManager.java index 286508f..6093d1d 100644 --- a/src/main/java/me/retucio/camtweaks/config/ConfigManager.java +++ b/src/main/java/me/retucio/camtweaks/config/ConfigManager.java @@ -6,6 +6,7 @@ import me.retucio.camtweaks.CameraTweaks; import me.retucio.camtweaks.module.Module; import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.settings.*; +import me.retucio.camtweaks.ui.frames.ModuleFrame; import me.retucio.camtweaks.ui.screen.ClickGUI; import me.retucio.camtweaks.ui.frames.ClientSettingsFrame; import me.retucio.camtweaks.ui.frames.SettingsFrame; @@ -23,24 +24,29 @@ public class ConfigManager { private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); private static final File CONFIG_FILE = new File("camera_tweaks.json"); - private static boolean loaded = false; + private static boolean loaded = false; private static ClientConfig config = null; + + // ------------------ MÉTODOS PRINCIPALES ------------------ + // guardar configuraciones public static void save() { ensureConfig(); + try (FileWriter writer = new FileWriter(CONFIG_FILE)) { GSON.toJson(config, writer); CameraTweaks.LOGGER.info("ajustes guardados"); } catch (IOException e) { - e.printStackTrace(); + CameraTweaks.LOGGER.error("error al guardar ajustes", e); } } // cargar configuraciones public static void load() { - CameraTweaks.LOGGER.info("ajustes cargados"); + CameraTweaks.LOGGER.info("cargando ajustes..."); + if (!CONFIG_FILE.exists()) { ensureConfig(); save(); @@ -49,79 +55,52 @@ public class ConfigManager { try (FileReader reader = new FileReader(CONFIG_FILE)) { config = GSON.fromJson(reader, ClientConfig.class); + CameraTweaks.LOGGER.info("ajustes cargados"); } catch (IOException e) { - e.printStackTrace(); + CameraTweaks.LOGGER.error("no se pudieron cargar los ajustes, usando ajustes por defecto", e); ensureConfig(); } } // aplicar configuraciones cargadas public static void applyConfig() { - if (CameraTweaks.mc == null || ModuleManager.INSTANCE == null || config == null) - return; + if (!shouldApply()) return; - ModuleManager.INSTANCE.getModules().forEach(module -> { - if (config.moduleStates.containsKey(module.getName())) - module.setEnabled(config.moduleStates.get(module.getName())); // estados - - module.getSettings().forEach(setting -> applySetting(module, setting)); - - if (config.settingsFrames.containsKey(module.getName())) { - int[] position = config.settingsFrames.get(module.getName()); - ClickGUI.INSTANCE.openSettingsFrame(module, position[0], position[1]); - } - }); - - if (config.searchBarPosition != null && config.searchBarPosition.length == 2) { - ClickGUI.INSTANCE.getSearchBar().setX(config.searchBarPosition[0]); - ClickGUI.INSTANCE.getSearchBar().setY(config.searchBarPosition[1]); - } - - ClientSettingsFrame.guiSettings.setEnabled(true); - ClientSettingsFrame.guiSettings.getSettings().forEach(setting -> applySetting(ClientSettingsFrame.guiSettings, setting)); - - CameraTweaks.LOGGER.info("módulos encendidos cargados"); - CameraTweaks.LOGGER.info("ajustes de módulos cargados"); - - ClientConfig.FrameData moduleFrameData = config.extendableFrames.get("M"); - if (moduleFrameData != null) { - ClickGUI.INSTANCE.getModulesFrame().x = moduleFrameData.x(); - ClickGUI.INSTANCE.getModulesFrame().y = moduleFrameData.y(); - ClickGUI.INSTANCE.getModulesFrame().extended = moduleFrameData.extended(); - } - - ClientConfig.FrameData guiSettingsData = config.extendableFrames.get("S"); - if (guiSettingsData != null) { - ClickGUI.INSTANCE.getGuiSettingsFrame().x = guiSettingsData.x(); - ClickGUI.INSTANCE.getGuiSettingsFrame().y = guiSettingsData.y(); - ClickGUI.INSTANCE.getGuiSettingsFrame().extended = guiSettingsData.extended(); - } - - CameraTweaks.LOGGER.info("posiciones de frames cargadas"); - ClickGUI.INSTANCE.refreshListButtons(); + applyModuleStates(); + applyModuleSettings(); + applySettingsFrames(); + applySearchBarPosition(); + applyGuiSettings(); + applyExtendableFrames(); loaded = true; + CameraTweaks.LOGGER.info("ajustes aplicados"); } + // obtener configuración actual public static ClientConfig getConfig() { + ensureConfig(); return config; } + + // ------------------ GUARDAR VALORES INDIVIDUALES EN LA CONFIG. ------------------ + public static void setModuleState(Module module) { ensureConfig(); config.moduleStates.put(module.getName(), module.isEnabled()); save(); } - public static void setSetting(AbstractSetting setting, Object value) { + public static void setSetting(Setting setting, Object value) { ensureConfig(); - config.settings.put(setting.getModule().getName() + ":" + setting.getName(), value); + config.settings.put(getSettingKey(setting), value); save(); } public static void setFramePosition(SettingsFrame frame) { ensureConfig(); - config.settingsFrames.put(frame.module.getName(), new int[]{frame.x, frame.y}); + config.settingsFrames.put(frame.module.getName(), new int[] {frame.x, frame.y}); save(); } @@ -133,7 +112,7 @@ public class ConfigManager { public static void setHudPosition(String id, int x, int y) { ensureConfig(); - config.hudPositions.put(id, new int[]{x, y}); + config.hudPositions.put(id, new int[] {x, y}); save(); } @@ -145,62 +124,197 @@ public class ConfigManager { public static void setSearchBarPosition(int x, int y) { ensureConfig(); - config.searchBarPosition = new int[]{x, y}; + config.searchBarPosition = new int[] {x, y}; save(); } + // ------------------ APLICAR AJUSTES ------------------ + @SuppressWarnings({"rawtypes", "unchecked"}) - public static void applySetting(Module parent, AbstractSetting setting) { - String id = parent.getName() + ":" + setting.getName(); - if (config.settings.containsKey(id)) { - Object value = config.settings.get(id); + public static void applySetting(Module parent, Setting setting) { + String key = getSettingKey(setting); - switch (setting) { - case BooleanSetting b -> b.setEnabled((boolean) value); - case EnumSetting e -> e.setIndex(value instanceof Double val ? val.intValue() : (int) value); - case NumberSetting n -> n.setValue((double) value); - case StringSetting s -> s.setValue((String) value); - case KeySetting k -> k.setKey(value instanceof Double val ? val.intValue() : (int) value); - case ListSetting l -> { - if (value instanceof Map map) { - Map converted = new HashMap<>(); - for (Object option : l.getOptions()) { - Object key = String.valueOf(option); - Object bv = map.get(key); - converted.put(option, bv instanceof Boolean b && b); - } - l.setValues(converted); - } - } case ColorSetting c -> { - if (value instanceof Map map) { - Number r = (Number) map.get("r"); - Number g = (Number) map.get("g"); - Number b = (Number) map.get("b"); - Number a = (Number) map.get("a"); - Boolean rainbow = (Boolean) map.get("rb"); - Number rainbowSpeed = (Number) map.get("rs"); - Number saturation = (Number) map.get("sat"); - Number brightness = (Number) map.get("bri"); + if (!config.settings.containsKey(key)) return; - if (r != null && g != null && b != null && a != null) - c.setRGB(r.intValue(), g.intValue(), b.intValue(), a.intValue()); + Object value = config.settings.get(key); - if (rainbow != null) c.setRainbow(rainbow); - if (rainbowSpeed != null) c.setRainbowSpeed(rainbowSpeed.intValue()); - if (saturation != null) c.setSaturation(saturation.floatValue()); - if (brightness != null) c.setBrightness(brightness.floatValue()); - } - } - default -> {} - } + switch (setting) { + case BooleanSetting booleanSetting -> applyBooleanSetting(booleanSetting, value); + case EnumSetting enumSetting -> applyEnumSetting(enumSetting, value); + case NumberSetting numberSetting -> applyNumberSetting(numberSetting, value); + case StringSetting stringSetting -> applyStringSetting(stringSetting, value); + case KeySetting keySetting -> applyKeySetting(keySetting, value); + case ListSetting listSetting -> applyListSetting(listSetting, value); + case ColorSetting colorSetting -> applyColorSetting(colorSetting, value); + case OptionSetting optionSetting -> applyOptionSetting(optionSetting, value); + default -> CameraTweaks.LOGGER.warn("watafac queseso: {}", setting.getClass().getSimpleName()); } } + private static void applyModuleStates() { + ModuleManager.INSTANCE.getModules().forEach(module -> { + if (config.moduleStates.containsKey(module.getName())) { + module.setEnabled(config.moduleStates.get(module.getName())); + } + }); + CameraTweaks.LOGGER.info("estados de módulos aplicados"); + } + + private static void applyModuleSettings() { + ModuleManager.INSTANCE.getModules().forEach(module -> { + module.getSettings().forEach(setting -> applySetting(module, setting)); + }); + CameraTweaks.LOGGER.info("ajustes de módulos aplicados"); + } + + private static void applySettingsFrames() { + config.settingsFrames.forEach((moduleName, position) -> { + Module module = ModuleManager.INSTANCE.getModuleByName(moduleName); + ClickGUI.INSTANCE.openSettingsFrame(module, position[0], position[1]); + }); + CameraTweaks.LOGGER.info("estados de marcos de ajustes aplicados"); + } + + private static void applySearchBarPosition() { + if (config.searchBarPosition != null && config.searchBarPosition.length == 2) { + ClickGUI.INSTANCE.getSearchBar().setX(config.searchBarPosition[0]); + ClickGUI.INSTANCE.getSearchBar().setY(config.searchBarPosition[1]); + } + CameraTweaks.LOGGER.info("posición de la barra de búsqueda aplicada"); + } + + private static void applyGuiSettings() { + ClientSettingsFrame.guiSettings.setEnabled(true); + ClientSettingsFrame.guiSettings.getSettings().forEach(setting -> { + applySetting(ClientSettingsFrame.guiSettings, setting); + }); + CameraTweaks.LOGGER.info("ajustes del cliente aplicados"); + } + + private static void applyExtendableFrames() { + applyExtendableFrame(ClickGUI.INSTANCE.getModulesFrame()); + applyExtendableFrame(ClickGUI.INSTANCE.getGuiSettingsFrame()); + + CameraTweaks.LOGGER.info("posiciones de marcos extendibles aplicadasa"); + ClickGUI.INSTANCE.refreshListButtons(); + } + + private static void applyExtendableFrame(ModuleFrame frame) { + ClientConfig.FrameData frameData = config.extendableFrames.get("M"); + if (frameData != null) { + frame.x = frameData.x(); + frame.y = frameData.y(); + frame.extended = frameData.extended(); + } + } + + private static void applyExtendableFrame(ClientSettingsFrame frame) { + ClientConfig.FrameData frameData = config.extendableFrames.get("S"); + if (frameData != null) { + frame.x = frameData.x(); + frame.y = frameData.y(); + frame.extended = frameData.extended(); + } + } + + // ajustes de módulos + + private static void applyBooleanSetting(BooleanSetting setting, Object value) { + if (value instanceof Boolean) { + setting.setEnabled((Boolean) value); + } + } + + private static > void applyEnumSetting(EnumSetting setting, Object value) { + if (value instanceof Double) { + setting.setIndex(((Double) value).intValue()); + } else if (value instanceof Integer) { + setting.setIndex((Integer) value); + } + } + + private static void applyNumberSetting(NumberSetting setting, Object value) { + if (value instanceof Double) { + setting.setValue((Double) value); + } + } + + private static void applyStringSetting(StringSetting setting, Object value) { + if (value instanceof String) { + setting.setValue((String) value); + } + } + + private static void applyKeySetting(KeySetting setting, Object value) { + if (value instanceof Double) { + setting.setKey(((Double) value).intValue()); + } else if (value instanceof Integer) { + setting.setKey((Integer) value); + } + } + + private static void applyListSetting(ListSetting setting, Object value) { + if (value instanceof Map map) { + Map convertedValues = new HashMap<>(); + + for (T option : setting.getOptions()) { + String key = setting.getDisplayName(option); + Object booleanValue = map.get(key); + convertedValues.put(option, booleanValue instanceof Boolean && (Boolean) booleanValue); + } + + setting.setValues(convertedValues); + } + } + + private static void applyColorSetting(ColorSetting setting, Object value) { + if (!(value instanceof Map map)) return; + + Number r = (Number) map.get("r"); + Number g = (Number) map.get("g"); + Number b = (Number) map.get("b"); + Number a = (Number) map.get("a"); + + if (r != null && g != null && b != null && a != null) + setting.setRGB(r.intValue(), g.intValue(), b.intValue(), a.intValue()); + + applyOptionalProperty(map, "rb", Boolean.class, setting::setRainbow); + applyOptionalProperty(map, "rs", Number.class, val -> setting.setRainbowSpeed(val.intValue())); + applyOptionalProperty(map, "sat", Number.class, val -> setting.setSaturation(val.floatValue())); + applyOptionalProperty(map, "bri", Number.class, val -> setting.setBrightness(val.floatValue())); + } + + private static void applyOptionSetting(OptionSetting setting, Object value) { + if (value instanceof Double) { + int index = ((Double) value).intValue(); + setting.setValue(setting.getOption(index)); + } + } + + private static void applyOptionalProperty(Map map, String key, Class type, java.util.function.Consumer setter) { + Object value = map.get(key); + if (type.isInstance(value)) { + setter.accept(type.cast(value)); + } + } + + + // ------------------ MÉTODOS DE AYUDA ------------------ + + private static boolean shouldApply() { + return CameraTweaks.mc != null && ModuleManager.INSTANCE != null && config != null; + } + + private static void ensureConfig() { if (config == null) config = new ClientConfig(); } + private static String getSettingKey(Setting setting) { + return setting.getModule().getName() + ":" + setting.getName(); + } + public static boolean hasLoaded() { return loaded; } diff --git a/src/main/java/me/retucio/camtweaks/event/JoinWorldEvent.java b/src/main/java/me/retucio/camtweaks/event/JoinWorldEvent.java new file mode 100644 index 0000000..6a82e37 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/event/JoinWorldEvent.java @@ -0,0 +1,21 @@ +package me.retucio.camtweaks.event; + +import net.minecraft.client.world.ClientWorld; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + + +/** + * @see me.retucio.camtweaks.mixin.MinecraftClientMixin#onJoinWorld + */ +public class JoinWorldEvent extends Event { + + private final ClientWorld world; + + public JoinWorldEvent(ClientWorld world) { + this.world = world; + } + + public ClientWorld getWorld() { + return world; + } +} diff --git a/src/main/java/me/retucio/camtweaks/event/events/PacketEvent.java b/src/main/java/me/retucio/camtweaks/event/events/PacketEvent.java index ca72ef2..7bc4e23 100644 --- a/src/main/java/me/retucio/camtweaks/event/events/PacketEvent.java +++ b/src/main/java/me/retucio/camtweaks/event/events/PacketEvent.java @@ -1,12 +1,14 @@ package me.retucio.camtweaks.event.events; +import io.netty.channel.ChannelFutureListener; import me.retucio.camtweaks.event.Event; import me.retucio.camtweaks.event.Stage; import net.minecraft.network.packet.Packet; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; /** - * @see me.retucio.camtweaks.mixin.ClientConnectionMixin#onSendPacketPre + * @see me.retucio.camtweaks.mixin.ClientConnectionMixin#onSendPacketPre * @see me.retucio.camtweaks.mixin.ClientConnectionMixin#onSendPacketPost * @see me.retucio.camtweaks.mixin.ClientConnectionMixin#onReceivePacket */ diff --git a/src/main/java/me/retucio/camtweaks/event/events/camtweaks/UpdateSettingEvent.java b/src/main/java/me/retucio/camtweaks/event/events/camtweaks/UpdateSettingEvent.java index d817f73..3a9d18d 100644 --- a/src/main/java/me/retucio/camtweaks/event/events/camtweaks/UpdateSettingEvent.java +++ b/src/main/java/me/retucio/camtweaks/event/events/camtweaks/UpdateSettingEvent.java @@ -1,20 +1,20 @@ package me.retucio.camtweaks.event.events.camtweaks; import me.retucio.camtweaks.event.Event; -import me.retucio.camtweaks.module.settings.AbstractSetting; +import me.retucio.camtweaks.module.settings.Setting; // se genera cada que se cambia el valor de un ajuste public class UpdateSettingEvent extends Event { - private final AbstractSetting setting; + private final Setting setting; private boolean shouldSave; - public UpdateSettingEvent(AbstractSetting setting, boolean shouldSave) { + public UpdateSettingEvent(Setting setting, boolean shouldSave) { this.setting = setting; this.shouldSave = shouldSave; } - public AbstractSetting getSetting() { + public Setting getSetting() { return setting; } diff --git a/src/main/java/me/retucio/camtweaks/mixin/InGameHudMixin.java b/src/main/java/me/retucio/camtweaks/mixin/InGameHudMixin.java index f406f43..599e6ea 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/InGameHudMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/InGameHudMixin.java @@ -5,7 +5,7 @@ import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.modules.ChatPlus; import me.retucio.camtweaks.module.modules.Freecam; import me.retucio.camtweaks.module.modules.NoRender; -import me.retucio.camtweaks.ui.HudRenderer; +import me.retucio.camtweaks.ui.hud.HudRenderer; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.hud.InGameHud; diff --git a/src/main/java/me/retucio/camtweaks/mixin/MinecraftClientMixin.java b/src/main/java/me/retucio/camtweaks/mixin/MinecraftClientMixin.java index 7ce972f..90f930e 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/MinecraftClientMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/MinecraftClientMixin.java @@ -4,6 +4,7 @@ import com.ibm.icu.util.CodePointTrie; import com.llamalad7.mixinextras.injector.ModifyReturnValue; import com.llamalad7.mixinextras.sugar.Local; import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.event.JoinWorldEvent; import me.retucio.camtweaks.event.events.OpenScreenEvent; import me.retucio.camtweaks.event.events.ShutdownEvent; import me.retucio.camtweaks.event.events.TickEvent; @@ -12,6 +13,7 @@ import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.modules.FastUse; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.world.ClientWorld; import net.minecraft.item.ItemStack; import net.minecraft.util.Hand; import org.spongepowered.asm.mixin.Mixin; @@ -70,4 +72,10 @@ public abstract class MinecraftClientMixin { if (!fastUse.isEnabled()) return; itemUseCooldown = fastUse.getCooldown(stack); } + + @Inject(method = "joinWorld", at = @At("HEAD"), cancellable = true) + private void onJoinWorld(ClientWorld world, CallbackInfo ci) { + JoinWorldEvent event = EVENT_BUS.post(new JoinWorldEvent(world)); + if (event.isCancelled()) ci.cancel(); + } } \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/accessor/HandledScreenAccessor.java b/src/main/java/me/retucio/camtweaks/mixin/accessor/HandledScreenAccessor.java index 4f1aa3a..459aa3f 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/accessor/HandledScreenAccessor.java +++ b/src/main/java/me/retucio/camtweaks/mixin/accessor/HandledScreenAccessor.java @@ -10,4 +10,7 @@ public interface HandledScreenAccessor { @Accessor("focusedSlot") Slot getFocusedSlot(); + + @Accessor("doubleClicking") + void setDoubleClicking(boolean doubleClicking); } diff --git a/src/main/java/me/retucio/camtweaks/module/Module.java b/src/main/java/me/retucio/camtweaks/module/Module.java index f69cef9..dee514d 100644 --- a/src/main/java/me/retucio/camtweaks/module/Module.java +++ b/src/main/java/me/retucio/camtweaks/module/Module.java @@ -1,12 +1,14 @@ package me.retucio.camtweaks.module; import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.config.ClientConfig; +import me.retucio.camtweaks.config.ConfigManager; import me.retucio.camtweaks.event.SubscribeEvent; import me.retucio.camtweaks.event.events.camtweaks.ToggleModuleEvent; import me.retucio.camtweaks.module.settings.BooleanSetting; import me.retucio.camtweaks.module.settings.EnumSetting; import me.retucio.camtweaks.module.settings.KeySetting; -import me.retucio.camtweaks.module.settings.AbstractSetting; +import me.retucio.camtweaks.module.settings.Setting; import me.retucio.camtweaks.util.ChatUtil; import net.minecraft.client.MinecraftClient; import org.lwjgl.glfw.GLFW; @@ -30,7 +32,7 @@ public class Module { protected KeySetting bind = new KeySetting("tecla", "tecla asignada al módulo, ESC para desactivar", GLFW.GLFW_KEY_UNKNOWN); protected BooleanSetting notify = new BooleanSetting("notificar", "notificar en el chat al activar / desactivar", true); - private final List settings = new ArrayList<>(); + private final List settings = new ArrayList<>(); protected MinecraftClient mc = MinecraftClient.getInstance(); @@ -45,23 +47,26 @@ public class Module { this.description = description; addSettings(bind, keyMode, notify); this.bind.setDefaultKey(key); - this.bind.setKey(key); + + // puto marcos + if (ConfigManager.getConfig().settings.get(this.getName() + ":" + bind.getName()) == null) + this.bind.setKey(key); } // ajustes - public List getSettings() { + public List getSettings() { return settings; } @SuppressWarnings("unchecked") - public S addSetting(AbstractSetting setting) { + public S addSetting(Setting setting) { settings.add(setting); setting.setModule(this); return (S) setting; // por conveniencia } - public void addSettings(AbstractSetting... settings) { - for (AbstractSetting setting : settings) addSetting(setting); + public void addSettings(Setting... settings) { + for (Setting setting : settings) addSetting(setting); } diff --git a/src/main/java/me/retucio/camtweaks/module/ModuleManager.java b/src/main/java/me/retucio/camtweaks/module/ModuleManager.java index a9b91d5..795a83d 100644 --- a/src/main/java/me/retucio/camtweaks/module/ModuleManager.java +++ b/src/main/java/me/retucio/camtweaks/module/ModuleManager.java @@ -1,5 +1,6 @@ package me.retucio.camtweaks.module; +import me.retucio.camtweaks.CameraTweaks; import me.retucio.camtweaks.event.EventBus; import me.retucio.camtweaks.event.SubscribeEvent; import me.retucio.camtweaks.module.modules.*; @@ -16,10 +17,8 @@ public class ModuleManager { public static ModuleManager INSTANCE; private final List modules = new ArrayList<>(); - private final EventBus eventBus; - public ModuleManager(EventBus bus) { - this.eventBus = bus; + public ModuleManager() { addModules(); } @@ -29,8 +28,10 @@ public class ModuleManager { modules.add(new AnvilFont()); modules.add(new AttributeSwapper()); modules.add(new AutoSign()); + modules.add(new BlockESP()); modules.add(new BlockOutline()); modules.add(new BossbarStack()); + modules.add(new BreakingProgress()); modules.add(new BungeecordSpoofer()); modules.add(new ChatPlus()); modules.add(new ColoredSigns()); @@ -45,19 +46,24 @@ public class ModuleManager { modules.add(new HandView()); modules.add(new Headhitters()); modules.add(new HUD()); + modules.add(new InventoryPlus()); modules.add(new LightOverlay()); modules.add(new LogoutSpots()); modules.add(new Nametags()); modules.add(new NoMiningInterruptions()); modules.add(new NoRender()); + modules.add(new Offhand()); + modules.add(new PacketDelay()); modules.add(new PerspectivePlus()); modules.add(new PortalGUI()); + modules.add(new Racist()); modules.add(new Reconnect()); modules.add(new Rotations()); modules.add(new RPackBypass()); modules.add(new ScreenshotPlus()); modules.add(new ShulkerPeek()); modules.add(new TimeChanger()); + modules.add(new UIMove()); modules.add(new WarnLowDurability()); modules.add(new Zoom()); @@ -67,7 +73,7 @@ public class ModuleManager { for (Module module : getEnabledModules()) { for (Method method : module.getClass().getDeclaredMethods()) { if (method.isAnnotationPresent(SubscribeEvent.class)) { - eventBus.register(module); + CameraTweaks.EVENT_BUS.register(module); break; } } diff --git a/src/main/java/me/retucio/camtweaks/module/modules/BlockESP.java b/src/main/java/me/retucio/camtweaks/module/modules/BlockESP.java new file mode 100644 index 0000000..5ab937a --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/module/modules/BlockESP.java @@ -0,0 +1,96 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.event.events.RenderWorldEvent; +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.BooleanSetting; +import me.retucio.camtweaks.module.settings.ColorSetting; +import me.retucio.camtweaks.module.settings.ListSetting; +import me.retucio.camtweaks.module.settings.NumberSetting; +import me.retucio.camtweaks.util.Colors; +import me.retucio.camtweaks.util.Lists; +import me.retucio.camtweaks.util.render.RenderUtil; +import net.minecraft.block.Block; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3i; +import net.minecraft.util.shape.VoxelShape; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + + +public class BlockESP extends Module { + + public ListSetting blocks = addSetting(new ListSetting<>("bloques", "bloques a resaltar", + Lists.blockList, Lists.allFalse(Lists.blockList), Lists.blockNames)); + + public NumberSetting radius = addSetting(new NumberSetting("radio", "radio de búsqueda de bloques", 24, 2, 128, 1)); + + public BooleanSetting outlines = addSetting(new BooleanSetting("contorno", "renderizar contorno de bloques", true)); + public ColorSetting outlineColor = addSetting(new ColorSetting("color del contorno", "color del contorno", Colors.CELESTE, false)); + public NumberSetting lineWidth = addSetting(new NumberSetting("grosor del contorno", "grosor de las líneas del contorno", 1, 1, 5, 0.2)); + + public BooleanSetting fillings = addSetting(new BooleanSetting("relleno", "renderizar relleno de bloques", true)); + public ColorSetting fillingColor = addSetting(new ColorSetting("color del relleno", "color del relleno", new Color(57, 177, 215, 67), false)); + + + public BlockESP() { + super("resaltado de bloques", "te muestra la posición de cierto tipo de bloque renderizando una caja con su forma"); + + outlines.onUpdate(v -> { + outlineColor.setVisible(v); + lineWidth.setVisible(v); + }); + + fillings.onUpdate(v -> fillingColor.setVisible(v)); + } + + @SubscribeEvent + public void onRenderWorld(RenderWorldEvent event) { + if (mc.player == null || mc.world == null) return; + + for (Block block : blocks.getOptions()) { + if (blocks.isEnabled(block)) { + List blocksToHighlight = getNearbyBlocks(block); + for (BlockPos pos : blocksToHighlight) { + if (outlines.isEnabled()) { + RenderUtil.drawVoxelShapeOutline( + event.getMatrices(), + getVoxelShape(pos), + pos, + outlineColor.getColor(), + lineWidth.getFloatValue()); + } + if (fillings.isEnabled()) { + RenderUtil.drawVoxelShapeFilled( + event.getMatrices(), + getVoxelShape(pos), + pos, + fillingColor.getColor()); + } + } + } + } + } + + private List getNearbyBlocks(Block block) { + List blockPosList = new ArrayList<>(); + + for (int i = -radius.getIntValue(); i < radius.getIntValue(); i++) { + for (int j = -radius.getIntValue(); j < radius.getIntValue(); j++) { + for (int k = -radius.getIntValue(); k < radius.getIntValue(); k++) { + BlockPos pos = mc.player.getBlockPos().add(new Vec3i(i, j, k)); + if (mc.world.getBlockState(pos).getBlock() == block) { + blockPosList.add(pos); + } + } + } + } + return blockPosList; + } + + private VoxelShape getVoxelShape(BlockPos pos) { + return mc.world.getBlockState(pos).getOutlineShape(mc.world, pos); + } +} diff --git a/src/main/java/me/retucio/camtweaks/module/modules/BreakingProgress.java b/src/main/java/me/retucio/camtweaks/module/modules/BreakingProgress.java new file mode 100644 index 0000000..628a5b7 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/module/modules/BreakingProgress.java @@ -0,0 +1,80 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.event.events.RenderWorldEvent; +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.BooleanSetting; +import me.retucio.camtweaks.module.settings.ColorSetting; +import me.retucio.camtweaks.module.settings.EnumSetting; +import me.retucio.camtweaks.module.settings.NumberSetting; +import me.retucio.camtweaks.util.render.RenderUtil; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.shape.VoxelShape; + +import java.awt.*; + +public class BreakingProgress extends Module { + + public EnumSetting breakMode = addSetting(new EnumSetting<>("modo de minado", "elige si el cubo se encoge o se dilata", + BreakMode.class, BreakMode.INWARDS)); + + public BooleanSetting outlines = addSetting(new BooleanSetting("contorno", "renderizar contorno", true)); + public ColorSetting outlineColor = addSetting(new ColorSetting("color del contorno", "color del contorno", + new Color(0, 255, 0, 200), false)); + public NumberSetting lineWidth = addSetting(new NumberSetting("grosor de línea", "grosor de las líneas del contorno", 1, 1, 5, 0.1)); + + public BooleanSetting fillings = addSetting(new BooleanSetting("relleno", "renderizar relleno", true)); + public ColorSetting fillingColor = addSetting(new ColorSetting("color del relleno", "color del relleno", + new Color(0, 255, 0, 60), false)); + + public BreakingProgress() { + super("progreso de minado", "te muestra el progreso de minado de un bloque de manera más visible"); + } + + @SubscribeEvent + public void onRenderWorld(RenderWorldEvent event) { + if (mc.interactionManager == null || mc.world == null) return; + if (!(mc.crosshairTarget instanceof BlockHitResult hitResult)) return; + BlockPos pos = hitResult.getBlockPos(); + + int breakingProgress = mc.interactionManager.getBlockBreakingProgress(); + if (breakingProgress <= 0) return; + float progress = breakingProgress / 10f; + + VoxelShape shape = mc.world.getBlockState(pos).getOutlineShape(mc.world, pos); + if (shape.isEmpty()) return; + + Box box = shape.getBoundingBox().offset(pos); + + float shrinkFactor = breakMode.is(BreakMode.INWARDS) + ? 1f - progress + : progress; + + double centerX = (box.minX + box.maxX) / 2; + double centerY = (box.minY + box.maxY) / 2; + double centerZ = (box.minZ + box.maxZ) / 2; + + double shrunkX = (box.maxX - box.minX) / 2 * shrinkFactor; + double shrunkY = (box.maxY - box.minY) / 2 * shrinkFactor; + double shrunkZ = (box.maxZ - box.minZ) / 2 * shrinkFactor; + + Box scaledBox = new Box( + centerX - shrunkX, centerY - shrunkY, centerZ - shrunkZ, + centerX + shrunkX, centerY + shrunkZ, centerZ + shrunkZ + ); + + if (outlines.isEnabled()) RenderUtil.drawOutlineBox(event.getMatrices(), scaledBox, outlineColor.getColor(), lineWidth.getFloatValue()); + if (fillings.isEnabled()) RenderUtil.drawFilledBox(event.getMatrices(), scaledBox, fillingColor.getColor()); + } + + public enum BreakMode { + INWARDS("para dentro"), + OUTWARDS("para fuera"); + + private final String name; + BreakMode(String name) { this.name = name; } + @Override public String toString() { return name; } + } +} diff --git a/src/main/java/me/retucio/camtweaks/module/modules/ChatPlus.java b/src/main/java/me/retucio/camtweaks/module/modules/ChatPlus.java index 5576f5a..9a957cb 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/ChatPlus.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/ChatPlus.java @@ -68,7 +68,7 @@ public class ChatPlus extends Module { private SimpleDateFormat dateFormat; private static final Pattern loggerRegex = Pattern.compile("\\n(\\n|\\s)+\\n"); - private static final Pattern usernameRegex = Pattern.compile("^(?:<[0-9]{2}:[0-9]{2}>\\s)?<(.*?)>.*"); + private static final Pattern usernameRegex = Pattern.compile("^(?:\\[[0-9]{2}:[0-9]{2}\\]\\s*)?(?:<([^<>\\s]+)>|([^<>\\s]+)).*"); private static final Pattern timestampRegex = Pattern.compile("^<\\d{1,2}:\\d{1,2}>"); private static final Pattern coordRegex = Pattern.compile("(?-?\\d{3,}(?:\\.\\d*)?)(?:\\s+(?-?\\d{1,3}(?:\\.\\d*)?))?\\s+(?-?\\d{3,}(?:\\.\\d*)?)"); @@ -96,7 +96,7 @@ public class ChatPlus extends Module { // agregar sellos de tiempo a los mensajes if (timestamps.isEnabled()) { - Text timestamp = Text.literal("<" + dateFormat.format(new Date()) + "> ").formatted(Formatting.GRAY); + Text timestamp = Text.literal("[" + dateFormat.format(new Date()) + "] ").formatted(Formatting.GRAY); message = Text.empty().append(timestamp).append(message); } @@ -178,6 +178,8 @@ public class ChatPlus extends Module { if (usernameMatcher.matches()) { String username = usernameMatcher.group(1); + if (username == null) + username = usernameMatcher.group(2); PlayerListEntry entry = mc.getNetworkHandler().getPlayerListEntry(username); if (entry != null) sender = entry.getProfile(); diff --git a/src/main/java/me/retucio/camtweaks/module/modules/HUD.java b/src/main/java/me/retucio/camtweaks/module/modules/HUD.java index 679c883..c4b246e 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/HUD.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/HUD.java @@ -2,14 +2,17 @@ package me.retucio.camtweaks.module.modules; import me.retucio.camtweaks.module.Module; import me.retucio.camtweaks.module.settings.*; -import me.retucio.camtweaks.ui.screen.HudEditorScreen; +import me.retucio.camtweaks.ui.hud.CoordsElement; +import me.retucio.camtweaks.ui.hud.HudElement; +import me.retucio.camtweaks.ui.hud.HudRenderer; +import me.retucio.camtweaks.ui.hud.HudEditorScreen; import org.lwjgl.glfw.GLFW; import java.awt.*; /** lógica del HUD manejada en: - * @see me.retucio.camtweaks.ui.HudRenderer - * @see me.retucio.camtweaks.ui.widgets.HudElement + * @see HudRenderer + * @see HudElement * @see HudEditorScreen */ @@ -28,6 +31,7 @@ public class HUD extends Module { public NumberSetting timezone = addSetting(new NumberSetting("zona horaria", "zona horaria en UTC+n", 1, -6, 6, 1)); public EnumSetting timeFormat = addSetting(new EnumSetting<>("formato de la hora", "12h o 24h", TimeFormat.class, TimeFormat.TWENTY_FOUR_HOUR)); public StringSetting customText = addSetting(new StringSetting("texto custom", "marca de agua (dejar vacío para quitar)", "adolf jitler inshtagram feishbuc twiter", 40)); + public EnumSetting coordsMode = addSetting(new EnumSetting<>("modo de coordenadas", "qué coordenadas mostrar", CoordsMode.class, CoordsMode.OVERWORLD)); public HUD() { super("HUD", "superposición de la pantalla con info. adicional"); @@ -41,4 +45,14 @@ public class HUD extends Module { TimeFormat(String name) { this.name = name; } @Override public String toString() { return name; } } + + public enum CoordsMode { + OVERWORLD("superficie"), + NETHER("nether"), + BOTH("ambas"); + + private final String name; + CoordsMode(String name) { this.name = name; } + @Override public String toString() { return name; } + } } diff --git a/src/main/java/me/retucio/camtweaks/module/modules/InventoryPlus.java b/src/main/java/me/retucio/camtweaks/module/modules/InventoryPlus.java new file mode 100644 index 0000000..6678e28 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/module/modules/InventoryPlus.java @@ -0,0 +1,70 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.event.Event; +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.event.events.KeyEvent; +import me.retucio.camtweaks.event.events.MouseClickEvent; +import me.retucio.camtweaks.mixin.accessor.HandledScreenAccessor; +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.KeySetting; +import me.retucio.camtweaks.util.InventoryUtil; +import me.retucio.camtweaks.util.KeyUtil; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.screen.slot.Slot; +import org.lwjgl.glfw.GLFW; + +public class InventoryPlus extends Module { + + public KeySetting row1key = addSetting(new KeySetting("fila 1", "tecla para mover items a la primera fila", GLFW.GLFW_KEY_A)); + public KeySetting row2key = addSetting(new KeySetting("fila 2", "tecla para mover items a la segunda fila", GLFW.GLFW_KEY_S)); + public KeySetting row3key = addSetting(new KeySetting("fila 3", "tecla para mover items a la tercera fila", GLFW.GLFW_KEY_D)); + + public InventoryPlus() { + super("inventario plus", "mueve ítems del inventario usando solo el teclado"); + } + + @SubscribeEvent + public void onKey(KeyEvent event) { + if (event.getAction() == GLFW.GLFW_RELEASE) return; + processInput(event.getKey(), event); + } + + @SubscribeEvent + public void onMouseButton(MouseClickEvent event) { + if (event.getAction() == GLFW.GLFW_RELEASE) return; + processInput(event.getButton(), event); + } + + private void processInput(int inputCode, Event event) { + if (!(mc.currentScreen instanceof HandledScreen screen) || mc.player == null) return; + + Slot focusedSlot = ((HandledScreenAccessor) screen).getFocusedSlot(); + if (focusedSlot == null) return; + + int containerSlot = focusedSlot.id; + int hotbarKeyIndex = InventoryUtil.getSlotNumberFromKey(inputCode); + if (hotbarKeyIndex == -1) return; + + int rowOffset = InventoryUtil.getRowOffset(screen); + + if (KeyUtil.isKeyDown(row1key.getKey())) { + event.cancel(); + swapWithRow(screen, containerSlot, hotbarKeyIndex, rowOffset); + } + else if (KeyUtil.isKeyDown(row2key.getKey())) { + event.cancel(); + swapWithRow(screen, containerSlot, hotbarKeyIndex, rowOffset + 9); + } + else if (KeyUtil.isKeyDown(row3key.getKey())) { + event.cancel(); + swapWithRow(screen, containerSlot, hotbarKeyIndex, rowOffset + 18); + } + } + + private void swapWithRow(HandledScreen screen, int containerSlot, int column, int rowOffset) { + int targetContainerSlot = InventoryUtil.calculateTargetSlot(screen, containerSlot, column, rowOffset); + if (targetContainerSlot != -1) { + InventoryUtil.swapSlots(containerSlot, targetContainerSlot, screen); + } + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/module/modules/LightOverlay.java b/src/main/java/me/retucio/camtweaks/module/modules/LightOverlay.java index 5653572..653bd9d 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/LightOverlay.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/LightOverlay.java @@ -50,6 +50,7 @@ public class LightOverlay extends Module { } for (BlockPos block : blocks) { + if (mc.world.getBlockState(block).isAir() || !mc.world.getBlockState(block.up()).isAir()) continue; if (!mc.world.isTopSolid(block, mc.player) || !mc.world.getBlockState(block).isOpaque()) continue; int light = mc.world.getLightLevel(LightType.BLOCK, block.up()); diff --git a/src/main/java/me/retucio/camtweaks/module/modules/LogoutSpots.java b/src/main/java/me/retucio/camtweaks/module/modules/LogoutSpots.java index 3208055..f89ee8d 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/LogoutSpots.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/LogoutSpots.java @@ -9,6 +9,8 @@ import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.settings.BooleanSetting; import me.retucio.camtweaks.module.settings.ColorSetting; import me.retucio.camtweaks.module.settings.EnumSetting; +import me.retucio.camtweaks.module.settings.NumberSetting; +import me.retucio.camtweaks.util.MiscUtil; import me.retucio.camtweaks.util.render.RenderUtil; import net.minecraft.client.network.OtherClientPlayerEntity; import net.minecraft.client.network.PlayerListEntry; @@ -33,6 +35,7 @@ public class LogoutSpots extends Module { public BooleanSetting outlines = addSetting(new BooleanSetting("contorno", "renderizar contorno de la caja (lados)", true)); public ColorSetting outlineColor = addSetting(new ColorSetting("color del contorno", "Color de las líneas", new Color(255, 0, 0, 230), false)); + public NumberSetting lineWidth = addSetting(new NumberSetting("grosor de línea", "grosor de las líneas del contorno", 1.5, 0.5, 5, 0.1)); public BooleanSetting filling = addSetting(new BooleanSetting("relleno", "renderizar relleno de la caja (caras)", true)); public ColorSetting fillingColor = addSetting(new ColorSetting("color del relleno", "Color de los lados", new Color(230, 0, 0, 55), false)); @@ -40,8 +43,6 @@ public class LogoutSpots extends Module { public BooleanSetting fullHeight = addSetting(new BooleanSetting("hitbox completa", "renderizar la caja completa de la hitbox, o solo marcar la posición", true)); public BooleanSetting dummy = addSetting(new BooleanSetting("monigote", "spawnear un monigote para marcar la posición", true)); - public EnumSetting healthMode = addSetting(new EnumSetting<>("formato de vida", "en qué formato mostrar la vida del jugador", - Nametags.HealthMode.class, Nametags.HealthMode.POINTS)); private final List players = new ArrayList<>(); private final List lastPlayerList = new ArrayList<>(); @@ -65,7 +66,6 @@ public class LogoutSpots extends Module { dummy.onUpdate(v -> { if (!v) removeDummies(); - healthMode.setVisible(v); }); } @@ -215,7 +215,6 @@ public class LogoutSpots extends Module { public final UUID uuid; public final String name; - public final int health; public final String logoutTime; public final String dummyName; @@ -234,45 +233,25 @@ public class LogoutSpots extends Module { this.uuid = player.getUuid(); this.name = player.getName().getString(); - this.health = Math.round(player.getHealth() + player.getAbsorptionAmount()); - this.logoutTime = getLogoutTime(); + this.logoutTime = MiscUtil.getCurrentFormattedTime(); - String healthText = healthMode.is(Nametags.HealthMode.HEARTS) - ? String.format("%.2f", (float) health / 2) - : health + "hp"; - - this.dummyName = name + " [" + healthText + "] (" + logoutTime + ")"; + this.dummyName = name + " (" + logoutTime + ")"; this.dummy = ModuleManager.INSTANCE.getModuleByClass(FakePlayer.class).addPlayer(player, dummyName); this.dummy.updatePositionAndAngles(x + halfWidth, y, z + halfWidth, player.getYaw(), player.getPitch()); } - private String getLogoutTime() { - try { - HUD hud = ModuleManager.INSTANCE.getModuleByClass(HUD.class); - Instant instant = Instant.now(); - ZoneOffset offset = ZoneOffset.ofHours(hud.timezone.getIntValue()); - LocalTime logoutTime = LocalTime.from(instant.atOffset(offset)); - - boolean is24 = hud.timeFormat.is(HUD.TimeFormat.TWENTY_FOUR_HOUR); - DateTimeFormatter format = DateTimeFormatter.ofPattern(is24 ? "HH:mm" : "hh:mm a"); - return logoutTime.format(format); - } catch (Exception e) { - return "??:??"; - } - } - public void renderBox(MatrixStack matrices) { if (fullHeight.isEnabled()) { if (outlines.isEnabled()) - RenderUtil.drawOutlineBox(matrices, new Box(x, y, z, x + xWidth, y + height, z + zWidth), outlineColor.getColor(), 1.5); + RenderUtil.drawOutlineBox(matrices, new Box(x, y, z, x + xWidth, y + height, z + zWidth), outlineColor.getColor(), lineWidth.getFloatValue()); if (filling.isEnabled()) RenderUtil.drawFilledBox(matrices, new Box(x, y, z, x + xWidth, y + height, z + zWidth), fillingColor.getColor()); } else { if (outlines.isEnabled()) { Box bottomBox = new Box(x, y, z, x + xWidth, y + 0.01, z + zWidth); - RenderUtil.drawOutlineBox(matrices, bottomBox, outlineColor.getColor(), 1.5); + RenderUtil.drawOutlineBox(matrices, bottomBox, outlineColor.getColor(), lineWidth.getFloatValue()); } if (filling.isEnabled()) { RenderUtil.drawBlockFaceFilled(matrices, diff --git a/src/main/java/me/retucio/camtweaks/module/modules/Nametags.java b/src/main/java/me/retucio/camtweaks/module/modules/Nametags.java index 22eda29..83d860f 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/Nametags.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/Nametags.java @@ -8,6 +8,7 @@ import me.retucio.camtweaks.module.settings.EnumSetting; import me.retucio.camtweaks.module.settings.ListSetting; import me.retucio.camtweaks.util.Lists; import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LazyEntityReference; import net.minecraft.entity.LivingEntity; @@ -24,6 +25,7 @@ import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URI; import java.net.URL; +import java.util.HashMap; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -39,8 +41,9 @@ import java.util.concurrent.Executors; public class Nametags extends Module { + Map, Boolean> defaultEntities = Lists.allFalse(Lists.entityList); public ListSetting> entities = addSetting(new ListSetting<>("entidades", "entidades cuyo nametag será visible", - Lists.entityList, Lists.allFalse(Lists.entityList), Lists.entityNames)); + Lists.entityList, defaultEntities, Lists.entityNames)); public BooleanSetting alwaysVisible = addSetting(new BooleanSetting("siempre mostrar nametags", "mostrar nametag cuando el jugador está agachado o es invisible", false)); public BooleanSetting health = addSetting(new BooleanSetting("mostrar vida", "muestra la vida de una entidad en su nametag", true)); @@ -62,17 +65,22 @@ public class Nametags extends Module { super("nametags", "modifica la manera en la que se renderizan los nametags"); // entidades activadas por defecto - entities.setEnabled(EntityType.PLAYER, true); - entities.setEnabled(EntityType.ITEM, true); - entities.setEnabled(EntityType.ARROW, true); - entities.setEnabled(EntityType.SPECTRAL_ARROW, true); - entities.setEnabled(EntityType.TRIDENT, true); - entities.setDefaultValues(entities.getValues()); + defaultEntities.replace(EntityType.PLAYER, true); + defaultEntities.replace(EntityType.ITEM, true); + defaultEntities.replace(EntityType.ARROW, true); + defaultEntities.replace(EntityType.SPECTRAL_ARROW, true); + defaultEntities.replace(EntityType.TRIDENT, true); + entities.setDefaultValues(defaultEntities); health.onUpdate(v -> healthMode.setVisible(v)); entities.onUpdate(entities -> { items.setVisible(entities.get(EntityType.ITEM)); + + boolean anyProjectile = entities.get(EntityType.TRIDENT) + || entities.get(EntityType.ARROW) + || entities.get(EntityType.SPECTRAL_ARROW); + showProjectileDamage.setVisible(anyProjectile); }); } diff --git a/src/main/java/me/retucio/camtweaks/module/modules/Offhand.java b/src/main/java/me/retucio/camtweaks/module/modules/Offhand.java new file mode 100644 index 0000000..f98cf08 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/module/modules/Offhand.java @@ -0,0 +1,83 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.BooleanSetting; +import me.retucio.camtweaks.module.settings.NumberSetting; +import me.retucio.camtweaks.module.settings.OptionSetting; +import me.retucio.camtweaks.util.Lists; +import net.minecraft.item.Item; +import net.minecraft.item.Items; +import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; +import net.minecraft.network.packet.c2s.play.UpdateSelectedSlotC2SPacket; +import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; + +public class Offhand extends Module { + + public OptionSetting item = addSetting(new OptionSetting<>("ítem", "ítem a equipar", + Lists.itemList, Items.TOTEM_OF_UNDYING, Lists.itemNames)); + public NumberSetting delaySetting = addSetting(new NumberSetting("delay", "delay del cambiazo (en ticks)", 0, 0, 20, 1)); + public BooleanSetting override = addSetting(new BooleanSetting("anular", "ignora que ya haya un ítem en la mano secundaria", true)); + + + private int delay; + private boolean holdingItem; + + public Offhand() { + super("mano secundaria", "automáticamente equipa un ítem en la mano secundaria"); + } + + @Override + public void onTick() { + if (mc.player == null || mc.interactionManager == null) return; + + if (holdingItem && mc.player.getOffHandStack().getItem() != item.getValue()) + delay = Math.max(delaySetting.getIntValue(), delay); + + holdingItem = mc.player.getOffHandStack().getItem() == item.getValue(); + + if (delay > 0) { + delay--; + return; + } + + if (holdingItem || (!mc.player.getOffHandStack().isEmpty() + && !override.isEnabled())) + return; + + if (mc.player.playerScreenHandler == mc.player.currentScreenHandler) { + for (int i = 9; i < 45; i++) { + + if (mc.player.getInventory().getStack(i >= 36 ? i - 36 : i).getItem() == item.getValue()) { + boolean itemInOffhand = !mc.player.getOffHandStack().isEmpty(); + + mc.interactionManager.clickSlot(mc.player.currentScreenHandler.syncId, i, 0, SlotActionType.PICKUP, mc.player); + mc.interactionManager.clickSlot(mc.player.currentScreenHandler.syncId, 45, 0, SlotActionType.PICKUP, mc.player); + + if (itemInOffhand) + mc.interactionManager.clickSlot(mc.player.currentScreenHandler.syncId, i, 0, SlotActionType.PICKUP, mc.player); + + delay = delaySetting.getIntValue(); + return; + } + } + } else { + for (int i = 0; i < 9; i++) { + if (mc.player.getInventory().getStack(i).getItem() == item.getValue()) { + if (i != mc.player.getInventory().getSelectedSlot()) { + mc.player.getInventory().setSelectedSlot(i); + mc.player.networkHandler.sendPacket(new UpdateSelectedSlotC2SPacket(i)); + } + + mc.player.networkHandler.sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.SWAP_ITEM_WITH_OFFHAND, + BlockPos.ORIGIN, + Direction.DOWN)); + delay = delaySetting.getIntValue(); + return; + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/module/modules/PacketDelay.java b/src/main/java/me/retucio/camtweaks/module/modules/PacketDelay.java new file mode 100644 index 0000000..aae2408 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/module/modules/PacketDelay.java @@ -0,0 +1,148 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.event.JoinWorldEvent; +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.event.events.DisconnectEvent; +import me.retucio.camtweaks.event.events.PacketEvent; +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.EnumSetting; +import me.retucio.camtweaks.module.settings.NumberSetting; +import me.retucio.camtweaks.util.ChatUtil; +import me.retucio.camtweaks.util.NetworkUtil; + +import net.minecraft.network.ClientConnection; +import net.minecraft.network.listener.PacketListener; +import net.minecraft.network.message.SentMessage; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.c2s.common.CustomPayloadC2SPacket; +import net.minecraft.network.packet.c2s.common.KeepAliveC2SPacket; +import net.minecraft.network.packet.s2c.common.KeepAliveS2CPacket; + +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; + + +public class PacketDelay extends Module { + + public NumberSetting delay = addSetting(new NumberSetting("delay", "delay a añadir a los paquetes, en milisegundos", 1500, 0, 3000, 5)); + public EnumSetting directions = addSetting(new EnumSetting<>("dirección", "dirección de los paquetes a los que añadir delay", + Directions.class, Directions.BOTH)); + public EnumSetting packets = addSetting(new EnumSetting<>("paquetes", "paquetes a los que aplicar el delay", + Packets.class, Packets.ALL)); + + private final List delayedPackets = new CopyOnWriteArrayList<>(); + private long lastProcessTime = 0; + + public PacketDelay() { + super("delay de paquetes", "aplica un delay a los paquetes"); + } + + @Override + public void onDisable() { + for (DelayedPacket delayedPacket : delayedPackets) + processDelayedPacket(delayedPacket); + delayedPackets.clear(); + super.onDisable(); + } + + @Override + public void onTick() { + if (mc.player == null || mc.world == null || mc.getNetworkHandler() == null) { + delayedPackets.clear(); + return; + } + + long currentTime = System.currentTimeMillis(); + if (currentTime - lastProcessTime < 50) return; + lastProcessTime = currentTime; + + List toProcess = new ArrayList<>(); + for (DelayedPacket packet : delayedPackets) { + if (System.currentTimeMillis() >= packet.scheduledTime()) + toProcess.add(packet); + } + + for (DelayedPacket packet : toProcess) { + processDelayedPacket(packet); + delayedPackets.remove(packet); + } + } + + @SubscribeEvent + public void onPacketSend(PacketEvent.Send event) { + if (directions.is(Directions.S2C) + || mc.player == null || mc.world == null || mc.getNetworkHandler() == null + || (event.getPacket() instanceof KeepAliveC2SPacket && !packets.is(Packets.OTHERS))) + return; + + event.cancel(); + + delayedPackets.add(new DelayedPacket( + event.getPacket(), + System.currentTimeMillis() + delay.getLongValue(), + true, + mc.getNetworkHandler().getConnection().getPacketListener() + )); + } + + @SubscribeEvent + public void onPacketReceive(PacketEvent.Receive event) { + if (mc.player == null || mc.world == null + || mc.getNetworkHandler() == null || mc.getNetworkHandler().getConnection() == null + || (event.getPacket() instanceof KeepAliveS2CPacket && !packets.is(Packets.OTHERS))) + return; + + event.cancel(); + + ClientConnection connection = mc.getNetworkHandler().getConnection(); + + delayedPackets.add(new DelayedPacket( + event.getPacket(), + System.currentTimeMillis() + delay.getLongValue(), + false, + connection.getPacketListener() + )); + } + + @SubscribeEvent + public void onJoinWorld(JoinWorldEvent event) { + ChatUtil.error("delay de paquetes no funciona en un solo jugador"); + toggle(); + } + + private void processDelayedPacket(DelayedPacket delayedPacket) { + if (mc.getNetworkHandler() == null) return; + + if (delayedPacket.isOutgoing()) { + NetworkUtil.sendPacketNoEvent(delayedPacket.packet()); + } else { + if (delayedPacket.packetListener != null && mc.getNetworkHandler().getConnection() != null) { + NetworkUtil.receivePacketNoEvent(delayedPacket.packet(), delayedPacket.packetListener()); + } else { + NetworkUtil.receivePacketNoEvent(delayedPacket.packet()); + } + } + } + + private record DelayedPacket(Packet packet, long scheduledTime, boolean isOutgoing, PacketListener packetListener) {} + + public enum Directions { + C2S("cliente a server"), + S2C("server a cliente"), + BOTH("ambos"); + + private final String name; + Directions(String name) { this.name = name; } + @Override public String toString() { return name; } + } + + public enum Packets { + KEEP_ALIVE("paquetes KeepAlive"), + OTHERS("todos menos KeepAlive"), + ALL("todos"); + + private final String name; + Packets(String name) { this.name = name; } + @Override public String toString() { return name; } + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/module/modules/Racist.java b/src/main/java/me/retucio/camtweaks/module/modules/Racist.java new file mode 100644 index 0000000..8044eca --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/module/modules/Racist.java @@ -0,0 +1,59 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.util.EntityUtil; +import net.minecraft.entity.Entity; +import net.minecraft.entity.mob.EndermanEntity; + +import java.util.ArrayList; +import java.util.List; + +public class Racist extends Module { + + private int lookTimer; + private final List lookedEndermen = new ArrayList<>(); + + public Racist() { + super("racismo", "amego segarro"); + } + + @Override + public void onDisable() { + lookedEndermen.clear(); + super.onDisable(); + } + + @Override + public void onTick() { + if (mc.world == null || mc.player == null) return; + + for (Entity entity : mc.world.getEntities()) { + if (!(entity instanceof EndermanEntity enderman)) continue; + + if (shouldLookAt(enderman)) { + lookAtEnderman(enderman); + + lookedEndermen.add(enderman); + lookTimer = 0; + return; + } + } + + lookTimer++; + } + + private boolean shouldLookAt(EndermanEntity enderman) { + return !(lookedEndermen.contains(enderman)) && lookTimer >= 10 + && EntityUtil.hasLineOfSight(mc.player, enderman); + } + + private void lookAtEnderman(EndermanEntity enderman) { + double yaw = EntityUtil.getYaw(enderman); + double pitch = EntityUtil.getPitch(enderman, EntityUtil.Target.HEAD); + + mc.player.setYaw((float) yaw); + mc.player.setPitch((float) pitch); + } + + +} diff --git a/src/main/java/me/retucio/camtweaks/module/modules/ShulkerPeek.java b/src/main/java/me/retucio/camtweaks/module/modules/ShulkerPeek.java index ab60909..419bf21 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/ShulkerPeek.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/ShulkerPeek.java @@ -10,6 +10,7 @@ import me.retucio.camtweaks.ui.screen.PreviewScreen; import me.retucio.camtweaks.util.ChatUtil; import me.retucio.camtweaks.util.Colors; +import me.retucio.camtweaks.util.InventoryUtil; import me.retucio.camtweaks.util.MiscUtil; import net.minecraft.block.ShulkerBoxBlock; import net.minecraft.client.gui.screen.Screen; @@ -94,11 +95,11 @@ public class ShulkerPeek extends Module { } else return; if (stack.getItem() == Items.ENDER_CHEST) { - if (MiscUtil.getEchestInv() == null) { + if (InventoryUtil.getEchestInv() == null) { ChatUtil.warn("abre un enderchest primero"); return; } - mc.setScreen(new PreviewScreen(MiscUtil.getEchestInv(), mc.currentScreen)); + mc.setScreen(new PreviewScreen(InventoryUtil.getEchestInv(), mc.currentScreen)); return; } diff --git a/src/main/java/me/retucio/camtweaks/module/modules/UIMove.java b/src/main/java/me/retucio/camtweaks/module/modules/UIMove.java new file mode 100644 index 0000000..1fe6f2a --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/module/modules/UIMove.java @@ -0,0 +1,88 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.mixin.accessor.KeyBindingAccessor; +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.ListSetting; +import me.retucio.camtweaks.ui.screen.ClickGUI; +import me.retucio.camtweaks.util.KeyUtil; +import me.retucio.camtweaks.util.Lists; + +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.screen.GenericContainerScreenHandler; +import net.minecraft.screen.ScreenHandlerType; + +import java.util.Arrays; +import java.util.List; + + +public class UIMove extends Module { + + public ListSetting> screens = addSetting(new ListSetting<>("interfaces", "interfaces en las que te podrás mover", + Lists.screenList, Lists.allTrue(Lists.screenList), Lists.screenNames)); + + private List movementKeys; + + private final ScreenHandlerType inventoryHandlerType = ScreenHandlerType.register( + "player_inventory", GenericContainerScreenHandler::createGeneric9x3); + private final ScreenHandlerType clickGuiHandlerType = ScreenHandlerType.register( + "camtweaks_clickgui", GenericContainerScreenHandler::createGeneric9x3); // 9x3 porque no importa (creo) + + public UIMove() { + super("moverse en interfaz", "te permite seguir usando las teclas de movimiento aún estando en ciertas interfaces"); + screens.addOption(inventoryHandlerType, true, "inventario"); + screens.addOption(clickGuiHandlerType, true, "interfaz del mod"); + + screens.onUpdate(v -> unpress()); + } + + @Override + public void onEnable() { + movementKeys = Arrays.asList( + mc.options.forwardKey, + mc.options.backKey, + mc.options.leftKey, + mc.options.rightKey, + mc.options.jumpKey, + mc.options.sneakKey, + mc.options.sprintKey); + super.onEnable(); + } + + @Override + public void onDisable() { + unpress(); + super.onDisable(); + } + + @Override + public void onTick() { + if (mc.player == null || mc.options == null || mc.currentScreen == null) return; + + ScreenHandlerType handler = null; + if (mc.currentScreen == ClickGUI.INSTANCE) + handler = clickGuiHandlerType; + + if (mc.currentScreen instanceof HandledScreen screen) { + try { + handler = screen.getScreenHandler().getType(); + } catch (UnsupportedOperationException e) { + handler = inventoryHandlerType; + } + } + + if (handler == null || !screens.isEnabled(handler)) return; + + for (KeyBinding kb : movementKeys) { + kb.setPressed(KeyUtil.isKeyDown(( + (KeyBindingAccessor) kb).getBoundKey().getCode())); + } + } + + private void unpress() { + if (movementKeys == null) return; + for (KeyBinding kb : movementKeys) { + kb.setPressed(false); + } + } +} diff --git a/src/main/java/me/retucio/camtweaks/module/modules/WarnLowDurability.java b/src/main/java/me/retucio/camtweaks/module/modules/WarnLowDurability.java index 6591406..fe0af81 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/WarnLowDurability.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/WarnLowDurability.java @@ -3,9 +3,12 @@ package me.retucio.camtweaks.module.modules; import me.retucio.camtweaks.module.Module; import me.retucio.camtweaks.module.settings.BooleanSetting; import me.retucio.camtweaks.module.settings.NumberSetting; +import me.retucio.camtweaks.module.settings.OptionSetting; import me.retucio.camtweaks.util.ChatUtil; +import me.retucio.camtweaks.util.Lists; import net.minecraft.item.ItemStack; import net.minecraft.sound.SoundCategory; +import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvents; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -15,19 +18,29 @@ import java.util.ArrayList; import java.util.List; -// al parecer DamageItemEvent no se lanza si estás en un server de Paper, o sea que ahora se usa onTick() public class WarnLowDurability extends Module { public NumberSetting limitPercentage = addSetting(new NumberSetting("porcentaje", "porcentaje de durabilidad restante a la que se te avisa", 5, 1, 100, 1)); - public BooleanSetting message = addSetting(new BooleanSetting("mensaje", "enviar un mensaje para alertar al usuario", true)); - public BooleanSetting sound = addSetting(new BooleanSetting("sonido", "reproducir un sonido para alertar al usuario", true)); + public BooleanSetting message = addSetting(new BooleanSetting("enviar mensaje", "enviar un mensaje para alertar al usuario", true)); + + public BooleanSetting playSound = addSetting(new BooleanSetting("reproducir sonido", "reproducir un sonido para alertar al usuario", true)); + public OptionSetting sound = addSetting(new OptionSetting<>("sonido", "qué sonido reproducir", + Lists.soundList, SoundEvents.BLOCK_NOTE_BLOCK_BELL.value(), Lists.soundNames)); + public NumberSetting volume = addSetting(new NumberSetting("volumen", "volumen del sonido", 70, 0, 125, 1)); + public NumberSetting pitch = addSetting(new NumberSetting("frecuencia", "altura del sonido", 70, 0, 125, 1)); private final List warned = new ArrayList<>(); public WarnLowDurability() { super("aviso de baja dur.", "te avisa cuando la herramienta que sostengas sobrepase un límite de durabilidad"); + + playSound.onUpdate(v -> { + sound.setVisible(v); + volume.setVisible(v); + pitch.setVisible(v); + }); } @Override @@ -39,9 +52,13 @@ public class WarnLowDurability extends Module { float percentage = (1 - (float) stack.getDamage() / stack.getMaxDamage()) * 100; if (percentage <= limitPercentage.getValue()) { - if (sound.isEnabled()) + if (playSound.isEnabled()) mc.world.playSound(mc.player, mc.player.getBlockPos(), - SoundEvents.BLOCK_BELL_USE, SoundCategory.AMBIENT, 1, 1); + sound.getValue(), + SoundCategory.AMBIENT, + toExponential(volume), + toExponential(pitch) + ); if (message.isEnabled()) { String customName = stack.getCustomName() == null ? "" : " \"" + stack.getCustomName().getString() + "\""; @@ -61,4 +78,15 @@ public class WarnLowDurability extends Module { warned.clear(); super.onDisable(); } + + // el sistema decibélico es un sistema logarítmico + private float toExponential(NumberSetting setting) { + double linear = setting.getValue(); + + double normalized = linear / (setting.getMax() - setting.getMax() / 4); + double exponential = Math.pow(normalized, 3); + + if (exponential < 0.01) exponential = 0; + return (float) exponential; + } } diff --git a/src/main/java/me/retucio/camtweaks/module/settings/BooleanSetting.java b/src/main/java/me/retucio/camtweaks/module/settings/BooleanSetting.java index ed1ec8b..66bd66c 100644 --- a/src/main/java/me/retucio/camtweaks/module/settings/BooleanSetting.java +++ b/src/main/java/me/retucio/camtweaks/module/settings/BooleanSetting.java @@ -1,12 +1,9 @@ package me.retucio.camtweaks.module.settings; -import me.retucio.camtweaks.CameraTweaks; -import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent; - import java.util.function.Consumer; // ajuste booleano, es decir, o se encuentra encencido o apagado (similar a un interruptor) -public class BooleanSetting extends AbstractSetting { +public class BooleanSetting extends Setting { private boolean defaultValue; private boolean enabled; diff --git a/src/main/java/me/retucio/camtweaks/module/settings/ColorSetting.java b/src/main/java/me/retucio/camtweaks/module/settings/ColorSetting.java index c606fcb..03c7c35 100644 --- a/src/main/java/me/retucio/camtweaks/module/settings/ColorSetting.java +++ b/src/main/java/me/retucio/camtweaks/module/settings/ColorSetting.java @@ -2,14 +2,13 @@ package me.retucio.camtweaks.module.settings; import me.retucio.camtweaks.util.Colors; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import java.awt.*; import java.util.HashMap; import java.util.Map; import java.util.function.Consumer; -public class ColorSetting extends AbstractSetting { +public class ColorSetting extends Setting { private Color color; private Consumer updateListener; diff --git a/src/main/java/me/retucio/camtweaks/module/settings/EnumSetting.java b/src/main/java/me/retucio/camtweaks/module/settings/EnumSetting.java index 2821f5a..1387a2a 100644 --- a/src/main/java/me/retucio/camtweaks/module/settings/EnumSetting.java +++ b/src/main/java/me/retucio/camtweaks/module/settings/EnumSetting.java @@ -1,14 +1,11 @@ package me.retucio.camtweaks.module.settings; -import me.retucio.camtweaks.CameraTweaks; -import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent; - import java.util.Arrays; import java.util.List; import java.util.function.Consumer; // ajuste que te deja elegir entre distintas opciones definidas, dentro de un Enum -public class EnumSetting> extends AbstractSetting { +public class EnumSetting> extends Setting { private final List values; private E defaultValue; diff --git a/src/main/java/me/retucio/camtweaks/module/settings/KeySetting.java b/src/main/java/me/retucio/camtweaks/module/settings/KeySetting.java index 0263684..4be90d3 100644 --- a/src/main/java/me/retucio/camtweaks/module/settings/KeySetting.java +++ b/src/main/java/me/retucio/camtweaks/module/settings/KeySetting.java @@ -9,7 +9,7 @@ import org.lwjgl.glfw.GLFW; import java.util.function.Consumer; -public class KeySetting extends AbstractSetting { +public class KeySetting extends Setting { private int key; private int defaultKey; diff --git a/src/main/java/me/retucio/camtweaks/module/settings/ListSetting.java b/src/main/java/me/retucio/camtweaks/module/settings/ListSetting.java index 8bc3d99..b7cbd3e 100644 --- a/src/main/java/me/retucio/camtweaks/module/settings/ListSetting.java +++ b/src/main/java/me/retucio/camtweaks/module/settings/ListSetting.java @@ -1,16 +1,14 @@ package me.retucio.camtweaks.module.settings; -import me.retucio.camtweaks.CameraTweaks; -import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent; - +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Consumer; -public class ListSetting extends AbstractSetting { +public class ListSetting extends Setting { - private final List options; + private List options; private Map values; private Map defaultValues; private Map displayNames = null; @@ -19,7 +17,7 @@ public class ListSetting extends AbstractSetting { public ListSetting(String name, String description, List options, Map initialValues) { super(name, description); - this.options = options; + this.options = new ArrayList<>(options); this.defaultValues = new HashMap<>(); for (T option : options) { @@ -66,6 +64,25 @@ public class ListSetting extends AbstractSetting { defaultValues = values; } + public Map getConfigValues() { + Map configValues = new HashMap<>(); + for (int i = 0; i < values.size(); i++) + configValues.put(getDisplayName(options.get(i)), values.get(options.get(i))); + return configValues; + } + + public void addOption(T option, boolean value, String displayName) { + if (!(this.options instanceof ArrayList)) + this.options = new ArrayList<>(this.options); + + this.options.add(option); + this.values.put(option, value); + this.defaultValues.put(option, value); + + if (this.displayNames != null) + this.displayNames.put(option, displayName); + } + public void reset() { values.clear(); values.putAll(defaultValues); diff --git a/src/main/java/me/retucio/camtweaks/module/settings/NumberSetting.java b/src/main/java/me/retucio/camtweaks/module/settings/NumberSetting.java index a0c6f04..bbe2aee 100644 --- a/src/main/java/me/retucio/camtweaks/module/settings/NumberSetting.java +++ b/src/main/java/me/retucio/camtweaks/module/settings/NumberSetting.java @@ -1,12 +1,9 @@ package me.retucio.camtweaks.module.settings; -import me.retucio.camtweaks.CameraTweaks; -import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent; - import java.util.function.Consumer; // ajuste numérico, es decir, que eliges un valor númerico entre el mínimo y el máximo disponibles -public class NumberSetting extends AbstractSetting { +public class NumberSetting extends Setting { private double value; private double defaultValue; diff --git a/src/main/java/me/retucio/camtweaks/module/settings/OptionSetting.java b/src/main/java/me/retucio/camtweaks/module/settings/OptionSetting.java new file mode 100644 index 0000000..b2781f3 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/module/settings/OptionSetting.java @@ -0,0 +1,98 @@ +package me.retucio.camtweaks.module.settings; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +public class OptionSetting extends Setting{ + + List options = new ArrayList<>(); + Map displayNames; + T option; + T defaultOption; + + private Consumer updateListener; + + public OptionSetting(String name, String description, List options, T defaultOption) { + super(name, description); + this.options = options; + this.option = defaultOption; + this.defaultOption = defaultOption; + } + + public OptionSetting(String name, String description, List options, T defaultOption, Map displayNames) { + super(name, description); + this.options = options; + this.option = defaultOption; + this.defaultOption = defaultOption; + this.displayNames = displayNames; + } + + public T getValue() { + return option; + } + + public void setValue(T option) { + if (options.contains(option)) this.option = option; + fireUpdateEvent(); + if (updateListener != null) updateListener.accept(option); + } + + public List getOptions() { + return options; + } + + public T getOption(int index) { + return options.get(index); + } + + public T getDefaultValue() { + return defaultOption; + } + + public int getSize() { + return options.size(); + } + + public int getIndex() { + int index = 0; + for (T option : options) { + if (this.option == option) break; + index += 1; + } + return index; + } + + public boolean is(T option) { + return getValue() == option; + } + + public int getIndex(T option1) { + int index = 0; + for (T option : options) { + if (option1 == option) break; + index += 1; + } + return index; + } + + public void reset() { + setValue(defaultOption); + } + + public void onUpdate(Consumer listener) { + this.updateListener = listener; + if (updateListener != null) updateListener.accept(option); + } + + public Map getDisplayNames() { + return displayNames; + } + + public String getDisplayName(T key) { + if (displayNames != null) return displayNames.get(key); + return key.toString(); + } +} diff --git a/src/main/java/me/retucio/camtweaks/module/settings/AbstractSetting.java b/src/main/java/me/retucio/camtweaks/module/settings/Setting.java similarity index 92% rename from src/main/java/me/retucio/camtweaks/module/settings/AbstractSetting.java rename to src/main/java/me/retucio/camtweaks/module/settings/Setting.java index 69fb7a4..59e17e8 100644 --- a/src/main/java/me/retucio/camtweaks/module/settings/AbstractSetting.java +++ b/src/main/java/me/retucio/camtweaks/module/settings/Setting.java @@ -5,7 +5,7 @@ import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent; import me.retucio.camtweaks.module.Module; // base para los tipos de ajustes -public abstract class AbstractSetting { +public abstract class Setting { private final String name; private final String description; @@ -15,7 +15,7 @@ public abstract class AbstractSetting { private Module module; - protected AbstractSetting(String name, String description) { + protected Setting(String name, String description) { this.name = name; this.description = description; } diff --git a/src/main/java/me/retucio/camtweaks/module/settings/StringSetting.java b/src/main/java/me/retucio/camtweaks/module/settings/StringSetting.java index 2494100..fad224c 100644 --- a/src/main/java/me/retucio/camtweaks/module/settings/StringSetting.java +++ b/src/main/java/me/retucio/camtweaks/module/settings/StringSetting.java @@ -1,11 +1,8 @@ package me.retucio.camtweaks.module.settings; -import me.retucio.camtweaks.CameraTweaks; -import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent; - import java.util.function.Consumer; -public class StringSetting extends AbstractSetting { +public class StringSetting extends Setting { private String value; private String defaultValue; diff --git a/src/main/java/me/retucio/camtweaks/ui/HudRenderer.java b/src/main/java/me/retucio/camtweaks/ui/HudRenderer.java deleted file mode 100644 index 98718fd..0000000 --- a/src/main/java/me/retucio/camtweaks/ui/HudRenderer.java +++ /dev/null @@ -1,241 +0,0 @@ -package me.retucio.camtweaks.ui; - -import me.retucio.camtweaks.config.ConfigManager; -import me.retucio.camtweaks.event.SubscribeEvent; -import me.retucio.camtweaks.event.events.PacketEvent; -import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent; -import me.retucio.camtweaks.module.ModuleManager; -import me.retucio.camtweaks.module.modules.Freecam; -import me.retucio.camtweaks.module.modules.HUD; -import me.retucio.camtweaks.ui.screen.HudEditorScreen; -import me.retucio.camtweaks.ui.widgets.HudElement; - -import me.retucio.camtweaks.util.Colors; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.ChatScreen; -import net.minecraft.client.gui.screen.TitleScreen; -import net.minecraft.client.network.PlayerListEntry; -import net.minecraft.client.render.RenderTickCounter; -import net.minecraft.network.packet.s2c.play.WorldTimeUpdateS2CPacket; -import net.minecraft.util.math.Vec3d; - -import java.awt.*; -import java.time.LocalTime; -import java.time.ZoneOffset; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - - -public class HudRenderer { - - private static final MinecraftClient mc = MinecraftClient.getInstance(); - - // tps - private static float estimatedTPS = 20f; - private static final List tpsHistory = new ArrayList<>(); - private long lastWorldTime = -1L; - private long lastRealTime = -1L; - - private static final Map positions = ConfigManager.getConfig().hudPositions; - private static final Map visibilities = ConfigManager.getConfig().hudVisibilities; - private static final List elements = new ArrayList<>(); - private static boolean initialized = false; - - private static HudElement customTextElement = null; - - public static void initElements() { - if (initialized) return; - initialized = true; - - HUD hud = ModuleManager.INSTANCE.getModuleByClass(HUD.class); - - // coordenadas - addElement("coords", 2, mc.getWindow().getScaledHeight() - mc.textRenderer.fontHeight, (ctx, mx, my, delta) -> { - drawSnappedText(ctx, getElementText("coords", delta, hud), mx, my, getColor(hud).getRGB(), hud.shadow.isEnabled()); - }); - - // FPS - addElement("fps", 2, 2, (ctx, mx, my, delta) -> { - drawSnappedText(ctx, getElementText("fps", 0, hud), mx, my, getColor(hud).getRGB(), hud.shadow.isEnabled()); - }); - - // TPS - addElement("tps", 2, mc.textRenderer.fontHeight + 4, (ctx, mx, my, delta) -> { - drawSnappedText(ctx, getElementText("tps", delta, hud), mx, my, getColor(hud).getRGB(), hud.shadow.isEnabled()); - }); - - // texto custom - addElement("customText", mc.getWindow().getScaledWidth() / 2 - mc.textRenderer.getWidth(getElementText("customText", 0, ModuleManager.INSTANCE.getModuleByClass(HUD.class))) / 2, 2, (ctx, mx, my, delta) -> { - drawSnappedText(ctx, getElementText("customText", delta, hud), mx, my, getColor(hud).getRGB(), hud.shadow.isEnabled()); - }); - - customTextElement = elements.stream() - .filter(e -> e.getId().equals("customText")) - .findFirst() - .orElse(null); - - // hora - addElement("time", mc.getWindow().getScaledWidth() - mc.textRenderer.getWidth("04:20"), mc.getWindow().getScaledHeight() - mc.textRenderer.fontHeight - 2, (ctx, mx, my, delta) -> { - drawSnappedText(ctx, getElementText("time", delta, hud), mx, my, getColor(hud).getRGB(), hud.shadow.isEnabled()); - }); - - // ping - addElement("ping", 2, 2 * (mc.textRenderer.fontHeight + 4), (ctx, mx, my, delta) -> { - drawSnappedText(ctx, getElementText("ping", delta, hud), mx, my, getColor(hud).getRGB(), hud.shadow.isEnabled()); - }); - - HudEditorScreen.INSTANCE.setElements(getElements()); - } - - private static void addElement(String id, int defX, int defY, HudElement.Renderer renderer) { - int[] saved = positions.get(id); - Boolean visible = visibilities.get(id); - int x = saved == null ? defX : saved[0]; - int y = saved == null ? defY : saved[1]; - boolean v = visible == null || visible; - if (visibilities.isEmpty()) v = true; - - elements.add(new HudElement(id, defX, defY, x, y, v) { - @Override public void render(DrawContext ctx, int mx, int my, float delta) { - renderer.render(ctx, x, y, delta); - } - }); - } - - public static Color getColor(HUD hud) { - return hud.color.getColor(); - } - - public static void drawSnappedText(DrawContext ctx, String text, int x, int y, int color, boolean shadow) { - int textWidth = mc.textRenderer.getWidth(text); - int screenWidth = mc.getWindow().getScaledWidth(); - int screenHeight = mc.getWindow().getScaledHeight(); - - boolean snapRight = x > screenWidth / 2; - int drawX = snapRight ? x + (textWidth + 2) - textWidth : x; - - // clampear y - y = Math.max(0, Math.min(y, screenHeight - mc.textRenderer.fontHeight)); - - // clampear x - drawX = Math.max(0, Math.min(drawX, screenWidth - textWidth)); - - ctx.drawText(mc.textRenderer, text, drawX, y, color, shadow); - } - - public static void render(DrawContext ctx, RenderTickCounter tc) { - if (ModuleManager.INSTANCE == null - || mc.player == null - || mc.getCameraEntity() == null - || mc.currentScreen instanceof TitleScreen - || mc.options.hudHidden) - return; - - HUD hud = ModuleManager.INSTANCE.getModuleByClass(HUD.class); - if (!hud.isEnabled()) return; - if (mc.debugHudEntryList.isF3Enabled() && !hud.showOnF3.isEnabled()) return; - if (mc.currentScreen instanceof ChatScreen && !hud.showOnChat.isEnabled()) return; - - initElements(); - - if (mc.currentScreen instanceof HudEditorScreen) return; - - float deltaTime = tc.getDynamicDeltaTicks(); - for (HudElement element : elements) - if (element.isVisible()) element.render(ctx, 0, 0, deltaTime); - } - - public static List getElements() { - return elements; - } - - // texto a dibujar por elemento - public static String getElementText(String id, float delta, HUD hud) { - switch (id) { - case "coords" -> { - Freecam freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); - Vec3d pos = freecam.isEnabled() - ? new Vec3d(freecam.getX(delta), freecam.getY(delta), freecam.getZ(delta)) - : mc.player.getEntityPos(); - - return (int) pos.x + " " + (int) pos.y + " " + (int) pos.z; - } - case "fps" -> { - return "FPS: " + mc.getCurrentFps(); - } - case "tps" -> { - return String.format("TPS: %.1f", estimatedTPS); - } - case "customText" -> { - return ModuleManager.INSTANCE.getModuleByClass(HUD.class).customText.getValue(); - } - case "time" -> { - ZoneOffset offset = ZoneOffset.ofHours(hud.timezone.getIntValue()); - LocalTime now = LocalTime.now(offset); - - boolean is24 = hud.timeFormat.is(HUD.TimeFormat.TWENTY_FOUR_HOUR); - DateTimeFormatter format = DateTimeFormatter.ofPattern(is24 ? "HH:mm" : "hh:mm a"); - return now.format(format); - } - case "ping" -> { - if (mc.getNetworkHandler() == null || mc.player == null) return "? ms"; - if (mc.isInSingleplayer()) return "-1 ms"; - - PlayerListEntry playerListEntry = mc.getNetworkHandler().getPlayerListEntry(mc.player.getUuid()); - return playerListEntry != null ? playerListEntry.getLatency() + " ms" : "? ms"; - } - default -> { return id; } - } - } - - @SubscribeEvent - public void onReceivePacket(PacketEvent.Receive event) { - if (event.getPacket() instanceof WorldTimeUpdateS2CPacket packet) { - long currentWorldTime = packet.time(); - long currentRealTime = System.currentTimeMillis(); - - if (lastWorldTime != -1L && lastRealTime != -1L) { - long elapsedRealTime = currentRealTime - lastRealTime; - long elapsedWorldTicks = currentWorldTime - lastWorldTime; - - if (elapsedRealTime > 0) { - // TPS = (ticks passed) / (seconds passed) - float tps = (float) elapsedWorldTicks / (elapsedRealTime / 1000.0f); - - // clampear - tps = Math.max(0.1f, Math.min(20.0f, tps)); - - // usar historial para suavizar resultados - tpsHistory.add(tps); - if (tpsHistory.size() > 10) - tpsHistory.removeFirst(); - - // calcular media de tps - float sum = 0; - for (float t : tpsHistory) sum += t; - estimatedTPS = sum / tpsHistory.size(); - } - } - - lastWorldTime = currentWorldTime; - lastRealTime = currentRealTime; - } - } - - /** para cuando se cambie el valor del texto custom */ - @SubscribeEvent - public void onUpdateSetting(UpdateSettingEvent event) { - if (ModuleManager.INSTANCE == null) return; - HUD hud = ModuleManager.INSTANCE.getModuleByClass(HUD.class); - if (event.getSetting() == hud.customText) { - if (customTextElement != null) { - int newX = mc.getWindow().getScaledWidth() / 2 - mc.textRenderer.getWidth(hud.customText.getValue()) / 2; - customTextElement.setX(newX); - } - } - } -} diff --git a/src/main/java/me/retucio/camtweaks/ui/buttons/ChooseButton.java b/src/main/java/me/retucio/camtweaks/ui/buttons/ChooseButton.java new file mode 100644 index 0000000..628830d --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/ui/buttons/ChooseButton.java @@ -0,0 +1,134 @@ +package me.retucio.camtweaks.ui.buttons; + +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.BooleanSetting; +import me.retucio.camtweaks.module.settings.OptionSetting; +import me.retucio.camtweaks.ui.frames.SettingsFrame; +import me.retucio.camtweaks.ui.screen.ClickGUI; +import me.retucio.camtweaks.util.Colors; +import net.minecraft.client.gui.DrawContext; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; + +import static me.retucio.camtweaks.CameraTweaks.mc; + +public class ChooseButton extends SettingButton { + + private final OptionSetting setting; + private final Module dummy; + private final Map optionButtons = new HashMap<>(); + private T lastSelectedValue; + + public ChooseButton(OptionSetting setting, SettingsFrame parent, int offset) { + super(setting, parent, offset); + this.setting = setting; + this.lastSelectedValue = setting.getValue(); + + // crear un módulo "dummy" (falso) + dummy = new Module(setting.getName(), setting.getDescription()) { + @Override public void onEnable() {} + @Override public void onDisable() {} + }; + + // ocultar cosas innecesarias + dummy.getBind().setVisible(false); + dummy.getSettings().stream() + .filter(s -> s.getName().equalsIgnoreCase("modo de tecla")) + .findFirst() + .ifPresent(s -> s.setVisible(false)); + dummy.getSettings().stream() + .filter(s -> s.getName().equalsIgnoreCase("notificar")) + .findFirst() + .ifPresent(s -> s.setVisible(false)); + dummy.shouldSaveSettings(false); + } + + @Override + public void render(DrawContext ctx, double mouseX, double mouseY, float delta) { + int bgColor = isHovered(mouseX, mouseY) + ? Colors.buttonColor.brighter().getRGB() + : Colors.buttonColor.getRGB(); + + ctx.fill(x, y, x + w, y + h, bgColor); + + String label = setting.getName() + ": " + setting.getDisplayName(setting.getValue()); + ctx.drawText(parent.mc.textRenderer, label, x + 5, y + 3, -1, true); + } + + @Override + public void mouseClicked(double mouseX, double mouseY, int button) { + if (isHovered(mouseX, mouseY) && ClickGUI.INSTANCE.trySelect(this)) { + // click izquierdo / derecho: abrir marco + if (button <= 1 && !mc.isShiftPressed()) { + if (ClickGUI.INSTANCE.isSettingsFrameOpen(dummy)) { + ClickGUI.INSTANCE.closeSettingsFrame(dummy); + return; + } + + rebuildDummy(); + ClickGUI.INSTANCE.openListSettingsFrame(dummy, parent.x + 40, parent.y + 40); + // shift + clic derecho: restablecer valores + } else if (button == 1 && mc.isShiftPressed()) { + setting.reset(); + refreshDummy(); + } + } + } + + private void rebuildDummy() { + dummy.getSettings().clear(); + optionButtons.clear(); + + setting.getOptions().stream() + .sorted(Comparator.comparing(setting::getDisplayName, String.CASE_INSENSITIVE_ORDER)) + .forEach(option -> { + String displayName = setting.getDisplayName(option); + BooleanSetting b = new BooleanSetting( + displayName, + "incluir " + displayName, + setting.is(option) + ); + + b.onUpdate(value -> { + if (value) { + // deseleccionar el resto de opciones + for (Map.Entry entry : optionButtons.entrySet()) { + if (!entry.getKey().equals(option)) + entry.getValue().setEnabled(false); + } + setting.setValue(option); + } else { + if (setting.is(option)) + b.setEnabled(true); + } + }); + + dummy.addSetting(b); + optionButtons.put(option, b); + }); + } + + public void refreshDummy() { + T currentValue = setting.getValue(); + for (Map.Entry entry : optionButtons.entrySet()) { + boolean shouldBeEnabled = entry.getKey().equals(currentValue); + if (entry.getValue().isEnabled() != shouldBeEnabled) { + entry.getValue().setEnabled(shouldBeEnabled); + } + } + } + + public OptionSetting getSetting() { + return setting; + } + + @Override + public void mouseReleased(double mouseX, double mouseY, int button) { + ClickGUI.INSTANCE.unselect(this); + } + + @Override + public void mouseDragged(double mouseX, double mouseY) {} +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/ui/buttons/SettingButton.java b/src/main/java/me/retucio/camtweaks/ui/buttons/SettingButton.java index 13c606e..130214b 100644 --- a/src/main/java/me/retucio/camtweaks/ui/buttons/SettingButton.java +++ b/src/main/java/me/retucio/camtweaks/ui/buttons/SettingButton.java @@ -1,6 +1,6 @@ package me.retucio.camtweaks.ui.buttons; -import me.retucio.camtweaks.module.settings.AbstractSetting; +import me.retucio.camtweaks.module.settings.Setting; import me.retucio.camtweaks.ui.screen.ClickGUI; import me.retucio.camtweaks.ui.frames.SettingsFrame; import net.minecraft.client.gui.DrawContext; @@ -9,13 +9,13 @@ import net.minecraft.text.Text; // clase base para los botones de los ajustes public abstract class SettingButton { - protected final AbstractSetting setting; + protected final Setting setting; protected final SettingsFrame parent; protected int offset; protected int x, y, w, h; - public SettingButton(AbstractSetting setting, SettingsFrame parent, int offset) { + public SettingButton(Setting setting, SettingsFrame parent, int offset) { this.setting = setting; this.parent = parent; this.offset = offset; @@ -42,7 +42,7 @@ public abstract class SettingButton { mouseY > y && mouseY < y + h; } - public AbstractSetting getSetting() { + public Setting getSetting() { return setting; } diff --git a/src/main/java/me/retucio/camtweaks/ui/frames/ColorPickerFrame.java b/src/main/java/me/retucio/camtweaks/ui/frames/ColorPickerFrame.java index 36824b3..f51980d 100644 --- a/src/main/java/me/retucio/camtweaks/ui/frames/ColorPickerFrame.java +++ b/src/main/java/me/retucio/camtweaks/ui/frames/ColorPickerFrame.java @@ -1,13 +1,12 @@ package me.retucio.camtweaks.ui.frames; import me.retucio.camtweaks.module.Module; -import me.retucio.camtweaks.module.settings.AbstractSetting; +import me.retucio.camtweaks.module.settings.Setting; import me.retucio.camtweaks.module.settings.BooleanSetting; import me.retucio.camtweaks.module.settings.ColorSetting; import me.retucio.camtweaks.module.settings.NumberSetting; import me.retucio.camtweaks.ui.buttons.*; import me.retucio.camtweaks.ui.screen.ClickGUI; -import me.retucio.camtweaks.util.ChatUtil; import me.retucio.camtweaks.util.Colors; import me.retucio.camtweaks.util.render.DrawUtil; import net.minecraft.client.gui.DrawContext; @@ -73,7 +72,7 @@ public class ColorPickerFrame extends SettingsFrame { // añadir ajustes y tal dummyModule.addSettings(redSetting, greenSetting, blueSetting, rainbowSpeedSetting, saturationSetting, brightnessSetting, rainbowSetting); - for (AbstractSetting setting : dummyModule.getSettings()) { + for (Setting setting : dummyModule.getSettings()) { if (setting instanceof NumberSetting n) n.onUpdate(v -> updateColorFromSettings()); if (setting instanceof BooleanSetting b) b.onUpdate(v -> updateColorFromSettings()); rainbowSetting.onUpdate(v -> { @@ -120,7 +119,7 @@ public class ColorPickerFrame extends SettingsFrame { updateWidth(); // al parecer este era el problema :/ - for (AbstractSetting setting : dummyModule.getSettings()) + for (Setting setting : dummyModule.getSettings()) if (setting instanceof NumberSetting ns) ns.setLocked( pickingAlpha || pickingHue || pickingSaturationBrightness); @@ -473,7 +472,7 @@ public class ColorPickerFrame extends SettingsFrame { private void updateSettingsFromColor() { if (colorSetting == null) return; - for (AbstractSetting setting : dummyModule.getSettings()) { + for (Setting setting : dummyModule.getSettings()) { switch (setting.getName()) { case "rojo" -> ((NumberSetting) setting).setValue(colorSetting.getR()); case "verde" -> ((NumberSetting) setting).setValue(colorSetting.getG()); diff --git a/src/main/java/me/retucio/camtweaks/ui/frames/SettingsFrame.java b/src/main/java/me/retucio/camtweaks/ui/frames/SettingsFrame.java index 2861f62..1a71911 100644 --- a/src/main/java/me/retucio/camtweaks/ui/frames/SettingsFrame.java +++ b/src/main/java/me/retucio/camtweaks/ui/frames/SettingsFrame.java @@ -50,7 +50,7 @@ public class SettingsFrame { // añadir el respectivo tipo de botón de cada ajuste a la lista de botones int offset = h; - for (AbstractSetting setting : module.getSettings()) { + for (Setting setting : module.getSettings()) { switch (setting) { case BooleanSetting b -> { addButton(new ToggleButton(b, this, offset)); @@ -73,6 +73,9 @@ public class SettingsFrame { } case ColorSetting c -> { addButton(new ColorButton(c, this, offset)); offset += 18; + } case OptionSetting o -> { + addButton(new ChooseButton<>(o, this, offset)); + offset += 18; } default -> {} } diff --git a/src/main/java/me/retucio/camtweaks/ui/screen/HudEditorScreen.java b/src/main/java/me/retucio/camtweaks/ui/hud/HudEditorScreen.java similarity index 52% rename from src/main/java/me/retucio/camtweaks/ui/screen/HudEditorScreen.java rename to src/main/java/me/retucio/camtweaks/ui/hud/HudEditorScreen.java index ec8bedf..621e2ed 100644 --- a/src/main/java/me/retucio/camtweaks/ui/screen/HudEditorScreen.java +++ b/src/main/java/me/retucio/camtweaks/ui/hud/HudEditorScreen.java @@ -1,19 +1,18 @@ -package me.retucio.camtweaks.ui.screen; +package me.retucio.camtweaks.ui.hud; import me.retucio.camtweaks.config.ConfigManager; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.HUD; import me.retucio.camtweaks.ui.frames.ClientSettingsFrame; -import me.retucio.camtweaks.ui.widgets.HudElement; import me.retucio.camtweaks.util.Colors; - import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.Click; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.input.KeyInput; import net.minecraft.text.Text; - -import org.lwjgl.glfw.GLFW; import org.jetbrains.annotations.Nullable; +import org.lwjgl.glfw.GLFW; import java.util.ArrayList; import java.util.List; @@ -30,7 +29,7 @@ public class HudEditorScreen extends Screen { private int dragOffsetX, dragOffsetY; public HudEditorScreen() { - super(Text.literal("editor del hud")); + super(Text.literal("editor del HUD")); } public void setElements(List elements) { @@ -42,24 +41,26 @@ public class HudEditorScreen extends Screen { public void render(DrawContext ctx, int mouseX, int mouseY, float delta) { ctx.fill(0, 0, this.width, this.height, Colors.hudEditorScreenBackgroundColor.getRGB()); - // texto con instrucciones - ctx.drawCenteredTextWithShadow(mc.textRenderer, "EDITOR DEL HUD", this.width / 2, this.height / 2 - mc.textRenderer.fontHeight, -1); + // instrucciones + ctx.drawCenteredTextWithShadow(mc.textRenderer, "editor del HUD", + this.width / 2, this.height / 2 - mc.textRenderer.fontHeight, -1); ctx.drawCenteredTextWithShadow(mc.textRenderer, - Text.literal("arrastrar para mover · click derecho para alternar visibilidad · esc para guardar y salir · shift + click derecho para restablecer"), + Text.literal("arrastrar para mover · clic derecho para visibilidad · ESC para guardar y salir · shift + clic derecho para restablecer"), this.width / 2, this.height / 2 + mc.textRenderer.fontHeight, Colors.instructionsTextColor.getRGB()); - // dibujar elementos + // elementos for (HudElement element : elements) - element.renderPreview(ctx); + element.renderInEditor(ctx, null); - // tooltips con información sobre el elemento sobre el que está el puntero del ratón + // tooltips if (!dragging) { for (HudElement element : elements) { if (!element.isVisible()) continue; - if (element.contains(mouseX, mouseY)) { - List tooltip = getTooltipFor(element); - if (!tooltip.isEmpty()) ctx.drawTooltip(mc.textRenderer, tooltip, mouseX + 7, mouseY + 20); + if (element.isHovered(mouseX, mouseY)) { + List tooltip = element.getTooltip(); + if (!tooltip.isEmpty()) + ctx.drawTooltip(mc.textRenderer, tooltip, mouseX + 7, mouseY + 20); break; } } @@ -73,28 +74,27 @@ public class HudEditorScreen extends Screen { int mouseX = (int) click.x(); int mouseY = (int) click.y(); - // iterar de atrás a adelante para respetar el orden z for (int i = elements.size() - 1; i >= 0; i--) { HudElement element = elements.get(i); - if (element.contains(mouseX, mouseY)) { + if (element.isHovered(mouseX, mouseY)) { selected = element; if (click.button() == 0) { dragging = true; - dragOffsetX = mouseX - element.getX(); dragOffsetY = mouseY - element.getY(); - // traer el elemento seleccionado al frente elements.remove(i); elements.add(element); return true; } else if (click.button() == 1) { - if (mc.isShiftPressed()) + if (mc.isShiftPressed()) { selected.resetPosition(); - else + } else { selected.setVisible(!selected.isVisible()); + } + saveElementToConfig(selected); return true; } } @@ -114,7 +114,6 @@ public class HudEditorScreen extends Screen { int newX = mouseX - dragOffsetX; int newY = mouseY - dragOffsetY; - // clampear para evitar que los elementos se salgan de la pantalla newX = Math.max(1, Math.min(newX, width - selected.getWidth() - 1)); newY = Math.max(1, Math.min(newY, height - selected.getHeight() - 1)); @@ -126,92 +125,46 @@ public class HudEditorScreen extends Screen { public boolean mouseReleased(Click click) { if (dragging && click.button() == 0) { dragging = false; - savePositionsToConfig(); // guardar inmediatamente al config - return true; - } else if (click.button() == 1 && selected != null) { - saveVisibilitiesToConfig(); - selected = null; + if (selected != null) + saveElementToConfig(selected); return true; } + selected = null; return super.mouseReleased(click); } @Override public boolean keyPressed(KeyInput input) { - // esc para guardar y salir if (input.key() == GLFW.GLFW_KEY_ESCAPE) { - saveAndClose(); + saveAllElementsToConfig(); + selected = null; + mc.setScreen(null); return true; } return super.keyPressed(input); } - private void savePositionsToConfig() { - for (HudElement element : elements) - ConfigManager.setHudPosition(element.getId(), element.getX(), element.getY()); - + private void saveElementToConfig(HudElement element) { + ConfigManager.setHudPosition(element.getId(), element.getX(), element.getY()); + ConfigManager.setHudVisibility(element.getId(), element.isVisible()); ConfigManager.save(); } - private void saveVisibilitiesToConfig() { - for (HudElement element : elements) - ConfigManager.setHudVisibility(element.getId(), element.isVisible()); - - ConfigManager.save(); - } - - private void saveAndClose() { - savePositionsToConfig(); - selected = null; - mc.setScreen(null); + private void saveAllElementsToConfig() { + for (HudElement element : elements) { + saveElementToConfig(element); + } } @Override protected void applyBlur(DrawContext ctx) { - if (ClientSettingsFrame.guiSettings.blur.isEnabled()) super.applyBlur(ctx); + if (ClientSettingsFrame.guiSettings.blur.isEnabled()) { + super.applyBlur(ctx); + } } public boolean isSelected(HudElement element) { return selected == element; } - - // para los tooltips - private List getTooltipFor(HudElement element) { - List list = new ArrayList<>(); - - switch (element.getId()) { - case "coords" -> { - list.add(Text.literal("coordenadas")); - list.add(Text.literal("te muestra tu posición en el mundo en coordenadas XYZ")); - } - case "fps" -> { - list.add(Text.literal("FPS")); - list.add(Text.literal("te muestra la tasa de fotogramas por segundo del juego")); - } - case "tps" -> { - list.add(Text.literal("tps")); - list.add(Text.literal("te muestra la tasa de ticks por segundo del servidor (0-20)")); - } - case "customText" -> { - list.add(Text.literal("texto custom")); - list.add(Text.literal("te permite renderizar texto al gusto")); - } - case "time" -> { - list.add(Text.literal("hora")); - list.add(Text.literal("te muestra la hora y los minutos de la zona horaria escogida")); - } - case "ping" -> { - list.add(Text.literal("ping")); - list.add(Text.literal("tiempo entre que se envía un paquete y este llega a su destino, en milisegundos")); - } - default -> { - list.add(Text.literal(element.getId())); - list.add(Text.literal(".")); - } - } - - return list; - } - -} +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/ui/hud/HudElement.java b/src/main/java/me/retucio/camtweaks/ui/hud/HudElement.java new file mode 100644 index 0000000..6ae0bce --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/ui/hud/HudElement.java @@ -0,0 +1,91 @@ +package me.retucio.camtweaks.ui.hud; + +import me.retucio.camtweaks.module.modules.HUD; +import me.retucio.camtweaks.util.Colors; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; + +import java.util.List; + +public abstract class HudElement { + + protected static final MinecraftClient mc = MinecraftClient.getInstance(); + + private final String id; + protected boolean visible; + protected int x, y; + protected final int defaultX, defaultY; + protected int width = 85, height = 14; + + public HudElement(String id, int defaultX, int defaultY) { + this.id = id; + this.defaultX = defaultX; + this.defaultY = defaultY; + this.visible = true; + } + + public abstract String getText(float delta, HUD hud); + public abstract String getPreviewText(); + + public void renderInGame(DrawContext ctx, float delta, HUD hud) { + String text = getText(delta, hud); + int color = hud != null ? HudRenderer.getColor(hud).getRGB() : -1; + boolean shadow = hud != null && hud.shadow.isEnabled(); + HudRenderer.drawSnappedText(ctx, text, x, y, color, shadow); + } + + public void renderInEditor(DrawContext ctx, HUD hud) { + String previewText = getPreviewText(); + width = mc.textRenderer.getWidth(previewText); + height = mc.textRenderer.fontHeight; + + drawEditorBackground(ctx); + + int color = hud != null ? HudRenderer.getColor(hud).getRGB() : -1; + boolean shadow = hud != null && hud.shadow.isEnabled(); + HudRenderer.drawSnappedText(ctx, previewText, x, y, color, shadow); + } + + public abstract List getTooltip(); + + private void drawEditorBackground(DrawContext ctx) { + int bg = visible ? Colors.visibleHudElementColor.getRGB() : Colors.disabledHudElementColor.getRGB(); + int outline = HudEditorScreen.INSTANCE != null && HudEditorScreen.INSTANCE.isSelected(this) + ? Colors.selectedHudElementOutlineColor.getRGB() + : Colors.unselectedHudElementOutlineColor.getRGB(); + + // fondo + ctx.fill(x - 1, y - 1, x + width + 1, y + height + 1, bg); + + // contorno + ctx.fill(x - 1, y - 1, x + width + 1, y, outline); + ctx.fill(x - 1, y + height, x + width + 1, y + height + 1, outline); + ctx.fill(x - 1, y, x, y + height, outline); + ctx.fill(x + width, y, x + width + 1, y + height, outline); + } + + public boolean isHovered(int mouseX, int mouseY) { + return mouseX >= x && mouseX <= x + width + && mouseY >= y && mouseY <= y + height; + } + + // Getters and setters + public String getId() { return id; } + public int getX() { return x; } + public int getY() { return y; } + public int getWidth() { return width; } + public int getHeight() { return height; } + public boolean isVisible() { return visible; } + public void setVisible(boolean visible) { this.visible = visible; } + + public void resetPosition() { + this.x = defaultX; + this.y = defaultY; + } + + public void setPosition(int x, int y) { + this.x = x; + this.y = y; + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/ui/hud/HudRenderer.java b/src/main/java/me/retucio/camtweaks/ui/hud/HudRenderer.java new file mode 100644 index 0000000..cb1beed --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/ui/hud/HudRenderer.java @@ -0,0 +1,111 @@ +package me.retucio.camtweaks.ui.hud; + +import me.retucio.camtweaks.config.ConfigManager; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.HUD; +import me.retucio.camtweaks.ui.hud.elements.*; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ChatScreen; +import net.minecraft.client.gui.screen.TitleScreen; +import net.minecraft.client.render.RenderTickCounter; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class HudRenderer { + + private static final MinecraftClient mc = MinecraftClient.getInstance(); + + private static final List elements = new ArrayList<>(); + private static boolean initialized = false; + + public static void init() { + if (initialized) return; + initialized = true; + + Map positions = ConfigManager.getConfig().hudPositions; + Map visibilities = ConfigManager.getConfig().hudVisibilities; + + addElement(new CoordsElement(), positions, visibilities); + addElement(new FpsElement(), positions, visibilities); + addElement(new TpsElement(), positions, visibilities); + addElement(new CustomTextElement(), positions, visibilities); + addElement(new TimeElement(), positions, visibilities); + addElement(new PingElement(), positions, visibilities); + + HudEditorScreen.INSTANCE.setElements(elements); + } + + private static void addElement(HudElement element, Map positions, Map visibilities) { + int[] savedPos; + + if (positions.get(element.getId()) == null) + savedPos = new int[] {element.defaultX, element.defaultY}; + else + savedPos = positions.get(element.getId()); + + Boolean savedVisibility = visibilities.get(element.getId()); + + if (savedPos != null) + element.setPosition(savedPos[0], savedPos[1]); + + if (savedVisibility != null) + element.setVisible(savedVisibility); + + elements.add(element); + } + + public static Color getColor(HUD hud) { + return hud.color.getColor(); + } + + public static void drawSnappedText(DrawContext ctx, String text, int x, int y, int color, boolean shadow) { + int textWidth = mc.textRenderer.getWidth(text); + int screenWidth = mc.getWindow().getScaledWidth(); + int screenHeight = mc.getWindow().getScaledHeight(); + + boolean snapRight = x > screenWidth / 2; + int drawX = snapRight ? x + (textWidth + 2) - textWidth : x; + + drawX = Math.max(0, Math.min(drawX, screenWidth - textWidth)); + y = Math.max(0, Math.min(y, screenHeight - mc.textRenderer.fontHeight)); + + ctx.drawText(mc.textRenderer, text, drawX, y, color, shadow); + } + + public static void render(DrawContext ctx, RenderTickCounter tickCounter) { + if (shouldSkipRendering()) return; + + HUD hud = ModuleManager.INSTANCE.getModuleByClass(HUD.class); + if (!hud.isEnabled()) return; + if (mc.debugHudEntryList.isF3Enabled() && !hud.showOnF3.isEnabled()) return; + if (mc.currentScreen instanceof ChatScreen && !hud.showOnChat.isEnabled()) return; + + init(); + + if (mc.currentScreen instanceof HudEditorScreen) return; + + float delta = tickCounter.getDynamicDeltaTicks(); + for (HudElement element : elements) { + if (element.isVisible()) { + element.renderInGame(ctx, delta, hud); + } + } + } + + private static boolean shouldSkipRendering() { + return ModuleManager.INSTANCE == null + || mc.player == null + || mc.getCameraEntity() == null + || mc.currentScreen instanceof TitleScreen + || mc.options.hudHidden; + } + + public static List getElements() { + return elements; + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/ui/hud/elements/CoordsElement.java b/src/main/java/me/retucio/camtweaks/ui/hud/elements/CoordsElement.java new file mode 100644 index 0000000..37cf30e --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/ui/hud/elements/CoordsElement.java @@ -0,0 +1,51 @@ +package me.retucio.camtweaks.ui.hud; + +import me.retucio.camtweaks.event.events.PacketEvent; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.Freecam; +import me.retucio.camtweaks.module.modules.HUD; +import net.minecraft.text.Text; +import net.minecraft.util.math.Vec3d; + +import java.util.List; + +public class CoordsElement extends HudElement { + + public CoordsElement() { + super("coords", 2, mc.getWindow().getScaledHeight() - mc.textRenderer.fontHeight); + } + + @Override + public String getText(float delta, HUD hud) { + Freecam freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); + Vec3d pos = freecam != null && freecam.isEnabled() + ? new Vec3d(freecam.getX(delta), freecam.getY(delta), freecam.getZ(delta)) + : mc.player.getEntityPos(); + + String overworldCoords = (int) pos.x + " " + (int) pos.y + " " + (int) pos.z; + String netherCoords = (int) pos.x / 8 + " " + (int) pos.y / 8 + " " + (int) pos.z / 8; + + if (hud.coordsMode.is(HUD.CoordsMode.OVERWORLD)) { + return overworldCoords; + } else if (hud.coordsMode.is(HUD.CoordsMode.NETHER)) { + return netherCoords; + } else { + return overworldCoords + " (" + netherCoords + ")"; + } + } + + @Override + public String getPreviewText() { + return getText( + mc.getRenderTickCounter().getDynamicDeltaTicks(), + ModuleManager.INSTANCE.getModuleByClass(HUD.class)); + } + + @Override + public List getTooltip() { + return List.of( + Text.literal(getId()), + Text.literal("te muestra tu posición XYZ en el mundo") + ); + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/ui/hud/elements/CustomTextElement.java b/src/main/java/me/retucio/camtweaks/ui/hud/elements/CustomTextElement.java new file mode 100644 index 0000000..54b901e --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/ui/hud/elements/CustomTextElement.java @@ -0,0 +1,49 @@ +package me.retucio.camtweaks.ui.hud.elements; + +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.HUD; +import me.retucio.camtweaks.ui.hud.HudElement; +import net.minecraft.text.Text; + +import java.util.List; + +public class CustomTextElement extends HudElement { + + public CustomTextElement() { + super("customText", mc.getWindow().getScaledWidth() / 2 - 40, 2); + } + + @Override + public String getText(float delta, HUD hud) { + return hud != null && hud.customText != null ? hud.customText.getValue() : ""; + } + + @Override + public String getPreviewText() { + HUD hud = ModuleManager.INSTANCE.getModuleByClass(HUD.class); + if (hud != null && hud.customText != null && !hud.customText.getValue().isEmpty()) + return hud.customText.getValue(); + + return "texto custom"; + } + + @Override + public List getTooltip() { + return List.of( + Text.literal("texto custom"), + Text.literal("texto que tú eliges") + ); + } + + @SubscribeEvent + public void onUpdateSetting(UpdateSettingEvent event) { + if (ModuleManager.INSTANCE == null) return; + HUD hud = ModuleManager.INSTANCE.getModuleByClass(HUD.class); + if (hud != null && event.getSetting() == hud.customText) { + int newX = mc.getWindow().getScaledWidth() / 2 - mc.textRenderer.getWidth(hud.customText.getValue()) / 2; + setPosition(newX, y); + } + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/ui/hud/elements/FpsElement.java b/src/main/java/me/retucio/camtweaks/ui/hud/elements/FpsElement.java new file mode 100644 index 0000000..931c806 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/ui/hud/elements/FpsElement.java @@ -0,0 +1,32 @@ +package me.retucio.camtweaks.ui.hud.elements; + +import me.retucio.camtweaks.module.modules.HUD; +import me.retucio.camtweaks.ui.hud.HudElement; +import net.minecraft.text.Text; + +import java.util.List; + +public class FpsElement extends HudElement { + + public FpsElement() { + super("fps", 2, 2); + } + + @Override + public String getText(float delta, HUD hud) { + return "FPS: " + mc.getCurrentFps(); + } + + @Override + public String getPreviewText() { + return "FPS: 67"; + } + + @Override + public List getTooltip() { + return List.of( + Text.literal("FPS"), + Text.literal("te muestra los fotogramas por segundo a los que corre el juego") + ); + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/ui/hud/elements/PingElement.java b/src/main/java/me/retucio/camtweaks/ui/hud/elements/PingElement.java new file mode 100644 index 0000000..6143e6f --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/ui/hud/elements/PingElement.java @@ -0,0 +1,37 @@ +package me.retucio.camtweaks.ui.hud.elements; + +import me.retucio.camtweaks.module.modules.HUD; +import me.retucio.camtweaks.ui.hud.HudElement; +import net.minecraft.client.network.PlayerListEntry; +import net.minecraft.text.Text; + +import java.util.List; + +public class PingElement extends HudElement { + + public PingElement() { + super("ping", 2, 2 * (mc.textRenderer.fontHeight + 4)); + } + + @Override + public String getText(float delta, HUD hud) { + if (mc.getNetworkHandler() == null || mc.player == null) return "? ms"; + if (mc.isInSingleplayer()) return "-1 ms"; + + PlayerListEntry playerListEntry = mc.getNetworkHandler().getPlayerListEntry(mc.player.getUuid()); + return playerListEntry != null ? playerListEntry.getLatency() + " ms" : "? ms"; + } + + @Override + public String getPreviewText() { + return "67 ms"; + } + + @Override + public List getTooltip() { + return List.of( + Text.literal("ping"), + Text.literal("latencia entre cliente y servidor, en milisegundos") + ); + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/ui/hud/elements/TimeElement.java b/src/main/java/me/retucio/camtweaks/ui/hud/elements/TimeElement.java new file mode 100644 index 0000000..a745638 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/ui/hud/elements/TimeElement.java @@ -0,0 +1,33 @@ +package me.retucio.camtweaks.ui.hud.elements; + +import me.retucio.camtweaks.module.modules.HUD; +import me.retucio.camtweaks.ui.hud.HudElement; +import me.retucio.camtweaks.util.MiscUtil; +import net.minecraft.text.Text; + +import java.util.List; + +public class TimeElement extends HudElement { + + public TimeElement() { + super("time", mc.getWindow().getScaledWidth() - 50, mc.getWindow().getScaledHeight() - mc.textRenderer.fontHeight - 2); + } + + @Override + public String getText(float delta, HUD hud) { + return MiscUtil.getCurrentFormattedTime(); + } + + @Override + public String getPreviewText() { + return "04:20 PM"; + } + + @Override + public List getTooltip() { + return List.of( + Text.literal("hora"), + Text.literal("hora y minutos de la zona horaria seleccionada") + ); + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/ui/hud/elements/TpsElement.java b/src/main/java/me/retucio/camtweaks/ui/hud/elements/TpsElement.java new file mode 100644 index 0000000..55d337b --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/ui/hud/elements/TpsElement.java @@ -0,0 +1,33 @@ +package me.retucio.camtweaks.ui.hud.elements; + +import me.retucio.camtweaks.module.modules.HUD; +import me.retucio.camtweaks.ui.hud.HudElement; +import me.retucio.camtweaks.util.NetworkUtil; +import net.minecraft.text.Text; + +import java.util.List; + +public class TpsElement extends HudElement { + + public TpsElement() { + super("tps", 2, mc.textRenderer.fontHeight + 4); + } + + @Override + public String getText(float delta, HUD hud) { + return "TPS: " + NetworkUtil.getTPS(); + } + + @Override + public String getPreviewText() { + return "TPS: 20.0"; + } + + @Override + public List getTooltip() { + return List.of( + Text.literal("TPS"), + Text.literal("te muestra la tasa de ticks por segundo del servidor (TPS óptimo: 20)") + ); + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/ui/screen/ClickGUI.java b/src/main/java/me/retucio/camtweaks/ui/screen/ClickGUI.java index 9175824..9a52de6 100644 --- a/src/main/java/me/retucio/camtweaks/ui/screen/ClickGUI.java +++ b/src/main/java/me/retucio/camtweaks/ui/screen/ClickGUI.java @@ -7,10 +7,8 @@ import me.retucio.camtweaks.event.events.MouseClickEvent; import me.retucio.camtweaks.event.events.MouseScrollEvent; import me.retucio.camtweaks.event.events.camtweaks.SettingsFrameEvent; import me.retucio.camtweaks.module.Module; -import me.retucio.camtweaks.module.ModuleManager; -import me.retucio.camtweaks.module.settings.AbstractSetting; +import me.retucio.camtweaks.module.settings.Setting; import me.retucio.camtweaks.module.settings.ColorSetting; -import me.retucio.camtweaks.ui.buttons.ColorButton; import me.retucio.camtweaks.ui.buttons.ListButton; import me.retucio.camtweaks.ui.buttons.ModuleButton; import me.retucio.camtweaks.ui.buttons.SettingButton; @@ -20,7 +18,6 @@ import me.retucio.camtweaks.ui.frames.ModuleFrame; import me.retucio.camtweaks.ui.frames.SettingsFrame; import me.retucio.camtweaks.ui.widgets.ScrollBarWidget; import me.retucio.camtweaks.ui.widgets.SearchBarWidget; -import me.retucio.camtweaks.util.ChatUtil; import me.retucio.camtweaks.util.KeyUtil; import net.minecraft.client.MinecraftClient; @@ -207,7 +204,7 @@ public class ClickGUI extends Screen { for (SettingsFrame sf : settingsFrames) { for (SettingButton sb : sf.getButtons()) { - AbstractSetting setting = sb.getSetting(); + Setting setting = sb.getSetting(); if (searchInput.isEmpty()) { setting.setSearchMatch(true); diff --git a/src/main/java/me/retucio/camtweaks/ui/widgets/Button.java b/src/main/java/me/retucio/camtweaks/ui/widgets/Button.java new file mode 100644 index 0000000..878eed7 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/ui/widgets/Button.java @@ -0,0 +1,36 @@ +package me.retucio.camtweaks.ui.widgets; + +import me.retucio.camtweaks.module.settings.Setting; +import me.retucio.camtweaks.ui.frames.SettingsFrame; +import me.retucio.camtweaks.ui.screen.ClickGUI; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; + +public abstract class Button { + + protected Frame parent; + protected int offset; + + protected int x, y, w, h; + + public Button(Frame parent, int offset) { + this.parent = parent; + this.offset = offset; + } + + public abstract void render(DrawContext ctx, int mouseX, int mouseY, float delta); + + public abstract void mouseClicked(int mouseX, int mouseY, int button); + public abstract void mouseDragged(int mouseX, int mouseY); + public void mouseReleased(int mouseX, int mouseY, int button) { + ClickGUI.INSTANCE.unselect(this); + } + + public abstract void drawTooltip(DrawContext ctx, double mouseX, double mouseY); + + protected boolean isHovered(int mouseX, int mouseY) { + if (!ClickGUI.INSTANCE.canSelect(this)) return false; + return mouseX > x && mouseX < x + w && + mouseY > y && mouseY < y + h; + } +} diff --git a/src/main/java/me/retucio/camtweaks/ui/widgets/Frame.java b/src/main/java/me/retucio/camtweaks/ui/widgets/Frame.java new file mode 100644 index 0000000..9ac2487 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/ui/widgets/Frame.java @@ -0,0 +1,63 @@ +package me.retucio.camtweaks.ui.widgets; + +import me.retucio.camtweaks.ui.screen.ClickGUI; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; + +import java.util.ArrayList; +import java.util.List; + +public abstract class Frame { + + private final MinecraftClient mc = MinecraftClient.getInstance(); + + public final String title; + private final List