Compare commits

...
17 Commits
Author SHA1 Message Date
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
retuci0 8891a57c7c v1.4 2025-10-12 13:00:18 +02:00
retuci0 e358b142c6 v1.3 2025-09-28 14:35:16 +02:00
retuci0 e7d872d75e mejoras a interfaz 1 2025-09-04 12:35:36 +02:00
retuci0 589279342d actualizar README 2025-09-01 18:43:45 +02:00
retuci0 054702999b v1.2 2025-09-01 18:22:39 +02:00
retuci0 ec7ff3a058 v1.1 2025-08-27 19:24:04 +02:00
302 changed files with 13715 additions and 1501 deletions

No files matched your search

+5 -1
View File
@@ -39,4 +39,8 @@ replay_*.log
*.hprof
*.jfr
todo.txt
# otros
todo.txt
cambios.md
remappedSrc/
+87
View File
@@ -0,0 +1,87 @@
# jenny's mod 2 100% real
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)
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.10`; Fabric `0.138.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`)
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)
## 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 atajos de teclado
## interfaz
- clic izquierdo para activar / desactivar módulos
- clic derecho para abrir sus ajustes
- clic izquierdo + arrastrar para mover marcos
- clic derecho en la cabeza del marco para expandirlo / contraerlo o para cerrarlo
- clic izquierdo sobre ajustes para modificarlos
- shift + clic derecho sobre ajustes para restablecerlos
- posiciona el puntero del ratón sobre un módulo o ajuste para leer su descripción
### protips
- shift mientras pasas el puntero por encima de un ajuste de modos para ver los modos disponibles
- clic derecho para ciclar hacia atrás en ajustes de modo
- usa la rueda del ratón para mover la interfaz verticalmente
- shift + rueda del ratón para mover todos los marcos a un rango visible en la pantalla
## capturas
<img src="screenshots/ui.png" alt="interfaz">
<img src="screenshots/nametags.png" alt="nametags mostrando daño de un tridente">
<img src="screenshots/chatplus.png" alt="chatplus y capturas en uso">
<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
sí por favor
## licencia
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
+5 -2
View File
@@ -24,11 +24,14 @@ dependencies {
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}"
}
loom {
accessWidenerPath = file("src/main/resources/camtweaks.accesswidener")
}
processResources {
inputs.property "version", project.version
+29
View File
@@ -0,0 +1,29 @@
# v2.1 (roto)
## novedades
- actualizado a la 1.21.11 (maomeno)
### adiciones
- categorías de módulos: ahora puedes buscar "cámara", "jugador", "mundo", "renderizado", "red", "cliente" o "misc" para que se filtren los módulos de esas categorías, respectivamente
#### módulos nuevos:
- muletas: hace te no te caigas (de bloques), como cuando estás agachado, pero sin agacharte
### arreglos / mejoras
- ahora ya puedes escribir espacios en la barra de búsqueda
- ahora se ignoran las tildes al buscar en la barra de búsqueda
- aviso de baja dur. ya no te avisa al reparar objetos dañados por debajo del límite
- creo que cielo custom ya funciona por completo (las fases lunares)
## problemas reconocidos
- muchos, pero repórtalos en la página de problemas si quieres para que queden bien registrados
- de esta actualización:
- superposición de daño no funciona porque no lo he podido actualizar porque han cambiado cosas relacionadas a la renderización
- la renderización de líneas (no rellenos) está rota, por el mismo motivo
- por el mismo motivo, destello de enchants no funciona
- minar sin interrupción no funciona
+11 -3
View File
@@ -1,3 +1,11 @@
meteor client
oyvey client (1.21 port by mioclient)
lennyboi (youtube)
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
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 :)
+8 -13
View File
@@ -1,18 +1,13 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx1G
org.gradle.parallel=true
# Fabric Properties
# check these on https://fabricmc.net/develop
minecraft_version=1.21.6
yarn_mappings=1.21.6+build.1
loader_version=0.17.2
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.0.0
fabric_api_version=0.140.2+1.21.11
mod_version=2.1
maven_group=me.retucio
archives_base_name=camtweaks
# Dependencies
fabric_version=0.128.2+1.21.6
archives_base_name=camtweaks
Binary file not shown.

After

Width:  |  Height:  |  Size: 864 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 915 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 KiB

+2 -2
View File
@@ -1,8 +1,8 @@
pluginManagement {
repositories {
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
name = "Fabric"
url = "https://maven.fabricmc.net/"
}
mavenCentral()
gradlePluginPortal()
BIN
View File
Binary file not shown.
@@ -1,61 +1,158 @@
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.settings.*;
import net.fabricmc.api.ModInitializer;
import me.retucio.camtweaks.module.modules.client.HUD;
import me.retucio.camtweaks.ui.screen.ClickGUI;
import me.retucio.camtweaks.ui.hud.HudEditorScreen;
import me.retucio.camtweaks.ui.hud.HudRenderer;
import me.retucio.camtweaks.ui.widgets.buttons.settings.BindButton;
import me.retucio.camtweaks.ui.widgets.buttons.SettingButton;
import me.retucio.camtweaks.ui.widgets.buttons.settings.TextButton;
import me.retucio.camtweaks.ui.widgets.frames.settings.ClientSettingsFrame;
import me.retucio.camtweaks.ui.widgets.frames.SettingsFrame;
import me.retucio.camtweaks.ui.widgets.Button;
import me.retucio.camtweaks.util.*;
import me.retucio.camtweaks.util.render.DrawUtil;
import me.retucio.camtweaks.util.render.RenderUtil;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.SharedConstants;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ChatScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.AbstractCommandBlockScreen;
import net.minecraft.client.gui.screen.ingame.AbstractSignEditScreen;
import net.minecraft.client.gui.screen.ingame.AnvilScreen;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.lwjgl.glfw.GLFW;
public class CameraTweaks implements ModInitializer {
public class CameraTweaks implements ClientModInitializer {
// cosas necesarias
public static final String MOD_ID = "camtweaks";
public static final CameraTweaks INSTANCE = new CameraTweaks();
public static final Logger LOGGER = LogManager.getLogger(CameraTweaks.class);
public static final EventBus EVENT_BUS = new EventBus();
public static final MinecraftClient mc = MinecraftClient.getInstance();
public static final Logger LOGGER = LogManager.getLogger(CameraTweaks.class);
public static MinecraftClient mc;
// id y versión
public static final String MOD_ID = "camtweaks";
public static final String MOD_VERSION;
static {
MOD_VERSION = FabricLoader.getInstance().getModContainer(MOD_ID)
.orElseThrow()
.getMetadata()
.getVersion()
.getFriendlyString();
}
private Screen prevScreen;
public static boolean settingsApplied = false;
// managers
public static ModuleManager moduleManager = new ModuleManager(EVENT_BUS);
public static CommandManager commandManager = new CommandManager();
@Override
public void onInitialize() {}
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();
ConfigManager.load();
EVENT_BUS.register(this);
EVENT_BUS.register(HudRenderer.class);
EVENT_BUS.register(ChatUtil.class);
EVENT_BUS.register(DrawUtil.class);
EVENT_BUS.register(EntityUtil.class);
EVENT_BUS.register(InventoryUtil.class);
EVENT_BUS.register(MiscUtil.class);
EVENT_BUS.register(NetworkUtil.class);
EVENT_BUS.register(RenderUtil.class);
Lists.init();
ModuleManager.INSTANCE = new ModuleManager();
EVENT_BUS.post(new LoadModuleManagerEvent());
CommandManager.INSTANCE = new CommandManager();
EVENT_BUS.post(new LoadCommandManagerEvent());
ClickGUI.INSTANCE = new ClickGUI();
HudEditorScreen.INSTANCE = new HudEditorScreen();
EVENT_BUS.post(new LoadClickGUIEvent());
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() {
if (!settingsApplied
&& ConfigManager.getConfig() != null
&& !ConfigManager.hasLoaded()) {
ConfigManager.applyConfig();
settingsApplied = true;
}
ModuleManager.INSTANCE.getEnabledModules().forEach(Module::onTick);
}
// se ejecuta cada vez que se presiona una tecla
public void onKeyPress(int key, int action) {
moduleManager.getEnabledModules().forEach(module -> module.onKey(key, action));
if (key == GLFW.GLFW_KEY_F3) return; // prevenir activación de módulos al usar combinaciones de F3
ModuleManager.INSTANCE.getEnabledModules().forEach(module -> module.onKey(key, action));
boolean anyFocused = isAnySettingButtonFocused();
boolean anyFocused = isAnySettingButtonFocused() || ClickGUI.INSTANCE.getSearchBar().isFocused();
ClickGUI.INSTANCE.setAnyFocused(anyFocused);
if (action == GLFW.GLFW_PRESS) {
handleModuleToggle(key, anyFocused);
if (action != GLFW.GLFW_RELEASE) {
if (BindCommand.onKeyPress(key)) return;
if (action == GLFW.GLFW_PRESS) {
handleModuleToggle(key, anyFocused);
handleClickGUIKey(key, anyFocused);
handleHudEditorKey(key, anyFocused);
}
handleSettingButtonsKey(key, action);
handleClickGUIKey(key, anyFocused);
BindCommand.onKeyPress(key);
} else if (action == GLFW.GLFW_RELEASE && !anyFocused) {
} else if (!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()) {
for (SettingsFrame sf : ClickGUI.INSTANCE.getSettingsFrames())
for (Button sb : sf.getButtons())
if ((sb instanceof BindButton b && b.isFocused()) || (sb instanceof TextButton t && t.isFocused()))
return true;
}
}
return false;
}
@@ -63,8 +160,8 @@ public class CameraTweaks implements ModInitializer {
private void handleModuleToggle(int key, boolean anyFocused) {
if (mc.currentScreen != null && mc.currentScreen != ClickGUI.INSTANCE) return;
for (Module module : moduleManager.getModules()) {
if (key != module.getKey() || anyFocused) continue;
for (Module module : ModuleManager.INSTANCE.getModules()) {
if (key != module.getKey() || anyFocused || KeyUtil.isKeyDown(GLFW.GLFW_KEY_F3)) continue; // evitar interrumpir combinaciones de teclas del F3
if (module.shouldToggleOnBindRelease() && !module.isEnabled())
module.setEnabled(true);
@@ -77,20 +174,42 @@ public class CameraTweaks implements ModInitializer {
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);
if (sb instanceof BindButton bb) bb.onKey(key, action);
if (sb instanceof TextButton tb) tb.onKey(key, action);
}
}
}
// maneja la lógica de apertura de la interfaz
private void handleClickGUIKey(int key, boolean anyFocused) {
if (key != ClickGUISettingsFrame.guiSettings.getKey() || anyFocused) return;
if (key != ClientSettingsFrame.guiSettings.getKey() || anyFocused || isOnTypingScreen())
return;
// al parecer esto hace que con la tecla de la interfaz puedas ir cambiando de splash text en la pantalla del título
// pero me ha hecho gracia así que así se queda
if (mc.currentScreen != ClickGUI.INSTANCE) {
prevScreen = mc.currentScreen;
mc.setScreen(ClickGUI.INSTANCE);
} else {
ClickGUI.INSTANCE.close();
mc.setScreen(prevScreen);
}
}
// manejar la lógica de apertura del editor de elementos del hud, con la misma lógica que handleClickGUIKey()
private void handleHudEditorKey(int key, boolean anyFocused) {
HUD hud = ModuleManager.INSTANCE.getModuleByClass(HUD.class);
if (key != hud.editorKey.getKey() || anyFocused || isOnTypingScreen()) return;
if (mc.currentScreen != HudEditorScreen.INSTANCE) {
if (!hud.isEnabled()) {
ChatUtil.warn("HUD está desactivado, lumbreras");
return;
}
prevScreen = mc.currentScreen;
mc.setScreen(HudEditorScreen.INSTANCE);
} else {
HudEditorScreen.INSTANCE.close();
mc.setScreen(prevScreen);
}
}
@@ -99,16 +218,24 @@ public class CameraTweaks implements ModInitializer {
private void handleModuleRelease(int key) {
if (mc.currentScreen != null && mc.currentScreen != ClickGUI.INSTANCE) return;
for (Module module : moduleManager.getEnabledModules()) {
if (module.shouldToggleOnBindRelease() && key == module.getKey()) {
for (Module module : ModuleManager.INSTANCE.getEnabledModules())
if (module.shouldToggleOnBindRelease() && key == module.getKey())
module.setEnabled(false);
}
}
}
// se ejecuta cada tick, es decir, 20 veces por segundo
public void onTick() {
if (mc.player == null) return;
moduleManager.getEnabledModules().forEach(Module::onTick);
private boolean isOnTypingScreen() {
return mc.currentScreen instanceof ChatScreen
|| mc.currentScreen instanceof AnvilScreen
|| mc.currentScreen instanceof AbstractSignEditScreen
|| mc.currentScreen instanceof AbstractCommandBlockScreen;
}
@SubscribeEvent
public void onStop(ShutdownEvent event) {
ConfigManager.save();
}
public static String getVersionName() {
return MOD_ID + "_v" + MOD_VERSION + "_" + SharedConstants.getGameVersion().name();
}
}
@@ -12,13 +12,12 @@ import net.minecraft.server.command.CommandManager;
import java.util.List;
import static me.retucio.camtweaks.CameraTweaks.commandManager;
public abstract class Command {
// utilizar los "registries" ya existentes de Brigadier para el autocompletado
protected static final CommandRegistryAccess REGISTRY_ACCESS = CommandManager.createRegistryAccess(BuiltinRegistries.createWrapperLookup());
protected static final int SUCCESS = com.mojang.brigadier.Command.SINGLE_SUCCESS;
protected static final MinecraftClient mc = MinecraftClient.getInstance();
private final String name, description;
@@ -66,7 +65,7 @@ public abstract class Command {
}
public String toString() {
return commandManager.getPrefix() + name;
return me.retucio.camtweaks.command.CommandManager.INSTANCE.getPrefix() + name;
}
public String toString(String... args) {
@@ -2,17 +2,24 @@ package me.retucio.camtweaks.command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.command.commands.*;
import me.retucio.camtweaks.event.SubscribeEvent;
import me.retucio.camtweaks.module.Module;
import net.minecraft.client.MinecraftClient;
import net.minecraft.command.CommandSource;
import java.lang.reflect.Method;
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<>();
@@ -26,10 +33,27 @@ public class CommandManager {
public static void registerCommands() {
addCommand(new BindCommand());
addCommand(new ToggleCommand());
addCommand(new SendCommand());
addCommand(new CopyScreenshotCommand());
addCommand(new EnderChestCommand());
addCommand(new GarbageCleanerCommand());
addCommand(new PeekCommand());
addCommand(new PrefixCommand());
addCommand(new PurgeCommand());
addCommand(new SaveScreenshotCommand());
addCommand(new SendCommand());
addCommand(new SpectateCommand());
addCommand(new ToggleCommand());
commands.sort(Comparator.comparing(Command::getName));
for (Command command : commands) {
for (Method method : command.getClass().getDeclaredMethods()) {
if (method.isAnnotationPresent(SubscribeEvent.class)) {
CameraTweaks.EVENT_BUS.register(command);
break;
}
}
}
}
public static void addCommand(Command command) {
@@ -39,13 +63,17 @@ public class CommandManager {
}
public static void dispatch(String message) throws CommandSyntaxException {
dispatcher.execute(message, mc.getNetworkHandler().getCommandSource());
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 (Command command : commands) {
if (command.getName().equals(name)) return command;
for (String alias : command.getAliases())
if (alias.equals(name)) return command;
}
return null;
}
@@ -0,0 +1,208 @@
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.util.EntityUtil;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.text.Text;
import javax.swing.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Pattern;
// para autocompletar entidades
import static me.retucio.camtweaks.CameraTweaks.mc;
public class EntityArgumentType implements ArgumentType<Entity> {
public static final EntityArgumentType INSTANCE = new EntityArgumentType();
private static final DynamicCommandExceptionType NO_SUCH_ENTITY = new DynamicCommandExceptionType(
name -> Text.literal("Entidad \"" + name + "\" no encontrada"));
private static final Collection<String> EXAMPLES = List.of(
"AdlerHitdolf",
"@p"
);
private static final Pattern UUID_PATTERN = Pattern.compile(
"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
);
private EntityArgumentType() {}
@Override
public Entity parse(StringReader reader) throws CommandSyntaxException {
String argument = reader.readString();
if (mc.world == null)
throw NO_SUCH_ENTITY.create(argument);
if (argument.startsWith("@"))
return parseSelector(argument);
if (isUUID(argument)) {
UUID uuid = UUID.fromString(argument);
return findEntityByUUID(uuid);
}
return findPlayerByName(argument);
}
private boolean isUUID(String input) {
return UUID_PATTERN.matcher(input).matches();
}
private Entity parseSelector(String selector) throws CommandSyntaxException {
if (mc.player == null) throw NO_SUCH_ENTITY.create(selector);
return switch (selector.toLowerCase()) {
case "@p" ->
findNearestPlayer();
case "@r" ->
findRandomPlayer();
case "@s" ->
mc.player;
case "@a" -> throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument()
.createWithContext(new StringReader(selector));
default -> {
if (selector.startsWith("@e"))
yield parseEntitySelector(selector);
else if (selector.startsWith("@p") && selector.length() > 2)
yield parsePlayerSelector(selector);
throw NO_SUCH_ENTITY.create(selector);
}
};
}
private Entity findNearestPlayer() throws CommandSyntaxException {
PlayerEntity nearest = null;
double nearestDistance = Double.MAX_VALUE;
for (PlayerEntity player : mc.world.getPlayers()) {
if (player == mc.player) continue;
double distance = mc.player.squaredDistanceTo(player);
if (distance < nearestDistance) {
nearestDistance = distance;
nearest = player;
}
}
if (nearest == null)
throw NO_SUCH_ENTITY.create("@p");
return nearest;
}
private Entity findRandomPlayer() throws CommandSyntaxException {
List<PlayerEntity> players = new ArrayList<>(mc.world.getPlayers());
if (players.isEmpty()) throw NO_SUCH_ENTITY.create("@r");
players.remove(mc.player);
if (players.isEmpty()) return mc.player;
Random random = new Random();
return players.get(random.nextInt(players.size()));
}
private Entity parseEntitySelector(String selector) throws CommandSyntaxException {
if (selector.equals("@e")) {
List<Entity> entities = new ArrayList<>();
for (Entity entity : mc.world.getEntities())
if (!(entity instanceof PlayerEntity))
entities.add(entity);
if (entities.isEmpty()) throw NO_SUCH_ENTITY.create(selector);
Random random = new Random();
return entities.get(random.nextInt(entities.size()));
}
if (selector.startsWith("@e[type=")) {
String type = selector.substring(8, selector.length() - 1);
return findEntityByType(type);
}
throw NO_SUCH_ENTITY.create(selector);
}
private Entity parsePlayerSelector(String selector) throws CommandSyntaxException {
return findNearestPlayer();
}
private Entity findEntityByType(String type) throws CommandSyntaxException {
List<Entity> matchingEntities = new ArrayList<>();
for (Entity entity : mc.world.getEntities()) {
String entityType = entity.getType().getTranslationKey();
if (entityType.contains(type.toLowerCase().replace("minecraft:", "")))
matchingEntities.add(entity);
}
if (matchingEntities.isEmpty()) throw NO_SUCH_ENTITY.create(type);
Entity nearest = null;
double nearestDistance = Double.MAX_VALUE;
for (Entity entity : matchingEntities) {
double distance = mc.player.squaredDistanceTo(entity);
if (distance < nearestDistance) {
nearestDistance = distance;
nearest = entity;
}
}
return nearest;
}
private Entity findEntityByUUID(UUID uuid) throws CommandSyntaxException {
for (Entity entity : mc.world.getEntities())
if (entity.getUuid().equals(uuid))
return entity;
throw NO_SUCH_ENTITY.create(uuid.toString());
}
private PlayerEntity findPlayerByName(String name) throws CommandSyntaxException {
for (PlayerEntity player : mc.world.getPlayers())
if (player.getName().getString().equalsIgnoreCase(name))
return player;
throw NO_SUCH_ENTITY.create(name);
}
@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
if (mc.world != null)
for (PlayerEntity player : mc.world.getPlayers())
builder.suggest(player.getName().getString());
builder.suggest("@p");
builder.suggest("@r");
builder.suggest("@s");
Entity lookingAt = EntityUtil.getEntityPlayerIsLookingAt();
if (lookingAt != null)
builder.suggest(lookingAt.getUuid().toString());
return builder.buildFuture();
}
@Override
public Collection<String> getExamples() {
return EXAMPLES;
}
public static Entity get(CommandContext<?> context, String name) {
return context.getArgument(name, Entity.class);
}
}
@@ -8,34 +8,34 @@ import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.module.ModuleManager;
import net.minecraft.command.CommandSource;
import net.minecraft.text.Text;
import java.util.Collection;
import java.util.concurrent.CompletableFuture;
import static me.retucio.camtweaks.CameraTweaks.moduleManager;
// para autocompletar nombres de módulos (los espacios se cambian por guiones bajos)
public class ModuleArgumentType implements ArgumentType<Module> {
public static final ModuleArgumentType INSTANCE = new ModuleArgumentType();
private static final DynamicCommandExceptionType unknownModuleE = new DynamicCommandExceptionType(
private static final DynamicCommandExceptionType UNKNOWN_MODULE = new DynamicCommandExceptionType(
name -> Text.literal("módulo \"" + name + "\" no encontrado"));
private static final Collection<String> examples = moduleManager.getModules()
.stream().limit(3).map(Module::getName).toList();
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();
Module module = moduleManager.getModuleByName(argument);
if (module == null) throw unknownModuleE.create(argument);
String argument = reader.readString().replace("_", " ");
Module module = ModuleManager.INSTANCE.getModuleByName(argument);
if (module == null) throw UNKNOWN_MODULE.create(argument);
return module;
}
@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
return CommandSource.suggestMatching(moduleManager.getModules().stream().map(Module::getName), builder);
return CommandSource.suggestMatching(ModuleManager.INSTANCE.getModules().stream().map(module -> module.getName().replace(" ", "_")), builder);
}
@Override
@@ -0,0 +1,61 @@
package me.retucio.camtweaks.command.args;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.command.CommandSource;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.text.Text;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import static me.retucio.camtweaks.CameraTweaks.mc;
// para autocompletar nombres de jugadores
public class PlayerArgumentType implements ArgumentType<PlayerEntity> {
public static final PlayerArgumentType INSTANCE = new PlayerArgumentType();
private static final DynamicCommandExceptionType NO_SUCH_PLAYER = new DynamicCommandExceptionType(name -> Text.literal("Player with name " + name + " doesn't exist."));
private static final Collection<String> EXAMPLES = List.of("retucio", "prepucio", "postpucio", "pucio", "adler hitdolf");
private PlayerArgumentType() {}
@Override
public PlayerEntity parse(StringReader reader) throws CommandSyntaxException {
String argument = reader.readString();
PlayerEntity playerEntity = null;
for (PlayerEntity p : mc.world.getPlayers())
if (p.getName().getString().equalsIgnoreCase(argument)) {
playerEntity = p;
break;
}
if (playerEntity == null) throw NO_SUCH_PLAYER.create(argument);
return playerEntity;
}
@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
return CommandSource.suggestMatching(mc.world.getPlayers().stream().map(
abstractClientPlayerEntity -> abstractClientPlayerEntity.getName().getString()), builder);
}
@Override
public Collection<String> getExamples() {
return EXAMPLES;
}
public static PlayerEntity get(CommandContext<?> context) {
return context.getArgument("jugador", PlayerEntity.class);
}
}
@@ -7,16 +7,13 @@ import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.module.settings.KeySetting;
import me.retucio.camtweaks.util.ChatUtil;
import me.retucio.camtweaks.util.KeyUtil;
import net.minecraft.client.MinecraftClient;
import net.minecraft.command.CommandSource;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import static me.retucio.camtweaks.CameraTweaks.moduleManager;
// asignar una tecla a un módulo, lógica similar a BindButton
public class BindCommand extends Command {
// The module currently waiting for a key press
private static Module listeningModule = null;
public BindCommand() {
@@ -29,27 +26,30 @@ public class BindCommand extends Command {
.then(argument("módulo", ModuleArgumentType.INSTANCE)
.executes(ctx -> {
Module module = ctx.getArgument("módulo", Module.class);
listeningModule = module;
ChatUtil.info("presiona una tecla para asignarla al módulo " + module.getName());
ChatUtil.info("presiona una tecla para asignarla al módulo " + Formatting.GREEN + module.getName());
return SUCCESS;
})
.then(literal("reset").executes(ctx -> {
Module module = ctx.getArgument("módulo", Module.class);
module.getBind().reset();
ChatUtil.info("tecla para el módulo " + Formatting.GREEN + module.getName() + " restablecida a " + Formatting.AQUA + KeyUtil.getKeyName(module.getKey()));
return SUCCESS;
}))
);
}
public static void onKeyPress(int key) {
if (listeningModule != null) {
KeySetting bind = listeningModule.getBind();
if (bind != null)
bind.setKey(key);
public static boolean onKeyPress(int key) {
if (listeningModule == null) return false;
KeySetting bind = listeningModule.getBind();
if (bind != null) bind.setKey(key);
ChatUtil.info(
Text.of("la tecla " + Formatting.AQUA + KeyUtil.getKeyName(key) + Formatting.RESET +
" ha sido asignada al módulo " + Formatting.GREEN + listeningModule.getName())
);
ChatUtil.info(
Text.of("la tecla " + Formatting.AQUA + KeyUtil.getKeyName(key) + Formatting.RESET +
" ha sido asignada al módulo " + Formatting.GREEN + listeningModule.getName())
);
listeningModule = null;
}
listeningModule = null;
return true;
}
}
@@ -0,0 +1,26 @@
package me.retucio.camtweaks.command.commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.camtweaks.command.Command;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.misc.ScreenshotPlus;
import net.minecraft.command.CommandSource;
// se usa principalmente para el módulo ScreenshotPlus, pero también se puede usar sin él supongo
public class CopyScreenshotCommand extends Command {
public CopyScreenshotCommand() {
super("copiarcaptura", "copia la captura más reciente al portapapeles");
}
@Override
public void build(LiteralArgumentBuilder<CommandSource> builder) {
builder.executes(ctx -> {
ScreenshotPlus screenshotPlus = ModuleManager.INSTANCE.getModuleByClass(ScreenshotPlus.class);
if (screenshotPlus.getScreenshot() != null) mc.execute(screenshotPlus::copyScreenshot);
return SUCCESS;
});
}
}
@@ -0,0 +1,47 @@
package me.retucio.camtweaks.command.commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.command.Command;
import me.retucio.camtweaks.event.SubscribeEvent;
import me.retucio.camtweaks.event.events.TickEvent;
import me.retucio.camtweaks.ui.screen.PreviewScreen;
import me.retucio.camtweaks.util.ChatUtil;
import me.retucio.camtweaks.util.InventoryUtil;
import net.minecraft.command.CommandSource;
// accede a los contenidos de tu enderchest
public class EnderChestCommand extends Command {
private boolean shouldOpenEchest = false;
public EnderChestCommand() {
super("echest", "muestra el contenido de tu enderchest (solo de ver)", "ec", "enderchest");
}
@Override
public void build(LiteralArgumentBuilder<CommandSource> builder) {
builder.executes(ctx -> {
mc.execute(() -> {
if (mc.player == null) return;
if (InventoryUtil.getEchestInv() == null) {
ChatUtil.warn("necesitas abrir un enderchest una vez primero");
return;
}
shouldOpenEchest = true;
});
return SUCCESS;
});
}
@SubscribeEvent
public void onTick(TickEvent.Post event) {
if (shouldOpenEchest) {
shouldOpenEchest = false;
if (InventoryUtil.getEchestInv() != null)
mc.setScreen(new PreviewScreen(InventoryUtil.getEchestInv(), null));
}
}
}
@@ -0,0 +1,23 @@
package me.retucio.camtweaks.command.commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.camtweaks.command.Command;
import me.retucio.camtweaks.util.ChatUtil;
import net.minecraft.command.CommandSource;
import net.minecraft.text.Text;
public class GarbageCleanerCommand extends Command {
public GarbageCleanerCommand() {
super("gc", "limpia la ram mediante el recolector de basura (gc)", "garbagecollect");
}
@Override
public void build(LiteralArgumentBuilder<CommandSource> builder) {
builder.executes(context -> {
System.gc();
ChatUtil.info(Text.of("basura recolectada"));
return SUCCESS;
});
}
}
@@ -0,0 +1,26 @@
package me.retucio.camtweaks.command.commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.camtweaks.command.Command;
import me.retucio.camtweaks.command.args.PlayerArgumentType;
import me.retucio.camtweaks.util.MiscUtil;
import net.minecraft.client.gui.screen.ingame.InventoryScreen;
import net.minecraft.command.CommandSource;
// comando que debería de mostrar el inventario de un jugador, pero por cómo funcionan los servers, solo te deja ver el ítem que tenga en la mano
public class PeekCommand extends Command {
public PeekCommand() {
super("inventario", "cotillea el inventario de otro jugador", "invsee", "peek", "inv");
}
@Override
public void build(LiteralArgumentBuilder<CommandSource> builder) {
builder
.then(argument("jugador", PlayerArgumentType.INSTANCE)
.executes(ctx -> {
MiscUtil.screen = new InventoryScreen(PlayerArgumentType.get(ctx));
return SUCCESS;
}));
}
}
@@ -3,12 +3,13 @@ package me.retucio.camtweaks.command.commands;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.camtweaks.command.Command;
import me.retucio.camtweaks.ui.settings.ClickGUISettingsFrame;
import me.retucio.camtweaks.ui.widgets.frames.settings.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() {
@@ -20,7 +21,7 @@ public class PrefixCommand extends Command {
builder
.then(argument("prefijo", StringArgumentType.word()).executes(ctx -> {
String prefix = ctx.getArgument("prefijo", String.class);
ClickGUISettingsFrame.guiSettings.commandPrefix.setValue(prefix);
ClientSettingsFrame.guiSettings.commandPrefix.setValue(prefix);
ChatUtil.info(Text.literal("prefijo cambiado a " + Formatting.AQUA + prefix));
return SUCCESS;
}));
@@ -0,0 +1,40 @@
package me.retucio.camtweaks.command.commands;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.camtweaks.command.Command;
import me.retucio.camtweaks.util.interfaces.IChatHud;
import net.minecraft.client.gui.hud.ChatHud;
import net.minecraft.client.gui.hud.ChatHudLine;
import net.minecraft.command.CommandSource;
import java.util.List;
public class PurgeCommand extends Command {
public PurgeCommand() {
super("purgar", "elimina mensajes del chat", "purge");
}
@Override
public void build(LiteralArgumentBuilder<CommandSource> builder) {
builder.then(argument("cantidad", IntegerArgumentType.integer(1))
.executes(context -> {
int amount = IntegerArgumentType.getInteger(context, "cantidad");
purgeMessages(amount);
return 1;
})
);
}
private void purgeMessages(int amount) {
ChatHud chatHud = mc.inGameHud.getChatHud();
synchronized (chatHud) {
List<ChatHudLine.Visible> visibleMessages = ((IChatHud) chatHud).smegma$getVisibleMessages();
int toRemove = Math.min(amount, visibleMessages.size());
for (int i = 0; i < toRemove; i++)
visibleMessages.removeFirst();
}
}
}
@@ -0,0 +1,37 @@
package me.retucio.camtweaks.command.commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.camtweaks.command.Command;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.misc.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;
});
}
}
@@ -3,9 +3,19 @@ package me.retucio.camtweaks.command.commands;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.camtweaks.command.Command;
import me.retucio.camtweaks.mixin.accessor.ClientPlayNetworkHandlerAccessor;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.command.CommandSource;
import net.minecraft.network.encryption.NetworkEncryptionUtils;
import net.minecraft.network.message.LastSeenMessagesCollector;
import net.minecraft.network.message.MessageBody;
import net.minecraft.network.message.MessageSignatureData;
import net.minecraft.network.packet.c2s.play.ChatMessageC2SPacket;
import net.minecraft.text.Text;
import java.time.Instant;
// uso principal: protección de coordenadas de ChatPlus, que ni siquiera funciona
public class SendCommand extends Command {
public SendCommand() {
@@ -14,13 +24,35 @@ public class SendCommand extends Command {
@Override
public void build(LiteralArgumentBuilder<CommandSource> builder) {
builder
.then(argument("mensaje", StringArgumentType.greedyString())
.executes(ctx -> {
if (mc.player == null) return 0;
mc.player.sendMessage(Text.of(ctx.getArgument("mensaje", String.class)), false);
return SUCCESS;
})
);
builder.then(argument("message", StringArgumentType.greedyString()).executes(context -> {
String message = context.getArgument("message", String.class);
if (message != null && !message.isEmpty()) {
Instant instant = Instant.now();
long salt = NetworkEncryptionUtils.SecureRandomUtil.nextLong();
ClientPlayNetworkHandler handler = mc.getNetworkHandler();
// obtener últimos mensajes vistos para la firma
LastSeenMessagesCollector.LastSeenMessages lastSeenMessages =
((ClientPlayNetworkHandlerAccessor) handler).getLastSeenMessagesCollector().collect();
// empacar firma para un chat seguro
MessageSignatureData messageSignatureData =
((ClientPlayNetworkHandlerAccessor) handler).getMessagePacker().pack(
new MessageBody(message, instant, salt, lastSeenMessages.lastSeen())
);
// enviar paquete para enviar mensaje
handler.sendPacket(new ChatMessageC2SPacket(
message,
instant,
salt,
messageSignatureData,
lastSeenMessages.update()
));
}
return SUCCESS;
}));
}
}
}
@@ -0,0 +1,50 @@
package me.retucio.camtweaks.command.commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.camtweaks.command.Command;
import me.retucio.camtweaks.command.args.EntityArgumentType;
import me.retucio.camtweaks.event.SubscribeEvent;
import me.retucio.camtweaks.event.events.KeyEvent;
import me.retucio.camtweaks.util.EntityUtil;
import me.retucio.camtweaks.util.MiscUtil;
import net.minecraft.command.CommandSource;
import net.minecraft.entity.Entity;
import org.lwjgl.glfw.GLFW;
public class SpectateCommand extends Command {
public SpectateCommand() {
super("espectar", "te permite adquirir el punto de vista de una entidad", "spectate", "spec");
}
@Override
public void build(LiteralArgumentBuilder<CommandSource> builder) {
builder
.executes(ctx -> { // If no argument, use the entity player is looking at
mc.execute(() -> {
Entity target = EntityUtil.getEntityPlayerIsLookingAt();
if (target != null)
mc.setCameraEntity(target);
});
return SUCCESS;
})
.then(argument("entidad", EntityArgumentType.INSTANCE)
.executes(ctx -> {
Entity entity = EntityArgumentType.get(ctx, "entidad");
if (mc.player != null && entity != null) {
mc.setCameraEntity(entity);
}
return SUCCESS;
})
);
}
@SubscribeEvent
public void onKey(KeyEvent event) {
if (mc.getCameraEntity() != mc.player && mc.currentScreen == null
&& event.getKey() == GLFW.GLFW_KEY_ESCAPE && event.getAction() != GLFW.GLFW_RELEASE ) {
event.cancel();
mc.setCameraEntity(mc.player);
}
}
}
@@ -4,10 +4,9 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.camtweaks.command.Command;
import me.retucio.camtweaks.command.args.ModuleArgumentType;
import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.module.ModuleManager;
import net.minecraft.command.CommandSource;
import static me.retucio.camtweaks.CameraTweaks.moduleManager;
// porque usar el ratón es más lento que escribir, a menos que tengas toque con el teclado como yo
public class ToggleCommand extends Command {
@@ -21,14 +20,14 @@ public class ToggleCommand extends Command {
.then(literal("todos")
.then(literal("on")
.executes(ctx -> {
moduleManager.getModules().forEach(module -> {
ModuleManager.INSTANCE.getModules().forEach(module -> {
if (!module.isEnabled()) module.toggle();
}); return SUCCESS;
})
)
.then(literal("off")
.executes(ctx -> {
moduleManager.getEnabledModules().forEach(Module::toggle);
ModuleManager.INSTANCE.getEnabledModules().forEach(Module::toggle);
return SUCCESS;
})
)
@@ -0,0 +1,120 @@
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.screen.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<>();
// id del elemento del hud -> posición (x, y)
public Map<String, int[]> hudPositions = new HashMap<>();
// id del elemento del hud -> true: visible / false: no visible
public Map<String, Boolean> hudVisibilities = new HashMap<>();
// posición de la barra de búsqueda (x, y)
public int[] searchBarPosition = new int[]{340, 16};
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.getConfigValues(); break;
case ColorSetting c: value = c.getConfigValue(); break;
case OptionSetting o: value = o.getIndex(); 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().getX(), event.getFrame().getY()});
ConfigManager.save();
}
@SubscribeEvent
public void onExtendModuleFrame(ModuleFrameEvent.Extend event) {
extendableFrames.put("M", new FrameData(
ClickGUI.INSTANCE.getModulesFrame().getX(),
ClickGUI.INSTANCE.getModulesFrame().getY(),
ClickGUI.INSTANCE.getModulesFrame().extended));
}
@SubscribeEvent
public void onMoveModuleFrame(ModuleFrameEvent.Move event) {
extendableFrames.replace("M", new FrameData(
ClickGUI.INSTANCE.getModulesFrame().getX(),
ClickGUI.INSTANCE.getModulesFrame().getY(),
ClickGUI.INSTANCE.getModulesFrame().extended));
}
@SubscribeEvent
public void onExtendGUISettingsFrame(GUISettingsFrameEvent.Extend event) {
extendableFrames.put("S", new FrameData(
ClickGUI.INSTANCE.getGuiSettingsFrame().getX(),
ClickGUI.INSTANCE.getGuiSettingsFrame().getY(),
ClickGUI.INSTANCE.getGuiSettingsFrame().extended));
}
@SubscribeEvent
public void onMoveGUISettingsFrame(GUISettingsFrameEvent.Move event) {
extendableFrames.replace("S", new FrameData(
ClickGUI.INSTANCE.getGuiSettingsFrame().getX(),
ClickGUI.INSTANCE.getGuiSettingsFrame().getY(),
ClickGUI.INSTANCE.getGuiSettingsFrame().extended));
}
public record FrameData(int x, int y, boolean extended) {}
}
@@ -0,0 +1,321 @@
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.widgets.frames.ModuleFrame;
import me.retucio.camtweaks.ui.screen.ClickGUI;
import me.retucio.camtweaks.ui.widgets.frames.settings.ClientSettingsFrame;
import me.retucio.camtweaks.ui.widgets.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 boolean loaded = false;
private static ClientConfig config = null;
// ------------------ MÉTODOS PRINCIPALES ------------------
// guardar configuraciones
public static void save() {
ensureConfig();
try (FileWriter writer = new FileWriter(CONFIG_FILE)) {
GSON.toJson(config, writer);
CameraTweaks.LOGGER.info("ajustes guardados");
} catch (IOException e) {
CameraTweaks.LOGGER.error("error al guardar ajustes", e);
}
}
// cargar configuraciones
public static void load() {
CameraTweaks.LOGGER.info("cargando ajustes...");
if (!CONFIG_FILE.exists()) {
ensureConfig();
save();
return;
}
try (FileReader reader = new FileReader(CONFIG_FILE)) {
config = GSON.fromJson(reader, ClientConfig.class);
CameraTweaks.LOGGER.info("ajustes cargados");
} catch (IOException e) {
CameraTweaks.LOGGER.error("no se pudieron cargar los ajustes, usando ajustes por defecto", e);
ensureConfig();
}
}
// aplicar configuraciones cargadas
public static void applyConfig() {
if (!shouldApply()) return;
applyModuleStates();
applyModuleSettings();
applySettingsFrames();
applySearchBarPosition();
applyGuiSettings();
applyExtendableFrames();
loaded = true;
CameraTweaks.LOGGER.info("ajustes aplicados");
}
// obtener configuración actual
public static ClientConfig getConfig() {
ensureConfig();
return config;
}
// ------------------ GUARDAR VALORES INDIVIDUALES EN LA CONFIG. ------------------
public static void setModuleState(Module module) {
ensureConfig();
config.moduleStates.put(module.getName(), module.isEnabled());
save();
}
public static void setSetting(Setting setting, Object value) {
ensureConfig();
config.settings.put(getSettingKey(setting), value);
save();
}
public static void setFramePosition(SettingsFrame frame) {
ensureConfig();
config.settingsFrames.put(frame.module.getName(), new int[] {frame.getX(), frame.getY()});
save();
}
public static void setExtendableFrame(String key, ClientConfig.FrameData data) {
ensureConfig();
config.extendableFrames.put(key, data);
save();
}
public static void setHudPosition(String id, int x, int y) {
ensureConfig();
config.hudPositions.put(id, new int[] {x, y});
save();
}
public static void setHudVisibility(String id, Boolean visible) {
ensureConfig();
config.hudVisibilities.put(id, visible);
save();
}
public static void setSearchBarPosition(int x, int y) {
ensureConfig();
config.searchBarPosition = new int[] {x, y};
save();
}
// ------------------ APLICAR AJUSTES ------------------
@SuppressWarnings({"rawtypes", "unchecked"})
public static void applySetting(Module parent, Setting setting) {
String key = getSettingKey(setting);
if (!config.settings.containsKey(key)) return;
Object value = config.settings.get(key);
switch (setting) {
case BooleanSetting booleanSetting -> applyBooleanSetting(booleanSetting, value);
case EnumSetting enumSetting -> applyEnumSetting(enumSetting, value);
case NumberSetting numberSetting -> applyNumberSetting(numberSetting, value);
case StringSetting stringSetting -> applyStringSetting(stringSetting, value);
case KeySetting keySetting -> applyKeySetting(keySetting, value);
case ListSetting listSetting -> applyListSetting(listSetting, value);
case ColorSetting colorSetting -> applyColorSetting(colorSetting, value);
case OptionSetting optionSetting -> applyOptionSetting(optionSetting, value);
default -> CameraTweaks.LOGGER.warn("watafac queseso: {}", setting.getClass().getSimpleName());
}
}
private static void applyModuleStates() {
ModuleManager.INSTANCE.getModules().forEach(module -> {
if (config.moduleStates.containsKey(module.getName())) {
module.setEnabled(config.moduleStates.get(module.getName()));
}
});
CameraTweaks.LOGGER.info("estados de módulos aplicados");
}
private static void applyModuleSettings() {
ModuleManager.INSTANCE.getModules().forEach(module -> {
module.getSettings().forEach(setting -> applySetting(module, setting));
});
CameraTweaks.LOGGER.info("ajustes de módulos aplicados");
}
private static void applySettingsFrames() {
config.settingsFrames.forEach((moduleName, position) -> {
Module module = ModuleManager.INSTANCE.getModuleByName(moduleName);
ClickGUI.INSTANCE.openSettingsFrame(module, position[0], position[1]);
});
CameraTweaks.LOGGER.info("estados de marcos de ajustes aplicados");
}
private static void applySearchBarPosition() {
if (config.searchBarPosition != null && config.searchBarPosition.length == 2) {
ClickGUI.INSTANCE.getSearchBar().setX(config.searchBarPosition[0]);
ClickGUI.INSTANCE.getSearchBar().setY(config.searchBarPosition[1]);
}
CameraTweaks.LOGGER.info("posición de la barra de búsqueda aplicada");
}
private static void applyGuiSettings() {
ClientSettingsFrame.guiSettings.setEnabled(true);
ClientSettingsFrame.guiSettings.getSettings().forEach(setting -> {
applySetting(ClientSettingsFrame.guiSettings, setting);
});
CameraTweaks.LOGGER.info("ajustes del cliente aplicados");
}
private static void applyExtendableFrames() {
applyExtendableFrame(ClickGUI.INSTANCE.getModulesFrame());
applyExtendableFrame(ClickGUI.INSTANCE.getGuiSettingsFrame());
CameraTweaks.LOGGER.info("posiciones de marcos extendibles aplicadasa");
ClickGUI.INSTANCE.refreshListButtons();
}
private static void applyExtendableFrame(ModuleFrame frame) {
ClientConfig.FrameData frameData = config.extendableFrames.get("M");
if (frameData != null) {
frame.setX(frameData.x());
frame.setY(frameData.y());
frame.extended = frameData.extended();
}
}
private static void applyExtendableFrame(ClientSettingsFrame frame) {
ClientConfig.FrameData frameData = config.extendableFrames.get("S");
if (frameData != null) {
frame.setX(frameData.x());
frame.setY(frameData.y());
frame.extended = frameData.extended();
}
}
// ajustes de módulos
private static void applyBooleanSetting(BooleanSetting setting, Object value) {
if (value instanceof Boolean) {
setting.setEnabled((Boolean) value);
}
}
private static <T extends Enum<T>> void applyEnumSetting(EnumSetting<T> setting, Object value) {
if (value instanceof Double) {
setting.setIndex(((Double) value).intValue());
} else if (value instanceof Integer) {
setting.setIndex((Integer) value);
}
}
private static void applyNumberSetting(NumberSetting setting, Object value) {
if (value instanceof Double) {
setting.setValue((Double) value);
}
}
private static void applyStringSetting(StringSetting setting, Object value) {
if (value instanceof String) {
setting.setValue((String) value);
}
}
private static void applyKeySetting(KeySetting setting, Object value) {
if (value instanceof Double) {
setting.setKey(((Double) value).intValue());
} else if (value instanceof Integer) {
setting.setKey((Integer) value);
}
}
private static <T> void applyListSetting(ListSetting<T> setting, Object value) {
if (value instanceof Map<?, ?> map) {
Map<T, Boolean> convertedValues = new HashMap<>();
for (T option : setting.getOptions()) {
String key = setting.getDisplayName(option);
Object booleanValue = map.get(key);
convertedValues.put(option, booleanValue instanceof Boolean && (Boolean) booleanValue);
}
setting.setValues(convertedValues);
}
}
private static void applyColorSetting(ColorSetting setting, Object value) {
if (!(value instanceof Map<?, ?> map)) return;
Number r = (Number) map.get("r");
Number g = (Number) map.get("g");
Number b = (Number) map.get("b");
Number a = (Number) map.get("a");
if (r != null && g != null && b != null && a != null)
setting.setRGB(r.intValue(), g.intValue(), b.intValue(), a.intValue());
applyOptionalProperty(map, "rb", Boolean.class, setting::setRainbow);
applyOptionalProperty(map, "rs", Number.class, val -> setting.setRainbowSpeed(val.intValue()));
applyOptionalProperty(map, "sat", Number.class, val -> setting.setSaturation(val.floatValue()));
applyOptionalProperty(map, "bri", Number.class, val -> setting.setBrightness(val.floatValue()));
}
private static <T> void applyOptionSetting(OptionSetting<T> setting, Object value) {
if (value instanceof Double) {
int index = ((Double) value).intValue();
setting.setValue(setting.getOption(index));
}
}
private static <T> void applyOptionalProperty(Map<?, ?> map, String key, Class<T> type, java.util.function.Consumer<T> setter) {
Object value = map.get(key);
if (type.isInstance(value)) {
setter.accept(type.cast(value));
}
}
// ------------------ MÉTODOS DE AYUDA ------------------
private static boolean shouldApply() {
return CameraTweaks.mc != null && ModuleManager.INSTANCE != null && config != null;
}
private static void ensureConfig() {
if (config == null) config = new ClientConfig();
}
private static String getSettingKey(Setting setting) {
return setting.getModule().getName() + ":" + setting.getName();
}
public static boolean hasLoaded() {
return loaded;
}
}
@@ -1,7 +1,8 @@
package me.retucio.camtweaks.event;
// evento base, cancelable
// evento base, cancelable (usado en mixins)
public class Event {
private boolean cancelled;
public boolean isCancelled() {
@@ -1,37 +1,54 @@
package me.retucio.camtweaks.event;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
// al llamar un evento, se guarda en el bus de eventos, de donde luego se puede detectar si ese evento ha sucedido
public class EventBus {
private final Map<Class<?>, List<ListenerMethod>> listeners = new HashMap<>();
private record ListenerMethod(Object instance, Method method) {}
public void register(Object listener) {
for (Method method : listener.getClass().getDeclaredMethods()) {
if (method.isAnnotationPresent(Subscribe.class)) {
if (method.getParameterCount() != 1) continue; // must take 1 param
Class<?> eventType = method.getParameterTypes()[0];
method.setAccessible(true);
Class<?> targetClass;
listeners.computeIfAbsent(eventType, k -> new ArrayList<>())
.add(new ListenerMethod(listener, method));
}
if (listener instanceof Class<?> clazz) {
targetClass = clazz; // "listeners" estáticos
listener = null;
} else {
targetClass = listener.getClass();
}
for (Method method : targetClass.getDeclaredMethods()) {
if (!method.isAnnotationPresent(SubscribeEvent.class)) continue;
if (method.getParameterCount() != 1) continue;
Class<?> eventType = method.getParameterTypes()[0];
method.setAccessible(true);
if (listener == null && !Modifier.isStatic(method.getModifiers())) continue;
listeners.computeIfAbsent(eventType, k -> new ArrayList<>())
.add(new ListenerMethod(listener, method));
}
}
public void subscribe(Object listener) { register(listener); }
public void unregister(Object listener) {
for (List<ListenerMethod> list : listeners.values()) {
list.removeIf(lm -> lm.instance == listener);
}
}
public void unsubscribe(Object listener) { unregister(listener); }
public <T extends Event> T post(T event) {
List<ListenerMethod> list = listeners.get(event.getClass());
if (list != null) {
for (ListenerMethod lm : list) {
for (ListenerMethod lm : new ArrayList<>(list)) { // copiar para evitar CME
try {
lm.method.invoke(lm.instance, event);
} catch (Exception e) {
@@ -52,4 +69,4 @@ public class EventBus {
}
return false;
}
}
}
@@ -0,0 +1,21 @@
package me.retucio.camtweaks.event;
import net.minecraft.client.world.ClientWorld;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* @see me.retucio.camtweaks.mixin.MinecraftClientMixin#onJoinWorld
*/
public class JoinWorldEvent extends Event {
private final ClientWorld world;
public JoinWorldEvent(ClientWorld world) {
this.world = world;
}
public ClientWorld getWorld() {
return world;
}
}
@@ -0,0 +1,6 @@
package me.retucio.camtweaks.event;
public enum Stage {
PRE, // antes de que haya sucedido
POST; // después de que haya sucedido
}
@@ -5,4 +5,4 @@ import java.lang.annotation.*;
// anotación para registar un "listener", que escucha cuando se llama un evento
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Subscribe {}
public @interface SubscribeEvent {}
@@ -0,0 +1,21 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.entity.Entity;
/**
* @see me.retucio.camtweaks.mixin.ClientWorldMixin#onAddEntity
*/
public class AddEntityEvent extends Event {
private final Entity entity;
public AddEntityEvent(Entity entity) {
this.entity = entity;
}
public Entity getEntity() {
return entity;
}
}
@@ -0,0 +1,21 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.entity.Entity;
/**
* @see me.retucio.camtweaks.mixin.ClientPlayerInteractionManagerMixin#onAttackEntity
*/
public class AttackEntityEvent extends Event {
private final Entity entity;
public AttackEntityEvent(Entity entity) {
this.entity = entity;
}
public Entity getEntity() {
return entity;
}
}
@@ -0,0 +1,25 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.util.math.BlockPos;
/**
* @see me.retucio.camtweaks.mixin.ClientPlayerInteractionManagerMixin#onBlockBreak
*/
public class BreakBlockEvent extends Event {
private BlockPos pos;
public BreakBlockEvent(BlockPos pos) {
this.pos = pos;
}
public BlockPos getPos() {
return pos;
}
public void setPos(BlockPos pos) {
this.pos = pos;
}
}
@@ -0,0 +1,36 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
/**
* @see me.retucio.camtweaks.mixin.EntityMixin#onRotation
* @see me.retucio.camtweaks.mixin.EntityMixin#onChangeYaw
* @see me.retucio.camtweaks.mixin.EntityMixin#onChangePitch
*/
public class ChangeRotationEvent extends Event {
private float yaw;
private float pitch;
public ChangeRotationEvent(float yaw, float pitch) {
this.yaw = yaw;
this.pitch = pitch;
}
public float getYaw() {
return yaw;
}
public void setYaw(float yaw) {
this.yaw = yaw;
}
public float getPitch() {
return pitch;
}
public void setPitch(float pitch) {
this.pitch = pitch;
}
}
@@ -0,0 +1,9 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
/**
* @see me.retucio.camtweaks.mixin.ChunkOcclusionDataBuilderMixin#onChunkOcclusion
*/
public class ChunkOcclusionEvent extends Event {}
@@ -1,7 +1,12 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.module.modules.misc.ChatPlus;
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 ChatPlus#getSendButton
*/
public class ClientClickEvent implements ClickEvent {
private final String value;
@@ -0,0 +1,20 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
public class ClipAtLedgeEvent extends Event {
private boolean clipping;
public ClipAtLedgeEvent(boolean clipping) {
this.clipping = clipping;
}
public boolean isClipping() {
return clipping;
}
public void setClipping(boolean clipping) {
this.clipping = clipping;
}
}
@@ -0,0 +1,27 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.item.ItemStack;
/**
* @see me.retucio.camtweaks.mixin.ItemStackMixin#onDamage
*/
public class DamageItemEvent extends Event {
private final int amount;
private final ItemStack stack;
public DamageItemEvent(int amount, ItemStack stack) {
this.amount = amount;
this.stack = stack;
}
public int getAmount() {
return amount;
}
public ItemStack getStack() {
return stack;
}
}
@@ -0,0 +1,28 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.client.network.ServerInfo;
import net.minecraft.network.DisconnectionInfo;
/**
* @see me.retucio.camtweaks.mixin.ClientConnectionMixin#onDisconnect
*/
public class DisconnectEvent extends Event {
private final DisconnectionInfo info;
private final ServerInfo server;
public DisconnectEvent(DisconnectionInfo info, ServerInfo server) {
this.info = info;
this.server = server;
}
public DisconnectionInfo getInfo() {
return info;
}
public ServerInfo getServer() {
return server;
}
}
@@ -2,6 +2,10 @@ package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
/**
* @see me.retucio.camtweaks.mixin.GameRendererMixin#modifyFov
*/
public class GetFOVEvent extends Event {
private float fov;
@@ -0,0 +1,32 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.entity.Entity;
import net.minecraft.util.Hand;
/**
* @see me.retucio.camtweaks.mixin.ClientPlayerInteractionManagerMixin#onEntityInteract
*/
public class InteractEntityEvent extends Event {
private final Entity entity;
private Hand hand;
public InteractEntityEvent(Entity entity, Hand hand) {
this.entity = entity;
this.hand = hand;
}
public Entity getEntity() {
return entity;
}
public Hand getHand() {
return hand;
}
public void setHand(Hand hand) {
this.hand = hand;
}
}
@@ -2,7 +2,10 @@ package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
// se genera en KeyboardMixin
/**
* @see me.retucio.camtweaks.mixin.KeyboardMixin#onKeyPress
*/
public class KeyEvent extends Event {
private final int key, scancode, action;
@@ -2,7 +2,10 @@ package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
// se genera en MouseMixin
/**
* @see me.retucio.camtweaks.mixin.MouseMixin#onMouseButton
*/
public class MouseClickEvent extends Event {
private final int action, button;
@@ -2,7 +2,10 @@ package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
// se genera en MouseMixin
/**
* @see me.retucio.camtweaks.mixin.MouseMixin#onMouseScroll
*/
public class MouseScrollEvent extends Event {
private double horizontal, vertical;
@@ -0,0 +1,21 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.client.gui.screen.Screen;
/**
* @see me.retucio.camtweaks.mixin.MinecraftClientMixin#onOpenScreen
*/
public class OpenScreenEvent extends Event {
private final Screen screen;
public OpenScreenEvent(Screen screen) {
this.screen = screen;
}
public Screen getScreen() {
return screen;
}
}
@@ -0,0 +1,48 @@
package me.retucio.camtweaks.event.events;
import io.netty.channel.ChannelFutureListener;
import me.retucio.camtweaks.event.Event;
import me.retucio.camtweaks.event.Stage;
import net.minecraft.network.packet.Packet;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* @see me.retucio.camtweaks.mixin.ClientConnectionMixin#onSendPacketPre
* @see me.retucio.camtweaks.mixin.ClientConnectionMixin#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;
}
}
}
@@ -3,7 +3,10 @@ package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.client.option.Perspective;
// se genera en GameOptionsMixin
/**
* @see me.retucio.camtweaks.mixin.GameOptionsMixin#changePerspective
*/
public class PerspectiveChangeEvent extends Event {
private Perspective perspective;
@@ -0,0 +1,36 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
/**
* @see me.retucio.camtweaks.mixin.ClientPlayerInteractionManagerMixin#onBlockPlace
*/
public class PlaceBlockEvent extends Event {
private Hand hand;
private BlockHitResult result;
public PlaceBlockEvent(Hand hand, BlockHitResult result) {
this.hand = hand;
this.result = result;
}
public Hand getHand() {
return hand;
}
public void setHand(Hand hand) {
this.hand = hand;
}
public BlockHitResult getResult() {
return result;
}
public void setResult(BlockHitResult result) {
this.result = result;
}
}
@@ -4,6 +4,9 @@ import me.retucio.camtweaks.event.Event;
import net.minecraft.client.gui.hud.MessageIndicator;
import net.minecraft.text.Text;
/**
* @see me.retucio.camtweaks.mixin.ChatHudMixin#onAddMessage
*/
public class ReceiveMessageEvent extends Event {
private Text text;
@@ -0,0 +1,21 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.entity.Entity;
/**
* @see me.retucio.camtweaks.mixin.ClientWorldMixin#onRemoveEntity
*/
public class RemoveEntityEvent extends Event {
private final Entity entity;
public RemoveEntityEvent(Entity entity) {
this.entity = entity;
}
public Entity getEntity() {
return entity;
}
}
@@ -4,6 +4,10 @@ import me.retucio.camtweaks.event.Event;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Hand;
/**
* @see me.retucio.camtweaks.mixin.HeldItemRendererMixin#onRenderArm
*/
public class RenderArmEvent extends Event {
private MatrixStack matrices;
@@ -0,0 +1,77 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.client.gui.hud.ClientBossBar;
import net.minecraft.text.Text;
import java.util.Iterator;
/**
* @see me.retucio.camtweaks.mixin.BossBarHudMixin#modifyBossBarIterator
* @see me.retucio.camtweaks.mixin.BossBarHudMixin#modifyBossBarName
* @see me.retucio.camtweaks.mixin.BossBarHudMixin#modifySpacingConstant
*/
public class RenderBossbarEvent {
public static class BossText extends Event {
private ClientBossBar bossBar;
private Text name;
public BossText(ClientBossBar bossBar, Text name) {
this.bossBar = bossBar;
this.name = name;
}
public ClientBossBar getBossBar() {
return bossBar;
}
public void setBossBar(ClientBossBar bossBar) {
this.bossBar = bossBar;
}
public Text getName() {
return name;
}
public void setName(Text name) {
this.name = name;
}
}
public static class BossSpacing extends Event {
private int spacing;
public BossSpacing(int spacing) {
this.spacing = spacing;
}
public int getSpacing() {
return spacing;
}
public void setSpacing(int spacing) {
this.spacing = spacing;
}
}
public static class BossIterator extends Event {
private Iterator<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,6 +0,0 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
public class RenderEvent extends Event {
}
@@ -4,12 +4,16 @@ import me.retucio.camtweaks.event.Event;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Hand;
public class HeldItemRendererEvent extends Event {
/**
* @see me.retucio.camtweaks.mixin.HeldItemRendererMixin#onRenderItem
*/
public class RenderHeldItemEvent extends Event {
private MatrixStack matrices;
private Hand hand;
public HeldItemRendererEvent(MatrixStack matrices, Hand hand) {
public RenderHeldItemEvent(MatrixStack matrices, Hand hand) {
this.matrices = matrices;
this.hand = hand;
}
@@ -0,0 +1,35 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.RenderTickCounter;
import net.minecraft.client.util.math.MatrixStack;
/**
* @see me.retucio.camtweaks.mixin.WorldRendererMixin#render
*/
public class RenderWorldEvent extends Event {
private final MatrixStack matrices;
private final RenderTickCounter tc;
private final Camera camera;
public RenderWorldEvent(MatrixStack matrices, RenderTickCounter tc, Camera camera) {
this.matrices = matrices;
this.tc = tc;
this.camera = camera;
}
public MatrixStack getMatrices() {
return matrices;
}
public RenderTickCounter getTickCounter() {
return tc;
}
public Camera getCamera() {
return camera;
}
}
@@ -2,6 +2,10 @@ package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
/**
* @see me.retucio.camtweaks.mixin.ClientPlayNetworkHandlerMixin#onSendMessage
*/
public class SendMessageEvent extends Event {
private String message;
@@ -0,0 +1,12 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
/**
* @see me.retucio.camtweaks.mixin.MinecraftClientMixin#onStop
*/
public class ShutdownEvent extends Event {
public ShutdownEvent() {}
}
@@ -0,0 +1,14 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
/**
* @see me.retucio.camtweaks.mixin.MinecraftClientMixin#onTickPre
* @see me.retucio.camtweaks.mixin.MinecraftClientMixin#onTickPost
*/
public class TickEvent {
public static class Pre extends Event {}
public static class Post extends Event {}
}
@@ -0,0 +1,36 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;
/**
* @see me.retucio.camtweaks.mixin.MinecraftClientMixin#onUseItem
*/
public class UseItemEvent extends Event {
private ItemStack stack;
private Hand hand;
public UseItemEvent(ItemStack stack, Hand hand) {
this.stack = stack;
this.hand = hand;
}
public ItemStack getStack() {
return stack;
}
public void setStack(ItemStack stack) {
this.stack = stack;
}
public Hand getHand() {
return hand;
}
public void setHand(Hand hand) {
this.hand = hand;
}
}
@@ -0,0 +1,10 @@
package me.retucio.camtweaks.event.events.camtweaks;
import me.retucio.camtweaks.event.Event;
// se genera cada que se interactúa con el marco de ajustes de la interfaz
public class GUISettingsFrameEvent {
public static class Extend extends Event {} // al extenderlo / contraerlo
public static class Move extends Event {} // al cambiarlo de posición
}
@@ -0,0 +1,6 @@
package me.retucio.camtweaks.event.events.camtweaks;
import me.retucio.camtweaks.event.Event;
// se genera cuando carga la interfaz del mod
public class LoadClickGUIEvent extends Event {}
@@ -0,0 +1,6 @@
package me.retucio.camtweaks.event.events.camtweaks;
import me.retucio.camtweaks.event.Event;
// se genera cuando carga el gestor de comandos
public class LoadCommandManagerEvent extends Event {}
@@ -0,0 +1,6 @@
package me.retucio.camtweaks.event.events.camtweaks;
import me.retucio.camtweaks.event.Event;
// se genera cuando carga el gestor de módulos
public class LoadModuleManagerEvent extends Event {}
@@ -0,0 +1,10 @@
package me.retucio.camtweaks.event.events.camtweaks;
import me.retucio.camtweaks.event.Event;
// se genera cada que se interactúa con el marco de módulos
public class ModuleFrameEvent {
public static class Extend extends Event {} // al extenderlo / contraerlo
public static class Move extends Event {} // al cambiarlo de posición
}
@@ -0,0 +1,27 @@
package me.retucio.camtweaks.event.events.camtweaks;
import me.retucio.camtweaks.event.Event;
import me.retucio.camtweaks.ui.widgets.frames.SettingsFrame;
// se genera cada que se interactúa con un marco de ajustes de un módulo
public class SettingsFrameEvent {
public static class Open extends Event { // al abrirlo
private final SettingsFrame frame;
public Open(SettingsFrame frame) { this.frame = frame; }
public SettingsFrame getFrame() { return frame; }
}
public static class Close extends Event { // al cerrarlo
private final SettingsFrame frame;
public Close(SettingsFrame frame) { this.frame = frame; }
public SettingsFrame getFrame() { return frame; }
}
public static class Move extends Event { // al cambiarlo de posición
private final SettingsFrame frame;
public Move(SettingsFrame frame) { this.frame = frame; }
public SettingsFrame getFrame() { return frame; }
}
}
@@ -0,0 +1,18 @@
package me.retucio.camtweaks.event.events.camtweaks;
import me.retucio.camtweaks.event.Event;
import me.retucio.camtweaks.module.Module;
// se genera cada que se enciende o apaga un módulo
public class ToggleModuleEvent extends Event {
private final Module module;
public ToggleModuleEvent(Module module) {
this.module = module;
}
public Module getModule() {
return module;
}
}
@@ -0,0 +1,28 @@
package me.retucio.camtweaks.event.events.camtweaks;
import me.retucio.camtweaks.event.Event;
import me.retucio.camtweaks.module.settings.Setting;
// se genera cada que se cambia el valor de un ajuste
public class UpdateSettingEvent extends Event {
private final Setting setting;
private boolean shouldSave;
public UpdateSettingEvent(Setting setting, boolean shouldSave) {
this.setting = setting;
this.shouldSave = shouldSave;
}
public Setting getSetting() {
return setting;
}
public boolean shouldSave() {
return shouldSave;
}
public void shouldSave(boolean value) {
this.shouldSave = value;
}
}
@@ -0,0 +1,38 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.sugar.Local;
import me.retucio.camtweaks.event.events.RenderBossbarEvent;
import net.minecraft.client.gui.hud.BossBarHud;
import net.minecraft.client.gui.hud.ClientBossBar;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Constant;
import org.spongepowered.asm.mixin.injection.ModifyConstant;
import java.util.Iterator;
import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
@Mixin(BossBarHud.class)
public abstract class BossBarHudMixin {
@ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Ljava/util/Collection;iterator()Ljava/util/Iterator;"))
public Iterator<ClientBossBar> modifyBossBarIterator(Iterator<ClientBossBar> original) {
RenderBossbarEvent.BossIterator event = EVENT_BUS.post(new RenderBossbarEvent.BossIterator(original));
return event.getIterator();
}
@ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ClientBossBar;getName()Lnet/minecraft/text/Text;"))
public Text modifyBossBarName(Text original, @Local ClientBossBar clientBossBar) {
RenderBossbarEvent.BossText event = EVENT_BUS.post(new RenderBossbarEvent.BossText(clientBossBar, original));
return event.getName();
}
@ModifyConstant(method = "render", constant = @Constant(intValue = 9, ordinal = 1))
public int modifySpacingConstant(int constant) {
RenderBossbarEvent.BossSpacing event = EVENT_BUS.post(new RenderBossbarEvent.BossSpacing(constant));
return event.getSpacing();
}
}
@@ -0,0 +1,20 @@
package me.retucio.camtweaks.mixin;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import me.retucio.camtweaks.util.render.GlintRenderLayer;
import net.minecraft.client.render.BufferBuilderStorage;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.util.BufferAllocator;
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(BufferBuilderStorage.class)
public abstract class BufferStorageMixin {
@Inject(method = "assignBufferBuilder", at = @At("HEAD"))
private static void addGlintTypes(Object2ObjectLinkedOpenHashMap<RenderLayer, BufferAllocator> builderStorage, RenderLayer layer, CallbackInfo ci) {
GlintRenderLayer.addGlintTypes(builderStorage);
}
}
@@ -1,29 +1,94 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.module.modules.Perspective;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.camera.Freelook;
import me.retucio.camtweaks.module.modules.camera.Freecam;
import me.retucio.camtweaks.module.modules.camera.PerspectivePlus;
import net.minecraft.client.render.Camera;
import net.minecraft.entity.Entity;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArgs;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import static me.retucio.camtweaks.CameraTweaks.moduleManager;
import org.spongepowered.asm.mixin.injection.invoke.arg.Args;
@Mixin(Camera.class)
public abstract class CameraMixin {
@Unique
private float tickDelta;
@Unique
PerspectivePlus perspectivePlus;
@Unique
Freecam freecam;
@Unique
Freelook freelook;
@Shadow
private boolean thirdPerson;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(CallbackInfo ci) {
perspectivePlus = ModuleManager.INSTANCE.getModuleByClass(PerspectivePlus.class);
freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
freelook = ModuleManager.INSTANCE.getModuleByClass(Freelook.class);
}
@Inject(method = "update", at = @At("HEAD"))
private void onUpdateHead(World area, Entity focusedEntity, boolean thirdPerson, boolean inverseView, float tickDelta, CallbackInfo ci) {
this.tickDelta = tickDelta;
}
// perspectiva
@ModifyVariable(method = "clipToSpace", at = @At("HEAD"), ordinal = 0, argsOnly = true)
private float modifyClipToSpace(float distance) {
Perspective perspective = moduleManager.getModuleByClass(Perspective.class);
return perspective.isEnabled() ? (float) perspective.getDistance() : distance;
if (freecam.isEnabled()) return 0;
return perspectivePlus.isEnabled() ? (float) perspectivePlus.getDistance() : distance;
}
@Inject(method = "clipToSpace", at = @At("HEAD"), cancellable = true)
private void onClipToSpace(float distance, CallbackInfoReturnable<Float> cir) {
if (moduleManager.getModuleByClass(Perspective.class).isEnabled()
&& moduleManager.getModuleByClass(Perspective.class).clip.isEnabled())
if (perspectivePlus.isEnabled() && perspectivePlus.clip.isEnabled())
cir.setReturnValue(distance);
}
}
// cámara libre
@Inject(method = "update", at = @At("TAIL"))
private void onUpdateTail(World area, Entity focusedEntity, boolean thirdPerson, boolean inverseView, float tickProgress, CallbackInfo ci) {
if (freecam.isEnabled())
this.thirdPerson = true;
}
@ModifyArgs(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/Camera;setPos(DDD)V"))
private void onUpdateSetPosArgs(Args args) {
if (freecam.isEnabled()) {
args.set(0, freecam.getX(tickDelta));
args.set(1, freecam.getY(tickDelta));
args.set(2, freecam.getZ(tickDelta));
}
}
@ModifyArgs(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/Camera;setRotation(FF)V"))
private void onUpdateSetRotationArgs(Args args) {
if (freecam.isEnabled()) {
args.set(0, freecam.getYaw(tickDelta));
args.set(1, freecam.getPitch(tickDelta));
} else if (freelook.isEnabled()) {
args.set(0, freelook.getYaw());
args.set(1, freelook.getPitch());
}
}
}
@@ -1,16 +1,15 @@
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.modules.BetterChat;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.misc.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.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.hud.ChatHud;
import net.minecraft.client.gui.hud.ChatHudLine;
import net.minecraft.client.gui.hud.MessageIndicator;
@@ -39,8 +38,8 @@ public abstract class ChatHudMixin implements IChatHud {
@Unique
private int nextId;
@Unique @Final
private BetterChat betterChat = moduleManager.getModuleByClass(BetterChat.class);
@Unique
ChatPlus chatPlus;
@Shadow @Final
private List<ChatHudLine> messages;
@@ -54,6 +53,10 @@ public abstract class ChatHudMixin implements IChatHud {
@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
@@ -65,12 +68,12 @@ public abstract class ChatHudMixin implements IChatHud {
nextId = 0;
}
@Inject(method = "addVisibleMessage", at = @At(value = "INVOKE", target = "Ljava/util/List;add(ILjava/lang/Object;)V", shift = At.Shift.AFTER))
@Inject(method = "addVisibleMessage", at = @At(value = "INVOKE", target = "Ljava/util/List;addFirst(Ljava/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))
@Inject(method = "addMessage(Lnet/minecraft/client/gui/hud/ChatHudLine;)V", at = @At(value = "INVOKE", target = "Ljava/util/List;addFirst(Ljava/lang/Object;)V", shift = At.Shift.AFTER))
private void onAddMessageAfterNewChatHudLine(ChatHudLine message, CallbackInfo ci) {
((IChatHudLine) (Object) messages.getFirst()).smegma$setId(nextId);
}
@@ -98,9 +101,14 @@ public abstract class ChatHudMixin implements IChatHud {
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;
@@ -115,7 +123,7 @@ public abstract class ChatHudMixin implements IChatHud {
for (int i = messages.size() - 1; i > -1; i--) {
if (((IChatHudLine) (Object) messages.get(i)).smegma$getId() == nextId && nextId != 0) {
messages.remove(i);
betterChat.removeLine(i);
chatPlus.removeLine(i);
}
}
@@ -133,62 +141,49 @@ public abstract class ChatHudMixin implements IChatHud {
// cabezas
@ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;ceil(F)I"))
@ModifyExpressionValue(method = "render(Lnet/minecraft/client/gui/hud/ChatHud$Backend;IIZ)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;ceil(F)I"))
private int onRender_modifyWidth(int width) {
return (betterChat.isEnabled() && betterChat.showHeads.isEnabled()) ? width + 10 : width;
return (chatPlus.isEnabled() && chatPlus.showHeads.isEnabled()) ? width + 10 : width;
}
@ModifyReceiver(method = "method_71991", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTextWithShadow(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/OrderedText;III)V"))
private DrawContext onRender_beforeDrawTextWithShadow(DrawContext context, TextRenderer textRenderer, OrderedText text, int x, int y, int color, @Local(argsOnly = true) ChatHudLine.Visible line) {
betterChat.beforeDrawMessage(context, line, y, color);
return context;
}
@Inject(method = "method_71991", at = @At("TAIL"))
private void onRender_afterDrawTextWithShadow(int i, DrawContext context, float f, int j, int k, int l, ChatHudLine.Visible visible, int m, float g, CallbackInfo info) {
betterChat.afterDrawMessage(context);
}
// 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 (!betterChat.isEnabled()) return size;
return size + betterChat.chatHistoryExtraLength.getIntValue();
if (!chatPlus.isEnabled()) return size;
return size + chatPlus.chatHistoryExtraLength.getIntValue();
}
@ModifyExpressionValue(method = "addVisibleMessage", at = @At(value = "CONSTANT", args = "intValue=100"))
private int maxLengthVisible(int size) {
if (!betterChat.isEnabled()) return size;
return size + betterChat.chatHistoryExtraLength.getIntValue();
if (!chatPlus.isEnabled()) return size;
return size + chatPlus.chatHistoryExtraLength.getIntValue();
}
@Inject(method = "addVisibleMessage", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;isChatFocused()Z"))
private void onBreakChatMessageLines(ChatHudLine message, CallbackInfo ci, @Local List<OrderedText> list) {
betterChat.lines.addFirst(list.size());
chatPlus.lines.addFirst(list.size());
}
@Inject(method = "addMessage(Lnet/minecraft/client/gui/hud/ChatHudLine;)V", at = @At(value = "INVOKE", target = "Ljava/util/List;remove(I)Ljava/lang/Object;"))
@Inject(method = "addMessage(Lnet/minecraft/client/gui/hud/ChatHudLine;)V", at = @At(value = "INVOKE", target = "Ljava/util/List;removeLast()Ljava/lang/Object;"))
private void onRemoveMessage(ChatHudLine message, CallbackInfo ci) {
int extra = betterChat.chatHistoryExtraLength.getIntValue();
int size = betterChat.lines.size();
int extra = chatPlus.chatHistoryExtraLength.getIntValue();
int size = chatPlus.lines.size();
while (size > 100 + extra) {
betterChat.lines.removeLast();
chatPlus.lines.removeLast();
size--;
}
}
@Inject(method = "clear", at = @At("HEAD"))
private void onClear(boolean clearHistory, CallbackInfo ci) {
betterChat.lines.clear();
chatPlus.lines.clear();
}
@Inject(method = "refresh", at = @At("HEAD"))
private void onRefresh(CallbackInfo ci) {
betterChat.lines.clear();
chatPlus.lines.clear();
}
}
@@ -17,7 +17,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.concurrent.CompletableFuture;
import static me.retucio.camtweaks.CameraTweaks.commandManager;
import static me.retucio.camtweaks.CameraTweaks.mc;
@Mixin(ChatInputSuggestor.class)
@@ -42,7 +41,7 @@ public abstract class ChatInputSuggestorMixin {
@Inject(method = "refresh", at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/StringReader;canRead()Z", remap = false), cancellable = true)
private void onRefresh(CallbackInfo ci, @Local StringReader reader) {
String prefix = commandManager.getPrefix();
String prefix = CommandManager.INSTANCE.getPrefix();
int length = prefix.length();
if (reader.canRead(length) && reader.getString().startsWith(prefix, reader.getCursor())) {
@@ -1,6 +1,7 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.modules.BetterChat;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.misc.ChatPlus;
import net.minecraft.client.gui.screen.ChatScreen;
import net.minecraft.client.gui.widget.TextFieldWidget;
import org.spongepowered.asm.mixin.Mixin;
@@ -9,17 +10,15 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.camtweaks.CameraTweaks.moduleManager;
@Mixin(value = ChatScreen.class, priority = 1001)
public class ChatScreenMixin {
public abstract class ChatScreenMixin {
@Shadow
protected TextFieldWidget chatField;
@Inject(method = "init", at = @At(value = "RETURN"))
private void onInit(CallbackInfo info) {
BetterChat betterChat = moduleManager.getModuleByClass(BetterChat.class);
if (betterChat.isEnabled() && betterChat.noCharLimit.isEnabled()) chatField.setMaxLength(Integer.MAX_VALUE);
ChatPlus chatPlus = ModuleManager.INSTANCE.getModuleByClass(ChatPlus.class);
if (chatPlus.isEnabled() && chatPlus.noCharLimit.isEnabled()) chatField.setMaxLength(Integer.MAX_VALUE);
}
}
@@ -0,0 +1,33 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.camera.Freecam;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.debug.ChunkBorderDebugRenderer;
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.injection.At;
@Mixin(ChunkBorderDebugRenderer.class)
public abstract class ChunkBorderDebugRendererMixin {
@Shadow @Final
private MinecraftClient client;
@ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/ChunkSectionPos;from(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/util/math/ChunkSectionPos;"))
private ChunkSectionPos getChunkPos(ChunkSectionPos chunkPos) {
Freecam freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
if (!freecam.isEnabled()) return chunkPos;
float delta = client.getRenderTickCounter().getTickProgress(true);
return ChunkSectionPos.from(
ChunkSectionPos.getSectionCoord(MathHelper.floor(freecam.getX(delta))),
ChunkSectionPos.getSectionCoord(MathHelper.floor(freecam.getY(delta))),
ChunkSectionPos.getSectionCoord(MathHelper.floor(freecam.getZ(delta)))
);
}
}
@@ -0,0 +1,21 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.event.events.ChunkOcclusionEvent;
import net.minecraft.client.render.chunk.ChunkOcclusionDataBuilder;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
@Mixin(ChunkOcclusionDataBuilder.class)
public abstract class ChunkOcclusionDataBuilderMixin {
@Inject(method = "markClosed", at = @At("HEAD"), cancellable = true)
private void onChunkOcclusion(BlockPos pos, CallbackInfo ci) {
ChunkOcclusionEvent event = EVENT_BUS.post(new ChunkOcclusionEvent());
if (event.isCancelled()) ci.cancel();
}
}
@@ -0,0 +1,67 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.mixin.accessor.ConfirmServerResourcePackScreenAccessor;
import me.retucio.camtweaks.mixin.accessor.PackAccessor;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.network.RPackBypass;
import me.retucio.camtweaks.util.interfaces.IConfirmScreen;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.network.ClientCommonNetworkHandler;
import net.minecraft.client.network.ServerInfo;
import net.minecraft.client.option.ServerList;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.packet.c2s.common.ResourcePackStatusC2SPacket;
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;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.net.URL;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@Mixin(ClientCommonNetworkHandler.class)
public abstract class ClientCommonNetworkHandlerMixin {
@Shadow @Final protected MinecraftClient client;
@Shadow @Final protected ServerInfo serverInfo;
@Shadow @Final protected ClientConnection connection;
@Unique // tardar 3 segundos porque algunos servers detectar el tiempo entre que se acepta y se carga el pack
private final Executor DELAYED_EXECUTOR = CompletableFuture.delayedExecutor(3L, TimeUnit.SECONDS);
@Inject(method = "createConfirmServerResourcePackScreen", at = @At("TAIL"))
private void setScreenBypassAction(UUID id, URL url, String hash, boolean required, Text prompt, CallbackInfoReturnable<Screen> cir) {
RPackBypass bypassPack = ModuleManager.INSTANCE.getModuleByClass(RPackBypass.class);
if (!bypassPack.isEnabled()) return;
final Screen screen = cir.getReturnValue();
((IConfirmScreen) screen).smegma$setBypassAction(() -> {
client.setScreen(((ConfirmServerResourcePackScreenAccessor) screen).getParentScreen());
if (this.serverInfo != null) {
this.serverInfo.setResourcePackPolicy(bypassPack.getPolicy());
this.client.getServerResourcePackProvider().acceptAll();
ServerList.updateServerListEntry(this.serverInfo);
}
bypass(((ConfirmServerResourcePackScreenAccessor) screen).getRequests().stream().map(PackAccessor::callId).toList());
});
}
@Unique
public void bypass(List<UUID> ids) {
ids.forEach(id -> connection.send(new ResourcePackStatusC2SPacket(id, ResourcePackStatusC2SPacket.Status.ACCEPTED)));
ids.forEach(id -> connection.send(new ResourcePackStatusC2SPacket(id, ResourcePackStatusC2SPacket.Status.DOWNLOADED)));
DELAYED_EXECUTOR.execute(() ->
ids.forEach(id -> connection.send(new ResourcePackStatusC2SPacket(id, ResourcePackStatusC2SPacket.Status.SUCCESSFULLY_LOADED)))
);
}
}
@@ -0,0 +1,53 @@
package me.retucio.camtweaks.mixin;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import me.retucio.camtweaks.event.Stage;
import me.retucio.camtweaks.event.events.DisconnectEvent;
import me.retucio.camtweaks.event.events.PacketEvent;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.DisconnectionInfo;
import net.minecraft.network.packet.Packet;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
import static me.retucio.camtweaks.CameraTweaks.mc;
@Mixin(ClientConnection.class)
public abstract class ClientConnectionMixin {
// mandar paquetes
@Inject(method = "send(Lnet/minecraft/network/packet/Packet;Lio/netty/channel/ChannelFutureListener;)V", at = @At("HEAD"), cancellable = true)
private void onSendPacketPre(Packet<?> packet, ChannelFutureListener channelFutureListener, CallbackInfo ci) {
PacketEvent.Send event = EVENT_BUS.post(new PacketEvent.Send(packet, Stage.PRE));
if (event.isCancelled()) ci.cancel();
}
@Inject(method = "send(Lnet/minecraft/network/packet/Packet;Lio/netty/channel/ChannelFutureListener;)V", at = @At("TAIL"), cancellable = true)
private void onSendPacketPost(Packet<?> packet, ChannelFutureListener channelFutureListener, CallbackInfo ci) {
PacketEvent.Send event = EVENT_BUS.post(new PacketEvent.Send(packet, Stage.POST));
if (event.isCancelled()) ci.cancel();
}
// recibir paquetes
@Inject(method = "channelRead0(Lio/netty/channel/ChannelHandlerContext;Lnet/minecraft/network/packet/Packet;)V", at = @At("HEAD"), cancellable = true)
private void onReceivePacket(ChannelHandlerContext context, Packet<?> packet, CallbackInfo ci) {
PacketEvent.Receive event = EVENT_BUS.post(new PacketEvent.Receive(packet));
if (event.isCancelled()) ci.cancel();
}
// otros
@Inject(method = "disconnect(Lnet/minecraft/network/DisconnectionInfo;)V", at = @At("HEAD"), cancellable = true)
private void onDisconnect(DisconnectionInfo disconnectionInfo, CallbackInfo ci) {
DisconnectEvent event = EVENT_BUS.post(new DisconnectEvent(disconnectionInfo, mc.getCurrentServerEntry()));
if (event.isCancelled()) ci.cancel();
}
}
@@ -3,13 +3,18 @@ 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.render.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 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.*;
@@ -26,7 +31,7 @@ public abstract class ClientPlayNetworkHandlerMixin {
@Inject(method = "sendChatMessage", at = @At("HEAD"), cancellable = true)
private void onSendMessage(String message, CallbackInfo ci) {
if (ignoreChatMessage) return;
if (!message.startsWith(commandManager.getPrefix())) {
if (!message.startsWith(CommandManager.INSTANCE.getPrefix())) {
SendMessageEvent event = EVENT_BUS.post(new SendMessageEvent(message));
if (!event.isCancelled()) {
ignoreChatMessage = true;
@@ -38,7 +43,7 @@ public abstract class ClientPlayNetworkHandlerMixin {
};
try {
CommandManager.dispatch(message.substring(commandManager.getPrefix().length()));
CommandManager.dispatch(message.substring(CommandManager.INSTANCE.getPrefix().length()));
} catch (CommandSyntaxException e) {
ChatUtil.error(e.getMessage());
}
@@ -46,4 +51,11 @@ public abstract class ClientPlayNetworkHandlerMixin {
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(floatingItem);
}
}
@@ -0,0 +1,38 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import com.llamalad7.mixinextras.sugar.Local;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.world.NoMiningInterruptions;
import me.retucio.camtweaks.module.modules.player.PortalGUI;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.hit.HitResult;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(ClientPlayerEntity.class)
public abstract class ClientPlayerEntityMixin {
@ModifyExpressionValue(method = "tickNausea", at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;currentScreen:Lnet/minecraft/client/gui/screen/Screen;", opcode = Opcodes.GETFIELD))
private Screen allowScreensInPortals(Screen original) {
if (ModuleManager.INSTANCE.getModuleByClass(PortalGUI.class).isEnabled()) return null;
return original;
}
@ModifyReturnValue(method = "getCrosshairTarget(FLnet/minecraft/entity/Entity;)Lnet/minecraft/util/hit/HitResult;", at = @At("RETURN"))
private static HitResult onGetCrosshairTarget(HitResult original, @Local HitResult hitResult) {
NoMiningInterruptions nmi = ModuleManager.INSTANCE.getModuleByClass(NoMiningInterruptions.class);
if (original instanceof EntityHitResult ehr) {
if (nmi.shouldIgnoreEntity(ehr.getEntity())
&& hitResult.getType() == HitResult.Type.BLOCK) {
return hitResult;
}
}
return original;
}
}
@@ -0,0 +1,72 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.event.events.AttackEntityEvent;
import me.retucio.camtweaks.event.events.BreakBlockEvent;
import me.retucio.camtweaks.event.events.InteractEntityEvent;
import me.retucio.camtweaks.event.events.PlaceBlockEvent;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.camera.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.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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
import static me.retucio.camtweaks.CameraTweaks.mc;
@Mixin(ClientPlayerInteractionManager.class)
public abstract class ClientPlayerInteractionManagerMixin {
@Shadow @Final
private MinecraftClient client;
@Unique
Freecam freecam;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(MinecraftClient client, ClientPlayNetworkHandler networkHandler, CallbackInfo ci) {
freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
}
@Inject(method = "breakBlock", at = @At("HEAD"), cancellable = true)
private void onBlockBreak(BlockPos pos, CallbackInfoReturnable<Boolean> cir) {
BreakBlockEvent event = EVENT_BUS.post(new BreakBlockEvent(pos));
if (event.isCancelled()) cir.cancel();
}
@Inject(method = "interactBlock", at = @At("HEAD"), cancellable = true)
private void onBlockPlace(ClientPlayerEntity player, Hand hand, BlockHitResult result, CallbackInfoReturnable<ActionResult> cir) {
if (mc.player != player) return;
PlaceBlockEvent event = EVENT_BUS.post(new PlaceBlockEvent(hand, result));
if (event.isCancelled()) cir.cancel();
}
@Inject(method = "interactEntity", at = @At("HEAD"), cancellable = true)
private void onEntityInteract(PlayerEntity player, Entity entity, Hand hand, CallbackInfoReturnable<ActionResult> cir) {
if (mc.player != player) return;
InteractEntityEvent event = EVENT_BUS.post(new InteractEntityEvent(entity, hand));
if (event.isCancelled()) cir.cancel();
}
@Inject(method = "attackEntity", at = @At("HEAD"), cancellable = true)
private void onAttackEntity(PlayerEntity player, Entity target, CallbackInfo ci) {
if (mc.player != player) return;
AttackEntityEvent event = EVENT_BUS.post(new AttackEntityEvent(target));
if (event.isCancelled()) ci.cancel();
}
}
@@ -0,0 +1,32 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.event.events.AddEntityEvent;
import me.retucio.camtweaks.event.events.RemoveEntityEvent;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
@Mixin(ClientWorld.class)
public abstract class ClientWorldMixin {
@Shadow @Nullable
public abstract Entity getEntityById(int id);
@Inject(method = "addEntity", at = @At("HEAD"))
private void onAddEntity(Entity entity, CallbackInfo ci) {
if (entity != null) EVENT_BUS.post(new AddEntityEvent(entity));
}
@Inject(method = "removeEntity", at = @At("HEAD"))
private void onRemoveEntity(int entityId, Entity.RemovalReason removalReason, CallbackInfo ci) {
Entity entity = getEntityById(entityId);
if (entity != null) EVENT_BUS.post(new RemoveEntityEvent(entity));
}
}
@@ -0,0 +1,19 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.world.TimeChanger;
import net.minecraft.client.world.ClientWorld;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ClientWorld.Properties.class)
public abstract class ClientWorldPropertiesMixin {
@Inject(method = "setTimeOfDay", at = @At("HEAD"), cancellable = true)
private void setTimeOfDay(long time, CallbackInfo ci) { // de no ser por esto, se verían "flashes" del tiempo real en el cielo
TimeChanger timeChanger = ModuleManager.INSTANCE.getModuleByClass(TimeChanger.class);
if (timeChanger.isEnabled() && time != timeChanger.time.getLongValue()) ci.cancel();
}
}
@@ -0,0 +1,39 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.network.RPackBypass;
import me.retucio.camtweaks.util.interfaces.IConfirmScreen;
import net.minecraft.client.gui.screen.ConfirmScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.DirectionalLayoutWidget;
import net.minecraft.text.Text;
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(ConfirmScreen.class)
public abstract class ConfirmScreenMixin extends Screen implements IConfirmScreen {
@Shadow protected DirectionalLayoutWidget layout;
@Unique private Runnable bypassAction = null;
protected ConfirmScreenMixin(final Text title) {
super(title);
}
@Inject(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ConfirmScreen;addButtons(Lnet/minecraft/client/gui/widget/DirectionalLayoutWidget;)V", shift = At.Shift.AFTER))
protected void addBypassButton(CallbackInfo ci) {
RPackBypass bypassPack = ModuleManager.INSTANCE.getModuleByClass(RPackBypass.class);
if (this.bypassAction != null && bypassPack.isEnabled())
this.layout.add(ButtonWidget.builder(bypassPack.BYPASS_TEXT, $ -> this.bypassAction.run()).build());
}
@Override
public void smegma$setBypassAction(Runnable bypass) {
this.bypassAction = bypass;
}
}
@@ -0,0 +1,46 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.render.CritsPlus;
import net.minecraft.client.particle.BillboardParticle;
import net.minecraft.client.particle.DamageParticle;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
@Mixin(DamageParticle.class)
public abstract class DamageParticleMixin {
@ModifyReturnValue(method = "getRenderType", at = @At("RETURN"))
private BillboardParticle.RenderType makeCritsTranslucent(BillboardParticle.RenderType original) {
if (ModuleManager.INSTANCE.getModuleByClass(CritsPlus.class).isEnabled()) return BillboardParticle.RenderType.PARTICLE_ATLAS_TRANSLUCENT;
return original;
}
}
@Mixin(DamageParticle.Factory.class)
abstract class DamageParticleFactoryMixin {
@ModifyVariable(method = "createParticle(Lnet/minecraft/particle/SimpleParticleType;Lnet/minecraft/client/world/ClientWorld;DDDDDDLnet/minecraft/util/math/random/Random;)Lnet/minecraft/client/particle/Particle;", at = @At(value = "STORE"))
private DamageParticle modifyCritColor(DamageParticle original) {
CritsPlus crits = ModuleManager.INSTANCE.getModuleByClass(CritsPlus.class);
if (!crits.isEnabled()) return original;
original.setColor(
crits.color.getR() / 255f,
crits.color.getG() / 255f,
crits.color.getB() / 255f
);
original.alpha = crits.color.getA() / 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;
}
}
@@ -0,0 +1,34 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.network.Reconnect;
import net.minecraft.client.gui.screen.DisconnectedScreen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.DirectionalLayoutWidget;
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.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(DisconnectedScreen.class)
public abstract class DisconnectedScreenMixin {
@Shadow @Final
private DirectionalLayoutWidget grid;
@Inject(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/DirectionalLayoutWidget;add(Lnet/minecraft/client/gui/widget/Widget;)Lnet/minecraft/client/gui/widget/Widget;", ordinal = 2, shift = At.Shift.AFTER))
private void addReconnectButton(CallbackInfo ci) {
Reconnect reconnect = ModuleManager.INSTANCE.getModuleByClass(Reconnect.class);
if (reconnect == null || !reconnect.isEnabled()) return;
grid.add(ButtonWidget.builder(
Text.literal("reconectarse"),
button -> reconnect.reconnect()
).build());
}
}
@@ -0,0 +1,152 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.event.events.ChangeRotationEvent;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.camera.Freecam;
import me.retucio.camtweaks.module.modules.camera.Freelook;
import me.retucio.camtweaks.module.modules.camera.Rotations;
import me.retucio.camtweaks.module.modules.misc.AntiInvis;
import me.retucio.camtweaks.module.modules.render.Nametags;
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.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.EVENT_BUS;
import static me.retucio.camtweaks.CameraTweaks.mc;
@Mixin(Entity.class)
public abstract class EntityMixin {
@Shadow public abstract Text getName();
@Shadow public abstract EntityType<?> getType();
@Shadow private float yaw;
@Shadow private float pitch;
@Unique
Freecam freecam;
@Unique
Freelook freelook;
@Unique
Nametags nametags;
@Unique
Rotations rotations;
@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);
rotations = ModuleManager.INSTANCE.getModuleByClass(Rotations.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) 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;
if ((Object) this instanceof ItemEntity i && !nametags.items.isEnabled(i.getStack().getItem())) 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;
}
// rotaciones
@Inject(method = "setRotation", at = @At("HEAD"), cancellable = true)
private void onRotation(float yaw, float pitch, CallbackInfo ci) {
if ((Object) this != mc.player) return;
ChangeRotationEvent event = EVENT_BUS.post(new ChangeRotationEvent(yaw, pitch));
if (event.isCancelled()) ci.cancel();
}
@Inject(method = "setYaw", at = @At("HEAD"), cancellable = true)
private void onChangeYaw(float yaw, CallbackInfo ci) {
if ((Object) this != mc.player) return;
ChangeRotationEvent event = EVENT_BUS.post(new ChangeRotationEvent(yaw, this.pitch));
if (event.isCancelled()) ci.cancel();
}
@Inject(method = "setPitch", at = @At("HEAD"), cancellable = true)
private void onChangePitch(float pitch, CallbackInfo ci) {
if ((Object) this != mc.player) return;
ChangeRotationEvent event = EVENT_BUS.post(new ChangeRotationEvent(this.yaw, pitch));
if (event.isCancelled()) ci.cancel();
}
// 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);
}
}
@@ -0,0 +1,19 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.render.GlintPlus;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.entity.equipment.EquipmentRenderer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(EquipmentRenderer.class)
public abstract class EquipmentRendererMixin {
@Redirect(method = "render(Lnet/minecraft/client/render/entity/equipment/EquipmentModel$LayerType;Lnet/minecraft/registry/RegistryKey;Lnet/minecraft/client/model/Model;Ljava/lang/Object;Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/command/OrderedRenderCommandQueue;ILnet/minecraft/util/Identifier;II)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/RenderLayers;armorEntityGlint()Lnet/minecraft/client/render/RenderLayer;"))
private RenderLayer redirectArmorEntityGlint() {
GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class);
return glintPlus.getArmorEntityGlint();
}
}
@@ -0,0 +1,59 @@
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.render.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;ILnet/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()))
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,10 +1,12 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.event.events.PerspectiveChangeEvent;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.camera.Freecam;
import net.minecraft.client.option.GameOptions;
import net.minecraft.client.option.Perspective;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -14,8 +16,13 @@ import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
@Mixin(GameOptions.class)
public abstract class GameOptionsMixin {
@Shadow
public abstract Perspective getPerspective();
@Inject(method = "setPerspective", at = @At("HEAD"), cancellable = true)
private void changePerspective(Perspective perspective, CallbackInfo ci) {
if (getPerspective() == null) return;
if (ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled()) ci.cancel();
PerspectiveChangeEvent event = EVENT_BUS.post(new PerspectiveChangeEvent(perspective));
if (event.isCancelled()) ci.cancel();
}
Loaded 100 of 302 files, more files were not shown because too many files have changed in this diff. Show more