Compare commits

...
5 Commits
Author SHA1 Message Date
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
160 changed files with 6169 additions and 890 deletions

No files matched your search

+3 -1
View File
@@ -39,4 +39,6 @@ replay_*.log
*.hprof
*.jfr
todo.txt
todo.txt
test.java
cambios.md
+61
View File
@@ -0,0 +1,61 @@
# jenny's mod 2 100% real
mod para Minecraft Fabric 1.21.6 que añade algunas cosas QOL, mayormente relacionadas a la cámara.
## instalación
### para gente normal:
1. ir a [lanzamientos](https://github.com/retuci0/camera-tweaks/releases)
2. selecionar la versión más reciente
3. descargar el .jar
4. moverlo a tu directorio de mods (probablemente `%appdata%/.minecraft/mods`)
asegúrate de tener una version de Minecraft y Fabric compatibles con el mod (MC 1.21.6; Fabric 0.128.2)
es posible que hayan problemas al usarlo junto a otros mods, especialmente otros clientes, pues pueden conflictar
### 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
`$` como prefijo por defecto para comandos (se autocompletan)
algunos módulos tienen teclas asignadas por defecto, asígnales `ESC` para desactivar sus teclas
## 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">
## contibuciones
sí por favor
## licencia
no sé, haz lo que quieras con esto, es puta basura xd
+4
View File
@@ -29,6 +29,10 @@ dependencies {
}
loom {
accessWidenerPath = file("src/main/resources/camtweaks.accesswidener")
}
processResources {
inputs.property "version", project.version
+28
View File
@@ -0,0 +1,28 @@
# v1.3
## novedades
### adiciones
- barra de búsqueda: filtra los ajustes de todos los paneles de ajustes, por nombre y descripción
- barra de deslizamiento
- módulo de jugador falso: invoca una entidad de jugador falsa, por motivos de testeo
- HUD: mostrar información adicional en pantalla (ej.: hora, fps, coordenadas, ...)
### arreglos / mejoras
- mejoras a la interfaz
- ahora el color de los widgets depende del color principal
- ahora solo se puede seleccionar un objeto de la interfaz a la vez
- cambiada la posición de los títulos de los marcos
- ahora los módulos están ordenados por orden alfabético
- ahora nametags también tiene en cuenta la absorción de un jugador al mostrar su vida
- el color del prefijo de las notificaciones por chat ahora depende de los ajustes de color
- ya no se muestra el prefijo equivocado en notificaciones por chat al meterse a un mundo por primera vez
## problemas reconocidos
- muchos, pero repórtalos en la página de problemas si quieres para que queden bien registrados
+4 -2
View File
@@ -1,3 +1,5 @@
meteor client
meteor client dev team
oyvey client (1.21 port by mioclient)
lennyboi (youtube)
lennyboi (youtube)
packbar by cattyn on github
shotify mod
+1 -1
View File
@@ -10,7 +10,7 @@ loader_version=0.17.2
loom_version=1.11-SNAPSHOT
# Mod Properties
mod_version=1.0.0
mod_version=1.3
maven_group=me.retucio
archives_base_name=camtweaks
Binary file not shown.

After

Width:  |  Height:  |  Size: 864 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: 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()
@@ -1,48 +1,114 @@
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.ui.buttons.BindButton;
import me.retucio.camtweaks.ui.buttons.SettingButton;
import me.retucio.camtweaks.ui.buttons.TextButton;
import me.retucio.camtweaks.ui.frames.ClientSettingsFrame;
import me.retucio.camtweaks.ui.frames.SettingsFrame;
import me.retucio.camtweaks.util.ChatUtil;
import me.retucio.camtweaks.util.KeyUtil;
import me.retucio.camtweaks.util.Lists;
import me.retucio.camtweaks.util.MiscUtil;
import net.fabricmc.api.ClientModInitializer;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.TitleScreen;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.lwjgl.glfw.GLFW;
public class CameraTweaks implements ModInitializer {
public class CameraTweaks implements ClientModInitializer {
// cosas necesarias
public static final String MOD_ID = "camtweaks";
public static final CameraTweaks INSTANCE = new CameraTweaks();
public static final Logger LOGGER = LogManager.getLogger(CameraTweaks.class);
public static final EventBus EVENT_BUS = new EventBus();
public static final MinecraftClient mc = MinecraftClient.getInstance();
public static MinecraftClient mc;
private Screen prevScreen;
// managers
public static ModuleManager moduleManager = new ModuleManager(EVENT_BUS);
public static CommandManager commandManager = new CommandManager();
public boolean settingsApplied = false;
@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();
EVENT_BUS.register(this);
EVENT_BUS.register(MiscUtil.class);
EVENT_BUS.register(ChatUtil.class);
Lists.init();
ModuleManager.INSTANCE = new ModuleManager(EVENT_BUS);
EVENT_BUS.post(new LoadModuleManagerEvent());
CommandManager.INSTANCE = new CommandManager();
EVENT_BUS.post(new LoadCommandManagerEvent());
ClickGUI.INSTANCE = new ClickGUI();
EVENT_BUS.post(new LoadClickGUIEvent());
ConfigManager.load();
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
ConfigManager.save();
EVENT_BUS.post(new ShutdownEvent());
}));
}
// se ejecuta cada tick, es decir, 20 veces por segundo
public void onTick() {
ModuleManager.INSTANCE.getEnabledModules().forEach(Module::onTick);
if (!settingsApplied
&& ConfigManager.getConfig() != null
&& mc.player != null && mc.world != null) {
ConfigManager.applyConfig();
settingsApplied = true;
}
}
// se ejecuta cada vez que se presiona una tecla
public void onKeyPress(int key, int action) {
moduleManager.getEnabledModules().forEach(module -> module.onKey(key, action));
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 (BindCommand.onKeyPress(key)) return;
handleSettingButtonsKey(key, action);
handleModuleToggle(key, anyFocused);
handleClickGUIKey(key, anyFocused);
BindCommand.onKeyPress(key);
} else if (action == GLFW.GLFW_RELEASE && !anyFocused) {
handleModuleRelease(key);
}
@@ -50,12 +116,10 @@ public class CameraTweaks implements ModInitializer {
// verifica si algún botón de ajustes está escuchando
private boolean isAnySettingButtonFocused() {
for (SettingsFrame sf : ClickGUI.INSTANCE.getSettingsFrames()) {
for (SettingButton sb : sf.getButtons()) {
for (SettingsFrame sf : ClickGUI.INSTANCE.getSettingsFrames())
for (SettingButton sb : sf.getButtons())
if ((sb instanceof BindButton b && b.isFocused()) || (sb instanceof TextButton t && t.isFocused()))
return true;
}
}
return false;
}
@@ -63,8 +127,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);
@@ -85,12 +149,15 @@ public class CameraTweaks implements ModInitializer {
// 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) return;
if (mc.currentScreen != ClickGUI.INSTANCE) {
// al parecer esto hace que con la tecla de la interfaz puedas ir cambiando de splash text en la pantalla del título
// pero me ha hecho gracia así que así se queda
if (mc.currentScreen != ClickGUI.INSTANCE && !(mc.currentScreen instanceof TitleScreen)) {
prevScreen = mc.currentScreen;
mc.setScreen(ClickGUI.INSTANCE);
} else {
ClickGUI.INSTANCE.close();
mc.setScreen(prevScreen);
}
}
@@ -99,16 +166,13 @@ public class CameraTweaks implements ModInitializer {
private void handleModuleRelease(int key) {
if (mc.currentScreen != null && mc.currentScreen != ClickGUI.INSTANCE) return;
for (Module module : moduleManager.getEnabledModules()) {
if (module.shouldToggleOnBindRelease() && key == module.getKey()) {
for (Module module : ModuleManager.INSTANCE.getEnabledModules())
if (module.shouldToggleOnBindRelease() && key == module.getKey())
module.setEnabled(false);
}
}
}
// se ejecuta cada tick, es decir, 20 veces por segundo
public void onTick() {
if (mc.player == null) return;
moduleManager.getEnabledModules().forEach(Module::onTick);
@SubscribeEvent
public void onStop(ShutdownEvent event) {
ConfigManager.save();
}
}
@@ -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) {
@@ -9,10 +9,13 @@ import net.minecraft.command.CommandSource;
import java.util.ArrayList;
import java.util.List;
import java.util.Comparator;
import java.util.Objects;
// registro de comandos
public class CommandManager {
public static CommandManager INSTANCE;
private String prefix = "$";
public static final List<Command> commands = new ArrayList<>();
@@ -26,9 +29,15 @@ public class CommandManager {
public static void registerCommands() {
addCommand(new BindCommand());
addCommand(new ToggleCommand());
addCommand(new SendCommand());
addCommand(new CopyScreenshotCommand());
// addCommand(new EnderChestCommand()); no funciona D:
addCommand(new PeekCommand());
addCommand(new PrefixCommand());
addCommand(new PurgeCommand());
addCommand(new SaveScreenshotCommand());
addCommand(new SendCommand());
addCommand(new ToggleCommand());
commands.sort(Comparator.comparing(Command::getName));
}
@@ -39,13 +48,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;
}
@@ -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(
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);
String argument = reader.readString().replace("_", " ");
Module module = ModuleManager.INSTANCE.getModuleByName(argument);
if (module == null) throw unknownModuleE.create(argument);
return module;
}
@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
return CommandSource.suggestMatching(moduleManager.getModules().stream().map(Module::getName), builder);
return CommandSource.suggestMatching(ModuleManager.INSTANCE.getModules().stream().map(module -> module.getName().replace(" ", "_")), builder);
}
@Override
@@ -0,0 +1,60 @@
package me.retucio.camtweaks.command.args;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.command.CommandSource;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.text.Text;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import static me.retucio.camtweaks.CameraTweaks.mc;
// para autocompletar nombres de jugadores
public class PlayerArgumentType implements ArgumentType<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,31 @@ public class BindCommand extends Command {
.then(argument("módulo", ModuleArgumentType.INSTANCE)
.executes(ctx -> {
Module module = ctx.getArgument("módulo", Module.class);
listeningModule = module;
ChatUtil.info("presiona una tecla para asignarla al módulo " + module.getName());
ChatUtil.info("presiona una tecla para asignarla al módulo " + Formatting.GREEN + module.getName());
return SUCCESS;
})
.then(literal("reset").executes(ctx -> {
Module module = ctx.getArgument("módulo", Module.class);
module.getBind().reset();
ChatUtil.info("tecla para el módulo " + Formatting.GREEN + module.getName() + " restablecida a " + Formatting.AQUA + KeyUtil.getKeyName(module.getKey()));
return SUCCESS;
}))
);
}
public static void onKeyPress(int key) {
if (listeningModule != null) {
KeySetting bind = listeningModule.getBind();
if (bind != null)
bind.setKey(key);
public static boolean onKeyPress(int key) {
if (listeningModule == null) return false;
KeySetting bind = listeningModule.getBind();
if (bind != null)
bind.setKey(key);
ChatUtil.info(
Text.of("la tecla " + Formatting.AQUA + KeyUtil.getKeyName(key) + Formatting.RESET +
" ha sido asignada al módulo " + Formatting.GREEN + listeningModule.getName())
);
ChatUtil.info(
Text.of("la tecla " + Formatting.AQUA + KeyUtil.getKeyName(key) + Formatting.RESET +
" ha sido asignada al módulo " + Formatting.GREEN + listeningModule.getName())
);
listeningModule = null;
}
listeningModule = null;
return true;
}
}
@@ -0,0 +1,26 @@
package me.retucio.camtweaks.command.commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.camtweaks.command.Command;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.ScreenshotPlus;
import net.minecraft.command.CommandSource;
// se usa principalmente para el módulo ScreenshotPlus, pero también se puede usar sin él supongo
public class CopyScreenshotCommand extends Command {
public CopyScreenshotCommand() {
super("copiarcaptura", "copia la captura más reciente al portapapeles");
}
@Override
public void build(LiteralArgumentBuilder<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,37 @@
package me.retucio.camtweaks.command.commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.camtweaks.command.Command;
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
import net.minecraft.command.CommandSource;
import net.minecraft.inventory.EnderChestInventory;
import net.minecraft.inventory.Inventories;
import net.minecraft.inventory.Inventory;
import net.minecraft.inventory.SimpleInventory;
import net.minecraft.screen.GenericContainerScreenHandler;
import net.minecraft.text.Text;
// accede a los contenidos de tu enderchest
public class EnderChestCommand extends Command {
public EnderChestCommand() {
super("echest", "muestra el contenido de tu enderchest", "ec", "enderchest");
}
@Override
public void build(LiteralArgumentBuilder<CommandSource> builder) {
builder.executes(ctx -> {
mc.execute(() -> { // para evitar llamar setScreen desde el hilo equivocado, que causa crashes
EnderChestInventory enderChestInv = mc.player.getEnderChestInventory();
// llámame imbécil pero no tengo ni idea de por qué no se abre
mc.setScreen(new GenericContainerScreen(
GenericContainerScreenHandler.createGeneric9x3(mc.player.currentScreenHandler.syncId + 1, mc.player.getInventory(), enderChestInv),
mc.player.getInventory(),
Text.translatable("container.enderchest")
));
});
return SUCCESS;
});
}
}
@@ -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.frames.ClientSettingsFrame;
import me.retucio.camtweaks.util.ChatUtil;
import net.minecraft.command.CommandSource;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
// también se puede hacer desde los ajustes de la interfaz
public class PrefixCommand extends Command {
public PrefixCommand() {
@@ -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.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;
}));
}
}
}
@@ -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,110 @@
package me.retucio.camtweaks.config;
import me.retucio.camtweaks.event.SubscribeEvent;
import me.retucio.camtweaks.event.events.camtweaks.*;
import me.retucio.camtweaks.module.settings.*;
import me.retucio.camtweaks.ui.ClickGUI;
import java.util.HashMap;
import java.util.Map;
import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
import static me.retucio.camtweaks.CameraTweaks.mc;
// clase donde se guardan las configuraciones temporalmente hasta escribirlas en camera_tweaks.json
public class ClientConfig {
// nombre del módulo -> estado del módulo
public Map<String, Boolean> moduleStates = new HashMap<>();
// nombre del ajuste -> valor
public Map<String, Object> settings = new HashMap<>();
// nombre del módulo -> posición (x, y)
public Map<String, int[]> settingsFrames = new HashMap<>();
// nombre del frame -> FrameData (que contiene extended, x & y)
public Map<String, FrameData> extendableFrames = new HashMap<>();
public ClientConfig() {
EVENT_BUS.register(this);
}
@SubscribeEvent
public void onToggleModule(ToggleModuleEvent event) {
ConfigManager.setModuleState(event.getModule());
}
@SuppressWarnings("rawtypes")
@SubscribeEvent
public void onUpdateSetting(UpdateSettingEvent event) {
if (mc == null || !event.shouldSave()) return;
// guardar ajustes con su respectivo tipo de valor, en formato "nombreMódulo:nombreAjuste"
Object value = null;
switch (event.getSetting()) {
case BooleanSetting b: value = b.isEnabled(); break;
case EnumSetting e: value = e.getIndex(); break;
case KeySetting k: value = k.getKey(); break;
case NumberSetting n: value = n.getValue(); break;
case StringSetting s: value = s.getValue(); break;
case ListSetting l: value = l.getValues(); break;
default: break;
}
ConfigManager.setSetting(event.getSetting(), value);
}
@SubscribeEvent
public void onOpenSettingsFrame(SettingsFrameEvent.Open event) {
if (settingsFrames.containsKey(event.getFrame().module.getName())) return;
ConfigManager.setFramePosition(event.getFrame());
}
@SubscribeEvent
public void onCloseSettingsFrame(SettingsFrameEvent.Close event) {
settingsFrames.remove(event.getFrame().module.getName());
ConfigManager.save();
}
@SubscribeEvent
public void onMoveSettingsFrame(SettingsFrameEvent.Move event) {
settingsFrames.replace(event.getFrame().module.getName(), new int[]{event.getFrame().x, event.getFrame().y});
ConfigManager.save();
}
@SubscribeEvent
public void onExtendModuleFrame(ModuleFrameEvent.Extend event) {
extendableFrames.put("M", new FrameData(
ClickGUI.INSTANCE.getModulesFrame().x,
ClickGUI.INSTANCE.getModulesFrame().y,
ClickGUI.INSTANCE.getModulesFrame().extended));
}
@SubscribeEvent
public void onMoveModuleFrame(ModuleFrameEvent.Move event) {
extendableFrames.replace("M", new FrameData(
ClickGUI.INSTANCE.getModulesFrame().x,
ClickGUI.INSTANCE.getModulesFrame().y,
ClickGUI.INSTANCE.getModulesFrame().extended));
}
@SubscribeEvent
public void onExtendGUISettingsFrame(GUISettingsFrameEvent.Extend event) {
extendableFrames.put("S", new FrameData(
ClickGUI.INSTANCE.getGuiSettingsFrame().x,
ClickGUI.INSTANCE.getGuiSettingsFrame().y,
ClickGUI.INSTANCE.getGuiSettingsFrame().extended));
}
@SubscribeEvent
public void onMoveGUISettingsFrame(GUISettingsFrameEvent.Move event) {
extendableFrames.replace("S", new FrameData(
ClickGUI.INSTANCE.getGuiSettingsFrame().x,
ClickGUI.INSTANCE.getGuiSettingsFrame().y,
ClickGUI.INSTANCE.getGuiSettingsFrame().extended));
}
public record FrameData(int x, int y, boolean extended) {}
}
@@ -0,0 +1,156 @@
package me.retucio.camtweaks.config;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.settings.*;
import me.retucio.camtweaks.ui.ClickGUI;
import me.retucio.camtweaks.ui.frames.ClientSettingsFrame;
import me.retucio.camtweaks.ui.frames.SettingsFrame;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
// se ocupa de guardar, cargar y aplicar ajustes
// pues no me ha dado dolores de cabeza el coso este con los NPE de los cojones...
public class ConfigManager {
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private static final File CONFIG_FILE = new File("camera_tweaks.json");
private static ClientConfig config = null;
// guardar configuraciones
public static void save() {
ensureConfig();
try (FileWriter writer = new FileWriter(CONFIG_FILE)) {
GSON.toJson(config, writer);
CameraTweaks.LOGGER.info("ajustes guardados");
} catch (IOException e) {
e.printStackTrace();
}
}
// cargar configuraciones
public static void load() {
CameraTweaks.LOGGER.info("ajustes cargados");
if (!CONFIG_FILE.exists()) {
ensureConfig();
save();
return;
}
try (FileReader reader = new FileReader(CONFIG_FILE)) {
config = GSON.fromJson(reader, ClientConfig.class);
} catch (IOException e) {
e.printStackTrace();
ensureConfig();
}
}
// aplicar configuraciones cargadas
public static void applyConfig() {
if (CameraTweaks.mc == null || ModuleManager.INSTANCE == null || config == null)
return;
ModuleManager.INSTANCE.getModules().forEach(module -> {
if (config.moduleStates.containsKey(module.getName()))
module.setEnabled(config.moduleStates.get(module.getName())); // estados
module.getSettings().forEach(setting -> applySetting(module, setting));
if (config.settingsFrames.containsKey(module.getName())) {
int[] position = config.settingsFrames.get(module.getName());
ClickGUI.INSTANCE.openSettingsFrame(module, position[0], position[1]);
}
});
ClientSettingsFrame.guiSettings.setEnabled(true);
ClientSettingsFrame.guiSettings.getSettings().forEach(setting -> applySetting(ClientSettingsFrame.guiSettings, setting));
CameraTweaks.LOGGER.info("módulos encendidos cargados");
CameraTweaks.LOGGER.info("ajustes de módulos cargados");
ClientConfig.FrameData moduleFrameData = config.extendableFrames.get("M");
if (moduleFrameData != null) {
ClickGUI.INSTANCE.getModulesFrame().x = moduleFrameData.x();
ClickGUI.INSTANCE.getModulesFrame().y = moduleFrameData.y();
ClickGUI.INSTANCE.getModulesFrame().extended = moduleFrameData.extended();
}
ClientConfig.FrameData guiSettingsData = config.extendableFrames.get("S");
if (guiSettingsData != null) {
ClickGUI.INSTANCE.getGuiSettingsFrame().x = guiSettingsData.x();
ClickGUI.INSTANCE.getGuiSettingsFrame().y = guiSettingsData.y();
ClickGUI.INSTANCE.getGuiSettingsFrame().extended = guiSettingsData.extended();
}
CameraTweaks.LOGGER.info("posiciones de frames cargadas");
ClickGUI.INSTANCE.refreshListButtons();
}
public static ClientConfig getConfig() {
return config;
}
public static void setModuleState(Module module) {
ensureConfig();
config.moduleStates.put(module.getName(), module.isEnabled());
save();
}
public static void setSetting(AbstractSetting setting, Object value) {
ensureConfig();
config.settings.put(setting.getModule().getName() + ":" + setting.getName(), value);
save();
}
public static void setFramePosition(SettingsFrame frame) {
ensureConfig();
config.settingsFrames.put(frame.module.getName(), new int[]{frame.x, frame.y});
ConfigManager.save();
}
public static void setExtendableFrame(String key, ClientConfig.FrameData data) {
ensureConfig();
config.extendableFrames.put(key, data);
save();
}
@SuppressWarnings({"rawtypes", "unchecked"})
public static void applySetting(Module parent, AbstractSetting setting) {
String id = parent.getName() + ":" + setting.getName();
if (config.settings.containsKey(id)) {
Object value = config.settings.get(id);
switch (setting) {
case BooleanSetting b -> b.setEnabled((boolean) value);
case EnumSetting e -> e.setIndex(value instanceof Double val ? val.intValue() : (int) value);
case NumberSetting n -> n.setValue((double) value);
case StringSetting s -> s.setValue((String) value);
case KeySetting k -> k.setKey(value instanceof Double val ? val.intValue() : (int) value);
case ListSetting l -> {
if (value instanceof Map<?, ?> map) {
Map<Object, Boolean> converted = new HashMap<>();
for (Object option : l.getOptions()) {
Object key = String.valueOf(option);
Object bv = map.get(key);
converted.put(option, bv instanceof Boolean b && b);
}
l.setValues(converted);
}
} default -> {}
}
}
}
private static void ensureConfig() {
if (config == null) config = new ClientConfig();
}
}
@@ -1,6 +1,6 @@
package me.retucio.camtweaks.event;
// evento base, cancelable
// evento base, cancelable (usado en mixins)
public class Event {
private boolean cancelled;
@@ -1,6 +1,7 @@
package me.retucio.camtweaks.event;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
// al llamar un evento, se guarda en el bus de eventos, de donde luego se puede detectar si ese evento ha sucedido
@@ -10,28 +11,43 @@ public class EventBus {
private record ListenerMethod(Object instance, Method method) {}
public void register(Object listener) {
for (Method method : listener.getClass().getDeclaredMethods()) {
if (method.isAnnotationPresent(Subscribe.class)) {
if (method.getParameterCount() != 1) continue; // must take 1 param
Class<?> eventType = method.getParameterTypes()[0];
method.setAccessible(true);
Class<?> targetClass;
listeners.computeIfAbsent(eventType, k -> new ArrayList<>())
.add(new ListenerMethod(listener, method));
}
if (listener instanceof Class<?> clazz) {
targetClass = clazz; // "listeners" estáticos
listener = null;
} else {
targetClass = listener.getClass();
}
for (Method method : targetClass.getDeclaredMethods()) {
if (!method.isAnnotationPresent(SubscribeEvent.class)) continue;
if (method.getParameterCount() != 1) continue;
Class<?> eventType = method.getParameterTypes()[0];
method.setAccessible(true);
if (listener == null && !Modifier.isStatic(method.getModifiers())) continue;
listeners.computeIfAbsent(eventType, k -> new ArrayList<>())
.add(new ListenerMethod(listener, method));
}
}
public void subscribe(Object listener) { register(listener); }
public void unregister(Object listener) {
for (List<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 +68,4 @@ public class EventBus {
}
return false;
}
}
}
@@ -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,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 {}
@@ -2,6 +2,10 @@ package me.retucio.camtweaks.event.events;
import net.minecraft.text.ClickEvent;
/** este evento es solo para asegurarse de que comandos del mod se puedan ejecutar solo desde el lado del cliente
* @see me.retucio.camtweaks.module.modules.ChatPlus#getSendButton
*/
public class ClientClickEvent implements ClickEvent {
private final String value;
@@ -0,0 +1,9 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
/**
* @see me.retucio.camtweaks.mixin.ClientConnectionMixin#onDisconnect
*/
public class DisconnectEvent extends Event {}
@@ -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;
@@ -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,46 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import me.retucio.camtweaks.event.Stage;
import net.minecraft.network.packet.Packet;
/**
* @see me.retucio.camtweaks.mixin.ClientConnectionMixin#onSendPacketPre
* @see me.retucio.camtweaks.mixin.ClientConnectionMixin#onSendPacketPost
* @see me.retucio.camtweaks.mixin.ClientConnectionMixin#onReceivePacket
*/
public class PacketEvent {
public static class Send extends Event {
private final Packet<?> packet;
private final Stage stage;
public Send(Packet<?> packet, Stage stage) {
this.packet = packet;
this.stage = stage;
}
public Packet<?> getPacket() {
return packet;
}
public Stage getStage() {
return stage;
}
}
public static class Receive extends Event {
private final Packet<?> packet;
public Receive(Packet<?> packet) {
this.packet = packet;
}
public Packet<?> getPacket() {
return packet;
}
}
}
@@ -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;
@@ -4,6 +4,10 @@ import me.retucio.camtweaks.event.Event;
import net.minecraft.client.gui.hud.MessageIndicator;
import net.minecraft.text.Text;
/**
* @see me.retucio.camtweaks.mixin.ChatHudMixin#onAddMessage
*/
public class ReceiveMessageEvent extends Event {
private Text text;
@@ -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;
}
@@ -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,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,5 @@
package me.retucio.camtweaks.event.events.camtweaks;
import me.retucio.camtweaks.event.Event;
public class LoadClickGUIEvent extends Event {}
@@ -0,0 +1,5 @@
package me.retucio.camtweaks.event.events.camtweaks;
import me.retucio.camtweaks.event.Event;
public class LoadCommandManagerEvent extends Event {}
@@ -0,0 +1,5 @@
package me.retucio.camtweaks.event.events.camtweaks;
import me.retucio.camtweaks.event.Event;
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.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.AbstractSetting;
// se genera cada que se cambia el valor de un ajuste
public class UpdateSettingEvent extends Event {
private final AbstractSetting setting;
private boolean shouldSave;
public UpdateSettingEvent(AbstractSetting setting, boolean shouldSave) {
this.setting = setting;
this.shouldSave = shouldSave;
}
public AbstractSetting getSetting() {
return setting;
}
public boolean shouldSave() {
return shouldSave;
}
public void shouldSave(boolean value) {
this.shouldSave = value;
}
}
@@ -0,0 +1,38 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.sugar.Local;
import me.retucio.camtweaks.event.events.RenderBossbarEvent;
import net.minecraft.client.gui.hud.BossBarHud;
import net.minecraft.client.gui.hud.ClientBossBar;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Constant;
import org.spongepowered.asm.mixin.injection.ModifyConstant;
import java.util.Iterator;
import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
@Mixin(BossBarHud.class)
public class BossBarHudMixin {
@ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Ljava/util/Collection;iterator()Ljava/util/Iterator;"))
public Iterator<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();
}
}
@@ -1,29 +1,94 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.module.modules.Perspective;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Freelook;
import me.retucio.camtweaks.module.modules.Freecam;
import me.retucio.camtweaks.module.modules.PerspectivePlus;
import net.minecraft.client.render.Camera;
import net.minecraft.entity.Entity;
import net.minecraft.world.BlockView;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArgs;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import static me.retucio.camtweaks.CameraTweaks.moduleManager;
import org.spongepowered.asm.mixin.injection.invoke.arg.Args;
@Mixin(Camera.class)
public abstract class CameraMixin {
@Unique
private float tickDelta;
@Unique
PerspectivePlus perspectivePlus;
@Unique
Freecam freecam;
@Unique
Freelook freelook;
@Shadow
private boolean thirdPerson;
@Inject(method = "<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(BlockView area, Entity focusedEntity, boolean thirdPerson, boolean inverseView, float tickDelta, CallbackInfo info) {
this.tickDelta = tickDelta;
}
// perspectiva
@ModifyVariable(method = "clipToSpace", at = @At("HEAD"), ordinal = 0, argsOnly = true)
private float modifyClipToSpace(float distance) {
Perspective perspective = moduleManager.getModuleByClass(Perspective.class);
return perspective.isEnabled() ? (float) perspective.getDistance() : distance;
if (freecam.isEnabled()) return 0;
return perspectivePlus.isEnabled() ? (float) perspectivePlus.getDistance() : distance;
}
@Inject(method = "clipToSpace", at = @At("HEAD"), cancellable = true)
private void onClipToSpace(float distance, CallbackInfoReturnable<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(BlockView area, Entity focusedEntity, boolean thirdPerson, boolean inverseView, float tickDelta, CallbackInfo info) {
if (freecam.isEnabled())
this.thirdPerson = true;
}
@ModifyArgs(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/Camera;setPos(DDD)V"))
private void onUpdateSetPosArgs(Args args) {
if (freecam.isEnabled()) {
args.set(0, freecam.getX(tickDelta));
args.set(1, freecam.getY(tickDelta));
args.set(2, freecam.getZ(tickDelta));
}
}
@ModifyArgs(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/Camera;setRotation(FF)V"))
private void onUpdateSetRotationArgs(Args args) {
if (freecam.isEnabled()) {
args.set(0, freecam.getYaw(tickDelta));
args.set(1, freecam.getPitch(tickDelta));
} else if (freelook.isEnabled()) {
args.set(0, freelook.getYaw());
args.set(1, freelook.getPitch());
}
}
}
@@ -4,11 +4,13 @@ import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.ModifyReceiver;
import com.llamalad7.mixinextras.sugar.Local;
import me.retucio.camtweaks.event.events.ReceiveMessageEvent;
import me.retucio.camtweaks.module.modules.BetterChat;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.ChatPlus;
import me.retucio.camtweaks.util.interfaces.IChatHud;
import me.retucio.camtweaks.util.interfaces.IChatHudLine;
import me.retucio.camtweaks.util.interfaces.IChatHudLineVisible;
import me.retucio.camtweaks.util.interfaces.IMessageHandler;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.hud.ChatHud;
@@ -39,8 +41,8 @@ public abstract class ChatHudMixin implements IChatHud {
@Unique
private int nextId;
@Unique @Final
private BetterChat betterChat = moduleManager.getModuleByClass(BetterChat.class);
@Unique
ChatPlus chatPlus;
@Shadow @Final
private List<ChatHudLine> messages;
@@ -54,7 +56,10 @@ public abstract class ChatHudMixin implements IChatHud {
@Shadow
public abstract void addMessage(Text message, @Nullable MessageSignatureData signatureData, @Nullable MessageIndicator indicator);
@Inject(method = "<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
@@ -98,6 +103,11 @@ public abstract class ChatHudMixin implements IChatHud {
return line;
}
@Override
public List<ChatHudLine.Visible> smegma$getVisibleMessages() {
return visibleMessages;
}
// modificar contenido del mensaje
@@ -115,7 +125,7 @@ public abstract class ChatHudMixin implements IChatHud {
for (int i = messages.size() - 1; i > -1; i--) {
if (((IChatHudLine) (Object) messages.get(i)).smegma$getId() == nextId && nextId != 0) {
messages.remove(i);
betterChat.removeLine(i);
chatPlus.removeLine(i);
}
}
@@ -135,18 +145,18 @@ public abstract class ChatHudMixin implements IChatHud {
@ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;ceil(F)I"))
private int onRender_modifyWidth(int width) {
return (betterChat.isEnabled() && betterChat.showHeads.isEnabled()) ? width + 10 : width;
return (chatPlus.isEnabled() && chatPlus.showHeads.isEnabled()) ? width + 10 : width;
}
@ModifyReceiver(method = "method_71991", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTextWithShadow(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/OrderedText;III)V"))
private DrawContext onRender_beforeDrawTextWithShadow(DrawContext context, TextRenderer textRenderer, OrderedText text, int x, int y, int color, @Local(argsOnly = true) ChatHudLine.Visible line) {
betterChat.beforeDrawMessage(context, line, y, color);
chatPlus.beforeDrawMessage(context, line, y, color);
return context;
}
@Inject(method = "method_71991", at = @At("TAIL"))
private void onRender_afterDrawTextWithShadow(int i, DrawContext context, float f, int j, int k, int l, ChatHudLine.Visible visible, int m, float g, CallbackInfo info) {
betterChat.afterDrawMessage(context);
chatPlus.afterDrawMessage(context);
}
@@ -155,40 +165,39 @@ public abstract class ChatHudMixin implements IChatHud {
@ModifyExpressionValue(method = "addMessage(Lnet/minecraft/client/gui/hud/ChatHudLine;)V", at = @At(value = "CONSTANT", args = "intValue=100"))
private int maxLength(int size) {
if (!betterChat.isEnabled()) return size;
return size + betterChat.chatHistoryExtraLength.getIntValue();
if (!chatPlus.isEnabled()) return size;
return size + chatPlus.chatHistoryExtraLength.getIntValue();
}
@ModifyExpressionValue(method = "addVisibleMessage", at = @At(value = "CONSTANT", args = "intValue=100"))
private int maxLengthVisible(int size) {
if (!betterChat.isEnabled()) return size;
return size + betterChat.chatHistoryExtraLength.getIntValue();
if (!chatPlus.isEnabled()) return size;
return size + chatPlus.chatHistoryExtraLength.getIntValue();
}
@Inject(method = "addVisibleMessage", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;isChatFocused()Z"))
private void onBreakChatMessageLines(ChatHudLine message, CallbackInfo ci, @Local List<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;"))
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.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,34 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Freecam;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.debug.ChunkBorderDebugRenderer;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.ChunkSectionPos;
import net.minecraft.util.math.MathHelper;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(ChunkBorderDebugRenderer.class)
public abstract class ChunkBorderDebugRendererMixin {
@Shadow @Final
private MinecraftClient client;
@ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getChunkPos()Lnet/minecraft/util/math/ChunkPos;"))
private ChunkPos getChunkPos(ChunkPos chunkPos) {
Freecam freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
if (!freecam.isEnabled()) return chunkPos;
float delta = client.getRenderTickCounter().getTickProgress(true);
return new ChunkPos(
ChunkSectionPos.getSectionCoord(MathHelper.floor(freecam.getX(delta))),
ChunkSectionPos.getSectionCoord(MathHelper.floor(freecam.getZ(delta))));
}
}
@@ -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,52 @@
package me.retucio.camtweaks.mixin;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import me.retucio.camtweaks.event.Stage;
import me.retucio.camtweaks.event.events.DisconnectEvent;
import me.retucio.camtweaks.event.events.PacketEvent;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.DisconnectionInfo;
import net.minecraft.network.packet.Packet;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
@Mixin(ClientConnection.class)
public abstract class ClientConnectionMixin {
// mandar paquetes
@Inject(method = "send(Lnet/minecraft/network/packet/Packet;Lio/netty/channel/ChannelFutureListener;)V", at = @At("HEAD"), cancellable = true)
private void onSendPacketPre(Packet<?> packet, ChannelFutureListener channelFutureListener, CallbackInfo ci) {
PacketEvent.Send event = EVENT_BUS.post(new PacketEvent.Send(packet, Stage.PRE));
if (event.isCancelled()) ci.cancel();
}
@Inject(method = "send(Lnet/minecraft/network/packet/Packet;Lio/netty/channel/ChannelFutureListener;)V", at = @At("TAIL"), cancellable = true)
private void onSendPacketPost(Packet<?> packet, ChannelFutureListener channelFutureListener, CallbackInfo ci) {
PacketEvent.Send event = EVENT_BUS.post(new PacketEvent.Send(packet, Stage.POST));
if (event.isCancelled()) ci.cancel();
}
// recibir paquetes
@Inject(method = "channelRead0(Lio/netty/channel/ChannelHandlerContext;Lnet/minecraft/network/packet/Packet;)V", at = @At("HEAD"), cancellable = true)
private void onReceivePacket(ChannelHandlerContext context, Packet<?> packet, CallbackInfo ci) {
PacketEvent.Receive event = EVENT_BUS.post(new PacketEvent.Receive(packet));
if (event.isCancelled()) ci.cancel();
}
// otros
@Inject(method = "disconnect(Lnet/minecraft/network/DisconnectionInfo;)V", at = @At("HEAD"), cancellable = true)
private void onDisconnect(DisconnectionInfo disconnectionInfo, CallbackInfo ci) {
DisconnectEvent event = EVENT_BUS.post(new DisconnectEvent());
if (event.isCancelled()) ci.cancel();
}
}
@@ -3,13 +3,19 @@ package me.retucio.camtweaks.mixin;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import me.retucio.camtweaks.command.CommandManager;
import me.retucio.camtweaks.event.events.SendMessageEvent;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.NoRender;
import me.retucio.camtweaks.util.ChatUtil;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.camtweaks.CameraTweaks.*;
@@ -26,7 +32,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 +44,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 +52,10 @@ 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(Items.TOTEM_OF_UNDYING.getDefaultStack());
}
}
@@ -0,0 +1,48 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Freecam;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerInteractionManager;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ClientPlayerInteractionManager.class)
public abstract class ClientPlayerInteractionManagerMixin {
@Unique
Freecam freecam;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(MinecraftClient client, ClientPlayNetworkHandler networkHandler, CallbackInfo ci) {
freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
}
// los paquetes ya se cancelan en la clase de Freecam, pero visualmente el bloque sigue apareciendo roto
@Inject(method = "breakBlock", at = @At("HEAD"), cancellable = true)
private void cancelBlockBreaking(BlockPos pos, CallbackInfoReturnable<Boolean> cir) {
if (freecam.isEnabled() && freecam.cancelActionPackets.isEnabled()) cir.setReturnValue(false);
}
@Inject(method = "interactBlock", at = @At("HEAD"), cancellable = true)
private void cancelBlockPlacement(ClientPlayerEntity player, Hand hand, BlockHitResult hitResult, CallbackInfoReturnable<ActionResult> cir) {
if (freecam.isEnabled() && freecam.cancelActionPackets.isEnabled()) cir.setReturnValue(ActionResult.FAIL);
}
@Inject(method = "interactEntity", at = @At("HEAD"), cancellable = true)
private void cancelEntityInteractions(PlayerEntity player, Entity entity, Hand hand, CallbackInfoReturnable<ActionResult> cir) {
if (freecam.isEnabled() && freecam.cancelActionPackets.isEnabled()) cir.setReturnValue(ActionResult.FAIL);
}
}
@@ -0,0 +1,19 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.TimeChanger;
import net.minecraft.client.world.ClientWorld;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ClientWorld.Properties.class)
public abstract class ClientWorldPropertiesMixin {
@Inject(method = "setTimeOfDay", at = @At("HEAD"), cancellable = true)
private void setTimeOfDay(long time, CallbackInfo ci) { // de no ser por esto, se verían "flashes" del tiempo real en el cielo
TimeChanger timeChanger = ModuleManager.INSTANCE.getModuleByClass(TimeChanger.class);
if (timeChanger.isEnabled() && time != timeChanger.time.getLongValue()) ci.cancel();
}
}
@@ -0,0 +1,48 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Freecam;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.item.property.numeric.CompassState;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.camtweaks.CameraTweaks.mc;
@Mixin(CompassState.class)
public abstract class CompassStateMixin {
@Unique
private static Freecam freecam;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(boolean wobble, CompassState.Target target, CallbackInfo ci) {
freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
}
@ModifyExpressionValue(method = "getBodyYaw", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getBodyYaw()F"))
private static float getBodyYaw(float original) {
if (freecam.isEnabled()) return mc.gameRenderer.getCamera().getYaw();
return original;
}
@ModifyReturnValue(method = "getAngleTo(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/math/BlockPos;)D", at = @At("RETURN"))
private static double getAngleTo(double original, Entity entity, BlockPos blockPos) {
if (freecam.isEnabled()) {
Vec3d vec3d = Vec3d.ofCenter(blockPos);
Camera camera = mc.gameRenderer.getCamera();
return Math.atan2(vec3d.getZ() - camera.getPos().z, vec3d.getX() - camera.getPos().x) / (float) (Math.PI * 2);
}
return original;
}
}
@@ -0,0 +1,57 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.CritsPlus;
import net.minecraft.client.particle.DamageParticle;
import net.minecraft.client.particle.ParticleTextureSheet;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import java.awt.*;
@Mixin(DamageParticle.class)
public abstract class DamageParticleMixin {
@ModifyReturnValue(method = "getType", at = @At("RETURN"))
private ParticleTextureSheet makeCritsTranslucent(ParticleTextureSheet original) {
if (ModuleManager.INSTANCE.getModuleByClass(CritsPlus.class).isEnabled()) return ParticleTextureSheet.PARTICLE_SHEET_TRANSLUCENT;
return original;
}
}
@Mixin(DamageParticle.Factory.class)
abstract class DamageParticleFactoryMixin {
@ModifyVariable(method = "createParticle(Lnet/minecraft/particle/SimpleParticleType;Lnet/minecraft/client/world/ClientWorld;DDDDDD)Lnet/minecraft/client/particle/Particle;", at = @At(value = "STORE"))
private DamageParticle modifyCritColor(DamageParticle original) {
CritsPlus crits = ModuleManager.INSTANCE.getModuleByClass(CritsPlus.class);
if (!crits.isEnabled()) return original;
if (crits.rainbow.isEnabled()) {
float speed = 10001 - crits.rainbowSpeed.getFloatValue();
float hue = (System.currentTimeMillis() % (int) speed) / speed;
Color gamning = Color.getHSBColor(hue, 1, 1);
original.setColor(
gamning.getRed() / 255f,
gamning.getGreen() / 255f,
gamning.getBlue() / 255f);
} else {
original.setColor(
crits.red.getFloatValue() / 255f,
crits.green.getFloatValue() / 255f,
crits.blue.getFloatValue() / 255f);
}
original.alpha = crits.alpha.getFloatValue() / 255f;
original.scale *= crits.scale.getFloatValue();
original.velocityMultiplier *= crits.velocityMultipler.getFloatValue();
original.gravityStrength *= crits.gravity.getFloatValue();
original.setMaxAge(crits.maxAge.getIntValue());
original.collidesWithWorld = crits.collide.isEnabled();
return original;
}
}
@@ -0,0 +1,22 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.TimeChanger;
import net.minecraft.world.dimension.DimensionType;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import static me.retucio.camtweaks.CameraTweaks.mc;
@Mixin(DimensionType.class)
public abstract class DimensionTypeMixin {
@ModifyReturnValue(method = "getMoonPhase", at = @At("RETURN"))
private int overrideMoonPhase(int original) {
TimeChanger timeChanger = ModuleManager.INSTANCE.getModuleByClass(TimeChanger.class);
if (timeChanger.isEnabled() && mc.world != null && !timeChanger.moonPhase.is(TimeChanger.MoonPhases.DEFAULT))
return timeChanger.getMoonPhase();
return original;
}
}
@@ -0,0 +1,19 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.NoRender;
import net.minecraft.particle.EntityEffectParticleEffect;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(EntityEffectParticleEffect.class)
public abstract class EntityEffectParticleEffectMixin {
@Inject(method = "getAlpha", at = @At("HEAD"), cancellable = true)
private void noRenderPotionParticles(CallbackInfoReturnable<Float> cir) {
NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
if (noRender.isEnabled()) cir.setReturnValue(256 - noRender.potionParticleAlpha.getFloatValue());
}
}
@@ -0,0 +1,125 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.AntiInvis;
import me.retucio.camtweaks.module.modules.Freecam;
import me.retucio.camtweaks.module.modules.Freelook;
import me.retucio.camtweaks.module.modules.Nametags;
import me.retucio.camtweaks.util.ChatUtil;
import net.minecraft.entity.*;
import net.minecraft.entity.passive.TameableEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import static me.retucio.camtweaks.CameraTweaks.mc;
@Mixin(Entity.class)
public abstract class EntityMixin {
@Shadow
public abstract Text getName();
@Shadow
public abstract EntityType<?> getType();
@Unique
Freecam freecam;
@Unique
Freelook freelook;
@Unique
Nametags nametags;
@SuppressWarnings("rawtypes")
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(EntityType type, World world, CallbackInfo ci) {
freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
freelook = ModuleManager.INSTANCE.getModuleByClass(Freelook.class);
nametags = ModuleManager.INSTANCE.getModuleByClass(Nametags.class);
}
// cámara libre & perspectiva libre
@SuppressWarnings("ConstantConditions")
@Inject(method = "changeLookDirection", at = @At("HEAD"), cancellable = true)
private void onChangeLookDirection(double cursorDeltaX, double cursorDeltaY, CallbackInfo ci) {
if ((Object) this != mc.player) return;
if (freecam.isEnabled()) {
freecam.changeLookDirection(cursorDeltaX * 0.15, cursorDeltaY * 0.15);
ci.cancel();
} else if (freelook.isEnabled() && freelook.mode.is(Freelook.CameraMode.CAMERA)) {
freelook.setYaw(freelook.getYaw() + (float) (cursorDeltaX / freelook.mouseSens.getFloatValue()));
freelook.setPitch(freelook.getPitch() + (float) (cursorDeltaY / freelook.mouseSens.getFloatValue()));
if (Math.abs(freelook.getPitch()) > 90.0F) freelook.setPitch(freelook.getPitch() > 0 ? 90 : -90);
ci.cancel();
}
}
// nametags
@SuppressWarnings("ConstantConditions")
@ModifyReturnValue(method = "isCustomNameVisible", at = @At("RETURN"))
private boolean renderEntityNametags(boolean original) {
if (!nametags.isEnabled()) return original;
if ((Object) this instanceof PersistentProjectileEntity p && p.isOnGround()) return false;
return nametags.entities.isEnabled((this.getType()));
}
@ModifyReturnValue(method = "getName", at = @At("RETURN"))
private Text showProjectileDamage(Text original) {
if (!nametags.isEnabled() || !nametags.showProjectileDamage.isEnabled()) return original;
if ((Object) this instanceof PersistentProjectileEntity arrow) { // aunque lo llame "arrow", también cubre flechas espectrales y tridentes
String damage = nametags.getArrowDamage(arrow);
if (!damage.equals("0")) return original.copy().append(Text.literal(" (" + damage + ")").formatted(Formatting.RED));
}
return original;
}
@SuppressWarnings("ConstantConditions")
@ModifyReturnValue(method = "getCustomName", at = @At("RETURN"))
private Text displayEntityOwner(Text original) {
if (!nametags.isEnabled() || !nametags.petOwner.isEnabled()) return original;
if ((Object) this instanceof TameableEntity entity && entity.getOwnerReference() != null) {
if (original != null) return original.copy().append(" (de " + nametags.getOwnerName(entity.getOwnerReference()) + ")");
else return Text.of(nametags.getOwnerName(entity.getOwnerReference()));
}
return original;
}
@SuppressWarnings("ConstantConditions")
@ModifyReturnValue(method = "getName", at = @At("RETURN"))
private Text showBabies(Text original) {
if (!nametags.isEnabled() || !nametags.distinguishBabies.isEnabled()) return original;
if ((Object) this instanceof LivingEntity entity && entity.isBaby()) return original.copy().append(" (baby)");
return original;
}
// otros
@Inject(method = "isInvisibleTo", at = @At("RETURN"), cancellable = true)
public void renderInvisPlayers(PlayerEntity player, CallbackInfoReturnable<Boolean> cir) {
if (ModuleManager.INSTANCE.getModuleByClass(AntiInvis.class).isEnabled()) cir.setReturnValue(false);
}
}
@@ -0,0 +1,60 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.NoRender;
import net.minecraft.block.enums.CameraSubmersionType;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.fog.FogModifier;
import net.minecraft.client.render.fog.FogRenderer;
import net.minecraft.entity.Entity;
import org.joml.Vector4f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(FogRenderer.class)
public abstract class FogRendererMixin {
@Unique
NoRender noRender;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(CallbackInfo ci) {
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
}
@Redirect(method = "applyFog(Lnet/minecraft/client/render/Camera;IZLnet/minecraft/client/render/RenderTickCounter;FLnet/minecraft/client/world/ClientWorld;)Lorg/joml/Vector4f;", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/fog/FogModifier;shouldApply(Lnet/minecraft/block/enums/CameraSubmersionType;Lnet/minecraft/entity/Entity;)Z"))
private boolean noRenderFogs(FogModifier instance, CameraSubmersionType cameraSubmersionType, Entity entity) {
if (!noRender.isEnabled()) return instance.shouldApply(cameraSubmersionType, entity);
String className = instance.getClass().getSimpleName();
if ((className.equals("BlindnessEffectFogModifier") && !noRender.blindnessEffect.isEnabled())
|| (className.equals("DarknessEffectFogModifier") && !noRender.darknessEffect.isEnabled())
|| ((className.equals("LavaFogModifier") || className.equals("WaterFogModifier")
|| className.equals("PowederSnowFogModifier")) && !noRender.fluidOverlay.isEnabled())
|| (className.equals("DimensionOrBossFogModifier") && !noRender.dimensionFog.isEnabled()))
return false;
return instance.shouldApply(cameraSubmersionType, entity);
}
@ModifyReturnValue(method = "getFogColor", at = @At("RETURN"))
private Vector4f modifyLavaFog(Vector4f original, Camera camera) {
if (noRender.isEnabled() && !noRender.fluidOverlay.isEnabled() &&
(camera.getSubmersionType() == CameraSubmersionType.LAVA
|| camera.getSubmersionType() == CameraSubmersionType.WATER))
return new Vector4f(original.x, original.y, original.z, 0f);
return original;
}
@ModifyExpressionValue(method = "getFogColor", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getUnderwaterVisibility()F"))
private float noRenderUnderwaterFog(float original) {
return (noRender.isEnabled() && !noRender.fluidOverlay.isEnabled()) ? 0 : original;
}
}
@@ -1,10 +1,12 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.event.events.PerspectiveChangeEvent;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Freecam;
import net.minecraft.client.option.GameOptions;
import net.minecraft.client.option.Perspective;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -14,8 +16,13 @@ import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
@Mixin(GameOptions.class)
public abstract class GameOptionsMixin {
@Shadow
public abstract Perspective getPerspective();
@Inject(method = "setPerspective", at = @At("HEAD"), cancellable = true)
private void changePerspective(Perspective perspective, CallbackInfo ci) {
if (getPerspective() == null) return;
if (ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled()) ci.cancel();
PerspectiveChangeEvent event = EVENT_BUS.post(new PerspectiveChangeEvent(perspective));
if (event.isCancelled()) ci.cancel();
}
@@ -1,17 +1,26 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.event.events.GetFOVEvent;
import me.retucio.camtweaks.event.events.RenderEvent;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Freecam;
import me.retucio.camtweaks.module.modules.NoRender;
import me.retucio.camtweaks.module.modules.Zoom;
import me.retucio.camtweaks.util.interfaces.IVec3d;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.BufferBuilderStorage;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.render.RenderTickCounter;
import net.minecraft.client.render.item.HeldItemRenderer;
import net.minecraft.entity.Entity;
import org.joml.Matrix4f;
import org.joml.Vector3d;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
@@ -20,21 +29,88 @@ import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
public abstract class GameRendererMixin {
@Unique
Zoom zoom = CameraTweaks.moduleManager.getModuleByClass(Zoom.class);
boolean freecamDone;
@Unique
Zoom zoom;
@Unique
Freecam freecam;
@Unique
NoRender noRender;
@Shadow @Final
private MinecraftClient client;
@Shadow
public abstract void updateCrosshairTarget(float tickDelta);
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(MinecraftClient client, HeldItemRenderer firstPersonHeldItemRenderer, BufferBuilderStorage buffers, CallbackInfo ci) {
zoom = ModuleManager.INSTANCE.getModuleByClass(Zoom.class);;
freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
}
@ModifyReturnValue(method = "getFov", at = @At("RETURN"))
private float modifyFov(float original) {
return EVENT_BUS.post(new GetFOVEvent(original)).getFov();
}
// @Inject(method = "render", at = @At("HEAD"))
// private void onRender(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci) {
// CameraTweaks.INSTANCE.EVENT_BUS.post(new RenderEvent());
// }
@Inject(method = "updateCrosshairTarget", at = @At("HEAD"), cancellable = true)
private void updateTargetedEntityInvoke(float tickDelta, CallbackInfo ci) {
if ((freecam.isEnabled()) && client.getCameraEntity() != null && !freecamDone) {
ci.cancel();
Entity cameraEntity = client.getCameraEntity();
Vector3d pos = freecam.getPos();
Vector3d prevPos = freecam.getPrevPos();
double x = cameraEntity.getX();
double y = cameraEntity.getY();
double z = cameraEntity.getZ();
double lastX = cameraEntity.lastX;
double lastY = cameraEntity.lastY;
double lastZ = cameraEntity.lastZ;
float yaw = cameraEntity.getYaw();
float pitch = cameraEntity.getPitch();
float lastYaw = cameraEntity.lastYaw;
float lastPitch = cameraEntity.lastPitch;
((IVec3d) cameraEntity.getPos()).smegma$set(pos.x, pos.y - cameraEntity.getEyeHeight(cameraEntity.getPose()), pos.z);
cameraEntity.lastX = prevPos.x;
cameraEntity.lastY = prevPos.y - cameraEntity.getEyeHeight(cameraEntity.getPose());
cameraEntity.lastZ = prevPos.z;
cameraEntity.setYaw(freecam.getYaw());
cameraEntity.setPitch(freecam.getPitch());
cameraEntity.lastYaw = freecam.getPrevYaw();
cameraEntity.lastPitch = freecam.getPrevPitch();
freecamDone = true;
updateCrosshairTarget(tickDelta);
freecamDone = false;
((IVec3d) cameraEntity.getPos()).smegma$set(x, y, z);
cameraEntity.lastX = lastX;
cameraEntity.lastY = lastY;
cameraEntity.lastZ = lastZ;
cameraEntity.setYaw(yaw);
cameraEntity.setPitch(pitch);
cameraEntity.lastYaw = lastYaw;
cameraEntity.lastPitch = lastPitch;
}
}
@Inject(method = "renderHand", at = @At("HEAD"), cancellable = true)
private void renderHand(float tickProgress, boolean sleeping, Matrix4f positionMatrix, CallbackInfo ci) {
if (zoom.isEnabled() && !zoom.showHands.isEnabled())
if ((zoom.isEnabled() && !zoom.showHands.isEnabled())
|| (freecam.isEnabled() && !freecam.renderHands.isEnabled()))
ci.cancel();
}
@ModifyVariable(method = "renderWorld", ordinal = 6, at = @At(value = "STORE"))
private float noRenderNauseaDistortion(float scaledNauseaEffectFactor) {
return (noRender.isEnabled() && !noRender.nauseaEffect.isEnabled()) ? 0 : scaledNauseaEffectFactor;
}
}
@@ -1,37 +1,69 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.event.events.HeldItemRendererEvent;
import me.retucio.camtweaks.event.events.RenderHeldItemEvent;
import me.retucio.camtweaks.event.events.RenderArmEvent;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.HandView;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.item.ItemModelManager;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.EntityRenderDispatcher;
import net.minecraft.client.render.item.HeldItemRenderer;
import net.minecraft.client.render.item.ItemRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Arm;
import net.minecraft.util.Hand;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
import static me.retucio.camtweaks.CameraTweaks.moduleManager;
import static me.retucio.camtweaks.CameraTweaks.*;
@Mixin(HeldItemRenderer.class)
public abstract class HeldItemRendererMixin {
@Unique
HandView handView = moduleManager.getModuleByClass(HandView.class);
HandView handView;
@Shadow
private float equipProgressMainHand;
@Shadow
private float equipProgressOffHand;
@Shadow
private ItemStack mainHand;
@Shadow
private ItemStack offHand;
@Shadow
protected abstract boolean shouldSkipHandAnimationOnSwap(ItemStack from, ItemStack to);
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(MinecraftClient client, EntityRenderDispatcher entityRenderDispatcher, ItemRenderer itemRenderer, ItemModelManager itemModelManager, CallbackInfo ci) {
handView = ModuleManager.INSTANCE.getModuleByClass(HandView.class);
}
@Inject(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ItemDisplayContext;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", shift = At.Shift.BEFORE))
private void onRenderItem(AbstractClientPlayerEntity player, float tickDelta, float pitch, Hand hand, float swingProgress, ItemStack item, float equipProgress, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) {
EVENT_BUS.post(new HeldItemRendererEvent(matrices, hand));
EVENT_BUS.post(new RenderHeldItemEvent(matrices, hand));
}
@Inject(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderArmHoldingItem(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IFFLnet/minecraft/util/Arm;)V"))
private void onRenderArm(AbstractClientPlayerEntity player, float tickDelta, float pitch, Hand hand, float swingProgress, ItemStack item, float equipProgress, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) {
EVENT_BUS.post(new RenderArmEvent(matrices, hand));
}
@ModifyReturnValue(method = "shouldSkipHandAnimationOnSwap", at = @At("RETURN"))
private boolean modifySkipSwapAnimation(boolean original) {
return original || (handView.isEnabled() && handView.skipSwapping.isEnabled());
@@ -42,8 +74,18 @@ public abstract class HeldItemRendererMixin {
if (handView.isEnabled() && handView.noFood.isEnabled()) ci.cancel();
}
@Inject(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderArmHoldingItem(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IFFLnet/minecraft/util/Arm;)V"))
private void onRenderArm(AbstractClientPlayerEntity player, float tickDelta, float pitch, Hand hand, float swingProgress, ItemStack item, float equipProgress, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) {
EVENT_BUS.post(new RenderArmEvent(matrices, hand));
@ModifyArg(method = "updateHeldItems", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;clamp(FFF)F", ordinal = 2), index = 0)
private float modifyEquipProgressMainhand(float value) {
if (mc.player == null) return value;
float progress = mc.player.getAttackCooldownProgress(1);
float modified = handView.isEnabled() && handView.oldAnimations.isEnabled() ? 1 : (float) Math.pow(progress, 3);
return (shouldSkipHandAnimationOnSwap(mainHand, mc.player.getMainHandStack()) ? modified : 0) - equipProgressMainHand;
}
}
@ModifyArg(method = "updateHeldItems", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;clamp(FFF)F", ordinal = 3), index = 0)
private float modifyEquipProgressOffhand(float value) {
if (mc.player == null) return value;
return (shouldSkipHandAnimationOnSwap(offHand, mc.player.getOffHandStack()) ? 1 : 0) - equipProgressOffHand;
}
}
@@ -1,28 +1,82 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.modules.BetterChat;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.ChatPlus;
import me.retucio.camtweaks.module.modules.Freecam;
import me.retucio.camtweaks.module.modules.NoRender;
import me.retucio.camtweaks.ui.HUD;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.hud.InGameHud;
import net.minecraft.client.render.RenderTickCounter;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.camtweaks.CameraTweaks.moduleManager;
@Mixin(InGameHud.class)
public abstract class InGameHudMixin {
@Inject(method = "render", at = @At("RETURN"), cancellable = true)
@Unique
NoRender noRender;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(MinecraftClient client, CallbackInfo ci) {
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
}
// norender
@Inject(method = "renderScoreboardSidebar*", at = @At("HEAD"), cancellable = true)
private void noRenderScoreboard(CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.scoreboard.isEnabled()) ci.cancel();
}
@Inject(method = "renderTitleAndSubtitle", at = @At("HEAD"), cancellable = true)
private void noRenderTitles(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.titles.isEnabled()) ci.cancel();
}
@Inject(method = "renderNauseaOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderNausea(DrawContext context, float nauseaStrength, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.nauseaEffect.isEnabled()) ci.cancel();
}
@Inject(method = "renderSpyglassOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderSpyglass(DrawContext context, float scale, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.spyglassOverlay.isEnabled()) ci.cancel();
}
@Inject(method = "renderPortalOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderPortal(DrawContext context, float nauseaStrength, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.portalOverlay.isEnabled()) ci.cancel();
}
@Inject(method = "renderOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderPumpkinBlur(DrawContext context, Identifier texture, float opacity, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.pumpkinOverlay.isEnabled() && texture.getPath().equals("textures/misc/pumpkinblur.png")) ci.cancel();
}
// otros
@Inject(method = "render", at = @At("RETURN"))
private void renderHUD(DrawContext ctx, RenderTickCounter tc, CallbackInfo ci) {
HUD.render(ctx, tc);
}
@ModifyExpressionValue(method = "renderCrosshair", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/option/Perspective;isFirstPerson()Z"))
private boolean alwaysRenderCrosshairInFreecam(boolean firstPerson) {
return ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled() || firstPerson;
}
@Inject(method = "clear", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;clear(Z)V"), cancellable = true)
private void onClear(CallbackInfo ci) {
BetterChat betterChat = moduleManager.getModuleByClass(BetterChat.class);
if (betterChat.isEnabled() && betterChat.logger.isEnabled()) ci.cancel();
ChatPlus chatPlus = ModuleManager.INSTANCE.getModuleByClass(ChatPlus.class);
if (chatPlus.isEnabled() && chatPlus.keepHistory.isEnabled()) ci.cancel();
}
}
@@ -0,0 +1,35 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.NoRender;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.hud.InGameOverlayRenderer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.MatrixStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(InGameOverlayRenderer.class)
public abstract class InGameOverlayRendererMixin {
@Unique
private static NoRender noRender;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(MinecraftClient client, VertexConsumerProvider vertexConsumers, CallbackInfo ci) {
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
}
@Inject(method = "renderFireOverlay", at = @At("HEAD"), cancellable = true)
private static void noRenderFireOverlay(MatrixStack matrices, VertexConsumerProvider vertexConsumers, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.fireOverlay.isEnabled()) ci.cancel();
}
@Inject(method = "renderUnderwaterOverlay", at = @At("HEAD"), cancellable = true)
private static void noRenderUnderwaterOverlay(MinecraftClient client, MatrixStack matrices, VertexConsumerProvider vertexConsumers, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.fluidOverlay.isEnabled()) ci.cancel();
}
}
@@ -0,0 +1,28 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Nametags;
import net.minecraft.entity.ItemEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(ItemEntity.class)
public abstract class ItemEntityMixin {
@Shadow
public abstract ItemStack getStack();
@ModifyReturnValue(method = "getName", at = @At("RETURN"))
private Text showItemCount(Text original) {
Nametags nametags = ModuleManager.INSTANCE.getModuleByClass(Nametags.class);
if (!nametags.isEnabled()) return original;
int count = this.getStack().getCount();
if (nametags.countItems.isEnabled() && count > 1) return original.copy().append(" x" + count);
return original;
}
}
@@ -0,0 +1,28 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Freecam;
import net.minecraft.client.input.Input;
import net.minecraft.client.input.KeyboardInput;
import net.minecraft.util.PlayerInput;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(KeyboardInput.class)
public abstract class KeyInputMixin extends Input {
@Inject(method = "tick", at = @At("TAIL"))
private void isPressed(CallbackInfo ci) {
Freecam freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
if (freecam.isEnabled() && freecam.stayCrouching.isEnabled() && freecam.isCrouching())
playerInput = new PlayerInput(
false, false,
false, false,
false,
true, // siempre agachado
false
);
}
}
@@ -3,7 +3,10 @@ package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.sugar.Local;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.textures.GpuTexture;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Fullbright;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.render.LightmapTextureManager;
import net.minecraft.util.math.ColorHelper;
import net.minecraft.util.profiler.Profiler;
@@ -15,23 +18,31 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.camtweaks.CameraTweaks.moduleManager;
@Mixin(LightmapTextureManager.class)
public abstract class LightmapTextureManagerMixin {
@Unique
Fullbright fullbright = moduleManager.getModuleByClass(Fullbright.class);
Fullbright fullbright;
@Shadow @Final
private GpuTexture glTexture;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(GameRenderer renderer, MinecraftClient client, CallbackInfo ci) {
fullbright = ModuleManager.INSTANCE.getModuleByClass(Fullbright.class);
}
@Inject(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;push(Ljava/lang/String;)V", shift = At.Shift.AFTER), cancellable = true)
private void update(float tickProgress, CallbackInfo ci, @Local Profiler profiler) {
if (fullbright.isEnabled() && fullbright.mode.is(Fullbright.Modes.GAMMA)) {
RenderSystem.getDevice().createCommandEncoder().clearColorTexture(glTexture, ColorHelper.getArgb(255, 255, 255, 255));
RenderSystem.getDevice().createCommandEncoder().clearColorTexture(glTexture, ColorHelper.getArgb(
fullbright.alpha.getIntValue(),
fullbright.red.getIntValue(),
fullbright.green.getIntValue(),
fullbright.blue.getIntValue()
));
profiler.pop();
ci.cancel();
}
}
}
}
@@ -0,0 +1,55 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import com.llamalad7.mixinextras.sugar.Local;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Freecam;
import me.retucio.camtweaks.module.modules.Nametags;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.render.entity.LivingEntityRenderer;
import net.minecraft.client.render.entity.PlayerEntityRenderer;
import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(LivingEntityRenderer.class)
public abstract class LivingEntityRendererMixin<T extends LivingEntity> {
@Unique
Nametags nametags;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(EntityRendererFactory.Context ctx, EntityModel<?> model, float shadowRadius, CallbackInfo ci) {
nametags = ModuleManager.INSTANCE.getModuleByClass(Nametags.class);
}
@ModifyExpressionValue(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;getCameraEntity()Lnet/minecraft/entity/Entity;"))
private Entity hasLabelGetCameraEntityProxy(Entity cameraEntity) {
return ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled() ? null : cameraEntity;
}
@ModifyExpressionValue(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;isSneaky()Z"))
private boolean renderSneakingPlayerNametags(boolean original) {
return (nametags.isEnabled() && nametags.alwaysVisible.isEnabled()) || original;
}
@ModifyExpressionValue(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;isInvisibleTo(Lnet/minecraft/entity/player/PlayerEntity;)Z"))
private boolean renderInvisPlayerNametags(boolean original) {
if (nametags.isEnabled() && nametags.alwaysVisible.isEnabled()) return false;
else return original;
}
@ModifyReturnValue(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At("RETURN"))
private boolean shouldRenderPlayerNametag(boolean original, @Local(argsOnly = true) T livingEntity) {
if (nametags.isEnabled() && livingEntity instanceof PlayerEntity) return nametags.entities.isEnabled(EntityType.PLAYER) && original;
return original;
}
}
@@ -1,17 +1,40 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.event.events.OpenScreenEvent;
import me.retucio.camtweaks.event.events.ShutdownEvent;
import me.retucio.camtweaks.event.events.TickEvent;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
@Mixin(MinecraftClient.class)
public abstract class MinecraftClientMixin {
@Inject(method = "tick", at = @At("HEAD"), cancellable = true)
private void onTick(CallbackInfo ci) {
@Inject(method = "tick", at = @At("HEAD"))
private void onTickPre(CallbackInfo ci) {
CameraTweaks.INSTANCE.onTick();
EVENT_BUS.post(new TickEvent.Pre());
}
}
@Inject(method = "tick", at = @At("TAIL"))
private void onTickPost(CallbackInfo ci) {
EVENT_BUS.post(new TickEvent.Post());
}
@Inject(method = "stop", at = @At("HEAD"))
private void onStop(CallbackInfo ci) {
EVENT_BUS.post(new ShutdownEvent());
}
@Inject(method = "setScreen", at = @At("HEAD"), cancellable = true)
private void onOpenScreen(Screen screen, CallbackInfo ci) {
OpenScreenEvent event = EVENT_BUS.post(new OpenScreenEvent(screen));
if (event.isCancelled()) ci.cancel();
}
}
@@ -0,0 +1,24 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.DamageOverlay;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.texture.NativeImageBackedTexture;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(OverlayTexture.class)
public abstract class OverlayTextureMixin implements AutoCloseable {
@Shadow @Final
private NativeImageBackedTexture texture;
@Inject(method = "<init>", at = @At("TAIL"))
private void modifyDamageOverlayColor(CallbackInfo ci) {
ModuleManager.INSTANCE.getModuleByClass(DamageOverlay.class).reloadOverlay(texture);
}
}
@@ -0,0 +1,22 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.NoRender;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.particle.ParticleManager;
import net.minecraft.particle.ParticleEffect;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ParticleManager.class)
public abstract class ParticleManagerMixin {
@Inject(method = "addParticle(Lnet/minecraft/particle/ParticleEffect;DDDDDD)Lnet/minecraft/client/particle/Particle;", at = @At("HEAD"), cancellable = true)
private void noRenderParticles(ParticleEffect parameters, double x, double y, double z, double velocityX, double velocityY, double velocityZ, CallbackInfoReturnable<Particle> cir) {
NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
if (!noRender.isEnabled()) return;
if (!noRender.particles.isEnabled(parameters.getType())) cir.setReturnValue(null);
}
}
@@ -0,0 +1,52 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Nametags;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(PlayerEntity.class)
public abstract class PlayerEntityMixin extends LivingEntity {
protected PlayerEntityMixin(EntityType<? extends LivingEntity> entityType, World world) {
super(entityType, world);
}
@ModifyReturnValue(method = "getDisplayName", at = @At("RETURN"))
private Text addHealthIndicator(Text original) {
Nametags nametags = ModuleManager.INSTANCE.getModuleByClass(Nametags.class);
if (!nametags.isEnabled() || !nametags.health.isEnabled()) return original;
float health = getHealth();
float absorption = getAbsorptionAmount();
Formatting color;
if (health < 5) color = Formatting.RED;
else if (health < 10) color = Formatting.YELLOW;
else if (health < 15) color = Formatting.GREEN;
else color = Formatting.DARK_GREEN;
// me gustaría también añadir un modo en el que se renderizan los corazones directamente en la nametag, pero no sé cómo hacer para las imágenes :'(
// ahora que lo pienso en la snapshot más reciente han metido iconos que se pueden usar en texto, y uno de ellos es un corazón :D
String text = " [" + color +
(nametags.healthMode.is(Nametags.HealthMode.HEARTS)
? String.format("%.2f", health / 2) // redondear a dos decimales
: (int) health) +
(absorption > 0 // tener absorción en cuenta
? Formatting.RESET + " + " + Formatting.GOLD +
(nametags.healthMode.is(Nametags.HealthMode.HEARTS)
? String.format("%.2f", absorption / 2)
: Integer.toString((int) absorption))
: "") +
Formatting.RESET + "]";
return original.copy().append(text);
}
}
@@ -0,0 +1,22 @@
package me.retucio.camtweaks.mixin;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import me.retucio.camtweaks.command.CommandManager;
import me.retucio.camtweaks.event.events.ClientClickEvent;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.ClickEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Screen.class)
public class ScreenMixin {
@Inject(method = "handleBasicClickEvent", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;error(Ljava/lang/String;Ljava/lang/Object;)V", remap = false))
private static void handleClientClickEvents(ClickEvent clickEvent, MinecraftClient client, Screen screen, CallbackInfo ci) throws CommandSyntaxException {
if (clickEvent instanceof ClientClickEvent event && event.getValue().startsWith(CommandManager.INSTANCE.getPrefix()))
CommandManager.dispatch(event.getValue().substring(CommandManager.INSTANCE.getPrefix().length()));
}
}
@@ -0,0 +1,53 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.ScreenshotPlus;
import net.minecraft.client.texture.NativeImage;
import net.minecraft.client.util.ScreenshotRecorder;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.io.File;
import java.io.IOException;
import java.util.function.Consumer;
@Mixin(ScreenshotRecorder.class)
public abstract class ScreenshotRecorderMixin {
// "method_22691" es la lambda de la función "saveScreenshot()" (por lo menos en 1.21.6)
@Inject(method = "method_22691", at = @At(value = "INVOKE", target = "Ljava/util/function/Consumer;accept(Ljava/lang/Object;)V"), cancellable = true)
private static void sendActionsMessage(NativeImage nativeImage, File file, Consumer<Text> consumer, CallbackInfo ci) {
ScreenshotPlus screenshotPlus = getScreenshotPlus();
if (screenshotPlus.isEnabled()) ci.cancel();
}
@Inject(method = "method_22691", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/texture/NativeImage;writeTo(Ljava/io/File;)V"), cancellable = true)
private static void interceptScreenshotFile(NativeImage nativeImage, File file, Consumer<Text> consumer, CallbackInfo ci) throws IOException {
ScreenshotPlus screenshotPlus = getScreenshotPlus();
// aunque el módulo esté apagado, pasar las referencias para poder usar los comandos para las capturas
screenshotPlus.setScreenshot(nativeImage);
screenshotPlus.setScreenshotFile(file);
if (!screenshotPlus.isEnabled()) return;
screenshotPlus.sendScreenshotMessage();
switch (screenshotPlus.defaultAction.getValue()) {
case COPY -> screenshotPlus.copyScreenshot(nativeImage);
case SAVE -> screenshotPlus.saveScreenshot();
case NONE -> ci.cancel();
}
ci.cancel();
}
@Unique
private static ScreenshotPlus getScreenshotPlus() {
return ModuleManager.INSTANCE.getModuleByClass(ScreenshotPlus.class);
}
}
@@ -0,0 +1,40 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.PerspectivePlus;
import me.retucio.camtweaks.module.modules.TimeChanger;
import net.minecraft.client.render.SkyRendering;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.MatrixStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(SkyRendering.class)
public abstract class SkyRendererMixin {
@Unique
TimeChanger timeChanger;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(CallbackInfo ci) {
timeChanger = ModuleManager.INSTANCE.getModuleByClass(TimeChanger.class);
}
@Inject(method = "renderSun", at = @At("HEAD"), cancellable = true)
private void onRenderSun(float alpha, VertexConsumerProvider vertexConsumers, MatrixStack matrices, CallbackInfo ci) {
if (timeChanger.isEnabled() && !timeChanger.renderSun.isEnabled()) ci.cancel();
}
@Inject(method = "renderMoon", at = @At("HEAD"), cancellable = true)
private void onRenderMoon(int phase, float alpha, VertexConsumerProvider vertexConsumers, MatrixStack matrices, CallbackInfo ci) {
if (timeChanger.isEnabled() && !timeChanger.renderMoon.isEnabled()) ci.cancel();
}
@Inject(method = "renderStars", at = @At("HEAD"), cancellable = true)
private void onRenderStars(float brightness, MatrixStack matrices, CallbackInfo ci) {
if (timeChanger.isEnabled() && !timeChanger.renderStars.isEnabled()) ci.cancel();
}
}
@@ -1,18 +1,18 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.modules.BetterChat;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.ChatPlus;
import net.minecraft.util.StringHelper;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import static me.retucio.camtweaks.CameraTweaks.moduleManager;
@Mixin(StringHelper.class)
public abstract class StringHelperMixin {
@ModifyArg(method = "truncateChat", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/StringHelper;truncate(Ljava/lang/String;IZ)Ljava/lang/String;"), index = 1)
private static int truncate(int maxLength) {
BetterChat betterChat = moduleManager.getModuleByClass(BetterChat.class);
return ((betterChat.isEnabled() && betterChat.noCharLimit.isEnabled()) ? Integer.MAX_VALUE : maxLength);
private static int onTruncate(int maxLength) {
ChatPlus chatPlus = ModuleManager.INSTANCE.getModuleByClass(ChatPlus.class);
return ((chatPlus.isEnabled() && chatPlus.noCharLimit.isEnabled()) ? Integer.MAX_VALUE : maxLength);
}
}
@@ -0,0 +1,19 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.NoRender;
import net.minecraft.client.render.entity.feature.StuckArrowsFeatureRenderer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(StuckArrowsFeatureRenderer.class)
public abstract class StuckArrowsFeatureRendererMixin {
@ModifyReturnValue(method = "getObjectCount", at = @At("RETURN"))
private int noRenderStuckArrows(int original) {
NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
if (noRender.isEnabled() && !noRender.stuckArrows.isEnabled()) return 0;
return original;
}
}
@@ -0,0 +1,49 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.NoRender;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.text.Style;
import net.minecraft.text.TextColor;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.*;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
// falta italics pero no sé dónde se comprueba eso, no es aquí :P
@Mixin(TextRenderer.Drawer.class)
public abstract class TextRendererDrawerMixin {
@Unique
NoRender noRender;
@Inject(method = "<init>(Lnet/minecraft/client/font/TextRenderer;FFIIZ)V", at = @At("TAIL"))
private void getModules(TextRenderer textRenderer, float x, float y, int color, int backgroundColor, boolean shadow, CallbackInfo ci) {
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
}
@Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isBold()Z"))
private boolean noRenderBold(Style style) {
return !(noRender.isEnabled() && !noRender.bold.isEnabled()) && style.isBold();
}
@Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isUnderlined()Z"))
private boolean noRenderUnderlined(Style style) {
return !(noRender.isEnabled() && !noRender.underlined.isEnabled()) && style.isUnderlined();
}
@Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isStrikethrough()Z"))
private boolean noRenderStrikethrough(Style style) {
return !(noRender.isEnabled() && !noRender.strikethrough.isEnabled()) && style.isStrikethrough();
}
@Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isObfuscated()Z"))
private boolean noRenderMTS(Style style) {
return !(noRender.isEnabled() && !noRender.scrambledText.isEnabled()) && style.isObfuscated();
}
@ModifyArg(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/TextRenderer$Drawer;getRenderColor(Lnet/minecraft/text/TextColor;)I"))
private TextColor noRenderColor(TextColor original) {
return !noRender.color.is(NoRender.Colors.DEFAULT) ? TextColor.fromFormatting(noRender.color.getValue().toFormatting()) : original;
}
}
@@ -0,0 +1,39 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.util.interfaces.IVec3d;
import net.minecraft.util.math.Vec3d;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(Vec3d.class)
public abstract class Vec3dMixin implements IVec3d {
@Shadow @Final @Mutable
public double x;
@Shadow @Final @Mutable
public double y;
@Shadow @Final @Mutable
public double z;
@Override
public void smegma$set(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
@Override
public void smegma$setXZ(double x, double z) {
this.x = x;
this.z = z;
}
@Override
public void smegma$setY(double y) {
this.y = y;
}
}
@@ -0,0 +1,43 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.NoRender;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.WeatherRendering;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.particle.ParticlesMode;
import net.minecraft.util.math.Vec3d;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List;
@Mixin(WeatherRendering.class)
public abstract class WeatherRenderingMixin {
@Unique
NoRender noRender;
@Inject(method = "<init>", at = @At("TAIL"))
public void getModules(CallbackInfo ci) {
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
}
@Inject(method = "addParticlesAndSound", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;addParticleClient(Lnet/minecraft/particle/ParticleEffect;DDDDDD)V"), cancellable = true)
private void noRainParticles(ClientWorld world, Camera camera, int ticks, ParticlesMode particlesMode, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.rain.isEnabled()) ci.cancel();
}
@Inject(method = "renderPrecipitation(Lnet/minecraft/client/render/VertexConsumerProvider;Lnet/minecraft/util/math/Vec3d;IFLjava/util/List;Ljava/util/List;)V", at = @At("HEAD"))
private void noRenderRainAndSnow(VertexConsumerProvider vertexConsumers, Vec3d pos, int range, float gradient, List<?> rainPieces, List<?> snowPieces, CallbackInfo ci) {
if (noRender.isEnabled()) {
if (!noRender.rain.isEnabled()) rainPieces.clear();
if (!noRender.snow.isEnabled()) snowPieces.clear();
}
}
}
@@ -0,0 +1,48 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.BlockOutline;
import me.retucio.camtweaks.module.modules.Freecam;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.util.math.ColorHelper;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.awt.*;
@Mixin(WorldRenderer.class)
public abstract class WorldRendererMixin {
@ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;setupTerrain(Lnet/minecraft/client/render/Camera;Lnet/minecraft/client/render/Frustum;ZZ)V"), index = 3)
private boolean renderSetupTerrainModifyArg(boolean hasForcedFrustum) {
return ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled() || hasForcedFrustum;
}
@Redirect(method = "renderTargetBlockOutline", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/ColorHelper;withAlpha(II)I"))
private int modifyBlockOutlineColor(int alpha, int rgb) {
BlockOutline outline = ModuleManager.INSTANCE.getModuleByClass(BlockOutline.class);
if (!outline.isEnabled()) return ColorHelper.withAlpha(alpha, rgb);
if (outline.rainbow.isEnabled()) {
float speed = 10001 - outline.rainbowSpeed.getFloatValue(); // 10001 para evitar divisiones por cero
float hue = (System.currentTimeMillis() % (int) speed) / speed;
Color gamingProMax = Color.getHSBColor(hue, 1, 1);
return new Color(
gamingProMax.getRed(),
gamingProMax.getGreen(),
gamingProMax.getBlue(),
outline.alpha.getIntValue()
).getRGB();
} else {
return new Color(
outline.red.getIntValue(),
outline.green.getIntValue(),
outline.blue.getIntValue(),
outline.alpha.getIntValue()
).getRGB();
}
}
}
@@ -0,0 +1,17 @@
package me.retucio.camtweaks.mixin.accessor;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.network.message.LastSeenMessagesCollector;
import net.minecraft.network.message.MessageChain;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(ClientPlayNetworkHandler.class)
public interface ClientPlayNetworkHandlerAccessor {
@Accessor("lastSeenMessagesCollector")
LastSeenMessagesCollector getLastSeenMessagesCollector();
@Accessor("messagePacker")
MessageChain.Packer getMessagePacker();
}
Loaded 100 of 160 files, more files were not shown because too many files have changed in this diff. Show more