This commit is contained in:
retuci0 committed 2025-09-01 18:22:39 +02:00
1 parent ec7ff3a058
commit 054702999b
83 files changed
+1886 -305

No files matched your search

+2 -1
View File
@@ -39,4 +39,5 @@ replay_*.log
*.hprof *.hprof
*.jfr *.jfr
todo.txt todo.txt
test.java
+4
View File
@@ -29,6 +29,10 @@ dependencies {
} }
loom {
accessWidenerPath = file("src/main/resources/camtweaks.accesswidener")
}
processResources { processResources {
inputs.property "version", project.version inputs.property "version", project.version
+2 -1
View File
@@ -1,4 +1,5 @@
meteor client dev team meteor client dev team
oyvey client (1.21 port by mioclient) oyvey client (1.21 port by mioclient)
lennyboi (youtube) lennyboi (youtube)
packbar by cattyn on github packbar by cattyn on github
shotify mod
+1 -1
View File
@@ -10,7 +10,7 @@ loader_version=0.17.2
loom_version=1.11-SNAPSHOT loom_version=1.11-SNAPSHOT
# Mod Properties # Mod Properties
mod_version=1.1 mod_version=1.2
maven_group=me.retucio maven_group=me.retucio
archives_base_name=camtweaks archives_base_name=camtweaks
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 973 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1005 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 942 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 560 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 484 KiB

@@ -10,6 +10,9 @@ import me.retucio.camtweaks.event.EventBus;
import me.retucio.camtweaks.event.SubscribeEvent; import me.retucio.camtweaks.event.SubscribeEvent;
import me.retucio.camtweaks.event.events.ShutdownEvent; 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.Module;
import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.ModuleManager;
@@ -17,10 +20,12 @@ import me.retucio.camtweaks.ui.ClickGUI;
import me.retucio.camtweaks.ui.buttons.BindButton; import me.retucio.camtweaks.ui.buttons.BindButton;
import me.retucio.camtweaks.ui.buttons.SettingButton; import me.retucio.camtweaks.ui.buttons.SettingButton;
import me.retucio.camtweaks.ui.buttons.TextButton; import me.retucio.camtweaks.ui.buttons.TextButton;
import me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame; import me.retucio.camtweaks.ui.frames.ClientSettingsFrame;
import me.retucio.camtweaks.ui.frames.SettingsFrame; import me.retucio.camtweaks.ui.frames.SettingsFrame;
import me.retucio.camtweaks.util.ChatUtil;
import me.retucio.camtweaks.util.KeyUtil; import me.retucio.camtweaks.util.KeyUtil;
import me.retucio.camtweaks.util.Lists;
import me.retucio.camtweaks.util.MiscUtil; import me.retucio.camtweaks.util.MiscUtil;
@@ -50,16 +55,27 @@ public class CameraTweaks implements ClientModInitializer {
@Override @Override
public void onInitializeClient() { 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(); mc = MinecraftClient.getInstance();
ModuleManager.INSTANCE = new ModuleManager(EVENT_BUS);
CommandManager.INSTANCE = new CommandManager();
ClickGUI.INSTANCE = new ClickGUI();
ConfigManager.load();
EVENT_BUS.register(this); EVENT_BUS.register(this);
EVENT_BUS.register(MiscUtil.class); EVENT_BUS.register(MiscUtil.class);
EVENT_BUS.register(ChatUtil.class);
Lists.init();
ModuleManager.INSTANCE = new ModuleManager(EVENT_BUS);
EVENT_BUS.post(new LoadModuleManagerEvent());
CommandManager.INSTANCE = new CommandManager();
EVENT_BUS.post(new LoadCommandManagerEvent());
ClickGUI.INSTANCE = new ClickGUI();
EVENT_BUS.post(new LoadClickGUIEvent());
ConfigManager.load();
Runtime.getRuntime().addShutdownHook(new Thread(() -> { Runtime.getRuntime().addShutdownHook(new Thread(() -> {
ConfigManager.save(); ConfigManager.save();
@@ -132,7 +148,7 @@ public class CameraTweaks implements ClientModInitializer {
// maneja la lógica de apertura de la interfaz // maneja la lógica de apertura de la interfaz
private void handleClickGUIKey(int key, boolean anyFocused) { private void handleClickGUIKey(int key, boolean anyFocused) {
if (key != ClickGUISettingsFrame.guiSettings.getKey() || anyFocused) return; if (key != ClientSettingsFrame.guiSettings.getKey() || anyFocused) return;
if (mc.currentScreen != ClickGUI.INSTANCE) { if (mc.currentScreen != ClickGUI.INSTANCE) {
prevScreen = mc.currentScreen; prevScreen = mc.currentScreen;
@@ -9,6 +9,7 @@ import net.minecraft.command.CommandSource;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Comparator; import java.util.Comparator;
import java.util.Objects;
// registro de comandos // registro de comandos
public class CommandManager { public class CommandManager {
@@ -28,9 +29,12 @@ public class CommandManager {
public static void registerCommands() { public static void registerCommands() {
addCommand(new BindCommand()); addCommand(new BindCommand());
addCommand(new CopyScreenshotCommand());
// addCommand(new EnderChestCommand()); no funciona D: // addCommand(new EnderChestCommand()); no funciona D:
addCommand(new PeekCommand()); addCommand(new PeekCommand());
addCommand(new PrefixCommand()); addCommand(new PrefixCommand());
addCommand(new PurgeCommand());
addCommand(new SaveScreenshotCommand());
addCommand(new SendCommand()); addCommand(new SendCommand());
addCommand(new ToggleCommand()); addCommand(new ToggleCommand());
@@ -44,17 +48,17 @@ public class CommandManager {
} }
public static void dispatch(String message) throws CommandSyntaxException { 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) { public static Command getCommandByName(String name) {
for (Command command : commands) { for (Command command : commands) {
if (command.getName().equals(name)) if (command.getName().equals(name)) return command;
return command;
for (String alias : command.getAliases()) for (String alias : command.getAliases())
if (alias.equals(name)) if (alias.equals(name)) return command;
return command;
} }
return null; return null;
} }
@@ -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;
});
}
}
@@ -3,7 +3,7 @@ package me.retucio.camtweaks.command.commands;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.camtweaks.command.Command; import me.retucio.camtweaks.command.Command;
import me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame; import me.retucio.camtweaks.ui.frames.ClientSettingsFrame;
import me.retucio.camtweaks.util.ChatUtil; import me.retucio.camtweaks.util.ChatUtil;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.text.Text; import net.minecraft.text.Text;
@@ -21,7 +21,7 @@ public class PrefixCommand extends Command {
builder builder
.then(argument("prefijo", StringArgumentType.word()).executes(ctx -> { .then(argument("prefijo", StringArgumentType.word()).executes(ctx -> {
String prefix = ctx.getArgument("prefijo", String.class); 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)); ChatUtil.info(Text.literal("prefijo cambiado a " + Formatting.AQUA + prefix));
return SUCCESS; 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;
});
}
}
@@ -4,7 +4,6 @@ import me.retucio.camtweaks.event.SubscribeEvent;
import me.retucio.camtweaks.event.events.camtweaks.*; import me.retucio.camtweaks.event.events.camtweaks.*;
import me.retucio.camtweaks.module.settings.*; import me.retucio.camtweaks.module.settings.*;
import me.retucio.camtweaks.ui.ClickGUI; import me.retucio.camtweaks.ui.ClickGUI;
import me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -37,9 +36,10 @@ public class ClientConfig {
ConfigManager.setModuleState(event.getModule()); ConfigManager.setModuleState(event.getModule());
} }
@SuppressWarnings("rawtypes")
@SubscribeEvent @SubscribeEvent
public void onUpdateSetting(UpdateSettingEvent event) { public void onUpdateSetting(UpdateSettingEvent event) {
if (mc == null) return; if (mc == null || !event.shouldSave()) return;
// guardar ajustes con su respectivo tipo de valor, en formato "nombreMódulo:nombreAjuste" // guardar ajustes con su respectivo tipo de valor, en formato "nombreMódulo:nombreAjuste"
Object value = null; Object value = null;
@@ -49,6 +49,7 @@ public class ClientConfig {
case KeySetting k: value = k.getKey(); break; case KeySetting k: value = k.getKey(); break;
case NumberSetting n: value = n.getValue(); break; case NumberSetting n: value = n.getValue(); break;
case StringSetting s: value = s.getValue(); break; case StringSetting s: value = s.getValue(); break;
case ListSetting l: value = l.getValues(); break;
default: break; default: break;
} }
@@ -7,13 +7,15 @@ import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.settings.*; import me.retucio.camtweaks.module.settings.*;
import me.retucio.camtweaks.ui.ClickGUI; import me.retucio.camtweaks.ui.ClickGUI;
import me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame; import me.retucio.camtweaks.ui.frames.ClientSettingsFrame;
import me.retucio.camtweaks.ui.frames.SettingsFrame; import me.retucio.camtweaks.ui.frames.SettingsFrame;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
// se ocupa de guardar, cargar y aplicar ajustes // 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... // pues no me ha dado dolores de cabeza el coso este con los NPE de los cojones...
@@ -69,8 +71,8 @@ public class ConfigManager {
} }
}); });
ClickGUISettingsFrame.guiSettings.setEnabled(true); ClientSettingsFrame.guiSettings.setEnabled(true);
ClickGUISettingsFrame.guiSettings.getSettings().forEach(setting -> applySetting(ClickGUISettingsFrame.guiSettings, setting)); ClientSettingsFrame.guiSettings.getSettings().forEach(setting -> applySetting(ClientSettingsFrame.guiSettings, setting));
CameraTweaks.LOGGER.info("módulos encendidos cargados"); CameraTweaks.LOGGER.info("módulos encendidos cargados");
CameraTweaks.LOGGER.info("ajustes de módulos cargados"); CameraTweaks.LOGGER.info("ajustes de módulos cargados");
@@ -90,6 +92,7 @@ public class ConfigManager {
} }
CameraTweaks.LOGGER.info("posiciones de frames cargadas"); CameraTweaks.LOGGER.info("posiciones de frames cargadas");
ClickGUI.INSTANCE.refreshListButtons();
} }
public static ClientConfig getConfig() { public static ClientConfig getConfig() {
@@ -102,7 +105,7 @@ public class ConfigManager {
save(); save();
} }
public static void setSetting(Setting setting, Object value) { public static void setSetting(AbstractSetting setting, Object value) {
ensureConfig(); ensureConfig();
config.settings.put(setting.getModule().getName() + ":" + setting.getName(), value); config.settings.put(setting.getModule().getName() + ":" + setting.getName(), value);
save(); save();
@@ -120,7 +123,8 @@ public class ConfigManager {
save(); save();
} }
public static void applySetting(Module parent, Setting setting) { @SuppressWarnings({"rawtypes", "unchecked"})
public static void applySetting(Module parent, AbstractSetting setting) {
String id = parent.getName() + ":" + setting.getName(); String id = parent.getName() + ":" + setting.getName();
if (config.settings.containsKey(id)) { if (config.settings.containsKey(id)) {
Object value = config.settings.get(id); Object value = config.settings.get(id);
@@ -131,7 +135,17 @@ public class ConfigManager {
case NumberSetting n -> n.setValue((double) value); case NumberSetting n -> n.setValue((double) value);
case StringSetting s -> s.setValue((String) value); case StringSetting s -> s.setValue((String) value);
case KeySetting k -> k.setKey(value instanceof Double val ? val.intValue() : (int) value); case KeySetting k -> k.setKey(value instanceof Double val ? val.intValue() : (int) value);
default -> {} 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 -> {}
} }
} }
} }
@@ -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 {}
@@ -1,18 +1,28 @@
package me.retucio.camtweaks.event.events.camtweaks; package me.retucio.camtweaks.event.events.camtweaks;
import me.retucio.camtweaks.event.Event; import me.retucio.camtweaks.event.Event;
import me.retucio.camtweaks.module.settings.Setting; import me.retucio.camtweaks.module.settings.AbstractSetting;
// se genera cada que se cambia el valor de un ajuste // se genera cada que se cambia el valor de un ajuste
public class UpdateSettingEvent extends Event { public class UpdateSettingEvent extends Event {
private final Setting setting; private final AbstractSetting setting;
private boolean shouldSave;
public UpdateSettingEvent(Setting setting) { public UpdateSettingEvent(AbstractSetting setting, boolean shouldSave) {
this.setting = setting; this.setting = setting;
this.shouldSave = shouldSave;
} }
public Setting getSetting() { public AbstractSetting getSetting() {
return setting; return setting;
} }
public boolean shouldSave() {
return shouldSave;
}
public void shouldSave(boolean value) {
this.shouldSave = value;
}
} }
@@ -103,6 +103,11 @@ public abstract class ChatHudMixin implements IChatHud {
return line; return line;
} }
@Override
public List<ChatHudLine.Visible> smegma$getVisibleMessages() {
return visibleMessages;
}
// modificar contenido del mensaje // modificar contenido del mensaje
@@ -3,13 +3,19 @@ package me.retucio.camtweaks.mixin;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import me.retucio.camtweaks.command.CommandManager; import me.retucio.camtweaks.command.CommandManager;
import me.retucio.camtweaks.event.events.SendMessageEvent; 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 me.retucio.camtweaks.util.ChatUtil;
import net.minecraft.client.network.ClientPlayNetworkHandler; 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.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.camtweaks.CameraTweaks.*; import static me.retucio.camtweaks.CameraTweaks.*;
@@ -46,4 +52,10 @@ public abstract class ClientPlayNetworkHandlerMixin {
mc.inGameHud.getChatHud().addToMessageHistory(message); mc.inGameHud.getChatHud().addToMessageHistory(message);
ci.cancel(); ci.cancel();
} }
@Redirect(method = "onEntityStatus", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;showFloatingItem(Lnet/minecraft/item/ItemStack;)V"))
private void noRenderTotemPop(GameRenderer instance, ItemStack floatingItem) {
NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
if (!noRender.isEnabled() || noRender.totemPop.isEnabled()) mc.gameRenderer.showFloatingItem(Items.TOTEM_OF_UNDYING.getDefaultStack());
}
} }
@@ -0,0 +1,48 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Freecam;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerInteractionManager;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ClientPlayerInteractionManager.class)
public abstract class ClientPlayerInteractionManagerMixin {
@Unique
Freecam freecam;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(MinecraftClient client, ClientPlayNetworkHandler networkHandler, CallbackInfo ci) {
freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
}
// los paquetes ya se cancelan en la clase de Freecam, pero visualmente el bloque sigue apareciendo roto
@Inject(method = "breakBlock", at = @At("HEAD"), cancellable = true)
private void cancelBlockBreaking(BlockPos pos, CallbackInfoReturnable<Boolean> cir) {
if (freecam.isEnabled() && freecam.cancelActionPackets.isEnabled()) cir.setReturnValue(false);
}
@Inject(method = "interactBlock", at = @At("HEAD"), cancellable = true)
private void cancelBlockPlacement(ClientPlayerEntity player, Hand hand, BlockHitResult hitResult, CallbackInfoReturnable<ActionResult> cir) {
if (freecam.isEnabled() && freecam.cancelActionPackets.isEnabled()) cir.setReturnValue(ActionResult.FAIL);
}
@Inject(method = "interactEntity", at = @At("HEAD"), cancellable = true)
private void cancelEntityInteractions(PlayerEntity player, Entity entity, Hand hand, CallbackInfoReturnable<ActionResult> cir) {
if (freecam.isEnabled() && freecam.cancelActionPackets.isEnabled()) cir.setReturnValue(ActionResult.FAIL);
}
}
@@ -0,0 +1,57 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.CritsPlus;
import net.minecraft.client.particle.DamageParticle;
import net.minecraft.client.particle.ParticleTextureSheet;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import java.awt.*;
@Mixin(DamageParticle.class)
public abstract class DamageParticleMixin {
@ModifyReturnValue(method = "getType", at = @At("RETURN"))
private ParticleTextureSheet makeCritsTranslucent(ParticleTextureSheet original) {
if (ModuleManager.INSTANCE.getModuleByClass(CritsPlus.class).isEnabled()) return ParticleTextureSheet.PARTICLE_SHEET_TRANSLUCENT;
return original;
}
}
@Mixin(DamageParticle.Factory.class)
abstract class DamageParticleFactoryMixin {
@ModifyVariable(method = "createParticle(Lnet/minecraft/particle/SimpleParticleType;Lnet/minecraft/client/world/ClientWorld;DDDDDD)Lnet/minecraft/client/particle/Particle;", at = @At(value = "STORE"))
private DamageParticle modifyCritColor(DamageParticle original) {
CritsPlus crits = ModuleManager.INSTANCE.getModuleByClass(CritsPlus.class);
if (!crits.isEnabled()) return original;
if (crits.rainbow.isEnabled()) {
float speed = 10001 - crits.rainbowSpeed.getFloatValue();
float hue = (System.currentTimeMillis() % (int) speed) / speed;
Color gamning = Color.getHSBColor(hue, 1, 1);
original.setColor(
gamning.getRed() / 255f,
gamning.getGreen() / 255f,
gamning.getBlue() / 255f);
} else {
original.setColor(
crits.red.getFloatValue() / 255f,
crits.green.getFloatValue() / 255f,
crits.blue.getFloatValue() / 255f);
}
original.alpha = crits.alpha.getFloatValue() / 255f;
original.scale *= crits.scale.getFloatValue();
original.velocityMultiplier *= crits.velocityMultipler.getFloatValue();
original.gravityStrength *= crits.gravity.getFloatValue();
original.setMaxAge(crits.maxAge.getIntValue());
original.collidesWithWorld = crits.collide.isEnabled();
return original;
}
}
@@ -0,0 +1,19 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.NoRender;
import net.minecraft.particle.EntityEffectParticleEffect;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(EntityEffectParticleEffect.class)
public abstract class EntityEffectParticleEffectMixin {
@Inject(method = "getAlpha", at = @At("HEAD"), cancellable = true)
private void noRenderPotionParticles(CallbackInfoReturnable<Float> cir) {
NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
if (noRender.isEnabled()) cir.setReturnValue(256 - noRender.potionParticleAlpha.getFloatValue());
}
}
@@ -5,16 +5,10 @@ import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Freecam; import me.retucio.camtweaks.module.modules.Freecam;
import me.retucio.camtweaks.module.modules.Freelook; import me.retucio.camtweaks.module.modules.Freelook;
import me.retucio.camtweaks.module.modules.Nametags; import me.retucio.camtweaks.module.modules.Nametags;
import net.minecraft.client.MinecraftClient; import me.retucio.camtweaks.util.ChatUtil;
import net.minecraft.client.render.entity.AgeableMobEntityRenderer;
import net.minecraft.entity.*; import net.minecraft.entity.*;
import net.minecraft.entity.mob.Monster;
import net.minecraft.entity.passive.PassiveEntity;
import net.minecraft.entity.passive.TameableEntity; import net.minecraft.entity.passive.TameableEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity; import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.entity.vehicle.VehicleEntity;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Formatting; import net.minecraft.util.Formatting;
import net.minecraft.world.World; import net.minecraft.world.World;
@@ -31,11 +25,11 @@ import static me.retucio.camtweaks.CameraTweaks.mc;
@Mixin(Entity.class) @Mixin(Entity.class)
public abstract class EntityMixin { public abstract class EntityMixin {
@Shadow public int age; @Shadow
public abstract Text getName();
@Shadow public abstract Text getName(); @Shadow
public abstract EntityType<?> getType();
@Shadow @Nullable public abstract Text getCustomName();
@Unique @Unique
Freecam freecam; Freecam freecam;
@@ -82,15 +76,8 @@ public abstract class EntityMixin {
@ModifyReturnValue(method = "isCustomNameVisible", at = @At("RETURN")) @ModifyReturnValue(method = "isCustomNameVisible", at = @At("RETURN"))
private boolean renderEntityNametags(boolean original) { private boolean renderEntityNametags(boolean original) {
if (!nametags.isEnabled()) return original; if (!nametags.isEnabled()) return original;
return switch ((Object) this) { if ((Object) this instanceof PersistentProjectileEntity p && p.isOnGround()) return false;
case PlayerEntity player -> nametags.namePlayers.isEnabled(); return nametags.entities.isEnabled((this.getType()));
case ItemEntity item -> nametags.nameItems.isEnabled();
case ProjectileEntity projectile -> nametags.nameProjectiles.isEnabled();
case Monster hostile -> nametags.nameHostileMobs.isEnabled() || original; // monster en vez de HostileEntity para también incluir slimes
case PassiveEntity passive -> nametags.namePassiveMobs.isEnabled() || original;
case VehicleEntity vehicle -> nametags.nameVehicles.isEnabled();
default -> nametags.nameMiscMobs.isEnabled() || original;
};
} }
@ModifyReturnValue(method = "getName", at = @At("RETURN")) @ModifyReturnValue(method = "getName", at = @At("RETURN"))
@@ -98,9 +85,10 @@ public abstract class EntityMixin {
if (!nametags.isEnabled() || !nametags.showProjectileDamage.isEnabled()) return 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 if ((Object) this instanceof PersistentProjectileEntity arrow) { // aunque lo llame "arrow", también cubre flechas espectrales y tridentes
float damage = nametags.getArrowDamage(arrow); String damage = nametags.getArrowDamage(arrow);
if (damage > 0) return original.copy().append(Text.literal(" (" + damage + ")").formatted(Formatting.RED)); if (!damage.equals("0")) return original.copy().append(Text.literal(" (" + damage + ")").formatted(Formatting.RED));
} }
return original; return original;
} }
@@ -1,26 +0,0 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.mixin.accessor.EntityRenderStateAccessor;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Nametags;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.client.render.entity.state.EntityRenderState;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text;
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(EntityRenderer.class)
public abstract class EntityRendererMixin<S extends EntityRenderState> {
@Inject(method = "renderLabelIfPresent", at = @At("HEAD"))
private void renderSneakingPlayerNametags(S state, Text text, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) {
Nametags nametags = ModuleManager.INSTANCE.getModuleByClass(Nametags.class);
if (nametags.isEnabled() && nametags.alwaysVisible.isEnabled())
((EntityRenderStateAccessor) state).setSneaking(false);
}
}
@@ -0,0 +1,60 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.NoRender;
import net.minecraft.block.enums.CameraSubmersionType;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.fog.FogModifier;
import net.minecraft.client.render.fog.FogRenderer;
import net.minecraft.entity.Entity;
import org.joml.Vector4f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(FogRenderer.class)
public abstract class FogRendererMixin {
@Unique
NoRender noRender;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(CallbackInfo ci) {
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
}
@Redirect(method = "applyFog(Lnet/minecraft/client/render/Camera;IZLnet/minecraft/client/render/RenderTickCounter;FLnet/minecraft/client/world/ClientWorld;)Lorg/joml/Vector4f;", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/fog/FogModifier;shouldApply(Lnet/minecraft/block/enums/CameraSubmersionType;Lnet/minecraft/entity/Entity;)Z"))
private boolean noRenderFogs(FogModifier instance, CameraSubmersionType cameraSubmersionType, Entity entity) {
if (!noRender.isEnabled()) return instance.shouldApply(cameraSubmersionType, entity);
String className = instance.getClass().getSimpleName();
if ((className.equals("BlindnessEffectFogModifier") && !noRender.blindnessEffect.isEnabled())
|| (className.equals("DarknessEffectFogModifier") && !noRender.darknessEffect.isEnabled())
|| ((className.equals("LavaFogModifier") || className.equals("WaterFogModifier")
|| className.equals("PowederSnowFogModifier")) && !noRender.fluidOverlay.isEnabled())
|| (className.equals("DimensionOrBossFogModifier") && !noRender.dimensionFog.isEnabled()))
return false;
return instance.shouldApply(cameraSubmersionType, entity);
}
@ModifyReturnValue(method = "getFogColor", at = @At("RETURN"))
private Vector4f modifyLavaFog(Vector4f original, Camera camera) {
if (noRender.isEnabled() && !noRender.fluidOverlay.isEnabled() &&
(camera.getSubmersionType() == CameraSubmersionType.LAVA
|| camera.getSubmersionType() == CameraSubmersionType.WATER))
return new Vector4f(original.x, original.y, original.z, 0f);
return original;
}
@ModifyExpressionValue(method = "getFogColor", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getUnderwaterVisibility()F"))
private float noRenderUnderwaterFog(float original) {
return (noRender.isEnabled() && !noRender.fluidOverlay.isEnabled()) ? 0 : original;
}
}
@@ -4,7 +4,7 @@ import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.event.events.GetFOVEvent; import me.retucio.camtweaks.event.events.GetFOVEvent;
import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Freecam; import me.retucio.camtweaks.module.modules.Freecam;
import me.retucio.camtweaks.module.modules.PerspectivePlus; import me.retucio.camtweaks.module.modules.NoRender;
import me.retucio.camtweaks.module.modules.Zoom; import me.retucio.camtweaks.module.modules.Zoom;
import me.retucio.camtweaks.util.interfaces.IVec3d; import me.retucio.camtweaks.util.interfaces.IVec3d;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
@@ -20,6 +20,7 @@ import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS; import static me.retucio.camtweaks.CameraTweaks.EVENT_BUS;
@@ -36,6 +37,9 @@ public abstract class GameRendererMixin {
@Unique @Unique
Freecam freecam; Freecam freecam;
@Unique
NoRender noRender;
@Shadow @Final @Shadow @Final
private MinecraftClient client; private MinecraftClient client;
@@ -46,6 +50,7 @@ public abstract class GameRendererMixin {
private void getModules(MinecraftClient client, HeldItemRenderer firstPersonHeldItemRenderer, BufferBuilderStorage buffers, CallbackInfo ci) { private void getModules(MinecraftClient client, HeldItemRenderer firstPersonHeldItemRenderer, BufferBuilderStorage buffers, CallbackInfo ci) {
zoom = ModuleManager.INSTANCE.getModuleByClass(Zoom.class);; zoom = ModuleManager.INSTANCE.getModuleByClass(Zoom.class);;
freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
} }
@ModifyReturnValue(method = "getFov", at = @At("RETURN")) @ModifyReturnValue(method = "getFov", at = @At("RETURN"))
@@ -103,4 +108,9 @@ public abstract class GameRendererMixin {
|| (freecam.isEnabled() && !freecam.renderHands.isEnabled())) || (freecam.isEnabled() && !freecam.renderHands.isEnabled()))
ci.cancel(); ci.cancel();
} }
@ModifyVariable(method = "renderWorld", ordinal = 6, at = @At(value = "STORE"))
private float noRenderNauseaDistortion(float scaledNauseaEffectFactor) {
return (noRender.isEnabled() && !noRender.nauseaEffect.isEnabled()) ? 0 : scaledNauseaEffectFactor;
}
} }
@@ -4,11 +4,15 @@ import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.ChatPlus; import me.retucio.camtweaks.module.modules.ChatPlus;
import me.retucio.camtweaks.module.modules.Freecam; import me.retucio.camtweaks.module.modules.Freecam;
import me.retucio.camtweaks.module.modules.NoRender;
import me.retucio.camtweaks.ui.HUD; import me.retucio.camtweaks.ui.HUD;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.hud.InGameHud; import net.minecraft.client.gui.hud.InGameHud;
import net.minecraft.client.render.RenderTickCounter; import net.minecraft.client.render.RenderTickCounter;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin; 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.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -16,6 +20,50 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(InGameHud.class) @Mixin(InGameHud.class)
public abstract class InGameHudMixin { public abstract class InGameHudMixin {
@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")) @Inject(method = "render", at = @At("RETURN"))
private void renderHUD(DrawContext ctx, RenderTickCounter tc, CallbackInfo ci) { private void renderHUD(DrawContext ctx, RenderTickCounter tc, CallbackInfo ci) {
HUD.render(ctx, tc); HUD.render(ctx, tc);
@@ -0,0 +1,35 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.NoRender;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.hud.InGameOverlayRenderer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.MatrixStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(InGameOverlayRenderer.class)
public abstract class InGameOverlayRendererMixin {
@Unique
private static NoRender noRender;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(MinecraftClient client, VertexConsumerProvider vertexConsumers, CallbackInfo ci) {
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
}
@Inject(method = "renderFireOverlay", at = @At("HEAD"), cancellable = true)
private static void noRenderFireOverlay(MatrixStack matrices, VertexConsumerProvider vertexConsumers, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.fireOverlay.isEnabled()) ci.cancel();
}
@Inject(method = "renderUnderwaterOverlay", at = @At("HEAD"), cancellable = true)
private static void noRenderUnderwaterOverlay(MinecraftClient client, MatrixStack matrices, VertexConsumerProvider vertexConsumers, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.fluidOverlay.isEnabled()) ci.cancel();
}
}
@@ -5,11 +5,9 @@ import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.textures.GpuTexture; import com.mojang.blaze3d.textures.GpuTexture;
import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Fullbright; import me.retucio.camtweaks.module.modules.Fullbright;
import me.retucio.camtweaks.module.modules.PerspectivePlus;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.GameRenderer; import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.render.LightmapTextureManager; import net.minecraft.client.render.LightmapTextureManager;
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
import net.minecraft.util.math.ColorHelper; import net.minecraft.util.math.ColorHelper;
import net.minecraft.util.profiler.Profiler; import net.minecraft.util.profiler.Profiler;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
@@ -37,7 +35,12 @@ public abstract class LightmapTextureManagerMixin {
@Inject(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;push(Ljava/lang/String;)V", shift = At.Shift.AFTER), cancellable = true) @Inject(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;push(Ljava/lang/String;)V", shift = At.Shift.AFTER), cancellable = true)
private void update(float tickProgress, CallbackInfo ci, @Local Profiler profiler) { private void update(float tickProgress, CallbackInfo ci, @Local Profiler profiler) {
if (fullbright.isEnabled() && fullbright.mode.is(Fullbright.Modes.GAMMA)) { if (fullbright.isEnabled() && fullbright.mode.is(Fullbright.Modes.GAMMA)) {
RenderSystem.getDevice().createCommandEncoder().clearColorTexture(glTexture, ColorHelper.getArgb(255, 255, 255, 255)); RenderSystem.getDevice().createCommandEncoder().clearColorTexture(glTexture, ColorHelper.getArgb(
fullbright.alpha.getIntValue(),
fullbright.red.getIntValue(),
fullbright.green.getIntValue(),
fullbright.blue.getIntValue()
));
profiler.pop(); profiler.pop();
ci.cancel(); ci.cancel();
} }
@@ -1,18 +1,55 @@
package me.retucio.camtweaks.mixin; package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import com.llamalad7.mixinextras.sugar.Local;
import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.Freecam; import me.retucio.camtweaks.module.modules.Freecam;
import me.retucio.camtweaks.module.modules.Nametags;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.render.entity.LivingEntityRenderer; import net.minecraft.client.render.entity.LivingEntityRenderer;
import net.minecraft.client.render.entity.PlayerEntityRenderer;
import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(LivingEntityRenderer.class) @Mixin(LivingEntityRenderer.class)
public abstract class LivingEntityRendererMixin { public abstract class LivingEntityRendererMixin<T extends LivingEntity> {
@Unique
Nametags nametags;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(EntityRendererFactory.Context ctx, EntityModel<?> model, float shadowRadius, CallbackInfo ci) {
nametags = ModuleManager.INSTANCE.getModuleByClass(Nametags.class);
}
@ModifyExpressionValue(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;getCameraEntity()Lnet/minecraft/entity/Entity;")) @ModifyExpressionValue(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;getCameraEntity()Lnet/minecraft/entity/Entity;"))
private Entity hasLabelGetCameraEntityProxy(Entity cameraEntity) { private Entity hasLabelGetCameraEntityProxy(Entity cameraEntity) {
return ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled() ? null : cameraEntity; return ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled() ? null : cameraEntity;
} }
@ModifyExpressionValue(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;isSneaky()Z"))
private boolean renderSneakingPlayerNametags(boolean original) {
return (nametags.isEnabled() && nametags.alwaysVisible.isEnabled()) || original;
}
@ModifyExpressionValue(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;isInvisibleTo(Lnet/minecraft/entity/player/PlayerEntity;)Z"))
private boolean renderInvisPlayerNametags(boolean original) {
if (nametags.isEnabled() && nametags.alwaysVisible.isEnabled()) return false;
else return original;
}
@ModifyReturnValue(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At("RETURN"))
private boolean shouldRenderPlayerNametag(boolean original, @Local(argsOnly = true) T livingEntity) {
if (nametags.isEnabled() && livingEntity instanceof PlayerEntity) return nametags.entities.isEnabled(EntityType.PLAYER) && original;
return original;
}
} }
@@ -0,0 +1,24 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.DamageOverlay;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.texture.NativeImageBackedTexture;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(OverlayTexture.class)
public abstract class OverlayTextureMixin implements AutoCloseable {
@Shadow @Final
private NativeImageBackedTexture texture;
@Inject(method = "<init>", at = @At("TAIL"))
private void modifyDamageOverlayColor(CallbackInfo ci) {
ModuleManager.INSTANCE.getModuleByClass(DamageOverlay.class).reloadOverlay(texture);
}
}
@@ -0,0 +1,22 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.NoRender;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.particle.ParticleManager;
import net.minecraft.particle.ParticleEffect;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ParticleManager.class)
public abstract class ParticleManagerMixin {
@Inject(method = "addParticle(Lnet/minecraft/particle/ParticleEffect;DDDDDD)Lnet/minecraft/client/particle/Particle;", at = @At("HEAD"), cancellable = true)
private void noRenderParticles(ParticleEffect parameters, double x, double y, double z, double velocityX, double velocityY, double velocityZ, CallbackInfoReturnable<Particle> cir) {
NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
if (!noRender.isEnabled()) return;
if (!noRender.particles.isEnabled(parameters.getType())) cir.setReturnValue(null);
}
}
@@ -22,7 +22,6 @@ public abstract class PlayerEntityMixin extends LivingEntity {
@ModifyReturnValue(method = "getDisplayName", at = @At("RETURN")) @ModifyReturnValue(method = "getDisplayName", at = @At("RETURN"))
private Text addHealthIndicator(Text original) { private Text addHealthIndicator(Text original) {
Nametags nametags = ModuleManager.INSTANCE.getModuleByClass(Nametags.class); Nametags nametags = ModuleManager.INSTANCE.getModuleByClass(Nametags.class);
if (nametags.isEnabled() && !nametags.namePlayers.isEnabled()) return null;
if (!nametags.isEnabled() || !nametags.health.isEnabled()) return original; if (!nametags.isEnabled() || !nametags.health.isEnabled()) return original;
float health = getHealth(); float health = getHealth();
@@ -34,6 +33,7 @@ public abstract class PlayerEntityMixin extends LivingEntity {
else color = Formatting.DARK_GREEN; else color = Formatting.DARK_GREEN;
// me gustaría también añadir un modo en el que se renderizan los corazones directamente en la nametag, pero no sé cómo hacer para las imágenes :'( // me gustaría también añadir un modo en el que se renderizan los corazones directamente en la nametag, pero no sé cómo hacer para las imágenes :'(
// ahora que lo pienso en la snapshot más reciente han metido iconos que se pueden usar en texto, y uno de ellos es un corazón :D
return original.copy().append(Text.literal(" [" + color + (nametags.healthMode.is(Nametags.HealthMode.HEARTS) return original.copy().append(Text.literal(" [" + color + (nametags.healthMode.is(Nametags.HealthMode.HEARTS)
? String.format("%.2f", health / 2) : (int) health) + Formatting.RESET + "]")); ? String.format("%.2f", health / 2) : (int) health) + Formatting.RESET + "]"));
} // redondear a dos decimales } // redondear a dos decimales
@@ -0,0 +1,53 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.ScreenshotPlus;
import net.minecraft.client.texture.NativeImage;
import net.minecraft.client.util.ScreenshotRecorder;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.io.File;
import java.io.IOException;
import java.util.function.Consumer;
@Mixin(ScreenshotRecorder.class)
public abstract class ScreenshotRecorderMixin {
// "method_22691" es la lambda de la función "saveScreenshot()" (por lo menos en 1.21.6)
@Inject(method = "method_22691", at = @At(value = "INVOKE", target = "Ljava/util/function/Consumer;accept(Ljava/lang/Object;)V"), cancellable = true)
private static void sendActionsMessage(NativeImage nativeImage, File file, Consumer<Text> consumer, CallbackInfo ci) {
ScreenshotPlus screenshotPlus = getScreenshotPlus();
if (screenshotPlus.isEnabled()) ci.cancel();
}
@Inject(method = "method_22691", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/texture/NativeImage;writeTo(Ljava/io/File;)V"), cancellable = true)
private static void interceptScreenshotFile(NativeImage nativeImage, File file, Consumer<Text> consumer, CallbackInfo ci) throws IOException {
ScreenshotPlus screenshotPlus = getScreenshotPlus();
// aunque el módulo esté apagado, pasar las referencias para poder usar los comandos para las capturas
screenshotPlus.setScreenshot(nativeImage);
screenshotPlus.setScreenshotFile(file);
if (!screenshotPlus.isEnabled()) return;
screenshotPlus.sendScreenshotMessage();
switch (screenshotPlus.defaultAction.getValue()) {
case COPY -> screenshotPlus.copyScreenshot(nativeImage);
case SAVE -> screenshotPlus.saveScreenshot();
case NONE -> ci.cancel();
}
ci.cancel();
}
@Unique
private static ScreenshotPlus getScreenshotPlus() {
return ModuleManager.INSTANCE.getModuleByClass(ScreenshotPlus.class);
}
}
@@ -0,0 +1,19 @@
package me.retucio.camtweaks.mixin;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.NoRender;
import net.minecraft.client.render.entity.feature.StuckArrowsFeatureRenderer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(StuckArrowsFeatureRenderer.class)
public abstract class StuckArrowsFeatureRendererMixin {
@ModifyReturnValue(method = "getObjectCount", at = @At("RETURN"))
private int noRenderStuckArrows(int original) {
NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
if (noRender.isEnabled() && !noRender.stuckArrows.isEnabled()) return 0;
return original;
}
}
@@ -0,0 +1,49 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.NoRender;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.text.Style;
import net.minecraft.text.TextColor;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.*;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
// falta italics pero no sé dónde se comprueba eso, no es aquí :P
@Mixin(TextRenderer.Drawer.class)
public abstract class TextRendererDrawerMixin {
@Unique
NoRender noRender;
@Inject(method = "<init>(Lnet/minecraft/client/font/TextRenderer;FFIIZ)V", at = @At("TAIL"))
private void getModules(TextRenderer textRenderer, float x, float y, int color, int backgroundColor, boolean shadow, CallbackInfo ci) {
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
}
@Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isBold()Z"))
private boolean noRenderBold(Style style) {
return !(noRender.isEnabled() && !noRender.bold.isEnabled()) && style.isBold();
}
@Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isUnderlined()Z"))
private boolean noRenderUnderlined(Style style) {
return !(noRender.isEnabled() && !noRender.underlined.isEnabled()) && style.isUnderlined();
}
@Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isStrikethrough()Z"))
private boolean noRenderStrikethrough(Style style) {
return !(noRender.isEnabled() && !noRender.strikethrough.isEnabled()) && style.isStrikethrough();
}
@Redirect(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isObfuscated()Z"))
private boolean noRenderMTS(Style style) {
return !(noRender.isEnabled() && !noRender.scrambledText.isEnabled()) && style.isObfuscated();
}
@ModifyArg(method = "accept", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/TextRenderer$Drawer;getRenderColor(Lnet/minecraft/text/TextColor;)I"))
private TextColor noRenderColor(TextColor original) {
return !noRender.color.is(NoRender.Colors.DEFAULT) ? TextColor.fromFormatting(noRender.color.getValue().toFormatting()) : original;
}
}
@@ -0,0 +1,43 @@
package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.NoRender;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.WeatherRendering;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.particle.ParticlesMode;
import net.minecraft.util.math.Vec3d;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List;
@Mixin(WeatherRendering.class)
public abstract class WeatherRenderingMixin {
@Unique
NoRender noRender;
@Inject(method = "<init>", at = @At("TAIL"))
public void getModules(CallbackInfo ci) {
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
}
@Inject(method = "addParticlesAndSound", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;addParticleClient(Lnet/minecraft/particle/ParticleEffect;DDDDDD)V"), cancellable = true)
private void noRainParticles(ClientWorld world, Camera camera, int ticks, ParticlesMode particlesMode, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.rain.isEnabled()) ci.cancel();
}
@Inject(method = "renderPrecipitation(Lnet/minecraft/client/render/VertexConsumerProvider;Lnet/minecraft/util/math/Vec3d;IFLjava/util/List;Ljava/util/List;)V", at = @At("HEAD"))
private void noRenderRainAndSnow(VertexConsumerProvider vertexConsumers, Vec3d pos, int range, float gradient, List<?> rainPieces, List<?> snowPieces, CallbackInfo ci) {
if (noRender.isEnabled()) {
if (!noRender.rain.isEnabled()) rainPieces.clear();
if (!noRender.snow.isEnabled()) snowPieces.clear();
}
}
}
@@ -1,11 +1,16 @@
package me.retucio.camtweaks.mixin; package me.retucio.camtweaks.mixin;
import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.modules.BlockOutline;
import me.retucio.camtweaks.module.modules.Freecam; import me.retucio.camtweaks.module.modules.Freecam;
import net.minecraft.client.render.WorldRenderer; import net.minecraft.client.render.WorldRenderer;
import net.minecraft.util.math.ColorHelper;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.awt.*;
@Mixin(WorldRenderer.class) @Mixin(WorldRenderer.class)
public abstract class WorldRendererMixin { public abstract class WorldRendererMixin {
@@ -14,4 +19,30 @@ public abstract class WorldRendererMixin {
private boolean renderSetupTerrainModifyArg(boolean hasForcedFrustum) { private boolean renderSetupTerrainModifyArg(boolean hasForcedFrustum) {
return ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled() || hasForcedFrustum; return ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled() || hasForcedFrustum;
} }
@Redirect(method = "renderTargetBlockOutline", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/ColorHelper;withAlpha(II)I"))
private int modifyBlockOutlineColor(int alpha, int rgb) {
BlockOutline outline = ModuleManager.INSTANCE.getModuleByClass(BlockOutline.class);
if (!outline.isEnabled()) return ColorHelper.withAlpha(alpha, rgb);
if (outline.rainbow.isEnabled()) {
float speed = 10001 - outline.rainbowSpeed.getFloatValue(); // 10001 para evitar divisiones por cero
float hue = (System.currentTimeMillis() % (int) speed) / speed;
Color gamingProMax = Color.getHSBColor(hue, 1, 1);
return new Color(
gamingProMax.getRed(),
gamingProMax.getGreen(),
gamingProMax.getBlue(),
outline.alpha.getIntValue()
).getRGB();
} else {
return new Color(
outline.red.getIntValue(),
outline.green.getIntValue(),
outline.blue.getIntValue(),
outline.alpha.getIntValue()
).getRGB();
}
}
} }
@@ -1,12 +0,0 @@
package me.retucio.camtweaks.mixin.accessor;
import net.minecraft.client.render.entity.state.EntityRenderState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(EntityRenderState.class)
public interface EntityRenderStateAccessor {
@Accessor("sneaking")
void setSneaking(boolean sneaking);
}
@@ -6,7 +6,7 @@ import me.retucio.camtweaks.event.events.camtweaks.ToggleModuleEvent;
import me.retucio.camtweaks.module.settings.BooleanSetting; import me.retucio.camtweaks.module.settings.BooleanSetting;
import me.retucio.camtweaks.module.settings.EnumSetting; import me.retucio.camtweaks.module.settings.EnumSetting;
import me.retucio.camtweaks.module.settings.KeySetting; import me.retucio.camtweaks.module.settings.KeySetting;
import me.retucio.camtweaks.module.settings.Setting; import me.retucio.camtweaks.module.settings.AbstractSetting;
import me.retucio.camtweaks.util.ChatUtil; import me.retucio.camtweaks.util.ChatUtil;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
@@ -22,13 +22,14 @@ public class Module {
private String name; private String name;
private String description; private String description;
private boolean enabled; private boolean enabled;
private boolean saveSettings = true;
// dejar al usuario elegir si el módulo debería apagarse tras soltar su tecla asignada, o si la tecla debería alternar su estado // dejar al usuario elegir si el módulo debería apagarse tras soltar su tecla asignada, o si la tecla debería alternar su estado
protected EnumSetting<KeyModes> keyMode = new EnumSetting<>("modo de tecla", "cómo interpretar la tecla configurada", KeyModes.class, KeyModes.TOGGLE); protected EnumSetting<KeyModes> keyMode = new EnumSetting<>("modo de tecla", "cómo interpretar la tecla configurada", KeyModes.class, KeyModes.TOGGLE);
protected KeySetting bind = new KeySetting("tecla", "tecla asignada al módulo, ESC para desactivar", GLFW.GLFW_KEY_UNKNOWN); protected KeySetting bind = new KeySetting("tecla", "tecla asignada al módulo, ESC para desactivar", GLFW.GLFW_KEY_UNKNOWN);
protected BooleanSetting notify = new BooleanSetting("notificar", "notificar en el chat al activar / desactivar", true); protected BooleanSetting notify = new BooleanSetting("notificar", "notificar en el chat al activar / desactivar", true);
private final List<Setting> settings = new ArrayList<>(); private final List<AbstractSetting> settings = new ArrayList<>();
protected MinecraftClient mc = MinecraftClient.getInstance(); protected MinecraftClient mc = MinecraftClient.getInstance();
@@ -40,19 +41,19 @@ public class Module {
// ajustes // ajustes
public List<Setting> getSettings() { public List<AbstractSetting> getSettings() {
return settings; return settings;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <S extends Setting> S addSetting(Setting setting) { public <S extends AbstractSetting> S addSetting(AbstractSetting setting) {
settings.add(setting); settings.add(setting);
setting.setModule(this); setting.setModule(this);
return (S) setting; // por convenciencia return (S) setting; // por convenciencia
} }
public void addSettings(Setting... settings) { public void addSettings(AbstractSetting... settings) {
for (Setting setting : settings) addSetting(setting); for (AbstractSetting setting : settings) addSetting(setting);
} }
@@ -115,6 +116,14 @@ public class Module {
return keyMode.is(KeyModes.HOLD); return keyMode.is(KeyModes.HOLD);
} }
public boolean shouldSaveSettings() {
return saveSettings;
}
public void shouldSaveSettings(boolean value) {
this.saveSettings = value;
}
public int getKey() { public int getKey() {
return bind.getKey(); return bind.getKey();
} }
@@ -22,16 +22,21 @@ public class ModuleManager {
addModules(); addModules();
} }
// por order alfabético y todo, flipas // por orden alfabético y todo, flipas
private void addModules() { private void addModules() {
modules.add(new BlockOutline());
modules.add(new BossbarStack()); modules.add(new BossbarStack());
modules.add(new ChatPlus()); modules.add(new ChatPlus());
modules.add(new CritsPlus());
modules.add(new DamageOverlay());
modules.add(new Freecam()); modules.add(new Freecam());
modules.add(new Freelook()); modules.add(new Freelook());
modules.add(new Fullbright()); modules.add(new Fullbright());
modules.add(new HandView()); modules.add(new HandView());
modules.add(new PerspectivePlus());
modules.add(new Nametags()); modules.add(new Nametags());
modules.add(new NoRender());
modules.add(new PerspectivePlus());
modules.add(new ScreenshotPlus());
modules.add(new TimeChanger()); modules.add(new TimeChanger());
modules.add(new Zoom()); modules.add(new Zoom());
@@ -0,0 +1,31 @@
package me.retucio.camtweaks.module.modules;
import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.module.settings.BooleanSetting;
import me.retucio.camtweaks.module.settings.NumberSetting;
/** continúa en:
* @see me.retucio.camtweaks.mixin.WorldRendererMixin
*/
public class BlockOutline extends Module {
public BooleanSetting rainbow = addSetting(new BooleanSetting("RGB", "erre ge be gueiming", false));
public NumberSetting rainbowSpeed = addSetting(new NumberSetting("velocidad", "velocidad de la bandera gay", 2000, 0, 10000, 2));
public NumberSetting red = addSetting(new NumberSetting("rojo", "factor r del rbg", 0, 0, 255, 1));
public NumberSetting green = addSetting(new NumberSetting("verde", "factor g del rgb", 0, 0, 255, 1));
public NumberSetting blue = addSetting(new NumberSetting("azul", "factor b del rbg", 0, 0, 255, 1));
public NumberSetting alpha = addSetting(new NumberSetting("opacidad", "transparencia invertida", 102, 0, 255, 1));
public BlockOutline() {
super("contorno", "customiza el contorno de los bloques");
rainbow.onUpdate(v -> {
rainbowSpeed.setVisible(v);
red.setVisible(!v);
green.setVisible(!v);
blue.setVisible(!v);
});
}
}
@@ -12,7 +12,6 @@ import me.retucio.camtweaks.event.events.SendMessageEvent;
import me.retucio.camtweaks.module.Module; import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.module.settings.BooleanSetting; import me.retucio.camtweaks.module.settings.BooleanSetting;
import me.retucio.camtweaks.module.settings.NumberSetting; import me.retucio.camtweaks.module.settings.NumberSetting;
import me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame;
import me.retucio.camtweaks.util.ChatUtil; import me.retucio.camtweaks.util.ChatUtil;
import me.retucio.camtweaks.util.interfaces.IChatHudLine; import me.retucio.camtweaks.util.interfaces.IChatHudLine;
import me.retucio.camtweaks.util.interfaces.IChatHudLineVisible; import me.retucio.camtweaks.util.interfaces.IChatHudLineVisible;
@@ -0,0 +1,38 @@
package me.retucio.camtweaks.module.modules;
import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.module.settings.BooleanSetting;
import me.retucio.camtweaks.module.settings.NumberSetting;
/** continúa en:
* @see me.retucio.camtweaks.mixin.DamageParticleMixin
* @see me.retucio.camtweaks.mixin.DamageParticleFactoryMixin
*/
public class CritsPlus extends Module {
public BooleanSetting rainbow = addSetting(new BooleanSetting("LUCES GAMING", "PARTÍCULAS GAMING", false));
public NumberSetting rainbowSpeed = addSetting(new NumberSetting("velocidad del erre ge be", "qué tan gaming son las luces gaming", 1000, 0, 10000, 2));
public NumberSetting red = addSetting(new NumberSetting("rojo", "comunismo", 0, 0, 255, 1));
public NumberSetting green = addSetting(new NumberSetting("verde", "vox", 0, 0, 255, 1));
public NumberSetting blue = addSetting(new NumberSetting("azul", "metanfetamina", 255, 0, 255, 1));
public NumberSetting alpha = addSetting(new NumberSetting("alpha", "opacidad", 255, 0, 255, 1));
public NumberSetting scale = addSetting(new NumberSetting("escala", "tamaño", 1, 0, 2, 0.05));
public NumberSetting multiplier; // no sé dónde se calcula cuántas partículas aparecen :/
public NumberSetting velocityMultipler = addSetting(new NumberSetting("dispersión", "multiplicador de la velocidad de dispersión", 1, 0, 10, 0.1));
public NumberSetting gravity = addSetting(new NumberSetting("gravedad", "multiplicador de fuerza de gravedad", 1, 0, 10, 0.1));
public NumberSetting maxAge = addSetting(new NumberSetting("vida máxima", "cuánto persiste la partícula", 4, 0, 50, 1));
public BooleanSetting collide = addSetting(new BooleanSetting("colisionar", "colisionar con bloques", false));
public CritsPlus() {
super("críticos", "cambia la apariencia de los críticos al gusto");
rainbow.onUpdate(v -> {
rainbowSpeed.setVisible(v);
red.setVisible(!v);
green.setVisible(!v);
blue.setVisible(!v);
});
}
}
@@ -0,0 +1,75 @@
package me.retucio.camtweaks.module.modules;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.textures.GpuTextureView;
import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.module.settings.NumberSetting;
import net.minecraft.client.texture.NativeImage;
import net.minecraft.client.texture.NativeImageBackedTexture;
import java.awt.*;
/** continúa en:
* @see me.retucio.camtweaks.mixin.OverlayTextureMixin
*/
public class DamageOverlay extends Module {
public NumberSetting red = addSetting(new NumberSetting("rojo", "r o j o", 255, 0, 255, 1));
public NumberSetting green = addSetting(new NumberSetting("verde", "v e r d e", 0, 0, 255, 1));
public NumberSetting blue = addSetting(new NumberSetting("azul", "a z u l", 0, 0, 255, 1));
public NumberSetting alpha = addSetting(new NumberSetting("alpha", "o p a c i d a d", 77, 0, 255, 1));
private NativeImageBackedTexture texture = null;
public DamageOverlay() {
super("superposición de daño", "modifica el color en el que se renderiza la superposición de recibir daño");
NumberSetting[] settings = {red, green, blue, alpha};
for (NumberSetting setting : settings)
setting.onUpdate(v -> reloadOverlayIfReady());
}
@Override
public void onEnable() {
reloadOverlayIfReady();
super.onEnable();
}
@Override
public void onDisable() {
reloadOverlayIfReady();
super.onDisable();
}
private void reloadOverlayIfReady() {
if (texture != null && texture.getImage() != null) reloadOverlay(texture);
}
// recargar el overlay (superposición)
public void reloadOverlay(NativeImageBackedTexture texture) {
if (this.texture == null) this.texture = texture;
int color = isEnabled() ?
new Color(red.getIntValue(), green.getIntValue(), blue.getIntValue(), 255 - alpha.getIntValue()).getRGB()
: new Color(255, 0, 0, 178).getRGB();
NativeImage image = texture.getImage();
for (int y = 0; y < 8; y++)
for (int x = 0; x < 16; x++)
image.setColorArgb(x, y, color);
uploadTexture();
}
// resubir las texturas
private void uploadTexture() {
GpuTextureView overlayTex = RenderSystem.getShaderTexture(33985);
RenderSystem.setShaderTexture(33985, overlayTex);
texture.upload();
GpuTextureView mainTex = RenderSystem.getShaderTexture(33984);
RenderSystem.setShaderTexture(33984, mainTex);
}
}
@@ -1,5 +1,6 @@
package me.retucio.camtweaks.module.modules; package me.retucio.camtweaks.module.modules;
import me.retucio.camtweaks.event.Stage;
import me.retucio.camtweaks.event.SubscribeEvent; import me.retucio.camtweaks.event.SubscribeEvent;
import me.retucio.camtweaks.event.events.*; import me.retucio.camtweaks.event.events.*;
import me.retucio.camtweaks.module.Module; import me.retucio.camtweaks.module.Module;
@@ -24,6 +25,7 @@ import org.lwjgl.glfw.GLFW;
/** continúa en: /** continúa en:
* @see me.retucio.camtweaks.mixin.CameraMixin * @see me.retucio.camtweaks.mixin.CameraMixin
* @see me.retucio.camtweaks.mixin.ChunkBorderDebugRendererMixin * @see me.retucio.camtweaks.mixin.ChunkBorderDebugRendererMixin
* @see me.retucio.camtweaks.mixin.ClientPlayerInteractionManagerMixin
* @see me.retucio.camtweaks.mixin.CompassStateMixin * @see me.retucio.camtweaks.mixin.CompassStateMixin
* @see me.retucio.camtweaks.mixin.EntityMixin * @see me.retucio.camtweaks.mixin.EntityMixin
* @see me.retucio.camtweaks.mixin.GameRendererMixin * @see me.retucio.camtweaks.mixin.GameRendererMixin
@@ -63,7 +65,7 @@ public class Freecam extends Module {
private float yaw, pitch; private float yaw, pitch;
public Freecam() { public Freecam() {
super("cámara libre", "perrmite a la cámara moverse independientemente del jugador. útil para explorar alrededores"); super("cámara libre", "permite a la cámara moverse independientemente del jugador. útil para explorar alrededores");
assignKey(GLFW.GLFW_KEY_V); assignKey(GLFW.GLFW_KEY_V);
speedSetting.onUpdate(newSpeed -> speed = newSpeed); speedSetting.onUpdate(newSpeed -> speed = newSpeed);
} }
@@ -187,12 +189,13 @@ public class Freecam extends Module {
@SubscribeEvent @SubscribeEvent
public void onPacketSend(PacketEvent.Send event) { public void onPacketSend(PacketEvent.Send event) {
if (!isEnabled() || !cancelActionPackets.isEnabled()) return; if (!isEnabled() || !cancelActionPackets.isEnabled()) return;
if (event.getStage() != Stage.PRE) return;
Packet<?> p = event.getPacket(); Packet<?> packet = event.getPacket();
if (p instanceof PlayerActionC2SPacket if (packet instanceof PlayerActionC2SPacket
|| p instanceof PlayerInteractBlockC2SPacket || packet instanceof PlayerInteractBlockC2SPacket
|| p instanceof PlayerInteractItemC2SPacket || packet instanceof PlayerInteractItemC2SPacket
|| p instanceof HandSwingC2SPacket) { || packet instanceof HandSwingC2SPacket) {
event.cancel(); event.cancel();
} }
} }
@@ -200,7 +203,7 @@ public class Freecam extends Module {
@SubscribeEvent @SubscribeEvent
public void onKey(KeyEvent event) { public void onKey(KeyEvent event) {
if (mc.currentScreen != null) return; if (mc.currentScreen != null) return;
if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_F3)) return; // ? if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_F3)) return;
boolean shouldCancel = true; boolean shouldCancel = true;
if (mc.options.forwardKey.matchesKey(event.getKey(), event.getScancode())) { if (mc.options.forwardKey.matchesKey(event.getKey(), event.getScancode())) {
@@ -3,6 +3,7 @@ package me.retucio.camtweaks.module.modules;
import me.retucio.camtweaks.mixin.accessor.StatusEffectInstanceAccessor; import me.retucio.camtweaks.mixin.accessor.StatusEffectInstanceAccessor;
import me.retucio.camtweaks.module.Module; import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.module.settings.EnumSetting; import me.retucio.camtweaks.module.settings.EnumSetting;
import me.retucio.camtweaks.module.settings.NumberSetting;
import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects; import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
@@ -16,10 +17,29 @@ public class Fullbright extends Module {
public EnumSetting<Modes> mode = addSetting(new EnumSetting<>("modo", "qué modo de iluminación emplear (usar poción con shaders)", Modes.class, Modes.GAMMA)); public EnumSetting<Modes> mode = addSetting(new EnumSetting<>("modo", "qué modo de iluminación emplear (usar poción con shaders)", Modes.class, Modes.GAMMA));
public NumberSetting red = addSetting(new NumberSetting("rojo", "cantidad de rojo a aplicar",
255, 0, 255, 1));
public NumberSetting green = addSetting(new NumberSetting("verde", "cantidad de verde a aplicar",
255, 0, 255, 1));
public NumberSetting blue = addSetting(new NumberSetting("azul", "cantidad de azul a aplicar",
255, 0, 255, 1));
public NumberSetting alpha = addSetting(new NumberSetting("opacidad", "opacidad del shader",
255, 0, 255, 1));
public Fullbright() { public Fullbright() {
super("brilli brilli", "deshabilita la oscuridad"); super("brilli brilli", "deshabilita la oscuridad (y aplica colores a los shaders)");
assignKey(GLFW.GLFW_KEY_K); assignKey(GLFW.GLFW_KEY_K);
mode.onUpdate(mode -> { if (mode != Modes.POTION) disableNightVision(); }); mode.onUpdate(mode -> { if (mode != Modes.POTION) disableNightVision(); });
mode.onUpdate(mode -> {
boolean v = mode.equals(Modes.GAMMA);
red.setVisible(v);
green.setVisible(v);
blue.setVisible(v);
alpha.setVisible(v);
});
} }
@Override @Override
@@ -34,7 +54,7 @@ public class Fullbright extends Module {
if (mc.player.hasStatusEffect(Registries.STATUS_EFFECT.getEntry(StatusEffects.NIGHT_VISION.value()))) { if (mc.player.hasStatusEffect(Registries.STATUS_EFFECT.getEntry(StatusEffects.NIGHT_VISION.value()))) {
StatusEffectInstance instance = mc.player.getStatusEffect(Registries.STATUS_EFFECT.getEntry(StatusEffects.NIGHT_VISION.value())); StatusEffectInstance instance = mc.player.getStatusEffect(Registries.STATUS_EFFECT.getEntry(StatusEffects.NIGHT_VISION.value()));
if (instance != null && instance.getDuration() < 69) ((StatusEffectInstanceAccessor) instance).setDuration(69); if (instance != null && instance.getDuration() < 5200) ((StatusEffectInstanceAccessor) instance).setDuration(5200);
} else { } else {
mc.player.addStatusEffect(new StatusEffectInstance(Registries.STATUS_EFFECT.getEntry(StatusEffects.NIGHT_VISION.value()), 69, 0)); mc.player.addStatusEffect(new StatusEffectInstance(Registries.STATUS_EFFECT.getEntry(StatusEffects.NIGHT_VISION.value()), 69, 0));
} }
@@ -53,8 +73,6 @@ public class Fullbright extends Module {
private final String name; private final String name;
Modes(String name) { this.name = name; } Modes(String name) { this.name = name; }
@Override public String toString() { return name; }
@Override
public String toString() { return name; }
} }
} }
@@ -1,6 +1,12 @@
package me.retucio.camtweaks.module.modules; package me.retucio.camtweaks.module.modules;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.command.CommandManager; import me.retucio.camtweaks.command.CommandManager;
import me.retucio.camtweaks.event.SubscribeEvent;
import me.retucio.camtweaks.event.events.TickEvent;
import me.retucio.camtweaks.event.events.camtweaks.LoadClickGUIEvent;
import me.retucio.camtweaks.event.events.camtweaks.LoadCommandManagerEvent;
import me.retucio.camtweaks.event.events.camtweaks.LoadModuleManagerEvent;
import me.retucio.camtweaks.module.Module; import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.module.settings.BooleanSetting; import me.retucio.camtweaks.module.settings.BooleanSetting;
@@ -12,37 +18,47 @@ import org.lwjgl.glfw.GLFW;
import java.awt.*; import java.awt.*;
import static me.retucio.camtweaks.CameraTweaks.LOGGER;
import static me.retucio.camtweaks.util.Colors.*; import static me.retucio.camtweaks.util.Colors.*;
// módulo no visible solo para los ajustes de la interfaz (y del cliente en general) // módulo no visible solo para los ajustes de la interfaz (y del cliente en general)
public class GUI extends Module { public class GUI extends Module {
public BooleanSetting rainbow = addSetting(new BooleanSetting("gaming", "gaming", false));
public NumberSetting rainbowSpeed = addSetting(new NumberSetting("velocidad del gaming", "velocidad, del gaming.",
1000, 0, 10000, 2));
public NumberSetting red = addSetting(new NumberSetting("rojo", "cantidad de rojo en el RGB del marco", 0, 0, 255, 1)); public NumberSetting red = addSetting(new NumberSetting("rojo", "cantidad de rojo en el RGB del marco", 0, 0, 255, 1));
public NumberSetting green = addSetting(new NumberSetting("verde", "cantidad de verde en el RGB del marco", 0, 0, 255, 1)); public NumberSetting green = addSetting(new NumberSetting("verde", "cantidad de verde en el RGB del marco", 0, 0, 255, 1));
public NumberSetting blue = addSetting(new NumberSetting("azul", "cantidad de azul en el RGB del marco", 255, 0, 255, 1)); public NumberSetting blue = addSetting(new NumberSetting("azul", "cantidad de azul en el RGB del marco", 255, 0, 255, 1));
public NumberSetting alpha = addSetting(new NumberSetting("alpha", "opacidad del marco", 180, 0, 255, 1)); public NumberSetting alpha = addSetting(new NumberSetting("alpha", "opacidad del marco", 180, 0, 255, 1));
// números negativos para deslizamiento inverso, 0 para desactivar
public NumberSetting scrollSens = addSetting(new NumberSetting("sensibilidad del scroll", "qué tan sensible es la interfaz a la rueda del ratón", public NumberSetting scrollSens = addSetting(new NumberSetting("sensibilidad del scroll", "qué tan sensible es la interfaz a la rueda del ratón",
5, 0, 15, 0.5)); 5, -15, 15, 0.5));
public StringSetting commandPrefix = addSetting(new StringSetting("prefijo", "prefijo de los comandos", "$", 10)); public StringSetting commandPrefix = addSetting(new StringSetting("prefijo", "prefijo de los comandos", "$", 10));
public StringSetting chatName = addSetting(new StringSetting("nombre", "qué nombre usar en notificaciones por el chat", "smegma", 20)); public StringSetting chatName = addSetting(new StringSetting("nombre", "qué nombre usar en notificaciones por el chat", "smegma", 20));
public BooleanSetting multipleKeybinds = addSetting(new BooleanSetting("teclas multimódulo", "permitir asignar la misma tecla a más de un módulo", false)); public BooleanSetting multipleKeybinds = addSetting(new BooleanSetting("teclas multimódulo", "permitir asignar la misma tecla a más de un módulo", false));
private int prevRed, prevGreen, prevBlue;
public GUI() { public GUI() {
super("interfaz", "ajustes de la interfaz, y otros misceláneos"); super("interfaz", "ajustes de la interfaz, y otros misceláneos");
assignKey(GLFW.GLFW_KEY_RIGHT_SHIFT); assignKey(GLFW.GLFW_KEY_RIGHT_SHIFT);
// registrar aquí, porque no se añade a ModuleManager.modules. de lo contrario no podría detectar eventos
CameraTweaks.EVENT_BUS.register(this);
keyMode.setVisible(false); keyMode.setVisible(false);
notify.setVisible(false); notify.setVisible(false);
}
@SubscribeEvent
public void onLoadCommandManager(LoadCommandManagerEvent event) {
commandPrefix.onUpdate(prefix -> CommandManager.INSTANCE.setPrefix(prefix)); commandPrefix.onUpdate(prefix -> CommandManager.INSTANCE.setPrefix(prefix));
red.onUpdate(r -> {frameHeadRed = r.intValue(); updateFrameHeadColor();}); commandPrefix.setDefaultValue(CommandManager.INSTANCE.getPrefix());
green.onUpdate(g -> {frameHeadGreen = g.intValue(); updateFrameHeadColor();});
blue.onUpdate(b -> {frameHeadBlue = b.intValue(); updateFrameHeadColor();});
alpha.onUpdate(a -> {frameHeadAlpha = a.intValue(); updateFrameHeadColor();});
if (mc != null) mc.execute(() -> commandPrefix.setDefaultValue(CommandManager.INSTANCE.getPrefix()));
chatName.onUpdate(name -> { chatName.onUpdate(name -> {
ChatUtil.updatePrefix(name); ChatUtil.updatePrefix(name);
@@ -50,6 +66,57 @@ public class GUI extends Module {
}); });
} }
// lógica un poco prolija pero bueno
@SubscribeEvent
public void onLoadClickGUI(LoadClickGUIEvent event) {
rainbow.onUpdate(v -> {
if (v) {
prevRed = red.getIntValue();
prevGreen = green.getIntValue();
prevBlue = blue.getIntValue();
} else {
red.setValue(prevRed);
green.setValue(prevGreen);
blue.setValue(prevBlue);
}
rainbowSpeed.setVisible(v);
red.setVisible(!v);
green.setVisible(!v);
blue.setVisible(!v);
applyRGBAColorUpdates();
});
red.onUpdate(r -> applyRGBAColorUpdates());
green.onUpdate(g -> applyRGBAColorUpdates());
blue.onUpdate(b -> applyRGBAColorUpdates());
alpha.onUpdate(a -> applyRGBAColorUpdates());
}
@SubscribeEvent
public void onTick(TickEvent.Post event) {
if (rainbow.isEnabled()) {
float speed = (float) (rainbowSpeed.getMax() - rainbowSpeed.getValue());
float hue = (System.currentTimeMillis() % (long) speed) / speed;
Color color = Color.getHSBColor(hue, 1f, 1f);
frameHeadRed = color.getRed();
frameHeadGreen = color.getGreen();
frameHeadBlue = color.getBlue();
updateFrameHeadColor();
}
}
private void applyRGBAColorUpdates() {
frameHeadRed = red.getIntValue();
frameHeadGreen = green.getIntValue();
frameHeadBlue = blue.getIntValue();
frameHeadAlpha = alpha.getIntValue();
updateFrameHeadColor();
}
private void updateFrameHeadColor() { private void updateFrameHeadColor() {
Colors.frameHeadColor = new Color( Colors.frameHeadColor = new Color(
frameHeadRed, frameHeadRed,
@@ -5,8 +5,10 @@ import com.google.gson.JsonParser;
import me.retucio.camtweaks.module.Module; import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.module.settings.BooleanSetting; import me.retucio.camtweaks.module.settings.BooleanSetting;
import me.retucio.camtweaks.module.settings.EnumSetting; import me.retucio.camtweaks.module.settings.EnumSetting;
import me.retucio.camtweaks.util.ChatUtil; import me.retucio.camtweaks.module.settings.ListSetting;
import me.retucio.camtweaks.util.Lists;
import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LazyEntityReference; import net.minecraft.entity.LazyEntityReference;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.damage.DamageSource;
@@ -14,7 +16,6 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity; import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import org.jetbrains.annotations.Nullable;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
@@ -29,30 +30,23 @@ import java.util.concurrent.Executors;
/** continúa en: /** continúa en:
* @see me.retucio.camtweaks.mixin.EntityMixin * @see me.retucio.camtweaks.mixin.EntityMixin
* @see me.retucio.camtweaks.mixin.ItemEntityMixin * @see me.retucio.camtweaks.mixin.ItemEntityMixin
* @see me.retucio.camtweaks.mixin.LivingEntityRendererMixin
* @see me.retucio.camtweaks.mixin.PlayerEntityMixin * @see me.retucio.camtweaks.mixin.PlayerEntityMixin
*/ */
public class Nametags extends Module { public class Nametags extends Module {
public BooleanSetting namePlayers = addSetting(new BooleanSetting("nombrar jugadores", "renderiza el nametag de jugadores", true)); public ListSetting<EntityType<?>> entities = addSetting(new ListSetting<>("entidades", "entidades cuyo nametag será visible",
Lists.entityList, Lists.allFalse(Lists.entityList), Lists.entityNames));
public BooleanSetting alwaysVisible = addSetting(new BooleanSetting("siempre mostrar nametags", "mostrar nametag cuando el jugador está agachado o es invisible", false));
public BooleanSetting health = addSetting(new BooleanSetting("mostrar vida", "muestra la vida de una entidad en su nametag", true)); public BooleanSetting health = addSetting(new BooleanSetting("mostrar vida", "muestra la vida de una entidad en su nametag", true));
public EnumSetting<HealthMode> healthMode = addSetting(new EnumSetting<>("mostrar vida en", "de qué manera mostrar la vida", HealthMode.class, HealthMode.POINTS)); public EnumSetting<HealthMode> healthMode = addSetting(new EnumSetting<>("mostrar vida en", "de qué manera mostrar la vida", HealthMode.class, HealthMode.POINTS));
public BooleanSetting alwaysVisible = addSetting(new BooleanSetting("siempre mostrar nametags", "mostrar nametags cuando no deberían de ser visibles", false));
public BooleanSetting namePassiveMobs = addSetting(new BooleanSetting("nombrar mobs pasivos", "renderiza el nametag de mobs pasivos", false));
public BooleanSetting nameHostileMobs = addSetting(new BooleanSetting("nombrar mobs hostiles", "renderiza el nametag de mobs hostiles", false));
public BooleanSetting nameMiscMobs = addSetting(new BooleanSetting("nombrar mobs neutrales", "renderiza el nametag de mobs neutrales", false));
public BooleanSetting distinguishBabies = addSetting(new BooleanSetting("distinguir bebés", "cambia el nametag cuando una entidad está en su fase bebé", false));
public BooleanSetting nameProjectiles = addSetting(new BooleanSetting("nombrar proyectiles", "renderiza el nametag de proyectiles", false));
public BooleanSetting showProjectileDamage = addSetting(new BooleanSetting("daño del proyectil", "muestra cuánto daño hace un proyectil en su nametag", false));
public BooleanSetting nameItems = addSetting(new BooleanSetting("nombrar items", "renderiza el nametag de items", true));
public BooleanSetting countItems = addSetting(new BooleanSetting("contar items", "muestra cuánto de un item hay en un stack dropeado", true)); public BooleanSetting countItems = addSetting(new BooleanSetting("contar items", "muestra cuánto de un item hay en un stack dropeado", true));
public BooleanSetting showProjectileDamage = addSetting(new BooleanSetting("daño del proyectil", "muestra cuánto daño hace un proyectil en su nametag", true));
public BooleanSetting nameVehicles = addSetting(new BooleanSetting("nombrar vehículos", "renderiza el nametag de botes, minecarts, ...", false)); public BooleanSetting distinguishBabies = addSetting(new BooleanSetting("distinguir bebés", "cambia el nametag cuando una entidad está en su fase bebé", false));
public BooleanSetting showPassengers = addSetting(new BooleanSetting("mostrar pasajeros", "muestra qué pasajeros tiene el vehículo", false));
public BooleanSetting petOwner = addSetting(new BooleanSetting("mostrar dueño", "muestra el dueño de una mascota (no funciona en servers no premium)", false)); public BooleanSetting petOwner = addSetting(new BooleanSetting("mostrar dueño", "muestra el dueño de una mascota (no funciona en servers no premium)", false));
private final Map<UUID, String> cache = new ConcurrentHashMap<>(); private final Map<UUID, String> cache = new ConcurrentHashMap<>();
@@ -61,46 +55,35 @@ public class Nametags extends Module {
public Nametags() { public Nametags() {
super("nametags", "modifica la manera en la que se renderizan los nametags"); super("nametags", "modifica la manera en la que se renderizan los nametags");
nameProjectiles.onUpdate(v -> showProjectileDamage.setVisible(v)); // entidades activadas por defecto
nameItems.onUpdate(v -> countItems.setVisible(v)); entities.setEnabled(EntityType.PLAYER, true);
nameVehicles.onUpdate(v -> showPassengers.setVisible(v)); entities.setEnabled(EntityType.ITEM, true);
entities.setEnabled(EntityType.ARROW, true);
namePassiveMobs.onUpdate(v -> distinguishBabies.setVisible(v || nameMiscMobs.isEnabled() || nameHostileMobs.isEnabled())); entities.setEnabled(EntityType.SPECTRAL_ARROW, true);
nameMiscMobs.onUpdate(v -> distinguishBabies.setVisible(v || namePassiveMobs.isEnabled() || nameHostileMobs.isEnabled())); entities.setEnabled(EntityType.TRIDENT, true);
nameHostileMobs.onUpdate(v -> distinguishBabies.setVisible(v || nameMiscMobs.isEnabled() || namePassiveMobs.isEnabled())); entities.setDefaultValues(entities.getValues());
health.onUpdate(v -> healthMode.setVisible(v)); health.onUpdate(v -> healthMode.setVisible(v));
} }
public enum HealthMode {
POINTS("hp (puntos de vida)"),
HEARTS("corazones");
private final String name;
HealthMode(String name) { this.name = name; }
@Override public String toString() { return name; }
}
// literalmente cómo lo calcula Minecraft // literalmente cómo lo calcula Minecraft
public float getArrowDamage(PersistentProjectileEntity arrow) { public String getArrowDamage(PersistentProjectileEntity arrow) {
if (mc.player == null) return 0; if (mc.player == null) return "0";
double initialDamage = 2; double initialDamage = 2;
double velocity = arrow.getVelocity().length(); double velocity = arrow.getVelocity().length();
DamageSource damageSource = arrow.getDamageSources().arrow(arrow, arrow.getOwner()); DamageSource damageSource = arrow.getDamageSources().arrow(arrow, arrow.getOwner());
if (arrow.getWeaponStack() != null) if (arrow.getWeaponStack() != null && arrow.getWorld() instanceof ServerWorld world)
if (arrow.getWorld() instanceof ServerWorld world) initialDamage = EnchantmentHelper.getDamage(world, arrow.getWeaponStack(), mc.player, damageSource, (float) initialDamage);
initialDamage = EnchantmentHelper.getDamage(world, arrow.getWeaponStack(), mc.player, damageSource, (float) initialDamage);
int finalDamage = MathHelper.ceil(MathHelper.clamp(velocity * initialDamage, 0, 2.147483647E9)); int finalDamage = MathHelper.ceil(MathHelper.clamp(velocity * initialDamage, 0, 2.147483647E9));
if (arrow.isCritical()) { long bonus = 0;
long bonus = arrow.getRandom().nextInt(finalDamage / 2 + 2); if (arrow.isCritical()) bonus = finalDamage / 2 - 1;
finalDamage = (int) Math.min(bonus + (long) finalDamage, 2147483647L);
}
return healthMode.is(HealthMode.HEARTS) ? finalDamage / 2f : finalDamage; if (healthMode.is(HealthMode.HEARTS)) finalDamage /= 2;
return finalDamage + (bonus > 0 ? " ~ " + (finalDamage + bonus) : "");
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@@ -141,4 +124,13 @@ public class Nametags extends Module {
return "..."; return "...";
} }
public enum HealthMode {
POINTS("hp (puntos de vida)"),
HEARTS("corazones");
private final String name;
HealthMode(String name) { this.name = name; }
@Override public String toString() { return name; }
}
} }
@@ -0,0 +1,89 @@
package me.retucio.camtweaks.module.modules;
import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.module.settings.BooleanSetting;
import me.retucio.camtweaks.module.settings.EnumSetting;
import me.retucio.camtweaks.module.settings.ListSetting;
import me.retucio.camtweaks.module.settings.NumberSetting;
import me.retucio.camtweaks.util.Lists;
import net.minecraft.particle.ParticleType;
import net.minecraft.util.Formatting;
/** continúa en:
* @see me.retucio.camtweaks.mixin.ClientPlayNetworkHandlerMixin
* @see me.retucio.camtweaks.mixin.EntityEffectParticleEffectMixin
* @see me.retucio.camtweaks.mixin.FogRendererMixin
* @see me.retucio.camtweaks.mixin.GameRendererMixin
* @see me.retucio.camtweaks.mixin.InGameHudMixin
* @see me.retucio.camtweaks.mixin.InGameOverlayRendererMixin
* @see me.retucio.camtweaks.mixin.ParticleManagerMixin
* @see me.retucio.camtweaks.mixin.StuckArrowsFeatureRendererMixin
* @see me.retucio.camtweaks.mixin.TextRendererDrawerMixin
* @see me.retucio.camtweaks.mixin.WeatherRenderingMixin
*/
public class NoRender extends Module {
public BooleanSetting spyglassOverlay = addSetting(new BooleanSetting("catalejo", "renderizar overlay del catalejo", false));
public BooleanSetting fluidOverlay = addSetting(new BooleanSetting("fluídos", "renderizar fluídos sobre la cámara como el agua, lava o nieve en polvo (aunque no sea un fluído)", false));
public BooleanSetting pumpkinOverlay = addSetting(new BooleanSetting("calabaza", "renderiza el overlay de la calabaza tallada", false));
public BooleanSetting fireOverlay = addSetting(new BooleanSetting("fuego", "renderizar llamas sobre la cámara", false));
public BooleanSetting portalOverlay = addSetting(new BooleanSetting("portal", "renderizar el overlay del portal del nether", false));
public BooleanSetting rain = addSetting(new BooleanSetting("lluvia", "l l u v i a", true));
public BooleanSetting snow = addSetting(new BooleanSetting("nieve", "n i e v e", true));
public BooleanSetting dimensionFog = addSetting(new BooleanSetting("niebla de dimensión", "n i e b l a", true));
public BooleanSetting endFlashes; // para cuando actualice
public ListSetting<ParticleType<?>> particles = addSetting(new ListSetting<>("partículas", "lista de partículas que se renderizan",
Lists.particleList, Lists.allTrue(Lists.particleList), Lists.particleNames));
public BooleanSetting nauseaEffect = addSetting(new BooleanSetting("náusea", "renderizar borrachera", false));
public BooleanSetting blindnessEffect = addSetting(new BooleanSetting("ceguera", "renderizar miopía", false));
public BooleanSetting darknessEffect = addSetting(new BooleanSetting("oscuridad", "renderizar miedo a la oscuridad", false));
public BooleanSetting nightVisionEffect;
public NumberSetting potionParticleAlpha = addSetting(new NumberSetting("opacidad de burbujas", "opacidad de las partículas de pociones",
170, 0, 255, 1));
public BooleanSetting scoreboard = addSetting(new BooleanSetting("marcador", "mostrar marcador a la derecha", false));
public BooleanSetting titles = addSetting(new BooleanSetting("títulos", "mostrar títulos (del comando /title)", false));
public BooleanSetting totemPop = addSetting(new BooleanSetting("tótem", "renderizar el pop del tótem", true));
public BooleanSetting stuckArrows = addSetting(new BooleanSetting("flechas clavadas", "renderizar flechas clavadas en jugadores", false));
public BooleanSetting bold = addSetting(new BooleanSetting("negrita", "letra pero §lgorda", true));
// public BooleanSetting italics = addSetting(new BooleanSetting("cursiva", "letra pero §otorcida", true));
public BooleanSetting underlined = addSetting(new BooleanSetting("subrayado", "letra pero §nen el suelo", true));
public BooleanSetting strikethrough = addSetting(new BooleanSetting("tachado", "letra pero §mdiscriminada", true));
public EnumSetting<Colors> color = addSetting(new EnumSetting<>("colores", "§co§4r§6g§eu§al§2l§9o §1g§5a§dy", Colors.class, Colors.DEFAULT));
public BooleanSetting scrambledText = addSetting(new BooleanSetting("garabato", "engarabatar texto (o como se diga) (§kasí§r)", false));
public NoRender() {
super("no render", "customiza qué se renderiza y qué no");
}
public enum Colors {
BLACK("negro"),
DARK_BLUE("azul oscuro"),
DARK_GREEN("verde"),
DARK_AQUA("cian"),
DARK_RED("granate"),
DARK_PURPLE("morado"),
GOLD("naranja"),
GRAY("gris claro"),
DARK_GRAY("gris oscuro"),
BLUE("azul"),
GREEN("lima"),
AQUA("turquesa"),
RED("rojo"),
LIGHT_PURPLE("lila"),
YELLOW("amarillo"),
WHITE("blanco"),
DEFAULT("por defecto");
private final String name;
Colors(String name) { this.name = name; }
@Override public String toString() { return name; }
public Formatting toFormatting() { return (Formatting.byColorIndex(this.ordinal())); }
}
}
@@ -0,0 +1,218 @@
package me.retucio.camtweaks.module.modules;
import me.retucio.camtweaks.command.CommandManager;
import me.retucio.camtweaks.event.events.ClientClickEvent;
import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.module.settings.BooleanSetting;
import me.retucio.camtweaks.module.settings.EnumSetting;
import me.retucio.camtweaks.util.ChatUtil;
import net.minecraft.client.texture.NativeImage;
import net.minecraft.text.ClickEvent;
import net.minecraft.text.HoverEvent;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
/** continúa en:
* @see me.retucio.camtweaks.mixin.ScreenshotRecorderMixin
*/
public class ScreenshotPlus extends Module {
public BooleanSetting saveButton = addSetting(new BooleanSetting("botón de guardar", "mostrar botón para guardar la captura localmente", true));
public BooleanSetting copyButton = addSetting(new BooleanSetting("botón de copiar", "mostrar botón para copiar la captura al portapapeles", true));
public BooleanSetting openButton = addSetting(new BooleanSetting("botón de abrir", "mostrar botón para abrir el archivo de la captura", true));
public BooleanSetting discardButton = addSetting(new BooleanSetting("botón de descartar", "mostrar botón para descartar la captura", true));
public EnumSetting<ScreenshotActions> defaultAction = addSetting(new EnumSetting<>("por defecto", "qué acción tomar por defecto",
ScreenshotActions.class, ScreenshotActions.NONE));
private NativeImage screenshot;
private File screenshotFile;
public ScreenshotPlus() {
super("capturas de pantalla", "elige qué hacer tras tomar una captura de pantalla");
}
public void sendScreenshotMessage() {
MutableText baseText = Text.literal("captura de pantalla tomada\n");
if (saveButton.isEnabled() && !defaultAction.is(ScreenshotActions.SAVE)) baseText.append(getSaveButton().append(" "));
if (copyButton.isEnabled()) baseText.append(getCopyButton().append(" "));
if (openButton.isEnabled() && defaultAction.is(ScreenshotActions.SAVE)) baseText.append(getOpenButton().append(" "));
if (discardButton.isEnabled() && !defaultAction.is(ScreenshotActions.NONE)) baseText.append(getDiscardButton().append(" "));
ChatUtil.info(baseText);
}
// acciones con la captura
public void copyScreenshot(NativeImage nativeImage) {
try {
BufferedImage bufferedImage = new BufferedImage(nativeImage.getWidth(), nativeImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
for (int x = 0; x < nativeImage.getWidth(); x++)
for (int y = 0; y < nativeImage.getHeight(); y++)
bufferedImage.setRGB(x, y, nativeImage.getColorArgb(x, y));
ScreenshotPlus.TransferableImage trans = new TransferableImage(bufferedImage);
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(trans, null);
ChatUtil.info("captura copiada al portapapeles");
} catch (Exception e) {
ChatUtil.error("no se pudo copiar la captura al portapapeles");
e.printStackTrace();
}
}
public void copyScreenshot() {
copyScreenshot(this.screenshot);
}
public void saveScreenshot(NativeImage image) throws IOException {
image.writeTo(screenshotFile);
ChatUtil.info(Text.literal("captura guardada como: ").append(
Text.literal(screenshotFile.getName())
.formatted(Formatting.UNDERLINE)
.styled(style -> style.withClickEvent(new ClickEvent.OpenFile(screenshotFile.getAbsoluteFile())))
)
);
}
public void saveScreenshot() throws IOException {
saveScreenshot(this.screenshot);
}
// clase ayudante para el portapapeles
public static class TransferableImage implements Transferable {
private final Image image;
public TransferableImage(Image image) {
this.image = image;
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[]{DataFlavor.imageFlavor};
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return DataFlavor.imageFlavor.equals(flavor);
}
@Override
public @NotNull Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
if (!DataFlavor.imageFlavor.equals(flavor))
throw new UnsupportedFlavorException(flavor);
return image;
}
}
// botones para el mensaje
@SuppressWarnings("DataFlowIssue")
private MutableText getSaveButton() {
MutableText button = Text.literal("[GUARDAR]");
MutableText hintBaseText = Text.literal("");
MutableText hintMsg = Text.literal(ScreenshotActions.SAVE.toString());
hintMsg.setStyle(hintBaseText.getStyle().withFormatting(Formatting.GRAY));
hintBaseText.append(hintMsg);
button.setStyle(button.getStyle()
.withFormatting(Formatting.BOLD, Formatting.GOLD)
.withClickEvent(new ClientClickEvent(CommandManager.getCommandByName("guardarcaptura").toString()))
.withHoverEvent(new HoverEvent.ShowText(hintBaseText)));
return button;
}
@SuppressWarnings("DataFlowIssue")
private MutableText getCopyButton() {
MutableText button = Text.literal("[COPIAR]");
MutableText hintBaseText = Text.literal("");
MutableText hintMsg = Text.literal(ScreenshotActions.COPY.toString());
hintMsg.setStyle(hintBaseText.getStyle().withFormatting(Formatting.GRAY));
hintBaseText.append(hintMsg);
button.setStyle(button.getStyle()
.withFormatting(Formatting.BOLD, Formatting.AQUA)
.withClickEvent(new ClientClickEvent(CommandManager.getCommandByName("copiarcaptura").toString()))
.withHoverEvent(new HoverEvent.ShowText(hintBaseText)));
return button;
}
private MutableText getOpenButton() {
MutableText button = Text.literal("[ABRIR]");
MutableText hintBaseText = Text.literal("");
MutableText hintMsg = Text.literal("abrir archivo de imagen");
hintMsg.setStyle(hintBaseText.getStyle().withFormatting(Formatting.GRAY));
hintBaseText.append(hintMsg);
button.setStyle(button.getStyle()
.withFormatting(Formatting.BOLD, Formatting.GRAY)
.withClickEvent(new ClickEvent.OpenFile(screenshotFile))
.withHoverEvent(new HoverEvent.ShowText(hintBaseText)));
return button;
}
@SuppressWarnings("DataFlowIssue")
private MutableText getDiscardButton() {
MutableText button = Text.literal("[DESCARTAR]");
MutableText hintBaseText = Text.literal("");
MutableText hintMsg = Text.literal(ScreenshotActions.NONE.toString());
hintMsg.setStyle(hintBaseText.getStyle().withFormatting(Formatting.GRAY));
hintBaseText.append(hintMsg);
button.setStyle(button.getStyle()
.withFormatting(Formatting.BOLD, Formatting.DARK_RED)
.withClickEvent(new ClientClickEvent(CommandManager.getCommandByName("purgar").toString("1")))
.withHoverEvent(new HoverEvent.ShowText(hintBaseText)));
return button;
}
// otros
public enum ScreenshotActions {
SAVE("guardar archivo"),
COPY("copiar al portapapeles"),
NONE("no hacer nada");
private final String name;
ScreenshotActions(String name) { this.name = name; }
@Override public String toString() { return name; }
}
public NativeImage getScreenshot() {
return screenshot;
}
public void setScreenshot(NativeImage screenshot) {
this.screenshot = screenshot;
}
public File getScreenshotFile() {
return screenshotFile;
}
public void setScreenshotFile(File screenshotFile) {
this.screenshotFile = screenshotFile;
}
}
@@ -1,9 +1,11 @@
package me.retucio.camtweaks.module.settings; package me.retucio.camtweaks.module.settings;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent;
import me.retucio.camtweaks.module.Module; import me.retucio.camtweaks.module.Module;
// base para los tipos de ajustes // base para los tipos de ajustes
public class Setting { public abstract class AbstractSetting {
private final String name; private final String name;
private final String description; private final String description;
@@ -11,7 +13,7 @@ public class Setting {
private Module module; private Module module;
protected Setting(String name, String description) { protected AbstractSetting(String name, String description) {
this.name = name; this.name = name;
this.description = description; this.description = description;
} }
@@ -39,4 +41,8 @@ public class Setting {
public void setModule(Module module) { public void setModule(Module module) {
this.module = module; this.module = module;
} }
public void fireUpdateEvent() {
CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this, module.shouldSaveSettings()));
}
} }
@@ -6,7 +6,7 @@ import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent;
import java.util.function.Consumer; import java.util.function.Consumer;
// ajuste booleano, es decir, o se encuentra encencido o apagado (similar a un interruptor) // ajuste booleano, es decir, o se encuentra encencido o apagado (similar a un interruptor)
public class BooleanSetting extends Setting { public class BooleanSetting extends AbstractSetting {
private boolean defaultValue; private boolean defaultValue;
private boolean enabled; private boolean enabled;
@@ -31,7 +31,7 @@ public class BooleanSetting extends Setting {
public void setEnabled(boolean enabled) { public void setEnabled(boolean enabled) {
if (this.enabled != enabled) { if (this.enabled != enabled) {
this.enabled = enabled; this.enabled = enabled;
CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this)); fireUpdateEvent();
if (updateListener != null) updateListener.accept(enabled); if (updateListener != null) updateListener.accept(enabled);
} }
} }
@@ -50,5 +50,6 @@ public class BooleanSetting extends Setting {
public void onUpdate(Consumer<Boolean> listener) { public void onUpdate(Consumer<Boolean> listener) {
this.updateListener = listener; this.updateListener = listener;
if (updateListener != null) updateListener.accept(enabled); // actualizar por primera vez
} }
} }
@@ -8,9 +8,8 @@ import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
// ajuste que te deja elegir entre distintas opciones definidas, dentro de un Enum // ajuste que te deja elegir entre distintas opciones definidas, dentro de un Enum
public class EnumSetting<E extends Enum<E>> extends Setting { public class EnumSetting<E extends Enum<E>> extends AbstractSetting {
private final Class<E> enumClass;
private final List<E> values; private final List<E> values;
private E defaultValue; private E defaultValue;
@@ -21,7 +20,6 @@ public class EnumSetting<E extends Enum<E>> extends Setting {
public EnumSetting(String name, String description, Class<E> enumClass, E defaultValue) { public EnumSetting(String name, String description, Class<E> enumClass, E defaultValue) {
super(name, description); super(name, description);
this.enumClass = enumClass;
this.values = Arrays.asList(enumClass.getEnumConstants()); this.values = Arrays.asList(enumClass.getEnumConstants());
this.defaultValue = defaultValue; this.defaultValue = defaultValue;
this.value = defaultValue; this.value = defaultValue;
@@ -36,7 +34,7 @@ public class EnumSetting<E extends Enum<E>> extends Setting {
if (this.value != value) { if (this.value != value) {
this.value = value; this.value = value;
this.index = values.indexOf(value); this.index = values.indexOf(value);
CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this)); fireUpdateEvent();
if (updateListener != null) updateListener.accept(value); if (updateListener != null) updateListener.accept(value);
} }
} }
@@ -87,5 +85,6 @@ public class EnumSetting<E extends Enum<E>> extends Setting {
public void onUpdate(Consumer<E> listener) { public void onUpdate(Consumer<E> listener) {
this.updateListener = listener; this.updateListener = listener;
if (updateListener != null) updateListener.accept(value);
} }
} }
@@ -1,17 +1,15 @@
package me.retucio.camtweaks.module.settings; package me.retucio.camtweaks.module.settings;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent;
import me.retucio.camtweaks.module.Module; import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.module.ModuleManager; import me.retucio.camtweaks.module.ModuleManager;
import me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame; import me.retucio.camtweaks.ui.frames.ClientSettingsFrame;
import me.retucio.camtweaks.util.ChatUtil; import me.retucio.camtweaks.util.ChatUtil;
import me.retucio.camtweaks.util.KeyUtil; import me.retucio.camtweaks.util.KeyUtil;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import java.util.function.Consumer; import java.util.function.Consumer;
public class KeySetting extends Setting { public class KeySetting extends AbstractSetting {
private int key; private int key;
private int defaultKey; private int defaultKey;
@@ -33,21 +31,21 @@ public class KeySetting extends Setting {
if (key == GLFW.GLFW_KEY_ESCAPE) { if (key == GLFW.GLFW_KEY_ESCAPE) {
this.key = GLFW.GLFW_KEY_UNKNOWN; // asignar la tecla ESC a deshabilitar la tecla this.key = GLFW.GLFW_KEY_UNKNOWN; // asignar la tecla ESC a deshabilitar la tecla
CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this)); fireUpdateEvent();
if (updateListener != null) updateListener.accept(key); if (updateListener != null) updateListener.accept(key);
return; return;
} }
if (ModuleManager.INSTANCE != null) { if (ModuleManager.INSTANCE != null) {
for (Module module : ModuleManager.INSTANCE.getModules()) for (Module module : ModuleManager.INSTANCE.getModules())
if (module.getKey() == key && !ClickGUISettingsFrame.guiSettings.multipleKeybinds.isEnabled() && key != -1) { if (module.getKey() == key && !ClientSettingsFrame.guiSettings.multipleKeybinds.isEnabled() && key != -1) {
module.setKey(-1); module.setKey(-1);
ChatUtil.info("tecla del módulo " + module.getName() + " restablecida"); ChatUtil.info("tecla del módulo " + module.getName() + " restablecida");
} }
} }
this.key = key; this.key = key;
CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this)); fireUpdateEvent();
if (updateListener != null) updateListener.accept(key); if (updateListener != null) updateListener.accept(key);
} }
@@ -69,5 +67,6 @@ public class KeySetting extends Setting {
public void onUpdate(Consumer<Integer> listener) { public void onUpdate(Consumer<Integer> listener) {
this.updateListener = listener; this.updateListener = listener;
if (updateListener != null) updateListener.accept(key);
} }
} }
@@ -0,0 +1,97 @@
package me.retucio.camtweaks.module.settings;
import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
public class ListSetting<T> extends AbstractSetting {
private final List<T> options;
private Map<T, Boolean> values;
private Map<T, Boolean> defaultValues;
private Map<T, String> displayNames = null;
private Consumer<Map<T, Boolean>> updateListener;
public ListSetting(String name, String description, List<T> options, Map<T, Boolean> initialValues) {
super(name, description);
this.options = options;
this.defaultValues = new HashMap<>();
for (T option : options) {
boolean enabled = initialValues != null && initialValues.getOrDefault(option, false);
defaultValues.put(option, enabled);
}
this.values = new HashMap<>(defaultValues);
}
public ListSetting(String name, String description, List<T> options, Map<T, Boolean> initialValues, Map<T, String> displayNames) {
this(name, description, options, initialValues);
this.displayNames = displayNames;
}
public boolean isEnabled(T option) {
return values.getOrDefault(option, false);
}
public void setEnabled(T option, boolean enabled) {
if (values.containsKey(option) && values.get(option) != enabled) {
values.put(option, enabled);
fireUpdateEvent();
if (updateListener != null) updateListener.accept(new HashMap<>(values));
}
}
public void toggle(T option) {
setEnabled(option, !isEnabled(option));
}
public Map<T, Boolean> getValues() {
return new HashMap<>(values);
}
public void setValues(Map<T, Boolean> values) {
this.values = new HashMap<>(values);
}
public Map<T, Boolean> getDefaultValues() {
return new HashMap<>(defaultValues);
}
public void setDefaultValues(Map<T, Boolean> values) {
defaultValues = values;
}
public void reset() {
values.clear();
values.putAll(defaultValues);
fireUpdateEvent();
if (updateListener != null) updateListener.accept(new HashMap<>(values));
}
public void setAll(boolean enabled) {
for (T option : options) values.put(option, enabled);
}
public void onUpdate(Consumer<Map<T, Boolean>> listener) {
this.updateListener = listener;
if (updateListener != null) updateListener.accept(new HashMap<>(values));
}
public List<T> getOptions() {
return options;
}
public Map<T, String> getDisplayNames() {
return displayNames;
}
public String getDisplayName(T key) {
if (displayNames != null) return displayNames.get(key);
return key.toString();
}
}
@@ -6,7 +6,7 @@ import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent;
import java.util.function.Consumer; import java.util.function.Consumer;
// ajuste numérico, es decir, que eliges un valor númerico entre el mínimo y el máximo disponibles // ajuste numérico, es decir, que eliges un valor númerico entre el mínimo y el máximo disponibles
public class NumberSetting extends Setting { public class NumberSetting extends AbstractSetting {
private double value; private double value;
private double defaultValue; private double defaultValue;
@@ -60,7 +60,7 @@ public class NumberSetting extends Setting {
if (this.value == value) return; if (this.value == value) return;
double clamped = clamp(value, min, max); double clamped = clamp(value, min, max);
this.value = Math.round(clamped / increment) * increment; this.value = Math.round(clamped / increment) * increment;
CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this)); fireUpdateEvent();
if (updateListener != null) updateListener.accept(this.value); if (updateListener != null) updateListener.accept(this.value);
} }
@@ -90,6 +90,6 @@ public class NumberSetting extends Setting {
public void onUpdate(Consumer<Double> listener) { public void onUpdate(Consumer<Double> listener) {
this.updateListener = listener; this.updateListener = listener;
CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this)); if (updateListener != null) updateListener.accept(value);
} }
} }
@@ -3,10 +3,9 @@ package me.retucio.camtweaks.module.settings;
import me.retucio.camtweaks.CameraTweaks; import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent; import me.retucio.camtweaks.event.events.camtweaks.UpdateSettingEvent;
import java.util.Objects;
import java.util.function.Consumer; import java.util.function.Consumer;
public class StringSetting extends Setting { public class StringSetting extends AbstractSetting {
private String value; private String value;
private String defaultValue; private String defaultValue;
@@ -28,7 +27,7 @@ public class StringSetting extends Setting {
public void setValue(String value) { public void setValue(String value) {
if (this.value.equals(value)) return; if (this.value.equals(value)) return;
this.value = value.length() > maxLength ? value.substring(0, maxLength) : value; this.value = value.length() > maxLength ? value.substring(0, maxLength) : value;
CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this)); fireUpdateEvent();
if (updateListener != null) updateListener.accept(this.value); if (updateListener != null) updateListener.accept(this.value);
} }
@@ -50,6 +49,6 @@ public class StringSetting extends Setting {
public void onUpdate(Consumer<String> listener) { public void onUpdate(Consumer<String> listener) {
this.updateListener = listener; this.updateListener = listener;
CameraTweaks.EVENT_BUS.post(new UpdateSettingEvent(this)); if (updateListener != null) updateListener.accept(value);
} }
} }
@@ -2,20 +2,25 @@ package me.retucio.camtweaks.ui;
import me.retucio.camtweaks.CameraTweaks; import me.retucio.camtweaks.CameraTweaks;
import me.retucio.camtweaks.event.SubscribeEvent; import me.retucio.camtweaks.event.SubscribeEvent;
import me.retucio.camtweaks.event.events.MouseClickEvent;
import me.retucio.camtweaks.event.events.MouseScrollEvent; import me.retucio.camtweaks.event.events.MouseScrollEvent;
import me.retucio.camtweaks.event.events.camtweaks.SettingsFrameEvent; import me.retucio.camtweaks.event.events.camtweaks.SettingsFrameEvent;
import me.retucio.camtweaks.module.Module; import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame; import me.retucio.camtweaks.ui.buttons.ListButton;
import me.retucio.camtweaks.ui.buttons.SettingButton;
import me.retucio.camtweaks.ui.frames.ClientSettingsFrame;
import me.retucio.camtweaks.ui.frames.ModuleFrame; import me.retucio.camtweaks.ui.frames.ModuleFrame;
import me.retucio.camtweaks.ui.frames.SettingsFrame; import me.retucio.camtweaks.ui.frames.SettingsFrame;
import me.retucio.camtweaks.util.KeyUtil;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import org.lwjgl.glfw.GLFW;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame.guiSettings; import static me.retucio.camtweaks.ui.frames.ClientSettingsFrame.guiSettings;
// interfaz gráfica, se abre con el shift derecho por defecto. aquí se encuentran los módulos y sus ajustes // interfaz gráfica, se abre con el shift derecho por defecto. aquí se encuentran los módulos y sus ajustes
public class ClickGUI extends Screen { public class ClickGUI extends Screen {
@@ -25,7 +30,7 @@ public class ClickGUI extends Screen {
private final ModuleFrame modulesFrame = new ModuleFrame(20, 30, 100, 20); private final ModuleFrame modulesFrame = new ModuleFrame(20, 30, 100, 20);
private final List<SettingsFrame> settingsFrames = new ArrayList<>(); private final List<SettingsFrame> settingsFrames = new ArrayList<>();
private final ClickGUISettingsFrame guiSettingsFrame = new ClickGUISettingsFrame(200, 30, 100, 20); private final ClientSettingsFrame guiSettingsFrame = new ClientSettingsFrame(200, 30, 100, 20);
public ClickGUI() { public ClickGUI() {
super(Text.of("interfaz")); super(Text.of("interfaz"));
@@ -77,6 +82,21 @@ public class ClickGUI extends Screen {
sf.y += (int) (event.getVertical() * guiSettings.scrollSens.getValue()); sf.y += (int) (event.getVertical() * guiSettings.scrollSens.getValue());
} }
@SubscribeEvent
public void onMouseMiddleButton(MouseClickEvent event) {
// mover todos los marcos a un punto visible al presionar shift + la rueda del ratón
if (CameraTweaks.mc.currentScreen != this || event.getButton() != 2 || !KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT)) return;
int h = CameraTweaks.mc.getWindow().getScaledHeight();
int minY = Math.min(modulesFrame.y, settingsFrames.stream().mapToInt(sf -> sf.y).min().orElse(modulesFrame.y));
int maxY = Math.max(modulesFrame.y + modulesFrame.h, settingsFrames.stream().mapToInt(sf -> sf.y + sf.h).max().orElse(modulesFrame.y + modulesFrame.h));
int correction = minY < 0 ? -minY + 4 : (maxY > h ? h - maxY - 4 : 0);
if (correction != 0) {
modulesFrame.y += correction;
settingsFrames.forEach(sf -> sf.y += correction);
}
}
public void openSettingsFrame(Module module, int x, int y) { public void openSettingsFrame(Module module, int x, int y) {
// abrir un marco donde se encuentran los ajustes del módulo deseado // abrir un marco donde se encuentran los ajustes del módulo deseado
if (isSettingsFrameOpen(module)) return; // permitir un solo marco de ajustes por módulo if (isSettingsFrameOpen(module)) return; // permitir un solo marco de ajustes por módulo
@@ -85,6 +105,12 @@ public class ClickGUI extends Screen {
CameraTweaks.EVENT_BUS.post(new SettingsFrameEvent.Open(frame)); CameraTweaks.EVENT_BUS.post(new SettingsFrameEvent.Open(frame));
} }
public void openListSettingsFrame(Module module, int x, int y) {
if (isSettingsFrameOpen(module)) return;
SettingsFrame frame = new SettingsFrame(module, x, y, 120, 18);
settingsFrames.add(frame);
}
// cerrar el marco de ajustes // cerrar el marco de ajustes
public void closeSettingsFrame(Module module) { public void closeSettingsFrame(Module module) {
// porque java.util.ConcurrentModificationException o algo no sé es lo único que se me ha ocurrido hacer // porque java.util.ConcurrentModificationException o algo no sé es lo único que se me ha ocurrido hacer
@@ -104,6 +130,13 @@ public class ClickGUI extends Screen {
.anyMatch(sf -> sf.module.getName().equals(module.getName())); .anyMatch(sf -> sf.module.getName().equals(module.getName()));
} }
public void refreshListButtons() {
for (SettingsFrame frame : settingsFrames)
for (SettingButton button : frame.getButtons())
if (button instanceof ListButton<?> lb)
lb.refreshDummy();
}
// no pausar el juego cuando se abre la interfaz // no pausar el juego cuando se abre la interfaz
@Override @Override
public boolean shouldPause() { public boolean shouldPause() {
@@ -114,7 +147,7 @@ public class ClickGUI extends Screen {
return modulesFrame; return modulesFrame;
} }
public ClickGUISettingsFrame getGuiSettingsFrame() { public ClientSettingsFrame getGuiSettingsFrame() {
return guiSettingsFrame; return guiSettingsFrame;
} }
@@ -28,7 +28,7 @@ public class BindButton extends SettingButton {
ctx.fill(x, y, x + w, y + height, bgColor); ctx.fill(x, y, x + w, y + height, bgColor);
String label = setting.getName() + ": " + (listening ? "..." : setting.getKeyName()); String label = setting.getName() + ": " + (listening ? "..." : setting.getKeyName());
ctx.drawTextWithShadow(parent.mc.textRenderer, label, x + 5, y + 3, -1); ctx.drawText(parent.mc.textRenderer, label, x + 5, y + 3, -1, true);
if (isHovered((int) mouseX, (int) mouseY)) { if (isHovered((int) mouseX, (int) mouseY)) {
Screen currentScreen = parent.mc.currentScreen; Screen currentScreen = parent.mc.currentScreen;
@@ -33,7 +33,7 @@ public class CycleButton<E extends Enum<E>> extends SettingButton {
// texto del botón: nombre + valor de texto del enum // texto del botón: nombre + valor de texto del enum
String label = setting.getName() + ": " + setting.getValue().toString(); String label = setting.getName() + ": " + setting.getValue().toString();
ctx.drawTextWithShadow(parent.mc.textRenderer, label, x + 5, y + 3, -1); ctx.drawText(parent.mc.textRenderer, label, x + 5, y + 3, -1, true);
// tooltip // tooltip
if (isHovered((int) mouseX, (int) mouseY)) { if (isHovered((int) mouseX, (int) mouseY)) {
@@ -0,0 +1,110 @@
package me.retucio.camtweaks.ui.buttons;
import me.retucio.camtweaks.module.Module;
import me.retucio.camtweaks.module.settings.BooleanSetting;
import me.retucio.camtweaks.module.settings.ListSetting;
import me.retucio.camtweaks.ui.ClickGUI;
import me.retucio.camtweaks.ui.frames.SettingsFrame;
import me.retucio.camtweaks.util.Colors;
import me.retucio.camtweaks.util.KeyUtil;
import net.minecraft.client.gui.DrawContext;
import org.lwjgl.glfw.GLFW;
import java.util.*;
public class ListButton<T> extends SettingButton {
private final ListSetting<T> setting;
private final Module dummy;
private final Map<T, BooleanSetting> optionButtons = new HashMap<>();
public ListButton(ListSetting<T> setting, SettingsFrame parent, int offset) {
super(setting, parent, offset);
this.setting = setting;
// crear un módulo "dummy" (falso), que se le añade cada entrada en la lista como un BooleanSetting
dummy = new Module(setting.getName(), setting.getDescription()) {
@Override public void onEnable() {}
@Override public void onDisable() {}
};
// ocultar cosas innecesarias
dummy.getBind().setVisible(false);
dummy.getSettings().stream()
.filter(s -> s.getName().equalsIgnoreCase("modo de tecla"))
.findFirst()
.ifPresent(s -> s.setVisible(false));
dummy.getSettings().stream()
.filter(s -> s.getName().equalsIgnoreCase("notificar"))
.findFirst()
.ifPresent(s -> s.setVisible(false));
dummy.shouldSaveSettings(false);
}
@Override
public void render(DrawContext ctx, double mouseX, double mouseY, float delta) {
int bgColor = isHovered(mouseX, mouseY)
? Colors.hoveredSettingButtonColor
: Colors.settingButtonColor;
ctx.fill(x, y, x + w, y + height, bgColor);
String label = setting.getName() + " (" + countEnabled() + "/" + setting.getOptions().size() + ")";
ctx.drawText(parent.mc.textRenderer, label, x + 5, y + 3, -1, true);
}
@Override
public void mouseClicked(double mouseX, double mouseY, int button) {
if (isHovered(mouseX, mouseY)) {
// click izquierdo / derecho: abrir marco
if (button <= 1 && !KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT)) {
if (ClickGUI.INSTANCE.isSettingsFrameOpen(dummy)) {
ClickGUI.INSTANCE.closeSettingsFrame(dummy);
return;
}
rebuildDummy();
ClickGUI.INSTANCE.openListSettingsFrame(dummy, parent.x + 40, parent.y + 40);
// shift + clic derecho: restablecer valores
} else if (button == 1 && KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT)) {
setting.reset();
refreshDummy();
}
}
}
private void rebuildDummy() {
dummy.getSettings().clear();
optionButtons.clear();
setting.getOptions().stream()
.sorted(Comparator.comparing(setting::getDisplayName, String.CASE_INSENSITIVE_ORDER))
.forEach(option -> {
String displayName = setting.getDisplayName(option);
BooleanSetting b = dummy.addSetting(new BooleanSetting(
displayName,
"incluir " + displayName,
setting.isEnabled(option)
));
b.onUpdate(value -> setting.setEnabled(option, value));
optionButtons.put(option, b);
});
}
public void refreshDummy() {
optionButtons.forEach((option, boolSetting) ->
boolSetting.setEnabled(setting.isEnabled(option)));
}
private int countEnabled() {
return (int) setting.getOptions().stream().filter(setting::isEnabled).count();
}
public ListSetting<T> getSetting() {
return setting;
}
@Override
public void mouseReleased(double mouseX, double mouseY, int button) {}
}
@@ -28,9 +28,10 @@ public class ModuleButton {
parent.x + parent.w - 2 , parent.y + height + offset, parent.x + parent.w - 2 , parent.y + height + offset,
determineColor(mouseX, mouseY)); determineColor(mouseX, mouseY));
ctx.drawTextWithShadow( // dibujar el nombre del módulo ctx.drawText( // dibujar el nombre del módulo
parent.mc.textRenderer, module.getName(), parent.mc.textRenderer, module.getName(),
parent.x + 5, parent.y + offset + (height / 2) - (parent.mc.textRenderer.fontHeight / 2) + 2, -1); parent.x + 5, parent.y + offset + (height / 2) - (parent.mc.textRenderer.fontHeight / 2) + 2,
-1, true);
// dibujar "tooltips" (cajas de texto) al pasar el puntero encima del botón, para mostrar su descripción // dibujar "tooltips" (cajas de texto) al pasar el puntero encima del botón, para mostrar su descripción
if (isHovered((int) mouseX, (int) mouseY)) { if (isHovered((int) mouseX, (int) mouseY)) {
@@ -1,20 +1,20 @@
package me.retucio.camtweaks.ui.buttons; package me.retucio.camtweaks.ui.buttons;
import me.retucio.camtweaks.module.settings.Setting; import me.retucio.camtweaks.module.settings.AbstractSetting;
import me.retucio.camtweaks.ui.frames.SettingsFrame; import me.retucio.camtweaks.ui.frames.SettingsFrame;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
// clase base para los botones de los ajustes // clase base para los botones de los ajustes
public abstract class SettingButton { public abstract class SettingButton {
protected final Setting setting; protected final AbstractSetting setting;
protected final SettingsFrame parent; protected final SettingsFrame parent;
protected int offset; protected int offset;
protected final int height = 15; protected final int height = 15;
protected int x, y, w, h; protected int x, y, w, h;
public SettingButton(Setting setting, SettingsFrame parent, int offset) { public SettingButton(AbstractSetting setting, SettingsFrame parent, int offset) {
this.setting = setting; this.setting = setting;
this.parent = parent; this.parent = parent;
this.offset = offset; this.offset = offset;
@@ -24,12 +24,16 @@ public abstract class SettingButton {
public abstract void mouseClicked(double mouseX, double mouseY, int button); public abstract void mouseClicked(double mouseX, double mouseY, int button);
public abstract void mouseReleased(double mouseX, double mouseY, int button); public abstract void mouseReleased(double mouseX, double mouseY, int button);
protected boolean isHovered(double mouseX, double mouseY) {
return isHovered((int) mouseX, (int) mouseY);
}
protected boolean isHovered(int mouseX, int mouseY) { protected boolean isHovered(int mouseX, int mouseY) {
return mouseX > x && mouseX < x + w && return mouseX > x && mouseX < x + w &&
mouseY > y && mouseY < y + h; mouseY > y && mouseY < y + h;
} }
public Setting getSetting() { public AbstractSetting getSetting() {
return setting; return setting;
} }
@@ -3,7 +3,7 @@ package me.retucio.camtweaks.ui.buttons;
import me.retucio.camtweaks.event.SubscribeEvent; import me.retucio.camtweaks.event.SubscribeEvent;
import me.retucio.camtweaks.event.events.KeyEvent; import me.retucio.camtweaks.event.events.KeyEvent;
import me.retucio.camtweaks.module.settings.NumberSetting; import me.retucio.camtweaks.module.settings.NumberSetting;
import me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame; import me.retucio.camtweaks.ui.frames.ClientSettingsFrame;
import me.retucio.camtweaks.ui.frames.SettingsFrame; import me.retucio.camtweaks.ui.frames.SettingsFrame;
import me.retucio.camtweaks.util.Colors; import me.retucio.camtweaks.util.Colors;
import me.retucio.camtweaks.util.KeyUtil; import me.retucio.camtweaks.util.KeyUtil;
@@ -40,7 +40,7 @@ public class SliderButton extends SettingButton {
ctx.fill(x, y, x + filled, y + height, Colors.sliderFillingColor); ctx.fill(x, y, x + filled, y + height, Colors.sliderFillingColor);
String label = setting.getName() + ": " + df.format(setting.getValue()); String label = setting.getName() + ": " + df.format(setting.getValue());
ctx.drawTextWithShadow(parent.mc.textRenderer, label, x + 5, y + 3, -1); ctx.drawText(parent.mc.textRenderer, label, x + 5, y + 3, -1, true);
// lógica para el arrastre (arrastramiento?) del valor // lógica para el arrastre (arrastramiento?) del valor
if (dragging) { if (dragging) {
@@ -75,7 +75,7 @@ public class SliderButton extends SettingButton {
@SubscribeEvent @SubscribeEvent
public void onKey(KeyEvent event) { public void onKey(KeyEvent event) {
// de no ser de esto, si se cierra la interfaz sin haber soltado el ratón mientras se arrastraba el valor, al reabrir la interfaz se seguía arrastrando, aún habiendo soltado ya el clic // de no ser de esto, si se cierra la interfaz sin haber soltado el ratón mientras se arrastraba el valor, al reabrir la interfaz se seguía arrastrando, aún habiendo soltado ya el clic
if (event.getKey() == GLFW.GLFW_KEY_ESCAPE || event.getKey() == ClickGUISettingsFrame.guiSettings.getKey()) dragging = false; if (event.getKey() == GLFW.GLFW_KEY_ESCAPE || event.getKey() == ClientSettingsFrame.guiSettings.getKey()) dragging = false;
} }
public NumberSetting getSetting() { public NumberSetting getSetting() {
@@ -29,7 +29,7 @@ public class TextButton extends SettingButton {
ctx.fill(x, y, x + w, y + height, bgColor); ctx.fill(x, y, x + w, y + height, bgColor);
String label = setting.getName() + ": " + (typing ? buffer + "_" : setting.getValue()); String label = setting.getName() + ": " + (typing ? buffer + "_" : setting.getValue());
ctx.drawTextWithShadow(parent.mc.textRenderer, label, x + 5, y + 3, -1); ctx.drawText(parent.mc.textRenderer, label, x + 5, y + 3, -1, true);
if (isHovered((int) mouseX, (int) mouseY)) { if (isHovered((int) mouseX, (int) mouseY)) {
if (parent.mc.currentScreen != null) if (parent.mc.currentScreen != null)
@@ -32,8 +32,7 @@ public class ToggleButton extends SettingButton {
// quizás debería de utilizar .brighter() más, en vez de dar valores personalizados // quizás debería de utilizar .brighter() más, en vez de dar valores personalizados
ctx.fill(x, y, x + w, y + height, color.getRGB()); ctx.fill(x, y, x + w, y + height, color.getRGB());
ctx.drawTextWithShadow(parent.mc.textRenderer, ctx.drawText(parent.mc.textRenderer, setting.getName(), x + 5, y + 3, -1, true);
setting.getName(), x + 5, y + 3, -1);
// dibujar "tooltips" (cajas de texto) al pasar el puntero encima del botón, para mostrar su descripción // dibujar "tooltips" (cajas de texto) al pasar el puntero encima del botón, para mostrar su descripción
if (isHovered((int) mouseX, (int) mouseY)) { if (isHovered((int) mouseX, (int) mouseY)) {
@@ -9,13 +9,13 @@ import net.minecraft.client.gui.DrawContext;
import java.util.List; import java.util.List;
public class ClickGUISettingsFrame extends SettingsFrame { public class ClientSettingsFrame extends SettingsFrame {
public static final GUI guiSettings = new GUI(); public static final GUI guiSettings = new GUI();
public boolean extended = false; public boolean extended = false;
private String title = "ajustes de la interfaz -"; private String title = "ajustes del mod -";
public ClickGUISettingsFrame(int x, int y, int w, int h) { public ClientSettingsFrame(int x, int y, int w, int h) {
super(guiSettings, x, y, w, h); super(guiSettings, x, y, w, h);
} }
@@ -27,7 +27,7 @@ public class ClickGUISettingsFrame extends SettingsFrame {
ctx.drawText(mc.textRenderer, title, ctx.drawText(mc.textRenderer, title,
x + (w / 2) - (mc.textRenderer.getWidth(title) / 2), x + (w / 2) - (mc.textRenderer.getWidth(title) / 2),
y + (h / 2) - (mc.textRenderer.fontHeight / 2), y + (h / 2) - (mc.textRenderer.fontHeight / 2),
-1, false); -1, true);
List<SettingButton> visibleButtons = settingButtons.stream() List<SettingButton> visibleButtons = settingButtons.stream()
.filter(sb -> sb.getSetting().isVisible()) .filter(sb -> sb.getSetting().isVisible())
@@ -57,7 +57,7 @@ public class ClickGUISettingsFrame extends SettingsFrame {
dragY = (int) (mouseY - y); dragY = (int) (mouseY - y);
} else if (button == 1) { } else if (button == 1) {
extended = !extended; extended = !extended;
title = extended ? "ajustes de la interfaz -" : "ajustes de la interfaz +"; title = extended ? "ajustes del mod -" : "ajustes del mod +";
CameraTweaks.EVENT_BUS.post(new GUISettingsFrameEvent.Extend()); CameraTweaks.EVENT_BUS.post(new GUISettingsFrameEvent.Extend());
} }
} }
@@ -60,7 +60,7 @@ public class ModuleFrame {
ctx.drawText(mc.textRenderer, title, ctx.drawText(mc.textRenderer, title,
x + (w / 2) - (mc.textRenderer.getWidth(title) / 2), x + (w / 2) - (mc.textRenderer.getWidth(title) / 2),
y + ( h /2) - (mc.textRenderer.fontHeight / 2), y + ( h /2) - (mc.textRenderer.fontHeight / 2),
-1, false); -1, true);
// dibujar sus módulos solo si está extendido // dibujar sus módulos solo si está extendido
if (extended) { if (extended) {
@@ -39,7 +39,7 @@ public class SettingsFrame {
// añadir el respectivo tipo de botón de cada ajuste a la lista de botones // añadir el respectivo tipo de botón de cada ajuste a la lista de botones
int offset = h; int offset = h;
for (Setting setting : module.getSettings()) { for (AbstractSetting setting : module.getSettings()) {
if (!setting.isVisible()) continue; if (!setting.isVisible()) continue;
switch (setting) { switch (setting) {
case BooleanSetting b -> { case BooleanSetting b -> {
@@ -57,6 +57,9 @@ public class SettingsFrame {
} case StringSetting s -> { } case StringSetting s -> {
addButton(new TextButton(s, this, offset)); addButton(new TextButton(s, this, offset));
offset += 18; offset += 18;
} case ListSetting l -> {
addButton(new ListButton<>(l, this, offset));
offset += 18;
} default -> {} } default -> {}
} }
} }
@@ -68,54 +71,57 @@ public class SettingsFrame {
updateWidth(); // actualizar anchura del frame tras cada iteración updateWidth(); // actualizar anchura del frame tras cada iteración
} }
@SuppressWarnings("rawtypes")
void updateWidth() {
// asegurarse de que todos los botones caben en el marco, haciendo que la anchura se ajuste al texto más largo
if (mc.textRenderer == null) return;
int maxWidth = mc.textRenderer.getWidth(title);
for (SettingButton button : settingButtons) {
String text = button.getSetting().getName();
switch (button) {
case SliderButton sliderButton -> text += ": " + sliderButton.df.format((sliderButton.getSetting()).getValue());
case CycleButton cycleButton -> text += ": " + cycleButton.getSetting().getValue();
case BindButton bindButton -> text += ": " + bindButton.getSetting().getKeyName();
case TextButton textButton -> text += ": " + textButton.getSetting().getValue();
default -> {}
}
int textWidth = mc.textRenderer.getWidth(text);
maxWidth = Math.max(maxWidth, textWidth);
}
this.w = maxWidth + 22;
}
public void render(DrawContext ctx, int mouseX, int mouseY, float delta) { public void render(DrawContext ctx, int mouseX, int mouseY, float delta) {
updateWidth(); updateWidth();
ctx.fill(x, y, x + w, y + h, module.isEnabled()
// cabezal
int centerX = x + w / 2;
int centerY = y + h / 2;
int titleWidth = mc.textRenderer.getWidth(title);
int titleX = centerX - titleWidth / 2;
int titleY = centerY - mc.textRenderer.fontHeight / 2;
int headerColor = module.isEnabled()
? Colors.enabledToggleButtonColor.getRGB() ? Colors.enabledToggleButtonColor.getRGB()
: Colors.disabledToggleButtonColor.getRGB()); : Colors.disabledToggleButtonColor.getRGB();
ctx.drawText(mc.textRenderer, title, ctx.fill(x, y, x + w, y + h, headerColor);
x + (w / 2) - (mc.textRenderer.getWidth(title) / 2), ctx.drawText(mc.textRenderer, title, titleX, titleY, -1, true);
y + (h / 2) - (mc.textRenderer.fontHeight / 2),
-1, false);
// descripción
List<SettingButton> visibleButtons = settingButtons.stream() List<SettingButton> visibleButtons = settingButtons.stream()
.filter(sb -> sb.getSetting().isVisible()) .filter(sb -> sb.getSetting().isVisible())
.toList(); .toList();
int currentY = y + h + 3; List<String> descLines = wrapDescription(module.getDescription(), w - 8);
ctx.fill(x, currentY - 2, x + w, currentY + visibleButtons.size() * h, Colors.frameBGColor); int lineSpacing = 2;
int descHeight = descLines.size() * mc.textRenderer.fontHeight + (descLines.size() - 1) * lineSpacing;
int descBoxTop = y + h + 5;
int descBoxBottom = descBoxTop + descHeight + 8;
int totalHeight = descHeight + 8 + h * visibleButtons.size() + 4;
ctx.fill(x, descBoxTop - 4, x + w, descBoxTop + totalHeight, Colors.frameBGColor);
ctx.fill(x + 4, descBoxTop, x + w - 4, descBoxBottom, Colors.settingButtonColor);
int firstLineY = descBoxTop + ((descBoxBottom - descBoxTop) - descHeight) / 2;
for (int i = 0; i < descLines.size(); i++) {
String line = descLines.get(i);
int lineX = centerX - mc.textRenderer.getWidth(line) / 2;
int lineY = firstLineY + i * (mc.textRenderer.fontHeight + lineSpacing);
ctx.drawText(mc.textRenderer, line, lineX, lineY, -1, true);
}
int startButtonY = firstLineY - descBoxTop + descBoxBottom;
for (SettingButton sb : visibleButtons) { for (SettingButton sb : visibleButtons) {
sb.setX(x + 4); sb.setX(x + 4);
sb.setY(currentY); sb.setY(startButtonY);
sb.setW(w - 8); sb.setW(w - 8);
sb.setH(h); sb.setH(h - 6);
sb.render(ctx, mouseX, mouseY, delta); sb.render(ctx, mouseX, mouseY, delta);
currentY += h; startButtonY += h;
} }
} }
@@ -157,6 +163,49 @@ public class SettingsFrame {
mouseY > y && mouseY < y + h; mouseY > y && mouseY < y + h;
} }
@SuppressWarnings("rawtypes")
void updateWidth() {
// asegurarse de que todos los botones caben en el marco, haciendo que la anchura se ajuste al texto más largo
if (mc.textRenderer == null) return;
int maxWidth = mc.textRenderer.getWidth(title);
for (SettingButton button : settingButtons) {
String text = button.getSetting().getName();
switch (button) {
case SliderButton sliderButton -> text += ": " + sliderButton.df.format((sliderButton.getSetting()).getValue());
case CycleButton cycleButton -> text += ": " + cycleButton.getSetting().getValue();
case BindButton bindButton -> text += ": " + bindButton.getSetting().getKeyName();
case TextButton textButton -> text += ": " + textButton.getSetting().getValue();
default -> {}
}
int textWidth = mc.textRenderer.getWidth(text);
maxWidth = Math.max(maxWidth, textWidth);
}
this.w = maxWidth + 22;
}
private List<String> wrapDescription(String text, int maxWidth) {
List<String> lines = new ArrayList<>();
if (mc.textRenderer == null) return lines;
String[] words = text.split(" ");
StringBuilder line = new StringBuilder();
for (String word : words) {
String testLine = line.isEmpty() ? word : line + " " + word;
if (mc.textRenderer.getWidth(testLine) > maxWidth - 8) { // padding of 4 each side
if (!line.isEmpty()) lines.add(line.toString());
line = new StringBuilder(word);
} else {
line = new StringBuilder(testLine);
}
}
if (!line.isEmpty()) lines.add(line.toString());
return lines;
}
public List<SettingButton> getButtons() { public List<SettingButton> getButtons() {
return settingButtons; return settingButtons;
} }
@@ -1,52 +0,0 @@
package me.retucio.camtweaks.ui.widgets;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gl.RenderPipelines;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
public class SearchBarWidget extends TextFieldWidget {
private static final Identifier MENU_LIST_BACKGROUND_TEXTURE = Identifier.ofVanilla("textures/gui/menu_list_background.png");
private static final Identifier INWORLD_MENU_LIST_BACKGROUND_TEXTURE = Identifier.ofVanilla("textures/gui/inworld_menu_list_background.png");
private boolean hookBackground;
public SearchBarWidget(TextRenderer textRenderer, int width, int height) {
super(textRenderer, width, height, Text.empty());
}
@Override
public void renderWidget(DrawContext context, int mouseX, int mouseY, float deltaTicks) {
if (drawsBackground()) drawBackground(context);
hookBackground = true;
super.renderWidget(context, mouseX, mouseY, deltaTicks);
hookBackground = false;
}
@Override
public boolean drawsBackground() {
if (hookBackground) return false;
return super.drawsBackground();
}
private void drawBackground(DrawContext context) {
Identifier identifier = MinecraftClient.getInstance().world == null ? MENU_LIST_BACKGROUND_TEXTURE : INWORLD_MENU_LIST_BACKGROUND_TEXTURE;
context.drawTexture(
RenderPipelines.GUI,
identifier,
this.getX(),
this.getY(),
this.getRight(),
this.getBottom(),
this.getWidth(),
this.getHeight(),
32,
32
);
}
}
@@ -1,6 +1,8 @@
package me.retucio.camtweaks.util; package me.retucio.camtweaks.util;
import me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame; import me.retucio.camtweaks.event.SubscribeEvent;
import me.retucio.camtweaks.event.events.camtweaks.LoadModuleManagerEvent;
import me.retucio.camtweaks.ui.frames.ClientSettingsFrame;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Formatting; import net.minecraft.util.Formatting;
@@ -9,7 +11,13 @@ import net.minecraft.util.Formatting;
public class ChatUtil { public class ChatUtil {
private static final MinecraftClient mc = MinecraftClient.getInstance(); private static final MinecraftClient mc = MinecraftClient.getInstance();
private static String prefix = Formatting.GREEN + "[" + ClickGUISettingsFrame.guiSettings.chatName.getValue() + "] "; private static String prefix = getDefaultPrefix();
@SubscribeEvent
public static void onLoadModuleManager(LoadModuleManagerEvent event) {
prefix = Formatting.GREEN + "[" + ClientSettingsFrame.guiSettings.chatName.getValue() + "] ";
}
public static void addMessage(String text) { public static void addMessage(String text) {
if (mc.inGameHud == null) return; if (mc.inGameHud == null) return;
@@ -67,10 +75,15 @@ public class ChatUtil {
} }
public static String getPrefixNoFormatting() { public static String getPrefixNoFormatting() {
return "[" + ClickGUISettingsFrame.guiSettings.chatName.getValue() + "] "; return prefix.split(Formatting.GREEN.toString())[1];
// return "[" + ClickGUISettingsFrame.guiSettings.chatName.getValue() + "] ";
} }
public static void updatePrefix(String newPrefix) { public static void updatePrefix(String newPrefix) {
prefix = Formatting.GREEN + "[" + newPrefix + "] "; prefix = Formatting.GREEN + "[" + newPrefix + "] ";
} }
public static String getDefaultPrefix() {
return Formatting.GREEN + "[smegma] ";
}
} }
@@ -2,7 +2,7 @@ package me.retucio.camtweaks.util;
import java.awt.*; import java.awt.*;
import static me.retucio.camtweaks.ui.frames.ClickGUISettingsFrame.guiSettings; import static me.retucio.camtweaks.ui.frames.ClientSettingsFrame.guiSettings;
// clase para los colores, para no repetirme (regla DRY) // clase para los colores, para no repetirme (regla DRY)
@@ -0,0 +1,60 @@
package me.retucio.camtweaks.util;
import net.minecraft.block.Block;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.entity.EntityType;
import net.minecraft.particle.ParticleType;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.registry.Registries;
import net.minecraft.text.Text;
import java.util.*;
import static me.retucio.camtweaks.CameraTweaks.mc;
public class Lists {
public static final List<EntityType<?>> entityList = Registries.ENTITY_TYPE.stream().toList();
public static Map<EntityType<?>, String> entityNames;
public static final List<ParticleType<?>> particleList = Registries.PARTICLE_TYPE.stream().toList();
public static Map<ParticleType<?>, String> particleNames;
public static final List<Block> blockList = Registries.BLOCK.stream().toList();
public static void init() {
// no consigo traducir el texto. a tomar por culo, se queda en inglés, si no entiendes pues a estudiar
entityNames = getMapOfLists(entityList,
entityList.stream().map(entity -> I18n.translate(entity.getTranslationKey())).toList());
// no hay traducciones para nombres de partículas, y paso de hacerlas yo
particleNames = getMapOfLists(particleList,
particleList.stream().map(particle -> Registries.PARTICLE_TYPE.getId(particle).toShortTranslationKey()).toList());
}
public static <T> Map<T, Boolean> allTrue(List<T> options) {
Map<T, Boolean> map = new HashMap<>();
for (T option : options) map.put(option, true);
return map;
}
public static <T> Map<T, Boolean> allFalse(List<T> options) {
Map<T, Boolean> map = new HashMap<>();
for (T option : options) map.put(option, false);
return map;
}
public static <T> Map<T, String> getMapOfLists(List<T> options, List<String> names) {
Map<T, String> result = new HashMap<>();
// no exceder los límites de ninguna de las dos listas
int size = Math.min(options.size(), names.size());
for (int i = 0; i < size; i++)
result.put(options.get(i), names.get(i));
return result;
}
}
@@ -1,8 +1,13 @@
package me.retucio.camtweaks.util.interfaces; package me.retucio.camtweaks.util.interfaces;
import net.minecraft.client.gui.hud.ChatHudLine;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import java.util.List;
public interface IChatHud { public interface IChatHud {
void smegma$add(Text message, int id); void smegma$add(Text message, int id);
List<ChatHudLine.Visible> smegma$getVisibleMessages();
} }
@@ -0,0 +1,9 @@
accessWidener v2 named
accessible class net/minecraft/client/font/TextRenderer$Drawer
accessible field net/minecraft/client/particle/Particle alpha F
accessible field net/minecraft/client/particle/BillboardParticle scale F
accessible field net/minecraft/client/particle/Particle velocityMultiplier F
accessible field net/minecraft/client/particle/Particle gravityStrength F
accessible field net/minecraft/client/particle/Particle collidesWithWorld Z
+12 -2
View File
@@ -5,6 +5,7 @@
"mixins": [ "mixins": [
"ClientConnectionMixin", "ClientConnectionMixin",
"DimensionTypeMixin", "DimensionTypeMixin",
"EntityEffectParticleEffectMixin",
"EntityMixin", "EntityMixin",
"ItemEntityMixin", "ItemEntityMixin",
"KeyInputMixin", "KeyInputMixin",
@@ -29,25 +30,34 @@
"ChatScreenMixin", "ChatScreenMixin",
"ChunkBorderDebugRendererMixin", "ChunkBorderDebugRendererMixin",
"ChunkOcclusionDataBuilderMixin", "ChunkOcclusionDataBuilderMixin",
"ClientPlayerInteractionManagerMixin",
"ClientPlayNetworkHandlerMixin", "ClientPlayNetworkHandlerMixin",
"ClientWorldPropertiesMixin", "ClientWorldPropertiesMixin",
"CompassStateMixin", "CompassStateMixin",
"EntityRendererMixin", "DamageParticleFactoryMixin",
"DamageParticleMixin",
"FogRendererMixin",
"GameOptionsMixin", "GameOptionsMixin",
"GameRendererMixin", "GameRendererMixin",
"HeldItemRendererMixin", "HeldItemRendererMixin",
"InGameHudMixin", "InGameHudMixin",
"InGameOverlayRendererMixin",
"KeyboardMixin", "KeyboardMixin",
"LightmapTextureManagerMixin", "LightmapTextureManagerMixin",
"LivingEntityRendererMixin", "LivingEntityRendererMixin",
"MessageHandlerMixin", "MessageHandlerMixin",
"MinecraftClientMixin", "MinecraftClientMixin",
"MouseMixin", "MouseMixin",
"OverlayTextureMixin",
"ParticleManagerMixin",
"ScreenMixin", "ScreenMixin",
"ScreenshotRecorderMixin",
"SkyRendererMixin", "SkyRendererMixin",
"StuckArrowsFeatureRendererMixin",
"TextRendererDrawerMixin",
"WeatherRenderingMixin",
"WorldRendererMixin", "WorldRendererMixin",
"accessor.ClientPlayNetworkHandlerAccessor", "accessor.ClientPlayNetworkHandlerAccessor",
"accessor.EntityRenderStateAccessor",
"accessor.KeyBindingAccessor" "accessor.KeyBindingAccessor"
] ]
} }
+1
View File
@@ -23,6 +23,7 @@
"mixins": [ "mixins": [
"camtweaks.mixins.json" "camtweaks.mixins.json"
], ],
"accessWidener": "camtweaks.accesswidener",
"depends": { "depends": {
"fabricloader": ">=0.16.14", "fabricloader": ">=0.16.14",
"minecraft": "~1.21.6", "minecraft": "~1.21.6",