Compare commits

...
17 Commits
Author SHA1 Message Date
retuci0 436b79fd2b v2.7 2026-01-17 00:33:24 +01:00
retuci0 9afaa4e0c8 v2.6 2026-01-11 11:12:44 +01:00
retuci0 f794457538 v2.5 2026-01-06 18:09:52 +01:00
retuci0 ec3e633cec v2.4 2026-01-05 22:16:01 +01:00
retuci0 8f17bd8e67 v2.3 - sputnik rename 2026-01-04 17:46:51 +01:00
retuci0 dc2429918e v2.2 2026-01-04 11:40:06 +01:00
retuci0 94a9b1dade v2.1 2026-01-02 13:59:08 +01:00
retuci0 48899f85f9 v2.0.1 2026-01-01 18:29:46 +01:00
retuci0 347ec658bb v2.0 2025-12-31 00:44:36 +01:00
retuci0 a9cf6dd924 v1.9.1 2025-12-28 00:58:08 +01:00
retuci0 8e44dda9cf v1.9 2025-12-26 22:45:43 +01:00
retuci0 2329476fe4 v1.8 2025-12-22 18:54:02 +01:00
retuci0 6b2ec0e69a v1.7.1 2025-12-14 21:31:58 +01:00
retuci0 6fa409d60a v1.7 2025-12-10 19:26:51 +01:00
retuci0 4f816381c3 upsi 2025-12-07 09:01:21 +01:00
retuci0 36c38bdf02 ups 2025-12-07 09:00:41 +01:00
retuci0 a6a6f1261e v1.5 2025-12-07 08:59:33 +01:00
585 changed files with 15021 additions and 13635 deletions

No files matched your search

+1 -3
View File
@@ -42,7 +42,5 @@ replay_*.log
# otros
todo.txt
test.java
cambios.md
# no está terminado
src/main/java/me/retucio/camtweaks/module/modules/TooltipsPlus.java
remappedSrc/
+35 -9
View File
@@ -1,31 +1,33 @@
# jenny's mod 2 100% real
mod para Minecraft Fabric 1.21.6 que añade algunas cosas QOL, mayormente relacionadas a la cámara.
mod para Minecraft Fabric 1.21.10 que añade algunas cosas QOL, mayormente relacionadas a la cámara.
## instalación
### para gente normal:
1. ir a [lanzamientos](https://github.com/retuci0/camera-tweaks/releases)
1. ir a [lanzamientos](https://github.com/retuci0/sputnik/releases)
2. selecionar la versión más reciente
3. descargar el .jar
4. moverlo a tu directorio de mods (probablemente `%appdata%/.minecraft/mods`)
asegúrate de tener una version de Minecraft y Fabric compatibles con el mod (MC 1.21.6; Fabric 0.128.2)
es posible que hayan problemas al usarlo junto a otros mods, especialmente otros clientes, pues pueden conflictar
asegúrate de tener una version de Minecraft y Fabric compatibles con el mod (MC `1.21.11`; Fabric `0.17.3`)
es posible que haya problemas al usarlo junto a otros mods, especialmente junto a otros clientes, pues pueden conflictar entre ellos.
### para frikis de 200 de iq
1. clona el respositorio (`git clone https://github.com/retuci0/camera-tweaks`)
2. entra al directorio del repositorio (`cd camera-tweaks`)
1. clona el respositorio (`git clone https://github.com/retuci0/sputnik`)
2. entra al directorio del repositorio (`cd sputnik`)
3. `gradlew build` para Windows o `chmod +x gradlew` + `./gradlew build` para Linux (Mac es Linux)
4. el resultado estará en `/build/libs/camtweaks-X.X.jar` (el que no lleva "sources" en el nombre)
4. el resultado estará en `/build/libs/sputnik-X.X.jar` (el que no lleva "sources" en el nombre)
## uso
`shift derecho` por defecto para abrir la interfaz
`pág. arriba` por defecto para abrir el editor del hud
`$` como prefijo por defecto para comandos (se autocompletan)
algunos módulos tienen teclas asignadas por defecto, asígnales `ESC` para desactivar sus teclas
algunos módulos tienen teclas asignadas por defecto, asígnales `ESC` para desactivar sus atajos de teclado
## interfaz
@@ -51,6 +53,8 @@ algunos módulos tienen teclas asignadas por defecto, asígnales `ESC` para desa
<img src="screenshots/crits.png" alt="críticos">
<img src="screenshots/fullbright.png" alt="fullbright en modo gamma cambiando el color de los shaders">
<img src="screenshots/hud.png" alt="HUD">
<img src="screenshots/hudeditor.png" alt="editor de HUD">
<img src="screenshots/colorpicker.png" alt="selector de colores">
## contibuciones
@@ -58,4 +62,26 @@ sí por favor
## licencia
no sé, haz lo que quieras con esto, es puta basura xd
no sé, haz lo que quieras con esto, es puta basura xd
aunque estaría guay que acreditases
pero bueno
## descargo de responsabilidad
me importa una puta mierda lo que pase al usar este mod en servers donde es baneable y así.
## mods recomendados
> mods que recomiendo usar junto a este:
- [fabric api (necesario)](https://modrinth.com/mod/fabric-api/): necesario para el mod
- [sodium](https://modrinth.com/mod/sodium): mejora el rendimiento general del juego
- [viafabricplus](https://modrinth.com/mod/viafabricplus): te permite conectarte a servidores que tengan una versión distinta a la de tu cliente
- [xaero's world map](https://modrinth.com/mod/xaeros-world-map/) y [xaero's minimap](https://modrinth.com/mod/xaeros-minimap/): mapa chulo
- [mod menu](https://modrinth.com/mod/modmenu): lista de los mods instalados, y sus ajustes
- [iris](https://modrinth.com/mod/iris): shaders
- [lambdynamiclights](https://modrinth.com/mod/lambdynamiclights): iluminación dinámica
- [appleskin](https://modrinth.com/mod/appleskin/): información relacionada con la comida
- [baritone (desactualizado)](https://github.com/cabaletta/baritone): google maps para juego de cubos
+13 -24
View File
@@ -11,26 +11,25 @@ base {
}
repositories {
// Add repositories to retrieve artifacts from in here.
// You should only use this when depending on other mods because
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories.
maven {
name = "FDD Maven"
url = "https://maven.firstdark.dev/releases"
}
}
dependencies {
// To change the versions see the gradle.properties file
// mc
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}"
// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
// otros
include(modImplementation "dev.firstdark.discordrpc:discord-rpc:1.0.3")
}
loom {
accessWidenerPath = file("src/main/resources/camtweaks.accesswidener")
accessWidenerPath = file("src/main/resources/sputnik.accesswidener")
}
processResources {
@@ -46,11 +45,6 @@ tasks.withType(JavaCompile).configureEach {
}
java {
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this line, sources will not be generated.
withSourcesJar()
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
@@ -59,11 +53,12 @@ jar {
inputs.property "archivesName", project.base.archivesName
from("LICENSE") {
rename { "${it}_${inputs.properties.archivesName}"}
rename {
"${it}_${inputs.properties.archivesName}"
}
}
}
// configure the maven publication
publishing {
publications {
create("mavenJava", MavenPublication) {
@@ -72,11 +67,5 @@ publishing {
}
}
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
// Notice: This block does NOT have the same function as the block in the top level.
// The repositories here will be used for publishing your artifact, not for
// retrieving dependencies.
}
repositories {}
}
+12 -12
View File
@@ -1,23 +1,23 @@
# v1.4
# v2.7
## novedades
- actualización a la 1.21.10
### adiciones
interfaz en portales: te permite interactuar con interfaces estando dentro de un bloque de portal del nether
- filtro por categoría de módulos en la barra de búsqueda
#### módulos nuevos:
- avioneta: vuela infinitamente usando el glitch de las elytras descubierto por Heppe, o al menos hasta que se te rompan las elytras
- triangulador de strongholds: usa geometría simple para calcular la intersección de las líneas creadas por los ojos de ender lanzados para obtener la posición aproximada de la stronghold más cercana
- discordrpc: personaliza la actividad de tu perfil de discord
### arreglos / mejoras
- 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
- ahora se puede hacer ctrl + v para pegar en los ajustes de texto
- el color por defecto de la superposición de daño ya es el color principal del mod
- arreglado el elemento del HUD de rotación
- arreglado los marcos de ajustes de selección
## problemas reconocidos
+12 -5
View File
@@ -1,5 +1,12 @@
meteor client dev team
oyvey client (1.21 port by mioclient)
lennyboi (youtube)
packbar by cattyn on github
shotify mod
Meteor Client: https://github.com/MeteorDevelopment/meteor-client | https://meteorclient.com
OyVey Port: https://github.com/mioclient/oyvey-ported/
Lenny Boi: https://www.youtube.com/@lennyboi7195
Shotify: https://modrinth.com/mod/shotify
No Telemetry: https://modrinth.com/mod/no-telemetry
Trouser Streak: https://github.com/etianl/Trouser-Streak
No More Purple: https://github.com/Pepperoni-Jabroni/NoMorePurple/
bypass-resource-pack: https://github.com/emilyy-dev/bypass-resource-pack
elytra-recast: https://github.com/InLieuOfLuna/elytra-recast/
probablemente más pero como tengo demencia se me olvida
si quieres que te acredite o quite tu código de mi mod, mándame un mensaje en discord (username: retucio) y sin problemas :)
+9 -14
View File
@@ -1,18 +1,13 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx1G
org.gradle.jvmargs=-Xmx2G
org.gradle.parallel=true
# Fabric Properties
# check these on https://fabricmc.net/develop
minecraft_version=1.21.10
yarn_mappings=1.21.10+build.2
loader_version=0.17.3
loom_version=1.11-SNAPSHOT
minecraft_version=1.21.11
yarn_mappings=1.21.11+build.3
loader_version=0.18.4
loom_version=1.13-SNAPSHOT
# Mod Properties
mod_version=1.4
fabric_api_version=0.140.2+1.21.11
mod_version=2.7
maven_group=me.retucio
archives_base_name=camtweaks
# Dependencies
fabric_version=0.135.0+1.21.10
archives_base_name=sputnik
@@ -1,178 +0,0 @@
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();
}
}
@@ -1,76 +0,0 @@
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<String> 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 <T> RequiredArgumentBuilder<CommandSource, T> argument(final String name, final ArgumentType<T> type) {
return RequiredArgumentBuilder.argument(name, type);
}
protected static LiteralArgumentBuilder<CommandSource> literal(final String name) {
return LiteralArgumentBuilder.literal(name);
}
// para registrar comandos
public final void registerTo(CommandDispatcher<CommandSource> dispatcher) {
register(dispatcher, name);
for (String alias : aliases) register(dispatcher, alias);
}
public void register(CommandDispatcher<CommandSource> dispatcher, String name) {
LiteralArgumentBuilder<CommandSource> builder = LiteralArgumentBuilder.literal(name);
build(builder);
dispatcher.register(builder);
}
public abstract void build(LiteralArgumentBuilder<CommandSource> builder);
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public List<String> 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();
}
}
@@ -1,79 +0,0 @@
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<Command> commands = new ArrayList<>();
public static final CommandDispatcher<CommandSource> 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 extends Command> T getCommandByClass(Class<T> 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;
}
}
@@ -1,49 +0,0 @@
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<Module> {
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<String> 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 <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
return CommandSource.suggestMatching(ModuleManager.INSTANCE.getModules().stream().map(module -> module.getName().replace(" ", "_")), builder);
}
@Override
public Collection<String> getExamples() {
return examples;
}
public static Module get(CommandContext<CommandSource> ctx) {
return ctx.getArgument("módulo", Module.class);
}
}
@@ -1,56 +0,0 @@
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<CommandSource> 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;
}
}
@@ -1,37 +0,0 @@
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<CommandSource> 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;
});
}
}
@@ -1,26 +0,0 @@
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<CommandSource> builder) {
builder
.then(argument("jugador", PlayerArgumentType.INSTANCE)
.executes(ctx -> {
MiscUtil.screen = new InventoryScreen(PlayerArgumentType.get(ctx));
return SUCCESS;
}));
}
}
@@ -1,29 +0,0 @@
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<CommandSource> 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;
}));
}
}
@@ -1,37 +0,0 @@
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<CommandSource> 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;
});
}
}
@@ -1,110 +0,0 @@
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<String, Boolean> moduleStates = new HashMap<>();
// nombre del ajuste -> valor
public Map<String, Object> settings = new HashMap<>();
// nombre del módulo -> posición (x, y)
public Map<String, int[]> settingsFrames = new HashMap<>();
// nombre del frame -> FrameData (que contiene extended, x & y)
public Map<String, FrameData> 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) {}
}
@@ -1,156 +0,0 @@
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<Object, Boolean> 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();
}
}
@@ -1,8 +0,0 @@
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 {}
@@ -1,9 +0,0 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
/**
* @see me.retucio.camtweaks.mixin.ChunkOcclusionDataBuilderMixin#onChunkOcclusion
*/
public class ChunkOcclusionEvent extends Event {}
@@ -1,26 +0,0 @@
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;
}
}
@@ -1,9 +0,0 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
/**
* @see me.retucio.camtweaks.mixin.ClientConnectionMixin#onDisconnect
*/
public class DisconnectEvent extends Event {}
@@ -1,33 +0,0 @@
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;
}
}
@@ -1,21 +0,0 @@
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;
}
}
@@ -1,46 +0,0 @@
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;
}
}
}
@@ -1,25 +0,0 @@
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;
}
}
@@ -1,36 +0,0 @@
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;
}
}
@@ -1,77 +0,0 @@
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<ClientBossBar> iterator;
public BossIterator(Iterator<ClientBossBar> iterator) {
this.iterator = iterator;
}
public Iterator<ClientBossBar> getIterator() {
return iterator;
}
public void setIterator(Iterator<ClientBossBar> iterator) {
this.iterator = iterator;
}
}
}
@@ -1,24 +0,0 @@
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;
}
}
@@ -1,12 +0,0 @@
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() {}
}
@@ -1,14 +0,0 @@
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 {}
}
@@ -1,10 +0,0 @@
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
}
@@ -1,5 +0,0 @@
package me.retucio.camtweaks.event.events.camtweaks;
import me.retucio.camtweaks.event.Event;
public class LoadClickGUIEvent extends Event {}
@@ -1,5 +0,0 @@
package me.retucio.camtweaks.event.events.camtweaks;
import me.retucio.camtweaks.event.Event;
public class LoadCommandManagerEvent extends Event {}
@@ -1,5 +0,0 @@
package me.retucio.camtweaks.event.events.camtweaks;
import me.retucio.camtweaks.event.Event;
public class LoadModuleManagerEvent extends Event {}
@@ -1,10 +0,0 @@
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
}
@@ -1,28 +0,0 @@
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;
}
}
@@ -1,38 +0,0 @@
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; }
}
@@ -1,203 +0,0 @@
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<ChatHudLine> messages;
@Shadow @Final
private List<ChatHudLine.Visible> visibleMessages;
@Shadow
public abstract void addMessage(Text message);
@Shadow
public abstract void addMessage(Text message, @Nullable MessageSignatureData signatureData, @Nullable MessageIndicator indicator);
@Inject(method = "<init>", 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<ChatHudLine.Visible> 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<OrderedText> 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();
}
}
@@ -1,34 +0,0 @@
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))));
}
}
@@ -1,21 +0,0 @@
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();
}
}
@@ -1,61 +0,0 @@
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());
}
}
@@ -1,48 +0,0 @@
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 = "<init>", 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<Boolean> 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<ActionResult> 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<ActionResult> cir) {
if (freecam.isEnabled() && freecam.cancelActionPackets.isEnabled()) cir.setReturnValue(ActionResult.FAIL);
}
}
@@ -1,48 +0,0 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Freecam;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.item.property.numeric.CompassState;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.camtweaks.CameraTweaks.mc;
@Mixin(CompassState.class)
public abstract class CompassStateMixin {
@Unique
private static Freecam freecam;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(boolean wobble, CompassState.Target target, CallbackInfo ci) {
freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
}
@ModifyExpressionValue(method = "getBodyYaw", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getBodyYaw()F"))
private static float getBodyYaw(float original) {
if (freecam.isEnabled()) return mc.gameRenderer.getCamera().getYaw();
return original;
}
@ModifyReturnValue(method = "getAngleTo(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/math/BlockPos;)D", at = @At("RETURN"))
private static double getAngleTo(double original, Entity entity, BlockPos blockPos) {
if (freecam.isEnabled()) {
Vec3d vec3d = Vec3d.ofCenter(blockPos);
Camera camera = mc.gameRenderer.getCamera();
return Math.atan2(vec3d.getZ() - camera.getPos().z, vec3d.getX() - camera.getPos().x) / (float) (Math.PI * 2);
}
return original;
}
}
@@ -1,57 +0,0 @@
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;
}
}
@@ -1,22 +0,0 @@
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;
}
}
@@ -1,19 +0,0 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.NoRender;
import net.minecraft.particle.EntityEffectParticleEffect;
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(EntityEffectParticleEffect.class)
public abstract class EntityEffectParticleEffectMixin {
@Inject(method = "getAlpha", at = @At("HEAD"), cancellable = true)
private void noRenderPotionParticles(CallbackInfoReturnable<Float> cir) {
NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
if (noRender.isEnabled()) cir.setReturnValue(256 - noRender.potionParticleAlpha.getFloatValue());
}
}
@@ -1,125 +0,0 @@
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 = "<init>", 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<Boolean> cir) {
if (ModuleManager.INSTANCE.getModuleByClass(AntiInvis.class).isEnabled()) cir.setReturnValue(false);
}
}
@@ -1,60 +0,0 @@
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 = "<init>", 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;
}
}
@@ -1,116 +0,0 @@
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 = "<init>", 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;
}
}
@@ -1,91 +0,0 @@
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 = "<init>", 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;
}
}
@@ -1,35 +0,0 @@
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 = "<init>", 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();
}
}
@@ -1,28 +0,0 @@
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;
}
}
@@ -1,28 +0,0 @@
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
);
}
}
@@ -1,23 +0,0 @@
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();
}
}
@@ -1,48 +0,0 @@
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 = "<init>", 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();
}
}
}
@@ -1,37 +0,0 @@
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<Boolean> 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<Boolean> info) {
this.sender = null;
}
@Override
public GameProfile smegma$getSender() {
return sender;
}
}
@@ -1,40 +0,0 @@
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();
}
}
@@ -1,28 +0,0 @@
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();
}
}
@@ -1,40 +0,0 @@
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 = "<init>", 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();
}
}
@@ -1,19 +0,0 @@
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;
}
}
@@ -1,49 +0,0 @@
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 = "<init>(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;
}
}
@@ -1,43 +0,0 @@
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 = "<init>", 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();
}
}
}
@@ -1,48 +0,0 @@
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();
}
}
}
@@ -1,13 +0,0 @@
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();
}
@@ -1,153 +0,0 @@
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<KeyModes> 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<AbstractSetting> 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<AbstractSetting> getSettings() {
return settings;
}
@SuppressWarnings("unchecked")
public <S extends AbstractSetting> 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; }
}
}
@@ -1,86 +0,0 @@
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<Module> 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<Module> getModules() {
return modules;
}
public List<Module> getEnabledModules() {
List<Module> 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 extends Module> T getModuleByClass(Class<T> clazz) {
for (Module module : modules)
if (clazz.isInstance(module))
return clazz.cast(module);
return null;
}
}
@@ -1,14 +0,0 @@
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");
}
}
@@ -1,31 +0,0 @@
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);
});
}
}
@@ -1,220 +0,0 @@
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<CustomHeadEntry> 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("(?<x>-?\\d{3,}(?:\\.\\d*)?)(?:\\s+(?<y>-?\\d{1,3}(?:\\.\\d*)?))?\\s+(?<z>-?\\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();
}
}
@@ -1,38 +0,0 @@
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);
});
}
}
@@ -1,75 +0,0 @@
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);
}
}
@@ -1,44 +0,0 @@
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();
}
}
@@ -1,375 +0,0 @@
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;
}
}
@@ -1,78 +0,0 @@
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<Modes> 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; }
}
}
@@ -1,139 +0,0 @@
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
));
}
}
@@ -1,56 +0,0 @@
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> 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; }
}
}
@@ -1,131 +0,0 @@
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);
}
}
@@ -1,136 +0,0 @@
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<EntityType<?>> 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> 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<UUID, String> 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<LivingEntity> 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; }
}
}
@@ -1,89 +0,0 @@
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<ParticleType<?>> 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<Colors> 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())); }
}
}
@@ -1,59 +0,0 @@
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;
}
}
@@ -1,85 +0,0 @@
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<MoonPhases> 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; }
}
}
@@ -1,100 +0,0 @@
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();
}
}
@@ -1,58 +0,0 @@
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()));
}
}
@@ -1,55 +0,0 @@
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<Boolean> 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<Boolean> listener) {
this.updateListener = listener;
if (updateListener != null) updateListener.accept(enabled); // actualizar por primera vez
}
}
@@ -1,90 +0,0 @@
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<E extends Enum<E>> extends AbstractSetting {
private final List<E> values;
private E defaultValue;
private E value;
private int index;
private Consumer<E> updateListener;
public EnumSetting(String name, String description, Class<E> 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<E> 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<E> listener) {
this.updateListener = listener;
if (updateListener != null) updateListener.accept(value);
}
}
@@ -1,72 +0,0 @@
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<Integer> 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<Integer> listener) {
this.updateListener = listener;
if (updateListener != null) updateListener.accept(key);
}
}
@@ -1,97 +0,0 @@
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<T> extends AbstractSetting {
private final List<T> options;
private Map<T, Boolean> values;
private Map<T, Boolean> defaultValues;
private Map<T, String> displayNames = null;
private Consumer<Map<T, Boolean>> updateListener;
public ListSetting(String name, String description, List<T> options, Map<T, Boolean> 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<T> options, Map<T, Boolean> initialValues, Map<T, String> 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<T, Boolean> getValues() {
return new HashMap<>(values);
}
public void setValues(Map<T, Boolean> values) {
this.values = new HashMap<>(values);
}
public Map<T, Boolean> getDefaultValues() {
return new HashMap<>(defaultValues);
}
public void setDefaultValues(Map<T, Boolean> 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<Map<T, Boolean>> listener) {
this.updateListener = listener;
if (updateListener != null) updateListener.accept(new HashMap<>(values));
}
public List<T> getOptions() {
return options;
}
public Map<T, String> getDisplayNames() {
return displayNames;
}
public String getDisplayName(T key) {
if (displayNames != null) return displayNames.get(key);
return key.toString();
}
}
@@ -1,95 +0,0 @@
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<Double> 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<Double> listener) {
this.updateListener = listener;
if (updateListener != null) updateListener.accept(value);
}
}
@@ -1,54 +0,0 @@
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<String> 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<String> listener) {
this.updateListener = listener;
if (updateListener != null) updateListener.accept(value);
}
}
@@ -1,303 +0,0 @@
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<SettingsFrame> 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<SettingsFrame> 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<SettingsFrame> 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);
}
}
@@ -1,110 +0,0 @@
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;
}
}
@@ -1,68 +0,0 @@
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);
}
}
@@ -1,85 +0,0 @@
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<E extends Enum<E>> extends SettingButton {
private final EnumSetting<E> setting;
public CycleButton(EnumSetting<E> 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<Text> 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<E> getSetting() {
return setting;
}
@Override
public void mouseReleased(double mouseX, double mouseY, int button) {
ClickGUI.INSTANCE.unselect(this);
}
}
@@ -1,119 +0,0 @@
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<T> extends SettingButton {
private final ListSetting<T> setting;
private final Module dummy;
private final Map<T, BooleanSetting> optionButtons = new HashMap<>();
public ListButton(ListSetting<T> 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<T> getSetting() {
return setting;
}
@Override
public void mouseReleased(double mouseX, double mouseY, int button) {
ClickGUI.INSTANCE.unselect(this);
}
}
@@ -1,74 +0,0 @@
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();
}
}
@@ -1,80 +0,0 @@
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;
}
}
@@ -1,88 +0,0 @@
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;
}
}
@@ -1,55 +0,0 @@
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;
}
}
@@ -1,85 +0,0 @@
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<SettingButton> 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);
}
}
@@ -1,243 +0,0 @@
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<SettingButton> settingButtons = new ArrayList<>();
public List<SettingButton> 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<String> 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<String> wrapDescription(String text, int maxWidth) {
List<String> 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<SettingButton> getButtons() {
return settingButtons;
}
public void updateRenderY(int scrollOffset) {
renderY = y - scrollOffset;
}
}
Loaded 100 of 585 files, more files were not shown because too many files have changed in this diff. Show more