diff --git a/README.md b/README.md new file mode 100644 index 0000000..fc278a8 --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ +# jenny's mod 2 100% real + +mod para Minecraft Fabric 1.21.6 que añade algunas cosas QOL, mayormente relacionadas a la cámara. + +## instalación + +### para gente normal: +1. ir a [lanzamientos](https://github.com/retuci0/camera-tweaks/releases) +2. selecionar la versión más reciente +3. descargar el .jar +4. moverlo a tu directorio de mods (probablemente `%appdata%/.minecraft/mods`) + +asegúrate de tener una version de Minecraft y Fabric compatibles con el mod + +### para frikis de 200 de iq +1. clona el respositorio +2. `gradlew build` para Windows o `chmod +x gradlew` + `./gradlew build` para Linux +3. el resultado estará en `/build/libs` (el que no lleva "sources" en el nombre) + +## uso + +`shift derecho` por defecto para abrir la interfaz + +`$` como prefijo por defecto para comandos (se autocompletan) + +## interfaz + +- clic izquierdo para activar / desactivar módulos +- clic derecho para abrir sus ajustes +- clic izquierdo + arrastrar para mover marcos +- clic derecho en la cabeza del marco para expandirlo / contraerlo o para cerrarlo +- clic izquierdo sobre ajustes para modificarlos +- shift + clic derecho sobre ajustes para restablecerlos +- posiciona el puntero del ratón sobre un módulo o ajuste para leer su descripción + +### protips +- shift mientras pasas el puntero por encima de un ajuste de modos para ver los modos disponibles +- clic derecho para ciclar hacia atrás en ajustes de modo +- usa la rueda del ratón para mover la interfaz verticalmente + +## capturas + +captura 1 (foto vieja) +captura 2 (interfaz) +captura 3 (interfaz) +captura 5 (comandos) +captura 6 (nametags & apilar bossbars) + +## contibuciones + +sí por favor + +## licencia + +no sé, haz lo que quieras con esto, es puta basura xd \ No newline at end of file diff --git a/credits.txt b/credits.txt index 11b5c0e..305c094 100644 --- a/credits.txt +++ b/credits.txt @@ -1,3 +1,4 @@ -meteor client +meteor client dev team oyvey client (1.21 port by mioclient) -lennyboi (youtube) \ No newline at end of file +lennyboi (youtube) +packbar by cattyn on github \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index b2bef23..fb63a9f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ loader_version=0.17.2 loom_version=1.11-SNAPSHOT # Mod Properties -mod_version=1.0.0 +mod_version=1.1 maven_group=me.retucio archives_base_name=camtweaks diff --git a/screenshots/2025-08-19_23.20.15.png b/screenshots/2025-08-19_23.20.15.png new file mode 100644 index 0000000..7d235de Binary files /dev/null and b/screenshots/2025-08-19_23.20.15.png differ diff --git a/screenshots/2025-08-22_00.18.51.png b/screenshots/2025-08-22_00.18.51.png new file mode 100644 index 0000000..b4024e7 Binary files /dev/null and b/screenshots/2025-08-22_00.18.51.png differ diff --git a/screenshots/2025-08-22_00.19.11.png b/screenshots/2025-08-22_00.19.11.png new file mode 100644 index 0000000..f0289ed Binary files /dev/null and b/screenshots/2025-08-22_00.19.11.png differ diff --git a/screenshots/2025-08-22_00.19.36.png b/screenshots/2025-08-22_00.19.36.png new file mode 100644 index 0000000..7c575d0 Binary files /dev/null and b/screenshots/2025-08-22_00.19.36.png differ diff --git a/screenshots/2025-08-22_00.22.41.png b/screenshots/2025-08-22_00.22.41.png new file mode 100644 index 0000000..c8637dc Binary files /dev/null and b/screenshots/2025-08-22_00.22.41.png differ diff --git a/screenshots/2025-08-27_18.44.41.png b/screenshots/2025-08-27_18.44.41.png new file mode 100644 index 0000000..e74a139 Binary files /dev/null and b/screenshots/2025-08-27_18.44.41.png differ diff --git a/settings.gradle b/settings.gradle index 75c4d72..320d55f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,8 +1,8 @@ pluginManagement { repositories { maven { - name = 'Fabric' - url = 'https://maven.fabricmc.net/' + name = "Fabric" + url = "https://maven.fabricmc.net/" } mavenCentral() gradlePluginPortal() diff --git a/src/main/java/me/retucio/camtweaks/CameraTweaks.java b/src/main/java/me/retucio/camtweaks/CameraTweaks.java index dfed583..8001d97 100644 --- a/src/main/java/me/retucio/camtweaks/CameraTweaks.java +++ b/src/main/java/me/retucio/camtweaks/CameraTweaks.java @@ -1,48 +1,97 @@ package me.retucio.camtweaks; + import me.retucio.camtweaks.command.CommandManager; import me.retucio.camtweaks.command.commands.BindCommand; + +import me.retucio.camtweaks.config.ConfigManager; + import me.retucio.camtweaks.event.EventBus; +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.event.events.ShutdownEvent; + import me.retucio.camtweaks.module.Module; import me.retucio.camtweaks.module.ModuleManager; + import me.retucio.camtweaks.ui.ClickGUI; -import me.retucio.camtweaks.ui.settings.*; -import net.fabricmc.api.ModInitializer; +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.ClickGUISettingsFrame; +import me.retucio.camtweaks.ui.frames.SettingsFrame; + +import me.retucio.camtweaks.util.KeyUtil; +import me.retucio.camtweaks.util.MiscUtil; + + +import net.fabricmc.api.ClientModInitializer; + import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; + import org.lwjgl.glfw.GLFW; -public class CameraTweaks implements ModInitializer { + + +public class CameraTweaks implements ClientModInitializer { // cosas necesarias public static final String MOD_ID = "camtweaks"; public static final CameraTweaks INSTANCE = new CameraTweaks(); public static final Logger LOGGER = LogManager.getLogger(CameraTweaks.class); public static final EventBus EVENT_BUS = new EventBus(); - public static final MinecraftClient mc = MinecraftClient.getInstance(); + public static MinecraftClient mc; private Screen prevScreen; - - // managers - public static ModuleManager moduleManager = new ModuleManager(EVENT_BUS); - public static CommandManager commandManager = new CommandManager(); + private boolean settingsApplied = false; @Override - public void onInitialize() {} + public void onInitializeClient() { + mc = MinecraftClient.getInstance(); + + ModuleManager.INSTANCE = new ModuleManager(EVENT_BUS); + CommandManager.INSTANCE = new CommandManager(); + ClickGUI.INSTANCE = new ClickGUI(); + + ConfigManager.load(); + + EVENT_BUS.register(this); + EVENT_BUS.register(MiscUtil.class); + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + ConfigManager.save(); + EVENT_BUS.post(new ShutdownEvent()); + })); + } + + // se ejecuta cada tick, es decir, 20 veces por segundo + public void onTick() { + ModuleManager.INSTANCE.getEnabledModules().forEach(Module::onTick); + + if (!settingsApplied + && ConfigManager.getConfig() != null + && mc.player != null && mc.world != null) { + ConfigManager.applyConfig(); + settingsApplied = true; + } + } + // se ejecuta cada vez que se presiona una tecla public void onKeyPress(int key, int action) { - moduleManager.getEnabledModules().forEach(module -> module.onKey(key, action)); + ModuleManager.INSTANCE.getEnabledModules().forEach(module -> module.onKey(key, action)); boolean anyFocused = isAnySettingButtonFocused(); + ClickGUI.INSTANCE.setAnyFocused(anyFocused); if (action == GLFW.GLFW_PRESS) { - handleModuleToggle(key, anyFocused); + if (BindCommand.onKeyPress(key)) return; handleSettingButtonsKey(key, action); + handleModuleToggle(key, anyFocused); handleClickGUIKey(key, anyFocused); - BindCommand.onKeyPress(key); } else if (action == GLFW.GLFW_RELEASE && !anyFocused) { handleModuleRelease(key); } @@ -50,12 +99,10 @@ public class CameraTweaks implements ModInitializer { // verifica si algún botón de ajustes está escuchando private boolean isAnySettingButtonFocused() { - for (SettingsFrame sf : ClickGUI.INSTANCE.getSettingsFrames()) { - for (SettingButton sb : sf.getButtons()) { + for (SettingsFrame sf : ClickGUI.INSTANCE.getSettingsFrames()) + for (SettingButton sb : sf.getButtons()) if ((sb instanceof BindButton b && b.isFocused()) || (sb instanceof TextButton t && t.isFocused())) return true; - } - } return false; } @@ -63,8 +110,8 @@ public class CameraTweaks implements ModInitializer { private void handleModuleToggle(int key, boolean anyFocused) { if (mc.currentScreen != null && mc.currentScreen != ClickGUI.INSTANCE) return; - for (Module module : moduleManager.getModules()) { - if (key != module.getKey() || anyFocused) continue; + for (Module module : ModuleManager.INSTANCE.getModules()) { + if (key != module.getKey() || anyFocused || KeyUtil.isKeyDown(GLFW.GLFW_KEY_F3)) continue; // evitar interrumpir combinaciones de teclas del F3 if (module.shouldToggleOnBindRelease() && !module.isEnabled()) module.setEnabled(true); @@ -99,16 +146,13 @@ public class CameraTweaks implements ModInitializer { private void handleModuleRelease(int key) { if (mc.currentScreen != null && mc.currentScreen != ClickGUI.INSTANCE) return; - for (Module module : moduleManager.getEnabledModules()) { - if (module.shouldToggleOnBindRelease() && key == module.getKey()) { + for (Module module : ModuleManager.INSTANCE.getEnabledModules()) + if (module.shouldToggleOnBindRelease() && key == module.getKey()) module.setEnabled(false); - } - } } - // se ejecuta cada tick, es decir, 20 veces por segundo - public void onTick() { - if (mc.player == null) return; - moduleManager.getEnabledModules().forEach(Module::onTick); + @SubscribeEvent + public void onStop(ShutdownEvent event) { + ConfigManager.save(); } } \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/command/Command.java b/src/main/java/me/retucio/camtweaks/command/Command.java index 8c8d1d4..b560d53 100644 --- a/src/main/java/me/retucio/camtweaks/command/Command.java +++ b/src/main/java/me/retucio/camtweaks/command/Command.java @@ -12,13 +12,12 @@ import net.minecraft.server.command.CommandManager; import java.util.List; -import static me.retucio.camtweaks.CameraTweaks.commandManager; - public abstract class Command { // utilizar los "registries" ya existentes de Brigadier para el autocompletado protected static final CommandRegistryAccess REGISTRY_ACCESS = CommandManager.createRegistryAccess(BuiltinRegistries.createWrapperLookup()); protected static final int SUCCESS = com.mojang.brigadier.Command.SINGLE_SUCCESS; + protected static final MinecraftClient mc = MinecraftClient.getInstance(); private final String name, description; @@ -66,7 +65,7 @@ public abstract class Command { } public String toString() { - return commandManager.getPrefix() + name; + return me.retucio.camtweaks.command.CommandManager.INSTANCE.getPrefix() + name; } public String toString(String... args) { diff --git a/src/main/java/me/retucio/camtweaks/command/CommandManager.java b/src/main/java/me/retucio/camtweaks/command/CommandManager.java index 6a53a7c..510b29d 100644 --- a/src/main/java/me/retucio/camtweaks/command/CommandManager.java +++ b/src/main/java/me/retucio/camtweaks/command/CommandManager.java @@ -13,6 +13,8 @@ import java.util.Comparator; // registro de comandos public class CommandManager { + public static CommandManager INSTANCE; + private String prefix = "$"; public static final List commands = new ArrayList<>(); @@ -26,9 +28,12 @@ public class CommandManager { public static void registerCommands() { addCommand(new BindCommand()); - addCommand(new ToggleCommand()); - addCommand(new SendCommand()); +// addCommand(new EnderChestCommand()); no funciona D: + addCommand(new PeekCommand()); addCommand(new PrefixCommand()); + addCommand(new SendCommand()); + addCommand(new ToggleCommand()); + commands.sort(Comparator.comparing(Command::getName)); } @@ -43,9 +48,13 @@ public class CommandManager { } public static Command getCommandByName(String name) { - for (Command command : commands) + for (Command command : commands) { if (command.getName().equals(name)) return command; + for (String alias : command.getAliases()) + if (alias.equals(name)) + return command; + } return null; } diff --git a/src/main/java/me/retucio/camtweaks/command/args/ModuleArgumentType.java b/src/main/java/me/retucio/camtweaks/command/args/ModuleArgumentType.java index 94ef217..8ad1416 100644 --- a/src/main/java/me/retucio/camtweaks/command/args/ModuleArgumentType.java +++ b/src/main/java/me/retucio/camtweaks/command/args/ModuleArgumentType.java @@ -8,34 +8,34 @@ import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.ModuleManager; import net.minecraft.command.CommandSource; import net.minecraft.text.Text; import java.util.Collection; import java.util.concurrent.CompletableFuture; -import static me.retucio.camtweaks.CameraTweaks.moduleManager; - +// para autocompletar nombres de módulos (los espacios se cambian por guiones bajos) public class ModuleArgumentType implements ArgumentType { public static final ModuleArgumentType INSTANCE = new ModuleArgumentType(); private static final DynamicCommandExceptionType unknownModuleE = new DynamicCommandExceptionType( name -> Text.literal("módulo \"" + name + "\" no encontrado")); - private static final Collection examples = moduleManager.getModules() - .stream().limit(3).map(Module::getName).toList(); + private static final Collection examples = ModuleManager.INSTANCE.getModules() + .stream().limit(3).map(module -> module.getName().replace(" ", "_")).toList(); @Override public Module parse(StringReader reader) throws CommandSyntaxException { - String argument = reader.readString(); - Module module = moduleManager.getModuleByName(argument); + String argument = reader.readString().replace("_", " "); + Module module = ModuleManager.INSTANCE.getModuleByName(argument); if (module == null) throw unknownModuleE.create(argument); return module; } @Override public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { - return CommandSource.suggestMatching(moduleManager.getModules().stream().map(Module::getName), builder); + return CommandSource.suggestMatching(ModuleManager.INSTANCE.getModules().stream().map(module -> module.getName().replace(" ", "_")), builder); } @Override diff --git a/src/main/java/me/retucio/camtweaks/command/args/PlayerArgumentType.java b/src/main/java/me/retucio/camtweaks/command/args/PlayerArgumentType.java new file mode 100644 index 0000000..62ad6e8 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/command/args/PlayerArgumentType.java @@ -0,0 +1,60 @@ +package me.retucio.camtweaks.command.args; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import net.minecraft.command.CommandSource; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.text.Text; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import static me.retucio.camtweaks.CameraTweaks.mc; + +// para autocompletar nombres de jugadores +public class PlayerArgumentType implements ArgumentType { + + public static final PlayerArgumentType INSTANCE = new PlayerArgumentType(); + private static final DynamicCommandExceptionType NO_SUCH_PLAYER = new DynamicCommandExceptionType(name -> Text.literal("Player with name " + name + " doesn't exist.")); + + private static final Collection EXAMPLES = List.of("retucio", "prepucio", "postpucio", "pucio", "adler hitdolf"); + + private PlayerArgumentType() {} + + @Override + public PlayerEntity parse(StringReader reader) throws CommandSyntaxException { + String argument = reader.readString(); + PlayerEntity playerEntity = null; + + for (PlayerEntity p : mc.world.getPlayers()) + if (p.getName().getString().equalsIgnoreCase(argument)) { + playerEntity = p; + break; + } + + if (playerEntity == null) throw NO_SUCH_PLAYER.create(argument); + + return playerEntity; + } + + @Override + public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { + return CommandSource.suggestMatching(mc.world.getPlayers().stream().map(abstractClientPlayerEntity -> abstractClientPlayerEntity.getName().getString()), builder); + } + + @Override + public Collection getExamples() { + return EXAMPLES; + } + + public static PlayerEntity get(CommandContext context) { + return context.getArgument("jugador", PlayerEntity.class); + } + +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/command/commands/BindCommand.java b/src/main/java/me/retucio/camtweaks/command/commands/BindCommand.java index 1fe65e4..4e60268 100644 --- a/src/main/java/me/retucio/camtweaks/command/commands/BindCommand.java +++ b/src/main/java/me/retucio/camtweaks/command/commands/BindCommand.java @@ -7,16 +7,13 @@ import me.retucio.camtweaks.module.Module; import me.retucio.camtweaks.module.settings.KeySetting; import me.retucio.camtweaks.util.ChatUtil; import me.retucio.camtweaks.util.KeyUtil; -import net.minecraft.client.MinecraftClient; import net.minecraft.command.CommandSource; import net.minecraft.text.Text; import net.minecraft.util.Formatting; -import static me.retucio.camtweaks.CameraTweaks.moduleManager; - +// asignar una tecla a un módulo, lógica similar a BindButton public class BindCommand extends Command { - // The module currently waiting for a key press private static Module listeningModule = null; public BindCommand() { @@ -29,27 +26,31 @@ public class BindCommand extends Command { .then(argument("módulo", ModuleArgumentType.INSTANCE) .executes(ctx -> { Module module = ctx.getArgument("módulo", Module.class); - listeningModule = module; - - ChatUtil.info("presiona una tecla para asignarla al módulo " + module.getName()); + ChatUtil.info("presiona una tecla para asignarla al módulo " + Formatting.GREEN + module.getName()); return SUCCESS; }) + .then(literal("reset").executes(ctx -> { + Module module = ctx.getArgument("módulo", Module.class); + module.getBind().reset(); + ChatUtil.info("tecla para el módulo " + Formatting.GREEN + module.getName() + " restablecida a " + Formatting.AQUA + KeyUtil.getKeyName(module.getKey())); + return SUCCESS; + })) ); } - public static void onKeyPress(int key) { - if (listeningModule != null) { - KeySetting bind = listeningModule.getBind(); - if (bind != null) - bind.setKey(key); + public static boolean onKeyPress(int key) { + if (listeningModule == null) return false; + KeySetting bind = listeningModule.getBind(); + if (bind != null) + bind.setKey(key); - ChatUtil.info( - Text.of("la tecla " + Formatting.AQUA + KeyUtil.getKeyName(key) + Formatting.RESET + - " ha sido asignada al módulo " + Formatting.GREEN + listeningModule.getName()) - ); + ChatUtil.info( + Text.of("la tecla " + Formatting.AQUA + KeyUtil.getKeyName(key) + Formatting.RESET + + " ha sido asignada al módulo " + Formatting.GREEN + listeningModule.getName()) + ); - listeningModule = null; - } + listeningModule = null; + return true; } } diff --git a/src/main/java/me/retucio/camtweaks/command/commands/EnderChestCommand.java b/src/main/java/me/retucio/camtweaks/command/commands/EnderChestCommand.java new file mode 100644 index 0000000..562ace0 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/command/commands/EnderChestCommand.java @@ -0,0 +1,37 @@ +package me.retucio.camtweaks.command.commands; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import me.retucio.camtweaks.command.Command; +import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; +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.screen.GenericContainerScreenHandler; +import net.minecraft.text.Text; + +// accede a los contenidos de tu enderchest +public class EnderChestCommand extends Command { + + public EnderChestCommand() { + super("echest", "muestra el contenido de tu enderchest", "ec", "enderchest"); + } + + @Override + public void build(LiteralArgumentBuilder builder) { + builder.executes(ctx -> { + mc.execute(() -> { // para evitar llamar setScreen desde el hilo equivocado, que causa crashes + EnderChestInventory enderChestInv = mc.player.getEnderChestInventory(); + + // llámame imbécil pero no tengo ni idea de por qué no se abre + mc.setScreen(new GenericContainerScreen( + GenericContainerScreenHandler.createGeneric9x3(mc.player.currentScreenHandler.syncId + 1, mc.player.getInventory(), enderChestInv), + mc.player.getInventory(), + Text.translatable("container.enderchest") + )); + }); + return SUCCESS; + }); + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/command/commands/PeekCommand.java b/src/main/java/me/retucio/camtweaks/command/commands/PeekCommand.java new file mode 100644 index 0000000..3b8403f --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/command/commands/PeekCommand.java @@ -0,0 +1,26 @@ +package me.retucio.camtweaks.command.commands; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import me.retucio.camtweaks.command.Command; +import me.retucio.camtweaks.command.args.PlayerArgumentType; +import me.retucio.camtweaks.util.MiscUtil; +import net.minecraft.client.gui.screen.ingame.InventoryScreen; +import net.minecraft.command.CommandSource; + +// comando que debería de mostrar el inventario de un jugador, pero por cómo funcionan los servers, solo te deja ver el ítem que tenga en la mano +public class PeekCommand extends Command { + + public PeekCommand() { + super("inventario", "cotillea el inventario de otro jugador", "invsee", "peek", "inv"); + } + + @Override + public void build(LiteralArgumentBuilder builder) { + builder + .then(argument("jugador", PlayerArgumentType.INSTANCE) + .executes(ctx -> { + MiscUtil.screen = new InventoryScreen(PlayerArgumentType.get(ctx)); + return SUCCESS; + })); + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/command/commands/PrefixCommand.java b/src/main/java/me/retucio/camtweaks/command/commands/PrefixCommand.java index 4ea0c09..f310add 100644 --- a/src/main/java/me/retucio/camtweaks/command/commands/PrefixCommand.java +++ b/src/main/java/me/retucio/camtweaks/command/commands/PrefixCommand.java @@ -3,12 +3,13 @@ package me.retucio.camtweaks.command.commands; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import me.retucio.camtweaks.command.Command; -import me.retucio.camtweaks.ui.settings.ClickGUISettingsFrame; +import me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame; import me.retucio.camtweaks.util.ChatUtil; import net.minecraft.command.CommandSource; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +// también se puede hacer desde los ajustes de la interfaz public class PrefixCommand extends Command { public PrefixCommand() { diff --git a/src/main/java/me/retucio/camtweaks/command/commands/SendCommand.java b/src/main/java/me/retucio/camtweaks/command/commands/SendCommand.java index 30c548a..7a86e2c 100644 --- a/src/main/java/me/retucio/camtweaks/command/commands/SendCommand.java +++ b/src/main/java/me/retucio/camtweaks/command/commands/SendCommand.java @@ -3,9 +3,19 @@ package me.retucio.camtweaks.command.commands; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import me.retucio.camtweaks.command.Command; +import me.retucio.camtweaks.mixin.accessor.ClientPlayNetworkHandlerAccessor; +import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.command.CommandSource; +import net.minecraft.network.encryption.NetworkEncryptionUtils; +import net.minecraft.network.message.LastSeenMessagesCollector; +import net.minecraft.network.message.MessageBody; +import net.minecraft.network.message.MessageSignatureData; +import net.minecraft.network.packet.c2s.play.ChatMessageC2SPacket; import net.minecraft.text.Text; +import java.time.Instant; + +// uso principal: protección de coordenadas de ChatPlus, que ni siquiera funciona public class SendCommand extends Command { public SendCommand() { @@ -14,13 +24,35 @@ public class SendCommand extends Command { @Override public void build(LiteralArgumentBuilder builder) { - builder - .then(argument("mensaje", StringArgumentType.greedyString()) - .executes(ctx -> { - if (mc.player == null) return 0; - mc.player.sendMessage(Text.of(ctx.getArgument("mensaje", String.class)), false); - return SUCCESS; - }) - ); + builder.then(argument("message", StringArgumentType.greedyString()).executes(context -> { + String message = context.getArgument("message", String.class); + + if (message != null && !message.isEmpty()) { + Instant instant = Instant.now(); + long salt = NetworkEncryptionUtils.SecureRandomUtil.nextLong(); + ClientPlayNetworkHandler handler = mc.getNetworkHandler(); + + // obtener últimos mensajes vistos para la firma + LastSeenMessagesCollector.LastSeenMessages lastSeenMessages = + ((ClientPlayNetworkHandlerAccessor) handler).getLastSeenMessagesCollector().collect(); + + // empacar firma para un chat seguro + MessageSignatureData messageSignatureData = + ((ClientPlayNetworkHandlerAccessor) handler).getMessagePacker().pack( + new MessageBody(message, instant, salt, lastSeenMessages.lastSeen()) + ); + + // enviar paquete para enviar mensaje + handler.sendPacket(new ChatMessageC2SPacket( + message, + instant, + salt, + messageSignatureData, + lastSeenMessages.update() + )); + } + + return SUCCESS; + })); } -} +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/command/commands/ToggleCommand.java b/src/main/java/me/retucio/camtweaks/command/commands/ToggleCommand.java index 046a114..67a8456 100644 --- a/src/main/java/me/retucio/camtweaks/command/commands/ToggleCommand.java +++ b/src/main/java/me/retucio/camtweaks/command/commands/ToggleCommand.java @@ -4,10 +4,9 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder; import me.retucio.camtweaks.command.Command; import me.retucio.camtweaks.command.args.ModuleArgumentType; import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.ModuleManager; import net.minecraft.command.CommandSource; -import static me.retucio.camtweaks.CameraTweaks.moduleManager; - // porque usar el ratón es más lento que escribir, a menos que tengas toque con el teclado como yo public class ToggleCommand extends Command { @@ -21,14 +20,14 @@ public class ToggleCommand extends Command { .then(literal("todos") .then(literal("on") .executes(ctx -> { - moduleManager.getModules().forEach(module -> { + ModuleManager.INSTANCE.getModules().forEach(module -> { if (!module.isEnabled()) module.toggle(); }); return SUCCESS; }) ) .then(literal("off") .executes(ctx -> { - moduleManager.getEnabledModules().forEach(Module::toggle); + ModuleManager.INSTANCE.getEnabledModules().forEach(Module::toggle); return SUCCESS; }) ) diff --git a/src/main/java/me/retucio/camtweaks/config/ClientConfig.java b/src/main/java/me/retucio/camtweaks/config/ClientConfig.java new file mode 100644 index 0000000..d75d06d --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/config/ClientConfig.java @@ -0,0 +1,109 @@ +package me.retucio.camtweaks.config; + +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.event.events.camtweaks.*; +import me.retucio.camtweaks.module.settings.*; +import me.retucio.camtweaks.ui.ClickGUI; +import me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame; + +import java.util.HashMap; +import java.util.Map; + +import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS; +import static me.retucio.camtweaks.CameraTweaks.mc; + +// clase donde se guardan las configuraciones temporalmente hasta escribirlas en camera_tweaks.json +public class ClientConfig { + + // nombre del módulo -> estado del módulo + public Map moduleStates = new HashMap<>(); + + // nombre del ajuste -> valor + public Map settings = new HashMap<>(); + + // nombre del módulo -> posición (x, y) + public Map settingsFrames = new HashMap<>(); + + // nombre del frame -> FrameData (que contiene extended, x & y) + public Map extendableFrames = new HashMap<>(); + + public ClientConfig() { + EVENT_BUS.register(this); + } + + + @SubscribeEvent + public void onToggleModule(ToggleModuleEvent event) { + ConfigManager.setModuleState(event.getModule()); + } + + @SubscribeEvent + public void onUpdateSetting(UpdateSettingEvent event) { + if (mc == null) return; + + // guardar ajustes con su respectivo tipo de valor, en formato "nombreMódulo:nombreAjuste" + Object value = null; + switch (event.getSetting()) { + case BooleanSetting b: value = b.isEnabled(); break; + case EnumSetting e: value = e.getIndex(); break; + case KeySetting k: value = k.getKey(); break; + case NumberSetting n: value = n.getValue(); break; + case StringSetting s: value = s.getValue(); break; + default: break; + } + + ConfigManager.setSetting(event.getSetting(), value); + } + + @SubscribeEvent + public void onOpenSettingsFrame(SettingsFrameEvent.Open event) { + if (settingsFrames.containsKey(event.getFrame().module.getName())) return; + ConfigManager.setFramePosition(event.getFrame()); + } + + @SubscribeEvent + public void onCloseSettingsFrame(SettingsFrameEvent.Close event) { + settingsFrames.remove(event.getFrame().module.getName()); + ConfigManager.save(); + } + + @SubscribeEvent + public void onMoveSettingsFrame(SettingsFrameEvent.Move event) { + settingsFrames.replace(event.getFrame().module.getName(), new int[]{event.getFrame().x, event.getFrame().y}); + ConfigManager.save(); + } + + @SubscribeEvent + public void onExtendModuleFrame(ModuleFrameEvent.Extend event) { + extendableFrames.put("M", new FrameData( + ClickGUI.INSTANCE.getModulesFrame().x, + ClickGUI.INSTANCE.getModulesFrame().y, + ClickGUI.INSTANCE.getModulesFrame().extended)); + } + + @SubscribeEvent + public void onMoveModuleFrame(ModuleFrameEvent.Move event) { + extendableFrames.replace("M", new FrameData( + ClickGUI.INSTANCE.getModulesFrame().x, + ClickGUI.INSTANCE.getModulesFrame().y, + ClickGUI.INSTANCE.getModulesFrame().extended)); + } + + @SubscribeEvent + public void onExtendGUISettingsFrame(GUISettingsFrameEvent.Extend event) { + extendableFrames.put("S", new FrameData( + ClickGUI.INSTANCE.getGuiSettingsFrame().x, + ClickGUI.INSTANCE.getGuiSettingsFrame().y, + ClickGUI.INSTANCE.getGuiSettingsFrame().extended)); + } + + @SubscribeEvent + public void onMoveGUISettingsFrame(GUISettingsFrameEvent.Move event) { + extendableFrames.replace("S", new FrameData( + ClickGUI.INSTANCE.getGuiSettingsFrame().x, + ClickGUI.INSTANCE.getGuiSettingsFrame().y, + ClickGUI.INSTANCE.getGuiSettingsFrame().extended)); + } + + public record FrameData(int x, int y, boolean extended) {} +} diff --git a/src/main/java/me/retucio/camtweaks/config/ConfigManager.java b/src/main/java/me/retucio/camtweaks/config/ConfigManager.java new file mode 100644 index 0000000..a5fdb87 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/config/ConfigManager.java @@ -0,0 +1,142 @@ +package me.retucio.camtweaks.config; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +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.ClickGUI; +import me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame; +import me.retucio.camtweaks.ui.frames.SettingsFrame; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; + +// se ocupa de guardar, cargar y aplicar ajustes +// pues no me ha dado dolores de cabeza el coso este con los NPE de los cojones... +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 ClientConfig config = null; + + // 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(); + } + } + + // cargar configuraciones + public static void load() { + CameraTweaks.LOGGER.info("ajustes cargados"); + if (!CONFIG_FILE.exists()) { + ensureConfig(); + save(); + return; + } + + try (FileReader reader = new FileReader(CONFIG_FILE)) { + config = GSON.fromJson(reader, ClientConfig.class); + } catch (IOException e) { + e.printStackTrace(); + ensureConfig(); + } + } + + // aplicar configuraciones cargadas + public static void applyConfig() { + if (CameraTweaks.mc == null || ModuleManager.INSTANCE == null || config == null) + 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]); + } + }); + + ClickGUISettingsFrame.guiSettings.setEnabled(true); + ClickGUISettingsFrame.guiSettings.getSettings().forEach(setting -> applySetting(ClickGUISettingsFrame.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"); + } + + public static ClientConfig getConfig() { + return config; + } + + public static void setModuleState(Module module) { + ensureConfig(); + config.moduleStates.put(module.getName(), module.isEnabled()); + save(); + } + + public static void setSetting(Setting setting, Object value) { + ensureConfig(); + config.settings.put(setting.getModule().getName() + ":" + setting.getName(), value); + save(); + } + + public static void setFramePosition(SettingsFrame frame) { + ensureConfig(); + config.settingsFrames.put(frame.module.getName(), new int[]{frame.x, frame.y}); + ConfigManager.save(); + } + + public static void setExtendableFrame(String key, ClientConfig.FrameData data) { + ensureConfig(); + config.extendableFrames.put(key, data); + save(); + } + + public static void applySetting(Module parent, Setting setting) { + String id = parent.getName() + ":" + setting.getName(); + if (config.settings.containsKey(id)) { + Object value = config.settings.get(id); + + 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); + default -> {} + } + } + } + + private static void ensureConfig() { + if (config == null) config = new ClientConfig(); + } +} diff --git a/src/main/java/me/retucio/camtweaks/event/Event.java b/src/main/java/me/retucio/camtweaks/event/Event.java index 0cc1277..ede96df 100644 --- a/src/main/java/me/retucio/camtweaks/event/Event.java +++ b/src/main/java/me/retucio/camtweaks/event/Event.java @@ -1,6 +1,6 @@ package me.retucio.camtweaks.event; -// evento base, cancelable +// evento base, cancelable (usado en mixins) public class Event { private boolean cancelled; diff --git a/src/main/java/me/retucio/camtweaks/event/EventBus.java b/src/main/java/me/retucio/camtweaks/event/EventBus.java index 403b02f..97e3f47 100644 --- a/src/main/java/me/retucio/camtweaks/event/EventBus.java +++ b/src/main/java/me/retucio/camtweaks/event/EventBus.java @@ -1,6 +1,7 @@ package me.retucio.camtweaks.event; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.*; // al llamar un evento, se guarda en el bus de eventos, de donde luego se puede detectar si ese evento ha sucedido @@ -10,28 +11,43 @@ public class EventBus { private record ListenerMethod(Object instance, Method method) {} public void register(Object listener) { - for (Method method : listener.getClass().getDeclaredMethods()) { - if (method.isAnnotationPresent(Subscribe.class)) { - if (method.getParameterCount() != 1) continue; // must take 1 param - Class eventType = method.getParameterTypes()[0]; - method.setAccessible(true); + Class targetClass; - listeners.computeIfAbsent(eventType, k -> new ArrayList<>()) - .add(new ListenerMethod(listener, method)); - } + if (listener instanceof Class clazz) { + targetClass = clazz; // "listeners" estáticos + listener = null; + } else { + targetClass = listener.getClass(); + } + + for (Method method : targetClass.getDeclaredMethods()) { + if (!method.isAnnotationPresent(SubscribeEvent.class)) continue; + if (method.getParameterCount() != 1) continue; + + Class eventType = method.getParameterTypes()[0]; + method.setAccessible(true); + + if (listener == null && !Modifier.isStatic(method.getModifiers())) continue; + + listeners.computeIfAbsent(eventType, k -> new ArrayList<>()) + .add(new ListenerMethod(listener, method)); } } + public void subscribe(Object listener) { register(listener); } + public void unregister(Object listener) { for (List list : listeners.values()) { list.removeIf(lm -> lm.instance == listener); } } + public void unsubscribe(Object listener) { unregister(listener); } + public T post(T event) { List list = listeners.get(event.getClass()); if (list != null) { - for (ListenerMethod lm : list) { + for (ListenerMethod lm : new ArrayList<>(list)) { // copiar para evitar CME try { lm.method.invoke(lm.instance, event); } catch (Exception e) { @@ -52,4 +68,4 @@ public class EventBus { } return false; } -} +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/event/Stage.java b/src/main/java/me/retucio/camtweaks/event/Stage.java new file mode 100644 index 0000000..b69c70a --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/event/Stage.java @@ -0,0 +1,6 @@ +package me.retucio.camtweaks.event; + +public enum Stage { + PRE, // antes de que haya sucedido + POST; // después de que haya sucedido +} diff --git a/src/main/java/me/retucio/camtweaks/event/Subscribe.java b/src/main/java/me/retucio/camtweaks/event/SubscribeEvent.java similarity index 85% rename from src/main/java/me/retucio/camtweaks/event/Subscribe.java rename to src/main/java/me/retucio/camtweaks/event/SubscribeEvent.java index 17dabfb..7c0413f 100644 --- a/src/main/java/me/retucio/camtweaks/event/Subscribe.java +++ b/src/main/java/me/retucio/camtweaks/event/SubscribeEvent.java @@ -5,4 +5,4 @@ import java.lang.annotation.*; // anotación para registar un "listener", que escucha cuando se llama un evento @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) -public @interface Subscribe {} \ No newline at end of file +public @interface SubscribeEvent {} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/event/events/ChunkOcclusionEvent.java b/src/main/java/me/retucio/camtweaks/event/events/ChunkOcclusionEvent.java new file mode 100644 index 0000000..28d8c28 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/event/events/ChunkOcclusionEvent.java @@ -0,0 +1,9 @@ +package me.retucio.camtweaks.event.events; + +import me.retucio.camtweaks.event.Event; + +/** + * @see me.retucio.camtweaks.mixin.ChunkOcclusionDataBuilderMixin#onChunkOcclusion + */ + +public class ChunkOcclusionEvent extends Event {} diff --git a/src/main/java/me/retucio/camtweaks/event/events/ClientClickEvent.java b/src/main/java/me/retucio/camtweaks/event/events/ClientClickEvent.java index fd4028f..9b306b5 100644 --- a/src/main/java/me/retucio/camtweaks/event/events/ClientClickEvent.java +++ b/src/main/java/me/retucio/camtweaks/event/events/ClientClickEvent.java @@ -2,6 +2,10 @@ package me.retucio.camtweaks.event.events; import net.minecraft.text.ClickEvent; +/** este evento es solo para asegurarse de que comandos del mod se puedan ejecutar solo desde el lado del cliente + * @see me.retucio.camtweaks.module.modules.ChatPlus#getSendButton + */ + public class ClientClickEvent implements ClickEvent { private final String value; diff --git a/src/main/java/me/retucio/camtweaks/event/events/DisconnectEvent.java b/src/main/java/me/retucio/camtweaks/event/events/DisconnectEvent.java new file mode 100644 index 0000000..6a1483a --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/event/events/DisconnectEvent.java @@ -0,0 +1,9 @@ +package me.retucio.camtweaks.event.events; + +import me.retucio.camtweaks.event.Event; + +/** + * @see me.retucio.camtweaks.mixin.ClientConnectionMixin#onDisconnect + */ + +public class DisconnectEvent extends Event {} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/event/events/GetFOVEvent.java b/src/main/java/me/retucio/camtweaks/event/events/GetFOVEvent.java index 9fd3b80..4527052 100644 --- a/src/main/java/me/retucio/camtweaks/event/events/GetFOVEvent.java +++ b/src/main/java/me/retucio/camtweaks/event/events/GetFOVEvent.java @@ -2,6 +2,10 @@ package me.retucio.camtweaks.event.events; import me.retucio.camtweaks.event.Event; +/** + * @see me.retucio.camtweaks.mixin.GameRendererMixin#modifyFov + */ + public class GetFOVEvent extends Event { private float fov; diff --git a/src/main/java/me/retucio/camtweaks/event/events/KeyEvent.java b/src/main/java/me/retucio/camtweaks/event/events/KeyEvent.java index 5117c90..5d8c708 100644 --- a/src/main/java/me/retucio/camtweaks/event/events/KeyEvent.java +++ b/src/main/java/me/retucio/camtweaks/event/events/KeyEvent.java @@ -2,7 +2,10 @@ package me.retucio.camtweaks.event.events; import me.retucio.camtweaks.event.Event; -// se genera en KeyboardMixin +/** + * @see me.retucio.camtweaks.mixin.KeyboardMixin#onKeyPress + */ + public class KeyEvent extends Event { private final int key, scancode, action; diff --git a/src/main/java/me/retucio/camtweaks/event/events/MouseClickEvent.java b/src/main/java/me/retucio/camtweaks/event/events/MouseClickEvent.java index 92524fd..ecba0f4 100644 --- a/src/main/java/me/retucio/camtweaks/event/events/MouseClickEvent.java +++ b/src/main/java/me/retucio/camtweaks/event/events/MouseClickEvent.java @@ -2,7 +2,10 @@ package me.retucio.camtweaks.event.events; import me.retucio.camtweaks.event.Event; -// se genera en MouseMixin +/** + * @see me.retucio.camtweaks.mixin.MouseMixin#onMouseButton + */ + public class MouseClickEvent extends Event { private final int action, button; diff --git a/src/main/java/me/retucio/camtweaks/event/events/MouseScrollEvent.java b/src/main/java/me/retucio/camtweaks/event/events/MouseScrollEvent.java index db61a20..17f8d7c 100644 --- a/src/main/java/me/retucio/camtweaks/event/events/MouseScrollEvent.java +++ b/src/main/java/me/retucio/camtweaks/event/events/MouseScrollEvent.java @@ -2,7 +2,10 @@ package me.retucio.camtweaks.event.events; import me.retucio.camtweaks.event.Event; -// se genera en MouseMixin +/** + * @see me.retucio.camtweaks.mixin.MouseMixin#onMouseScroll + */ + public class MouseScrollEvent extends Event { private double horizontal, vertical; diff --git a/src/main/java/me/retucio/camtweaks/event/events/OpenScreenEvent.java b/src/main/java/me/retucio/camtweaks/event/events/OpenScreenEvent.java new file mode 100644 index 0000000..3f51b99 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/event/events/OpenScreenEvent.java @@ -0,0 +1,21 @@ +package me.retucio.camtweaks.event.events; + +import me.retucio.camtweaks.event.Event; +import net.minecraft.client.gui.screen.Screen; + +/** + * @see me.retucio.camtweaks.mixin.MinecraftClientMixin#onOpenScreen + */ + +public class OpenScreenEvent extends Event { + + private final Screen screen; + + public OpenScreenEvent(Screen screen) { + this.screen = screen; + } + + public Screen getScreen() { + return screen; + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/event/events/PacketEvent.java b/src/main/java/me/retucio/camtweaks/event/events/PacketEvent.java new file mode 100644 index 0000000..b46e80c --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/event/events/PacketEvent.java @@ -0,0 +1,46 @@ +package me.retucio.camtweaks.event.events; + +import me.retucio.camtweaks.event.Event; +import me.retucio.camtweaks.event.Stage; +import net.minecraft.network.packet.Packet; + +/** + * @see me.retucio.camtweaks.mixin.ClientConnectionMixin#onSendPacketPre + * @see me.retucio.camtweaks.mixin.ClientConnectionMixin#onSendPacketPost + * @see me.retucio.camtweaks.mixin.ClientConnectionMixin#onReceivePacket + */ + +public class PacketEvent { + + public static class Send extends Event { + + private final Packet packet; + private final Stage stage; + + public Send(Packet packet, Stage stage) { + this.packet = packet; + this.stage = stage; + } + + public Packet getPacket() { + return packet; + } + + public Stage getStage() { + return stage; + } + } + + public static class Receive extends Event { + + private final Packet packet; + + public Receive(Packet packet) { + this.packet = packet; + } + + public Packet getPacket() { + return packet; + } + } +} diff --git a/src/main/java/me/retucio/camtweaks/event/events/PerspectiveChangeEvent.java b/src/main/java/me/retucio/camtweaks/event/events/PerspectiveChangeEvent.java index b9e4283..db4d5ed 100644 --- a/src/main/java/me/retucio/camtweaks/event/events/PerspectiveChangeEvent.java +++ b/src/main/java/me/retucio/camtweaks/event/events/PerspectiveChangeEvent.java @@ -3,7 +3,10 @@ package me.retucio.camtweaks.event.events; import me.retucio.camtweaks.event.Event; import net.minecraft.client.option.Perspective; -// se genera en GameOptionsMixin +/** + * @see me.retucio.camtweaks.mixin.GameOptionsMixin#changePerspective + */ + public class PerspectiveChangeEvent extends Event { private Perspective perspective; diff --git a/src/main/java/me/retucio/camtweaks/event/events/ReceiveMessageEvent.java b/src/main/java/me/retucio/camtweaks/event/events/ReceiveMessageEvent.java index 9a84a4f..0c17879 100644 --- a/src/main/java/me/retucio/camtweaks/event/events/ReceiveMessageEvent.java +++ b/src/main/java/me/retucio/camtweaks/event/events/ReceiveMessageEvent.java @@ -4,6 +4,10 @@ import me.retucio.camtweaks.event.Event; import net.minecraft.client.gui.hud.MessageIndicator; import net.minecraft.text.Text; +/** + * @see me.retucio.camtweaks.mixin.ChatHudMixin#onAddMessage + */ + public class ReceiveMessageEvent extends Event { private Text text; diff --git a/src/main/java/me/retucio/camtweaks/event/events/RenderArmEvent.java b/src/main/java/me/retucio/camtweaks/event/events/RenderArmEvent.java index e9c9ae8..4cfa59b 100644 --- a/src/main/java/me/retucio/camtweaks/event/events/RenderArmEvent.java +++ b/src/main/java/me/retucio/camtweaks/event/events/RenderArmEvent.java @@ -4,6 +4,10 @@ import me.retucio.camtweaks.event.Event; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.Hand; +/** + * @see me.retucio.camtweaks.mixin.HeldItemRendererMixin#onRenderArm + */ + public class RenderArmEvent extends Event { private MatrixStack matrices; diff --git a/src/main/java/me/retucio/camtweaks/event/events/RenderBossbarEvent.java b/src/main/java/me/retucio/camtweaks/event/events/RenderBossbarEvent.java new file mode 100644 index 0000000..51223ad --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/event/events/RenderBossbarEvent.java @@ -0,0 +1,77 @@ +package me.retucio.camtweaks.event.events; + +import me.retucio.camtweaks.event.Event; +import net.minecraft.client.gui.hud.ClientBossBar; +import net.minecraft.text.Text; + +import java.util.Iterator; + +/** + * @see me.retucio.camtweaks.mixin.BossBarHudMixin#modifyBossBarIterator + * @see me.retucio.camtweaks.mixin.BossBarHudMixin#modifyBossBarName + * @see me.retucio.camtweaks.mixin.BossBarHudMixin#modifySpacingConstant + */ + +public class RenderBossbarEvent { + + public static class BossText extends Event { + + private ClientBossBar bossBar; + private Text name; + + public BossText(ClientBossBar bossBar, Text name) { + this.bossBar = bossBar; + this.name = name; + } + + public ClientBossBar getBossBar() { + return bossBar; + } + + public void setBossBar(ClientBossBar bossBar) { + this.bossBar = bossBar; + } + + public Text getName() { + return name; + } + + public void setName(Text name) { + this.name = name; + } + } + + public static class BossSpacing extends Event { + + private int spacing; + + public BossSpacing(int spacing) { + this.spacing = spacing; + } + + public int getSpacing() { + return spacing; + } + + public void setSpacing(int spacing) { + this.spacing = spacing; + } + } + + public static class BossIterator extends Event { + + private Iterator iterator; + + public BossIterator(Iterator iterator) { + this.iterator = iterator; + } + + public Iterator getIterator() { + return iterator; + } + + public void setIterator(Iterator iterator) { + this.iterator = iterator; + } + } +} diff --git a/src/main/java/me/retucio/camtweaks/event/events/RenderEvent.java b/src/main/java/me/retucio/camtweaks/event/events/RenderEvent.java deleted file mode 100644 index bba6f65..0000000 --- a/src/main/java/me/retucio/camtweaks/event/events/RenderEvent.java +++ /dev/null @@ -1,6 +0,0 @@ -package me.retucio.camtweaks.event.events; - -import me.retucio.camtweaks.event.Event; - -public class RenderEvent extends Event { -} diff --git a/src/main/java/me/retucio/camtweaks/event/events/HeldItemRendererEvent.java b/src/main/java/me/retucio/camtweaks/event/events/RenderHeldItemEvent.java similarity index 75% rename from src/main/java/me/retucio/camtweaks/event/events/HeldItemRendererEvent.java rename to src/main/java/me/retucio/camtweaks/event/events/RenderHeldItemEvent.java index 5c467dc..d90543e 100644 --- a/src/main/java/me/retucio/camtweaks/event/events/HeldItemRendererEvent.java +++ b/src/main/java/me/retucio/camtweaks/event/events/RenderHeldItemEvent.java @@ -4,12 +4,16 @@ import me.retucio.camtweaks.event.Event; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.Hand; -public class HeldItemRendererEvent extends Event { +/** + * @see me.retucio.camtweaks.mixin.HeldItemRendererMixin#onRenderItem + */ + +public class RenderHeldItemEvent extends Event { private MatrixStack matrices; private Hand hand; - public HeldItemRendererEvent(MatrixStack matrices, Hand hand) { + public RenderHeldItemEvent(MatrixStack matrices, Hand hand) { this.matrices = matrices; this.hand = hand; } diff --git a/src/main/java/me/retucio/camtweaks/event/events/SendMessageEvent.java b/src/main/java/me/retucio/camtweaks/event/events/SendMessageEvent.java index 0fa6d61..478cc5f 100644 --- a/src/main/java/me/retucio/camtweaks/event/events/SendMessageEvent.java +++ b/src/main/java/me/retucio/camtweaks/event/events/SendMessageEvent.java @@ -2,6 +2,10 @@ package me.retucio.camtweaks.event.events; import me.retucio.camtweaks.event.Event; +/** + * @see me.retucio.camtweaks.mixin.ClientPlayNetworkHandlerMixin#onSendMessage + */ + public class SendMessageEvent extends Event { private String message; diff --git a/src/main/java/me/retucio/camtweaks/event/events/ShutdownEvent.java b/src/main/java/me/retucio/camtweaks/event/events/ShutdownEvent.java new file mode 100644 index 0000000..dc59fc5 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/event/events/ShutdownEvent.java @@ -0,0 +1,12 @@ +package me.retucio.camtweaks.event.events; + +import me.retucio.camtweaks.event.Event; + +/** + * @see me.retucio.camtweaks.mixin.MinecraftClientMixin#onStop + */ + +public class ShutdownEvent extends Event { + + public ShutdownEvent() {} +} diff --git a/src/main/java/me/retucio/camtweaks/event/events/TickEvent.java b/src/main/java/me/retucio/camtweaks/event/events/TickEvent.java new file mode 100644 index 0000000..d056fea --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/event/events/TickEvent.java @@ -0,0 +1,14 @@ +package me.retucio.camtweaks.event.events; + +import me.retucio.camtweaks.event.Event; + +/** + * @see me.retucio.camtweaks.mixin.MinecraftClientMixin#onTickPre + * @see me.retucio.camtweaks.mixin.MinecraftClientMixin#onTickPost + */ + +public class TickEvent { + + public static class Pre extends Event {} + public static class Post extends Event {} +} diff --git a/src/main/java/me/retucio/camtweaks/event/events/camtweaks/GUISettingsFrameEvent.java b/src/main/java/me/retucio/camtweaks/event/events/camtweaks/GUISettingsFrameEvent.java new file mode 100644 index 0000000..f1fdf22 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/event/events/camtweaks/GUISettingsFrameEvent.java @@ -0,0 +1,10 @@ +package me.retucio.camtweaks.event.events.camtweaks; + +import me.retucio.camtweaks.event.Event; + +// se genera cada que se interactúa con el marco de ajustes de la interfaz +public class GUISettingsFrameEvent { + + public static class Extend extends Event {} // al extenderlo / contraerlo + public static class Move extends Event {} // al cambiarlo de posición +} diff --git a/src/main/java/me/retucio/camtweaks/event/events/camtweaks/ModuleFrameEvent.java b/src/main/java/me/retucio/camtweaks/event/events/camtweaks/ModuleFrameEvent.java new file mode 100644 index 0000000..154b341 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/event/events/camtweaks/ModuleFrameEvent.java @@ -0,0 +1,10 @@ +package me.retucio.camtweaks.event.events.camtweaks; + +import me.retucio.camtweaks.event.Event; + +// se genera cada que se interactúa con el marco de módulos +public class ModuleFrameEvent { + + public static class Extend extends Event {} // al extenderlo / contraerlo + public static class Move extends Event {} // al cambiarlo de posición +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/event/events/camtweaks/SettingsFrameEvent.java b/src/main/java/me/retucio/camtweaks/event/events/camtweaks/SettingsFrameEvent.java new file mode 100644 index 0000000..d733660 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/event/events/camtweaks/SettingsFrameEvent.java @@ -0,0 +1,27 @@ +package me.retucio.camtweaks.event.events.camtweaks; + +import me.retucio.camtweaks.event.Event; +import me.retucio.camtweaks.ui.frames.SettingsFrame; + +// se genera cada que se interactúa con un marco de ajustes de un módulo +public class SettingsFrameEvent { + + public static class Open extends Event { // al abrirlo + private final SettingsFrame frame; + public Open(SettingsFrame frame) { this.frame = frame; } + public SettingsFrame getFrame() { return frame; } + } + + public static class Close extends Event { // al cerrarlo + private final SettingsFrame frame; + public Close(SettingsFrame frame) { this.frame = frame; } + public SettingsFrame getFrame() { return frame; } + } + + public static class Move extends Event { // al cambiarlo de posición + private final SettingsFrame frame; + public Move(SettingsFrame frame) { this.frame = frame; } + public SettingsFrame getFrame() { return frame; } + } + +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/event/events/camtweaks/ToggleModuleEvent.java b/src/main/java/me/retucio/camtweaks/event/events/camtweaks/ToggleModuleEvent.java new file mode 100644 index 0000000..8670ba2 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/event/events/camtweaks/ToggleModuleEvent.java @@ -0,0 +1,18 @@ +package me.retucio.camtweaks.event.events.camtweaks; + +import me.retucio.camtweaks.event.Event; +import me.retucio.camtweaks.module.Module; + +// se genera cada que se enciende o apaga un módulo +public class ToggleModuleEvent extends Event { + + private final Module module; + + public ToggleModuleEvent(Module module) { + this.module = module; + } + + public Module getModule() { + return module; + } +} 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 new file mode 100644 index 0000000..3cb82bc --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/event/events/camtweaks/UpdateSettingEvent.java @@ -0,0 +1,18 @@ +package me.retucio.camtweaks.event.events.camtweaks; + +import me.retucio.camtweaks.event.Event; +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 Setting setting; + + public UpdateSettingEvent(Setting setting) { + this.setting = setting; + } + + public Setting getSetting() { + return setting; + } +} diff --git a/src/main/java/me/retucio/camtweaks/mixin/BossBarHudMixin.java b/src/main/java/me/retucio/camtweaks/mixin/BossBarHudMixin.java new file mode 100644 index 0000000..1b909f6 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/BossBarHudMixin.java @@ -0,0 +1,38 @@ +package me.retucio.camtweaks.mixin; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; +import me.retucio.camtweaks.event.events.RenderBossbarEvent; +import net.minecraft.client.gui.hud.BossBarHud; +import net.minecraft.client.gui.hud.ClientBossBar; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyConstant; + +import java.util.Iterator; + +import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS; + +@Mixin(BossBarHud.class) +public class BossBarHudMixin { + + @ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Ljava/util/Collection;iterator()Ljava/util/Iterator;")) + public Iterator modifyBossBarIterator(Iterator original) { + RenderBossbarEvent.BossIterator event = EVENT_BUS.post(new RenderBossbarEvent.BossIterator(original)); + return event.getIterator(); + } + + @ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ClientBossBar;getName()Lnet/minecraft/text/Text;")) + public Text modifyBossBarName(Text original, @Local ClientBossBar clientBossBar) { + RenderBossbarEvent.BossText event = EVENT_BUS.post(new RenderBossbarEvent.BossText(clientBossBar, original)); + return event.getName(); + } + + @ModifyConstant(method = "render", constant = @Constant(intValue = 9, ordinal = 1)) + public int modifySpacingConstant(int constant) { + RenderBossbarEvent.BossSpacing event = EVENT_BUS.post(new RenderBossbarEvent.BossSpacing(constant)); + return event.getSpacing(); + } +} diff --git a/src/main/java/me/retucio/camtweaks/mixin/CameraMixin.java b/src/main/java/me/retucio/camtweaks/mixin/CameraMixin.java index fd50dbb..da6e8dc 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/CameraMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/CameraMixin.java @@ -1,29 +1,94 @@ package me.retucio.camtweaks.mixin; -import me.retucio.camtweaks.CameraTweaks; -import me.retucio.camtweaks.module.modules.Perspective; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.Freelook; +import me.retucio.camtweaks.module.modules.Freecam; +import me.retucio.camtweaks.module.modules.PerspectivePlus; import net.minecraft.client.render.Camera; +import net.minecraft.entity.Entity; +import net.minecraft.world.BlockView; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArgs; import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import static me.retucio.camtweaks.CameraTweaks.moduleManager; +import org.spongepowered.asm.mixin.injection.invoke.arg.Args; @Mixin(Camera.class) public abstract class CameraMixin { + @Unique + private float tickDelta; + + @Unique + PerspectivePlus perspectivePlus; + + @Unique + Freecam freecam; + + @Unique + Freelook freelook; + + @Shadow + private boolean thirdPerson; + + @Inject(method = "", at = @At("TAIL")) + private void getModules(CallbackInfo ci) { + perspectivePlus = ModuleManager.INSTANCE.getModuleByClass(PerspectivePlus.class); + freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); + freelook = ModuleManager.INSTANCE.getModuleByClass(Freelook.class); + } + + @Inject(method = "update", at = @At("HEAD")) + private void onUpdateHead(BlockView area, Entity focusedEntity, boolean thirdPerson, boolean inverseView, float tickDelta, CallbackInfo info) { + this.tickDelta = tickDelta; + } + + + // perspectiva + @ModifyVariable(method = "clipToSpace", at = @At("HEAD"), ordinal = 0, argsOnly = true) private float modifyClipToSpace(float distance) { - Perspective perspective = moduleManager.getModuleByClass(Perspective.class); - return perspective.isEnabled() ? (float) perspective.getDistance() : distance; + if (freecam.isEnabled()) return 0; + return perspectivePlus.isEnabled() ? (float) perspectivePlus.getDistance() : distance; } @Inject(method = "clipToSpace", at = @At("HEAD"), cancellable = true) private void onClipToSpace(float distance, CallbackInfoReturnable cir) { - if (moduleManager.getModuleByClass(Perspective.class).isEnabled() - && moduleManager.getModuleByClass(Perspective.class).clip.isEnabled()) + if (perspectivePlus.isEnabled() && perspectivePlus.clip.isEnabled()) cir.setReturnValue(distance); } -} + + + // cámara libre + + @Inject(method = "update", at = @At("TAIL")) + private void onUpdateTail(BlockView area, Entity focusedEntity, boolean thirdPerson, boolean inverseView, float tickDelta, CallbackInfo info) { + if (freecam.isEnabled()) + this.thirdPerson = true; + } + + @ModifyArgs(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/Camera;setPos(DDD)V")) + private void onUpdateSetPosArgs(Args args) { + if (freecam.isEnabled()) { + args.set(0, freecam.getX(tickDelta)); + args.set(1, freecam.getY(tickDelta)); + args.set(2, freecam.getZ(tickDelta)); + } + } + + @ModifyArgs(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/Camera;setRotation(FF)V")) + private void onUpdateSetRotationArgs(Args args) { + if (freecam.isEnabled()) { + args.set(0, freecam.getYaw(tickDelta)); + args.set(1, freecam.getPitch(tickDelta)); + } else if (freelook.isEnabled()) { + args.set(0, freelook.getYaw()); + args.set(1, freelook.getPitch()); + } + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/ChatHudMixin.java b/src/main/java/me/retucio/camtweaks/mixin/ChatHudMixin.java index 4bfc00c..c831e3a 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/ChatHudMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/ChatHudMixin.java @@ -4,11 +4,13 @@ import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.ModifyReceiver; import com.llamalad7.mixinextras.sugar.Local; import me.retucio.camtweaks.event.events.ReceiveMessageEvent; -import me.retucio.camtweaks.module.modules.BetterChat; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.ChatPlus; import me.retucio.camtweaks.util.interfaces.IChatHud; import me.retucio.camtweaks.util.interfaces.IChatHudLine; import me.retucio.camtweaks.util.interfaces.IChatHudLineVisible; import me.retucio.camtweaks.util.interfaces.IMessageHandler; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.hud.ChatHud; @@ -39,8 +41,8 @@ public abstract class ChatHudMixin implements IChatHud { @Unique private int nextId; - @Unique @Final - private BetterChat betterChat = moduleManager.getModuleByClass(BetterChat.class); + @Unique + ChatPlus chatPlus; @Shadow @Final private List messages; @@ -54,7 +56,10 @@ public abstract class ChatHudMixin implements IChatHud { @Shadow public abstract void addMessage(Text message, @Nullable MessageSignatureData signatureData, @Nullable MessageIndicator indicator); - + @Inject(method = "", at = @At("TAIL")) + private void getModules(MinecraftClient client, CallbackInfo ci) { + chatPlus = ModuleManager.INSTANCE.getModuleByClass(ChatPlus.class); + } // métodos relacionados a las interfaces IChatHud, IChatHudLine, IChadHudLineVisible y IMessageHandler @@ -115,7 +120,7 @@ public abstract class ChatHudMixin implements IChatHud { for (int i = messages.size() - 1; i > -1; i--) { if (((IChatHudLine) (Object) messages.get(i)).smegma$getId() == nextId && nextId != 0) { messages.remove(i); - betterChat.removeLine(i); + chatPlus.removeLine(i); } } @@ -135,18 +140,18 @@ public abstract class ChatHudMixin implements IChatHud { @ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;ceil(F)I")) private int onRender_modifyWidth(int width) { - return (betterChat.isEnabled() && betterChat.showHeads.isEnabled()) ? width + 10 : width; + return (chatPlus.isEnabled() && chatPlus.showHeads.isEnabled()) ? width + 10 : width; } @ModifyReceiver(method = "method_71991", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTextWithShadow(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/OrderedText;III)V")) private DrawContext onRender_beforeDrawTextWithShadow(DrawContext context, TextRenderer textRenderer, OrderedText text, int x, int y, int color, @Local(argsOnly = true) ChatHudLine.Visible line) { - betterChat.beforeDrawMessage(context, line, y, color); + chatPlus.beforeDrawMessage(context, line, y, color); return context; } @Inject(method = "method_71991", at = @At("TAIL")) private void onRender_afterDrawTextWithShadow(int i, DrawContext context, float f, int j, int k, int l, ChatHudLine.Visible visible, int m, float g, CallbackInfo info) { - betterChat.afterDrawMessage(context); + chatPlus.afterDrawMessage(context); } @@ -155,40 +160,39 @@ public abstract class ChatHudMixin implements IChatHud { @ModifyExpressionValue(method = "addMessage(Lnet/minecraft/client/gui/hud/ChatHudLine;)V", at = @At(value = "CONSTANT", args = "intValue=100")) private int maxLength(int size) { - if (!betterChat.isEnabled()) return size; - return size + betterChat.chatHistoryExtraLength.getIntValue(); + if (!chatPlus.isEnabled()) return size; + return size + chatPlus.chatHistoryExtraLength.getIntValue(); } @ModifyExpressionValue(method = "addVisibleMessage", at = @At(value = "CONSTANT", args = "intValue=100")) private int maxLengthVisible(int size) { - if (!betterChat.isEnabled()) return size; - return size + betterChat.chatHistoryExtraLength.getIntValue(); + if (!chatPlus.isEnabled()) return size; + return size + chatPlus.chatHistoryExtraLength.getIntValue(); } @Inject(method = "addVisibleMessage", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;isChatFocused()Z")) private void onBreakChatMessageLines(ChatHudLine message, CallbackInfo ci, @Local List list) { - betterChat.lines.addFirst(list.size()); + chatPlus.lines.addFirst(list.size()); } @Inject(method = "addMessage(Lnet/minecraft/client/gui/hud/ChatHudLine;)V", at = @At(value = "INVOKE", target = "Ljava/util/List;remove(I)Ljava/lang/Object;")) private void onRemoveMessage(ChatHudLine message, CallbackInfo ci) { - int extra = betterChat.chatHistoryExtraLength.getIntValue(); - int size = betterChat.lines.size(); + int extra = chatPlus.chatHistoryExtraLength.getIntValue(); + int size = chatPlus.lines.size(); while (size > 100 + extra) { - betterChat.lines.removeLast(); + chatPlus.lines.removeLast(); size--; } } @Inject(method = "clear", at = @At("HEAD")) private void onClear(boolean clearHistory, CallbackInfo ci) { - betterChat.lines.clear(); + chatPlus.lines.clear(); } @Inject(method = "refresh", at = @At("HEAD")) private void onRefresh(CallbackInfo ci) { - betterChat.lines.clear(); + chatPlus.lines.clear(); } - } \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/ChatInputSuggestorMixin.java b/src/main/java/me/retucio/camtweaks/mixin/ChatInputSuggestorMixin.java index 679bc4b..4dce8d1 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/ChatInputSuggestorMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/ChatInputSuggestorMixin.java @@ -17,7 +17,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.concurrent.CompletableFuture; -import static me.retucio.camtweaks.CameraTweaks.commandManager; import static me.retucio.camtweaks.CameraTweaks.mc; @Mixin(ChatInputSuggestor.class) @@ -42,7 +41,7 @@ public abstract class ChatInputSuggestorMixin { @Inject(method = "refresh", at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/StringReader;canRead()Z", remap = false), cancellable = true) private void onRefresh(CallbackInfo ci, @Local StringReader reader) { - String prefix = commandManager.getPrefix(); + String prefix = CommandManager.INSTANCE.getPrefix(); int length = prefix.length(); if (reader.canRead(length) && reader.getString().startsWith(prefix, reader.getCursor())) { diff --git a/src/main/java/me/retucio/camtweaks/mixin/ChatScreenMixin.java b/src/main/java/me/retucio/camtweaks/mixin/ChatScreenMixin.java index e4a1f0c..9a27213 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/ChatScreenMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/ChatScreenMixin.java @@ -1,6 +1,7 @@ package me.retucio.camtweaks.mixin; -import me.retucio.camtweaks.module.modules.BetterChat; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.ChatPlus; import net.minecraft.client.gui.screen.ChatScreen; import net.minecraft.client.gui.widget.TextFieldWidget; import org.spongepowered.asm.mixin.Mixin; @@ -9,17 +10,15 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import static me.retucio.camtweaks.CameraTweaks.moduleManager; - @Mixin(value = ChatScreen.class, priority = 1001) -public class ChatScreenMixin { +public abstract class ChatScreenMixin { @Shadow protected TextFieldWidget chatField; @Inject(method = "init", at = @At(value = "RETURN")) private void onInit(CallbackInfo info) { - BetterChat betterChat = moduleManager.getModuleByClass(BetterChat.class); - if (betterChat.isEnabled() && betterChat.noCharLimit.isEnabled()) chatField.setMaxLength(Integer.MAX_VALUE); + ChatPlus chatPlus = ModuleManager.INSTANCE.getModuleByClass(ChatPlus.class); + if (chatPlus.isEnabled() && chatPlus.noCharLimit.isEnabled()) chatField.setMaxLength(Integer.MAX_VALUE); } } \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/ChunkBorderDebugRendererMixin.java b/src/main/java/me/retucio/camtweaks/mixin/ChunkBorderDebugRendererMixin.java new file mode 100644 index 0000000..fde5a83 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/ChunkBorderDebugRendererMixin.java @@ -0,0 +1,34 @@ +package me.retucio.camtweaks.mixin; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.Freecam; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.debug.ChunkBorderDebugRenderer; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.ChunkSectionPos; +import net.minecraft.util.math.MathHelper; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ChunkBorderDebugRenderer.class) +public abstract class ChunkBorderDebugRendererMixin { + + @Shadow @Final + private MinecraftClient client; + + @ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getChunkPos()Lnet/minecraft/util/math/ChunkPos;")) + private ChunkPos getChunkPos(ChunkPos chunkPos) { + Freecam freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); + if (!freecam.isEnabled()) return chunkPos; + + float delta = client.getRenderTickCounter().getTickProgress(true); + return new ChunkPos( + ChunkSectionPos.getSectionCoord(MathHelper.floor(freecam.getX(delta))), + ChunkSectionPos.getSectionCoord(MathHelper.floor(freecam.getZ(delta)))); + } +} diff --git a/src/main/java/me/retucio/camtweaks/mixin/ChunkOcclusionDataBuilderMixin.java b/src/main/java/me/retucio/camtweaks/mixin/ChunkOcclusionDataBuilderMixin.java new file mode 100644 index 0000000..32b2c37 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/ChunkOcclusionDataBuilderMixin.java @@ -0,0 +1,21 @@ +package me.retucio.camtweaks.mixin; + +import me.retucio.camtweaks.event.events.ChunkOcclusionEvent; +import net.minecraft.client.render.chunk.ChunkOcclusionDataBuilder; +import net.minecraft.util.math.BlockPos; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS; + +@Mixin(ChunkOcclusionDataBuilder.class) +public abstract class ChunkOcclusionDataBuilderMixin { + + @Inject(method = "markClosed", at = @At("HEAD"), cancellable = true) + private void onChunkOcclusion(BlockPos pos, CallbackInfo ci) { + ChunkOcclusionEvent event = EVENT_BUS.post(new ChunkOcclusionEvent()); + if (event.isCancelled()) ci.cancel(); + } +} diff --git a/src/main/java/me/retucio/camtweaks/mixin/ClientConnectionMixin.java b/src/main/java/me/retucio/camtweaks/mixin/ClientConnectionMixin.java new file mode 100644 index 0000000..fbc8737 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/ClientConnectionMixin.java @@ -0,0 +1,52 @@ +package me.retucio.camtweaks.mixin; + +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import me.retucio.camtweaks.event.Stage; +import me.retucio.camtweaks.event.events.DisconnectEvent; +import me.retucio.camtweaks.event.events.PacketEvent; +import net.minecraft.network.ClientConnection; +import net.minecraft.network.DisconnectionInfo; +import net.minecraft.network.packet.Packet; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS; + +@Mixin(ClientConnection.class) +public abstract class ClientConnectionMixin { + + // mandar paquetes + + @Inject(method = "send(Lnet/minecraft/network/packet/Packet;Lio/netty/channel/ChannelFutureListener;)V", at = @At("HEAD"), cancellable = true) + private void onSendPacketPre(Packet packet, ChannelFutureListener channelFutureListener, CallbackInfo ci) { + PacketEvent.Send event = EVENT_BUS.post(new PacketEvent.Send(packet, Stage.PRE)); + if (event.isCancelled()) ci.cancel(); + } + + @Inject(method = "send(Lnet/minecraft/network/packet/Packet;Lio/netty/channel/ChannelFutureListener;)V", at = @At("TAIL"), cancellable = true) + private void onSendPacketPost(Packet packet, ChannelFutureListener channelFutureListener, CallbackInfo ci) { + PacketEvent.Send event = EVENT_BUS.post(new PacketEvent.Send(packet, Stage.POST)); + if (event.isCancelled()) ci.cancel(); + } + + + // recibir paquetes + + @Inject(method = "channelRead0(Lio/netty/channel/ChannelHandlerContext;Lnet/minecraft/network/packet/Packet;)V", at = @At("HEAD"), cancellable = true) + private void onReceivePacket(ChannelHandlerContext context, Packet packet, CallbackInfo ci) { + PacketEvent.Receive event = EVENT_BUS.post(new PacketEvent.Receive(packet)); + if (event.isCancelled()) ci.cancel(); + } + + + // otros + + @Inject(method = "disconnect(Lnet/minecraft/network/DisconnectionInfo;)V", at = @At("HEAD"), cancellable = true) + private void onDisconnect(DisconnectionInfo disconnectionInfo, CallbackInfo ci) { + DisconnectEvent event = EVENT_BUS.post(new DisconnectEvent()); + if (event.isCancelled()) ci.cancel(); + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/me/retucio/camtweaks/mixin/ClientPlayNetworkHandlerMixin.java index e912bdf..65091b1 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/ClientPlayNetworkHandlerMixin.java @@ -26,7 +26,7 @@ public abstract class ClientPlayNetworkHandlerMixin { @Inject(method = "sendChatMessage", at = @At("HEAD"), cancellable = true) private void onSendMessage(String message, CallbackInfo ci) { if (ignoreChatMessage) return; - if (!message.startsWith(commandManager.getPrefix())) { + if (!message.startsWith(CommandManager.INSTANCE.getPrefix())) { SendMessageEvent event = EVENT_BUS.post(new SendMessageEvent(message)); if (!event.isCancelled()) { ignoreChatMessage = true; @@ -38,7 +38,7 @@ public abstract class ClientPlayNetworkHandlerMixin { }; try { - CommandManager.dispatch(message.substring(commandManager.getPrefix().length())); + CommandManager.dispatch(message.substring(CommandManager.INSTANCE.getPrefix().length())); } catch (CommandSyntaxException e) { ChatUtil.error(e.getMessage()); } diff --git a/src/main/java/me/retucio/camtweaks/mixin/ClientWorldPropertiesMixin.java b/src/main/java/me/retucio/camtweaks/mixin/ClientWorldPropertiesMixin.java new file mode 100644 index 0000000..e897cc2 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/ClientWorldPropertiesMixin.java @@ -0,0 +1,19 @@ +package me.retucio.camtweaks.mixin; + +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.TimeChanger; +import net.minecraft.client.world.ClientWorld; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientWorld.Properties.class) +public abstract class ClientWorldPropertiesMixin { + + @Inject(method = "setTimeOfDay", at = @At("HEAD"), cancellable = true) + private void setTimeOfDay(long time, CallbackInfo ci) { // de no ser por esto, se verían "flashes" del tiempo real en el cielo + TimeChanger timeChanger = ModuleManager.INSTANCE.getModuleByClass(TimeChanger.class); + if (timeChanger.isEnabled() && time != timeChanger.time.getLongValue()) ci.cancel(); + } +} diff --git a/src/main/java/me/retucio/camtweaks/mixin/CompassStateMixin.java b/src/main/java/me/retucio/camtweaks/mixin/CompassStateMixin.java new file mode 100644 index 0000000..94a1a88 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/CompassStateMixin.java @@ -0,0 +1,48 @@ +package me.retucio.camtweaks.mixin; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.Freecam; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.item.property.numeric.CompassState; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import static me.retucio.camtweaks.CameraTweaks.mc; + +@Mixin(CompassState.class) +public abstract class CompassStateMixin { + + @Unique + private static Freecam freecam; + + @Inject(method = "", at = @At("TAIL")) + private void getModules(boolean wobble, CompassState.Target target, CallbackInfo ci) { + freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); + } + + @ModifyExpressionValue(method = "getBodyYaw", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getBodyYaw()F")) + private static float getBodyYaw(float original) { + if (freecam.isEnabled()) return mc.gameRenderer.getCamera().getYaw(); + return original; + } + + @ModifyReturnValue(method = "getAngleTo(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/math/BlockPos;)D", at = @At("RETURN")) + private static double getAngleTo(double original, Entity entity, BlockPos blockPos) { + if (freecam.isEnabled()) { + Vec3d vec3d = Vec3d.ofCenter(blockPos); + Camera camera = mc.gameRenderer.getCamera(); + return Math.atan2(vec3d.getZ() - camera.getPos().z, vec3d.getX() - camera.getPos().x) / (float) (Math.PI * 2); + } + return original; + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/DimensionTypeMixin.java b/src/main/java/me/retucio/camtweaks/mixin/DimensionTypeMixin.java new file mode 100644 index 0000000..8ec5cde --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/DimensionTypeMixin.java @@ -0,0 +1,22 @@ +package me.retucio.camtweaks.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.TimeChanger; +import net.minecraft.world.dimension.DimensionType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import static me.retucio.camtweaks.CameraTweaks.mc; + +@Mixin(DimensionType.class) +public abstract class DimensionTypeMixin { + + @ModifyReturnValue(method = "getMoonPhase", at = @At("RETURN")) + private int overrideMoonPhase(int original) { + TimeChanger timeChanger = ModuleManager.INSTANCE.getModuleByClass(TimeChanger.class); + if (timeChanger.isEnabled() && mc.world != null && !timeChanger.moonPhase.is(TimeChanger.MoonPhases.DEFAULT)) + return timeChanger.getMoonPhase(); + return original; + } +} diff --git a/src/main/java/me/retucio/camtweaks/mixin/EntityMixin.java b/src/main/java/me/retucio/camtweaks/mixin/EntityMixin.java new file mode 100644 index 0000000..6d6e824 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/EntityMixin.java @@ -0,0 +1,126 @@ +package me.retucio.camtweaks.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.Freecam; +import me.retucio.camtweaks.module.modules.Freelook; +import me.retucio.camtweaks.module.modules.Nametags; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.entity.AgeableMobEntityRenderer; +import net.minecraft.entity.*; +import net.minecraft.entity.mob.Monster; +import net.minecraft.entity.passive.PassiveEntity; +import net.minecraft.entity.passive.TameableEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.projectile.PersistentProjectileEntity; +import net.minecraft.entity.projectile.ProjectileEntity; +import net.minecraft.entity.vehicle.VehicleEntity; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import static me.retucio.camtweaks.CameraTweaks.mc; + +@Mixin(Entity.class) +public abstract class EntityMixin { + + @Shadow public int age; + + @Shadow public abstract Text getName(); + + @Shadow @Nullable public abstract Text getCustomName(); + + @Unique + Freecam freecam; + + @Unique + Freelook freelook; + + @Unique + Nametags nametags; + + @SuppressWarnings("rawtypes") + @Inject(method = "", at = @At("TAIL")) + private void getModules(EntityType type, World world, CallbackInfo ci) { + freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); + freelook = ModuleManager.INSTANCE.getModuleByClass(Freelook.class); + nametags = ModuleManager.INSTANCE.getModuleByClass(Nametags.class); + } + + + // cámara libre & perspectiva libre + + @SuppressWarnings("ConstantConditions") + @Inject(method = "changeLookDirection", at = @At("HEAD"), cancellable = true) + private void onChangeLookDirection(double cursorDeltaX, double cursorDeltaY, CallbackInfo ci) { + if ((Object) this != mc.player) return; + + if (freecam.isEnabled()) { + freecam.changeLookDirection(cursorDeltaX * 0.15, cursorDeltaY * 0.15); + ci.cancel(); + + } else if (freelook.isEnabled() && freelook.mode.is(Freelook.CameraMode.CAMERA)) { + freelook.setYaw(freelook.getYaw() + (float) (cursorDeltaX / freelook.mouseSens.getFloatValue())); + freelook.setPitch(freelook.getPitch() + (float) (cursorDeltaY / freelook.mouseSens.getFloatValue())); + + if (Math.abs(freelook.getPitch()) > 90.0F) freelook.setPitch(freelook.getPitch() > 0 ? 90 : -90); + ci.cancel(); + } + } + + + // nametags + + @SuppressWarnings("ConstantConditions") + @ModifyReturnValue(method = "isCustomNameVisible", at = @At("RETURN")) + private boolean renderEntityNametags(boolean original) { + if (!nametags.isEnabled()) return original; + return switch ((Object) this) { + case PlayerEntity player -> nametags.namePlayers.isEnabled(); + case ItemEntity item -> nametags.nameItems.isEnabled(); + case ProjectileEntity projectile -> nametags.nameProjectiles.isEnabled(); + case Monster hostile -> nametags.nameHostileMobs.isEnabled() || original; // monster en vez de HostileEntity para también incluir slimes + case PassiveEntity passive -> nametags.namePassiveMobs.isEnabled() || original; + case VehicleEntity vehicle -> nametags.nameVehicles.isEnabled(); + default -> nametags.nameMiscMobs.isEnabled() || original; + }; + } + + @ModifyReturnValue(method = "getName", at = @At("RETURN")) + private Text showProjectileDamage(Text original) { + if (!nametags.isEnabled() || !nametags.showProjectileDamage.isEnabled()) return original; + + if ((Object) this instanceof PersistentProjectileEntity arrow) { // aunque lo llame "arrow", también cubre flechas espectrales y tridentes + float damage = nametags.getArrowDamage(arrow); + if (damage > 0) return original.copy().append(Text.literal(" (" + damage + ")").formatted(Formatting.RED)); + } + return original; + } + + @SuppressWarnings("ConstantConditions") + @ModifyReturnValue(method = "getCustomName", at = @At("RETURN")) + private Text displayEntityOwner(Text original) { + if (!nametags.isEnabled() || !nametags.petOwner.isEnabled()) return original; + if ((Object) this instanceof TameableEntity entity && entity.getOwnerReference() != null) { + if (original != null) return original.copy().append(" (de " + nametags.getOwnerName(entity.getOwnerReference()) + ")"); + else return Text.of(nametags.getOwnerName(entity.getOwnerReference())); + } + return original; + } + + + @SuppressWarnings("ConstantConditions") + @ModifyReturnValue(method = "getName", at = @At("RETURN")) + private Text showBabies(Text original) { + if (!nametags.isEnabled() || !nametags.distinguishBabies.isEnabled()) return original; + if ((Object) this instanceof LivingEntity entity && entity.isBaby()) return original.copy().append(" (baby)"); + return original; + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/EntityRendererMixin.java b/src/main/java/me/retucio/camtweaks/mixin/EntityRendererMixin.java new file mode 100644 index 0000000..7bfba0e --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/EntityRendererMixin.java @@ -0,0 +1,26 @@ +package me.retucio.camtweaks.mixin; + +import me.retucio.camtweaks.mixin.accessor.EntityRenderStateAccessor; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.Nametags; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.entity.EntityRenderer; +import net.minecraft.client.render.entity.state.EntityRenderState; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(EntityRenderer.class) +public abstract class EntityRendererMixin { + + @Inject(method = "renderLabelIfPresent", at = @At("HEAD")) + private void renderSneakingPlayerNametags(S state, Text text, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) { + Nametags nametags = ModuleManager.INSTANCE.getModuleByClass(Nametags.class); + + if (nametags.isEnabled() && nametags.alwaysVisible.isEnabled()) + ((EntityRenderStateAccessor) state).setSneaking(false); + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/GameOptionsMixin.java b/src/main/java/me/retucio/camtweaks/mixin/GameOptionsMixin.java index 198de98..9515e5b 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/GameOptionsMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/GameOptionsMixin.java @@ -1,10 +1,12 @@ package me.retucio.camtweaks.mixin; -import me.retucio.camtweaks.CameraTweaks; import me.retucio.camtweaks.event.events.PerspectiveChangeEvent; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.Freecam; import net.minecraft.client.option.GameOptions; import net.minecraft.client.option.Perspective; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -14,8 +16,13 @@ import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS; @Mixin(GameOptions.class) public abstract class GameOptionsMixin { + @Shadow + public abstract Perspective getPerspective(); + @Inject(method = "setPerspective", at = @At("HEAD"), cancellable = true) private void changePerspective(Perspective perspective, CallbackInfo ci) { + if (getPerspective() == null) return; + if (ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled()) ci.cancel(); PerspectiveChangeEvent event = EVENT_BUS.post(new PerspectiveChangeEvent(perspective)); if (event.isCancelled()) ci.cancel(); } diff --git a/src/main/java/me/retucio/camtweaks/mixin/GameRendererMixin.java b/src/main/java/me/retucio/camtweaks/mixin/GameRendererMixin.java index 1d63310..278871c 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/GameRendererMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/GameRendererMixin.java @@ -1,14 +1,22 @@ package me.retucio.camtweaks.mixin; import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import me.retucio.camtweaks.CameraTweaks; import me.retucio.camtweaks.event.events.GetFOVEvent; -import me.retucio.camtweaks.event.events.RenderEvent; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.Freecam; +import me.retucio.camtweaks.module.modules.PerspectivePlus; import me.retucio.camtweaks.module.modules.Zoom; +import me.retucio.camtweaks.util.interfaces.IVec3d; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.BufferBuilderStorage; import net.minecraft.client.render.GameRenderer; -import net.minecraft.client.render.RenderTickCounter; +import net.minecraft.client.render.item.HeldItemRenderer; +import net.minecraft.entity.Entity; import org.joml.Matrix4f; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -20,21 +28,79 @@ import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS; public abstract class GameRendererMixin { @Unique - Zoom zoom = CameraTweaks.moduleManager.getModuleByClass(Zoom.class); + boolean freecamDone; + + @Unique + Zoom zoom; + + @Unique + Freecam freecam; + + @Shadow @Final + private MinecraftClient client; + + @Shadow + public abstract void updateCrosshairTarget(float tickDelta); + + @Inject(method = "", at = @At("TAIL")) + private void getModules(MinecraftClient client, HeldItemRenderer firstPersonHeldItemRenderer, BufferBuilderStorage buffers, CallbackInfo ci) { + zoom = ModuleManager.INSTANCE.getModuleByClass(Zoom.class);; + freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); + } @ModifyReturnValue(method = "getFov", at = @At("RETURN")) private float modifyFov(float original) { return EVENT_BUS.post(new GetFOVEvent(original)).getFov(); } -// @Inject(method = "render", at = @At("HEAD")) -// private void onRender(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci) { -// CameraTweaks.INSTANCE.EVENT_BUS.post(new RenderEvent()); -// } + @Inject(method = "updateCrosshairTarget", at = @At("HEAD"), cancellable = true) + private void updateTargetedEntityInvoke(float tickDelta, CallbackInfo ci) { + if ((freecam.isEnabled()) && client.getCameraEntity() != null && !freecamDone) { + ci.cancel(); + + Entity cameraEntity = client.getCameraEntity(); + Vector3d pos = freecam.getPos(); + Vector3d prevPos = freecam.getPrevPos(); + + double x = cameraEntity.getX(); + double y = cameraEntity.getY(); + double z = cameraEntity.getZ(); + double lastX = cameraEntity.lastX; + double lastY = cameraEntity.lastY; + double lastZ = cameraEntity.lastZ; + float yaw = cameraEntity.getYaw(); + float pitch = cameraEntity.getPitch(); + float lastYaw = cameraEntity.lastYaw; + float lastPitch = cameraEntity.lastPitch; + + ((IVec3d) cameraEntity.getPos()).smegma$set(pos.x, pos.y - cameraEntity.getEyeHeight(cameraEntity.getPose()), pos.z); + cameraEntity.lastX = prevPos.x; + cameraEntity.lastY = prevPos.y - cameraEntity.getEyeHeight(cameraEntity.getPose()); + cameraEntity.lastZ = prevPos.z; + cameraEntity.setYaw(freecam.getYaw()); + cameraEntity.setPitch(freecam.getPitch()); + cameraEntity.lastYaw = freecam.getPrevYaw(); + cameraEntity.lastPitch = freecam.getPrevPitch(); + + freecamDone = true; + updateCrosshairTarget(tickDelta); + freecamDone = false; + + ((IVec3d) cameraEntity.getPos()).smegma$set(x, y, z); + cameraEntity.lastX = lastX; + cameraEntity.lastY = lastY; + cameraEntity.lastZ = lastZ; + cameraEntity.setYaw(yaw); + cameraEntity.setPitch(pitch); + cameraEntity.lastYaw = lastYaw; + cameraEntity.lastPitch = lastPitch; + } + } @Inject(method = "renderHand", at = @At("HEAD"), cancellable = true) private void renderHand(float tickProgress, boolean sleeping, Matrix4f positionMatrix, CallbackInfo ci) { - if (zoom.isEnabled() && !zoom.showHands.isEnabled()) + if ((zoom.isEnabled() && !zoom.showHands.isEnabled()) + || (freecam.isEnabled() && !freecam.renderHands.isEnabled())) ci.cancel(); } } diff --git a/src/main/java/me/retucio/camtweaks/mixin/HeldItemRendererMixin.java b/src/main/java/me/retucio/camtweaks/mixin/HeldItemRendererMixin.java index 7c76ad4..fa81d62 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/HeldItemRendererMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/HeldItemRendererMixin.java @@ -1,37 +1,69 @@ package me.retucio.camtweaks.mixin; import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import me.retucio.camtweaks.event.events.HeldItemRendererEvent; +import me.retucio.camtweaks.event.events.RenderHeldItemEvent; import me.retucio.camtweaks.event.events.RenderArmEvent; +import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.modules.HandView; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.item.ItemModelManager; import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.entity.EntityRenderDispatcher; import net.minecraft.client.render.item.HeldItemRenderer; +import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.util.Arm; import net.minecraft.util.Hand; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS; -import static me.retucio.camtweaks.CameraTweaks.moduleManager; +import static me.retucio.camtweaks.CameraTweaks.*; @Mixin(HeldItemRenderer.class) public abstract class HeldItemRendererMixin { @Unique - HandView handView = moduleManager.getModuleByClass(HandView.class); + HandView handView; + + @Shadow + private float equipProgressMainHand; + + @Shadow + private float equipProgressOffHand; + + @Shadow + private ItemStack mainHand; + + @Shadow + private ItemStack offHand; + + @Shadow + protected abstract boolean shouldSkipHandAnimationOnSwap(ItemStack from, ItemStack to); + + @Inject(method = "", at = @At("TAIL")) + private void getModules(MinecraftClient client, EntityRenderDispatcher entityRenderDispatcher, ItemRenderer itemRenderer, ItemModelManager itemModelManager, CallbackInfo ci) { + handView = ModuleManager.INSTANCE.getModuleByClass(HandView.class); + } @Inject(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ItemDisplayContext;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", shift = At.Shift.BEFORE)) private void onRenderItem(AbstractClientPlayerEntity player, float tickDelta, float pitch, Hand hand, float swingProgress, ItemStack item, float equipProgress, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) { - EVENT_BUS.post(new HeldItemRendererEvent(matrices, hand)); + EVENT_BUS.post(new RenderHeldItemEvent(matrices, hand)); } + @Inject(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderArmHoldingItem(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IFFLnet/minecraft/util/Arm;)V")) + private void onRenderArm(AbstractClientPlayerEntity player, float tickDelta, float pitch, Hand hand, float swingProgress, ItemStack item, float equipProgress, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) { + EVENT_BUS.post(new RenderArmEvent(matrices, hand)); + } + + @ModifyReturnValue(method = "shouldSkipHandAnimationOnSwap", at = @At("RETURN")) private boolean modifySkipSwapAnimation(boolean original) { return original || (handView.isEnabled() && handView.skipSwapping.isEnabled()); @@ -42,8 +74,18 @@ public abstract class HeldItemRendererMixin { if (handView.isEnabled() && handView.noFood.isEnabled()) ci.cancel(); } - @Inject(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderArmHoldingItem(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IFFLnet/minecraft/util/Arm;)V")) - private void onRenderArm(AbstractClientPlayerEntity player, float tickDelta, float pitch, Hand hand, float swingProgress, ItemStack item, float equipProgress, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) { - EVENT_BUS.post(new RenderArmEvent(matrices, hand)); + @ModifyArg(method = "updateHeldItems", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;clamp(FFF)F", ordinal = 2), index = 0) + private float modifyEquipProgressMainhand(float value) { + if (mc.player == null) return value; + float progress = mc.player.getAttackCooldownProgress(1); + float modified = handView.isEnabled() && handView.oldAnimations.isEnabled() ? 1 : (float) Math.pow(progress, 3); + + return (shouldSkipHandAnimationOnSwap(mainHand, mc.player.getMainHandStack()) ? modified : 0) - equipProgressMainHand; } -} + + @ModifyArg(method = "updateHeldItems", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;clamp(FFF)F", ordinal = 3), index = 0) + private float modifyEquipProgressOffhand(float value) { + if (mc.player == null) return value; + return (shouldSkipHandAnimationOnSwap(offHand, mc.player.getOffHandStack()) ? 1 : 0) - equipProgressOffHand; + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/InGameHudMixin.java b/src/main/java/me/retucio/camtweaks/mixin/InGameHudMixin.java index 2b044c5..580c07f 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/InGameHudMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/InGameHudMixin.java @@ -1,6 +1,9 @@ package me.retucio.camtweaks.mixin; -import me.retucio.camtweaks.module.modules.BetterChat; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.ChatPlus; +import me.retucio.camtweaks.module.modules.Freecam; import me.retucio.camtweaks.ui.HUD; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.hud.InGameHud; @@ -10,19 +13,22 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import static me.retucio.camtweaks.CameraTweaks.moduleManager; - @Mixin(InGameHud.class) public abstract class InGameHudMixin { - @Inject(method = "render", at = @At("RETURN"), cancellable = true) + @Inject(method = "render", at = @At("RETURN")) private void renderHUD(DrawContext ctx, RenderTickCounter tc, CallbackInfo ci) { HUD.render(ctx, tc); } + @ModifyExpressionValue(method = "renderCrosshair", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/option/Perspective;isFirstPerson()Z")) + private boolean alwaysRenderCrosshairInFreecam(boolean firstPerson) { + return ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled() || firstPerson; + } + @Inject(method = "clear", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;clear(Z)V"), cancellable = true) private void onClear(CallbackInfo ci) { - BetterChat betterChat = moduleManager.getModuleByClass(BetterChat.class); - if (betterChat.isEnabled() && betterChat.logger.isEnabled()) ci.cancel(); + ChatPlus chatPlus = ModuleManager.INSTANCE.getModuleByClass(ChatPlus.class); + if (chatPlus.isEnabled() && chatPlus.keepHistory.isEnabled()) ci.cancel(); } } diff --git a/src/main/java/me/retucio/camtweaks/mixin/ItemEntityMixin.java b/src/main/java/me/retucio/camtweaks/mixin/ItemEntityMixin.java new file mode 100644 index 0000000..53ca637 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/ItemEntityMixin.java @@ -0,0 +1,28 @@ +package me.retucio.camtweaks.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.Nametags; +import net.minecraft.entity.ItemEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ItemEntity.class) +public abstract class ItemEntityMixin { + + @Shadow + public abstract ItemStack getStack(); + + @ModifyReturnValue(method = "getName", at = @At("RETURN")) + private Text showItemCount(Text original) { + Nametags nametags = ModuleManager.INSTANCE.getModuleByClass(Nametags.class); + if (!nametags.isEnabled()) return original; + + int count = this.getStack().getCount(); + if (nametags.countItems.isEnabled() && count > 1) return original.copy().append(" x" + count); + return original; + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/KeyInputMixin.java b/src/main/java/me/retucio/camtweaks/mixin/KeyInputMixin.java new file mode 100644 index 0000000..26ef5c2 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/KeyInputMixin.java @@ -0,0 +1,28 @@ +package me.retucio.camtweaks.mixin; + +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.Freecam; +import net.minecraft.client.input.Input; +import net.minecraft.client.input.KeyboardInput; +import net.minecraft.util.PlayerInput; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(KeyboardInput.class) +public abstract class KeyInputMixin extends Input { + + @Inject(method = "tick", at = @At("TAIL")) + private void isPressed(CallbackInfo ci) { + Freecam freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); + if (freecam.isEnabled() && freecam.stayCrouching.isEnabled() && freecam.isCrouching()) + playerInput = new PlayerInput( + false, false, + false, false, + false, + true, // siempre agachado + false + ); + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/LightmapTextureManagerMixin.java b/src/main/java/me/retucio/camtweaks/mixin/LightmapTextureManagerMixin.java index d4bfddf..c51f13d 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/LightmapTextureManagerMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/LightmapTextureManagerMixin.java @@ -3,8 +3,13 @@ package me.retucio.camtweaks.mixin; import com.llamalad7.mixinextras.sugar.Local; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.textures.GpuTexture; +import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.modules.Fullbright; +import me.retucio.camtweaks.module.modules.PerspectivePlus; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.GameRenderer; import net.minecraft.client.render.LightmapTextureManager; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import net.minecraft.util.math.ColorHelper; import net.minecraft.util.profiler.Profiler; import org.spongepowered.asm.mixin.Final; @@ -15,17 +20,20 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import static me.retucio.camtweaks.CameraTweaks.moduleManager; - @Mixin(LightmapTextureManager.class) public abstract class LightmapTextureManagerMixin { @Unique - Fullbright fullbright = moduleManager.getModuleByClass(Fullbright.class); + Fullbright fullbright; @Shadow @Final private GpuTexture glTexture; + @Inject(method = "", at = @At("TAIL")) + private void getModules(GameRenderer renderer, MinecraftClient client, CallbackInfo ci) { + fullbright = ModuleManager.INSTANCE.getModuleByClass(Fullbright.class); + } + @Inject(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;push(Ljava/lang/String;)V", shift = At.Shift.AFTER), cancellable = true) private void update(float tickProgress, CallbackInfo ci, @Local Profiler profiler) { if (fullbright.isEnabled() && fullbright.mode.is(Fullbright.Modes.GAMMA)) { @@ -34,4 +42,4 @@ public abstract class LightmapTextureManagerMixin { ci.cancel(); } } -} +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/LivingEntityRendererMixin.java b/src/main/java/me/retucio/camtweaks/mixin/LivingEntityRendererMixin.java new file mode 100644 index 0000000..270eb34 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/LivingEntityRendererMixin.java @@ -0,0 +1,18 @@ +package me.retucio.camtweaks.mixin; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.Freecam; +import net.minecraft.client.render.entity.LivingEntityRenderer; +import net.minecraft.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(LivingEntityRenderer.class) +public abstract class LivingEntityRendererMixin { + + @ModifyExpressionValue(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;getCameraEntity()Lnet/minecraft/entity/Entity;")) + private Entity hasLabelGetCameraEntityProxy(Entity cameraEntity) { + return ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled() ? null : cameraEntity; + } +} diff --git a/src/main/java/me/retucio/camtweaks/mixin/MinecraftClientMixin.java b/src/main/java/me/retucio/camtweaks/mixin/MinecraftClientMixin.java index 10887eb..5d0ff78 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/MinecraftClientMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/MinecraftClientMixin.java @@ -1,17 +1,40 @@ package me.retucio.camtweaks.mixin; import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.event.events.OpenScreenEvent; +import me.retucio.camtweaks.event.events.ShutdownEvent; +import me.retucio.camtweaks.event.events.TickEvent; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS; + @Mixin(MinecraftClient.class) public abstract class MinecraftClientMixin { - @Inject(method = "tick", at = @At("HEAD"), cancellable = true) - private void onTick(CallbackInfo ci) { + @Inject(method = "tick", at = @At("HEAD")) + private void onTickPre(CallbackInfo ci) { CameraTweaks.INSTANCE.onTick(); + EVENT_BUS.post(new TickEvent.Pre()); } -} + + @Inject(method = "tick", at = @At("TAIL")) + private void onTickPost(CallbackInfo ci) { + EVENT_BUS.post(new TickEvent.Post()); + } + + @Inject(method = "stop", at = @At("HEAD")) + private void onStop(CallbackInfo ci) { + EVENT_BUS.post(new ShutdownEvent()); + } + + @Inject(method = "setScreen", at = @At("HEAD"), cancellable = true) + private void onOpenScreen(Screen screen, CallbackInfo ci) { + OpenScreenEvent event = EVENT_BUS.post(new OpenScreenEvent(screen)); + if (event.isCancelled()) ci.cancel(); + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/PlayerEntityMixin.java b/src/main/java/me/retucio/camtweaks/mixin/PlayerEntityMixin.java new file mode 100644 index 0000000..bea705b --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/PlayerEntityMixin.java @@ -0,0 +1,40 @@ +package me.retucio.camtweaks.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.Nametags; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(PlayerEntity.class) +public abstract class PlayerEntityMixin extends LivingEntity { + + protected PlayerEntityMixin(EntityType entityType, World world) { + super(entityType, world); + } + + @ModifyReturnValue(method = "getDisplayName", at = @At("RETURN")) + private Text addHealthIndicator(Text original) { + Nametags nametags = ModuleManager.INSTANCE.getModuleByClass(Nametags.class); + if (nametags.isEnabled() && !nametags.namePlayers.isEnabled()) return null; + if (!nametags.isEnabled() || !nametags.health.isEnabled()) return original; + + float health = getHealth(); + Formatting color; + + if (health < 5) color = Formatting.RED; + else if (health < 10) color = Formatting.YELLOW; + else if (health < 15) color = Formatting.GREEN; + else color = Formatting.DARK_GREEN; + + // me gustaría también añadir un modo en el que se renderizan los corazones directamente en la nametag, pero no sé cómo hacer para las imágenes :'( + return original.copy().append(Text.literal(" [" + color + (nametags.healthMode.is(Nametags.HealthMode.HEARTS) + ? String.format("%.2f", health / 2) : (int) health) + Formatting.RESET + "]")); + } // redondear a dos decimales +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/ScreenMixin.java b/src/main/java/me/retucio/camtweaks/mixin/ScreenMixin.java new file mode 100644 index 0000000..d44f5a4 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/ScreenMixin.java @@ -0,0 +1,22 @@ +package me.retucio.camtweaks.mixin; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import me.retucio.camtweaks.command.CommandManager; +import me.retucio.camtweaks.event.events.ClientClickEvent; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.ClickEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Screen.class) +public class ScreenMixin { + + @Inject(method = "handleBasicClickEvent", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;error(Ljava/lang/String;Ljava/lang/Object;)V", remap = false)) + private static void handleClientClickEvents(ClickEvent clickEvent, MinecraftClient client, Screen screen, CallbackInfo ci) throws CommandSyntaxException { + if (clickEvent instanceof ClientClickEvent event && event.getValue().startsWith(CommandManager.INSTANCE.getPrefix())) + CommandManager.dispatch(event.getValue().substring(CommandManager.INSTANCE.getPrefix().length())); + } +} diff --git a/src/main/java/me/retucio/camtweaks/mixin/SkyRendererMixin.java b/src/main/java/me/retucio/camtweaks/mixin/SkyRendererMixin.java new file mode 100644 index 0000000..8510ed3 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/SkyRendererMixin.java @@ -0,0 +1,40 @@ +package me.retucio.camtweaks.mixin; + +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.PerspectivePlus; +import me.retucio.camtweaks.module.modules.TimeChanger; +import net.minecraft.client.render.SkyRendering; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.util.math.MatrixStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(SkyRendering.class) +public abstract class SkyRendererMixin { + + @Unique + TimeChanger timeChanger; + + @Inject(method = "", at = @At("TAIL")) + private void getModules(CallbackInfo ci) { + timeChanger = ModuleManager.INSTANCE.getModuleByClass(TimeChanger.class); + } + + @Inject(method = "renderSun", at = @At("HEAD"), cancellable = true) + private void onRenderSun(float alpha, VertexConsumerProvider vertexConsumers, MatrixStack matrices, CallbackInfo ci) { + if (timeChanger.isEnabled() && !timeChanger.renderSun.isEnabled()) ci.cancel(); + } + + @Inject(method = "renderMoon", at = @At("HEAD"), cancellable = true) + private void onRenderMoon(int phase, float alpha, VertexConsumerProvider vertexConsumers, MatrixStack matrices, CallbackInfo ci) { + if (timeChanger.isEnabled() && !timeChanger.renderMoon.isEnabled()) ci.cancel(); + } + + @Inject(method = "renderStars", at = @At("HEAD"), cancellable = true) + private void onRenderStars(float brightness, MatrixStack matrices, CallbackInfo ci) { + if (timeChanger.isEnabled() && !timeChanger.renderStars.isEnabled()) ci.cancel(); + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/StringHelperMixin.java b/src/main/java/me/retucio/camtweaks/mixin/StringHelperMixin.java index be51ad3..3a130b7 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/StringHelperMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/StringHelperMixin.java @@ -1,18 +1,18 @@ package me.retucio.camtweaks.mixin; -import me.retucio.camtweaks.module.modules.BetterChat; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.ChatPlus; import net.minecraft.util.StringHelper; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyArg; -import static me.retucio.camtweaks.CameraTweaks.moduleManager; - @Mixin(StringHelper.class) public abstract class StringHelperMixin { + @ModifyArg(method = "truncateChat", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/StringHelper;truncate(Ljava/lang/String;IZ)Ljava/lang/String;"), index = 1) - private static int truncate(int maxLength) { - BetterChat betterChat = moduleManager.getModuleByClass(BetterChat.class); - return ((betterChat.isEnabled() && betterChat.noCharLimit.isEnabled()) ? Integer.MAX_VALUE : maxLength); + private static int onTruncate(int maxLength) { + ChatPlus chatPlus = ModuleManager.INSTANCE.getModuleByClass(ChatPlus.class); + return ((chatPlus.isEnabled() && chatPlus.noCharLimit.isEnabled()) ? Integer.MAX_VALUE : maxLength); } } \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/Vec3dMixin.java b/src/main/java/me/retucio/camtweaks/mixin/Vec3dMixin.java new file mode 100644 index 0000000..5549be6 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/Vec3dMixin.java @@ -0,0 +1,39 @@ +package me.retucio.camtweaks.mixin; + +import me.retucio.camtweaks.util.interfaces.IVec3d; +import net.minecraft.util.math.Vec3d; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(Vec3d.class) +public abstract class Vec3dMixin implements IVec3d { + + @Shadow @Final @Mutable + public double x; + + @Shadow @Final @Mutable + public double y; + + @Shadow @Final @Mutable + public double z; + + @Override + public void smegma$set(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public void smegma$setXZ(double x, double z) { + this.x = x; + this.z = z; + } + + @Override + public void smegma$setY(double y) { + this.y = y; + } +} diff --git a/src/main/java/me/retucio/camtweaks/mixin/WorldRendererMixin.java b/src/main/java/me/retucio/camtweaks/mixin/WorldRendererMixin.java new file mode 100644 index 0000000..c62a89f --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/WorldRendererMixin.java @@ -0,0 +1,17 @@ +package me.retucio.camtweaks.mixin; + +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.Freecam; +import net.minecraft.client.render.WorldRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; + +@Mixin(WorldRenderer.class) +public abstract class WorldRendererMixin { + + @ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;setupTerrain(Lnet/minecraft/client/render/Camera;Lnet/minecraft/client/render/Frustum;ZZ)V"), index = 3) + private boolean renderSetupTerrainModifyArg(boolean hasForcedFrustum) { + return ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled() || hasForcedFrustum; + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/accessor/ClientPlayNetworkHandlerAccessor.java b/src/main/java/me/retucio/camtweaks/mixin/accessor/ClientPlayNetworkHandlerAccessor.java new file mode 100644 index 0000000..b01662e --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/accessor/ClientPlayNetworkHandlerAccessor.java @@ -0,0 +1,17 @@ +package me.retucio.camtweaks.mixin.accessor; + +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.message.LastSeenMessagesCollector; +import net.minecraft.network.message.MessageChain; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ClientPlayNetworkHandler.class) +public interface ClientPlayNetworkHandlerAccessor { + + @Accessor("lastSeenMessagesCollector") + LastSeenMessagesCollector getLastSeenMessagesCollector(); + + @Accessor("messagePacker") + MessageChain.Packer getMessagePacker(); +} diff --git a/src/main/java/me/retucio/camtweaks/mixin/accessor/EntityRenderStateAccessor.java b/src/main/java/me/retucio/camtweaks/mixin/accessor/EntityRenderStateAccessor.java new file mode 100644 index 0000000..554ff49 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/accessor/EntityRenderStateAccessor.java @@ -0,0 +1,12 @@ +package me.retucio.camtweaks.mixin.accessor; + +import net.minecraft.client.render.entity.state.EntityRenderState; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(EntityRenderState.class) +public interface EntityRenderStateAccessor { + + @Accessor("sneaking") + void setSneaking(boolean sneaking); +} diff --git a/src/main/java/me/retucio/camtweaks/mixin/accessor/KeyBindingAccessor.java b/src/main/java/me/retucio/camtweaks/mixin/accessor/KeyBindingAccessor.java new file mode 100644 index 0000000..2395094 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/accessor/KeyBindingAccessor.java @@ -0,0 +1,13 @@ +package me.retucio.camtweaks.mixin.accessor; + +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.util.InputUtil; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(KeyBinding.class) +public interface KeyBindingAccessor { + + @Accessor("boundKey") + InputUtil.Key getBoundKey(); +} diff --git a/src/main/java/me/retucio/camtweaks/module/Module.java b/src/main/java/me/retucio/camtweaks/module/Module.java index ccc5792..fcd3248 100644 --- a/src/main/java/me/retucio/camtweaks/module/Module.java +++ b/src/main/java/me/retucio/camtweaks/module/Module.java @@ -1,7 +1,8 @@ package me.retucio.camtweaks.module; import me.retucio.camtweaks.CameraTweaks; -import me.retucio.camtweaks.event.Subscribe; +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; @@ -43,8 +44,11 @@ public class Module { return settings; } - public void addSetting(Setting setting) { + @SuppressWarnings("unchecked") + public S addSetting(Setting setting) { settings.add(setting); + setting.setModule(this); + return (S) setting; // por convenciencia } public void addSettings(Setting... settings) { @@ -57,22 +61,24 @@ public class Module { enabled = !enabled; if (enabled) onEnable(); else onDisable(); + CameraTweaks.EVENT_BUS.post(new ToggleModuleEvent(this)); } public void onEnable() { if (notify.isEnabled()) ChatUtil.info(getName() + " fue activado"); - for (Method method : getClass().getDeclaredMethods()) { - if (method.isAnnotationPresent(Subscribe.class)) { + for (Method method : getClass().getDeclaredMethods()) + if (method.isAnnotationPresent(SubscribeEvent.class)) { CameraTweaks.EVENT_BUS.register(this); break; - } } + CameraTweaks.EVENT_BUS.post(new ToggleModuleEvent(this)); } public void onDisable() { if (notify.isEnabled()) ChatUtil.info(getName() + " fue desactivado"); if (CameraTweaks.EVENT_BUS.isRegistered(this)) CameraTweaks.EVENT_BUS.unregister(this); + CameraTweaks.EVENT_BUS.post(new ToggleModuleEvent(this)); } @@ -80,13 +86,6 @@ public class Module { public void onTick() {} public void onKey(int key, int action) {} - public boolean nullCheck() { - return mc.player == null; - } - public boolean fullNullCheck() { - return mc.player == null || mc.world == null; - } - // getters y setters public String getName() { return name; @@ -106,6 +105,7 @@ public class Module { return enabled; } public void setEnabled(boolean enabled) { + if (this.enabled == enabled) return; // para evitar NPEs al cargar ajustes porque soy imbécil this.enabled = enabled; if (enabled) onEnable(); else onDisable(); @@ -121,7 +121,11 @@ public class Module { public void setKey(int key) { bind.setKey(key); + } + + public void assignKey(int key) { bind.setDefaultKey(key); + bind.setKey(key); } public KeySetting getBind() { @@ -132,6 +136,7 @@ public class Module { HOLD("mantener"), TOGGLE("alternar"); + // ojalá hubiera una manera de evitar repetirse con esto pero no la hay (creo) ... private final String name; KeyModes(String name) { this.name = name; } @Override public String toString() { return name; } diff --git a/src/main/java/me/retucio/camtweaks/module/ModuleManager.java b/src/main/java/me/retucio/camtweaks/module/ModuleManager.java index 598ee24..9ce033e 100644 --- a/src/main/java/me/retucio/camtweaks/module/ModuleManager.java +++ b/src/main/java/me/retucio/camtweaks/module/ModuleManager.java @@ -1,7 +1,7 @@ package me.retucio.camtweaks.module; import me.retucio.camtweaks.event.EventBus; -import me.retucio.camtweaks.event.Subscribe; +import me.retucio.camtweaks.event.SubscribeEvent; import me.retucio.camtweaks.module.modules.*; import java.lang.reflect.Method; @@ -9,9 +9,11 @@ import java.util.ArrayList; import java.util.List; -// donde se regisran los módulos, y los "listeners" de eventos en cada módulo que lo necesite +// donde se registran los módulos, y los "listeners" de eventos en cada módulo que lo necesite public class ModuleManager { + public static ModuleManager INSTANCE; + private final List modules = new ArrayList<>(); private final EventBus eventBus; @@ -20,17 +22,23 @@ public class ModuleManager { addModules(); } + // por order alfabético y todo, flipas private void addModules() { + modules.add(new BossbarStack()); + modules.add(new ChatPlus()); + modules.add(new Freecam()); + modules.add(new Freelook()); modules.add(new Fullbright()); - modules.add(new Zoom()); - modules.add(new Perspective()); modules.add(new HandView()); - modules.add(new BetterChat()); + modules.add(new PerspectivePlus()); + modules.add(new Nametags()); + modules.add(new TimeChanger()); + modules.add(new Zoom()); // registrar los "listeners" necesarios for (Module module : getEnabledModules()) { for (Method method : module.getClass().getDeclaredMethods()) { - if (method.isAnnotationPresent(Subscribe.class)) { + if (method.isAnnotationPresent(SubscribeEvent.class)) { eventBus.register(module); break; } diff --git a/src/main/java/me/retucio/camtweaks/module/modules/BossbarStack.java b/src/main/java/me/retucio/camtweaks/module/modules/BossbarStack.java new file mode 100644 index 0000000..799e162 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/module/modules/BossbarStack.java @@ -0,0 +1,62 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.event.events.RenderBossbarEvent; +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.BooleanSetting; +import me.retucio.camtweaks.module.settings.NumberSetting; +import net.minecraft.client.gui.hud.ClientBossBar; +import net.minecraft.text.Text; + +import java.util.HashMap; +import java.util.Map; +import java.util.WeakHashMap; + +public class BossbarStack extends Module { + + public BooleanSetting stackBars = addSetting(new BooleanSetting("apilar barras", "apilar las bossbars", true)); + public BooleanSetting hideNames = addSetting(new BooleanSetting("esconder nombres", "no renderiza el nombre de los bosses", false)); + public NumberSetting spaceReduction = addSetting(new NumberSetting("reducción de espacio", "cuánto reducir el espacio entre bossbars", + 0, 0, 10, 0.1)); + + private final Map bossBarMap = new WeakHashMap<>(); + + public BossbarStack() { + super("apilar bossbars", "apila bossbars para reducir el espacio que ocupan en pantalla"); + } + + @SubscribeEvent + private void onRenderBossText(RenderBossbarEvent.BossText event) { + if (hideNames.isEnabled()) { + event.setName(Text.empty()); + return; + } else if (bossBarMap.isEmpty() || !stackBars.isEnabled()) return; + + ClientBossBar bar = event.getBossBar(); + Integer amount = bossBarMap.get(bar); + bossBarMap.remove(bar); + + if (amount != null && !hideNames.isEnabled()) + event.setName(event.getName().copy().append(" x" + amount)); + } + + @SubscribeEvent + private void onRenderBossSpacing(RenderBossbarEvent.BossSpacing event) { + event.setSpacing(10 - spaceReduction.getIntValue()); + } + + @SubscribeEvent + private void onRenderBossBars(RenderBossbarEvent.BossIterator event) { + if (stackBars.isEnabled()) { + HashMap chosenBarMap = new HashMap<>(); + event.getIterator().forEachRemaining(bar -> { + String name = bar.getName().getString(); + if (chosenBarMap.containsKey(name)) + bossBarMap.compute(chosenBarMap.get(name), (clientBossBar, integer) -> (integer == null) ? 2 : integer + 1); + else + chosenBarMap.put(name, bar); + }); + event.setIterator(chosenBarMap.values().iterator()); + } + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/module/modules/BetterChat.java b/src/main/java/me/retucio/camtweaks/module/modules/ChatPlus.java similarity index 69% rename from src/main/java/me/retucio/camtweaks/module/modules/BetterChat.java rename to src/main/java/me/retucio/camtweaks/module/modules/ChatPlus.java index 0e212f4..5972950 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/BetterChat.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/ChatPlus.java @@ -5,13 +5,14 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import me.retucio.camtweaks.CameraTweaks; import me.retucio.camtweaks.command.CommandManager; -import me.retucio.camtweaks.event.Subscribe; +import me.retucio.camtweaks.event.SubscribeEvent; import me.retucio.camtweaks.event.events.ClientClickEvent; import me.retucio.camtweaks.event.events.ReceiveMessageEvent; import me.retucio.camtweaks.event.events.SendMessageEvent; import me.retucio.camtweaks.module.Module; import me.retucio.camtweaks.module.settings.BooleanSetting; import me.retucio.camtweaks.module.settings.NumberSetting; +import me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame; import me.retucio.camtweaks.util.ChatUtil; import me.retucio.camtweaks.util.interfaces.IChatHudLine; import me.retucio.camtweaks.util.interfaces.IChatHudLineVisible; @@ -33,59 +34,56 @@ import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; -// continúa en ChatHudMixin, ChatScreenMixin, InGameHudMixin & StringHelperMixin -public class BetterChat extends Module { +/** continúa en: + * @see me.retucio.camtweaks.mixin.ChatHudMixin + * @see me.retucio.camtweaks.mixin.ChatScreenMixin + * @see me.retucio.camtweaks.mixin.InGameHudMixin + * @see me.retucio.camtweaks.mixin.StringHelperMixin + */ + +public class ChatPlus extends Module { // ajustes - public BooleanSetting timestamps = new BooleanSetting("sello de tiempo", "muestra a qué hora se ha enviado un mensaje", false); - public BooleanSetting timestampSecs = new BooleanSetting("mostrar segundos", "muestra segundos también en el sello de tiempo", false); - public BooleanSetting showHeads = new BooleanSetting("cabezas", "muestra la cabeza del jugador junto a su mensaje", true); - public BooleanSetting coordsProtection = new BooleanSetting("proteger coordenadas", "evitar enviar coordenadas por el chat", true); + public BooleanSetting timestamps = addSetting(new BooleanSetting("sello de tiempo", "muestra a qué hora se ha enviado un mensaje", true)); + public BooleanSetting timestampSecs = addSetting(new BooleanSetting("mostrar segundos", "muestra segundos también en el sello de tiempo", false)); + public BooleanSetting showHeads = addSetting(new BooleanSetting("cabezas", "muestra la cabeza del jugador junto a su mensaje", true)); + public BooleanSetting coordsProtection = addSetting(new BooleanSetting("proteger coordenadas", "evitar enviar coordenadas por el chat", true)); - public BooleanSetting keepHistory = new BooleanSetting("no borrar chat", "no borrar el chat tras desconectarse", true); - public BooleanSetting logger = new BooleanSetting("registro", "evita que se borre el chat de un server", true); - public BooleanSetting noCharLimit = new BooleanSetting("quitar límite de caracteres", "te deja escribir mensajes tan largos como desees", false); - public NumberSetting chatHistoryExtraLength = new NumberSetting("expandir chat", "cuántas líneas añadir al historial del chat", - 0, 0, 1000, 1); + public BooleanSetting keepHistory = addSetting(new BooleanSetting("no borrar chat", "no borrar el chat tras desconectarse", true)); + public BooleanSetting logger = addSetting(new BooleanSetting("registro", "evita que se borre el chat de un server", true)); + public BooleanSetting noCharLimit = addSetting(new BooleanSetting("quitar límite de caracteres", "te deja escribir mensajes tan largos como desees", false)); + public NumberSetting chatHistoryExtraLength = addSetting(new NumberSetting("expandir chat", "cuántas líneas añadir al historial del chat", + 0, 0, 1000, 1)); - public BetterChat() { + public ChatPlus() { super("chat plus", "mejoras para el chat"); - addSettings(timestamps, timestampSecs, showHeads, coordsProtection, keepHistory, logger, noCharLimit, chatHistoryExtraLength); - updateDateFormat(); - timestamps.onUpdate(b -> timestampSecs.setVisible(b)); + updateClientName(); + timestamps.onUpdate(v -> timestampSecs.setVisible(v)); timestampSecs.onUpdate(x -> updateDateFormat()); } public final IntList lines = new IntArrayList(); - private static final Pattern antiClearRegex = Pattern.compile("\\n(\\n|\\s)+\\n"); - private static final Pattern usernameRegex = Pattern.compile("^(?:<[0-9]{2}:[0-9]{2}>\\s)?<(.*?)>.*"); - private record CustomHeadEntry(String prefix, Identifier texture) {} private static final List CUSTOM_HEAD_ENTRIES = new ArrayList<>(); - private static final Pattern TIMESTAMP_REGEX = Pattern.compile("^<\\d{1,2}:\\d{1,2}>"); - private SimpleDateFormat dateFormat; - private void updateDateFormat() { - dateFormat = new SimpleDateFormat(timestampSecs.isEnabled() ? "HH:mm:ss" : "HH:mm"); - } + 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 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*)?)"); - private boolean containsCoordinates(String message) { - return coordRegex.matcher(message).find(); - } - @Subscribe + @SubscribeEvent public void onReceiveMessage(ReceiveMessageEvent event) { Text message = event.getMessage(); // registrar mensajes para evitar su eliminación if (logger.isEnabled()) { String messageString = message.getString(); - if (antiClearRegex.matcher(messageString).find()) { + if (loggerRegex.matcher(messageString).find()) { MutableText newMessage = Text.empty(); TextVisitor.visit(message, (text, style, string) -> { - Matcher antiClearMatcher = antiClearRegex.matcher(string); + Matcher antiClearMatcher = loggerRegex.matcher(string); if (antiClearMatcher.find()) newMessage.append(Text.literal(antiClearMatcher.replaceAll("\n\n")).setStyle(style)); else @@ -107,25 +105,23 @@ public class BetterChat extends Module { event.setMessage(message); } - @Subscribe + @SubscribeEvent private void onSendMessage(SendMessageEvent event) { - String message = event.getMessage(); - // evitar mandar coordenadas por el chat - if (coordsProtection.isEnabled() && containsCoordinates(message)) { + if (coordsProtection.isEnabled() && containsCoordinates(event.getMessage())) { ChatUtil.warn(Text.literal("cuidadito con las coordenadas chavalín").append( - getSendButton(message))); + getSendButton(event.getMessage()))); event.cancel(); - return; } - event.setMessage(message); } - static { - CUSTOM_HEAD_ENTRIES.add(new CustomHeadEntry("smegma", Identifier.of(CameraTweaks.MOD_ID, "icon_chat.png"))); + public void updateClientName() { + CUSTOM_HEAD_ENTRIES.add(new CustomHeadEntry(ChatUtil.getPrefixNoFormatting(), Identifier.of(CameraTweaks.MOD_ID, "icon_chat.png"))); // no funciona con formato de colores + CUSTOM_HEAD_ENTRIES.add(new CustomHeadEntry("[Debug]", Identifier.of(CameraTweaks.MOD_ID, "icon_mc.png"))); } + @SuppressWarnings("DataFlowIssue") public void beforeDrawMessage(DrawContext context, ChatHudLine.Visible line, int y, int color) { if (!isEnabled() || !showHeads.isEnabled()) return; @@ -143,6 +139,7 @@ public class BetterChat extends Module { context.getMatrices().popMatrix(); } + @SuppressWarnings("DataFlowIssue") private void drawTexture(DrawContext context, IChatHudLine line, int y, int color) { String text = line.smegma$getText().trim(); @@ -150,13 +147,13 @@ public class BetterChat extends Module { // buscar el sello del tiempo si lo hay para dibujar la cabeza correctamente try { - Matcher m = TIMESTAMP_REGEX.matcher(text); + Matcher m = timestampRegex.matcher(text); if (m.find()) startOffset = m.end() + 1; } catch (IllegalStateException ignored) {} // dibujar el icono del mod for (CustomHeadEntry entry : CUSTOM_HEAD_ENTRIES) { - if (text.startsWith(entry.prefix(), startOffset)) { + if (text.startsWith(entry.prefix().trim(), startOffset)) { context.drawTexture(RenderPipelines.GUI_TEXTURED, entry.texture(), 0, y, 0, 0, 8, 8, 64, 64, 64, 64, color); return; } @@ -172,8 +169,9 @@ public class BetterChat extends Module { PlayerSkinDrawer.draw(context, entry.getSkinTextures(), 0, y, 8); } - // obtener el jugador que envió un mensaje + @SuppressWarnings("DataFlowIssue") private GameProfile getSender(IChatHudLine line, String text) { + // obtener el jugador que envió un mensaje GameProfile sender = line.smegma$getSender(); if (sender == null) { @@ -189,9 +187,10 @@ public class BetterChat extends Module { return sender; } - // botón para enviar mensaje con coordenadas de todos modos + @SuppressWarnings("DataFlowIssue") private MutableText getSendButton(String message) { - MutableText sendButton = Text.literal("[ME LA SUDA]"); + // botón para enviar mensaje con coordenadas de todos modos + MutableText sendButton = Text.literal("\n[ME LA SUDA]"); MutableText hintBaseText = Text.literal(""); MutableText hintMsg = Text.literal("enviar de todos modos:"); @@ -211,4 +210,12 @@ public class BetterChat extends Module { public void removeLine(int index) { lines.removeInt(index); } + + private void updateDateFormat() { + dateFormat = new SimpleDateFormat(timestampSecs.isEnabled() ? "HH:mm:ss" : "HH:mm"); + } + + private boolean containsCoordinates(String message) { + return coordRegex.matcher(message).find(); + } } \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/module/modules/Freecam.java b/src/main/java/me/retucio/camtweaks/module/modules/Freecam.java new file mode 100644 index 0000000..9b5388c --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/module/modules/Freecam.java @@ -0,0 +1,372 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.event.events.*; +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.BooleanSetting; +import me.retucio.camtweaks.module.settings.NumberSetting; +import me.retucio.camtweaks.util.ChatUtil; +import me.retucio.camtweaks.util.KeyUtil; +import me.retucio.camtweaks.util.MiscUtil; +import net.minecraft.client.option.Perspective; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerInteractItemC2SPacket; +import net.minecraft.network.packet.s2c.play.DeathMessageS2CPacket; +import net.minecraft.network.packet.s2c.play.HealthUpdateS2CPacket; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import org.joml.Vector3d; +import org.lwjgl.glfw.GLFW; + +/** continúa en: + * @see me.retucio.camtweaks.mixin.CameraMixin + * @see me.retucio.camtweaks.mixin.ChunkBorderDebugRendererMixin + * @see me.retucio.camtweaks.mixin.CompassStateMixin + * @see me.retucio.camtweaks.mixin.EntityMixin + * @see me.retucio.camtweaks.mixin.GameRendererMixin + * @see me.retucio.camtweaks.mixin.KeyInputMixin + * @see me.retucio.camtweaks.mixin.LivingEntityRendererMixin + * @see me.retucio.camtweaks.mixin.WorldRendererMixin + */ + +public class Freecam extends Module { + + // ajustes + + public BooleanSetting toggleOnDamage = addSetting(new BooleanSetting("desactivar al recibir daño", "desactiva el módulo tras recibir daño", true)); + public BooleanSetting reloadChunks = addSetting(new BooleanSetting("recargar chunks", "recargar chunks para arreglar el culling de las cuevas", true)); + public BooleanSetting renderHands = addSetting(new BooleanSetting("manos visibles", "decide si se renderizan las manos mientras la cámara esté libre", true)); + public BooleanSetting stayCrouching = addSetting(new BooleanSetting("mantenerse agachado", "mantener al jugador agachado tras entrar en el modo de cámara libre", false)); + public BooleanSetting staticView = addSetting(new BooleanSetting("visión estática", "desactiva ajustes que muevan la cámara", true)); + public BooleanSetting cancelActionPackets = addSetting(new BooleanSetting("cancelar paquetes", "evita flaggear el anticheat al interactuar con bloques / entidades", true)); + + public NumberSetting speedSetting = addSetting(new NumberSetting( + "velocidad", "velocidad de movimiento de la cámara", + 1, 0, 10, 0.2)); + public NumberSetting scrollSens = addSetting(new NumberSetting( + "sensibilidad del scroll", "sensibilidad de la rueda del ratón para modificar la velocidad, 0 para desactivar", + 0, 0, 2, 0.1)); + + + // rotate? + + private final Vector3d prevPos = new Vector3d(); + private float prevYaw, prevPitch; + + private final Vector3d pos = new Vector3d(); + private Perspective perspective; + private double fovScale, speed; + private boolean forward, backward, right, left, up, down, crouching, viewBobbing; + private float yaw, pitch; + + public Freecam() { + super("cámara libre", "perrmite a la cámara moverse independientemente del jugador. útil para explorar alrededores"); + assignKey(GLFW.GLFW_KEY_V); + speedSetting.onUpdate(newSpeed -> speed = newSpeed); + } + + @Override + public void onEnable() { + if (mc.player == null || mc.options == null) return; + + fovScale = mc.options.getFovEffectScale().getValue(); + viewBobbing = mc.options.getBobView().getValue(); + + if (staticView.isEnabled()) { + mc.options.getFovEffectScale().setValue(0D); + mc.options.getBobView().setValue(false); + } + + yaw = mc.player.getYaw(); + pitch = mc.player.getPitch(); + perspective = mc.options.getPerspective(); + + speed = speedSetting.getValue(); + + MiscUtil.copyVector(pos, mc.gameRenderer.getCamera().getCameraPos()); + MiscUtil.copyVector(prevPos, mc.gameRenderer.getCamera().getCameraPos()); + + if (mc.options.getPerspective() == Perspective.THIRD_PERSON_FRONT) { + yaw += 180; + pitch *= -1; + } + + prevYaw = yaw; + prevPitch = pitch; + + crouching = mc.options.sneakKey.isPressed(); + + forward = KeyUtil.isKeyDown(mc.options.forwardKey); + backward = KeyUtil.isKeyDown(mc.options.backKey); + right = KeyUtil.isKeyDown(mc.options.rightKey); + left = KeyUtil.isKeyDown(mc.options.leftKey); + up = KeyUtil.isKeyDown(mc.options.jumpKey); + down = KeyUtil.isKeyDown(mc.options.sneakKey); + + unpress(); + if (reloadChunks.isEnabled()) mc.worldRenderer.reload(); + super.onEnable(); + } + + @Override + public void onDisable() { + if (reloadChunks.isEnabled()) mc.execute(mc.worldRenderer::reload); + + mc.options.setPerspective(perspective); + crouching = false; + + if (staticView.isEnabled()) { + mc.options.getFovEffectScale().setValue(fovScale); + mc.options.getBobView().setValue(viewBobbing); + } + + // para no flaggear el anticheat, cancelar cualquier acción dejada a medias estando en modo libre + if (cancelActionPackets.isEnabled()) { + if (mc.interactionManager != null) + mc.interactionManager.cancelBlockBreaking(); + + if (mc.options != null) { + mc.options.attackKey.setPressed(false); + mc.options.useKey.setPressed(false); + } + } + + super.onDisable(); + } + + @Override + public void onTick() { + if (mc.cameraEntity == null || perspective == null) return; + + mc.cameraEntity.noClip = mc.cameraEntity.isInsideWall(); + if (!perspective.isFirstPerson()) mc.options.setPerspective(Perspective.FIRST_PERSON); + + Vec3d forward = Vec3d.fromPolar(0, yaw); + Vec3d right = Vec3d.fromPolar(0, yaw + 90); + double dx = 0, dy = 0, dz = 0; + + double speedMultiplier = speed * (KeyUtil.isKeyDown(mc.options.sprintKey) ? 1 : 0.5); + + boolean zMovement = false; + if (this.forward) { + dx += forward.x * speedMultiplier; + dz += forward.z * speedMultiplier; + zMovement = true; + } if (this.backward) { + dx -= forward.x * speedMultiplier; + dz -= forward.z * speedMultiplier; + zMovement = true; + } + + boolean xMovement = false; + if (this.right) { + dx += right.x * speedMultiplier; + dz += right.z * speedMultiplier; + xMovement = true; + } if (this.left) { + dx -= right.x * speedMultiplier; + dz -= right.z * speedMultiplier; + xMovement = true; + } + + if (xMovement && zMovement) { // movimiento diagonal, teorema de Pitágoras + dx /= Math.sqrt(2); + dz /= Math.sqrt(2); + } + + if (this.up) dy += speedMultiplier; + if (this.down) dy -= speedMultiplier; + + prevPos.set(pos); + pos.set(pos.x + dx, pos.y + dy, pos.z + dz); + } + + @SubscribeEvent + public void onPacketSend(PacketEvent.Send event) { + if (!isEnabled() || !cancelActionPackets.isEnabled()) return; + + Packet p = event.getPacket(); + if (p instanceof PlayerActionC2SPacket + || p instanceof PlayerInteractBlockC2SPacket + || p instanceof PlayerInteractItemC2SPacket + || p instanceof HandSwingC2SPacket) { + event.cancel(); + } + } + + @SubscribeEvent + public void onKey(KeyEvent event) { + if (mc.currentScreen != null) return; + if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_F3)) return; // ? + + boolean shouldCancel = true; + if (mc.options.forwardKey.matchesKey(event.getKey(), event.getScancode())) { + forward = event.getAction() != GLFW.GLFW_RELEASE; + mc.options.forwardKey.setPressed(false); + } else if (mc.options.backKey.matchesKey(event.getKey(), event.getScancode())) { + backward = event.getAction() != GLFW.GLFW_RELEASE; + mc.options.backKey.setPressed(false); + } else if (mc.options.rightKey.matchesKey(event.getKey(), event.getScancode())) { + right = event.getAction() != GLFW.GLFW_RELEASE; + mc.options.rightKey.setPressed(false); + } else if (mc.options.leftKey.matchesKey(event.getKey(), event.getScancode())) { + left = event.getAction() != GLFW.GLFW_RELEASE; + mc.options.leftKey.setPressed(false); + } else if (mc.options.jumpKey.matchesKey(event.getKey(), event.getScancode())) { + up = event.getAction() != GLFW.GLFW_RELEASE; + mc.options.jumpKey.setPressed(false); + } else if (mc.options.sneakKey.matchesKey(event.getKey(), event.getScancode())) { + down = event.getAction() != GLFW.GLFW_RELEASE; + mc.options.sneakKey.setPressed(false); + } else { + shouldCancel = false; + } + + if (shouldCancel) event.cancel(); + } + + @SubscribeEvent + public void onMouseClick(MouseClickEvent event) { // por si el restrasado del usuario usa el ratón para moverse + if (mc.currentScreen != null) return; + + boolean shouldCancel = true; + if (mc.options.forwardKey.matchesKey(event.getButton(), 0)) { + forward = event.getAction() != GLFW.GLFW_RELEASE; + mc.options.forwardKey.setPressed(false); + } else if (mc.options.backKey.matchesKey(event.getButton(), 0)) { + backward = event.getAction() != GLFW.GLFW_RELEASE; + mc.options.backKey.setPressed(false); + } else if (mc.options.rightKey.matchesKey(event.getButton(), 0)) { + right = event.getAction() != GLFW.GLFW_RELEASE; + mc.options.rightKey.setPressed(false); + } else if (mc.options.leftKey.matchesKey(event.getButton(), 0)) { + left = event.getAction() != GLFW.GLFW_RELEASE; + mc.options.leftKey.setPressed(false); + } else if (mc.options.jumpKey.matchesKey(event.getButton(), 0)) { + up = event.getAction() != GLFW.GLFW_RELEASE; + mc.options.jumpKey.setPressed(false); + } else if (mc.options.sneakKey.matchesKey(event.getButton(), 0)) { + down = event.getAction() != GLFW.GLFW_RELEASE; + mc.options.sneakKey.setPressed(false); + } else { + shouldCancel = false; + } + + if (shouldCancel) event.cancel(); + } + + @SubscribeEvent + private void onMouseScroll(MouseScrollEvent event) { + if (scrollSens.getValue() > 0 && mc.currentScreen == null) { + speed += event.getVertical() / 4 * (scrollSens.getValue() * speed); + if (speed < 0.1) speed = 0.1; + event.cancel(); + } + } + + @SubscribeEvent + private void onChunkOcclusion(ChunkOcclusionEvent event) { + event.cancel(); + } + + @SubscribeEvent + public void onLeaveGame(DisconnectEvent event) { + toggle(); + } + + @SubscribeEvent + public void onPacketReceive(PacketEvent.Receive event) { + if (mc.player == null) return; // el jugador probablemente nunca sea nulo bajo estas circunstancias pero quién sabe + + if (event.getPacket() instanceof DeathMessageS2CPacket packet) { + if (mc.player.getId() == packet.playerId()) + toggle(); + } else if (event.getPacket() instanceof HealthUpdateS2CPacket packet) { + if (mc.player.getHealth() - packet.getHealth() > 0 && toggleOnDamage.isEnabled()) { + ChatUtil.info("cámara libre se ha desactivado porque has recibido daño"); + toggle(); + } + } + } + + @SubscribeEvent + public void onOpenScreen(OpenScreenEvent event) { + unpress(); + prevPos.set(pos); + prevYaw = yaw; + prevPitch = pitch; + } + + public void changeLookDirection(double deltaX, double deltaY) { + prevYaw = yaw; + prevPitch = pitch; + + yaw += (float) deltaX; + pitch += (float) deltaY; + + pitch = MathHelper.clamp(pitch, -90, 90); + } + + private void unpress() { + mc.options.forwardKey.setPressed(false); + mc.options.backKey.setPressed(false); + mc.options.rightKey.setPressed(false); + mc.options.leftKey.setPressed(false); + mc.options.jumpKey.setPressed(false); + mc.options.sneakKey.setPressed(false); + } + + + // getters + + public Vector3d getPos() { + return pos; + } + + public Vector3d getPrevPos() { + return prevPos; + } + + public float getYaw() { + return yaw; + } + + public float getYaw(float tickDelta) { + return MathHelper.lerp(tickDelta, prevYaw, yaw); + } + + public float getPitch() { + return pitch; + } + + public float getPitch(float tickDelta) { + return MathHelper.lerp(tickDelta, prevPitch, pitch); + } + + public float getPrevYaw() { + return prevYaw; + } + + public float getPrevPitch() { + return prevPitch; + } + + public double getX(float tickDelta) { + return MathHelper.lerp(tickDelta, prevPos.x, pos.x); + } + + public double getY(float tickDelta) { + return MathHelper.lerp(tickDelta, prevPos.y, pos.y); + } + + public double getZ(float tickDelta) { + return MathHelper.lerp(tickDelta, prevPos.z, pos.z); + } + + public boolean isCrouching() { + return crouching; + } +} diff --git a/src/main/java/me/retucio/camtweaks/module/modules/Freelook.java b/src/main/java/me/retucio/camtweaks/module/modules/Freelook.java new file mode 100644 index 0000000..51fceb4 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/module/modules/Freelook.java @@ -0,0 +1,115 @@ +package me.retucio.camtweaks.module.modules; + +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.KeyUtil; +import net.minecraft.client.option.Perspective; +import net.minecraft.util.math.MathHelper; +import org.lwjgl.glfw.GLFW; + +/** continúa en: + * @see me.retucio.camtweaks.mixin.CameraMixin + * @see me.retucio.camtweaks.mixin.EntityMixin + */ + +public class Freelook extends Module { + + public EnumSetting mode = addSetting(new EnumSetting<>("cámara a mover", "elige cual cámara mover con el ratón y cuál se queda estática", + CameraMode.class, CameraMode.CAMERA)); + + public NumberSetting arrowSens = addSetting(new NumberSetting("sensibilidad de las flechas", "cuánto rotan la cámara estática las flechas (0 para desactivar)", + 4, 0, 10, 0.1)); + + public NumberSetting mouseSens = addSetting(new NumberSetting("sensibilidad del ratón", ".", + 8, 0, 10, 0.1)); + + private float yaw; + private float pitch; + private Perspective prevPerspective; + + public Freelook() { + super("perspectiva libre", "te permite mover la cámara de la perspectiva sin mover la del jugador, o vice versa"); + assignKey(GLFW.GLFW_KEY_B); + keyMode.setValue(KeyModes.HOLD); + notify.setEnabled(false); + } + + @Override + public void onEnable() { + if (mc.player == null) return; + + yaw = mc.player.getYaw(); + pitch = mc.player.getPitch(); + + prevPerspective = mc.options.getPerspective(); + if (prevPerspective != Perspective.THIRD_PERSON_BACK) + mc.options.setPerspective(Perspective.THIRD_PERSON_BACK); + + super.onEnable(); + } + + @Override + public void onDisable() { + if (mc.options.getPerspective() != prevPerspective) + mc.options.setPerspective(prevPerspective); + super.onDisable(); + } + + @Override + public void onTick() { + if (mc.player == null) return; + + if (arrowSens.getValue() > 0) { + for (int i = 0; i < (arrowSens.getValue() * 2); i++) { + switch (mode.getValue()) { + case PLAYER -> { + if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT)) yaw -= 0.5f; + if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_RIGHT)) yaw += 0.5f; + if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_UP)) pitch -= 0.5f; + if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_DOWN)) pitch += 0.5f; + } case CAMERA -> { + float yaw = mc.player.getYaw(); + float pitch = mc.player.getPitch(); + + if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT)) yaw -= 0.5f; + if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_RIGHT)) yaw += 0.5f; + if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_UP)) pitch -= 0.5f; + if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_DOWN)) pitch += 0.5f; + + mc.player.setYaw(yaw); + mc.player.setPitch(pitch); + } + } + } + } + + mc.player.setPitch(MathHelper.clamp(mc.player.getPitch(), -90, 90)); + pitch = MathHelper.clamp(pitch, -90, 90); + } + + public float getYaw() { + return yaw; + } + + public void setYaw(float yaw) { + this.yaw = yaw; + } + + public float getPitch() { + return pitch; + } + + public void setPitch(float pitch) { + this.pitch = pitch; + } + + public enum CameraMode { + PLAYER("jugador"), + CAMERA("cámara"); + + private final String name; + CameraMode(String name) { this.name = name; } + @Override public String toString() { return name; } + } +} diff --git a/src/main/java/me/retucio/camtweaks/module/modules/Fullbright.java b/src/main/java/me/retucio/camtweaks/module/modules/Fullbright.java index 02122fa..a178e1e 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/Fullbright.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/Fullbright.java @@ -8,22 +8,24 @@ import net.minecraft.entity.effect.StatusEffects; import net.minecraft.registry.Registries; import org.lwjgl.glfw.GLFW; -// continúa en LightmapTextureManagerMixin +/** continúa en: + * @see me.retucio.camtweaks.mixin.LightmapTextureManagerMixin + */ + public class Fullbright extends Module { - public EnumSetting mode = new EnumSetting<>("modo", "qué modo de iluminación emplear (usar poción con shaders)", Modes.class, Modes.GAMMA); + public EnumSetting mode = addSetting(new EnumSetting<>("modo", "qué modo de iluminación emplear (usar poción con shaders)", Modes.class, Modes.GAMMA)); public Fullbright() { - super("brilli-brilli", "deshabilita la oscuridad"); - setKey(GLFW.GLFW_KEY_B); - addSetting(mode); - + super("brilli brilli", "deshabilita la oscuridad"); + assignKey(GLFW.GLFW_KEY_K); mode.onUpdate(mode -> { if (mode != Modes.POTION) disableNightVision(); }); } @Override public void onDisable() { disableNightVision(); + super.onDisable(); } @Override diff --git a/src/main/java/me/retucio/camtweaks/module/modules/GUI.java b/src/main/java/me/retucio/camtweaks/module/modules/GUI.java index 97263e3..0802379 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/GUI.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/GUI.java @@ -1,41 +1,53 @@ package me.retucio.camtweaks.module.modules; +import me.retucio.camtweaks.command.CommandManager; import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.settings.BooleanSetting; import me.retucio.camtweaks.module.settings.NumberSetting; import me.retucio.camtweaks.module.settings.StringSetting; +import me.retucio.camtweaks.util.ChatUtil; import me.retucio.camtweaks.util.Colors; import org.lwjgl.glfw.GLFW; import java.awt.*; -import static me.retucio.camtweaks.CameraTweaks.commandManager; import static me.retucio.camtweaks.util.Colors.*; +// módulo no visible solo para los ajustes de la interfaz (y del cliente en general) public class GUI extends Module { - public NumberSetting red = new NumberSetting("rojo", "cantidad de rojo en el RGB del marco", 0, 0, 255, 1); - public NumberSetting green = new NumberSetting("verde", "cantidad de verde en el RGB del marco", 0, 0, 255, 1); - public NumberSetting blue = new NumberSetting("azul", "cantidad de azul en el RGB del marco", 255, 0, 255, 1); - public NumberSetting alpha = new NumberSetting("alpha", "opacidad del marco", 180, 0, 255, 1); + public NumberSetting red = addSetting(new NumberSetting("rojo", "cantidad de rojo en el RGB del marco", 0, 0, 255, 1)); + public NumberSetting green = addSetting(new NumberSetting("verde", "cantidad de verde en el RGB del marco", 0, 0, 255, 1)); + public NumberSetting blue = addSetting(new NumberSetting("azul", "cantidad de azul en el RGB del marco", 255, 0, 255, 1)); + public NumberSetting alpha = addSetting(new NumberSetting("alpha", "opacidad del marco", 180, 0, 255, 1)); - public NumberSetting scrollSens = new NumberSetting("sensibilidad del scroll", "qué tan sensible es la interfaz a la rueda del ratón", - 5, 0, 15, 0.5); + public NumberSetting scrollSens = addSetting(new NumberSetting("sensibilidad del scroll", "qué tan sensible es la interfaz a la rueda del ratón", + 5, 0, 15, 0.5)); - public StringSetting commandPrefix = new StringSetting("prefijo", "prefijo de los comandos", commandManager.getPrefix(), 10); + public StringSetting commandPrefix = addSetting(new StringSetting("prefijo", "prefijo de los comandos", "$", 10)); + public StringSetting chatName = addSetting(new StringSetting("nombre", "qué nombre usar en notificaciones por el chat", "smegma", 20)); + + public BooleanSetting multipleKeybinds = addSetting(new BooleanSetting("teclas multimódulo", "permitir asignar la misma tecla a más de un módulo", false)); public GUI() { super("interfaz", "ajustes de la interfaz, y otros misceláneos"); - addSettings(red, green, blue, alpha, scrollSens, commandPrefix); - setKey(GLFW.GLFW_KEY_RIGHT_SHIFT); - + assignKey(GLFW.GLFW_KEY_RIGHT_SHIFT); keyMode.setVisible(false); notify.setVisible(false); - commandPrefix.onUpdate(prefix -> commandManager.setPrefix(prefix)); + commandPrefix.onUpdate(prefix -> CommandManager.INSTANCE.setPrefix(prefix)); red.onUpdate(r -> {frameHeadRed = r.intValue(); updateFrameHeadColor();}); green.onUpdate(g -> {frameHeadGreen = g.intValue(); updateFrameHeadColor();}); blue.onUpdate(b -> {frameHeadBlue = b.intValue(); updateFrameHeadColor();}); alpha.onUpdate(a -> {frameHeadAlpha = a.intValue(); updateFrameHeadColor();}); + + if (mc != null) mc.execute(() -> commandPrefix.setDefaultValue(CommandManager.INSTANCE.getPrefix())); + + chatName.onUpdate(name -> { + ChatUtil.updatePrefix(name); + ModuleManager.INSTANCE.getModuleByClass(ChatPlus.class).updateClientName(); + }); } private void updateFrameHeadColor() { diff --git a/src/main/java/me/retucio/camtweaks/module/modules/HandView.java b/src/main/java/me/retucio/camtweaks/module/modules/HandView.java index f8ddd66..0b00eb5 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/HandView.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/HandView.java @@ -1,7 +1,7 @@ package me.retucio.camtweaks.module.modules; -import me.retucio.camtweaks.event.Subscribe; -import me.retucio.camtweaks.event.events.HeldItemRendererEvent; +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.event.events.RenderHeldItemEvent; import me.retucio.camtweaks.event.events.RenderArmEvent; import me.retucio.camtweaks.module.Module; import me.retucio.camtweaks.module.settings.BooleanSetting; @@ -10,99 +10,90 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.Hand; import net.minecraft.util.math.RotationAxis; import org.joml.Vector3d; -import org.lwjgl.glfw.GLFW; + +/** continúa en: + * @see me.retucio.camtweaks.mixin.HeldItemRendererMixin + */ public class HandView extends Module { // ajustes de animaciones - public BooleanSetting oldAnimations = new BooleanSetting("animaciones viejas", "como las de la 1.8, al pegar", false); - public BooleanSetting skipSwapping = new BooleanSetting("no swap", "se salta la animación de cambiar items de mano", false); - public BooleanSetting noFood = new BooleanSetting("no comer", "no renderiza la animación de comer", false); + public BooleanSetting oldAnimations = addSetting(new BooleanSetting("animaciones viejas", "como las de la 1.8, al pegar", false)); + public BooleanSetting skipSwapping = addSetting(new BooleanSetting("no swap", "se salta la animación de cambiar items de mano", false)); + public BooleanSetting noFood = addSetting(new BooleanSetting("no comer", "no renderiza la animación de comer", false)); // ajustes de mano principal - public NumberSetting scaleMainX = new NumberSetting("escala de la mano principal (X)", ".", - 1, 0.01, 5, 0.1); - public NumberSetting scaleMainY = new NumberSetting("escala de la mano principal (Y)", ".", - 1, 0.01, 5, 0.1); - public NumberSetting scaleMainZ = new NumberSetting("escala de la mano principal (Z)", ".", - 1, 0.01, 5, 0.1); + public NumberSetting scaleMainX = addSetting(new NumberSetting("escala de la mano principal (X)", ".", + 1, 0.01, 5, 0.1)); + public NumberSetting scaleMainY = addSetting(new NumberSetting("escala de la mano principal (Y)", ".", + 1, 0.01, 5, 0.1)); + public NumberSetting scaleMainZ = addSetting(new NumberSetting("escala de la mano principal (Z)", ".", + 1, 0.01, 5, 0.1)); - public NumberSetting posMainX = new NumberSetting("posición de la mano principal (X)", ".", - 0, -3, 3, 0.1); - public NumberSetting posMainY = new NumberSetting("posición de la mano principal (Y)", ".", - 0, -3, 3, 0.1); - public NumberSetting posMainZ = new NumberSetting("posición de la mano principal (Z)", ".", - 0, -3, 3, 0.1); + public NumberSetting posMainX = addSetting(new NumberSetting("posición de la mano principal (X)", ".", + 0, -3, 3, 0.1)); + public NumberSetting posMainY = addSetting(new NumberSetting("posición de la mano principal (Y)", ".", + 0, -3, 3, 0.1)); + public NumberSetting posMainZ = addSetting(new NumberSetting("posición de la mano principal (Z)", ".", + 0, -3, 3, 0.1)); - public NumberSetting rotMainX = new NumberSetting("rotación de la mano principal (X)", ".", - 0, -180, 180, 1); - public NumberSetting rotMainY = new NumberSetting("rotación de la mano principal (Y)", ".", - 0, -180, 180, 1); - public NumberSetting rotMainZ = new NumberSetting("rotación de la mano principal (Z)", ".", - 0, -180, 180, 1); + public NumberSetting rotMainX = addSetting(new NumberSetting("rotación de la mano principal (X)", ".", + 0, -180, 180, 1)); + public NumberSetting rotMainY = addSetting(new NumberSetting("rotación de la mano principal (Y)", ".", + 0, -180, 180, 1)); + public NumberSetting rotMainZ = addSetting(new NumberSetting("rotación de la mano principal (Z)", ".", + 0, -180, 180, 1)); // ajustes de mano secundaria - public NumberSetting scaleOffX = new NumberSetting("escala de la mano secundaria (X)", ".", - 1, 0.01, 5, 0.1); - public NumberSetting scaleOffY = new NumberSetting("escala de la mano secundaria (Y)", ".", - 1, 0.01, 5, 0.1); - public NumberSetting scaleOffZ = new NumberSetting("escala de la mano secundaria (Z)", ".", - 1, 0.01, 5, 0.1); + public NumberSetting scaleOffX = addSetting(new NumberSetting("escala de la mano secundaria (X)", ".", + 1, 0.01, 5, 0.1)); + public NumberSetting scaleOffY = addSetting(new NumberSetting("escala de la mano secundaria (Y)", ".", + 1, 0.01, 5, 0.1)); + public NumberSetting scaleOffZ = addSetting(new NumberSetting("escala de la mano secundaria (Z)", ".", + 1, 0.01, 5, 0.1)); - public NumberSetting posOffX = new NumberSetting("posición de la mano secundaria (X)", ".", - 0, -3, 3, 0.1); - public NumberSetting posOffY = new NumberSetting("posición de la mano secundaria (Y)", ".", - 0, -3, 3, 0.1); - public NumberSetting posOffZ = new NumberSetting("posición de la mano secundaria (Z)", ".", - 0, -3, 3, 0.1); + public NumberSetting posOffX = addSetting(new NumberSetting("posición de la mano secundaria (X)", ".", + 0, -3, 3, 0.1)); + public NumberSetting posOffY = addSetting(new NumberSetting("posición de la mano secundaria (Y)", ".", + 0, -3, 3, 0.1)); + public NumberSetting posOffZ = addSetting(new NumberSetting("posición de la mano secundaria (Z)", ".", + 0, -3, 3, 0.1)); - public NumberSetting rotOffX = new NumberSetting("rotación de la mano secundaria (X)", ".", - 0, -180, 180, 1); - public NumberSetting rotOffY = new NumberSetting("rotación de la mano secundaria (Y)", ".", - 0, -180, 180, 1); - public NumberSetting rotOffZ = new NumberSetting("rotación de la mano secundaria (Z)", ".", - 0, -180, 180, 1); + public NumberSetting rotOffX = addSetting(new NumberSetting("rotación de la mano secundaria (X)", ".", + 0, -180, 180, 1)); + public NumberSetting rotOffY = addSetting(new NumberSetting("rotación de la mano secundaria (Y)", ".", + 0, -180, 180, 1)); + public NumberSetting rotOffZ = addSetting(new NumberSetting("rotación de la mano secundaria (Z)", ".", + 0, -180, 180, 1)); // brazo - public NumberSetting scaleArmX = new NumberSetting("escala del brazo (X)", ".", - 1, 0.01, 5, 0.1); - public NumberSetting scaleArmY = new NumberSetting("escala del brazo (Y)", ".", - 1, 0.01, 5, 0.1); - public NumberSetting scaleArmZ = new NumberSetting("escala del brazo (Z)", ".", - 1, 0.01, 5, 0.1); + public NumberSetting scaleArmX = addSetting(new NumberSetting("escala del brazo (X)", ".", + 1, 0.01, 5, 0.1)); + public NumberSetting scaleArmY = addSetting(new NumberSetting("escala del brazo (Y)", ".", + 1, 0.01, 5, 0.1)); + public NumberSetting scaleArmZ = addSetting(new NumberSetting("escala del brazo (Z)", ".", + 1, 0.01, 5, 0.1)); - public NumberSetting posArmX = new NumberSetting("posición del brazo (X)", ".", - 0, -3, 3, 0.1); - public NumberSetting posArmY = new NumberSetting("posición del brazo (Y)", ".", - 0, -3, 3, 0.1); - public NumberSetting posArmZ = new NumberSetting("posición del brazo (Z)", ".", - 0, -3, 3, 0.1); + public NumberSetting posArmX = addSetting(new NumberSetting("posición del brazo (X)", ".", + 0, -3, 3, 0.1)); + public NumberSetting posArmY = addSetting(new NumberSetting("posición del brazo (Y)", ".", + 0, -3, 3, 0.1)); + public NumberSetting posArmZ = addSetting(new NumberSetting("posición del brazo (Z)", ".", + 0, -3, 3, 0.1)); - public NumberSetting rotArmX = new NumberSetting("rotación del brazo (X)", ".", - 0, -180, 180, 1); - public NumberSetting rotArmY = new NumberSetting("rotación del brazo (Y)", ".", - 0, -180, 180, 1); - public NumberSetting rotArmZ = new NumberSetting("rotación del brazo (Z)", ".", - 0, -180, 180, 1); + public NumberSetting rotArmX = addSetting(new NumberSetting("rotación del brazo (X)", ".", + 0, -180, 180, 1)); + public NumberSetting rotArmY = addSetting(new NumberSetting("rotación del brazo (Y)", ".", + 0, -180, 180, 1)); + public NumberSetting rotArmZ = addSetting(new NumberSetting("rotación del brazo (Z)", ".", + 0, -180, 180, 1)); public HandView() { super("manos", "modifica la manera en la que se renderizan las manos"); - addSettings( - oldAnimations, skipSwapping, noFood, - scaleMainX, scaleMainY, scaleMainZ, - posMainX, posMainY, posMainZ, - rotMainX, rotMainY, rotMainZ, - scaleOffX, scaleOffY, scaleOffZ, - posOffX, posOffY, posOffZ, - rotOffX, rotOffY, rotOffZ, - scaleArmX, scaleArmY, scaleArmZ, - posArmX, posArmY, posArmZ, - rotArmX, rotArmY, rotArmZ); - setKey(GLFW.GLFW_KEY_UNKNOWN); } - @Subscribe - public void onHeldItemRender(HeldItemRendererEvent event) { + @SubscribeEvent + public void onHeldItemRender(RenderHeldItemEvent event) { if (event.getHand() == Hand.MAIN_HAND) { scale(event.getMatrices(), new Vector3d(scaleMainX.getValue(), scaleMainY.getValue(), scaleMainZ.getValue())); translate(event.getMatrices(), new Vector3d(posMainX.getValue(), posMainY.getValue(), posMainZ.getValue())); @@ -115,7 +106,7 @@ public class HandView extends Module { } } - @Subscribe + @SubscribeEvent public void onRenderArm(RenderArmEvent event) { scale(event.getMatrices(), new Vector3d(scaleArmX.getValue(), scaleArmY.getValue(), scaleArmZ.getValue())); translate(event.getMatrices(), new Vector3d(posArmX.getValue(), posArmY.getValue(), posArmZ.getValue())); diff --git a/src/main/java/me/retucio/camtweaks/module/modules/Nametags.java b/src/main/java/me/retucio/camtweaks/module/modules/Nametags.java new file mode 100644 index 0000000..c2fc563 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/module/modules/Nametags.java @@ -0,0 +1,144 @@ +package me.retucio.camtweaks.module.modules; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.BooleanSetting; +import me.retucio.camtweaks.module.settings.EnumSetting; +import me.retucio.camtweaks.util.ChatUtil; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.LazyEntityReference; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.projectile.PersistentProjectileEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.MathHelper; +import org.jetbrains.annotations.Nullable; + +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URL; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** continúa en: + * @see me.retucio.camtweaks.mixin.EntityMixin + * @see me.retucio.camtweaks.mixin.ItemEntityMixin + * @see me.retucio.camtweaks.mixin.PlayerEntityMixin + */ + +public class Nametags extends Module { + + public BooleanSetting namePlayers = addSetting(new BooleanSetting("nombrar jugadores", "renderiza el nametag de jugadores", true)); + public BooleanSetting health = addSetting(new BooleanSetting("mostrar vida", "muestra la vida de una entidad en su nametag", true)); + public EnumSetting healthMode = addSetting(new EnumSetting<>("mostrar vida en", "de qué manera mostrar la vida", HealthMode.class, HealthMode.POINTS)); + public BooleanSetting alwaysVisible = addSetting(new BooleanSetting("siempre mostrar nametags", "mostrar nametags cuando no deberían de ser visibles", false)); + + public BooleanSetting namePassiveMobs = addSetting(new BooleanSetting("nombrar mobs pasivos", "renderiza el nametag de mobs pasivos", false)); + public BooleanSetting nameHostileMobs = addSetting(new BooleanSetting("nombrar mobs hostiles", "renderiza el nametag de mobs hostiles", false)); + public BooleanSetting nameMiscMobs = addSetting(new BooleanSetting("nombrar mobs neutrales", "renderiza el nametag de mobs neutrales", false)); + public BooleanSetting distinguishBabies = addSetting(new BooleanSetting("distinguir bebés", "cambia el nametag cuando una entidad está en su fase bebé", false)); + + public BooleanSetting nameProjectiles = addSetting(new BooleanSetting("nombrar proyectiles", "renderiza el nametag de proyectiles", false)); + public BooleanSetting showProjectileDamage = addSetting(new BooleanSetting("daño del proyectil", "muestra cuánto daño hace un proyectil en su nametag", false)); + + public BooleanSetting nameItems = addSetting(new BooleanSetting("nombrar items", "renderiza el nametag de items", true)); + public BooleanSetting countItems = addSetting(new BooleanSetting("contar items", "muestra cuánto de un item hay en un stack dropeado", true)); + + public BooleanSetting nameVehicles = addSetting(new BooleanSetting("nombrar vehículos", "renderiza el nametag de botes, minecarts, ...", false)); + public BooleanSetting showPassengers = addSetting(new BooleanSetting("mostrar pasajeros", "muestra qué pasajeros tiene el vehículo", false)); + + public BooleanSetting petOwner = addSetting(new BooleanSetting("mostrar dueño", "muestra el dueño de una mascota (no funciona en servers no premium)", false)); + + private final Map cache = new ConcurrentHashMap<>(); + private static final ExecutorService executor = Executors.newCachedThreadPool(); + + public Nametags() { + super("nametags", "modifica la manera en la que se renderizan los nametags"); + + nameProjectiles.onUpdate(v -> showProjectileDamage.setVisible(v)); + nameItems.onUpdate(v -> countItems.setVisible(v)); + nameVehicles.onUpdate(v -> showPassengers.setVisible(v)); + + namePassiveMobs.onUpdate(v -> distinguishBabies.setVisible(v || nameMiscMobs.isEnabled() || nameHostileMobs.isEnabled())); + nameMiscMobs.onUpdate(v -> distinguishBabies.setVisible(v || namePassiveMobs.isEnabled() || nameHostileMobs.isEnabled())); + nameHostileMobs.onUpdate(v -> distinguishBabies.setVisible(v || nameMiscMobs.isEnabled() || namePassiveMobs.isEnabled())); + + health.onUpdate(v -> healthMode.setVisible(v)); + } + + public enum HealthMode { + POINTS("hp (puntos de vida)"), + HEARTS("corazones"); + + private final String name; + HealthMode(String name) { this.name = name; } + @Override public String toString() { return name; } + } + + // literalmente cómo lo calcula Minecraft + public float getArrowDamage(PersistentProjectileEntity arrow) { + if (mc.player == null) return 0; + + double initialDamage = 2; + double velocity = arrow.getVelocity().length(); + DamageSource damageSource = arrow.getDamageSources().arrow(arrow, arrow.getOwner()); + + if (arrow.getWeaponStack() != null) + if (arrow.getWorld() instanceof ServerWorld world) + initialDamage = EnchantmentHelper.getDamage(world, arrow.getWeaponStack(), mc.player, damageSource, (float) initialDamage); + + int finalDamage = MathHelper.ceil(MathHelper.clamp(velocity * initialDamage, 0, 2.147483647E9)); + + if (arrow.isCritical()) { + long bonus = arrow.getRandom().nextInt(finalDamage / 2 + 2); + finalDamage = (int) Math.min(bonus + (long) finalDamage, 2147483647L); + } + + return healthMode.is(HealthMode.HEARTS) ? finalDamage / 2f : finalDamage; + } + + @SuppressWarnings("deprecation") + public String getOwnerName(LazyEntityReference owner) { + // si el dueño está en línea + LivingEntity ownerEntity = owner.resolve(mc.world, LivingEntity.class); + if (ownerEntity instanceof PlayerEntity playerEntity) return playerEntity.getName().getString(); + + // mirar si ya está en la caché + UUID uuid = owner.getUuid(); + String cachedName = cache.get(uuid); + if (cachedName != null) return cachedName; + + cache.put(uuid, "..."); // mientras se obtiene el nombre + + // si no está en la caché, ni en línea, obtener nombre de los servers de Mojang + executor.execute(() -> { + try { + String url = "https://sessionserver.mojang.com/session/minecraft/profile/" + uuid.toString().replace("-", ""); + HttpURLConnection req = (HttpURLConnection) new URL(url).openConnection(); + req.setRequestMethod("GET"); + req.setConnectTimeout(5000); + req.setReadTimeout(5000); + if (req.getResponseCode() != 200) { + cache.put(uuid, "?"); + return; + } + + JsonObject obj = JsonParser.parseReader(new InputStreamReader(req.getInputStream())).getAsJsonObject(); + String name = obj.get("name").getAsString(); + cache.put(uuid, name); + + } catch (Exception e) { + e.printStackTrace(); + cache.put(uuid, "?"); + } + }); + + return "..."; + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/module/modules/Perspective.java b/src/main/java/me/retucio/camtweaks/module/modules/PerspectivePlus.java similarity index 63% rename from src/main/java/me/retucio/camtweaks/module/modules/Perspective.java rename to src/main/java/me/retucio/camtweaks/module/modules/PerspectivePlus.java index 2de9ea7..59a2a8c 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/Perspective.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/PerspectivePlus.java @@ -1,6 +1,6 @@ package me.retucio.camtweaks.module.modules; -import me.retucio.camtweaks.event.Subscribe; +import me.retucio.camtweaks.event.SubscribeEvent; import me.retucio.camtweaks.event.events.MouseScrollEvent; import me.retucio.camtweaks.event.events.PerspectiveChangeEvent; import me.retucio.camtweaks.module.Module; @@ -9,28 +9,26 @@ import me.retucio.camtweaks.util.KeyUtil; import org.lwjgl.glfw.GLFW; // continúa en CameraMixin -public class Perspective extends Module { +public class PerspectivePlus extends Module { private double distance; // ajustes - public BooleanSetting clip = new BooleanSetting( - "clip", "atravesar bloques con la cámara", true); + public BooleanSetting clip = addSetting(new BooleanSetting( + "clip", "atravesar bloques con la cámara", true)); - public NumberSetting defaultDistance = new NumberSetting( + public NumberSetting defaultDistance = addSetting(new NumberSetting( "distancia", "distancia a la que está la cámara del jugador por defecto", - 4, 1, 20, 0.2); + 4, 1, 20, 0.2)); - public NumberSetting scrollSens = new NumberSetting( + public NumberSetting scrollSens = addSetting(new NumberSetting( "sensibilidad del scroll", "sensibilidad de la rueda del ratón (0 para desactivar)", - 1, 0, 8, 0.1); + 1, 0, 8, 0.1)); - public KeySetting scrollKey = new KeySetting("tecla del scroll", "qué tecla mantener para usar la rueda del ratón", GLFW.GLFW_KEY_LEFT_ALT); + public KeySetting scrollKey = addSetting(new KeySetting("tecla del scroll", "qué tecla mantener para usar la rueda del ratón", GLFW.GLFW_KEY_LEFT_ALT)); - public Perspective() { - super("perspectiva", "añade cositas chulas al cambio de perspectiva"); - addSettings(clip, defaultDistance, scrollSens, scrollKey); - setKey(GLFW.GLFW_KEY_UNKNOWN); + public PerspectivePlus() { + super("perspectiva plus", "añade cositas chulas al cambio de perspectiva"); } @Override @@ -39,12 +37,12 @@ public class Perspective extends Module { super.onEnable(); } - @Subscribe + @SubscribeEvent public void onPerspectiveChange(PerspectiveChangeEvent event) { distance = defaultDistance.getValue(); } - @Subscribe + @SubscribeEvent public void onMouseScroll(MouseScrollEvent event) { if (mc.options.getPerspective() == net.minecraft.client.option.Perspective.FIRST_PERSON || mc.currentScreen != null || scrollSens.getValue() <= 0) return; diff --git a/src/main/java/me/retucio/camtweaks/module/modules/TimeChanger.java b/src/main/java/me/retucio/camtweaks/module/modules/TimeChanger.java new file mode 100644 index 0000000..7ffe811 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/module/modules/TimeChanger.java @@ -0,0 +1,85 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.event.events.PacketEvent; +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.BooleanSetting; +import me.retucio.camtweaks.module.settings.EnumSetting; +import me.retucio.camtweaks.module.settings.NumberSetting; +import net.minecraft.network.packet.s2c.play.WorldTimeUpdateS2CPacket; + +// continúa en ClientWorldPropertiesMixin, DimensionTypeMixin, +public class TimeChanger extends Module { + + public BooleanSetting renderSun = addSetting(new BooleanSetting("sol", "que haya sol o no", true)); + public BooleanSetting renderMoon = addSetting(new BooleanSetting("luna", "que haya luna o no", true)); + public BooleanSetting renderStars = addSetting(new BooleanSetting("estrellas", "que hayan estrellas o no", true)); + + public EnumSetting moonPhase = addSetting(new EnumSetting<>("fase lunar", "fase lunar actual", MoonPhases.class, MoonPhases.DEFAULT)); + public NumberSetting time = addSetting(new NumberSetting("hora", "hora del juego", 0, -20000, 20000, 1)); + + public TimeChanger() { + super("cielo custom", "te deja cambiar visualmente el progreso del día"); + renderMoon.onUpdate(v -> moonPhase.setVisible(v)); + } + + private long realTime; + + @Override + public void onEnable() { + if (mc.world == null) return; + realTime = mc.world.getTime(); + } + + @Override + public void onDisable() { + if (mc.world == null) return; + mc.world.getLevelProperties().setTimeOfDay(realTime); + } + + @SubscribeEvent + public void onPacketReceive(PacketEvent.Receive event) { + if (event.getPacket() instanceof WorldTimeUpdateS2CPacket packet) { + realTime = packet.timeOfDay(); + event.cancel(); + } + } + + @Override + public void onTick() { + if (mc.world == null) return; + mc.world.getLevelProperties().setTimeOfDay(time.getLongValue()); + } + + public int getMoonPhase() { + if (mc.world == null) return -1; + + return switch (moonPhase.getValue()) { + case DEFAULT -> (int) (mc.world.getLunarTime() / 24000L) % 8; + case FULL_MOON -> 0; + case WANING_GIBBOUS -> 1; + case LAST_QUARTER -> 2; + case WANING_CRESCENT -> 3; + case NEW_MOON -> 4; + case WAXING_CRESCENT -> 5; + case FIRST_QUARTER -> 6; + case WAXING_GIBBOUS -> 7; + }; + } + + public enum MoonPhases { + DEFAULT("por defecto"), + FULL_MOON("luna llena"), + WANING_GIBBOUS("menguante gibosa"), + LAST_QUARTER("cuarto menguante"), + WANING_CRESCENT("luna vieja"), + NEW_MOON("luna nueva"), + WAXING_CRESCENT("creciente"), + FIRST_QUARTER("cuarto creciente"), + WAXING_GIBBOUS("creciente gibosa"); + + private final String name; + MoonPhases(String name) { this.name = name; } + @Override public String toString() { return name; } + } +} diff --git a/src/main/java/me/retucio/camtweaks/module/modules/Zoom.java b/src/main/java/me/retucio/camtweaks/module/modules/Zoom.java index 4c7e999..7d87f4d 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/Zoom.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/Zoom.java @@ -1,36 +1,34 @@ package me.retucio.camtweaks.module.modules; import me.retucio.camtweaks.CameraTweaks; -import me.retucio.camtweaks.event.Subscribe; +import me.retucio.camtweaks.event.SubscribeEvent; import me.retucio.camtweaks.event.events.GetFOVEvent; import me.retucio.camtweaks.event.events.MouseScrollEvent; import me.retucio.camtweaks.module.Module; import me.retucio.camtweaks.module.settings.BooleanSetting; import me.retucio.camtweaks.module.settings.KeySetting; import me.retucio.camtweaks.module.settings.NumberSetting; -import me.retucio.camtweaks.util.ChatUtil; import me.retucio.camtweaks.util.KeyUtil; -import net.minecraft.text.Text; import org.lwjgl.glfw.GLFW; // continúa en GameRendererMixin public class Zoom extends Module { - public BooleanSetting showHands = new BooleanSetting("mostrar manos", "esconde o muestra las manos al hacer zoom", true); - public BooleanSetting showHUD = new BooleanSetting("mostrar HUD", "esconde o muestra los indicadores en pantalla", true); + public BooleanSetting showHands = addSetting(new BooleanSetting("mostrar manos", "esconde o muestra las manos al hacer zoom", true)); + public BooleanSetting showHUD = addSetting(new BooleanSetting("mostrar HUD", "esconde o muestra los indicadores en pantalla", true)); - public NumberSetting scrollSens = new NumberSetting("sensibilidad del scroll", "sensibilidad de la rueda del ratón (0 para desactivar)", - 0.4, 0, 8, 0.1); + public NumberSetting scrollSens = addSetting(new NumberSetting("sensibilidad del scroll", "sensibilidad de la rueda del ratón (0 para desactivar)", + 0.4, 0, 8, 0.1)); - public KeySetting scrollKey = new KeySetting("tecla del scroll", "qué tecla mantener para usar la rueda del ratón", GLFW.GLFW_KEY_LEFT_CONTROL); + public KeySetting scrollKey = addSetting(new KeySetting("tecla del scroll", "qué tecla mantener para usar la rueda del ratón", GLFW.GLFW_KEY_LEFT_CONTROL)); - public NumberSetting defaultZoom = new NumberSetting("zoom", "cantidad de zoom", - 6, 1, 10, 0.1); + public NumberSetting defaultZoom = addSetting(new NumberSetting("zoom", "cantidad de zoom", + 6, 1, 10, 0.1)); - public NumberSetting mouseSensMultiplier = new NumberSetting("sensibilidad", "multiplicador de la sensibilidad del ratón", - 0.7, 0.01, 1, 0.05); + public NumberSetting mouseSensMultiplier = addSetting(new NumberSetting("sensibilidad", "multiplicador de la sensibilidad del ratón", + 0.7, 0.01, 1, 0.05)); - public BooleanSetting smoothCam = new BooleanSetting("cámara cinemática", "usa la cámara cinemática mientras hagas zoom", false); + public BooleanSetting smoothCam = addSetting(new BooleanSetting("cámara cinemática", "usa la cámara cinemática mientras hagas zoom", false)); private boolean prevSmoothCam; private double prevMouseSens; @@ -44,12 +42,13 @@ public class Zoom extends Module { super.keyMode.setDefaultValue(KeyModes.HOLD); super.notify.setEnabled(false); super.notify.setDefaultValue(false); - setKey(GLFW.GLFW_KEY_F); - addSettings(showHands, showHUD, scrollSens, scrollKey, defaultZoom, mouseSensMultiplier, smoothCam); + assignKey(GLFW.GLFW_KEY_F); } @Override public void onEnable() { + if (mc.options == null) return; + CameraTweaks.EVENT_BUS.register(this); prevSmoothCam = mc.options.smoothCameraEnabled; @@ -63,6 +62,7 @@ public class Zoom extends Module { @Override public void onDisable() { + if (mc.options == null) return; CameraTweaks.EVENT_BUS.unregister(this); mc.options.smoothCameraEnabled = prevSmoothCam; @@ -79,9 +79,10 @@ public class Zoom extends Module { mc.options.getMouseSensitivity().setValue(prevMouseSens * mouseSensMultiplier.getValue()); } - @Subscribe + @SubscribeEvent private void onMouseScroll(MouseScrollEvent event) { - if (scrollSens.getValue() > 0 && isEnabled() && KeyUtil.isKeyDown(scrollKey.getKey())) { + boolean key = scrollKey.getKey() == GLFW.GLFW_KEY_UNKNOWN || KeyUtil.isKeyDown(scrollKey.getKey()); + if (isEnabled() && scrollSens.getValue() > 0 && key) { value += event.getVertical() * 0.25 * (scrollSens.getValue() * value); if (value < 1) value = 1; @@ -89,7 +90,7 @@ public class Zoom extends Module { } } - @Subscribe + @SubscribeEvent private void onGetFov(GetFOVEvent event) { event.setFov((float) (event.getFov() / value)); 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 117da5b..23bf18a 100644 --- a/src/main/java/me/retucio/camtweaks/module/settings/BooleanSetting.java +++ b/src/main/java/me/retucio/camtweaks/module/settings/BooleanSetting.java @@ -1,5 +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; // ajuste booleano, es decir, o se encuentra encencido o apagado (similar a un interruptor) @@ -17,7 +20,7 @@ public class BooleanSetting extends Setting { } public void toggle() { - enabled = !enabled; + setEnabled(!enabled); if (updateListener != null) updateListener.accept(enabled); } @@ -28,6 +31,7 @@ public class BooleanSetting extends Setting { public void setEnabled(boolean enabled) { if (this.enabled != enabled) { this.enabled = enabled; + CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this)); if (updateListener != null) updateListener.accept(enabled); } } 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 cd4ba9b..39100c0 100644 --- a/src/main/java/me/retucio/camtweaks/module/settings/EnumSetting.java +++ b/src/main/java/me/retucio/camtweaks/module/settings/EnumSetting.java @@ -1,5 +1,8 @@ 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; @@ -33,6 +36,7 @@ public class EnumSetting> extends Setting { if (this.value != value) { this.value = value; this.index = values.indexOf(value); + CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this)); if (updateListener != null) updateListener.accept(value); } } 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 8d84ddb..69e6219 100644 --- a/src/main/java/me/retucio/camtweaks/module/settings/KeySetting.java +++ b/src/main/java/me/retucio/camtweaks/module/settings/KeySetting.java @@ -1,6 +1,13 @@ package me.retucio.camtweaks.module.settings; +import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent; +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame; +import me.retucio.camtweaks.util.ChatUtil; import me.retucio.camtweaks.util.KeyUtil; +import org.lwjgl.glfw.GLFW; import java.util.function.Consumer; @@ -23,7 +30,24 @@ public class KeySetting extends Setting { public void setKey(int key) { if (this.key == key) return; + + if (key == GLFW.GLFW_KEY_ESCAPE) { + this.key = GLFW.GLFW_KEY_UNKNOWN; // asignar la tecla ESC a deshabilitar la tecla + CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this)); + if (updateListener != null) updateListener.accept(key); + return; + } + + if (ModuleManager.INSTANCE != null) { + for (Module module : ModuleManager.INSTANCE.getModules()) + if (module.getKey() == key && !ClickGUISettingsFrame.guiSettings.multipleKeybinds.isEnabled() && key != -1) { + module.setKey(-1); + ChatUtil.info("tecla del módulo " + module.getName() + " restablecida"); + } + } this.key = key; + + CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this)); if (updateListener != null) updateListener.accept(key); } 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 88f6ac3..c36132a 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,15 @@ 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 Setting { private double value; - private final double defaultValue; + private double defaultValue; private final double min; private final double max; @@ -49,10 +52,15 @@ public class NumberSetting extends Setting { return (int) value; // en "int" (número entero) por conveniencia } + public long getLongValue() { + return (long) value; // lo mismo para "longs" + } + public void setValue(double value) { if (this.value == value) return; double clamped = clamp(value, min, max); this.value = Math.round(clamped / increment) * increment; + CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this)); if (updateListener != null) updateListener.accept(this.value); } @@ -60,6 +68,10 @@ public class NumberSetting extends Setting { return defaultValue; } + public void setDefaultValue(double value) { + defaultValue = value; + } + public void reset() { setValue(defaultValue); } @@ -78,5 +90,6 @@ public class NumberSetting extends Setting { public void onUpdate(Consumer listener) { this.updateListener = listener; + CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this)); } } diff --git a/src/main/java/me/retucio/camtweaks/module/settings/Setting.java b/src/main/java/me/retucio/camtweaks/module/settings/Setting.java index 33ab92d..e30baca 100644 --- a/src/main/java/me/retucio/camtweaks/module/settings/Setting.java +++ b/src/main/java/me/retucio/camtweaks/module/settings/Setting.java @@ -1,5 +1,7 @@ package me.retucio.camtweaks.module.settings; +import me.retucio.camtweaks.module.Module; + // base para los tipos de ajustes public class Setting { @@ -7,6 +9,8 @@ public class Setting { private final String description; private boolean visible = true; + private Module module; + protected Setting(String name, String description) { this.name = name; this.description = description; @@ -27,4 +31,12 @@ public class Setting { public String getDescription() { return description; } + + public Module getModule() { + return module; + } + + public void setModule(Module module) { + this.module = module; + } } 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 f1b2032..2e4f4dc 100644 --- a/src/main/java/me/retucio/camtweaks/module/settings/StringSetting.java +++ b/src/main/java/me/retucio/camtweaks/module/settings/StringSetting.java @@ -1,5 +1,8 @@ package me.retucio.camtweaks.module.settings; +import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent; + import java.util.Objects; import java.util.function.Consumer; @@ -25,6 +28,7 @@ public class StringSetting extends Setting { public void setValue(String value) { if (this.value.equals(value)) return; this.value = value.length() > maxLength ? value.substring(0, maxLength) : value; + CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this)); if (updateListener != null) updateListener.accept(this.value); } @@ -46,5 +50,6 @@ public class StringSetting extends Setting { public void onUpdate(Consumer listener) { this.updateListener = listener; + CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this)); } } diff --git a/src/main/java/me/retucio/camtweaks/ui/ClickGUI.java b/src/main/java/me/retucio/camtweaks/ui/ClickGUI.java index d053ac2..03f5744 100644 --- a/src/main/java/me/retucio/camtweaks/ui/ClickGUI.java +++ b/src/main/java/me/retucio/camtweaks/ui/ClickGUI.java @@ -1,11 +1,13 @@ package me.retucio.camtweaks.ui; import me.retucio.camtweaks.CameraTweaks; -import me.retucio.camtweaks.event.Subscribe; +import me.retucio.camtweaks.event.SubscribeEvent; 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.ui.settings.ClickGUISettingsFrame; -import me.retucio.camtweaks.ui.settings.SettingsFrame; +import me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame; +import me.retucio.camtweaks.ui.frames.ModuleFrame; +import me.retucio.camtweaks.ui.frames.SettingsFrame; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; @@ -13,18 +15,19 @@ import net.minecraft.text.Text; import java.util.ArrayList; import java.util.List; -import static me.retucio.camtweaks.ui.settings.ClickGUISettingsFrame.guiSettings; +import static me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame.guiSettings; // interfaz gráfica, se abre con el shift derecho por defecto. aquí se encuentran los módulos y sus ajustes public class ClickGUI extends Screen { - public static final ClickGUI INSTANCE = new ClickGUI(); + public static ClickGUI INSTANCE; + private boolean anyFocused; private final ModuleFrame modulesFrame = new ModuleFrame(20, 30, 100, 20); private final List settingsFrames = new ArrayList<>(); private final ClickGUISettingsFrame guiSettingsFrame = new ClickGUISettingsFrame(200, 30, 100, 20); - protected ClickGUI() { + public ClickGUI() { super(Text.of("interfaz")); settingsFrames.add(guiSettingsFrame); CameraTweaks.EVENT_BUS.register(this); @@ -32,16 +35,16 @@ public class ClickGUI extends Screen { @Override public void render(DrawContext ctx, int mouseX, int mouseY, float delta) { - // renderizar el marco de los módulos - modulesFrame.render(ctx, mouseX, mouseY, delta); - modulesFrame.updatePosition(mouseX, mouseY); - // renderizar el marco de los ajustes de cada módulo que lo tenga abierto. se abre haciendo clic derecho sobre el módulo - for (SettingsFrame sf : new ArrayList<>(settingsFrames)) { + for (SettingsFrame sf : settingsFrames.reversed()) { sf.render(ctx, mouseX, mouseY, delta); sf.updatePosition(mouseX, mouseY); } + // renderizar el marco de los módulos + modulesFrame.render(ctx, mouseX, mouseY, delta); + modulesFrame.updatePosition(mouseX, mouseY); + super.render(ctx, mouseX, mouseY, delta); } @@ -51,6 +54,7 @@ public class ClickGUI extends Screen { modulesFrame.mouseClicked(mouseX, mouseY, button); for (SettingsFrame sf : new ArrayList<>(settingsFrames)) sf.mouseClicked(mouseX, mouseY, button); + return super.mouseClicked(mouseX, mouseY, button); } @@ -63,7 +67,7 @@ public class ClickGUI extends Screen { return super.mouseReleased(mouseX, mouseY, button); } - @Subscribe + @SubscribeEvent public void onMouseScroll(MouseScrollEvent event) { // subir y bajar la pantalla con la rueda del ratón if (CameraTweaks.mc.currentScreen != this) return; @@ -76,12 +80,22 @@ public class ClickGUI extends Screen { public void openSettingsFrame(Module module, int x, int y) { // abrir un marco donde se encuentran los ajustes del módulo deseado if (isSettingsFrameOpen(module)) return; // permitir un solo marco de ajustes por módulo - settingsFrames.add(new SettingsFrame(module, x + 120, y, 120, 18)); + SettingsFrame frame = new SettingsFrame(module, x, y, 120, 20); + settingsFrames.add(frame); + CameraTweaks.EVENT_BUS.post(new SettingsFrameEvent.Open(frame)); } // cerrar el marco de ajustes public void closeSettingsFrame(Module module) { - settingsFrames.removeIf(sf -> sf.module == module); + // porque java.util.ConcurrentModificationException o algo no sé es lo único que se me ha ocurrido hacer + List toRemove = new ArrayList<>(); + for (SettingsFrame sf : settingsFrames) { + if (sf.module == module) { + CameraTweaks.EVENT_BUS.post(new SettingsFrameEvent.Close(sf)); + toRemove.add(sf); + } + } + settingsFrames.removeAll(toRemove); } // verificar si un módulo tiene su marco de ajustes abierto @@ -104,8 +118,16 @@ public class ClickGUI extends Screen { return guiSettingsFrame; } + public void setAnyFocused(boolean anyFocused) { + this.anyFocused = anyFocused; + } + + @Override + public boolean shouldCloseOnEsc() { + return super.shouldCloseOnEsc() && !anyFocused; + } + public List getSettingsFrames() { return settingsFrames; } - } diff --git a/src/main/java/me/retucio/camtweaks/ui/HUD.java b/src/main/java/me/retucio/camtweaks/ui/HUD.java index 6439457..4606fca 100644 --- a/src/main/java/me/retucio/camtweaks/ui/HUD.java +++ b/src/main/java/me/retucio/camtweaks/ui/HUD.java @@ -5,6 +5,7 @@ import net.minecraft.client.gui.DrawContext; import net.minecraft.client.render.RenderTickCounter; // en un principio esto iba a mostrar en pantalla los módulos activados, pero me parece innecesario. se queda aquí por si acaso +// igual lo uso para algo... public class HUD { private static final MinecraftClient mc = MinecraftClient.getInstance(); diff --git a/src/main/java/me/retucio/camtweaks/ui/settings/BindButton.java b/src/main/java/me/retucio/camtweaks/ui/buttons/BindButton.java similarity index 90% rename from src/main/java/me/retucio/camtweaks/ui/settings/BindButton.java rename to src/main/java/me/retucio/camtweaks/ui/buttons/BindButton.java index 58114ae..daeb0e4 100644 --- a/src/main/java/me/retucio/camtweaks/ui/settings/BindButton.java +++ b/src/main/java/me/retucio/camtweaks/ui/buttons/BindButton.java @@ -1,6 +1,7 @@ -package me.retucio.camtweaks.ui.settings; +package me.retucio.camtweaks.ui.buttons; import me.retucio.camtweaks.module.settings.KeySetting; +import me.retucio.camtweaks.ui.frames.SettingsFrame; import me.retucio.camtweaks.util.Colors; import me.retucio.camtweaks.util.KeyUtil; import net.minecraft.client.gui.DrawContext; @@ -21,13 +22,9 @@ public class BindButton extends SettingButton { @Override public void render(DrawContext ctx, double mouseX, double mouseY, float delta) { - int x = parent.x + 4; - int y = parent.y + offset + 3; - int w = parent.w - 8; - int bgColor = isHovered((int) mouseX, (int) mouseY) - ? Colors.hoveredCycleButtonColor - : Colors.cycleButtonColor; + ? Colors.hoveredSettingButtonColor + : Colors.settingButtonColor; ctx.fill(x, y, x + w, y + height, bgColor); String label = setting.getName() + ": " + (listening ? "..." : setting.getKeyName()); diff --git a/src/main/java/me/retucio/camtweaks/ui/settings/CycleButton.java b/src/main/java/me/retucio/camtweaks/ui/buttons/CycleButton.java similarity index 80% rename from src/main/java/me/retucio/camtweaks/ui/settings/CycleButton.java rename to src/main/java/me/retucio/camtweaks/ui/buttons/CycleButton.java index 03231aa..c5349a4 100644 --- a/src/main/java/me/retucio/camtweaks/ui/settings/CycleButton.java +++ b/src/main/java/me/retucio/camtweaks/ui/buttons/CycleButton.java @@ -1,6 +1,7 @@ -package me.retucio.camtweaks.ui.settings; +package me.retucio.camtweaks.ui.buttons; import me.retucio.camtweaks.module.settings.EnumSetting; +import me.retucio.camtweaks.ui.frames.SettingsFrame; import me.retucio.camtweaks.util.Colors; import me.retucio.camtweaks.util.KeyUtil; import net.minecraft.client.gui.DrawContext; @@ -24,13 +25,9 @@ public class CycleButton> extends SettingButton { @Override public void render(DrawContext ctx, double mouseX, double mouseY, float delta) { - int x = parent.x + 4; - int y = parent.y + offset + 3; - int w = parent.w - 8; - int bgColor = isHovered((int) mouseX, (int) mouseY) - ? Colors.hoveredCycleButtonColor - : Colors.cycleButtonColor; + ? Colors.hoveredSettingButtonColor + : Colors.settingButtonColor; ctx.fill(x, y, x + w, y + height, bgColor); // fondo del botón @@ -41,25 +38,25 @@ public class CycleButton> extends SettingButton { // tooltip if (isHovered((int) mouseX, (int) mouseY)) { Screen currentScreen = parent.mc.currentScreen; - if (currentScreen != null) - // si shift está presionado mientras el puntero está encima, mostrar los modos disponibles - if (GLFW.glfwGetKey(parent.mc.getWindow().getHandle(), GLFW.GLFW_KEY_LEFT_SHIFT) != GLFW.GLFW_RELEASE) { + if (currentScreen != null) { + if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT)) { List lines = new ArrayList<>(); lines.add(Text.literal("modos disponibles:")); for (Enum val : setting.getValues()) { if (val == setting.getValue()) - lines.add(Text.literal("> " + val.toString() + " <").formatted(Formatting.GREEN)); // destacar modo actualmente seleccionado + lines.add(Text.literal("> " + val.toString() + " <").formatted(Formatting.GREEN)); else lines.add(Text.literal(val.toString())); } ctx.drawTooltip(parent.mc.textRenderer, lines, (int) mouseX, (int) mouseY + 20); - // si shift no está siendo presionado, simplemente mostrar la descripción } else { ctx.drawTooltip(Text.of(setting.getDescription()), (int) mouseX, (int) mouseY + 20); } + } } } + @Override public void mouseClicked(double mouseX, double mouseY, int button) { if (isHovered((int) mouseX, (int) mouseY)) { diff --git a/src/main/java/me/retucio/camtweaks/ui/ModuleButton.java b/src/main/java/me/retucio/camtweaks/ui/buttons/ModuleButton.java similarity index 78% rename from src/main/java/me/retucio/camtweaks/ui/ModuleButton.java rename to src/main/java/me/retucio/camtweaks/ui/buttons/ModuleButton.java index f3334ce..70471f1 100644 --- a/src/main/java/me/retucio/camtweaks/ui/ModuleButton.java +++ b/src/main/java/me/retucio/camtweaks/ui/buttons/ModuleButton.java @@ -1,13 +1,13 @@ -package me.retucio.camtweaks.ui; +package me.retucio.camtweaks.ui.buttons; import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.ui.ClickGUI; +import me.retucio.camtweaks.ui.frames.ModuleFrame; import me.retucio.camtweaks.util.Colors; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; -import java.awt.*; - // clase para el botón para cada módulo public class ModuleButton { @@ -41,16 +41,14 @@ public class ModuleButton { } public void mouseClicked(double mouseX, double mouseY, int button) { - if (isHovered((int) mouseX, (int) mouseY)) { - if (button == 0) // clic izquierdo para activar / desactivar el módulo - module.toggle(); - else if (button == 1) { // clic derecho para el marco de ajustes (también lo cierra si está abierto) - if (ClickGUI.INSTANCE.isSettingsFrameOpen(module)) - ClickGUI.INSTANCE.closeSettingsFrame(module); - else - ClickGUI.INSTANCE.openSettingsFrame(module, - parent.x + parent.w, parent.y + offset); - } + if (button == 0) {// clic izquierdo para activar / desactivar el módulo + module.toggle(); + } else if (button == 1) { // clic derecho para el marco de ajustes (también lo cierra si está abierto) + if (ClickGUI.INSTANCE.isSettingsFrameOpen(module)) + ClickGUI.INSTANCE.closeSettingsFrame(module); + else + ClickGUI.INSTANCE.openSettingsFrame(module, + parent.x + parent.w + 120, parent.y + offset); } } diff --git a/src/main/java/me/retucio/camtweaks/ui/settings/SettingButton.java b/src/main/java/me/retucio/camtweaks/ui/buttons/SettingButton.java similarity index 53% rename from src/main/java/me/retucio/camtweaks/ui/settings/SettingButton.java rename to src/main/java/me/retucio/camtweaks/ui/buttons/SettingButton.java index 29bb5e0..695aa4f 100644 --- a/src/main/java/me/retucio/camtweaks/ui/settings/SettingButton.java +++ b/src/main/java/me/retucio/camtweaks/ui/buttons/SettingButton.java @@ -1,6 +1,7 @@ -package me.retucio.camtweaks.ui.settings; +package me.retucio.camtweaks.ui.buttons; import me.retucio.camtweaks.module.settings.Setting; +import me.retucio.camtweaks.ui.frames.SettingsFrame; import net.minecraft.client.gui.DrawContext; // clase base para los botones de los ajustes @@ -11,6 +12,8 @@ public abstract class SettingButton { protected int offset; protected final int height = 15; + protected int x, y, w, h; + public SettingButton(Setting setting, SettingsFrame parent, int offset) { this.setting = setting; this.parent = parent; @@ -22,7 +25,43 @@ public abstract class SettingButton { public abstract void mouseReleased(double mouseX, double mouseY, int button); protected boolean isHovered(int mouseX, int mouseY) { - return mouseX > parent.x + 4 && mouseX < parent.x + parent.w - 4 && - mouseY > parent.y + offset && mouseY < parent.y + offset + height; + return mouseX > x && mouseX < x + w && + mouseY > y && mouseY < y + h; + } + + public Setting getSetting() { + return setting; + } + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + + public int getW() { + return w; + } + + public void setW(int w) { + this.w = w; + } + + public int getH() { + return h; + } + + public void setH(int h) { + this.h = h; } } \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/ui/settings/SliderButton.java b/src/main/java/me/retucio/camtweaks/ui/buttons/SliderButton.java similarity index 77% rename from src/main/java/me/retucio/camtweaks/ui/settings/SliderButton.java rename to src/main/java/me/retucio/camtweaks/ui/buttons/SliderButton.java index 5cb5231..da0c9b5 100644 --- a/src/main/java/me/retucio/camtweaks/ui/settings/SliderButton.java +++ b/src/main/java/me/retucio/camtweaks/ui/buttons/SliderButton.java @@ -1,6 +1,10 @@ -package me.retucio.camtweaks.ui.settings; +package me.retucio.camtweaks.ui.buttons; +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.event.events.KeyEvent; import me.retucio.camtweaks.module.settings.NumberSetting; +import me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame; +import me.retucio.camtweaks.ui.frames.SettingsFrame; import me.retucio.camtweaks.util.Colors; import me.retucio.camtweaks.util.KeyUtil; import net.minecraft.client.gui.DrawContext; @@ -8,9 +12,10 @@ import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; import org.lwjgl.glfw.GLFW; -import java.awt.*; import java.text.DecimalFormat; +import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS; + // slider (barrita) para los ajustes numéricos public class SliderButton extends SettingButton { @@ -22,14 +27,11 @@ public class SliderButton extends SettingButton { super(setting, parent, offset); this.setting = setting; this.df = new DecimalFormat("#.##"); // solo mostrar dos décimales + EVENT_BUS.subscribe(this); // para poder escuchar teclas } @Override public void render(DrawContext ctx, double mouseX, double mouseY, float delta) { - int x = parent.x + 4; - int y = parent.y + offset + 3; - int w = parent.w - 8; - ctx.fill(x, y, x + w, y + height, Colors.moduleButtonColor); // calcular cómo de llena tendría que estar el "slider" @@ -40,7 +42,7 @@ public class SliderButton extends SettingButton { String label = setting.getName() + ": " + df.format(setting.getValue()); ctx.drawTextWithShadow(parent.mc.textRenderer, label, x + 5, y + 3, -1); - // lógica para el arrastre del valor + // lógica para el arrastre (arrastramiento?) del valor if (dragging) { double newVal = setting.getMin() + ((mouseX - x) / (double) w) * (setting.getMax() - setting.getMin()); newVal = Math.max(setting.getMin(), Math.min(setting.getMax(), newVal)); @@ -70,6 +72,12 @@ public class SliderButton extends SettingButton { if (button == 0) dragging = false; } + @SubscribeEvent + public void onKey(KeyEvent event) { + // de no ser de esto, si se cierra la interfaz sin haber soltado el ratón mientras se arrastraba el valor, al reabrir la interfaz se seguía arrastrando, aún habiendo soltado ya el clic + if (event.getKey() == GLFW.GLFW_KEY_ESCAPE || event.getKey() == ClickGUISettingsFrame.guiSettings.getKey()) dragging = false; + } + public NumberSetting getSetting() { return setting; } diff --git a/src/main/java/me/retucio/camtweaks/ui/settings/TextButton.java b/src/main/java/me/retucio/camtweaks/ui/buttons/TextButton.java similarity index 85% rename from src/main/java/me/retucio/camtweaks/ui/settings/TextButton.java rename to src/main/java/me/retucio/camtweaks/ui/buttons/TextButton.java index ee9e546..e45d69b 100644 --- a/src/main/java/me/retucio/camtweaks/ui/settings/TextButton.java +++ b/src/main/java/me/retucio/camtweaks/ui/buttons/TextButton.java @@ -1,6 +1,7 @@ -package me.retucio.camtweaks.ui.settings; +package me.retucio.camtweaks.ui.buttons; import me.retucio.camtweaks.module.settings.StringSetting; +import me.retucio.camtweaks.ui.frames.SettingsFrame; import me.retucio.camtweaks.util.Colors; import me.retucio.camtweaks.util.KeyUtil; import net.minecraft.client.gui.DrawContext; @@ -21,16 +22,13 @@ public class TextButton extends SettingButton { @Override public void render(DrawContext ctx, double mouseX, double mouseY, float delta) { - int x = parent.x + 4; - int y = parent.y + offset + 3; - int w = parent.w - 8; int bgColor = isHovered((int) mouseX, (int) mouseY) - ? Colors.hoveredCycleButtonColor - : Colors.cycleButtonColor; + ? Colors.hoveredSettingButtonColor + : Colors.settingButtonColor; ctx.fill(x, y, x + w, y + height, bgColor); - String label = setting.getName() + ": " + (typing ? buffer.toString() + "_" : setting.getValue()); + String label = setting.getName() + ": " + (typing ? buffer + "_" : setting.getValue()); ctx.drawTextWithShadow(parent.mc.textRenderer, label, x + 5, y + 3, -1); if (isHovered((int) mouseX, (int) mouseY)) { @@ -56,21 +54,21 @@ public class TextButton extends SettingButton { } public void onKey(int key, int action) { - if (!typing || action != GLFW.GLFW_PRESS) return; + if (!typing || action == GLFW.GLFW_RELEASE) return; switch (key) { // casos para teclas especiales como enter, escape o borrar case GLFW.GLFW_KEY_ENTER -> { setting.setValue(buffer.toString()); typing = false; } case GLFW.GLFW_KEY_BACKSPACE -> { - buffer.deleteCharAt(buffer.length() - 1); + onBackspace(); } case GLFW.GLFW_KEY_ESCAPE -> { typing = false; } default -> { String c = KeyUtil.getKeyName(key); if (c.length() == 1) { if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT) || KeyUtil.isKeyDown(GLFW.GLFW_KEY_RIGHT_SHIFT)) - charTyped(c.toUpperCase().charAt(0)); + charTyped(KeyUtil.shiftKey(c).charAt(0)); else charTyped(c.toLowerCase().charAt(0)); } @@ -91,7 +89,10 @@ public class TextButton extends SettingButton { return setting; } + private void onBackspace() { + if (!buffer.isEmpty()) buffer.deleteCharAt(buffer.length() - 1); + } + @Override public void mouseReleased(double mouseX, double mouseY, int button) {} - -} +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/ui/settings/ToggleButton.java b/src/main/java/me/retucio/camtweaks/ui/buttons/ToggleButton.java similarity index 92% rename from src/main/java/me/retucio/camtweaks/ui/settings/ToggleButton.java rename to src/main/java/me/retucio/camtweaks/ui/buttons/ToggleButton.java index 9727bd8..341a10e 100644 --- a/src/main/java/me/retucio/camtweaks/ui/settings/ToggleButton.java +++ b/src/main/java/me/retucio/camtweaks/ui/buttons/ToggleButton.java @@ -1,6 +1,7 @@ -package me.retucio.camtweaks.ui.settings; +package me.retucio.camtweaks.ui.buttons; import me.retucio.camtweaks.module.settings.BooleanSetting; +import me.retucio.camtweaks.ui.frames.SettingsFrame; import me.retucio.camtweaks.util.Colors; import me.retucio.camtweaks.util.KeyUtil; import net.minecraft.client.gui.DrawContext; @@ -22,16 +23,13 @@ public class ToggleButton extends SettingButton { @Override public void render(DrawContext ctx, double mouseX, double mouseY, float delta) { - int x = parent.x + 4; - int y = parent.y + offset + 3; - int w = parent.w - 8; - Color color = setting.isEnabled() ? Colors.enabledToggleButtonColor : Colors.disabledToggleButtonColor; if (isHovered((int) mouseX, (int) mouseY)) color = color.brighter(); // simplemente utilizar el método "built-in" de Java para hacer el botón más claro cuando el puntero se encuentra encima de él + // quizás debería de utilizar .brighter() más, en vez de dar valores personalizados ctx.fill(x, y, x + w, y + height, color.getRGB()); ctx.drawTextWithShadow(parent.mc.textRenderer, diff --git a/src/main/java/me/retucio/camtweaks/ui/settings/ClickGUISettingsFrame.java b/src/main/java/me/retucio/camtweaks/ui/frames/ClickGUISettingsFrame.java similarity index 56% rename from src/main/java/me/retucio/camtweaks/ui/settings/ClickGUISettingsFrame.java rename to src/main/java/me/retucio/camtweaks/ui/frames/ClickGUISettingsFrame.java index a6be623..1f1593d 100644 --- a/src/main/java/me/retucio/camtweaks/ui/settings/ClickGUISettingsFrame.java +++ b/src/main/java/me/retucio/camtweaks/ui/frames/ClickGUISettingsFrame.java @@ -1,37 +1,24 @@ -package me.retucio.camtweaks.ui.settings; +package me.retucio.camtweaks.ui.frames; +import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.event.events.camtweaks.GUISettingsFrameEvent; import me.retucio.camtweaks.module.modules.GUI; +import me.retucio.camtweaks.ui.buttons.SettingButton; import me.retucio.camtweaks.util.Colors; import net.minecraft.client.gui.DrawContext; +import java.util.List; + public class ClickGUISettingsFrame extends SettingsFrame { public static final GUI guiSettings = new GUI(); - private boolean extended = false; + public boolean extended = false; private String title = "ajustes de la interfaz -"; public ClickGUISettingsFrame(int x, int y, int w, int h) { super(guiSettings, x, y, w, h); } - @Override - public void mouseClicked(double mouseX, double mouseY, int button) { - if (isHovered(mouseX, mouseY)) { - if (button == 0) { - dragging = true; - dragX = (int) (mouseX - x); - dragY = (int) (mouseY - y); - } else if (button == 1) { - extended = !extended; - title = extended ? "ajustes de la interfaz -" : "ajustes de la interfaz +"; - } - } - - if (!extended) return; // solo dejar clicar en los módulos si el marco está extendido - for (SettingButton settingButton : settingButtons) - settingButton.mouseClicked(mouseX, mouseY, button); - } - @Override public void render(DrawContext ctx, int mouseX, int mouseY, float delta) { updateWidth(); @@ -42,12 +29,49 @@ public class ClickGUISettingsFrame extends SettingsFrame { y + (h / 2) - (mc.textRenderer.fontHeight / 2), -1, false); - if (extended) { - int totalHeight = settingButtons.size() * h + 3; - ctx.fill(x, y + h + 1, x + w, y + h + totalHeight, Colors.frameBGColor); + List visibleButtons = settingButtons.stream() + .filter(sb -> sb.getSetting().isVisible()) + .toList(); - for (SettingButton button : settingButtons) - button.render(ctx, mouseX, mouseY, delta); + if (extended) { + int currentY = y + h + 3; + ctx.fill(x, currentY - 2, x + w, currentY + visibleButtons.size() * h, Colors.frameBGColor); + + for (SettingButton sb : visibleButtons) { + sb.setX(x + 4); + sb.setY(currentY); + sb.setW(w - 8); + sb.setH(h); + sb.render(ctx, mouseX, mouseY, delta); + currentY += h; + } } } -} \ No newline at end of file + + @Override + public void mouseClicked(double mouseX, double mouseY, int button) { + if (isHovered(mouseX, mouseY)) { + if (button == 0) { + dragging = true; + dragX = (int) (mouseX - x); + dragY = (int) (mouseY - y); + } else if (button == 1) { + extended = !extended; + title = extended ? "ajustes de la interfaz -" : "ajustes de la interfaz +"; + CameraTweaks.EVENT_BUS.post(new GUISettingsFrameEvent.Extend()); + } + } + + if (!extended) return; // solo dejar clicar en los módulos si el marco está extendido + for (SettingButton settingButton : settingButtons) + settingButton.mouseClicked(mouseX, mouseY, button); + } + + @Override + public void mouseRelease(double mouseX, double mouseY, int button) { + if (button == 0 && dragging) { + CameraTweaks.EVENT_BUS.post(new GUISettingsFrameEvent.Move()); + } + super.mouseRelease(mouseX, mouseY, button); + } +} diff --git a/src/main/java/me/retucio/camtweaks/ui/ModuleFrame.java b/src/main/java/me/retucio/camtweaks/ui/frames/ModuleFrame.java similarity index 80% rename from src/main/java/me/retucio/camtweaks/ui/ModuleFrame.java rename to src/main/java/me/retucio/camtweaks/ui/frames/ModuleFrame.java index 7b71227..9a71262 100644 --- a/src/main/java/me/retucio/camtweaks/ui/ModuleFrame.java +++ b/src/main/java/me/retucio/camtweaks/ui/frames/ModuleFrame.java @@ -1,14 +1,10 @@ -package me.retucio.camtweaks.ui; +package me.retucio.camtweaks.ui.frames; import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.event.events.camtweaks.ModuleFrameEvent; import me.retucio.camtweaks.module.Module; -import me.retucio.camtweaks.module.settings.EnumSetting; -import me.retucio.camtweaks.module.settings.KeySetting; -import me.retucio.camtweaks.module.settings.NumberSetting; -import me.retucio.camtweaks.ui.settings.BindButton; -import me.retucio.camtweaks.ui.settings.CycleButton; -import me.retucio.camtweaks.ui.settings.SettingButton; -import me.retucio.camtweaks.ui.settings.SliderButton; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.ui.buttons.ModuleButton; import me.retucio.camtweaks.util.Colors; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; @@ -25,7 +21,7 @@ public class ModuleFrame { private final List moduleButtons = new ArrayList<>(); - protected MinecraftClient mc = MinecraftClient.getInstance(); + public MinecraftClient mc = MinecraftClient.getInstance(); public ModuleFrame(int x, int y, int w, int h) { this.x = x; @@ -37,7 +33,7 @@ public class ModuleFrame { // determinar el saliente para cada botón de módulo int offset = h; - for (Module module : CameraTweaks.moduleManager.getModules()) { + for (Module module : ModuleManager.INSTANCE.getModules()) { moduleButtons.add(new ModuleButton(module, this, offset)); updateWidth(); offset += h; @@ -46,6 +42,8 @@ public class ModuleFrame { void updateWidth() { // asegurarse de que todos los botones caben en el marco, haciendo que la anchura se ajuste al texto más largo + if (mc.textRenderer == null) return; + int maxWidth = mc.textRenderer.getWidth(title); for (ModuleButton button : moduleButtons) { String text = button.module.getName(); @@ -88,17 +86,25 @@ public class ModuleFrame { } else if (button == 1) { // clic derecho para extenderlo extended = !extended; title = extended ? "módulos -" : "módulos +"; + CameraTweaks.EVENT_BUS.post(new ModuleFrameEvent.Extend()); } } if (!extended) return; // solo dejar clicar en los módulos si el marco está extendido - for (ModuleButton moduleButton : moduleButtons) - moduleButton.mouseClicked(mouseX, mouseY, button); + for (ModuleButton moduleButton : moduleButtons) { + if (moduleButton.isHovered((int) mouseX, (int) mouseY)) { + moduleButton.mouseClicked(mouseX, mouseY, button); + break; + } + } } // detectar cuándo se suelta el clic public void mouseReleased(double mouseX, double mouseY, int button) { - if (button == 0 && dragging) dragging = false; + if (button == 0 && dragging) { + dragging = false; + } + CameraTweaks.EVENT_BUS.post(new ModuleFrameEvent.Move()); } // verificar si el puntero del ratón se encuentra encima diff --git a/src/main/java/me/retucio/camtweaks/ui/settings/SettingsFrame.java b/src/main/java/me/retucio/camtweaks/ui/frames/SettingsFrame.java similarity index 73% rename from src/main/java/me/retucio/camtweaks/ui/settings/SettingsFrame.java rename to src/main/java/me/retucio/camtweaks/ui/frames/SettingsFrame.java index 034a795..f59393a 100644 --- a/src/main/java/me/retucio/camtweaks/ui/settings/SettingsFrame.java +++ b/src/main/java/me/retucio/camtweaks/ui/frames/SettingsFrame.java @@ -1,13 +1,18 @@ -package me.retucio.camtweaks.ui.settings; +package me.retucio.camtweaks.ui.frames; +import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.event.events.camtweaks.SettingsFrameEvent; import me.retucio.camtweaks.module.Module; import me.retucio.camtweaks.module.settings.*; import me.retucio.camtweaks.ui.ClickGUI; +import me.retucio.camtweaks.ui.buttons.*; +import me.retucio.camtweaks.ui.buttons.SliderButton; +import me.retucio.camtweaks.ui.buttons.TextButton; +import me.retucio.camtweaks.ui.buttons.ToggleButton; import me.retucio.camtweaks.util.Colors; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; -import java.awt.Color; import java.util.ArrayList; import java.util.List; @@ -20,11 +25,11 @@ public class SettingsFrame { public int x, y, w, h; boolean dragging; - int dragX; - int dragY; + int dragX, dragY; - final MinecraftClient mc = MinecraftClient.getInstance(); + public final MinecraftClient mc = MinecraftClient.getInstance(); + @SuppressWarnings({"rawtypes", "unchecked"}) public SettingsFrame(Module module, int x, int y, int w, int h) { this.module = module; this.x = x; @@ -63,11 +68,14 @@ public class SettingsFrame { updateWidth(); // actualizar anchura del frame tras cada iteración } + @SuppressWarnings("rawtypes") void updateWidth() { // asegurarse de que todos los botones caben en el marco, haciendo que la anchura se ajuste al texto más largo + if (mc.textRenderer == null) return; + int maxWidth = mc.textRenderer.getWidth(title); for (SettingButton button : settingButtons) { - String text = button.setting.getName(); + String text = button.getSetting().getName(); switch (button) { case SliderButton sliderButton -> text += ": " + sliderButton.df.format((sliderButton.getSetting()).getValue()); @@ -94,25 +102,24 @@ public class SettingsFrame { y + (h / 2) - (mc.textRenderer.fontHeight / 2), -1, false); - // si no hay ajustes disponibles para un módulo, hacerle saber al usuario - if (settingButtons.isEmpty()) { - String msg = "no hay ajustes :("; - ctx.fill(x, y + h, x + w, y + 2 * h, Colors.frameBGColor); + List visibleButtons = settingButtons.stream() + .filter(sb -> sb.getSetting().isVisible()) + .toList(); - ctx.drawText(mc.textRenderer, msg, - x + (w / 2) - (mc.textRenderer.getWidth(msg) / 2), - (int) (y + h * 1.25), - -1, false); - return; + int currentY = y + h + 3; + ctx.fill(x, currentY - 2, x + w, currentY + visibleButtons.size() * h, Colors.frameBGColor); + + for (SettingButton sb : visibleButtons) { + sb.setX(x + 4); + sb.setY(currentY); + sb.setW(w - 8); + sb.setH(h); + sb.render(ctx, mouseX, mouseY, delta); + currentY += h; } - - int totalHeight = settingButtons.size() * h + 3; - ctx.fill(x, y + h + 1, x + w, y + h + totalHeight, Colors.frameBGColor); - - for (SettingButton sb : settingButtons) - if (sb.setting.isVisible()) sb.render(ctx, mouseX, mouseY, delta); } + public void mouseClicked(double mouseX, double mouseY, int button) { if (isHovered(mouseX, mouseY)) { if (button == 0) { @@ -125,13 +132,17 @@ public class SettingsFrame { } for (SettingButton sb : settingButtons) - if (sb.setting.isVisible()) sb.mouseClicked(mouseX, mouseY, button); + if (sb.getSetting().isVisible()) + sb.mouseClicked(mouseX, mouseY, button); } public void mouseRelease(double mouseX, double mouseY, int button) { - if (button == 0) dragging = false; + if (button == 0) { + dragging = false; + CameraTweaks.EVENT_BUS.post(new SettingsFrameEvent.Move(this)); + } for (SettingButton sb : settingButtons) - if (sb.setting.isVisible()) sb.mouseReleased(mouseX, mouseY, button); + if (sb.getSetting().isVisible()) sb.mouseReleased(mouseX, mouseY, button); } public void updatePosition(double mouseX, double mouseY) { @@ -141,7 +152,7 @@ public class SettingsFrame { } } - boolean isHovered(double mouseX, double mouseY) { + public boolean isHovered(double mouseX, double mouseY) { return mouseX > x && mouseX < x + w && mouseY > y && mouseY < y + h; } diff --git a/src/main/java/me/retucio/camtweaks/ui/widgets/SearchBarWidget.java b/src/main/java/me/retucio/camtweaks/ui/widgets/SearchBarWidget.java new file mode 100644 index 0000000..2828ef8 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/ui/widgets/SearchBarWidget.java @@ -0,0 +1,52 @@ +package me.retucio.camtweaks.ui.widgets; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gl.RenderPipelines; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; + +public class SearchBarWidget extends TextFieldWidget { + + private static final Identifier MENU_LIST_BACKGROUND_TEXTURE = Identifier.ofVanilla("textures/gui/menu_list_background.png"); + private static final Identifier INWORLD_MENU_LIST_BACKGROUND_TEXTURE = Identifier.ofVanilla("textures/gui/inworld_menu_list_background.png"); + + private boolean hookBackground; + + public SearchBarWidget(TextRenderer textRenderer, int width, int height) { + super(textRenderer, width, height, Text.empty()); + } + + @Override + public void renderWidget(DrawContext context, int mouseX, int mouseY, float deltaTicks) { + if (drawsBackground()) drawBackground(context); + + hookBackground = true; + super.renderWidget(context, mouseX, mouseY, deltaTicks); + hookBackground = false; + } + + @Override + public boolean drawsBackground() { + if (hookBackground) return false; + return super.drawsBackground(); + } + + private void drawBackground(DrawContext context) { + Identifier identifier = MinecraftClient.getInstance().world == null ? MENU_LIST_BACKGROUND_TEXTURE : INWORLD_MENU_LIST_BACKGROUND_TEXTURE; + context.drawTexture( + RenderPipelines.GUI, + identifier, + this.getX(), + this.getY(), + this.getRight(), + this.getBottom(), + this.getWidth(), + this.getHeight(), + 32, + 32 + ); + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/util/ChatUtil.java b/src/main/java/me/retucio/camtweaks/util/ChatUtil.java index 57e1121..8c4274c 100644 --- a/src/main/java/me/retucio/camtweaks/util/ChatUtil.java +++ b/src/main/java/me/retucio/camtweaks/util/ChatUtil.java @@ -1,5 +1,6 @@ package me.retucio.camtweaks.util; +import me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame; import net.minecraft.client.MinecraftClient; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -8,12 +9,15 @@ import net.minecraft.util.Formatting; public class ChatUtil { private static final MinecraftClient mc = MinecraftClient.getInstance(); + private static String prefix = Formatting.GREEN + "[" + ClickGUISettingsFrame.guiSettings.chatName.getValue() + "] "; public static void addMessage(String text) { + if (mc.inGameHud == null) return; mc.inGameHud.getChatHud().addMessage(Text.of(text)); } public static void addMessage(Text text) { + if (mc.inGameHud == null) return; mc.inGameHud.getChatHud().addMessage(text); } @@ -22,31 +26,31 @@ public class ChatUtil { } public static void addMessageWithPrefix(Text text) { - addMessage(Text.literal(Formatting.GREEN + "[smegma] " + Formatting.RESET).append(text)); + addMessage(Text.literal(prefix + Formatting.RESET).append(text)); } public static void info(String text) { - addMessage(Text.literal(Formatting.GREEN + "[smegma] " + Formatting.RESET + text)); + addMessage(Text.literal(prefix + Formatting.RESET + text)); } public static void info(Text text) { - addMessage(Text.literal(Formatting.GREEN + "[smegma] " + Formatting.RESET).append(text)); + addMessage(Text.literal(prefix + Formatting.RESET).append(text)); } public static void warn(String text) { - addMessage(Text.literal(Formatting.GREEN + "[smegma] " + Formatting.YELLOW + text)); + addMessage(Text.literal(prefix + Formatting.YELLOW + text)); } public static void warn(Text text) { - addMessage(Text.literal(Formatting.GREEN + "[smegma] " + Formatting.YELLOW).append(text)); + addMessage(Text.literal(prefix + Formatting.YELLOW).append(text)); } public static void error(String text) { - addMessage(Text.literal(Formatting.GREEN + "[smegma] " + Formatting.RED + text)); + addMessage(Text.literal(prefix + Formatting.RED + text)); } public static void error(Text text) { - addMessage(Text.literal(Formatting.GREEN + "[smegma] " + Formatting.RED).append(text)); + addMessage(Text.literal(prefix + Formatting.RED).append(text)); } public static void sendServerMessage(String text) { @@ -57,4 +61,16 @@ public class ChatUtil { if (mc.player == null) return; mc.player.sendMessage(text, false); } + + public static String getPrefix() { + return prefix; + } + + public static String getPrefixNoFormatting() { + return "[" + ClickGUISettingsFrame.guiSettings.chatName.getValue() + "] "; + } + + public static void updatePrefix(String newPrefix) { + prefix = Formatting.GREEN + "[" + newPrefix + "] "; + } } diff --git a/src/main/java/me/retucio/camtweaks/util/Colors.java b/src/main/java/me/retucio/camtweaks/util/Colors.java index 4c91855..9190fe8 100644 --- a/src/main/java/me/retucio/camtweaks/util/Colors.java +++ b/src/main/java/me/retucio/camtweaks/util/Colors.java @@ -1,13 +1,11 @@ package me.retucio.camtweaks.util; -import me.retucio.camtweaks.ui.ClickGUI; - import java.awt.*; -import static me.retucio.camtweaks.ui.settings.ClickGUISettingsFrame.guiSettings; +import static me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame.guiSettings; -// interfaz para los colores, para no repetirme (regla DRY) +// clase para los colores, para no repetirme (regla DRY) // si se ve especificado como color en algún lado "-1", significa blanco public class Colors { @@ -30,12 +28,12 @@ public class Colors { public static int hoveredModuleButtonColor = new Color(30, 30, 30, 100).getRGB(); public static int moduleButtonColor = new Color(40, 40, 40, 75).getRGB(); - public static int hoveredCycleButtonColor = new Color(70, 70, 70, 180).getRGB(); - public static int cycleButtonColor = new Color(50, 50, 50, 150).getRGB(); - + public static int hoveredSettingButtonColor = new Color(30, 30, 30, 100).getRGB(); + public static int settingButtonColor = new Color(40, 40, 40, 75).getRGB(); public static int sliderFillingColor = new Color(60, 120, 220, 180).getRGB(); // necesitan ser de tipo java.awt.Color para utilizar el método .brighter() public static Color enabledToggleButtonColor = new Color(0, 180, 0, 180); public static Color disabledToggleButtonColor = new Color(120, 30, 30, 150); + } diff --git a/src/main/java/me/retucio/camtweaks/util/KeyUtil.java b/src/main/java/me/retucio/camtweaks/util/KeyUtil.java index 8dc7f71..1967999 100644 --- a/src/main/java/me/retucio/camtweaks/util/KeyUtil.java +++ b/src/main/java/me/retucio/camtweaks/util/KeyUtil.java @@ -1,6 +1,8 @@ package me.retucio.camtweaks.util; import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.mixin.accessor.KeyBindingAccessor; +import net.minecraft.client.option.KeyBinding; import org.lwjgl.glfw.GLFW; // cosas útiles relacionadas a las teclas @@ -12,34 +14,69 @@ public class KeyUtil { key) != GLFW.GLFW_RELEASE; } + public static boolean isKeyDown(KeyBinding key) { + return GLFW.glfwGetKey( + CameraTweaks.mc.getWindow().getHandle(), + ((KeyBindingAccessor) key).getBoundKey().getCode() + ) != GLFW.GLFW_RELEASE; + } + public static String getKeyName(int key) { - if (key == GLFW.GLFW_KEY_UNKNOWN) return "ninguna"; + if (key == GLFW.GLFW_KEY_UNKNOWN) return "ninguna"; - String name = GLFW.glfwGetKeyName(key, 0); - if (name != null) return name.toUpperCase(); + String name = GLFW.glfwGetKeyName(key, 0); + if (name != null) return name.toUpperCase(); - // para teclas especiales - return switch (key) { - case GLFW.GLFW_KEY_SPACE -> "espacio"; - case GLFW.GLFW_KEY_LEFT_SHIFT -> "shift izquierdo"; - case GLFW.GLFW_KEY_RIGHT_SHIFT -> "shift derecho"; - case GLFW.GLFW_KEY_LEFT_CONTROL -> "ctrl izquierdo"; - case GLFW.GLFW_KEY_RIGHT_CONTROL -> "ctrl derecho"; - case GLFW.GLFW_KEY_LEFT_ALT -> "alt izquierdo"; - case GLFW.GLFW_KEY_RIGHT_ALT -> "alt gr"; - case GLFW.GLFW_KEY_TAB -> "tab"; - case GLFW.GLFW_KEY_ENTER -> "enter"; - case GLFW.GLFW_KEY_BACKSPACE -> "borrar"; - case GLFW.GLFW_KEY_DELETE -> "suprimir"; - case GLFW.GLFW_KEY_UP -> "arriba"; - case GLFW.GLFW_KEY_DOWN -> "abajo"; - case GLFW.GLFW_KEY_LEFT -> "izquierda"; - case GLFW.GLFW_KEY_RIGHT -> "derecha"; - default -> { // F1–F25 - if (key >= GLFW.GLFW_KEY_F1 && key <= GLFW.GLFW_KEY_F25) - yield "F" + (key - GLFW.GLFW_KEY_F1 + 1); - yield "tecla " + key; - } - }; - } + // para teclas especiales + return switch (key) { + case GLFW.GLFW_KEY_SPACE -> "espacio"; + case GLFW.GLFW_KEY_LEFT_SHIFT -> "shift izquierdo"; + case GLFW.GLFW_KEY_RIGHT_SHIFT -> "shift derecho"; + case GLFW.GLFW_KEY_LEFT_CONTROL -> "ctrl izquierdo"; + case GLFW.GLFW_KEY_RIGHT_CONTROL -> "ctrl derecho"; + case GLFW.GLFW_KEY_LEFT_ALT -> "alt izquierdo"; + case GLFW.GLFW_KEY_RIGHT_ALT -> "alt gr"; + case GLFW.GLFW_KEY_TAB -> "tab"; + case GLFW.GLFW_KEY_ENTER -> "enter"; + case GLFW.GLFW_KEY_BACKSPACE -> "borrar"; + case GLFW.GLFW_KEY_DELETE -> "suprimir"; + case GLFW.GLFW_KEY_UP -> "arriba"; + case GLFW.GLFW_KEY_DOWN -> "abajo"; + case GLFW.GLFW_KEY_LEFT -> "izquierda"; + case GLFW.GLFW_KEY_RIGHT -> "derecha"; + default -> { // F1–F25 + if (key >= GLFW.GLFW_KEY_F1 && key <= GLFW.GLFW_KEY_F25) + yield "F" + (key - GLFW.GLFW_KEY_F1 + 1); + yield "tecla " + key; + } + }; + } + + // quizás debería de añadir layouts... + public static String shiftKey(String c) { + return switch (c) { + case "`" -> "~"; + case "1" -> "!"; + case "2" -> "@"; + case "3" -> "#"; + case "4" -> "$"; + case "5" -> "%"; + case "6" -> "^"; + case "7" -> "&"; + case "8" -> "*"; + case "9" -> "("; + case "0" -> ")"; + case "-" -> "_"; + case "=" -> "+"; + case "[" -> "{"; + case "]" -> "}"; + case "\\" -> "|"; + case ";" -> ":"; + case "'" -> "\""; + case "," -> "<"; + case "." -> ">"; + case "/" -> "?"; + default -> c.toUpperCase(); + }; + } } diff --git a/src/main/java/me/retucio/camtweaks/util/MiscUtil.java b/src/main/java/me/retucio/camtweaks/util/MiscUtil.java new file mode 100644 index 0000000..faf5740 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/util/MiscUtil.java @@ -0,0 +1,39 @@ +package me.retucio.camtweaks.util; + +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.event.events.TickEvent; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import org.joml.Vector3d; + +import static me.retucio.camtweaks.CameraTweaks.mc; + +public class MiscUtil { + + public static Screen screen; + + private MiscUtil() {} + + @SubscribeEvent + public static void onTick(TickEvent.Post event) { + if (screen != null && mc.currentScreen == null) { + mc.setScreen(screen); + screen = null; + } + } + + public static void copyVector(Vector3d destination, Vec3d source) { + destination.x = source.x; + destination.y = source.y; + destination.z = source.z; + } + + public static Vector3d getEntityVector(Vector3d vector, Entity entity, double tickDelta) { + vector.x = MathHelper.lerp(tickDelta, entity.lastRenderX, entity.getX()); + vector.y = MathHelper.lerp(tickDelta, entity.lastRenderY, entity.getY()); + vector.z = MathHelper.lerp(tickDelta, entity.lastRenderZ, entity.getZ()); + return vector; + } +} diff --git a/src/main/java/me/retucio/camtweaks/util/interfaces/IVec3d.java b/src/main/java/me/retucio/camtweaks/util/interfaces/IVec3d.java new file mode 100644 index 0000000..d3fd230 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/util/interfaces/IVec3d.java @@ -0,0 +1,14 @@ +package me.retucio.camtweaks.util.interfaces; + +import net.minecraft.util.math.Vec3i; +import org.joml.Vector3d; + +public interface IVec3d { + + void smegma$set(double x, double y, double z); + default void smegma$set(Vec3i vec) { smegma$set(vec.getX(), vec.getY(), vec.getZ()); } + default void semgma$set(Vector3d vec) { smegma$set(vec.x, vec.y, vec.z); } + + void smegma$setXZ(double x, double z); + void smegma$setY(double y); +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/util/interfaces/TextVisitor.java b/src/main/java/me/retucio/camtweaks/util/interfaces/TextVisitor.java index 86990aa..8d5a50e 100644 --- a/src/main/java/me/retucio/camtweaks/util/interfaces/TextVisitor.java +++ b/src/main/java/me/retucio/camtweaks/util/interfaces/TextVisitor.java @@ -1,3 +1,5 @@ +/* code by meteorclient dev team */ + package me.retucio.camtweaks.util.interfaces; import net.minecraft.text.PlainTextContent; @@ -9,6 +11,9 @@ import java.util.ArrayDeque; import java.util.Optional; import java.util.Queue; +// lo siento por robaros el código, meteor :( +// sorry for stealing your code, meteor dev team + @FunctionalInterface public interface TextVisitor { Optional accept(Text text, Style style, String string); diff --git a/src/main/resources/assets/camtweaks/icon_mc.png b/src/main/resources/assets/camtweaks/icon_mc.png new file mode 100644 index 0000000..0c0fbf8 Binary files /dev/null and b/src/main/resources/assets/camtweaks/icon_mc.png differ diff --git a/src/main/resources/camtweaks.mixins.json b/src/main/resources/camtweaks.mixins.json index 8b04163..2125317 100644 --- a/src/main/resources/camtweaks.mixins.json +++ b/src/main/resources/camtweaks.mixins.json @@ -3,7 +3,14 @@ "package": "me.retucio.camtweaks.mixin", "compatibilityLevel": "JAVA_21", "mixins": [ + "ClientConnectionMixin", + "DimensionTypeMixin", + "EntityMixin", + "ItemEntityMixin", + "KeyInputMixin", + "PlayerEntityMixin", "StringHelperMixin", + "Vec3dMixin", "accessor.StatusEffectInstanceAccessor" ], "injectors": { @@ -13,21 +20,34 @@ "requireAnnotations": true }, "client": [ + "BossBarHudMixin", "CameraMixin", "ChatHudLineMixin", "ChatHudLineVisibleMixin", "ChatHudMixin", "ChatInputSuggestorMixin", "ChatScreenMixin", + "ChunkBorderDebugRendererMixin", + "ChunkOcclusionDataBuilderMixin", "ClientPlayNetworkHandlerMixin", + "ClientWorldPropertiesMixin", + "CompassStateMixin", + "EntityRendererMixin", "GameOptionsMixin", "GameRendererMixin", "HeldItemRendererMixin", "InGameHudMixin", "KeyboardMixin", "LightmapTextureManagerMixin", + "LivingEntityRendererMixin", "MessageHandlerMixin", "MinecraftClientMixin", - "MouseMixin" + "MouseMixin", + "ScreenMixin", + "SkyRendererMixin", + "WorldRendererMixin", + "accessor.ClientPlayNetworkHandlerAccessor", + "accessor.EntityRenderStateAccessor", + "accessor.KeyBindingAccessor" ] } \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index cc2d6ee..8c9ee72 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -5,7 +5,7 @@ "name": "mod de putas de retucio", "description": "cositas chulas pa la cámara", "authors": [ - "prepucio" + "el prepu" ], "contact": { "homepage": "https://github.com/retuci0", @@ -16,6 +16,7 @@ "environment": "*", "entrypoints": { "main": [ + ], "client": [ "me.retucio.camtweaks.CameraTweaks" ] },