Compare commits

...
12 Commits
Author SHA1 Message Date
retuci0 2329476fe4 v1.8 2025-12-22 18:54:02 +01:00
retuci0 6b2ec0e69a v1.7.1 2025-12-14 21:31:58 +01:00
retuci0 6fa409d60a v1.7 2025-12-10 19:26:51 +01:00
retuci0 4f816381c3 upsi 2025-12-07 09:01:21 +01:00
retuci0 36c38bdf02 ups 2025-12-07 09:00:41 +01:00
retuci0 a6a6f1261e v1.5 2025-12-07 08:59:33 +01:00
retuci0 8891a57c7c v1.4 2025-10-12 13:00:18 +02:00
retuci0 e358b142c6 v1.3 2025-09-28 14:35:16 +02:00
retuci0 e7d872d75e mejoras a interfaz 1 2025-09-04 12:35:36 +02:00
retuci0 589279342d actualizar README 2025-09-01 18:43:45 +02:00
retuci0 054702999b v1.2 2025-09-01 18:22:39 +02:00
retuci0 ec7ff3a058 v1.1 2025-08-27 19:24:04 +02:00
261 changed files with 9531 additions and 1139 deletions

No files matched your search

+5 -1
View File
@@ -39,4 +39,8 @@ replay_*.log
*.hprof
*.jfr
todo.txt
# otros
todo.txt
cambios.md
remappedSrc/
+86
View File
@@ -0,0 +1,86 @@
# jenny's mod 2 100% real
mod para Minecraft Fabric 1.21.10 que añade algunas cosas QOL, mayormente relacionadas a la cámara.
## instalación
### para gente normal:
1. ir a [lanzamientos](https://github.com/retuci0/camera-tweaks/releases)
2. selecionar la versión más reciente
3. descargar el .jar
4. moverlo a tu directorio de mods (probablemente `%appdata%/.minecraft/mods`)
asegúrate de tener una version de Minecraft y Fabric compatibles con el mod (MC `1.21.10`; Fabric `0.138.3`)
es posible que haya problemas al usarlo junto a otros mods, especialmente junto a otros clientes, pues pueden conflictar entre ellos.
### para frikis de 200 de iq
1. clona el respositorio (`git clone https://github.com/retuci0/camera-tweaks`)
2. entra al directorio del repositorio (`cd camera-tweaks`)
3. `gradlew build` para Windows o `chmod +x gradlew` + `./gradlew build` para Linux (Mac es Linux)
4. el resultado estará en `/build/libs/camtweaks-X.X.jar` (el que no lleva "sources" en el nombre)
## uso
`shift derecho` por defecto para abrir la interfaz
`pág. arriba` por defecto para abrir el editor del hud
`$` como prefijo por defecto para comandos (se autocompletan)
algunos módulos tienen teclas asignadas por defecto, asígnales `ESC` para desactivar sus atajos de teclado
## interfaz
- clic izquierdo para activar / desactivar módulos
- clic derecho para abrir sus ajustes
- clic izquierdo + arrastrar para mover marcos
- clic derecho en la cabeza del marco para expandirlo / contraerlo o para cerrarlo
- clic izquierdo sobre ajustes para modificarlos
- shift + clic derecho sobre ajustes para restablecerlos
- posiciona el puntero del ratón sobre un módulo o ajuste para leer su descripción
### protips
- shift mientras pasas el puntero por encima de un ajuste de modos para ver los modos disponibles
- clic derecho para ciclar hacia atrás en ajustes de modo
- usa la rueda del ratón para mover la interfaz verticalmente
- shift + rueda del ratón para mover todos los marcos a un rango visible en la pantalla
## capturas
<img src="screenshots/ui.png" alt="interfaz">
<img src="screenshots/nametags.png" alt="nametags mostrando daño de un tridente">
<img src="screenshots/chatplus.png" alt="chatplus y capturas en uso">
<img src="screenshots/crits.png" alt="críticos">
<img src="screenshots/fullbright.png" alt="fullbright en modo gamma cambiando el color de los shaders">
<img src="screenshots/hud.png" alt="HUD">
<img src="screenshots/hudeditor.png" alt="editor de HUD">
## contibuciones
sí por favor
## licencia
no sé, haz lo que quieras con esto, es puta basura xd
aunque estaría guay que acreditases
pero bueno
## descargo de responsabilidad
me importa una puta mierda lo que pase al usar este mod en servers donde es baneable y así.
## mods recomendados
> mods que recomiendo usar junto a este:
- [fabric api (necesario)](https://modrinth.com/mod/fabric-api/): necesario para el mod
- [sodium](https://modrinth.com/mod/sodium): mejora el rendimiento general del juego
- [viafabricplus](https://modrinth.com/mod/viafabricplus): te permite conectarte a servidores que tengan una versión distinta a la de tu cliente
- [xaero's world map](https://modrinth.com/mod/xaeros-world-map/) y [xaero's minimap](https://modrinth.com/mod/xaeros-minimap/): mapa chulo
- [mod menu](https://modrinth.com/mod/modmenu): lista de los mods instalados, y sus ajustes
- [iris](https://modrinth.com/mod/iris): shaders
- [lambdynamiclights](https://modrinth.com/mod/lambdynamiclights): iluminación dinámica
- [appleskin](https://modrinth.com/mod/appleskin/): información relacionada con la comida
- [baritone (desactualizado)](https://github.com/cabaletta/baritone): google maps para juego de cubos
+4 -1
View File
@@ -24,11 +24,14 @@ dependencies {
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
}
loom {
accessWidenerPath = file("src/main/resources/camtweaks.accesswidener")
}
processResources {
inputs.property "version", project.version
+30
View File
@@ -0,0 +1,30 @@
# v1.7
## novedades
### adiciones
- comando `$echest` (o `$ec` si eres un puto vago) para previsualizar los contenidos del enderchest en cualquier momento
- se ha añadido un gradiente negro leve en la parte inferior del clickgui si el contenido excede los límites de la pantalla, para indicarlo visualmente
#### módulos nuevos:
- aviso de baja durabilidad: te avisa cuando un ítem llega a cierto porcentaje de durabilidad
- bypassear packs: te permite omitir packs de recursos forzados por el servidor, al establecer el modo en "preguntar" y seleccionar la opción "nuh uh"
- destello de enchants.: modifica el color del destello de los items y armadura encantada
### arreglos / mejoras
- ahora puedes volver a abrir el clickgui y el editor de hud en la pantalla de inicio
- ya no se deja de renderizar el hud si algún modo de debug (chunks, hitboxes, etc.) está activado y "mostar en F3" está desactivado
- ahora se pueden previsualizar enderchests igual que shulkers, desde el inventario (prev. de shulkers)
- ahora el mod funciona al compilarlo tras clonarlo por github, ya que había gitignorado algunos archivos importantes jsajajs
- arreglados los problemas del módulo zoom (creo)
- arregladas las opciones de ceguera y oscuridad de norender
- el color de la interfaz ya no es negro en el primer launch o cuando no se ha generado el archivo de config todavía
- arreglado el problema donde se muestra la marca de agua por defecto en la pantalla de inicio si no se abre un mundo primero
## problemas reconocidos
- muchos, pero repórtalos en la página de problemas si quieres para que queden bien registrados
+11 -3
View File
@@ -1,3 +1,11 @@
meteor client
oyvey client (1.21 port by mioclient)
lennyboi (youtube)
Meteor Client: https://github.com/MeteorDevelopment/meteor-client | https://meteorclient.com
OyVey Port: https://github.com/mioclient/oyvey-ported/
Lenny Boi: https://www.youtube.com/@lennyboi7195
Shotify: https://modrinth.com/mod/shotify
No Telemetry: https://modrinth.com/mod/no-telemetry
Trouser Streak: https://github.com/etianl/Trouser-Streak
No More Purple: https://github.com/Pepperoni-Jabroni/NoMorePurple/
bypass-resource-pack: https://github.com/emilyy-dev/bypass-resource-pack
probablemente más pero como tengo demencia se me olvida
si quieres que te acredite o quite tu código de mi mod, mándame un mensaje en discord (username: retucio) y sin problemas :)
+5 -10
View File
@@ -1,18 +1,13 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx1G
org.gradle.parallel=true
# Fabric Properties
# check these on https://fabricmc.net/develop
minecraft_version=1.21.6
yarn_mappings=1.21.6+build.1
loader_version=0.17.2
minecraft_version=1.21.10
yarn_mappings=1.21.10+build.2
loader_version=0.17.3
loom_version=1.11-SNAPSHOT
# Mod Properties
mod_version=1.0.0
mod_version=1.8
maven_group=me.retucio
archives_base_name=camtweaks
# Dependencies
fabric_version=0.128.2+1.21.6
fabric_version=0.135.0+1.21.10
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: 243 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 KiB

+2 -2
View File
@@ -1,8 +1,8 @@
pluginManagement {
repositories {
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
name = "Fabric"
url = "https://maven.fabricmc.net/"
}
mavenCentral()
gradlePluginPortal()
BIN
View File
Binary file not shown.
@@ -1,61 +1,147 @@
package me.retucio.camtweaks;
import me.retucio.camtweaks.command.CommandManager;
import me.retucio.camtweaks.command.commands.BindCommand;
import me.retucio.camtweaks.config.ConfigManager;
import me.retucio.camtweaks.event.EventBus;
import me.retucio.camtweaks.event.SubscribeEvent;
import me.retucio.camtweaks.event.events.ShutdownEvent;
import me.retucio.camtweaks.event.events.camtweaks.LoadClickGUIEvent;
import me.retucio.camtweaks.event.events.camtweaks.LoadCommandManagerEvent;
import me.retucio.camtweaks.event.events.camtweaks.LoadModuleManagerEvent;
import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.ui.ClickGUI;
import me.retucio.camtweaks.ui.settings.*;
import net.fabricmc.api.ModInitializer;
import me.retucio.camtweaks.module.modules.HUD;
import me.retucio.camtweaks.ui.screen.ClickGUI;
import me.retucio.camtweaks.ui.screen.HudEditorScreen;
import me.retucio.camtweaks.ui.HudRenderer;
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.fabricmc.loader.api.FabricLoader;
import net.minecraft.SharedConstants;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.lwjgl.glfw.GLFW;
public class CameraTweaks implements ModInitializer {
public class CameraTweaks implements ClientModInitializer {
// cosas necesarias
public static final String MOD_ID = "camtweaks";
public static final CameraTweaks INSTANCE = new CameraTweaks();
public static final Logger LOGGER = LogManager.getLogger(CameraTweaks.class);
public static final EventBus EVENT_BUS = new EventBus();
public static final MinecraftClient mc = MinecraftClient.getInstance();
public static final Logger LOGGER = LogManager.getLogger(CameraTweaks.class);
public static MinecraftClient mc;
// id y versión
public static final String MOD_ID = "camtweaks";
public static final String MOD_VERSION;
static {
MOD_VERSION = FabricLoader.getInstance().getModContainer(MOD_ID)
.orElseThrow()
.getMetadata()
.getVersion()
.getFriendlyString();
}
private Screen prevScreen;
public boolean settingsApplied = false;
// managers
public static ModuleManager moduleManager = new ModuleManager(EVENT_BUS);
public static CommandManager commandManager = new CommandManager();
@Override
public void onInitialize() {}
public void onInitializeClient() {
// por algún motivo aunque lo añada a los args de la JVM sigue siendo true a menos que haga esto??? puta vida
System.setProperty("java.awt.headless", "false");
mc = MinecraftClient.getInstance();
ConfigManager.load();
EVENT_BUS.register(this);
EVENT_BUS.register(MiscUtil.class);
EVENT_BUS.register(ChatUtil.class);
EVENT_BUS.register(HudRenderer.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();
HudEditorScreen.INSTANCE = new HudEditorScreen();
EVENT_BUS.post(new LoadClickGUIEvent());
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
ConfigManager.save();
EVENT_BUS.post(new ShutdownEvent());
}));
}
// se ejecuta cada tick, es decir, 20 veces por segundo
public void onTick() {
if (!settingsApplied
&& ConfigManager.getConfig() != null
&& !ConfigManager.hasLoaded()) {
ConfigManager.applyConfig();
settingsApplied = true;
}
ModuleManager.INSTANCE.getEnabledModules().forEach(Module::onTick);
}
// se ejecuta cada vez que se presiona una tecla
public void onKeyPress(int key, int action) {
moduleManager.getEnabledModules().forEach(module -> module.onKey(key, action));
if (key == GLFW.GLFW_KEY_F3) return; // prevenir activación de módulos al usar combinaciones de F3
ModuleManager.INSTANCE.getEnabledModules().forEach(module -> module.onKey(key, action));
boolean anyFocused = isAnySettingButtonFocused();
boolean anyFocused = isAnySettingButtonFocused() || ClickGUI.INSTANCE.getSearchBar().isFocused();
ClickGUI.INSTANCE.setAnyFocused(anyFocused);
if (action == GLFW.GLFW_PRESS) {
handleModuleToggle(key, anyFocused);
if (action != GLFW.GLFW_RELEASE) {
if (BindCommand.onKeyPress(key)) return;
if (action == GLFW.GLFW_PRESS) {
handleModuleToggle(key, anyFocused);
handleClickGUIKey(key, anyFocused);
handleHudEditorKey(key, anyFocused);
}
handleSettingButtonsKey(key, action);
handleClickGUIKey(key, anyFocused);
BindCommand.onKeyPress(key);
} else if (action == GLFW.GLFW_RELEASE && !anyFocused) {
} else if (!anyFocused) {
handleModuleRelease(key);
}
}
// verifica si algún botón de ajustes está escuchando
private boolean isAnySettingButtonFocused() {
for (SettingsFrame sf : ClickGUI.INSTANCE.getSettingsFrames()) {
for (SettingButton sb : sf.getButtons()) {
for (SettingsFrame sf : ClickGUI.INSTANCE.getSettingsFrames())
for (SettingButton sb : sf.getButtons())
if ((sb instanceof BindButton b && b.isFocused()) || (sb instanceof TextButton t && t.isFocused()))
return true;
}
}
return false;
}
@@ -63,8 +149,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 +171,28 @@ 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;
// al parecer esto hace que con la tecla de la interfaz puedas ir cambiando de splash text en la pantalla del título
// pero me ha hecho gracia así que así se queda
if (mc.currentScreen != ClickGUI.INSTANCE) {
prevScreen = mc.currentScreen;
mc.setScreen(ClickGUI.INSTANCE);
} else {
ClickGUI.INSTANCE.close();
mc.setScreen(prevScreen);
}
}
// manejar la lógica de apertura del editor de elementos del hud, con la misma lógica que handleClickGUIKey()
private void handleHudEditorKey(int key, boolean anyFocused) {
if (key != ModuleManager.INSTANCE.getModuleByClass(HUD.class).editorKey.getKey() || anyFocused) return;
if (mc.currentScreen != HudEditorScreen.INSTANCE) {
prevScreen = mc.currentScreen;
mc.setScreen(HudEditorScreen.INSTANCE);
} else {
HudEditorScreen.INSTANCE.close();
mc.setScreen(prevScreen);
}
}
@@ -99,16 +201,17 @@ 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();
}
public static String getVersionName() {
return MOD_ID + "_v" + MOD_VERSION + "_" + SharedConstants.getGameVersion().name();
}
}
@@ -12,13 +12,12 @@ import net.minecraft.server.command.CommandManager;
import java.util.List;
import static me.retucio.camtweaks.CameraTweaks.commandManager;
public abstract class Command {
// utilizar los "registries" ya existentes de Brigadier para el autocompletado
protected static final CommandRegistryAccess REGISTRY_ACCESS = CommandManager.createRegistryAccess(BuiltinRegistries.createWrapperLookup());
protected static final int SUCCESS = com.mojang.brigadier.Command.SINGLE_SUCCESS;
protected static final MinecraftClient mc = MinecraftClient.getInstance();
private final String name, description;
@@ -66,7 +65,7 @@ public abstract class Command {
}
public String toString() {
return commandManager.getPrefix() + name;
return me.retucio.camtweaks.command.CommandManager.INSTANCE.getPrefix() + name;
}
public String toString(String... args) {
@@ -2,17 +2,24 @@ package me.retucio.camtweaks.command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.command.commands.*;
import me.retucio.camtweaks.event.SubscribeEvent;
import me.retucio.camtweaks.module.Module;
import net.minecraft.client.MinecraftClient;
import net.minecraft.command.CommandSource;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Comparator;
import java.util.Objects;
// registro de comandos
public class CommandManager {
public static CommandManager INSTANCE;
private String prefix = "$";
public static final List<Command> commands = new ArrayList<>();
@@ -26,10 +33,26 @@ public class CommandManager {
public static void registerCommands() {
addCommand(new BindCommand());
addCommand(new ToggleCommand());
addCommand(new SendCommand());
addCommand(new CopyScreenshotCommand());
addCommand(new EnderChestCommand());
addCommand(new GarbageCleanerCommand());
addCommand(new PeekCommand());
addCommand(new PrefixCommand());
addCommand(new PurgeCommand());
addCommand(new SaveScreenshotCommand());
addCommand(new SendCommand());
addCommand(new ToggleCommand());
commands.sort(Comparator.comparing(Command::getName));
for (Command command : commands) {
for (Method method : command.getClass().getDeclaredMethods()) {
if (method.isAnnotationPresent(SubscribeEvent.class)) {
CameraTweaks.EVENT_BUS.register(command);
break;
}
}
}
}
public static void addCommand(Command command) {
@@ -39,13 +62,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,59 @@
package me.retucio.camtweaks.command.commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.command.Command;
import me.retucio.camtweaks.event.SubscribeEvent;
import me.retucio.camtweaks.event.events.DisconnectEvent;
import me.retucio.camtweaks.event.events.OpenScreenEvent;
import me.retucio.camtweaks.event.events.PacketEvent;
import me.retucio.camtweaks.event.events.TickEvent;
import me.retucio.camtweaks.ui.screen.PreviewScreen;
import me.retucio.camtweaks.util.ChatUtil;
import me.retucio.camtweaks.util.MiscUtil;
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.network.packet.s2c.play.CloseScreenS2CPacket;
import net.minecraft.screen.GenericContainerScreenHandler;
import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
// accede a los contenidos de tu enderchest
public class EnderChestCommand extends Command {
private boolean shouldOpenEchest = false;
public EnderChestCommand() {
super("echest", "muestra el contenido de tu enderchest (solo de ver)", "ec", "enderchest");
}
@Override
public void build(LiteralArgumentBuilder<CommandSource> builder) {
builder.executes(ctx -> {
mc.execute(() -> {
if (mc.player == null) return;
if (MiscUtil.getEchestInv() == null) {
ChatUtil.warn("necesitas abrir un enderchest una vez primero");
return;
}
shouldOpenEchest = true;
});
return SUCCESS;
});
}
@SubscribeEvent
public void tickEvent(TickEvent.Post event) {
if (shouldOpenEchest) {
shouldOpenEchest = false;
if (MiscUtil.getEchestInv() != null)
mc.setScreen(new PreviewScreen(MiscUtil.getEchestInv(), null));
}
}
}
@@ -0,0 +1,23 @@
package me.retucio.camtweaks.command.commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.camtweaks.command.Command;
import me.retucio.camtweaks.util.ChatUtil;
import net.minecraft.command.CommandSource;
import net.minecraft.text.Text;
public class GarbageCleanerCommand extends Command {
public GarbageCleanerCommand() {
super("cleanram", "limpia la ram mediante el recolector de basura (gc)", "gc", "garbagecollect");
}
@Override
public void build(LiteralArgumentBuilder<CommandSource> builder) {
builder.executes(context -> {
System.gc();
ChatUtil.info(Text.of("ram limpiada"));
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,115 @@
package me.retucio.camtweaks.config;
import me.retucio.camtweaks.event.SubscribeEvent;
import me.retucio.camtweaks.event.events.camtweaks.*;
import me.retucio.camtweaks.module.settings.*;
import me.retucio.camtweaks.ui.screen.ClickGUI;
import java.util.HashMap;
import java.util.Map;
import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
import static me.retucio.camtweaks.CameraTweaks.mc;
// clase donde se guardan las configuraciones temporalmente hasta escribirlas en camera_tweaks.json
public class ClientConfig {
// nombre del módulo -> estado del módulo
public Map<String, Boolean> moduleStates = new HashMap<>();
// nombre del ajuste -> valor
public Map<String, Object> settings = new HashMap<>();
// nombre del módulo -> posición (x, y)
public Map<String, int[]> settingsFrames = new HashMap<>();
// nombre del frame -> FrameData (que contiene extended, x & y)
public Map<String, FrameData> extendableFrames = new HashMap<>();
// id del elemento del hud -> posición (x, y)
public Map<String, int[]> hudPositions = new HashMap<>();
// id del elemento del hud -> true: visible / false: no visible
public Map<String, Boolean> hudVisibilities = new HashMap<>();
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,176 @@
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.screen.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 boolean loaded = false;
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();
loaded = true;
}
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});
save();
}
public static void setExtendableFrame(String key, ClientConfig.FrameData data) {
ensureConfig();
config.extendableFrames.put(key, data);
save();
}
public static void setHudPosition(String id, int x, int y) {
ensureConfig();
config.hudPositions.put(id, new int[]{x, y});
save();
}
public static void setHudVisibility(String id, Boolean visible) {
ensureConfig();
config.hudVisibilities.put(id, visible);
save();
}
@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();
}
public static boolean hasLoaded() {
return loaded;
}
}
@@ -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,17 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.entity.Entity;
public class AttackEntityEvent extends Event {
private final Entity entity;
public AttackEntityEvent(Entity entity) {
this.entity = entity;
}
public Entity getEntity() {
return entity;
}
}
@@ -0,0 +1,21 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.util.math.BlockPos;
public class BreakBlockEvent extends Event {
private BlockPos pos;
public BreakBlockEvent(BlockPos pos) {
this.pos = pos;
}
public BlockPos getPos() {
return pos;
}
public void setPos(BlockPos pos) {
this.pos = pos;
}
}
@@ -0,0 +1,30 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
public class ChangeRotationEvent extends Event {
private float yaw;
private float pitch;
public ChangeRotationEvent(float yaw, float pitch) {
this.yaw = yaw;
this.pitch = pitch;
}
public float getYaw() {
return yaw;
}
public void setYaw(float yaw) {
this.yaw = yaw;
}
public float getPitch() {
return pitch;
}
public void setPitch(float pitch) {
this.pitch = pitch;
}
}
@@ -0,0 +1,9 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
/**
* @see me.retucio.camtweaks.mixin.ChunkOcclusionDataBuilderMixin#onChunkOcclusion
*/
public class ChunkOcclusionEvent extends Event {}
@@ -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,23 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.item.ItemStack;
public class DamageItemEvent extends Event {
private final int amount;
private final ItemStack stack;
public DamageItemEvent(int amount, ItemStack stack) {
this.amount = amount;
this.stack = stack;
}
public int getAmount() {
return amount;
}
public ItemStack getStack() {
return stack;
}
}
@@ -0,0 +1,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;
@@ -0,0 +1,29 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.entity.Entity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
public class InteractEntityEvent extends Event {
private final Entity entity;
private Hand hand;
public InteractEntityEvent(Entity entity, Hand hand) {
this.entity = entity;
this.hand = hand;
}
public Entity getEntity() {
return entity;
}
public Hand getHand() {
return hand;
}
public void setHand(Hand hand) {
this.hand = hand;
}
}
@@ -2,7 +2,10 @@ package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
// se genera en KeyboardMixin
/**
* @see me.retucio.camtweaks.mixin.KeyboardMixin#onKeyPress
*/
public class KeyEvent extends Event {
private final int key, scancode, action;
@@ -2,7 +2,10 @@ package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
// se genera en MouseMixin
/**
* @see me.retucio.camtweaks.mixin.MouseMixin#onMouseButton
*/
public class MouseClickEvent extends Event {
private final int action, button;
@@ -2,7 +2,10 @@ package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
// se genera en MouseMixin
/**
* @see me.retucio.camtweaks.mixin.MouseMixin#onMouseScroll
*/
public class MouseScrollEvent extends Event {
private double horizontal, vertical;
@@ -0,0 +1,21 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.client.gui.screen.Screen;
/**
* @see me.retucio.camtweaks.mixin.MinecraftClientMixin#onOpenScreen
*/
public class OpenScreenEvent extends Event {
private final Screen screen;
public OpenScreenEvent(Screen screen) {
this.screen = screen;
}
public Screen getScreen() {
return screen;
}
}
@@ -0,0 +1,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;
@@ -0,0 +1,33 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
public class PlaceBlockEvent extends Event {
private Hand hand;
private BlockHitResult result;
public PlaceBlockEvent(Hand hand, BlockHitResult result) {
this.hand = hand;
this.result = result;
}
public Hand getHand() {
return hand;
}
public void setHand(Hand hand) {
this.hand = hand;
}
public BlockHitResult getResult() {
return result;
}
public void setResult(BlockHitResult result) {
this.result = result;
}
}
@@ -4,6 +4,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;
}
@@ -0,0 +1,31 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.RenderTickCounter;
import net.minecraft.client.util.math.MatrixStack;
public class RenderWorldEvent extends Event {
private final MatrixStack matrices;
private final RenderTickCounter tc;
private final Camera camera;
public RenderWorldEvent(MatrixStack matrices, RenderTickCounter tc, Camera camera) {
this.matrices = matrices;
this.tc = tc;
this.camera = camera;
}
public MatrixStack getMatrices() {
return matrices;
}
public RenderTickCounter getTickCounter() {
return tc;
}
public Camera getCamera() {
return camera;
}
}
@@ -2,6 +2,10 @@ package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
/**
* @see me.retucio.camtweaks.mixin.ClientPlayNetworkHandlerMixin#onSendMessage
*/
public class SendMessageEvent extends Event {
private String message;
@@ -0,0 +1,12 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
/**
* @see me.retucio.camtweaks.mixin.MinecraftClientMixin#onStop
*/
public class ShutdownEvent extends Event {
public ShutdownEvent() {}
}
@@ -0,0 +1,14 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
/**
* @see me.retucio.camtweaks.mixin.MinecraftClientMixin#onTickPre
* @see me.retucio.camtweaks.mixin.MinecraftClientMixin#onTickPost
*/
public class TickEvent {
public static class Pre extends Event {}
public static class Post extends Event {}
}
@@ -0,0 +1,32 @@
package me.retucio.camtweaks.event.events;
import me.retucio.camtweaks.event.Event;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;
public class UseItemEvent extends Event {
private ItemStack stack;
private Hand hand;
public UseItemEvent(ItemStack stack, Hand hand) {
this.stack = stack;
this.hand = hand;
}
public ItemStack getStack() {
return stack;
}
public void setStack(ItemStack stack) {
this.stack = stack;
}
public Hand getHand() {
return hand;
}
public void setHand(Hand hand) {
this.hand = hand;
}
}
@@ -0,0 +1,17 @@
package me.retucio.camtweaks.event.events.camtweaks;
import me.retucio.camtweaks.event.Event;
import net.minecraft.entity.Entity;
public class AddEntityEvent extends Event {
private final Entity entity;
public AddEntityEvent(Entity entity) {
this.entity = entity;
}
public Entity getEntity() {
return entity;
}
}
@@ -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,17 @@
package me.retucio.camtweaks.event.events.camtweaks;
import me.retucio.camtweaks.event.Event;
import net.minecraft.entity.Entity;
public class RemoveEntityEvent extends Event {
private final Entity entity;
public RemoveEntityEvent(Entity entity) {
this.entity = entity;
}
public Entity getEntity() {
return entity;
}
}
@@ -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();
}
}
@@ -0,0 +1,20 @@
package me.retucio.camtweaks.mixin;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import me.retucio.camtweaks.util.render.GlintRenderLayer;
import net.minecraft.client.render.BufferBuilderStorage;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.util.BufferAllocator;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(BufferBuilderStorage.class)
public abstract class BufferStorageMixin {
@Inject(method = "assignBufferBuilder", at = @At("HEAD"))
private static void addGlintTypes(Object2ObjectLinkedOpenHashMap<RenderLayer, BufferAllocator> builderStorage, RenderLayer layer, CallbackInfo ci) {
GlintRenderLayer.addGlintTypes(builderStorage);
}
}
@@ -1,29 +1,94 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.module.modules.Perspective;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.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,67 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.mixin.accessor.ConfirmServerResourcePackScreenAccessor;
import me.retucio.camtweaks.mixin.accessor.PackAccessor;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.RPackBypass;
import me.retucio.camtweaks.util.interfaces.IConfirmScreen;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.network.ClientCommonNetworkHandler;
import net.minecraft.client.network.ServerInfo;
import net.minecraft.client.option.ServerList;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.packet.c2s.common.ResourcePackStatusC2SPacket;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.net.URL;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@Mixin(ClientCommonNetworkHandler.class)
public abstract class ClientCommonNetworkHandlerMixin {
@Shadow @Final protected MinecraftClient client;
@Shadow @Final protected ServerInfo serverInfo;
@Shadow @Final protected ClientConnection connection;
@Unique // tardar 3 segundos porque algunos servers
private final Executor DELAYED_EXECUTOR = CompletableFuture.delayedExecutor(3L, TimeUnit.SECONDS);
@Inject(method = "createConfirmServerResourcePackScreen", at = @At("TAIL"))
private void setScreenBypassAction(UUID id, URL url, String hash, boolean required, Text prompt, CallbackInfoReturnable<Screen> cir) {
RPackBypass bypassPack = ModuleManager.INSTANCE.getModuleByClass(RPackBypass.class);
if (!bypassPack.isEnabled()) return;
final Screen screen = cir.getReturnValue();
((IConfirmScreen) screen).smegma$setBypassAction(() -> {
client.setScreen(((ConfirmServerResourcePackScreenAccessor) screen).getParentScreen());
if (this.serverInfo != null) {
this.serverInfo.setResourcePackPolicy(bypassPack.getPolicy());
this.client.getServerResourcePackProvider().acceptAll();
ServerList.updateServerListEntry(this.serverInfo);
}
bypass(((ConfirmServerResourcePackScreenAccessor) screen).getRequests().stream().map(PackAccessor::callId).toList());
});
}
@Unique
public void bypass(List<UUID> ids) {
ids.forEach(id -> connection.send(new ResourcePackStatusC2SPacket(id, ResourcePackStatusC2SPacket.Status.ACCEPTED)));
ids.forEach(id -> connection.send(new ResourcePackStatusC2SPacket(id, ResourcePackStatusC2SPacket.Status.DOWNLOADED)));
DELAYED_EXECUTOR.execute(() ->
ids.forEach(id -> connection.send(new ResourcePackStatusC2SPacket(id, ResourcePackStatusC2SPacket.Status.SUCCESSFULLY_LOADED)))
);
}
}
@@ -0,0 +1,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,19 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.PortalGUI;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.network.ClientPlayerEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(ClientPlayerEntity.class)
public abstract class ClientPlayerEntityMixin {
@ModifyExpressionValue(method = "tickNausea", at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;currentScreen:Lnet/minecraft/client/gui/screen/Screen;"))
private Screen allowScreensInPortals(Screen original) {
if (ModuleManager.INSTANCE.getModuleByClass(PortalGUI.class).isEnabled()) return null;
return original;
}
}
@@ -0,0 +1,75 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import com.llamalad7.mixinextras.sugar.Local;
import me.retucio.camtweaks.event.events.AttackEntityEvent;
import me.retucio.camtweaks.event.events.BreakBlockEvent;
import me.retucio.camtweaks.event.events.InteractEntityEvent;
import me.retucio.camtweaks.event.events.PlaceBlockEvent;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Freecam;
import me.retucio.camtweaks.util.ChatUtil;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerInteractionManager;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
import static me.retucio.camtweaks.CameraTweaks.mc;
@Mixin(ClientPlayerInteractionManager.class)
public abstract class ClientPlayerInteractionManagerMixin {
@Shadow
@Final
private MinecraftClient client;
@Unique
Freecam freecam;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(MinecraftClient client, ClientPlayNetworkHandler networkHandler, CallbackInfo ci) {
freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
}
@Inject(method = "breakBlock", at = @At("HEAD"), cancellable = true)
private void onBlockBreak(BlockPos pos, CallbackInfoReturnable<Boolean> cir) {
BreakBlockEvent event = EVENT_BUS.post(new BreakBlockEvent(pos));
if (event.isCancelled()) cir.cancel();
}
@Inject(method = "interactBlock", at = @At("HEAD"), cancellable = true)
private void onBlockPlace(ClientPlayerEntity player, Hand hand, BlockHitResult result, CallbackInfoReturnable<ActionResult> cir) {
if (mc.player != player) return;
PlaceBlockEvent event = EVENT_BUS.post(new PlaceBlockEvent(hand, result));
if (event.isCancelled()) cir.cancel();
}
@Inject(method = "interactEntity", at = @At("HEAD"), cancellable = true)
private void onEntityInteract(PlayerEntity player, Entity entity, Hand hand, CallbackInfoReturnable<ActionResult> cir) {
if (mc.player != player) return;
InteractEntityEvent event = EVENT_BUS.post(new InteractEntityEvent(entity, hand));
if (event.isCancelled()) cir.cancel();
}
@Inject(method = "attackEntity", at = @At("HEAD"), cancellable = true)
private void onAttackEntity(PlayerEntity player, Entity target, CallbackInfo ci) {
if (player != client.player) return;
AttackEntityEvent event = EVENT_BUS.post(new AttackEntityEvent(target));
if (event.isCancelled()) ci.cancel();
}
}
@@ -0,0 +1,32 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.event.events.camtweaks.AddEntityEvent;
import me.retucio.camtweaks.event.events.camtweaks.RemoveEntityEvent;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
@Mixin(ClientWorld.class)
public abstract class ClientWorldMixin {
@Shadow @Nullable
public abstract Entity getEntityById(int id);
@Inject(method = "addEntity", at = @At("HEAD"))
private void onEntityAdded(Entity entity, CallbackInfo ci) {
if (entity != null) EVENT_BUS.post(new AddEntityEvent(entity));
}
@Inject(method = "removeEntity", at = @At("HEAD"))
private void onRemoveEntity(int entityId, Entity.RemovalReason removalReason, CallbackInfo ci) {
Entity entity = getEntityById(entityId);
if (entity != null) EVENT_BUS.post(new RemoveEntityEvent(entity));
}
}
@@ -0,0 +1,19 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.TimeChanger;
import net.minecraft.client.world.ClientWorld;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ClientWorld.Properties.class)
public abstract class ClientWorldPropertiesMixin {
@Inject(method = "setTimeOfDay", at = @At("HEAD"), cancellable = true)
private void setTimeOfDay(long time, CallbackInfo ci) { // de no ser por esto, se verían "flashes" del tiempo real en el cielo
TimeChanger timeChanger = ModuleManager.INSTANCE.getModuleByClass(TimeChanger.class);
if (timeChanger.isEnabled() && time != timeChanger.time.getLongValue()) ci.cancel();
}
}
@@ -0,0 +1,39 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.RPackBypass;
import me.retucio.camtweaks.util.interfaces.IConfirmScreen;
import net.minecraft.client.gui.screen.ConfirmScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.DirectionalLayoutWidget;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ConfirmScreen.class)
public abstract class ConfirmScreenMixin extends Screen implements IConfirmScreen {
@Shadow protected DirectionalLayoutWidget layout;
@Unique private Runnable bypassAction = null;
protected ConfirmScreenMixin(final Text title) {
super(title);
}
@Inject(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ConfirmScreen;addButtons(Lnet/minecraft/client/gui/widget/DirectionalLayoutWidget;)V", shift = At.Shift.AFTER))
protected void addBypassButton(CallbackInfo ci) {
RPackBypass bypassPack = ModuleManager.INSTANCE.getModuleByClass(RPackBypass.class);
if (this.bypassAction != null && bypassPack.isEnabled())
this.layout.add(ButtonWidget.builder(bypassPack.BYPASS_TEXT, $ -> this.bypassAction.run()).build());
}
@Override
public void smegma$setBypassAction(Runnable bypass) {
this.bypassAction = bypass;
}
}
@@ -0,0 +1,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 me.retucio.camtweaks.util.Colors;
import net.minecraft.client.particle.BillboardParticle;
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 = "getRenderType", at = @At("RETURN"))
private BillboardParticle.RenderType makeCritsTranslucent(BillboardParticle.RenderType original) {
if (ModuleManager.INSTANCE.getModuleByClass(CritsPlus.class).isEnabled()) return BillboardParticle.RenderType.PARTICLE_ATLAS_TRANSLUCENT;
return original;
}
}
@Mixin(DamageParticle.Factory.class)
abstract class DamageParticleFactoryMixin {
@ModifyVariable(method = "createParticle(Lnet/minecraft/particle/SimpleParticleType;Lnet/minecraft/client/world/ClientWorld;DDDDDDLnet/minecraft/util/math/random/Random;)Lnet/minecraft/client/particle/Particle;", at = @At(value = "STORE"))
private DamageParticle modifyCritColor(DamageParticle original) {
CritsPlus crits = ModuleManager.INSTANCE.getModuleByClass(CritsPlus.class);
if (!crits.isEnabled()) return original;
if (crits.rainbow.isEnabled()) {
Color gamning = Colors.rainbowColor(crits.rainbowSpeed.getIntValue(), crits.alpha.getIntValue());
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,157 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.event.events.ChangeRotationEvent;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.*;
import net.minecraft.entity.*;
import net.minecraft.entity.passive.TameableEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
import static me.retucio.camtweaks.CameraTweaks.mc;
@Mixin(Entity.class)
public abstract class EntityMixin {
@Shadow
public abstract Text getName();
@Shadow
public abstract EntityType<?> getType();
@Shadow
private float yaw;
@Shadow
private float pitch;
@Unique
Freecam freecam;
@Unique
Freelook freelook;
@Unique
Nametags nametags;
@Unique
Rotations rotations;
@SuppressWarnings("rawtypes")
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(EntityType type, World world, CallbackInfo ci) {
freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
freelook = ModuleManager.INSTANCE.getModuleByClass(Freelook.class);
nametags = ModuleManager.INSTANCE.getModuleByClass(Nametags.class);
rotations = ModuleManager.INSTANCE.getModuleByClass(Rotations.class);
}
// cámara libre & perspectiva libre
@SuppressWarnings("ConstantConditions")
@Inject(method = "changeLookDirection", at = @At("HEAD"), cancellable = true)
private void onChangeLookDirection(double cursorDeltaX, double cursorDeltaY, CallbackInfo ci) {
if ((Object) this != mc.player) return;
if (freecam.isEnabled()) {
freecam.changeLookDirection(cursorDeltaX * 0.15, cursorDeltaY * 0.15);
ci.cancel();
} else if (freelook.isEnabled() && freelook.mode.is(Freelook.CameraMode.CAMERA)) {
freelook.setYaw(freelook.getYaw() + (float) (cursorDeltaX * freelook.mouseSens.getFloatValue()));
freelook.setPitch(freelook.getPitch() + (float) (cursorDeltaY * freelook.mouseSens.getFloatValue()));
if (Math.abs(freelook.getPitch()) > 90) freelook.setPitch(freelook.getPitch() > 0 ? 90 : -90);
ci.cancel();
}
}
// nametags
@SuppressWarnings("ConstantConditions")
@ModifyReturnValue(method = "isCustomNameVisible", at = @At("RETURN"))
private boolean renderEntityNametags(boolean original) {
if (!nametags.isEnabled()) return original;
if ((Object) this instanceof PersistentProjectileEntity p && p.isOnGround()) return false;
if ((Object) this instanceof ItemEntity i && !nametags.items.isEnabled(i.getStack().getItem())) return false;
return nametags.entities.isEnabled((this.getType()));
}
@ModifyReturnValue(method = "getName", at = @At("RETURN"))
private Text showProjectileDamage(Text original) {
if (!nametags.isEnabled() || !nametags.showProjectileDamage.isEnabled()) return original;
if ((Object) this instanceof PersistentProjectileEntity arrow) { // aunque lo llame "arrow", también cubre flechas espectrales y tridentes
String damage = nametags.getArrowDamage(arrow);
if (!damage.equals("0")) return original.copy().append(Text.literal(" (" + damage + ")").formatted(Formatting.RED));
}
return original;
}
@SuppressWarnings("ConstantConditions")
@ModifyReturnValue(method = "getCustomName", at = @At("RETURN"))
private Text displayEntityOwner(Text original) {
if (!nametags.isEnabled() || !nametags.petOwner.isEnabled()) return original;
if ((Object) this instanceof TameableEntity entity && entity.getOwnerReference() != null) {
if (original != null) return original.copy().append(" (de " + nametags.getOwnerName(entity.getOwnerReference()) + ")");
else return Text.of(nametags.getOwnerName(entity.getOwnerReference()));
}
return original;
}
@SuppressWarnings("ConstantConditions")
@ModifyReturnValue(method = "getName", at = @At("RETURN"))
private Text showBabies(Text original) {
if (!nametags.isEnabled() || !nametags.distinguishBabies.isEnabled()) return original;
if ((Object) this instanceof LivingEntity entity && entity.isBaby()) return original.copy().append(" (baby)");
return original;
}
// rotaciones
@Inject(method = "setRotation", at = @At("HEAD"), cancellable = true)
private void onRotation(float yaw, float pitch, CallbackInfo ci) {
if ((Object) this != mc.player) return;
ChangeRotationEvent event = EVENT_BUS.post(new ChangeRotationEvent(yaw, pitch));
if (event.isCancelled()) ci.cancel();
}
@Inject(method = "setYaw", at = @At("HEAD"), cancellable = true)
private void onChangeYaw(float yaw, CallbackInfo ci) {
if ((Object) this != mc.player) return;
ChangeRotationEvent event = EVENT_BUS.post(new ChangeRotationEvent(yaw, this.pitch));
if (event.isCancelled()) ci.cancel();
}
@Inject(method = "setPitch", at = @At("HEAD"), cancellable = true)
private void onChangePitch(float pitch, CallbackInfo ci) {
if ((Object) this != mc.player) return;
ChangeRotationEvent event = EVENT_BUS.post(new ChangeRotationEvent(this.yaw, pitch));
if (event.isCancelled()) ci.cancel();
}
// otros
@Inject(method = "isInvisibleTo", at = @At("RETURN"), cancellable = true)
public void renderInvisPlayers(PlayerEntity player, CallbackInfoReturnable<Boolean> cir) {
if (ModuleManager.INSTANCE.getModuleByClass(AntiInvis.class).isEnabled()) cir.setReturnValue(false);
}
}
@@ -0,0 +1,19 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.GlintPlus;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.entity.equipment.EquipmentRenderer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(EquipmentRenderer.class)
public abstract class EquipmentRendererMixin {
@Redirect(method = "render(Lnet/minecraft/client/render/entity/equipment/EquipmentModel$LayerType;Lnet/minecraft/registry/RegistryKey;Lnet/minecraft/client/model/Model;Ljava/lang/Object;Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/command/OrderedRenderCommandQueue;ILnet/minecraft/util/Identifier;II)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/RenderLayer;getArmorEntityGlint()Lnet/minecraft/client/render/RenderLayer;"))
private RenderLayer redirectArmorEntityGlint() {
GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class);
return glintPlus.getArmorEntityGlint();
}
}
@@ -0,0 +1,59 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.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()))
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,40 +1,137 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.CameraTweaks;
import com.llamalad7.mixinextras.sugar.Local;
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.NoMiningInterruptions;
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.block.BlockRenderManager;
import net.minecraft.client.render.item.HeldItemRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.hit.HitResult;
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 com.llamalad7.mixinextras.injector.ModifyReturnValue;
import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
@Mixin(GameRenderer.class)
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, BlockRenderManager blockRenderManager, 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.getEntityPos()).smegma$set(pos.x, pos.y - cameraEntity.getEyeHeight(cameraEntity.getPose()), pos.z);
cameraEntity.lastX = prevPos.x;
cameraEntity.lastY = prevPos.y - cameraEntity.getEyeHeight(cameraEntity.getPose());
cameraEntity.lastZ = prevPos.z;
cameraEntity.setYaw(freecam.getYaw());
cameraEntity.setPitch(freecam.getPitch());
cameraEntity.lastYaw = freecam.getPrevYaw();
cameraEntity.lastPitch = freecam.getPrevPitch();
freecamDone = true;
updateCrosshairTarget(tickDelta);
freecamDone = false;
((IVec3d) cameraEntity.getEntityPos()).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;
}
@ModifyReturnValue(method = "findCrosshairTarget", at = @At("RETURN"))
private HitResult onTargetEntity(HitResult original, @Local HitResult hitResult) {
NoMiningInterruptions nmi = ModuleManager.INSTANCE.getModuleByClass(NoMiningInterruptions.class);
Entity entity = original instanceof EntityHitResult result ? result.getEntity() : null;
if (nmi.shouldIgnoreEntity(entity) && hitResult.getType() == HitResult.Type.BLOCK)
return hitResult;
return original;
}
}
@@ -0,0 +1,77 @@
package me.retucio.camtweaks.mixin;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.BungeecordSpoofer;
import net.minecraft.network.packet.c2s.handshake.ConnectionIntent;
import net.minecraft.network.packet.c2s.handshake.HandshakeC2SPacket;
import org.spongepowered.asm.mixin.*;
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.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static me.retucio.camtweaks.CameraTweaks.mc;
@Mixin(HandshakeC2SPacket.class)
public abstract class HandshakeC2SPacketMixin {
@Shadow @Mutable @Final
private String address;
@Unique
private final Gson gson = new Gson();
@Unique
private static final ExecutorService executor = Executors.newCachedThreadPool();
@Shadow
public abstract ConnectionIntent intendedState();
@SuppressWarnings("deprecation")
@Inject(method = "<init>(ILjava/lang/String;ILnet/minecraft/network/packet/c2s/handshake/ConnectionIntent;)V", at = @At("RETURN"))
private void onHandshakeC2SPacket(int i, String string, int j, ConnectionIntent connectionIntent, CallbackInfo ci) {
BungeecordSpoofer spoofer = ModuleManager.INSTANCE.getModuleByClass(BungeecordSpoofer.class);
if (!spoofer.isEnabled()) return;
if (this.intendedState() != ConnectionIntent.LOGIN) return;
final String[] spoofedUUID = {CameraTweaks.mc.getSession().getUuidOrNull().toString()};
String URL = "https://api.mojang.com/users/profiles/minecraft/" + mc.getSession().getUsername();
executor.execute(() -> {
try {
HttpURLConnection req = (HttpURLConnection) new URL(URL).openConnection();
req.setRequestMethod("GET");
req.setConnectTimeout(5000);
req.setReadTimeout(5000);
if (req.getResponseCode() != 200) {
this.address += "\u0000" + spoofer.address.getValue() + "\u0000" + spoofedUUID[0];
return;
}
JsonObject obj = JsonParser.parseReader(new InputStreamReader(req.getInputStream())).getAsJsonObject();
if (obj.has("id"))
spoofedUUID[0] = obj.get("id").getAsString();
this.address += "\u0000" + spoofer.address.getValue() + "\u0000" + spoofedUUID[0];
} catch (Exception e) {
e.printStackTrace();
this.address += "\u0000" + spoofer.address.getValue() + "\u0000" + spoofedUUID[0];
}
});
}
}
@@ -1,37 +1,70 @@
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.command.OrderedRenderCommandQueue;
import net.minecraft.client.render.entity.EntityRenderManager;
import net.minecraft.client.render.item.HeldItemRenderer;
import net.minecraft.client.render.item.ItemRenderer;
import net.minecraft.client.util.math.MatrixStack;
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;
@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));
@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, EntityRenderManager entityRenderDispatcher, ItemRenderer itemRenderer, ItemModelManager itemModelManager, CallbackInfo ci) {
handView = ModuleManager.INSTANCE.getModuleByClass(HandView.class);
}
@Inject(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ItemDisplayContext;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/command/OrderedRenderCommandQueue;I)V", shift = At.Shift.BEFORE))
private void onRenderItem(AbstractClientPlayerEntity player, float tickProgress, float pitch, Hand hand, float swingProgress, ItemStack item, float equipProgress, MatrixStack matrices, OrderedRenderCommandQueue orderedRenderCommandQueue, int light, CallbackInfo ci) {
EVENT_BUS.post(new RenderHeldItemEvent(matrices, hand));
}
@Inject(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderArmHoldingItem(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/command/OrderedRenderCommandQueue;IFFLnet/minecraft/util/Arm;)V"))
private void onRenderArm(AbstractClientPlayerEntity player, float tickProgress, float pitch, Hand hand, float swingProgress, ItemStack item, float equipProgress, MatrixStack matrices, OrderedRenderCommandQueue orderedRenderCommandQueue, int light, CallbackInfo ci) {
EVENT_BUS.post(new RenderArmEvent(matrices, hand));
}
@ModifyReturnValue(method = "shouldSkipHandAnimationOnSwap", at = @At("RETURN"))
private boolean modifySkipSwapAnimation(boolean original) {
return original || (handView.isEnabled() && handView.skipSwapping.isEnabled());
@@ -42,8 +75,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 me.retucio.camtweaks.ui.HUD;
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.HudRenderer;
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);
HudRenderer.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,37 @@
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.texture.Sprite;
import net.minecraft.client.texture.SpriteHolder;
import net.minecraft.client.util.math.MatrixStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
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, SpriteHolder spriteHolder, VertexConsumerProvider vertexConsumers, CallbackInfo ci) {
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
}
@Inject(method = "renderFireOverlay", at = @At("HEAD"), cancellable = true)
private static void noRenderFireOverlay(MatrixStack matrices, VertexConsumerProvider vertexConsumers, Sprite sprite, 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();
}
}
Loaded 100 of 261 files, more files were not shown because too many files have changed in this diff. Show more