This commit is contained in:
retucio committed 2026-07-15 21:50:51 +02:00
1 parent 957fab15aa
commit aeadfb28b1
131 files changed
+4047 -638

No files matched your search

+2 -1
View File
@@ -43,4 +43,5 @@ replay_*.log
todo.txt todo.txt
cambios.md cambios.md
remappedSrc/ remappedSrc/
.claude/
+20 -5
View File
@@ -1,18 +1,33 @@
# v5.2 # v5.3
## novedades ## novedades
- actualizado a 26.2
### adiciones ### adiciones
- el mod ya está traducido y sigue el idioma del juego: de momento español e inglés
- nuevo elemento del HUD: `armadura`
#### módulos nuevos: #### módulos nuevos:
### arreglos / mejoras ### arreglos / mejoras
- `andamios` ya funciona correctamente - los módulos con tilde en el nombre (`cámara libre`, `críticos`, `partículas`...) ya recuperan
- autoguardado cada cierto intervalo de tiempo en vez de guardar inmediatamente tras cada cambio en los ajustes, por optimización la posición de su marco de ajustes al arrancar; eran 12 y ninguno la guardaba
- el guardado se realiza desde otro hilo ahora, para evitar que el I/O bloque el hilo principal - los marcos ya guardan su posición al moverlos, aunque no se hayan plegado nunca antes
- la barra de búsqueda ya no deja escondidos los módulos que no casaban al vaciarla o al desactivarla
- `teclas multimódulo` ya deja compartir tecla entre módulos, que es lo que dice hacer;
antes sólo servía para las teclas de vanilla y le quitaba la tecla al otro módulo igualmente
- `notificar` ya se respeta al desactivar un módulo, no sólo al activarlo
- `delay de paquetes` ya no se apaga solo al entrar a un servidor
- `selección de minado`: el `delay` de reintentos y el de selección ya no comparten el valor guardado
- `$bind` ya avisa de que una tecla está cogida (el aviso no saltaba nunca) y muestra bien el nombre de la tecla
- `$clickslot` ya acepta las sugerencias que él mismo da
## problemas reconocidos ## problemas reconocidos
- lo de siempre. - lo de siempre.
- el ítem del tótem no se renderiza en el editor del HUD si es abierto en la pantalla de inicio - los nombres de los módulos y de los ajustes se guardan en la config. en español, se ponga el idioma
que se ponga. es a propósito: son la clave con la que se guardan, así que traducirlos resetearía
los ajustes de todo el mundo al cambiar de idioma
+5 -5
View File
@@ -1,15 +1,15 @@
org.gradle.jvmargs=-Xmx2G org.gradle.jvmargs=-Xmx2G
org.gradle.parallel=true org.gradle.parallel=true
minecraft_version=26.1.2 minecraft_version=26.2
loader_version=0.19.2 loader_version=0.19.3
loom_version=1.16-SNAPSHOT loom_version=1.17-SNAPSHOT
fabric_api_version=0.146.0+26.1.2 fabric_api_version=0.154.0+26.2
discord_rpc_version=1.0.3 discord_rpc_version=1.0.3
neutrino_version=1.1.0 neutrino_version=1.1.0
jdk_version=25 jdk_version=25
mod_version=5.2 mod_version=5.3
maven_group=me.retucio maven_group=me.retucio
archives_base_name=sputnik archives_base_name=sputnik
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
+30 -19
View File
@@ -47,6 +47,7 @@ import net.minecraft.client.gui.screens.TitleScreen;
import net.minecraft.client.gui.screens.inventory.AbstractCommandBlockEditScreen; import net.minecraft.client.gui.screens.inventory.AbstractCommandBlockEditScreen;
import net.minecraft.client.gui.screens.inventory.AbstractSignEditScreen; import net.minecraft.client.gui.screens.inventory.AbstractSignEditScreen;
import net.minecraft.client.gui.screens.inventory.AnvilScreen; import net.minecraft.client.gui.screens.inventory.AnvilScreen;
import net.minecraft.network.chat.Component;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@@ -183,7 +184,7 @@ public class Sputnik implements ClientModInitializer {
// se ocupa de la lógica de encendido y apagado de los módulos // se ocupa de la lógica de encendido y apagado de los módulos
private void handleModuleToggle(int key, boolean anyFocused) { private void handleModuleToggle(int key, boolean anyFocused) {
if (mc.screen != null && mc.screen != ClickGui.INSTANCE) return; if (mc.gui.screen() != null && mc.gui.screen() != ClickGui.INSTANCE) return;
for (Module module : ModuleManager.INSTANCE.getModules()) { for (Module module : ModuleManager.INSTANCE.getModules()) {
// evitar interrumpir combinaciones de teclas del F3 // evitar interrumpir combinaciones de teclas del F3
@@ -211,12 +212,12 @@ public class Sputnik implements ClientModInitializer {
if (key != ClientSettingsPanel.clientSettings.getKey() || anyFocused || isOnTypingScreen()) if (key != ClientSettingsPanel.clientSettings.getKey() || anyFocused || isOnTypingScreen())
return; return;
if (mc.screen != ClickGui.INSTANCE) { if (mc.gui.screen() != ClickGui.INSTANCE) {
prevScreen = mc.screen; prevScreen = mc.gui.screen();
mc.setScreen(ClickGui.INSTANCE); mc.gui.setScreen(ClickGui.INSTANCE);
} else { } else {
ClickGui.INSTANCE.onClose(); ClickGui.INSTANCE.onClose();
mc.setScreen(prevScreen); mc.gui.setScreen(prevScreen);
} }
} }
@@ -225,22 +226,22 @@ public class Sputnik implements ClientModInitializer {
Hud hud = ModuleManager.INSTANCE.getModuleByClass(Hud.class); Hud hud = ModuleManager.INSTANCE.getModuleByClass(Hud.class);
if (key != hud.editorKey.getValue() || anyFocused || isOnTypingScreen()) return; if (key != hud.editorKey.getValue() || anyFocused || isOnTypingScreen()) return;
if (mc.screen != HudEditorScreen.INSTANCE) { if (mc.gui.screen() != HudEditorScreen.INSTANCE) {
if (!hud.isEnabled()) { if (!hud.isEnabled()) {
ChatUtil.warn("HUD está desactivado, lumbreras"); ChatUtil.warn(Component.translatable("sputnik.hud.disabled"));
return; return;
} }
prevScreen = mc.screen; prevScreen = mc.gui.screen();
mc.setScreen(HudEditorScreen.INSTANCE); mc.gui.setScreen(HudEditorScreen.INSTANCE);
} else { } else {
HudEditorScreen.INSTANCE.onClose(); HudEditorScreen.INSTANCE.onClose();
mc.setScreen(prevScreen); mc.gui.setScreen(prevScreen);
} }
} }
// se ocupa de apagar los módulos que tengan configurado hacerlo tras soltar su tecla // se ocupa de apagar los módulos que tengan configurado hacerlo tras soltar su tecla
private void handleModuleRelease(int key) { private void handleModuleRelease(int key) {
if (mc.screen != null && mc.screen != ClickGui.INSTANCE) return; if (mc.gui.screen() != null && mc.gui.screen() != ClickGui.INSTANCE) return;
for (Module module : ModuleManager.INSTANCE.getEnabledModules()) for (Module module : ModuleManager.INSTANCE.getEnabledModules())
if (module.shouldToggleOnBindRelease() && key == module.getKey()) if (module.shouldToggleOnBindRelease() && key == module.getKey())
@@ -248,19 +249,29 @@ public class Sputnik implements ClientModInitializer {
} }
private boolean isOnTypingScreen() { private boolean isOnTypingScreen() {
return mc.screen instanceof ChatScreen return mc.gui.screen() instanceof ChatScreen
|| mc.screen instanceof AnvilScreen || mc.gui.screen() instanceof AnvilScreen
|| mc.screen instanceof AbstractSignEditScreen || mc.gui.screen() instanceof AbstractSignEditScreen
|| mc.screen instanceof AbstractCommandBlockEditScreen; || mc.gui.screen() instanceof AbstractCommandBlockEditScreen;
} }
private boolean keysVerified = false;
@EventListener @EventListener
// notificar al usuario de que hay una actualización disponible, si la hay // notificar al usuario de que hay una actualización disponible, si la hay
public void onSetScreen(OpenScreenEvent event) { public void onSetScreen(OpenScreenEvent event) {
if (VersionChecker.INSTANCE.shouldShowScreen && event.getScreen() instanceof TitleScreen) { if (event.getScreen() instanceof TitleScreen) {
event.cancel(); // aquí el idioma ya está cargado, que en onInitializeClient todavía no
VersionChecker.INSTANCE.shouldShowScreen = false; if (!keysVerified) {
mc.execute(() -> mc.screen = new UpdateScreen()); keysVerified = true;
I18nUtil.verifyKeys();
}
if (VersionChecker.INSTANCE.shouldShowScreen) {
event.cancel();
VersionChecker.INSTANCE.shouldShowScreen = false;
mc.execute(() -> mc.gui.setScreen(new UpdateScreen()));
}
} }
} }
@@ -25,7 +25,7 @@ public class EntityArgumentType implements ArgumentType<Entity> {
public static final EntityArgumentType INSTANCE = new EntityArgumentType(); public static final EntityArgumentType INSTANCE = new EntityArgumentType();
private static final DynamicCommandExceptionType NO_SUCH_ENTITY = new DynamicCommandExceptionType( private static final DynamicCommandExceptionType NO_SUCH_ENTITY = new DynamicCommandExceptionType(
name -> Component.literal("Entidad \"" + name + "\" no encontrada")); name -> Component.translatable("sputnik.args.entity.notfound", name));
private static final Collection<String> EXAMPLES = List.of( private static final Collection<String> EXAMPLES = List.of(
"AdlerHitdolf", "AdlerHitdolf",
@@ -15,7 +15,8 @@ import java.util.concurrent.CompletableFuture;
public class EnumArgumentType<T extends Enum<T>> implements ArgumentType<T> { public class EnumArgumentType<T extends Enum<T>> implements ArgumentType<T> {
private static final DynamicCommandExceptionType NO_SUCH_TYPE = new DynamicCommandExceptionType((value) -> Component.nullToEmpty(" argumento inválido: " + value)); private static final DynamicCommandExceptionType NO_SUCH_TYPE = new DynamicCommandExceptionType(
(value) -> Component.translatable("sputnik.args.enum.invalid", value));
private final T[] values; private final T[] values;
@@ -33,8 +34,10 @@ public class EnumArgumentType<T extends Enum<T>> implements ArgumentType<T> {
public T parse(StringReader reader) throws CommandSyntaxException { public T parse(StringReader reader) throws CommandSyntaxException {
String argument = reader.readString(); String argument = reader.readString();
// ignorando mayúsculas: listSuggestions sugiere en minúsculas, así que comparar
// con equals() hacía que las propias sugerencias no se pudieran parsear
return Arrays.stream(this.values) return Arrays.stream(this.values)
.filter((value) -> value.toString().equals(argument)) .filter((value) -> value.toString().equalsIgnoreCase(argument))
.findFirst() .findFirst()
.orElseThrow(() -> NO_SUCH_TYPE.create(argument) .orElseThrow(() -> NO_SUCH_TYPE.create(argument)
); );
@@ -22,15 +22,15 @@ public class ModuleArgumentType implements ArgumentType<Module> {
public static final ModuleArgumentType INSTANCE = new ModuleArgumentType(); public static final ModuleArgumentType INSTANCE = new ModuleArgumentType();
private static final DynamicCommandExceptionType UNKNOWN_MODULE = new DynamicCommandExceptionType( private static final DynamicCommandExceptionType UNKNOWN_MODULE = new DynamicCommandExceptionType(
name -> Component.literal("módulo \"" + name + "\" no encontrado")); name -> Component.translatable("sputnik.args.module.notfound", name));
private static final Collection<String> examples = ModuleManager.INSTANCE.getModules() private static final Collection<String> examples = ModuleManager.INSTANCE.getModules()
.stream().limit(3).map(module -> module.getName().replace(" ", "_")).toList(); .stream().limit(3).map(module -> module.getDisplayName().replace(" ", "_")).toList();
@Override @Override
public Module parse(StringReader reader) throws CommandSyntaxException { public Module parse(StringReader reader) throws CommandSyntaxException {
String argument = reader.readString().replace("_", " "); String argument = reader.readString().replace("_", " ");
Module module = ModuleManager.INSTANCE.getModuleByName(argument); Module module = ModuleManager.INSTANCE.getModuleByDisplayName(argument);
if (module == null) throw UNKNOWN_MODULE.create(argument); if (module == null) throw UNKNOWN_MODULE.create(argument);
return module; return module;
} }
@@ -38,7 +38,7 @@ public class ModuleArgumentType implements ArgumentType<Module> {
@Override @Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) { public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
return SharedSuggestionProvider.suggest(ModuleManager.INSTANCE.getModules() return SharedSuggestionProvider.suggest(ModuleManager.INSTANCE.getModules()
.stream().map(module -> MiscUtil.removeAccentMarks(module.getName().replace(" ", "_"))), builder); .stream().map(module -> MiscUtil.removeAccentMarks(module.getDisplayName().replace(" ", "_"))), builder);
} }
@Override @Override
@@ -21,7 +21,8 @@ import static me.retucio.sputnik.Sputnik.mc;
public class PlayerArgumentType implements ArgumentType<Player> { public class PlayerArgumentType implements ArgumentType<Player> {
public static final PlayerArgumentType INSTANCE = new PlayerArgumentType(); public static final PlayerArgumentType INSTANCE = new PlayerArgumentType();
private static final DynamicCommandExceptionType NO_SUCH_PLAYER = new DynamicCommandExceptionType(name -> Component.literal("Player with name " + name + " doesn't exist.")); private static final DynamicCommandExceptionType NO_SUCH_PLAYER = new DynamicCommandExceptionType(
name -> Component.translatable("sputnik.args.player.notfound", name));
private static final Collection<String> EXAMPLES = List.of("retucio", "prepucio", "postpucio", "pucio", "adler hitdolf"); private static final Collection<String> EXAMPLES = List.of("retucio", "prepucio", "postpucio", "pucio", "adler hitdolf");
@@ -24,7 +24,7 @@ public class BindCommand extends Command {
private static Module listeningModule = null; private static Module listeningModule = null;
public BindCommand() { public BindCommand() {
super("bind", "asigna una tecla a un módulo", "keybind"); super("bind", Component.translatable("sputnik.commands.bind.desc").getString(), "keybind", "kb", "tecla");
} }
@Override @Override
@@ -34,14 +34,16 @@ public class BindCommand extends Command {
.executes(ctx -> { .executes(ctx -> {
Module module = ctx.getArgument("módulo", Module.class); Module module = ctx.getArgument("módulo", Module.class);
listeningModule = module; listeningModule = module;
ChatUtil.info("presiona una tecla para asignarla al módulo " + ChatFormatting.GREEN + module.getName()); ChatUtil.info(Component.translatable("sputnik.commands.bind.presskey", ChatFormatting.GREEN + module.getDisplayName()));
return SUCCESS; return SUCCESS;
}) })
.then(literal("reset").executes(ctx -> { .then(literal("reset").executes(ctx -> {
Module module = ctx.getArgument("módulo", Module.class); Module module = ctx.getArgument("módulo", Module.class);
module.getBind().reset(); module.getBind().reset();
ChatUtil.info("tecla para el módulo " + ChatFormatting.GREEN + module.getName() ChatUtil.info(Component.translatable("sputnik.commands.bind.keyreset",
+ " restablecida a " + ChatFormatting.AQUA + KeyUtil.getKeyName(module.getKey())); ChatFormatting.GREEN + module.getDisplayName(),
ChatFormatting.AQUA + KeyUtil.getKeyName(module.getKey())
));
return SUCCESS; return SUCCESS;
})) }))
); );
@@ -51,17 +53,18 @@ public class BindCommand extends Command {
if (listeningModule == null) return false; if (listeningModule == null) return false;
KeySetting bind = listeningModule.getBind(); KeySetting bind = listeningModule.getBind();
if (ClientSettingsPanel.clientSettings.multipleKeybinds.getValue()) { // solo hay que avisar de que la tecla está cogida cuando NO se permiten teclas repetidas.
// antes esto entraba con multipleKeybinds activado y luego comprobaba !allowMultiple con el
// mismo valor, así que nunca se llegaba a avisar
if (!ClientSettingsPanel.clientSettings.multipleKeybinds.getValue()) {
List<KeyMapping> keys = new ArrayList<>(List.of(mc.options.keyMappings)); List<KeyMapping> keys = new ArrayList<>(List.of(mc.options.keyMappings));
keys.removeAll(List.of(mc.options.debugKeys)); keys.removeAll(List.of(mc.options.debugKeys));
for (KeyMapping kb : keys) { for (KeyMapping kb : keys) {
boolean keyAlreadyBound = kb.matches(new KeyEvent(key, 0, 0)); if (kb.matches(new KeyEvent(key, 0, 0))) {
boolean allowMultiple = ClientSettingsPanel.clientSettings.multipleKeybinds.getValue(); // la comilla iba dentro del I18n.get, así que buscaba una clave inexistente
ChatUtil.warn(Component.translatable("sputnik.commands.bind.keytaken",
if (keyAlreadyBound && !allowMultiple) { ChatFormatting.GREEN + "\"" + I18n.get(kb.getName()) + "\""));
ChatUtil.warn("esa tecla ya está cogida por "
+ ChatFormatting.GREEN + "\"" + I18n.get(kb.getName() + "\""));
listeningModule = null; listeningModule = null;
return true; return true;
} }
@@ -70,10 +73,10 @@ public class BindCommand extends Command {
if (bind != null) bind.setValue(key); if (bind != null) bind.setValue(key);
ChatUtil.info( ChatUtil.info(Component.translatable("sputnik.commands.bind.keybound",
Component.nullToEmpty("la tecla " + ChatFormatting.AQUA + KeyUtil.getKeyName(key) + ChatFormatting.RESET + ChatFormatting.AQUA + KeyUtil.getKeyName(key) + ChatFormatting.RESET,
" ha sido asignada al módulo " + ChatFormatting.GREEN + listeningModule.getName()) ChatFormatting.GREEN + listeningModule.getDisplayName()
); ));
listeningModule = null; listeningModule = null;
return true; return true;
@@ -7,13 +7,14 @@ import me.retucio.sputnik.command.args.EnumArgumentType;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.ContainerScreen; import net.minecraft.client.gui.screens.inventory.ContainerScreen;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component;
import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.inventory.ContainerInput;
// https://cdn.discordapp.com/attachments/1456079799045980400/1457154232737206375/dupersunited-public-addon-1.21.11-3.1.3.jar?ex=69735be1&is=69720a61&hm=77fb6faee49762e0a812661f0d98931e89cb725db711c45722249d0efe3b91e4& // https://cdn.discordapp.com/attachments/1456079799045980400/1457154232737206375/dupersunited-public-addon-1.21.11-3.1.3.jar?ex=69735be1&is=69720a61&hm=77fb6faee49762e0a812661f0d98931e89cb725db711c45722249d0efe3b91e4&
public class ClickSlotCommand extends Command { public class ClickSlotCommand extends Command {
public ClickSlotCommand() { public ClickSlotCommand() {
super("clickslot", "simula un clic a un slot"); super("clickslot", Component.translatable("sputnik.commands.clickslot.desc").getString(), "cs");
} }
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) { public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
@@ -23,7 +24,7 @@ public class ClickSlotCommand extends Command {
.executes(context -> { .executes(context -> {
int slot = context.getArgument("slot", Integer.class), button = context.getArgument("botón", Integer.class); int slot = context.getArgument("slot", Integer.class), button = context.getArgument("botón", Integer.class);
ContainerInput action = context.getArgument("acción", ContainerInput.class); ContainerInput action = context.getArgument("acción", ContainerInput.class);
Screen screen = mc.screen; Screen screen = mc.gui.screen();
int syncId = (screen instanceof ContainerScreen cScreen) ? cScreen.getMenu().containerId : 0; int syncId = (screen instanceof ContainerScreen cScreen) ? cScreen.getMenu().containerId : 0;
if (mc.gameMode == null) return 0; if (mc.gameMode == null) return 0;
mc.gameMode.handleContainerInput(syncId, slot, button, action, mc.player); mc.gameMode.handleContainerInput(syncId, slot, button, action, mc.player);
@@ -9,11 +9,12 @@ import me.retucio.sputnik.ui.screen.ClickGui;
import me.retucio.sputnik.ui.widgets.panels.SettingsPanel; import me.retucio.sputnik.ui.widgets.panels.SettingsPanel;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.Module;
import net.minecraft.network.chat.Component;
public class ConfigCommand extends Command { public class ConfigCommand extends Command {
public ConfigCommand() { public ConfigCommand() {
super("config", "abre el marco de ajustes de un módulo", "ajustes", "settings"); super("config", Component.translatable("sputnik.commands.config.desc").getString(), "ajustes", "settings");
} }
@Override @Override
@@ -40,7 +41,7 @@ public class ConfigCommand extends Command {
private void openSf(CommandContext<SharedSuggestionProvider> ctx) { private void openSf(CommandContext<SharedSuggestionProvider> ctx) {
Module module = ctx.getArgument("módulo", Module.class); Module module = ctx.getArgument("módulo", Module.class);
mc.setScreen(ClickGui.INSTANCE); mc.gui.setScreen(ClickGui.INSTANCE);
if (ClickGui.INSTANCE.isSettingsPanelOpen(module)) return; if (ClickGui.INSTANCE.isSettingsPanelOpen(module)) return;
@@ -53,7 +54,7 @@ public class ConfigCommand extends Command {
private void openSfWithPos(CommandContext<SharedSuggestionProvider> ctx, int x, int y) { private void openSfWithPos(CommandContext<SharedSuggestionProvider> ctx, int x, int y) {
Module module = ctx.getArgument("módulo", Module.class); Module module = ctx.getArgument("módulo", Module.class);
mc.setScreen(ClickGui.INSTANCE); mc.gui.setScreen(ClickGui.INSTANCE);
if (ClickGui.INSTANCE.isSettingsPanelOpen(module)) { if (ClickGui.INSTANCE.isSettingsPanelOpen(module)) {
SettingsPanel sf = ClickGui.INSTANCE.getSettingsPanelOfModule(module); SettingsPanel sf = ClickGui.INSTANCE.getSettingsPanelOfModule(module);
@@ -5,12 +5,13 @@ import me.retucio.sputnik.command.Command;
import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.misc.ScreenshotPlus; import me.retucio.sputnik.module.modules.misc.ScreenshotPlus;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component;
// se usa principalmente para el módulo ScreenshotPlus, pero también se puede usar sin él supongo // se usa principalmente para el módulo ScreenshotPlus, pero también se puede usar sin él supongo
public class CopyScreenshotCommand extends Command { public class CopyScreenshotCommand extends Command {
public CopyScreenshotCommand() { public CopyScreenshotCommand() {
super("copiarcaptura", "copia la captura más reciente al portapapeles"); super("copiarcaptura", Component.translatable("sputnik.commands.copyscreenshot.desc").getString(), "copyscreenshot");
} }
@Override @Override
@@ -8,6 +8,7 @@ import me.retucio.sputnik.ui.screen.PreviewScreen;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import me.retucio.sputnik.util.InventoryUtil; import me.retucio.sputnik.util.InventoryUtil;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component;
// accede a los contenidos de tu enderchest // accede a los contenidos de tu enderchest
public class EnderChestCommand extends Command { public class EnderChestCommand extends Command {
@@ -15,7 +16,7 @@ public class EnderChestCommand extends Command {
private boolean shouldOpenEchest = false; private boolean shouldOpenEchest = false;
public EnderChestCommand() { public EnderChestCommand() {
super("echest", "muestra el contenido de tu enderchest (solo de ver)", "ec", "enderchest"); super("echest", Component.translatable("sputnik.commands.echest.desc").getString(), "ec", "enderchest");
} }
@Override @Override
@@ -24,7 +25,7 @@ public class EnderChestCommand extends Command {
mc.execute(() -> { mc.execute(() -> {
if (mc.player == null) return; if (mc.player == null) return;
if (InventoryUtil.getEchestInv() == null) { if (InventoryUtil.getEchestInv() == null) {
ChatUtil.warn("necesitas abrir un enderchest una vez primero"); ChatUtil.warn(Component.translatable( "sputnik.commands.echest.openfirst"));
return; return;
} }
@@ -40,7 +41,7 @@ public class EnderChestCommand extends Command {
if (shouldOpenEchest) { if (shouldOpenEchest) {
shouldOpenEchest = false; shouldOpenEchest = false;
if (InventoryUtil.getEchestInv() != null) if (InventoryUtil.getEchestInv() != null)
mc.setScreen(new PreviewScreen(InventoryUtil.getEchestInv(), null)); mc.gui.setScreen(new PreviewScreen(InventoryUtil.getEchestInv(), null));
} }
} }
} }
@@ -8,12 +8,14 @@ import me.retucio.sputnik.friend.FriendManager;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
public class FriendCommand extends Command { public class FriendCommand extends Command {
public FriendCommand() { public FriendCommand() {
super("friend", "gestión de amigos", "amigo", "f"); super("friend", Component.translatable("sputnik.commands.friend.desc").getString(), "amigo", "f");
} }
@Override @Override
@@ -24,7 +26,10 @@ public class FriendCommand extends Command {
.executes(ctx -> { .executes(ctx -> {
Player friend = ctx.getArgument("amigo", Player.class); Player friend = ctx.getArgument("amigo", Player.class);
FriendManager.INSTANCE.add(friend.getUUID()); FriendManager.INSTANCE.add(friend.getUUID());
ChatUtil.info(ChatFormatting.GREEN + friend.getName().getString() + ChatFormatting.RESET + " ahora es tu amigo :)"); ChatUtil.info(Component.translatable(
"sputnik.commands.friend.added",
ChatFormatting.GREEN + friend.getName().getString() + ChatFormatting.RESET
));
return SUCCESS; return SUCCESS;
}) })
) )
@@ -34,14 +39,17 @@ public class FriendCommand extends Command {
.executes(ctx -> { .executes(ctx -> {
Player friend = ctx.getArgument("amigo", Player.class); Player friend = ctx.getArgument("amigo", Player.class);
FriendManager.INSTANCE.remove(friend.getUUID()); FriendManager.INSTANCE.remove(friend.getUUID());
ChatUtil.info(ChatFormatting.GREEN + friend.getName().getString() + ChatFormatting.RESET + " ya no es tu amigo :("); ChatUtil.info(Component.translatable(
"sputnik.commands.friend.removed",
ChatFormatting.GREEN + friend.getName().getString() + ChatFormatting.RESET
));
return SUCCESS; return SUCCESS;
}) })
) )
) )
.then(literal("list") .then(literal("list")
.executes(ctx -> { .executes(ctx -> {
ChatUtil.info(ChatFormatting.GOLD + "amigos:"); ChatUtil.info(ChatFormatting.GOLD + Component.translatable("sputnik.commands.friend.list").getString());
for (Friend friend : FriendManager.INSTANCE.getFriends()) { for (Friend friend : FriendManager.INSTANCE.getFriends()) {
ChatUtil.info("- " + friend.getName()); ChatUtil.info("- " + friend.getName());
} }
@@ -9,14 +9,14 @@ import net.minecraft.network.chat.Component;
public class GarbageCleanerCommand extends Command { public class GarbageCleanerCommand extends Command {
public GarbageCleanerCommand() { public GarbageCleanerCommand() {
super("gc", "limpia la ram mediante el recolector de basura (gc)", "garbagecollect"); super("gc", Component.translatable("sputnik.commands.gc.desc").getString(), "garbagecollect");
} }
@Override @Override
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) { public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
builder.executes(context -> { builder.executes(context -> {
System.gc(); System.gc();
ChatUtil.info(Component.nullToEmpty("basura recolectada")); ChatUtil.info(Component.translatable("sputnik.commands.gc.collected"));
return SUCCESS; return SUCCESS;
}); });
} }
@@ -6,12 +6,15 @@ import me.retucio.sputnik.command.args.PlayerArgumentType;
import me.retucio.sputnik.util.MiscUtil; import me.retucio.sputnik.util.MiscUtil;
import net.minecraft.client.gui.screens.inventory.InventoryScreen; import net.minecraft.client.gui.screens.inventory.InventoryScreen;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component;
import java.awt.*;
// comando que debería de mostrar el inventario de un jugador, pero por cómo funcionan los servers, solo te deja ver el ítem que tenga en la mano // comando que debería de mostrar el inventario de un jugador, pero por cómo funcionan los servers, solo te deja ver el ítem que tenga en la mano
public class PeekCommand extends Command { public class PeekCommand extends Command {
public PeekCommand() { public PeekCommand() {
super("inventario", "cotillea el inventario de otro jugador", "invsee", "peek", "inv"); super("inventario", Component.translatable("sputnik.commands.peek.desc").getString(), "invsee", "peek", "inv");
} }
@Override @Override
@@ -12,6 +12,7 @@ import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.client.multiplayer.ClientSuggestionProvider; import net.minecraft.client.multiplayer.ClientSuggestionProvider;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundCommandsPacket; import net.minecraft.network.protocol.game.ClientboundCommandsPacket;
import java.util.HashSet; import java.util.HashSet;
@@ -23,7 +24,7 @@ public class PluginsCommand extends Command {
private boolean scanning = false; private boolean scanning = false;
public PluginsCommand() { public PluginsCommand() {
super("plugins", "busca los plugins que tenga el server", "pl", "serverplugins"); super("plugins", Component.translatable("sputnik.commands.plugins.desc").getString(), "pl", "serverplugins");
Sputnik.EVENT_BUS.subscribe(this); Sputnik.EVENT_BUS.subscribe(this);
} }
@@ -31,12 +32,12 @@ public class PluginsCommand extends Command {
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) { public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
builder.executes(context -> { builder.executes(context -> {
if (mc.hasSingleplayerServer()) { if (mc.hasSingleplayerServer()) {
ChatUtil.error("estás en un solo jugador"); ChatUtil.error(Component.translatable("sputnik.commands.plugins.singleplayer"));
return SUCCESS; return SUCCESS;
} }
if (scanning) { if (scanning) {
ChatUtil.error("calmaaa"); ChatUtil.error(Component.translatable("sputnik.commands.plugins.calmdown"));
return SUCCESS; return SUCCESS;
} }
@@ -60,7 +61,7 @@ public class PluginsCommand extends Command {
root.getChildren().forEach(this::checkNodeForPlugins); root.getChildren().forEach(this::checkNodeForPlugins);
if (!plugins.isEmpty()) { if (!plugins.isEmpty()) {
ChatUtil.info(plugins.size() + " namespace(s) encontrado(s) de comandos:"); ChatUtil.info(Component.translatable("sputnik.commands.plugins.namespacesfound", plugins.size()));
plugins.stream() plugins.stream()
.sorted() .sorted()
.forEach(plugin -> ChatUtil.info(" - " + plugin)); .forEach(plugin -> ChatUtil.info(" - " + plugin));
@@ -69,7 +70,7 @@ public class PluginsCommand extends Command {
displayResults(); displayResults();
} catch (Exception e) { } catch (Exception e) {
ChatUtil.error("error analizando comandos: " + e.getMessage()); ChatUtil.error(Component.translatable("sputnik.commands.plugins.erroranalyzingcommands", e.getMessage()));
} }
} }
@@ -99,11 +100,11 @@ public class PluginsCommand extends Command {
private void displayResults() { private void displayResults() {
if (!plugins.isEmpty()) { if (!plugins.isEmpty()) {
ChatUtil.info(plugins.size() + " plugin(s) encontrado(s)"); ChatUtil.info(Component.translatable("sputnik.commands.plugins.pluginsfound", plugins.size()));
plugins.stream().sorted() plugins.stream().sorted()
.forEach(plugin -> ChatUtil.info(" - " + plugin)); .forEach(plugin -> ChatUtil.info(" - " + plugin));
} else { } else {
ChatUtil.warn("sin plugins (probablemente)"); ChatUtil.warn(Component.translatable("sputnik.commands.plugins.noplugins"));
} }
scanning = false; scanning = false;
@@ -13,17 +13,17 @@ import net.minecraft.network.chat.Component;
public class PrefixCommand extends Command { public class PrefixCommand extends Command {
public PrefixCommand() { public PrefixCommand() {
super("prefijo", "cambia el prefijo de los comandos", "prefix"); super("prefijo", Component.translatable("sputnik.commands.prefix.desc").getString(), "prefix");
} }
@Override @Override
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) { public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
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);
ClientSettingsPanel.clientSettings.commandPrefix.setValue(prefix); ClientSettingsPanel.clientSettings.commandPrefix.setValue(prefix);
ChatUtil.info(Component.literal("prefijo cambiado a " + ChatFormatting.AQUA + prefix)); ChatUtil.info(Component.translatable("sputnik.commands.prefix.changed", ChatFormatting.AQUA + prefix));
return SUCCESS; return SUCCESS;
})); }));
} }
} }
@@ -7,13 +7,15 @@ import me.retucio.sputnik.util.interfaces.IChatComponent;
import net.minecraft.client.gui.components.ChatComponent; import net.minecraft.client.gui.components.ChatComponent;
import net.minecraft.client.multiplayer.chat.GuiMessage; import net.minecraft.client.multiplayer.chat.GuiMessage;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component;
import java.awt.*;
import java.util.List; import java.util.List;
public class PurgeCommand extends Command { public class PurgeCommand extends Command {
public PurgeCommand() { public PurgeCommand() {
super("purgar", "elimina mensajes del chat", "purge"); super("purgar", Component.translatable("sputnik.commands.purge.desc").getString(), "purge");
} }
@Override @Override
@@ -28,7 +30,7 @@ public class PurgeCommand extends Command {
} }
private void purgeMessages(int amount) { private void purgeMessages(int amount) {
ChatComponent chatHud = mc.gui.getChat(); ChatComponent chatHud = mc.gui.hud.getChat();
synchronized (chatHud) { synchronized (chatHud) {
List<GuiMessage.Line> visibleMessages = ((IChatComponent) chatHud).sputnik$getVisibleMessages(); List<GuiMessage.Line> visibleMessages = ((IChatComponent) chatHud).sputnik$getVisibleMessages();
@@ -6,11 +6,12 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.sputnik.command.Command; import me.retucio.sputnik.command.Command;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component;
public class RepeatCommand extends Command { public class RepeatCommand extends Command {
public RepeatCommand() { public RepeatCommand() {
super("repetir", "repite un comando x veces", "repeat"); super("repetir", Component.translatable("sputnik.commands.repeat.desc").getString(), "repeat");
} }
@Override @Override
@@ -6,6 +6,7 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.sputnik.command.Command; import me.retucio.sputnik.command.Command;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -13,7 +14,7 @@ import java.util.concurrent.TimeUnit;
public class RepeatWaitCommand extends Command { public class RepeatWaitCommand extends Command {
public RepeatWaitCommand() { public RepeatWaitCommand() {
super("repesperar", "combinación de $repetir y $esperar"); super("repesperar", Component.translatable("sputnik.commands.repeatwait.desc").getString(), "repeatwait");
} }
@Override @Override
@@ -6,6 +6,7 @@ import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.misc.ScreenshotPlus; import me.retucio.sputnik.module.modules.misc.ScreenshotPlus;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component;
import java.io.IOException; import java.io.IOException;
@@ -13,7 +14,7 @@ import java.io.IOException;
public class SaveScreenshotCommand extends Command { public class SaveScreenshotCommand extends Command {
public SaveScreenshotCommand() { public SaveScreenshotCommand() {
super("guardarcaptura", "guarda localmente la captura más reciente"); super("guardarcaptura", Component.translatable("sputnik.commands.savescreenshot.desc").getString(), "savescreenshot");
} }
@Override @Override
@@ -26,7 +27,7 @@ public class SaveScreenshotCommand extends Command {
try { try {
screenshotPlus.saveScreenshot(); screenshotPlus.saveScreenshot();
} catch (IOException e) { } catch (IOException e) {
ChatUtil.error("no se pudo guardar la captura"); ChatUtil.error(Component.translatable("sputnik.commands.savescreenshot.error"));
} }
} }
}); });
@@ -6,6 +6,7 @@ import me.retucio.sputnik.command.Command;
import me.retucio.sputnik.mixin.accessors.ClientPacketListenerAccessor; import me.retucio.sputnik.mixin.accessors.ClientPacketListenerAccessor;
import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.LastSeenMessagesTracker; import net.minecraft.network.chat.LastSeenMessagesTracker;
import net.minecraft.network.chat.MessageSignature; import net.minecraft.network.chat.MessageSignature;
import net.minecraft.network.chat.SignedMessageBody; import net.minecraft.network.chat.SignedMessageBody;
@@ -18,7 +19,7 @@ import java.time.Instant;
public class SendCommand extends Command { public class SendCommand extends Command {
public SendCommand() { public SendCommand() {
super("enviar", "manda un mensaje en el chat", "send"); super("enviar", Component.translatable("sputnik.commands.send.desc").getString(), "send");
} }
@Override @Override
@@ -37,7 +38,7 @@ public class SendCommand extends Command {
LastSeenMessagesTracker tracker = ((ClientPacketListenerAccessor) handler).getLastSeenMessagesTracker(); LastSeenMessagesTracker tracker = ((ClientPacketListenerAccessor) handler).getLastSeenMessagesTracker();
LastSeenMessagesTracker.Update lastSeenMessages = tracker.generateAndApplyUpdate(); LastSeenMessagesTracker.Update lastSeenMessages = tracker.generateAndApplyUpdate();
// empacar firma para un chat seguro // empacar firma
MessageSignature messageSignature = ((ClientPacketListenerAccessor) handler) MessageSignature messageSignature = ((ClientPacketListenerAccessor) handler)
.getSignedMessageEncoder() .getSignedMessageEncoder()
.pack(new SignedMessageBody( .pack(new SignedMessageBody(
@@ -7,19 +7,22 @@ import me.retucio.sputnik.command.args.EntityArgumentType;
import me.retucio.sputnik.event.input.KeyEvent; import me.retucio.sputnik.event.input.KeyEvent;
import me.retucio.sputnik.util.EntityUtil; import me.retucio.sputnik.util.EntityUtil;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import java.awt.*;
public class SpectateCommand extends Command { public class SpectateCommand extends Command {
public SpectateCommand() { public SpectateCommand() {
super("espectar", "te permite adquirir el punto de vista de una entidad", "spectate", "spec"); super("espectar", Component.translatable("sputnik.commands.spectate.desc").getString(), "spectate", "spec");
} }
@Override @Override
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) { public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
builder builder
.executes(ctx -> { // If no argument, use the entity player is looking at .executes(ctx -> {
mc.execute(() -> { mc.execute(() -> {
Entity target = EntityUtil.getEntityPlayerIsLookingAt(); Entity target = EntityUtil.getEntityPlayerIsLookingAt();
if (target != null) if (target != null)
@@ -40,7 +43,7 @@ public class SpectateCommand extends Command {
@EventListener @EventListener
public void onKey(KeyEvent event) { public void onKey(KeyEvent event) {
if (mc.getCameraEntity() != mc.player && mc.screen == null if (mc.getCameraEntity() != mc.player && mc.gui.screen() == null
&& event.getKey() == GLFW.GLFW_KEY_ESCAPE && event.getAction() != GLFW.GLFW_RELEASE ) { && event.getKey() == GLFW.GLFW_KEY_ESCAPE && event.getAction() != GLFW.GLFW_RELEASE ) {
event.cancel(); event.cancel();
mc.setCameraEntity(mc.player); mc.setCameraEntity(mc.player);
@@ -6,12 +6,15 @@ import me.retucio.sputnik.command.args.ModuleArgumentType;
import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.ModuleManager;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component;
import java.awt.*;
// porque usar el ratón es más lento que escribir, a menos que tengas toque con el teclado como yo // porque usar el ratón es más lento que escribir, a menos que tengas toque con el teclado como yo
public class ToggleCommand extends Command { public class ToggleCommand extends Command {
public ToggleCommand() { public ToggleCommand() {
super("alternar", "enciende / apaga módulos", "toggle"); super("alternar", Component.translatable("sputnik.commands.toggle.desc").getString(), "toggle");
} }
@Override @Override
@@ -6,6 +6,7 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.sputnik.command.Command; import me.retucio.sputnik.command.Command;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
@@ -16,7 +17,7 @@ public class WaitCommand extends Command {
private static final ScheduledExecutorService DELAYED_EXECUTOR = new ScheduledThreadPoolExecutor(2); private static final ScheduledExecutorService DELAYED_EXECUTOR = new ScheduledThreadPoolExecutor(2);
public WaitCommand() { public WaitCommand() {
super("wait", "espera un tiempo determinado antes de ejecutar otro comando", "esperar", "sleep", "delay"); super("wait", Component.translatable("sputnik.commands.wait.desc").getString(), "esperar", "sleep", "delay");
} }
@Override @Override
@@ -1,5 +1,7 @@
package me.retucio.sputnik.config; package me.retucio.sputnik.config;
import net.minecraft.network.chat.Component;
import java.io.*; import java.io.*;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
@@ -83,25 +85,26 @@ public class BinarySerializer {
public static ClientConfig readConfig(File file) public static ClientConfig readConfig(File file)
throws IOException { throws IOException {
if (!file.exists() || file.length() == 0) { if (!file.exists() || file.length() == 0) {
throw new IOException("archivo de config. vacío o inexistente"); throw new IOException(Component.translatable("sputnik.config.error.empty").getString());
} }
try (DataInputStream in = new DataInputStream( try (DataInputStream in = new DataInputStream(
new BufferedInputStream(new FileInputStream(file)))) { new BufferedInputStream(new FileInputStream(file)))) {
if (file.length() < 8) { if (file.length() < 8) {
throw new IOException("archivo demasiado pequeño para ser válido"); throw new IOException(Component.translatable("sputnik.config.error.toosmall").getString());
} }
// verificar cabezal // verificar cabezal
int magic = in.readInt(); int magic = in.readInt();
if (magic != MAGIC_NUMBER) { if (magic != MAGIC_NUMBER) {
throw new IOException("formato de archivo inválido: " + magic); throw new IOException(Component.translatable("sputnik.config.error.invalidformat", magic).getString());
} }
// todo: sustituir por lógica de migración en vez de simplemente no aceptarlo
int version = in.readInt(); int version = in.readInt();
if (version != VERSION) { if (version != VERSION) {
throw new IOException("versión inválida: " + version); throw new IOException(Component.translatable("sputnik.config.error.invalidversion", version).getString());
} }
ClientConfig config = new ClientConfig(); ClientConfig config = new ClientConfig();
@@ -17,7 +17,7 @@ import java.util.Map;
import static me.retucio.sputnik.Sputnik.EVENT_BUS; import static me.retucio.sputnik.Sputnik.EVENT_BUS;
import static me.retucio.sputnik.Sputnik.mc; import static me.retucio.sputnik.Sputnik.mc;
// clase donde se guardan las configuraciones temporalmente hasta escribirlas en camera_tweaks.json // clase donde se guardan las configuraciones temporalmente hasta escribirlas en sputnik.dat
public class ClientConfig { public class ClientConfig {
// nombre del módulo -> estado del módulo // nombre del módulo -> estado del módulo
@@ -104,9 +104,11 @@ public class ClientConfig {
ConfigManager.INSTANCE.markDirty(); ConfigManager.INSTANCE.markDirty();
} }
// put y no replace: replace no hace nada si la clave no está todavía, así que mover un
// marco sin haberlo plegado antes (que es lo que crea la entrada) no se guardaba
@EventListener @EventListener
public void onMoveModulePanel(ModulePanelEvent.Move event) { public void onMoveModulePanel(ModulePanelEvent.Move event) {
extendablePanels.replace(event.getPanel().category.toString(), new PanelData( extendablePanels.put(event.getPanel().category.toString(), new PanelData(
event.getPanel().getX(), event.getPanel().getX(),
event.getPanel().getY(), event.getPanel().getY(),
event.getPanel().isExtended())); event.getPanel().isExtended()));
@@ -124,7 +126,7 @@ public class ClientConfig {
@EventListener @EventListener
public void onMoveClientSettingsPanel(ClientSettingsPanelEvent.Move event) { public void onMoveClientSettingsPanel(ClientSettingsPanelEvent.Move event) {
extendablePanels.replace("ajustes", new PanelData( extendablePanels.put("ajustes", new PanelData(
ClickGui.INSTANCE.getClientSettingsPanel().getX(), ClickGui.INSTANCE.getClientSettingsPanel().getX(),
ClickGui.INSTANCE.getClientSettingsPanel().getY(), ClickGui.INSTANCE.getClientSettingsPanel().getY(),
ClickGui.INSTANCE.getClientSettingsPanel().isExtended())); ClickGui.INSTANCE.getClientSettingsPanel().isExtended()));
@@ -142,7 +144,7 @@ public class ClientConfig {
@EventListener @EventListener
public void onMoveFriendsPanel(FriendPanelEvent.Move event) { public void onMoveFriendsPanel(FriendPanelEvent.Move event) {
extendablePanels.replace("amigos", new PanelData( extendablePanels.put("amigos", new PanelData(
ClickGui.INSTANCE.getFriendsPanel().getX(), ClickGui.INSTANCE.getFriendsPanel().getX(),
ClickGui.INSTANCE.getFriendsPanel().getY(), ClickGui.INSTANCE.getFriendsPanel().getY(),
ClickGui.INSTANCE.getFriendsPanel().isExtended())); ClickGui.INSTANCE.getFriendsPanel().isExtended()));
@@ -12,12 +12,14 @@ import me.retucio.sputnik.module.setting.*;
import me.retucio.sputnik.module.setting.settings.*; import me.retucio.sputnik.module.setting.settings.*;
import me.retucio.sputnik.ui.hud.HudRenderer; import me.retucio.sputnik.ui.hud.HudRenderer;
import me.retucio.sputnik.ui.widgets.Panel; import me.retucio.sputnik.ui.widgets.Panel;
import me.retucio.sputnik.ui.widgets.panels.ExtendablePanel;
import me.retucio.sputnik.ui.widgets.panels.FriendsPanel; import me.retucio.sputnik.ui.widgets.panels.FriendsPanel;
import me.retucio.sputnik.ui.widgets.panels.ModulePanel; import me.retucio.sputnik.ui.widgets.panels.ModulePanel;
import me.retucio.sputnik.ui.screen.ClickGui; import me.retucio.sputnik.ui.screen.ClickGui;
import me.retucio.sputnik.ui.widgets.panels.settings.ClientSettingsPanel; import me.retucio.sputnik.ui.widgets.panels.settings.ClientSettingsPanel;
import me.retucio.sputnik.ui.widgets.panels.SettingsPanel; import me.retucio.sputnik.ui.widgets.panels.SettingsPanel;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.network.chat.Component;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
@@ -65,7 +67,7 @@ public class ConfigManager {
try { try {
snapshot = BinarySerializer.toBytes(config); snapshot = BinarySerializer.toBytes(config);
} catch (IOException e) { } catch (IOException e) {
Sputnik.LOGGER.error("error al serializar ajustes", e); Sputnik.LOGGER.error(Component.translatable("sputnik.config.error.serialization").getString(), e);
return; return;
} }
@@ -75,9 +77,9 @@ public class ConfigManager {
saveExecutor.execute(() -> { saveExecutor.execute(() -> {
try { try {
BinarySerializer.writeBytes(snapshot, CONFIG_FILE); BinarySerializer.writeBytes(snapshot, CONFIG_FILE);
Sputnik.LOGGER.info("ajustes guardados"); Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.saved").getString());
} catch (IOException e) { } catch (IOException e) {
Sputnik.LOGGER.error("error al guardar ajustes", e); Sputnik.LOGGER.error(Component.translatable("sputnik.config.error.saving").getString(), e);
} finally { } finally {
saveQueued.set(false); saveQueued.set(false);
} }
@@ -90,7 +92,7 @@ public class ConfigManager {
try { try {
// dar hasta 5 segundos para que termine el guardado en curso // dar hasta 5 segundos para que termine el guardado en curso
if (!saveExecutor.awaitTermination(5, TimeUnit.SECONDS)) { if (!saveExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
Sputnik.LOGGER.warn("el hilo de guardado no terminó a tiempo"); Sputnik.LOGGER.warn(Component.translatable("sputnik.config.warn.thread").getString());
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
@@ -101,15 +103,15 @@ public class ConfigManager {
} }
public void load() { public void load() {
Sputnik.LOGGER.info("cargando ajustes..."); Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.loading").getString());
if (CONFIG_FILE.exists()) { if (CONFIG_FILE.exists()) {
try { try {
config = BinarySerializer.readConfig(CONFIG_FILE); config = BinarySerializer.readConfig(CONFIG_FILE);
Sputnik.LOGGER.info("ajustes cargados"); Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.loaded").getString());
return; return;
} catch (IOException e) { } catch (IOException e) {
Sputnik.LOGGER.error("error cargando ajustes, intentando json", e); Sputnik.LOGGER.error(Component.translatable("sputnik.config.error.loading").getString(), e);
} }
} }
@@ -118,12 +120,12 @@ public class ConfigManager {
try (FileReader reader = new FileReader(LEGACY_JSON_FILE)) { try (FileReader reader = new FileReader(LEGACY_JSON_FILE)) {
Gson gson = new GsonBuilder().setPrettyPrinting().create(); Gson gson = new GsonBuilder().setPrettyPrinting().create();
config = gson.fromJson(reader, ClientConfig.class); config = gson.fromJson(reader, ClientConfig.class);
Sputnik.LOGGER.info("ajustes json cargados (migración)"); Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.json").getString());
save(); save();
return; return;
} catch (IOException e) { } catch (IOException e) {
Sputnik.LOGGER.error("error cargando json, usando defaults", e); Sputnik.LOGGER.error(Component.translatable("sputnik.config.error.json").getString(), e);
} }
} }
@@ -145,7 +147,7 @@ public class ConfigManager {
applyFriends(); applyFriends();
loaded = true; loaded = true;
Sputnik.LOGGER.info("ajustes aplicados"); Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.applied").getString());
} }
// obtener configuración actual // obtener configuración actual
@@ -211,7 +213,7 @@ public class ConfigManager {
friend.setName(name); friend.setName(name);
FriendManager.INSTANCE.add(friend); FriendManager.INSTANCE.add(friend);
}); });
Sputnik.LOGGER.info("amigos aplicados"); Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.friends").getString());
} }
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
@@ -231,7 +233,8 @@ public class ConfigManager {
case ListSetting listSetting -> applyListSetting(listSetting, value); case ListSetting listSetting -> applyListSetting(listSetting, value);
case ColorSetting colorSetting -> applyColorSetting(colorSetting, value); case ColorSetting colorSetting -> applyColorSetting(colorSetting, value);
case OptionSetting optionSetting -> applyOptionSetting(optionSetting, value); case OptionSetting optionSetting -> applyOptionSetting(optionSetting, value);
default -> Sputnik.LOGGER.warn("watafac queseso: {}", setting.getClass().getSimpleName()); default -> Sputnik.LOGGER.warn(Component.translatable("sputnik.config.warn.unknownsetting",
setting.getClass().getSimpleName()).getString());
} }
} }
@@ -241,14 +244,14 @@ public class ConfigManager {
module.setEnabled(config.moduleStates.get(module.getName())); module.setEnabled(config.moduleStates.get(module.getName()));
} }
}); });
Sputnik.LOGGER.info("estados de módulos aplicados"); Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.modulestates").getString());
} }
private void applyModuleSettings() { private void applyModuleSettings() {
ModuleManager.INSTANCE.getModules().forEach(module -> { ModuleManager.INSTANCE.getModules().forEach(module -> {
module.getSettings().forEach(this::applySetting); module.getSettings().forEach(this::applySetting);
}); });
Sputnik.LOGGER.info("ajustes de módulos aplicados"); Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.modulesettings").getString());
} }
private void applySettingsPanels() { private void applySettingsPanels() {
@@ -256,14 +259,14 @@ public class ConfigManager {
Module module = ModuleManager.INSTANCE.getModuleByName(moduleName); Module module = ModuleManager.INSTANCE.getModuleByName(moduleName);
if (module == null) { if (module == null) {
Sputnik.LOGGER.warn("\"null\" como módulo (\"{}\")", moduleName); Sputnik.LOGGER.warn(Component.translatable("sputnik.config.warn.nullmodule", moduleName).getString());
return; return;
} }
ClickGui.INSTANCE.openSettingsPanel(module, position[0], position[1]); ClickGui.INSTANCE.openSettingsPanel(module, position[0], position[1]);
}); });
Sputnik.LOGGER.info("estados de marcos de ajustes aplicados"); Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.settingspanels").getString());
} }
private void applySearchBarPosition() { private void applySearchBarPosition() {
@@ -271,13 +274,13 @@ public class ConfigManager {
ClickGui.INSTANCE.getSearchBar().setX(config.searchBarPosition[0]); ClickGui.INSTANCE.getSearchBar().setX(config.searchBarPosition[0]);
ClickGui.INSTANCE.getSearchBar().setY(config.searchBarPosition[1]); ClickGui.INSTANCE.getSearchBar().setY(config.searchBarPosition[1]);
} }
Sputnik.LOGGER.info("posición de la barra de búsqueda aplicada"); Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.searchbar").getString());
} }
private void applyClientSettings() { private void applyClientSettings() {
ClientSettingsPanel.clientSettings.setEnabled(true); ClientSettingsPanel.clientSettings.setEnabled(true);
ClientSettingsPanel.clientSettings.getSettings().forEach(this::applySetting); ClientSettingsPanel.clientSettings.getSettings().forEach(this::applySetting);
Sputnik.LOGGER.info("ajustes del cliente aplicados"); Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.clientsettings").getString());
} }
private void applyExtendablePanels() { private void applyExtendablePanels() {
@@ -287,7 +290,7 @@ public class ConfigManager {
applyExtendablePanel(ClickGui.INSTANCE.getClientSettingsPanel()); applyExtendablePanel(ClickGui.INSTANCE.getClientSettingsPanel());
applyExtendablePanel(ClickGui.INSTANCE.getFriendsPanel()); applyExtendablePanel(ClickGui.INSTANCE.getFriendsPanel());
Sputnik.LOGGER.info("posiciones de marcos extendibles aplicadas"); Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.extendablepanels").getString());
ClickGui.INSTANCE.refreshListButtons(); ClickGui.INSTANCE.refreshListButtons();
} }
@@ -308,14 +311,8 @@ public class ConfigManager {
panel.setX(panelData.x()); panel.setX(panelData.x());
panel.setY(panelData.y()); panel.setY(panelData.y());
if (panel instanceof ModulePanel mPanel) { if (panel instanceof ExtendablePanel<?> ePanel) {
mPanel.setExtended(panelData.extended()); ePanel.setExtended(panelData.extended());
}
if (panel instanceof ClientSettingsPanel sPanel) {
sPanel.setExtended(panelData.extended());
}
if (panel instanceof FriendsPanel fPanel) {
fPanel.setExtended(panelData.extended());
} }
} }
} }
@@ -444,7 +441,9 @@ public class ConfigManager {
long intervalMs = (long) (settings.autosaveInterval.getValue() * 1000); long intervalMs = (long) (settings.autosaveInterval.getValue() * 1000);
if (System.currentTimeMillis() - lastDirtyTime < intervalMs) return; if (System.currentTimeMillis() - lastDirtyTime < intervalMs) return;
HudRenderer.INSTANCE.pushNotification("autoguardando...", "guardando configuración..."); HudRenderer.INSTANCE.pushNotification(
Component.translatable("sputnik.config.autosaving.title").getString(),
Component.translatable("sputnik.config.autosaving.desc").getString());
save(); save();
dirty = false; dirty = false;
} }
@@ -8,6 +8,7 @@ import me.retucio.sputnik.module.modules.movement.Velocity;
import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.player.LocalPlayer;
import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource; import net.minecraft.sounds.SoundSource;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
@@ -61,8 +62,8 @@ public abstract class LivingEntityMixin {
if (step.isEnabled()) cir.setReturnValue(step.height.getFloatValue()); if (step.isEnabled()) cir.setReturnValue(step.height.getFloatValue());
} }
@Inject(method = "knockback", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setDeltaMovement(DDD)V"), cancellable = true) @Inject(method = "knockback(DDDLnet/minecraft/world/damagesource/DamageSource;FZ)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setDeltaMovement(DDD)V"), cancellable = true)
private void onTakeKb(double strength, double x, double z, CallbackInfo ci, @Local(name = "deltaMovement") Vec3 dm, @Local(name = "deltaVector") Vec3 dv) { private void onTakeKb(double strength, double x, double z, DamageSource source, float damage, boolean comesFromEffect, CallbackInfo ci, @Local(name = "deltaMovement") Vec3 dm, @Local(name = "deltaVector") Vec3 dv) {
Velocity velocity = ModuleManager.INSTANCE.getModuleByClass(Velocity.class); Velocity velocity = ModuleManager.INSTANCE.getModuleByClass(Velocity.class);
if (!velocity.isEnabled() || velocity.hits.getValue()) return; if (!velocity.isEnabled() || velocity.hits.getValue()) return;
boolean onGround = ((LivingEntity) (Object) this).onGround(); boolean onGround = ((LivingEntity) (Object) this).onGround();
@@ -83,7 +83,7 @@ public abstract class ChatComponentMixin implements IChatComponent {
@ModifyExpressionValue(method = "addMessageToDisplayQueue", at = @At(value = "NEW", target = "(Lnet/minecraft/client/multiplayer/chat/GuiMessage;Lnet/minecraft/util/FormattedCharSequence;Z)Lnet/minecraft/client/multiplayer/chat/GuiMessage$Line;")) @ModifyExpressionValue(method = "addMessageToDisplayQueue", at = @At(value = "NEW", target = "(Lnet/minecraft/client/multiplayer/chat/GuiMessage;Lnet/minecraft/util/FormattedCharSequence;Z)Lnet/minecraft/client/multiplayer/chat/GuiMessage$Line;"))
private GuiMessage.Line onAddMessage_modifyChatHudLineVisible(GuiMessage.Line line, @Local(name = "i") int i) { private GuiMessage.Line onAddMessage_modifyChatHudLineVisible(GuiMessage.Line line, @Local(name = "i") int i) {
IChatListener iListener = (IChatListener) Sputnik.mc.getChatListener(); IChatListener iListener = (IChatListener) Sputnik.mc.gui.chatListener();
IGuiMessageLine iLine = (IGuiMessageLine) (Object) line; IGuiMessageLine iLine = (IGuiMessageLine) (Object) line;
iLine.sputnik$setSender(iListener.sputnik$getSender()); iLine.sputnik$setSender(iListener.sputnik$getSender());
@@ -94,7 +94,7 @@ public abstract class ChatComponentMixin implements IChatComponent {
@ModifyExpressionValue(method = "addMessage", at = @At(value = "NEW", target = "(ILnet/minecraft/network/chat/Component;Lnet/minecraft/network/chat/MessageSignature;Lnet/minecraft/client/multiplayer/chat/GuiMessageSource;Lnet/minecraft/client/multiplayer/chat/GuiMessageTag;)Lnet/minecraft/client/multiplayer/chat/GuiMessage;")) @ModifyExpressionValue(method = "addMessage", at = @At(value = "NEW", target = "(ILnet/minecraft/network/chat/Component;Lnet/minecraft/network/chat/MessageSignature;Lnet/minecraft/client/multiplayer/chat/GuiMessageSource;Lnet/minecraft/client/multiplayer/chat/GuiMessageTag;)Lnet/minecraft/client/multiplayer/chat/GuiMessage;"))
private GuiMessage onAddMessage_modifyChatHudLine(GuiMessage line) { private GuiMessage onAddMessage_modifyChatHudLine(GuiMessage line) {
IChatListener iListener = (IChatListener) Sputnik.mc.getChatListener(); IChatListener iListener = (IChatListener) Sputnik.mc.gui.chatListener();
((IGuiMessage) (Object) line).sputnik$setSender(iListener.sputnik$getSender()); ((IGuiMessage) (Object) line).sputnik$setSender(iListener.sputnik$getSender());
return line; return line;
} }
@@ -1,107 +1,21 @@
package me.retucio.sputnik.mixin.mixins.hud; package me.retucio.sputnik.mixin.mixins.hud;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.sugar.Local;
import com.mojang.blaze3d.pipeline.RenderPipeline;
import me.retucio.sputnik.Sputnik; import me.retucio.sputnik.Sputnik;
import me.retucio.sputnik.event.render.Render2DEvent; import me.retucio.sputnik.event.interact.OpenScreenEvent;
import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.camera.CrosshairPlus;
import me.retucio.sputnik.module.modules.misc.ChatPlus;
import me.retucio.sputnik.module.modules.camera.Freecam;
import me.retucio.sputnik.module.modules.render.NoRender;
import me.retucio.sputnik.ui.hud.HudRenderer;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.renderer.RenderPipelines;
import net.minecraft.resources.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.ModifyArgs;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.invoke.arg.Args;
// lo del hud se mudó a HudMixin; Gui ya sólo lleva las pantallas
@Mixin(Gui.class) @Mixin(Gui.class)
public abstract class GuiMixin { public abstract class GuiMixin {
@Unique @Inject(method = "setScreen", at = @At("HEAD"), cancellable = true)
NoRender noRender; private void onOpenScreen(Screen screen, CallbackInfo ci) {
OpenScreenEvent event = Sputnik.EVENT_BUS.post(new OpenScreenEvent(screen));
@Inject(method = "<init>", at = @At("TAIL")) if (event.isCancelled()) ci.cancel();
private void getModules(CallbackInfo ci) {
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
}
@Inject(method = "extractRenderState", at = @At("TAIL"))
private void onRenderHud(GuiGraphicsExtractor gui, DeltaTracker dt, CallbackInfo ci) {
Sputnik.EVENT_BUS.post(new Render2DEvent(gui, dt));
}
// norender
@Inject(method = "extractScoreboardSidebar", at = @At("HEAD"), cancellable = true)
private void noRenderScoreboard(CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.scoreboard.getValue()) ci.cancel();
}
@Inject(method = "extractTitle", at = @At("HEAD"), cancellable = true)
private void noRenderTitles(GuiGraphicsExtractor graphics, DeltaTracker deltaTracker, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.titles.getValue()) ci.cancel();
}
@Inject(method = "extractConfusionOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderNausea(GuiGraphicsExtractor graphics, float strength, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.nauseaEffect.getValue()) ci.cancel();
}
@Inject(method = "extractSpyglassOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderSpyglass(GuiGraphicsExtractor graphics, float scale, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.spyglassOverlay.getValue()) ci.cancel();
}
@Inject(method = "extractPortalOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderPortal(GuiGraphicsExtractor graphics, float alpha, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.portalOverlay.getValue()) ci.cancel();
}
@Inject(method = "extractTextureOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderPumpkinBlur(GuiGraphicsExtractor graphics, Identifier texture, float alpha, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.pumpkinOverlay.getValue() && texture.getPath().equals("textures/misc/pumpkinblur.png")) ci.cancel();
}
// otros
@Inject(method = "extractRenderState", at = @At("RETURN"))
private void renderHUD(GuiGraphicsExtractor gui, DeltaTracker dt, CallbackInfo ci) {
HudRenderer.INSTANCE.render(gui, dt);
}
@Redirect(method = "extractCrosshair", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;blitSprite(Lcom/mojang/blaze3d/pipeline/RenderPipeline;Lnet/minecraft/resources/Identifier;IIII)V", ordinal = 0))
private void onRenderCrosshair(GuiGraphicsExtractor gui, RenderPipeline pipeline, Identifier id, int x, int y, int width, int height) {
// dangerous abbreviation
CrosshairPlus cp = ModuleManager.INSTANCE.getModuleByClass(CrosshairPlus.class);
int color = cp.isEnabled() ? cp.color.getRGB() : -1;
int w = cp.isEnabled() ? cp.width.getIntValue() : width;
int h = cp.isEnabled() ? cp.height.getIntValue() : height;
gui.blitSprite(pipeline, id, (gui.guiWidth() - w) / 2, (gui.guiHeight() - h) / 2, w, h, color);
}
@ModifyExpressionValue(method = "extractCrosshair", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/CameraType;isFirstPerson()Z"))
private boolean alwaysRenderCrosshairInFreecam(boolean firstPerson) {
return ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled() || firstPerson;
}
@Inject(method = "onDisconnected", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/components/ChatComponent;clearMessages(Z)V"), cancellable = true)
private void onClear(CallbackInfo ci) {
ChatPlus chatPlus = ModuleManager.INSTANCE.getModuleByClass(ChatPlus.class);
if (chatPlus.isEnabled() && chatPlus.keepHistory.getValue()) ci.cancel();
} }
} }
@@ -0,0 +1,104 @@
package me.retucio.sputnik.mixin.mixins.hud;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.mojang.blaze3d.pipeline.RenderPipeline;
import me.retucio.sputnik.Sputnik;
import me.retucio.sputnik.event.render.Render2DEvent;
import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.camera.CrosshairPlus;
import me.retucio.sputnik.module.modules.misc.ChatPlus;
import me.retucio.sputnik.module.modules.camera.Freecam;
import me.retucio.sputnik.module.modules.render.NoRender;
import me.retucio.sputnik.ui.hud.HudRenderer;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.gui.GuiGraphicsExtractor;
import net.minecraft.client.gui.Hud;
import net.minecraft.resources.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
// 26.2 partió Gui en Gui (pantallas) y Hud (el hud en sí); todo esto vivía en GuiMixin
@Mixin(Hud.class)
public abstract class HudMixin {
@Unique
NoRender noRender;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(CallbackInfo ci) {
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
}
@Inject(method = "extractRenderState", at = @At("TAIL"))
private void onRenderHud(GuiGraphicsExtractor gui, DeltaTracker dt, CallbackInfo ci) {
Sputnik.EVENT_BUS.post(new Render2DEvent(gui, dt));
}
// norender
@Inject(method = "extractScoreboardSidebar", at = @At("HEAD"), cancellable = true)
private void noRenderScoreboard(CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.scoreboard.getValue()) ci.cancel();
}
@Inject(method = "extractTitle", at = @At("HEAD"), cancellable = true)
private void noRenderTitles(GuiGraphicsExtractor graphics, DeltaTracker deltaTracker, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.titles.getValue()) ci.cancel();
}
@Inject(method = "extractConfusionOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderNausea(GuiGraphicsExtractor graphics, float strength, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.nauseaEffect.getValue()) ci.cancel();
}
@Inject(method = "extractSpyglassOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderSpyglass(GuiGraphicsExtractor graphics, float scale, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.spyglassOverlay.getValue()) ci.cancel();
}
@Inject(method = "extractPortalOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderPortal(GuiGraphicsExtractor graphics, float alpha, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.portalOverlay.getValue()) ci.cancel();
}
@Inject(method = "extractTextureOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderPumpkinBlur(GuiGraphicsExtractor graphics, Identifier texture, float alpha, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.pumpkinOverlay.getValue() && texture.getPath().equals("textures/misc/pumpkinblur.png")) ci.cancel();
}
// otros
@Inject(method = "extractRenderState", at = @At("RETURN"))
private void renderHUD(GuiGraphicsExtractor gui, DeltaTracker dt, CallbackInfo ci) {
HudRenderer.INSTANCE.render(gui, dt);
}
@Redirect(method = "extractCrosshair", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;blitSprite(Lcom/mojang/blaze3d/pipeline/RenderPipeline;Lnet/minecraft/resources/Identifier;IIII)V", ordinal = 0))
private void onRenderCrosshair(GuiGraphicsExtractor gui, RenderPipeline pipeline, Identifier id, int x, int y, int width, int height) {
// dangerous abbreviation
CrosshairPlus cp = ModuleManager.INSTANCE.getModuleByClass(CrosshairPlus.class);
int color = cp.isEnabled() ? cp.color.getRGB() : -1;
int w = cp.isEnabled() ? cp.width.getIntValue() : width;
int h = cp.isEnabled() ? cp.height.getIntValue() : height;
gui.blitSprite(pipeline, id, (gui.guiWidth() - w) / 2, (gui.guiHeight() - h) / 2, w, h, color);
}
@ModifyExpressionValue(method = "extractCrosshair", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/CameraType;isFirstPerson()Z"))
private boolean alwaysRenderCrosshairInFreecam(boolean firstPerson) {
return ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled() || firstPerson;
}
@Inject(method = "onDisconnected", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/components/ChatComponent;clearMessages(Z)V"), cancellable = true)
private void onClear(CallbackInfo ci) {
ChatPlus chatPlus = ModuleManager.INSTANCE.getModuleByClass(ChatPlus.class);
if (chatPlus.isEnabled() && chatPlus.keepHistory.getValue()) ci.cancel();
}
}
@@ -27,13 +27,13 @@ public abstract class ItemMixin {
if (stack.getItem() instanceof BlockItem blockItem && blockItem.getBlock() instanceof ShulkerBoxBlock) { if (stack.getItem() instanceof BlockItem blockItem && blockItem.getBlock() instanceof ShulkerBoxBlock) {
if (ShulkerPeek.isShulkerEmpty(stack)) { if (ShulkerPeek.isShulkerEmpty(stack)) {
builder.accept(Component.literal("vacío").withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC)); builder.accept(Component.translatable("sputnik.module.shulkerpeek.empty")
.withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC));
} else { } else {
builder.accept( builder.accept(
Component.literal("mantén ") Component.translatable("sputnik.module.shulkerpeek.holdtopreview",
.append(Component.literal(shulkerPeek.previewKey.getKeyName()) Component.literal(shulkerPeek.previewKey.getKeyName())
.withStyle(ChatFormatting.GOLD, ChatFormatting.BOLD)) .withStyle(ChatFormatting.GOLD, ChatFormatting.BOLD))
.append(" para previsualizar")
.withStyle(ChatFormatting.GRAY) .withStyle(ChatFormatting.GRAY)
); );
} }
@@ -38,9 +38,6 @@ public abstract class MinecraftMixin {
// eventos // eventos
@Shadow @Nullable
public Screen screen;
@Shadow @Shadow
public abstract @Nullable Entity getCameraEntity(); public abstract @Nullable Entity getCameraEntity();
@@ -63,12 +60,6 @@ public abstract class MinecraftMixin {
Sputnik.EVENT_BUS.post(new ShutdownEvent()); Sputnik.EVENT_BUS.post(new ShutdownEvent());
} }
@Inject(method = "setScreen", at = @At("HEAD"), cancellable = true)
private void onOpenScreen(Screen screen, CallbackInfo ci) {
OpenScreenEvent event = Sputnik.EVENT_BUS.post(new OpenScreenEvent(screen));
if (event.isCancelled()) ci.cancel();
}
@Inject(method = "setLevel", at = @At("HEAD"), cancellable = true) @Inject(method = "setLevel", at = @At("HEAD"), cancellable = true)
private void onJoinWorld(ClientLevel level, CallbackInfo ci) { private void onJoinWorld(ClientLevel level, CallbackInfo ci) {
JoinWorldEvent event = Sputnik.EVENT_BUS.post(new JoinWorldEvent(level)); JoinWorldEvent event = Sputnik.EVENT_BUS.post(new JoinWorldEvent(level));
@@ -46,7 +46,7 @@ public abstract class ClientCommonPacketListenerImplMixin {
final Screen screen = cir.getReturnValue(); final Screen screen = cir.getReturnValue();
((IConfirmScreen) screen).sputnik$setBypassAction(() -> { ((IConfirmScreen) screen).sputnik$setBypassAction(() -> {
minecraft.setScreen(((PackConfirmScreenAccessor) screen).getParentScreen()); minecraft.gui.setScreen(((PackConfirmScreenAccessor) screen).getParentScreen());
if (serverData != null) { if (serverData != null) {
serverData.setResourcePackStatus(bypassPack.getStatus()); serverData.setResourcePackStatus(bypassPack.getStatus());
minecraft.getDownloadedPackSource().allowServerPacks(); minecraft.getDownloadedPackSource().allowServerPacks();
@@ -48,7 +48,7 @@ public abstract class ClientPacketListenerMixin {
ChatUtil.error(e.getMessage()); ChatUtil.error(e.getMessage());
} }
mc.gui.getChat().addRecentChat(content); mc.gui.hud.getChat().addRecentChat(content);
ci.cancel(); ci.cancel();
} }
@@ -12,7 +12,6 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.objectweb.asm.Opcodes;
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.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -28,7 +27,7 @@ public abstract class LocalPlayerMixin {
throw new UnsupportedOperationException("Implemented via mixin"); throw new UnsupportedOperationException("Implemented via mixin");
} }
@ModifyExpressionValue(method = "handlePortalTransitionEffect", at = @At(value = "FIELD", target = "Lnet/minecraft/client/Minecraft;screen:Lnet/minecraft/client/gui/screens/Screen;", opcode = Opcodes.GETFIELD)) @ModifyExpressionValue(method = "handlePortalTransitionEffect", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/Gui;screen()Lnet/minecraft/client/gui/screens/Screen;"))
private Screen allowScreensInPortals(Screen original) { private Screen allowScreensInPortals(Screen original) {
if (ModuleManager.INSTANCE.getModuleByClass(PortalGUI.class).isEnabled()) return null; if (ModuleManager.INSTANCE.getModuleByClass(PortalGUI.class).isEnabled()) return null;
return original; return original;
@@ -1,5 +1,6 @@
package me.retucio.sputnik.mixin.mixins.render; package me.retucio.sputnik.mixin.mixins.render;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.ModifyReturnValue; import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import me.retucio.sputnik.Sputnik; import me.retucio.sputnik.Sputnik;
import me.retucio.sputnik.event.render.GetFOVEvent; import me.retucio.sputnik.event.render.GetFOVEvent;
@@ -78,6 +79,13 @@ public abstract class CameraMixin {
if (freecam.isEnabled()) this.detached = true; if (freecam.isEnabled()) this.detached = true;
} }
// el culling inteligente se desactiva estando en espectador dentro de un bloque sólido,
// así el terreno se sigue renderizando con la cámara metida en bloques
@ModifyExpressionValue(method = "extractRenderState", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;isSpectator()Z"))
private boolean noSmartCullFreecam(boolean original) {
return freecam.isEnabled() || original;
}
@ModifyArgs(method = "alignWithEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;setPosition(DDD)V")) @ModifyArgs(method = "alignWithEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;setPosition(DDD)V"))
private void onUpdateSetPosArgs(Args args) { private void onUpdateSetPosArgs(Args args) {
if (freecam.isEnabled()) { if (freecam.isEnabled()) {
@@ -14,7 +14,6 @@ import net.minecraft.client.DeltaTracker;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.ItemInHandRenderer; import net.minecraft.client.renderer.ItemInHandRenderer;
import net.minecraft.client.renderer.RenderBuffers;
import net.minecraft.client.renderer.state.level.CameraRenderState; import net.minecraft.client.renderer.state.level.CameraRenderState;
import net.minecraft.client.resources.model.ModelManager; import net.minecraft.client.resources.model.ModelManager;
import org.joml.Matrix4fc; import org.joml.Matrix4fc;
@@ -44,7 +43,7 @@ public abstract class GameRendererMixin {
private Minecraft minecraft; private Minecraft minecraft;
@Inject(method = "<init>", at = @At("TAIL")) @Inject(method = "<init>", at = @At("TAIL"))
private void getModules(Minecraft minecraft, ItemInHandRenderer itemInHandRenderer, RenderBuffers renderBuffers, ModelManager modelManager, CallbackInfo ci) { private void getModules(Minecraft minecraft, ItemInHandRenderer itemInHandRenderer, ModelManager modelManager, 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); noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
@@ -15,21 +15,14 @@ public abstract class ItemFeatureRendererMixin {
// obtener módulo en cada redirect, ya que tiene un inicializador estático // obtener módulo en cada redirect, ya que tiene un inicializador estático
@Redirect(method = "getFoilRenderType", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/rendertype/RenderTypes;glint()Lnet/minecraft/client/renderer/rendertype/RenderType;")) @Redirect(method = "getFoilBuffer", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/rendertype/RenderTypes;glint()Lnet/minecraft/client/renderer/rendertype/RenderType;"))
private static RenderType redirectGlint() { private static RenderType redirectGlint() {
GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class); GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class);
if (glintPlus == null) return RenderTypes.glint(); if (glintPlus == null) return RenderTypes.glint();
return glintPlus.getGlint(); return glintPlus.getGlint();
} }
@Redirect(method = "getFoilRenderType", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/rendertype/RenderTypes;entityGlint()Lnet/minecraft/client/renderer/rendertype/RenderType;")) @Redirect(method = "getFoilBuffer", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/rendertype/RenderTypes;glintTranslucent()Lnet/minecraft/client/renderer/rendertype/RenderType;"))
private static RenderType redirectEntityGlint() {
GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class);
if (glintPlus == null) return RenderTypes.entityGlint();
return glintPlus.getEntityGlint();
}
@Redirect(method = "getFoilRenderType", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/rendertype/RenderTypes;glintTranslucent()Lnet/minecraft/client/renderer/rendertype/RenderType;"))
private static RenderType redirectGlintTranslucent() { private static RenderType redirectGlintTranslucent() {
GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class); GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class);
if (glintPlus == null) return RenderTypes.glintTranslucent(); if (glintPlus == null) return RenderTypes.glintTranslucent();
@@ -49,12 +49,12 @@ public abstract class ItemInHandRendererMixin {
handView = ModuleManager.INSTANCE.getModuleByClass(HandView.class); handView = ModuleManager.INSTANCE.getModuleByClass(HandView.class);
} }
@Inject(method = "renderArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;renderItem(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemDisplayContext;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;I)V", shift = At.Shift.BEFORE)) @Inject(method = "submitArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;renderItem(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemDisplayContext;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;I)V", shift = At.Shift.BEFORE))
private void onRenderItem(AbstractClientPlayer player, float frameInterp, float xRot, InteractionHand hand, float attack, ItemStack itemStack, float inverseArmHeight, PoseStack matrices, SubmitNodeCollector submitNodeCollector, int lightCoords, CallbackInfo ci) { private void onRenderItem(AbstractClientPlayer player, float frameInterp, float xRot, InteractionHand hand, float attack, ItemStack itemStack, float inverseArmHeight, PoseStack matrices, SubmitNodeCollector submitNodeCollector, int lightCoords, CallbackInfo ci) {
EVENT_BUS.post(new RenderHeldItemEvent(matrices, hand)); EVENT_BUS.post(new RenderHeldItemEvent(matrices, hand));
} }
@Inject(method = "renderArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;renderPlayerArm(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;IFFLnet/minecraft/world/entity/HumanoidArm;)V")) @Inject(method = "submitArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;renderPlayerArm(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;IFFLnet/minecraft/world/entity/HumanoidArm;)V"))
private void onRenderArm(AbstractClientPlayer player, float frameInterp, float xRot, InteractionHand hand, float attack, ItemStack itemStack, float inverseArmHeight, PoseStack matrices, SubmitNodeCollector submitNodeCollector, int lightCoords, CallbackInfo ci) { private void onRenderArm(AbstractClientPlayer player, float frameInterp, float xRot, InteractionHand hand, float attack, ItemStack itemStack, float inverseArmHeight, PoseStack matrices, SubmitNodeCollector submitNodeCollector, int lightCoords, CallbackInfo ci) {
EVENT_BUS.post(new RenderArmEvent(matrices, hand)); EVENT_BUS.post(new RenderArmEvent(matrices, hand));
} }
@@ -12,8 +12,7 @@ import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.camera.Freecam; import me.retucio.sputnik.module.modules.camera.Freecam;
import net.minecraft.client.DeltaTracker; import net.minecraft.client.DeltaTracker;
import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.SubmitNodeCollector;
import net.minecraft.client.renderer.chunk.ChunkSectionsToRender;
import net.minecraft.client.renderer.state.level.CameraRenderState; import net.minecraft.client.renderer.state.level.CameraRenderState;
import net.minecraft.client.renderer.state.level.LevelRenderState; import net.minecraft.client.renderer.state.level.LevelRenderState;
import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.util.profiling.ProfilerFiller;
@@ -31,14 +30,8 @@ import static me.retucio.sputnik.Sputnik.mc;
@Mixin(LevelRenderer.class) @Mixin(LevelRenderer.class)
public abstract class LevelRendererMixin { public abstract class LevelRendererMixin {
// renderLevel()?? @Inject(method = "render", at = @At("RETURN"))
@ModifyArg(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;cullTerrain(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/culling/Frustum;Z)V"), index = 2) private void render(GraphicsResourceAllocator resourceAllocator, DeltaTracker dt, boolean renderOutline, CameraRenderState cameraState, Matrix4fc modelViewMatrix, GpuBufferSlice terrainFog, Vector4f fogColor, boolean shouldRenderSky, CallbackInfo ci, @Local(name = "profiler") ProfilerFiller profiler) {
private boolean renderSetupTerrainModifyArg(boolean spectator) {
return ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled() || spectator;
}
@Inject(method = "renderLevel", at = @At("RETURN"))
private void render(GraphicsResourceAllocator resourceAllocator, DeltaTracker dt, boolean renderOutline, CameraRenderState cameraState, Matrix4fc modelViewMatrix, GpuBufferSlice terrainFog, Vector4f fogColor, boolean shouldRenderSky, ChunkSectionsToRender chunkSectionsToRender, CallbackInfo ci, @Local(name = "profiler") ProfilerFiller profiler) {
if (mc == null || mc.level == null) return; if (mc == null || mc.level == null) return;
PoseStack matrices = new PoseStack(); PoseStack matrices = new PoseStack();
@@ -54,8 +47,8 @@ public abstract class LevelRendererMixin {
matrices.popPose(); matrices.popPose();
} }
@Inject(method = "renderBlockOutline", at = @At("HEAD"), cancellable = true) @Inject(method = "submitBlockOutline", at = @At("HEAD"), cancellable = true)
private void noRenderBlockOutlinesFreecam(MultiBufferSource.BufferSource bufferSource, PoseStack poseStack, boolean onlyTranslucentBlocks, LevelRenderState levelRenderState, CallbackInfo ci) { private void noRenderBlockOutlinesFreecam(PoseStack poseStack, SubmitNodeCollector collector, LevelRenderState levelRenderState, CallbackInfo ci) {
Freecam freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); Freecam freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
if (freecam.isEnabled() && !freecam.blockOutlines.getValue()) ci.cancel(); if (freecam.isEnabled() && !freecam.blockOutlines.getValue()) ci.cancel();
} }
@@ -68,13 +61,13 @@ public abstract class LevelRendererMixin {
// } // }
// puto mojang con sus nombres confusos // puto mojang con sus nombres confusos
@ModifyArgs(method = "renderBlockOutline", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;renderHitOutline(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;DDDLnet/minecraft/client/renderer/state/level/BlockOutlineRenderState;IF)V")) @ModifyArgs(method = "submitBlockOutline", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;submitHitOutline(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/rendertype/RenderType;Lnet/minecraft/client/renderer/state/level/BlockOutlineRenderState;IFZ)V"))
private void modifyBlockOutline(Args args) { private void modifyBlockOutline(Args args) {
// SIX SEVEN!!! (me pegan en casa) // ahora cuatro cinco... (rip 67)
RenderBlockOutlineEvent event = EVENT_BUS.post(new RenderBlockOutlineEvent(args.get(6), args.get(7))); RenderBlockOutlineEvent event = EVENT_BUS.post(new RenderBlockOutlineEvent(args.get(4), args.get(5)));
if (event.getColor() != (int) args.get(6)) if (event.getColor() != (int) args.get(4))
args.set(6, event.getColor()); args.set(4, event.getColor());
if (event.getLineWidth() != (float) args.get(7)) if (event.getLineWidth() != (float) args.get(5))
args.set(7, event.getLineWidth()); args.set(5, event.getLineWidth());
} }
} }
@@ -31,7 +31,7 @@ public abstract class LightmapMixin {
profiler.push("lightmap"); profiler.push("lightmap");
RenderSystem.getDevice().createCommandEncoder() RenderSystem.getDevice().createCommandEncoder()
.clearColorTexture(texture, ARGB.color(255, 255, 255, 255)); .clearColorTexture(texture, ARGB.vector4fFromARGB32(ARGB.color(255, 255, 255, 255)));
profiler.pop(); profiler.pop();
ci.cancel(); ci.cancel();
@@ -9,6 +9,7 @@ import me.retucio.sputnik.module.modules.render.Nametags;
import net.minecraft.client.renderer.entity.LivingEntityRenderer; import net.minecraft.client.renderer.entity.LivingEntityRenderer;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@@ -50,7 +51,7 @@ public abstract class LivingEntityRendererMixin<T extends LivingEntity> {
@ModifyReturnValue(method = "shouldShowName(Lnet/minecraft/world/entity/LivingEntity;D)Z", at = @At("RETURN")) @ModifyReturnValue(method = "shouldShowName(Lnet/minecraft/world/entity/LivingEntity;D)Z", at = @At("RETURN"))
private boolean shouldRenderPlayerNametag(boolean original, @Local(argsOnly = true) T livingEntity) { private boolean shouldRenderPlayerNametag(boolean original, @Local(argsOnly = true) T livingEntity) {
if (nametags.isEnabled() && livingEntity instanceof Player) if (nametags.isEnabled() && livingEntity instanceof Player)
return nametags.entities.isEnabled(EntityType.PLAYER) && original; return nametags.entities.isEnabled(EntityTypes.PLAYER) && original;
return original; return original;
} }
@@ -1,25 +1,18 @@
package me.retucio.sputnik.mixin.mixins.render; package me.retucio.sputnik.mixin.mixins.render;
import com.mojang.blaze3d.vertex.ByteBufferBuilder; import me.retucio.sputnik.util.render.SputnikBuffers;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import me.retucio.sputnik.util.render.GlintRenderType;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderBuffers; import net.minecraft.client.renderer.RenderBuffers;
import net.minecraft.client.renderer.rendertype.RenderType;
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.Redirect; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.SequencedMap;
@Mixin(RenderBuffers.class) @Mixin(RenderBuffers.class)
public abstract class RenderBuffersMixin { public abstract class RenderBuffersMixin {
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/MultiBufferSource;immediateWithBuffers(Ljava/util/SequencedMap;Lcom/mojang/blaze3d/vertex/ByteBufferBuilder;)Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;", ordinal = 0)) // devolvemos nuestros buffers al pool cuando el juego hace lo propio
private MultiBufferSource.BufferSource injectGlintBuffers(SequencedMap<RenderType, ByteBufferBuilder> fixedBuffers, ByteBufferBuilder sharedBuffer) { @Inject(method = "endFrame", at = @At("TAIL"))
if (fixedBuffers instanceof Object2ObjectLinkedOpenHashMap<RenderType, ByteBufferBuilder> map) { private void endSputnikFrame(CallbackInfo ci) {
GlintRenderType.addGlintTypes(map); SputnikBuffers.endFrame();
}
return MultiBufferSource.immediateWithBuffers(fixedBuffers, sharedBuffer);
} }
} }
@@ -4,8 +4,8 @@ import com.mojang.blaze3d.vertex.PoseStack;
import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.render.NoRender; import me.retucio.sputnik.module.modules.render.NoRender;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.ScreenEffectRenderer; import net.minecraft.client.renderer.ScreenEffectRenderer;
import net.minecraft.client.renderer.SubmitNodeCollector;
import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
@@ -25,13 +25,13 @@ public abstract class ScreenEffectRendererMixin {
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
} }
@Inject(method = "renderFire", at = @At("HEAD"), cancellable = true) @Inject(method = "submitFire", at = @At("HEAD"), cancellable = true)
private static void noRenderFireOverlay(PoseStack matrices, MultiBufferSource bufferSource, TextureAtlasSprite sprite, CallbackInfo ci) { private static void noRenderFireOverlay(PoseStack matrices, SubmitNodeCollector collector, TextureAtlasSprite sprite, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.fireOverlay.getValue()) ci.cancel(); if (noRender.isEnabled() && !noRender.fireOverlay.getValue()) ci.cancel();
} }
@Inject(method = "renderWater", at = @At("HEAD"), cancellable = true) @Inject(method = "submitWater", at = @At("HEAD"), cancellable = true)
private static void noRenderUnderwaterOverlay(Minecraft minecraft, PoseStack matrices, MultiBufferSource bufferSource, CallbackInfo ci) { private static void noRenderUnderwaterOverlay(Minecraft minecraft, PoseStack matrices, SubmitNodeCollector collector, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.fluidOverlay.getValue()) ci.cancel(); if (noRender.isEnabled() && !noRender.fluidOverlay.getValue()) ci.cancel();
} }
} }
@@ -2,11 +2,8 @@ package me.retucio.sputnik.mixin.mixins.render;
import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.render.NoRender; import me.retucio.sputnik.module.modules.render.NoRender;
import net.minecraft.client.Camera;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.WeatherEffectRenderer; import net.minecraft.client.renderer.WeatherEffectRenderer;
import net.minecraft.client.renderer.state.level.WeatherRenderState; import net.minecraft.client.renderer.state.level.WeatherRenderState;
import net.minecraft.server.level.ParticleStatus;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
@@ -26,11 +23,6 @@ public abstract class WeatherEffectRendererMixin {
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
} }
@Inject(method = "tickRainParticles", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientLevel;addParticle(Lnet/minecraft/core/particles/ParticleOptions;DDDDDD)V"), cancellable = true)
private void noRainParticles(ClientLevel level, Camera camera, int ticks, ParticleStatus particleStatus, int weatherRadius, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.rain.getValue()) ci.cancel();
}
@Inject(method = "render", at = @At("HEAD")) @Inject(method = "render", at = @At("HEAD"))
private void noRenderRainAndSnow(Vec3 cameraPos, WeatherRenderState renderState, CallbackInfo ci) { private void noRenderRainAndSnow(Vec3 cameraPos, WeatherRenderState renderState, CallbackInfo ci) {
if (noRender.isEnabled()) { if (noRender.isEnabled()) {
@@ -33,14 +33,14 @@ public abstract class AbstractContainerScreenMixin {
int by = bgTop - bh - 5; int by = bgTop - bh - 5;
if (burglar.showStealButton.getValue()) { if (burglar.showStealButton.getValue()) {
Button stealButton = Button.builder(Component.literal("robar"), bnutton -> { Button stealButton = Button.builder(Component.translatable("sputnik.module.burglar.steal"), bnutton -> {
burglar.steal(screen); burglar.steal(screen);
}).bounds(bx, by, bw, bh).build(); }).bounds(bx, by, bw, bh).build();
screen.addRenderableWidget(stealButton); screen.addRenderableWidget(stealButton);
} }
if (burglar.showDumpButton.getValue()) { if (burglar.showDumpButton.getValue()) {
Button dumpButton = Button.builder(Component.literal("dejar"), button -> { Button dumpButton = Button.builder(Component.translatable("sputnik.module.burglar.dump"), button -> {
burglar.dump(screen); burglar.dump(screen);
}).bounds(bx + bw + gap, by, bw, bh).build(); }).bounds(bx + bw + gap, by, bw, bh).build();
screen.addRenderableWidget(dumpButton); screen.addRenderableWidget(dumpButton);
@@ -27,7 +27,7 @@ public abstract class DisconnectedScreenMixin {
if (reconnect == null || !reconnect.isEnabled()) return; if (reconnect == null || !reconnect.isEnabled()) return;
layout.addChild(Button.builder( layout.addChild(Button.builder(
Component.literal("reconectarse"), Component.translatable("sputnik.module.reconnect.button"),
button -> reconnect.reconnect() button -> reconnect.reconnect()
).build()); ).build());
} }
@@ -2,6 +2,8 @@ package me.retucio.sputnik.mixin.mixins.world;
import me.retucio.sputnik.event.network.AddEntityEvent; import me.retucio.sputnik.event.network.AddEntityEvent;
import me.retucio.sputnik.event.network.RemoveEntityEvent; import me.retucio.sputnik.event.network.RemoveEntityEvent;
import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.render.NoRender;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -29,4 +31,11 @@ public abstract class ClientLevelMixin {
Entity entity = getEntity(entityId); Entity entity = getEntity(entityId);
if (entity != null) EVENT_BUS.post(new RemoveEntityEvent(entity)); if (entity != null) EVENT_BUS.post(new RemoveEntityEvent(entity));
} }
// las partículas de lluvia se generan aquí desde 26.2, antes en WeatherEffectRenderer
@Inject(method = "tickWeatherEffects", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientLevel;addParticle(Lnet/minecraft/core/particles/ParticleOptions;DDDDDD)V"), cancellable = true)
private void noRainParticles(CallbackInfo ci) {
NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
if (noRender.isEnabled() && !noRender.rain.getValue()) ci.cancel();
}
} }
@@ -1,5 +1,7 @@
package me.retucio.sputnik.module; package me.retucio.sputnik.module;
import me.retucio.sputnik.util.I18nUtil;
public enum Category { public enum Category {
COMBAT("combate"), COMBAT("combate"),
@@ -19,5 +21,12 @@ public enum Category {
private final String name; private final String name;
Category(String name) { this.name = name; } Category(String name) { this.name = name; }
// OJO: toString() es la clave de la config. (ConfigManager#applyExtendablePanel guarda los
// marcos por categoría). no se traduce; para mostrarla usar getDisplayName()
@Override public String toString() { return name; } @Override public String toString() { return name; }
public String getDisplayName() {
return I18nUtil.orElse("sputnik.category." + I18nUtil.slug(name), name);
}
} }
@@ -11,7 +11,9 @@ import me.retucio.sputnik.module.setting.settings.KeySetting;
import me.retucio.sputnik.module.setting.Setting; import me.retucio.sputnik.module.setting.Setting;
import me.retucio.sputnik.ui.hud.HudRenderer; import me.retucio.sputnik.ui.hud.HudRenderer;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import me.retucio.sputnik.util.I18nUtil;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@@ -33,34 +35,36 @@ public class Module {
// ajustes que están en todos los módulos // ajustes que están en todos los módulos
// estos cuatro están en los 93 módulos, así que comparten clave en vez de derivar una por módulo
protected KeySetting bind = new KeySetting( protected KeySetting bind = new KeySetting(
"tecla", "tecla",
"tecla asignada al módulo, ESC para desactivar", "tecla asignada al módulo, ESC para desactivar",
GLFW.GLFW_KEY_UNKNOWN GLFW.GLFW_KEY_UNKNOWN
); ).translationKey("sputnik.setting.common.bind");
// 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<KeyMode> keyMode = new EnumSetting<>( protected EnumSetting<KeyMode> keyMode = new EnumSetting<KeyMode>(
"modo de tecla", "modo de tecla",
"cómo interpretar la tecla configurada", "cómo interpretar la tecla configurada",
KeyMode.class, KeyMode.TOGGLE KeyMode.class, KeyMode.TOGGLE
); ).translationKey("sputnik.setting.common.keymode");
protected BooleanSetting notify = new BooleanSetting( protected BooleanSetting notify = new BooleanSetting(
"notificar", "notificar",
"notificar al activar / desactivar", "notificar al activar / desactivar",
true true
); ).translationKey("sputnik.setting.common.notify");
protected EnumSetting<NotifyMode> notifyMode = new EnumSetting<>( protected EnumSetting<NotifyMode> notifyMode = new EnumSetting<NotifyMode>(
"modo de notificación", "modo de notificación",
"cómo notificar cuando se activa / desactiva", "cómo notificar cuando se activa / desactiva",
NotifyMode.class, NotifyMode.WIDGET NotifyMode.class, NotifyMode.WIDGET
); ).translationKey("sputnik.setting.common.notifymode");
protected final List<SettingGroup> sgs = new ArrayList<>(); protected final List<SettingGroup> sgs = new ArrayList<>();
protected final SettingGroup sgModule = addSg(new SettingGroup("módulo", false)); protected final SettingGroup sgModule = addSg(new SettingGroup("módulo", false, "sputnik.group.common.module"));
protected final SettingGroup sgGeneral = addSg(new SettingGroup("general", true)); protected final SettingGroup sgGeneral = addSg(new SettingGroup("general", true, "sputnik.group.common.general"));
protected static final Minecraft mc = Minecraft.getInstance(); protected static final Minecraft mc = Minecraft.getInstance();
@@ -79,8 +83,12 @@ public class Module {
this.bind.setDefaultValue(key); this.bind.setDefaultValue(key);
// puto marcos // puto marcos
// la clave tiene que salir igual que en ConfigManager#getSettingKey, o sea con los
// nombres internos: Module#getName ya lo es, pero en los ajustes el traducido es
// getName() y el interno getTrueName(). si no cuadran no se encuentra la tecla
// guardada y se le pisa al usuario con la de por defecto
if (ConfigManager.INSTANCE.getConfig().settings if (ConfigManager.INSTANCE.getConfig().settings
.get(this.getName() + ":" + bind.getName()) == null) .get(this.getName() + ":" + bind.getTrueName()) == null)
this.bind.setValue(key); this.bind.setValue(key);
} }
@@ -101,9 +109,10 @@ public class Module {
return sgs; return sgs;
} }
// por nombre interno, no por el traducido (igual que SettingGroup#getSetting)
public SettingGroup getSg(String name) { public SettingGroup getSg(String name) {
for (SettingGroup sg : sgs) { for (SettingGroup sg : sgs) {
if (sg.getName().equals(name)) { if (sg.getTrueName().equals(name)) {
return sg; return sg;
} }
} }
@@ -134,10 +143,7 @@ public class Module {
} }
public void onEnable() { public void onEnable() {
if (notify.getValue()) { notifyToggle(true);
if (notifyMode.is(NotifyMode.CHAT)) ChatUtil.info(getName() + " fue activado");
else HudRenderer.INSTANCE.pushNotification(getName() + " fue activado", getName() + " fue activado.");
}
for (Method method : getClass().getDeclaredMethods()) { for (Method method : getClass().getDeclaredMethods()) {
if (method.isAnnotationPresent(EventListener.class)) { if (method.isAnnotationPresent(EventListener.class)) {
Sputnik.EVENT_BUS.subscribe(this); Sputnik.EVENT_BUS.subscribe(this);
@@ -147,13 +153,23 @@ public class Module {
} }
public void onDisable() { public void onDisable() {
if (notifyMode.is(NotifyMode.CHAT)) ChatUtil.info(getName() + " fue desactivado"); notifyToggle(false);
else HudRenderer.INSTANCE.pushNotification(getName() + " fue desactivado", getName() + " fue desactivado.");
if (Sputnik.EVENT_BUS.isSubscribed(this)) { if (Sputnik.EVENT_BUS.isSubscribed(this)) {
Sputnik.EVENT_BUS.unsubscribe(this); Sputnik.EVENT_BUS.unsubscribe(this);
} }
} }
// onDisable no miraba notify.getValue(), así que avisaba aunque estuviera desactivado
private void notifyToggle(boolean on) {
if (!notify.getValue()) return;
String key = on ? "sputnik.module.toggled.on" : "sputnik.module.toggled.off";
Component message = Component.translatable(key, getDisplayName());
if (notifyMode.is(NotifyMode.CHAT)) ChatUtil.info(message);
else HudRenderer.INSTANCE.pushNotification(message.getString(), message.getString());
}
// tick (ejecutado 20 veces por segundo) // tick (ejecutado 20 veces por segundo)
public void onTick() {} public void onTick() {}
@@ -161,6 +177,8 @@ public class Module {
// getters y setters // getters y setters
// OJO: nombre interno. es la clave de la config. (moduleStates, getSettingKey, settingsPanels)
// y no se traduce nunca. para mostrarlo al usuario usar getDisplayName()
public String getName() { public String getName() {
return name; return name;
} }
@@ -168,6 +186,19 @@ public class Module {
this.name = name; this.name = name;
} }
public String getTranslationKey() {
return "sputnik.module." + I18nUtil.slug(name);
}
// nombre visible, traducido
public String getDisplayName() {
return I18nUtil.orElse(getTranslationKey() + ".name", name);
}
public String getDisplayDescription() {
return I18nUtil.orElse(getTranslationKey() + ".desc", description);
}
public String getDescription() { public String getDescription() {
return description; return description;
} }
@@ -48,7 +48,7 @@ public class ModuleManager {
addRender(); addRender();
addWorld(); addWorld();
modules.sort(Comparator.comparing(module -> MiscUtil.removeAccentMarks(module.getName().toLowerCase()))); modules.sort(Comparator.comparing(module -> MiscUtil.removeAccentMarks(module.getDisplayName().toLowerCase())));
// registrar los "listeners" necesarios // registrar los "listeners" necesarios
for (Module module : getEnabledModules()) { for (Module module : getEnabledModules()) {
@@ -205,9 +205,20 @@ public class ModuleManager {
return enabledModules; return enabledModules;
} }
// busca por nombre interno, tal cual se guarda en la config. antes quitaba las tildes al
// nombre del módulo pero no al argumento, así que "cámara libre" no encontraba nada
public Module getModuleByName(String name) { public Module getModuleByName(String name) {
for (Module module : modules) for (Module module : modules)
if (MiscUtil.removeAccentMarks(module.getName()).equalsIgnoreCase(name)) if (module.getName().equalsIgnoreCase(name))
return module;
return null;
}
// busca por nombre visible: lo que el usuario teclea en los comandos, sin tildes y con "_"
public Module getModuleByDisplayName(String name) {
String target = MiscUtil.removeAccentMarks(name).replace("_", " ");
for (Module module : modules)
if (MiscUtil.removeAccentMarks(module.getDisplayName()).equalsIgnoreCase(target))
return module; return module;
return null; return null;
} }
@@ -25,6 +25,7 @@ import me.retucio.sputnik.util.MiscUtil;
import net.minecraft.client.CameraType; import net.minecraft.client.CameraType;
import net.minecraft.client.input.MouseButtonEvent; import net.minecraft.client.input.MouseButtonEvent;
import net.minecraft.client.input.MouseButtonInfo; import net.minecraft.client.input.MouseButtonInfo;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.*; import net.minecraft.network.protocol.game.*;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
@@ -150,8 +151,8 @@ public class Freecam extends Module {
speed = speedSetting.getValue(); speed = speedSetting.getValue();
MiscUtil.copyVector(pos, mc.gameRenderer.getMainCamera().position()); MiscUtil.copyVector(pos, mc.gameRenderer.mainCamera().position());
MiscUtil.copyVector(prevPos, mc.gameRenderer.getMainCamera().position()); MiscUtil.copyVector(prevPos, mc.gameRenderer.mainCamera().position());
if (mc.options.getCameraType() == CameraType.THIRD_PERSON_FRONT) { if (mc.options.getCameraType() == CameraType.THIRD_PERSON_FRONT) {
yaw += 180; yaw += 180;
@@ -171,14 +172,20 @@ public class Freecam extends Module {
down = KeyUtil.isKeyDown(mc.options.keyShift); down = KeyUtil.isKeyDown(mc.options.keyShift);
unpress(); unpress();
if (reloadChunks.getValue()) mc.levelRenderer.allChanged(); if (reloadChunks.getValue()) invalidateChunks();
super.onEnable(); super.onEnable();
} }
// allChanged() ya no existe; ahora hay que pasarle el estado a mano
private static void invalidateChunks() {
if (mc.level == null) return;
mc.levelRenderer.invalidateCompiledGeometry(mc.level, mc.options, mc.gameRenderer.mainCamera(), mc.getBlockColors());
}
@Override @Override
public void onDisable() { public void onDisable() {
if (reloadChunks.getValue()) mc.execute(mc.levelRenderer::allChanged); if (reloadChunks.getValue()) mc.execute(Freecam::invalidateChunks);
mc.options.setCameraType(perspective); mc.options.setCameraType(perspective);
crouching = false; crouching = false;
@@ -265,7 +272,7 @@ public class Freecam extends Module {
@EventListener @EventListener
private void onKey(KeyEvent event) { private void onKey(KeyEvent event) {
if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_F3)) return; if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_F3)) return;
if (mc.screen != null) return; if (mc.gui.screen() != null) return;
net.minecraft.client.input.KeyEvent key = new net.minecraft.client.input.KeyEvent(event.getKey(), event.getScancode(), 0); net.minecraft.client.input.KeyEvent key = new net.minecraft.client.input.KeyEvent(event.getKey(), event.getScancode(), 0);
@@ -298,7 +305,7 @@ public class Freecam extends Module {
@EventListener @EventListener
private void onMouseClick(MouseClickEvent event) { // por si el restrasado del usuario usa el ratón para moverse private void onMouseClick(MouseClickEvent event) { // por si el restrasado del usuario usa el ratón para moverse
if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_F3)) return; if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_F3)) return;
if (mc.screen != null) return; if (mc.gui.screen() != null) return;
MouseButtonEvent click = new MouseButtonEvent(0, 0, new MouseButtonInfo(event.getButton(), 0)); MouseButtonEvent click = new MouseButtonEvent(0, 0, new MouseButtonInfo(event.getButton(), 0));
@@ -330,7 +337,7 @@ public class Freecam extends Module {
@EventListener @EventListener
private void onMouseScroll(MouseScrollEvent event) { private void onMouseScroll(MouseScrollEvent event) {
if (scrollSens.getValue() > 0 && mc.screen == null && scrollKey.isDown()) { if (scrollSens.getValue() > 0 && mc.gui.screen() == null && scrollKey.isDown()) {
speed += event.getVertical() / 4 * (scrollSens.getValue() * speed); speed += event.getVertical() / 4 * (scrollSens.getValue() * speed);
if (speed < 0.1) speed = 0.1; if (speed < 0.1) speed = 0.1;
event.cancel(); event.cancel();
@@ -356,7 +363,7 @@ public class Freecam extends Module {
toggle(); toggle();
} else if (event.getPacket() instanceof ClientboundSetHealthPacket packet) { } else if (event.getPacket() instanceof ClientboundSetHealthPacket packet) {
if (mc.player.getHealth() - packet.getHealth() > 0 && toggleOnDamage.getValue()) { if (mc.player.getHealth() - packet.getHealth() > 0 && toggleOnDamage.getValue()) {
ChatUtil.info("cámara libre se ha desactivado porque has recibido daño"); ChatUtil.info(Component.translatable("sputnik.module.freecam.damagedisable"));
toggle(); toggle();
} }
} }
@@ -60,7 +60,7 @@ public class PerspectivePlus extends Module {
@EventListener @EventListener
private void onMouseScroll(MouseScrollEvent event) { private void onMouseScroll(MouseScrollEvent event) {
if (mc.options.getCameraType() == CameraType.FIRST_PERSON if (mc.options.getCameraType() == CameraType.FIRST_PERSON
|| mc.screen != null || scrollSens.getValue() <= 0) return; || mc.gui.screen() != null || scrollSens.getValue() <= 0) return;
if (scrollKey.isDown()) { if (scrollKey.isDown()) {
distance -= event.getVertical() / 4 * (scrollSens.getValue() * distance); distance -= event.getVertical() / 4 * (scrollSens.getValue() * distance);
@@ -58,13 +58,24 @@ public class Zoom extends Module {
notify.setValue(false); notify.setValue(false);
} }
// lo que hacía el antiguo LevelRenderer.needsUpdate(), que ya no existe
private static void needsUpdate() {
mc.levelRenderer.sectionOcclusionGraph().invalidate();
mc.levelRenderer.cloudRenderer().markForRebuild();
}
// el Hud ya sólo se puede alternar, no asignar
private static void setHudHidden(boolean hidden) {
if (mc.gui.hud.isHidden() != hidden) mc.gui.hud.toggle();
}
@Override @Override
public void onEnable() { public void onEnable() {
prevSmoothCam = mc.options.smoothCamera; prevSmoothCam = mc.options.smoothCamera;
prevMouseSens = mc.options.sensitivity().get(); prevMouseSens = mc.options.sensitivity().get();
prevFov = mc.options.fov().get(); prevFov = mc.options.fov().get();
prevHUD = mc.options.hideGui; prevHUD = mc.gui.hud.isHidden();
mc.options.hideGui = !showHUD.getValue(); setHudHidden(!showHUD.getValue());
value = defaultZoom.getValue(); value = defaultZoom.getValue();
@@ -75,9 +86,9 @@ public class Zoom extends Module {
public void onDisable() { public void onDisable() {
mc.options.smoothCamera = prevSmoothCam; mc.options.smoothCamera = prevSmoothCam;
mc.options.sensitivity().set(prevMouseSens); mc.options.sensitivity().set(prevMouseSens);
mc.options.hideGui = prevHUD; setHudHidden(prevHUD);
mc.levelRenderer.needsUpdate(); needsUpdate();
super.onDisable(); super.onDisable();
} }
@@ -105,7 +116,7 @@ public class Zoom extends Module {
private void onGetFov(GetFOVEvent event) { private void onGetFov(GetFOVEvent event) {
event.setFov((float) (event.getFov() / value)); event.setFov((float) (event.getFov() / value));
if (prevFov != event.getFov()) mc.levelRenderer.needsUpdate(); if (prevFov != event.getFov()) needsUpdate();
prevFov = event.getFov(); prevFov = event.getFov();
} }
} }
@@ -15,6 +15,7 @@ import me.retucio.sputnik.module.setting.SettingGroup;
import me.retucio.sputnik.module.setting.settings.EnumSetting; import me.retucio.sputnik.module.setting.settings.EnumSetting;
import me.retucio.sputnik.module.setting.settings.StringSetting; import me.retucio.sputnik.module.setting.settings.StringSetting;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.network.chat.Component;
/** /**
@@ -111,13 +112,13 @@ public class DiscordRPC extends Module {
@Override @Override
public void disconnected(ErrorCode errorCode, String message) { public void disconnected(ErrorCode errorCode, String message) {
ChatUtil.warn("desconectado: " + errorCode + " - " + message); ChatUtil.warn(Component.translatable("sputnik.module.discordrpc.disconnected", errorCode, message));
toggle(); toggle();
} }
@Override @Override
public void errored(ErrorCode errorCode, String message) { public void errored(ErrorCode errorCode, String message) {
ChatUtil.error("error: " + errorCode + " - " + message); ChatUtil.error(Component.translatable("sputnik.module.discordrpc.error", errorCode, message));
toggle(); toggle();
} }
}; };
@@ -142,7 +143,7 @@ public class DiscordRPC extends Module {
public void onEnable() { public void onEnable() {
String token = appId.getValue(); String token = appId.getValue();
if (token == null || token.trim().isEmpty()) { if (token == null || token.trim().isEmpty()) {
ChatUtil.error("configura el token del bot primero"); ChatUtil.error(Component.translatable("sputnik.module.discordrpc.notoken"));
toggle(); toggle();
return; return;
} }
@@ -151,10 +152,10 @@ public class DiscordRPC extends Module {
rpc.init(token, handler, false); rpc.init(token, handler, false);
initialized = true; initialized = true;
} catch (UnsupportedOsType e) { } catch (UnsupportedOsType e) {
ChatUtil.error("sistema operativo no soportado"); ChatUtil.error(Component.translatable("sputnik.module.discordrpc.unsupportedos"));
toggle(); toggle();
} catch (Exception e) { } catch (Exception e) {
ChatUtil.error("error al inicializar rpc: " + e.getMessage()); ChatUtil.error(Component.translatable("sputnik.module.discordrpc.initerror", e.getMessage()));
toggle(); toggle();
} }
@@ -191,7 +192,7 @@ public class DiscordRPC extends Module {
try { try {
rpc.updatePresence(getPresence()); rpc.updatePresence(getPresence());
} catch (Exception e) { } catch (Exception e) {
ChatUtil.error("error al actualizar rpc: " + e.getMessage()); ChatUtil.error(Component.translatable("sputnik.module.discordrpc.updateerror", e.getMessage()));
} }
} }
} }
@@ -215,7 +216,7 @@ public class DiscordRPC extends Module {
try { try {
timestamp = Long.parseLong(startTimestamp.getValue()); timestamp = Long.parseLong(startTimestamp.getValue());
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
ChatUtil.error("introduce un NÚMERO (o déjalo vacío)"); ChatUtil.error(Component.translatable("sputnik.module.discordrpc.notanumber"));
timestamp = System.currentTimeMillis(); timestamp = System.currentTimeMillis();
} }
} }
@@ -9,6 +9,7 @@ import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.BooleanSetting; import me.retucio.sputnik.module.setting.settings.BooleanSetting;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
@@ -42,12 +43,16 @@ public class Friends extends Module {
if (FriendManager.INSTANCE.isFriend(target)) { if (FriendManager.INSTANCE.isFriend(target)) {
FriendManager.INSTANCE.remove(target); FriendManager.INSTANCE.remove(target);
ChatUtil.info(ChatFormatting.GREEN + target.getName().getString() + ChatFormatting.RESET + " ya no es tu amigo :("); ChatUtil.info(Component.translatable("sputnik.commands.friend.removed",
ChatFormatting.GREEN + target.getName().getString() + ChatFormatting.RESET));
} else { } else {
switch (FriendManager.INSTANCE.add(target)) { switch (FriendManager.INSTANCE.add(target)) {
case SUCCESS -> ChatUtil.info(ChatFormatting.GREEN + target.getName().getString() + ChatFormatting.RESET + " agregado como amigo :)"); case SUCCESS -> ChatUtil.info(Component.translatable("sputnik.commands.friend.added",
case ALREADY_BEFRIENDED -> ChatUtil.warn(ChatFormatting.GREEN + target.getName().getString() + ChatFormatting.RESET + " ya es tu amigo"); ChatFormatting.GREEN + target.getName().getString() + ChatFormatting.RESET));
case NOT_PLAYER -> ChatUtil.error("no se pudo añadir a " + ChatFormatting.GREEN + target.getName().getString() + ChatFormatting.RESET + " como amigo"); case ALREADY_BEFRIENDED -> ChatUtil.warn(Component.translatable("sputnik.module.friends.already",
ChatFormatting.GREEN + target.getName().getString() + ChatFormatting.RESET));
case NOT_PLAYER -> ChatUtil.error(Component.translatable("sputnik.module.friends.notplayer",
ChatFormatting.GREEN + target.getName().getString() + ChatFormatting.RESET));
} }
} }
} }
@@ -7,6 +7,7 @@ import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.BooleanSetting; import me.retucio.sputnik.module.setting.settings.BooleanSetting;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import me.retucio.sputnik.util.InventoryUtil; import me.retucio.sputnik.util.InventoryUtil;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ServerboundAttackPacket; import net.minecraft.network.protocol.game.ServerboundAttackPacket;
import net.minecraft.network.protocol.game.ServerboundInteractPacket; import net.minecraft.network.protocol.game.ServerboundInteractPacket;
import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.EquipmentSlot;
@@ -36,7 +37,7 @@ public class ChestplateSwitch extends Module {
if (mc.player.hasItemInSlot(EquipmentSlot.CHEST) || mc.player.getItemBySlot(EquipmentSlot.CHEST).is(Items.ELYTRA)) { if (mc.player.hasItemInSlot(EquipmentSlot.CHEST) || mc.player.getItemBySlot(EquipmentSlot.CHEST).is(Items.ELYTRA)) {
int slot = InventoryUtil.findSlot(this::isChestplate); int slot = InventoryUtil.findSlot(this::isChestplate);
if (!Inventory.isHotbarSlot(slot)) { if (!Inventory.isHotbarSlot(slot)) {
ChatUtil.error("no se encontró una pechera en la hotbar"); ChatUtil.error(Component.translatable("sputnik.module.chestplateswitch.nochestplate"));
return; return;
} }
@@ -19,6 +19,7 @@ import net.minecraft.network.protocol.game.ServerboundUseItemOnPacket;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.boss.enderdragon.EndCrystal; import net.minecraft.world.entity.boss.enderdragon.EndCrystal;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Inventory;
@@ -47,7 +48,7 @@ public class CrystalAura extends Module {
private final ListSetting<EntityType<?>> entities = sgGeneral.add(new ListSetting<>( private final ListSetting<EntityType<?>> entities = sgGeneral.add(new ListSetting<>(
"entidades", "entidades a las que atacar", "entidades", "entidades a las que atacar",
Lists.entityList, Lists.allFalseExcept(Lists.entityList, EntityType.PLAYER), Lists.entityNames Lists.entityList, Lists.allFalseExcept(Lists.entityList, EntityTypes.PLAYER), Lists.entityNames
)); ));
private final NumberSetting targetRange = sgGeneral.add(new NumberSetting( private final NumberSetting targetRange = sgGeneral.add(new NumberSetting(
@@ -205,7 +206,7 @@ public class CrystalAura extends Module {
} }
} }
// asegurarse de que no está dentro del bloque // asegurarse de que no está dentro del bloque
if (mc.level.isEmptyBlock(pos) && mc.level.getBlockState(pos.below()).isSolid() && mc.level.isEmptyBlock(pos.above()) && targetPos.distanceTo(pos.getCenter()) > 0.6) { if (mc.level.isEmptyBlock(pos) && mc.level.getBlockState(pos.below()).isSolid() && mc.level.isEmptyBlock(pos.above()) && targetPos.distanceTo(Vec3.atCenterOf(pos)) > 0.6) {
double dist = targetPos.distanceToSqr(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5); double dist = targetPos.distanceToSqr(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5);
if (dist < bestObbyPlaceDist[0]) { if (dist < bestObbyPlaceDist[0]) {
bestObbyPlaceDist[0] = dist; bestObbyPlaceDist[0] = dist;
@@ -253,7 +254,7 @@ public class CrystalAura extends Module {
return; return;
} }
if (rotateToPlace.getValue()) EntityUtil.lookAt(result.getBlockPos().getCenter()); if (rotateToPlace.getValue()) EntityUtil.lookAt(Vec3.atCenterOf(result.getBlockPos()));
mc.gameMode.startPrediction(mc.level, (sequence) -> new ServerboundUseItemOnPacket(hand, result, sequence)); mc.gameMode.startPrediction(mc.level, (sequence) -> new ServerboundUseItemOnPacket(hand, result, sequence));
} }
@@ -272,7 +273,7 @@ public class CrystalAura extends Module {
BlockPos supportPos = pos.below(); BlockPos supportPos = pos.below();
BlockHitResult result = new BlockHitResult(Vec3.atCenterOf(supportPos), Direction.UP, supportPos, false); BlockHitResult result = new BlockHitResult(Vec3.atCenterOf(supportPos), Direction.UP, supportPos, false);
if (rotateToPlace.getValue()) EntityUtil.lookAt(pos.getCenter()); if (rotateToPlace.getValue()) EntityUtil.lookAt(Vec3.atCenterOf(pos));
mc.gameMode.startPrediction(mc.level, (sequence) -> new ServerboundUseItemOnPacket(hand, result, sequence)); mc.gameMode.startPrediction(mc.level, (sequence) -> new ServerboundUseItemOnPacket(hand, result, sequence));
} }
@@ -8,6 +8,7 @@ import me.retucio.sputnik.module.setting.settings.BooleanSetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting; import me.retucio.sputnik.module.setting.settings.NumberSetting;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ServerboundAttackPacket; import net.minecraft.network.protocol.game.ServerboundAttackPacket;
import net.minecraft.network.protocol.game.ServerboundInteractPacket; import net.minecraft.network.protocol.game.ServerboundInteractPacket;
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket; import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
@@ -154,7 +155,7 @@ public class MaceKill extends Module {
} }
} }
} catch (Exception e) { } catch (Exception e) {
ChatUtil.error("upsi: " + e.getMessage()); ChatUtil.error(Component.translatable("sputnik.module.macekill.oops", e.getMessage()));
} }
} }
} }
@@ -183,7 +183,7 @@ public class ProjectileTrajectories extends Module {
} }
private Vec3 calculateHandToEyeDelta(Vec3 offset, Vec3 startPos, Vec3 eye, int handMultiplier, float tickProgress) { private Vec3 calculateHandToEyeDelta(Vec3 offset, Vec3 startPos, Vec3 eye, int handMultiplier, float tickProgress) {
if (mc.gameRenderer.getMainCamera().isDetached()) { if (mc.gameRenderer.mainCamera().isDetached()) {
offset = offset.scale(0); offset = offset.scale(0);
} }
@@ -204,7 +204,7 @@ public class ProjectileTrajectories extends Module {
private void renderTrajectory(PoseStack matrices, List<Vec3> trajectoryPoints, Vec3 handToEyeDelta, boolean hasHit) { private void renderTrajectory(PoseStack matrices, List<Vec3> trajectoryPoints, Vec3 handToEyeDelta, boolean hasHit) {
if (trajectoryPoints.isEmpty()) return; if (trajectoryPoints.isEmpty()) return;
Vec3 cameraPos = mc.gameRenderer.getMainCamera().position(); Vec3 cameraPos = mc.gameRenderer.mainCamera().position();
matrices.pushPose(); matrices.pushPose();
matrices.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z); matrices.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z);
@@ -68,7 +68,7 @@ public class Burglar extends Module {
@EventListener @EventListener
private void onKey(KeyEvent event) { private void onKey(KeyEvent event) {
if (!triggerKey.isDown() || event.getAction() != GLFW.GLFW_PRESS if (!triggerKey.isDown() || event.getAction() != GLFW.GLFW_PRESS
|| !(mc.screen instanceof AbstractContainerScreen<?> container)) return; || !(mc.gui.screen() instanceof AbstractContainerScreen<?> container)) return;
if (event.getKey() == stealKey.getValue()) steal(container); if (event.getKey() == stealKey.getValue()) steal(container);
if (event.getKey() == dumpKey.getValue()) dump(container); if (event.getKey() == dumpKey.getValue()) dump(container);
} }
@@ -44,7 +44,7 @@ public class InventoryPlus extends Module {
} }
private void processInput(int inputCode, Event event) { private void processInput(int inputCode, Event event) {
if (!(mc.screen instanceof AbstractContainerScreen<?> screen) || mc.player == null) return; if (!(mc.gui.screen() instanceof AbstractContainerScreen<?> screen) || mc.player == null) return;
Slot focusedSlot = ((AbstractContainerScreenAccessor) screen).getHoveredSlot(); Slot focusedSlot = ((AbstractContainerScreenAccessor) screen).getHoveredSlot();
if (focusedSlot == null) return; if (focusedSlot == null) return;
@@ -14,7 +14,9 @@ import me.retucio.sputnik.util.InventoryUtil;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.core.component.DataComponents; import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.DyeColor;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
@@ -40,22 +42,22 @@ public class ShulkerPeek extends Module {
// colores y tal (https://github.com/kgriff0n/shulker-preview) // colores y tal (https://github.com/kgriff0n/shulker-preview)
SHULKER_COLORS.put(Items.SHULKER_BOX, Colors.LAVENDER); SHULKER_COLORS.put(Items.SHULKER_BOX, Colors.LAVENDER);
SHULKER_COLORS.put(Items.WHITE_SHULKER_BOX, Colors.WHITE); SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.WHITE), Colors.WHITE);
SHULKER_COLORS.put(Items.LIGHT_GRAY_SHULKER_BOX, Colors.SILVER); SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.LIGHT_GRAY), Colors.SILVER);
SHULKER_COLORS.put(Items.GRAY_SHULKER_BOX, Colors.GRAY); SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.GRAY), Colors.GRAY);
SHULKER_COLORS.put(Items.BLACK_SHULKER_BOX, Colors.BLACK); SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.BLACK), Colors.BLACK);
SHULKER_COLORS.put(Items.BROWN_SHULKER_BOX, Colors.BROWN); SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.BROWN), Colors.BROWN);
SHULKER_COLORS.put(Items.RED_SHULKER_BOX, Colors.RED); SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.RED), Colors.RED);
SHULKER_COLORS.put(Items.ORANGE_SHULKER_BOX, Colors.ORANGE); SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.ORANGE), Colors.ORANGE);
SHULKER_COLORS.put(Items.YELLOW_SHULKER_BOX, Colors.YELLOW); SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.YELLOW), Colors.YELLOW);
SHULKER_COLORS.put(Items.LIME_SHULKER_BOX, Colors.LIME); SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.LIME), Colors.LIME);
SHULKER_COLORS.put(Items.GREEN_SHULKER_BOX, Colors.GREEN); SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.GREEN), Colors.GREEN);
SHULKER_COLORS.put(Items.CYAN_SHULKER_BOX, Colors.CYAN); SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.CYAN), Colors.CYAN);
SHULKER_COLORS.put(Items.LIGHT_BLUE_SHULKER_BOX, Colors.CELESTE); SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.LIGHT_BLUE), Colors.CELESTE);
SHULKER_COLORS.put(Items.BLUE_SHULKER_BOX, Colors.BLUE); SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.BLUE), Colors.BLUE);
SHULKER_COLORS.put(Items.PURPLE_SHULKER_BOX, Colors.PURPLE); SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.PURPLE), Colors.PURPLE);
SHULKER_COLORS.put(Items.MAGENTA_SHULKER_BOX, Colors.MAGENTA); SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.MAGENTA), Colors.MAGENTA);
SHULKER_COLORS.put(Items.PINK_SHULKER_BOX, Colors.PINK); SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.PINK), Colors.PINK);
} }
@EventListener @EventListener
@@ -69,7 +71,7 @@ public class ShulkerPeek extends Module {
} }
if (event.getAction() == GLFW.GLFW_REPEAT) { if (event.getAction() == GLFW.GLFW_REPEAT) {
if (mc.screen instanceof PreviewScreen preview) { if (mc.gui.screen() instanceof PreviewScreen preview) {
if (preview.getType() != PreviewScreen.PreviewType.SHULKER) if (preview.getType() != PreviewScreen.PreviewType.SHULKER)
openPreviewScreen(); openPreviewScreen();
} else openPreviewScreen(); } else openPreviewScreen();
@@ -77,7 +79,7 @@ public class ShulkerPeek extends Module {
} }
if (event.getAction() == GLFW.GLFW_RELEASE) { if (event.getAction() == GLFW.GLFW_RELEASE) {
if (mc.screen instanceof PreviewScreen preview) if (mc.gui.screen() instanceof PreviewScreen preview)
preview.onClose(); preview.onClose();
} }
} }
@@ -85,25 +87,25 @@ public class ShulkerPeek extends Module {
private void openPreviewScreen() { private void openPreviewScreen() {
ItemStack stack; ItemStack stack;
if (mc.screen instanceof PreviewScreen previewScreen) { if (mc.gui.screen() instanceof PreviewScreen previewScreen) {
int focusedSlot = previewScreen.getFocusedSlot(); int focusedSlot = previewScreen.getFocusedSlot();
if (focusedSlot == -1) return; if (focusedSlot == -1) return;
stack = previewScreen.getInventory().get(focusedSlot); stack = previewScreen.getInventory().get(focusedSlot);
} else if (mc.screen instanceof AbstractContainerScreen<?> handledScreen) { } else if (mc.gui.screen() instanceof AbstractContainerScreen<?> handledScreen) {
stack = ((AbstractContainerScreenAccessor) handledScreen).getHoveredSlot().getItem(); stack = ((AbstractContainerScreenAccessor) handledScreen).getHoveredSlot().getItem();
} else return; } else return;
if (stack.getItem() == Items.ENDER_CHEST) { if (stack.getItem() == Items.ENDER_CHEST) {
if (InventoryUtil.getEchestInv() == null) { if (InventoryUtil.getEchestInv() == null) {
ChatUtil.warn("abre un enderchest primero"); ChatUtil.warn(Component.translatable("sputnik.module.shulkerpeek.openechest"));
return; return;
} }
mc.setScreen(new PreviewScreen(InventoryUtil.getEchestInv(), mc.screen)); mc.gui.setScreen(new PreviewScreen(InventoryUtil.getEchestInv(), mc.gui.screen()));
return; return;
} }
else if (isShulkerEmpty(stack)) return; else if (isShulkerEmpty(stack)) return;
mc.setScreen(new PreviewScreen(stack, mc.screen)); mc.gui.setScreen(new PreviewScreen(stack, mc.gui.screen()));
} }
public static boolean isShulkerEmpty(ItemStack stack) { public static boolean isShulkerEmpty(ItemStack stack) {
@@ -60,13 +60,13 @@ public class UIMove extends Module {
@Override @Override
public void onTick() { public void onTick() {
if (mc.player == null || mc.screen == null) return; if (mc.player == null || mc.gui.screen() == null) return;
MenuType<?> handler = null; MenuType<?> handler = null;
if (mc.screen == ClickGui.INSTANCE) if (mc.gui.screen() == ClickGui.INSTANCE)
handler = clickGuiHandlerType; handler = clickGuiHandlerType;
if (mc.screen instanceof AbstractContainerScreen<?> screen) { if (mc.gui.screen() instanceof AbstractContainerScreen<?> screen) {
try { try {
handler = screen.getMenu().getType(); handler = screen.getMenu().getType();
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
@@ -74,10 +74,10 @@ public class AnvilFont extends Module {
@Override @Override
public void onTick() { public void onTick() {
if (mc.screen == null) return; if (mc.gui.screen() == null) return;
if (mc.screen instanceof AnvilScreen) { if (mc.gui.screen() instanceof AnvilScreen) {
EditBox nameField = ((AnvilScreenAccessor) mc.screen).getNameField(); EditBox nameField = ((AnvilScreenAccessor) mc.gui.screen()).getNameField();
if (fontMode.getValue() != FontMode.NORMAL) if (fontMode.getValue() != FontMode.NORMAL)
text = fonts.get(fontMode.getIndex()).replace(nameField.getValue()); text = fonts.get(fontMode.getIndex()).replace(nameField.getValue());
@@ -87,7 +87,7 @@ public class AnvilFont extends Module {
if (!text.equals(nameField.getValue())) if (!text.equals(nameField.getValue()))
nameField.setValue(text); nameField.setValue(text);
((AnvilScreenAccessor) mc.screen).setNameField(nameField); ((AnvilScreenAccessor) mc.gui.screen()).setNameField(nameField);
} }
} }
@@ -107,7 +107,7 @@ public class BookBot extends Module {
ItemStack book = InventoryUtil.findStack(bookPredicate); ItemStack book = InventoryUtil.findStack(bookPredicate);
if (book == null) { if (book == null) {
ChatUtil.warn("no se encontró ningún libro"); ChatUtil.warn(Component.translatable("sputnik.module.bookbot.nobook"));
toggle(); toggle();
return; return;
} }
@@ -193,7 +193,7 @@ public class BookBot extends Module {
} }
if (bookCount > 0) { if (bookCount > 0) {
ChatUtil.info("creado libro n. " + bookCount); ChatUtil.info(Component.translatable("sputnik.module.bookbot.created", bookCount));
} }
createBook(pages, filteredPages); createBook(pages, filteredPages);
@@ -123,7 +123,7 @@ public class ChatPlus extends Module {
private void onSendMessage(SendMessageEvent event) { private void onSendMessage(SendMessageEvent event) {
// evitar mandar coordenadas por el chat // evitar mandar coordenadas por el chat
if (coordsProtection.getValue() && containsCoordinates(event.getMessage())) { if (coordsProtection.getValue() && containsCoordinates(event.getMessage())) {
ChatUtil.warn(Component.literal("cuidadito con las coordenadas chavalín").append( ChatUtil.warn(Component.translatable("sputnik.module.chatplus.coordswarn").append(
getSendButton(event.getMessage()))); getSendButton(event.getMessage())));
event.cancel(); event.cancel();
@@ -200,10 +200,11 @@ public class ChatPlus extends Module {
@SuppressWarnings("DataFlowIssue") @SuppressWarnings("DataFlowIssue")
private MutableComponent getSendButton(String message) { private MutableComponent getSendButton(String message) {
// botón para enviar mensaje con coordenadas de todos modos // botón para enviar mensaje con coordenadas de todos modos
MutableComponent sendButton = Component.literal("\n[ME LA SUDA]"); MutableComponent sendButton = Component.literal("\n").append(
Component.translatable("sputnik.module.chatplus.sendanyway"));
MutableComponent hintBaseText = Component.literal(""); MutableComponent hintBaseText = Component.literal("");
MutableComponent hintMsg = Component.literal("enviar de todos modos:"); MutableComponent hintMsg = Component.translatable("sputnik.module.chatplus.sendanyway.hint");
hintMsg.setStyle(hintBaseText.getStyle().applyFormat(ChatFormatting.GRAY)); hintMsg.setStyle(hintBaseText.getStyle().applyFormat(ChatFormatting.GRAY));
hintBaseText.append(hintMsg); hintBaseText.append(hintMsg);
@@ -52,7 +52,8 @@ public class ScreenshotPlus extends Module {
} }
public void sendScreenshotMessage() { public void sendScreenshotMessage() {
MutableComponent baseText = Component.literal("captura de pantalla tomada\n"); MutableComponent baseText = Component.translatable("sputnik.module.screenshot.taken")
.append(Component.literal("\n"));
if (saveButton.getValue() && !defaultAction.is(ScreenshotActions.SAVE)) baseText.append(getSaveButton().append(" ")); if (saveButton.getValue() && !defaultAction.is(ScreenshotActions.SAVE)) baseText.append(getSaveButton().append(" "));
if (copyButton.getValue()) baseText.append(getCopyButton().append(" ")); if (copyButton.getValue()) baseText.append(getCopyButton().append(" "));
if (openButton.getValue() && defaultAction.is(ScreenshotActions.SAVE)) baseText.append(getOpenButton().append(" ")); if (openButton.getValue() && defaultAction.is(ScreenshotActions.SAVE)) baseText.append(getOpenButton().append(" "));
@@ -72,9 +73,9 @@ public class ScreenshotPlus extends Module {
ScreenshotPlus.TransferableImage trans = new TransferableImage(bufferedImage); ScreenshotPlus.TransferableImage trans = new TransferableImage(bufferedImage);
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(trans, null); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(trans, null);
ChatUtil.info("captura copiada al portapapeles"); ChatUtil.info(Component.translatable("sputnik.module.screenshot.copied"));
} catch (Exception e) { } catch (Exception e) {
ChatUtil.error("no se pudo copiar la captura al portapapeles"); ChatUtil.error(Component.translatable("sputnik.module.screenshot.copyfailed"));
e.printStackTrace(); e.printStackTrace();
} }
} }
@@ -85,7 +86,7 @@ public class ScreenshotPlus extends Module {
public void saveScreenshot(NativeImage image) throws IOException { public void saveScreenshot(NativeImage image) throws IOException {
image.writeToFile(screenshotFile); image.writeToFile(screenshotFile);
ChatUtil.info(Component.literal("captura guardada como: ").append( ChatUtil.info(Component.translatable("sputnik.module.screenshot.savedas").append(
Component.literal(screenshotFile.getName()) Component.literal(screenshotFile.getName())
.withStyle(ChatFormatting.UNDERLINE) .withStyle(ChatFormatting.UNDERLINE)
.withStyle(style -> style.withClickEvent(new ClickEvent.OpenFile(screenshotFile.getAbsoluteFile()))) .withStyle(style -> style.withClickEvent(new ClickEvent.OpenFile(screenshotFile.getAbsoluteFile())))
@@ -129,7 +130,7 @@ public class ScreenshotPlus extends Module {
@SuppressWarnings("DataFlowIssue") @SuppressWarnings("DataFlowIssue")
private MutableComponent getSaveButton() { private MutableComponent getSaveButton() {
MutableComponent button = Component.literal("[GUARDAR]"); MutableComponent button = Component.translatable("sputnik.module.screenshot.button.save");
MutableComponent hintBaseText = Component.literal(""); MutableComponent hintBaseText = Component.literal("");
MutableComponent hintMsg = Component.literal(ScreenshotActions.SAVE.toString()); MutableComponent hintMsg = Component.literal(ScreenshotActions.SAVE.toString());
@@ -146,7 +147,7 @@ public class ScreenshotPlus extends Module {
@SuppressWarnings("DataFlowIssue") @SuppressWarnings("DataFlowIssue")
private MutableComponent getCopyButton() { private MutableComponent getCopyButton() {
MutableComponent button = Component.literal("[COPIAR]"); MutableComponent button = Component.translatable("sputnik.module.screenshot.button.copy");
MutableComponent hintBaseText = Component.literal(""); MutableComponent hintBaseText = Component.literal("");
MutableComponent hintMsg = Component.literal(ScreenshotActions.COPY.toString()); MutableComponent hintMsg = Component.literal(ScreenshotActions.COPY.toString());
@@ -162,10 +163,10 @@ public class ScreenshotPlus extends Module {
} }
private MutableComponent getOpenButton() { private MutableComponent getOpenButton() {
MutableComponent button = Component.literal("[ABRIR]"); MutableComponent button = Component.translatable("sputnik.module.screenshot.button.open");
MutableComponent hintBaseText = Component.literal(""); MutableComponent hintBaseText = Component.literal("");
MutableComponent hintMsg = Component.literal("abrir archivo de imagen"); MutableComponent hintMsg = Component.translatable("sputnik.module.screenshot.button.open.hint");
hintMsg.setStyle(hintBaseText.getStyle().applyFormats(ChatFormatting.GRAY)); hintMsg.setStyle(hintBaseText.getStyle().applyFormats(ChatFormatting.GRAY));
hintBaseText.append(hintMsg); hintBaseText.append(hintMsg);
@@ -179,7 +180,7 @@ public class ScreenshotPlus extends Module {
@SuppressWarnings("DataFlowIssue") @SuppressWarnings("DataFlowIssue")
private MutableComponent getDiscardButton() { private MutableComponent getDiscardButton() {
MutableComponent button = Component.literal("[DESCARTAR]"); MutableComponent button = Component.translatable("sputnik.module.screenshot.button.discard");
MutableComponent hintBaseText = Component.literal(""); MutableComponent hintBaseText = Component.literal("");
MutableComponent hintMsg = Component.literal(ScreenshotActions.NONE.toString()); MutableComponent hintMsg = Component.literal(ScreenshotActions.NONE.toString());
@@ -4,6 +4,7 @@ import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.StringSetting; import me.retucio.sputnik.module.setting.settings.StringSetting;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.network.chat.Component;
public class BungeecordSpoofer extends Module { public class BungeecordSpoofer extends Module {
@@ -17,7 +18,7 @@ public class BungeecordSpoofer extends Module {
address.onUpdate(text -> { address.onUpdate(text -> {
if (!text.matches("^[0-9a-f\\\\.:]{0,45}$")) { if (!text.matches("^[0-9a-f\\\\.:]{0,45}$")) {
address.setValue(address.getDefaultValue()); address.setValue(address.getDefaultValue());
ChatUtil.error("dirección IP inválida"); ChatUtil.error(Component.translatable("sputnik.module.bungeespoofer.invalidip"));
} }
}); });
} }
@@ -8,9 +8,11 @@ import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.EnumSetting; import me.retucio.sputnik.module.setting.settings.EnumSetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting; import me.retucio.sputnik.module.setting.settings.NumberSetting;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import me.retucio.sputnik.util.MiscUtil;
import me.retucio.sputnik.util.NetworkUtil; import me.retucio.sputnik.util.NetworkUtil;
import net.minecraft.network.Connection; import net.minecraft.network.Connection;
import net.minecraft.network.PacketListener; import net.minecraft.network.PacketListener;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.common.ClientboundKeepAlivePacket; import net.minecraft.network.protocol.common.ClientboundKeepAlivePacket;
import net.minecraft.network.protocol.common.ServerboundKeepAlivePacket; import net.minecraft.network.protocol.common.ServerboundKeepAlivePacket;
@@ -38,8 +40,8 @@ public class PacketDelay extends Module {
@Override @Override
public void onEnable() { public void onEnable() {
if (mc.isSingleplayer()) { if (MiscUtil.isSingleplayer()) {
ChatUtil.error("delay de paquetes no funciona en un solo jugador"); ChatUtil.error(Component.translatable("sputnik.module.packetdelay.singleplayer"));
toggle(); toggle();
return; return;
} }
@@ -118,7 +120,11 @@ public class PacketDelay extends Module {
@EventListener @EventListener
private void onJoinWorld(JoinWorldEvent event) { private void onJoinWorld(JoinWorldEvent event) {
ChatUtil.error("delay de paquetes no funciona en un solo jugador"); // el aviso iba sin condición, así que el módulo se apagaba solo al entrar
// a cualquier mundo, servidores incluidos
if (!MiscUtil.isSingleplayer()) return;
ChatUtil.error(Component.translatable("sputnik.module.packetdelay.singleplayer"));
toggle(); toggle();
} }
@@ -15,6 +15,7 @@ import me.retucio.sputnik.util.EntityUtil;
import me.retucio.sputnik.util.render.RenderUtil; import me.retucio.sputnik.util.render.RenderUtil;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
@@ -53,8 +54,10 @@ public class PacketMine extends Module {
ClickAction.ADD_PRIORITY ClickAction.ADD_PRIORITY
)); ));
// el espacio del final es a propósito: compartía clave de config. con retryTime ("delay"),
// así que se pisaban el valor. se muestra igual porque getName() hace strip()
private final NumberSetting selectionDelay = sgGeneral.add(new NumberSetting( private final NumberSetting selectionDelay = sgGeneral.add(new NumberSetting(
"delay", "delay ",
"delay entre selecciones de bloques", "delay entre selecciones de bloques",
5, 5,
0, 0,
@@ -270,7 +273,7 @@ public class PacketMine extends Module {
if (dontBreak.getValue() if (dontBreak.getValue()
&& mc.player.isHolding(ItemStack::isDamageableItem) && mc.player.isHolding(ItemStack::isDamageableItem)
&& mc.player.getMainHandItem().getMaxDamage() - mc.player.getMainHandItem().getDamageValue() <= 1) { && mc.player.getMainHandItem().getMaxDamage() - mc.player.getMainHandItem().getDamageValue() <= 1) {
ChatUtil.warn("pico por romperse"); ChatUtil.warn(Component.translatable("sputnik.module.packetmine.pickbreaking"));
toggle(); toggle();
return false; return false;
} }
@@ -10,6 +10,7 @@ import me.retucio.sputnik.module.setting.settings.BooleanSetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting; import me.retucio.sputnik.module.setting.settings.NumberSetting;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import me.retucio.sputnik.util.InventoryUtil; import me.retucio.sputnik.util.InventoryUtil;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
@@ -129,7 +130,7 @@ public class AutoFish extends Module {
ItemStack rod = mc.player.getInventory().getItem(slot); ItemStack rod = mc.player.getInventory().getItem(slot);
if (rod.getDamageValue() >= rod.getMaxDamage() - 1 && dontBreak.getValue()) { if (rod.getDamageValue() >= rod.getMaxDamage() - 1 && dontBreak.getValue()) {
if (!warned) { if (!warned) {
ChatUtil.warn("caña a punto de romperse"); ChatUtil.warn(Component.translatable("sputnik.module.autofish.rodbreaking"));
warned = true; warned = true;
} }
return; return;
@@ -5,6 +5,7 @@ import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.BooleanSetting; import me.retucio.sputnik.module.setting.settings.BooleanSetting;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import me.retucio.sputnik.util.InventoryUtil; import me.retucio.sputnik.util.InventoryUtil;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
@@ -49,7 +50,7 @@ public class KeyPearl extends Module {
int slot = InventoryUtil.findSlot(stack -> stack.is(Items.ENDER_PEARL)); int slot = InventoryUtil.findSlot(stack -> stack.is(Items.ENDER_PEARL));
if (slot < 0) { if (slot < 0) {
ChatUtil.error("no tienes perlas"); ChatUtil.error(Component.translatable("sputnik.module.keypearl.nopearls"));
toggle(); toggle();
return; return;
} }
@@ -12,6 +12,7 @@ import me.retucio.sputnik.util.ChatUtil;
import me.retucio.sputnik.util.InventoryUtil; import me.retucio.sputnik.util.InventoryUtil;
import me.retucio.sputnik.util.Lists; import me.retucio.sputnik.util.Lists;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket; import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
@@ -27,27 +28,23 @@ import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import java.util.List; import java.util.List;
import java.util.stream.Stream;
// todo: arreglar MLGs con bloques // todo: arreglar MLGs con bloques
public class NoFall extends Module { public class NoFall extends Module {
private boolean placed, shouldUse; private boolean placed, shouldUse;
private final List<Item> mlgItems = List.of(Items.WATER_BUCKET, Items.ENDER_PEARL, private final List<Item> mlgItems = Stream.concat(
Items.POWDER_SNOW_BUCKET, Items.TWISTING_VINES, Items.SLIME_BLOCK, Stream.of(Items.WATER_BUCKET, Items.ENDER_PEARL,
Items.HAY_BLOCK, Items.HONEY_BLOCK, Items.BLACK_BED, Items.POWDER_SNOW_BUCKET, Items.TWISTING_VINES, Items.SLIME_BLOCK,
Items.BLUE_BED, Items.BROWN_BED, Items.CYAN_BED, Items.GRAY_BED, Items.HAY_BLOCK, Items.HONEY_BLOCK),
Items.GREEN_BED, Items.LIGHT_BLUE_BED, Items.LIGHT_GRAY_BED, Items.LIME_BED, Items.BED.asList().stream()).toList();
Items.MAGENTA_BED, Items.ORANGE_BED, Items.PINK_BED, Items.PURPLE_BED,
Items.RED_BED, Items.WHITE_BED, Items.YELLOW_BED);
private final List<Block> safeBlocks = List.of( private final List<Block> safeBlocks = Stream.concat(
Blocks.WATER, Blocks.SLIME_BLOCK, Blocks.HAY_BLOCK, Blocks.HONEY_BLOCK, Stream.of(Blocks.WATER, Blocks.SLIME_BLOCK, Blocks.HAY_BLOCK,
Blocks.TWISTING_VINES, Blocks.BLACK_BED, Blocks.BLUE_BED, Blocks.BROWN_BED, Blocks.HONEY_BLOCK, Blocks.TWISTING_VINES),
Blocks.CYAN_BED, Blocks.GRAY_BED, Blocks.GREEN_BED, Blocks.LIGHT_BLUE_BED, Blocks.BED.asList().stream()).toList();
Blocks.LIGHT_GRAY_BED, Blocks.LIME_BED, Blocks.MAGENTA_BED, Blocks.ORANGE_BED,
Blocks.PINK_BED, Blocks.PURPLE_BED, Blocks.RED_BED, Blocks. WHITE_BED,
Blocks.YELLOW_BED);
private final EnumSetting<NoFallMode> mode = sgGeneral.add(new EnumSetting<>( private final EnumSetting<NoFallMode> mode = sgGeneral.add(new EnumSetting<>(
"modo", "modo",
@@ -110,7 +107,7 @@ public class NoFall extends Module {
&& !placed) { && !placed) {
if (center.getValue()) { if (center.getValue()) {
Vec3 diff = mc.player.position().subtract(mc.player.blockPosition().getCenter()); Vec3 diff = mc.player.position().subtract(Vec3.atCenterOf(mc.player.blockPosition()));
if (diff.lengthSqr() > 10e-3) { if (diff.lengthSqr() > 10e-3) {
Vec3 impulse = new Vec3(-diff.x * 0.05, 0, -diff.z * 0.05); Vec3 impulse = new Vec3(-diff.x * 0.05, 0, -diff.z * 0.05);
mc.player.push(impulse.x, impulse.y, impulse.z); mc.player.push(impulse.x, impulse.y, impulse.z);
@@ -129,11 +126,11 @@ public class NoFall extends Module {
ItemStack mlgItem = getMlgItem(); ItemStack mlgItem = getMlgItem();
if (mlgItem == null) { if (mlgItem == null) {
if (!placed) { if (!placed) {
ChatUtil.warn("amortiguador (agua, etc.) no encontrado"); ChatUtil.warn(Component.translatable("sputnik.module.nofall.nocushion"));
placed = true; placed = true;
if (clutch.getValue()) { if (clutch.getValue()) {
mode.setValue(NoFallMode.PACKET); mode.setValue(NoFallMode.PACKET);
ChatUtil.info("cambiado a modo de paquetes"); ChatUtil.info(Component.translatable("sputnik.module.nofall.packetmode"));
} }
} }
return; return;
@@ -150,7 +150,7 @@ public class BlockESP extends Module {
searchBlocks(); searchBlocks();
} }
Vec3 cameraPos = mc.gameRenderer.getMainCamera().position(); Vec3 cameraPos = mc.gameRenderer.mainCamera().position();
int rendered = 0; int rendered = 0;
Iterator<Map.Entry<BlockPos, VoxelShape>> iterator = cachedBlocks.entrySet().iterator(); Iterator<Map.Entry<BlockPos, VoxelShape>> iterator = cachedBlocks.entrySet().iterator();
@@ -19,6 +19,7 @@ import net.minecraft.util.Mth;
import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.EntityReference;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.item.PrimedTnt; import net.minecraft.world.entity.item.PrimedTnt;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
@@ -79,25 +80,25 @@ public class Nametags extends Module {
Category.RENDER); Category.RENDER);
// entidades activadas por defecto // entidades activadas por defecto
defaultEntities.replace(EntityType.PLAYER, true); defaultEntities.replace(EntityTypes.PLAYER, true);
defaultEntities.replace(EntityType.ITEM, true); defaultEntities.replace(EntityTypes.ITEM, true);
defaultEntities.replace(EntityType.ARROW, true); defaultEntities.replace(EntityTypes.ARROW, true);
defaultEntities.replace(EntityType.SPECTRAL_ARROW, true); defaultEntities.replace(EntityTypes.SPECTRAL_ARROW, true);
defaultEntities.replace(EntityType.TRIDENT, true); defaultEntities.replace(EntityTypes.TRIDENT, true);
defaultEntities.replace(EntityType.TNT, true); defaultEntities.replace(EntityTypes.TNT, true);
entities.setDefaultValue(defaultEntities); entities.setDefaultValue(defaultEntities);
health.onUpdate(v -> healthMode.visibility(v)); health.onUpdate(v -> healthMode.visibility(v));
entities.onUpdate(entities -> { entities.onUpdate(entities -> {
items.visibility(entities.get(EntityType.ITEM)); items.visibility(entities.get(EntityTypes.ITEM));
boolean anyProjectile = entities.get(EntityType.TRIDENT) boolean anyProjectile = entities.get(EntityTypes.TRIDENT)
|| entities.get(EntityType.ARROW) || entities.get(EntityTypes.ARROW)
|| entities.get(EntityType.SPECTRAL_ARROW); || entities.get(EntityTypes.SPECTRAL_ARROW);
showProjectileDamage.visibility(anyProjectile); showProjectileDamage.visibility(anyProjectile);
tntPrime.visibility(entities.get(EntityType.TNT)); tntPrime.visibility(entities.get(EntityTypes.TNT));
}); });
} }
@@ -93,6 +93,7 @@ public class NoRender extends Module {
private final String name; private final String name;
Colors(String name) { this.name = name; } Colors(String name) { this.name = name; }
@Override public String toString() { return name; } @Override public String toString() { return name; }
public ChatFormatting toFormatting() { return ChatFormatting.getById(this.ordinal()); } // los nombres coinciden con los de ChatFormatting; DEFAULT no tiene equivalente
public ChatFormatting toFormatting() { return ChatFormatting.valueOf(this.name()); }
} }
} }
@@ -14,6 +14,7 @@ import me.retucio.sputnik.util.Lists;
import me.retucio.sputnik.util.render.RenderUtil; import me.retucio.sputnik.util.render.RenderUtil;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
@@ -87,7 +88,7 @@ public class Tracers extends Module {
public Tracers() { public Tracers() {
super("trazos", "trazar líneas de la cámara a las entidades seleccionadas", Category.RENDER); super("trazos", "trazar líneas de la cámara a las entidades seleccionadas", Category.RENDER);
defaultEntities.replace(EntityType.PLAYER, true); defaultEntities.replace(EntityTypes.PLAYER, true);
entities.setDefaultValue(defaultEntities); entities.setDefaultValue(defaultEntities);
} }
@@ -9,6 +9,7 @@ import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.client.gui.screens.inventory.AbstractSignEditScreen; import net.minecraft.client.gui.screens.inventory.AbstractSignEditScreen;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket; import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket;
import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.level.block.entity.SignBlockEntity;
@@ -25,7 +26,7 @@ public class AutoSign extends Module {
@Override @Override
public void onEnable() { public void onEnable() {
if (text == null) ChatUtil.info("coloca un primer cartel, del cual copiar el contenido"); if (text == null) ChatUtil.info(Component.translatable("sputnik.module.autosign.placefirst"));
super.onEnable(); super.onEnable();
} }
@@ -12,6 +12,7 @@ import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.Identifier; import net.minecraft.resources.Identifier;
import net.minecraft.world.inventory.DataSlot; import net.minecraft.world.inventory.DataSlot;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
@@ -64,7 +65,7 @@ public class BlockInfo extends Module {
); );
if (result.getType() == HitResult.Type.MISS) { if (result.getType() == HitResult.Type.MISS) {
ChatUtil.warn("no estás apuntando a ningún bloque"); ChatUtil.warn(Component.translatable("sputnik.module.blockinfo.noblock"));
return; return;
} }
@@ -76,7 +77,7 @@ public class BlockInfo extends Module {
} }
copy(blockHitResult, data); copy(blockHitResult, data);
} else { } else {
ChatUtil.warn("no estás apuntando a ningún bloque"); ChatUtil.warn(Component.translatable("sputnik.module.blockinfo.noblock"));
} }
} }
@@ -90,7 +91,7 @@ public class BlockInfo extends Module {
} }
if (propertyMap.isEmpty()) { if (propertyMap.isEmpty()) {
ChatUtil.warn("no hay propiedades que copiar para este bloque"); ChatUtil.warn(Component.translatable("sputnik.module.blockinfo.noproperties"));
return; return;
} }
@@ -147,7 +147,7 @@ public class LightOverlay extends Module {
} }
// renderizado // renderizado
Vec3 cameraPos = mc.gameRenderer.getMainCamera().position(); Vec3 cameraPos = mc.gameRenderer.mainCamera().position();
int radiusValue = radius.getIntValue(); int radiusValue = radius.getIntValue();
double radiusSq = radiusValue * radiusValue; double radiusSq = radiusValue * radiusValue;
@@ -41,8 +41,8 @@ public class StrongholdTriangulator extends Module {
@Override @Override
public void onEnable() { public void onEnable() {
super.onEnable(); super.onEnable();
ChatUtil.info("para empezar, lanza un ojo de ender"); ChatUtil.info(Component.translatable("sputnik.module.stronghold.throwfirst"));
ChatUtil.info("al lanzar los ojos, quédate quieto, o puede que la posición calculada salga errónea"); ChatUtil.info(Component.translatable("sputnik.module.stronghold.standstill"));
} }
@Override @Override
@@ -61,16 +61,15 @@ public class StrongholdTriangulator extends Module {
if (result != null) { if (result != null) {
if (result.errorMessage == null) { if (result.errorMessage == null) {
ChatUtil.info(Component.literal("stronghold aproximadamente en: " ChatUtil.info(Component.translatable("sputnik.module.stronghold.found",
+ ChatFormatting.GREEN ChatFormatting.GREEN
+ String.format("%.2f, %.2f", result.x, result.z) + String.format("%.2f, %.2f", result.x, result.z)
+ ChatFormatting.RESET + ChatFormatting.RESET));
));
} else { } else {
ChatUtil.error(result.errorMessage); ChatUtil.error(result.errorMessage);
} }
} else { } else {
ChatUtil.error("upsi"); ChatUtil.error(Component.translatable("sputnik.module.stronghold.oops"));
} }
reset(); reset();
@@ -101,8 +100,8 @@ public class StrongholdTriangulator extends Module {
firstEyeThrown = true; firstEyeThrown = true;
ChatUtil.info("primer ojo registrado: " ChatUtil.info("primer ojo registrado: "
+ String.format("%.1f, %.1f (%.1f°)", a.x, a.z, alpha)); + String.format("%.1f, %.1f (%.1f°)", a.x, a.z, alpha));
ChatUtil.info("ahora muévete unos 200 bloques en una dirección distinta a la del ojo para lanzar el segundo"); ChatUtil.info(Component.translatable("sputnik.module.stronghold.movenow"));
ChatUtil.info("cuanta más distancia te separes, más preciso será el resultado"); ChatUtil.info(Component.translatable("sputnik.module.stronghold.moreaccurate"));
} else if (!secondEyeThrown) { } else if (!secondEyeThrown) {
b = throwPos; b = throwPos;
beta = yaw; beta = yaw;
@@ -142,11 +141,11 @@ public class StrongholdTriangulator extends Module {
// posibles casos // posibles casos
if (x0 == x1 && z0 == z1) { // ambos ojos lanzados desde la misma pos. if (x0 == x1 && z0 == z1) { // ambos ojos lanzados desde la misma pos.
return new StrongholdResult(null, null, "pero muévete"); return new StrongholdResult(null, null, Component.translatable("sputnik.module.stronghold.error.move"));
} else if (Double.isNaN(d0)) { } else if (Double.isNaN(d0)) {
return new StrongholdResult(null, null, "los ojos forman líneas paralelas o coincidentes"); return new StrongholdResult(null, null, Component.translatable("sputnik.module.stronghold.error.parallel"));
} else if (d0 < 0 || d1 < 0) { } else if (d0 < 0 || d1 < 0) {
return new StrongholdResult(null, null, "los ojos apuntan a strongholds distintas"); return new StrongholdResult(null, null, Component.translatable("sputnik.module.stronghold.error.different"));
} else { } else {
return new StrongholdResult(x, z, null); return new StrongholdResult(x, z, null);
} }
@@ -159,5 +158,5 @@ public class StrongholdTriangulator extends Module {
b = null; b = null;
} }
public record StrongholdResult(Double x, Double z, String errorMessage) {} public record StrongholdResult(Double x, Double z, Component errorMessage) {}
} }
@@ -3,6 +3,7 @@ package me.retucio.sputnik.module.setting;
import me.retucio.sputnik.Sputnik; import me.retucio.sputnik.Sputnik;
import me.retucio.sputnik.event.sputnik.UpdateSettingEvent; import me.retucio.sputnik.event.sputnik.UpdateSettingEvent;
import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.util.I18nUtil;
import java.util.function.BooleanSupplier; import java.util.function.BooleanSupplier;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -10,9 +11,16 @@ import java.util.function.Consumer;
// base para los tipos de ajustes // base para los tipos de ajustes
public abstract class Setting<T> { public abstract class Setting<T> {
// OJO: `name` es la clave de la config. (ver ConfigManager#getSettingKey). nunca se muestra
// ni se traduce; cambiarlo resetea el ajuste a todos los usuarios. lo que se ve es getName().
protected final String name; protected final String name;
protected final String description; protected final String description;
// si es null se deriva del módulo + nombre. los ajustes comunes a todos los módulos
// la fijan a mano para compartir una sola entrada en el lang.
protected String translationKey = null;
private String derivedKey = null;
protected T value; protected T value;
protected T defaultValue; protected T defaultValue;
@@ -49,6 +57,13 @@ public abstract class Setting<T> {
return (S) this; return (S) this;
} }
// fija la clave a mano en vez de derivarla, para compartir texto entre módulos
@SuppressWarnings("unchecked")
public <S extends Setting<T>> S translationKey(String key) {
this.translationKey = key;
return (S) this;
}
public boolean isSearchMatch() { public boolean isSearchMatch() {
return searchMatch; return searchMatch;
} }
@@ -57,14 +72,32 @@ public abstract class Setting<T> {
this.searchMatch = searchMatch; this.searchMatch = searchMatch;
} }
public String getName() { public String getTranslationKey() {
return name.strip(); if (translationKey != null) return translationKey;
if (derivedKey != null) return derivedKey;
// sg se asigna después de construir, así que se deriva tarde y solo se cachea cuando ya hay módulo
Module module = (sg != null) ? sg.getModule() : null;
if (module == null) return "sputnik.setting." + I18nUtil.slug(name);
// getTrueName() en el grupo para que la clave no dependa del idioma.
// paddedSlug conserva los espacios del final, que aquí distinguen ajustes distintos
derivedKey = "sputnik.setting." + I18nUtil.slug(module.getName())
+ "." + I18nUtil.slug(sg.getTrueName())
+ "." + I18nUtil.paddedSlug(name);
return derivedKey;
} }
// nombre visible, traducido. para la clave de la config. usar getTrueName()
public String getName() {
return I18nUtil.orElse(getTranslationKey() + ".name", name.strip());
}
// nombre interno: clave de la config. no traducir
public String getTrueName() { return name; } public String getTrueName() { return name; }
public String getDescription() { public String getDescription() {
return description; return I18nUtil.orElse(getTranslationKey() + ".desc", description);
} }
public T getValue() { public T getValue() {
@@ -1,6 +1,7 @@
package me.retucio.sputnik.module.setting; package me.retucio.sputnik.module.setting;
import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.util.I18nUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -15,6 +16,9 @@ public class SettingGroup implements Iterable<Setting<?>> {
private String name; private String name;
private boolean extended; private boolean extended;
// si es null se deriva del módulo + nombre; los grupos comunes la fijan para compartir texto
private String translationKey = null;
final List<Setting<?>> settings = new ArrayList<>(1); final List<Setting<?>> settings = new ArrayList<>(1);
public SettingGroup(String name, boolean extended) { public SettingGroup(String name, boolean extended) {
@@ -22,6 +26,11 @@ public class SettingGroup implements Iterable<Setting<?>> {
this.extended = extended; this.extended = extended;
} }
public SettingGroup(String name, boolean extended, String translationKey) {
this(name, extended);
this.translationKey = translationKey;
}
@Override @Override
public @NotNull Iterator<Setting<?>> iterator() { public @NotNull Iterator<Setting<?>> iterator() {
return settings.iterator(); return settings.iterator();
@@ -40,9 +49,10 @@ public class SettingGroup implements Iterable<Setting<?>> {
} }
} }
// busca por nombre interno, no por el traducido
public Setting<?> getSetting(String name) { public Setting<?> getSetting(String name) {
for (Setting<?> setting : this) for (Setting<?> setting : this)
if (setting.getName().equals(name)) if (setting.getTrueName().equals(name))
return setting; return setting;
return null; return null;
@@ -52,10 +62,21 @@ public class SettingGroup implements Iterable<Setting<?>> {
return settings; return settings;
} }
// nombre visible, traducido. los grupos no se guardan en la config., pero la clave se
// deriva igual que en Setting para que el lang siga un solo patrón
public String getName() { public String getName() {
return name; return I18nUtil.orElse(getTranslationKey(), name);
} }
public String getTranslationKey() {
if (translationKey != null) return translationKey;
return (module != null)
? "sputnik.group." + I18nUtil.slug(module.getName()) + "." + I18nUtil.slug(name)
: "sputnik.group." + I18nUtil.slug(name);
}
public String getTrueName() { return name; }
public void setName(String name) { this.name = name; } public void setName(String name) { this.name = name; }
public boolean isExtended() { public boolean isExtended() {
@@ -228,7 +228,7 @@ public class ColorSetting extends Setting<Color> {
} }
public Component getTooltipText() { public Component getTooltipText() {
if (rainbow) return Component.literal("arcoíris"); if (rainbow) return Component.translatable("sputnik.setting.color.rainbow");
return Component.literal(Colors.getFormatting(value) + Colors.ARGBtoHex(a, r, g, b)); return Component.literal(Colors.getFormatting(value) + Colors.ARGBtoHex(a, r, g, b));
} }
@@ -3,8 +3,10 @@ package me.retucio.sputnik.module.setting.settings;
import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.setting.Setting; import me.retucio.sputnik.module.setting.Setting;
import me.retucio.sputnik.ui.widgets.panels.settings.ClientSettingsPanel;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import me.retucio.sputnik.util.KeyUtil; import me.retucio.sputnik.util.KeyUtil;
import net.minecraft.network.chat.Component;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
public class KeySetting extends Setting<Integer> { public class KeySetting extends Setting<Integer> {
@@ -22,15 +24,21 @@ public class KeySetting extends Setting<Integer> {
if (value == GLFW.GLFW_KEY_ESCAPE) { if (value == GLFW.GLFW_KEY_ESCAPE) {
this.value = GLFW.GLFW_KEY_UNKNOWN; // asignar la tecla ESC a deshabilitar la tecla this.value = GLFW.GLFW_KEY_UNKNOWN; // asignar la tecla ESC a deshabilitar la tecla
fireUpdateEvent(); fireUpdateEvent();
if (updateListener != null) updateListener.accept(value); // this.value y no value: lo que se ha guardado es UNKNOWN, no ESC. si no, al
// listener se le decía que la tecla era ESC
if (updateListener != null) updateListener.accept(this.value);
return; return;
} }
if (ModuleManager.INSTANCE != null) { // con "teclas multimódulo" puesto se permite repetir tecla, que es justo lo que
// dice el ajuste. antes se le quitaba la tecla al otro módulo igualmente, así que
// el ajuste sólo servía para las teclas de vanilla
if (ModuleManager.INSTANCE != null
&& !ClientSettingsPanel.clientSettings.multipleKeybinds.getValue()) {
for (Module module : ModuleManager.INSTANCE.getModules()) for (Module module : ModuleManager.INSTANCE.getModules())
if (module.getKey() == value && value != -1) { if (module.getKey() == value && value != -1) {
module.setKey(-1); module.setKey(-1);
ChatUtil.info("tecla del módulo " + module.getName() + " restablecida"); ChatUtil.info(Component.translatable("sputnik.setting.key.reset", module.getDisplayName()));
} }
} }
@@ -34,7 +34,7 @@ public class HudEditorScreen extends Screen {
private int dragX, dragY; private int dragX, dragY;
public HudEditorScreen() { public HudEditorScreen() {
super(Component.literal("editor del HUD")); super(Component.translatable("sputnik.hud.editor.title"));
Sputnik.EVENT_BUS.subscribe(this); Sputnik.EVENT_BUS.subscribe(this);
} }
@@ -50,7 +50,7 @@ public class HudEditorScreen extends Screen {
// instrucciones // instrucciones
gui.centeredText(mc.font, title, this.width / 2, this.height / 2 - mc.font.lineHeight, -1); gui.centeredText(mc.font, title, this.width / 2, this.height / 2 - mc.font.lineHeight, -1);
gui.centeredText(mc.font, gui.centeredText(mc.font,
Component.literal("arrastrar para mover · clic derecho para visibilidad · ESC para guardar y salir · shift + clic derecho para restablecer"), Component.translatable("sputnik.hud.editor.instructions"),
this.width / 2, this.height / 2 + mc.font.lineHeight, Colors.instructionsTextColor.getRGB()); this.width / 2, this.height / 2 + mc.font.lineHeight, Colors.instructionsTextColor.getRGB());
// movimiento axial // movimiento axial
@@ -157,7 +157,7 @@ public class HudEditorScreen extends Screen {
// he sustituído el método del súper por un evento para ver si así se podían // he sustituído el método del súper por un evento para ver si así se podían
// registrar dos teclas a la vez, pero resulta que no :P // registrar dos teclas a la vez, pero resulta que no :P
public void onKey(KeyEvent event) { public void onKey(KeyEvent event) {
if (!(mc.screen == INSTANCE)) return; if (!(mc.gui.screen() == INSTANCE)) return;
if (event.getAction() == GLFW.GLFW_RELEASE) return; if (event.getAction() == GLFW.GLFW_RELEASE) return;
event.cancel(); event.cancel();
@@ -165,7 +165,7 @@ public class HudEditorScreen extends Screen {
if (event.getKey() == GLFW.GLFW_KEY_ESCAPE) { if (event.getKey() == GLFW.GLFW_KEY_ESCAPE) {
saveAllElementsToConfig(); saveAllElementsToConfig();
selected = null; selected = null;
mc.setScreen(null); mc.gui.setScreen(null);
} }
// movimiento de los elementos con las teclas de las flechas // movimiento de los elementos con las teclas de las flechas
else if (hud.arrowMovement.getValue() && selected != null) { else if (hud.arrowMovement.getValue() && selected != null) {
@@ -47,6 +47,7 @@ public class HudRenderer {
addElement(new DynoElement(), positions, visibilities); addElement(new DynoElement(), positions, visibilities);
addElement(new EchestElement(), positions, visibilities); addElement(new EchestElement(), positions, visibilities);
addElement(new TotemsElement(), positions, visibilities); addElement(new TotemsElement(), positions, visibilities);
addElement(new ArmorElement(), positions, visibilities);
HudEditorScreen.INSTANCE.setElements(elements); HudEditorScreen.INSTANCE.setElements(elements);
} }
@@ -72,8 +73,9 @@ public class HudRenderer {
public HudElement getElement(Class<? extends HudElement> clazz) { public HudElement getElement(Class<? extends HudElement> clazz) {
for (HudElement element : elements) { for (HudElement element : elements) {
if (element.getClass() == clazz) if (element.getClass() == clazz) {
return element; return element;
}
} }
return null; return null;
@@ -110,7 +112,7 @@ public class HudRenderer {
List<NotificationWidget> toRemove = new ArrayList<>(); List<NotificationWidget> toRemove = new ArrayList<>();
for (NotificationWidget notification : notifications) { for (NotificationWidget notification : notifications) {
notification.setIndex(notifications.indexOf(notification)); notification.setIndex(notifications.indexOf(notification));
notification.render(gui, 0, 0, 0); if (!shouldSkipRendering()) notification.render(gui, 0, 0, 0);
if (System.currentTimeMillis() >= notification.popTime) { if (System.currentTimeMillis() >= notification.popTime) {
toRemove.add(notification); toRemove.add(notification);
} }
@@ -123,12 +125,12 @@ public class HudRenderer {
return ModuleManager.INSTANCE == null return ModuleManager.INSTANCE == null
|| mc.player == null || mc.player == null
|| mc.getCameraEntity() == null || mc.getCameraEntity() == null
|| mc.screen instanceof TitleScreen || mc.gui.screen() instanceof TitleScreen
|| mc.options.hideGui || mc.gui.hud.isHidden()
|| !hud.isEnabled() || !hud.isEnabled()
|| (mc.debugEntries.isOverlayVisible() && !hud.showOnF3.getValue()) || (mc.debugEntries.isOverlayVisible() && !hud.showOnF3.getValue())
|| (mc.screen instanceof ChatScreen && !hud.showOnChat.getValue()) || (mc.gui.screen() instanceof ChatScreen && !hud.showOnChat.getValue())
|| mc.screen instanceof HudEditorScreen; || mc.gui.screen() instanceof HudEditorScreen;
} }
public void pushNotification(String title, String desc) { public void pushNotification(String title, String desc) {
@@ -7,6 +7,7 @@ import me.retucio.sputnik.util.Colors;
import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.GuiGraphicsExtractor;
import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.client.renderer.RenderPipelines;
import net.minecraft.client.renderer.texture.DynamicTexture; import net.minecraft.client.renderer.texture.DynamicTexture;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.Identifier; import net.minecraft.resources.Identifier;
@@ -60,10 +61,10 @@ public abstract class ImageHudElement extends HudElement {
mc.getTextureManager().register(textureId, texture); mc.getTextureManager().register(textureId, texture);
textureLoaded = true; textureLoaded = true;
Sputnik.LOGGER.info("textura para el elemento del HUD {} cargada", getId()); Sputnik.LOGGER.info(Component.translatable("sputnik.hud.info.textureloaded", getId()).getString());
} }
} catch (Exception e) { } catch (Exception e) {
Sputnik.LOGGER.error("no se pudo cargar la textura para el elemento del HUD {}: {}", getId(), e.getMessage()); Sputnik.LOGGER.error(Component.translatable("sputnik.hud.error.texture", getId(), e.getMessage()).getString());
} }
} }
@@ -0,0 +1,90 @@
package me.retucio.sputnik.ui.hud.elements;
import me.retucio.sputnik.module.modules.client.Hud;
import me.retucio.sputnik.ui.hud.ImageHudElement;
import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.client.gui.GuiGraphicsExtractor;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import java.util.List;
public class ArmorElement extends ImageHudElement {
private final EquipmentSlot[] armorSlots;
private List<ItemStack> previewStacks = null;
public ArmorElement() {
super("armor", mc.getWindow().getGuiScaledWidth() - 16, (mc.getWindow().getGuiScaledHeight() - 16 * 4) / 2);
this.w = 16;
this.h = 16 * 4;
armorSlots = new EquipmentSlot[]{
EquipmentSlot.HEAD,
EquipmentSlot.CHEST,
EquipmentSlot.LEGS,
EquipmentSlot.FEET
};
reloadTexture();
}
@Override
public void renderInGame(GuiGraphicsExtractor gui, float d, Hud hud) {
if (!isVisible()) return;
for (EquipmentSlot slot : List.of(armorSlots)) {
ItemStack stack = mc.player.getItemBySlot(slot);
int y = this.y + 16 * (3 - slot.getIndex());
gui.item(stack, x, y);
gui.itemBar(stack, x, y + 2);
}
}
@Override
public void renderInEditor(GuiGraphicsExtractor gui, Hud hud) {
if (mc.player != null && mc.level != null) {
drawEditorBackground(gui);
renderInGame(gui, 0, hud);
return;
}
drawEditorBackground(gui);
for (ItemStack stack : getPreviewStacks()) {
int y = this.y + 16 * getPreviewStacks().indexOf(stack);
gui.item(stack, x, y);
gui.itemBar(stack, x, y + 2);
}
}
@Override
protected String getImagePath() { return ""; }
@Override
public List<Component> getTooltip() {
return List.of(Component.translatable("sputnik.hud.element.armor.desc"));
}
private List<ItemStack> getPreviewStacks() {
if (previewStacks == null) {
try {
List<ItemStack> stacks = List.of(
new ItemStack(Items.DIAMOND_HELMET),
new ItemStack(Items.DIAMOND_CHESTPLATE),
new ItemStack(Items.DIAMOND_LEGGINGS),
new ItemStack(Items.DIAMOND_BOOTS)
);
for (ItemStack stack : stacks) {
stack.setDamageValue(stack.getMaxDamage() / 2);
}
previewStacks = stacks;
} catch (Exception e) {
return List.of(); // not ready yet, return empty
}
}
return previewStacks;
}
}
@@ -48,7 +48,7 @@ public class CoordsElement extends TextHudElement {
public List<Component> getTooltip() { public List<Component> getTooltip() {
return List.of( return List.of(
Component.literal(getId()), Component.literal(getId()),
Component.literal("te muestra tu posición XYZ en el mundo") Component.translatable("sputnik.hud.element.coords.desc")
); );
} }
} }
@@ -32,8 +32,8 @@ public class CustomTextElement extends TextHudElement {
@Override @Override
public List<Component> getTooltip() { public List<Component> getTooltip() {
return List.of( return List.of(
Component.literal("texto custom"), Component.translatable("sputnik.hud.element.customtext.name"),
Component.literal("texto que tú eliges") Component.translatable("sputnik.hud.element.customtext.desc")
); );
} }
@@ -35,8 +35,8 @@ public class DynoElement extends ImageHudElement {
@Override @Override
public List<Component> getTooltip() { public List<Component> getTooltip() {
return List.of( return List.of(
Component.literal("dinosaurio: " + dyno), Component.translatable("sputnik.hud.element.dyno.name", dyno),
Component.literal("que viva el autismo joder") Component.translatable("sputnik.hud.element.dyno.desc")
); );
} }
} }
@@ -86,8 +86,8 @@ public class EchestElement extends ImageHudElement {
@Override @Override
public List<Component> getTooltip() { public List<Component> getTooltip() {
List<Component> tooltip = new ArrayList<>(); List<Component> tooltip = new ArrayList<>();
tooltip.add(Component.literal("echest")); tooltip.add(Component.translatable("sputnik.hud.element.echest.name"));
tooltip.add(Component.literal("items en tu echest")); tooltip.add(Component.translatable("sputnik.hud.element.echest.desc"));
return tooltip; return tooltip;
} }
@@ -26,8 +26,8 @@ public class FpsElement extends TextHudElement {
@Override @Override
public List<Component> getTooltip() { public List<Component> getTooltip() {
return List.of( return List.of(
Component.literal("FPS"), Component.translatable("sputnik.hud.element.fps.name"),
Component.literal("te muestra los fotogramas por segundo a los que corre el juego") Component.translatable("sputnik.hud.element.fps.desc")
); );
} }
} }
@@ -2,6 +2,7 @@ package me.retucio.sputnik.ui.hud.elements;
import me.retucio.sputnik.module.modules.client.Hud; import me.retucio.sputnik.module.modules.client.Hud;
import me.retucio.sputnik.ui.hud.TextHudElement; import me.retucio.sputnik.ui.hud.TextHudElement;
import me.retucio.sputnik.util.MiscUtil;
import net.minecraft.client.multiplayer.PlayerInfo; import net.minecraft.client.multiplayer.PlayerInfo;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
@@ -17,7 +18,7 @@ public class PingElement extends TextHudElement {
@Override @Override
public String getText(float delta, Hud hud) { public String getText(float delta, Hud hud) {
if (mc.getConnection() == null || mc.player == null) return "? ms"; if (mc.getConnection() == null || mc.player == null) return "? ms";
if (mc.isSingleplayer()) return "-1 ms"; if (MiscUtil.isSingleplayer()) return "-1 ms";
PlayerInfo playerListEntry = mc.getConnection().getPlayerInfo(mc.player.getUUID()); PlayerInfo playerListEntry = mc.getConnection().getPlayerInfo(mc.player.getUUID());
return playerListEntry != null ? playerListEntry.getLatency() + " ms" : "? ms"; return playerListEntry != null ? playerListEntry.getLatency() + " ms" : "? ms";
@@ -31,8 +32,8 @@ public class PingElement extends TextHudElement {
@Override @Override
public List<Component> getTooltip() { public List<Component> getTooltip() {
return List.of( return List.of(
Component.literal("ping"), Component.translatable("sputnik.hud.element.ping.name"),
Component.literal("latencia entre cliente y servidor, en milisegundos") Component.translatable("sputnik.hud.element.ping.desc")
); );
} }
} }
Loaded 100 of 131 files, more files were not shown because too many files have changed in this diff. Show more