diff --git a/.gitignore b/.gitignore index 0cb7916..8c630fc 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,10 @@ replay_*.log *.hprof *.jfr +# otros + todo.txt test.java -cambios.md \ No newline at end of file +cambios.md +# no está terminado +src/main/java/me/retucio/camtweaks/module/modules/TooltipsPlus.java \ No newline at end of file diff --git a/cambios.md b/cambios.md index f7c4dda..6627253 100644 --- a/cambios.md +++ b/cambios.md @@ -1,27 +1,23 @@ -# v1.3 +# v1.4 ## novedades +- actualización a la 1.21.10 + ### adiciones -- barra de búsqueda: filtra los ajustes de todos los paneles de ajustes, por nombre y descripción -- barra de deslizamiento -- módulo de jugador falso: invoca una entidad de jugador falsa, por motivos de testeo -- HUD: mostrar información adicional en pantalla (ej.: hora, fps, coordenadas, ...) +interfaz en portales: te permite interactuar con interfaces estando dentro de un bloque de portal del nether ### arreglos / mejoras -- mejoras a la interfaz - - ahora el color de los widgets depende del color principal - - ahora solo se puede seleccionar un objeto de la interfaz a la vez - - cambiada la posición de los títulos de los marcos - -- ahora los módulos están ordenados por orden alfabético - -- ahora nametags también tiene en cuenta la absorción de un jugador al mostrar su vida - -- el color del prefijo de las notificaciones por chat ahora depende de los ajustes de color -- ya no se muestra el prefijo equivocado en notificaciones por chat al meterse a un mundo por primera vez +- ahora puedes elegir con qué items aparece el nametag, útil para poder distinguir unos items de otros +- ahora F1 también oculta los elementos del HUD, y ya no se muestra en la pantalla de inicio +- ahora los items con el nombre cambiado usarán este en sus nametags, y estarán en cursiva +- ahora puedes elegir si el contorno de los bloques se renderiza en modo cámara libre +- ya no se activarán / desactivarán módulos cuando la tecla F3 esté presionada, para evitar intervenir en combinaciones de teclas con F3 +- arreglado lo de la ceguera y la oscuridad de NoRender (en un principio) +- si una tecla ya está cogida por otra acción, a menos que teclas multimódulos esté activado, se previene configurar esta tecla a un módulo +- poco más la verdad ## problemas reconocidos diff --git a/gradle.properties b/gradle.properties index ac7a1ef..488f492 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,15 +4,15 @@ org.gradle.parallel=true # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.21.6 -yarn_mappings=1.21.6+build.1 -loader_version=0.17.2 +minecraft_version=1.21.10 +yarn_mappings=1.21.10+build.2 +loader_version=0.17.3 loom_version=1.11-SNAPSHOT # Mod Properties -mod_version=1.3 +mod_version=1.4 maven_group=me.retucio archives_base_name=camtweaks # Dependencies -fabric_version=0.128.2+1.21.6 \ No newline at end of file +fabric_version=0.135.0+1.21.10 \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/CameraTweaks.java b/remappedSrc/me/retucio/camtweaks/CameraTweaks.java new file mode 100644 index 0000000..ded60d7 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/CameraTweaks.java @@ -0,0 +1,178 @@ +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.event.events.camtweaks.LoadClickGUIEvent; +import me.retucio.camtweaks.event.events.camtweaks.LoadCommandManagerEvent; +import me.retucio.camtweaks.event.events.camtweaks.LoadModuleManagerEvent; +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.ModuleManager; + +import me.retucio.camtweaks.ui.ClickGUI; +import me.retucio.camtweaks.ui.buttons.BindButton; +import me.retucio.camtweaks.ui.buttons.SettingButton; +import me.retucio.camtweaks.ui.buttons.TextButton; +import me.retucio.camtweaks.ui.frames.ClientSettingsFrame; +import me.retucio.camtweaks.ui.frames.SettingsFrame; + +import me.retucio.camtweaks.util.ChatUtil; +import me.retucio.camtweaks.util.KeyUtil; +import me.retucio.camtweaks.util.Lists; +import me.retucio.camtweaks.util.MiscUtil; + + +import net.fabricmc.api.ClientModInitializer; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; + +import net.minecraft.client.gui.screen.TitleScreen; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import org.lwjgl.glfw.GLFW; + + + +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 MinecraftClient mc; + + private Screen prevScreen; + public boolean settingsApplied = false; + + @Override + public void onInitializeClient() { + // por algún motivo aunque lo añada a los args de la JVM sigue siendo true a menos que haga esto??? puta vida + System.setProperty("java.awt.headless", "false"); + + mc = MinecraftClient.getInstance(); + + EVENT_BUS.register(this); + EVENT_BUS.register(MiscUtil.class); + EVENT_BUS.register(ChatUtil.class); + + Lists.init(); + + ModuleManager.INSTANCE = new ModuleManager(EVENT_BUS); + EVENT_BUS.post(new LoadModuleManagerEvent()); + + CommandManager.INSTANCE = new CommandManager(); + EVENT_BUS.post(new LoadCommandManagerEvent()); + + ClickGUI.INSTANCE = new ClickGUI(); + EVENT_BUS.post(new LoadClickGUIEvent()); + + ConfigManager.load(); + + 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.INSTANCE.getEnabledModules().forEach(module -> module.onKey(key, action)); + + boolean anyFocused = isAnySettingButtonFocused() || ClickGUI.INSTANCE.getSearchBar().isFocused(); + ClickGUI.INSTANCE.setAnyFocused(anyFocused); + + if (action == GLFW.GLFW_PRESS) { + if (BindCommand.onKeyPress(key)) return; + handleSettingButtonsKey(key, action); + handleModuleToggle(key, anyFocused); + handleClickGUIKey(key, anyFocused); + } else if (action == GLFW.GLFW_RELEASE && !anyFocused) { + handleModuleRelease(key); + } + } + + // verifica si algún botón de ajustes está escuchando + private boolean isAnySettingButtonFocused() { + 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; + } + + // se ocupa de la lógica de encendido y apagado de los módulos + private void handleModuleToggle(int key, boolean anyFocused) { + if (mc.currentScreen != null && mc.currentScreen != ClickGUI.INSTANCE) return; + + 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); + else if (!module.shouldToggleOnBindRelease()) + module.toggle(); + } + } + + // se ocupa de hacer los botones de ajustes que lo necesiten escuchar teclas + private void handleSettingButtonsKey(int key, int action) { + for (SettingsFrame sf : ClickGUI.INSTANCE.getSettingsFrames()) { + for (SettingButton sb : sf.getButtons()) { + if (sb instanceof BindButton b) b.onKey(key, action); + else if (sb instanceof TextButton t) t.onKey(key, action); + } + } + } + + // maneja la lógica de apertura de la interfaz + private void handleClickGUIKey(int key, boolean anyFocused) { + if (key != ClientSettingsFrame.guiSettings.getKey() || anyFocused) return; + + // al parecer esto hace que con la tecla de la interfaz puedas ir cambiando de splash text en la pantalla del título + // pero me ha hecho gracia así que así se queda + if (mc.currentScreen != ClickGUI.INSTANCE && !(mc.currentScreen instanceof TitleScreen)) { + prevScreen = mc.currentScreen; + mc.setScreen(ClickGUI.INSTANCE); + } else { + ClickGUI.INSTANCE.close(); + mc.setScreen(prevScreen); + } + } + + // se ocupa de apagar los módulos que tengan configurado hacerlo tras soltar su tecla + private void handleModuleRelease(int key) { + if (mc.currentScreen != null && mc.currentScreen != ClickGUI.INSTANCE) return; + + for (Module module : ModuleManager.INSTANCE.getEnabledModules()) + if (module.shouldToggleOnBindRelease() && key == module.getKey()) + module.setEnabled(false); + } + + @SubscribeEvent + public void onStop(ShutdownEvent event) { + ConfigManager.save(); + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/command/Command.java b/remappedSrc/me/retucio/camtweaks/command/Command.java new file mode 100644 index 0000000..b560d53 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/command/Command.java @@ -0,0 +1,76 @@ +package me.retucio.camtweaks.command; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import net.minecraft.client.MinecraftClient; +import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.command.CommandSource; +import net.minecraft.registry.BuiltinRegistries; +import net.minecraft.server.command.CommandManager; + +import java.util.List; + +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; + private final List aliases; + + public Command(String name, String description, String... aliases) { + this.name = name; + this.description = description; + this.aliases = List.of(aliases); + } + + // métodos "helper" para reducir el "boilerplate" + protected static RequiredArgumentBuilder argument(final String name, final ArgumentType type) { + return RequiredArgumentBuilder.argument(name, type); + } + + protected static LiteralArgumentBuilder literal(final String name) { + return LiteralArgumentBuilder.literal(name); + } + + // para registrar comandos + public final void registerTo(CommandDispatcher dispatcher) { + register(dispatcher, name); + for (String alias : aliases) register(dispatcher, alias); + } + + public void register(CommandDispatcher dispatcher, String name) { + LiteralArgumentBuilder builder = LiteralArgumentBuilder.literal(name); + build(builder); + dispatcher.register(builder); + } + + public abstract void build(LiteralArgumentBuilder builder); + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public List getAliases() { + return aliases; + } + + public String toString() { + return me.retucio.camtweaks.command.CommandManager.INSTANCE.getPrefix() + name; + } + + public String toString(String... args) { + StringBuilder sb = new StringBuilder(toString()); + for (String arg : args) sb.append(" ").append(arg); + return sb.toString(); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/command/CommandManager.java b/remappedSrc/me/retucio/camtweaks/command/CommandManager.java new file mode 100644 index 0000000..6e50973 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/command/CommandManager.java @@ -0,0 +1,79 @@ +package me.retucio.camtweaks.command; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import me.retucio.camtweaks.command.commands.*; +import net.minecraft.client.MinecraftClient; +import net.minecraft.command.CommandSource; + +import java.util.ArrayList; +import java.util.List; +import java.util.Comparator; +import java.util.Objects; + +// registro de comandos +public class CommandManager { + + public static CommandManager INSTANCE; + + private String prefix = "$"; + + public static final List commands = new ArrayList<>(); + public static final CommandDispatcher dispatcher = new CommandDispatcher<>(); + + private static final MinecraftClient mc = MinecraftClient.getInstance(); + + public CommandManager() { + registerCommands(); + } + + public static void registerCommands() { + addCommand(new BindCommand()); + addCommand(new CopyScreenshotCommand()); +// addCommand(new EnderChestCommand()); no funciona D: + addCommand(new PeekCommand()); + addCommand(new PrefixCommand()); + addCommand(new PurgeCommand()); + addCommand(new SaveScreenshotCommand()); + addCommand(new SendCommand()); + addCommand(new ToggleCommand()); + + commands.sort(Comparator.comparing(Command::getName)); + } + + public static void addCommand(Command command) { + commands.removeIf(existing -> existing.getName().equals(command.getName())); + command.registerTo(dispatcher); + commands.add(command); + } + + public static void dispatch(String message) throws CommandSyntaxException { + dispatcher.execute(message, Objects.requireNonNull(mc.getNetworkHandler()).getCommandSource()); + } + + public static Command getCommandByName(String name) { + for (Command command : commands) { + if (command.getName().equals(name)) return command; + + for (String alias : command.getAliases()) + if (alias.equals(name)) return command; + } + + return null; + } + + public T getCommandByClass(Class clazz) { + for (Command command : commands) + if (clazz.isInstance(command)) + return clazz.cast(command); + return null; + } + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/command/args/ModuleArgumentType.java b/remappedSrc/me/retucio/camtweaks/command/args/ModuleArgumentType.java new file mode 100644 index 0000000..8ad1416 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/command/args/ModuleArgumentType.java @@ -0,0 +1,49 @@ +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 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; + +// 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.INSTANCE.getModules() + .stream().limit(3).map(module -> module.getName().replace(" ", "_")).toList(); + + @Override + public Module parse(StringReader reader) throws CommandSyntaxException { + 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.INSTANCE.getModules().stream().map(module -> module.getName().replace(" ", "_")), builder); + } + + @Override + public Collection getExamples() { + return examples; + } + + public static Module get(CommandContext ctx) { + return ctx.getArgument("módulo", Module.class); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/command/args/PlayerArgumentType.java b/remappedSrc/me/retucio/camtweaks/command/args/PlayerArgumentType.java new file mode 100644 index 0000000..62ad6e8 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/command/commands/BindCommand.java b/remappedSrc/me/retucio/camtweaks/command/commands/BindCommand.java new file mode 100644 index 0000000..4e60268 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/command/commands/BindCommand.java @@ -0,0 +1,56 @@ +package me.retucio.camtweaks.command.commands; + +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.settings.KeySetting; +import me.retucio.camtweaks.util.ChatUtil; +import me.retucio.camtweaks.util.KeyUtil; +import net.minecraft.command.CommandSource; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// asignar una tecla a un módulo, lógica similar a BindButton +public class BindCommand extends Command { + + private static Module listeningModule = null; + + public BindCommand() { + super("bind", "asigna una tecla a un módulo", "keybind"); + } + + @Override + public void build(LiteralArgumentBuilder builder) { + builder + .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 " + 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 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()) + ); + + listeningModule = null; + return true; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/command/commands/CopyScreenshotCommand.java b/remappedSrc/me/retucio/camtweaks/command/commands/CopyScreenshotCommand.java new file mode 100644 index 0000000..a53b4f4 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/command/commands/CopyScreenshotCommand.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.module.ModuleManager; +import me.retucio.camtweaks.module.modules.ScreenshotPlus; +import net.minecraft.command.CommandSource; + +// se usa principalmente para el módulo ScreenshotPlus, pero también se puede usar sin él supongo +public class CopyScreenshotCommand extends Command { + + public CopyScreenshotCommand() { + super("copiarcaptura", "copia la captura más reciente al portapapeles"); + } + + @Override + public void build(LiteralArgumentBuilder builder) { + builder.executes(ctx -> { + ScreenshotPlus screenshotPlus = ModuleManager.INSTANCE.getModuleByClass(ScreenshotPlus.class); + + if (screenshotPlus.getScreenshot() != null) mc.execute(screenshotPlus::copyScreenshot); + + return SUCCESS; + }); + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/command/commands/EnderChestCommand.java b/remappedSrc/me/retucio/camtweaks/command/commands/EnderChestCommand.java new file mode 100644 index 0000000..562ace0 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/command/commands/PeekCommand.java b/remappedSrc/me/retucio/camtweaks/command/commands/PeekCommand.java new file mode 100644 index 0000000..3b8403f --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/command/commands/PrefixCommand.java b/remappedSrc/me/retucio/camtweaks/command/commands/PrefixCommand.java new file mode 100644 index 0000000..53aff00 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/command/commands/PrefixCommand.java @@ -0,0 +1,29 @@ +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.frames.ClientSettingsFrame; +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() { + super("prefijo", "cambia el prefijo de los comandos", "prefix"); + } + + @Override + public void build(LiteralArgumentBuilder builder) { + builder + .then(argument("prefijo", StringArgumentType.word()).executes(ctx -> { + String prefix = ctx.getArgument("prefijo", String.class); + ClientSettingsFrame.guiSettings.commandPrefix.setValue(prefix); + ChatUtil.info(Text.literal("prefijo cambiado a " + Formatting.AQUA + prefix)); + return SUCCESS; + })); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/command/commands/PurgeCommand.java b/remappedSrc/me/retucio/camtweaks/command/commands/PurgeCommand.java new file mode 100644 index 0000000..b2f0d78 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/command/commands/PurgeCommand.java @@ -0,0 +1,40 @@ +package me.retucio.camtweaks.command.commands; + +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import me.retucio.camtweaks.command.Command; +import me.retucio.camtweaks.util.interfaces.IChatHud; +import net.minecraft.client.gui.hud.ChatHud; +import net.minecraft.client.gui.hud.ChatHudLine; +import net.minecraft.command.CommandSource; + +import java.util.List; + +public class PurgeCommand extends Command { + + public PurgeCommand() { + super("purgar", "elimina mensajes del chat", "purge"); + } + + @Override + public void build(LiteralArgumentBuilder builder) { + builder.then(argument("cantidad", IntegerArgumentType.integer(1)) + .executes(context -> { + int amount = IntegerArgumentType.getInteger(context, "cantidad"); + purgeMessages(amount); + return 1; + }) + ); + } + + private void purgeMessages(int amount) { + ChatHud chatHud = mc.inGameHud.getChatHud(); + + synchronized (chatHud) { + List visibleMessages = ((IChatHud) chatHud).smegma$getVisibleMessages(); + int toRemove = Math.min(amount, visibleMessages.size()); + for (int i = 0; i < toRemove; i++) + visibleMessages.removeFirst(); + } + } +} diff --git a/remappedSrc/me/retucio/camtweaks/command/commands/SaveScreenshotCommand.java b/remappedSrc/me/retucio/camtweaks/command/commands/SaveScreenshotCommand.java new file mode 100644 index 0000000..2e210b7 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/command/commands/SaveScreenshotCommand.java @@ -0,0 +1,37 @@ +package me.retucio.camtweaks.command.commands; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import me.retucio.camtweaks.command.Command; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.ScreenshotPlus; +import me.retucio.camtweaks.util.ChatUtil; +import net.minecraft.command.CommandSource; + +import java.io.IOException; + +// se usa principalmente para el módulo ScreenshotPlus, pero también se puede usar sin él supongo +public class SaveScreenshotCommand extends Command { + + public SaveScreenshotCommand() { + super("guardarcaptura", "guarda localmente la captura más reciente"); + } + + @Override + public void build(LiteralArgumentBuilder builder) { + builder.executes(ctx -> { + ScreenshotPlus screenshotPlus = ModuleManager.INSTANCE.getModuleByClass(ScreenshotPlus.class); + + mc.execute(() -> { + if (screenshotPlus.getScreenshot() != null) { + try { + screenshotPlus.saveScreenshot(); + } catch (IOException e) { + ChatUtil.error("no se pudo guardar la captura"); + } + } + }); + + return SUCCESS; + }); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/command/commands/SendCommand.java b/remappedSrc/me/retucio/camtweaks/command/commands/SendCommand.java new file mode 100644 index 0000000..7a86e2c --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/command/commands/SendCommand.java @@ -0,0 +1,58 @@ +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() { + super("enviar", "manda un mensaje en el chat", "send"); + } + + @Override + public void build(LiteralArgumentBuilder builder) { + 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/remappedSrc/me/retucio/camtweaks/command/commands/ToggleCommand.java b/remappedSrc/me/retucio/camtweaks/command/commands/ToggleCommand.java new file mode 100644 index 0000000..67a8456 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/command/commands/ToggleCommand.java @@ -0,0 +1,57 @@ +package me.retucio.camtweaks.command.commands; + +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; + +// 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 { + + public ToggleCommand() { + super("alternar", "enciende / apaga módulos", "toggle"); + } + + @Override + public void build(LiteralArgumentBuilder builder) { + builder + .then(literal("todos") + .then(literal("on") + .executes(ctx -> { + ModuleManager.INSTANCE.getModules().forEach(module -> { + if (!module.isEnabled()) module.toggle(); + }); return SUCCESS; + }) + ) + .then(literal("off") + .executes(ctx -> { + ModuleManager.INSTANCE.getEnabledModules().forEach(Module::toggle); + return SUCCESS; + }) + ) + ) + .then(argument("módulo", ModuleArgumentType.INSTANCE) + .executes(ctx -> { + Module module = ctx.getArgument("módulo", Module.class); + module.toggle(); + return SUCCESS; + }) + .then(literal("on") + .executes(ctx -> { + Module module = ctx.getArgument("módulo", Module.class); + module.setEnabled(true); + return SUCCESS; + }) + ) + .then(literal("off") + .executes(ctx -> { + Module module = ctx.getArgument("módulo", Module.class); + module.setEnabled(false); + return SUCCESS; + }) + ) + ); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/config/ClientConfig.java b/remappedSrc/me/retucio/camtweaks/config/ClientConfig.java new file mode 100644 index 0000000..8c9062f --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/config/ClientConfig.java @@ -0,0 +1,110 @@ +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 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()); + } + + @SuppressWarnings("rawtypes") + @SubscribeEvent + public void onUpdateSetting(UpdateSettingEvent event) { + if (mc == null || !event.shouldSave()) 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; + case ListSetting l: value = l.getValues(); 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/remappedSrc/me/retucio/camtweaks/config/ConfigManager.java b/remappedSrc/me/retucio/camtweaks/config/ConfigManager.java new file mode 100644 index 0000000..b82abbd --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/config/ConfigManager.java @@ -0,0 +1,156 @@ +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.ClientSettingsFrame; +import me.retucio.camtweaks.ui.frames.SettingsFrame; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +// 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]); + } + }); + + ClientSettingsFrame.guiSettings.setEnabled(true); + ClientSettingsFrame.guiSettings.getSettings().forEach(setting -> applySetting(ClientSettingsFrame.guiSettings, setting)); + + CameraTweaks.LOGGER.info("módulos encendidos cargados"); + CameraTweaks.LOGGER.info("ajustes de módulos cargados"); + + ClientConfig.FrameData moduleFrameData = config.extendableFrames.get("M"); + if (moduleFrameData != null) { + ClickGUI.INSTANCE.getModulesFrame().x = moduleFrameData.x(); + ClickGUI.INSTANCE.getModulesFrame().y = moduleFrameData.y(); + ClickGUI.INSTANCE.getModulesFrame().extended = moduleFrameData.extended(); + } + + ClientConfig.FrameData guiSettingsData = config.extendableFrames.get("S"); + if (guiSettingsData != null) { + ClickGUI.INSTANCE.getGuiSettingsFrame().x = guiSettingsData.x(); + ClickGUI.INSTANCE.getGuiSettingsFrame().y = guiSettingsData.y(); + ClickGUI.INSTANCE.getGuiSettingsFrame().extended = guiSettingsData.extended(); + } + + CameraTweaks.LOGGER.info("posiciones de frames cargadas"); + ClickGUI.INSTANCE.refreshListButtons(); + } + + 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(AbstractSetting 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(); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + public static void applySetting(Module parent, AbstractSetting setting) { + String id = parent.getName() + ":" + setting.getName(); + if (config.settings.containsKey(id)) { + Object value = config.settings.get(id); + + switch (setting) { + case BooleanSetting b -> b.setEnabled((boolean) value); + case EnumSetting e -> e.setIndex(value instanceof Double val ? val.intValue() : (int) value); + case NumberSetting n -> n.setValue((double) value); + case StringSetting s -> s.setValue((String) value); + case KeySetting k -> k.setKey(value instanceof Double val ? val.intValue() : (int) value); + case ListSetting l -> { + if (value instanceof Map map) { + Map converted = new HashMap<>(); + for (Object option : l.getOptions()) { + Object key = String.valueOf(option); + Object bv = map.get(key); + converted.put(option, bv instanceof Boolean b && b); + } + l.setValues(converted); + } + } default -> {} + } + } + } + + private static void ensureConfig() { + if (config == null) config = new ClientConfig(); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/event/Event.java b/remappedSrc/me/retucio/camtweaks/event/Event.java new file mode 100644 index 0000000..ede96df --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/event/Event.java @@ -0,0 +1,14 @@ +package me.retucio.camtweaks.event; + +// evento base, cancelable (usado en mixins) +public class Event { + private boolean cancelled; + + public boolean isCancelled() { + return cancelled; + } + + public void cancel() { + cancelled = true; + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/event/EventBus.java b/remappedSrc/me/retucio/camtweaks/event/EventBus.java new file mode 100644 index 0000000..97e3f47 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/event/EventBus.java @@ -0,0 +1,71 @@ +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 +public class EventBus { + private final Map, List> listeners = new HashMap<>(); + + private record ListenerMethod(Object instance, Method method) {} + + public void register(Object listener) { + Class targetClass; + + 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 : new ArrayList<>(list)) { // copiar para evitar CME + try { + lm.method.invoke(lm.instance, event); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + return event; + } + + public boolean isRegistered(Object listener) { + for (List list : listeners.values()) { + for (ListenerMethod lm : list) { + if (lm.instance == listener) { + return true; + } + } + } + return false; + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/event/Stage.java b/remappedSrc/me/retucio/camtweaks/event/Stage.java new file mode 100644 index 0000000..b69c70a --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/event/SubscribeEvent.java b/remappedSrc/me/retucio/camtweaks/event/SubscribeEvent.java new file mode 100644 index 0000000..7c0413f --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/event/SubscribeEvent.java @@ -0,0 +1,8 @@ +package me.retucio.camtweaks.event; + +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 SubscribeEvent {} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/event/events/ChunkOcclusionEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/ChunkOcclusionEvent.java new file mode 100644 index 0000000..28d8c28 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/event/events/ClientClickEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/ClientClickEvent.java new file mode 100644 index 0000000..9b306b5 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/event/events/ClientClickEvent.java @@ -0,0 +1,26 @@ +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; + + public ClientClickEvent(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + @Override + public Action getAction() { + return Action.RUN_COMMAND; + } + +} diff --git a/remappedSrc/me/retucio/camtweaks/event/events/DisconnectEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/DisconnectEvent.java new file mode 100644 index 0000000..6a1483a --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/event/events/GetFOVEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/GetFOVEvent.java new file mode 100644 index 0000000..4527052 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/event/events/GetFOVEvent.java @@ -0,0 +1,24 @@ +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; + + public GetFOVEvent(float fov) { + this.fov = fov; + } + + public float getFov() { + return fov; + } + + public void setFov(float fov) { + this.fov = fov; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/event/events/KeyEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/KeyEvent.java new file mode 100644 index 0000000..5d8c708 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/event/events/KeyEvent.java @@ -0,0 +1,30 @@ +package me.retucio.camtweaks.event.events; + +import me.retucio.camtweaks.event.Event; + +/** + * @see me.retucio.camtweaks.mixin.KeyboardMixin#onKeyPress + */ + +public class KeyEvent extends Event { + + private final int key, scancode, action; + + public KeyEvent(int key, int scancode, int action) { + this.key = key; + this.scancode = scancode; + this.action = action; + } + + public int getKey() { + return key; + } + + public int getAction() { + return action; + } + + public int getScancode() { + return scancode; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/event/events/MouseClickEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/MouseClickEvent.java new file mode 100644 index 0000000..ecba0f4 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/event/events/MouseClickEvent.java @@ -0,0 +1,25 @@ +package me.retucio.camtweaks.event.events; + +import me.retucio.camtweaks.event.Event; + +/** + * @see me.retucio.camtweaks.mixin.MouseMixin#onMouseButton + */ + +public class MouseClickEvent extends Event { + + private final int action, button; + + public MouseClickEvent(int action, int button) { + this.action = action; + this.button = button; + } + + public int getAction() { + return action; + } + + public int getButton() { + return button; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/event/events/MouseScrollEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/MouseScrollEvent.java new file mode 100644 index 0000000..17f8d7c --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/event/events/MouseScrollEvent.java @@ -0,0 +1,33 @@ +package me.retucio.camtweaks.event.events; + +import me.retucio.camtweaks.event.Event; + +/** + * @see me.retucio.camtweaks.mixin.MouseMixin#onMouseScroll + */ + +public class MouseScrollEvent extends Event { + + private double horizontal, vertical; + + public MouseScrollEvent(double horizontal, double vertical) { + this.horizontal = horizontal; + this.vertical = vertical; + } + + public double getHorizontal() { + return horizontal; + } + + public void setHorizontal(double horizontal) { + this.horizontal = horizontal; + } + + public double getVertical() { + return vertical; + } + + public void setVertical(double vertical) { + this.vertical = vertical; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/event/events/OpenScreenEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/OpenScreenEvent.java new file mode 100644 index 0000000..3f51b99 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/event/events/PacketEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/PacketEvent.java new file mode 100644 index 0000000..b46e80c --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/event/events/PerspectiveChangeEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/PerspectiveChangeEvent.java new file mode 100644 index 0000000..db4d5ed --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/event/events/PerspectiveChangeEvent.java @@ -0,0 +1,25 @@ +package me.retucio.camtweaks.event.events; + +import me.retucio.camtweaks.event.Event; +import net.minecraft.client.option.Perspective; + +/** + * @see me.retucio.camtweaks.mixin.GameOptionsMixin#changePerspective + */ + +public class PerspectiveChangeEvent extends Event { + + private Perspective perspective; + + public PerspectiveChangeEvent(Perspective perspective) { + this.perspective = perspective; + } + + public Perspective getPerspective() { + return perspective; + } + + public void setPerspective(Perspective perspective) { + this.perspective = perspective; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/event/events/ReceiveMessageEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/ReceiveMessageEvent.java new file mode 100644 index 0000000..0c17879 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/event/events/ReceiveMessageEvent.java @@ -0,0 +1,47 @@ +package me.retucio.camtweaks.event.events; + +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; + private MessageIndicator indicator; + private int id; + private boolean modified = false; + + public ReceiveMessageEvent(Text text, MessageIndicator indicator, int id) { + this.text = text; + this.indicator = indicator; + this.id = id; + } + + public Text getMessage() { + return text; + } + + public MessageIndicator getIndicator() { + return indicator; + } + + public void setMessage(Text message) { + this.text = message; + this.modified = true; + } + + public void setIndicator(MessageIndicator indicator) { + this.indicator = indicator; + this.modified = true; + } + + public boolean wasModified() { + return modified; + } + + +} diff --git a/remappedSrc/me/retucio/camtweaks/event/events/RenderArmEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/RenderArmEvent.java new file mode 100644 index 0000000..4cfa59b --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/event/events/RenderArmEvent.java @@ -0,0 +1,36 @@ +package me.retucio.camtweaks.event.events; + +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; + private Hand hand; + + public RenderArmEvent(MatrixStack matrices, Hand hand) { + this.matrices = matrices; + this.hand = hand; + } + + public MatrixStack getMatrices() { + return matrices; + } + + public void setMatrices(MatrixStack matrices) { + this.matrices = matrices; + } + + public Hand getHand() { + return hand; + } + + public void setHand(Hand hand) { + this.hand = hand; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/event/events/RenderBossbarEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/RenderBossbarEvent.java new file mode 100644 index 0000000..51223ad --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/event/events/RenderHeldItemEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/RenderHeldItemEvent.java new file mode 100644 index 0000000..d90543e --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/event/events/RenderHeldItemEvent.java @@ -0,0 +1,36 @@ +package me.retucio.camtweaks.event.events; + +import me.retucio.camtweaks.event.Event; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.Hand; + +/** + * @see me.retucio.camtweaks.mixin.HeldItemRendererMixin#onRenderItem + */ + +public class RenderHeldItemEvent extends Event { + + private MatrixStack matrices; + private Hand hand; + + public RenderHeldItemEvent(MatrixStack matrices, Hand hand) { + this.matrices = matrices; + this.hand = hand; + } + + public MatrixStack getMatrices() { + return matrices; + } + + public void setMatrices(MatrixStack matrices) { + this.matrices = matrices; + } + + public Hand getHand() { + return hand; + } + + public void setHand(Hand hand) { + this.hand = hand; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/event/events/SendMessageEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/SendMessageEvent.java new file mode 100644 index 0000000..478cc5f --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/event/events/SendMessageEvent.java @@ -0,0 +1,24 @@ +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; + + public SendMessageEvent(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/event/events/ShutdownEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/ShutdownEvent.java new file mode 100644 index 0000000..dc59fc5 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/event/events/TickEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/TickEvent.java new file mode 100644 index 0000000..d056fea --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/GUISettingsFrameEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/GUISettingsFrameEvent.java new file mode 100644 index 0000000..f1fdf22 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/LoadClickGUIEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/LoadClickGUIEvent.java new file mode 100644 index 0000000..d53cfc0 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/LoadClickGUIEvent.java @@ -0,0 +1,5 @@ +package me.retucio.camtweaks.event.events.camtweaks; + +import me.retucio.camtweaks.event.Event; + +public class LoadClickGUIEvent extends Event {} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/LoadCommandManagerEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/LoadCommandManagerEvent.java new file mode 100644 index 0000000..2e16348 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/LoadCommandManagerEvent.java @@ -0,0 +1,5 @@ +package me.retucio.camtweaks.event.events.camtweaks; + +import me.retucio.camtweaks.event.Event; + +public class LoadCommandManagerEvent extends Event {} diff --git a/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/LoadModuleManagerEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/LoadModuleManagerEvent.java new file mode 100644 index 0000000..2d3ed01 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/LoadModuleManagerEvent.java @@ -0,0 +1,5 @@ +package me.retucio.camtweaks.event.events.camtweaks; + +import me.retucio.camtweaks.event.Event; + +public class LoadModuleManagerEvent extends Event {} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/ModuleFrameEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/ModuleFrameEvent.java new file mode 100644 index 0000000..154b341 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/SettingsFrameEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/SettingsFrameEvent.java new file mode 100644 index 0000000..d733660 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/ToggleModuleEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/ToggleModuleEvent.java new file mode 100644 index 0000000..8670ba2 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/UpdateSettingEvent.java b/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/UpdateSettingEvent.java new file mode 100644 index 0000000..d817f73 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/event/events/camtweaks/UpdateSettingEvent.java @@ -0,0 +1,28 @@ +package me.retucio.camtweaks.event.events.camtweaks; + +import me.retucio.camtweaks.event.Event; +import me.retucio.camtweaks.module.settings.AbstractSetting; + +// se genera cada que se cambia el valor de un ajuste +public class UpdateSettingEvent extends Event { + + private final AbstractSetting setting; + private boolean shouldSave; + + public UpdateSettingEvent(AbstractSetting setting, boolean shouldSave) { + this.setting = setting; + this.shouldSave = shouldSave; + } + + public AbstractSetting getSetting() { + return setting; + } + + public boolean shouldSave() { + return shouldSave; + } + + public void shouldSave(boolean value) { + this.shouldSave = value; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/mixin/BossBarHudMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/BossBarHudMixin.java new file mode 100644 index 0000000..1b909f6 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/mixin/CameraMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/CameraMixin.java new file mode 100644 index 0000000..da6e8dc --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/CameraMixin.java @@ -0,0 +1,94 @@ +package me.retucio.camtweaks.mixin; + +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 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) { + 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 (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/remappedSrc/me/retucio/camtweaks/mixin/ChatHudLineMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/ChatHudLineMixin.java new file mode 100644 index 0000000..5eaf08e --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/ChatHudLineMixin.java @@ -0,0 +1,38 @@ +package me.retucio.camtweaks.mixin; + +import com.mojang.authlib.GameProfile; +import me.retucio.camtweaks.util.interfaces.IChatHudLine; +import net.minecraft.client.gui.hud.ChatHudLine; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(ChatHudLine.class) +public class ChatHudLineMixin implements IChatHudLine { + + @Shadow @Final + private Text content; + + @Unique + private int id; + + @Unique + private GameProfile sender; + + @Override + public String smegma$getText() { return content.toString(); } + + @Override + public int smegma$getId() { return id; } + + @Override + public void smegma$setId(int id) { this.id = id; } + + @Override + public GameProfile smegma$getSender() { return sender; } + + @Override + public void smegma$setSender(GameProfile profile) { this.sender = profile; } +} diff --git a/remappedSrc/me/retucio/camtweaks/mixin/ChatHudLineVisibleMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/ChatHudLineVisibleMixin.java new file mode 100644 index 0000000..1e99861 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/ChatHudLineVisibleMixin.java @@ -0,0 +1,55 @@ +package me.retucio.camtweaks.mixin; + +import com.mojang.authlib.GameProfile; +import me.retucio.camtweaks.util.interfaces.IChatHudLineVisible; +import net.minecraft.client.gui.hud.ChatHudLine; +import net.minecraft.text.OrderedText; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(ChatHudLine.Visible.class) +public class ChatHudLineVisibleMixin implements IChatHudLineVisible { + + @Shadow @Final + private OrderedText content; + + @Unique + private int id; + + @Unique + private GameProfile sender; + + @Unique + private boolean startOfEntry; + + @Override + public String smegma$getText() { + StringBuilder sb = new StringBuilder(); + + content.accept((index, style, codePoint) -> { + sb.appendCodePoint(codePoint); + return true; + }); + return sb.toString(); + } + + @Override + public int smegma$getId() { return id; } + + @Override + public void smegma$setId(int id) { this.id = id; } + + @Override + public GameProfile smegma$getSender() { return sender; } + + @Override + public void smegma$setSender(GameProfile profile) { this.sender = profile; } + + @Override + public boolean smegma$isStartOfEntry() { return startOfEntry; } + + @Override + public void smegma$setStartOfEntry(boolean start) { this.startOfEntry = start; } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/mixin/ChatHudMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/ChatHudMixin.java new file mode 100644 index 0000000..62f9f6d --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/ChatHudMixin.java @@ -0,0 +1,203 @@ +package me.retucio.camtweaks.mixin; + +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.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; +import net.minecraft.client.gui.hud.ChatHudLine; +import net.minecraft.client.gui.hud.MessageIndicator; +import net.minecraft.network.message.MessageSignatureData; +import net.minecraft.text.OrderedText; +import net.minecraft.text.Text; +import org.jetbrains.annotations.Nullable; +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; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +import static me.retucio.camtweaks.CameraTweaks.*; + +@Mixin(ChatHud.class) +public abstract class ChatHudMixin implements IChatHud { + + @Unique + private boolean skipOnAddMessage; + + @Unique + private int nextId; + + @Unique + ChatPlus chatPlus; + + @Shadow @Final + private List messages; + + @Shadow @Final + private List visibleMessages; + + @Shadow + public abstract void addMessage(Text message); + + @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 + + @Override + public void smegma$add(Text message, int id) { + nextId = id; + addMessage(message); + nextId = 0; + } + + @Inject(method = "addVisibleMessage", at = @At(value = "INVOKE", target = "Ljava/util/List;add(ILjava/lang/Object;)V", shift = At.Shift.AFTER)) + private void onAddMessageAfterNewChatHudLineVisible(ChatHudLine message, CallbackInfo ci) { + ((IChatHudLine) (Object) visibleMessages.getFirst()).smegma$setId(nextId); + } + + @Inject(method = "addMessage(Lnet/minecraft/client/gui/hud/ChatHudLine;)V", at = @At(value = "INVOKE", target = "Ljava/util/List;add(ILjava/lang/Object;)V", shift = At.Shift.AFTER)) + private void onAddMessageAfterNewChatHudLine(ChatHudLine message, CallbackInfo ci) { + ((IChatHudLine) (Object) messages.getFirst()).smegma$setId(nextId); + } + + @SuppressWarnings("DataFlowIssue") + @ModifyExpressionValue(method = "addVisibleMessage", at = @At(value = "NEW", target = "(ILnet/minecraft/text/OrderedText;Lnet/minecraft/client/gui/hud/MessageIndicator;Z)Lnet/minecraft/client/gui/hud/ChatHudLine$Visible;")) + private ChatHudLine.Visible onAddMessage_modifyChatHudLineVisible(ChatHudLine.Visible line, @Local(ordinal = 1) int j) { + IMessageHandler handler = (IMessageHandler) mc.getMessageHandler(); + if (handler == null) return line; + + IChatHudLineVisible iLine = (IChatHudLineVisible) (Object) line; + + iLine.smegma$setSender(handler.smegma$getSender()); + iLine.smegma$setStartOfEntry(j == 0); + + return line; + } + + @ModifyExpressionValue(method = "addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;Lnet/minecraft/client/gui/hud/MessageIndicator;)V", at = @At(value = "NEW", target = "(ILnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;Lnet/minecraft/client/gui/hud/MessageIndicator;)Lnet/minecraft/client/gui/hud/ChatHudLine;")) + private ChatHudLine onAddMessage_modifyChatHudLine(ChatHudLine line) { + IMessageHandler handler = (IMessageHandler) mc.getMessageHandler(); + if (handler == null) return line; + + ((IChatHudLine) (Object) line).smegma$setSender(handler.smegma$getSender()); + return line; + } + + @Override + public List smegma$getVisibleMessages() { + return visibleMessages; + } + + + + // modificar contenido del mensaje + @Inject(at = @At("HEAD"), method = "addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;Lnet/minecraft/client/gui/hud/MessageIndicator;)V", cancellable = true) + private void onAddMessage(Text message, MessageSignatureData signatureData, MessageIndicator indicator, CallbackInfo ci) { + if (skipOnAddMessage) return; + + ReceiveMessageEvent event = EVENT_BUS.post(new ReceiveMessageEvent(message, indicator, nextId)); + + if (event.isCancelled()) { + ci.cancel(); + } else { + visibleMessages.removeIf(msg -> ((IChatHudLine) (Object) msg).smegma$getId() == nextId && nextId != 0); + + for (int i = messages.size() - 1; i > -1; i--) { + if (((IChatHudLine) (Object) messages.get(i)).smegma$getId() == nextId && nextId != 0) { + messages.remove(i); + chatPlus.removeLine(i); + } + } + + if (event.wasModified()) { + ci.cancel(); + + skipOnAddMessage = true; + addMessage(event.getMessage(), signatureData, event.getIndicator()); + skipOnAddMessage = false; + } + } + } + + + + // cabezas + + @ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;ceil(F)I")) + private int onRender_modifyWidth(int 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) { + 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) { + chatPlus.afterDrawMessage(context); + } + + + + // historial (registro) del chat + + @ModifyExpressionValue(method = "addMessage(Lnet/minecraft/client/gui/hud/ChatHudLine;)V", at = @At(value = "CONSTANT", args = "intValue=100")) + private int maxLength(int size) { + 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 (!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) { + 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 = chatPlus.chatHistoryExtraLength.getIntValue(); + int size = chatPlus.lines.size(); + + while (size > 100 + extra) { + chatPlus.lines.removeLast(); + size--; + } + } + + @Inject(method = "clear", at = @At("HEAD")) + private void onClear(boolean clearHistory, CallbackInfo ci) { + chatPlus.lines.clear(); + } + + @Inject(method = "refresh", at = @At("HEAD")) + private void onRefresh(CallbackInfo ci) { + chatPlus.lines.clear(); + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/mixin/ChatInputSuggestorMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/ChatInputSuggestorMixin.java new file mode 100644 index 0000000..4dce8d1 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/ChatInputSuggestorMixin.java @@ -0,0 +1,62 @@ +package me.retucio.camtweaks.mixin; + +import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.brigadier.ParseResults; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.suggestion.Suggestions; +import me.retucio.camtweaks.command.CommandManager; +import net.minecraft.client.gui.screen.ChatInputSuggestor; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.command.CommandSource; +import org.spongepowered.asm.mixin.Final; +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; + +import java.util.concurrent.CompletableFuture; + +import static me.retucio.camtweaks.CameraTweaks.mc; + +@Mixin(ChatInputSuggestor.class) +public abstract class ChatInputSuggestorMixin { + + @Shadow + private ParseResults parse; + + @Shadow @Final + TextFieldWidget textField; + + @Shadow + private ChatInputSuggestor.SuggestionWindow window; + + @Shadow + boolean completingSuggestions; + + @Shadow + private CompletableFuture pendingSuggestions; + + @Shadow protected abstract void showCommandSuggestions(); + + @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.INSTANCE.getPrefix(); + int length = prefix.length(); + + if (reader.canRead(length) && reader.getString().startsWith(prefix, reader.getCursor())) { + reader.setCursor(reader.getCursor() + length); + + if (parse == null) this.parse = CommandManager.dispatcher.parse(reader, mc.getNetworkHandler().getCommandSource()); + + int cursor = textField.getCursor(); + if (cursor >= length && (window == null || !completingSuggestions)) { + pendingSuggestions = CommandManager.dispatcher.getCompletionSuggestions(parse, cursor); + pendingSuggestions.thenRun(() -> { + if (pendingSuggestions.isDone()) showCommandSuggestions(); + }); + } + ci.cancel(); + } + } +} diff --git a/remappedSrc/me/retucio/camtweaks/mixin/ChatScreenMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/ChatScreenMixin.java new file mode 100644 index 0000000..9a27213 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/ChatScreenMixin.java @@ -0,0 +1,24 @@ +package me.retucio.camtweaks.mixin; + +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; +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; + +@Mixin(value = ChatScreen.class, priority = 1001) +public abstract class ChatScreenMixin { + + @Shadow + protected TextFieldWidget chatField; + + @Inject(method = "init", at = @At(value = "RETURN")) + private void onInit(CallbackInfo info) { + 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/remappedSrc/me/retucio/camtweaks/mixin/ChunkBorderDebugRendererMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/ChunkBorderDebugRendererMixin.java new file mode 100644 index 0000000..fde5a83 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/mixin/ChunkOcclusionDataBuilderMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/ChunkOcclusionDataBuilderMixin.java new file mode 100644 index 0000000..32b2c37 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/mixin/ClientConnectionMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/ClientConnectionMixin.java new file mode 100644 index 0000000..fbc8737 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/mixin/ClientPlayNetworkHandlerMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/ClientPlayNetworkHandlerMixin.java new file mode 100644 index 0000000..67f4c3d --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/ClientPlayNetworkHandlerMixin.java @@ -0,0 +1,61 @@ +package me.retucio.camtweaks.mixin; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import me.retucio.camtweaks.command.CommandManager; +import me.retucio.camtweaks.event.events.SendMessageEvent; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.NoRender; +import me.retucio.camtweaks.util.ChatUtil; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import static me.retucio.camtweaks.CameraTweaks.*; + +@Mixin(ClientPlayNetworkHandler.class) +public abstract class ClientPlayNetworkHandlerMixin { + + @Unique + private boolean ignoreChatMessage; + + @Shadow + public abstract void sendChatMessage(String content); + + @Inject(method = "sendChatMessage", at = @At("HEAD"), cancellable = true) + private void onSendMessage(String message, CallbackInfo ci) { + if (ignoreChatMessage) return; + if (!message.startsWith(CommandManager.INSTANCE.getPrefix())) { + SendMessageEvent event = EVENT_BUS.post(new SendMessageEvent(message)); + if (!event.isCancelled()) { + ignoreChatMessage = true; + sendChatMessage(event.getMessage()); + ignoreChatMessage = false; + } + ci.cancel(); + return; + }; + + try { + CommandManager.dispatch(message.substring(CommandManager.INSTANCE.getPrefix().length())); + } catch (CommandSyntaxException e) { + ChatUtil.error(e.getMessage()); + } + + mc.inGameHud.getChatHud().addToMessageHistory(message); + ci.cancel(); + } + + @Redirect(method = "onEntityStatus", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;showFloatingItem(Lnet/minecraft/item/ItemStack;)V")) + private void noRenderTotemPop(GameRenderer instance, ItemStack floatingItem) { + NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); + if (!noRender.isEnabled() || noRender.totemPop.isEnabled()) mc.gameRenderer.showFloatingItem(Items.TOTEM_OF_UNDYING.getDefaultStack()); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/mixin/ClientPlayerInteractionManagerMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/ClientPlayerInteractionManagerMixin.java new file mode 100644 index 0000000..31fa683 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/ClientPlayerInteractionManagerMixin.java @@ -0,0 +1,48 @@ +package me.retucio.camtweaks.mixin; + +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.Freecam; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ClientPlayerInteractionManager.class) +public abstract class ClientPlayerInteractionManagerMixin { + + @Unique + Freecam freecam; + + @Inject(method = "", at = @At("TAIL")) + private void getModules(MinecraftClient client, ClientPlayNetworkHandler networkHandler, CallbackInfo ci) { + freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); + } + + // los paquetes ya se cancelan en la clase de Freecam, pero visualmente el bloque sigue apareciendo roto + @Inject(method = "breakBlock", at = @At("HEAD"), cancellable = true) + private void cancelBlockBreaking(BlockPos pos, CallbackInfoReturnable cir) { + if (freecam.isEnabled() && freecam.cancelActionPackets.isEnabled()) cir.setReturnValue(false); + } + + @Inject(method = "interactBlock", at = @At("HEAD"), cancellable = true) + private void cancelBlockPlacement(ClientPlayerEntity player, Hand hand, BlockHitResult hitResult, CallbackInfoReturnable cir) { + if (freecam.isEnabled() && freecam.cancelActionPackets.isEnabled()) cir.setReturnValue(ActionResult.FAIL); + } + + @Inject(method = "interactEntity", at = @At("HEAD"), cancellable = true) + private void cancelEntityInteractions(PlayerEntity player, Entity entity, Hand hand, CallbackInfoReturnable cir) { + if (freecam.isEnabled() && freecam.cancelActionPackets.isEnabled()) cir.setReturnValue(ActionResult.FAIL); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/mixin/ClientWorldPropertiesMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/ClientWorldPropertiesMixin.java new file mode 100644 index 0000000..e897cc2 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/mixin/CompassStateMixin.java similarity index 100% rename from src/main/java/me/retucio/camtweaks/mixin/CompassStateMixin.java rename to remappedSrc/me/retucio/camtweaks/mixin/CompassStateMixin.java diff --git a/remappedSrc/me/retucio/camtweaks/mixin/DamageParticleMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/DamageParticleMixin.java new file mode 100644 index 0000000..056a360 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/DamageParticleMixin.java @@ -0,0 +1,57 @@ +package me.retucio.camtweaks.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.CritsPlus; +import net.minecraft.client.particle.DamageParticle; +import net.minecraft.client.particle.ParticleTextureSheet; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +import java.awt.*; + +@Mixin(DamageParticle.class) +public abstract class DamageParticleMixin { + + @ModifyReturnValue(method = "getType", at = @At("RETURN")) + private ParticleTextureSheet makeCritsTranslucent(ParticleTextureSheet original) { + if (ModuleManager.INSTANCE.getModuleByClass(CritsPlus.class).isEnabled()) return ParticleTextureSheet.PARTICLE_SHEET_TRANSLUCENT; + return original; + } +} + + +@Mixin(DamageParticle.Factory.class) +abstract class DamageParticleFactoryMixin { + + @ModifyVariable(method = "createParticle(Lnet/minecraft/particle/SimpleParticleType;Lnet/minecraft/client/world/ClientWorld;DDDDDD)Lnet/minecraft/client/particle/Particle;", at = @At(value = "STORE")) + private DamageParticle modifyCritColor(DamageParticle original) { + CritsPlus crits = ModuleManager.INSTANCE.getModuleByClass(CritsPlus.class); + if (!crits.isEnabled()) return original; + + if (crits.rainbow.isEnabled()) { + float speed = 10001 - crits.rainbowSpeed.getFloatValue(); + float hue = (System.currentTimeMillis() % (int) speed) / speed; + Color gamning = Color.getHSBColor(hue, 1, 1); + original.setColor( + gamning.getRed() / 255f, + gamning.getGreen() / 255f, + gamning.getBlue() / 255f); + } else { + original.setColor( + crits.red.getFloatValue() / 255f, + crits.green.getFloatValue() / 255f, + crits.blue.getFloatValue() / 255f); + } + + original.alpha = crits.alpha.getFloatValue() / 255f; + original.scale *= crits.scale.getFloatValue(); + original.velocityMultiplier *= crits.velocityMultipler.getFloatValue(); + original.gravityStrength *= crits.gravity.getFloatValue(); + original.setMaxAge(crits.maxAge.getIntValue()); + original.collidesWithWorld = crits.collide.isEnabled(); + + return original; + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/mixin/DimensionTypeMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/DimensionTypeMixin.java new file mode 100644 index 0000000..8ec5cde --- /dev/null +++ b/remappedSrc/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/EntityEffectParticleEffectMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/EntityEffectParticleEffectMixin.java similarity index 100% rename from src/main/java/me/retucio/camtweaks/mixin/EntityEffectParticleEffectMixin.java rename to remappedSrc/me/retucio/camtweaks/mixin/EntityEffectParticleEffectMixin.java diff --git a/remappedSrc/me/retucio/camtweaks/mixin/EntityMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/EntityMixin.java new file mode 100644 index 0000000..9b8aea9 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/EntityMixin.java @@ -0,0 +1,125 @@ +package me.retucio.camtweaks.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.AntiInvis; +import me.retucio.camtweaks.module.modules.Freecam; +import me.retucio.camtweaks.module.modules.Freelook; +import me.retucio.camtweaks.module.modules.Nametags; +import me.retucio.camtweaks.util.ChatUtil; +import net.minecraft.entity.*; +import net.minecraft.entity.passive.TameableEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.projectile.PersistentProjectileEntity; +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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import static me.retucio.camtweaks.CameraTweaks.mc; + +@Mixin(Entity.class) +public abstract class EntityMixin { + + @Shadow + public abstract Text getName(); + + @Shadow + public abstract EntityType getType(); + + @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; + if ((Object) this instanceof PersistentProjectileEntity p && p.isOnGround()) return false; + return nametags.entities.isEnabled((this.getType())); + } + + @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 + String damage = nametags.getArrowDamage(arrow); + if (!damage.equals("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; + } + + + // otros + + @Inject(method = "isInvisibleTo", at = @At("RETURN"), cancellable = true) + public void renderInvisPlayers(PlayerEntity player, CallbackInfoReturnable cir) { + if (ModuleManager.INSTANCE.getModuleByClass(AntiInvis.class).isEnabled()) cir.setReturnValue(false); + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/mixin/FogRendererMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/FogRendererMixin.java new file mode 100644 index 0000000..ad94c71 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/FogRendererMixin.java @@ -0,0 +1,60 @@ +package me.retucio.camtweaks.mixin; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.NoRender; +import net.minecraft.block.enums.CameraSubmersionType; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.fog.FogModifier; +import net.minecraft.client.render.fog.FogRenderer; +import net.minecraft.entity.Entity; +import org.joml.Vector4f; +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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(FogRenderer.class) +public abstract class FogRendererMixin { + + @Unique + NoRender noRender; + + @Inject(method = "", at = @At("TAIL")) + private void getModules(CallbackInfo ci) { + noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); + } + + @Redirect(method = "applyFog(Lnet/minecraft/client/render/Camera;IZLnet/minecraft/client/render/RenderTickCounter;FLnet/minecraft/client/world/ClientWorld;)Lorg/joml/Vector4f;", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/fog/FogModifier;shouldApply(Lnet/minecraft/block/enums/CameraSubmersionType;Lnet/minecraft/entity/Entity;)Z")) + private boolean noRenderFogs(FogModifier instance, CameraSubmersionType cameraSubmersionType, Entity entity) { + if (!noRender.isEnabled()) return instance.shouldApply(cameraSubmersionType, entity); + String className = instance.getClass().getSimpleName(); + + if ((className.equals("BlindnessEffectFogModifier") && !noRender.blindnessEffect.isEnabled()) + || (className.equals("DarknessEffectFogModifier") && !noRender.darknessEffect.isEnabled()) + || ((className.equals("LavaFogModifier") || className.equals("WaterFogModifier") + || className.equals("PowederSnowFogModifier")) && !noRender.fluidOverlay.isEnabled()) + || (className.equals("DimensionOrBossFogModifier") && !noRender.dimensionFog.isEnabled())) + return false; + + return instance.shouldApply(cameraSubmersionType, entity); + } + + @ModifyReturnValue(method = "getFogColor", at = @At("RETURN")) + private Vector4f modifyLavaFog(Vector4f original, Camera camera) { + if (noRender.isEnabled() && !noRender.fluidOverlay.isEnabled() && + (camera.getSubmersionType() == CameraSubmersionType.LAVA + || camera.getSubmersionType() == CameraSubmersionType.WATER)) + return new Vector4f(original.x, original.y, original.z, 0f); + + return original; + } + + @ModifyExpressionValue(method = "getFogColor", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getUnderwaterVisibility()F")) + private float noRenderUnderwaterFog(float original) { + return (noRender.isEnabled() && !noRender.fluidOverlay.isEnabled()) ? 0 : original; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/mixin/GameOptionsMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/GameOptionsMixin.java new file mode 100644 index 0000000..9515e5b --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/GameOptionsMixin.java @@ -0,0 +1,29 @@ +package me.retucio.camtweaks.mixin; + +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; + +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/remappedSrc/me/retucio/camtweaks/mixin/GameRendererMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/GameRendererMixin.java new file mode 100644 index 0000000..461aa37 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/GameRendererMixin.java @@ -0,0 +1,116 @@ +package me.retucio.camtweaks.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import me.retucio.camtweaks.event.events.GetFOVEvent; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.Freecam; +import me.retucio.camtweaks.module.modules.NoRender; +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.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; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS; + +@Mixin(GameRenderer.class) +public abstract class GameRendererMixin { + + @Unique + boolean freecamDone; + + @Unique + Zoom zoom; + + @Unique + Freecam freecam; + + @Unique + NoRender noRender; + + @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); + noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); + } + + @ModifyReturnValue(method = "getFov", at = @At("RETURN")) + private float modifyFov(float original) { + return EVENT_BUS.post(new GetFOVEvent(original)).getFov(); + } + + @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()) + || (freecam.isEnabled() && !freecam.renderHands.isEnabled())) + ci.cancel(); + } + + @ModifyVariable(method = "renderWorld", ordinal = 6, at = @At(value = "STORE")) + private float noRenderNauseaDistortion(float scaledNauseaEffectFactor) { + return (noRender.isEnabled() && !noRender.nauseaEffect.isEnabled()) ? 0 : scaledNauseaEffectFactor; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/mixin/HeldItemRendererMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/HeldItemRendererMixin.java new file mode 100644 index 0000000..fa81d62 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/HeldItemRendererMixin.java @@ -0,0 +1,91 @@ +package me.retucio.camtweaks.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +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.*; + +@Mixin(HeldItemRenderer.class) +public abstract class HeldItemRendererMixin { + + @Unique + 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 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()); + } + + @Inject(method = "applyEatOrDrinkTransformation", at = @At(value = "INVOKE", target = "Ljava/lang/Math;pow(DD)D", shift = At.Shift.BEFORE), cancellable = true) + private void cancelTransformations(MatrixStack matrices, float tickDelta, Arm arm, ItemStack stack, PlayerEntity player, CallbackInfo ci) { + if (handView.isEnabled() && handView.noFood.isEnabled()) ci.cancel(); + } + + @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/remappedSrc/me/retucio/camtweaks/mixin/InGameHudMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/InGameHudMixin.java new file mode 100644 index 0000000..ca78dcc --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/InGameHudMixin.java @@ -0,0 +1,82 @@ +package me.retucio.camtweaks.mixin; + +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.module.modules.NoRender; +import me.retucio.camtweaks.ui.HUD; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.hud.InGameHud; +import net.minecraft.client.render.RenderTickCounter; +import net.minecraft.util.Identifier; +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(InGameHud.class) +public abstract class InGameHudMixin { + + @Unique + NoRender noRender; + + @Inject(method = "", at = @At("TAIL")) + private void getModules(MinecraftClient client, CallbackInfo ci) { + noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); + } + + + // norender + + @Inject(method = "renderScoreboardSidebar*", at = @At("HEAD"), cancellable = true) + private void noRenderScoreboard(CallbackInfo ci) { + if (noRender.isEnabled() && !noRender.scoreboard.isEnabled()) ci.cancel(); + } + + @Inject(method = "renderTitleAndSubtitle", at = @At("HEAD"), cancellable = true) + private void noRenderTitles(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) { + if (noRender.isEnabled() && !noRender.titles.isEnabled()) ci.cancel(); + } + + @Inject(method = "renderNauseaOverlay", at = @At("HEAD"), cancellable = true) + private void noRenderNausea(DrawContext context, float nauseaStrength, CallbackInfo ci) { + if (noRender.isEnabled() && !noRender.nauseaEffect.isEnabled()) ci.cancel(); + } + + @Inject(method = "renderSpyglassOverlay", at = @At("HEAD"), cancellable = true) + private void noRenderSpyglass(DrawContext context, float scale, CallbackInfo ci) { + if (noRender.isEnabled() && !noRender.spyglassOverlay.isEnabled()) ci.cancel(); + } + + @Inject(method = "renderPortalOverlay", at = @At("HEAD"), cancellable = true) + private void noRenderPortal(DrawContext context, float nauseaStrength, CallbackInfo ci) { + if (noRender.isEnabled() && !noRender.portalOverlay.isEnabled()) ci.cancel(); + } + + @Inject(method = "renderOverlay", at = @At("HEAD"), cancellable = true) + private void noRenderPumpkinBlur(DrawContext context, Identifier texture, float opacity, CallbackInfo ci) { + if (noRender.isEnabled() && !noRender.pumpkinOverlay.isEnabled() && texture.getPath().equals("textures/misc/pumpkinblur.png")) ci.cancel(); + } + + + // otros + + @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) { + ChatPlus chatPlus = ModuleManager.INSTANCE.getModuleByClass(ChatPlus.class); + if (chatPlus.isEnabled() && chatPlus.keepHistory.isEnabled()) ci.cancel(); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/mixin/InGameOverlayRendererMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/InGameOverlayRendererMixin.java new file mode 100644 index 0000000..dfea32d --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/InGameOverlayRendererMixin.java @@ -0,0 +1,35 @@ +package me.retucio.camtweaks.mixin; + +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.NoRender; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.hud.InGameOverlayRenderer; +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(InGameOverlayRenderer.class) +public abstract class InGameOverlayRendererMixin { + + @Unique + private static NoRender noRender; + + @Inject(method = "", at = @At("TAIL")) + private void getModules(MinecraftClient client, VertexConsumerProvider vertexConsumers, CallbackInfo ci) { + noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); + } + + @Inject(method = "renderFireOverlay", at = @At("HEAD"), cancellable = true) + private static void noRenderFireOverlay(MatrixStack matrices, VertexConsumerProvider vertexConsumers, CallbackInfo ci) { + if (noRender.isEnabled() && !noRender.fireOverlay.isEnabled()) ci.cancel(); + } + + @Inject(method = "renderUnderwaterOverlay", at = @At("HEAD"), cancellable = true) + private static void noRenderUnderwaterOverlay(MinecraftClient client, MatrixStack matrices, VertexConsumerProvider vertexConsumers, CallbackInfo ci) { + if (noRender.isEnabled() && !noRender.fluidOverlay.isEnabled()) ci.cancel(); + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/mixin/ItemEntityMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/ItemEntityMixin.java new file mode 100644 index 0000000..53ca637 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/mixin/KeyInputMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/KeyInputMixin.java new file mode 100644 index 0000000..26ef5c2 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/mixin/KeyboardMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/KeyboardMixin.java new file mode 100644 index 0000000..08ad4d4 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/KeyboardMixin.java @@ -0,0 +1,23 @@ +package me.retucio.camtweaks.mixin; + +import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.event.events.KeyEvent; +import net.minecraft.client.Keyboard; +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(Keyboard.class) +public abstract class KeyboardMixin { + + @Inject(method = "onKey", at = @At("HEAD"), cancellable = true) + private void onKeyPress(long window, int key, int scancode, int action, int modifiers, CallbackInfo ci) { + CameraTweaks.INSTANCE.onKeyPress(key, action); + + KeyEvent event = EVENT_BUS.post(new KeyEvent(key, scancode, action)); + if (event.isCancelled()) ci.cancel(); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/mixin/LightmapTextureManagerMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/LightmapTextureManagerMixin.java new file mode 100644 index 0000000..9db7f17 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/LightmapTextureManagerMixin.java @@ -0,0 +1,48 @@ +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 net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.render.LightmapTextureManager; +import net.minecraft.util.math.ColorHelper; +import net.minecraft.util.profiler.Profiler; +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; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(LightmapTextureManager.class) +public abstract class LightmapTextureManagerMixin { + + @Unique + 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)) { + RenderSystem.getDevice().createCommandEncoder().clearColorTexture(glTexture, ColorHelper.getArgb( + fullbright.alpha.getIntValue(), + fullbright.red.getIntValue(), + fullbright.green.getIntValue(), + fullbright.blue.getIntValue() + )); + profiler.pop(); + ci.cancel(); + } + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/mixin/LivingEntityRendererMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/LivingEntityRendererMixin.java new file mode 100644 index 0000000..4822dfc --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/LivingEntityRendererMixin.java @@ -0,0 +1,55 @@ +package me.retucio.camtweaks.mixin; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import com.llamalad7.mixinextras.sugar.Local; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.Freecam; +import me.retucio.camtweaks.module.modules.Nametags; +import net.minecraft.client.render.entity.EntityRendererFactory; +import net.minecraft.client.render.entity.LivingEntityRenderer; +import net.minecraft.client.render.entity.PlayerEntityRenderer; +import net.minecraft.client.render.entity.model.EntityModel; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +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(LivingEntityRenderer.class) +public abstract class LivingEntityRendererMixin { + + @Unique + Nametags nametags; + + @Inject(method = "", at = @At("TAIL")) + private void getModules(EntityRendererFactory.Context ctx, EntityModel model, float shadowRadius, CallbackInfo ci) { + nametags = ModuleManager.INSTANCE.getModuleByClass(Nametags.class); + } + + @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; + } + + @ModifyExpressionValue(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;isSneaky()Z")) + private boolean renderSneakingPlayerNametags(boolean original) { + return (nametags.isEnabled() && nametags.alwaysVisible.isEnabled()) || original; + } + + @ModifyExpressionValue(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;isInvisibleTo(Lnet/minecraft/entity/player/PlayerEntity;)Z")) + private boolean renderInvisPlayerNametags(boolean original) { + if (nametags.isEnabled() && nametags.alwaysVisible.isEnabled()) return false; + else return original; + } + + @ModifyReturnValue(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At("RETURN")) + private boolean shouldRenderPlayerNametag(boolean original, @Local(argsOnly = true) T livingEntity) { + if (nametags.isEnabled() && livingEntity instanceof PlayerEntity) return nametags.entities.isEnabled(EntityType.PLAYER) && original; + return original; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/mixin/MessageHandlerMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/MessageHandlerMixin.java new file mode 100644 index 0000000..09029d7 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/MessageHandlerMixin.java @@ -0,0 +1,37 @@ +package me.retucio.camtweaks.mixin; + +import com.mojang.authlib.GameProfile; +import me.retucio.camtweaks.util.interfaces.IMessageHandler; +import net.minecraft.client.network.message.MessageHandler; +import net.minecraft.network.message.MessageType; +import net.minecraft.network.message.SignedMessage; +import net.minecraft.text.Text; +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.CallbackInfoReturnable; + +import java.time.Instant; + +@Mixin(MessageHandler.class) +public abstract class MessageHandlerMixin implements IMessageHandler { + + @Unique + private GameProfile sender; + + @Inject(method = "processChatMessageInternal", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;Lnet/minecraft/client/gui/hud/MessageIndicator;)V", shift = At.Shift.BEFORE)) + private void onProcessChatMessageInternal_beforeAddMessage(MessageType.Parameters params, SignedMessage message, Text decorated, GameProfile sender, boolean onlyShowSecureChat, Instant receptionTimestamp, CallbackInfoReturnable info) { + this.sender = sender; + } + + @Inject(method = "processChatMessageInternal", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;Lnet/minecraft/client/gui/hud/MessageIndicator;)V", shift = At.Shift.AFTER)) + private void onProcessChatMessageInternal_afterAddMessage(MessageType.Parameters params, SignedMessage message, Text decorated, GameProfile sender, boolean onlyShowSecureChat, Instant receptionTimestamp, CallbackInfoReturnable info) { + this.sender = null; + } + + @Override + public GameProfile smegma$getSender() { + return sender; + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/mixin/MinecraftClientMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/MinecraftClientMixin.java new file mode 100644 index 0000000..5d0ff78 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/MinecraftClientMixin.java @@ -0,0 +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")) + 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/remappedSrc/me/retucio/camtweaks/mixin/MouseMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/MouseMixin.java new file mode 100644 index 0000000..7495d35 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/MouseMixin.java @@ -0,0 +1,28 @@ +package me.retucio.camtweaks.mixin; + +import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.event.events.MouseClickEvent; +import me.retucio.camtweaks.event.events.MouseScrollEvent; +import net.minecraft.client.Mouse; +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(Mouse.class) +public abstract class MouseMixin { + + @Inject(method = "onMouseButton", at = @At("HEAD"), cancellable = true) + private void onMouseButton(long window, int button, int action, int mods, CallbackInfo ci) { + MouseClickEvent event = EVENT_BUS.post(new MouseClickEvent(action, button)); + if (event.isCancelled()) ci.cancel(); + } + + @Inject(method = "onMouseScroll", at = @At("HEAD"), cancellable = true) + private void onMouseScroll(long window, double horizontal, double vertical, CallbackInfo ci) { + MouseScrollEvent event = EVENT_BUS.post(new MouseScrollEvent(horizontal, vertical)); + if (event.isCancelled()) ci.cancel(); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/mixin/OverlayTextureMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/OverlayTextureMixin.java new file mode 100644 index 0000000..85f42db --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/OverlayTextureMixin.java @@ -0,0 +1,24 @@ +package me.retucio.camtweaks.mixin; + +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.DamageOverlay; +import net.minecraft.client.render.OverlayTexture; +import net.minecraft.client.texture.NativeImageBackedTexture; +import org.spongepowered.asm.mixin.Final; +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; + +@Mixin(OverlayTexture.class) +public abstract class OverlayTextureMixin implements AutoCloseable { + + @Shadow @Final + private NativeImageBackedTexture texture; + + @Inject(method = "", at = @At("TAIL")) + private void modifyDamageOverlayColor(CallbackInfo ci) { + ModuleManager.INSTANCE.getModuleByClass(DamageOverlay.class).reloadOverlay(texture); + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/mixin/ParticleManagerMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/ParticleManagerMixin.java new file mode 100644 index 0000000..e932db2 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/ParticleManagerMixin.java @@ -0,0 +1,22 @@ +package me.retucio.camtweaks.mixin; + +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.NoRender; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.particle.ParticleManager; +import net.minecraft.particle.ParticleEffect; +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.CallbackInfoReturnable; + +@Mixin(ParticleManager.class) +public abstract class ParticleManagerMixin { + + @Inject(method = "addParticle(Lnet/minecraft/particle/ParticleEffect;DDDDDD)Lnet/minecraft/client/particle/Particle;", at = @At("HEAD"), cancellable = true) + private void noRenderParticles(ParticleEffect parameters, double x, double y, double z, double velocityX, double velocityY, double velocityZ, CallbackInfoReturnable cir) { + NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); + if (!noRender.isEnabled()) return; + if (!noRender.particles.isEnabled(parameters.getType())) cir.setReturnValue(null); + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/mixin/PlayerEntityMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/PlayerEntityMixin.java new file mode 100644 index 0000000..bf4df58 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/PlayerEntityMixin.java @@ -0,0 +1,52 @@ +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.health.isEnabled()) return original; + + float health = getHealth(); + float absorption = getAbsorptionAmount(); + 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 :'( + // ahora que lo pienso en la snapshot más reciente han metido iconos que se pueden usar en texto, y uno de ellos es un corazón :D + String text = " [" + color + + (nametags.healthMode.is(Nametags.HealthMode.HEARTS) + ? String.format("%.2f", health / 2) // redondear a dos decimales + : (int) health) + + (absorption > 0 // tener absorción en cuenta + ? Formatting.RESET + " + " + Formatting.GOLD + + (nametags.healthMode.is(Nametags.HealthMode.HEARTS) + ? String.format("%.2f", absorption / 2) + : Integer.toString((int) absorption)) + : "") + + Formatting.RESET + "]"; + + return original.copy().append(text); + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/mixin/ScreenMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/ScreenMixin.java new file mode 100644 index 0000000..d44f5a4 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/mixin/ScreenshotRecorderMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/ScreenshotRecorderMixin.java new file mode 100644 index 0000000..ddff55e --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/ScreenshotRecorderMixin.java @@ -0,0 +1,53 @@ +package me.retucio.camtweaks.mixin; + +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.ScreenshotPlus; +import net.minecraft.client.texture.NativeImage; +import net.minecraft.client.util.ScreenshotRecorder; +import net.minecraft.text.Text; +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 java.io.File; +import java.io.IOException; +import java.util.function.Consumer; + +@Mixin(ScreenshotRecorder.class) +public abstract class ScreenshotRecorderMixin { + + // "method_22691" es la lambda de la función "saveScreenshot()" (por lo menos en 1.21.6) + @Inject(method = "method_22691", at = @At(value = "INVOKE", target = "Ljava/util/function/Consumer;accept(Ljava/lang/Object;)V"), cancellable = true) + private static void sendActionsMessage(NativeImage nativeImage, File file, Consumer consumer, CallbackInfo ci) { + ScreenshotPlus screenshotPlus = getScreenshotPlus(); + if (screenshotPlus.isEnabled()) ci.cancel(); + } + + @Inject(method = "method_22691", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/texture/NativeImage;writeTo(Ljava/io/File;)V"), cancellable = true) + private static void interceptScreenshotFile(NativeImage nativeImage, File file, Consumer consumer, CallbackInfo ci) throws IOException { + ScreenshotPlus screenshotPlus = getScreenshotPlus(); + + // aunque el módulo esté apagado, pasar las referencias para poder usar los comandos para las capturas + screenshotPlus.setScreenshot(nativeImage); + screenshotPlus.setScreenshotFile(file); + + if (!screenshotPlus.isEnabled()) return; + + screenshotPlus.sendScreenshotMessage(); + + switch (screenshotPlus.defaultAction.getValue()) { + case COPY -> screenshotPlus.copyScreenshot(nativeImage); + case SAVE -> screenshotPlus.saveScreenshot(); + case NONE -> ci.cancel(); + } + + ci.cancel(); + } + + @Unique + private static ScreenshotPlus getScreenshotPlus() { + return ModuleManager.INSTANCE.getModuleByClass(ScreenshotPlus.class); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/mixin/SkyRendererMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/SkyRendererMixin.java new file mode 100644 index 0000000..8510ed3 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/mixin/StringHelperMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/StringHelperMixin.java new file mode 100644 index 0000000..3a130b7 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/StringHelperMixin.java @@ -0,0 +1,18 @@ +package me.retucio.camtweaks.mixin; + +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; + +@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 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/remappedSrc/me/retucio/camtweaks/mixin/StuckArrowsFeatureRendererMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/StuckArrowsFeatureRendererMixin.java new file mode 100644 index 0000000..51f0864 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/StuckArrowsFeatureRendererMixin.java @@ -0,0 +1,19 @@ +package me.retucio.camtweaks.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.NoRender; +import net.minecraft.client.render.entity.feature.StuckArrowsFeatureRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(StuckArrowsFeatureRenderer.class) +public abstract class StuckArrowsFeatureRendererMixin { + + @ModifyReturnValue(method = "getObjectCount", at = @At("RETURN")) + private int noRenderStuckArrows(int original) { + NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); + if (noRender.isEnabled() && !noRender.stuckArrows.isEnabled()) return 0; + return original; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/mixin/TextRendererDrawerMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/TextRendererDrawerMixin.java new file mode 100644 index 0000000..2f4b7e8 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/TextRendererDrawerMixin.java @@ -0,0 +1,49 @@ +package me.retucio.camtweaks.mixin; + +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.NoRender; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.text.Style; +import net.minecraft.text.TextColor; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.*; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +// falta italics pero no sé dónde se comprueba eso, no es aquí :P +@Mixin(TextRenderer.Drawer.class) +public abstract class TextRendererDrawerMixin { + + @Unique + NoRender noRender; + + @Inject(method = "(Lnet/minecraft/client/font/TextRenderer;FFIIZ)V", at = @At("TAIL")) + private void getModules(TextRenderer textRenderer, float x, float y, int color, int backgroundColor, boolean shadow, CallbackInfo ci) { + noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); + } + + @Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isBold()Z")) + private boolean noRenderBold(Style style) { + return !(noRender.isEnabled() && !noRender.bold.isEnabled()) && style.isBold(); + } + + @Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isUnderlined()Z")) + private boolean noRenderUnderlined(Style style) { + return !(noRender.isEnabled() && !noRender.underlined.isEnabled()) && style.isUnderlined(); + } + + @Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isStrikethrough()Z")) + private boolean noRenderStrikethrough(Style style) { + return !(noRender.isEnabled() && !noRender.strikethrough.isEnabled()) && style.isStrikethrough(); + } + + @Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isObfuscated()Z")) + private boolean noRenderMTS(Style style) { + return !(noRender.isEnabled() && !noRender.scrambledText.isEnabled()) && style.isObfuscated(); + } + + @ModifyArg(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/TextRenderer$Drawer;getRenderColor(Lnet/minecraft/text/TextColor;)I")) + private TextColor noRenderColor(TextColor original) { + return !noRender.color.is(NoRender.Colors.DEFAULT) ? TextColor.fromFormatting(noRender.color.getValue().toFormatting()) : original; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/mixin/Vec3dMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/Vec3dMixin.java new file mode 100644 index 0000000..5549be6 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/mixin/WeatherRenderingMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/WeatherRenderingMixin.java new file mode 100644 index 0000000..47eb40f --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/WeatherRenderingMixin.java @@ -0,0 +1,43 @@ +package me.retucio.camtweaks.mixin; + +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.NoRender; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.WeatherRendering; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.particle.ParticlesMode; +import net.minecraft.util.math.Vec3d; +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 java.util.List; + + +@Mixin(WeatherRendering.class) +public abstract class WeatherRenderingMixin { + + @Unique + NoRender noRender; + + @Inject(method = "", at = @At("TAIL")) + public void getModules(CallbackInfo ci) { + noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); + } + + @Inject(method = "addParticlesAndSound", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;addParticleClient(Lnet/minecraft/particle/ParticleEffect;DDDDDD)V"), cancellable = true) + private void noRainParticles(ClientWorld world, Camera camera, int ticks, ParticlesMode particlesMode, CallbackInfo ci) { + if (noRender.isEnabled() && !noRender.rain.isEnabled()) ci.cancel(); + } + + @Inject(method = "renderPrecipitation(Lnet/minecraft/client/render/VertexConsumerProvider;Lnet/minecraft/util/math/Vec3d;IFLjava/util/List;Ljava/util/List;)V", at = @At("HEAD")) + private void noRenderRainAndSnow(VertexConsumerProvider vertexConsumers, Vec3d pos, int range, float gradient, List rainPieces, List snowPieces, CallbackInfo ci) { + if (noRender.isEnabled()) { + if (!noRender.rain.isEnabled()) rainPieces.clear(); + if (!noRender.snow.isEnabled()) snowPieces.clear(); + } + } +} diff --git a/remappedSrc/me/retucio/camtweaks/mixin/WorldRendererMixin.java b/remappedSrc/me/retucio/camtweaks/mixin/WorldRendererMixin.java new file mode 100644 index 0000000..cc28b47 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/WorldRendererMixin.java @@ -0,0 +1,48 @@ +package me.retucio.camtweaks.mixin; + +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.BlockOutline; +import me.retucio.camtweaks.module.modules.Freecam; +import net.minecraft.client.render.WorldRenderer; +import net.minecraft.util.math.ColorHelper; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.awt.*; + +@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; + } + + @Redirect(method = "renderTargetBlockOutline", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/ColorHelper;withAlpha(II)I")) + private int modifyBlockOutlineColor(int alpha, int rgb) { + BlockOutline outline = ModuleManager.INSTANCE.getModuleByClass(BlockOutline.class); + if (!outline.isEnabled()) return ColorHelper.withAlpha(alpha, rgb); + + if (outline.rainbow.isEnabled()) { + float speed = 10001 - outline.rainbowSpeed.getFloatValue(); // 10001 para evitar divisiones por cero + float hue = (System.currentTimeMillis() % (int) speed) / speed; + Color gamingProMax = Color.getHSBColor(hue, 1, 1); + + return new Color( + gamingProMax.getRed(), + gamingProMax.getGreen(), + gamingProMax.getBlue(), + outline.alpha.getIntValue() + ).getRGB(); + } else { + return new Color( + outline.red.getIntValue(), + outline.green.getIntValue(), + outline.blue.getIntValue(), + outline.alpha.getIntValue() + ).getRGB(); + } + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/mixin/accessor/ClientPlayNetworkHandlerAccessor.java b/remappedSrc/me/retucio/camtweaks/mixin/accessor/ClientPlayNetworkHandlerAccessor.java new file mode 100644 index 0000000..b01662e --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/mixin/accessor/KeyBindingAccessor.java b/remappedSrc/me/retucio/camtweaks/mixin/accessor/KeyBindingAccessor.java new file mode 100644 index 0000000..2395094 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/mixin/accessor/StatusEffectInstanceAccessor.java b/remappedSrc/me/retucio/camtweaks/mixin/accessor/StatusEffectInstanceAccessor.java new file mode 100644 index 0000000..4882be7 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/mixin/accessor/StatusEffectInstanceAccessor.java @@ -0,0 +1,12 @@ +package me.retucio.camtweaks.mixin.accessor; + +import net.minecraft.entity.effect.StatusEffectInstance; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(StatusEffectInstance.class) +public interface StatusEffectInstanceAccessor { + + @Accessor("duration") + void setDuration(int duration); +} diff --git a/remappedSrc/me/retucio/camtweaks/module/Module.java b/remappedSrc/me/retucio/camtweaks/module/Module.java new file mode 100644 index 0000000..970d25e --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/Module.java @@ -0,0 +1,153 @@ +package me.retucio.camtweaks.module; + +import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.event.events.camtweaks.ToggleModuleEvent; +import me.retucio.camtweaks.module.settings.BooleanSetting; +import me.retucio.camtweaks.module.settings.EnumSetting; +import me.retucio.camtweaks.module.settings.KeySetting; +import me.retucio.camtweaks.module.settings.AbstractSetting; +import me.retucio.camtweaks.util.ChatUtil; +import net.minecraft.client.MinecraftClient; +import org.lwjgl.glfw.GLFW; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +// clase base para los módulos +public class Module { + + // atributos + private String name; + private String description; + private boolean enabled; + private boolean saveSettings = true; + + // dejar al usuario elegir si el módulo debería apagarse tras soltar su tecla asignada, o si la tecla debería alternar su estado + protected EnumSetting keyMode = new EnumSetting<>("modo de tecla", "cómo interpretar la tecla configurada", KeyModes.class, KeyModes.TOGGLE); + protected KeySetting bind = new KeySetting("tecla", "tecla asignada al módulo, ESC para desactivar", GLFW.GLFW_KEY_UNKNOWN); + protected BooleanSetting notify = new BooleanSetting("notificar", "notificar en el chat al activar / desactivar", true); + + private final List settings = new ArrayList<>(); + + protected MinecraftClient mc = MinecraftClient.getInstance(); + + public Module(String name, String description) { + this.name = name; + this.description = description; + addSettings(bind, keyMode, notify); + } + + + // ajustes + public List getSettings() { + return settings; + } + + @SuppressWarnings("unchecked") + public S addSetting(AbstractSetting setting) { + settings.add(setting); + setting.setModule(this); + return (S) setting; // por convenciencia + } + + public void addSettings(AbstractSetting... settings) { + for (AbstractSetting setting : settings) addSetting(setting); + } + + + // encendido y apagado del módulo + public void toggle() { + 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(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)); + } + + + // otros métodos + public void onTick() {} + public void onKey(int key, int action) {} + + // getters y setters + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + + public boolean isEnabled() { + 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(); + } + + public boolean shouldToggleOnBindRelease() { + return keyMode.is(KeyModes.HOLD); + } + + public boolean shouldSaveSettings() { + return saveSettings; + } + + public void shouldSaveSettings(boolean value) { + this.saveSettings = value; + } + + public int getKey() { + return bind.getKey(); + } + + public void setKey(int key) { + bind.setKey(key); + } + + public void assignKey(int key) { + bind.setDefaultKey(key); + bind.setKey(key); + } + + public KeySetting getBind() { + return bind; + } + + public enum KeyModes { + 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; } + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/module/ModuleManager.java b/remappedSrc/me/retucio/camtweaks/module/ModuleManager.java new file mode 100644 index 0000000..5f86a0f --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/ModuleManager.java @@ -0,0 +1,86 @@ +package me.retucio.camtweaks.module; + +import me.retucio.camtweaks.event.EventBus; +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.module.modules.*; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + + +// 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; + + public ModuleManager(EventBus bus) { + this.eventBus = bus; + addModules(); + } + + // por orden alfabético y todo, flipas + private void addModules() { + modules.add(new AntiInvis()); + modules.add(new BlockOutline()); + modules.add(new BossbarStack()); + modules.add(new ChatPlus()); + modules.add(new CritsPlus()); + modules.add(new DamageOverlay()); + modules.add(new FakePlayer()); + modules.add(new Freecam()); + modules.add(new Freelook()); + modules.add(new Fullbright()); + modules.add(new HandView()); + modules.add(new HUD()); + modules.add(new Nametags()); + modules.add(new NoRender()); + modules.add(new PerspectivePlus()); + modules.add(new ScreenshotPlus()); + modules.add(new TimeChanger()); + modules.add(new Zoom()); + + modules.sort(Comparator.comparing(module -> module.getName().toLowerCase())); + + // registrar los "listeners" necesarios + for (Module module : getEnabledModules()) { + for (Method method : module.getClass().getDeclaredMethods()) { + if (method.isAnnotationPresent(SubscribeEvent.class)) { + eventBus.register(module); + break; + } + } + } + } + + + // para obtener módulos más fácilmente (por nombre, clase, o la lista completa) + public List getModules() { + return modules; + } + + public List getEnabledModules() { + List enabledModules = new ArrayList<>(); + for (Module module : modules) + if (module.isEnabled()) enabledModules.add(module); + + return enabledModules; + } + + public Module getModuleByName(String name) { + for (Module module : modules) + if (module.getName().equalsIgnoreCase(name)) return module; + return null; + } + + public T getModuleByClass(Class clazz) { + for (Module module : modules) + if (clazz.isInstance(module)) + return clazz.cast(module); + return null; + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/module/modules/AntiInvis.java b/remappedSrc/me/retucio/camtweaks/module/modules/AntiInvis.java new file mode 100644 index 0000000..e46c211 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/modules/AntiInvis.java @@ -0,0 +1,14 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.module.Module; + +/** continúa en: + * @see me.retucio.camtweaks.mixin.EntityMixin + */ + +public class AntiInvis extends Module { + + public AntiInvis() { + super("anti invis", "te permite ver a los jugadores invisibles"); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/module/modules/BlockOutline.java b/remappedSrc/me/retucio/camtweaks/module/modules/BlockOutline.java new file mode 100644 index 0000000..bc93592 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/modules/BlockOutline.java @@ -0,0 +1,31 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.BooleanSetting; +import me.retucio.camtweaks.module.settings.NumberSetting; + +/** continúa en: + * @see me.retucio.camtweaks.mixin.WorldRendererMixin + */ + +public class BlockOutline extends Module { + + public BooleanSetting rainbow = addSetting(new BooleanSetting("RGB", "erre ge be gueiming", false)); + public NumberSetting rainbowSpeed = addSetting(new NumberSetting("velocidad", "velocidad de la bandera gay", 2000, 0, 10000, 2)); + + public NumberSetting red = addSetting(new NumberSetting("rojo", "factor r del rbg", 0, 0, 255, 1)); + public NumberSetting green = addSetting(new NumberSetting("verde", "factor g del rgb", 0, 0, 255, 1)); + public NumberSetting blue = addSetting(new NumberSetting("azul", "factor b del rbg", 0, 0, 255, 1)); + + public NumberSetting alpha = addSetting(new NumberSetting("opacidad", "transparencia invertida", 102, 0, 255, 1)); + + public BlockOutline() { + super("contorno", "customiza el contorno de los bloques"); + rainbow.onUpdate(v -> { + rainbowSpeed.setVisible(v); + red.setVisible(!v); + green.setVisible(!v); + blue.setVisible(!v); + }); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/module/modules/BossbarStack.java b/remappedSrc/me/retucio/camtweaks/module/modules/BossbarStack.java new file mode 100644 index 0000000..799e162 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/module/modules/ChatPlus.java b/remappedSrc/me/retucio/camtweaks/module/modules/ChatPlus.java new file mode 100644 index 0000000..119412d --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/modules/ChatPlus.java @@ -0,0 +1,220 @@ +package me.retucio.camtweaks.module.modules; + +import com.mojang.authlib.GameProfile; +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.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.util.ChatUtil; +import me.retucio.camtweaks.util.interfaces.IChatHudLine; +import me.retucio.camtweaks.util.interfaces.IChatHudLineVisible; +import me.retucio.camtweaks.util.interfaces.TextVisitor; +import net.minecraft.client.gl.RenderPipelines; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.PlayerSkinDrawer; +import net.minecraft.client.gui.hud.ChatHudLine; +import net.minecraft.client.network.PlayerListEntry; +import net.minecraft.text.*; +import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** 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 = 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 = 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 ChatPlus() { + super("chat plus", "mejoras para el chat"); + updateDateFormat(); + updateClientName(); + timestamps.onUpdate(v -> timestampSecs.setVisible(v)); + timestampSecs.onUpdate(x -> updateDateFormat()); + } + + public final IntList lines = new IntArrayList(); + private record CustomHeadEntry(String prefix, Identifier texture) {} + private static final List CUSTOM_HEAD_ENTRIES = new ArrayList<>(); + private SimpleDateFormat dateFormat; + + private static final Pattern loggerRegex = Pattern.compile("\\n(\\n|\\s)+\\n"); + private static final Pattern usernameRegex = Pattern.compile("^(?:<[0-9]{2}:[0-9]{2}>\\s)?<(.*?)>.*"); + private static final Pattern 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*)?)"); + + @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 (loggerRegex.matcher(messageString).find()) { + MutableText newMessage = Text.empty(); + TextVisitor.visit(message, (text, style, string) -> { + Matcher antiClearMatcher = loggerRegex.matcher(string); + if (antiClearMatcher.find()) + newMessage.append(Text.literal(antiClearMatcher.replaceAll("\n\n")).setStyle(style)); + else + newMessage.append(text.copyContentOnly().setStyle(style)); + + return Optional.empty(); + }, Style.EMPTY); + message = newMessage; + } + } + + // agregar sellos de tiempo a los mensajes + if (timestamps.isEnabled()) { + Text timestamp = Text.literal("<" + dateFormat.format(new Date()) + "> ").formatted(Formatting.GRAY); + message = Text.empty().append(timestamp).append(message); + } + + // modificar el mensaje final + event.setMessage(message); + } + + @SubscribeEvent + private void onSendMessage(SendMessageEvent event) { + // evitar mandar coordenadas por el chat + if (coordsProtection.isEnabled() && containsCoordinates(event.getMessage())) { + ChatUtil.warn(Text.literal("cuidadito con las coordenadas chavalín").append( + getSendButton(event.getMessage()))); + + event.cancel(); + } + } + + 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; + + // dibujar la cabeza al principio del mensaje + if (((IChatHudLineVisible) (Object) line).smegma$isStartOfEntry()) + drawTexture(context, (IChatHudLine) (Object) line, y, color); + + context.getMatrices().pushMatrix(); + context.getMatrices().translate(10, 0); + } + + public void afterDrawMessage(DrawContext context) { + // finalizar renderizado de la cabeza + if (!isEnabled() || !showHeads.isEnabled()) return; + context.getMatrices().popMatrix(); + } + + @SuppressWarnings("DataFlowIssue") + private void drawTexture(DrawContext context, IChatHudLine line, int y, int color) { + String text = line.smegma$getText().trim(); + + int startOffset = 0; + + // buscar el sello del tiempo si lo hay para dibujar la cabeza correctamente + try { + 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().trim(), startOffset)) { + context.drawTexture(RenderPipelines.GUI_TEXTURED, entry.texture(), 0, y, 0, 0, 8, 8, 64, 64, 64, 64, color); + return; + } + } + + // obtener y dibujar la cabeza del jugador + GameProfile sender = getSender(line, text); + if (sender == null) return; + + PlayerListEntry entry = mc.getNetworkHandler().getPlayerListEntry(sender.getId()); + if (entry == null) return; + + PlayerSkinDrawer.draw(context, entry.getSkinTextures(), 0, y, 8); + } + + @SuppressWarnings("DataFlowIssue") + private GameProfile getSender(IChatHudLine line, String text) { + // obtener el jugador que envió un mensaje + GameProfile sender = line.smegma$getSender(); + + if (sender == null) { + Matcher usernameMatcher = usernameRegex.matcher(text); + + if (usernameMatcher.matches()) { + String username = usernameMatcher.group(1); + + PlayerListEntry entry = mc.getNetworkHandler().getPlayerListEntry(username); + if (entry != null) sender = entry.getProfile(); + } + } + return sender; + } + + @SuppressWarnings("DataFlowIssue") + private MutableText getSendButton(String message) { + // 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:"); + hintMsg.setStyle(hintBaseText.getStyle().withFormatting(Formatting.GRAY)); + hintBaseText.append(hintMsg); + + hintBaseText.append(Text.literal("\n" + message)); + + sendButton.setStyle(sendButton.getStyle() + .withFormatting(Formatting.DARK_RED) + .withClickEvent(new ClientClickEvent(CommandManager.getCommandByName("send").toString(message))) + .withHoverEvent(new HoverEvent.ShowText(hintBaseText))); + + return sendButton; + } + + 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/remappedSrc/me/retucio/camtweaks/module/modules/CritsPlus.java b/remappedSrc/me/retucio/camtweaks/module/modules/CritsPlus.java new file mode 100644 index 0000000..bb71255 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/modules/CritsPlus.java @@ -0,0 +1,38 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.BooleanSetting; +import me.retucio.camtweaks.module.settings.NumberSetting; + +/** continúa en: + * @see me.retucio.camtweaks.mixin.DamageParticleMixin + * @see me.retucio.camtweaks.mixin.DamageParticleFactoryMixin + */ + +public class CritsPlus extends Module { + + public BooleanSetting rainbow = addSetting(new BooleanSetting("LUCES GAMING", "PARTÍCULAS GAMING", false)); + public NumberSetting rainbowSpeed = addSetting(new NumberSetting("velocidad del erre ge be", "qué tan gaming son las luces gaming", 1000, 0, 10000, 2)); + + public NumberSetting red = addSetting(new NumberSetting("rojo", "comunismo", 0, 0, 255, 1)); + public NumberSetting green = addSetting(new NumberSetting("verde", "vox", 0, 0, 255, 1)); + public NumberSetting blue = addSetting(new NumberSetting("azul", "metanfetamina", 255, 0, 255, 1)); + public NumberSetting alpha = addSetting(new NumberSetting("alpha", "opacidad", 255, 0, 255, 1)); + + public NumberSetting scale = addSetting(new NumberSetting("escala", "tamaño", 1, 0, 2, 0.05)); + public NumberSetting multiplier; // no sé dónde se calcula cuántas partículas aparecen :/ + public NumberSetting velocityMultipler = addSetting(new NumberSetting("dispersión", "multiplicador de la velocidad de dispersión", 1, 0, 10, 0.1)); + public NumberSetting gravity = addSetting(new NumberSetting("gravedad", "multiplicador de fuerza de gravedad", 1, 0, 10, 0.1)); + public NumberSetting maxAge = addSetting(new NumberSetting("vida máxima", "cuánto persiste la partícula", 4, 0, 50, 1)); + public BooleanSetting collide = addSetting(new BooleanSetting("colisionar", "colisionar con bloques", false)); + + public CritsPlus() { + super("críticos", "cambia la apariencia de los críticos al gusto"); + rainbow.onUpdate(v -> { + rainbowSpeed.setVisible(v); + red.setVisible(!v); + green.setVisible(!v); + blue.setVisible(!v); + }); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/module/modules/DamageOverlay.java b/remappedSrc/me/retucio/camtweaks/module/modules/DamageOverlay.java new file mode 100644 index 0000000..b65f03e --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/modules/DamageOverlay.java @@ -0,0 +1,75 @@ +package me.retucio.camtweaks.module.modules; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.textures.GpuTextureView; +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.NumberSetting; +import net.minecraft.client.texture.NativeImage; +import net.minecraft.client.texture.NativeImageBackedTexture; + +import java.awt.*; + +/** continúa en: + * @see me.retucio.camtweaks.mixin.OverlayTextureMixin + */ + +public class DamageOverlay extends Module { + + public NumberSetting red = addSetting(new NumberSetting("rojo", "r o j o", 255, 0, 255, 1)); + public NumberSetting green = addSetting(new NumberSetting("verde", "v e r d e", 0, 0, 255, 1)); + public NumberSetting blue = addSetting(new NumberSetting("azul", "a z u l", 0, 0, 255, 1)); + public NumberSetting alpha = addSetting(new NumberSetting("alpha", "o p a c i d a d", 77, 0, 255, 1)); + + private NativeImageBackedTexture texture = null; + + public DamageOverlay() { + super("superposición de daño", "modifica el color en el que se renderiza la superposición de recibir daño"); + + NumberSetting[] settings = {red, green, blue, alpha}; + for (NumberSetting setting : settings) + setting.onUpdate(v -> reloadOverlayIfReady()); + } + + @Override + public void onEnable() { + reloadOverlayIfReady(); + super.onEnable(); + } + + @Override + public void onDisable() { + reloadOverlayIfReady(); + super.onDisable(); + } + + private void reloadOverlayIfReady() { + if (texture != null && texture.getImage() != null) reloadOverlay(texture); + } + + // recargar el overlay (superposición) + public void reloadOverlay(NativeImageBackedTexture texture) { + if (this.texture == null) this.texture = texture; + + int color = isEnabled() ? + new Color(red.getIntValue(), green.getIntValue(), blue.getIntValue(), 255 - alpha.getIntValue()).getRGB() + : new Color(255, 0, 0, 178).getRGB(); + + NativeImage image = texture.getImage(); + for (int y = 0; y < 8; y++) + for (int x = 0; x < 16; x++) + image.setColorArgb(x, y, color); + + uploadTexture(); + } + + // resubir las texturas + private void uploadTexture() { + GpuTextureView overlayTex = RenderSystem.getShaderTexture(33985); + RenderSystem.setShaderTexture(33985, overlayTex); + + texture.upload(); + + GpuTextureView mainTex = RenderSystem.getShaderTexture(33984); + RenderSystem.setShaderTexture(33984, mainTex); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/module/modules/FakePlayer.java b/remappedSrc/me/retucio/camtweaks/module/modules/FakePlayer.java new file mode 100644 index 0000000..27edae9 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/modules/FakePlayer.java @@ -0,0 +1,44 @@ +package me.retucio.camtweaks.module.modules; + +import com.mojang.authlib.GameProfile; +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.StringSetting; +import net.minecraft.client.network.OtherClientPlayerEntity; +import net.minecraft.entity.Entity; + +import java.util.UUID; + +public class FakePlayer extends Module { + + public StringSetting name = addSetting(new StringSetting("nombre", "qué nombre asignarle al jugador", "apio boy", 22)); + + private OtherClientPlayerEntity player = null; + + public FakePlayer() { + super("jugador falso", "invoca una entidad de jugador falsa por motivos de testeo"); + } + + @Override + public void onEnable() { + if (mc.world == null) return; + + player = new OtherClientPlayerEntity(mc.world, new GameProfile(UUID.randomUUID(), name.getValue())); +// player.copyPositionAndRotation(mc.player); + player.copyFrom(mc.player); + + mc.world.addEntity(player); + + super.onEnable(); + } + + @Override + public void onDisable() { + if (mc.world == null || player == null) return; + + player.setRemoved(Entity.RemovalReason.KILLED); + player.onRemoved(); + player = null; + + super.onDisable(); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/module/modules/Freecam.java b/remappedSrc/me/retucio/camtweaks/module/modules/Freecam.java new file mode 100644 index 0000000..61547d4 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/modules/Freecam.java @@ -0,0 +1,375 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.event.Stage; +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.ClientPlayerInteractionManagerMixin + * @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", "permite 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; + if (event.getStage() != Stage.PRE) return; + + Packet packet = event.getPacket(); + if (packet instanceof PlayerActionC2SPacket + || packet instanceof PlayerInteractBlockC2SPacket + || packet instanceof PlayerInteractItemC2SPacket + || packet 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/remappedSrc/me/retucio/camtweaks/module/modules/Freelook.java b/remappedSrc/me/retucio/camtweaks/module/modules/Freelook.java new file mode 100644 index 0000000..51fceb4 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/module/modules/Fullbright.java b/remappedSrc/me/retucio/camtweaks/module/modules/Fullbright.java new file mode 100644 index 0000000..b0b4777 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/modules/Fullbright.java @@ -0,0 +1,78 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.mixin.accessor.StatusEffectInstanceAccessor; +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.EnumSetting; +import me.retucio.camtweaks.module.settings.NumberSetting; +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.entity.effect.StatusEffects; +import net.minecraft.registry.Registries; +import org.lwjgl.glfw.GLFW; + +/** continúa en: + * @see me.retucio.camtweaks.mixin.LightmapTextureManagerMixin + */ + +public class Fullbright extends Module { + + public EnumSetting mode = addSetting(new EnumSetting<>("modo", "qué modo de iluminación emplear (usar poción con shaders)", Modes.class, Modes.GAMMA)); + + public NumberSetting red = addSetting(new NumberSetting("rojo", "cantidad de rojo a aplicar", + 255, 0, 255, 1)); + + public NumberSetting green = addSetting(new NumberSetting("verde", "cantidad de verde a aplicar", + 255, 0, 255, 1)); + + public NumberSetting blue = addSetting(new NumberSetting("azul", "cantidad de azul a aplicar", + 255, 0, 255, 1)); + + public NumberSetting alpha = addSetting(new NumberSetting("opacidad", "opacidad del shader", + 255, 0, 255, 1)); + + public Fullbright() { + super("brilli brilli", "deshabilita la oscuridad (y aplica colores a los shaders)"); + assignKey(GLFW.GLFW_KEY_K); + mode.onUpdate(mode -> { if (mode != Modes.POTION) disableNightVision(); }); + mode.onUpdate(mode -> { + boolean v = mode.equals(Modes.GAMMA); + red.setVisible(v); + green.setVisible(v); + blue.setVisible(v); + alpha.setVisible(v); + }); + } + + @Override + public void onDisable() { + disableNightVision(); + super.onDisable(); + } + + @Override + public void onTick() { + if (mc.player == null || !mode.getValue().equals(Modes.POTION)) return; + + if (mc.player.hasStatusEffect(Registries.STATUS_EFFECT.getEntry(StatusEffects.NIGHT_VISION.value()))) { + StatusEffectInstance instance = mc.player.getStatusEffect(Registries.STATUS_EFFECT.getEntry(StatusEffects.NIGHT_VISION.value())); + if (instance != null && instance.getDuration() < 5200) ((StatusEffectInstanceAccessor) instance).setDuration(5200); + } else { + mc.player.addStatusEffect(new StatusEffectInstance(Registries.STATUS_EFFECT.getEntry(StatusEffects.NIGHT_VISION.value()), 69, 0)); + } + } + + private void disableNightVision() { + if (mc.player == null) return; + if (mc.player.hasStatusEffect(Registries.STATUS_EFFECT.getEntry(StatusEffects.NIGHT_VISION.value()))) + mc.player.removeStatusEffect(Registries.STATUS_EFFECT.getEntry(StatusEffects.NIGHT_VISION.value())); + } + + + public enum Modes { + GAMMA("gamma"), + POTION("poción"); + + private final String name; + Modes(String name) { this.name = name; } + @Override public String toString() { return name; } + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/module/modules/GUI.java b/remappedSrc/me/retucio/camtweaks/module/modules/GUI.java new file mode 100644 index 0000000..9ec7597 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/modules/GUI.java @@ -0,0 +1,139 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.command.CommandManager; +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.event.events.TickEvent; +import me.retucio.camtweaks.event.events.camtweaks.LoadClickGUIEvent; +import me.retucio.camtweaks.event.events.camtweaks.LoadCommandManagerEvent; +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.*; + +// módulo no visible solo para los ajustes de la interfaz (y del cliente en general) +public class GUI extends Module { + + public BooleanSetting rainbow = addSetting(new BooleanSetting("gaming", "gaming", false)); + public NumberSetting rainbowSpeed = addSetting(new NumberSetting("velocidad del gaming", "velocidad, del gaming.", + 1000, 0, 10000, 2)); + public NumberSetting saturation = addSetting(new NumberSetting("saturación del gaming", "saturación, del gaming", + 1, 0, 1, 0.01)); + public NumberSetting brightness = addSetting(new NumberSetting("brillo del gaming", "brillo, del gaming", + 0.8, 0, 1, 0.01)); + + public NumberSetting red = addSetting(new NumberSetting("rojo", "cantidad de rojo en el RGB del marco", 70, 0, 255, 1)); + public NumberSetting green = addSetting(new NumberSetting("verde", "cantidad de verde en el RGB del marco", 20, 0, 255, 1)); + public NumberSetting blue = addSetting(new NumberSetting("azul", "cantidad de azul en el RGB del marco", 210, 0, 255, 1)); + public NumberSetting alpha = addSetting(new NumberSetting("alpha", "opacidad del marco", 230, 0, 255, 1)); + + // números negativos para deslizamiento inverso, 0 para desactivar + public NumberSetting scrollSens = addSetting(new NumberSetting("sensibilidad del scroll", "qué tan sensible es la interfaz a la rueda del ratón", + 5, -15, 15, 0.5)); + public BooleanSetting scrollBar = addSetting(new BooleanSetting("barra de desplazamiento", "renderizar una barra de desplazamiento a la derecha de la interfaz", true)); + + public BooleanSetting searchBar = addSetting(new BooleanSetting("barra de búsqueda", "renderizar una barra de búsqueda que filtra resultados en todos los marcos abiertos", true)); + public BooleanSetting matchCase = addSetting(new BooleanSetting("distinguir mayúsculas", "la búsqueda es sensible a mayúsculas y minúsculas", false)); + // ^^^ no sé de qué sirve porque está todo en minúsculas pero bueno + + public BooleanSetting blur = addSetting(new BooleanSetting("desenfoque", "desenfocar el fondo mientras la interfaz está abierta", true)); + + 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)); + + private int prevRed, prevGreen, prevBlue; + + public GUI() { + super("interfaz", "ajustes de la interfaz, y otros misceláneos"); + assignKey(GLFW.GLFW_KEY_RIGHT_SHIFT); + + // registrar aquí, porque no se añade a ModuleManager.modules. de lo contrario no podría detectar eventos + CameraTweaks.EVENT_BUS.register(this); + + keyMode.setVisible(false); + notify.setVisible(false); + + searchBar.onUpdate(v -> matchCase.setVisible(v)); + } + + @SubscribeEvent + public void onLoadCommandManager(LoadCommandManagerEvent event) { + commandPrefix.onUpdate(prefix -> CommandManager.INSTANCE.setPrefix(prefix)); + commandPrefix.setDefaultValue(CommandManager.INSTANCE.getPrefix()); + + chatName.onUpdate(name -> { + ChatUtil.updatePrefix(name); + ModuleManager.INSTANCE.getModuleByClass(ChatPlus.class).updateClientName(); + }); + } + + // lógica un poco prolija pero bueno + @SubscribeEvent + public void onLoadClickGUI(LoadClickGUIEvent event) { + rainbow.onUpdate(v -> { + if (v) { + prevRed = red.getIntValue(); + prevGreen = green.getIntValue(); + prevBlue = blue.getIntValue(); + } else { + red.setValue(prevRed); + green.setValue(prevGreen); + blue.setValue(prevBlue); + } + + rainbowSpeed.setVisible(v); + saturation.setVisible(v); + brightness.setVisible(v); + red.setVisible(!v); + green.setVisible(!v); + blue.setVisible(!v); + + applyRGBAColorUpdates(); + }); + + red.onUpdate(r -> applyRGBAColorUpdates()); + green.onUpdate(g -> applyRGBAColorUpdates()); + blue.onUpdate(b -> applyRGBAColorUpdates()); + alpha.onUpdate(a -> applyRGBAColorUpdates()); + } + + @SubscribeEvent + public void onTick(TickEvent.Post event) { + if (rainbow.isEnabled()) { + float speed = (float) (rainbowSpeed.getMax() - rainbowSpeed.getValue()); + float hue = (System.currentTimeMillis() % (long) speed) / speed; + Color color = Color.getHSBColor(hue, saturation.getFloatValue(), brightness.getFloatValue()); + + Colors.red = color.getRed(); + Colors.green = color.getGreen(); + Colors.blue = color.getBlue(); + + updateColor(); + } + } + + private void applyRGBAColorUpdates() { + Colors.red = red.getIntValue(); + Colors.green = green.getIntValue(); + Colors.blue = blue.getIntValue(); + Colors.alpha = alpha.getIntValue(); + updateColor(); + } + + private void updateColor() { + Colors.updateAllColors(new Color( + Colors.red, + Colors.green, + Colors.blue, + Colors.alpha + )); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/module/modules/HUD.java b/remappedSrc/me/retucio/camtweaks/module/modules/HUD.java new file mode 100644 index 0000000..654cf7a --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/modules/HUD.java @@ -0,0 +1,56 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.BooleanSetting; +import me.retucio.camtweaks.module.settings.EnumSetting; +import me.retucio.camtweaks.module.settings.NumberSetting; +import me.retucio.camtweaks.module.settings.StringSetting; + +public class HUD extends Module { + + public NumberSetting red = addSetting(new NumberSetting("rojo", "cantidad de rojo", 255, 0, 255, 1)); + public NumberSetting green = addSetting(new NumberSetting("verde", "cantidad de verde", 255, 0, 255, 1)); + public NumberSetting blue = addSetting(new NumberSetting("azul", "cantidad de azul", 255, 0, 255, 1)); + + public BooleanSetting rainbow = addSetting(new BooleanSetting("arcoíris", "gay.", false)); + public NumberSetting rainbowSpeed = addSetting(new NumberSetting("velocidad del arcoíris", "velocidad del arcoíris", 1000, 0, 10000, 2)); + + public NumberSetting alpha = addSetting(new NumberSetting("opacidad", "antitransparencia", 255, 0, 255, 1)); + public BooleanSetting shadow = addSetting(new BooleanSetting("sombra", "texto con sombra", true)); + + public BooleanSetting dontOverride = addSetting(new BooleanSetting("no sobreescribir", "evita dibujar por encima de otros elementos de la interfaz", true)); + + public EnumSetting timeFormat = addSetting(new EnumSetting<>("formato de la hora", "12h o 24h", TimeFormat.class, TimeFormat.TWENTY_FOUR_HOUR)); + public NumberSetting timezone = addSetting(new NumberSetting("zona horaria", "zona horaria en UTC+n", 1, -6, 6, 1)); + + public BooleanSetting coords = addSetting(new BooleanSetting("coordenadas", "mostrar coordenadas", true)); + public StringSetting customText = addSetting(new StringSetting("texto custom", "marca de agua (dejar vacío para quitar)", "ESCROTO", 40)); + public BooleanSetting fps = addSetting(new BooleanSetting("fps", "mostrar frames por segundo", true)); + public BooleanSetting tps = addSetting(new BooleanSetting("tps", "mostrar tasa de ticks por segundo del server", true)); + public BooleanSetting time = addSetting(new BooleanSetting("hora", "mostrar hora actual", true)); + + public HUD() { + super("HUD", "superposición de la pantalla con info. adicional"); + + rainbow.onUpdate(v -> { + rainbowSpeed.setVisible(v); + red.setVisible(!v); + green.setVisible(!v); + blue.setVisible(!v); + }); + + time.onUpdate(v -> { + timeFormat.setVisible(v); + timezone.setVisible(v); + }); + } + + public enum TimeFormat { + TWENTY_FOUR_HOUR("24h"), + TWELVE_HOUR("12h"); + + final String name; + TimeFormat(String name) { this.name = name; } + @Override public String toString() { return name; } + } +} diff --git a/remappedSrc/me/retucio/camtweaks/module/modules/HandView.java b/remappedSrc/me/retucio/camtweaks/module/modules/HandView.java new file mode 100644 index 0000000..0b00eb5 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/modules/HandView.java @@ -0,0 +1,131 @@ +package me.retucio.camtweaks.module.modules; + +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; +import me.retucio.camtweaks.module.settings.NumberSetting; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.Hand; +import net.minecraft.util.math.RotationAxis; +import org.joml.Vector3d; + +/** continúa en: + * @see me.retucio.camtweaks.mixin.HeldItemRendererMixin + */ + +public class HandView extends Module { + + // ajustes de animaciones + 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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"); + } + + @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())); + rotate(event.getMatrices(), new Vector3d(rotMainX.getValue(), rotMainY.getValue(), rotMainZ.getValue())); + } + else { + scale(event.getMatrices(), new Vector3d(scaleOffX.getValue(), scaleOffY.getValue(), scaleOffZ.getValue())); + translate(event.getMatrices(), new Vector3d(posOffX.getValue(), posOffY.getValue(), posOffZ.getValue())); + rotate(event.getMatrices(), new Vector3d(rotOffX.getValue(), rotOffY.getValue(), rotOffZ.getValue())); + } + } + + @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())); + rotate(event.getMatrices(), new Vector3d(rotArmX.getValue(), rotArmY.getValue(), rotArmZ.getValue())); + } + + private void rotate(MatrixStack matrix, Vector3d rotation) { + matrix.multiply(RotationAxis.POSITIVE_X.rotationDegrees((float) rotation.x)); + matrix.multiply(RotationAxis.POSITIVE_Y.rotationDegrees((float) rotation.y)); + matrix.multiply(RotationAxis.POSITIVE_Z.rotationDegrees((float) rotation.z)); + } + + private void scale(MatrixStack matrix, Vector3d scale) { + matrix.scale((float) scale.x, (float) scale.y, (float) scale.z); + } + + private void translate(MatrixStack matrix, Vector3d translation) { + matrix.translate((float) translation.x, (float) translation.y, (float) translation.z); + } + + +} diff --git a/remappedSrc/me/retucio/camtweaks/module/modules/Nametags.java b/remappedSrc/me/retucio/camtweaks/module/modules/Nametags.java new file mode 100644 index 0000000..f406a52 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/modules/Nametags.java @@ -0,0 +1,136 @@ +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.module.settings.ListSetting; +import me.retucio.camtweaks.util.Lists; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.EntityType; +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 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.LivingEntityRendererMixin + * @see me.retucio.camtweaks.mixin.PlayerEntityMixin + */ + +public class Nametags extends Module { + + public ListSetting> entities = addSetting(new ListSetting<>("entidades", "entidades cuyo nametag será visible", + Lists.entityList, Lists.allFalse(Lists.entityList), Lists.entityNames)); + + public BooleanSetting alwaysVisible = addSetting(new BooleanSetting("siempre mostrar nametags", "mostrar nametag cuando el jugador está agachado o es invisible", false)); + public BooleanSetting health = addSetting(new BooleanSetting("mostrar vida", "muestra la vida de una entidad en su nametag", true)); + public EnumSetting healthMode = addSetting(new EnumSetting<>("mostrar vida en", "de qué manera mostrar la vida", HealthMode.class, HealthMode.POINTS)); + + public BooleanSetting countItems = addSetting(new BooleanSetting("contar items", "muestra cuánto de un item hay en un stack dropeado", true)); + public BooleanSetting showProjectileDamage = addSetting(new BooleanSetting("daño del proyectil", "muestra cuánto daño hace un proyectil en su nametag", true)); + + public BooleanSetting distinguishBabies = addSetting(new BooleanSetting("distinguir bebés", "cambia el nametag cuando una entidad está en su fase bebé", 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"); + + // entidades activadas por defecto + entities.setEnabled(EntityType.PLAYER, true); + entities.setEnabled(EntityType.ITEM, true); + entities.setEnabled(EntityType.ARROW, true); + entities.setEnabled(EntityType.SPECTRAL_ARROW, true); + entities.setEnabled(EntityType.TRIDENT, true); + entities.setDefaultValues(entities.getValues()); + + health.onUpdate(v -> healthMode.setVisible(v)); + } + + // literalmente cómo lo calcula Minecraft + public String 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 && 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)); + + long bonus = 0; + if (arrow.isCritical()) bonus = finalDamage / 2 - 1; + + if (healthMode.is(HealthMode.HEARTS)) finalDamage /= 2; + return finalDamage + (bonus > 0 ? " ~ " + (finalDamage + bonus) : ""); + } + + @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 "..."; + } + 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; } + } + +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/module/modules/NoRender.java b/remappedSrc/me/retucio/camtweaks/module/modules/NoRender.java new file mode 100644 index 0000000..6b3c41a --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/modules/NoRender.java @@ -0,0 +1,89 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.BooleanSetting; +import me.retucio.camtweaks.module.settings.EnumSetting; +import me.retucio.camtweaks.module.settings.ListSetting; +import me.retucio.camtweaks.module.settings.NumberSetting; +import me.retucio.camtweaks.util.Lists; +import net.minecraft.particle.ParticleType; +import net.minecraft.util.Formatting; + +/** continúa en: + * @see me.retucio.camtweaks.mixin.ClientPlayNetworkHandlerMixin + * @see me.retucio.camtweaks.mixin.EntityEffectParticleEffectMixin + * @see me.retucio.camtweaks.mixin.FogRendererMixin + * @see me.retucio.camtweaks.mixin.GameRendererMixin + * @see me.retucio.camtweaks.mixin.InGameHudMixin + * @see me.retucio.camtweaks.mixin.InGameOverlayRendererMixin + * @see me.retucio.camtweaks.mixin.ParticleManagerMixin + * @see me.retucio.camtweaks.mixin.StuckArrowsFeatureRendererMixin + * @see me.retucio.camtweaks.mixin.TextRendererDrawerMixin + * @see me.retucio.camtweaks.mixin.WeatherRenderingMixin + */ + +public class NoRender extends Module { + + public BooleanSetting spyglassOverlay = addSetting(new BooleanSetting("catalejo", "renderizar overlay del catalejo", false)); + public BooleanSetting fluidOverlay = addSetting(new BooleanSetting("fluídos", "renderizar fluídos sobre la cámara como el agua, lava o nieve en polvo (aunque no sea un fluído)", false)); + public BooleanSetting pumpkinOverlay = addSetting(new BooleanSetting("calabaza", "renderiza el overlay de la calabaza tallada", false)); + public BooleanSetting fireOverlay = addSetting(new BooleanSetting("fuego", "renderizar llamas sobre la cámara", false)); + public BooleanSetting portalOverlay = addSetting(new BooleanSetting("portal", "renderizar el overlay del portal del nether", false)); + + public BooleanSetting rain = addSetting(new BooleanSetting("lluvia", "l l u v i a", true)); + public BooleanSetting snow = addSetting(new BooleanSetting("nieve", "n i e v e", true)); + public BooleanSetting dimensionFog = addSetting(new BooleanSetting("niebla de dimensión", "n i e b l a", true)); + public BooleanSetting endFlashes; // para cuando actualice + + public ListSetting> particles = addSetting(new ListSetting<>("partículas", "lista de partículas que se renderizan", + Lists.particleList, Lists.allTrue(Lists.particleList), Lists.particleNames)); + + public BooleanSetting nauseaEffect = addSetting(new BooleanSetting("náusea", "renderizar borrachera", false)); + public BooleanSetting blindnessEffect = addSetting(new BooleanSetting("ceguera", "renderizar miopía", false)); + public BooleanSetting darknessEffect = addSetting(new BooleanSetting("oscuridad", "renderizar miedo a la oscuridad", false)); + public BooleanSetting nightVisionEffect; + public NumberSetting potionParticleAlpha = addSetting(new NumberSetting("opacidad de burbujas", "opacidad de las partículas de pociones", + 170, 0, 255, 1)); + + public BooleanSetting scoreboard = addSetting(new BooleanSetting("marcador", "mostrar marcador a la derecha", false)); + public BooleanSetting titles = addSetting(new BooleanSetting("títulos", "mostrar títulos (del comando /title)", false)); + public BooleanSetting totemPop = addSetting(new BooleanSetting("tótem", "renderizar el pop del tótem", true)); + + public BooleanSetting stuckArrows = addSetting(new BooleanSetting("flechas clavadas", "renderizar flechas clavadas en jugadores", false)); + + public BooleanSetting bold = addSetting(new BooleanSetting("negrita", "letra pero §lgorda", true)); +// public BooleanSetting italics = addSetting(new BooleanSetting("cursiva", "letra pero §otorcida", true)); + public BooleanSetting underlined = addSetting(new BooleanSetting("subrayado", "letra pero §nen el suelo", true)); + public BooleanSetting strikethrough = addSetting(new BooleanSetting("tachado", "letra pero §mdiscriminada", true)); + public EnumSetting color = addSetting(new EnumSetting<>("colores", "§co§4r§6g§eu§al§2l§9o §1g§5a§dy", Colors.class, Colors.DEFAULT)); + public BooleanSetting scrambledText = addSetting(new BooleanSetting("garabato", "engarabatar texto (o como se diga) (§kasí§r)", false)); + + public NoRender() { + super("no render", "customiza qué se renderiza y qué no"); + } + + public enum Colors { + BLACK("negro"), + DARK_BLUE("azul oscuro"), + DARK_GREEN("verde"), + DARK_AQUA("cian"), + DARK_RED("granate"), + DARK_PURPLE("morado"), + GOLD("naranja"), + GRAY("gris claro"), + DARK_GRAY("gris oscuro"), + BLUE("azul"), + GREEN("lima"), + AQUA("turquesa"), + RED("rojo"), + LIGHT_PURPLE("lila"), + YELLOW("amarillo"), + WHITE("blanco"), + DEFAULT("por defecto"); + + private final String name; + Colors(String name) { this.name = name; } + @Override public String toString() { return name; } + public Formatting toFormatting() { return (Formatting.byColorIndex(this.ordinal())); } + } +} diff --git a/remappedSrc/me/retucio/camtweaks/module/modules/PerspectivePlus.java b/remappedSrc/me/retucio/camtweaks/module/modules/PerspectivePlus.java new file mode 100644 index 0000000..59a2a8c --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/modules/PerspectivePlus.java @@ -0,0 +1,59 @@ +package me.retucio.camtweaks.module.modules; + +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; +import me.retucio.camtweaks.module.settings.*; +import me.retucio.camtweaks.util.KeyUtil; +import org.lwjgl.glfw.GLFW; + +// continúa en CameraMixin +public class PerspectivePlus extends Module { + + private double distance; + + // ajustes + public BooleanSetting clip = addSetting(new BooleanSetting( + "clip", "atravesar bloques con la cámara", true)); + + public NumberSetting defaultDistance = addSetting(new NumberSetting( + "distancia", "distancia a la que está la cámara del jugador por defecto", + 4, 1, 20, 0.2)); + + public NumberSetting scrollSens = addSetting(new NumberSetting( + "sensibilidad del scroll", "sensibilidad de la rueda del ratón (0 para desactivar)", + 1, 0, 8, 0.1)); + + 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 PerspectivePlus() { + super("perspectiva plus", "añade cositas chulas al cambio de perspectiva"); + } + + @Override + public void onEnable() { + distance = defaultDistance.getValue(); + super.onEnable(); + } + + @SubscribeEvent + public void onPerspectiveChange(PerspectiveChangeEvent event) { + distance = defaultDistance.getValue(); + } + + @SubscribeEvent + public void onMouseScroll(MouseScrollEvent event) { + if (mc.options.getPerspective() == net.minecraft.client.option.Perspective.FIRST_PERSON + || mc.currentScreen != null || scrollSens.getValue() <= 0) return; + + if (KeyUtil.isKeyDown(scrollKey.getKey())) { + distance -= event.getVertical() / 4 * (scrollSens.getValue() * distance); + event.cancel(); + } + } + + public double getDistance() { + return distance; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/module/modules/ScreenshotPlus.java b/remappedSrc/me/retucio/camtweaks/module/modules/ScreenshotPlus.java new file mode 100644 index 0000000..4bbad22 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/modules/ScreenshotPlus.java @@ -0,0 +1,218 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.command.CommandManager; +import me.retucio.camtweaks.event.events.ClientClickEvent; +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.client.texture.NativeImage; +import net.minecraft.text.ClickEvent; +import net.minecraft.text.HoverEvent; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import org.jetbrains.annotations.NotNull; + +import java.awt.*; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + + +/** continúa en: + * @see me.retucio.camtweaks.mixin.ScreenshotRecorderMixin + */ + +public class ScreenshotPlus extends Module { + + public BooleanSetting saveButton = addSetting(new BooleanSetting("botón de guardar", "mostrar botón para guardar la captura localmente", true)); + public BooleanSetting copyButton = addSetting(new BooleanSetting("botón de copiar", "mostrar botón para copiar la captura al portapapeles", true)); + public BooleanSetting openButton = addSetting(new BooleanSetting("botón de abrir", "mostrar botón para abrir el archivo de la captura", true)); + public BooleanSetting discardButton = addSetting(new BooleanSetting("botón de descartar", "mostrar botón para descartar la captura", true)); + + public EnumSetting defaultAction = addSetting(new EnumSetting<>("por defecto", "qué acción tomar por defecto", + ScreenshotActions.class, ScreenshotActions.NONE)); + + private NativeImage screenshot; + private File screenshotFile; + + public ScreenshotPlus() { + super("capturas de pantalla", "elige qué hacer tras tomar una captura de pantalla"); + } + + public void sendScreenshotMessage() { + MutableText baseText = Text.literal("captura de pantalla tomada\n"); + if (saveButton.isEnabled() && !defaultAction.is(ScreenshotActions.SAVE)) baseText.append(getSaveButton().append(" ")); + if (copyButton.isEnabled()) baseText.append(getCopyButton().append(" ")); + if (openButton.isEnabled() && defaultAction.is(ScreenshotActions.SAVE)) baseText.append(getOpenButton().append(" ")); + if (discardButton.isEnabled() && !defaultAction.is(ScreenshotActions.NONE)) baseText.append(getDiscardButton().append(" ")); + ChatUtil.info(baseText); + } + + + // acciones con la captura + + public void copyScreenshot(NativeImage nativeImage) { + try { + BufferedImage bufferedImage = new BufferedImage(nativeImage.getWidth(), nativeImage.getHeight(), BufferedImage.TYPE_INT_ARGB); + for (int x = 0; x < nativeImage.getWidth(); x++) + for (int y = 0; y < nativeImage.getHeight(); y++) + bufferedImage.setRGB(x, y, nativeImage.getColorArgb(x, y)); + + ScreenshotPlus.TransferableImage trans = new TransferableImage(bufferedImage); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(trans, null); + ChatUtil.info("captura copiada al portapapeles"); + } catch (Exception e) { + ChatUtil.error("no se pudo copiar la captura al portapapeles"); + e.printStackTrace(); + } + } + + public void copyScreenshot() { + copyScreenshot(this.screenshot); + } + + public void saveScreenshot(NativeImage image) throws IOException { + image.writeTo(screenshotFile); + ChatUtil.info(Text.literal("captura guardada como: ").append( + Text.literal(screenshotFile.getName()) + .formatted(Formatting.UNDERLINE) + .styled(style -> style.withClickEvent(new ClickEvent.OpenFile(screenshotFile.getAbsoluteFile()))) + ) + ); + } + + public void saveScreenshot() throws IOException { + saveScreenshot(this.screenshot); + } + + // clase ayudante para el portapapeles + public static class TransferableImage implements Transferable { + private final Image image; + + public TransferableImage(Image image) { + this.image = image; + } + + @Override + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[]{DataFlavor.imageFlavor}; + } + + @Override + public boolean isDataFlavorSupported(DataFlavor flavor) { + return DataFlavor.imageFlavor.equals(flavor); + } + + @Override + public @NotNull Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { + if (!DataFlavor.imageFlavor.equals(flavor)) + throw new UnsupportedFlavorException(flavor); + + return image; + } + } + + + // botones para el mensaje + + @SuppressWarnings("DataFlowIssue") + private MutableText getSaveButton() { + MutableText button = Text.literal("[GUARDAR]"); + MutableText hintBaseText = Text.literal(""); + + MutableText hintMsg = Text.literal(ScreenshotActions.SAVE.toString()); + hintMsg.setStyle(hintBaseText.getStyle().withFormatting(Formatting.GRAY)); + hintBaseText.append(hintMsg); + + button.setStyle(button.getStyle() + .withFormatting(Formatting.BOLD, Formatting.GOLD) + .withClickEvent(new ClientClickEvent(CommandManager.getCommandByName("guardarcaptura").toString())) + .withHoverEvent(new HoverEvent.ShowText(hintBaseText))); + + return button; + } + + @SuppressWarnings("DataFlowIssue") + private MutableText getCopyButton() { + MutableText button = Text.literal("[COPIAR]"); + MutableText hintBaseText = Text.literal(""); + + MutableText hintMsg = Text.literal(ScreenshotActions.COPY.toString()); + hintMsg.setStyle(hintBaseText.getStyle().withFormatting(Formatting.GRAY)); + hintBaseText.append(hintMsg); + + button.setStyle(button.getStyle() + .withFormatting(Formatting.BOLD, Formatting.AQUA) + .withClickEvent(new ClientClickEvent(CommandManager.getCommandByName("copiarcaptura").toString())) + .withHoverEvent(new HoverEvent.ShowText(hintBaseText))); + + return button; + } + + private MutableText getOpenButton() { + MutableText button = Text.literal("[ABRIR]"); + MutableText hintBaseText = Text.literal(""); + + MutableText hintMsg = Text.literal("abrir archivo de imagen"); + hintMsg.setStyle(hintBaseText.getStyle().withFormatting(Formatting.GRAY)); + hintBaseText.append(hintMsg); + + button.setStyle(button.getStyle() + .withFormatting(Formatting.BOLD, Formatting.GRAY) + .withClickEvent(new ClickEvent.OpenFile(screenshotFile)) + .withHoverEvent(new HoverEvent.ShowText(hintBaseText))); + + return button; + } + + @SuppressWarnings("DataFlowIssue") + private MutableText getDiscardButton() { + MutableText button = Text.literal("[DESCARTAR]"); + MutableText hintBaseText = Text.literal(""); + + MutableText hintMsg = Text.literal(ScreenshotActions.NONE.toString()); + hintMsg.setStyle(hintBaseText.getStyle().withFormatting(Formatting.GRAY)); + hintBaseText.append(hintMsg); + + button.setStyle(button.getStyle() + .withFormatting(Formatting.BOLD, Formatting.DARK_RED) + .withClickEvent(new ClientClickEvent(CommandManager.getCommandByName("purgar").toString("1"))) + .withHoverEvent(new HoverEvent.ShowText(hintBaseText))); + + return button; + } + + + // otros + + public enum ScreenshotActions { + SAVE("guardar archivo"), + COPY("copiar al portapapeles"), + NONE("no hacer nada"); + + private final String name; + ScreenshotActions(String name) { this.name = name; } + @Override public String toString() { return name; } + } + + public NativeImage getScreenshot() { + return screenshot; + } + + public void setScreenshot(NativeImage screenshot) { + this.screenshot = screenshot; + } + + public File getScreenshotFile() { + return screenshotFile; + } + + public void setScreenshotFile(File screenshotFile) { + this.screenshotFile = screenshotFile; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/module/modules/TimeChanger.java b/remappedSrc/me/retucio/camtweaks/module/modules/TimeChanger.java new file mode 100644 index 0000000..7ffe811 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/module/modules/Zoom.java b/remappedSrc/me/retucio/camtweaks/module/modules/Zoom.java new file mode 100644 index 0000000..7d87f4d --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/modules/Zoom.java @@ -0,0 +1,100 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.CameraTweaks; +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.KeyUtil; +import org.lwjgl.glfw.GLFW; + +// continúa en GameRendererMixin +public class Zoom extends Module { + + 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 = 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 = addSetting(new KeySetting("tecla del scroll", "qué tecla mantener para usar la rueda del ratón", GLFW.GLFW_KEY_LEFT_CONTROL)); + + public NumberSetting defaultZoom = addSetting(new NumberSetting("zoom", "cantidad de zoom", + 6, 1, 10, 0.1)); + + public NumberSetting mouseSensMultiplier = addSetting(new NumberSetting("sensibilidad", "multiplicador de la sensibilidad del ratón", + 0.7, 0.01, 1, 0.05)); + + 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; + private double prevFov; + private boolean prevHUD; + private double value; + + public Zoom() { + super("zoom", "lupa"); + super.keyMode.setValue(KeyModes.HOLD); + super.keyMode.setDefaultValue(KeyModes.HOLD); + super.notify.setEnabled(false); + super.notify.setDefaultValue(false); + assignKey(GLFW.GLFW_KEY_F); + } + + @Override + public void onEnable() { + if (mc.options == null) return; + + CameraTweaks.EVENT_BUS.register(this); + + prevSmoothCam = mc.options.smoothCameraEnabled; + prevMouseSens = mc.options.getMouseSensitivity().getValue(); + prevFov = mc.options.getFov().getValue(); + prevHUD = mc.options.hudHidden; + mc.options.hudHidden = !showHUD.isEnabled(); + + value = defaultZoom.getValue(); + } + + @Override + public void onDisable() { + if (mc.options == null) return; + CameraTweaks.EVENT_BUS.unregister(this); + + mc.options.smoothCameraEnabled = prevSmoothCam; + mc.options.getMouseSensitivity().setValue(prevMouseSens); + mc.options.hudHidden = prevHUD; + + mc.worldRenderer.scheduleTerrainUpdate(); + } + + @Override + public void onTick() { + mc.options.smoothCameraEnabled = smoothCam.isEnabled(); + if (!smoothCam.isEnabled()) + mc.options.getMouseSensitivity().setValue(prevMouseSens * mouseSensMultiplier.getValue()); + } + + @SubscribeEvent + private void onMouseScroll(MouseScrollEvent event) { + 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; + + event.cancel(); + } + } + + @SubscribeEvent + private void onGetFov(GetFOVEvent event) { + event.setFov((float) (event.getFov() / value)); + + if (prevFov != event.getFov()) mc.worldRenderer.scheduleTerrainUpdate(); + prevFov = event.getFov(); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/module/settings/AbstractSetting.java b/remappedSrc/me/retucio/camtweaks/module/settings/AbstractSetting.java new file mode 100644 index 0000000..69fb7a4 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/settings/AbstractSetting.java @@ -0,0 +1,58 @@ +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; + +// base para los tipos de ajustes +public abstract class AbstractSetting { + + private final String name; + private final String description; + + private boolean visible = true; + private boolean searchMatch = true; + + private Module module; + + protected AbstractSetting(String name, String description) { + this.name = name; + this.description = description; + } + + public boolean isVisible() { + return visible; + } + + public void setVisible(boolean visible) { + this.visible = visible; + } + + public boolean isSearchMatch() { + return searchMatch; + } + + public void setSearchMatch(boolean searchMatch) { + this.searchMatch = searchMatch; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public Module getModule() { + return module; + } + + public void setModule(Module module) { + this.module = module; + } + + public void fireUpdateEvent() { + CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this, module.shouldSaveSettings())); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/module/settings/BooleanSetting.java b/remappedSrc/me/retucio/camtweaks/module/settings/BooleanSetting.java new file mode 100644 index 0000000..ed1ec8b --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/settings/BooleanSetting.java @@ -0,0 +1,55 @@ +package me.retucio.camtweaks.module.settings; + +import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent; + +import java.util.function.Consumer; + +// ajuste booleano, es decir, o se encuentra encencido o apagado (similar a un interruptor) +public class BooleanSetting extends AbstractSetting { + + private boolean defaultValue; + private boolean enabled; + + private Consumer updateListener; + + public BooleanSetting(String name, String description, boolean defaultValue) { + super(name, description); + this.enabled = defaultValue; + this.defaultValue = defaultValue; + } + + public void toggle() { + setEnabled(!enabled); + if (updateListener != null) updateListener.accept(enabled); + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + if (this.enabled != enabled) { + this.enabled = enabled; + fireUpdateEvent(); + if (updateListener != null) updateListener.accept(enabled); + } + } + + public boolean getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(boolean value) { + defaultValue = value; + } + + public void reset() { + setEnabled(defaultValue); + } + + public void onUpdate(Consumer listener) { + this.updateListener = listener; + if (updateListener != null) updateListener.accept(enabled); // actualizar por primera vez + } +} diff --git a/remappedSrc/me/retucio/camtweaks/module/settings/EnumSetting.java b/remappedSrc/me/retucio/camtweaks/module/settings/EnumSetting.java new file mode 100644 index 0000000..2821f5a --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/settings/EnumSetting.java @@ -0,0 +1,90 @@ +package me.retucio.camtweaks.module.settings; + +import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; + +// ajuste que te deja elegir entre distintas opciones definidas, dentro de un Enum +public class EnumSetting> extends AbstractSetting { + + private final List values; + private E defaultValue; + + private E value; + private int index; + + private Consumer updateListener; + + public EnumSetting(String name, String description, Class enumClass, E defaultValue) { + super(name, description); + this.values = Arrays.asList(enumClass.getEnumConstants()); + this.defaultValue = defaultValue; + this.value = defaultValue; + this.index = values.indexOf(defaultValue); + } + + public E getValue() { + return value; + } + + public void setValue(E value) { + if (this.value != value) { + this.value = value; + this.index = values.indexOf(value); + fireUpdateEvent(); + if (updateListener != null) updateListener.accept(value); + } + } + + public List getValues() { + return values; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + if (this.index != index) + setValue(values.get(index)); + } + + public boolean is(E value) { + return this.value == value; + } + + // ciclar entre los valores del enum + public void cycle() { + if (index < values.size() - 1) + setIndex(index + 1); + else + setIndex(0); + } + + public void cycleBackwards() { + if (index > 0) + setIndex(index - 1); + else + setIndex(values.size() - 1); + } + + public void setDefaultValue(E value) { + defaultValue = value; + } + + public E getDefaultValue() { + return defaultValue; + } + + public void reset() { + setValue(defaultValue); + } + + public void onUpdate(Consumer listener) { + this.updateListener = listener; + if (updateListener != null) updateListener.accept(value); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/module/settings/KeySetting.java b/remappedSrc/me/retucio/camtweaks/module/settings/KeySetting.java new file mode 100644 index 0000000..0263684 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/settings/KeySetting.java @@ -0,0 +1,72 @@ +package me.retucio.camtweaks.module.settings; + +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.ui.frames.ClientSettingsFrame; +import me.retucio.camtweaks.util.ChatUtil; +import me.retucio.camtweaks.util.KeyUtil; +import org.lwjgl.glfw.GLFW; + +import java.util.function.Consumer; + +public class KeySetting extends AbstractSetting { + + private int key; + private int defaultKey; + + private Consumer updateListener; + + public KeySetting(String name, String description, int defaultKey) { + super(name, description); + this.key = defaultKey; + this.defaultKey = defaultKey; + } + + public int getKey() { + return key; + } + + 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 + fireUpdateEvent(); + if (updateListener != null) updateListener.accept(key); + return; + } + + if (ModuleManager.INSTANCE != null) { + for (Module module : ModuleManager.INSTANCE.getModules()) + if (module.getKey() == key && !ClientSettingsFrame.guiSettings.multipleKeybinds.isEnabled() && key != -1) { + module.setKey(-1); + ChatUtil.info("tecla del módulo " + module.getName() + " restablecida"); + } + } + this.key = key; + + fireUpdateEvent(); + if (updateListener != null) updateListener.accept(key); + } + + public int getDefaultKey() { + return defaultKey; + } + + public void setDefaultKey(int key) { + this.defaultKey = key; + } + + public String getKeyName() { + return KeyUtil.getKeyName(key); + } + + public void reset() { + setKey(defaultKey); + } + + public void onUpdate(Consumer listener) { + this.updateListener = listener; + if (updateListener != null) updateListener.accept(key); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/module/settings/ListSetting.java b/remappedSrc/me/retucio/camtweaks/module/settings/ListSetting.java new file mode 100644 index 0000000..8bc3d99 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/settings/ListSetting.java @@ -0,0 +1,97 @@ +package me.retucio.camtweaks.module.settings; + +import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +public class ListSetting extends AbstractSetting { + + private final List options; + private Map values; + private Map defaultValues; + private Map displayNames = null; + + private Consumer> updateListener; + + public ListSetting(String name, String description, List options, Map initialValues) { + super(name, description); + this.options = options; + this.defaultValues = new HashMap<>(); + + for (T option : options) { + boolean enabled = initialValues != null && initialValues.getOrDefault(option, false); + defaultValues.put(option, enabled); + } + this.values = new HashMap<>(defaultValues); + } + + public ListSetting(String name, String description, List options, Map initialValues, Map displayNames) { + this(name, description, options, initialValues); + this.displayNames = displayNames; + } + + public boolean isEnabled(T option) { + return values.getOrDefault(option, false); + } + + public void setEnabled(T option, boolean enabled) { + if (values.containsKey(option) && values.get(option) != enabled) { + values.put(option, enabled); + fireUpdateEvent(); + if (updateListener != null) updateListener.accept(new HashMap<>(values)); + } + } + + public void toggle(T option) { + setEnabled(option, !isEnabled(option)); + } + + public Map getValues() { + return new HashMap<>(values); + } + + public void setValues(Map values) { + this.values = new HashMap<>(values); + } + + public Map getDefaultValues() { + return new HashMap<>(defaultValues); + } + + public void setDefaultValues(Map values) { + defaultValues = values; + } + + public void reset() { + values.clear(); + values.putAll(defaultValues); + fireUpdateEvent(); + if (updateListener != null) updateListener.accept(new HashMap<>(values)); + } + + public void setAll(boolean enabled) { + for (T option : options) values.put(option, enabled); + } + + public void onUpdate(Consumer> listener) { + this.updateListener = listener; + if (updateListener != null) updateListener.accept(new HashMap<>(values)); + } + + public List getOptions() { + return options; + } + + public Map getDisplayNames() { + return displayNames; + } + + public String getDisplayName(T key) { + if (displayNames != null) return displayNames.get(key); + return key.toString(); + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/module/settings/NumberSetting.java b/remappedSrc/me/retucio/camtweaks/module/settings/NumberSetting.java new file mode 100644 index 0000000..82a095e --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/settings/NumberSetting.java @@ -0,0 +1,95 @@ +package me.retucio.camtweaks.module.settings; + +import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent; + +import java.util.function.Consumer; + +// ajuste numérico, es decir, que eliges un valor númerico entre el mínimo y el máximo disponibles +public class NumberSetting extends AbstractSetting { + + private double value; + private double defaultValue; + + private final double min; + private final double max; + private final double increment; // el "increment" es el salto que hay entre valores disponibles + + private Consumer updateListener; + + public NumberSetting(String name, String description, double defaultValue, double min, double max, double increment) { + super(name, description); + this.defaultValue = defaultValue; + this.value = defaultValue; + this.min = min; + this.max = max; + this.increment = increment; + } + + // no permitir valores ajenos a los límites definidos + public static double clamp(double value, double min, double max) { + return Math.clamp(value, min, max); + } + + // como decía, el valor crece o decrece por el "increment" definido + public void increment(boolean positive) { + if (positive) value += increment; + else value -= increment; + value = clamp(value, min, max); + if (updateListener != null) updateListener.accept(value); + } + + + public double getValue() { + return value; + } + + public float getFloatValue() { + return (float) value; // en "float" por conveniencia + } + + public int getIntValue() { + 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; + fireUpdateEvent(); + if (updateListener != null) updateListener.accept(this.value); + } + + public double getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(double value) { + defaultValue = value; + } + + public void reset() { + setValue(defaultValue); + } + + public double getMin() { + return min; + } + + public double getMax() { + return max; + } + + public double getIncrement() { + return increment; + } + + public void onUpdate(Consumer listener) { + this.updateListener = listener; + if (updateListener != null) updateListener.accept(value); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/module/settings/StringSetting.java b/remappedSrc/me/retucio/camtweaks/module/settings/StringSetting.java new file mode 100644 index 0000000..2494100 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/module/settings/StringSetting.java @@ -0,0 +1,54 @@ +package me.retucio.camtweaks.module.settings; + +import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent; + +import java.util.function.Consumer; + +public class StringSetting extends AbstractSetting { + + private String value; + private String defaultValue; + private final int maxLength; + + private Consumer updateListener; + + public StringSetting(String name, String description, String defaultValue, int maxLength) { + super(name, description); + this.value = defaultValue; + this.defaultValue = defaultValue; + this.maxLength = maxLength; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + if (this.value.equals(value)) return; + this.value = value.length() > maxLength ? value.substring(0, maxLength) : value; + fireUpdateEvent(); + if (updateListener != null) updateListener.accept(this.value); + } + + public String getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + public void reset() { + setValue(defaultValue); + } + + public int getMaxLength() { + return maxLength; + } + + public void onUpdate(Consumer listener) { + this.updateListener = listener; + if (updateListener != null) updateListener.accept(value); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/ui/ClickGUI.java b/remappedSrc/me/retucio/camtweaks/ui/ClickGUI.java new file mode 100644 index 0000000..b742bf1 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/ui/ClickGUI.java @@ -0,0 +1,303 @@ +package me.retucio.camtweaks.ui; + +import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.event.events.KeyEvent; +import me.retucio.camtweaks.event.events.MouseClickEvent; +import me.retucio.camtweaks.event.events.MouseScrollEvent; +import me.retucio.camtweaks.event.events.camtweaks.SettingsFrameEvent; +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.AbstractSetting; +import me.retucio.camtweaks.ui.buttons.ListButton; +import me.retucio.camtweaks.ui.buttons.SettingButton; +import me.retucio.camtweaks.ui.frames.ClientSettingsFrame; +import me.retucio.camtweaks.ui.frames.ModuleFrame; +import me.retucio.camtweaks.ui.frames.SettingsFrame; +import me.retucio.camtweaks.ui.widgets.ScrollBarWidget; +import me.retucio.camtweaks.ui.widgets.SearchBarWidget; +import me.retucio.camtweaks.util.ChatUtil; +import me.retucio.camtweaks.util.KeyUtil; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.Text; +import org.lwjgl.glfw.GLFW; + +import java.util.ArrayList; +import java.util.List; + +import static me.retucio.camtweaks.ui.frames.ClientSettingsFrame.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 ClickGUI INSTANCE; + private boolean anyFocused; + private Object selected = null; + + private final ModuleFrame modulesFrame = new ModuleFrame(20, 30, 100, 20); + private final List settingsFrames = new ArrayList<>(); + private final ClientSettingsFrame guiSettingsFrame = new ClientSettingsFrame(200, 30, 100, 20); + + private final ScrollBarWidget scrollBar = new ScrollBarWidget(); + private final SearchBarWidget searchBar = new SearchBarWidget(340, 16, 300, 20); + + private final MinecraftClient mc = MinecraftClient.getInstance(); + + public ClickGUI() { + super(Text.of("interfaz")); + settingsFrames.add(guiSettingsFrame); + CameraTweaks.EVENT_BUS.register(this); + } + + @Override + public void render(DrawContext ctx, int mouseX, int mouseY, float delta) { + scrollBar.setWindowHeight(mc.getWindow().getScaledHeight()); + scrollBar.setContentHeight(calculateContentHeight()); + scrollBar.render(ctx, mouseX, mouseY); + + int scrollOffset = scrollBar.getScrollOffset(); + + searchBar.updateRenderY(scrollOffset); + searchBar.render(ctx, mouseX, mouseY, delta); + searchBar.updatePosition(mouseX, mouseY); + + // actualizar la posición de renderizado vertical de los marcos cada tick + modulesFrame.updateRenderY(scrollOffset); + for (SettingsFrame sf : settingsFrames) + sf.updateRenderY(scrollOffset); + + // 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 : 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); + + for (SettingsFrame sf : settingsFrames) + sf.drawTooltips(ctx, mouseX, mouseY); + + filterSearchResults(); + + super.render(ctx, mouseX, mouseY, delta); + } + + private int calculateContentHeight() { + int bottom = modulesFrame.y + modulesFrame.h + modulesFrame.totalHeight; + for (SettingsFrame frame : settingsFrames) + bottom = Math.max(bottom, frame.y + frame.h + frame.totalHeight); + + return bottom + 20; // padding + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + scrollBar.mouseClicked(mouseX, mouseY, button); + searchBar.mouseClicked(mouseX, mouseY, button); + + // detectar clics sobre los marcos + modulesFrame.mouseClicked(mouseX, mouseY, button); + for (SettingsFrame sf : new ArrayList<>(settingsFrames)) + sf.mouseClicked(mouseX, mouseY, button); + + return super.mouseClicked(mouseX, mouseY, button); + } + + @Override + public boolean mouseReleased(double mouseX, double mouseY, int button) { + scrollBar.mouseReleased(mouseX, mouseY, button); + searchBar.mouseReleased(mouseX, mouseY, button); + + // registrar cuándo se suelta el clic, en cada marco respectivamente + modulesFrame.mouseReleased(mouseX, mouseY, button); + for (SettingsFrame sf : new ArrayList<>(settingsFrames)) + sf.mouseRelease(mouseX, mouseY, button); + return super.mouseReleased(mouseX, mouseY, button); + } + + @Override + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + scrollBar.mouseDragged(mouseY); + return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + } + + @SubscribeEvent + public void onKey(KeyEvent event) { + searchBar.onKey(event.getKey(), event.getAction()); + } + + @SubscribeEvent + public void onMouseScroll(MouseScrollEvent event) { + // subir y bajar la pantalla con la rueda del ratón + scrollBar.onMouseScroll(event.getVertical() * guiSettings.scrollSens.getValue()); + } + + @SubscribeEvent + public void onMouseMiddleButton(MouseClickEvent event) { + // mover todos los marcos a un punto visible al presionar shift + la rueda del ratón + if (CameraTweaks.mc.currentScreen != this || event.getButton() != 2 || !KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT)) return; + + int h = CameraTweaks.mc.getWindow().getScaledHeight(); + int minY = Math.min(modulesFrame.y, settingsFrames.stream().mapToInt(sf -> sf.y).min().orElse(modulesFrame.y)); + int maxY = Math.max(modulesFrame.y + modulesFrame.h, settingsFrames.stream().mapToInt(sf -> sf.y + sf.h).max().orElse(modulesFrame.y + modulesFrame.h)); + int correction = minY < 0 ? -minY + 4 : (maxY > h ? h - maxY - 4 : 0); + + if (correction != 0) { + modulesFrame.y += correction; + settingsFrames.forEach(sf -> sf.y += correction); + } + } + + public void filterSearchResults() { + if (!guiSettings.searchBar.isEnabled()) return; + String searchInput = searchBar.getSearchInput().trim(); + if (!guiSettings.matchCase.isEnabled()) searchInput = searchInput.toLowerCase(); + + for (SettingsFrame sf : settingsFrames) { + for (SettingButton sb : sf.getButtons()) { + AbstractSetting setting = sb.getSetting(); + + if (searchInput.isEmpty()) { + setting.setSearchMatch(true); + continue; + } + + String name = setting.getName(); + String description = setting.getDescription(); + + if (!guiSettings.matchCase.isEnabled()) { + name = name.toLowerCase(); + description = description.toLowerCase(); + } + + setting.setSearchMatch(name.contains(searchInput) || description.contains(searchInput)); + } + } + } + + 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 + SettingsFrame frame = new SettingsFrame(module, x, y, 120, 20); + settingsFrames.add(frame); + CameraTweaks.EVENT_BUS.post(new SettingsFrameEvent.Open(frame)); + } + + public void openListSettingsFrame(Module module, int x, int y) { + if (isSettingsFrameOpen(module)) return; + SettingsFrame frame = new SettingsFrame(module, x, y, 120, 18); + settingsFrames.add(frame); + } + + // cerrar el marco de ajustes + public void closeSettingsFrame(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); + unselect(sf); + } + } + settingsFrames.removeAll(toRemove); + } + + // verificar si un módulo tiene su marco de ajustes abierto + public boolean isSettingsFrameOpen(Module module) { + return settingsFrames.stream() + .anyMatch(sf -> sf.module.getName().equals(module.getName())); + } + + + + public void refreshListButtons() { + for (SettingsFrame frame : settingsFrames) + for (SettingButton button : frame.getButtons()) + if (button instanceof ListButton lb) + lb.refreshDummy(); + } + + + // métodos del súper + + @Override + public void close() { // evitar que al reabrir la interfaz sin previamente haber soltado el clic, se sigan arrastrando objetos + modulesFrame.mouseReleased(0, 0, 0); + settingsFrames.forEach(sf -> sf.mouseRelease(0, 0, 0)); + scrollBar.mouseReleased(0, 0, 0); + searchBar.mouseReleased(0, 0, 0); + + unselect(selected); + super.close(); + } + + @Override + public boolean shouldPause() { + // no pausar el juego cuando se abre la interfaz + return false; + } + + @Override + public boolean shouldCloseOnEsc() { + return super.shouldCloseOnEsc() && !anyFocused; + } + + @Override + protected void applyBlur(DrawContext context) { + if (guiSettings.blur.isEnabled()) super.applyBlur(context); + } + + + // getters y setters de widgets + + public ModuleFrame getModulesFrame() { + return modulesFrame; + } + + public ClientSettingsFrame getGuiSettingsFrame() { + return guiSettingsFrame; + } + + public List getSettingsFrames() { + return settingsFrames; + } + + public SearchBarWidget getSearchBar() { + return searchBar; + } + + public void setAnyFocused(boolean anyFocused) { + this.anyFocused = anyFocused; + } + + + // selección de widgets + + public Object getSelected() { + return selected; + } + + public void setSelected(Object object) { + this.selected = object; + } + + public boolean canSelect(Object object) { + return getSelected() == null || getSelected() == object; + } + + public boolean trySelect(Object object) { + if (canSelect(object)) { + setSelected(object); + return true; + } + return false; + } + + public void unselect(Object object) { + if (selected == object) setSelected(null); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/ui/HUD.java b/remappedSrc/me/retucio/camtweaks/ui/HUD.java new file mode 100644 index 0000000..65fb3d6 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/ui/HUD.java @@ -0,0 +1,110 @@ +package me.retucio.camtweaks.ui; + +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.event.events.PacketEvent; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.Freecam; +import me.retucio.camtweaks.module.modules.HUD.TimeFormat; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ChatScreen; +import net.minecraft.client.render.RenderTickCounter; +import net.minecraft.util.math.Vec3d; + +import java.awt.Color; +import java.time.LocalTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; + +// 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(); + + private long lastPacketTime = 0; + private static float estimatedTPS = 20f; + + public static void render(DrawContext ctx, RenderTickCounter tc) { + if (ModuleManager.INSTANCE == null || mc.player == null || mc.cameraEntity == null) return; + me.retucio.camtweaks.module.modules.HUD hud = ModuleManager.INSTANCE.getModuleByClass(me.retucio.camtweaks.module.modules.HUD.class); + + int width = mc.getWindow().getScaledWidth(); + int height = mc.getWindow().getScaledHeight(); + + Color color; + if (hud.rainbow.isEnabled()) { + float speed = 10001 - hud.rainbowSpeed.getFloatValue(); + float hue = (System.currentTimeMillis() % (int) speed) / speed; + Color gamning = Color.getHSBColor(hue, 1, 1); + color = new Color(gamning.getRed(), gamning.getGreen(), gamning.getBlue(), hud.alpha.getIntValue()); + } else { + color = new Color(hud.red.getIntValue(), hud.green.getIntValue(), hud.blue.getIntValue(), hud.alpha.getIntValue()); + } + boolean shadow = hud.shadow.isEnabled(); + + if (hud.isEnabled()) { + + // coordenadas + if (hud.coords.isEnabled()) { + Vec3d coords; + Freecam freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); + if (freecam.isEnabled()) + coords = new Vec3d( + freecam.getX(tc.getDynamicDeltaTicks()), + freecam.getY(tc.getDynamicDeltaTicks()), + freecam.getZ(tc.getDynamicDeltaTicks()) + ); + else + coords = mc.player.getPos(); + + String text = (int) coords.x + " " + (int) coords.y + " " + (int) coords.z; + ctx.drawText(mc.textRenderer, text, + width - mc.textRenderer.getWidth(text) - 2, + height - mc.textRenderer.fontHeight - 2, + color.getRGB(), shadow); + } + + // fps y tps + if (hud.fps.isEnabled()) + ctx.drawText(mc.textRenderer, "FPS: " + mc.getCurrentFps(), 2, 2, color.getRGB(), shadow); + + if (hud.tps.isEnabled()) + ctx.drawText(mc.textRenderer, "TPS: " + estimatedTPS, 2, 4 + mc.textRenderer.fontHeight, color.getRGB(), shadow); + + // marca de agua + if (!hud.customText.getValue().isEmpty()) { + int y; + if (!mc.player.getActiveStatusEffects().isEmpty() && hud.dontOverride.isEnabled()) y = 26; + else y = 2; + ctx.drawText(mc.textRenderer, hud.customText.getValue(), width - mc.textRenderer.getWidth(hud.customText.getValue()) - 2, y, color.getRGB(), shadow); + } + + // hora real + if (hud.time.isEnabled()) { + int y; + if (mc.currentScreen instanceof ChatScreen && hud.dontOverride.isEnabled()) y = height - mc.textRenderer.fontHeight - 14; + else y = height - mc.textRenderer.fontHeight - 2; + + ZoneOffset offset = ZoneOffset.ofHours(hud.timezone.getIntValue()); + LocalTime now = LocalTime.now(offset); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(hud.timeFormat.is(TimeFormat.TWENTY_FOUR_HOUR) ? "HH:mm" : "hh:mm a"); + String time = now.format(formatter); + + ctx.drawText(mc.textRenderer, time, 2, y, color.getRGB(), shadow); + } + } + } + + @SubscribeEvent + public void onReceivePacket(PacketEvent.Receive event) { + // estimar el tps teniendo en cuenta el tiempo entre paquetes + long now = System.currentTimeMillis(); + if (lastPacketTime > 0) { + long diff = now - lastPacketTime; // ms entre paquetes + float tps = 1000f / diff; + estimatedTPS = Math.min(20.0f, tps); + } + lastPacketTime = now; + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/ui/buttons/BindButton.java b/remappedSrc/me/retucio/camtweaks/ui/buttons/BindButton.java new file mode 100644 index 0000000..39031ec --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/ui/buttons/BindButton.java @@ -0,0 +1,68 @@ +package me.retucio.camtweaks.ui.buttons; + +import me.retucio.camtweaks.module.settings.KeySetting; +import me.retucio.camtweaks.ui.ClickGUI; +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; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.Text; +import org.lwjgl.glfw.GLFW; + +// botón para configurar la tecla asignada a un módulo. comienza a escuchar al hacerle clic +public class BindButton extends SettingButton { + + private final KeySetting setting; + private boolean listening = false; + + public BindButton(KeySetting setting, SettingsFrame parent, int offset) { + super(setting, parent, offset); + this.setting = setting; + } + + @Override + public void render(DrawContext ctx, double mouseX, double mouseY, float delta) { + int bgColor = isHovered((int) mouseX, (int) mouseY) + ? Colors.buttonColor.brighter().getRGB() + : Colors.buttonColor.getRGB(); + + ctx.fill(x, y, x + w, y + h, bgColor); + String label = setting.getName() + ": " + (listening ? "..." : setting.getKeyName()); + ctx.drawText(parent.mc.textRenderer, label, x + 5, y + 3, -1, true); + } + + @Override + public void mouseClicked(double mouseX, double mouseY, int button) { + if (isHovered((int) mouseX, (int) mouseY) && ClickGUI.INSTANCE.trySelect(this)) { + if (button == 0) listening = !listening; + else if (button == 1 && KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT)) + setting.reset(); + } else { + listening = false; + } + } + + public void onKey(int key, int action) { + if (listening && action == GLFW.GLFW_PRESS) { + if (key == GLFW.GLFW_KEY_ESCAPE) + setting.setKey(GLFW.GLFW_KEY_UNKNOWN); + else + setting.setKey(key); + listening = false; + } + } + + public boolean isFocused() { + return listening; + } + + public KeySetting getSetting() { + return setting; + } + + @Override + public void mouseReleased(double mouseX, double mouseY, int button) { + ClickGUI.INSTANCE.unselect(this); + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/ui/buttons/CycleButton.java b/remappedSrc/me/retucio/camtweaks/ui/buttons/CycleButton.java new file mode 100644 index 0000000..728a4f3 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/ui/buttons/CycleButton.java @@ -0,0 +1,85 @@ +package me.retucio.camtweaks.ui.buttons; + +import me.retucio.camtweaks.module.settings.EnumSetting; +import me.retucio.camtweaks.ui.ClickGUI; +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; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import org.lwjgl.glfw.GLFW; + +import java.util.ArrayList; +import java.util.List; + +// botón para los ajustes tipo EnumSetting (de modo) +public class CycleButton> extends SettingButton { + + private final EnumSetting setting; + + public CycleButton(EnumSetting setting, SettingsFrame parent, int offset) { + super(setting, parent, offset); + this.setting = setting; + } + + @Override + public void render(DrawContext ctx, double mouseX, double mouseY, float delta) { + int bgColor = isHovered((int) mouseX, (int) mouseY) + ? Colors.buttonColor.brighter().getRGB() + : Colors.buttonColor.getRGB(); + + ctx.fill(x, y, x + w, y + h, bgColor); // fondo del botón + + // texto del botón: nombre + valor de texto del enum + String label = setting.getName() + ": " + setting.getValue().toString(); + ctx.drawText(parent.mc.textRenderer, label, x + 5, y + 3, -1, true); + } + + @Override + public void drawTooltip(DrawContext ctx, double mouseX, double mouseY) { + if (isHovered((int) mouseX, (int) mouseY)) { + Screen currentScreen = parent.mc.currentScreen; + 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)); + else + lines.add(Text.literal(val.toString())); + } + ctx.drawTooltip(parent.mc.textRenderer, lines, (int) mouseX, (int) mouseY + 20); + } 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) && ClickGUI.INSTANCE.trySelect(this)) { + if (button == 0) { + setting.cycle(); // clic izquierdo -> ciclar + } else if (button == 1) { + // shift + clic derecho -> restablecer + if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT)) + setting.reset(); + else + setting.cycleBackwards(); // solamente clic derecho -> ciclar valores pero hacia atrás + } + } + } + + public EnumSetting getSetting() { + return setting; + } + + @Override + public void mouseReleased(double mouseX, double mouseY, int button) { + ClickGUI.INSTANCE.unselect(this); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/ui/buttons/ListButton.java b/remappedSrc/me/retucio/camtweaks/ui/buttons/ListButton.java new file mode 100644 index 0000000..dc26743 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/ui/buttons/ListButton.java @@ -0,0 +1,119 @@ +package me.retucio.camtweaks.ui.buttons; + +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.BooleanSetting; +import me.retucio.camtweaks.module.settings.ListSetting; +import me.retucio.camtweaks.ui.ClickGUI; +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; +import net.minecraft.text.Text; +import org.lwjgl.glfw.GLFW; + +import java.util.*; + +public class ListButton extends SettingButton { + + private final ListSetting setting; + private final Module dummy; + + private final Map optionButtons = new HashMap<>(); + + public ListButton(ListSetting setting, SettingsFrame parent, int offset) { + super(setting, parent, offset); + this.setting = setting; + + // crear un módulo "dummy" (falso), que se le añade cada entrada en la lista como un BooleanSetting + dummy = new Module(setting.getName(), setting.getDescription()) { + @Override public void onEnable() {} + @Override public void onDisable() {} + }; + + // ocultar cosas innecesarias + dummy.getBind().setVisible(false); + dummy.getSettings().stream() + .filter(s -> s.getName().equalsIgnoreCase("modo de tecla")) + .findFirst() + .ifPresent(s -> s.setVisible(false)); + dummy.getSettings().stream() + .filter(s -> s.getName().equalsIgnoreCase("notificar")) + .findFirst() + .ifPresent(s -> s.setVisible(false)); + dummy.shouldSaveSettings(false); + } + + @Override + public void render(DrawContext ctx, double mouseX, double mouseY, float delta) { + int bgColor = isHovered(mouseX, mouseY) + ? Colors.buttonColor.brighter().getRGB() + : Colors.buttonColor.getRGB(); + + ctx.fill(x, y, x + w, y + h, bgColor); + + String label = setting.getName() + " (" + countEnabled() + "/" + setting.getOptions().size() + ")"; + ctx.drawText(parent.mc.textRenderer, label, x + 5, y + 3, -1, true); + } + + @Override + public void drawTooltip(DrawContext ctx, double mouseX, double mouseY) { + if (isHovered(mouseX, mouseY)) + ctx.drawTooltip(Text.of(setting.getDescription() + "( " + countEnabled() + " de " + setting.getOptions().size() + ")"), (int) mouseX, (int) mouseY); + } + + @Override + public void mouseClicked(double mouseX, double mouseY, int button) { + if (isHovered(mouseX, mouseY) && ClickGUI.INSTANCE.trySelect(this)) { + // click izquierdo / derecho: abrir marco + if (button <= 1 && !KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT)) { + if (ClickGUI.INSTANCE.isSettingsFrameOpen(dummy)) { + ClickGUI.INSTANCE.closeSettingsFrame(dummy); + return; + } + + rebuildDummy(); + ClickGUI.INSTANCE.openListSettingsFrame(dummy, parent.x + 40, parent.y + 40); + // shift + clic derecho: restablecer valores + } else if (button == 1 && KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT)) { + setting.reset(); + refreshDummy(); + } + } + } + + private void rebuildDummy() { + dummy.getSettings().clear(); + optionButtons.clear(); + + setting.getOptions().stream() + .sorted(Comparator.comparing(setting::getDisplayName, String.CASE_INSENSITIVE_ORDER)) + .forEach(option -> { + String displayName = setting.getDisplayName(option); + BooleanSetting b = dummy.addSetting(new BooleanSetting( + displayName, + "incluir " + displayName, + setting.isEnabled(option) + )); + b.onUpdate(value -> setting.setEnabled(option, value)); + optionButtons.put(option, b); + }); + } + + public void refreshDummy() { + optionButtons.forEach((option, boolSetting) -> + boolSetting.setEnabled(setting.isEnabled(option))); + } + + private int countEnabled() { + return (int) setting.getOptions().stream().filter(setting::isEnabled).count(); + } + + public ListSetting getSetting() { + return setting; + } + + @Override + public void mouseReleased(double mouseX, double mouseY, int button) { + ClickGUI.INSTANCE.unselect(this); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/ui/buttons/ModuleButton.java b/remappedSrc/me/retucio/camtweaks/ui/buttons/ModuleButton.java new file mode 100644 index 0000000..040a31c --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/ui/buttons/ModuleButton.java @@ -0,0 +1,74 @@ +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; + +// clase para el botón para cada módulo +public class ModuleButton { + + public Module module; + public ModuleFrame parent; + public int offset; + public final int height = 18; + + public ModuleButton(Module module, ModuleFrame parent, int offset) { + this.module = module; + this.parent = parent; + this.offset = offset; + } + + public void render(DrawContext ctx, double mouseX, double mouseY, float delta) { + ctx.fill( // dibujar el contorno del botón + parent.x + 2, parent.renderY + offset + 3, + parent.x + parent.w - 2 , parent.renderY + height + offset, + determineColor(mouseX, mouseY)); + + ctx.drawText( // dibujar el nombre del módulo + parent.mc.textRenderer, module.getName(), + parent.x + 5, parent.renderY + offset + (height / 2) - (parent.mc.textRenderer.fontHeight / 2) + 2, + -1, true); + + // dibujar "tooltips" (cajas de texto) al pasar el puntero encima del botón, para mostrar su descripción + if (isHovered((int) mouseX, (int) mouseY)) + ctx.drawTooltip(Text.of(module.getDescription()), (int) mouseX, (int) mouseY + 20); + } + + public void mouseClicked(double mouseX, double mouseY, int button) { + if (isHovered((int) mouseX, (int) mouseY) && ClickGUI.INSTANCE.trySelect(this)) { + 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.renderY + offset); + } + } + } + + public void mouseReleased(double mouseX, double mouseY, int button) { + ClickGUI.INSTANCE.unselect(this); + } + + // verifica si el puntero del ratón se encuentra sobre el botón del módulo + public boolean isHovered(int mouseX, int mouseY) { + return ClickGUI.INSTANCE.canSelect(this) + && mouseX > parent.x + && mouseX < parent.x + parent.w + && mouseY > parent.renderY + offset + && mouseY < parent.renderY + height + offset; + } + + public int determineColor(double mouseX, double mouseY) { + // determina el color del botón, dependiendo de si está el puntero encima y si está activado + if (module.isEnabled()) + return isHovered((int) mouseX, (int) mouseY) ? Colors.mainColor.brighter().getRGB() : Colors.mainColor.getRGB(); + return isHovered((int) mouseX, (int) mouseY) ? Colors.buttonColor.brighter().getRGB() : Colors.buttonColor.getRGB(); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/ui/buttons/SettingButton.java b/remappedSrc/me/retucio/camtweaks/ui/buttons/SettingButton.java new file mode 100644 index 0000000..b96794f --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/ui/buttons/SettingButton.java @@ -0,0 +1,80 @@ +package me.retucio.camtweaks.ui.buttons; + +import me.retucio.camtweaks.module.settings.AbstractSetting; +import me.retucio.camtweaks.ui.ClickGUI; +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; + +// clase base para los botones de los ajustes +public abstract class SettingButton { + + protected final AbstractSetting setting; + protected final SettingsFrame parent; + protected int offset; + + protected int x, y, w, h; + + public SettingButton(AbstractSetting setting, SettingsFrame parent, int offset) { + this.setting = setting; + this.parent = parent; + this.offset = offset; + } + + public abstract void render(DrawContext ctx, double mouseX, double mouseY, float delta); + public abstract void mouseClicked(double mouseX, double mouseY, int button); + public abstract void mouseReleased(double mouseX, double mouseY, int button); + + // dibujar "tooltips" (cajitas de texto bajo el puntero del ratón) con la descripción para asistir al usuario en el caso de que tenga down + public void drawTooltip(DrawContext ctx, double mouseX, double mouseY) { + if (isHovered((int) mouseX, (int) mouseY)) + ctx.drawTooltip(Text.of(setting.getDescription()), (int) mouseX, (int) mouseY + 20); + } + + protected boolean isHovered(double mouseX, double mouseY) { + return isHovered((int) mouseX, (int) mouseY); + } + + protected boolean isHovered(int mouseX, int mouseY) { + if (!ClickGUI.INSTANCE.canSelect(this)) return false; + return mouseX > x && mouseX < x + w && + mouseY > y && mouseY < y + h; + } + + public AbstractSetting 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/remappedSrc/me/retucio/camtweaks/ui/buttons/SliderButton.java b/remappedSrc/me/retucio/camtweaks/ui/buttons/SliderButton.java new file mode 100644 index 0000000..7ae54e9 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/ui/buttons/SliderButton.java @@ -0,0 +1,88 @@ +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.ClickGUI; +import me.retucio.camtweaks.ui.frames.ClientSettingsFrame; +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; +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 { + + private final NumberSetting setting; + private boolean dragging = false; + public final DecimalFormat df; // usar formato decimal para el valor del ajuste + + public SliderButton(NumberSetting setting, SettingsFrame parent, int offset) { + 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) { + Color bgColor = Colors.buttonColor; + Color fillingColor = Colors.mainColor; + + if (isHovered(mouseX, mouseY)) { + bgColor = bgColor.brighter(); + fillingColor = fillingColor.brighter(); + } + + ctx.fill(x, y, x + w, y + h, bgColor.getRGB()); + + // calcular cómo de lleno tendría que estar el "slider" + double percent = (setting.getValue() - setting.getMin()) / (setting.getMax() - setting.getMin()); + int filled = (int) (percent * w); + ctx.fill(x, y, x + filled, y + h, fillingColor.getRGB()); + + String label = setting.getName() + ": " + df.format(setting.getValue()); + ctx.drawText(parent.mc.textRenderer, label, x + 5, y + 3, -1, true); + + // 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)); + newVal = Math.round(newVal / setting.getIncrement()) * setting.getIncrement(); + setting.setValue((float) newVal); + } + } + + @Override + public void mouseClicked(double mouseX, double mouseY, int button) { + if (isHovered((int) mouseX, (int) mouseY) && ClickGUI.INSTANCE.trySelect(this)) { + if (button == 0) dragging = true; // arrastrar con el clic izquierdo + else if (button == 1 && KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT)) // restablecer al valor por defecto con shift izquerdo + clic derecho + setting.reset(); + } + } + + @Override + public void mouseReleased(double mouseX, double mouseY, int button) { + ClickGUI.INSTANCE.unselect(this); + 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() == ClientSettingsFrame.guiSettings.getKey()) dragging = false; + } + + public NumberSetting getSetting() { + return setting; + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/ui/buttons/TextButton.java b/remappedSrc/me/retucio/camtweaks/ui/buttons/TextButton.java new file mode 100644 index 0000000..51fabe6 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/ui/buttons/TextButton.java @@ -0,0 +1,99 @@ +package me.retucio.camtweaks.ui.buttons; + +import me.retucio.camtweaks.module.settings.StringSetting; +import me.retucio.camtweaks.ui.ClickGUI; +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; +import net.minecraft.text.Text; +import org.lwjgl.glfw.GLFW; + +import static me.retucio.camtweaks.CameraTweaks.mc; + +// botón para los ajustes que requieran introducir texto +public class TextButton extends SettingButton { + + private boolean typing; + private final StringSetting setting; + private final StringBuilder buffer = new StringBuilder(); + + public TextButton(StringSetting setting, SettingsFrame parent, int offset) { + super(setting, parent, offset); + this.setting = setting; + } + + @Override + public void render(DrawContext ctx, double mouseX, double mouseY, float delta) { + int bgColor = isHovered((int) mouseX, (int) mouseY) + ? Colors.buttonColor.brighter().getRGB() + : Colors.buttonColor.getRGB(); + + ctx.fill(x, y, x + w, y + h, bgColor); + + String label = setting.getName() + ": " + (typing ? buffer + "_" : setting.getValue()); + ctx.drawText(parent.mc.textRenderer, label, x + 5, y + 3, -1, true); + } + + @Override + public void mouseClicked(double mouseX, double mouseY, int button) { + if (isHovered((int) mouseX, (int) mouseY) && ClickGUI.INSTANCE.trySelect(this)) { + if (button == 0) { + typing = true; + buffer.setLength(0); + buffer.append(setting.getValue()); // precargar valor anterior + } else if (button == 1 && KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT)) { + typing = false; + setting.reset(); + } + } else { + typing = false; + } + } + + @Override + public void mouseReleased(double mouseX, double mouseY, int button) { + ClickGUI.INSTANCE.unselect(this); + } + + public void onKey(int key, int action) { + 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 -> { + 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(KeyUtil.shiftKey(c).charAt(0)); + else + charTyped(c.toLowerCase().charAt(0)); + } + } + } + } + + private void charTyped(char c) { + if (!typing) return; + buffer.append(c); + if (mc.textRenderer.getWidth(setting.getName() + ": " + buffer + "_") > w - 8) onBackspace(); + } + + public boolean isFocused() { + return typing; + } + + public StringSetting getSetting() { + return setting; + } + + private void onBackspace() { + if (!buffer.isEmpty()) buffer.deleteCharAt(buffer.length() - 1); + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/ui/buttons/ToggleButton.java b/remappedSrc/me/retucio/camtweaks/ui/buttons/ToggleButton.java new file mode 100644 index 0000000..886182d --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/ui/buttons/ToggleButton.java @@ -0,0 +1,55 @@ +package me.retucio.camtweaks.ui.buttons; + +import me.retucio.camtweaks.module.settings.BooleanSetting; +import me.retucio.camtweaks.ui.ClickGUI; +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; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.Text; +import org.lwjgl.glfw.GLFW; + +import java.awt.*; + +// botón para los ajustes booleanos (funciona como un interruptor) +public class ToggleButton extends SettingButton { + + private final BooleanSetting setting; + + public ToggleButton(BooleanSetting setting, SettingsFrame parent, int offset) { + super(setting, parent, offset); + this.setting = setting; + } + + @Override + public void render(DrawContext ctx, double mouseX, double mouseY, float delta) { + Color color = setting.isEnabled() + ? Colors.enabledToggleButtonColor + : Colors.disabledToggleButtonColor; + + if (isHovered((int) mouseX, (int) mouseY)) + color = color.brighter(); + + ctx.fill(x, y, x + w, y + h, color.getRGB()); + ctx.drawText(parent.mc.textRenderer, setting.getName(), x + 5, y + 3, -1, true); + } + + @Override + public void mouseClicked(double mouseX, double mouseY, int button) { + if (isHovered((int) mouseX, (int) mouseY) && ClickGUI.INSTANCE.trySelect(this)) { + if (button == 0) setting.toggle(); // clic izquierdo para alternar + else if (button == 1 && KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT)) // shift izquierdo + clic derecho para restablecer al valor por defecto + setting.reset(); + } + } + + @Override + public void mouseReleased(double mouseX, double mouseY, int button) { + ClickGUI.INSTANCE.unselect(this); + } + + public BooleanSetting getSetting() { + return setting; + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/ui/frames/ClientSettingsFrame.java b/remappedSrc/me/retucio/camtweaks/ui/frames/ClientSettingsFrame.java new file mode 100644 index 0000000..8cfc933 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/ui/frames/ClientSettingsFrame.java @@ -0,0 +1,85 @@ +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.ClickGUI; +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 ClientSettingsFrame extends SettingsFrame { + + public static final GUI guiSettings = new GUI(); + public boolean extended = false; + private final String title = "ajustes del mod"; + + public ClientSettingsFrame(int x, int y, int w, int h) { + super(guiSettings, x, y, w, h); + } + + @Override + public void render(DrawContext ctx, int mouseX, int mouseY, float delta) { + updateWidth(); + ctx.fill(x, renderY, x + w, renderY + h, Colors.mainColor.getRGB()); + + ctx.drawText(mc.textRenderer, title, + x + 8, + renderY + (h / 2) - (mc.textRenderer.fontHeight / 2), + -1, true); + + ctx.drawText(mc.textRenderer, extended ? "-" : "+", + x + w - mc.textRenderer.getWidth("+") - 8, + renderY + (h / 2) - (mc.textRenderer.fontHeight / 2), + -1, true); + + List visibleButtons = settingButtons.stream() + .filter(sb -> sb.getSetting().isVisible() && sb.getSetting().isSearchMatch()) + .toList(); + + if (extended) { + int currentY = renderY + h + 3; + totalHeight = visibleButtons.size() * h; + ctx.fill(x, currentY - 2, x + w, currentY + totalHeight, Colors.frameBGColor.getRGB()); + + for (SettingButton sb : visibleButtons) { + sb.setX(x + 4); + sb.setY(currentY); + sb.setW(w - 8); + sb.setH(h - h / 4); + sb.render(ctx, mouseX, mouseY, delta); + sb.drawTooltip(ctx, mouseX, mouseY); + currentY += h; + } + } else totalHeight = 0; + } + + @Override + public void mouseClicked(double mouseX, double mouseY, int button) { + if (isHovered(mouseX, mouseY) && ClickGUI.INSTANCE.trySelect(this)) { + if (button == 0) { + dragging = true; + dragX = (int) (mouseX - x); + dragY = (int) (mouseY - y); + } else if (button == 1) { + extended = !extended; + 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) { + ClickGUI.INSTANCE.unselect(this); + if (button == 0 && dragging) + CameraTweaks.EVENT_BUS.post(new GUISettingsFrameEvent.Move()); + + super.mouseRelease(mouseX, mouseY, button); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/ui/frames/ModuleFrame.java b/remappedSrc/me/retucio/camtweaks/ui/frames/ModuleFrame.java new file mode 100644 index 0000000..b2e2c67 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/ui/frames/ModuleFrame.java @@ -0,0 +1,139 @@ +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.ModuleManager; +import me.retucio.camtweaks.ui.ClickGUI; +import me.retucio.camtweaks.ui.buttons.ModuleButton; +import me.retucio.camtweaks.util.Colors; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +import java.util.ArrayList; +import java.util.List; + +// marco para los módulos +public class ModuleFrame { + + public int x, y, w, h; + public int renderY; + public int dragX, dragY; + public int totalHeight = 0; + public boolean dragging, extended; + public final String title = "módulos"; + + private final List moduleButtons = new ArrayList<>(); + + public MinecraftClient mc = MinecraftClient.getInstance(); + + public ModuleFrame(int x, int y, int w, int h) { + this.x = x; + this.y = y; + this.w = w; + this.h = h; + dragging = false; + extended = true; + + // determinar el saliente para cada botón de módulo + int offset = h; + for (Module module : ModuleManager.INSTANCE.getModules()) { + moduleButtons.add(new ModuleButton(module, this, offset)); + updateWidth(); + offset += h; + } + } + + public void updateRenderY(int scrollOffset) { + renderY = y - scrollOffset; + } + + 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(); + int textWidth = mc.textRenderer.getWidth(text); + maxWidth = Math.max(maxWidth, textWidth); + } + this.w = maxWidth + 22; + } + + public void render(DrawContext ctx, int mouseX, int mouseY, float delta) { + updateWidth(); + ctx.fill(x, renderY, x + w, renderY + h, Colors.mainColor.getRGB()); // cabeza del marco + // título del marco + ctx.drawText(mc.textRenderer, Text.literal(Formatting.BOLD + title), + x + 8, + renderY + (h / 2) - (mc.textRenderer.fontHeight / 2), + -1, true); + + ctx.drawText(mc.textRenderer, extended ? "-" : "+", + x + w - mc.textRenderer.getWidth("+") - 8, // '+' y '-' tienen la misma anchura, o sea que no importa cuál use + renderY + (h / 2) - (mc.textRenderer.fontHeight / 2), + -1, true); + + // dibujar sus módulos solo si está extendido + if (extended) { + totalHeight = moduleButtons.size() * h + 3; + ctx.fill( // fondo para los botones + x, renderY + h + 1, + x + w, renderY + h + totalHeight, + Colors.frameBGColor.getRGB()); + + // dibujar los botones para cada módulo + for (ModuleButton moduleButton : moduleButtons) + moduleButton.render(ctx, mouseX, mouseY, delta); + } else totalHeight = 0; + } + + public void mouseClicked(double mouseX, double mouseY, int button) { + // registrar clics + if (isHovered(mouseX, mouseY) && ClickGUI.INSTANCE.trySelect(this)) { + if (button == 0) { // clic izquierdo para arrastrarlo + dragging = true; + dragX = (int) (mouseX - x); + dragY = (int) (mouseY - y); + } else if (button == 1) { // clic derecho para extenderlo + extended = !extended; + 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); + } + + // detectar cuándo se suelta el clic + public void mouseReleased(double mouseX, double mouseY, int button) { + ClickGUI.INSTANCE.unselect(this); + if (button == 0 && dragging) + dragging = false; + + for (ModuleButton moduleButton : moduleButtons) { + if (moduleButton.isHovered((int) mouseX, (int) mouseY)) + moduleButton.mouseReleased(mouseX, mouseY, button); + } + + if (isHovered(mouseX, mouseY)) + CameraTweaks.EVENT_BUS.post(new ModuleFrameEvent.Move()); + } + + // verificar si el puntero del ratón se encuentra encima + public boolean isHovered(double mouseX, double mouseY) { + return mouseX > x && mouseX < x + w && mouseY > renderY && mouseY < renderY + h; + } + + // actualizar la posición al arrastrar el marco + public void updatePosition(double mouseX, double mouseY) { + if (dragging) { + x = (int) (mouseX - dragX); + y = (int) (mouseY - dragY); + } + } +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/ui/frames/SettingsFrame.java b/remappedSrc/me/retucio/camtweaks/ui/frames/SettingsFrame.java new file mode 100644 index 0000000..18858e6 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/ui/frames/SettingsFrame.java @@ -0,0 +1,243 @@ +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.util.Colors; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +// marco para los botones de los ajustes de cada módulo +public class SettingsFrame { + + private final String title; + public final Module module; + final List settingButtons = new ArrayList<>(); + + public List visibleButtons = new ArrayList<>(); + + public int x, y, w, h; + public int renderY; + int dragX, dragY; + boolean dragging; + public int totalHeight = 0; + + 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; + this.y = y; + this.w = w; + this.h = h; + + // añadir el respectivo tipo de botón de cada ajuste a la lista de botones + int offset = h; + for (AbstractSetting setting : module.getSettings()) { + if (!setting.isVisible()) continue; + switch (setting) { + case BooleanSetting b -> { + addButton(new ToggleButton(b, this, offset)); + offset += 18; + } case NumberSetting n -> { + addButton(new SliderButton(n, this, offset)); + offset += 18; + } case EnumSetting e -> { + addButton(new CycleButton<>(e, this, offset)); + offset += 18; + } case KeySetting k -> { + addButton(new BindButton(k, this, offset)); + offset += 18; + } case StringSetting s -> { + addButton(new TextButton(s, this, offset)); + offset += 18; + } case ListSetting l -> { + addButton(new ListButton<>(l, this, offset)); + offset += 18; + } default -> {} + } + } + title = "ajustes de " + module.getName(); + + visibleButtons = settingButtons.stream() + .filter(sb -> sb.getSetting().isVisible()) + .toList(); + } + + public void addButton(SettingButton button) { + settingButtons.add(button); + updateWidth(); // actualizar anchura del frame tras cada iteración + } + + public void render(DrawContext ctx, int mouseX, int mouseY, float delta) { + updateWidth(); + + // cabezal + int centerX = x + w / 2; + int centerY = renderY + h / 2; + int titleX = x + 8; + int titleY = centerY - mc.textRenderer.fontHeight / 2; + + int headerColor = module.isEnabled() + ? Colors.enabledToggleButtonColor.getRGB() + : Colors.disabledToggleButtonColor.getRGB(); + + int closeButtonColor = isCloseButtonHovered(mouseX, mouseY) + ? Color.RED.getRGB() + : -1; + + if (!module.shouldSaveSettings()) headerColor = (int) module.getSettings().stream().filter(s -> ((BooleanSetting) s).isEnabled()).count() > 0 + ? Colors.enabledToggleButtonColor.getRGB() + : Colors.disabledToggleButtonColor.getRGB(); + + ctx.fill(x, renderY, x + w, renderY + h, headerColor); + ctx.drawText(mc.textRenderer, title, titleX, titleY, -1, true); + ctx.drawText(mc.textRenderer, "×", x + w - mc.textRenderer.getWidth("×") - 8, titleY, closeButtonColor, true); + + // descripción + visibleButtons = settingButtons.stream() + .filter(sb -> sb.getSetting().isVisible() && sb.getSetting().isSearchMatch()) + .toList(); + + List descLines = wrapDescription(module.getDescription(), w - 8); + int lineSpacing = 2; + + int descHeight = descLines.size() * mc.textRenderer.fontHeight + (descLines.size() - 1) * lineSpacing; + int descBoxTop = renderY + h + 5; + int descBoxBottom = descBoxTop + descHeight + 8; + + totalHeight = descHeight + 8 + h * visibleButtons.size() + 4; + + ctx.fill(x, descBoxTop - 4, x + w, descBoxTop + totalHeight, Colors.frameBGColor.getRGB()); + ctx.fill(x + 4, descBoxTop, x + w - 4, descBoxBottom, Colors.buttonColor.getRGB()); + + int firstLineY = descBoxTop + ((descBoxBottom - descBoxTop) - descHeight) / 2; + for (int i = 0; i < descLines.size(); i++) { + String line = descLines.get(i); + int lineX = centerX - mc.textRenderer.getWidth(line) / 2; + int lineY = firstLineY + i * (mc.textRenderer.fontHeight + lineSpacing); + ctx.drawText(mc.textRenderer, line, lineX, lineY, -1, true); + } + + int startButtonY = firstLineY - descBoxTop + descBoxBottom; + for (SettingButton sb : visibleButtons) { + sb.setX(x + 4); + sb.setY(startButtonY); + sb.setW(w - 8); + sb.setH(h - h / 4); + sb.render(ctx, mouseX, mouseY, delta); + startButtonY += h; + } + } + + public void drawTooltips(DrawContext ctx, double mouseX, double mouseY) { + for (SettingButton sb : visibleButtons) + sb.drawTooltip(ctx, mouseX, mouseY); + } + + + public void mouseClicked(double mouseX, double mouseY, int button) { + if (isHovered(mouseX, mouseY) && ClickGUI.INSTANCE.trySelect(this)) { + if (isCloseButtonHovered(mouseX, mouseY)) { + ClickGUI.INSTANCE.closeSettingsFrame(this.module); + return; + } if (button == 0) { + dragging = true; + dragX = (int) (mouseX - x); + dragY = (int) (mouseY - y); + } else if (button == 1) { + ClickGUI.INSTANCE.closeSettingsFrame(module); + } + } + + for (SettingButton sb : settingButtons) + if (sb.getSetting().isVisible()) + sb.mouseClicked(mouseX, mouseY, button); + } + + public void mouseRelease(double mouseX, double mouseY, int button) { + ClickGUI.INSTANCE.unselect(this); + if (button == 0) { + dragging = false; + CameraTweaks.EVENT_BUS.post(new SettingsFrameEvent.Move(this)); + } + for (SettingButton sb : settingButtons) + if (sb.getSetting().isVisible()) sb.mouseReleased(mouseX, mouseY, button); + } + + public void updatePosition(double mouseX, double mouseY) { + if (dragging) { + x = (int) (mouseX - dragX); + y = (int) (mouseY - dragY); + } + } + + public boolean isHovered(double mouseX, double mouseY) { + return mouseX > x && mouseX < x + w && + mouseY > renderY && mouseY < renderY + h; + } + + public boolean isCloseButtonHovered(double mouseX, double mouseY) { + return mouseX > x + w - mc.textRenderer.getWidth("×") - 12 && mouseX < x + w - 4 + && mouseY > renderY + 4 && mouseY < renderY + h - 4; + } + + @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.getSetting().getName(); + + switch (button) { + case SliderButton sliderButton -> text += ": " + sliderButton.df.format((sliderButton.getSetting()).getValue()); + case CycleButton cycleButton -> text += ": " + cycleButton.getSetting().getValue(); + case BindButton bindButton -> text += ": " + bindButton.getSetting().getKeyName(); + case TextButton textButton -> text += ": " + textButton.getSetting().getValue(); + default -> {} + } + + int textWidth = mc.textRenderer.getWidth(text); + maxWidth = Math.max(maxWidth, textWidth); + } + this.w = maxWidth + 30; + } + + private List wrapDescription(String text, int maxWidth) { + List lines = new ArrayList<>(); + if (mc.textRenderer == null) return lines; + + String[] words = text.split(" "); + StringBuilder line = new StringBuilder(); + + for (String word : words) { + String testLine = line.isEmpty() ? word : line + " " + word; + if (mc.textRenderer.getWidth(testLine) > maxWidth - 8) { // padding of 4 each side + if (!line.isEmpty()) lines.add(line.toString()); + line = new StringBuilder(word); + } else { + line = new StringBuilder(testLine); + } + } + if (!line.isEmpty()) lines.add(line.toString()); + return lines; + } + + public List getButtons() { + return settingButtons; + } + + public void updateRenderY(int scrollOffset) { + renderY = y - scrollOffset; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/ui/widgets/ScrollBarWidget.java b/remappedSrc/me/retucio/camtweaks/ui/widgets/ScrollBarWidget.java new file mode 100644 index 0000000..af22c8a --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/ui/widgets/ScrollBarWidget.java @@ -0,0 +1,115 @@ +package me.retucio.camtweaks.ui.widgets; + +import me.retucio.camtweaks.ui.ClickGUI; +import me.retucio.camtweaks.ui.frames.ClientSettingsFrame; +import me.retucio.camtweaks.util.Colors; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; + +import java.awt.*; + +public class ScrollBarWidget { + + private boolean dragging; + private int dragY, scrollStart; + private int scrollOffset = 0; + + private int contentHeight, windowHeight; + + private final MinecraftClient mc = MinecraftClient.getInstance(); + + public ScrollBarWidget() {} + + public void render(DrawContext ctx, double mouseX, double mouseY) { + if (contentHeight <= windowHeight || !ClientSettingsFrame.guiSettings.scrollBar.isEnabled()) return; + + int trackX1 = mc.getWindow().getScaledWidth() - 10; + int trackX2 = trackX1 + 10; + + ctx.fill(trackX1, 0, trackX2, windowHeight, Colors.buttonColor.getRGB()); + + int thumbHeight = getThumbHeight(); + int thumbY = getThumbY(); + + Color thumbColor = isThumbHovered(mouseX, mouseY) + ? Colors.mainColor.brighter() + : Colors.mainColor; + + if (dragging) thumbColor = Colors.mainColor.darker(); + + ctx.fill(trackX1 + 1, thumbY + 1, trackX2 - 1, thumbY + thumbHeight - 1, thumbColor.getRGB()); + } + + public void mouseClicked(double mouseX, double mouseY, int button) { + if (button != 0 || !ClientSettingsFrame.guiSettings.scrollBar.isEnabled()) return; + if (isThumbHovered(mouseX, mouseY) && ClickGUI.INSTANCE.trySelect(this)) { + dragging = true; + dragY = (int) mouseY; + scrollStart = scrollOffset; + } + } + + public void mouseReleased(double mouseX, double mouseY, int button) { + ClickGUI.INSTANCE.unselect(this); + dragging = false; + } + + public void mouseDragged(double mouseY) { + if (!dragging || !ClientSettingsFrame.guiSettings.scrollBar.isEnabled()) return; + + int thumbHeight = getThumbHeight(); + int trackHeight = windowHeight - thumbHeight; + + float ratio = (float) (contentHeight - windowHeight) / trackHeight; + int deltaY = (int) mouseY - dragY; + scrollOffset = scrollStart + (int) (deltaY * ratio); + clampOffset(); + } + + public void onMouseScroll(double amount) { + if (contentHeight <= windowHeight) return; + scrollOffset -= (int) amount * 20; + clampOffset(); + } + + private boolean isThumbHovered(double mouseX, double mouseY) { + if (!ClickGUI.INSTANCE.canSelect(this)) return false; + int trackX1 = mc.getWindow().getScaledWidth() - 10; + int trackX2 = trackX1 + 10; + int thumbY = getThumbY(); + int thumbHeight = getThumbHeight(); + return mouseX >= trackX1 && mouseX <= trackX2 && mouseY >= thumbY && mouseY <= thumbY + thumbHeight; + } + + private void clampOffset() { + if (contentHeight <= windowHeight) + scrollOffset = 0; + else + scrollOffset = Math.max(0, Math.min(contentHeight - windowHeight, scrollOffset)); + } + + private int getThumbY() { + int thumbHeight = getThumbHeight(); + float scrollProgress = (float) scrollOffset / (contentHeight - windowHeight); + return (int) (scrollProgress * (windowHeight - thumbHeight)); + } + + private int getThumbHeight() { + float visibleRatio = (float) windowHeight / contentHeight; + return Math.max(20, (int) (windowHeight * visibleRatio)); + } + + public int getScrollOffset() { + return scrollOffset; + } + + public void setContentHeight(int h) { + this.contentHeight = h; + clampOffset(); + } + + public void setWindowHeight(int h) { + this.windowHeight = h; + clampOffset(); + } +} diff --git a/remappedSrc/me/retucio/camtweaks/ui/widgets/SearchBarWidget.java b/remappedSrc/me/retucio/camtweaks/ui/widgets/SearchBarWidget.java new file mode 100644 index 0000000..7d282da --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/ui/widgets/SearchBarWidget.java @@ -0,0 +1,156 @@ +package me.retucio.camtweaks.ui.widgets; + +import me.retucio.camtweaks.ui.ClickGUI; +import me.retucio.camtweaks.ui.frames.ClientSettingsFrame; +import me.retucio.camtweaks.util.ChatUtil; +import me.retucio.camtweaks.util.Colors; +import me.retucio.camtweaks.util.KeyUtil; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import org.lwjgl.glfw.GLFW; + +import java.awt.Color; + +public class SearchBarWidget { + + private boolean dragging; + private int dragX, dragY; + + private int x, y; + private final int w, h; + private int renderY; + + private boolean focused; + private final StringBuilder buffer = new StringBuilder(); + + private final MinecraftClient mc = MinecraftClient.getInstance(); + + public SearchBarWidget(int x, int y, int w, int h) { + this.x = x; + this.y = y; + this.w = w; + this.h = h; + } + + public void render(DrawContext ctx, double mouseX, double mouseY, float delta) { + if (!ClientSettingsFrame.guiSettings.searchBar.isEnabled()) return; + + Color textFieldColor = isTextFieldHovered(mouseX, mouseY) + ? Colors.buttonColor.brighter() + : Colors.buttonColor; + + if (focused) textFieldColor = Colors.buttonColor.darker(); + + // bordes de la barra, para no obstruir la transparencia del campo de texto + ctx.fill(x, renderY, x + 20, renderY + h, Colors.mainColor.getRGB()); + ctx.fill(x, renderY, x + w, renderY + 2, Colors.mainColor.getRGB()); + ctx.fill(x, renderY + h, x + w, renderY + h - 2, Colors.mainColor.getRGB()); + ctx.fill(x + w - 20, renderY, x + w, renderY + h, Colors.mainColor.getRGB()); + + ctx.fill(x + 20, renderY + 2, x + w - 20, renderY + h - 2, textFieldColor.getRGB()); + + // dibujar líneas en la parte agarrable, para indicárselo al usuario + for (int i = 0; i < 4; i++) + ctx.drawHorizontalLine(x + 4, x + 16, renderY + 3 * i + 5, Color.LIGHT_GRAY.getRGB()); + + // texto + Text label = Text.literal(focused ? buffer + "_" : (buffer.isEmpty() ? Formatting.ITALIC + "buscar..." : buffer.toString())); + ctx.drawText(mc.textRenderer, label, + x + 24, renderY + h / 2 - mc.textRenderer.fontHeight / 2, + (buffer.isEmpty() && !focused) ? Color.LIGHT_GRAY.getRGB() : -1, true); + + // botón para borrar búsqueda actual + ctx.drawText(mc.textRenderer, "×", x + w - mc.textRenderer.getWidth("×") - 6, renderY + (h / 2) - mc.textRenderer.fontHeight / 2, + isClearButtonHovered(mouseX, mouseY) ? Color.RED.getRGB() : -1, true); + } + + public void mouseClicked(double mouseX, double mouseY, int button) { + if (button != 0 || !ClientSettingsFrame.guiSettings.searchBar.isEnabled()) return; + if (isHandleHovered(mouseX, mouseY) && ClickGUI.INSTANCE.trySelect(this)) { + dragging = true; + dragX = (int) mouseX - x; + dragY = (int) mouseY - y; + } else if (isClearButtonHovered(mouseX, mouseY)) { + buffer.setLength(0); + } + focused = isTextFieldHovered(mouseX, mouseY) && ClickGUI.INSTANCE.trySelect(this); + } + + public void mouseReleased(double mouseX, double mouseY, int button) { + if (!ClientSettingsFrame.guiSettings.searchBar.isEnabled()) return; + ClickGUI.INSTANCE.unselect(this); + if (button == 0 && dragging) dragging = false; + } + + public void onKey(int key, int action) { + if (!ClientSettingsFrame.guiSettings.searchBar.isEnabled()) return; + if (!focused || action == GLFW.GLFW_RELEASE) return; + + switch (key) { + case GLFW.GLFW_KEY_ENTER -> focused = false; + case GLFW.GLFW_KEY_ESCAPE -> { + buffer.setLength(0); + focused = false; + } + case GLFW.GLFW_KEY_BACKSPACE -> onBackspace(); + 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(KeyUtil.shiftKey(c).charAt(0)); + else + charTyped(c.toLowerCase().charAt(0)); + } + } + } + } + + public void onBackspace() { + if (!buffer.isEmpty()) buffer.deleteCharAt(buffer.length() - 1); + } + + public void charTyped(char c) { + if (!focused) return; + buffer.append(c); + if (mc.textRenderer.getWidth(buffer.toString()) > w - 30) onBackspace(); + } + + public String getSearchInput() { + return buffer.toString(); + } + + public boolean isHandleHovered(double mouseX, double mouseY) { + return ClickGUI.INSTANCE.canSelect(this) + && mouseX > x && mouseX < x + 18 + && mouseY > renderY && mouseY < renderY + h; + } + + public boolean isTextFieldHovered(double mouseX, double mouseY) { + return ClickGUI.INSTANCE.canSelect(this) + && mouseX > x + 20 && mouseX < x + w - 20 + && mouseY > renderY + 2 && mouseY < renderY + h - 2; + } + + public boolean isClearButtonHovered(double mouseX, double mouseY) { + return ClickGUI.INSTANCE.canSelect(this) + && mouseX > x + w - 15 && mouseX < x + w - 3 + && mouseY > renderY + 3 && mouseY < renderY + h - 5; + } + + public boolean isFocused() { + return focused && ClientSettingsFrame.guiSettings.searchBar.isEnabled(); + } + + public void updateRenderY(int scrollOffset) { + renderY = y - scrollOffset; + } + + public void updatePosition(double mouseX, double mouseY) { + if (dragging) { + x = (int) (mouseX - dragX); + y = (int) (mouseY - dragY); + } + } +} diff --git a/remappedSrc/me/retucio/camtweaks/util/ChatUtil.java b/remappedSrc/me/retucio/camtweaks/util/ChatUtil.java new file mode 100644 index 0000000..3f8d29b --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/util/ChatUtil.java @@ -0,0 +1,93 @@ +package me.retucio.camtweaks.util; + +import me.retucio.camtweaks.CameraTweaks; +import me.retucio.camtweaks.event.SubscribeEvent; +import me.retucio.camtweaks.event.events.camtweaks.LoadModuleManagerEvent; +import me.retucio.camtweaks.ui.frames.ClientSettingsFrame; +import net.minecraft.client.MinecraftClient; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// cosas útiles relacionadas al chat +public class ChatUtil { + + private static final MinecraftClient mc = MinecraftClient.getInstance(); + private static String prefix = getDefaultPrefix(); + + @SubscribeEvent + public static void onLoadModuleManager(LoadModuleManagerEvent event) { + prefix = Colors.getFormatting(Colors.mainColor) + "[" + ClientSettingsFrame.guiSettings.chatName.getValue() + "] "; + } + + + public static void addMessage(String text) { + addMessage(Text.of(text)); + } + + public static void addMessage(Text text) { + if (mc.inGameHud == null || !CameraTweaks.INSTANCE.settingsApplied) return; + mc.inGameHud.getChatHud().addMessage(text); + } + + public static void addMessageWithPrefix(String text) { + addMessageWithPrefix(Text.of(text)); + } + + public static void addMessageWithPrefix(Text text) { + addMessage(Text.literal(getPrefix() + Formatting.RESET).append(text)); + } + + public static void info(String text) { + addMessage(Text.literal(getPrefix() + Formatting.RESET + text)); + } + + public static void info(Text text) { + addMessage(Text.literal(getPrefix() + Formatting.RESET).append(text)); + } + + public static void warn(String text) { + addMessage(Text.literal(getPrefix() + Formatting.YELLOW + text)); + } + + public static void warn(Text text) { + addMessage(Text.literal(getPrefix() + Formatting.YELLOW).append(text)); + } + + public static void error(String text) { + addMessage(Text.literal(getPrefix() + Formatting.RED + text)); + } + + public static void error(Text text) { + addMessage(Text.literal(getPrefix() + Formatting.RED).append(text)); + } + + public static void sendServerMessage(String text) { + sendServerMessage(Text.of(text)); + } + + public static void sendServerMessage(Text text) { + if (mc.player == null) return; + mc.player.sendMessage(text, false); + } + + public static String getPrefix() { + return prefix; + } + + public static String getJustPrefix() { + return ClientSettingsFrame.guiSettings.chatName.getValue(); + } + + public static String getPrefixNoFormatting() { + return getPrefix().split(Colors.getFormatting(Colors.mainColor).toString())[1]; + } + + + public static void updatePrefix(String newPrefix) { + prefix = Colors.getFormatting(Colors.mainColor) + "[" + newPrefix + "] "; + } + + public static String getDefaultPrefix() { + return Colors.getFormatting(Colors.mainColor) + "[smegma] "; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/util/Colors.java b/remappedSrc/me/retucio/camtweaks/util/Colors.java new file mode 100644 index 0000000..1146b6a --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/util/Colors.java @@ -0,0 +1,76 @@ +package me.retucio.camtweaks.util; + +import net.minecraft.util.Formatting; + +import java.awt.*; + +import static me.retucio.camtweaks.ui.frames.ClientSettingsFrame.guiSettings; + + +// clase para los colores +// si se ve especificado como color en algún lado "-1", significa blanco +public class Colors { + + public static int red = guiSettings.red.getIntValue(); + public static int green = guiSettings.green.getIntValue(); + public static int blue = guiSettings.blue.getIntValue(); + public static int alpha = guiSettings.alpha.getIntValue(); + + public static Color mainColor; + public static Color frameBGColor = new Color(40, 40, 40, 75); + public static Color buttonColor = new Color(75, 75, 75, 100); + public static Color enabledToggleButtonColor; + public static Color disabledToggleButtonColor; + + static { + updateAllColors(new Color(red, green, blue, alpha)); + } + + public static void updateAllColors(Color color) { + mainColor = color; + enabledToggleButtonColor = mixWithMainColor(new Color(10, 150, 10), 0.8f); + disabledToggleButtonColor = mixWithMainColor(new Color(150, 10, 10), 0.8f); + + ChatUtil.updatePrefix(ChatUtil.getJustPrefix()); + } + + public static Color mixWithMainColor(Color color, float ratio) { + return mix(mainColor, color, ratio); + } + + public static Color mix(Color c1, Color c2, float ratio) { + float r = c1.getRed() * (1 - ratio) + c2.getRed() * ratio; + float g = c1.getGreen() * (1 - ratio) + c2.getGreen() * ratio; + float b = c1.getBlue() * (1 - ratio) + c2.getBlue() * ratio; + return new Color((int) r, (int) g, (int) b, alpha); + } + + public static Formatting getFormatting(Color color) { + return nearest(color); + } + + public static Formatting nearest(Color input) { + Formatting nearest = null; + double minDistance = Double.MAX_VALUE; + + for (Formatting formatting : Formatting.values()) { + if (formatting.getColorValue() == null) continue; // saltarse los modificadores + + Color candidate = new Color(formatting.getColorValue()); + double dist = colorDistance(input, candidate); + + if (dist < minDistance) { + minDistance = dist; + nearest = formatting; + } + } + return nearest; + } + + private static double colorDistance(Color c1, Color c2) { + int rDiff = c1.getRed() - c2.getRed(); + int gDiff = c1.getGreen() - c2.getGreen(); + int bDiff = c1.getBlue() - c2.getBlue(); + return rDiff * rDiff + gDiff * gDiff + bDiff * bDiff; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/util/KeyUtil.java b/remappedSrc/me/retucio/camtweaks/util/KeyUtil.java new file mode 100644 index 0000000..1967999 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/util/KeyUtil.java @@ -0,0 +1,82 @@ +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 +public class KeyUtil { + + public static boolean isKeyDown(int key) { + return GLFW.glfwGetKey( + CameraTweaks.mc.getWindow().getHandle(), + 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"; + + 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; + } + }; + } + + // 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/remappedSrc/me/retucio/camtweaks/util/Lists.java b/remappedSrc/me/retucio/camtweaks/util/Lists.java new file mode 100644 index 0000000..767a92a --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/util/Lists.java @@ -0,0 +1,60 @@ +package me.retucio.camtweaks.util; + +import net.minecraft.block.Block; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.resource.language.I18n; +import net.minecraft.entity.EntityType; +import net.minecraft.particle.ParticleType; +import net.minecraft.particle.ParticleTypes; +import net.minecraft.registry.Registries; +import net.minecraft.text.Text; + +import java.util.*; + +import static me.retucio.camtweaks.CameraTweaks.mc; + +public class Lists { + + public static final List> entityList = Registries.ENTITY_TYPE.stream().toList(); + public static Map, String> entityNames; + + + public static final List> particleList = Registries.PARTICLE_TYPE.stream().toList(); + public static Map, String> particleNames; + + public static final List blockList = Registries.BLOCK.stream().toList(); + + public static void init() { + // no consigo traducir el texto. a tomar por culo, se queda en inglés, si no entiendes pues a estudiar + entityNames = getMapOfLists(entityList, + entityList.stream().map(entity -> I18n.translate(entity.getTranslationKey())).toList()); + + // no hay traducciones para nombres de partículas, y paso de hacerlas yo + particleNames = getMapOfLists(particleList, + particleList.stream().map(particle -> Registries.PARTICLE_TYPE.getId(particle).toShortTranslationKey()).toList()); + } + + public static Map allTrue(List options) { + Map map = new HashMap<>(); + for (T option : options) map.put(option, true); + return map; + } + + public static Map allFalse(List options) { + Map map = new HashMap<>(); + for (T option : options) map.put(option, false); + return map; + } + + public static Map getMapOfLists(List options, List names) { + Map result = new HashMap<>(); + + // no exceder los límites de ninguna de las dos listas + int size = Math.min(options.size(), names.size()); + + for (int i = 0; i < size; i++) + result.put(options.get(i), names.get(i)); + + return result; + } +} diff --git a/remappedSrc/me/retucio/camtweaks/util/MiscUtil.java b/remappedSrc/me/retucio/camtweaks/util/MiscUtil.java new file mode 100644 index 0000000..faf5740 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/util/interfaces/IChatHud.java b/remappedSrc/me/retucio/camtweaks/util/interfaces/IChatHud.java new file mode 100644 index 0000000..01017bb --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/util/interfaces/IChatHud.java @@ -0,0 +1,13 @@ +package me.retucio.camtweaks.util.interfaces; + +import net.minecraft.client.gui.hud.ChatHudLine; +import net.minecraft.text.Text; + +import java.util.List; + +public interface IChatHud { + + void smegma$add(Text message, int id); + + List smegma$getVisibleMessages(); +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/util/interfaces/IChatHudLine.java b/remappedSrc/me/retucio/camtweaks/util/interfaces/IChatHudLine.java new file mode 100644 index 0000000..fa5724a --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/util/interfaces/IChatHudLine.java @@ -0,0 +1,14 @@ +package me.retucio.camtweaks.util.interfaces; + +import com.mojang.authlib.GameProfile; + +public interface IChatHudLine { + + String smegma$getText(); + + int smegma$getId(); + void smegma$setId(int id); + + GameProfile smegma$getSender(); + void smegma$setSender(GameProfile profile); +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/util/interfaces/IChatHudLineVisible.java b/remappedSrc/me/retucio/camtweaks/util/interfaces/IChatHudLineVisible.java new file mode 100644 index 0000000..3013a07 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/util/interfaces/IChatHudLineVisible.java @@ -0,0 +1,7 @@ +package me.retucio.camtweaks.util.interfaces; + +public interface IChatHudLineVisible extends IChatHudLine { + + boolean smegma$isStartOfEntry(); + void smegma$setStartOfEntry(boolean start); +} \ No newline at end of file diff --git a/remappedSrc/me/retucio/camtweaks/util/interfaces/IMessageHandler.java b/remappedSrc/me/retucio/camtweaks/util/interfaces/IMessageHandler.java new file mode 100644 index 0000000..531eaa6 --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/util/interfaces/IMessageHandler.java @@ -0,0 +1,8 @@ +package me.retucio.camtweaks.util.interfaces; + +import com.mojang.authlib.GameProfile; + +public interface IMessageHandler { + + GameProfile smegma$getSender(); +} diff --git a/remappedSrc/me/retucio/camtweaks/util/interfaces/IVec3d.java b/remappedSrc/me/retucio/camtweaks/util/interfaces/IVec3d.java new file mode 100644 index 0000000..d3fd230 --- /dev/null +++ b/remappedSrc/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/remappedSrc/me/retucio/camtweaks/util/interfaces/TextVisitor.java b/remappedSrc/me/retucio/camtweaks/util/interfaces/TextVisitor.java new file mode 100644 index 0000000..8d5a50e --- /dev/null +++ b/remappedSrc/me/retucio/camtweaks/util/interfaces/TextVisitor.java @@ -0,0 +1,46 @@ +/* code by meteorclient dev team */ + +package me.retucio.camtweaks.util.interfaces; + +import net.minecraft.text.PlainTextContent; +import net.minecraft.text.StringVisitable; +import net.minecraft.text.Style; +import net.minecraft.text.Text; + +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); + + static Optional visit(Text text, TextVisitor visitor, Style baseStyle) { + Queue queue = collectSiblings(text); + return text.visit((style, string) -> visitor.accept(queue.remove(), style, string), baseStyle); + } + + /** + * Collapses the tree of {@link Text} siblings into a one dimensional FIFO {@link Queue}. To match the behaviours of + * the {@link Text#visit(StringVisitable.Visitor)} and {@link Text#visit(StringVisitable.StyledVisitor, Style)} + * methods, texts with empty contents (created from {@link Text#empty()}) are ignored but their siblings are still + * processed. + * @param text the text + * @return the text and its siblings in the order they appear when rendered. + */ + static ArrayDeque collectSiblings(Text text) { + ArrayDeque queue = new ArrayDeque<>(); + collectSiblings(text, queue); + return queue; + } + + private static void collectSiblings(Text text, Queue queue) { + if (!(text.getContent() instanceof PlainTextContent ptc) || !ptc.string().isEmpty()) queue.add(text); + for (Text sibling : text.getSiblings()) { + collectSiblings(sibling, queue); + } + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/CameraTweaks.java b/src/main/java/me/retucio/camtweaks/CameraTweaks.java index ded60d7..3c785d7 100644 --- a/src/main/java/me/retucio/camtweaks/CameraTweaks.java +++ b/src/main/java/me/retucio/camtweaks/CameraTweaks.java @@ -99,6 +99,7 @@ public class CameraTweaks implements ClientModInitializer { // se ejecuta cada vez que se presiona una tecla public void onKeyPress(int key, int action) { + if (key == GLFW.GLFW_KEY_F3) return; // prevenir activación de módulos al usar combinaciones de F3 ModuleManager.INSTANCE.getEnabledModules().forEach(module -> module.onKey(key, action)); boolean anyFocused = isAnySettingButtonFocused() || ClickGUI.INSTANCE.getSearchBar().isFocused(); diff --git a/src/main/java/me/retucio/camtweaks/mixin/ClientPlayerEntityMixin.java b/src/main/java/me/retucio/camtweaks/mixin/ClientPlayerEntityMixin.java new file mode 100644 index 0000000..56b4040 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/ClientPlayerEntityMixin.java @@ -0,0 +1,19 @@ +package me.retucio.camtweaks.mixin; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import me.retucio.camtweaks.module.ModuleManager; +import me.retucio.camtweaks.module.modules.PortalGUI; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.network.ClientPlayerEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ClientPlayerEntity.class) +public abstract class ClientPlayerEntityMixin { + + @ModifyExpressionValue(method = "tickNausea", at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;currentScreen:Lnet/minecraft/client/gui/screen/Screen;")) + private Screen allowScreensInPortals(Screen original) { + if (ModuleManager.INSTANCE.getModuleByClass(PortalGUI.class).isEnabled()) return null; + return original; + } +} diff --git a/src/main/java/me/retucio/camtweaks/mixin/DamageParticleMixin.java b/src/main/java/me/retucio/camtweaks/mixin/DamageParticleMixin.java index 056a360..fc0e83b 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/DamageParticleMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/DamageParticleMixin.java @@ -3,6 +3,7 @@ package me.retucio.camtweaks.mixin; import com.llamalad7.mixinextras.injector.ModifyReturnValue; import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.modules.CritsPlus; +import net.minecraft.client.particle.BillboardParticle; import net.minecraft.client.particle.DamageParticle; import net.minecraft.client.particle.ParticleTextureSheet; import org.spongepowered.asm.mixin.Mixin; @@ -14,9 +15,9 @@ import java.awt.*; @Mixin(DamageParticle.class) public abstract class DamageParticleMixin { - @ModifyReturnValue(method = "getType", at = @At("RETURN")) - private ParticleTextureSheet makeCritsTranslucent(ParticleTextureSheet original) { - if (ModuleManager.INSTANCE.getModuleByClass(CritsPlus.class).isEnabled()) return ParticleTextureSheet.PARTICLE_SHEET_TRANSLUCENT; + @ModifyReturnValue(method = "getRenderType", at = @At("RETURN")) + private BillboardParticle.RenderType makeCritsTranslucent(BillboardParticle.RenderType original) { + if (ModuleManager.INSTANCE.getModuleByClass(CritsPlus.class).isEnabled()) return BillboardParticle.RenderType.PARTICLE_ATLAS_TRANSLUCENT; return original; } } @@ -25,7 +26,7 @@ public abstract class DamageParticleMixin { @Mixin(DamageParticle.Factory.class) abstract class DamageParticleFactoryMixin { - @ModifyVariable(method = "createParticle(Lnet/minecraft/particle/SimpleParticleType;Lnet/minecraft/client/world/ClientWorld;DDDDDD)Lnet/minecraft/client/particle/Particle;", at = @At(value = "STORE")) + @ModifyVariable(method = "createParticle(Lnet/minecraft/particle/SimpleParticleType;Lnet/minecraft/client/world/ClientWorld;DDDDDDLnet/minecraft/util/math/random/Random;)Lnet/minecraft/client/particle/Particle;", at = @At(value = "STORE")) private DamageParticle modifyCritColor(DamageParticle original) { CritsPlus crits = ModuleManager.INSTANCE.getModuleByClass(CritsPlus.class); if (!crits.isEnabled()) return original; diff --git a/src/main/java/me/retucio/camtweaks/mixin/EntityMixin.java b/src/main/java/me/retucio/camtweaks/mixin/EntityMixin.java index 9b8aea9..963930f 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/EntityMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/EntityMixin.java @@ -6,7 +6,6 @@ import me.retucio.camtweaks.module.modules.AntiInvis; import me.retucio.camtweaks.module.modules.Freecam; import me.retucio.camtweaks.module.modules.Freelook; import me.retucio.camtweaks.module.modules.Nametags; -import me.retucio.camtweaks.util.ChatUtil; import net.minecraft.entity.*; import net.minecraft.entity.passive.TameableEntity; import net.minecraft.entity.player.PlayerEntity; @@ -14,7 +13,6 @@ import net.minecraft.entity.projectile.PersistentProjectileEntity; 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; @@ -80,6 +78,7 @@ public abstract class EntityMixin { private boolean renderEntityNametags(boolean original) { if (!nametags.isEnabled()) return original; if ((Object) this instanceof PersistentProjectileEntity p && p.isOnGround()) return false; + if ((Object) this instanceof ItemEntity i && !nametags.items.isEnabled(i.getStack().getItem())) return false; return nametags.entities.isEnabled((this.getType())); } diff --git a/src/main/java/me/retucio/camtweaks/mixin/GameRendererMixin.java b/src/main/java/me/retucio/camtweaks/mixin/GameRendererMixin.java index 461aa37..4344160 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/GameRendererMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/GameRendererMixin.java @@ -10,6 +10,7 @@ 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.block.BlockRenderManager; import net.minecraft.client.render.item.HeldItemRenderer; import net.minecraft.entity.Entity; import org.joml.Matrix4f; @@ -47,7 +48,7 @@ public abstract class GameRendererMixin { public abstract void updateCrosshairTarget(float tickDelta); @Inject(method = "", at = @At("TAIL")) - private void getModules(MinecraftClient client, HeldItemRenderer firstPersonHeldItemRenderer, BufferBuilderStorage buffers, CallbackInfo ci) { + private void getModules(MinecraftClient client, HeldItemRenderer firstPersonHeldItemRenderer, BufferBuilderStorage buffers, BlockRenderManager blockRenderManager, CallbackInfo ci) { zoom = ModuleManager.INSTANCE.getModuleByClass(Zoom.class);; freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); @@ -78,7 +79,7 @@ public abstract class GameRendererMixin { float lastYaw = cameraEntity.lastYaw; float lastPitch = cameraEntity.lastPitch; - ((IVec3d) cameraEntity.getPos()).smegma$set(pos.x, pos.y - cameraEntity.getEyeHeight(cameraEntity.getPose()), pos.z); + ((IVec3d) cameraEntity.getEntityPos()).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; @@ -91,7 +92,7 @@ public abstract class GameRendererMixin { updateCrosshairTarget(tickDelta); freecamDone = false; - ((IVec3d) cameraEntity.getPos()).smegma$set(x, y, z); + ((IVec3d) cameraEntity.getEntityPos()).smegma$set(x, y, z); cameraEntity.lastX = lastX; cameraEntity.lastY = lastY; cameraEntity.lastZ = lastZ; diff --git a/src/main/java/me/retucio/camtweaks/mixin/HeldItemRendererMixin.java b/src/main/java/me/retucio/camtweaks/mixin/HeldItemRendererMixin.java index fa81d62..c668814 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/HeldItemRendererMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/HeldItemRendererMixin.java @@ -9,7 +9,8 @@ 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.command.OrderedRenderCommandQueue; +import net.minecraft.client.render.entity.EntityRenderManager; import net.minecraft.client.render.item.HeldItemRenderer; import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.util.math.MatrixStack; @@ -49,17 +50,17 @@ public abstract class HeldItemRendererMixin { 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) { + private void getModules(MinecraftClient client, EntityRenderManager 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) { + @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/command/OrderedRenderCommandQueue;I)V", shift = At.Shift.BEFORE)) + private void onRenderItem(AbstractClientPlayerEntity player, float tickProgress, float pitch, Hand hand, float swingProgress, ItemStack item, float equipProgress, MatrixStack matrices, OrderedRenderCommandQueue orderedRenderCommandQueue, int light, CallbackInfo ci) { 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) { + @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/command/OrderedRenderCommandQueue;IFFLnet/minecraft/util/Arm;)V")) + private void onRenderArm(AbstractClientPlayerEntity player, float tickProgress, float pitch, Hand hand, float swingProgress, ItemStack item, float equipProgress, MatrixStack matrices, OrderedRenderCommandQueue orderedRenderCommandQueue, int light, CallbackInfo ci) { EVENT_BUS.post(new RenderArmEvent(matrices, hand)); } diff --git a/src/main/java/me/retucio/camtweaks/mixin/InGameOverlayRendererMixin.java b/src/main/java/me/retucio/camtweaks/mixin/InGameOverlayRendererMixin.java index dfea32d..06b2709 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/InGameOverlayRendererMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/InGameOverlayRendererMixin.java @@ -5,6 +5,8 @@ import me.retucio.camtweaks.module.modules.NoRender; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.hud.InGameOverlayRenderer; import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.texture.Sprite; +import net.minecraft.client.texture.SpriteHolder; import net.minecraft.client.util.math.MatrixStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -19,12 +21,12 @@ public abstract class InGameOverlayRendererMixin { private static NoRender noRender; @Inject(method = "", at = @At("TAIL")) - private void getModules(MinecraftClient client, VertexConsumerProvider vertexConsumers, CallbackInfo ci) { + private void getModules(MinecraftClient client, SpriteHolder spriteHolder, VertexConsumerProvider vertexConsumers, CallbackInfo ci) { noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); } @Inject(method = "renderFireOverlay", at = @At("HEAD"), cancellable = true) - private static void noRenderFireOverlay(MatrixStack matrices, VertexConsumerProvider vertexConsumers, CallbackInfo ci) { + private static void noRenderFireOverlay(MatrixStack matrices, VertexConsumerProvider vertexConsumers, Sprite sprite, CallbackInfo ci) { if (noRender.isEnabled() && !noRender.fireOverlay.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 index 53ca637..21fc6c2 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/ItemEntityMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/ItemEntityMixin.java @@ -5,7 +5,9 @@ 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.MutableText; import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -22,7 +24,15 @@ public abstract class ItemEntityMixin { if (!nametags.isEnabled()) return original; int count = this.getStack().getCount(); - if (nametags.countItems.isEnabled() && count > 1) return original.copy().append(" x" + count); + MutableText name = this.getStack().getCustomName() != null ? this.getStack().getCustomName().copyContentOnly() : original.copyContentOnly(); + + if (!name.equals(original)) name = name.formatted(Formatting.ITALIC); + + if (nametags.countItems.isEnabled()) { + if (count > 1) return name.copy().append(" x" + count); + return name; + } + return original; } } \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/mixin/KeyboardMixin.java b/src/main/java/me/retucio/camtweaks/mixin/KeyboardMixin.java index 08ad4d4..fbbad87 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/KeyboardMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/KeyboardMixin.java @@ -3,6 +3,7 @@ package me.retucio.camtweaks.mixin; import me.retucio.camtweaks.CameraTweaks; import me.retucio.camtweaks.event.events.KeyEvent; import net.minecraft.client.Keyboard; +import net.minecraft.client.input.KeyInput; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -14,10 +15,10 @@ import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS; public abstract class KeyboardMixin { @Inject(method = "onKey", at = @At("HEAD"), cancellable = true) - private void onKeyPress(long window, int key, int scancode, int action, int modifiers, CallbackInfo ci) { - CameraTweaks.INSTANCE.onKeyPress(key, action); + private void onKeyPress(long window, int action, KeyInput input, CallbackInfo ci) { + CameraTweaks.INSTANCE.onKeyPress(input.key(), action); - KeyEvent event = EVENT_BUS.post(new KeyEvent(key, scancode, action)); + KeyEvent event = EVENT_BUS.post(new KeyEvent(input.key(), input.scancode(), action)); if (event.isCancelled()) ci.cancel(); } } diff --git a/src/main/java/me/retucio/camtweaks/mixin/MouseMixin.java b/src/main/java/me/retucio/camtweaks/mixin/MouseMixin.java index 7495d35..3176d1a 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/MouseMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/MouseMixin.java @@ -4,6 +4,7 @@ import me.retucio.camtweaks.CameraTweaks; import me.retucio.camtweaks.event.events.MouseClickEvent; import me.retucio.camtweaks.event.events.MouseScrollEvent; import net.minecraft.client.Mouse; +import net.minecraft.client.input.MouseInput; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -15,8 +16,8 @@ import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS; public abstract class MouseMixin { @Inject(method = "onMouseButton", at = @At("HEAD"), cancellable = true) - private void onMouseButton(long window, int button, int action, int mods, CallbackInfo ci) { - MouseClickEvent event = EVENT_BUS.post(new MouseClickEvent(action, button)); + private void onMouseButton(long window, MouseInput input, int action, CallbackInfo ci) { + MouseClickEvent event = EVENT_BUS.post(new MouseClickEvent(action, input.button())); if (event.isCancelled()) ci.cancel(); } diff --git a/src/main/java/me/retucio/camtweaks/mixin/SkyRendererMixin.java b/src/main/java/me/retucio/camtweaks/mixin/SkyRendererMixin.java index 8510ed3..153d515 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/SkyRendererMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/SkyRendererMixin.java @@ -24,12 +24,12 @@ public abstract class SkyRendererMixin { } @Inject(method = "renderSun", at = @At("HEAD"), cancellable = true) - private void onRenderSun(float alpha, VertexConsumerProvider vertexConsumers, MatrixStack matrices, CallbackInfo ci) { + private void onRenderSun(float alpha, 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) { + private void onRenderMoon(int phase, float alpha, MatrixStack matrixStack, CallbackInfo ci) { if (timeChanger.isEnabled() && !timeChanger.renderMoon.isEnabled()) ci.cancel(); } diff --git a/src/main/java/me/retucio/camtweaks/mixin/TextRendererDrawerMixin.java b/src/main/java/me/retucio/camtweaks/mixin/TextRendererDrawerMixin.java index 2f4b7e8..a1cdcfc 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/TextRendererDrawerMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/TextRendererDrawerMixin.java @@ -1,15 +1,22 @@ package me.retucio.camtweaks.mixin; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.modules.NoRender; +import net.minecraft.client.font.BakedGlyph; +import net.minecraft.client.font.GlyphProvider; import net.minecraft.client.font.TextRenderer; import net.minecraft.text.Style; import net.minecraft.text.TextColor; +import net.minecraft.util.math.MathHelper; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.*; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import static me.retucio.camtweaks.CameraTweaks.mc; + // falta italics pero no sé dónde se comprueba eso, no es aquí :P @Mixin(TextRenderer.Drawer.class) public abstract class TextRendererDrawerMixin { @@ -22,27 +29,22 @@ public abstract class TextRendererDrawerMixin { noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); } - @Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isBold()Z")) + @Redirect(method = "accept(ILnet/minecraft/text/Style;Lnet/minecraft/client/font/BakedGlyph;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isBold()Z")) private boolean noRenderBold(Style style) { return !(noRender.isEnabled() && !noRender.bold.isEnabled()) && style.isBold(); } - @Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isUnderlined()Z")) + @Redirect(method = "accept(ILnet/minecraft/text/Style;Lnet/minecraft/client/font/BakedGlyph;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isUnderlined()Z")) private boolean noRenderUnderlined(Style style) { return !(noRender.isEnabled() && !noRender.underlined.isEnabled()) && style.isUnderlined(); } - @Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isStrikethrough()Z")) + @Redirect(method = "accept(ILnet/minecraft/text/Style;Lnet/minecraft/client/font/BakedGlyph;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isStrikethrough()Z")) private boolean noRenderStrikethrough(Style style) { return !(noRender.isEnabled() && !noRender.strikethrough.isEnabled()) && style.isStrikethrough(); } - @Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isObfuscated()Z")) - private boolean noRenderMTS(Style style) { - return !(noRender.isEnabled() && !noRender.scrambledText.isEnabled()) && style.isObfuscated(); - } - - @ModifyArg(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/TextRenderer$Drawer;getRenderColor(Lnet/minecraft/text/TextColor;)I")) + @ModifyArg(method = "accept(ILnet/minecraft/text/Style;Lnet/minecraft/client/font/BakedGlyph;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/TextRenderer$Drawer;getRenderColor(Lnet/minecraft/text/TextColor;)I")) private TextColor noRenderColor(TextColor original) { return !noRender.color.is(NoRender.Colors.DEFAULT) ? TextColor.fromFormatting(noRender.color.getValue().toFormatting()) : original; } diff --git a/src/main/java/me/retucio/camtweaks/mixin/TextRendererMixin.java b/src/main/java/me/retucio/camtweaks/mixin/TextRendererMixin.java new file mode 100644 index 0000000..ef779bc --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/mixin/TextRendererMixin.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.NoRender; +import net.minecraft.client.font.TextRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(TextRenderer.class) +public abstract class TextRendererMixin { + + @ModifyExpressionValue(method = "getGlyph", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isObfuscated()Z")) + private boolean noRenderMTS(boolean original) { + NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); + return (!noRender.isEnabled() || noRender.scrambledText.isEnabled()) && original; + } +} diff --git a/src/main/java/me/retucio/camtweaks/mixin/WeatherRenderingMixin.java b/src/main/java/me/retucio/camtweaks/mixin/WeatherRenderingMixin.java index 47eb40f..30a5e47 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/WeatherRenderingMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/WeatherRenderingMixin.java @@ -5,6 +5,7 @@ import me.retucio.camtweaks.module.modules.NoRender; import net.minecraft.client.render.Camera; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.WeatherRendering; +import net.minecraft.client.render.state.WeatherRenderState; import net.minecraft.client.world.ClientWorld; import net.minecraft.particle.ParticlesMode; import net.minecraft.util.math.Vec3d; @@ -33,11 +34,11 @@ public abstract class WeatherRenderingMixin { if (noRender.isEnabled() && !noRender.rain.isEnabled()) ci.cancel(); } - @Inject(method = "renderPrecipitation(Lnet/minecraft/client/render/VertexConsumerProvider;Lnet/minecraft/util/math/Vec3d;IFLjava/util/List;Ljava/util/List;)V", at = @At("HEAD")) - private void noRenderRainAndSnow(VertexConsumerProvider vertexConsumers, Vec3d pos, int range, float gradient, List rainPieces, List snowPieces, CallbackInfo ci) { + @Inject(method = "renderPrecipitation", at = @At("HEAD")) + private void noRenderRainAndSnow(VertexConsumerProvider vertexConsumers, Vec3d pos, WeatherRenderState weatherRenderState, CallbackInfo ci) { if (noRender.isEnabled()) { - if (!noRender.rain.isEnabled()) rainPieces.clear(); - if (!noRender.snow.isEnabled()) snowPieces.clear(); + if (!noRender.rain.isEnabled()) weatherRenderState.rainPieces.clear(); + if (!noRender.snow.isEnabled()) weatherRenderState.snowPieces.clear(); } } } diff --git a/src/main/java/me/retucio/camtweaks/mixin/WorldRendererMixin.java b/src/main/java/me/retucio/camtweaks/mixin/WorldRendererMixin.java index cc28b47..9a107ba 100644 --- a/src/main/java/me/retucio/camtweaks/mixin/WorldRendererMixin.java +++ b/src/main/java/me/retucio/camtweaks/mixin/WorldRendererMixin.java @@ -3,21 +3,43 @@ package me.retucio.camtweaks.mixin; import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.modules.BlockOutline; import me.retucio.camtweaks.module.modules.Freecam; +import me.retucio.camtweaks.module.modules.NoRender; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.Frustum; +import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.WorldRenderer; +import net.minecraft.client.render.state.WorldRenderState; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.ColorHelper; 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.ModifyArg; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.awt.*; @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; + @ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;method_74752(Lnet/minecraft/client/render/Camera;Lnet/minecraft/client/render/Frustum;Z)V"), index = 2) + private boolean renderSetupTerrainModifyArg(boolean spectator) { + return ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled() || spectator; + } + + @Inject(method = "renderTargetBlockOutline", at = @At("HEAD"), cancellable = true) + private void noRenderBlockOutlinesFreecam(VertexConsumerProvider.Immediate immediate, MatrixStack matrices, boolean renderBlockOutline, WorldRenderState renderStates, CallbackInfo ci) { + Freecam freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); + if (freecam.isEnabled() && !freecam.blockOutlines.isEnabled()) ci.cancel(); + } + + @Inject(method = "hasBlindnessOrDarkness(Lnet/minecraft/client/render/Camera;)Z", at = @At("HEAD"), cancellable = true) + private void hasBlindnessOrDarkness(Camera camera, CallbackInfoReturnable cir) { + NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); + if (!noRender.isEnabled()) return; + if (!noRender.blindnessEffect.isEnabled() || !noRender.darknessEffect.isEnabled()) cir.setReturnValue(null); } @Redirect(method = "renderTargetBlockOutline", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/ColorHelper;withAlpha(II)I")) diff --git a/src/main/java/me/retucio/camtweaks/module/ModuleManager.java b/src/main/java/me/retucio/camtweaks/module/ModuleManager.java index 5f86a0f..a4bfc94 100644 --- a/src/main/java/me/retucio/camtweaks/module/ModuleManager.java +++ b/src/main/java/me/retucio/camtweaks/module/ModuleManager.java @@ -40,8 +40,10 @@ public class ModuleManager { modules.add(new Nametags()); modules.add(new NoRender()); modules.add(new PerspectivePlus()); + modules.add(new PortalGUI()); modules.add(new ScreenshotPlus()); modules.add(new TimeChanger()); +// modules.add(new TooltipsPlus()); modules.add(new Zoom()); modules.sort(Comparator.comparing(module -> module.getName().toLowerCase())); diff --git a/src/main/java/me/retucio/camtweaks/module/modules/ChatPlus.java b/src/main/java/me/retucio/camtweaks/module/modules/ChatPlus.java index 119412d..5576f5a 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/ChatPlus.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/ChatPlus.java @@ -162,7 +162,7 @@ public class ChatPlus extends Module { GameProfile sender = getSender(line, text); if (sender == null) return; - PlayerListEntry entry = mc.getNetworkHandler().getPlayerListEntry(sender.getId()); + PlayerListEntry entry = mc.getNetworkHandler().getPlayerListEntry(sender.id()); if (entry == null) return; PlayerSkinDrawer.draw(context, entry.getSkinTextures(), 0, y, 8); diff --git a/src/main/java/me/retucio/camtweaks/module/modules/Freecam.java b/src/main/java/me/retucio/camtweaks/module/modules/Freecam.java index 61547d4..a811b97 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/Freecam.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/Freecam.java @@ -9,6 +9,10 @@ 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.gui.Click; +import net.minecraft.client.input.KeyInput; +import net.minecraft.client.input.MouseInput; +import net.minecraft.client.option.KeyBinding; import net.minecraft.client.option.Perspective; import net.minecraft.network.packet.Packet; import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; @@ -44,6 +48,7 @@ public class Freecam extends Module { 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 BooleanSetting blockOutlines = addSetting(new BooleanSetting("contorno de bloques", "mostrar el contorno de los bloques estando en el modo de cámara libre", true)); public NumberSetting speedSetting = addSetting(new NumberSetting( "velocidad", "velocidad de movimiento de la cámara", @@ -141,9 +146,9 @@ public class Freecam extends Module { @Override public void onTick() { - if (mc.cameraEntity == null || perspective == null) return; + if (mc.getCameraEntity() == null || perspective == null) return; - mc.cameraEntity.noClip = mc.cameraEntity.isInsideWall(); + mc.getCameraEntity().noClip = mc.getCameraEntity().isInsideWall(); if (!perspective.isFirstPerson()) mc.options.setPerspective(Perspective.FIRST_PERSON); Vec3d forward = Vec3d.fromPolar(0, yaw); @@ -204,24 +209,25 @@ public class Freecam extends Module { public void onKey(KeyEvent event) { if (mc.currentScreen != null) return; if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_F3)) return; + KeyInput key = new KeyInput(event.getKey(), event.getScancode(), 0); boolean shouldCancel = true; - if (mc.options.forwardKey.matchesKey(event.getKey(), event.getScancode())) { + if (mc.options.forwardKey.matchesKey(key)) { forward = event.getAction() != GLFW.GLFW_RELEASE; mc.options.forwardKey.setPressed(false); - } else if (mc.options.backKey.matchesKey(event.getKey(), event.getScancode())) { + } else if (mc.options.backKey.matchesKey(key)) { backward = event.getAction() != GLFW.GLFW_RELEASE; mc.options.backKey.setPressed(false); - } else if (mc.options.rightKey.matchesKey(event.getKey(), event.getScancode())) { + } else if (mc.options.rightKey.matchesKey(key)) { right = event.getAction() != GLFW.GLFW_RELEASE; mc.options.rightKey.setPressed(false); - } else if (mc.options.leftKey.matchesKey(event.getKey(), event.getScancode())) { + } else if (mc.options.leftKey.matchesKey(key)) { left = event.getAction() != GLFW.GLFW_RELEASE; mc.options.leftKey.setPressed(false); - } else if (mc.options.jumpKey.matchesKey(event.getKey(), event.getScancode())) { + } else if (mc.options.jumpKey.matchesKey(key)) { up = event.getAction() != GLFW.GLFW_RELEASE; mc.options.jumpKey.setPressed(false); - } else if (mc.options.sneakKey.matchesKey(event.getKey(), event.getScancode())) { + } else if (mc.options.sneakKey.matchesKey(key)) { down = event.getAction() != GLFW.GLFW_RELEASE; mc.options.sneakKey.setPressed(false); } else { @@ -234,24 +240,25 @@ public class Freecam extends Module { @SubscribeEvent public void onMouseClick(MouseClickEvent event) { // por si el restrasado del usuario usa el ratón para moverse if (mc.currentScreen != null) return; + Click click = new Click(0, 0, new MouseInput(event.getButton(), 0)); boolean shouldCancel = true; - if (mc.options.forwardKey.matchesKey(event.getButton(), 0)) { + if (mc.options.forwardKey.matchesMouse(click)) { forward = event.getAction() != GLFW.GLFW_RELEASE; mc.options.forwardKey.setPressed(false); - } else if (mc.options.backKey.matchesKey(event.getButton(), 0)) { + } else if (mc.options.backKey.matchesMouse(click)) { backward = event.getAction() != GLFW.GLFW_RELEASE; mc.options.backKey.setPressed(false); - } else if (mc.options.rightKey.matchesKey(event.getButton(), 0)) { + } else if (mc.options.rightKey.matchesMouse(click)) { right = event.getAction() != GLFW.GLFW_RELEASE; mc.options.rightKey.setPressed(false); - } else if (mc.options.leftKey.matchesKey(event.getButton(), 0)) { + } else if (mc.options.leftKey.matchesMouse(click)) { left = event.getAction() != GLFW.GLFW_RELEASE; mc.options.leftKey.setPressed(false); - } else if (mc.options.jumpKey.matchesKey(event.getButton(), 0)) { + } else if (mc.options.jumpKey.matchesMouse(click)) { up = event.getAction() != GLFW.GLFW_RELEASE; mc.options.jumpKey.setPressed(false); - } else if (mc.options.sneakKey.matchesKey(event.getButton(), 0)) { + } else if (mc.options.sneakKey.matchesMouse(click)) { down = event.getAction() != GLFW.GLFW_RELEASE; mc.options.sneakKey.setPressed(false); } else { 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 b0b4777..67dc5ea 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/Fullbright.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/Fullbright.java @@ -39,6 +39,8 @@ public class Fullbright extends Module { green.setVisible(v); blue.setVisible(v); alpha.setVisible(v); + + if (v) disableNightVision(); }); } diff --git a/src/main/java/me/retucio/camtweaks/module/modules/HUD.java b/src/main/java/me/retucio/camtweaks/module/modules/HUD.java index 654cf7a..1feeeb6 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/HUD.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/HUD.java @@ -23,12 +23,26 @@ public class HUD extends Module { public EnumSetting timeFormat = addSetting(new EnumSetting<>("formato de la hora", "12h o 24h", TimeFormat.class, TimeFormat.TWENTY_FOUR_HOUR)); public NumberSetting timezone = addSetting(new NumberSetting("zona horaria", "zona horaria en UTC+n", 1, -6, 6, 1)); + // elementos public BooleanSetting coords = addSetting(new BooleanSetting("coordenadas", "mostrar coordenadas", true)); - public StringSetting customText = addSetting(new StringSetting("texto custom", "marca de agua (dejar vacío para quitar)", "ESCROTO", 40)); - public BooleanSetting fps = addSetting(new BooleanSetting("fps", "mostrar frames por segundo", true)); - public BooleanSetting tps = addSetting(new BooleanSetting("tps", "mostrar tasa de ticks por segundo del server", true)); - public BooleanSetting time = addSetting(new BooleanSetting("hora", "mostrar hora actual", true)); + public NumberSetting coordsX = new NumberSetting("X de las coordenadas", ".", -1, -1, 1920, 1); + public NumberSetting coordsY = new NumberSetting("Y de las coordenadas", ".", -1, -1, 1080, 1); + public StringSetting customText = addSetting(new StringSetting("texto custom", "marca de agua (dejar vacío para quitar)", "", 40)); + public NumberSetting customTextX = new NumberSetting("X de la marca de agua", ".", -1, -1, 1920, 1); + public NumberSetting customTextY = new NumberSetting("Y de la marca de agua", ".", -1, -1, 1080, 1); + + public BooleanSetting fps = addSetting(new BooleanSetting("fps", "mostrar frames por segundo", true)); + public NumberSetting fpsX = new NumberSetting("X de los fps", ".", -1, -1, 1920, 1); + public NumberSetting fpsY = new NumberSetting("Y de los fps", ".", -1, -1, 1080, 1); + + public BooleanSetting tps = addSetting(new BooleanSetting("tps", "mostrar tasa de ticks por segundo del server", true)); + public NumberSetting tpsX = new NumberSetting("X del tps", ".", -1, -1, 1920, 1); + public NumberSetting tpsY = new NumberSetting("Y del tps", ".", -1, -1, 1080, 1); + + public BooleanSetting time = addSetting(new BooleanSetting("hora", "mostrar hora actual", true)); + public NumberSetting timeX = new NumberSetting("X de la hora", ".", -1, -1, 1920, 1); + public NumberSetting timeY = new NumberSetting("Y de la hora", ".", -1, -1, 1080, 1); public HUD() { super("HUD", "superposición de la pantalla con info. adicional"); diff --git a/src/main/java/me/retucio/camtweaks/module/modules/Nametags.java b/src/main/java/me/retucio/camtweaks/module/modules/Nametags.java index f406a52..1322a5b 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/Nametags.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/Nametags.java @@ -14,8 +14,11 @@ 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.item.Item; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.MathHelper; +import net.minecraft.world.entity.EntityQueriable; +import net.minecraft.world.entity.UniquelyIdentifiable; import java.io.InputStreamReader; import java.net.HttpURLConnection; @@ -44,6 +47,8 @@ public class Nametags extends Module { public EnumSetting healthMode = addSetting(new EnumSetting<>("mostrar vida en", "de qué manera mostrar la vida", HealthMode.class, HealthMode.POINTS)); public BooleanSetting countItems = addSetting(new BooleanSetting("contar items", "muestra cuánto de un item hay en un stack dropeado", true)); + public ListSetting items = addSetting(new ListSetting<>("items", "te permite elegir cuáles items tienen su nombre visible", + Lists.itemList, Lists.allTrue(Lists.itemList), Lists.itemNames)); public BooleanSetting showProjectileDamage = addSetting(new BooleanSetting("daño del proyectil", "muestra cuánto daño hace un proyectil en su nametag", true)); public BooleanSetting distinguishBabies = addSetting(new BooleanSetting("distinguir bebés", "cambia el nametag cuando una entidad está en su fase bebé", false)); @@ -64,6 +69,10 @@ public class Nametags extends Module { entities.setDefaultValues(entities.getValues()); health.onUpdate(v -> healthMode.setVisible(v)); + + entities.onUpdate(entities -> { + items.setVisible(entities.get(EntityType.ITEM)); + }); } // literalmente cómo lo calcula Minecraft @@ -74,7 +83,7 @@ public class Nametags extends Module { double velocity = arrow.getVelocity().length(); DamageSource damageSource = arrow.getDamageSources().arrow(arrow, arrow.getOwner()); - if (arrow.getWeaponStack() != null && arrow.getWorld() instanceof ServerWorld world) + if (arrow.getWeaponStack() != null && arrow.getEntityWorld() 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)); @@ -89,7 +98,7 @@ public class Nametags extends Module { @SuppressWarnings("deprecation") public String getOwnerName(LazyEntityReference owner) { // si el dueño está en línea - LivingEntity ownerEntity = owner.resolve(mc.world, LivingEntity.class); + LivingEntity ownerEntity = owner.resolve((EntityQueriable) mc.world, LivingEntity.class); if (ownerEntity instanceof PlayerEntity playerEntity) return playerEntity.getName().getString(); // mirar si ya está en la caché diff --git a/src/main/java/me/retucio/camtweaks/module/modules/NoRender.java b/src/main/java/me/retucio/camtweaks/module/modules/NoRender.java index 6b3c41a..5c0aabf 100644 --- a/src/main/java/me/retucio/camtweaks/module/modules/NoRender.java +++ b/src/main/java/me/retucio/camtweaks/module/modules/NoRender.java @@ -42,8 +42,6 @@ public class NoRender extends Module { public BooleanSetting blindnessEffect = addSetting(new BooleanSetting("ceguera", "renderizar miopía", false)); public BooleanSetting darknessEffect = addSetting(new BooleanSetting("oscuridad", "renderizar miedo a la oscuridad", false)); public BooleanSetting nightVisionEffect; - public NumberSetting potionParticleAlpha = addSetting(new NumberSetting("opacidad de burbujas", "opacidad de las partículas de pociones", - 170, 0, 255, 1)); public BooleanSetting scoreboard = addSetting(new BooleanSetting("marcador", "mostrar marcador a la derecha", false)); public BooleanSetting titles = addSetting(new BooleanSetting("títulos", "mostrar títulos (del comando /title)", false)); diff --git a/src/main/java/me/retucio/camtweaks/module/modules/PortalGUI.java b/src/main/java/me/retucio/camtweaks/module/modules/PortalGUI.java new file mode 100644 index 0000000..7cc0344 --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/module/modules/PortalGUI.java @@ -0,0 +1,14 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.module.Module; + +/** continúa en: + * @see me.retucio.camtweaks.mixin.ClientPlayerEntityMixin + */ + +public class PortalGUI extends Module { + + public PortalGUI() { + super("interfaz en portales", "te permite abrir interfaces dentro de portales, como el chat o el inventario"); + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/camtweaks/module/modules/TooltipsPlus.java b/src/main/java/me/retucio/camtweaks/module/modules/TooltipsPlus.java new file mode 100644 index 0000000..353b86d --- /dev/null +++ b/src/main/java/me/retucio/camtweaks/module/modules/TooltipsPlus.java @@ -0,0 +1,51 @@ +package me.retucio.camtweaks.module.modules; + +import me.retucio.camtweaks.module.Module; +import me.retucio.camtweaks.module.settings.BooleanSetting; +import me.retucio.camtweaks.module.settings.EnumSetting; +import me.retucio.camtweaks.module.settings.KeySetting; +import org.lwjgl.glfw.GLFW; + +public class TooltipsPlus extends Module { + + public EnumSetting displayMode = addSetting(new EnumSetting<>( + "mostrar", "cúando mostrar la cajita de los huevos", DisplayModes.class, DisplayModes.ALWAYS)); + + public KeySetting displayKey = addSetting(new KeySetting( + "tecla de visualización", "tecla a presionar para mostrar la cajita", GLFW.GLFW_KEY_LEFT_CONTROL)); + + public BooleanSetting middleClickPreview = addSetting(new BooleanSetting("preview de middle click", + "abre una interfaz con los contenidos de un bloque de almacenamiento al presionar el middle click (la ruedita)", false)); + + public EnumSetting itemSize = addSetting(new EnumSetting<>( + "tamaño del ítem", "cómo mostrar el tamaño del ítem en memoria", SizeFormat.class, SizeFormat.NONE)); + + + + public TooltipsPlus() { + super("tooltips plus", "mejoras varias a las cajitas de descripción de items"); + } + + public enum DisplayModes { + ALWAYS("siempre"), + KEY("al presionar una tecla"), + NEVER("nunca"); + + final String name; + DisplayModes(String name) { this.name = name; } + @Override public String toString() { return name; } + } + + public enum SizeFormat { + NONE("no mostrar"), + BYTES("bytes"), + KB("kilobytes"), + MB("megabytes"); + + final String name; + SizeFormat(String name) { this.name = name; } + @Override public String toString() { return name; } + } + + +} diff --git a/src/main/java/me/retucio/camtweaks/ui/ClickGUI.java b/src/main/java/me/retucio/camtweaks/ui/ClickGUI.java index b742bf1..202c60e 100644 --- a/src/main/java/me/retucio/camtweaks/ui/ClickGUI.java +++ b/src/main/java/me/retucio/camtweaks/ui/ClickGUI.java @@ -18,6 +18,7 @@ import me.retucio.camtweaks.ui.widgets.SearchBarWidget; import me.retucio.camtweaks.util.ChatUtil; import me.retucio.camtweaks.util.KeyUtil; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.Click; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; @@ -93,35 +94,35 @@ public class ClickGUI extends Screen { return bottom + 20; // padding } - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - scrollBar.mouseClicked(mouseX, mouseY, button); - searchBar.mouseClicked(mouseX, mouseY, button); + + public boolean mouseClicked(Click click, boolean doubled) { + scrollBar.mouseClicked(click.x(), click.y(), click.button()); + searchBar.mouseClicked(click.x(), click.y(), click.button()); // detectar clics sobre los marcos - modulesFrame.mouseClicked(mouseX, mouseY, button); + modulesFrame.mouseClicked(click.x(), click.y(), click.button()); for (SettingsFrame sf : new ArrayList<>(settingsFrames)) - sf.mouseClicked(mouseX, mouseY, button); + sf.mouseClicked(click.x(), click.y(), click.button()); - return super.mouseClicked(mouseX, mouseY, button); + return super.mouseClicked(click, doubled); } @Override - public boolean mouseReleased(double mouseX, double mouseY, int button) { - scrollBar.mouseReleased(mouseX, mouseY, button); - searchBar.mouseReleased(mouseX, mouseY, button); + public boolean mouseReleased(Click click) { + scrollBar.mouseReleased(click.x(), click.y(), click.button()); + searchBar.mouseReleased(click.x(), click.y(), click.button()); // registrar cuándo se suelta el clic, en cada marco respectivamente - modulesFrame.mouseReleased(mouseX, mouseY, button); + modulesFrame.mouseReleased(click.x(), click.y(), click.button()); for (SettingsFrame sf : new ArrayList<>(settingsFrames)) - sf.mouseRelease(mouseX, mouseY, button); - return super.mouseReleased(mouseX, mouseY, button); + sf.mouseRelease(click.x(), click.y(), click.button()); + return super.mouseReleased(click); } @Override - public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - scrollBar.mouseDragged(mouseY); - return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + public boolean mouseDragged(Click click, double deltaX, double deltaY) { + scrollBar.mouseDragged(click.y()); + return super.mouseDragged(click, deltaX, deltaY); } @SubscribeEvent diff --git a/src/main/java/me/retucio/camtweaks/ui/HUD.java b/src/main/java/me/retucio/camtweaks/ui/HUD.java index 65fb3d6..690928a 100644 --- a/src/main/java/me/retucio/camtweaks/ui/HUD.java +++ b/src/main/java/me/retucio/camtweaks/ui/HUD.java @@ -8,6 +8,7 @@ import me.retucio.camtweaks.module.modules.HUD.TimeFormat; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.ChatScreen; +import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.render.RenderTickCounter; import net.minecraft.util.math.Vec3d; @@ -26,7 +27,13 @@ public class HUD { private static float estimatedTPS = 20f; public static void render(DrawContext ctx, RenderTickCounter tc) { - if (ModuleManager.INSTANCE == null || mc.player == null || mc.cameraEntity == null) return; + if (ModuleManager.INSTANCE == null + || mc.player == null + || mc.getCameraEntity() == null + || mc.currentScreen instanceof TitleScreen + || mc.options.hudHidden) + return; + me.retucio.camtweaks.module.modules.HUD hud = ModuleManager.INSTANCE.getModuleByClass(me.retucio.camtweaks.module.modules.HUD.class); int width = mc.getWindow().getScaledWidth(); @@ -56,12 +63,12 @@ public class HUD { freecam.getZ(tc.getDynamicDeltaTicks()) ); else - coords = mc.player.getPos(); + coords = mc.player.getEntityPos(); String text = (int) coords.x + " " + (int) coords.y + " " + (int) coords.z; ctx.drawText(mc.textRenderer, text, - width - mc.textRenderer.getWidth(text) - 2, - height - mc.textRenderer.fontHeight - 2, + (hud.coordsX.getIntValue() == -1) ? width - mc.textRenderer.getWidth(text) - 2 : hud.coordsX.getIntValue(), + (hud.coordsY.getIntValue() == -1) ? height - mc.textRenderer.fontHeight - 2 : hud.coordsY.getIntValue(), color.getRGB(), shadow); } diff --git a/src/main/java/me/retucio/camtweaks/ui/buttons/BindButton.java b/src/main/java/me/retucio/camtweaks/ui/buttons/BindButton.java index 39031ec..4fd546b 100644 --- a/src/main/java/me/retucio/camtweaks/ui/buttons/BindButton.java +++ b/src/main/java/me/retucio/camtweaks/ui/buttons/BindButton.java @@ -2,14 +2,22 @@ package me.retucio.camtweaks.ui.buttons; import me.retucio.camtweaks.module.settings.KeySetting; import me.retucio.camtweaks.ui.ClickGUI; +import me.retucio.camtweaks.ui.frames.ClientSettingsFrame; import me.retucio.camtweaks.ui.frames.SettingsFrame; +import me.retucio.camtweaks.util.ChatUtil; import me.retucio.camtweaks.util.Colors; import me.retucio.camtweaks.util.KeyUtil; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.input.KeyInput; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.resource.language.I18n; import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import org.lwjgl.glfw.GLFW; +import static me.retucio.camtweaks.CameraTweaks.mc; + // botón para configurar la tecla asignada a un módulo. comienza a escuchar al hacerle clic public class BindButton extends SettingButton { @@ -44,15 +52,29 @@ public class BindButton extends SettingButton { } public void onKey(int key, int action) { - if (listening && action == GLFW.GLFW_PRESS) { - if (key == GLFW.GLFW_KEY_ESCAPE) - setting.setKey(GLFW.GLFW_KEY_UNKNOWN); - else - setting.setKey(key); - listening = false; + if (!listening || action != GLFW.GLFW_PRESS) return; + + if (key == GLFW.GLFW_KEY_ESCAPE) { + setting.setKey(GLFW.GLFW_KEY_UNKNOWN); + } else { + for (KeyBinding bind : mc.options.allKeys) { + boolean keyAlreadyBound = bind.matchesKey(new KeyInput(key, 0, 0)); + boolean allowMultiple = ClientSettingsFrame.guiSettings.multipleKeybinds.isEnabled(); + + if (keyAlreadyBound && !allowMultiple) { + ChatUtil.warn("esa tecla ya está cogida por " + + Formatting.GREEN + "\"" + I18n.translate(bind.getId()) + "\""); + listening = false; + return; + } + } + setting.setKey(key); } + + listening = false; } + public boolean isFocused() { return listening; } diff --git a/src/main/java/me/retucio/camtweaks/util/Lists.java b/src/main/java/me/retucio/camtweaks/util/Lists.java index 767a92a..6ec7d38 100644 --- a/src/main/java/me/retucio/camtweaks/util/Lists.java +++ b/src/main/java/me/retucio/camtweaks/util/Lists.java @@ -4,6 +4,7 @@ import net.minecraft.block.Block; import net.minecraft.client.particle.Particle; import net.minecraft.client.resource.language.I18n; import net.minecraft.entity.EntityType; +import net.minecraft.item.Item; import net.minecraft.particle.ParticleType; import net.minecraft.particle.ParticleTypes; import net.minecraft.registry.Registries; @@ -18,10 +19,12 @@ public class Lists { public static final List> entityList = Registries.ENTITY_TYPE.stream().toList(); public static Map, String> entityNames; - public static final List> particleList = Registries.PARTICLE_TYPE.stream().toList(); public static Map, String> particleNames; + public static final List itemList = Registries.ITEM.stream().toList(); + public static Map itemNames; + public static final List blockList = Registries.BLOCK.stream().toList(); public static void init() { @@ -32,6 +35,9 @@ public class Lists { // no hay traducciones para nombres de partículas, y paso de hacerlas yo particleNames = getMapOfLists(particleList, particleList.stream().map(particle -> Registries.PARTICLE_TYPE.getId(particle).toShortTranslationKey()).toList()); + + itemNames = getMapOfLists(itemList, + itemList.stream().map(item -> I18n.translate(item.getTranslationKey())).toList()); } public static Map allTrue(List options) { diff --git a/src/main/resources/camtweaks.accesswidener b/src/main/resources/camtweaks.accesswidener index 7f6fa2c..3257b7b 100644 --- a/src/main/resources/camtweaks.accesswidener +++ b/src/main/resources/camtweaks.accesswidener @@ -2,8 +2,10 @@ accessWidener v2 named accessible class net/minecraft/client/font/TextRenderer$Drawer -accessible field net/minecraft/client/particle/Particle alpha F +accessible field net/minecraft/client/particle/BillboardParticle alpha F accessible field net/minecraft/client/particle/BillboardParticle scale F accessible field net/minecraft/client/particle/Particle velocityMultiplier F accessible field net/minecraft/client/particle/Particle gravityStrength F -accessible field net/minecraft/client/particle/Particle collidesWithWorld Z \ No newline at end of file +accessible field net/minecraft/client/particle/Particle collidesWithWorld Z + +accessible method net/minecraft/client/render/WorldRenderer method_74752 (Lnet/minecraft/client/render/Camera;Lnet/minecraft/client/render/Frustum;Z)V \ No newline at end of file diff --git a/src/main/resources/camtweaks.mixins.json b/src/main/resources/camtweaks.mixins.json index 2e95819..b9ebca7 100644 --- a/src/main/resources/camtweaks.mixins.json +++ b/src/main/resources/camtweaks.mixins.json @@ -5,7 +5,6 @@ "mixins": [ "ClientConnectionMixin", "DimensionTypeMixin", - "EntityEffectParticleEffectMixin", "EntityMixin", "ItemEntityMixin", "KeyInputMixin", @@ -30,10 +29,10 @@ "ChatScreenMixin", "ChunkBorderDebugRendererMixin", "ChunkOcclusionDataBuilderMixin", + "ClientPlayerEntityMixin", "ClientPlayerInteractionManagerMixin", "ClientPlayNetworkHandlerMixin", "ClientWorldPropertiesMixin", - "CompassStateMixin", "DamageParticleFactoryMixin", "DamageParticleMixin", "FogRendererMixin", @@ -55,6 +54,7 @@ "SkyRendererMixin", "StuckArrowsFeatureRendererMixin", "TextRendererDrawerMixin", + "TextRendererMixin", "WeatherRenderingMixin", "WorldRendererMixin", "accessor.ClientPlayNetworkHandlerAccessor", diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 0553aa3..434d78d 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -25,12 +25,10 @@ ], "accessWidener": "camtweaks.accesswidener", "depends": { - "fabricloader": ">=0.16.14", - "minecraft": "~1.21.6", + "fabricloader": ">=0.17.3", + "minecraft": "~1.21.10", "java": ">=21", "fabric-api": "*" }, - "suggests": { - "another-mod": "*" - } + "suggests": {} } \ No newline at end of file